示例#1
0
    def test_simulate_dual_basis_hamiltonian(self):
        hamiltonian = dual_basis_hamiltonian(1, self.size)
        self.engine.flush()

        # Choose random state.
        initial_state = numpy.zeros(2**self.size, dtype=complex)
        for i in range(len(initial_state)):
            initial_state[i] = (random.random() *
                                numpy.exp(1j * 2 * numpy.pi * random.random()))
        initial_state /= numpy.linalg.norm(initial_state)

        # Put randomly chosen state in the registers.
        self.engine.backend.set_wavefunction(initial_state, self.register)

        _low_depth_trotter_simulation.simulate_dual_basis_evolution(
            self.register, hamiltonian, trotter_steps=7, first_order=False)

        self.engine.flush()

        # get_sparse_operator reverses the indices, but the jellium
        # Hamiltonian is symmetric.
        evol_matrix = expm(
            -1j *
            get_sparse_operator(hamiltonian, n_qubits=self.size)).todense()
        initial_state = numpy.matrix(initial_state).T
        expected = evol_matrix * initial_state

        self.assertTrue(
            numpy.allclose(ordered_wavefunction(self.engine),
                           expected.T,
                           atol=1e-2),
            msg=str(
                numpy.array(ordered_wavefunction(self.engine) - expected.T)))
示例#2
0
    def test_simulate_overlapping_number_and_hopping_terms(self):
        hamiltonian = (0.37 * FermionOperator('1^ 0^ 1 0') +
                       FermionOperator('2^ 0') + FermionOperator('0^ 2'))

        projectq.ops.All(projectq.ops.H) | self.register

        _low_depth_trotter_simulation.simulate_dual_basis_evolution(
            self.register, hamiltonian, trotter_steps=2, first_order=False)

        self.engine.flush()

        # get_sparse_operator reverses the indices, so reverse the sites
        # the Hamiltonian acts on so as to compare them.
        reversed_operator = (0.37 * FermionOperator('3^ 2^ 3 2') +
                             FermionOperator('3^ 1') + FermionOperator('1^ 3'))
        evol_matrix = expm(-1j * get_sparse_operator(
            reversed_operator, n_qubits=self.size)).todense()
        expected = evol_matrix * numpy.matrix(
            [2**(-self.size / 2.)] * 2**self.size).T

        self.assertTrue(
            numpy.allclose(ordered_wavefunction(self.engine),
                           expected.T,
                           atol=1e-2),
            msg=str(
                numpy.array(ordered_wavefunction(self.engine) - expected.T)))
示例#3
0
    def test_trotter_order_does_not_matter_for_high_trotter_number(self):
        size = 4
        hamiltonian = dual_basis_hamiltonian(n_dimensions=1, system_size=size)
        hamiltonian.compress()

        eng1 = projectq.MainEngine()
        eng2 = projectq.MainEngine()
        reg1 = eng1.allocate_qureg(size)
        reg2 = eng2.allocate_qureg(size)
        eng1.flush()
        eng2.flush()

        # Choose random state.
        state = numpy.zeros(2**size, dtype=complex)
        for i in range(len(state)):
            state[i] = (random.random() *
                        numpy.exp(1j * 2 * numpy.pi * random.random()))
        state /= numpy.linalg.norm(state)

        # Put randomly chosen state in the registers.
        eng1.backend.set_wavefunction(state, reg1)
        eng2.backend.set_wavefunction(state, reg2)

        # Swap and change the input ordering for reg1. These operations should
        # cancel each other out.
        projectq.ops.Swap | (reg1[1], reg1[2])
        projectq.ops.C(projectq.ops.Z) | (reg1[1], reg1[2])

        _low_depth_trotter_simulation.simulate_dual_basis_evolution(
            reg1,
            hamiltonian=hamiltonian,
            trotter_steps=7,
            input_ordering=[0, 2, 1, 3],
            first_order=False)
        _low_depth_trotter_simulation.simulate_dual_basis_evolution(
            reg2, hamiltonian=hamiltonian, trotter_steps=7, first_order=False)

        # Undo the inital swaps on reg1.
        projectq.ops.Swap | (reg1[1], reg1[2])
        projectq.ops.C(projectq.ops.Z) | (reg1[1], reg1[2])

        projectq.ops.All(projectq.ops.H) | reg1
        eng1.flush()
        projectq.ops.All(projectq.ops.H) | reg2
        eng2.flush()

        self.assertTrue(
            numpy.allclose(ordered_wavefunction(eng1),
                           ordered_wavefunction(eng2),
                           atol=1e-2))
        projectq.ops.All(projectq.ops.Measure) | reg1
        projectq.ops.All(projectq.ops.Measure) | reg2
    def test_simulate_hopping_0_to_3(self):
        hamiltonian = FermionOperator('0^ 3') + FermionOperator('3^ 0')

        projectq.ops.All(projectq.ops.H) | self.register

        _low_depth_trotter_simulation.simulate_dual_basis_evolution(
            self.register, hamiltonian, trotter_steps=1, first_order=False)
        self.engine.flush()

        # Use 0^ 2 + 2^ 0 because get_sparse_operator reverses the indices.
        evol_matrix = expm(-1j * get_sparse_operator(
            hamiltonian, n_qubits=self.size)).todense()
        expected = evol_matrix * numpy.matrix([2 ** (-self.size / 2.)] *
                                              2 ** self.size).T

        self.assertTrue(numpy.allclose(ordered_wavefunction(self.engine),
                                       expected.T))
