Skip to content

Commit f0abf7d

Browse files
committed
Add try_const to lift.
1 parent 7673277 commit f0abf7d

4 files changed

Lines changed: 30 additions & 23 deletions

File tree

qiskit/circuit/classical/expr/constructors.py

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def lift_legacy_condition(
9191
return Binary(Binary.Op.EQUAL, left, right, types.Bool())
9292

9393

94-
def lift(value: typing.Any, /, type: types.Type | None = None) -> Expr:
94+
def lift(value: typing.Any, /, type: types.Type | None = None, *, try_const: bool = True) -> Expr:
9595
"""Lift the given Python ``value`` to a :class:`~.expr.Value` or :class:`~.expr.Var`.
9696
9797
If an explicit ``type`` is given, the typing in the output will reflect that.
@@ -125,7 +125,7 @@ def lift(value: typing.Any, /, type: types.Type | None = None) -> Expr:
125125

126126
inferred: types.Type
127127
if value is True or value is False:
128-
inferred = types.Bool(const=True)
128+
inferred = types.Bool(const=try_const)
129129
constructor = Value
130130
elif isinstance(value, Clbit):
131131
inferred = types.Bool()
@@ -136,7 +136,7 @@ def lift(value: typing.Any, /, type: types.Type | None = None) -> Expr:
136136
elif isinstance(value, int):
137137
if value < 0:
138138
raise ValueError("cannot represent a negative value")
139-
inferred = types.Uint(width=value.bit_length() or 1, const=True)
139+
inferred = types.Uint(width=value.bit_length() or 1, const=try_const)
140140
constructor = Value
141141
else:
142142
raise TypeError(f"failed to infer a type for '{value}'")
@@ -223,24 +223,19 @@ def _lift_binary_operands(left: typing.Any, right: typing.Any) -> tuple[Expr, Ex
223223
right_int = isinstance(right, int) and not right_bool
224224
if not (left_int or right_int):
225225
if left_bool == right_bool:
226-
# If they're both bool, lifting them will produce const Bool.
227-
# If neither are bool, they're a mix of bits/registers (which are always
228-
# non-const) and Expr, which we can't modify the const-ness of without
229-
# a cast node.
230-
left = lift(left)
231-
right = lift(right)
226+
# If they're both bool, they'll lift as const here.
227+
# If neither are, we've already checked for int, so they must be bits,
228+
# registers, or expressions, none of which we can't lift to be const.
229+
left = lift(left, try_const=True)
230+
right = lift(right, try_const=True)
232231
elif not right_bool:
233-
# Left is a bool
232+
# Left is a bool, which should only be const if right is const.
234233
right = lift(right)
235-
# TODO: if right.type isn't Bool, there's a type mismatch so we _should_
236-
# raise here. But, _binary_bitwise will error for us with a better msg.
237-
left = lift(left, right.type if right.type.kind is types.Bool else None)
234+
left = lift(left, try_const=right.type.const)
238235
elif not left_bool:
239-
# Right is a bool.
236+
# Right is a bool, which should only be const if left is const.
240237
left = lift(left)
241-
# TODO: if left.type isn't Bool, there's a type mismatch so we _should_
242-
# raise here. But, _binary_bitwise will error for us with a better msg.
243-
right = lift(right, left.type if left.type.kind is types.Bool else None)
238+
right = lift(right, try_const=left.type.const)
244239
elif not right_int:
245240
# Left is an int.
246241
right = lift(right)

qiskit/circuit/classical/types/ordering.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
import enum
2828

29-
from .types import Type, Bool, Uint, Duration, Stretch
29+
from .types import Type, Bool, Uint
3030

3131

3232
# While the type system is simple, it's overkill to represent the complete partial ordering graph of
@@ -70,8 +70,6 @@ def _order_uint_uint(left: Uint, right: Uint, /) -> Ordering:
7070
_ORDERERS = {
7171
(Bool, Bool): _order_identical,
7272
(Uint, Uint): _order_uint_uint,
73-
(Duration, Duration): _order_identical,
74-
(Stretch, Stretch): _order_identical,
7573
}
7674

7775

qiskit/circuit/classical/types/types.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ def kind(self):
6464
this a hashable enum-like discriminator you can rely on."""
6565
return self.__class__
6666

67+
@property
68+
def const(self):
69+
"""Get the const-ness of this type."""
70+
raise NotImplementedError("types must implement the 'const' attribute")
71+
6772
# Enforcement of immutability. The constructor methods need to manually skip this.
6873

6974
def __setattr__(self, _key, _value):

test/python/circuit/classical/test_expr_constructors.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,6 @@ def test_binary_logical_lift_scalars(self, function, op):
242242
types.Bool(),
243243
)
244244
)
245-
print(f"HI: {function(cr_3, True)}")
246245
self.assertEqual(
247246
function(cr_3, True),
248247
expr.Binary(
@@ -416,7 +415,7 @@ def test_binary_logical_explicit(self, function, opcode):
416415
expr.Binary(
417416
opcode,
418417
expr.Cast(expr.Var(cr, types.Uint(cr.size)), types.Bool(), implicit=True),
419-
expr.Cast(expr.Value(3, types.Uint(2, const=True)), types.Bool(const=True), implicit=True),
418+
expr.Cast(expr.Value(3, types.Uint(cr.size)), types.Bool(), implicit=True),
420419
types.Bool(),
421420
),
422421
)
@@ -425,12 +424,22 @@ def test_binary_logical_explicit(self, function, opcode):
425424
function(False, clbit),
426425
expr.Binary(
427426
opcode,
428-
expr.Value(False, types.Bool(const=True)),
427+
expr.Value(False, types.Bool()),
429428
expr.Var(clbit, types.Bool()),
430429
types.Bool(),
431430
),
432431
)
433432

433+
self.assertEqual(
434+
function(False, 3),
435+
expr.Binary(
436+
opcode,
437+
expr.Value(False, types.Bool(const=True)),
438+
expr.Cast(expr.Value(3, types.Uint(2, const=True)), types.Bool(const=True), implicit=True),
439+
types.Bool(const=True)
440+
)
441+
)
442+
434443
@ddt.data(
435444
(expr.equal, expr.Binary.Op.EQUAL),
436445
(expr.not_equal, expr.Binary.Op.NOT_EQUAL),

0 commit comments

Comments
 (0)