Beispiel #1
0
def test_probabilities():
    p = 1
    n_qubits = 2
    # known set of angles for barbell
    angles = [1.96348709, 4.71241069]

    wf = np.array([
        -1.17642098e-05 - 1j * 7.67538040e-06,
        -7.67563580e-06 - 1j * 7.07106781e-01,
        -7.67563580e-06 - 1j * 7.07106781e-01,
        -1.17642098e-05 - 1j * 7.67538040e-06
    ])
    with patch("grove.pyqaoa.qaoa.WavefunctionSimulator") as mock_wfs:
        fake_wfs = Mock(WavefunctionSimulator)
        fake_wfs.wavefunction.return_value = Wavefunction(wf)
        mock_wfs.return_value = fake_wfs

        fake_qc = Mock(QuantumComputer)
        inst = QAOA(qc=fake_qc,
                    qubits=list(range(n_qubits)),
                    steps=p,
                    rand_seed=42)

        probs = inst.probabilities(angles)
        assert isinstance(probs, np.ndarray)

    prob_true = np.zeros((inst.nstates, 1))
    prob_true[1] = 0.5
    prob_true[2] = 0.5
    assert np.isclose(probs, prob_true).all()
Beispiel #2
0
def recover_complexes(coef_string, classical_addresses):
    """
    From a bit packed string, unpacks to get the wavefunction and classical measurement results
    :param coef_string:
    :param classical_addresses:
    :return:
    """
    num_octets = len(coef_string)
    num_addresses = len(classical_addresses)
    num_memory_octets = _round_to_next_multiple(num_addresses, 8) // 8
    num_wavefunction_octets = num_octets - num_memory_octets

    # Parse the classical memory
    mem = []
    for i in range(num_memory_octets):
        octet = struct.unpack('B', coef_string[i:i + 1])[0]
        mem.extend(_octet_bits(octet))

    mem = mem[0:num_addresses]

    # Parse the wavefunction
    wf = np.zeros(num_wavefunction_octets // OCTETS_PER_COMPLEX_DOUBLE,
                  dtype=np.cfloat)
    for i, p in enumerate(
            range(num_memory_octets, num_octets, OCTETS_PER_COMPLEX_DOUBLE)):
        re_be = coef_string[p:p + OCTETS_PER_DOUBLE_FLOAT]
        im_be = coef_string[p + OCTETS_PER_DOUBLE_FLOAT:p +
                            OCTETS_PER_COMPLEX_DOUBLE]
        re = struct.unpack('>d', re_be)[0]
        im = struct.unpack('>d', im_be)[0]
        wf[i] = complex(re, im)

    return Wavefunction(wf), mem
Beispiel #3
0
    def get_wavefunction(self, circuit):
        """Run a circuit and get the wavefunction of the resulting statevector.

        Args:
            circuit (zquantum.core.circuit.Circuit): the circuit to prepare the state
        Returns:
            pyquil.wavefunction.Wavefunction
        """
        self.num_circuits_run += 1
        self.num_jobs_run += 1
        ibmq_circuit = circuit.to_qiskit()

        coupling_map = None
        if self.device_connectivity is not None:
            coupling_map = CouplingMap(self.device_connectivity.connectivity)

        # Execute job to get wavefunction
        job = execute(
            ibmq_circuit,
            self.device,
            noise_model=self.noise_model,
            coupling_map=coupling_map,
            basis_gates=self.basis_gates,
        )
        wavefunction = job.result().get_statevector(ibmq_circuit, decimals=20)
        return Wavefunction(wavefunction)
Beispiel #4
0
 def test_sample_from_wavefunction_list(self):
     n_qubits = 4
     # NOTE: our indexing places the state of qubit i at the ith index of the tuple. Hence |01> will result in
     # the tuple (1, 0)
     expected_bitstring = (1, 0, 0, 0)
     amplitudes = [0] * (2**n_qubits)
     amplitudes[1] = 1  # |0001> will be measured in all cases.
     wavefunction = Wavefunction(amplitudes)
     sample = set(sample_from_wavefunction(wavefunction, 500))
     self.assertEqual(len(sample), 1)
     self.assertEqual(sample.pop(), expected_bitstring)
def test_sample_from_wavefunction_row_vector():
    n_qubits = 4
    # NOTE: our indexing places the state of qubit i at the ith index of the tuple. Hence |01> will result in
    # the tuple (1, 0)
    expected_bitstring = (1, 0, 0, 0)
    amplitudes = np.array([0] * (2**n_qubits))
    amplitudes[1] = 1  # |0001> will be measured in all cases.
    wavefunction = Wavefunction(amplitudes)
    sample = set(sample_from_wavefunction(wavefunction, 500))
    assert len(sample) == 1
    assert sample.pop() == expected_bitstring
