Truncating floats in QASM dump alters circuit's functionality
See original GitHub issueInformation
- Qiskit Terra version: 0.18.3 (dates back to 0.14)
- Python version: Any
- Operating system: Any
What is the current behavior?
In #4276, the pi_check
function was introduced for pretty printing the list of parameters when dumping a QuantumCircuit
to qasm
, see
https://github.com/Qiskit/qiskit-terra/blob/637acc0c408d8199dd58780cc3dafabc14e61a0f/qiskit/circuit/instruction.py#L450-L463
This also introduced a fixed truncation (ndigits=8
) of floating point numbers that are not close to any fraction or fraction of pi. However, 8 digits is not enough to uniquely identify a double precision floating point number. You need up to 17 significant digits for that. This leads to the following situation:
Let’s say I have a circuit that contains, e.g., a phase gate with more than 8 significant digits in its rotation angle.
Then, I dump the circuit to a .qasm
file and read that file back into a QuantumCircuit
.
If I compare both unitary functionalities (i.e., the respective unitary matrices), these will no longer be equal due to the numerical error introduced by the truncation.
Steps to reproduce the problem
from qiskit import QuantumCircuit, execute, Aer
qc = QuantumCircuit(1)
qc.p(1/4096, 0)
qasm_str = qc.qasm()
backend = Aer.get_backend('aer_simulator')
qc.save_unitary()
job = execute(qc, backend)
result = job.result()
unitary = result.get_unitary(qc)
qc_qasm = QuantumCircuit.from_qasm_str(qasm_str)
qc_qasm.save_unitary()
job = execute(qc_qasm, backend)
result = job.result()
unitary_qasm = result.get_unitary(qc_qasm)
print(unitary == unitary_qasm)
yields
[[ True True]
[ True False]]
What is the expected behavior?
Merely dumping a file to .qasm
should not alter a circuit’s functionality.
Suggested solutions
A quick fix for this would be to just change the default value for the ndigits
parameter in the respective function call to 17
.
Issue Analytics
- State:
- Created 2 years ago
- Comments:12 (11 by maintainers)
Top GitHub Comments
I get that. But then I would suggest the easiest workaround/fix that does not need any kind of deprecation would just be to change the magic
ndigits
constant in theInstruction.qasm()
from 8 to 17. In addition to that it might make sense to explicitly specify a smallereps
(something in the range of 1e-12 to 1e-14), in order to lessen the impact of the approximation to fractions of pi.In this fashion, no compatibility is broken and the export to OpenQASM 2 gets a lot more accurate / less lossy.
I tend to agree that having lossless-as-possible mode for qasm export is a useful enhancement. Both for the reason of interfacing with external tools, and also for debug purposes.