def test_derivative_wrt_pulse_zero(tls_control_system): """Test that μ=0 if taking derivative wrt pulse not in objective""" objectives, pulses, pulses_mapping = tls_control_system # distinction between controls and pulses doesn't matter here, we're only # considering linear controls and don't plug in any time_index i_objective = 0 mu = krotov.mu.derivative_wrt_pulse( objectives, i_objective, pulses, pulses_mapping, i_pulse=1, time_index=0, ) for state in (ket('0'), ket('1')): assert mu(state).norm('max') == 0 assert (mu(state)).dims == state.dims i_objective = 1 mu = krotov.mu.derivative_wrt_pulse( objectives, i_objective, pulses, pulses_mapping, i_pulse=0, time_index=0, ) for state in (ket('0'), ket('1')): assert mu(state).norm('max') == 0 assert (mu(state)).dims == state.dims
def test_chi_hs_transmon(transmon_3states_objectives): objectives = transmon_3states_objectives n_qubit = objectives[0].initial_state.dims[0][0] 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)) ρ_mixed = 0.25 * (ket00 * ket00.dag() + ket01 * ket01.dag() + ket10 * ket10.dag() + ket11 * ket11.dag()) assert (ρ_mixed * ρ_mixed).tr() == 0.25 assert (ρ_mixed - objectives[2].target).norm('max') < 1e-14 fw_states_T = [ρ_mixed, ρ_mixed, ρ_mixed] χs = krotov.functionals.chis_hs(fw_states_T, objectives, None) χ1 = (1 / 6.0) * (60.0 / 22.0) * (objectives[0].target - ρ_mixed) χ2 = (1 / 6.0) * (3.0 / 22.0) * (objectives[1].target - ρ_mixed) χ3 = 0.0 * ρ_mixed assert (χs[0] - χ1).norm('max') < 1e-14 assert (χs[1] - χ2).norm('max') < 1e-14 assert (χs[2] - χ3).norm('max') < 1e-14 # without weights objectives = copy.deepcopy(objectives) for obj in objectives: del obj.weight χs = krotov.functionals.chis_hs(fw_states_T, objectives, None) χ1 = (1 / 6.0) * (objectives[0].target - ρ_mixed) χ2 = (1 / 6.0) * (objectives[1].target - ρ_mixed) χ3 = 0.0 * ρ_mixed assert (χs[0] - χ1).norm('max') < 1e-14 assert (χs[1] - χ2).norm('max') < 1e-14 assert (χs[2] - χ3).norm('max') < 1e-14
def teleport(state, mres): q0, q1 = map(int, twoQ_basis[mres]) s0_name = twoQ_basis[mres] + '0' s1_name = twoQ_basis[mres] + '1' s0 = qt.bra(s0_name) s1 = qt.bra(s1_name) a = (s0 * state).tr() b = (s1 * state).tr() red_state = (a * qt.ket([0], 2) + b * qt.ket([1], 2)).unit() H = Gate('SNOT', targets=0) sqrtX = Gate('SQRTNOT', targets=0) qc = QubitCircuit(N=1) if q1 == 1: qc.add_gate(sqrtX) qc.add_gate(sqrtX) if q0 == 1: qc.add_gate(H) qc.add_gate(sqrtX) qc.add_gate(sqrtX) qc.add_gate(H) gates_sequence = qc.propagators() scheme = oper.gate_sequence_product(gates_sequence) return scheme * red_state
def test_derivative_wrt_pulse_no_timedependent_cops(tls_control_system_tdcops): """Test that time-dependent collapse operators are no allowed""" objectives, pulses, pulses_mapping = tls_control_system_tdcops i_objective = 0 with pytest.raises(NotImplementedError): krotov.mu.derivative_wrt_pulse( objectives, i_objective, pulses, pulses_mapping, i_pulse=0, time_index=0, ) # however, we do allow the c_ops to be time-dependent with controls we're # not taking the derivative with respect to mu = krotov.mu.derivative_wrt_pulse( objectives, i_objective, pulses, pulses_mapping, i_pulse=1, time_index=0, ) for state in (ket('0'), ket('1')): assert mu(state).norm('max') == 0 assert (mu(state)).dims == state.dims
def infer_classical_state(qubits, idx, subset=None): """ Finds classical state of n qubits given index of basis state in H2^n. Input -------------------------------------------------- qubits: list--qubits in numeric order idx: int--index of '1' in basis state of 2^n dimensional Hilbert space subset: optional list--only output state of qubits in subset list Output -------------------------------------------------- state: dict--{q0: qutip ket 0 or ket 1, ...} """ state = {} num_qubits = len(qubits) if subset is None: subset = qubits # find classical state of qubits with tensor product ordering assumption for (n, qubit) in enumerate(qubits): if qubit in subset: power = num_qubits - n mod = 2**power cut_off = mod / 2 if idx % mod >= cut_off: state[qubit] = qt.ket('1') else: state[qubit] = qt.ket('0') return state
def simple_state_to_state_system(): """System from 01_example_simple_state_to_state.ipynb""" omega = 1.0 ampl0 = 0.2 H0 = -0.5 * omega * qutip.operators.sigmaz() H1 = qutip.operators.sigmax() eps0 = lambda t, args: ampl0 H = [H0, [H1, eps0]] psi0 = qutip.ket('0') psi1 = qutip.ket('1') objectives = [krotov.Objective(initial_state=psi0, target=psi1, H=H)] def S(t): """Shape function for the field update""" return krotov.shapes.flattop( t, t_start=0, t_stop=5, t_rise=0.3, t_fall=0.3, func='sinsq' ) pulse_options = {H[1][1]: dict(lambda_a=5, update_shape=S)} tlist = np.linspace(0, 5, 500) return objectives, pulse_options, tlist
def test_summarize_component_direct(): krotov.objectives.Objective.reset_symbol_counters() H = ['H0', ['H1', 2j]] res = krotov.objectives._summarize_component(H, 'op') expected = '[H0, [H1, 2j]]' assert res == expected with pytest.raises(ValueError): krotov.objectives._summarize_component(H, 'invalid') ket0 = qutip.ket('0') ket1 = qutip.ket('1') ket2 = copy.deepcopy(ket0) assert krotov.objectives._summarize_component(ket0, 'state') == '|Ψ₀(2)⟩' assert krotov.objectives._summarize_component(ket1, 'state') == '|Ψ₁(2)⟩' assert krotov.objectives._summarize_component(ket2, 'state') == '|Ψ₂(2)⟩' krotov.objectives.Objective.reset_symbol_counters() assert krotov.objectives._summarize_component(ket2, 'state') == '|Ψ₀(2)⟩' H = qutip.sigmaz() assert krotov.objectives._summarize_component(H, 'op') == 'H₀[2,2]' assert krotov.objectives._summarize_component(H, 'lindblad') == 'L₀[2,2]' krotov.objectives.Objective.reset_symbol_counters()
def frem_anneal(self, fsch, rsch, rinit, partition, disc=0.0001, history=False): """ Performs a numeric FREM anneal on H using QuTip. Inputs: --------- *fsch: list--forward annealing schedule [[t0, 0], ..., [tf, 1]] *rsch: list--reverse annealing schedule [[t0, 1], ..., [tf, 1]] *rinit: dict--initial state of HR *partition: dict--contains F-parition (HF), R-partition (HR), and Rqubits {'HF': {HF part}, 'HR': {HR part}, 'Rqubits': [list]} *disc: float--discretization between times in numeric anneal *history: bool--False final prob vector; True all intermediate states Outputs: --------- *final_state: numpy array--if history is True, then contains wave function amps with tensor product ordering else: contains sesolve output with all intermediate states """ # slim down rinit to only those states relevant for R partition Rstate = {q: rinit[q] for q in rinit if q in partition['Rqubits']} # add pause to f/r schedule if it is shorter than the other Tf = fsch[-1][0] Tr = rsch[-1][0] rdiff = Tr - Tf if rdiff != 0: if rdiff > 0: fsch.append([Tf + rdiff, 1]) else: rsch.append([Tr + (-1 * rdiff), 1]) # prepare Hamiltonian/ weight function list for QuTip se solver fsch = utils.make_numeric_schedule(fsch, disc) rsch = utils.make_numeric_schedule(rsch, disc) fsch_A, fsch_B = utils.time_interpolation(fsch, self.processor_data) rsch_A, rsch_B = utils.time_interpolation(rsch, self.processor_data) # list H for schrodinger equation solver f_Hx, f_Hz, r_Hx, r_Hz = utils.get_frem_Hs(self.qubits, partition) listH = [[f_Hx, fsch_A], [f_Hz, fsch_B], [r_Hx, rsch_A], [r_Hz, rsch_B]] # create the initial state vector for the FREM anneal statelist = [] xstate = (qt.ket('0') - qt.ket('1')).unit() for qubit in self.qubits: if qubit in Rstate: statelist.append(Rstate[qubit]) else: statelist.append(xstate) init_state = qt.tensor(*statelist) # run the numerical simulation and extract the final state results = qt.sesolve(listH, init_state, fsch[0]) # only output final result if history is set to False if history is False: state = utils.qto_to_npa(results.states[-1]) probs = (state.conj()*state).real return probs return results
def test_base_2_or_e(self): rho = qutip.ket2dm(qutip.ket("00")) sigma = rho + qutip.ket2dm(qutip.ket("01")) sigma = sigma.unit() assert (qutip.entropy_relative(rho, sigma) == pytest.approx(np.log(2))) assert (qutip.entropy_relative(rho, sigma, base=np.e) == pytest.approx(0.69314718)) assert qutip.entropy_relative(rho, sigma, base=2) == pytest.approx(1)
def test_gate_objectives_single_qubit_gate(): """Test initialization of objectives for simple single-qubit gate""" basis = [ket([0]), ket([1])] gate = sigmay() # = -i|0⟩⟨1| + i|1⟩⟨0| H = [sigmaz(), [sigmax(), lambda t, args: 1.0]] objectives = krotov.objectives.gate_objectives(basis, gate, H) assert objectives == [ krotov.Objective(initial_state=basis[0], target=(1j * basis[1]), H=H), krotov.Objective(initial_state=basis[1], target=(-1j * basis[0]), H=H), ]
def test_gate_objectives_shape_error(): """Test that trying to construct gate objectives with a gate whose shape mismatches the basis throws an exception""" basis = [qutip.ket([0]), qutip.ket([1])] gate = qutip.tensor(qutip.operators.sigmay(), qutip.identity(2)) H = [ qutip.operators.sigmaz(), [qutip.operators.sigmax(), lambda t, args: 1.0], ] with pytest.raises(ValueError) as exc_info: krotov.objectives.gate_objectives(basis, gate, H) assert "same dimension as the number of basis" in str(exc_info.value)
def numeric_anneal(self, sch, disc=0.0001, init_state=None, history=False): """ Performs in-house (QuTiP based) numeric anneal. Input -------------------- *usch: list -- [[t0, s0], [t1, s1], ..., [tn, sn]] *disc (0.01): float -- discretization used between times *init_state (None): dict -- maps qubits to up (1) or down (0) None means calculate here as gs of Hx (for forward) *history: bool, True means return all intermediate states False returns only final probability vector Output -------------------- if history == None: outputs-->(energy, state) energy: float, energy of final state reached state: numpy array of wave-function amplitudes else: outputs-->QuTip result """ # create numeric anneal schedule sch = utils.make_numeric_schedule(sch, disc) # interpolate A and B according to schedule sch_A, sch_B = utils.time_interpolation(sch, self.processor_data) # list H for schrodinger equation solver listH = [[self.num_Hx, sch_A], [self.num_Hz, sch_B]] # calculate ground-state at H(t=0) if init_state not specified if init_state is None: xstate = (qt.ket('0') - qt.ket('1')).unit() statelist = [xstate for i in range(len(self.qubits))] init_state = qt.tensor(*statelist) else: statelist = [] for qubit in self.qubits: if qubit in init_state: statelist.append(init_state[qubit]) else: raise ValueError("init_state does not specify state of qubit {}".format(qubit)) init_state = qt.tensor(*statelist) # peform a numerical anneal on H (sch[0] is list of discrete times) results = qt.sesolve(listH, init_state, sch[0]) # only output final result if history set to False if history is False: state = utils.qto_to_npa(results.states[-1]) probs = (state.conj()*state).real return probs return results
def test_rho_and_sigma_have_different_shape_and_dims(self): # test different shape and dims rho = qutip.ket("00") sigma = qutip.ket("0") with pytest.raises(ValueError) as exc: qutip.entropy_relative(rho, sigma) assert str(exc.value) == "Inputs must have the same shape and dims." # test same shape, difference dims rho = qutip.basis([2, 3], [0, 0]) sigma = qutip.basis([3, 2], [0, 0]) with pytest.raises(ValueError) as exc: qutip.entropy_relative(rho, sigma) assert str(exc.value) == "Inputs must have the same shape and dims."
def seepage_from_superoperator(U): """ Calculates seepage by summing over all in and output states outside the computational subspace. L1 = 1- 1/2^{number non-computational states} sum_i sum_j abs(|<phi_i|U|phi_j>|)**2 """ if U.type=='oper': sump = 0 for i_list in [[0,2],[1,2],[2,0],[2,1],[2,2]]: for j_list in [[0,2],[1,2],[2,0],[2,1],[2,2]]: bra_i = qtp.tensor(qtp.ket([i_list[0]], dim=[3]), qtp.ket([i_list[1]], dim=[3])).dag() ket_j = qtp.tensor(qtp.ket([j_list[0]], dim=[3]), qtp.ket([j_list[1]], dim=[3])) p = np.abs((bra_i*U*ket_j).data[0, 0])**2 # could be sped up sump += p sump /= 5 # divide by number of non-computational states L1 = 1-sump return L1 elif U.type=='super': sump = 0 for i_list in [[0,2],[1,2],[2,0],[2,1],[2,2]]: for j_list in [[0,2],[1,2],[2,0],[2,1],[2,2]]: ket_i = qtp.tensor(qtp.ket([i_list[0]], dim=[3]), qtp.ket([i_list[1]], dim=[3])) rho_i=qtp.operator_to_vector(qtp.ket2dm(ket_i)) ket_j = qtp.tensor(qtp.ket([j_list[0]], dim=[3]), qtp.ket([j_list[1]], dim=[3])) rho_j=qtp.operator_to_vector(qtp.ket2dm(ket_j)) p = (rho_i.dag()*U*rho_j).data[0, 0] sump += p sump /= 5 # divide by number of non-computational states sump=np.real(sump) L1 = 1-sump return L1
def calc_population_02_state(U): """ Calculates the population that escapes from |11> to |02>. Formula for unitary propagator: population = |<02|U|11>|^2 and similarly for the superoperator case. The function assumes that the computational subspace (:= the 4 energy levels chosen as the two qubits) is given by the standard basis |0> /otimes |0>, |0> /otimes |1>, |1> /otimes |0>, |1> /otimes |1>. If this is not the case, one need to change the basis to that one, before calling this function. """ if U.type == 'oper': sump = 0 for i_list in [[0, 2]]: for j_list in [[1, 1]]: bra_i = qtp.tensor(qtp.ket([i_list[0]], dim=[3]), qtp.ket([i_list[1]], dim=[3])).dag() ket_j = qtp.tensor(qtp.ket([j_list[0]], dim=[3]), qtp.ket([j_list[1]], dim=[3])) p = np.abs((bra_i * U * ket_j).data[0, 0])**2 sump += p return np.real(sump) elif U.type == 'super': sump = 0 for i_list in [[0, 2]]: for j_list in [[1, 1]]: ket_i = qtp.tensor(qtp.ket([i_list[0]], dim=[3]), qtp.ket([i_list[1]], dim=[3])) rho_i = qtp.operator_to_vector(qtp.ket2dm(ket_i)) ket_j = qtp.tensor(qtp.ket([j_list[0]], dim=[3]), qtp.ket([j_list[1]], dim=[3])) rho_j = qtp.operator_to_vector(qtp.ket2dm(ket_j)) p = (rho_i.dag() * U * rho_j).data[0, 0] sump += p return np.real(sump)
def numpy_control_system(): """Optimization system for State-to-State Transfer This is the same as in 01_example_simple_state_to_state.ipynb, but using a numpy array as the control. """ tlist = np.linspace(0, 5, 500) def hamiltonian(omega=1.0, ampl0=0.2): """Two-level-system Hamiltonian Args: omega (float): energy separation of the qubit levels ampl0 (float): constant amplitude of the driving field """ H0 = -0.5 * omega * qutip.operators.sigmaz() H1 = qutip.operators.sigmax() def guess_control(t, args): return ampl0 * krotov.shapes.flattop( t, t_start=0, t_stop=5, t_rise=0.3, func="blackman") guess_array = np.array([guess_control(t, []) for t in tlist]) # return [H0, [H1, guess_control]] return [H0, [H1, guess_array]] H = hamiltonian() objectives = [ krotov.Objective( initial_state=qutip.ket("0"), target=qutip.ket("1"), H=H, ) ] def S(t): """Shape function for the field update""" return krotov.shapes.flattop(t, t_start=0, t_stop=5, t_rise=0.3, t_fall=0.3, func='blackman') # pulse_options = {H[1][1]: dict(lambda_a=5, update_shape=S)} pulse_options = {id(H[1][1]): dict(lambda_a=5, update_shape=S)} return tlist, objectives, pulse_options
def test_density_matrices_with_non_real_eigenvalues(self): rho = qutip.ket2dm(qutip.ket("00")) sigma = qutip.ket2dm(qutip.ket("01")) with pytest.raises(ValueError) as exc: qutip.entropy_relative(rho + 1j, sigma) assert str(exc.value) == "Input rho has non-real eigenvalues." with pytest.raises(ValueError) as exc: qutip.entropy_relative(rho - 1j, sigma) assert str(exc.value) == "Input rho has non-real eigenvalues." with pytest.raises(ValueError) as exc: qutip.entropy_relative(rho, sigma + 1j) assert str(exc.value) == "Input sigma has non-real eigenvalues." with pytest.raises(ValueError) as exc: qutip.entropy_relative(rho, sigma - 1j) assert str(exc.value) == "Input sigma has non-real eigenvalues."
def objective_liouville(): a1 = np.random.random(100) + 1j * np.random.random(100) a2 = np.random.random(100) + 1j * np.random.random(100) H = [ tensor(sigmaz(), identity(2)) + tensor(identity(2), sigmaz()), [tensor(sigmax(), identity(2)), a1], [tensor(identity(2), sigmax()), a2], ] L = krotov.objectives.liouvillian(H, c_ops=[]) ket00 = ket((0, 0)) ket11 = ket((1, 1)) obj = krotov.Objective( initial_state=qutip.ket2dm(ket00), target=qutip.ket2dm(ket11), H=L ) return obj
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 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_gate_objectives_5states(two_qubit_liouvillian): """Test the initialization of the "d + 1" objectives""" L = two_qubit_liouvillian basis = [qutip.ket(n) for n in [(0, 0), (0, 1), (1, 0), (1, 1)]] CNOT = qutip_gates.cnot() objectives = krotov.objectives.gate_objectives( basis, CNOT, L, liouville_states_set='d+1' ) assert len(objectives) == 5 rho_1 = basis[0] * basis[0].dag() rho_2 = basis[1] * basis[1].dag() rho_3 = basis[2] * basis[2].dag() rho_4 = basis[3] * basis[3].dag() rho_5 = qutip.Qobj(np.full((4, 4), 1 / 4), dims=[[2, 2], [2, 2]]) tgt_1 = CNOT * rho_1 * CNOT.dag() tgt_2 = CNOT * rho_2 * CNOT.dag() tgt_3 = CNOT * rho_3 * CNOT.dag() tgt_4 = CNOT * rho_4 * CNOT.dag() tgt_5 = CNOT * rho_5 * CNOT.dag() assert (objectives[0].initial_state - rho_1).norm('max') < 1e-14 assert (objectives[1].initial_state - rho_2).norm('max') < 1e-14 assert (objectives[2].initial_state - rho_3).norm('max') < 1e-14 assert (objectives[3].initial_state - rho_4).norm('max') < 1e-14 assert (objectives[4].initial_state - rho_5).norm('max') < 1e-14 assert (objectives[0].target - tgt_1).norm('max') < 1e-14 assert (objectives[1].target - tgt_2).norm('max') < 1e-14 assert (objectives[2].target - tgt_3).norm('max') < 1e-14 assert (objectives[3].target - tgt_4).norm('max') < 1e-14 assert (objectives[4].target - tgt_5).norm('max') < 1e-14
def test_derivative_wrt_pulse_multiple_terms(tls_control_system): """Test the calculation of μ if the same control appears more than once""" objectives, pulses, pulses_mapping = tls_control_system # distinction between controls and pulses doesn't matter here, we're only # considering linear controls and don't plug in any time_index i_objective = 0 mu = krotov.mu.derivative_wrt_pulse( objectives, i_objective, pulses, pulses_mapping, i_pulse=0, time_index=0, ) # 0.5 * (σ₊ + σ₋) = σₓ for state in (ket('0'), ket('1')): assert (mu(state) - (sigmax())(state)).norm('max') == 0 assert (mu(state)).dims == state.dims
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 seepage_from_unitary(U): """ Calculates leakage by summing over all in and output states in the computational subspace. L1 = 1- sum_i sum_j abs(|<phi_i|U|phi_j>|)**2 """ sump = 0 for i in range(2): for j in range(2): bra_i = qtp.tensor(qtp.ket([i], dim=[2]), qtp.ket([2], dim=[3])).dag() ket_j = qtp.tensor(qtp.ket([j], dim=[2]), qtp.ket([2], dim=[3])) p = np.abs((bra_i*U*ket_j).data[0, 0])**2 sump += p sump /= 2 # divide by dimension of comp subspace L1 = 1-sump return L1
def objective_with_c_ops(): u1 = lambda t, args: 1.0 u2 = lambda t, args: 1.0 a1 = np.random.random(100) + 1j * np.random.random(100) a2 = np.random.random(100) + 1j * np.random.random(100) H = [ tensor(sigmaz(), identity(2)) + tensor(identity(2), sigmaz()), [tensor(sigmax(), identity(2)), u1], [tensor(identity(2), sigmax()), u2], ] C1 = [[tensor(identity(2), sigmap()), a1]] C2 = [[tensor(sigmap(), identity(2)), a2]] ket00 = ket((0, 0)) ket11 = ket((1, 1)) obj = krotov.Objective( initial_state=ket00, target=ket11, H=H, c_ops=[C1, C2] ) return obj
def tls_control_system_tdcops(tls_control_system): """Control system with time-dependent collapse operators""" objectives, controls, _ = tls_control_system c_op = [[0.1 * sigmap(), controls[0]]] c_ops = [c_op] H1 = objectives[0].H H2 = objectives[1].H objectives = [ krotov.Objective( initial_state=ket('0'), target=ket('1'), H=H1, c_ops=c_ops ), krotov.Objective( initial_state=ket('0'), target=ket('1'), H=H2, c_ops=c_ops ), ] controls_mapping = krotov.conversions.extract_controls_mapping( objectives, controls ) return objectives, controls, controls_mapping
def test_mapped_basis_preserves_hs_structure(): """Test that mapped_basis preserves the hilbert space structure of the input basis.""" basis = [ket(nums) for nums in [(0, 0), (0, 1), (1, 0), (1, 1)]] states = krotov.functionals.mapped_basis(qutip_gates.cnot(), basis) for state in states: assert isinstance(state, qutip.Qobj) assert state.dims == basis[0].dims assert state.shape == basis[0].shape assert state.type == basis[0].type
def tls_control_system(): """Non-trivial control system defined on a TLS""" eps1 = lambda t, args: 0.5 eps2 = lambda t, args: 1 H1 = [0.5 * sigmaz(), [sigmap(), eps1], [sigmam(), eps1]] H2 = [0.5 * sigmaz(), [sigmaz(), eps2]] c_ops = [0.1 * sigmap()] objectives = [ krotov.Objective( initial_state=ket('0'), target=ket('1'), H=H1, c_ops=c_ops ), krotov.Objective( initial_state=ket('0'), target=ket('1'), H=H2, c_ops=c_ops ), ] controls = [eps1, eps2] controls_mapping = krotov.conversions.extract_controls_mapping( objectives, controls ) return objectives, controls, controls_mapping
def initialise_TLS(init_sys, init_RC, states, w0, T_ph, H_RC=np.ones((2, 2))): # allows specific state TLS-RC states to be constructed easily G = qt.ket([0]) E = qt.ket([1]) ground_list, excited_list = ground_and_excited_states(states) concat_list = [ground_list, excited_list] N = states[1].shape[0] / 2 if init_sys == 'coherence': rho_left = (states[concat_list[0][init_RC]] + states[concat_list[1][init_RC]]) / np.sqrt(2) rho_right = rho_left.dag() init_rho = rho_left * rho_right elif type(init_sys) == tuple: #coherence state if type(init_RC) == tuple: # take in a 2-tuple to initialise in coherence state. print((init_sys, init_RC)) rho_left = states[concat_list[init_sys[0]][init_RC[0]]] rho_right = states[concat_list[init_sys[1]][init_RC[1]]].dag() init_rho = rho_left * rho_right else: raise ValueError elif init_sys == 0: # population state init_rho = states[ground_list[init_RC]] * states[ ground_list[init_RC]].dag() elif init_sys == 1: init_rho = states[excited_list[init_RC]] * states[ excited_list[init_RC]].dag() elif init_sys == 2: Therm = qt.thermal_dm(N, Occupation(w0, T_ph)) init_rho = qt.tensor(E * E.dag(), Therm) # if in neither ground or excited # for the minute, do nothing. This'll be fixed below. else: # finally, if not in either G or E, initialise as thermal num = (-H_RC * beta_f(T_ph)).expm() init_rho = num / num.tr() return init_rho
def leakage_from_superoperator(U): if U.type == 'oper': """ Calculates leakage by summing over all in and output states in the computational subspace. L1 = 1- 1/2^{number computational qubits} sum_i sum_j abs(|<phi_i|U|phi_j>|)**2 The function assumes that the computational subspace (:= the 4 energy levels chosen as the two qubits) is given by the standard basis |0> /otimes |0>, |0> /otimes |1>, |1> /otimes |0>, |1> /otimes |1>. If this is not the case, one need to change the basis to that one, before calling this function. """ sump = 0 for i in range(4): for j in range(4): bra_i = qtp.tensor(qtp.ket([i // 2], dim=[3]), qtp.ket([i % 2], dim=[3])).dag() ket_j = qtp.tensor(qtp.ket([j // 2], dim=[3]), qtp.ket([j % 2], dim=[3])) p = np.abs((bra_i * U * ket_j).data[0, 0])**2 sump += p sump /= 4 # divide by dimension of comp subspace L1 = 1 - sump return L1 elif U.type == 'super': """ Calculates leakage by summing over all in and output states in the computational subspace. L1 = 1- 1/2^{number computational qubits} sum_i sum_j Tr(rho_{x'y'}C_U(rho_{xy})) where C_U is U in the channel representation The function assumes that the computational subspace (:= the 4 energy levels chosen as the two qubits) is given by the standard basis |0> /otimes |0>, |0> /otimes |1>, |1> /otimes |0>, |1> /otimes |1>. If this is not the case, one need to change the basis to that one, before calling this function. """ sump = 0 for i in range(4): for j in range(4): ket_i = qtp.tensor(qtp.ket([i // 2], dim=[3]), qtp.ket([i % 2], dim=[3])) #notice it's a ket rho_i = qtp.operator_to_vector(qtp.ket2dm(ket_i)) ket_j = qtp.tensor(qtp.ket([j // 2], dim=[3]), qtp.ket([j % 2], dim=[3])) rho_j = qtp.operator_to_vector(qtp.ket2dm(ket_j)) p = (rho_i.dag() * U * rho_j).data[0, 0] sump += p sump /= 4 # divide by dimension of comp subspace sump = np.real(sump) L1 = 1 - sump return L1
def genstate(s): """helper function to obtain the correct initialization""" newstr = s.replace("+","0") newstr = newstr.replace("-","1") print(newstr) state = qt.ket(newstr) if s[0] == "+" or s[0]=="-": operator=qt.hadamard_transform() else: operator=qt.identity(2) for i in range(1,len(s),1): if s[i] == "+" or s[i]=="-": #apply hadamard operator = qt.tensor([operator,qt.hadamard_transform()]) else: operator = qt.tensor([operator,qt.identity(2)]) return operator * state
def test_ket_type(): "State CSR Type: ket" st = ket('10') assert_equal(isspmatrix_csr(st.data), True)
qc = qutip.QubitCircuit(n) if n == 1: qc.add_gate("SNOT", targets=[0]) else: for i in range(n): qc.add_gate("SNOT", targets=[i]) for j in range(2, n - i + 1): qc.add_gate(r"CPHASE", targets=[i], controls=[i + j - 1], arg_label=r"{\pi/2^{%d}}" % (j - 1), arg_value=numpy.pi / (2 ** (j - 1))) if swapping is True: for i in range(n // 2): qc.add_gate(r"SWAP", targets=[i, n - 1 - i]) return qc psi = qutip.ket('0' * n) # start timing start_time = timeit.default_timer() qc0 = qft_gate_sequence(n, True) for gate in qc0.propagators(): psi = gate * psi elapsed = timeit.default_timer() - start_time # end timing print("{0}, {1}, {2}".format(num_cores, n, elapsed))