Skip to content

Commit bc9382c

Browse files
Raise an exception for delays or boxes with known negative duration (#85)
* raise an exception for delays with known negative duration * check duration for Box
1 parent d16f4af commit bc9382c

File tree

3 files changed

+29
-4
lines changed

3 files changed

+29
-4
lines changed

oqpy/program.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ def delay(
423423
"""Apply a delay to a set of qubits or frames."""
424424
if not isinstance(qubits_or_frames, Iterable):
425425
qubits_or_frames = [qubits_or_frames]
426-
ast_duration = to_ast(self, convert_float_to_duration(time))
426+
ast_duration = to_ast(self, convert_float_to_duration(time, require_nonnegative=True))
427427
ast_qubits_or_frames = map_to_ast(self, qubits_or_frames)
428428
self._add_statement(ast.DelayInstruction(ast_duration, ast_qubits_or_frames))
429429
return self

oqpy/timing.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
def Box(program: Program, duration: AstConvertible | None = None) -> Iterator[None]:
4444
"""Creates a section of the program with a specified duration."""
4545
if duration is not None:
46-
duration = convert_float_to_duration(duration)
46+
duration = convert_float_to_duration(duration, require_nonnegative=True)
4747
program._push()
4848
yield
4949
state = program._pop()
@@ -60,9 +60,17 @@ def make_duration(time: AstConvertible) -> HasToAst:
6060
return convert_float_to_duration(time)
6161

6262

63-
def convert_float_to_duration(time: AstConvertible) -> HasToAst:
64-
"""Make value into an expression representing a duration."""
63+
def convert_float_to_duration(time: AstConvertible, require_nonnegative: bool = False) -> HasToAst:
64+
"""Make value into an expression representing a duration.
65+
66+
Args:
67+
time: the time
68+
require_nonnegative: if True, raise an exception if the time value is known to
69+
be negative.
70+
"""
6571
if isinstance(time, (float, int)):
72+
if require_nonnegative and time < 0:
73+
raise ValueError(f"Expected a non-negative duration, but got {time}")
6674
return OQDurationLiteral(time)
6775
if isinstance(time, OQPyExpression):
6876
if isinstance(time.type, (ast.UintType, ast.IntType, ast.FloatType)):

tests/test_directives.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2579,3 +2579,20 @@ def test_function_call(args, assigns_to, expected):
25792579
prog.function_call("my_function", args, assigns_to)
25802580
assert prog.to_qasm() == expected
25812581
_check_respects_type_hints(prog)
2582+
2583+
2584+
def test_delay_with_negative_duration():
2585+
prog = Program()
2586+
port = oqpy.PortVar(name="my_port")
2587+
frame = oqpy.FrameVar(name="my_frame", port=port, frequency=1e9, phase=0)
2588+
with pytest.raises(ValueError, match="Expected a non-negative duration, but got -4e-09"):
2589+
prog.delay(-4e-9, frame)
2590+
2591+
2592+
def test_box_with_negative_duration():
2593+
prog = Program()
2594+
with pytest.raises(ValueError, match="Expected a non-negative duration, but got -4e-09"):
2595+
with Box(prog, -4e-9):
2596+
pass
2597+
2598+

0 commit comments

Comments
 (0)