def pauli_gadget(alpha, s, n_qubits): c1 = U(s, n_qubits) c2 = phi([x for x in range(n_qubits) if s[x] != "I"], alpha, n_qubits) c = Circuit(n_qubits) c.add_circuit(c1, list(range(n_qubits))) c.add_circuit(c2, list(range(n_qubits))) c.add_circuit(c1.dagger(), list(range(n_qubits))) return c
def approximate_with_cnots(unitary): n_qubits = int(math.log(unitary.shape[0], 2)) mnots = function_to_mnots( matrix_to_function(suggest_cnot_unitary(unitary), n_qubits), n_qubits) circs = mnot_templates(n_qubits) c = Circuit(n_qubits) for mnot in mnots: n_controls = len(mnot[0]) c.add_circuit(circs[n_controls - 1], mnot[0] + [mnot[1]]) return c
def mnot_templates(n_controls): if n_controls == 0: return Circuit(1) c1 = Circuit(2) c1.CX(0, 1) c1.add_circuit(c1.copy(), [0, 1]) if n_controls == 1: return c1 c2 = Circuit(3) c2.CX(1, 2) c2.CX(0, 1) c2.CX(1, 2) c2.CX(0, 1) c2.CX(0, 2) circs = [c1, c2] for i in range(3, n_controls + 1): c = Circuit(i + 1) c.CX(i - 1, i) c.CX(i - 1, i) c.add_circuit(circs[-1], list(range(i))) c.CX(i - 1, i) c.CX(i - 1, i) c.add_circuit(circs[-1], list(range(i))) c.add_circuit(circs[-1], list(range(i - 1)) + [i]) c.add_circuit(circs[-1], list(range(i - 1)) + [i]) circs.append(c) return circs
def random_gadget_circuit(n_qubits, n_gadgets): c = Circuit(n_qubits) for _ in range(n_gadgets): c.add_circuit(random_pauli_gadget(n_qubits), list(range(n_qubits))) return c