Skip to content

Commit e39b2e4

Browse files
yitchen-timanuragmjcjaskula-awsdependabot[bot]jmdewart
authored
Merge latest update from openqasm:main (#1)
* Fix code of conduct link (openqasm#27) Co-authored-by: Jean-Christophe Jaskula <[email protected]> * Add support for arrays (openqasm#28) * Add array variable * Enable indexing * Add a test * More tests * Allow specifying type and dimensions in declaration * Explicitly test setting with variable * Typing: allow assignment to indexed expressions * Union type typealias * Fix comment, provide OQIndexExpression from the module * Pydocstyle Why complain now? * Add base type to ComplexVar and propagate it to arrays * Bump setuptools from 65.4.1 to 65.5.1 (openqasm#30) Bumps [setuptools](https://github.com/pypa/setuptools) from 65.4.1 to 65.5.1. - [Release notes](https://github.com/pypa/setuptools/releases) - [Changelog](https://github.com/pypa/setuptools/blob/main/CHANGES.rst) - [Commits](pypa/setuptools@v65.4.1...v65.5.1) --- updated-dependencies: - dependency-name: setuptools dependency-type: indirect ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump cryptography from 37.0.4 to 39.0.1 (openqasm#29) Bumps [cryptography](https://github.com/pyca/cryptography) from 37.0.4 to 39.0.1. - [Release notes](https://github.com/pyca/cryptography/releases) - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](pyca/cryptography@37.0.4...39.0.1) --- updated-dependencies: - dependency-name: cryptography dependency-type: indirect ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Add shift and bitwise operations (openqasm#31) * Add shift and logical operations * Add logical OR and AND --------- Co-authored-by: Mitch D'Ewart <[email protected]> --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: Anurag Mishra <[email protected]> Co-authored-by: Jean-Christophe Jaskula <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: jmdewart <[email protected]> Co-authored-by: Mitch D'Ewart <[email protected]>
1 parent f1f8528 commit e39b2e4

File tree

6 files changed

+1111
-827
lines changed

6 files changed

+1111
-827
lines changed

CODE_OF_CONDUCT.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33
All members of this project agree to adhere to the [Qiskit Code of Conduct][qiskit-coc].
44

5-
[qiskit-coc]: https://github.com/Qiskit/qiskit/blob/main/CODE_OF_CONDUCT.md
5+
[qiskit-coc]: https://github.com/Qiskit/qiskit/blob/master/CODE_OF_CONDUCT.md

oqpy/base.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,36 @@ def __pow__(self, other: AstConvertible) -> OQPyBinaryExpression:
107107
def __rpow__(self, other: AstConvertible) -> OQPyBinaryExpression:
108108
return self._to_binary("**", other, self)
109109

110+
def __lshift__(self, other: AstConvertible) -> OQPyBinaryExpression:
111+
return self._to_binary("<<", self, other)
112+
113+
def __rlshift__(self, other: AstConvertible) -> OQPyBinaryExpression:
114+
return self._to_binary("<<", other, self)
115+
116+
def __rshift__(self, other: AstConvertible) -> OQPyBinaryExpression:
117+
return self._to_binary(">>", self, other)
118+
119+
def __rrshift__(self, other: AstConvertible) -> OQPyBinaryExpression:
120+
return self._to_binary(">>", other, self)
121+
122+
def __and__(self, other: AstConvertible) -> OQPyBinaryExpression:
123+
return self._to_binary("&", self, other)
124+
125+
def __rand__(self, other: AstConvertible) -> OQPyBinaryExpression:
126+
return self._to_binary("&", other, self)
127+
128+
def __or__(self, other: AstConvertible) -> OQPyBinaryExpression:
129+
return self._to_binary("|", self, other)
130+
131+
def __ror__(self, other: AstConvertible) -> OQPyBinaryExpression:
132+
return self._to_binary("|", other, self)
133+
134+
def __xor__(self, other: AstConvertible) -> OQPyBinaryExpression:
135+
return self._to_binary("^", self, other)
136+
137+
def __rxor__(self, other: AstConvertible) -> OQPyBinaryExpression:
138+
return self._to_binary("^", other, self)
139+
110140
def __eq__(self, other: AstConvertible) -> OQPyBinaryExpression: # type: ignore[override]
111141
return self._to_binary("==", self, other)
112142

@@ -125,13 +155,26 @@ def __ge__(self, other: AstConvertible) -> OQPyBinaryExpression:
125155
def __le__(self, other: AstConvertible) -> OQPyBinaryExpression:
126156
return self._to_binary("<=", self, other)
127157

158+
def __invert__(self) -> OQPyUnaryExpression:
159+
return self._to_unary("~", self)
160+
128161
def __bool__(self) -> bool:
129162
raise RuntimeError(
130163
"OQPy expressions cannot be converted to bool. This can occur if you try to check "
131164
"the equality of expressions using == instead of expr_matches."
132165
)
133166

134167

168+
def logical_and(first: AstConvertible, second: AstConvertible) -> OQPyBinaryExpression:
169+
"""Logical AND."""
170+
return OQPyBinaryExpression(ast.BinaryOperator["&&"], first, second)
171+
172+
173+
def logical_or(first: AstConvertible, second: AstConvertible) -> OQPyBinaryExpression:
174+
"""Logical OR."""
175+
return OQPyBinaryExpression(ast.BinaryOperator["||"], first, second)
176+
177+
135178
def expr_matches(a: Any, b: Any) -> bool:
136179
"""Check equality of the given objects.
137180

oqpy/classical_types.py

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939

4040
__all__ = [
4141
"pi",
42+
"ArrayVar",
4243
"BoolVar",
4344
"IntVar",
4445
"UintVar",
@@ -48,6 +49,7 @@
4849
"ComplexVar",
4950
"DurationVar",
5051
"OQFunctionCall",
52+
"OQIndexExpression",
5153
"StretchVar",
5254
"_ClassicalVar",
5355
"duration",
@@ -272,18 +274,20 @@ class ComplexVar(_ClassicalVar):
272274
"""An oqpy variable with bit type."""
273275

274276
type_cls = ast.ComplexType
277+
base_type: ast.FloatType = float64
275278

276-
def __class_getitem__(cls, item: Type[ast.FloatType]) -> Callable[..., ComplexVar]:
279+
def __class_getitem__(cls, item: ast.FloatType) -> Callable[..., ComplexVar]:
277280
return functools.partial(cls, base_type=item)
278281

279282
def __init__(
280283
self,
281284
init_expression: AstConvertible | None = None,
282285
*args: Any,
283-
base_type: Type[ast.FloatType] = float64,
286+
base_type: ast.FloatType = float64,
284287
**kwargs: Any,
285288
) -> None:
286289
assert isinstance(base_type, ast.FloatType)
290+
self.base_type = base_type
287291

288292
if not isinstance(init_expression, (complex, type(None), OQPyExpression)):
289293
init_expression = complex(init_expression) # type: ignore[arg-type]
@@ -313,6 +317,80 @@ class StretchVar(_ClassicalVar):
313317
type_cls = ast.StretchType
314318

315319

320+
AllowedArrayTypes = Union[_SizedVar, DurationVar, BoolVar, ComplexVar]
321+
322+
323+
class ArrayVar(_ClassicalVar):
324+
"""An oqpy array variable."""
325+
326+
type_cls = ast.ArrayType
327+
dimensions: list[int]
328+
base_type: type[AllowedArrayTypes]
329+
330+
def __class_getitem__(
331+
cls, item: tuple[type[AllowedArrayTypes], int] | type[AllowedArrayTypes]
332+
) -> Callable[..., ArrayVar]:
333+
# Allows usage like ArrayVar[FloatVar, 32](...) or ArrayVar[FloatVar]
334+
if isinstance(item, tuple):
335+
base_type = item[0]
336+
dimensions = list(item[1:])
337+
return functools.partial(cls, dimensions=dimensions, base_type=base_type)
338+
else:
339+
return functools.partial(cls, base_type=item)
340+
341+
def __init__(
342+
self,
343+
*args: Any,
344+
dimensions: list[int],
345+
base_type: type[AllowedArrayTypes] = IntVar,
346+
**kwargs: Any,
347+
) -> None:
348+
self.dimensions = dimensions
349+
self.base_type = base_type
350+
351+
# Creating a dummy variable supports IntVar[64] etc.
352+
base_type_instance = base_type()
353+
if isinstance(base_type_instance, _SizedVar):
354+
array_base_type = base_type_instance.type_cls(
355+
size=ast.IntegerLiteral(base_type_instance.size)
356+
)
357+
elif isinstance(base_type_instance, ComplexVar):
358+
array_base_type = base_type_instance.type_cls(base_type=base_type_instance.base_type)
359+
else:
360+
array_base_type = base_type_instance.type_cls()
361+
362+
# Automatically handle Duration array.
363+
if base_type is DurationVar and kwargs["init_expression"]:
364+
kwargs["init_expression"] = (make_duration(i) for i in kwargs["init_expression"])
365+
366+
super().__init__(
367+
*args,
368+
**kwargs,
369+
dimensions=[ast.IntegerLiteral(dimension) for dimension in dimensions],
370+
base_type=array_base_type,
371+
)
372+
373+
def __getitem__(self, index: AstConvertible) -> OQIndexExpression:
374+
return OQIndexExpression(collection=self, index=index)
375+
376+
377+
class OQIndexExpression(OQPyExpression):
378+
"""An oqpy expression corresponding to an index expression."""
379+
380+
def __init__(self, collection: AstConvertible, index: AstConvertible):
381+
self.collection = collection
382+
self.index = index
383+
384+
if isinstance(collection, ArrayVar):
385+
self.type = collection.base_type().type_cls()
386+
387+
def to_ast(self, program: Program) -> ast.IndexExpression:
388+
"""Converts this oqpy index expression into an ast node."""
389+
return ast.IndexExpression(
390+
collection=to_ast(program, self.collection), index=[to_ast(program, self.index)]
391+
)
392+
393+
316394
class OQFunctionCall(OQPyExpression):
317395
"""An oqpy expression corresponding to a function call."""
318396

oqpy/program.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,11 @@ def _do_assignment(self, var: AstConvertible, op: str, value: AstConvertible) ->
459459
)
460460
)
461461

462-
def set(self, var: classical_types._ClassicalVar, value: AstConvertible) -> Program:
462+
def set(
463+
self,
464+
var: classical_types._ClassicalVar | classical_types.OQIndexExpression,
465+
value: AstConvertible,
466+
) -> Program:
463467
"""Set a variable value."""
464468
self._do_assignment(var, "=", value)
465469
return self

0 commit comments

Comments
 (0)