Qiskit / qiskit-ibm-runtime

IBM Client for Qiskit Runtime
https://docs.quantum.ibm.com/api/qiskit-ibm-runtime
Apache License 2.0
148 stars 155 forks source link

Cannot transpile dynamic circuits with simulator backends #1295

Open jyu00 opened 1 year ago

jyu00 commented 1 year ago

Information

What is the current behavior?

Transpiling a dynamic circuit works with a real backend:

from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister, transpile

qr = QuantumRegister(2)
cr = ClassicalRegister(2)

qc_if_else = QuantumCircuit(qr, cr)

qc_if_else.h(0)
qc_if_else.measure(qr[0], cr[1])

with qc_if_else.if_test((cr[0], True)) as else_:
    qc_if_else.x(qr[0])
with else_:
    qc_if_else.x(qr[1])

qc_if_else.measure(qr[0], cr[1])

from qiskit_ibm_provider import IBMProvider

provider = IBMProvider()
backend = provider.get_backend("ibm_sherbrooke")
qc_if_else_transpiled = transpile(qc_if_else, backend)

But not with ibmq_qasm_simulator:

sim_backend = provider.get_backend("ibmq_qasm_simulator")
qc_if_else_transpiled = transpile(qc_if_else, sim_backend)

TranspilerError: "The control-flow construct 'if_else' is not supported by the backend."

It also doesn't work with any backend from qiskit-ibm-runtime

Steps to reproduce the problem

See above.

What is the expected behavior?

Transpilation should work.

Suggested solutions

jyu00 commented 3 months ago

I think this was fixed when we did the ISA circuit change, but someone should test it.

kt474 commented 3 months ago

Getting the same error with ibmq_qasm_simulator: TranspilerError: "The control-flow construct 'if_else' is not supported by the backend."

jyu00 commented 2 months ago

We should check if the backend config file has those instructions. If not, then IQP needs to update them

kt474 commented 1 month ago

Can confirm that the ibmq_qasm_simulator configuration does not have any supported instructions:

Also left a comment in sw-api-iqp issue 1252

