def pea_program(ancillary_start, ancillary_num, time, H2_distance, trotter_order): """ Creates a pyquil Program for the phase estimation algorithm (PEA) :param ancillary_start: index of the first ancillary qubit. :param ancillary_num: how many ancillaries to use corresponds to precision in PEA algorithm :param time: t in exp(-iHt), where H is the Hamiltonian :param H2_distance: the distance between to H atoms in H2 molecule :return: a pyquil Program for PEA algorithm """ phase_estimation_program = Program() unitary = exp_hamiltoniantrot_H2(time, H2_distance, trotter_order) phase_estimation_program.inst(create_CRX(), create_CRZ(), create_CH()) Hadamard_ancilaries = Program() for index in range(0, ancillary_num): Hadamard_ancilaries.inst(H(ancillary_start + index)) phase_estimation_program += Hadamard_ancilaries for index in range(0, ancillary_num): cont_first_order = Program() control_program(unitary, cont_first_order, ancillary_start + index) control_unitary = repeat_program(cont_first_order, 2**index) phase_estimation_program += control_unitary ancilary_list = list( range(ancillary_start, ancillary_start + ancillary_num)) inv_qft_prog = inverse_qft(ancilary_list) phase_estimation_program += inv_qft_prog return phase_estimation_program
def test_qc_calibration_2q(forest): # noise model with 95% symmetrized readout fidelity per qubit noise_model = asymmetric_ro_model([0, 1], 0.945, 0.955) qc = get_qc("2q-qvm") qc.qam.noise_model = noise_model # bell state program (doesn't matter) p = Program() p += RESET() p += H(0) p += CNOT(0, 1) p.wrap_in_numshots_loop(10000) # ZZ experiment sz = ExperimentSetting(in_state=sZ(0) * sZ(1), out_operator=sZ(0) * sZ(1)) e = Experiment(settings=[sz], program=p) results = qc.calibrate(e) # ZZ expectation should just be (1 - 2 * readout_error_q0) * (1 - 2 * readout_error_q1) np.isclose(results[0].expectation, 0.81, atol=0.01) assert results[0].total_counts == 40000
def test_qc_calibration_1q(client_configuration: QCSClientConfiguration): # noise model with 95% symmetrized readout fidelity per qubit noise_model = asymmetric_ro_model([0], 0.945, 0.955) qc = get_qc("1q-qvm", client_configuration=client_configuration) qc.qam.noise_model = noise_model # bell state program (doesn't matter) p = Program() p += RESET() p += H(0) p += CNOT(0, 1) p.wrap_in_numshots_loop(10000) # Z experiment sz = ExperimentSetting(in_state=_pauli_to_product_state(sZ(0)), out_operator=sZ(0)) e = Experiment(settings=[sz], program=p) results = qc.calibrate(e) # Z expectation value should just be 1 - 2 * readout_error np.isclose(results[0].expectation, 0.9, atol=0.01) assert results[0].total_counts == 20000
def phase_estimation(U: np.ndarray, accuracy: int, reg_offset: int = 0) -> Program: """ Generate a circuit for quantum phase estimation. :param U: A unitary matrix. :param accuracy: Number of bits of accuracy desired. :param reg_offset: Where to start writing measurements (default 0). :return: A Quil program to perform phase estimation. """ assert isinstance(accuracy, int) rows, cols = U.shape m = int(log2(rows)) output_qubits = range(0, accuracy) U_qubits = range(accuracy, accuracy + m) p = Program() ro = p.declare('ro', 'BIT', len(output_qubits)) # Hadamard initialization for i in output_qubits: p.inst(H(i)) # Controlled unitaries for i in output_qubits: if i > 0: U = np.dot(U, U) cU = controlled(U) name = "CONTROLLED-U{0}".format(2**i) # define the gate p.defgate(name, cU) # apply it p.inst((name, i) + tuple(U_qubits)) # Compute the QFT p = p + inverse_qft(output_qubits) # Perform the measurements for i in output_qubits: p.measure(i, ro[reg_offset + i]) return p
def test_run(client_configuration: QCSClientConfiguration): quantum_processor = NxQuantumProcessor(nx.complete_graph(3)) qc = QuantumComputer( name="testy!", qam=QVM(client_configuration=client_configuration, gate_noise=(0.01, 0.01, 0.01)), compiler=DummyCompiler(quantum_processor=quantum_processor, client_configuration=client_configuration), ) bitstrings = qc.run( Program( Declare("ro", "BIT", 3), H(0), CNOT(0, 1), CNOT(1, 2), MEASURE(0, MemoryReference("ro", 0)), MEASURE(1, MemoryReference("ro", 1)), MEASURE(2, MemoryReference("ro", 2)), ).wrap_in_numshots_loop(1000) ) assert bitstrings.shape == (1000, 3) parity = np.sum(bitstrings, axis=1) % 3 assert 0 < np.mean(parity) < 0.15
def test_expectation(): """expectation() routine can take a PauliSum operator on a matrix. Check this functionality and the return of the correct scalar value""" X = np.array([[0, 1], [1, 0]]) def RX_gate(phi): return expm(-1j * phi * X) def rotation_wavefunction(phi): state = np.array([[1], [0]]) return RX_gate(phi).dot(state) prog = Program([RX(-2.5)(0)]) hamiltonian = PauliTerm("Z", 0, 1.0) minimizer = MagicMock() fake_result = Mock() fake_result.fun = 1.0 minimizer.return_value = fake_result fake_qvm = Mock(spec=['wavefunction', 'expectation', 'run']) fake_qvm.wavefunction.return_value = (Wavefunction( rotation_wavefunction(-2.5))) fake_qvm.expectation.return_value = [0.28366219] # for testing expectation fake_qvm.run.return_value = [[0], [0]] inst = VQE(minimizer) energy = inst.expectation(prog, PauliSum([hamiltonian]), None, fake_qvm) assert np.isclose(energy, 0.28366219) hamiltonian = np.array([[1, 0], [0, -1]]) energy = inst.expectation(prog, hamiltonian, None, fake_qvm) assert np.isclose(energy, 0.28366219) prog = Program(H(0)) hamiltonian = PauliSum([PauliTerm('X', 0)]) energy = inst.expectation(prog, hamiltonian, 2, fake_qvm) assert np.isclose(energy, 1.0)
def teleport(start_index, end_index, ancilla_index): """Teleport a qubit from start to end using an ancilla qubit """ program = make_bell_pair(end_index, ancilla_index) ro = program.declare("ro", memory_size=3) # do the teleportation program.inst(CNOT(start_index, ancilla_index)) program.inst(H(start_index)) # measure the results and store them in classical registers [0] and [1] program.measure(start_index, ro[0]) program.measure(ancilla_index, ro[1]) program.if_then(ro[1], X(2)) program.if_then(ro[0], Z(2)) program.measure(end_index, ro[2]) print(program) return program
def test_run(forest): device = NxDevice(nx.complete_graph(3)) qc = QuantumComputer( name="testy!", qam=QVM(connection=forest, gate_noise=[0.01] * 3), device=device, compiler=DummyCompiler(), ) bitstrings = qc.run( Program( Declare("ro", "BIT", 3), H(0), CNOT(0, 1), CNOT(1, 2), MEASURE(0, MemoryReference("ro", 0)), MEASURE(1, MemoryReference("ro", 1)), MEASURE(2, MemoryReference("ro", 2)), ).wrap_in_numshots_loop(1000)) assert bitstrings.shape == (1000, 3) parity = np.sum(bitstrings, axis=1) % 3 assert 0 < np.mean(parity) < 0.15
def prepare_bitstring(bitstring: Sequence[int], register: Sequence[int], in_x_basis: bool = False): """ Creates a program to prepare the input bitstring on the qubits given by the corresponding label in the register. :param bitstring: :param register: a list of qubits on which to prepare the bitstring. The first :param in_x_basis: if true, prepare the bitstring-representation of the numbers in the x basis. :returns: state_prep_prog - program """ state_prep_prog = Program() for bit, qubit_label in zip(bitstring, register): if bit == 1: state_prep_prog += X(qubit_label) # if we are doing logic in X basis, follow each bit preparation with a Hadamard # H |0> = |+> and H |1> = |-> where + and - label the X basis vectors. if in_x_basis: state_prep_prog += H(qubit_label) return state_prep_prog
def run_bell_low_level(n_shots=1000): # Step 1. Get some device components qc = get_qc('9q-generic-qvm') compiler = qc.compiler qam = qc.qam del qc q = [4, 5] # qubits # Step 2. Construct your program program = Program() program += H(q[0]) program += CNOT(q[0], q[1]) # Step 2.1. Manage read-out memory ro = program.declare('ro', memory_type='BIT', memory_size='2') program += MEASURE(q[0], ro[0]) program += MEASURE(q[1], ro[1]) # Step 2.2. Run the program in a loop program = program.wrap_in_numshots_loop(n_shots) # Step 3. Compile and run nq_program = compiler.quil_to_native_quil(program) executable = compiler.native_quil_to_executable(nq_program) bitstrings = qam.load(executable) \ .run() \ .wait() \ .read_memory(region_name="ro") # Bincount bitstrings basis = np.array([2**i for i in range(len(q))]) ints = np.sum(bitstrings * basis, axis=1) print('bincounts', np.bincount(ints)) # Check parity parities = np.sum(bitstrings, axis=1) % 2 print('avg parity', np.mean(parities))
def test_control_flows(): outer_loop = Program() classical_flag_register = outer_loop.declare('classical_flag_register', 'BIT') outer_loop += MOVE(classical_flag_register, 1) # initialize inner_loop = Program() inner_loop += Program(X(0), H(0)) inner_loop += MEASURE(0, classical_flag_register) # run inner_loop in a loop until classical_flag_register is 0 outer_loop.while_do(classical_flag_register, inner_loop) assert outer_loop.out() == '\n'.join([ "DECLARE classical_flag_register BIT[1]", "MOVE classical_flag_register 1", "LABEL @START1", "JUMP-UNLESS @END2 classical_flag_register", "X 0", "H 0", "MEASURE 0 classical_flag_register", "JUMP @START1", "LABEL @END2", "" ])
def test_variance_bootstrap(): qubits = [0, 1] qc = get_test_qc(n_qubits=len(qubits)) state_prep = Program([H(q) for q in qubits]) state_prep.inst(CZ(qubits[0], qubits[1])) tomo_expt = generate_state_tomography_experiment(state_prep, qubits) results = list(measure_observables(qc=qc, tomo_experiment=tomo_expt, n_shots=4000)) estimate, status = iterative_mle_state_estimate(results=results, qubits=qubits, dilution=0.5) rho_est = estimate.estimate.state_point_est purity = np.trace(rho_est @ rho_est) purity = np.real_if_close(purity) assert purity.imag == 0.0 def my_mle_estimator(_r, _q): return iterative_mle_state_estimate(results=_r, qubits=_q, dilution=0.5, entropy_penalty=0.0, beta=0.0)[0] boot_purity, boot_var = estimate_variance(results=results, qubits=qubits, tomo_estimator=my_mle_estimator, functional=dm.purity, n_resamples=5, project_to_physical=False) np.testing.assert_allclose(purity, boot_purity, atol=2 * np.sqrt(boot_var), rtol=0.01)
def test_expectation(forest: ForestConnection): # The forest fixture (argument) to this test is to ensure this is # skipped when a forest web api key is unavailable. You could also # pass it to the constructor of WavefunctionSimulator() but it is not # necessary. wfnsim = WavefunctionSimulator() bell = Program( H(0), CNOT(0, 1), ) expects = wfnsim.expectation(bell, [ sZ(0) * sZ(1), sZ(0), sZ(1), sX(0) * sX(1), ]) assert expects.size == 4 np.testing.assert_allclose(expects, [1, 0, 0, 1]) pauli_sum = PauliSum([sZ(0) * sZ(1)]) expects = wfnsim.expectation(bell, pauli_sum) assert expects.size == 1 np.testing.assert_allclose(expects, [1])
def test_qc_expectation(forest): device = NxDevice(nx.complete_graph(2)) qc = QuantumComputer(name='testy!', qam=QVM(connection=forest), device=device, compiler=DummyCompiler()) # bell state program p = Program() p += RESET() p += H(0) p += CNOT(0, 1) p.wrap_in_numshots_loop(10) # XX, YY, ZZ experiment sx = ExperimentSetting(in_state=sZ(0) * sZ(1), out_operator=sX(0) * sX(1)) sy = ExperimentSetting(in_state=sZ(0) * sZ(1), out_operator=sY(0) * sY(1)) sz = ExperimentSetting(in_state=sZ(0) * sZ(1), out_operator=sZ(0) * sZ(1)) e = TomographyExperiment(settings=[sx, sy, sz], program=p) results = qc.experiment(e) # XX expectation value for bell state |00> + |11> is 1 assert np.isclose(results[0].expectation, 1) assert np.isclose(results[0].std_err, 0) assert results[0].total_counts == 40 # YY expectation value for bell state |00> + |11> is -1 assert np.isclose(results[1].expectation, -1) assert np.isclose(results[1].std_err, 0) assert results[1].total_counts == 40 # ZZ expectation value for bell state |00> + |11> is 1 assert np.isclose(results[2].expectation, 1) assert np.isclose(results[2].std_err, 0) assert results[2].total_counts == 40
def amplification_circuit(algorithm, oracle, qubits, num_iter, decompose_diffusion=False): """ Returns a program that does ``num_iter`` rounds of amplification, given a measurement-less algorithm, an oracle, and a list of qubits to operate on. :param Program algorithm: A program representing a measurement-less algorithm run on qubits. :param Program oracle: An oracle maps any basis vector ``|psi>`` to either ``+|psi>`` or ``-|psi>`` depending on whether ``|psi>`` is in the desirable subspace or the undesirable subspace. :param Sequence qubits: the qubits to operate on :param int num_iter: number of iterations of amplifications to run :param bool decompose_diffusion: If True, decompose the Grover diffusion gate into two qubit gates. If False, use a defgate to define the gate. :return: The amplified algorithm. :rtype: Program """ program = pq.Program() uniform_superimposer = pq.Program().inst([H(qubit) for qubit in qubits]) program += uniform_superimposer if decompose_diffusion: diffusion = decomposed_diffusion_program(qubits) else: diffusion = diffusion_program(qubits) # To avoid redefining gates, we collect them before building our program. defined_gates = oracle.defined_gates + algorithm.defined_gates + diffusion.defined_gates for _ in range(num_iter): program += (oracle.instructions + algorithm.dagger().instructions + diffusion.instructions + algorithm.instructions) # We redefine the gates in the new program. for gate in defined_gates: program.defgate(gate.name, gate.matrix) return program
def test_get_expectation_values_for_circuitset(self, backend): # Given num_circuits = 10 circuitset = [ Circuit(Program(H(0), CNOT(0, 1), CNOT(1, 2))) for _ in range(num_circuits) ] operator = IsingOperator("[]") target_expectation_values = np.array([1]) # When backend.n_samples = 1 expectation_values_set = backend.get_expectation_values_for_circuitset( circuitset, operator ) # Then assert len(expectation_values_set) == num_circuits for expectation_values in expectation_values_set: assert isinstance(expectation_values, ExpectationValues) assert isinstance(expectation_values.values, np.ndarray) assert expectation_values.values == pytest.approx( target_expectation_values, abs=1e-15 )
def grover_run(self, bit): self._run_init(bit) oracle = Program() oracle_name = "grover_oracle" oracle.defgate(oracle_name, self._grover_oracle_matrix(bit)) oracle.inst(tuple([oracle_name] + self.qubits)) diffusion = self._grover_diffusion_op() p = Program() Hm = Program().inst([H(qubit) for qubit in grover.qubits]) p += Hm ## Repeating part of the algorithm for _ in range(self.num_iter): p += oracle p += Hm p += diffusion p += Hm # run the program on a QVM qc = get_qc('9q-square-qvm') result = qc.run_and_measure(p, trials=10) pprint.pprint(result)
def get_test_program(measure: bool = False) -> Program: PI = float(pi.evalf()) p = Program() p += X(0) p += Y(1) p += Z(2) p += H(3) p += S(0) p += T(1) p += RX(PI / 2, 2) p += RY(PI / 2, 3) p += RZ(PI / 2, 0) p += CZ(0, 1) p += CNOT(2, 3) p += CCNOT(0, 1, 2) p += CPHASE(PI / 4, 2, 1) p += SWAP(0, 3) if measure: ro = p.declare("ro", "BIT", 4) p += MEASURE(0, ro[0]) p += MEASURE(3, ro[1]) p += MEASURE(2, ro[2]) p += MEASURE(1, ro[3]) return p
def amplification_circuit(algorithm, oracle, qubits, num_iter): """ Returns a program that does n rounds of amplification, given a measurement-less algorithm, an oracle, and a list of qubits to operate on. :param Program algorithm: A program representing a measurement-less algorithm run on qubits. :param Program oracle: An oracle maps any basis vector to either |0> or |1>. :param Sequence qubits: the qubits to operate on :param int num_iter: number of iterations of amplifications to run :return: The amplified algorithm. :rtype: Program """ if num_iter <= 0: raise ValueError("num_iter must be greater than zero") prog = pq.Program() uniform_superimposer = pq.Program().inst([H(qubit) for qubit in qubits]) prog += uniform_superimposer for _ in range(num_iter): prog += oracle + algorithm.dagger() + diffusion_program( qubits) + algorithm return prog
def test_get_expectation_values_for_circuitset(self): # Given num_circuits = 10 circuitset = [ Circuit(Program(H(0), CNOT(0, 1), CNOT(1, 2))) for _ in range(num_circuits) ] operator = IsingOperator('[]') target_expectation_values = np.array([1]) # When for backend in self.backends: backend.n_samples = 1 expectation_values_set = backend.get_expectation_values_for_circuitset( circuitset, operator) # Then self.assertEqual(len(expectation_values_set), num_circuits) for expectation_values in expectation_values_set: self.assertIsInstance(expectation_values, ExpectationValues) np.testing.assert_array_almost_equal(expectation_values.values, target_expectation_values, decimal=15)
def get_qaoa_program(qubits, driver, reward, betas, gammas) -> Program: """ Return the pyQuil program to construct the QAOA state for the problem given beta and gamma angles :param driver: The driver PauliSum. Usually X_i on all qubits. :param problem_ham: The PauliSum representing the problem reward :param betas: Beta angles for parameterizing the driver unitary. :param gammas: Gamma angles for parameterizing the problem hamiltonian unitary. :return: The program """ assert len(betas) == len(gammas) prob_progs = [exponentiate_reward(reward, gamma) for gamma in gammas] driver_progs = [exponentiate_driver(driver, beta) for beta in betas] interleaved_progs = [ prob_prog + driver_prog for prob_prog, driver_prog in zip(prob_progs, driver_progs) ] prog = Program([H(q) for q in qubits]) for iprog in interleaved_progs: prog += iprog return prog
def test_qc_expectation_larger_lattice(client_configuration: QCSClientConfiguration, dummy_compiler: DummyCompiler): qc = QuantumComputer(name="testy!", qam=QVM(client_configuration=client_configuration), compiler=dummy_compiler) q0 = 2 q1 = 3 # bell state program p = Program() p += RESET() p += H(q0) p += CNOT(q0, q1) p.wrap_in_numshots_loop(10) # XX, YY, ZZ experiment sx = ExperimentSetting(in_state=_pauli_to_product_state(sZ(q0) * sZ(q1)), out_operator=sX(q0) * sX(q1)) sy = ExperimentSetting(in_state=_pauli_to_product_state(sZ(q0) * sZ(q1)), out_operator=sY(q0) * sY(q1)) sz = ExperimentSetting(in_state=_pauli_to_product_state(sZ(q0) * sZ(q1)), out_operator=sZ(q0) * sZ(q1)) e = Experiment(settings=[sx, sy, sz], program=p) results = qc.experiment(e) # XX expectation value for bell state |00> + |11> is 1 assert np.isclose(results[0].expectation, 1) assert np.isclose(results[0].std_err, 0) assert results[0].total_counts == 40 # YY expectation value for bell state |00> + |11> is -1 assert np.isclose(results[1].expectation, -1) assert np.isclose(results[1].std_err, 0) assert results[1].total_counts == 40 # ZZ expectation value for bell state |00> + |11> is 1 assert np.isclose(results[2].expectation, 1) assert np.isclose(results[2].std_err, 0) assert results[2].total_counts == 40
def rotate_density(rho, pauli_term, debug=False): """ Rotate the density so I can read off in the computational basis """ # rotate operator into computational basis rot_prog = Program() n_qubits = int(np.log2(rho.shape[0])) marked_qubits = [] for key, value in pauli_term._ops.iteritems(): marked_qubits.append(key) if value == "X": rot_prog.inst(H(key)) elif value == "Y": rot_prog.inst(RX(np.pi / 2)(key)) rot_prog.inst(I(n_qubits - 1)) qvm_unitary = QVMConnection(type_trans='unitary') if debug: ham_op = tensor_up(PauliSum([pauli_term]), n_qubits) e_true = np.trace(ham_op.dot(rho)) unitary = qvm_unitary.unitary(rot_prog) rho = unitary.dot(rho.dot(np.conj(unitary).T)) if debug: z_term = PauliTerm("I", 0) for idx in marked_qubits: z_term = z_term * PauliTerm("Z", idx) ham_op_2 = tensor_up(pauli_term.coefficient * PauliSum([z_term]), n_qubits) test_expect = np.trace(np.dot(ham_op_2, rho)) assert np.isclose(test_expect, e_true) return rho, marked_qubits
def maxcut_qaoa_program(gamma: float) -> Program: """ Generates a 2Q MAXCUT QAOA circuit with beta = pi/8 and with the provided gamma. Args: gamma: One of the two variational parameters (the other is fixed). Returns: A 2Q MAXCUT QAOA circuit with fixed beta and gamma. """ q0, q1 = (0, 1) p = Program() p += H(q0) p += H(q1) p += CNOT(q0, q1) p += RZ(2 * gamma, q1) p += CNOT(q0, q1) p += H(q0) p += H(q1) p += RZ(np.pi / 4, q0) p += RZ(np.pi / 4, q1) p += H(q0) p += H(q1) return p
def test_append_measure_register(): q0 = QubitPlaceholder() p = Program(H(q0), RX(np.pi/2, 0)) p = append_measure_register(p) assert str(p[-1]) == "MEASURE 0 ro[1]"
def test_run_and_measure_qubits(client_configuration: QCSClientConfiguration): wfnsim = WavefunctionSimulator(client_configuration=client_configuration) bell = Program(H(0), CNOT(0, 1)) bitstrings = wfnsim.run_and_measure(bell, qubits=[0, 100], trials=1000) assert np.all(bitstrings[:, 1] == 0) assert 0.4 < np.mean(bitstrings[:, 0]) < 0.6
def test_run_and_measure(client_configuration: QCSClientConfiguration): wfnsim = WavefunctionSimulator(client_configuration=client_configuration) bell = Program(H(0), CNOT(0, 1)) bitstrings = wfnsim.run_and_measure(bell, trials=1000) parity = np.sum(bitstrings, axis=1) % 2 assert np.all(parity == 0)
def test_trotterize(): term_one = PauliTerm("X", 0, 1.0) term_two = PauliTerm("Z", 0, 1.0) with pytest.raises(ValueError): trotterize(term_one, term_two, trotter_order=0) with pytest.raises(ValueError): trotterize(term_one, term_two, trotter_order=5) prog, _ = trotterize(term_one, term_one) result_prog = Program().inst( [H(0), RZ(2.0)(0), H(0), H(0), RZ(2.0)(0), H(0)]) compare_progs(prog, result_prog) # trotter_order 1 steps 1 prog, _ = trotterize(term_one, term_two, trotter_steps=1) result_prog = Program().inst([H(0), RZ(2.0)(0), H(0), RZ(2.0)(0)]) compare_progs(prog, result_prog) # trotter_order 1 steps 2 prog, _ = trotterize(term_one, term_two, trotter_steps=2) result_prog = Program().inst([ H(0), RZ(1.0)(0), H(0), RZ(1.0)(0), H(0), RZ(1.0)(0), H(0), RZ(1.0)(0) ]) compare_progs(prog, result_prog) # trotter_order 2 steps 1 prog, _ = trotterize(term_one, term_two, trotter_order=2) result_prog = Program().inst( [H(0), RZ(1.0)(0), H(0), RZ(2.0)(0), H(0), RZ(1.0)(0), H(0)]) compare_progs(prog, result_prog) # trotter_order 2 steps 2 prog, _ = trotterize(term_one, term_two, trotter_order=2, trotter_steps=2) result_prog = Program().inst([ H(0), RZ(0.5)(0), H(0), RZ(1.0)(0), H(0), RZ(0.5)(0), H(0), H(0), RZ(0.5)(0), H(0), RZ(1.0)(0), H(0), RZ(0.5)(0), H(0) ]) compare_progs(prog, result_prog) # trotter_order 3 steps 1 prog, _ = trotterize(term_one, term_two, trotter_order=3, trotter_steps=1) result_prog = Program().inst([ H(0), RZ(14.0 / 24)(0), H(0), RZ(4.0 / 3.0)(0), H(0), RZ(1.5)(0), H(0), RZ(-4.0 / 3.0)(0), H(0), RZ(-2.0 / 24)(0), H(0), RZ(2.0)(0) ]) compare_progs(prog, result_prog)
def test_exponentiate(): # test rotation of single qubit generator = PauliTerm("Z", 0, 1.0) para_prog = exponential_map(generator) prog = para_prog(1) result_prog = Program().inst(RZ(2.0)(0)) compare_progs(prog, result_prog) # testing general 2-circuit generator = PauliTerm("Z", 1, 1.0) * PauliTerm("Z", 0, 1.0) para_prog = exponential_map(generator) prog = para_prog(1) result_prog = Program().inst(CNOT(0, 1)).inst(RZ(2.0)(1)).inst(CNOT(0, 1)) compare_progs(prog, result_prog) # testing change of basis position 0 generator = PauliTerm("Z", 1, 1.0) * PauliTerm("X", 0, 1.0) param_prog = exponential_map(generator) prog = param_prog(1) result_prog = Program().inst( [H(0), CNOT(0, 1), RZ(2.0)(1), CNOT(0, 1), H(0)]) compare_progs(prog, result_prog) # testing change of basis position 1 generator = PauliTerm("X", 1, 1.0) * PauliTerm("Z", 0, 1.0) para_prog = exponential_map(generator) prog = para_prog(1) result_prog = Program().inst( [H(1), CNOT(0, 1), RZ(2.0)(1), CNOT(0, 1), H(1)]) compare_progs(prog, result_prog) # testing change of basis position 0 generator = PauliTerm("Z", 1, 1.0) * PauliTerm("Y", 0, 1.0) para_prog = exponential_map(generator) prog = para_prog(1) result_prog = Program().inst([ RX(math.pi / 2.0)(0), CNOT(0, 1), RZ(2.0)(1), CNOT(0, 1), RX(-math.pi / 2)(0) ]) compare_progs(prog, result_prog) # testing change of basis position 1 generator = PauliTerm("Y", 1, 1.0) * PauliTerm("Z", 0, 1.0) para_prog = exponential_map(generator) prog = para_prog(1) result_prog = Program().inst([ RX(math.pi / 2.0)(1), CNOT(0, 1), RZ(2.0)(1), CNOT(0, 1), RX(-math.pi / 2.0)(1) ]) compare_progs(prog, result_prog) # testing circuit for 3-terms with change of basis generator = PauliTerm("X", 2, 1.0) * PauliTerm("Y", 1, 1.0) * PauliTerm( "Z", 0, 1.0) para_prog = exponential_map(generator) prog = para_prog(1) result_prog = Program().inst([ RX(math.pi / 2.0)(1), H(2), CNOT(0, 1), CNOT(1, 2), RZ(2.0)(2), CNOT(1, 2), CNOT(0, 1), RX(-math.pi / 2.0)(1), H(2) ]) compare_progs(prog, result_prog) # testing circuit for 3-terms non-sequential generator = PauliTerm("Y", 3, 1.0) * PauliTerm("Y", 2, 1.0) * PauliTerm( "I", 1, 1.0) * PauliTerm("Y", 0, 1.0) para_prog = exponential_map(generator) prog = para_prog(1) result_prog = Program().inst([ RX(math.pi / 2.0)(0), RX(math.pi / 2.0)(2), RX(math.pi / 2.0)(3), CNOT(0, 2), CNOT(2, 3), RZ(2.0)(3), CNOT(2, 3), CNOT(0, 2), RX(-math.pi / 2.0)(0), RX(-math.pi / 2.0)(2), RX(-math.pi / 2.0)(3) ]) compare_progs(prog, result_prog)
def implementGate(device, gate, qubit, script, frac=0): # *This function contains SDK specific code.* # # Input: # * *device* - String specifying the device on which the game is played. # Details about the device will be obtained using getLayout. # * *gate* - String that specifies gate type. # * *qubit* - Qubit, list of two qubits or qubit register on which the gate is applied. # * *script* - # * *frac* - # # Process: # * For gates of type 'X', 'Z' and 'XX', the gate $U = \exp(-i \,\times\, gate \,\times\, frac )$ is implemented on the qubit or pair of qubits in *qubit*. # * *gate='Finish'* implements the measurement command on the qubit register required for ProjectQ to not complain. # # Output: # * None are returned, but modifications are made to the classes that contain the quantum program. num, area, entangleType, pairs, pos, example, sdk, runs = getLayout(device) if sdk in ["QISKit", "ManualQISKit"]: if gate == 'X': script.u3(frac * math.pi, -math.pi / 2, math.pi / 2, qubit) elif gate == 'Z': # actually a Y axis rotation script.u3(frac * math.pi, 0, 0, qubit) elif gate == 'XX': if entangleType == 'CX': script.cx(qubit[0], qubit[1]) script.u3(frac * math.pi, -math.pi / 2, math.pi / 2, qubit[0]) script.cx(qubit[0], qubit[1]) elif entangleType == 'CZ': script.h(qubit[1]) script.cz(qubit[0], qubit[1]) script.u3(frac * math.pi, -math.pi / 2, math.pi / 2, qubit[0]) script.cz(qubit[0], qubit[1]) script.h(qubit[1]) else: print("Support for this is yet to be added") elif sdk == "ProjectQ": if gate == 'X': Rx(frac * math.pi) | qubit elif gate == 'Z': # actually a Y axis rotation Ry(frac * math.pi) | qubit elif gate == 'XX': if entangleType == 'CX': CNOT | (qubit[0], qubit[1]) Rx(frac * math.pi) | qubit[0] CNOT | (qubit[0], qubit[1]) elif entangleType == 'CZ': H | qubit[1] C(Z) | (qubit[0], qubit[1]) Rx(frac * math.pi) | qubit[0] C(Z) | (qubit[0], qubit[1]) H | qubit[1] else: print("Support for this is yet to be added") elif gate == 'finish': Measure | qubit elif sdk == "Forest": if gate == 'X': if qubit in pos.keys(): # only if qubit is active script.inst(RX(frac * math.pi, qubit)) elif gate == 'Z': # actually a Y axis rotation if qubit in pos.keys(): # only if qubit is active script.inst(RY(frac * math.pi, qubit)) elif gate == 'XX': if entangleType == 'CX': script.inst(CNOT(qubit[0], qubit[1])) script.inst(RX(frac * math.pi, qubit[0])) script.inst(CNOT(qubit[0], qubit[1])) elif entangleType == 'CZ': script.inst(H(qubit[1])) script.inst(CZ(qubit[0], qubit[1])) script.inst(RX(frac * math.pi, qubit[0])) script.inst(CZ(qubit[0], qubit[1])) script.inst(H(qubit[1])) elif entangleType == 'none': script.inst(RX(frac * math.pi, qubit[0])) script.inst(RX(frac * math.pi, qubit[1])) else: print("Support for this is yet to be added")