Exemple #1
0
    def __init__(self, q_system, excited_state=0):
        self.q_system = q_system

        H_sparse_matrix = get_sparse_operator(q_system.jw_qubit_ham)
        if excited_state > 0:
            # H_sparse_matrix = backend. ham_sparse_matrix(q_system, excited_state=excited_state)
            H_sparse_matrix = get_sparse_operator(q_system.jw_qubit_ham)
            if excited_state > 0:
                H_lower_state_terms = q_system.H_lower_state_terms
                assert H_lower_state_terms is not None
                assert len(H_lower_state_terms) >= excited_state
                for i in range(excited_state):
                    term = H_lower_state_terms[i]
                    state = term[1]
                    statevector = QiskitSimBackend.statevector_from_ansatz(
                        state.ansatz_elements,
                        state.parameters,
                        state.n_qubits,
                        state.n_electrons,
                        init_state_qasm=state.init_state_qasm)
                    # add the outer product of the lower lying state to the Hamiltonian
                    H_sparse_matrix += scipy.sparse.csr_matrix(
                        term[0] * numpy.outer(statevector, statevector))

        if H_sparse_matrix.data.nbytes > config.matrix_size_threshold:
            # decrease the size of the matrix. Typically it will have a lot of insignificant very small (~1e-19)
            # elements that do not contribute to the accuracy but inflate the size of the matrix (~200 MB for Lih)
            logging.warning('Hamiltonian sparse matrix accuracy decrease!!!')
            H_sparse_matrix = scipy.sparse.csr_matrix(
                H_sparse_matrix.todense().round(
                    config.floating_point_accuracy_digits))

        super(GlobalCache,
              self).__init__(H_sparse_matrix=H_sparse_matrix,
                             n_qubits=q_system.n_qubits,
                             n_electrons=q_system.n_electrons,
                             commutators_sparse_matrices_dict=None)
Exemple #2
0
def test_spin_symmetric_bogoliubov_transform(n_spatial_orbitals,
                                             conserves_particle_number,
                                             atol=5e-5):
    n_qubits = 2 * n_spatial_orbitals
    qubits = LineQubit.range(n_qubits)

    # Initialize a random quadratic Hamiltonian
    quad_ham = random_quadratic_hamiltonian(n_spatial_orbitals,
                                            conserves_particle_number,
                                            real=True,
                                            expand_spin=True,
                                            seed=28166)

    # Reorder the Hamiltonian and get sparse matrix
    quad_ham = openfermion.get_quadratic_hamiltonian(
        openfermion.reorder(openfermion.get_fermion_operator(quad_ham),
                            openfermion.up_then_down))
    quad_ham_sparse = get_sparse_operator(quad_ham)

    # Compute the orbital energies and transformation_matrix
    up_orbital_energies, _, _ = (quad_ham.diagonalizing_bogoliubov_transform(
        spin_sector=0))
    down_orbital_energies, _, _ = (quad_ham.diagonalizing_bogoliubov_transform(
        spin_sector=1))
    _, transformation_matrix, _ = (
        quad_ham.diagonalizing_bogoliubov_transform())

    # Pick some orbitals to occupy
    up_orbitals = list(range(2))
    down_orbitals = [0, 2, 3]
    energy = sum(up_orbital_energies[up_orbitals]) + sum(
        down_orbital_energies[down_orbitals]) + quad_ham.constant

    # Construct initial state
    initial_state = (sum(2**(n_qubits - 1 - int(i)) for i in up_orbitals) +
                     sum(2**(n_qubits - 1 - int(i + n_spatial_orbitals))
                         for i in down_orbitals))

    # Apply the circuit
    circuit = cirq.Circuit(
        bogoliubov_transform(qubits,
                             transformation_matrix,
                             initial_state=initial_state))
    state = circuit.final_wavefunction(initial_state)

    # Check that the result is an eigenstate with the correct eigenvalue
    numpy.testing.assert_allclose(quad_ham_sparse.dot(state),
                                  energy * state,
                                  atol=atol)
Exemple #3
0
def test_prepare_gaussian_state_with_spin_symmetry(n_spatial_orbitals,
                                                   conserves_particle_number,
                                                   occupied_orbitals,
                                                   initial_state,
                                                   atol=1e-5):

    n_qubits = 2 * n_spatial_orbitals
    qubits = LineQubit.range(n_qubits)

    # Initialize a random quadratic Hamiltonian
    quad_ham = random_quadratic_hamiltonian(
            n_spatial_orbitals,
            conserves_particle_number,
            real=True,
            expand_spin=True,
            seed=639)

    # Reorder the Hamiltonian and get sparse matrix
    quad_ham = openfermion.get_quadratic_hamiltonian(
            openfermion.reorder(
                openfermion.get_fermion_operator(quad_ham),
                openfermion.up_then_down)
    )
    quad_ham_sparse = get_sparse_operator(quad_ham)

    # Compute the energy of the desired state
    energy = 0.0
    for spin_sector in range(2):
        orbital_energies, _, _ = (
            quad_ham.diagonalizing_bogoliubov_transform(
                spin_sector=spin_sector)
        )
        energy += sum(orbital_energies[i]
                      for i in occupied_orbitals[spin_sector])
    energy += quad_ham.constant

    # Get the state using a circuit simulation
    circuit = cirq.Circuit.from_ops(
            prepare_gaussian_state(
                qubits, quad_ham, occupied_orbitals,
                initial_state=initial_state))

    if isinstance(initial_state, list):
        initial_state = sum(1 << (n_qubits - 1 - i) for i in initial_state)
    state = circuit.apply_unitary_effect_to_state(initial_state)

    # Check that the result is an eigenstate with the correct eigenvalue
    numpy.testing.assert_allclose(
            quad_ham_sparse.dot(state), energy * state, atol=atol)
Exemple #4
0
    def get_excitations_generators_matrices_multithread(
            ansatz_element, n_qubits):
        t0 = time.time()
        # in the case of a spin complement pair, there are two generators for each excitation in the pair
        excitations_generators_matrices = []
        sqr_excitations_generators_matrices_form = []
        for term in ansatz_element.excitations_generators:
            excitations_generators_matrices.append(
                get_sparse_operator(term, n_qubits=n_qubits))
            sqr_excitations_generators_matrices_form.append(
                excitations_generators_matrices[-1] *
                excitations_generators_matrices[-1])

        #print('Calculated excitation matrix time ', time.time() - t0)
        return excitations_generators_matrices, sqr_excitations_generators_matrices_form
def test_get_one_qubit_hydrogen_hamiltonian():

    # Define interaction hamiltonian
    h2_hamiltonian_int = InteractionOperator(
        constant=constant,
        one_body_tensor=one_body_tensor,
        two_body_tensor=two_body_tensor,
    )
    save_interaction_operator(h2_hamiltonian_int, "interaction-operator.json")

    get_one_qubit_hydrogen_hamiltonian("interaction-operator.json")
    h2_1qubit = load_qubit_operator("qubit-operator.json")
    h2_1qubit_sparse = get_sparse_operator(h2_1qubit, n_qubits=1)
    h2_1qubit_dense = h2_1qubit_sparse.toarray()
    # print(h2_1qubit_dense)

    e_1q = eigvalsh(h2_1qubit_dense)

    gs_4q = get_ground_state(get_sparse_operator(h2_hamiltonian_int))

    os.remove("interaction-operator.json")
    os.remove("qubit-operator.json")

    assert isclose(e_1q[0], gs_4q[0])
