# Is there a way to generate random circuits in qiskit with only certain allowed 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')

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

• That's neat, I can indeed modify the source code of random circuit. It's probably not useful enough for most people to make a feature request but it's nice to have for me. Thank you! – user1936752 Sep 13 '20 at 0:49