From 16db4aa87e505011cc8d1ddaee85a132ec0fe8bb Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Fri, 2 Dec 2022 16:09:42 -0500 Subject: [PATCH] Make heuristic score sorting robust in 1q optimization pass In #8197 the Optimize1qGatesDecomposition was updated to be target aware and as part of that a new heuristic scoring was added to determine which decomposition was the best performing and should be used. However, in the case of an error rate of 0.0 the desired behavior was to pick the decomposition which was shortest. In #8197 this was accomplished by just doing `-100 + len(decomposition)` which worked in the general case as long as the gate counts are < 100 (which in practice will always be the case). For robustness this changes the return for the scoring function to be `(error_rate, sequence_length)` to give us the sorting without changing the measured error rate. --- .../optimization/optimize_1q_decomposition.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py b/qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py index 51b21aca7e99..ce595def47d9 100644 --- a/qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +++ b/qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py @@ -112,13 +112,18 @@ 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 = _error(new_circ, self._target, qubit) + if isinstance(new_error, tuple): + error_rate = new_error[0] + else: + error_rate = new_error return ( uncalibrated_and_not_basis_p or ( uncalibrated_p - and _error(new_circ, self._target, qubit) < _error(old_run, self._target, qubit) + and new_error < _error(old_run, self._target, qubit) ) - or np.isclose(_error(new_circ, self._target, qubit), 0) + or np.isclose(error_rate, 0) ) @control_flow.trivial_recurse @@ -189,7 +194,4 @@ def _error(circuit, target, qubit): for inst in circuit ] gate_error = 1 - np.product(gate_fidelities) - if gate_error == 0.0: - return -100 + len(circuit) # prefer shorter circuits among those with zero error - else: - return gate_error + return (gate_error, len(circuit))