Exemple #6
0
def test_hamiltonian_objective_value():

    obj = HamiltonianObjective(test_hamiltonian)
    obj_linear_op = HamiltonianObjective(test_hamiltonian, use_linear_op=True)
    hamiltonian_sparse = openfermion.get_sparse_operator(test_hamiltonian)

    simulator = cirq.google.XmonSimulator()
    numpy.random.seed(10581)
    result = simulator.simulate(cirq.testing.random_circuit(4, 5, 0.8))
    correct_val = openfermion.expectation(hamiltonian_sparse,
                                          result.final_state)

    numpy.testing.assert_allclose(
            obj.value(result), correct_val, atol=1e-5)
    numpy.testing.assert_allclose(
            obj_linear_op.value(result), correct_val, 1e-5)
Exemple #7
0
def test_expectation_values(qubitop, state_binary):
    """Test PauliSum and QubitOperator expectation value."""
    n_qubits = openfermion.count_qubits(qubitop)
    state = numpy.zeros(2**n_qubits, dtype='complex64')
    state[int(state_binary, 2)] = 1.0
    qubit_map = {cirq.LineQubit(i): i for i in range(n_qubits)}

    pauli_str = _qubit_operator_term_to_pauli_string(
        term=list(qubitop.terms.items())[0],
        qubits=cirq.LineQubit.range(n_qubits))
    op_mat = openfermion.get_sparse_operator(qubitop, n_qubits)

    expct_qop = openfermion.expectation(op_mat, state)
    expct_pauli = pauli_str.expectation_from_state_vector(state, qubit_map)

    numpy.testing.assert_allclose(expct_qop, expct_pauli)
Exemple #8
0
        def single_test(i):
            N = 8

            #k = np.random.rand(N,N)
            #k -= (k+k.T)/2  # random real antisymmetric matrix
            k = get_random_antihermite_mat(N)
            umat = scipy.linalg.expm(k)
            #print(umat)

            c1 = freqerica.circuit.rotorb.OrbitalRotation(umat)

            from openfermion import FermionOperator, jordan_wigner, get_sparse_operator
            fop = FermionOperator()
            for p in range(N):
                for q in range(N):
                    fop += FermionOperator(((p, 1), (q, 0)), k[p, q])
            qop = jordan_wigner(fop)
            #print(qop)

            #from freqerica.circuit.trotter import TrotterStep
            from freqerica.util.qulacsnize import convert_state_vector
            import qulacs
            #M = 100
            #c2 = TrotterStep(N, qop/M)

            s1 = qulacs.QuantumState(N)
            s1.set_Haar_random_state()
            #s2 = s1.copy()
            s3 = convert_state_vector(N, s1.get_vector())

            c1._circuit.update_quantum_state(s1)
            #for i in range(M): c2._circuit.update_quantum_state(s2)

            s3 = scipy.sparse.linalg.expm_multiply(get_sparse_operator(qop),
                                                   s3)

            #ip12 = qulacs.state.inner_product(s1, s2)
            ip13 = np.conjugate(convert_state_vector(N,
                                                     s1.get_vector())).dot(s3)
            #ip23 = np.conjugate(convert_state_vector(N, s2.get_vector())).dot(s3)
            #print('dot(s1,s2)', abs(ip12), ip12)
            #print('dot(s1,s3)', abs(ip13), ip13)
            #print('dot(s2,s3)', abs(ip23), ip23)

            print('[trial{:02d}] fidelity-1 : {:+.1e}   dot=({:+.5f})'.format(
                i,
                abs(ip13) - 1, ip13))
Exemple #9
0
    def get_ansatz_element_excitations_matrices(self, ansatz_element,
                                                parameter):
        excitations_generators = ansatz_element.excitations_generators
        key = str(excitations_generators)
        # if the element exists and the parameter is the same, return the excitation matrix
        if key in self.excitations_sparse_matrices_dict:
            dict_term = self.excitations_sparse_matrices_dict[key]
            previous_parameter = dict_term['parameter']
            if previous_parameter == parameter:
                # this can be a list of one or two matrices depending on if its a spin-complement pair
                return self.excitations_sparse_matrices_dict[key]['matrices']

        # otherwise update the excitations_sparse_matrices_dict
        try:
            excitations_generators_matrices = self.exc_gen_sparse_matrices_dict[
                key]
            sqr_excitations_generators_matrices = self.sqr_exc_gen_sparse_matrices_dict[
                key]

        # TODO not checked !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        # this exception is triggered when we add a spin-complement ansatz element to the ansatz, for which we have not
        # precomputed the excitation generator matrices
        except KeyError:
            excitations_generators_matrices = []
            sqr_excitations_generators_matrices = []
            for term in ansatz_element.excitations_generators:
                excitations_generators_matrices.append(
                    get_sparse_operator(term, n_qubits=self.n_qubits))
                sqr_excitations_generators_matrices.append(
                    excitations_generators_matrices[-1] *
                    excitations_generators_matrices[-1])
            self.exc_gen_sparse_matrices_dict[
                key] = excitations_generators_matrices
            self.sqr_exc_gen_sparse_matrices_dict[
                key] = sqr_excitations_generators_matrices

        excitations_matrices = []
        # calculate each excitation matrix using an efficient decomposition: exp(t*A) = I + sin(t)A + (1-cos(t))A^2
        for i in range(len(excitations_generators_matrices)):
            term1 = numpy.sin(parameter) * excitations_generators_matrices[i]
            term2 = (1 - numpy.cos(parameter)
                     ) * sqr_excitations_generators_matrices[i]
            excitations_matrices.append(self.identity + term1 + term2)

        dict_term = {'parameter': parameter, 'matrices': excitations_matrices}
        self.excitations_sparse_matrices_dict[key] = dict_term
        return excitations_matrices
