def test_parallel_map_fw_prop_step_loky(transmon_xgate_system): """Test optimization with parallel_map parameter, using loky.""" objectives, pulse_options, tlist = transmon_xgate_system krotov.parallelization.USE_LOKY = True log = io.StringIO() opt_result_loky = krotov.optimize_pulses( objectives, pulse_options, tlist, propagator=krotov.propagators.expm, chi_constructor=krotov.functionals.chis_re, info_hook=partial(krotov.info_hooks.print_debug_information, out=log), iter_stop=1, skip_initial_forward_propagation=True, parallel_map=( krotov.parallelization.parallel_map, krotov.parallelization.parallel_map, krotov.parallelization.parallel_map_fw_prop_step, ), ) tau1_loky = abs(opt_result_loky.tau_vals[0][0]) tau2_loky = abs(opt_result_loky.tau_vals[0][1]) assert abs(tau1_loky - 0.9693) < 1e-3 assert abs(tau2_loky - 0.7743) < 1e-3 krotov.parallelization.USE_LOKY = False # in order to be pickleable, all functions must be defined in a module # (transmon_xgate_system_mod) H = transmon_xgate_system_mod.transmon_hamiltonian() pulse_options = { H[1][1]: dict(lambda_a=1, update_shape=transmon_xgate_system_mod.S) } psi0, psi1 = transmon_xgate_system_mod.logical_basis(H) objectives = krotov.gate_objectives( basis_states=[psi0, psi1], gate=qutip.operators.sigmax(), H=H ) try: opt_result = krotov.optimize_pulses( objectives, pulse_options, tlist, propagator=krotov.propagators.expm, chi_constructor=krotov.functionals.chis_re, iter_stop=1, skip_initial_forward_propagation=True, parallel_map=( krotov.parallelization.parallel_map, krotov.parallelization.parallel_map, krotov.parallelization.parallel_map_fw_prop_step, ), ) tau1 = abs(opt_result.tau_vals[0][0]) tau2 = abs(opt_result.tau_vals[0][1]) assert abs(tau1_loky - tau1) < 1e-12 assert abs(tau2_loky - tau2) < 1e-12 except RuntimeError: # parallelization without LOKY doesn't work on all platforms pass
def test_gate_objectives_pe(): """Test gate objectives for a PE optimization""" from qutip import ket, tensor, sigmaz, sigmax, identity from weylchamber import bell_basis basis = [ket(n) for n in [(0, 0), (0, 1), (1, 0), (1, 1)]] H = [ tensor(sigmaz(), identity(2)) + tensor(identity(2), sigmaz()), [tensor(sigmax(), identity(2)), lambda t, args: 1.0], [tensor(identity(2), sigmax()), lambda t, args: 1.0], ] objectives = krotov.gate_objectives(basis, 'PE', H) assert len(objectives) == 4 bell_basis_states = bell_basis(basis) for state in bell_basis_states: assert isinstance(state, qutip.Qobj) for i in range(4): expected_objective = krotov.Objective( initial_state=bell_basis_states[i], target='PE', H=H ) assert objectives[i] == expected_objective assert krotov.gate_objectives(basis, 'perfect_entangler', H) == objectives assert krotov.gate_objectives(basis, 'perfect entangler', H) == objectives assert krotov.gate_objectives(basis, 'Perfect Entangler', H) == objectives with pytest.raises(ValueError): krotov.gate_objectives(basis, 'prefect(!) entanglers', H)
def test_transmon_3states_objectives(): L = qutip.Qobj() # dummy Liouvillian (won't be used) n_qubit = 3 ket00 = qutip.ket((0, 0), dim=(n_qubit, n_qubit)) ket01 = qutip.ket((0, 1), dim=(n_qubit, n_qubit)) ket10 = qutip.ket((1, 0), dim=(n_qubit, n_qubit)) ket11 = qutip.ket((1, 1), dim=(n_qubit, n_qubit)) basis = [ket00, ket01, ket10, ket11] weights = [20, 1, 1] objectives = krotov.gate_objectives( basis, qutip_gates.sqrtiswap(), L, liouville_states_set='3states', weights=weights, ) rho1_tgt = ( 0.4 * ket00 * ket00.dag() + (0.5 / 2) * ket01 * ket01.dag() - (0.1j / 2) * ket01 * ket10.dag() + (0.1j / 2) * ket10 * ket01.dag() + (0.5 / 2) * ket10 * ket10.dag() + 0.1 * ket11 * ket11.dag() ) ket00_tgt = ket00 ket01_tgt = (ket01 + 1j * ket10) / np.sqrt(2) ket10_tgt = (1j * ket01 + ket10) / np.sqrt(2) ket11_tgt = ket11 target_basis = [ket00_tgt, ket01_tgt, ket10_tgt, ket11_tgt] rho2_tgt = 0.25 * sum( [psi * phi.dag() for (psi, phi) in product(target_basis, target_basis)] ) rho3_tgt = 0.25 * ( ket00 * ket00.dag() + ket01 * ket01.dag() + ket10 * ket10.dag() + ket11 * ket11.dag() ) assert (objectives[0].target - rho1_tgt).norm('max') < 1e-14 assert (objectives[1].target - rho2_tgt).norm('max') < 1e-14 assert (objectives[2].target - rho3_tgt).norm('max') < 1e-14 assert objectives[0].weight == 60.0 / 22.0 assert objectives[1].weight == 3.0 / 22.0 assert objectives[2].weight == 3.0 / 22.0
def transmon_xgate_system(): """Optimization system for a single-qubit transmont gate. See example "Optimization of an X-Gate for a Transmon Qubit". """ def eps0(t, args): T = 10 return 4 * np.exp(-40.0 * (t / T - 0.5)**2) def transmon_hamiltonian(Ec=0.386, EjEc=45, nstates=2, ng=0.0, T=10.0): Ej = EjEc * Ec n = np.arange(-nstates, nstates + 1) up = np.diag(np.ones(2 * nstates), k=-1) do = up.T H0 = qutip.Qobj(np.diag(4 * Ec * (n - ng)**2) - Ej * (up + do) / 2.0) H1 = qutip.Qobj(-2 * np.diag(n)) return [H0, [H1, eps0]] def logical_basis(H): H0 = H[0] eigenvals, eigenvecs = scipy.linalg.eig(H0.full()) ndx = np.argsort(eigenvals.real) V = eigenvecs[:, ndx] psi0 = qutip.Qobj(V[:, 0]) psi1 = qutip.Qobj(V[:, 1]) return psi0, psi1 def S(t): return krotov.shapes.flattop(t, t_start=0.0, t_stop=10.0, t_rise=0.5, func='sinsq') tlist = np.linspace(0, 10, 100) H = transmon_hamiltonian() pulse_options = {H[1][1]: dict(lambda_a=1, update_shape=S)} psi0, psi1 = logical_basis(H) objectives = krotov.gate_objectives(basis_states=[psi0, psi1], gate=qutip.operators.sigmax(), H=H) return objectives, pulse_options, tlist
def transmon_3states_objectives(): # see also test_objectives:test_transmon_3states_objectives L = qutip.Qobj() # dummy Liouvillian (won't be used) n_qubit = 3 ket00 = qutip.ket((0, 0), dim=(n_qubit, n_qubit)) ket01 = qutip.ket((0, 1), dim=(n_qubit, n_qubit)) ket10 = qutip.ket((1, 0), dim=(n_qubit, n_qubit)) ket11 = qutip.ket((1, 1), dim=(n_qubit, n_qubit)) basis = [ket00, ket01, ket10, ket11] weights = [20, 1, 1] objectives = krotov.gate_objectives( basis, qutip_gates.sqrtiswap(), L, liouville_states_set='3states', weights=weights, ) return objectives
def iswap_state_objectives(canonical_basis): H = qutip.Qobj() # dummy Hamiltonian (won't be used) objectives = krotov.gate_objectives(canonical_basis, qutip_gates.sqrtiswap(), H) return objectives
def optimize(self): # We can now call any Python lib to # perform pulse optimization (marshalling the options/parameters if required) # For example, one can use Qutip pulse optimization: # Notes about data types: # - targerU: flatten (row-by-row) U matrix into a 1-D array of complex numbers # - H0: string-type representation of the static Hamiltonian: # e.g.: 0.123 Z0Z1 # - Hops: array of strings represent terms on the Hamiltonian which can be controlled. # Depending on the specific library we use for pulse optimization, # we may need to marshal these data types accordingly. # Run the optimization H = self.construct_hamiltonian() tlist = np.arange(0.0, self.tMax, self.dt) # TODO: this should be an IR transformation option def S(t): """Shape function for the field update""" return krotov.shapes.flattop( t, t_start=0, t_stop=self.tMax, t_rise=self.tMax / self.rise_fall_coeff, t_fall=self.tMax / self.rise_fall_coeff, func=self.func_name) pulse_options = {H[1][1]: dict(lambda_a=self.lambda_a, update_shape=S)} print('Krotov: Target Unitary Object:') print(self.targetObj()) objectives = krotov.gate_objectives( # Target is the unitary: i.e. transform all states -> expected result. basis_states=self.logical_basis(), gate=self.targetObj(), H=H) opt_result = krotov.optimize_pulses( objectives, pulse_options, tlist, propagator=krotov.propagators.expm, chi_constructor=krotov.functionals.chis_ss, info_hook=krotov.info_hooks.print_table( J_T=krotov.functionals.J_T_ss), check_convergence=krotov.convergence.Or( krotov.convergence.value_below('1e-3', name='J_T'), krotov.convergence.check_monotonic_error, ), store_all_pulses=True, ) plotFile = self.plot_control_field_iterations(opt_result) print(opt_result) print('*************************************************') print('**Plot of control field iterations is saved to:**') print(plotFile) print('*************************************************') pulse = opt_result.optimized_controls[0] return (0.0, pulse)
def S(t): """Scales the Krotov methods update of the pulse value at the time t""" return krotov.shapes.flattop(t, t_start=0.0, t_stop=10.0, t_rise=0.5, func='sinsq') H = transmon_hamiltonian() psi0, psi1 = logical_basis(H) proj0 = qutip.ket2dm(psi0) proj1 = qutip.ket2dm(psi1) objectives = krotov.gate_objectives(basis_states=[psi0, psi1], gate=qutip.operators.sigmax(), H=H) guess_dynamics = [ objectives[x].mesolve(tlist, e_ops=[proj0, proj1]) for x in [0, 1] ] plot_population(guess_dynamics[0]) plot_population(guess_dynamics[1]) pulse_options = {H[1][1]: dict(lambda_a=1, update_shape=S)} opt_result = krotov.optimize_pulses( objectives, pulse_options, tlist,