{'_data': {'allow_q_object': True},
 'backend_name': 'ibmq_qasm_simulator',
 'backend_version': '0.1.547',
 'n_qubits': 32,
 'basis_gates': ['u1',
  'u2',
  'u3',
  'u',
  'p',
  'r',
  'rx',
  'ry',
  'rz',
  'id',
  'x',
  'y',
  'z',
  'h',
  's',
  'sdg',
  'sx',
  't',
  'tdg',
  'swap',
  'cx',
  'cy',
  'cz',
  'csx',
  'cp',
  'cu1',
  'cu2',
  'cu3',
  'rxx',
  'ryy',
  'rzz',
  'rzx',
  'ccx',
  'cswap',
  'mcx',
  'mcy',
  'mcz',
  'mcsx',
  'mcp',
  'mcu1',
  'mcu2',
  'mcu3',
  'mcrx',
  'mcry',
  'mcrz',
  'mcr',
  'mcswap',
  'unitary',
  'diagonal',
  'multiplexer',
  'initialize',
  'kraus',
  'roerror',
  'delay'],
 'gates': [GateConfig(u1, ['lam'], gate u1(lam) q { U(0,0,lam) q; }, True, 'Single-qubit gate [[1, 0], [0, exp(1j*lam)]]'),
  GateConfig(u2, ['phi', 'lam'], gate u2(phi,lam) q { U(pi/2,phi,lam) q; }, True, 'Single-qubit gate [[1, -exp(1j*lam)], [exp(1j*phi), exp(1j*(phi+lam))]]/sqrt(2)'),
  GateConfig(u3, ['theta', 'phi', 'lam'], gate u3(theta,phi,lam) q { U(theta,phi,lam) q; }, True, 'Single-qubit gate with three rotation angles'),
  GateConfig(u, ['theta', 'phi', 'lam'], gate u(theta,phi,lam) q { U(theta,phi,lam) q; }, True, 'Single-qubit gate with three rotation angles'),
  GateConfig(p, ['lam'], gate p(lam) q { U(0,0,lam) q; }, True, 'Single-qubit rotation about the Z axis'),
  GateConfig(r, ['theta', 'phi'], gate r(theta,phi) q { U(theta,phi-pi/2,-phi+pi/2) q; }, True, 'Rotation around an axis in x-y plane'),
  GateConfig(rx, ['theta'], gate rx(theta) q { U(theta,-pi/2,pi/2) q; }, True, 'Rotation around the X axis'),
  GateConfig(ry, ['theta'], gate ry(theta) q { U(theta,0,0) q; }, True, 'Rotation around the Y axis'),
  GateConfig(rz, ['phi'], gate rz(phi) q { U(0,0,phi) q; }, True, 'Rotation around the Z axis'),
  GateConfig(cx, [], gate cx c,t { CX c,t; }, True, 'Two-qubit Controlled-NOT gate'),
  GateConfig(cy, [], gate cy a,b { U(0,0,-pi/2) b; CX a,b; U(0,0,pi/2) b; }, True, 'Two-qubit Controlled-Y gate'),
  GateConfig(cz, [], gate cz a,b { U(pi/2,0,pi) b; CX a,b; U(pi/2,0,pi) b; }, True, 'Two-qubit Controlled-Z gate'),
  GateConfig(csx, [], gate csx a,b { U(pi/2,0,pi) b; CX a,b; U(pi/2,0,pi) b; U(0,0,lam/2) a; CX a,b; U(0,0,-lam/2) b; CX a,b; U(0,0,lam/2) b; U(pi/2,0,pi) b; }, True, 'Two-qubit Controlled Sqrt(X) gate'),
  GateConfig(cp, [], gate cp(theta) a,b { U(0,0,theta/2) a; CX a,b; U(0,0,-theta/2) b; CX a,b; U(0,0,theta/2) b; }, True, 'Controlled-Phase gate'),
  GateConfig(id, [], gate id a { U(0,0,0) a; }, True, 'Single-qubit identity gate'),
  GateConfig(x, [], gate x a { U(pi,0,pi) a; }, True, 'Single-qubit Pauli-X gate'),
  GateConfig(y, [], gate y a { U(pi,pi/2,pi/2) a; }, True, 'Single-qubit Pauli-Y gate'),
  GateConfig(z, [], gate z a { U(0,0,pi) a; }, True, 'Single-qubit Pauli-Z gate'),
  GateConfig(h, [], gate h q { U(pi/2,0,pi) q; }, True, 'Single-qubit Hadamard gate'),
  GateConfig(s, [], gate s q { U(0,0,pi/2) q; }, True, 'Single-qubit phase gate'),
  GateConfig(sdg, [], gate sdg q { U(0,0,-pi/2) q; }, True, 'Single-qubit adjoint phase gate'),
  GateConfig(sx, [], gate sx q { U(pi/2,-pi/2,pi/2) q; }, True, 'Single-qubit Sqrt(X) gate'),
  GateConfig(t, [], gate t q { U(0,0,pi/4) q; }, True, 'Single-qubit T gate'),
  GateConfig(tdg, [], gate t q { U(0,0,-pi/4) q; }, True, 'Single-qubit adjoint T gate'),
  GateConfig(swap, [], TODO, True, 'Two-qubit SWAP gate'),
  GateConfig(ccx, [], TODO, True, 'Three-qubit Toffoli gate'),
  GateConfig(cswap, [], TODO, True, 'Three-qubit Fredkin (controlled-SWAP) gate'),
  GateConfig(unitary, ['matrix'], unitary(matrix) q1, q2,..., True, 'N-qubit unitary gate. The parameter is the N-qubit matrix to apply.'),
  GateConfig(diagonal, ['diag_elements'], TODO, True, 'N-qubit diagonal unitary gate. The parameters are the diagonal entries of the N-qubit matrix to apply.'),
  GateConfig(initialize, ['vector'], initialize(vector) q1, q2,..., False, 'N-qubit state initialize. Resets qubits then sets statevector to the parameter vector.'),
  GateConfig(cu1, ['lam'], gate cu1(lam) a,b { U(0,0,lam/2) a; CX a,b; U(0,0,-lam/2) b; CX a,b; U(0,0,lam/2) b; }, True, 'Two-qubit Controlled-u1 gate'),
  GateConfig(cu2, ['phi', 'lam'], TODO, True, 'Two-qubit Controlled-u2 gate'),
  GateConfig(cu3, ['theta', 'phi', 'lam'], TODO, True, 'Two-qubit Controlled-u3 gate'),
  GateConfig(rxx, ['theta'], gate rxx a,b { U(pi/2,0,pi) a; U(pi/2,0,pi) b; CX a,b; U(0,0,phi) b; CX a,b; U(pi/2,0,pi) b; U(pi/2,0,pi) a; }, True, 'Two-qubit XX-rotation gate'),
  GateConfig(ryy, ['theta'], gate ryy a,b { U(pi/2,-pi/2,pi/2) a; U(pi/2,-pi/2,pi/2) b; CX a,b; U(0,0,theta) q; CX a,b; U(-pi/2,-pi/2,pi/2) a; U(-pi/2,-pi/2,pi/2) b; }, True, 'Two-qubit YY-rotation gate'),
  GateConfig(rzz, ['theta'], gate rzz a,b { CX a,b; U(0,0,theta) b; CX a,b; }, True, 'Two-qubit ZZ-rotation gate'),
  GateConfig(rzx, ['theta'], gate rzx a,b { U(pi/2,0,pi) b; CX a,b; U(0,0,theta) b; CX a,b; U(pi/2,0,pi) b; }, True, 'Two-qubit ZX-rotation gate'),
  GateConfig(mcx, [], TODO, True, 'N-qubit multi-controlled-X gate'),
  GateConfig(mcy, [], TODO, True, 'N-qubit multi-controlled-Y gate'),
  GateConfig(mcz, [], TODO, True, 'N-qubit multi-controlled-Z gate'),
  GateConfig(mcsx, [], TODO, True, ''),
  GateConfig(mcp, ['lam'], TODO, True, 'Multi-controlled-Phase gate'),
  GateConfig(mcu1, ['lam'], TODO, True, 'N-qubit multi-controlled-u1 gate'),
  GateConfig(mcu2, ['phi', 'lam'], TODO, True, 'N-qubit multi-controlled-u2 gate'),
  GateConfig(mcu3, ['theta', 'phi', 'lam'], TODO, True, 'N-qubit multi-controlled-u3 gate'),
  GateConfig(mcrx, ['theta'], TODO, True, 'Multiple-Controlled X rotation gate'),
  GateConfig(mcry, ['theta'], TODO, True, 'Multiple-Controlled Y rotation gate'),
  GateConfig(mcrz, ['theta'], TODO, True, 'Multiple-Controlled Z rotation gate'),
  GateConfig(mcr, [], TODO, True, 'Multiple-Controlled rotation gate'),
  GateConfig(mcswap, [], TODO, True, 'N-qubit multi-controlled-SWAP gate'),
  GateConfig(multiplexer, ['mat1', 'mat2', '...'], TODO, True, 'N-qubit multi-plexer gate. The input parameters are the gates for each value.'),
  GateConfig(kraus, ['mat1', 'mat2', '...'], TODO, True, 'N-qubit Kraus error instruction. The input parameters are the Kraus matrices.'),
  GateConfig(delay, [], TODO, True, 'Delay instruction'),
  GateConfig(roerror, ['matrix'], TODO, False, 'N-bit classical readout error instruction. The input parameter is the readout error probability matrix.')],
 'local': False,
 'simulator': True,
 'conditional': True,
 'open_pulse': False,
 'memory': True,
 'max_shots': 100000,
 'coupling_map': None,
 'dynamic_reprate_enabled': False,
 'max_experiments': 300,
 'online_date': datetime.datetime(2019, 5, 2, 8, 15, tzinfo=tzutc())}