Exemple #10
0
    def calculate_energy_eigenvalues(self, k):
        logging.info('Calculating excited states exact eigenvalues.')
        t0 = time.time()
        H_sparse_matrix = get_sparse_operator(self.jw_qubit_ham)

        # do not calculate all eigenvectors of H, since this is very slow
        calculate_first_n = k + 1
        # use sigma to ensure we get the smallest eigenvalues
        eigvv = scipy.sparse.linalg.eigsh(H_sparse_matrix.todense(),
                                          k=calculate_first_n,
                                          which='SR')
        eigenvalues = list(eigvv[0])
        eigenvectors = list(eigvv[1].T)
        eigenvalues, eigenvectors = [
            *zip(
                *sorted([*zip(eigenvalues, eigenvectors)], key=lambda x: x[0]))
        ]  # sort w.r.t. eigenvalues

        self.energy_eigenvalues = []

        i = 0
        while len(self.energy_eigenvalues) < k:

            if i >= len(eigenvalues):
                calculate_first_n += k
                eigvv = scipy.sparse.linalg.eigs(H_sparse_matrix.todense(),
                                                 k=calculate_first_n,
                                                 which='SR')
                eigenvalues = list(eigvv[0])
                eigenvectors = list(eigvv[1].T)
                eigenvalues, eigenvectors = [
                    *zip(*sorted([*zip(eigenvalues, eigenvectors)],
                                 key=lambda x: x[0]))
                ]

            if MatrixUtils.statevector_hamming_weight(eigenvectors[i].round(
                    10)) == self.n_electrons:  # rounding set at random
                self.energy_eigenvalues.append(eigenvalues[i].real)

            i += 1
            if i == self.n_qubits**2:
                logging.warning(
                    'WARNING: Only {} eigenvalues found corresponding to the n_electrons'
                    .format(len(self.energy_eigenvalues)))
                break
        logging.info('Time: {}'.format(time.time() - t0))
        return self.energy_eigenvalues
    def get_simulated_noisy_expectation_value(w: IWaveFunction,
                                              r_c: cirq.circuits.circuit,
                                              r: cirq.study.resolver) -> float:
        simulator = cirq.DensityMatrixSimulator(
            ignore_measurement_results=False)  # Mixed state simulator
        simulated_result = simulator.simulate(
            program=r_c, param_resolver=r)  # Include final density matrix

        qubit_operator = QPU.get_hamiltonian_evaluation_operator(w)
        H_operator = get_sparse_operator(qubit_operator)  # Observable
        # Perform trace between Hamiltonian operator and final state density matrix
        sparse_density_matrix = csc_matrix(
            simulated_result.final_density_matrix)
        # Tr( rho * H )
        trace = (sparse_density_matrix * H_operator).diagonal().sum(
        )  # Complex stored value that should always be real
        return trace.real  # objective.value(simulated_result)  # If simulation result is cirq.WaveFunctionTrialResult
Exemple #12
0
def test_fqe_givens():
    """Test Givens Rotation evolution for correctness."""
    # set up
    norbs = 4
    n_elec = norbs
    sz = 0
    n_qubits = 2 * norbs
    time = 0.126
    fqe_wfn = fqe.Wavefunction([[n_elec, sz, norbs]])
    fqe_wfn.set_wfn(strategy="random")
    ikappa = random_quadratic_hamiltonian(
        norbs,
        conserves_particle_number=True,
        real=False,
        expand_spin=False,
        seed=2,
    )
    fqe_ham = RestrictedHamiltonian((ikappa.n_body_tensors[1, 0], ))
    u = expm(-1j * ikappa.n_body_tensors[1, 0] * time)

    # time-evolve
    final_fqe_wfn = fqe_wfn.time_evolve(time, fqe_ham)
    spin_ham = np.kron(ikappa.n_body_tensors[1, 0], np.eye(2))
    assert of.is_hermitian(spin_ham)
    ikappa_spin = of.InteractionOperator(
        constant=0,
        one_body_tensor=spin_ham,
        two_body_tensor=np.zeros((n_qubits, n_qubits, n_qubits, n_qubits)),
    )
    bigU = expm(-1j * of.get_sparse_operator(ikappa_spin).toarray() * time)
    initial_wf = fqe.to_cirq(fqe_wfn).reshape((-1, 1))
    final_wf = bigU @ initial_wf
    final_wfn_test = fqe.from_cirq(final_wf.flatten(), 1.0e-12)

    assert np.allclose(final_fqe_wfn.rdm("i^ j"), final_wfn_test.rdm("i^ j"))
    assert np.allclose(final_fqe_wfn.rdm("i^ j^ k l"),
                       final_wfn_test.rdm("i^ j^ k l"))

    final_wfn_test2 = fqe.from_cirq(
        evolve_wf_givens(initial_wf.copy(), u.copy()).flatten(), 1.0e-12)
    givens_fqe_wfn = evolve_fqe_givens(fqe_wfn, u.copy())
    assert np.allclose(givens_fqe_wfn.rdm("i^ j"), final_wfn_test2.rdm("i^ j"))
    assert np.allclose(givens_fqe_wfn.rdm("i^ j^ k l"),
                       final_wfn_test2.rdm("i^ j^ k l"))
Exemple #13
0
def produce_simulation_test_parameters(
    n_qubits: int,
    time: float,
    hamiltonian_factory: Callable[[int, Optional[bool]], Hamiltonian],
    real: bool,
    seed: Optional[int] = None
) -> Tuple[Hamiltonian, numpy.ndarray, numpy.ndarray]:
    """Produce objects for testing Hamiltonian simulation.

    Constructs a Hamiltonian with the given parameters, produces a random
    initial state, and evolves the initial state for the specified amount of
    time. Returns the constructed Hamiltonian, the initial state, and the
    final state.

    Args:
        n_qubits: The number of qubits of the Hamiltonian
        time: The time to evolve for
        hamiltonian_factory: A Callable that takes a takes two arguments,
            (n_qubits, real) giving the number of qubits and whether
            to use only real numbers, and returns a Hamiltonian.
        real: Whether the Hamiltonian should use only real numbers
        seed: an RNG seed.
    """

    numpy.random.seed(seed)

    # Construct a random initial state
    initial_state = numpy.random.randn(2**n_qubits)
    initial_state /= numpy.linalg.norm(initial_state)
    initial_state = initial_state.astype(numpy.complex64, copy=False)
    assert numpy.allclose(numpy.linalg.norm(initial_state), 1.0)

    # Construct a Hamiltonian
    hamiltonian = hamiltonian_factory(n_qubits, real)

    # Simulate exact evolution
    hamiltonian_sparse = openfermion.get_sparse_operator(hamiltonian)
    exact_state = scipy.sparse.linalg.expm_multiply(
        -1j * time * hamiltonian_sparse, initial_state)

    # Make sure the time is not too small
    assert fidelity(exact_state, initial_state) < .95

    return hamiltonian, initial_state, exact_state
