Skip to content

Commit

Permalink
Don't substitute ideal gates in target with Optimize1qGatesDecomposit…
Browse files Browse the repository at this point in the history
…ion (#11351) (#11359)

* Don't substitute ideal gates in target with Optimize1qGatesDecomposition

This commit fixes an issue in Optimize1qGatesDecomposition where the
pass would defer to synthesized gates if the output from synthesis was
ideal even if the input gate was also ideal. This typically comes up in
simulators where there are no error rates for any gates and everything
is listed as ideal. This would cause the transpiler to translate gates
unnecessarily which was unexpected. This commit fixes this by adding an
additional check to the subsitution condition to ensure we're only
substituting a gate if it's not in the target (when they're all ideal).

Fixes #10568

* Update releasenotes/notes/fix-optimize-1q-sim-407b88e45e6062b6.yaml

Co-authored-by: Jake Lishman <jake@binhbar.com>

* Update qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py

* Fix formatting

---------

Co-authored-by: Jake Lishman <jake@binhbar.com>
(cherry picked from commit f12db3b)

Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
  • Loading branch information
mergify[bot] and mtreinish authored Dec 1, 2023
1 parent a2de351 commit 908e555
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,16 @@ def _substitution_checks(self, dag, old_run, new_circ, basis, qubit):
# if we're outside of the basis set, we're obligated to logically decompose.
# if we're outside of the set of gates for which we have physical definitions,
# then we _try_ to decompose, using the results if we see improvement.
new_error = 0.0
old_error = 0.0
if not uncalibrated_and_not_basis_p:
new_error = self._error(new_circ, qubit)
old_error = self._error(old_run, qubit)

return (
uncalibrated_and_not_basis_p
or (uncalibrated_p and self._error(new_circ, qubit) < self._error(old_run, qubit))
or math.isclose(self._error(new_circ, qubit)[0], 0)
or (uncalibrated_p and new_error < old_error)
or (math.isclose(new_error[0], 0) and not math.isclose(old_error[0], 0))
)

@control_flow.trivial_recurse
Expand Down
10 changes: 10 additions & 0 deletions releasenotes/notes/fix-optimize-1q-sim-407b88e45e6062b6.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
fixes:
- |
Fixed an issue with the :class:`.Optimize1qGatesDecomposition` transpiler
pass where it would potentially resynthesize a single ideal (meaning the
error rate is ``0.0``) gate which was present in the :class:`.Target`. This
is now fixed so the pass :class:`.Optimize1qGatesDecomposition` will defer
to the circuit's gate if the error rate (which includes number of gates)
are the same.
Fixed `#10568 <https://github.com/Qiskit/qiskit/issues/10568>`__
14 changes: 14 additions & 0 deletions test/python/transpiler/test_optimize_1q_decomposition.py
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,20 @@ def test_nested_control_flow(self):
result = passmanager.run(test)
self.assertEqual(result, expected)

def test_prefer_no_substitution_if_all_ideal(self):
"""Test that gates are not substituted if all our ideal gates in basis."""
target = Target(num_qubits=1)
target.add_instruction(HGate(), {(0,): InstructionProperties(error=0)})
target.add_instruction(
UGate(Parameter("a"), Parameter("b"), Parameter("c")),
{(0,): InstructionProperties(error=0)},
)
qc = QuantumCircuit(1)
qc.h(0)
opt_pass = Optimize1qGatesDecomposition(target)
res = opt_pass(qc)
self.assertEqual(res, qc)


if __name__ == "__main__":
unittest.main()

0 comments on commit 908e555

Please sign in to comment.