示例#5
0
    def test_simulate_dual_basis_hamiltonian_with_spin_and_potentials(self):
        big_eng = projectq.MainEngine()
        big_reg = big_eng.allocate_qureg(2 * self.size)
        hamiltonian = dual_basis_hamiltonian(1, self.size, spinless=False)

        for i in range(2 * self.size):
            coefficient = 1. / (i + 1)
            if i % 3:
                coefficient = -coefficient
            hamiltonian += FermionOperator(((i, 1), (i, 0)), coefficient)

        # Choose random state.
        initial_state = numpy.zeros(2**(2 * self.size), dtype=complex)
        for i in range(len(initial_state)):
            initial_state[i] = (random.random() *
                                numpy.exp(1j * 2 * numpy.pi * random.random()))
        initial_state /= numpy.linalg.norm(initial_state)

        # Put randomly chosen state in the registers.
        big_eng.flush()
        big_eng.backend.set_wavefunction(initial_state, big_reg)

        _low_depth_trotter_simulation.simulate_dual_basis_evolution(
            big_reg,
            hamiltonian,
            trotter_steps=7,
            first_order=False,
            input_ordering=list(range(7, -1, -1)))

        big_eng.flush()

        # get_sparse_operator reverses the indices - we've accounted for this
        # with the reversed input_ordering.
        evol_matrix = expm(-1j * get_sparse_operator(
            hamiltonian, n_qubits=2 * self.size)).todense()
        initial_state = numpy.matrix(initial_state).T
        expected = evol_matrix * initial_state

        self.assertTrue(
            numpy.allclose(ordered_wavefunction(big_eng),
                           expected.T,
                           atol=1e-2),
            msg=str(numpy.array(ordered_wavefunction(big_eng) - expected.T)))

        projectq.ops.All(projectq.ops.Measure) | big_reg
示例#6
0
    def test_first_order_even_number_of_steps_no_reversal(self):
        hamiltonian = FermionOperator('2^ 3') + FermionOperator('3^ 2')

        projectq.ops.All(projectq.ops.H) | self.register

        _low_depth_trotter_simulation.simulate_dual_basis_evolution(
            self.register, hamiltonian, trotter_steps=2, first_order=True)

        self.engine.flush()

        # Use 0^ 1 + 1^ 0 because get_sparse_operator reverses the indices.
        reversed_operator = FermionOperator('0^ 1') + FermionOperator('1^ 0')
        evol_matrix = expm(-1j * get_sparse_operator(
            reversed_operator, n_qubits=self.size)).todense()
        expected = evol_matrix * numpy.matrix(
            [2**(-self.size / 2.)] * 2**self.size).T

        self.assertTrue(
            numpy.allclose(ordered_wavefunction(self.engine), expected.T))
示例#7
0
    def test_simulate_n0n3(self):
        hamiltonian = FermionOperator('3^ 0^ 3 0')

        projectq.ops.All(projectq.ops.H) | self.register

        _low_depth_trotter_simulation.simulate_dual_basis_evolution(
            self.register, hamiltonian, trotter_steps=1, first_order=False)
        self.engine.flush()

        # Though get_sparse_operator reverses the indices, this is symmetric.
        evol_matrix = expm(
            -1j *
            get_sparse_operator(hamiltonian, n_qubits=self.size)).todense()
        expected = evol_matrix * numpy.matrix(
            [2**(-self.size / 2.)] * 2**self.size).T

        self.assertTrue(
            numpy.allclose(ordered_wavefunction(self.engine), expected.T),
            msg=str(ordered_wavefunction(self.engine) - expected.T))
示例#8
0
 def test_simulate_dual_basis_evolution_bad_n_trotter_steps(self):
     with self.assertRaises(ValueError):
         _low_depth_trotter_simulation.simulate_dual_basis_evolution(
             self.register, FermionOperator(), trotter_steps=0)
示例#9
0
 def test_simulate_dual_basis_evolution_bad_input_ordering(self):
     with self.assertRaises(ValueError):
         _low_depth_trotter_simulation.simulate_dual_basis_evolution(
             self.register, FermionOperator(), input_ordering=[1, 2])