def test_expectation_value() -> None: c = Circuit(2) c.H(0) c.CX(0, 1) op = QubitPauliOperator({ QubitPauliString({ Qubit(0): Pauli.Z, Qubit(1): Pauli.Z }): 1.0, QubitPauliString({ Qubit(0): Pauli.X, Qubit(1): Pauli.X }): 0.3, QubitPauliString({ Qubit(0): Pauli.Z, Qubit(1): Pauli.Y }): 0.8j, QubitPauliString({Qubit(0): Pauli.Y}): -0.4j, }) b = MyBackend() b.compile_circuit(c) assert get_operator_expectation_value(c, op, b) == pytest.approx(1.3)
def test_sampler_expectation_value() -> None: c = Circuit(2) c.H(0) c.CX(0, 1) op = QubitPauliOperator({ QubitPauliString({ Qubit(0): Pauli.Z, Qubit(1): Pauli.Z }): 1.0, QubitPauliString({ Qubit(0): Pauli.X, Qubit(1): Pauli.X }): 0.3, QubitPauliString({ Qubit(0): Pauli.Z, Qubit(1): Pauli.Y }): 0.8j, QubitPauliString({Qubit(0): Pauli.Y}): -0.4j, }) b = MySampler() b.compile_circuit(c) expectation = get_operator_expectation_value(c, op, b, n_shots=2000, seed=0) assert (np.real(expectation), np.imag(expectation)) == pytest.approx( (1.3, 0.0), abs=0.1)
def gen_pauli_measurement_circuits(state_circuit, compiler_pass, operator): # compile main circuit once state_cu = CompilationUnit(state_circuit) compiler_pass.apply(state_cu) compiled_state = state_cu.circuit final_map = state_cu.final_map # make a measurement circuit for each pauli pauli_circuits = [] coeffs = [] energy = 0 for p, c in operator.terms.items(): if p == (): # constant term energy += c else: # make measurement circuits and compile them pauli_circ = Circuit(state_circuit.n_qubits - 1) # ignore syndrome qubit append_pauli_measurement(qps_from_openfermion(p), pauli_circ) pauli_cu = CompilationUnit(pauli_circ) compiler_pass.apply(pauli_cu) pauli_circ = pauli_cu.circuit init_map = pauli_cu.initial_map # map measurements onto the placed qubits from the state rename_map = { i: final_map[o] for o, i in init_map.items() if o in final_map } pauli_circ.rename_units(rename_map) state_and_measure = compiled_state.copy() state_and_measure.append(pauli_circ) pauli_circuits.append(state_and_measure) coeffs.append(c) return pauli_circuits, coeffs, energy
def phi(qubits, alpha, n_qubits): c = Circuit(n_qubits) for i in range(len(qubits) - 1): c.CX(qubits[i], qubits[i + 1]) c.Rz(qubits[-1], alpha) for i in range(len(qubits) - 1): c.CX(qubits[-i - 2], qubits[-i - 1]) return c
def test_bell() -> None: c = Circuit(2) c.H(0) c.CX(0, 1) b = MyBackend() b.compile_circuit(c) assert np.allclose(b.get_state(c), np.asarray([1, 0, 0, 1]) * 1 / np.sqrt(2))
def ucc(params): ansatz = Circuit(4) ansatz.X(1).X(3) add_excitation(ansatz, singles_a, params[0]) add_excitation(ansatz, singles_b, params[1]) add_excitation(ansatz, doubles, params[2]) DecomposeBoxes().apply(ansatz) return ansatz
def test_basisorder() -> None: c = Circuit(2) c.X(1) b = MyBackend() b.compile_circuit(c) assert np.allclose(b.get_state(c), np.asarray([0, 1, 0, 0])) assert np.allclose(b.get_state(c, basis=BasisOrder.dlo), np.asarray([0, 0, 1, 0]))
def sq(a, b, c): circ = Circuit(1) if c != 0: circ.Rz(c, 0) if b != 0: circ.Rx(b, 0) if a != 0: circ.Rz(a, 0) return circ
def hea(params): ansatz = Circuit(4) for i in range(4): ansatz.Ry(params[i], i) for i in range(3): ansatz.CX(i, i + 1) for i in range(4): ansatz.Ry(params[4 + i], i) return ansatz
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 test_sampler_basisorder() -> None: c = Circuit(2, 2) c.X(1) c.measure_all() b = MySampler() b.compile_circuit(c) assert b.get_counts(c, n_shots=10, seed=0) == {(0, 1): 10} assert b.get_counts(c, n_shots=10, seed=0, basis=BasisOrder.dlo) == { (1, 0): 10 }
def cnot_unitary_to_circuit(u, n_qubits): # desc = greedy(matrix_to_function(u, n_qubits), n_qubits) # Doesn't converge, don't run this desc = decompose_unitary(u) c = Circuit(n_qubits) for d in desc: if d[0] == "N": c.X(int(d[2:])) elif d[0] == "C": c.CX(int(d.split(":")[1]), int(d.split(":")[2])) return c
def U(s, n_qubits): c = Circuit(n_qubits) for i in range(len(s)): if s[i] == "X": c.H(i) elif s[i] == "Y": c.Rx(i, 0.5) elif s[i] == "Z": pass return c
def to_tket(self): if self.out_par != mat22partition(Mat2.id(self.n_qubits)): print(self.out_par) raise NotImplementedError("The linear transformation part of the phase polynomial cannot yet be transformed into a tket circuit") circuit = TketCircuit(self.n_qubits) for parity, phase in self.zphases.items(): qubits = [i for i,s in enumerate(parity) if s == '1'] circuit.add_pauliexpbox(PauliExpBox([Pauli.Z]*len(qubits), phase), qubits) # TODO add the linear combination part with CNOTs Transform.DecomposeBoxes().apply(circuit) return circuit
def add_params_to_template(template: Circuit, params: np.ndarray): params = params.reshape((template.n_gates * 2 + template.n_qubits, 3)) c = Circuit(template.n_qubits) for i in range(template.n_gates): cnot_gate = template.get_commands()[i] c.add_operation(OpType.U3, params[2 * i], [cnot_gate.qubits[0]]) c.add_operation(OpType.U3, params[2 * i + 1], [cnot_gate.qubits[1]]) c.CX(cnot_gate.qubits[0], cnot_gate.qubits[1]) for q in range(template.n_qubits): c.add_operation(OpType.U3, params[template.n_gates * 2 + q], [q]) return c
def measure_x(quantum_circuit: Circuit, qubit: int, bit: int) -> None: """Measures a specified qubit in the Hadamard (X) basis. Args: quantum_circuit (pytket.circuit.Circuit): The quantum circuit to apply the measurement to. qubit (int): The qubit to measure. bit (int): The bit to save the qubit measurement result into. """ # Apply Hadamard gate to the qubit. # Measure the qubit into the bit. quantum_circuit.H(qubit) quantum_circuit.Measure(qubit, bit)
def ucc(params): ansatz = Circuit(4) # Set initial reference state ansatz.X(1).X(3) # Evolve by excitations for term, coeff in singles_a.items(): add_operator_term(ansatz, term, coeff * params[0]) for term, coeff in singles_b.items(): add_operator_term(ansatz, term, coeff * params[1]) for term, coeff in doubles.items(): add_operator_term(ansatz, term, coeff * params[2]) return ansatz
def get_pauli_expectation(c: Circuit, initial_circuit: Circuit, pauli_string: str, backend, shots: int = 100) -> float: n_qubits = len(pauli_string) circuit = initial_circuit.copy() circuit.add_circuit(c.copy(), list(range(n_qubits))) black_box_exp = backend.get_pauli_expectation_value( circuit, [(i, pauli_string[i]) for i in range(len(pauli_string)) if pauli_string[i] != "I"], shots=shots).real return black_box_exp
def test_sampler_compilation_pass() -> None: b = MySampler() for opt_level in range(3): c = Circuit(2) c.CX(0, 1) u = np.asarray([[0, 1], [-1j, 0]]) c.add_unitary1qbox(Unitary1qBox(u), 1) c.CX(0, 1) c.add_gate(OpType.CRz, 0.35, [1, 0]) c.measure_all() assert not (b.valid_circuit(c)) b.compile_circuit(c, optimisation_level=opt_level) assert b.valid_circuit(c)
def instructions_to_circuit(instructions): c = Circuit(n_qubit) for inst in instructions: t = inst.op.get_type() c.add_operation(t, inst.op.get_params(), inst.qubits) return c # circ = instructions_to_circuit(circ.get_commands()[:24]) # print(circ.n_gates) # print(dag_to_circuit(tk_to_dagcircuit(circ)))
def test_transpile_grid_circuit(self): c = Circuit() qb = pytket._tket.circuit.Qubit("grid", 0, 0) c.add_qubit(qb) c.Rz(1, qb) qsc = jaqal_circuit_from_tket_circuit(c) jcirc = CircuitBuilder() reg = jcirc.register("baseregister", 1) reg2 = jcirc.map("grid0_0", reg, slice(0, 1, 1)) block = jcirc.block() block.gate("prepare_all") block.gate("Rz", reg2[0], pi) block.gate("measure_all") self.assertEqual(generate_jaqal_program(jcirc.build()), generate_jaqal_program(qsc))
def approximate_via_cnots(unitary): dim = unitary.shape[0] n_qubits = int(math.log(dim, 2)) converter.n_qubits = n_qubits r = RewriteTket(Circuit(n_qubits), [], []) r.set_target_unitary(unitary) # cnot_circuit = approximate_with_cnots(unitary) cnot_circuit = qft3 # print(dag_to_circuit(tk_to_dagcircuit(cnot_circuit))) n_params = (cnot_circuit.n_gates * 2 + n_qubits) * 3 def distance(params): f = r.fidelity(add_params_to_template(cnot_circuit, params)) return (1 - max(0, f)**0.5)**0.5 best_distance = 1 best_circ = None for _ in range(10): initial = np.random.random((n_params, )) res = scipy.optimize.minimize(distance, initial, method='SLSQP', options={'ftol': 0.01}, callback=lambda x: print(distance(x))) if res.success and res.fun < best_distance: best_distance = res.fun best_circ = add_params_to_template(cnot_circuit, res.x) if res.fun < 0.01: return best_circ, best_distance return best_circ, best_distance
def simulated_annealing(unitary, n_layers): dim = unitary.shape[0] n_qubits = int(math.log(dim, 2)) converter.n_qubits = n_qubits n_cnots = (n_layers // 2) * (n_qubits // 2) + ((n_qubits - 1) // 2) * ( (n_layers + 1) // 2) r = RewriteTket(Circuit(n_qubits), [], []) r.set_target_unitary(unitary) skips = [] circuit, distance = approximate_scipy(unitary, n_layers, r, []) for k in range(10): new_skip = random.choice([i for i in range(n_cnots) if i not in skips]) print("maybe I will skip", new_skip) new_circ, new_d = approximate_scipy(unitary, n_layers, r, skips + [new_skip]) if new_d <= distance: # or random.random() < (1 - new_d + distance) / (5 * k + 1): print("skipping", new_skip) circuit, distance, skips = new_circ, new_d, skips + [new_skip] else: print("not skipping", new_skip) print(circuit.n_gates, circuit.n_gates_of_type(OpType.CX)) if distance < 0.01: print("returning early", distance) return circuit, r.fidelity(circuit) print(distance) return circuit, r.fidelity(circuit)
def measurement_circuits(hamiltonian, n_qubits): all_circs = [] for pauli, _ in hamiltonian.terms.items(): if not pauli: continue # Ignore the constant term measure_circ = Circuit(n_qubits, n_qubits) for qb, p in pauli: if p == 'I': continue # Discard I qubits elif p == 'X': measure_circ.H(qb) elif p == 'Y': measure_circ.Rx(0.5, qb) measure_circ.Measure(qb, qb) all_circs.append(measure_circ) return all_circs
def ucc(params): singles_params = {qps: params[0] * coeff for qps, coeff in singles.items()} doubles_params = {qps: params[1] * coeff for qps, coeff in doubles.items()} excitation_op = QubitPauliOperator({**singles_params, **doubles_params}) reference_circ = Circuit(4).X(1).X(3) ansatz = gen_term_sequence_circuit(excitation_op, reference_circ) GuidedPauliSimp().apply(ansatz) FullPeepholeOptimise().apply(ansatz) return ansatz
def generate_hf_wavefunction_circuit(n_qubit: int, n_alpha_electron: int, n_beta_electron: int): """ Args: n_qubit (int): n_alpha_electron (int): n_beta_electron (int): """ circuit = Circuit(n_qubit) for i in range(n_alpha_electron): idx_alpha = 2 * i circuit.X(idx_alpha) for i in range(n_beta_electron): idx_beta = 2 * i + 1 circuit.X(idx_beta) return circuit
def measure_z(quantum_circuit: Circuit, qubit: int, bit: int) -> None: """Measures a specified qubit in the Computational (Z) basis. Args: quantum_circuit (pytket.circuit.Circuit): The quantum circuit to apply the measurement to. qubit (int): The qubit to measure. bit (int): The bit to save the qubit measurement result into. """ # Measure the qubit into the bit. quantum_circuit.Measure(qubit, bit)
def circuit_from_string(op_string: Iterable[Any], *, n_qubits: int = 1, key: Dict[Any, Callable] = None) -> Circuit: if key is None: key = ops circuit = Circuit(n_qubits) for s in op_string[::-1]: key[s](circuit) return circuit
def pauli_measurement(pauli_string:Iterable[Tuple[int,str]], circ:Circuit) : """Appends measurement instructions to a given circuit, measuring each qubit in a given basis :param pauli_string: The pauli operator to measure, as tuples of pauli name and qubit. :type pauli_string: Iterable[Tuple[int,str]] :param circ: Circuit to add measurement to. :type circ: Circuit """ measured_qbs = [] for qb_idx, p in pauli_string: measured_qbs.append(qb_idx) if p=='X': circ.H(qb_idx) elif p=='Y': circ.Sdg(qb_idx) circ.H(qb_idx) for idx in measured_qbs: circ.Measure(idx, idx)
def run_multiple(n_qubits, n_iter): c = Circuit(n_qubits) rewriter = RewriteTket(c, single_noise, cnot_noise, verbose=False) rewriter.verbose = True for _ in range(n_iter): circuit = random_pauli_gadget(n_qubits) Transform.OptimisePauliGadgets().apply(circuit) rewriter.set_circuit_and_target(circuit) rewriter.reduce() print(rewriter.instructions) print("\n\n")