Repository: PennyLaneAI/pennylane
Pull request #2071 (2022-01-05 14:02:55)

Fix openqasm test
Presumably due to a change in precision handling of a dependency, a qasm test started failing because of a different string representation of a 15th digit.

This PR adds a precision argument to the `to_openqasm` method, and uses it in the test. A test for the argument is also added.

mariaschuld: @mlxd I just assume in good faith that the CI passes in 1000 hours - if not ignore the review request and I'll fix

codecov[bot]: # [Codecov](https://codecov.io/gh/PennyLaneAI/pennylane/pull/2071?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) Report
> Merging [#2071](https://codecov.io/gh/PennyLaneAI/pennylane/pull/2071?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) (4fb6e86) into [master](https://codecov.io/gh/PennyLaneAI/pennylane/commit/b44998095806e75a07407ec41d5f388efd722b5b?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) (b449980) will **increase** coverage by `2.79%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/PennyLaneAI/pennylane/pull/2071/graphs/tree.svg?width=650&height=150&src=pr&token=9S3YzlUgGk&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI)](https://codecov.io/gh/PennyLaneAI/pennylane/pull/2071?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI)

```diff
@@            Coverage Diff             @@
##           master    #2071      +/-   ##
==========================================
+ Coverage   94.31%   97.10%   +2.79%     
==========================================
  Files         226      226              
  Lines       17298    17354      +56     
==========================================
+ Hits        16315    16852     +537     
+ Misses        983      502     -481     
```


| [Impacted Files](https://codecov.io/gh/PennyLaneAI/pennylane/pull/2071?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) | Coverage Δ | |
|---|---|---|
| [pennylane/tape/tape.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/2071/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL3RhcGUvdGFwZS5weQ==) | `98.95% <100.00%> (+0.02%)` | :arrow_up: |
| [pennylane/vqe/vqe.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/2071/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL3ZxZS92cWUucHk=) | `100.00% <0.00%> (ø)` | |
| [pennylane/drawer/tape\_mpl.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/2071/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL2RyYXdlci90YXBlX21wbC5weQ==) | `100.00% <0.00%> (ø)` | |
| [pennylane/transforms/control.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/2071/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL3RyYW5zZm9ybXMvY29udHJvbC5weQ==) | `100.00% <0.00%> (ø)` | |
| [pennylane/ops/qubit/attributes.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/2071/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL29wcy9xdWJpdC9hdHRyaWJ1dGVzLnB5) | `100.00% <0.00%> (ø)` | |
| [pennylane/optimize/shot\_adaptive.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/2071/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL29wdGltaXplL3Nob3RfYWRhcHRpdmUucHk=) | `100.00% <0.00%> (ø)` | |
| [pennylane/gradients/parameter\_shift.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/2071/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL2dyYWRpZW50cy9wYXJhbWV0ZXJfc2hpZnQucHk=) | `100.00% <0.00%> (ø)` | |
| [pennylane/drawer/representation\_resolver.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/2071/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL2RyYXdlci9yZXByZXNlbnRhdGlvbl9yZXNvbHZlci5weQ==) | `99.43% <0.00%> (+<0.01%)` | :arrow_up: |
| [pennylane/\_qubit\_device.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/2071/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL19xdWJpdF9kZXZpY2UucHk=) | `98.70% <0.00%> (+<0.01%)` | :arrow_up: |
| [pennylane/queuing.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/2071/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL3F1ZXVpbmcucHk=) | `98.83% <0.00%> (+0.01%)` | :arrow_up: |
| ... and [27 more](https://codecov.io/gh/PennyLaneAI/pennylane/pull/2071/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/PennyLaneAI/pennylane/pull/2071?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/PennyLaneAI/pennylane/pull/2071?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI). Last update [b449980...4fb6e86](https://codecov.io/gh/PennyLaneAI/pennylane/pull/2071?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).


Patch:
diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md
index 16cf40bed..b01b28dbc 100644
--- a/doc/releases/changelog-dev.md
+++ b/doc/releases/changelog-dev.md
@@ -147,6 +147,10 @@
 
 <h3>Improvements</h3>
 
+* A precision argument has been added to the tape's ``to_openqasm`` function 
+  to control the precision of parameters.
+  [(#2071)](https://github.com/PennyLaneAI/pennylane/pull/2071)
+
 * Insert transform now supports adding operation after or before certain specific gates.
   [(#1980)](https://github.com/PennyLaneAI/pennylane/pull/1980)
 
diff --git a/pennylane/tape/tape.py b/pennylane/tape/tape.py
index 63f02cc9c..e3f3fcb76 100644
--- a/pennylane/tape/tape.py
+++ b/pennylane/tape/tape.py
@@ -1130,7 +1130,7 @@ class QuantumTape(AnnotatedQueue):
             max_length=max_length,
         )
 
-    def to_openqasm(self, wires=None, rotations=True, measure_all=True):
+    def to_openqasm(self, wires=None, rotations=True, measure_all=True, precision=None):
         """Serialize the circuit as an OpenQASM 2.0 program.
 
         Measurements are assumed to be performed on all qubits in the computational basis. An
@@ -1150,6 +1150,7 @@ class QuantumTape(AnnotatedQueue):
                 measured wires such that they are in the eigenbasis of the circuit observables.
             measure_all (bool): whether to perform a computational basis measurement on all qubits
                 or just those specified in the tape
+            precision (int): decimal digits to display for parameters
 
         Returns:
             str: OpenQASM serialization of the circuit
@@ -1200,7 +1201,11 @@ class QuantumTape(AnnotatedQueue):
             if op.num_params > 0:
                 # If the operation takes parameters, construct a string
                 # with parameter values.
-                params = "(" + ",".join([str(p) for p in op.parameters]) + ")"
+                if precision is not None:
+                    params = "(" + ",".join([f"{p:.{precision}}" for p in op.parameters]) + ")"
+                else:
+                    # use default precision
+                    params = "(" + ",".join([str(p) for p in op.parameters]) + ")"
 
             qasm_str += f"{gate}{params} {wire_labels};\n"
 


Test patch:
diff --git a/tests/circuit_graph/test_qasm.py b/tests/circuit_graph/test_qasm.py
index ebd7d14a1..d6c6961c1 100644
--- a/tests/circuit_graph/test_qasm.py
+++ b/tests/circuit_graph/test_qasm.py
@@ -162,12 +162,12 @@ class TestToQasmUnitTests:
         with qml.tape.QuantumTape() as circuit1:
             qml.QubitStateVector(psi, wires=[0, 1])
 
-        qasm1 = circuit1.to_openqasm()
+        qasm1 = circuit1.to_openqasm(precision=11)
 
         with qml.tape.QuantumTape() as circuit2:
             qml.QubitStateVector.decomposition(psi, wires=[0, 1])
 
-        qasm2 = circuit2.to_openqasm(wires=Wires([0, 1]))
+        qasm2 = circuit2.to_openqasm(wires=Wires([0, 1]), precision=11)
 
         expected = dedent(
             """\
@@ -175,18 +175,19 @@ class TestToQasmUnitTests:
             include "qelib1.inc";
             qreg q[2];
             creg c[2];
-            ry(1.5707963267948968) q[0];
-            ry(1.5707963267948968) q[1];
+            ry(1.5707963268) q[0];
+            ry(1.5707963268) q[1];
             cx q[0],q[1];
             cx q[0],q[1];
             cx q[0],q[1];
-            rz(3.141592653589793) q[1];
+            rz(3.1415926536) q[1];
             cx q[0],q[1];
             measure q[0] -> c[0];
             measure q[1] -> c[1];
             """
         )
 
+        # different
         assert qasm1 == expected
         assert qasm1 == qasm2
 
@@ -557,7 +558,7 @@ class TestQNodeQasmIntegrationTests:
 
         # construct the qnode circuit
         qnode(state=np.array([1, -1, -1, 1]) / np.sqrt(4))
-        res = qnode.qtape.to_openqasm()
+        res = qnode.qtape.to_openqasm(precision=11)
 
         expected = dedent(
             """\
@@ -565,12 +566,12 @@ class TestQNodeQasmIntegrationTests:
             include "qelib1.inc";
             qreg q[2];
             creg c[2];
-            ry(1.5707963267948968) q[0];
-            ry(1.5707963267948968) q[1];
+            ry(1.5707963268) q[0];
+            ry(1.5707963268) q[1];
             cx q[0],q[1];
             cx q[0],q[1];
             cx q[0],q[1];
-            rz(3.141592653589793) q[1];
+            rz(3.1415926536) q[1];
             cx q[0],q[1];
             measure q[0] -> c[0];
             measure q[1] -> c[1];
@@ -699,6 +700,31 @@ class TestQNodeQasmIntegrationTests:
 
         assert res == expected
 
+    def test_precision(self):
+        """Test that the QASM serializer takes into account the desired precision."""
+        dev = qml.device("default.qubit", wires=["a"])
+
+        @qml.qnode(dev)
+        def qnode():
+            qml.RX(np.pi, wires="a")
+            return qml.expval(qml.PauliZ("a"))
+
+        qnode()
+        res = qnode.qtape.to_openqasm(precision=4)
+
+        expected = dedent(
+            """\
+            OPENQASM 2.0;
+            include "qelib1.inc";
+            qreg q[1];
+            creg c[1];
+            rx(3.142) q[0];
+            measure q[0] -> c[0];
+            """
+        )
+
+        assert res == expected
+
 
 @pytest.mark.slow
 class TestQASMConformanceTests: