Download dense_evolution/random_circuit.py from Tatopenn/dense-Evolution: direct link, hf CLI and curl.
- Browser
- Download file 3.33 kB
-
https://huggingface.co/Tatopenn/dense-Evolution/resolve/main/dense_evolution/random_circuit.py
- Command line
-
hf download hf://Tatopenn/dense-Evolution/dense_evolution/random_circuit.py
-
curl -L -o random_circuit.py https://huggingface.co/Tatopenn/dense-Evolution/resolve/main/dense_evolution/random_circuit.py
3.33 kB
| """ | |
| Random circuit generation for benchmarking and fuzz-testing -- the same | |
| purpose Qiskit's `random_circuit` serves. | |
| """ | |
| import numpy as np | |
| __all__ = ['random_circuit'] | |
| _1Q_STATIC = ('h', 'x', 'y', 'z', 's', 'sdg', 't', 'tdg', 'sx') | |
| _1Q_PARAMETRIC = ('rx', 'ry', 'rz') | |
| _2Q_STATIC = ('cx', 'cz', 'cy', 'swap') | |
| _ALL_KNOWN = set(_1Q_STATIC) | set(_1Q_PARAMETRIC) | set(_2Q_STATIC) | |
| def random_circuit(n_qubits, n_gates, seed=None, gate_set=None, two_qubit_prob=0.4): | |
| """ | |
| Build a random circuit for benchmarking or fuzz-testing. | |
| Parameters | |
| ---------- | |
| n_qubits : int | |
| Number of qubits, must be >= 1. | |
| n_gates : int | |
| Number of gate operations to generate, must be >= 0. | |
| seed : int | numpy.random.Generator, optional | |
| Seed (or an existing Generator) for reproducible circuits. | |
| gate_set : iterable of str, optional | |
| Restrict generation to this set of gate names, mixing 1- and | |
| 2-qubit gates freely (default spans both: h, x, y, z, s, sdg, t, | |
| tdg, sx, rx, ry, rz, cx, cz, cy, swap). Unrecognized names raise | |
| immediately rather than failing later inside run_circuit. | |
| two_qubit_prob : float | |
| Probability in [0, 1] of picking a 2-qubit gate at each step. | |
| Ignored (forced to single-qubit gates) once n_qubits < 2, or once | |
| gate_set excludes every 2-qubit gate name. | |
| Returns | |
| ------- | |
| list[tuple] | |
| """ | |
| if n_qubits < 1: | |
| raise ValueError(f"random_circuit needs at least 1 qubit, got {n_qubits}") | |
| if n_gates < 0: | |
| raise ValueError(f"n_gates must be >= 0, got {n_gates}") | |
| if not (0.0 <= two_qubit_prob <= 1.0): | |
| raise ValueError(f"two_qubit_prob must be in [0, 1], got {two_qubit_prob}") | |
| rng = seed if isinstance(seed, np.random.Generator) else np.random.default_rng(seed) | |
| if gate_set is not None: | |
| gate_set = list(gate_set) | |
| unknown = set(gate_set) - _ALL_KNOWN | |
| if unknown: | |
| raise ValueError(f"unknown gate name(s) in gate_set: {sorted(unknown)}") | |
| one_q_static = [g for g in gate_set if g in _1Q_STATIC] | |
| one_q_param = [g for g in gate_set if g in _1Q_PARAMETRIC] | |
| two_q = [g for g in gate_set if g in _2Q_STATIC] | |
| else: | |
| one_q_static = list(_1Q_STATIC) | |
| one_q_param = list(_1Q_PARAMETRIC) | |
| two_q = list(_2Q_STATIC) if n_qubits >= 2 else [] | |
| one_q_pool = one_q_static + one_q_param | |
| if not one_q_pool and not two_q: | |
| raise ValueError("gate_set leaves no usable gates for this n_qubits") | |
| ops = [] | |
| for _ in range(n_gates): | |
| use_two_qubit = ( | |
| bool(two_q) and n_qubits >= 2 | |
| and (not one_q_pool or rng.random() < two_qubit_prob) | |
| ) | |
| if use_two_qubit: | |
| name = two_q[rng.integers(len(two_q))] | |
| a, b = rng.choice(n_qubits, size=2, replace=False) | |
| ops.append((name, int(a), int(b))) | |
| else: | |
| name = one_q_pool[rng.integers(len(one_q_pool))] | |
| q = int(rng.integers(n_qubits)) | |
| if name in _1Q_PARAMETRIC: | |
| theta = float(rng.uniform(0, 2 * np.pi)) | |
| ops.append((name, q, theta)) | |
| else: | |
| ops.append((name, q)) | |
| return ops | |