Skip to content

Commit

Permalink
Fix UnitarySynthesis with target that contains custom gates (Qiskit#9677
Browse files Browse the repository at this point in the history
)

* Fix UnitarySynthesis with target that contains custom gates

Since Qiskit#9175 merged the UnitarySynthesis pass has been updated to
consider multiple different potential target bases and select the best
performing synthesis output found. When UnitarySynthesis is provided a
Target object this involves querying the target for the error rates and
duration of the instructions used and determining which bases are valid.
As part of this lookup the Operator for the 2q gates in the target is
needed to determine the characteristics of the 2q gates. However, the
code for doing this wasn't considering that some operations in the
target might not have sufficient information to build a unitary
representation of the operation. This could come up with the use of
custom opaque gates in the target that don't have a definition defined
or a matrix defined. This commit fixes this oversight and handles the
case where building an Operator for the gate fails.

Related to #9675 (the underlying issue is in the qiskit-ibm-runtime
package for not mapping the "ecr" string to the "ECRGate" object, so
this won't close that issue).

* Fix lint

* Only run Operator construction under try block

The error we're trying to catch and handle is if a gate object doesn't
have sufficient information to get it's matrix. This commit updates the
try block to only run on the Operator construction so we don't
potentially mas errors in the TwoQubitWeylDecomposition construction.

---------

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
mtreinish and mergify[bot] authored Mar 3, 2023
1 parent 4005362 commit 258b4b5
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 3 deletions.
13 changes: 11 additions & 2 deletions qiskit/transpiler/passes/synthesis/unitary_synthesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
)
from qiskit.providers.models import BackendProperties
from qiskit.circuit.library.standard_gates import get_standard_gate_name_mapping
from qiskit.exceptions import QiskitError


KAK_GATE_NAMES = {
Expand Down Expand Up @@ -635,11 +636,19 @@ def _decomposer_2q_from_target(self, target, qubits, approximation_degree):
decomposers = []

def is_supercontrolled(gate):
kak = TwoQubitWeylDecomposition(Operator(gate).data)
try:
operator = Operator(gate)
except QiskitError:
return False
kak = TwoQubitWeylDecomposition(operator.data)
return isclose(kak.a, pi / 4) and isclose(kak.c, 0.0)

def is_controlled(gate):
kak = TwoQubitWeylDecomposition(Operator(gate).data)
try:
operator = Operator(gate)
except QiskitError:
return False
kak = TwoQubitWeylDecomposition(operator.data)
return isclose(kak.b, 0.0) and isclose(kak.c, 0.0)

# possible supercontrolled decomposers (i.e. TwoQubitBasisDecomposer)
Expand Down
23 changes: 22 additions & 1 deletion test/python/transpiler/test_unitary_synthesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
RXXGate,
)
from qiskit.circuit.controlflow import IfElseOp
from qiskit.circuit import Parameter
from qiskit.circuit import Parameter, Gate


@ddt
Expand Down Expand Up @@ -836,6 +836,27 @@ def test_unitary_synthesis_with_ideal_and_variable_width_ops(self):
result_qc = dag_to_circuit(result_dag)
self.assertEqual(result_qc, QuantumCircuit(2))

def test_unitary_synthesis_custom_gate_target(self):
qc = QuantumCircuit(2)
qc.unitary(np.eye(4), [0, 1])
dag = circuit_to_dag(qc)

class CustomGate(Gate):
"""Custom Opaque Gate"""

def __init__(self):
super().__init__("custom", 2, [])

target = Target(num_qubits=2)
target.add_instruction(
UGate(Parameter("t"), Parameter("p"), Parameter("l")), {(0,): None, (1,): None}
)
target.add_instruction(CustomGate(), {(0, 1): None, (1, 0): None})
unitary_synth_pass = UnitarySynthesis(target=target)
result_dag = unitary_synth_pass.run(dag)
result_qc = dag_to_circuit(result_dag)
self.assertEqual(result_qc, QuantumCircuit(2))


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

0 comments on commit 258b4b5

Please sign in to comment.