def test_sesolve_bad_H(): H = sigmaz(), psi0 = basis(2, 0) tlist = np.linspace(0, 20, 200) with pytest.raises(TypeError) as exc: sesolve(H, psi0, tlist=tlist, e_ops=[qeye(3)]) assert str(exc.value).startswith("Invalid H:")
def compare_evolution(self, H, psi0, tlist, normalize=False, td_args={}, tol=5e-5): """ Compare integrated evolution of unitary operator with state evo """ U0 = qeye(2) options = Options(store_states=True, normalize_output=normalize) out_s = sesolve(H, psi0, tlist, [sigmax(), sigmay(), sigmaz()], options=options, args=td_args) xs, ys, zs = out_s.expect[0], out_s.expect[1], out_s.expect[2] out_u = sesolve(H, U0, tlist, options=options, args=td_args) xu = [expect(sigmax(), U * psi0) for U in out_u.states] yu = [expect(sigmay(), U * psi0) for U in out_u.states] zu = [expect(sigmaz(), U * psi0) for U in out_u.states] if normalize: msg_ext = ". (Normalized)" else: msg_ext = ". (Not normalized)" assert_(max(abs(xs - xu)) < tol, msg="expect X not matching" + msg_ext) assert_(max(abs(ys - yu)) < tol, msg="expect Y not matching" + msg_ext) assert_(max(abs(zs - zu)) < tol, msg="expect Z not matching" + msg_ext)
def test_07_1_dynamic_args(self): "sesolve: state feedback" tol = 1e-3 def f(t, args): return np.abs(args["state_vec"][1]) H = [qeye(2), [destroy(2) + create(2), f]] res = sesolve(H, basis(2, 1), tlist=np.linspace(0, 10, 11), e_ops=[num(2)], args={"state_vec": basis(2, 1)}) assert_(max(abs(res.expect[0][5:])) < tol, msg="evolution with feedback not proceding as expected") def f(t, args): return np.sqrt(args["expect_op_0"]) H = [qeye(2), [destroy(2) + create(2), f]] res = sesolve(H, basis(2, 1), tlist=np.linspace(0, 10, 11), e_ops=[num(2)], args={"expect_op_0": num(2)}) assert_(max(abs(res.expect[0][5:])) < tol, msg="evolution with feedback not proceding as expected")
def check_evolution(self, H, delta, psi0, tlist, analytic_func, U0=None, td_args={}, tol=5e-3): """ Compare integrated evolution with analytical result If U0 is not None then operator evo is checked Otherwise state evo """ if U0 is None: output = sesolve(H, psi0, tlist, [sigmax(), sigmay(), sigmaz()], args=td_args) sx, sy, sz = output.expect[0], output.expect[1], output.expect[2] else: output = sesolve(H, U0, tlist, args=td_args) sx = [expect(sigmax(), U*psi0) for U in output.states] sy = [expect(sigmay(), U*psi0) for U in output.states] sz = [expect(sigmaz(), U*psi0) for U in output.states] sx_analytic = np.zeros(np.shape(tlist)) sy_analytic = np.array([-np.sin(delta*analytic_func(t, td_args)) for t in tlist]) sz_analytic = np.array([np.cos(delta*analytic_func(t, td_args)) for t in tlist]) assert_(max(abs(sx - sx_analytic)) < tol, msg="expect X not matching analytic") assert_(max(abs(sy - sy_analytic)) < tol, msg="expect Y not matching analytic") assert_(max(abs(sz - sz_analytic)) < tol, msg="expect Z not matching analytic")
def monitor(self, init_state: Qobj, amps: List[Callable], times: Sequence[float], observables: List[Qobj] = None) -> Union[List[Qobj], List[Sequence[complex]]]: """ Monitor the system at a range of points in time. This method allows one to look at the system continuously during a evolution. More specifically, the expectation value of the specified observables are returned at the specified points in time. If no observables are specified, the full ket vectors of the state at the specified points of time are returned. Parameters ---------- init_state : Qobj The initial state. amps : list of complex numbers The control amplitudes. Must be a list of callables (which must return complex number) whose length is exactly the number of control operators. times : array_like The points in time where the monitoring are done. observables : list of Qobj or None The observables for which the expectation values are calculated. If None, then the ket vectors are returned instead of some expectation values. Returns ------- list of floats Notes ----- The state is not collapsed during monitoring, only the expectation values are evaluated and the state is not affected (which is of course impossible in an actual experiment). That is why this method is not called `measure` or `observe` to avoid confusion. """ H_td = [] H_td.append([self._ctrl_ops[0], lambda t, *_: amps[0](t)]) H_td.append([self._ctrl_ops[0].dag(), lambda t, *_: np.conj(amps[0](t))]) H_td.append([self._ctrl_ops[1], lambda t, *_: amps[1](t)]) H_td.append([self._ctrl_ops[1].dag(), lambda t, *_: np.conj(amps[1](t))]) H_td.append([self._ctrl_ops[2], lambda t, *_: amps[2](t)]) H_td.append([self._ctrl_ops[2].dag(), lambda t, *_: np.conj(amps[2](t))]) if observables is None: return sesolve(H_td, init_state, times, []).states else: return sesolve(H_td, init_state, times, observables).expect
def pulse(initial_state, duration, rabi, error = False): t0 = omega_plus + omega_minus #transition frequency H0 = ((1/2) * t0 * sigma_z) H_laser = rabi * sigma_x if error == False: H_final = [H0, [H_laser, H_laser_coeff]] if error == True: H1 = (1/2) * sigma_z H_final = [H0, [H1, pink_noise_coeff], [H_laser, H_laser_coeff]] optns = qt.Options() optns.nsteps = 1000 states = qt.sesolve(H_final, initial_state, np.linspace(0,duration,100), options = optns).states final_state = states[-1] return(final_state, states)
def time_evolution(psi, H, t): """ Schrodinger evolution of a state psi under a Hamiltonian H, during a time t. Parameters ---------- psi: qutip.Qobj() quantum state under evolution H: qutip.Qobj() Hamiltonian t: scalar time during which H is applied to psi Returns ------- psi2 : qutip.Qobj() final state """ if t == 0: return psi else: tlist = np.linspace(0, t, 20) psi2 = qutip.sesolve(H, psi, tlist).states[-1] return psi2
def nf_anneal(self, schedule): """ Performs a numeric forward anneal on H using QuTip. inputs: --------- schedule - a numeric anneal schedule defined with anneal length outputs: --------- probs - probability of each output state as a list ordered in canconically w.r.t. tensor product """ times, svals = schedule # create a numeric representation of H ABfuncs = time_interpolation(schedule, self.processordata) numericH = get_numeric_H(self) A = ABfuncs['A(t)'] B = ABfuncs['B(t)'] HX = numericH['HX'] HZ = numericH['HZ'] # "Analytic" or function H(t) analH = lambda t: A(t) * HX + B(t) * HZ # Define list_H for QuTiP listH = [[HX, A], [HZ, B]] # perform a numerical forward anneal on H results = qt.sesolve(listH, gs_calculator(analH(0)), times) probs = np.array([ abs(results.states[-1][i].flatten()[0])**2 for i in range(self.Hsize) ]) return probs
def solve_sdeq(self, tlist, e_ops=None, sched_prob=None, sched_driver=None): annealing_time = tlist[-1] evals_driver, ekets_driver = self.H_driver.eigenstates() psi0 = ekets_driver[np.argmin(evals_driver)] if e_ops is None: e_ops = [ket2dm(ek) for ek in self.ekets_prob] Hlist = self._gen_hamil_list(sched_prob, sched_driver) result = sesolve(Hlist, psi0, tlist, e_ops=e_ops, args={'annealing_time': annealing_time}) expects = np.transpose(result.expect) arr = np.array(list(zip(tlist, expects)), dtype=[('time', float), ('expect', (float, len(expects[0])))]) return arr.view(np.recarray)
def f(mol_list, run_qutip=True): tentative_mpo = Mpo(mol_list) init_mps = (Mpo.onsite(mol_list, r"a^\dagger", mol_idx_set={0}) @ Mps.gs( mol_list, False)).expand_bond_dimension(hint_mpo=tentative_mpo) init_mpdm = MpDm.from_mps(init_mps).expand_bond_dimension( hint_mpo=tentative_mpo) e = init_mps.expectation(tentative_mpo) mpo = Mpo(mol_list, offset=Quantity(e)) if run_qutip: # calculate result in ZT. FT result is exactly the same TIME_LIMIT = 10 QUTIP_STEP = 0.01 N_POINTS = TIME_LIMIT / QUTIP_STEP + 1 qutip_time_series = np.linspace(0, TIME_LIMIT, N_POINTS) init = qutip.Qobj(init_mps.full_wfn(), [qutip_h.dims[0], [1] * len(qutip_h.dims[0])]) # the result is not exact and the error scale is approximately 1e-5 res = qutip.sesolve(qutip_h - e, init, qutip_time_series, e_ops=[c.dag() * c for c in qutip_clist]) qutip_expectations = np.array(res.expect).T return qutip_expectations, QUTIP_STEP, init_mps, init_mpdm, mpo else: return init_mps, init_mpdm, mpo
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 solve(self): # noinspection PyTypeChecker self.solve_result = sesolve( self.get_hamiltonian(), self.psi_0, self.t_list, # e_ops=get_exp_list(self.N)[2], options=Options(store_states=True, nsteps=100000), # ntraj=2 )
def observe(self, init_state, param_vec, times, e_ops=[]): amps_func = self.get_amps_func(param_vec) H = [] for i in range(6): H.append([self._ctrl_hamils[i], amps_func[i]]) result = sesolve(H, init_state, times, e_ops) if e_ops == []: return result.states else: return result.expect
def imperfect_state(coeff, error=0.2, H_rand=False, with_phase=False): s = state(*coeff) if H_rand == False: H_rand = q.rand_dm_ginibre(len(coeff)) H_rand = H_rand / H_rand.norm() H_rand = q.Qobj( lin.block_diag(H_rand[:], np.zeros((N - len(coeff), N - len(coeff))))) s_e = q.sesolve(H_rand, s, [0., error]).states[1] if with_phase: return s_e else: return list(np.ndarray.flatten(np.abs(s_e[:len(coeff)])**2))
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 pattern_diff(t, args, N_, prob_no): m_state_t = q.sesolve(-H, m_state, [0., t]).states[1] P_mixed = q.expect(system, m_state_t) probs = np.array(args[-prob_no:]) P_list = np.empty(int(len(args[:-prob_no]) / (N_ - 1))) for i in range(int(len(args[:-prob_no]) / (N_ - 1))): state_coeffs = [0, *args[i * (N_ - 1):(i + 1) * (N_ - 1)]] state_coeffs = np.roll(state_coeffs, i) pattern_state = q.ket2dm(state(*state_coeffs)) P_list[i] = q.expect(pattern_state, m_state_t) return np.abs(P_mixed - np.sum(probs * P_list))
def simple_check_states_e_ops( self, H, psi0, tlist, tol=1e-5, tol2=1e-4, krylov_dim=25, square_hamiltonian=True, ): """ Compare integrated evolution with sesolve and exactsolve result. """ options = Options(store_states=True) e_ops = [ jmat((H.shape[0] - 1) / 2.0, "x"), jmat((H.shape[0] - 1) / 2.0, "y"), jmat((H.shape[0] - 1) / 2.0, "z"), ] if not square_hamiltonian: _e_ops = [] for op in e_ops: op2 = op.copy() op2.dims = H.dims _e_ops.append(op2) e_ops = _e_ops output = krylovsolve( H, psi0, tlist, krylov_dim, e_ops=e_ops, options=options ) output_ss = sesolve(H, psi0, tlist, e_ops=e_ops, options=options) output_exact = exactsolve(H, psi0, tlist) assert_err_states_less_than_tol(res_1=output, res_2=output_ss, tol=tol) assert_err_states_less_than_tol(res_1=output, res_2=output_exact, tol=tol) # for the operators, test against exactsolve for accuracy for i in range(len(e_ops)): output_exact.expect = expect_value(e_ops[i], output_exact, tlist) assert_err_expect_less_than_tol(exp_1=output.expect[i], exp_2=output_exact.expect, tol=tol)
def schroedinger_sequence( model, psi0, durations, fields, dt=None, e_ops=None, args=None, options=None, progress_bar=None, _safe_mode=True, ): if options is None: options = qt.Options(store_final_state=True) else: options.store_final_state = True H_int = model.hamiltonian_int() t0 = 0 expect = [np.array([qt.expect(e_ops, psi0)])] times = [np.array([t0])] for duration, field in zip(durations, fields): t1 = t0 + duration if dt is None: time_interval = [t0, t1] else: time_interval = np.arange(t0, t1, dt) if time_interval[-1] != t1: time_interval = np.append(time_interval, t1) t0 = t1 H_ext = model.hamiltonian_field(*field) result = qt.sesolve( H_int + H_ext, psi0, time_interval, e_ops=e_ops, args=args, options=options, progress_bar=progress_bar, _safe_mode=_safe_mode, ) psi0 = result.final_state expect.append(np.array(result.expect)[:, 1:]) times.append(time_interval[1:]) return np.concatenate(times), np.concatenate(expect, axis=1)
def run(self, initial_state=None, progress_bar=None, **options): """Simulate the sequence using QuTiP's solvers. Keyword Args: initial_state (array): The initial quantum state of the evolution. Will be transformed into a ``qutip.Qobj`` instance. progress_bar (bool): If True, the progress bar of QuTiP's ``qutip.sesolve()`` will be shown. Other Parameters: options: Additional simulation settings. These correspond to the keyword arguments of ``qutip.solver.Options`` for the ``qutip.sesolve()`` method. Returns: SimulationResults: Object containing the time evolution results. """ if initial_state is not None: if isinstance(initial_state, qutip.Qobj): if initial_state.shape != (self.dim**self._size, 1): raise ValueError("Incompatible shape of initial_state") self._initial_state = initial_state else: if initial_state.shape != (self.dim**self._size,): raise ValueError("Incompatible shape of initial_state") self._initial_state = qutip.Qobj(initial_state) else: # by default, initial state is "ground" state of g-r basis. all_ground = [self.basis['g'] for _ in range(self._size)] self._initial_state = qutip.tensor(all_ground) result = qutip.sesolve(self._hamiltonian, self._initial_state, self._times, progress_bar=progress_bar, options=qutip.Options(max_step=5, **options) ) if hasattr(self._seq, '_measurement'): meas_basis = self._seq._measurement else: meas_basis = None return SimulationResults( result.states, self.dim, self._size, self.basis_name, meas_basis=meas_basis )
def time_evol(self, psi0, psif, t0 = 0, T = 10, dt = 1e-2, plot=True): ''' Simulate the unitary time evolution for a given Hamiltonian over a certain timespan. Then return output data and plot if desired. Arguments: H - The Hamiltonian to be applied in the time evolution unitary. psi0 - Initial state of system. psif - Final (desired) state of system against which to check fidelity t0 - Start time of simulation T - End time of simulation dt - Time increment display_progress - Choose whether to show progress of simulation whilst it runs. plot - Boolean to set whether a graph is plotted. ''' times = np.arange(t0,T,dt) optns = qt.Options() optns.nsteps = 10000 results = qt.sesolve(self.__H, psi0, times, options = optns,progress_bar=True) states = results.states overlap = [] for i in states: ov = i.overlap(psif) overlap.append(ov*np.conj(ov)) if plot==True: plt.plot(times, overlap) plt.xlabel('Time/(hbar*nu)') plt.ylabel('|<psi(t)|D>|^2') # plt.ylim([0.96,1.04]) plt.show() return(overlap)
def check_e_ops_callable( self, H, psi0, tlist, dim, krylov_dim=35, tol=1e-5, square_hamiltonian=True, ): "Check input possibilities when e_ops=callable" def e_ops(t, psi): return expect(num(dim), psi) if not square_hamiltonian: H.dims = [[H.shape[0]], [H.shape[0]]] psi0.dims = [[H.shape[0]], [1]] krylov_outputs = krylovsolve(H, psi0, tlist, krylov_dim, e_ops=e_ops) exact_output = exactsolve(H, psi0, tlist) exact_output.expect = expect_value(e_ops=e_ops, res_1=exact_output, tlist=tlist) try: sesolve_outputs = sesolve(H, psi0, tlist, e_ops=e_ops) except IndexError: # if tlist=[], sesolve breaks but krylov doesn't pass if len(tlist) > 1: assert len(krylov_outputs.expect) == len( sesolve_outputs.expect ), "shape of outputs between krylov and sesolve differs" assert_err_expect_less_than_tol(exp_1=krylov_outputs.expect, exp_2=exact_output.expect, tol=tol) elif len(tlist) == 1: assert ( np.abs(krylov_outputs.expect[0] - sesolve_outputs.expect[0]) <= 1e-7 ), "krylov and sesolve outputs differ for len(tlist)=1" else: assert krylov_outputs.states == []
def time_evol(H, psi0, psif, t0, T, dt, display_progress=True, plot=True): ''' Simulate the unitary time evolution for a given Hamiltonian over a certain timespan. Then return output data and plot if desired. Arguments: H - The Hamiltonian to be applied in the time evolution unitary. psi0 - Initial state of system. psif - Final (desired) state of system against which to check fidelity t0 - Start time of simulation T - End time of simulation dt - Time increment display_progress - Choose whether to show progress of simulation whilst it runs. plot - Boolean to set whether a graph is plotted. ''' times = np.arange(t0, T, dt) optns = qt.Options() optns.nsteps = 10000 results = qt.sesolve(H, psi0, times, progress_bar=display_progress, options=optns) states = results.states fidelities = [] for i in states: fidelities.append(qt.fidelity(i, psif)) if plot == True: plt.plot(times, fidelities) plt.show() # print(optns) return (fidelities)
def QuantumAnnealing(Hi, Hf, psii, As, Bs, tlist): """ Return the system states along the interpolation for a given parametrization and a time list Parameters: Hi : Initial Hamiltonian (qutip object) Hf : Final Hamiltonian (qutip object) psii : Initial State (qutip object) As : Parametrization function (python function) Bs : Parametrization function (python function) tlist : time list (np.array) Return: system state in each interpolation time interval """ Ht = [[Hi, As], [Hf, Bs]] args = {'t_max': tlist[-1]} result = qt.sesolve(H=Ht, psi0=psii, tlist=tlist, args=args) return result.states
def evolution_psi_microwave(system, H_drive, initial_state, t_points=None, **kwargs): """ Calculates the evolution of a specific starting state for the gate activated by a microwave drive. Parameters ---------- system : :class:`coupobj.CoupledObjects` or similar An object of a quantum system supporting system.H() method for the Hamiltonian. H_drive : :class:`qutip.Qobj` The time-independent part of the driving term. Example: f * (a + a.dag()) or f * qubit.n() Normalization: see `H_drive_coeff_gate` function. initial_state : :class:`qutip.Qobj` Initial state of the system. t_points : *array* of float (optional) Times at which the evolution operator is returned. If None, it is generated from `kwargs['T_gate']`. **kwargs: Contains gate parameters such as pulse shape and gate time. Returns ------- *array* of :class:`qutip.Qobj` The evolving state at time(s) defined in `t_points`. """ if t_points is None: T_gate = kwargs['T_gate'] t_points = np.linspace(0, T_gate, 2 * int(T_gate) + 1) H_nodrive = system.H() H = [2 * np.pi * H_nodrive, [H_drive, H_drive_coeff_gate]] result = qt.sesolve(H, initial_state, t_points, [], args=kwargs, options=qt.Options(nsteps=25000)) return result.states
def schroedinger( self, model, psi0, dt=None, e_ops=None, options=None, progress_bar=None, _safe_mode=True, gaussian=False, ): if options is None: options = qt.Options(store_final_state=True) else: options.store_final_state = True H_int = model.hamiltonian_int() t0 = 0 expect = [np.array([qt.expect(e_ops, psi0)])] times = [np.array([t0])] for duration, field in zip(self.durations, self.fields): time_interval = self.get_time_interval(t0, duration, dt) if gaussian: H_ext = [model.hamiltonian_field(*field), self.gaussian] else: H_ext = model.hamiltonian_field(*field) result = qt.sesolve( [H_int, H_ext], psi0, time_interval, e_ops=e_ops, options=options, progress_bar=progress_bar, _safe_mode=_safe_mode, args={"t0": t0, "sigma": duration / 4}, ) t0 = t0 + duration psi0 = result.final_state expect.append(np.array(result.expect)[:, 1:]) times.append(time_interval[1:]) return np.concatenate(times), np.concatenate(expect, axis=1)
def check_e_ops_list_single_operator( self, e_ops, H, psi0, tlist, dim, krylov_dim=35, tol=1e-5, square_hamiltonian=True, ): "Check input possibilities when e_ops=[callable | qobj]" if not square_hamiltonian: H.dims = [[H.shape[0]], [H.shape[0]]] psi0.dims = [[H.shape[0]], [1]] krylov_outputs = krylovsolve(H, psi0, tlist, krylov_dim, e_ops=e_ops) exact_output = exactsolve(H, psi0, tlist) exact_output.expect = expect_value(e_ops[0], exact_output, tlist) try: sesolve_outputs = sesolve(H, psi0, tlist, e_ops=e_ops) except IndexError: # if tlist=[], sesolve breaks but krylov doesn't pass if len(tlist) > 1: assert len(krylov_outputs.expect) == len( sesolve_outputs.expect ), "shape of outputs between krylov and sesolve differs" assert_err_expect_less_than_tol(exp_1=krylov_outputs.expect[0], exp_2=exact_output.expect, tol=tol) elif len(tlist) == 1: assert ( np.abs(krylov_outputs.expect[0] - sesolve_outputs.expect[0]) <= tol ), "expect outputs from krylovsolve and sesolve are not equal" else: assert krylov_outputs.states == []
def check_e_ops_none( self, H, psi0, tlist, dim, krylov_dim=30, tol=1e-5, tol2=1e-4 ): "Check input possibilities when e_ops=None" krylov_outputs = krylovsolve(H, psi0, tlist, krylov_dim, e_ops=None) try: sesolve_outputs = sesolve(H, psi0, tlist, e_ops=None) except IndexError: # if tlist=[], sesolve breaks but krylov doesn't pass if len(tlist) > 1: assert_err_states_less_than_tol( krylov_outputs, sesolve_outputs, tol) elif len(tlist) == 1: assert krylov_outputs.states == sesolve_outputs.states else: assert krylov_outputs.states == []
def __init__(self, H, ts, psi0=qutip.basis(3, 1), options=qutip.solver.Options(), force_recompute=False): self.H = H if H.is_constant() or H.T is None: self.output = qutip.sesolve( H.get_qutip_descriptor(time_offset=min(ts)), psi0, ts - min(ts), options=options) else: #Periodic hamiltonian, use Floquet Formalism self.output = qutip.fsesolve( H.get_qutip_descriptor(time_offset=min(ts)), psi0, ts - min(ts), e_ops=[], T=H.T, args={})
def nr_anneal(self, schedule, init_state): """ Performs a numeric reverse anneal on H using QuTip. inputs: --------- schedule - a numeric anneal schedule init_state - the starting state for the reverse anneal listed as string or list e.g. '111' or [010] outputs: --------- probs - probability of each output state as a list ordered in canconically w.r.t. tensor product """ times, svals = schedule # create a numeric representation of H ABfuncs = time_interpolation(schedule, self.processordata) numericH = get_numeric_H(self) A = ABfuncs['A(t)'] B = ABfuncs['B(t)'] HX = numericH['HX'] HZ = numericH['HZ'] # Define list_H for QuTiP listH = [[HX, A], [HZ, B]] # create a valid QuTip initial state qubit_states = [qts.ket([int(i)]) for i in init_state] QuTip_init_state = qt.tensor(*qubit_states) # perform a numerical reverse anneal on H results = qt.sesolve(listH, QuTip_init_state, times) probs = np.array([ abs(results.states[-1][i].flatten()[0])**2 for i in range(self.Hsize) ]) return probs
def _run_solver() -> CoherentResults: """Returns CoherentResults: Object containing evolution results.""" # Decide if progress bar will be fed to QuTiP solver p_bar: Optional[bool] if progress_bar is True: p_bar = True elif (progress_bar is False) or (progress_bar is None): p_bar = None else: raise ValueError("`progress_bar` must be a bool.") if "dephasing" in self.config.noise: # temporary workaround due to a qutip bug when using mesolve liouvillian = qutip.liouvillian(self._hamiltonian, self._collapse_ops) result = qutip.mesolve( liouvillian, self.initial_state, self._eval_times_array, progress_bar=p_bar, options=solv_ops, ) else: result = qutip.sesolve( self._hamiltonian, self.initial_state, self._eval_times_array, progress_bar=p_bar, options=solv_ops, ) return CoherentResults( result.states, self._size, self.basis_name, self._eval_times_array, self._meas_basis, meas_errors, )
def solve_particle(self, time_list): pauli_basis = [qt.sigmax(), qt.sigmay(), qt.sigmaz()] output = qt.sesolve(self.local_hamiltonian, self.state, time_list, pauli_basis) return output