Beispiel #6
0
def jw_get_ground_state_at_particle_number(particle_number, qubit_operator):
    qubit_operator = load_qubit_operator(qubit_operator)
    sparse_matrix = qubit_operator_sparse(qubit_operator)

    ground_energy, ground_state_amplitudes = _jw_get_ground_state_at_particle_number(
        sparse_matrix, particle_number
    )
    ground_state = Wavefunction(ground_state_amplitudes)
    value_estimate = ValueEstimate(ground_energy)

    save_wavefunction(ground_state, "ground-state.json")
    save_value_estimate(value_estimate, "value-estimate.json")
Beispiel #7
0
def create_random_wavefunction(n_qubits, seed=None):
    if seed:
        np.random.seed(seed)

    random_vector = [
        complex(a, b) for a, b in zip(np.random.rand(2**n_qubits),
                                      np.random.rand(2**n_qubits))
    ]
    normalization_factor = np.sqrt(np.sum(np.abs(random_vector)**2))
    random_vector /= normalization_factor

    return Wavefunction(random_vector)
    def wavefunction(self, program):
        """
        Simulate the program and then project out the final state.

        Return the final state as a wavefunction pyquil object

        :param program: pyQuil program composed of stabilizer operations only
        :return: pyquil.Wavefunction.wavefunction object.
        """
        self.load_program(program)
        self.tableau = self._n_qubit_tableau(self.num_qubits)
        self.kernel()
        stabilizers = binary_stabilizer_to_pauli_stabilizer(
            self.stabilizer_tableau())
        stabilizer_state = project_stabilized_state(stabilizers)
        stabilizer_state = stabilizer_state.toarray()
        return Wavefunction(stabilizer_state.flatten())
Beispiel #9
0
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


    with patch("pyquil.api.QuantumComputer") as fake_qc, \
            patch("grove.pyvqe.vqe.WavefunctionSimulator") as mock_wfs:
        fake_qc.run.return_value = [[0], [0]]

        fake_wfs = Mock(WavefunctionSimulator)
        fake_wfs.wavefunction.return_value = Wavefunction(
            rotation_wavefunction(-2.5))
        fake_wfs.expectation.return_value = [0.28366219]
        mock_wfs.return_value = fake_wfs

        inst = VQE(minimizer)
        energy = inst.expectation(prog, PauliSum([hamiltonian]), None, fake_qc)
        assert np.isclose(energy, 0.28366219)

        hamiltonian = np.array([[1, 0], [0, -1]])
        energy = inst.expectation(prog, hamiltonian, None, fake_qc)
        assert np.isclose(energy, 0.28366219)

        prog = Program(H(0))
        hamiltonian = PauliSum([PauliTerm('X', 0)])
        energy = inst.expectation(prog, hamiltonian, 2, fake_qc)
        assert np.isclose(energy, 1.0)
Beispiel #10
0
    def wavefunction(self, pyquil_program, classical_addresses=None):
        """
        Simulate a pyQuil program and get the wavefunction back.

        :param Program pyquil_program: A pyQuil program.
        :param list classical_addresses: An optional list of classical
                 addresses.

        :return: A tuple whose first element is a Wavefunction object,
                 and whose second element is the list of classical bits
                 corresponding to the classical addresses.
        :rtype: tuple
        """
        # load program
        self.load_program(pyquil_program)

        # check valid classical memory access
        if not isinstance(classical_addresses, type(None)):
            # check that no classical addresses are repeated
            assert len(set(classical_addresses)) == len(classical_addresses)
            # check that all classical addresses are valid
            if np.min(classical_addresses) < 0 or \
               np.max(classical_addresses) >= len(self.classical_memory):
                raise RuntimeError("Improper classical memory access outside "
                                   "allocated classical memory range.")
            # set classical bitmask
            mask = np.array(classical_addresses)
        else:
            mask = None

        # setup wavefunction
        self.wf = np.zeros(2**self.num_qubits, dtype=np.complex128)
        self.wf[0] = complex(1.0, 0)

        # evolve wf with program, via kernel
        self.kernel()

        # convert bools (False, True) to ints (0, 1)
        if isinstance(mask, type(None)):
            # return all
            results = [int(x) for x in self.classical_memory]
        else:
            results = [int(x) for x in self.classical_memory[mask]]

        return Wavefunction(self.wf), results
def load_wavefunction(file: TextIO) -> Wavefunction:
    """Load a qubit wavefunction from a file.

    Args:
        file (str or file-like object): the name of the file, or a file-like object.

    Returns:
        wavefunction (pyquil.wavefunction.Wavefunction): the wavefunction object
    """

    if isinstance(file, str):
        with open(file, 'r') as f:
            data = json.load(f)
    else:
        data = json.load(file)

    wavefunction = Wavefunction(convert_dict_to_array(data['amplitudes']))
    return wavefunction