Exemple #14
0
def test_rotorb_circuit():
    import scipy.linalg
    np.set_printoptions(linewidth=300)

    N = 8

    #k = np.random.rand(N,N)
    #k -= (k+k.T)/2  # random real antisymmetric matrix
    k = get_random_antihermite_mat(N)
    umat = scipy.linalg.expm(k)
    print(umat)

    c1 = OrbitalRotation(umat)

    from openfermion import FermionOperator, jordan_wigner, get_sparse_operator
    fop = FermionOperator()
    for p in range(N):
        for q in range(N):
            fop += FermionOperator(((p, 1), (q, 0)), k[p, q])
    qop = jordan_wigner(fop)
    #print(qop)

    from trotter_qulacs import TrotterStep
    from util_qulacs import convert_state_vector
    M = 100
    c2 = TrotterStep(N, qop / M)

    s1 = qulacs.QuantumState(N)
    s1.set_Haar_random_state()
    s2 = s1.copy()
    s3 = convert_state_vector(N, s1.get_vector())

    c1._circuit.update_quantum_state(s1)
    for i in range(M):
        c2._circuit.update_quantum_state(s2)

    s3 = scipy.sparse.linalg.expm_multiply(get_sparse_operator(qop), s3)

    ip12 = qulacs.state.inner_product(s1, s2)
    ip13 = np.conjugate(convert_state_vector(N, s1.get_vector())).dot(s3)
    ip23 = np.conjugate(convert_state_vector(N, s2.get_vector())).dot(s3)
    print('dot(s1,s2)', abs(ip12), ip12)
    print('dot(s1,s3)', abs(ip13), ip13)
    print('dot(s2,s3)', abs(ip23), ip23)
    def _tensor_construct(self, rank, conjugates, updown):
        """
        General procedure for evaluating the expected value of second quantized ops

        :param Int rank: number of second quantized operators to product out
        :param List conjugates: Indicator of the conjugate type of the second
                                quantized operator
        :param List updown: SymmOrbitalDensity matrices are index by spatial orbital
                            Indices.  This value is self.dim/2 for Fermionic systems.
                            When projecting out expected values to form the marginals,
                            we need to know if the spin-part of the spatial basis
                            funciton.  updown is a list corresponding with the
                            conjugates telling us if we are projecting an up spin or
                            down spin.  0 is for up. 1 is for down.

                            Example: to get the 1-RDM alpha-block we would pass the
                            following:

                                rank = 2, conjugates = [-1, 1], updown=[0, 0]

        :returns: a tensor of (rank) specified by input
        :rytpe: np.ndarray
        """
        # self.dim/2 because rank is now spatial basis function rank
        tensor = np.zeros(tuple([int(self.dim / 2)] * rank), dtype=complex)
        of_con_upper = [
            1 if np.isclose(x, -1) else 0 for x in conjugates[:rank // 2]
        ]
        of_con_lower = [
            1 if np.isclose(x, -1) else 0 for x in conjugates[rank // 2:]
        ]
        updown_upper = updown[:rank // 2]
        updown_lower = updown[rank // 2:]
        for indices in product(range(self.dim // 2), repeat=rank):
            fop_u = [(2 * x + y, of_con_upper[idx]) for idx, (
                x, y) in enumerate(zip(indices[:rank // 2], updown_upper))]
            fop_l = [(2 * x + y, of_con_lower[idx]) for idx, (
                x, y) in enumerate(zip(indices[rank // 2:], updown_lower))]
            print(fop_u + fop_l[::-1])
            op = of.get_sparse_operator(of.FermionOperator(
                tuple(fop_u + fop_l[::-1])),
                                        n_qubits=self.dim)
            tensor[indices] = (op @ self.rho).diagonal().sum()
        return tensor
Exemple #16
0
    def calculate_exc_gen_sparse_matrices_dict(self, ansatz_elements):
        logging.info('Calculating excitation generators')
        exc_gen_sparse_matrices_dict = {}
        sqr_exc_gen_sparse_matrices_dict = {}
        if config.multithread:
            ray.init(
                num_cpus=config.ray_options['n_cpus'],
                object_store_memory=config.ray_options['object_store_memory'])
            elements_ray_ids = [[
                element,
                GlobalCache.get_excitations_generators_matrices_multithread.
                remote(element, n_qubits=self.q_system.n_qubits)
            ] for element in ansatz_elements]
            for element_ray_id in elements_ray_ids:
                key = str(element_ray_id[0].excitations_generators)
                exc_gen_sparse_matrices_dict[key] = ray.get(
                    element_ray_id[1])[0]
                sqr_exc_gen_sparse_matrices_dict[key] = ray.get(
                    element_ray_id[1])[1]

            del elements_ray_ids
            ray.shutdown()
        else:
            for i, element in enumerate(ansatz_elements):
                excitation_generators = element.excitations_generators
                key = str(excitation_generators)
                logging.info(
                    'Calculated excitation generator matrix {}'.format(key))
                exc_gen_matrix_form = []
                sqr_exc_gen_matrix_form = []
                for term in excitation_generators:
                    exc_gen_matrix_form.append(
                        get_sparse_operator(term,
                                            n_qubits=self.q_system.n_qubits))
                    sqr_exc_gen_matrix_form.append(exc_gen_matrix_form[-1] *
                                                   exc_gen_matrix_form[-1])
                exc_gen_sparse_matrices_dict[key] = exc_gen_matrix_form
                sqr_exc_gen_sparse_matrices_dict[key] = sqr_exc_gen_matrix_form

        self.exc_gen_sparse_matrices_dict = exc_gen_sparse_matrices_dict
        self.sqr_exc_gen_sparse_matrices_dict = sqr_exc_gen_sparse_matrices_dict
        return exc_gen_sparse_matrices_dict
    def test_fermionops_tomatrix_hubbard_model(self):
        hubbard = fermi_hubbard(1,
                                4,
                                tunneling=1.0,
                                coulomb=2.0,
                                periodic=False)

        init_wfn = Wavefunction([[2, 0, 4]])
        init_wfn.set_wfn(strategy="random")

        # This calls fermionops_tomatrix.
        evolved_wfn = init_wfn.time_evolve(1.0, hubbard)

        # Check.
        wfn_cirq = to_cirq(init_wfn)
        unitary = scipy.linalg.expm(-1j * get_sparse_operator(hubbard))
        evolved_wfn_cirq = unitary @ wfn_cirq

        fidelity = abs(
            vdot(evolved_wfn, from_cirq(evolved_wfn_cirq, thresh=1e-12)))**2
        assert numpy.isclose(fidelity, 1.0)
Exemple #18
0
def system():
    print('Running System Setup')
    basis = 'sto-3g'
    multiplicity = 1
    charge = 1
    geometry = [('He', [0.0, 0.0, 0.0]), ('H', [0, 0, 0.740848149])]
    molecule = MolecularData(geometry, basis, multiplicity, charge)
    # Run Psi4.
    molecule = run_psi4(molecule,
                        run_scf=True,
                        run_mp2=False,
                        run_cisd=False,
                        run_ccsd=False,
                        run_fci=True,
                        delete_input=False)

    op_mat = of.get_sparse_operator(
        molecule.get_molecular_hamiltonian()).toarray()
    w, v = np.linalg.eigh(op_mat)
    n_density = v[:, [2]] @ v[:, [2]].conj().T
    rdm_generator = AntiSymmOrbitalDensity(n_density, molecule.n_qubits)
    transform = jordan_wigner
    return n_density, rdm_generator, transform, molecule
def test_prepare_gaussian_state(n_qubits,
                                conserves_particle_number,
                                occupied_orbitals,
                                initial_state,
                                atol=1e-5):

    qubits = LineQubit.range(n_qubits)
    if isinstance(initial_state, list):
        initial_state = sum(1 << (n_qubits - 1 - i) for i in initial_state)

    # Initialize a random quadratic Hamiltonian
    quad_ham = random_quadratic_hamiltonian(n_qubits,
                                            conserves_particle_number,
                                            real=False)
    quad_ham_sparse = get_sparse_operator(quad_ham)

    # Compute the energy of the desired state
    if occupied_orbitals is None:
        energy = quad_ham.ground_energy()
    else:
        orbital_energies, _, constant = (
            quad_ham.diagonalizing_bogoliubov_transform())
        energy = sum(orbital_energies[i] for i in occupied_orbitals) + constant

    # Get the state using a circuit simulation
    circuit = cirq.Circuit(
        prepare_gaussian_state(qubits,
                               quad_ham,
                               occupied_orbitals,
                               initial_state=initial_state))
    state = circuit.apply_unitary_effect_to_state(initial_state)

    # Check that the result is an eigenstate with the correct eigenvalue
    numpy.testing.assert_allclose(quad_ham_sparse.dot(state),
                                  energy * state,
                                  atol=atol)
Exemple #20
0
def test_prepare_gaussian_state(n_qubits,
                                conserves_particle_number,
                                occupied_orbitals,
                                initial_state,
                                atol=1e-5):
    simulator = cirq.google.XmonSimulator()
    qubits = LineQubit.range(n_qubits)

    # Initialize a random quadratic Hamiltonian
    quad_ham = random_quadratic_hamiltonian(n_qubits,
                                            conserves_particle_number,
                                            real=False)
    quad_ham_sparse = get_sparse_operator(quad_ham)

    # Compute the energy of the desired state
    if occupied_orbitals is None:
        energy = quad_ham.ground_energy()
    else:
        orbital_energies, constant = quad_ham.orbital_energies()
        energy = sum(orbital_energies[i] for i in occupied_orbitals) + constant

    # Get the state using a circuit simulation
    circuit = cirq.Circuit.from_ops(
        prepare_gaussian_state(qubits,
                               quad_ham,
                               occupied_orbitals,
                               initial_state=initial_state))
    if isinstance(initial_state, list):
        initial_state = sum(1 << (n_qubits - 1 - i) for i in initial_state)
    result = simulator.simulate(circuit, initial_state=initial_state)
    state = result.final_state

    # Check that the result is an eigenstate with the correct eigenvalue
    numpy.testing.assert_allclose(quad_ham_sparse.dot(state),
                                  energy * state,
                                  atol=atol)
Exemple #21
0
def compare_openfermion_fermions():
    # skip test if openfermion not installed
    pytest.importorskip("openfermion")
    from openfermion import FermionOperator, get_sparse_operator

    # openfermion
    of = FermionOperator("0^ 1", 1.0) + FermionOperator("1^ 0", 1.0)
    of_dense = get_sparse_operator(of).todense()
    # from_openfermion
    fo = nkx.operator.FermionOperator2nd.from_openfermion(of)
    fo_dense = fo.to_dense()
    # FermionOperator2nd
    hi = nkx.hilbert.SpinOrbitalFermions(2)  # two sites
    fermop = nkx.operator.FermionOperator2nd(hi,
                                             terms=(((0, 1), (1, 0)),
                                                    ((1, 1), (0, 0))),
                                             weights=(1.0, 1.0))
    fermop_dense = fermop.to_dense()
    # compare openfermion vs from_openfermion
    assert np.array_equal(of_dense, fo_dense)
    # compare openfermion vs FermionOperator2nd
    assert np.array_equal(of_dense, fermop_dense)
    # compare from_openfermion vs FermionOperator 2nd
    assert np.array_equal(fo_dense, fermop_dense)
Exemple #22
0
def estimate_correlation(ham_qop,
                         state,
                         dt,
                         max_trotter_step,
                         outputter,
                         savefilename=None):
    const_term = ham_qop.terms[()]
    n_site = openfermion.count_qubits(ham_qop)
    outputter.n_qubit = n_site
    outputter.n_trott_step = max_trotter_step

    #circuit_time_evo = qulacs.QuantumCircuit(n_site)
    #trotter.trotter_step_2nd_order(circuit_time_evo, -1j * dt * ham_qop)
    trotterstep = trotter.TrotterStep(n_site, -1j * dt * ham_qop)
    circuit_time_evo = trotterstep._circuit
    outputter.ngate = trotterstep.count_gates()
    print(trotterstep)
    print(circuit_time_evo)

    ham_tensor = openfermion.get_sparse_operator(ham_qop)

    state_vec_exact = convert_state_vector(n_site, state.get_vector())

    steps = np.arange(max_trotter_step + 1)

    save_state_vec_exact = np.empty((len(steps), 2**n_site), np.complex128)
    save_state_vec_trotter = np.empty((len(steps), 2**n_site), np.complex128)
    save_time_energy_fidelity = np.empty((len(steps), 4), float)
    save_time_energy_fidelity[:, 0] = steps * dt

    time_sim = 0

    for istep, n_trotter_step in enumerate(steps):
        state_vec_trotter = convert_state_vector(n_site, state.get_vector())

        # calculate energy and fidelity
        energy_exact = openfermion.expectation(ham_tensor, state_vec_exact)
        energy_trotter = openfermion.expectation(ham_tensor, state_vec_trotter)
        fidelity = np.abs(
            np.dot(np.conjugate(state_vec_exact), state_vec_trotter))**2

        # save
        save_state_vec_exact[istep] = state_vec_exact
        save_state_vec_trotter[istep] = state_vec_trotter
        save_time_energy_fidelity[istep, 1] = energy_exact.real
        save_time_energy_fidelity[istep, 2] = energy_trotter.real
        save_time_energy_fidelity[istep, 3] = fidelity

        # time propergation
        time_bgn = time()
        circuit_time_evo.update_quantum_state(state)
        time_sim += time() - time_bgn
        state_vec_exact = scipy.sparse.linalg.expm_multiply(
            -1j * dt * ham_tensor, state_vec_exact)

    corr_exact = np.dot(save_state_vec_exact[0], save_state_vec_exact.T)
    corr_trotter = np.dot(
        save_state_vec_trotter[0],
        save_state_vec_trotter.T)  # * np.exp(-1j * dt * steps * const_term)

    outputter.time_sim = time_sim

    if savefilename:
        np.save(savefilename + '_ham_tensor', ham_tensor.todense())
        np.save(savefilename + '_corr_exact.npy', corr_exact)
        np.save(savefilename + '_corr_trotter.npy', corr_trotter)
        np.save(savefilename + '_state_vec_exact.npy', save_state_vec_exact)
        np.save(savefilename + '_state_vec_trotter.npy',
                save_state_vec_trotter)
        np.save(savefilename + '_time_energy_fidelity.npy',
                save_time_energy_fidelity)

    return EstimateCorrelationResult(corr_exact, corr_trotter,
                                     save_state_vec_exact,
                                     save_state_vec_trotter,
                                     save_time_energy_fidelity)
Exemple #23
0
    def test_trotterstep_circuit(self):
        from freqerica.op.symbol import WrappedExpr as Symbol
        from openfermion import FermionOperator, jordan_wigner, get_sparse_operator
        from sympy import Array
        import numpy as np
        np.random.seed(100)
        import scipy
        import qulacs

        n_orb = 2

        const = Symbol('const')
        T1 = [[None for _ in range(n_orb)] for _ in range(n_orb)]
        for p in range(n_orb):
            for q in range(p, n_orb):
                t = Symbol('t{}{}'.format(p,q))
                T1[p][q] = T1[q][p] = t
        T1 = Array(T1)
        print(T1)

        const_value = np.random.rand()
        T1_value = np.random.rand(n_orb,n_orb)*0.01
        T1_value += T1_value.T
        print(const_value)
        print(T1_value)

        def op1e(const, Tmat):
            fop = FermionOperator('', const)
            for p in range(n_orb):
                for q in range(n_orb):
                    fop += FermionOperator( ((2*p  , 1),(2*q  , 0)), Tmat[p,q] )
                    fop += FermionOperator( ((2*p+1, 1),(2*q+1, 0)), Tmat[p,q] )
            return fop

        fop_symbol = op1e(const, T1)
        qop_symbol = jordan_wigner(fop_symbol)
        print(fop_symbol)
        print(qop_symbol)

        n_qubit = n_orb*2

        # c1 : TrotterStep with symbolic qop
        c1 = freqerica.circuit.trotter.TrotterStep(n_qubit, (-1j)*qop_symbol)
        print(c1)
        symbol_number_pairs = [(const, const_value), (T1, T1_value)]
        c1.subs(symbol_number_pairs)
        print(c1)

        # c2 : TrotterStep with numerical qop
        fop_number = op1e(const_value, T1_value)
        qop_number = jordan_wigner(fop_number)
        c2 = freqerica.circuit.trotter.TrotterStep(n_qubit, (-1j)*qop_number)
        print(c2)

        # c3 : oldtype with numerical qop
        c3 = qulacs.QuantumCircuit(n_qubit)
        freqerica.circuit.trotter.trotter_step_2nd_order(c3, (-1j)*qop_number)



        s0 = qulacs.QuantumState(n_qubit)
        s0.set_Haar_random_state()
        s1 = s0.copy()
        s2 = s0.copy()
        s3 = s0.copy()
        from freqerica.util.qulacsnize import convert_state_vector
        sv = convert_state_vector( n_qubit, s0.get_vector() )

        corr1 = []
        corr2 = []
        corr3 = []
        corrv = []
        for t in range(100):
            corr1.append( qulacs.state.inner_product(s0, s1) )
            corr2.append( qulacs.state.inner_product(s0, s2) )
            corr3.append( qulacs.state.inner_product(s0, s3)*np.exp(-1j*qop_number.terms[()]*t) )
            corrv.append( np.dot(np.conjugate(convert_state_vector(n_qubit, s0.get_vector())), sv) )
            c1._circuit.update_quantum_state(s1)
            c2._circuit.update_quantum_state(s2)
            c3.update_quantum_state(s3)
            sv = scipy.sparse.linalg.expm_multiply(-1j * get_sparse_operator(qop_number), sv)
def dqg_run_bpsdp():
    import sys
    from openfermion.hamiltonians import MolecularData
    from openfermionpsi4 import run_psi4
    from openfermionpyscf import run_pyscf
    from openfermion.utils import map_one_pdm_to_one_hole_dm, \
        map_two_pdm_to_two_hole_dm, map_two_pdm_to_particle_hole_dm

    print('Running System Setup')
    basis = 'sto-6g'
    # basis = '6-31g'
    multiplicity = 1
    # charge = 0
    # geometry = [('H', [0.0, 0.0, 0.0]), ('H', [0, 0, 0.75])]
    # charge = 1
    # geometry = [('H', [0.0, 0.0, 0.0]), ('He', [0, 0, 0.75])]
    charge = 0
    bd = 1.2
    # geometry = [('H', [0.0, 0.0, 0.0]), ('H', [0, 0, bd]),
    #             ('H', [0.0, 0.0, 2 * bd]), ('H', [0, 0, 3 * bd])]
    # geometry = [['H', [0, 0, 0]], ['H', [1.2, 0, 0]],
    #             ['H', [0, 1.2, 0]], ['H', [1.2, 1.2, 0]]]
    # geometry = [['He', [0, 0, 0]], ['H', [0, 0, 1.2]]]
    #  geometry = [['Be' [0, 0, 0]], [['B', [1.2, 0, 0]]]]
    geometry = [['N', [0, 0, 0]], ['N', [0, 0, 1.1]]]
    molecule = MolecularData(geometry, basis, multiplicity, charge)
    # Run Psi4.
    # molecule = run_psi4(molecule,
    #                     run_scf=True,
    #                     run_mp2=False,
    #                     run_cisd=False,
    #                     run_ccsd=False,
    #                     run_fci=True,
    #                     delete_input=True)
    molecule = run_pyscf(molecule,
                         run_scf=True,
                         run_mp2=False,
                         run_cisd=False,
                         run_ccsd=False,
                         run_fci=True)

    print('nuclear_repulsion', molecule.nuclear_repulsion)
    print('gs energy ', molecule.fci_energy)
    print("hf energy ", molecule.hf_energy)

    nuclear_repulsion = molecule.nuclear_repulsion
    gs_energy = molecule.fci_energy

    import openfermion as of
    hamiltonian = molecule.get_molecular_hamiltonian(
        occupied_indices=[0], active_indices=[1, 2, 3, 4])
    print(type(hamiltonian))
    print(hamiltonian)
    nuclear_repulsion = hamiltonian.constant
    hamiltonian.constant = 0
    ham = of.get_sparse_operator(hamiltonian).toarray()
    w, v = np.linalg.eigh(ham)
    idx = 0
    gs_energy = w[idx]
    n_density = v[:, [idx]] @ v[:, [idx]].conj().T

    from representability.fermions.density.antisymm_sz_density import AntiSymmOrbitalDensity

    density = AntiSymmOrbitalDensity(n_density, 8)
    opdm_a, opdm_b = density.construct_opdm()
    tpdm_aa, tpdm_bb, tpdm_ab, _ = density.construct_tpdm()

    true_tpdm = density.get_tpdm(density.rho, density.dim)
    true_tpdm = true_tpdm.transpose(0, 1, 3, 2)
    test_tpdm = unspin_adapt(tpdm_aa, tpdm_bb, tpdm_ab)
    assert np.allclose(true_tpdm, test_tpdm)

    tqdm_aa, tqdm_bb, tqdm_ab, _ = density.construct_thdm()
    phdm_ab, phdm_ba, phdm_aabb = density.construct_phdm()
    Na = np.round(opdm_a.trace()).real
    Nb = np.round(opdm_b.trace()).real

    one_body_ints, two_body_ints = hamiltonian.one_body_tensor, hamiltonian.two_body_tensor
    two_body_ints = np.einsum('ijkl->ijlk', two_body_ints)

    n_electrons = Na + Nb
    print('n_electrons', n_electrons)
    dim = one_body_ints.shape[0]
    spatial_basis_rank = dim // 2
    bij_bas_aa, bij_bas_ab = geminal_spin_basis(spatial_basis_rank)

    opdm_a_interaction, opdm_b_interaction, v2aa, v2bb, v2ab = \
        spin_adapted_interaction_tensor_rdm_consistent(two_body_ints,
                                                       one_body_ints)

    dual_basis = sz_adapted_linear_constraints(
        spatial_basis_rank,
        Na,
        Nb, ['ck', 'kc', 'cckk', 'ckck', 'kkcc'],
        S=1,
        M=-1)
    print("constructed dual basis")

    opdm_a = Tensor(opdm_a, name='ck_a')
    opdm_b = Tensor(opdm_b, name='ck_b')
    oqdm_a = Tensor(np.eye(dim // 2) - opdm_a.data, name='kc_a')
    oqdm_b = Tensor(np.eye(dim // 2) - opdm_b.data, name='kc_b')

    tpdm_aa = Tensor(tpdm_aa, name='cckk_aa', basis=bij_bas_aa)
    tpdm_bb = Tensor(tpdm_bb, name='cckk_bb', basis=bij_bas_aa)
    tpdm_ab = Tensor(tpdm_ab, name='cckk_ab', basis=bij_bas_ab)

    tqdm_aa = Tensor(tqdm_aa, name='kkcc_aa', basis=bij_bas_aa)
    tqdm_bb = Tensor(tqdm_bb, name='kkcc_bb', basis=bij_bas_aa)
    tqdm_ab = Tensor(tqdm_ab, name='kkcc_ab', basis=bij_bas_ab)

    phdm_ab = Tensor(phdm_ab, name='ckck_ab', basis=bij_bas_ab)
    phdm_ba = Tensor(phdm_ba, name='ckck_ba', basis=bij_bas_ab)
    phdm_aabb = Tensor(phdm_aabb, name='ckck_aabb')

    dtensor = MultiTensor([
        opdm_a, opdm_b, oqdm_a, oqdm_b, tpdm_aa, tpdm_bb, tpdm_ab, tqdm_aa,
        tqdm_bb, tqdm_ab, phdm_ab, phdm_ba, phdm_aabb
    ])

    copdm_a = opdm_a_interaction
    copdm_b = opdm_b_interaction
    coqdm_a = Tensor(np.zeros((spatial_basis_rank, spatial_basis_rank)),
                     name='kc_a')
    coqdm_b = Tensor(np.zeros((spatial_basis_rank, spatial_basis_rank)),
                     name='kc_b')
    ctpdm_aa = v2aa
    ctpdm_bb = v2bb
    ctpdm_ab = v2ab
    ctqdm_aa = Tensor(np.zeros_like(v2aa.data),
                      name='kkcc_aa',
                      basis=bij_bas_aa)
    ctqdm_bb = Tensor(np.zeros_like(v2bb.data),
                      name='kkcc_bb',
                      basis=bij_bas_aa)
    ctqdm_ab = Tensor(np.zeros_like(v2ab.data),
                      name='kkcc_ab',
                      basis=bij_bas_ab)
    cphdm_ab = Tensor(np.zeros((spatial_basis_rank**2, spatial_basis_rank**2)),
                      name='ckck_ab',
                      basis=bij_bas_ab)
    cphdm_ba = Tensor(np.zeros((spatial_basis_rank**2, spatial_basis_rank**2)),
                      name='ckck_ba',
                      basis=bij_bas_ab)
    cphdm_aabb = Tensor(np.zeros(
        (2 * spatial_basis_rank**2, 2 * spatial_basis_rank**2)),
                        name='ckck_aabb')

    ctensor = MultiTensor([
        copdm_a, copdm_b, coqdm_a, coqdm_b, ctpdm_aa, ctpdm_bb, ctpdm_ab,
        ctqdm_aa, ctqdm_bb, ctqdm_ab, cphdm_ab, cphdm_ba, cphdm_aabb
    ])

    print(
        (ctensor.vectorize_tensors().T @ dtensor.vectorize_tensors())[0,
                                                                      0].real)
    print(gs_energy)

    ctensor.dual_basis = dual_basis
    A, _, b = ctensor.synthesize_dual_basis()
    print("size of dual basis", len(dual_basis.elements))

    print(A @ dtensor.vectorize_tensors() - b)

    nc, nv = A.shape
    A.eliminate_zeros()
    nnz = A.nnz

    from sdpsolve.sdp import SDP
    from sdpsolve.solvers.bpsdp import solve_bpsdp
    from sdpsolve.solvers.bpsdp.bpsdp_old import solve_bpsdp
    from sdpsolve.utils.matreshape import vec2block
    sdp = SDP()

    sdp.nc = nc
    sdp.nv = nv
    sdp.nnz = nnz
    sdp.blockstruct = list(map(lambda x: int(np.sqrt(x.size)),
                               ctensor.tensors))
    sdp.nb = len(sdp.blockstruct)
    sdp.Amat = A.real
    sdp.bvec = b.todense().real
    sdp.cvec = ctensor.vectorize_tensors().real

    sdp.Initialize()
    epsilon = 1.0E-7
    sdp.epsilon = float(epsilon)
    sdp.epsilon_inner = float(epsilon) / 100

    sdp.disp = True
    sdp.iter_max = 70000
    sdp.inner_solve = 'CG'
    sdp.inner_iter_max = 2

    # # sdp_data = solve_bpsdp(sdp)
    solve_bpsdp(sdp)
    # # create all the psd-matrices for the
    # variable_dictionary = {}
    # for tensor in ctensor.tensors:
    #     linear_dim = int(np.sqrt(tensor.size))
    #     variable_dictionary[tensor.name] = cvx.Variable(shape=(linear_dim, linear_dim), PSD=True, name=tensor.name)

    # print("constructing constraints")
    # constraints = []
    # for dbe in dual_basis:
    #     single_constraint = []
    #     for tname, v_elements, p_coeffs in dbe:
    #         active_indices = get_var_indices(ctensor.tensors[tname], v_elements)
    #         single_constraint.append(variable_dictionary[tname][active_indices] * p_coeffs)
    #     constraints.append(cvx.sum(single_constraint) == dbe.dual_scalar)
    # print('constraints constructed')

    # print("constructing the problem")
    # objective = cvx.Minimize(
    #             cvx.trace(copdm_a.data @ variable_dictionary['ck_a']) +
    #             cvx.trace(copdm_b.data @ variable_dictionary['ck_b']) +
    #             cvx.trace(ctpdm_aa.data @ variable_dictionary['cckk_aa']) +
    #             cvx.trace(ctpdm_bb.data @ variable_dictionary['cckk_bb']) +
    #             cvx.trace(ctpdm_ab.data @ variable_dictionary['cckk_ab']))

    # cvx_problem = cvx.Problem(objective, constraints=constraints)
    # print('problem constructed')

    # cvx_problem.solve(solver=cvx.SCS, verbose=True, eps=0.5E-5, max_iters=100000)

    # rdms_solution = vec2block(sdp.blockstruct, sdp.primal)

    print(gs_energy)
    # print(cvx_problem.value + nuclear_repulsion)
    # print(sdp_data.primal_value() + nuclear_repulsion)
    print(sdp.primal.T @ sdp.cvec)

    print(nuclear_repulsion)
    rdms = vec2block(sdp.blockstruct, sdp.primal)

    tpdm = unspin_adapt(rdms[4], rdms[5], rdms[6])
    print(np.einsum('ijij', tpdm))
    tpdm = np.einsum('ijkl->ijlk', tpdm)
Exemple #25
0
    ansatz = ansatz_1()

    init_qasm = None

    global_cache = GlobalCache(e_system, excited_state=0)
    global_cache.calculate_exc_gen_sparse_matrices_dict(ansatz)

    backend = MatrixCacheBackend

    optimizer = 'BFGS'
    optimizer_options = {'gtol': 10e-8, 'maxiter': 10}
    vqe_runner = VQERunner(e_system, backend=backend, print_var_parameters=False, use_ansatz_gradient=True,
                           optimizer=optimizer, optimizer_options=optimizer_options)

    result = vqe_runner.vqe_run(ansatz=ansatz,  cache=global_cache, init_state_qasm=init_qasm)

    parameters = result.x
    statevector = global_cache.get_statevector(ansatz, parameters, init_state_qasm=init_qasm)
    statevector = statevector.todense()

    operator = 'elenaananana'   # TODO: TOVA trqbva da e klas openfermion.FermionicOperator
    operator = openfermion.jordan_wigner(operator)
    operator = openfermion.get_sparse_operator(operator, n_orbitals)

    expectation_value = statevector.dot(operator).dot(statevector.conj().transpose())

    print(expectation_value)

    print('yolo')

# Add diagonal phase rotations to circuit
for k, eigenvalue in enumerate(eigenvalues):
    phase = -eigenvalue * simulation_time
    circuit.append(cirq.Rz(rads=phase).on(qubits[k]))

# Finally, change back to the computational basis
basis_rotation = openfermioncirq.bogoliubov_transform(
    qubits, basis_transformation_matrix
)
circuit.append(basis_rotation)

# Initialize a random initial state
initial_state = openfermion.haar_random_vector(
    2 ** n_qubits, random_seed).astype(numpy.complex64)

# Numerically compute the correct circuit output
hamiltonian_sparse = openfermion.get_sparse_operator(H)
exact_state = scipy.sparse.linalg.expm_multiply(
    -1j * simulation_time * hamiltonian_sparse, initial_state
)

# Use Cirq simulator to apply circuit
simulator = cirq.Simulator()
result = simulator.simulate(circuit, qubit_order=qubits,
                            initial_state=initial_state)
simulated_state = result.final_state

# Print final fidelity
fidelity = abs(numpy.dot(simulated_state, numpy.conjugate(exact_state)))**2
print("\nfidelity =", round(fidelity, 4))
def test_bogoliubov_transform_quadratic_hamiltonian(n_qubits,
                                                    conserves_particle_number,
                                                    atol=5e-5):
    simulator = cirq.google.XmonSimulator()
    qubits = LineQubit.range(n_qubits)

    # Initialize a random quadratic Hamiltonian
    quad_ham = random_quadratic_hamiltonian(n_qubits,
                                            conserves_particle_number,
                                            real=False)
    quad_ham_sparse = get_sparse_operator(quad_ham)

    # Compute the orbital energies and circuit
    orbital_energies, constant = quad_ham.orbital_energies()
    transformation_matrix = quad_ham.diagonalizing_bogoliubov_transform()
    circuit = cirq.Circuit.from_ops(
        bogoliubov_transform(qubits, transformation_matrix))

    # Pick some random eigenstates to prepare, which correspond to random
    # subsets of [0 ... n_qubits - 1]
    n_eigenstates = min(2**n_qubits, 5)
    subsets = [
        numpy.random.choice(range(n_qubits),
                            numpy.random.randint(1, n_qubits + 1), False)
        for _ in range(n_eigenstates)
    ]
    # Also test empty subset
    subsets += [()]

    for occupied_orbitals in subsets:
        # Compute the energy of this eigenstate
        energy = (sum(orbital_energies[i]
                      for i in occupied_orbitals) + constant)

        # Construct initial state
        initial_state = sum(2**(n_qubits - 1 - int(i))
                            for i in occupied_orbitals)

        # Get the state using a circuit simulation
        result = simulator.simulate(circuit,
                                    qubit_order=qubits,
                                    initial_state=initial_state)
        state1 = result.final_state

        # Also test the option to start with a computational basis state
        special_circuit = cirq.Circuit.from_ops(
            bogoliubov_transform(qubits,
                                 transformation_matrix,
                                 initial_state=initial_state))
        result = simulator.simulate(special_circuit,
                                    qubit_order=qubits,
                                    initial_state=initial_state)
        state2 = result.final_state

        # Check that the result is an eigenstate with the correct eigenvalue
        numpy.testing.assert_allclose(quad_ham_sparse.dot(state1),
                                      energy * state1,
                                      atol=atol)
        numpy.testing.assert_allclose(quad_ham_sparse.dot(state2),
                                      energy * state2,
                                      atol=atol)
 def get_hamiltonian_objective_operator(w: IWaveFunction) -> np.ndarray:
     qubit_operator = QPU.get_hamiltonian_evaluation_operator(w)
     return get_sparse_operator(qubit_operator)
Exemple #29
0
def estimate_corr_new__(ham,
                        dt,
                        max_trotter_step,
                        outputter,
                        savefilename=None):
    n_site = openfermion.count_qubits(ham.ham_qop)
    #state = ham.state
    #state_vec_exact = convert_state_vector(n_site, state.get_vector())

    steps = np.arange(max_trotter_step + 1)

    save_state_vec_exact = np.empty((len(steps), 2**n_site), np.complex128)
    save_state_vec_trotter = np.empty((len(steps), 2**n_site), np.complex128)
    save_time_energy_fidelity = np.empty((len(steps), 4), float)
    save_time_energy_fidelity[:, 0] = steps * dt

    time_sim = 0

    ham.init_propagate(dt)
    ham_tensor = openfermion.get_sparse_operator(ham.ham_qop)

    for istep, n_trotter_step in enumerate(steps):
        state_vec_trotter = convert_state_vector(n_site,
                                                 ham.state.get_vector())

        # calculate energy and fidelity
        energy_exact = openfermion.expectation(ham_tensor, state_vec_exact)
        energy_trotter = openfermion.expectation(ham_tensor, state_vec_trotter)
        fidelity = np.abs(
            np.dot(np.conjugate(state_vec_exact), state_vec_trotter))**2

        # save
        save_state_vec_exact[istep] = state_vec_exact
        save_state_vec_trotter[istep] = state_vec_trotter
        save_time_energy_fidelity[istep, 1] = energy_exact.real
        save_time_energy_fidelity[istep, 2] = energy_trotter.real
        save_time_energy_fidelity[istep, 3] = fidelity

        # time propergation
        time_bgn = time()
        ham.propagate()
        time_sim += time() - time_bgn
        state_vec_exact = scipy.sparse.linalg.expm_multiply(
            -1j * dt * ham_tensor, state_vec_exact)

    corr_exact = np.dot(save_state_vec_exact[0], save_state_vec_exact.T)
    corr_trotter = np.dot(save_state_vec_trotter[0], save_state_vec_trotter.T)

    outputter.n_qubit = n_site
    outputter.n_trott_step = max_trotter_step
    outputter.ngate = ham.trotterstep.count_gates()
    outputter.time_sim = time_sim

    if savefilename:
        np.save(savefilename + '_ham_tensor', ham_tensor.todense())
        np.save(savefilename + '_corr_exact.npy', corr_exact)
        np.save(savefilename + '_corr_trotter.npy', corr_trotter)
        np.save(savefilename + '_state_vec_exact.npy', save_state_vec_exact)
        np.save(savefilename + '_state_vec_trotter.npy',
                save_state_vec_trotter)
        np.save(savefilename + '_time_energy_fidelity.npy',
                save_time_energy_fidelity)

    return EstimateCorrelationResult(corr_exact, corr_trotter,
                                     save_state_vec_exact,
                                     save_state_vec_trotter,
                                     save_time_energy_fidelity)
 def get_expectation_value(t_r: cirq.TrialResult, w: IWaveFunction):
     qubit_operator = QPU.get_hamiltonian_evaluation_operator(w)
     objective = get_sparse_operator(qubit_operator)
     return objective.value(t_r.measurements['x'])