def test_against_ref_qft_8(): p = Program(QFT_8_INSTRUCTIONS) qam = PyQVM(n_qubits=8, quantum_simulator_type=ReferenceWavefunctionSimulator) qam.execute(p) wf = qam.wf_simulator.wf np.testing.assert_allclose(QFT_8_WF_PROBS, wf)
def test_qaoa_circuit(): wf_true = [ 0.00167784 + 1.00210180e-05 * 1j, 0.50000000 - 4.99997185e-01 * 1j, 0.50000000 - 4.99997185e-01 * 1j, 0.00167784 + 1.00210180e-05 * 1j, ] prog = Program() prog.inst( [ RY(np.pi / 2, 0), RX(np.pi, 0), RY(np.pi / 2, 1), RX(np.pi, 1), CNOT(0, 1), RX(-np.pi / 2, 1), RY(4.71572463191, 1), RX(np.pi / 2, 1), CNOT(0, 1), RX(-2 * 2.74973750579, 0), RX(-2 * 2.74973750579, 1), ] ) qam = PyQVM(n_qubits=2, quantum_simulator_type=ReferenceWavefunctionSimulator) qam.execute(prog) wf = qam.wf_simulator.wf np.testing.assert_allclose(wf_true, wf, atol=1e-8)
def test_sample_bitstrings(): prog = Program(H(0), H(1)) qam = PyQVM(n_qubits=3, quantum_simulator_type=NumpyWavefunctionSimulator, seed=52) qam.execute(prog) bitstrings = qam.wf_simulator.sample_bitstrings(10000) assert bitstrings.shape == (10000, 3) np.testing.assert_allclose([0.5, 0.5, 0], np.mean(bitstrings, axis=0), rtol=1e-2)
def test_einsum_simulator_1(): prog = Program(H(0), CNOT(0, 1)) qam = PyQVM(n_qubits=2, quantum_simulator_type=NumpyWavefunctionSimulator) qam.execute(prog) wf = qam.wf_simulator.wf np.testing.assert_allclose( wf, 1 / np.sqrt(2) * np.reshape([1, 0, 0, 1], (2, 2)))
def test_exp_circuit(): true_wf = np.array( [ 0.54030231 - 0.84147098j, 0.00000000 + 0.0j, 0.00000000 + 0.0j, 0.00000000 + 0.0j, 0.00000000 + 0.0j, 0.00000000 + 0.0j, 0.00000000 + 0.0j, 0.00000000 + 0.0j, ] ) create2kill1 = PauliTerm("X", 1, -0.25) * PauliTerm("Y", 2) create2kill1 += PauliTerm("Y", 1, 0.25) * PauliTerm("Y", 2) create2kill1 += PauliTerm("Y", 1, 0.25) * PauliTerm("X", 2) create2kill1 += PauliTerm("X", 1, 0.25) * PauliTerm("X", 2) create2kill1 += PauliTerm("I", 0, 1.0) prog = Program() for term in create2kill1.terms: single_exp_prog = exponentiate(term) prog += single_exp_prog qam = PyQVM(n_qubits=3, quantum_simulator_type=ReferenceWavefunctionSimulator) qam.execute(prog) wf = qam.wf_simulator.wf np.testing.assert_allclose(wf.dot(np.conj(wf).T), true_wf.dot(np.conj(true_wf).T))
def test_einsum_simulator_CCNOT(): prog = Program(X(2), X(0), CCNOT(2, 1, 0)) qam = PyQVM(n_qubits=3, quantum_simulator_type=NumpyWavefunctionSimulator) qam.execute(prog) wf = qam.wf_simulator.wf should_be = np.zeros((2, 2, 2)) should_be[1, 0, 1] = 1 np.testing.assert_allclose(wf, should_be)
def test_bell_state(): prog = Program().inst([H(0), CNOT(0, 1)]) qam = PyQVM(n_qubits=2, quantum_simulator_type=ReferenceWavefunctionSimulator) qam.execute(prog) wf = qam.wf_simulator.wf ref_bell = np.zeros(4) ref_bell[0] = ref_bell[-1] = 1.0 / np.sqrt(2) np.testing.assert_allclose(ref_bell, wf)
def test_occupation_basis(): prog = Program().inst([X(0), X(1), I(2), I(3)]) state = np.zeros(2 ** 4) state[3] = 1.0 qam = PyQVM(n_qubits=4, quantum_simulator_type=ReferenceWavefunctionSimulator) qam.execute(prog) np.testing.assert_allclose(state, qam.wf_simulator.wf)
def test_kraus_application_bitflip(): p = 0.372 qam = PyQVM(n_qubits=1, quantum_simulator_type=ReferenceDensitySimulator, post_gate_noise_probabilities={'bit_flip': p}) initial_density = _random_1q_density() qam.wf_simulator.density = initial_density qam.execute(Program(I(0))) final_density = (1 - p) * initial_density + p * qmats.X.dot(initial_density).dot(qmats.X) np.testing.assert_allclose(final_density, qam.wf_simulator.density)
def test_kraus_application_dephasing(): p = 0.372 qam = PyQVM(n_qubits=1, quantum_simulator_type=ReferenceDensitySimulator, post_gate_noise_probabilities={'dephasing': p}) rho = _random_1q_density() qam.wf_simulator.density = rho qam.execute(Program(I(0))) final_density = np.array([[rho[0, 0], (1 - p) * rho[0, 1]], [(1 - p) * rho[1, 0], rho[1, 1]]]) np.testing.assert_allclose(final_density, qam.wf_simulator.density)
def test_einsum_simulator_10q(): prog = Program(H(0)) for i in range(10 - 1): prog += CNOT(i, i + 1) qam = PyQVM(n_qubits=10, quantum_simulator_type=NumpyWavefunctionSimulator) qam.execute(prog) wf = qam.wf_simulator.wf should_be = np.zeros((2, ) * 10) should_be[0, 0, 0, 0, 0, 0, 0, 0, 0, 0] = 1 / np.sqrt(2) should_be[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] = 1 / np.sqrt(2) np.testing.assert_allclose(wf, should_be)
def test_measure(): qam = PyQVM(n_qubits=3, quantum_simulator_type=NumpyWavefunctionSimulator) qam.execute(Program(Declare("ro", "BIT", 64), H(0), CNOT(0, 1), MEASURE(0, MemoryReference("ro", 63)))) measured_bit = qam.ram["ro"][-1] should_be = np.zeros((2, 2, 2)) if measured_bit == 1: should_be[1, 1, 0] = 1 else: should_be[0, 0, 0] = 1 np.testing.assert_allclose(qam.wf_simulator.wf, should_be)
def test_kraus_application_depolarizing(): p = 0.372 qam = PyQVM(n_qubits=1, quantum_simulator_type=ReferenceDensitySimulator, post_gate_noise_probabilities={'depolarizing': p}) rho = _random_1q_density() qam.wf_simulator.density = rho qam.execute(Program(I(0))) final_density = (1 - p) * rho + (p / 3) * (qmats.X.dot(rho).dot(qmats.X) + qmats.Y.dot(rho).dot(qmats.Y) + qmats.Z.dot(rho).dot(qmats.Z)) np.testing.assert_allclose(final_density, qam.wf_simulator.density)
def test_if_then_2(): # if FALSE creg, then measure 0 should give 1 prog = Program() creg = prog.declare("creg", "BIT") prog.inst(MOVE(creg, 0), X(0)) branch_a = Program(X(0)) branch_b = Program() prog.if_then(creg, branch_a, branch_b) prog += MEASURE(0, creg) qam = PyQVM(n_qubits=1, quantum_simulator_type=ReferenceWavefunctionSimulator) qam.execute(prog) assert qam.ram["creg"][0] == 1
def test_kraus_compound_T1T2_application(): p1 = 0.372 p2 = 0.45 qam = PyQVM(n_qubits=1, quantum_simulator_type=ReferenceDensitySimulator, post_gate_noise_probabilities={'relaxation': p1, 'dephasing': p2}) rho = _random_1q_density() qam.wf_simulator.density = rho qam.execute(Program(I(0))) final_density = np.array([[rho[0, 0] + rho[1, 1] * p1, (1 - p2) * np.sqrt(1 - p1) * rho[0, 1]], [(1 - p2) * np.sqrt(1 - p1) * rho[1, 0], (1 - p1) * rho[1, 1]]]) np.testing.assert_allclose(final_density, qam.wf_simulator.density)
def test_while(): init_register = Program() classical_flag_register = init_register.declare("classical_flag_register", "BIT") init_register += MOVE(classical_flag_register, True) loop_body = Program(X(0), H(0)).measure(0, classical_flag_register) # Put it all together in a loop program: loop_prog = init_register.while_do(classical_flag_register, loop_body) qam = PyQVM(n_qubits=1, quantum_simulator_type=ReferenceWavefunctionSimulator) qam.execute(loop_prog) assert qam.ram[classical_flag_register.name][0] == 0
def test_generate_arbitrary_states(arbitrary_state): prog, v = arbitrary_state prog = Program(prog) qam = PyQVM(n_qubits=8, quantum_simulator_type=ReferenceWavefunctionSimulator) qam.execute(prog) wf = qam.wf_simulator.wf # check actual part of wavefunction np.testing.assert_allclose(v, wf[: len(v)], atol=1e-10) # check remaining zeros part of wavefunction np.testing.assert_allclose(np.zeros(wf.shape[0] - len(v)), wf[len(v) :])
def test_vs_lisp_qvm(qvm, n_qubits, prog_length): for _ in range(10): prog = _generate_random_program(n_qubits=n_qubits, length=prog_length) lisp_wf = WavefunctionSimulator() # force lisp wfs to allocate all qubits lisp_wf = lisp_wf.wavefunction(Program(I(q) for q in range(n_qubits)) + prog) lisp_wf = lisp_wf.amplitudes ref_qam = PyQVM(n_qubits=n_qubits, quantum_simulator_type=ReferenceWavefunctionSimulator) ref_qam.execute(prog) ref_wf = ref_qam.wf_simulator.wf np.testing.assert_allclose(lisp_wf, ref_wf, atol=1e-15)
def test_if_then(): # if TRUE creg, then measure 0 should give 0 prog = Program() creg = prog.declare('creg', 'BIT') prog.inst(MOVE(creg, 1), X(0)) branch_a = Program(X(0)) branch_b = Program() prog.if_then(creg, branch_a, branch_b) prog += MEASURE(0, creg) qam = PyQVM(n_qubits=1, quantum_simulator_type=ReferenceWavefunctionSimulator) qam.execute(prog) assert qam.ram['creg'][0] == 0
def test_vs_ref_simulator(n_qubits, prog_length, include_measures): if include_measures: seed = 52 else: seed = None for _ in range(10): prog = _generate_random_program(n_qubits=n_qubits, length=prog_length, include_measures=include_measures) ref_qam = PyQVM(n_qubits=n_qubits, seed=seed, quantum_simulator_type=ReferenceWavefunctionSimulator) ref_qam.execute(prog) ref_wf = ref_qam.wf_simulator.wf es_qam = PyQVM(n_qubits=n_qubits, seed=seed, quantum_simulator_type=NumpyWavefunctionSimulator) es_qam.execute(prog) es_wf = es_qam.wf_simulator.wf # einsum has its wavefunction as a vector of shape (2, 2, 2, ...) where qubits are indexed # from left to right. We transpose then flatten. es_wf = es_wf.transpose().reshape(-1) np.testing.assert_allclose(ref_wf, es_wf, atol=1e-15)
def test_defgate(): # regression test for https://github.com/rigetti/pyquil/issues/1059 theta = np.pi / 2 U = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, np.cos(theta / 2), -1j * np.sin(theta / 2)], [0, 0, -1j * np.sin(theta / 2), np.cos(theta / 2)]]) gate_definition = DefGate('U_test', U) U_test = gate_definition.get_constructor() p = Program() p += gate_definition p += X(1) p += U_test(1, 0) qam = PyQVM(n_qubits=2, quantum_simulator_type=NumpyWavefunctionSimulator) qam.execute(p) wf1 = qam.wf_simulator.wf should_be = np.zeros((2, 2), dtype=np.complex128) one_over_sqrt2 = 1 / np.sqrt(2) should_be[0, 1] = one_over_sqrt2 should_be[1, 1] = -1j * one_over_sqrt2 np.testing.assert_allclose(wf1, should_be) # Ensure the output of the custom U_test gate matches the standard RX gate. Something like # RX(theta, 0).controlled(1) would be a more faithful reproduction of U_test, but # NumpyWavefunctionSimulator doesn't (yet) support gate modifiers, so just apply the RX gate # unconditionally. p = Program() p += X(1) p += RX(theta, 0) qam = PyQVM(n_qubits=2, quantum_simulator_type=NumpyWavefunctionSimulator) qam.execute(p) wf2 = qam.wf_simulator.wf np.testing.assert_allclose(wf1, wf2)
def test_measure_bitstrings(client_configuration: QCSClientConfiguration): quantum_processor = NxQuantumProcessor(nx.complete_graph(2)) dummy_compiler = DummyCompiler(quantum_processor=quantum_processor, client_configuration=client_configuration) qc_pyqvm = QuantumComputer(name="testy!", qam=PyQVM(n_qubits=2), compiler=dummy_compiler) qc_forest = QuantumComputer( name="testy!", qam=QVM(client_configuration=client_configuration, gate_noise=(0.00, 0.00, 0.00)), compiler=dummy_compiler, ) prog = Program(I(0), I(1)) meas_qubits = [0, 1] sym_progs, flip_array = _symmetrization(prog, meas_qubits, symm_type=-1) results = _measure_bitstrings(qc_pyqvm, sym_progs, meas_qubits, num_shots=1) # test with pyQVM answer = [ np.array([[0, 0]]), np.array([[0, 1]]), np.array([[1, 0]]), np.array([[1, 1]]) ] assert all([np.allclose(x, y) for x, y in zip(results, answer)]) # test with regular QVM results = _measure_bitstrings(qc_forest, sym_progs, meas_qubits, num_shots=1) assert all([np.allclose(x, y) for x, y in zip(results, answer)])
def test_larger_qaoa_density(): prog = Program(H(0), H(1), H(2), H(3), X(0), PHASE(0.3928244130249029, 0), X(0), PHASE(0.3928244130249029, 0), CNOT(0, 1), RZ(0.78564882604980579, 1), CNOT(0, 1), X(0), PHASE(0.3928244130249029, 0), X(0), PHASE(0.3928244130249029, 0), CNOT(0, 3), RZ(0.78564882604980579, 3), CNOT(0, 3), X(0), PHASE(0.3928244130249029, 0), X(0), PHASE(0.3928244130249029, 0), CNOT(1, 2), RZ(0.78564882604980579, 2), CNOT(1, 2), X(0), PHASE(0.3928244130249029, 0), X(0), PHASE(0.3928244130249029, 0), CNOT(2, 3), RZ(0.78564882604980579, 3), CNOT(2, 3), H(0), RZ(-0.77868204192240842, 0), H(0), H(1), RZ(-0.77868204192240842, 1), H(1), H(2), RZ(-0.77868204192240842, 2), H(2), H(3), RZ(-0.77868204192240842, 3), H(3)) qam = PyQVM(n_qubits=4, quantum_simulator_type=ReferenceDensitySimulator) \ .execute(prog) rho_test = qam.wf_simulator.density wf_true = np.array([ 8.43771693e-05 - 0.1233845 * 1j, -1.24927731e-01 + 0.00329533 * 1j, -1.24927731e-01 + 0.00329533 * 1j, -2.50040954e-01 + 0.12661547 * 1j, -1.24927731e-01 + 0.00329533 * 1j, -4.99915497e-01 - 0.12363516 * 1j, -2.50040954e-01 + 0.12661547 * 1j, -1.24927731e-01 + 0.00329533 * 1j, -1.24927731e-01 + 0.00329533 * 1j, -2.50040954e-01 + 0.12661547 * 1j, -4.99915497e-01 - 0.12363516 * 1j, -1.24927731e-01 + 0.00329533 * 1j, -2.50040954e-01 + 0.12661547 * 1j, -1.24927731e-01 + 0.00329533 * 1j, -1.24927731e-01 + 0.00329533 * 1j, 8.43771693e-05 - 0.1233845 * 1j ]) wf_true = np.reshape(wf_true, (2**4, 1)) rho_true = np.dot(wf_true, np.conj(wf_true).T) np.testing.assert_allclose(rho_true, rho_test, atol=1e-8)
def test_qaoa_density(): wf_true = [ 0.00167784 + 1.00210180e-05 * 1j, 0.50000000 - 4.99997185e-01 * 1j, 0.50000000 - 4.99997185e-01 * 1j, 0.00167784 + 1.00210180e-05 * 1j ] wf_true = np.reshape(np.array(wf_true), (4, 1)) rho_true = np.dot(wf_true, np.conj(wf_true).T) prog = Program() prog.inst([ RY(np.pi / 2, 0), RX(np.pi, 0), RY(np.pi / 2, 1), RX(np.pi, 1), CNOT(0, 1), RX(-np.pi / 2, 1), RY(4.71572463191, 1), RX(np.pi / 2, 1), CNOT(0, 1), RX(-2 * 2.74973750579, 0), RX(-2 * 2.74973750579, 1) ]) qam = PyQVM(n_qubits=2, quantum_simulator_type=ReferenceDensitySimulator) \ .execute(prog) rho = qam.wf_simulator.density np.testing.assert_allclose(rho_true, rho, atol=1e-8)
class NumpyWavefunctionDevice(WavefunctionDevice): r"""NumpyWavefunction simulator device for PennyLane. Args: wires (int): the number of qubits to initialize the device in shots (int): Number of circuit evaluations/random samples used to estimate expectation values of observables. """ name = "pyQVM NumpyWavefunction Simulator Device" short_name = "forest.numpy_wavefunction" observables = {"PauliX", "PauliY", "PauliZ", "Hadamard", "Hermitian", "Identity"} def __init__(self, wires, *, shots=1000, analytic=True, **kwargs): super(WavefunctionDevice, self).__init__(wires, shots, analytic, **kwargs) self.qc = PyQVM(n_qubits=wires, quantum_simulator_type=NumpyWavefunctionSimulator) self.state = None def pre_apply(self): self.reset() self.qc.wf_simulator.reset() def pre_measure(self): # TODO: currently, the PyQVM considers qubit 0 as the leftmost bit and therefore # returns amplitudes in the opposite of the Rigetti Lisp QVM (which considers qubit # 0 as the rightmost bit). This may change in the future, so in the future this # might need to get udpated to be similar to the pre_measure function of # pennylane_forest/wavefunction.py self.state = self.qc.execute(self.prog).wf_simulator.wf.flatten()
class NumpyWavefunctionDevice(ForestDevice): r"""NumpyWavefunction simulator device for PennyLane. Args: wires (int or Iterable[Number, str]]): Number of subsystems represented by the device, or iterable that contains unique labels for the subsystems as numbers (i.e., ``[-1, 0, 2]``) or strings (``['ancilla', 'q1', 'q2']``). shots (int): Number of circuit evaluations/random samples used to estimate expectation values of observables. """ name = "pyQVM NumpyWavefunction Simulator Device" short_name = "forest.numpy_wavefunction" observables = { "PauliX", "PauliY", "PauliZ", "Hadamard", "Hermitian", "Identity" } def __init__(self, wires, *, shots=None, **kwargs): super().__init__(wires, shots, **kwargs) self.qc = PyQVM(n_qubits=len(self.wires), quantum_simulator_type=NumpyWavefunctionSimulator) self._state = None def apply(self, operations, **kwargs): self.reset() self.qc.wf_simulator.reset() super().apply(operations, **kwargs) # TODO: currently, the PyQVM considers qubit 0 as the leftmost bit and therefore # returns amplitudes in the opposite of the Rigetti Lisp QVM (which considers qubit # 0 as the rightmost bit). This may change in the future, so in the future this # might need to get udpated to be similar to the pre_measure function of # pennylane_forest/wavefunction.py self._state = self.qc.execute(self.prog).wf_simulator.wf.flatten()
def test_for_negative_probabilities(): # trivial program to do state tomography on prog = Program(I(0)) # make TomographyExperiment expt_settings = [ExperimentSetting(zeros_state([0]), pt) for pt in [sI(0), sX(0), sY(0), sZ(0)]] experiment_1q = TomographyExperiment(settings=expt_settings, program=prog) # make a quantum computer object device = NxDevice(nx.complete_graph(1)) qc_density = QuantumComputer( name="testy!", qam=PyQVM(n_qubits=1, quantum_simulator_type=ReferenceDensitySimulator), device=device, compiler=DummyCompiler(), ) # initialize with a pure state initial_density = np.array([[1.0, 0.0], [0.0, 0.0]]) qc_density.qam.wf_simulator.density = initial_density try: list(measure_observables(qc=qc_density, tomo_experiment=experiment_1q, n_shots=3000)) except ValueError as e: # the error is from np.random.choice by way of self.rs.choice in ReferenceDensitySimulator assert str(e) != "probabilities are not non-negative" # initialize with a mixed state initial_density = np.array([[0.9, 0.0], [0.0, 0.1]]) qc_density.qam.wf_simulator.density = initial_density try: list(measure_observables(qc=qc_density, tomo_experiment=experiment_1q, n_shots=3000)) except ValueError as e: assert str(e) != "probabilities are not non-negative"
def test_measure_bitstrings(forest): device = NxDevice(nx.complete_graph(2)) qc_pyqvm = QuantumComputer(name='testy!', qam=PyQVM(n_qubits=2), device=device, compiler=DummyCompiler()) qc_forest = QuantumComputer(name='testy!', qam=QVM(connection=forest, gate_noise=[0.00] * 3), device=device, compiler=DummyCompiler()) prog = Program(I(0), I(1)) meas_qubits = [0, 1] sym_progs, flip_array = _symmetrization(prog, meas_qubits, symm_type=-1) results = _measure_bitstrings(qc_pyqvm, sym_progs, meas_qubits, num_shots=1) # test with pyQVM answer = [ np.array([[0, 0]]), np.array([[0, 1]]), np.array([[1, 0]]), np.array([[1, 1]]) ] assert all([np.allclose(x, y) for x, y in zip(results, answer)]) # test with regular QVM results = _measure_bitstrings(qc_forest, sym_progs, meas_qubits, num_shots=1) assert all([np.allclose(x, y) for x, y in zip(results, answer)])
def test_kraus_application_relaxation(): p = 0.372 qam = PyQVM( n_qubits=1, quantum_simulator_type=ReferenceDensitySimulator, post_gate_noise_probabilities={"relaxation": p}, ) rho = _random_1q_density() qam.wf_simulator.density = rho qam.execute_once(Program(I(0))) final_density = np.array([ [rho[0, 0] + rho[1, 1] * p, np.sqrt(1 - p) * rho[0, 1]], [np.sqrt(1 - p) * rho[1, 0], (1 - p) * rho[1, 1]], ]) np.testing.assert_allclose(final_density, qam.wf_simulator.density)
def _get_qvm_or_pyqvm(qvm_type, connection, noise_model=None, device=None, requires_executable=False): if qvm_type == 'qvm': return QVM(connection=connection, noise_model=noise_model, requires_executable=requires_executable) elif qvm_type == 'pyqvm': return PyQVM(n_qubits=device.qubit_topology().number_of_nodes()) raise ValueError("Unknown qvm type {}".format(qvm_type))