CHI_F = -1.02e-3 #GHz CHI_PRIME = 0 MAX_AMP_C = 2 * np.pi * 2e-3 #GHz MAX_AMP_T = 2 * np.pi * 2e-2 #GHz CAVITY_STATE_COUNT = 5 CAVITY_ZERO = np.array([[1], [0], [0], [0], [0]]) CAVITY_ONE = np.array([[0], [1], [0], [0], [0]]) CAVITY_TWO = np.array([[0], [0], [1], [0], [0]]) CAVITY_THREE = np.array([[0], [0], [0], [1], [0]]) CAVITY_FOUR = np.array([[0], [0], [0], [0], [1]]) CAVITY_PSI_UP = np.divide(CAVITY_ZERO + CAVITY_FOUR, np.sqrt(2)) CAVITY_PSI_DOWN = CAVITY_TWO I_C = np.eye(CAVITY_STATE_COUNT) A_C = get_annihilation_operator(CAVITY_STATE_COUNT) A_DAGGER_C = get_creation_operator(CAVITY_STATE_COUNT) A_DAGGER_2_A_2_C = matmuls(A_DAGGER_C, A_DAGGER_C, A_C, A_C) N_C = matmuls(A_DAGGER_C, A_C) TRANSMON_STATE_COUNT = 3 TRANSMON_G = np.array([[1], [0], [0]]) TRANSMON_E = np.array([[0], [1], [0]]) TRANSMON_F = np.array([[0], [0], [1]]) I_T = np.eye(TRANSMON_STATE_COUNT) A_T = get_annihilation_operator(TRANSMON_STATE_COUNT) A_DAGGER_T = get_creation_operator(TRANSMON_STATE_COUNT) A_DAGGER_2_A_2_T = matmuls(A_DAGGER_T, A_DAGGER_T, A_T, A_T) N_T = matmuls(A_DAGGER_T, A_T) HILBERT_SIZE = CAVITY_STATE_COUNT * TRANSMON_STATE_COUNT H_SYSTEM_0 = (
def test_evolve_lindblad_discrete(): """ Run end-to-end tests on evolve_lindblad_discrete. """ import numpy as np from qutip import mesolve, Qobj from qoc.core.lindbladdiscrete import evolve_lindblad_discrete from qoc.standard import ( conjugate_transpose, SIGMA_X, SIGMA_Y, matrix_to_column_vector_list, SIGMA_PLUS, SIGMA_MINUS, get_creation_operator, get_annihilation_operator, ) big = 4 # Test that evolution WITH a hamiltonian and WITHOUT lindblad operators # yields a known result. # Use e.q. 109 from # https://arxiv.org/abs/1904.06560 hilbert_size = 4 identity_matrix = np.eye(hilbert_size, dtype=np.complex128) iswap_unitary = np.array( ((1, 0, 0, 0), (0, 0, -1j, 0), (0, -1j, 0, 0), (0, 0, 0, 1))) initial_states = matrix_to_column_vector_list(identity_matrix) target_states = matrix_to_column_vector_list(iswap_unitary) initial_densities = np.matmul(initial_states, conjugate_transpose(initial_states)) target_densities = np.matmul(target_states, conjugate_transpose(target_states)) system_hamiltonian = ( (1 / 2) * (np.kron(SIGMA_X, SIGMA_X) + np.kron(SIGMA_Y, SIGMA_Y))) hamiltonian = lambda controls, time: system_hamiltonian system_eval_count = 2 evolution_time = np.pi / 2 result = evolve_lindblad_discrete(evolution_time, initial_densities, system_eval_count, hamiltonian=hamiltonian) final_densities = result.final_densities assert (np.allclose(final_densities, target_densities)) # Note that qutip only gets this result within 1e-5 error. tlist = np.array([0, evolution_time]) c_ops = list() e_ops = list() for i, initial_density in enumerate(initial_densities): result = mesolve( Qobj(system_hamiltonian), Qobj(initial_density), tlist, c_ops, e_ops, ) final_density = result.states[-1].full() target_density = target_densities[i] #ENDFOR # Test that evolution WITHOUT a hamiltonian and WITH lindblad operators # yields a known result. # This test ensures that dissipators are working correctly. # Use e.q.14 from # https://inst.eecs.berkeley.edu/~cs191/fa14/lectures/lecture15.pdf. hilbert_size = 2 gamma = 2 lindblad_dissipators = np.array((gamma, )) sigma_plus = np.array([[0, 1], [0, 0]]) lindblad_operators = np.stack((sigma_plus, )) lindblad_data = lambda time: (lindblad_dissipators, lindblad_operators) evolution_time = 1. system_eval_count = 2 inv_sqrt_2 = 1 / np.sqrt(2) a0 = np.random.rand() c0 = 1 - a0 b0 = np.random.rand() b0_star = np.conj(b0) initial_density_0 = np.array(((a0, b0), (b0_star, c0))) initial_densities = np.stack((initial_density_0, )) gt = gamma * evolution_time expected_final_density = np.array( ((1 - c0 * np.exp(-gt), b0 * np.exp(-gt / 2)), (b0_star * np.exp(-gt / 2), c0 * np.exp(-gt)))) result = evolve_lindblad_discrete(evolution_time, initial_densities, system_eval_count, lindblad_data=lindblad_data) final_density = result.final_densities[0] assert (np.allclose(final_density, expected_final_density)) # Test that evolution WITH a random hamiltonian and WITH random lindblad operators # yields a similar result to qutip. matrix_size = 4 evolution_time = 5 system_eval_count = 2 e_ops_qutip = list() tlist = np.array(( 0, evolution_time, )) for i in range(big): # Evolve under lindbladian. hamiltonian_matrix = random_hermitian_matrix(matrix_size) hamiltonian = lambda controls, time: hamiltonian_matrix lindblad_operator_count = np.random.randint(1, matrix_size) lindblad_operators = np.stack([ random_complex_matrix(matrix_size) for _ in range(lindblad_operator_count) ]) lindblad_dissipators = np.ones((lindblad_operator_count, )) lindblad_data = lambda time: (lindblad_dissipators, lindblad_operators) density_matrix = random_hermitian_matrix(matrix_size) initial_densities = np.stack((density_matrix, )) result = evolve_lindblad_discrete(evolution_time, initial_densities, system_eval_count, hamiltonian=hamiltonian, lindblad_data=lindblad_data) final_density = result.final_densities[0] # Evolve under lindbladian with qutip. hamiltonian_qutip = Qobj(hamiltonian_matrix) initial_density_qutip = Qobj(density_matrix) lindblad_operators_qutip = [ Qobj(lindblad_operator) for lindblad_operator in lindblad_operators ] result_qutip = mesolve( hamiltonian_qutip, initial_density_qutip, tlist, lindblad_operators_qutip, e_ops_qutip, ) final_density_qutip = result_qutip.states[-1].full() assert (np.allclose(final_density, final_density_qutip)) #ENDFOR # Test that evolvution with a random hamiltonain, # random control amplitudes, and random lindblad operators yields # a similar result to qutip. # qoc constatns matrix_size = 4 evolution_time = 5 system_eval_count = 2 control_eval_count = 100 control_count = 1 controls_shape = (control_eval_count, control_count) create = get_creation_operator(matrix_size) annihilate = get_annihilation_operator(matrix_size) # qutip constants e_ops_qutip = list() tlist = np.linspace(0, evolution_time, control_eval_count) hc0_qutip = Qobj(annihilate + create) hc1_qutip = Qobj(1j * (annihilate - create)) lindblad_operator_count = 1 for i in range(big): hamiltonian_matrix = random_hermitian_matrix(matrix_size) hamiltonian = lambda controls, time: (hamiltonian_matrix + controls[ 0] * annihilate + np.conjugate(controls[0]) * create) lindblad_operators = np.stack([ random_complex_matrix(matrix_size) for _ in range(lindblad_operator_count) ]) lindblad_dissipators = np.ones((lindblad_operator_count, )) lindblad_data = lambda time: (lindblad_dissipators, lindblad_operators) density_matrix = random_hermitian_matrix(matrix_size) initial_densities = np.stack((density_matrix, )) controls = np.random.rand( *controls_shape) + 1j * np.random.rand(*controls_shape) result = evolve_lindblad_discrete(evolution_time, initial_densities, system_eval_count, controls=controls, hamiltonian=hamiltonian, lindblad_data=lindblad_data) final_density = result.final_densities[0] hamiltonian_qutip = Qobj(hamiltonian_matrix) c0_qutip = np.real(controls)[:, 0] c1_qutip = np.imag(controls)[:, 0] h0_ones = np.ones_like(controls[:, 0]) h_list = [[hamiltonian_qutip, h0_ones], [hc0_qutip, c0_qutip], [hc1_qutip, c1_qutip]] initial_density_qutip = Qobj(density_matrix) lindblad_operators_qutip = [ Qobj(lindblad_operator) for lindblad_operator in lindblad_operators ] result_qutip = mesolve( h_list, initial_density_qutip, tlist, lindblad_operators_qutip, e_ops_qutip, ) final_density_qutip = result_qutip.states[-1].full() # Qutip does a cubic fit, by default, on their controls and we do a linear fit, # by default. # 1e-2 is reasonable, taking interpolation method differences # into consideration. assert (np.allclose(final_density, final_density_qutip, atol=1e-2))
def test_evolve_schroedinger_discrete(): """ Run end-to-end test on the evolve_schroedinger_discrete function. """ import numpy as np from qutip import mesolve, Qobj, Options from scipy.linalg import norm from qoc.core import evolve_schroedinger_discrete from qoc.models import ( MagnusPolicy, ) from qoc.standard import ( matrix_to_column_vector_list, SIGMA_X, SIGMA_Y, get_creation_operator, get_annihilation_operator, ) big = 10 magnus_policies = ( MagnusPolicy.M2, MagnusPolicy.M4, MagnusPolicy.M6, ) # Test that evolving states under a known hamiltonian yields # a known result. Use e.q. 109 of # https://arxiv.org/abs/1904.06560. hilbert_size = 4 identity_matrix = np.eye(hilbert_size, dtype=np.complex128) iswap_unitary = np.array( ((1, 0, 0, 0), (0, 0, -1j, 0), (0, -1j, 0, 0), (0, 0, 0, 1))) hamiltonian_matrix = np.divide( 1, 2) * (np.kron(SIGMA_X, SIGMA_X) + np.kron(SIGMA_Y, SIGMA_Y)) hamiltonian = lambda controls, time: hamiltonian_matrix initial_states = matrix_to_column_vector_list(identity_matrix) target_states = matrix_to_column_vector_list(iswap_unitary) evolution_time = np.divide(np.pi, 2) system_eval_count = int(1e3) for magnus_policy in magnus_policies: result = evolve_schroedinger_discrete(evolution_time, hamiltonian, initial_states, system_eval_count, magnus_policy=magnus_policy) final_states = result.final_states assert (np.allclose(final_states, target_states)) #ENDFOR # Test that evolving random states under a random hamiltonian yields # a result similar to qutip. # qoc constants hilbert_size = 4 system_eval_count = int(1e3) evolution_time = 1 initial_state_shape = (hilbert_size, 1) # qutip constants tlist = np.array([0, evolution_time]) c_ops = e_ops = list() for _ in range(big): # qoc setup hamiltonian_matrix = random_hermitian_matrix(hilbert_size) hamiltonian = lambda controls, time: hamiltonian_matrix initial_state = (np.random.rand(*initial_state_shape) + 1j * np.random.rand(*initial_state_shape)) initial_state = initial_state / norm(initial_state) initial_states = np.stack((initial_state, )) # qutip setup hamiltonian_qutip = Qobj(hamiltonian_matrix) initial_state_qutip = Qobj(initial_state) # run qutip result = mesolve( hamiltonian_qutip, initial_state_qutip, tlist, c_ops, e_ops, ) final_state_qutip = result.states[-1].full() # run qoc for magnus_policy in magnus_policies: result = evolve_schroedinger_discrete(evolution_time, hamiltonian, initial_states, system_eval_count, magnus_policy=magnus_policy) final_state = result.final_states[0] assert (np.allclose(final_state, final_state_qutip, atol=1e-4)) #ENDFOR #ENDFOR # Test that evolving under a random hamiltonian and random controls yields # a result similar to qutip. # qoc constants hilbert_size = 4 control_eval_count = 100 control_count = 1 controls_shape = (control_eval_count, control_count) system_eval_count = int(1e3) evolution_time = 1 initial_state_shape = (hilbert_size, 1) create = get_creation_operator(hilbert_size) annihilate = get_annihilation_operator(hilbert_size) # qutip constants c_ops = e_ops = list() hc0_qutip = Qobj(annihilate + create) hc1_qutip = Qobj(1j * (annihilate - create)) tlist = np.linspace(0, evolution_time, control_eval_count) for _ in range(big): # setup qoc controls = (np.random.rand(*controls_shape) + 1j * np.random.rand(*controls_shape)) hamiltonian_matrix = random_hermitian_matrix(hilbert_size) hamiltonian = lambda controls, time: (hamiltonian_matrix + controls[ 0] * annihilate + np.conjugate(controls[0]) * create) initial_state = (np.random.rand(*initial_state_shape) + 1j * np.random.rand(*initial_state_shape)) initial_state = initial_state / norm(initial_state) initial_states = np.stack((initial_state, )) # setup qutip hamiltonian_qutip = Qobj(hamiltonian_matrix) initial_state_qutip = Qobj(initial_state) h0_ones = np.ones(controls.shape[0]) c0_qutip = np.real(controls)[:, 0] c1_qutip = np.imag(controls)[:, 0] h_list = [[hamiltonian_qutip, h0_ones], [hc0_qutip, c0_qutip], [hc1_qutip, c1_qutip]] # run qutip result = mesolve( h_list, initial_state_qutip, tlist, c_ops, e_ops, ) final_state_qutip = result.states[-1].full() # run QOC for magnus_policy in magnus_policies: result = evolve_schroedinger_discrete(evolution_time, hamiltonian, initial_states, system_eval_count, controls=controls, magnus_policy=magnus_policy) final_state = result.final_states[0] # Again, we see 1e-2 tolerance. # Note that we interpolate controls linearly whereas # qutip interpolates controls cubically. assert (np.allclose(final_state, final_state_qutip, atol=1e-2))
import ray.tune from ray.tune.suggest.hyperopt import HyperOptSearch # Specify computer specs. CORE_COUNT = 8 # Define experimental constants. CHI_E = -5.65e-4 #GHz CHI_F = 2 * CHI_E #GHz MAX_AMP_C = 2 * anp.pi * 2e-3 #GHz MAX_AMP_T = 2 * anp.pi * 2e-2 #GHz # Define the system. CAVITY_STATE_COUNT = 5 CAVITY_ANNIHILATE = get_annihilation_operator(CAVITY_STATE_COUNT) CAVITY_CREATE = get_creation_operator(CAVITY_STATE_COUNT) CAVITY_NUMBER = anp.matmul(CAVITY_CREATE, CAVITY_ANNIHILATE) CAVITY_ZERO = anp.array(((1, ), (0, ), (0, ), (0, ), (0, ))) CAVITY_ONE = anp.array(((0, ), (1, ), (0, ), (0, ), (0, ))) CAVITY_TWO = anp.array(((0, ), (0, ), (1, ), (0, ), (0, ))) CAVITY_THREE = anp.array(((0, ), (0, ), (0, ), (1, ), (0, ))) CAVITY_FOUR = anp.array(((0, ), (0, ), (0, ), (0, ), (1, ))) CAVITY_I = anp.eye(CAVITY_STATE_COUNT) TRANSMON_STATE_COUNT = 3 TRANSMON_G = anp.array(((1, ), (0, ), (0, ))) TRANSMON_G_DAGGER = conjugate_transpose(TRANSMON_G) TRANSMON_E = anp.array(((0, ), (1, ), (0, ))) TRANSMON_E_DAGGER = conjugate_transpose(TRANSMON_E) TRANSMON_F = anp.array(((0, ), (0, ), (1, ))) TRANSMON_F_DAGGER = conjugate_transpose(TRANSMON_F)
from qoc.standard import ( TargetDensityInfidelity, conjugate_transpose, get_annihilation_operator, get_creation_operator, SIGMA_Z, SIGMA_PLUS, generate_save_file_path, LBFGSB, Adam, ) # Define the system. HILBERT_SIZE = 2 ANNIHILATION_OPERATOR = get_annihilation_operator(HILBERT_SIZE) CREATION_OPERATOR = get_creation_operator(HILBERT_SIZE) # E.q. 19 (p. 6) of # https://arxiv.org/abs/1904.06560. H_SYSTEM_0 = SIGMA_Z / 2 # Use a + a^{dagger} as the drive term to control. hamiltonian = lambda controls, time: (H_SYSTEM_0 + controls[ 0] * ANNIHILATION_OPERATOR + anp.conjugate(controls[0]) * CREATION_OPERATOR ) # Subject the system to T1 type decoherence per fig. 11 of # https://www.sciencedirect.com/science/article/pii/S0003491617301252. LINDBLAD_OPERATORS = anp.stack((ANNIHILATION_OPERATOR, )) T1 = 1e3 #ns GAMMA_1 = 1 / T1 LINDBLAD_DISSIPATORS = anp.stack((GAMMA_1, )) lindblad_data = lambda time: (LINDBLAD_DISSIPATORS, LINDBLAD_OPERATORS)
SAVE_PATH = os.path.join(BASE_PATH, "out", EXPERIMENT_NAME) # Define experimental constants. All units are in GHz. CAVITY_FREQ = 2 * np.pi * 4.4526 KAPPA = 2 * np.pi * -2.82e-6 TRANSMON_FREQ = 2 * np.pi * 5.6640 ALPHA = 2 * np.pi * -1.395126e-1 CHI_E = 2 * np.pi * -5.64453e-4 CHI_E_2 = 2 * np.pi * -7.3e-7 MAX_AMP_NORM_CAVITY = np.sqrt(2) * 2 * np.pi * 4e-4 MAX_AMP_NORM_TRANSMON = np.sqrt(2) * 2 * np.pi * 4e-3 # Define the system CAVITY_STATE_COUNT = 3 CAVITY_ANNIHILATE = get_annihilation_operator(CAVITY_STATE_COUNT) CAVITY_CREATE = get_creation_operator(CAVITY_STATE_COUNT) CAVITY_NUMBER = np.matmul(CAVITY_CREATE, CAVITY_ANNIHILATE) CAVITY_C2_A2 = matmuls(CAVITY_CREATE, CAVITY_CREATE, CAVITY_ANNIHILATE, CAVITY_ANNIHILATE) CAVITY_ID = np.eye(CAVITY_STATE_COUNT) CAVITY_VACUUM = np.zeros((CAVITY_STATE_COUNT, 1)) CAVITY_ZERO = np.copy(CAVITY_VACUUM) CAVITY_ZERO[0][0] = 1 CAVITY_ONE = np.copy(CAVITY_VACUUM) CAVITY_ONE[1][0] = 1 CAVITY_TWO = np.copy(CAVITY_VACUUM) CAVITY_TWO[2][0] = 1 TRANSMON_STATE_COUNT = 3 TRANSMON_ANNIHILATE = get_annihilation_operator(TRANSMON_STATE_COUNT) TRANSMON_CREATE = get_creation_operator(TRANSMON_STATE_COUNT)