Beispiel #12
0
def jw_get_ground_state_at_particle_number(
        particle_number: int, qubit_operator: Union[str, SymbolicOperator]):
    """Get the ground state wavefunction of the operator for the input particle number. Outputs are serialized to JSON
    within the files: "ground-state.json" and "value-estimate.json"

    ARGS:
        particle_number (int): The given number of particles in the system
        qubit_operator (Union[str, SymbolicOperator]): The operator for which to find the ground state
    """
    if isinstance(qubit_operator, str):
        qubit_operator = load_qubit_operator(qubit_operator)
    sparse_matrix = qubit_operator_sparse(qubit_operator)

    ground_energy, ground_state_amplitudes = _jw_get_ground_state_at_particle_number(
        sparse_matrix, particle_number)
    ground_state = Wavefunction(ground_state_amplitudes)
    value_estimate = ValueEstimate(ground_energy)

    save_wavefunction(ground_state, "ground-state.json")
    save_value_estimate(value_estimate, "value-estimate.json")
Beispiel #13
0
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)), [0])
    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)
Beispiel #14
0
def test_probabilities():
    p = 1
    n_qubits = 2
    # known set of angles for barbell
    angles = [1.96348709,  4.71241069]
    wf = np.array([-1.17642098e-05 - 1j*7.67538040e-06,
                   -7.67563580e-06 - 1j*7.07106781e-01,
                   -7.67563580e-06 - 1j*7.07106781e-01,
                   -1.17642098e-05 - 1j*7.67538040e-06])
    fakeQVM = Mock(spec=qvm_module.SyncConnection())
    fakeQVM.wavefunction = Mock(return_value=(Wavefunction(wf), 0))
    inst = QAOA(fakeQVM, n_qubits, steps=p,
                rand_seed=42)

    true_probs = np.zeros_like(wf)
    for xx in range(wf.shape[0]):
        true_probs[xx] = np.conj(wf[xx]) * wf[xx]
    probs = inst.probabilities(angles)
    assert isinstance(probs, np.ndarray)
    prob_true = np.zeros((2**inst.n_qubits, 1))
    prob_true[1] = 0.5
    prob_true[2] = 0.5
    assert np.isclose(probs, prob_true).all()
Beispiel #15
0
    def get_wavefunction(self, circuit):
        """
        Returns a wavefunction representing quantum state produced by a circuit

        Args:
            circuit (core.circuit.Circuit): quantum circuit to be executed.

        Returns:
            pyquil.Wafefunction: wavefunction object.

        """
        num_qubits = len(circuit.get_qubits())
        dev = qml.device(self.device, wires=num_qubits)

        ansatz = qml.from_qiskit(circuit.to_qiskit())

        @qml.qnode(dev)
        def _circuit():
            ansatz(wires=list(range(num_qubits)))
            return qml.expval(qml.Identity(0))

        _circuit()
        return Wavefunction(dev.state)
def test_imag_wavefunction_io():
    wf = Wavefunction([0, 1j, 0, 0, 0, 0, 0, 0])
    save_wavefunction(wf, "wavefunction.json")
    loaded_wf = load_wavefunction("wavefunction.json")
    assert np.allclose(wf.amplitudes, loaded_wf.amplitudes)
    remove_file_if_exists("wavefunction.json")
Beispiel #17
0
 def get_wavefunction(self, circuit):
     qulacs_state = self.get_qulacs_state_from_circuit(circuit)
     amplitudes = qulacs_state.get_vector()
     return Wavefunction(amplitudes)
Beispiel #18
0
 def test_imag_wavefunction_io(self):
     wf = Wavefunction([0, 1j, 0, 0, 0, 0, 0, 0])
     save_wavefunction(wf, "wavefunction.json")
     loaded_wf = load_wavefunction("wavefunction.json")
     self.assertTrue(np.allclose(wf.amplitudes, loaded_wf.amplitudes))
     os.remove("wavefunction.json")
def wvf():
    return Wavefunction(np.array([1.0, 1.j, 0.000005, 0.02]))
 def test_real_wavefunction_io(self):
     wf = Wavefunction([0, 1, 0, 0, 0, 0, 0, 0])
     save_wavefunction(wf, 'wavefunction.json')
     loaded_wf = load_wavefunction('wavefunction.json')
     self.assertTrue(np.allclose(wf.amplitudes, loaded_wf.amplitudes))
     os.remove('wavefunction.json')
Beispiel #21
0
def wvf():
    amps = np.array([1.0, 1.j, 0.000005, 0.02])
    amps /= np.sqrt(np.sum(np.abs(amps)**2))
    return Wavefunction(amps)