It seems like I can use https://qiskit.org/documentation/stubs/qiskit.circuit.random.random_circuit.html but I would like to control the gates that are allowed.
What is an efficient way to make random circuits with a fixed set of gates?
It seems like I can use https://qiskit.org/documentation/stubs/qiskit.circuit.random.random_circuit.html but I would like to control the gates that are allowed.
What is an efficient way to make random circuits with a fixed set of gates?
I think you should report of "feature request" issue if you have a good use case for this. It should not be hard to implement and I could help with it.
If by any chance your fixed set of gates is based on the amount of qubits involved in gate, you can control that with max_operands
. For example, you can exclude CCXGate
and CSwapGate
(3-qubit operands) with max_operand=2
.
If this is not the case, the source code for random_circuit
seems straightforward to modify for your need. You can remove or add the gates from *_q_ops
and *_param
variables on top.
def random_circuit(num_qubits, depth, max_operands=3, measure=False,
conditional=False, reset=False, seed=None):
if max_operands < 1 or max_operands > 3:
raise CircuitError("max_operands must be between 1 and 3")
one_q_ops = [IGate, U1Gate, U2Gate, U3Gate, XGate, YGate, ZGate,
HGate, SGate, SdgGate, TGate, TdgGate, RXGate, RYGate, RZGate]
one_param = [U1Gate, RXGate, RYGate, RZGate, RZZGate, CU1Gate, CRZGate]
two_param = [U2Gate]
three_param = [U3Gate, CU3Gate]
two_q_ops = [CXGate, CYGate, CZGate, CHGate, CRZGate,
CU1Gate, CU3Gate, SwapGate, RZZGate]
three_q_ops = [CCXGate, CSwapGate]
qr = QuantumRegister(num_qubits, 'q')
qc = QuantumCircuit(num_qubits)
if measure or conditional:
cr = ClassicalRegister(num_qubits, 'c')
qc.add_register(cr)
if reset:
one_q_ops += [Reset]
if seed is None:
seed = np.random.randint(0, np.iinfo(np.int32).max)
rng = np.random.default_rng(seed)
# apply arbitrary random operations at every depth
for _ in range(depth):
# choose either 1, 2, or 3 qubits for the operation
remaining_qubits = list(range(num_qubits))
while remaining_qubits:
max_possible_operands = min(len(remaining_qubits), max_operands)
num_operands = rng.choice(range(max_possible_operands)) + 1
rng.shuffle(remaining_qubits)
operands = remaining_qubits[:num_operands]
remaining_qubits = [q for q in remaining_qubits if q not in operands]
if num_operands == 1:
operation = rng.choice(one_q_ops)
elif num_operands == 2:
operation = rng.choice(two_q_ops)
elif num_operands == 3:
operation = rng.choice(three_q_ops)
if operation in one_param:
num_angles = 1
elif operation in two_param:
num_angles = 2
elif operation in three_param:
num_angles = 3
else:
num_angles = 0
angles = [rng.uniform(0, 2 * np.pi) for x in range(num_angles)]
register_operands = [qr[i] for i in operands]
op = operation(*angles)
# with some low probability, condition on classical bit values
if conditional and rng.choice(range(10)) == 0:
value = rng.integers(0, np.power(2, num_qubits))
op.condition = (cr, value)
qc.append(op, register_operands)
if measure:
qc.measure(qr, cr)
return qc
You have the random_circuit
function in qiskit.circuit.random
to generate a random circuit of arbitrary size and form. Have a look at the documentation. This function will generate a random circuit by randomly selecting gates from the set of standard gates in qiskit.extensions
.
The signature of the function with all the params is the following:
random_circuit(num_qubits, depth, max_operands=3, measure=False, conditional=False, reset=False, seed=None, *, n_qubits=None)
Following code
from qiskit.circuit.random import random_circuit
circ = random_circuit(2, 2, measure=True)
circ.draw(output='mpl')
will produce, for instance, this circuit:
Just in case you need coding your own function, the whole source code of that function is here: https://qiskit.org/documentation/stable/0.19/_modules/qiskit/circuit/random/utils.html#random_circuit