def quantum_volume_circuit(n, depth, measure=True, seed=None): """Create a quantum volume circuit without measurement. The model circuits consist of layers of Haar random elements of SU(4) applied between corresponding pairs of qubits in a random bipartition. Args: n (int): number of qubits depth (int): ideal depth of each model circuit (over SU(4)) measure (bool): include measurement in circuit. Returns: QuantumCircuit: A quantum volume circuit. """ # Create random number generator with possibly fixed seed rng = random.RandomState(seed) # Create quantum/classical registers of size n qr = QuantumRegister(n) circuit = QuantumCircuit(qr) # For each layer for _ in repeat(None, depth): # Generate uniformly random permutation Pj of [0...n-1] perm = rng.permutation(n) # For each consecutive pair in Pj, generate Haar random SU(4) # Decompose each SU(4) into CNOT + SU(2) and add to Ci for k in range(math.floor(n / 2)): # Generate random SU(4) matrix X = (rng.randn(4, 4) + 1j * rng.randn(4, 4)) SU4, _ = linalg.qr(X) # Q is a unitary matrix SU4 /= pow(linalg.det(SU4), 1 / 4) # make Q a special unitary decomposed_SU4 = two_qubit_kak( SU4) # Decompose into CX and U gates qubits = [int(perm[2 * k]), int(perm[2 * k + 1])] for gate in decomposed_SU4: i0 = qubits[gate["args"][0]] if gate["name"] == "cx": i1 = qubits[gate["args"][1]] circuit.cx(qr[i0], qr[i1]) elif gate["name"] == "u1": circuit.u1(gate["params"][2], qr[i0]) elif gate["name"] == "u2": circuit.u2(gate["params"][1], gate["params"][2], qr[i0]) elif gate["name"] == "u3": circuit.u3(gate["params"][0], gate["params"][1], gate["params"][2], qr[i0]) elif gate["name"] == "id": pass if measure is True: cr = ClassicalRegister(n) meas = QuantumCircuit(qr, cr) meas.barrier(qr) meas.measure(qr, cr) circuit = circuit + meas return circuit
def build_model_circuits(n, depth, num_circ=1): """Create a quantum program containing model circuits. The model circuits consist of layers of Haar random elements of SU(4) applied between corresponding pairs of qubits in a random bipartition. Args: n (int): number of qubits depth (int): ideal depth of each model circuit (over SU(4)) num_circ (int): number of model circuits to construct Returns: list(QuantumCircuit): list of quantum volume circuits """ # Create quantum/classical registers of size n q = QuantumRegister(n) c = ClassicalRegister(n) # For each sample number, build the model circuits circuits = [] for i in range(num_circ): # Initialize empty circuit circuit = QuantumCircuit(q, c) # For each layer for j in range(depth): # Generate uniformly random permutation Pj of [0...n-1] perm = random.permutation(n) # For each consecutive pair in Pj, generate Haar random SU(4) # Decompose each SU(4) into CNOT + SU(2) and add to Ci for k in range(math.floor(n / 2)): qubits = [int(perm[2 * k]), int(perm[2 * k + 1])] SU = random_SU(4) decomposed_SU = two_qubit_kak(SU) for gate in decomposed_SU: i0 = qubits[gate["args"][0]] if gate["name"] == "cx": i1 = qubits[gate["args"][1]] circuit.cx(q[i0], q[i1]) elif gate["name"] == "u1": circuit.u1(gate["params"][2], q[i0]) elif gate["name"] == "u2": circuit.u2(gate["params"][1], gate["params"][2], q[i0]) elif gate["name"] == "u3": circuit.u3(gate["params"][0], gate["params"][1], gate["params"][2], q[i0]) elif gate["name"] == "id": pass # Barrier before measurement to prevent reordering, then measure circuit.barrier(q) circuit.measure(q, c) # Save sample circuit circuits.append(circuit) return circuits
def build_model_circuits(name, n, depth, num_circ=1): """Create a quantum program containing model circuits. The model circuits consist of layers of Haar random elements of SU(4) applied between corresponding pairs of qubits in a random bipartition. name = leading name of circuits n = number of qubits depth = ideal depth of each model circuit (over SU(4)) num_circ = number of model circuits to construct Return a quantum program. """ qp = QuantumProgram() q = qp.create_quantum_register("q", n) c = qp.create_classical_register("c", n) # Create measurement subcircuit meas = qp.create_circuit("meas", [q], [c]) for j in range(n): meas.measure(q[j], c[j]) # For each sample number, build the model circuits for i in range(num_circ): # Initialize empty circuit Ci without measurement circuit_i = qp.create_circuit("%s_%d" % (name, i), [q], [c]) # For each layer for j in range(depth): # Generate uniformly random permutation Pj of [0...n-1] perm = np.random.permutation(n) # For each pair p in Pj, generate Haar random SU(4) # Decompose each SU(4) into CNOT + SU(2) and add to Ci for k in range(math.floor(n / 2)): qubits = [int(perm[2 * k]), int(perm[2 * k + 1])] SU = random_SU(4) for gate in two_qubit_kak(SU): i0 = qubits[gate["args"][0]] if gate["name"] == "cx": i1 = qubits[gate["args"][1]] circuit_i.cx(q[i0], q[i1]) elif gate["name"] == "u1": circuit_i.u1(gate["params"][2], q[i0]) elif gate["name"] == "u2": circuit_i.u2(gate["params"][1], gate["params"][2], q[i0]) elif gate["name"] == "u3": circuit_i.u3(gate["params"][0], gate["params"][1], gate["params"][2], q[i0]) elif gate["name"] == "id": pass # do nothing # circuit_i.barrier(q) # barriers between layers circuit_i.barrier(q) # barrier before measurement # Create circuit with final measurement qp.add_circuit("%s_%d_meas" % (name, i), circuit_i + meas) return qp
def makeGatesFrom4DMatrix(qc, qubits, mat): """makeGatesFrom4DMatrix :param qc: QuantumCircuit to apply the gate to :param qubits: qubits this gate acts on (2 qubits in an array) :param mat: unitary matrix (4D) """ q1 = qubits[0] q2 = qubits[1] mat = filterNpdArray(mat) print('mat: ') test = filterNpdArray(dot(mat, mat.conj().T)) matprint(test) MS_gate = two_qubit_kak(mat) mp = createMapping(qc) n = len(MS_gate) for i in range(n): gate = MS_gate[i]['name'] qubits_direction = MS_gate[i]['args'] params = MS_gate[i]['params'] # grabs the gate (function) from mapping qiskit_gate = mp[gate]['gate'] num_args = mp[gate]['args'] argpos = mp[gate]['argpos'] # num_ctl = mp[gate]['ctl'] paramsf = [] # print(params) if num_args != 0: for index in argpos: print(index) paramsf.append(params[index]) qubits_inorder = [] print(gate) for j in range(len(qubits_direction)): if qubits_direction[j] == 1: qubits_inorder.append(q2) else: qubits_inorder.append(q1) # implements the gate qiskit_gate(*paramsf, *qubits_inorder)
def quantum_volume(qubit, final_measure=True, depth=10, seed=0): qreg = QuantumRegister(qubit) width = qubit np.random.seed(seed) circuit = QuantumCircuit(qreg, name=f"Qvolume: {width} by {depth}, seed: {seed}") for _ in range(depth): # Generate uniformly random permutation Pj of [0...n-1] perm = np.random.permutation(width) # For each pair p in Pj, generate Haar random U(4) # Decompose each U(4) into CNOT + SU(2) for k in range(width // 2): U = random_unitary_matrix(4) for gate in two_qubit_kak(U): qs = [qreg[int(perm[2 * k + i])] for i in gate["args"]] pars = gate["params"] name = gate["name"] if name == "cx": circuit.cx(qs[0], qs[1]) elif name == "u1": circuit.u1(pars[0], qs[0]) elif name == "u2": circuit.u2(*pars[:2], qs[0]) elif name == "u3": circuit.u3(*pars[:3], qs[0]) elif name == "id": pass # do nothing else: raise Exception(f"Unexpected gate name: {name}") circuit.barrier(qreg) if final_measure: creg = ClassicalRegister(qubit) circuit.add_register(creg) circuit.measure(qreg, creg) return circuit
def build_model_circuit_kak(width, depth, seed=None): """Create quantum volume model circuit on quantum register qreg of given depth (default depth is equal to width) and random seed. The model circuits consist of layers of Haar random elements of U(4) applied between corresponding pairs of qubits in a random bipartition. """ qreg = QuantumRegister(width) depth = depth or width np.random.seed(seed) circuit = QuantumCircuit(qreg, name="Qvolume: %s by %s, seed: %s" % (width, depth, seed)) for _ in range(depth): # Generate uniformly random permutation Pj of [0...n-1] perm = np.random.permutation(width) # For each pair p in Pj, generate Haar random U(4) # Decompose each U(4) into CNOT + SU(2) for k in range(width // 2): U = random_unitary_matrix(4) for gate in two_qubit_kak(U): qs = [qreg[int(perm[2 * k + i])] for i in gate["args"]] pars = gate["params"] name = gate["name"] if name == "cx": circuit.cx(qs[0], qs[1]) elif name == "u1": circuit.u1(pars[0], qs[0]) elif name == "u2": circuit.u2(*pars[:2], qs[0]) elif name == "u3": circuit.u3(*pars[:3], qs[0]) elif name == "id": pass # do nothing else: raise Exception("Unexpected gate name: %s" % name) return circuit
def random_circuit(n: int, depth: int = 20, seed: int = None) -> QuantumCircuit: """Create a quantum program containing model circuits. The model circuits consist of layers of Haar random elements of SU(4) applied between corresponding pairs of qubits in a random bipartition. name = leading name of circuits n = number of qubits depth = ideal depth of each model circuit (over SU(4)) Return a quantum circuit. """ np_random = np.random.RandomState(seed) q = QuantumRegister(n) qc = QuantumCircuit(q) # For each layer for j in range(depth): # Generate uniformly random permutation Pj of [0...n-1] perm = np_random.permutation(n) # For each pair p in Pj, generate Haar random SU(4) for k in range(math.floor(n / 2)): qubits = [int(perm[2 * k]), int(perm[2 * k + 1])] U = random_unitary(4, np_random) # TODO: Replace this with a general "two-qubit" gate instead of decomposing it. for gate in two_qubit_kak(U): i0 = qubits[gate["args"][0]] if gate["name"] == "cx": i1 = qubits[gate["args"][1]] qc.cx(q[i0], q[i1]) elif gate["name"] == "u1": qc.u1(gate["params"][2], q[i0]) elif gate["name"] == "u2": qc.u2(gate["params"][1], gate["params"][2], q[i0]) elif gate["name"] == "u3": qc.u3(gate["params"][0], gate["params"][1], gate["params"][2], q[i0]) elif gate["name"] == "id": pass # do nothing return qc
from math import log, floor ############################################################################### # Testing values sqrtX = array( [[0.5 * (1 + 1j), 0.5 * (1 - 1j)], [0.5 * (1 - 1j), 0.5 * (1 + 1j)]], dtype=complex) sqrtX2, sqrtX2_I = sqrtGate() MS = array( [[1, 0, 0, 0 - 1j], [0, 1, 0 - 1j, 0], [0, 0 - 1j, 1, 0], [0 - 1j, 0, 0, 1]], dtype=complex) theta, phi, lmbda, s = euler_angles_1q(sqrtX) theta2, phi2, lmbda2, s2 = euler_angles_1q(sqrtX2) MS_gate = two_qubit_kak(MS) print(theta, phi, lmbda, s) print(theta2, phi2, lmbda2, s2) for gate in MS_gate: print(gate) ############################################################################### # still have to construct the controlled versions of the sqrt gates! def change_basis(qc, q, theta, phi): qc.u3(theta, phi, phi, q) def R(qc, q, theta, phi): """R