-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Split2QUnitaries assumes node.op is ndarray #12970
Comments
Do you have example code and a traceback showing the error you're hitting? The object model/type should be protecting against this if your custom class is an Looking at the code you're right there is a mismatch with the argument typing and the pass is not accounting for the case it should be passing |
Thanks for the report. Do you have a small producer script that shows the problem? I think I know what's happening, but it'd be good to be certain. The type hint of the decomposer isn't really correct, and it's actually anything that can be cast to an array, which is true of most gates - but there's no requirement that a user gate has a matrix form. (Fwiw, if you want to, give your gate a |
This reproduces the problem: import numpy as np
import qiskit
from qiskit import QuantumCircuit
from qiskit.circuit import Gate, QuantumCircuit
class MyGate(Gate):
def __init__(self):
super().__init__("mygate", 2, [])
def to_matrix(self):
return np.eye(4, dtype=complex)
# return np.eye(4, dtype=float)
def mygate(self, qubit1, qubit2):
return self.append(MyGate(), [qubit1, qubit2], [])
QuantumCircuit.mygate = mygate
qc = QuantumCircuit(2)
qc.mygate(0, 1)
basis_gates = [
"mygate",
]
circuit = qiskit.transpile(qc, basis_gates=basis_gates, optimization_level=2) gives: File "/home/amos/miniconda3/envs/py311/lib/python3.11/site-packages/qiskit/transpiler/passes/optimization/split_2q_unitaries.py", line 54, in run
decomp = TwoQubitWeylDecomposition(node.op, fidelity=self.requested_fidelity)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/amos/miniconda3/envs/py311/lib/python3.11/site-packages/qiskit/synthesis/two_qubit/two_qubit_decompose.py", line 191, in __init__
unitary_matrix = np.asarray(unitary_matrix, dtype=complex)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: must be real number, not MyGate Note: the dtype of my actual matrix needs to be |
Thanks! As an immediate workaround, you should rename your That said, there's still no reason for the code to crash on this example, and we can get |
If I try this: # def to_matrix(self):
def __array__(self, dtype=None, copy=None):
return np.eye(4, dtype=complex)
# return np.eye(4, dtype=float) if that's approximately what you meant, then I get a different exception:
Probably that's just due to how crude my example is. I'm ok with my workaround of lowering the optimization level because this is just old test code I've been lugging around and should probably just delete. Thanks for the link -- that page didn't exist years ago when I wrote these gates! 😁 |
Thanks - out of curiosity, would (About the subclassing docs: yeah, they just got written very recently. A bit embarrassing that it took us as long as this, really...) |
Yes, the specific unit test would pass if if my original code I switched: - def to_matrix(self):
+ def __array__(self, *args, **kwargs): |
Ok, if it previously passed at O2 and now doesn't, then it feels like we've made a mistake in the preset pass-manager logic about when it's acceptable to run |
I think that this transpiler exception comes from the change in the internal You can fix the example by simply completing the basis set:
This was not the case in 1.1 because the passes were run differently in the cases where a target wasn't explicitly provided (and now all passes follow the "target path"), but this behavior wasn't super clearly documented. I will think of what we can do to better document edge cases like this. |
Elena: for the input circuit, the basis |
To add some more details, this does indeed break because
|
That's an odd edge case to consider. because it means there is a 2q basis gate that is the product of single qubit gates. I'm not sure what the correct/expected behavior is in that case. My gut is that we should always be breaking up gates like this, but I never considered a target that included such a gate. |
FWIW, in my real code, I have several gates like this one here that are actually 2q. |
So currently we run from qiskit import QuantumCircuit, transpile
from qiskit.circuit.library import *
gate = PauliGate("XX")
qc = QuantumCircuit(2)
qc.append(gate, [0, 1])
basis_gates = ["x"] # gate decomposes into XX
circuit = transpile(qc, basis_gates=basis_gates, optimization_level=1) # works
circuit = transpile(qc, basis_gates=basis_gates, optimization_level=2) # fails -- cannot map U to the basis So maybe we should disable |
The
TwoQubitWeylDecomposition
says it only accepts ndarray:qiskit/qiskit/synthesis/two_qubit/two_qubit_decompose.py
Lines 184 to 190 in 713ab38
However this line is passing a node op:
qiskit/qiskit/transpiler/passes/optimization/split_2q_unitaries.py
Line 53 in 713ab38
some of my code is now failing in qiskit 1.2.0 because in some of my unit tests, this is an
Instruction
which is, for what it's worth, not a gate in the qiskit library.My problem goes away if I replace this:
in my test with:
Linking associated PRs:
#12727
#12898
The text was updated successfully, but these errors were encountered: