Qiskit / qiskit

Qiskit is an open-source SDK for working with quantum computers at the level of extended quantum circuits, operators, and primitives.
https://www.ibm.com/quantum/qiskit
Apache License 2.0
5.19k stars 2.35k forks source link

ValueError: too many subscripts in einsum for a circuit containing controlled RZXGate #11989

Open jiannanWang opened 7 months ago

jiannanWang commented 7 months ago

Environment

What is happening?

Running the below code results in the exception copied in the "What should happen" section. I would expect the code to run without error.

This crash happens for num_ctrl_qubits>=9. For num_ctrl_qubits<9, the program hangs for a long time and I need to kill the process.

How can we reproduce the issue?

from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister
from qiskit.circuit.library.standard_gates import RZXGate

qr = QuantumRegister(11, name='qr')
cr = ClassicalRegister(11, name='cr')
qc = QuantumCircuit(qr, cr, name='qc')
qc.append(RZXGate(0.7773868957129396).control(num_ctrl_qubits=9, ctrl_state=0).power(1), qargs=qr, cargs=[])

What should happen?

Traceback (most recent call last):
  File "/mnt/tests/reproduction/reproduce_too_many_subscripts_in_einsum.py", line 7, in <module>
    qc.append(RZXGate(0.7773868957129396).control(num_ctrl_qubits=9, ctrl_state=0).power(1), qargs=qr, cargs=[])
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/anaconda3/envs/qiskit1.0.2/lib/python3.11/site-packages/qiskit/circuit/gate.py", line 81, in power
    return UnitaryGate(Operator(self).power(exponent), label=f"{self.name}^{exponent}")
                       ^^^^^^^^^^^^^^
  File "/root/anaconda3/envs/qiskit1.0.2/lib/python3.11/site-packages/qiskit/quantum_info/operators/operator.py", line 97, in __init__
    self._data = self._init_instruction(data).data
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/anaconda3/envs/qiskit1.0.2/lib/python3.11/site-packages/qiskit/quantum_info/operators/operator.py", line 707, in _init_instruction
    op._append_instruction(instruction)
  File "/root/anaconda3/envs/qiskit1.0.2/lib/python3.11/site-packages/qiskit/quantum_info/operators/operator.py", line 785, in _append_instruction
    self._append_instruction(instruction.operation, qargs=new_qargs)
  File "/root/anaconda3/envs/qiskit1.0.2/lib/python3.11/site-packages/qiskit/quantum_info/operators/operator.py", line 762, in _append_instruction
    op = self.compose(
         ^^^^^^^^^^^^^
  File "/root/anaconda3/envs/qiskit1.0.2/lib/python3.11/site-packages/qiskit/quantum_info/operators/operator.py", line 505, in compose
    Operator._einsum_matmul(tensor, mat, indices, shift, right_mul), final_shape
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/anaconda3/envs/qiskit1.0.2/lib/python3.11/site-packages/qiskit/quantum_info/operators/operator.py", line 693, in _einsum_matmul
    return np.einsum(tensor, indices_tensor, mat, indices_mat)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/anaconda3/envs/qiskit1.0.2/lib/python3.11/site-packages/numpy/core/einsumfunc.py", line 1371, in einsum
    return c_einsum(*operands, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: too many subscripts in einsum

Any suggestions?

No response

jakelishman commented 7 months ago

Right now, all the chained methods on Gate, like control and power do things eagerly and (largely) non-symbolically. This means that your code is attempting to build an 11q matrix and decompose it. It so happens that there are a couple of tensor contractions we do in places that have happened to explode here, but that eager synthesis is the main problem you're seeing.

You can switch to our (somewhat experimental) symbolic representations of control and power operations by passing annotated=True to the Gate.control and Gate.power methods, but beware that at the moment, we'll still be using inefficient syntheses during transpilation for those. We're working on improving that, though - you can see some discussion in #11823.

ShellyGarion commented 7 months ago

I think this method should work for generating a multi-controlled RZ gate:

q_controls = list(range(num_ctrl_qubits))
q_target = num_ctrl_qubits
qc.mcrz(0.7773868957129396, q_controls, q_target)

Sorry, this comment is relevant for RZGate or RXGate, but not directly for RZXGate.

However, as you can decompose RZXGate into CX, RX, RY, RZ and Phase gates - then you can write an efficient synthesis of multi-controlled RZX by calling mcx, mcrx, mcry, mcrz and mcp.