def test_2mode_ffft_correct_frequencies(self): n_qubits = 2 frequencies_seen = numpy.zeros(n_qubits) for qubit in range(n_qubits): engine = MainEngine() register = engine.allocate_qureg(n_qubits) X | register[qubit] ffft(engine, register, n_qubits) engine.flush() wavefunction = ordered_wavefunction(engine) nonzero_wavefunction_elmts = [] for el in wavefunction: if abs(el) > 10 ** -5: nonzero_wavefunction_elmts.append(el) All(Measure) | register phase_factor = (nonzero_wavefunction_elmts[1] / nonzero_wavefunction_elmts[0]) offset = numpy.angle(nonzero_wavefunction_elmts[0]) self.assertAlmostEqual(offset, 0.0) for i in range(1, len(nonzero_wavefunction_elmts)): self.assertAlmostEqual(phase_factor, (nonzero_wavefunction_elmts[i] / nonzero_wavefunction_elmts[i - 1])) frequencies_seen[qubit] = numpy.angle(phase_factor) frequencies_seen = numpy.sort(frequencies_seen) expected = numpy.sort(2 * numpy.pi * numpy.arange(n_qubits) / n_qubits) self.assertTrue(numpy.allclose(frequencies_seen, expected))
def test_8mode_ffft_with_external_swaps_on_single_logical_state(self): n_qubits = 8 grid = Grid(dimensions=1, length=n_qubits, scale=1.0) eng = MainEngine() register = eng.allocate_qureg(n_qubits) state_index = 157 prepare_logical_state(register, state_index) ffft(eng, register, n_qubits) Ph(3 * numpy.pi / 4) | register[0] eng.flush() wvfn = ordered_wavefunction(eng) fermion_operator = prepare_integer_fermion_operator(state_index) # Swap 01234567 to 45670123 for fourier_transform. Additionally, # the FFFT's ordering is 04261537, so swap 04261537 to 01234567, # and then 01234567 to 45670123. swap_mode_list = ([1, 3, 5, 2, 4, 1, 3, 5] + [3, 2, 4, 1, 3, 5, 0, 2, 4, 6, 1, 3, 5, 2, 4, 3]) for mode in swap_mode_list: fermion_operator = normal_ordered(fermion_operator) fermion_operator = swap_adjacent_fermionic_modes( fermion_operator, mode) ffft_result = fourier_transform(fermion_operator, grid, spinless=True) ffft_result = normal_ordered(ffft_result) # After the FFFT, swap 45670123 -> 01234567. swap_mode_list = [3, 2, 4, 1, 3, 5, 0, 2, 4, 6, 1, 3, 5, 2, 4, 3] for mode in swap_mode_list: ffft_result = swap_adjacent_fermionic_modes(ffft_result, mode) converted_wvfn = numpy.zeros(2 ** n_qubits, dtype=complex) for term in ffft_result.terms: index = sum(2 ** site[0] for site in term) converted_wvfn[index] = ffft_result.terms[term] All(Measure) | register self.assertTrue(numpy.allclose(wvfn, converted_wvfn))
def test_ffft_2modes_properly_applied(self): eng_ft_0 = MainEngine() reg_ft_0 = eng_ft_0.allocate_qureg(2) eng_ffft_recursive = MainEngine() reg_ffft_recursive = eng_ffft_recursive.allocate_qureg(2) ffft(eng_ffft_recursive, reg_ffft_recursive, 2) fourier_transform_0(reg_ft_0, 0, 1) eng_ffft_recursive.flush() eng_ft_0.flush() All(Measure) | reg_ffft_recursive All(Measure) | reg_ft_0 self.assertTrue(numpy.allclose( ordered_wavefunction(eng_ffft_recursive), ordered_wavefunction(eng_ft_0)))
def test_4mode_ffft_with_external_swaps_all_logical_states(self): n_qubits = 4 grid = Grid(dimensions=1, length=n_qubits, scale=1.0) for i in range(2**n_qubits): eng = MainEngine() register = eng.allocate_qureg(n_qubits) prepare_logical_state(register, i) ffft(eng, register, n_qubits) Ph(3 * numpy.pi / 4) | register[0] eng.flush() wvfn = ordered_wavefunction(eng) fermion_operator = prepare_integer_fermion_operator(i) # Reorder the modes for correct input to the FFFT. # Swap 0123 to 2301 for fourier_transform. Additionally, the # FFFT's ordering is 0213, so connect 0213 -> 0123 -> 2301. swap_mode_list = [1] + [1, 0, 2, 1] for mode in swap_mode_list: fermion_operator = normal_ordered(fermion_operator) fermion_operator = swap_adjacent_fermionic_modes( fermion_operator, mode) ffft_result = fourier_transform(fermion_operator, grid, spinless=True) ffft_result = normal_ordered(ffft_result) swap_mode_list = [1, 0, 2, 1] # After FFFT, swap 2301 -> 0123 for mode in swap_mode_list: ffft_result = swap_adjacent_fermionic_modes(ffft_result, mode) converted_wvfn = numpy.zeros(2**n_qubits, dtype=complex) for term in ffft_result.terms: index = sum(2**site[0] for site in term) converted_wvfn[index] = ffft_result.terms[term] All(Measure) | register self.assertTrue(numpy.allclose(wvfn, converted_wvfn))
def test_8mode_ffft_with_external_swaps_equal_expectation_values(self): n_qubits = 8 grid = Grid(dimensions=1, length=n_qubits, scale=1.0) dual_basis = jellium_model(grid, spinless=True, plane_wave=False) ffft_result = normal_ordered(dual_basis) # Swap 01234567 to 45670123 for fourier_transform. Additionally, # the FFFT's ordering is 04261537, so swap 04261537 to 01234567, # and then 01234567 to 45670123. swap_mode_list = ([1, 3, 5, 2, 4, 1, 3, 5] + [3, 2, 4, 1, 3, 5, 0, 2, 4, 6, 1, 3, 5, 2, 4, 3]) for mode in swap_mode_list: ffft_result = swap_adjacent_fermionic_modes(ffft_result, mode) ffft_result = normal_ordered(ffft_result) ffft_result = fourier_transform(ffft_result, grid, spinless=True) ffft_result = normal_ordered(ffft_result) # After the FFFT, swap 45670123 -> 01234567. swap_mode_list = [3, 2, 4, 1, 3, 5, 0, 2, 4, 6, 1, 3, 5, 2, 4, 3] for mode in swap_mode_list: ffft_result = swap_adjacent_fermionic_modes(ffft_result, mode) ffft_result = normal_ordered(ffft_result) jw_dual_basis = jordan_wigner(dual_basis) jw_plane_wave = jordan_wigner(ffft_result) # Do plane wave and dual basis calculations simultaneously. pw_engine = MainEngine() pw_wavefunction = pw_engine.allocate_qureg(n_qubits) db_engine = MainEngine() db_wavefunction = db_engine.allocate_qureg(n_qubits) pw_engine.flush() db_engine.flush() # Choose random state. state = numpy.zeros(2 ** n_qubits, 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. pw_engine.backend.set_wavefunction(state, pw_wavefunction) db_engine.backend.set_wavefunction(state, db_wavefunction) prepare_logical_state(pw_wavefunction, i) prepare_logical_state(db_wavefunction, i) All(H) | [pw_wavefunction[1], pw_wavefunction[3]] All(H) | [db_wavefunction[1], db_wavefunction[3]] ffft(db_engine, db_wavefunction, n_qubits) Ph(3 * numpy.pi / 4) | db_wavefunction[0] # Flush the engine and compute expectation values and eigenvalues. pw_engine.flush() db_engine.flush() plane_wave_expectation_value = ( pw_engine.backend.get_expectation_value( jw_dual_basis, pw_wavefunction)) dual_basis_expectation_value = ( db_engine.backend.get_expectation_value( jw_plane_wave, db_wavefunction)) All(Measure) | pw_wavefunction All(Measure) | db_wavefunction self.assertAlmostEqual(plane_wave_expectation_value, dual_basis_expectation_value)
def test_ffft_1mode_error(self): eng = MainEngine() reg = eng.allocate_qureg(1) with self.assertRaises(ValueError): ffft(eng, reg, 1)