Skip to content

Commit

Permalink
Force decimal points in OpenQASM 2 floats (#10532)
Browse files Browse the repository at this point in the history
* Force decimal points in OpenQASM 2 floats

The letter of the OpenQASM 2 specification has a regex defining
floating-point literals that requires a decimal point, even in the
presence of an exponential component.  This is unusual for most
programming languages, but Qiskit's exporter should follow the spec as
close as we can to increase interop.  Our parser accepts floats with an
exponent and no decimal point as a minor syntax extension, unless in
strict mode.

* Simplify English
  • Loading branch information
jakelishman committed Jul 31, 2023
1 parent c8552f6 commit 4722c50
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 6 deletions.
11 changes: 5 additions & 6 deletions qiskit/circuit/tools/pi_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,11 @@ def normalize(single_inpt):
str_out = f"{neg_str}{numer}/{denom}{pi}"
return str_out

# Nothing found
if ndigits is None:
str_out = "{}".format(single_inpt)
else:
str_out = "{:.{}g}".format(single_inpt, ndigits)
return str_out
# Nothing found. The '#' forces a decimal point to be included, which OQ2 needs, but other
# formats don't really.
if output == "qasm":
return f"{single_inpt:#}" if ndigits is None else f"{single_inpt:#.{ndigits}g}"
return f"{single_inpt}" if ndigits is None else f"{single_inpt:.{ndigits}g}"

complex_inpt = complex(inpt)
real, imag = map(normalize, [complex_inpt.real, complex_inpt.imag])
Expand Down
8 changes: 8 additions & 0 deletions releasenotes/notes/qasm2-float-decimal-76b44281d9249f7a.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
fixes:
- |
Angles in the OpenQASM 2 exporter (:func:`.QuantumCircuit.qasm`) will now always include a
decimal point, for example in the case of ``1.e-5``. This is required by a strict interpretation of the
floating-point-literal specification in OpenQASM 2. Qiskit's OpenQASM 2 parser
(:func:`.qasm2.load` and :func:`~.qasm2.loads`) is more permissive by default, and will allow
``1e-5`` without the decimal point unless in ``strict`` mode.
14 changes: 14 additions & 0 deletions test/python/circuit/test_circuit_qasm.py
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,20 @@ def test_empty_barrier(self):
qreg qr1[2];
qreg qr2[3];
barrier qr1[0],qr1[1],qr2[0],qr2[1],qr2[2];
"""
self.assertEqual(qc.qasm(), expected)

def test_small_angle_valid(self):
"""Test that small angles do not get converted to invalid OQ2 floating-point values."""
# OQ2 _technically_ requires a decimal point in all floating-point values, even ones that
# are followed by an exponent.
qc = QuantumCircuit(1)
qc.rx(0.000001, 0)
expected = """\
OPENQASM 2.0;
include "qelib1.inc";
qreg q[1];
rx(1.e-06) q[0];
"""
self.assertEqual(qc.qasm(), expected)

Expand Down

0 comments on commit 4722c50

Please sign in to comment.