def test_rhs_reuse(): """ rhs_reuse : pyx filenames match for rhs_reus= True """ N = 10 a = qt.destroy(N) H = [a.dag() * a, [a + a.dag(), 'sin(t)']] psi0 = qt.fock(N, 3) tlist = np.linspace(0, 10, 10) e_ops = [a.dag() * a] c_ops = [0.25 * a] # Test sesolve out1 = qt.mesolve(H, psi0, tlist, e_ops=e_ops) _temp_config_name = config.tdname out2 = qt.mesolve(H, psi0, tlist, e_ops=e_ops) assert_(config.tdname != _temp_config_name) _temp_config_name = config.tdname out3 = qt.mesolve(H, psi0, tlist, e_ops=e_ops, options=qt.Options(rhs_reuse=True)) assert_(config.tdname == _temp_config_name) # Test mesolve out1 = qt.mesolve(H, psi0, tlist, c_ops=c_ops, e_ops=e_ops) _temp_config_name = config.tdname out2 = qt.mesolve(H, psi0, tlist, c_ops=c_ops, e_ops=e_ops) assert_(config.tdname != _temp_config_name) _temp_config_name = config.tdname out3 = qt.mesolve(H, psi0, tlist, e_ops=e_ops, c_ops=c_ops, options=qt.Options(rhs_reuse=True)) assert_(config.tdname == _temp_config_name)
def test_numerical_circuit(circuit, device_class, kwargs, schedule_mode): num_qubits = circuit.N with warnings.catch_warnings(record=True): device = device_class(circuit.N, **kwargs) device.load_circuit(circuit, schedule_mode=schedule_mode) state = qutip.rand_ket(2**num_qubits) state.dims = [[2] * num_qubits, [1] * num_qubits] target = gate_sequence_product([state] + circuit.propagators()) if isinstance(device, DispersiveCavityQED): num_ancilla = len(device.dims) - num_qubits ancilla_indices = slice(0, num_ancilla) extra = qutip.basis(device.dims[ancilla_indices], [0] * num_ancilla) init_state = qutip.tensor(extra, state) elif isinstance(device, SCQubits): # expand to 3-level represetnation init_state = _ket_expaned_dims(state, device.dims) else: init_state = state options = qutip.Options(store_final_state=True, nsteps=50_000) result = device.run_state(init_state=init_state, analytical=False, options=options) if isinstance(device, DispersiveCavityQED): target = qutip.tensor(extra, target) elif isinstance(device, SCQubits): target = _ket_expaned_dims(target, device.dims) assert _tol > abs(1 - qutip.metrics.fidelity(result.final_state, target))
def test_compatibility_with_solver(solve): e_ops = [getattr(qutip, 'sigma'+x)() for x in 'xyzmp'] e_ops += [lambda t, psi: np.sin(t)] h = qutip.sigmax() state = qutip.basis(2, 0) times = np.linspace(0, 10, 101) options = qutip.Options(store_states=True) result = solve(h, state, times, e_ops=e_ops, options=options) direct, states = result.expect, result.states indirect = qutip.expect(e_ops[:-1], states) # check measurement operators based on quantum objects assert len(direct)-1 == len(indirect) for direct_, indirect_ in zip(direct, indirect): assert len(direct_) == len(indirect_) assert isinstance(direct_, np.ndarray) assert isinstance(indirect_, np.ndarray) assert direct_.dtype == indirect_.dtype np.testing.assert_allclose(direct_, indirect_, atol=1e-12) # test measurement operators based on lambda functions direct_ = direct[-1] # by design, lambda measurements are of complex type indirect_ = np.sin(times, dtype=complex) assert len(direct_) == len(indirect_) assert isinstance(direct_, np.ndarray) assert isinstance(indirect_, np.ndarray) assert direct_.dtype == indirect_.dtype np.testing.assert_allclose(direct_, indirect_, atol=1e-12)
def solve(): ### TwoOB two_obj = ob_two.OBTwo(gammas=[2 * pi * 0.]) two_obj.set_H_Delta([2 * pi * 0.]) squares = lambda t, args: (tf.square_1(t, args) + tf.square_2(t, args)) two_obj.set_H_Omega([2 * pi * 10.], [squares]) args = { 'on_1': .3, 'off_1': .325, 'ampl_1': 1., 'on_2': .6, 'off_2': .625, 'ampl_2': 1. } ### Solve with QuTiP tlist = np.linspace(0., 1., 201) # Need to set a max step or it won't see the switch on opts = qu.Options(max_step=.01) two_obj.mesolve(tlist, td=True, args=args, opts=opts, show_pbar=False) return two_obj, args
def evolution_operator_microwave( H_nodrive, H_drive, t_points=None, parallel=False, **kwargs): """ Calculates the unitary evolution operator for a gate activated by a microwave drive. Parameters ---------- H_nodrive : :class:`qutip.Qobj` The Hamiltonian without the drive term. 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. t_points : *array* of float (optional) Times at which the evolution operator is returned. If None, it is generated from `kwargs['T_gate']`. parallel : True or False Run the qutip propagator function in parallel mode **kwargs: Contains gate parameters such as pulse shape and gate time. Returns ------- U_t : *array* of :class:`qutip.Qobj` The evolution operator 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 = [2 * np.pi * H_nodrive, [H_drive, H_drive_coeff_gate]] U_t = qt.propagator(H, t_points, [], args=kwargs, parallel=parallel, options=qt.Options(nsteps=1000)) return U_t
def evolution_psi_microwave_nonorm_diss( H_nodrive, H_drive, psi0, c_ops = [], t_points=None, **kwargs): """ Calculates the unitary evolution of a specific starting state for a gate activated by a microwave drive. Parameters ---------- H_nodrive : :class:`qutip.Qobj` The Hamiltonian without the drive term. 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. psi0 : :class:`qutip.Qobj` Initial state of the system (ket or density matrix). 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 = [2 * np.pi * H_nodrive, [H_drive, H_drive_coeff_gate_nonorm]] result = qt.mesolve(H, psi0, t_points, c_ops, args=kwargs, options=qt.Options(nsteps=100000, atol=1e-12, rtol=1e-10)) return result.states
def test_numerical_evolution(num_qubits, gates, device_class, kwargs): num_qubits = 2 circuit = QubitCircuit(num_qubits) for gate in gates: circuit.add_gate(gate) device = device_class(num_qubits, **kwargs) device.load_circuit(circuit) state = qutip.rand_ket(2**num_qubits) state.dims = [[2] * num_qubits, [1] * num_qubits] target = gate_sequence_product([state] + circuit.propagators()) if isinstance(device, DispersiveCavityQED): num_ancilla = len(device.dims) - num_qubits ancilla_indices = slice(0, num_ancilla) extra = qutip.basis(device.dims[ancilla_indices], [0] * num_ancilla) init_state = qutip.tensor(extra, state) elif isinstance(device, SCQubits): # expand to 3-level represetnation init_state = _ket_expaned_dims(state, device.dims) else: init_state = state options = qutip.Options(store_final_state=True, nsteps=50_000) result = device.run_state(init_state=init_state, analytical=False, options=options) numerical_result = result.final_state if isinstance(device, DispersiveCavityQED): target = qutip.tensor(extra, target) elif isinstance(device, SCQubits): target = _ket_expaned_dims(target, device.dims) assert _tol > abs(1 - qutip.metrics.fidelity(numerical_result, target))
def test_numerical_evolution(num_qubits, gates, device_class, kwargs): num_qubits = 3 circuit = qutip.qip.circuit.QubitCircuit(num_qubits) for gate in gates: circuit.add_gate(gate) with warnings.catch_warnings(record=True): device = device_class(num_qubits, **kwargs) device.load_circuit(circuit) state = qutip.rand_ket(2**num_qubits) state.dims = [[2] * num_qubits, [1] * num_qubits] target = gate_sequence_product([state] + circuit.propagators()) if len(device.dims) > num_qubits: num_ancilla = len(device.dims) - num_qubits ancilla_indices = slice(0, num_ancilla) extra = qutip.basis(device.dims[ancilla_indices], [0] * num_ancilla) init_state = qutip.tensor(extra, state) else: init_state = state options = qutip.Options(store_final_state=True, nsteps=50_000) result = device.run_state(init_state=init_state, analytical=False, options=options) if len(device.dims) > num_qubits: target = qutip.tensor(extra, target) assert _tol > abs(1 - qutip.metrics.fidelity(result.final_state, target))
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 do_pulse_sequence(self, psi0, **kwargs): ''' Run a detuning pulse sequence ''' opts = qu.Options(nsteps=100000) self.device.build_hamiltonian(detuning=0) initial_hamiltonian = self.device.Hamiltonian conversion_factor = self.device.alpha * const.eV / const.h # Convert voltage pulse to frequency units detuning_hamiltonian = conversion_factor * qu.Qobj( np.array([[1 / 2, 0, 0, 0, 0], [0, 1 / 2, 0, 0, 0], [0, 0, 1 / 2, 0, 0], [0, 0, 0, 1 / 2, 0], [0, 0, 0, 0, -1 / 2]])) qutip_time_dependence = qu.Cubic_Spline( self.lePulse.time_vec[0], self.lePulse.time_vec[-1], self.lePulse.simulation_waveform) full_H = [ initial_hamiltonian, [detuning_hamiltonian, qutip_time_dependence] ] output = qu.mesolve(full_H, psi0, tlist=self.lePulse.time_vec, c_ops=[], e_ops=[], options=opts, progress_bar=True) self.simulation_result = output
def build_opts(self, opts): """ This currently just sets the options to default. Issue #96. """ self.opts = qu.Options() return self.opts
def solve(self, rho0=None, e_ops=[], opts=qu.Options(), recalc=True, show_pbar=False, save=True): # When we're calling from MBSolve, we don't want to save each step. # So we pass in save=False. if save: savefile = self.savefile else: savefile = None if self.method == 'mesolve': self.atom.mesolve(self.tlist, rho0=rho0, e_ops=e_ops, opts=opts, recalc=recalc, savefile=savefile, show_pbar=show_pbar) return self.atom.states_t() # self.atom.result
def test_states_and_expect(self, hamiltonian, args, c_ops, expected, tol): options = qutip.Options(average_states=True, store_states=True) result = qutip.mcsolve(hamiltonian, self.state, self.times, args=args, c_ops=c_ops, e_ops=self.e_ops, ntraj=self.ntraj, options=options) self._assert_expect(result, expected, tol) self._assert_states(result, expected, tol)
def solve(self, e_ops=[], opts=None, recalc=True, show_pbar=False, save=True): # When we're calling from MBSolve, we don't want to save each step. # So we pass in save=False. if save: savefile = self.savefile else: savefile = None # Choosing to overwrite opts at the solve stage. if opts: self.build_opts(opts) options = qu.Options(**self.opts) if self.method == 'mesolve': self.atom.mesolve(self.tlist, e_ops=e_ops, options=options, recalc=recalc, savefile=savefile, show_pbar=show_pbar) return self.atom.states_t() # self.atom.result
def setup(N): options = qt.Options() options.nsteps = 1000000 options.atol = 1e-8 options.rtol = 1e-6 options.rhs_reuse = True return options
def free_ev(initial_state, duration, error = False): t0 = omega_plus + omega_minus #transition frequency # H_couple = nu * ld * (a + a_dag) * sigma_z H0 = ((1/2) * t0 * sigma_z) if error == False: H_final = H0 if error == True: H1 = (1/2) * sigma_z H_final = [H0, [H1, pink_noise_coeff]] optns = qt.Options() optns.nsteps = 100000 states = qt.mesolve(H_final, rho0 = initial_state, tlist= np.linspace(0,duration,100), options = optns).states final_state = states[-1] return(final_state, states)
def _integrate(L, E0, ti, tf, integrator='propagator', parallel=False, opt=qt.Options()): """ Basic ode integrator """ if tf > ti: if integrator == 'mesolve': if parallel: warnings.warn('parallelization not implemented for "mesolve"') opt.store_final_state = True sol = qt.mesolve(L, E0, [ti, tf], [], [], options=opt) return sol.final_state elif integrator == 'propagator': return qt.propagator( L, (tf - ti), [], [], parallel=parallel, options=opt) * E0 else: raise ValueError('integrator keyword must be either "propagator"' + 'or "mesolve"') else: return E0
def mesolve(self, tlist, rho0=None, td=False, e_ops=[], args={}, opts=qu.Options(), recalc=True, savefile=None, show_pbar=False): if not rho0: rho0 = self.ground_state() savefile_exists = os.path.isfile(str(savefile) + '.qu') # Solve if 1) we ask for it to be recalculated or 2) it *must* be # calculated because no savefile exists. if recalc or not savefile_exists: # Is the Hamiltonian time-dependent? if td: # If so H is a list of [H_i, t_func_i] pairs. H = [self.H_0, self.H_Delta] H.extend(self.H_I_list()) else: # If not it's a single QObj H = self.H_0 + self.H_Delta + self.H_I_sum() if show_pbar: pbar = qu.ui.progressbar.TextProgressBar() else: pbar = qu.ui.progressbar.BaseProgressBar() self.result = qu.mesolve(H, rho0, tlist, self.c_ops, e_ops, args=args, options=opts, progress_bar=pbar) self.rho = self.result.states[-1] # Set rho to the final state. # Only save the file if we have a place to save it. if savefile: print('Saving OBBase to {0}.qu'.format(savefile)) qu.qsave(self.result, savefile) # Otherwise load the steady state rho_v_delta from file else: print('Loading from {0}.qu'.format(savefile)) self.result = qu.qload(savefile) self.rho = self.result.states[-1] return self.result
def evolution_mcsolve_microwave(system, H_drive, initial_state, c_ops, e_ops, num_cpus=0, nsteps=2000, ntraj=1000, t_points=None, **kwargs): """ Calculates the expectation values vs time for a dissipative system 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. c_ops : *list* of :class:`qutip.Qobj` The list of collaps operators for MC solver. e_ops : *list* of :class:`qutip.Qobj` The list of operators to calculate expectation values. num_cpus, nsteps, ntraj : int Parameters for MC solver 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* result.expect of mcsolve (time-dependent expectation values) result.expect[0] for the expectation value of the first operator """ 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]] options = qt.Options(num_cpus=num_cpus, nsteps=nsteps) result = qt.mcsolve(H, initial_state, t_points, c_ops=c_ops, e_ops=e_ops, args=kwargs, ntraj=ntraj, options=options) return result.expect
def _integrate(L, E0, ti, tf, opt=qt.Options()): """ Basic ode integrator """ opt.store_final_state = True if tf > ti: sol = qt.mesolve(L, E0, [ti, tf], [], [], options=opt) return sol.final_state else: return E0
def test_seeds_can_be_reused(self): args = (self.H, self.state, self.times) kwargs = {'c_ops': self.c_ops, 'ntraj': self.ntraj} first = qutip.mcsolve(*args, **kwargs) options = qutip.Options(seeds=first.seeds) second = qutip.mcsolve(*args, options=options, **kwargs) for first_t, second_t in zip(first.col_times, second.col_times): np.testing.assert_equal(first_t, second_t) for first_w, second_w in zip(first.col_which, second.col_which): np.testing.assert_equal(first_w, second_w)
def do_qt_mesolve(state, H, lindblads, steps, tau, **kwargs): progress = kwargs.pop('progress_bar', None) times = kwargs.pop('times', None) if times is None: times = np.linspace(0, steps * tau, steps, dtype=np.float_) return qt.mesolve(H, qt.ket2dm(state), times, lindblads, [], options=qt.Options(**kwargs), progress_bar=progress).states
def run(neq=10, ntraj=100, solver='both', ncpus=1): # sparse initial state # psi0 = basis(neq,neq-1) # dense initial state psi0 = qt.Qobj(np.ones((neq, 1))).unit() a = qt.destroy(neq) ad = a.dag() H = ad * a # c_ops = [gamma*a] c_ops = [qt.qeye(neq)] e_ops = [ad * a] # Times T = 10.0 dt = 0.1 nstep = int(T / dt) tlist = np.linspace(0, T, nstep) # set options opts = qt.Options() opts.num_cpus = ncpus opts.gui = False mcf90_time = 0. mc_time = 0. if (solver == 'mcf90' or solver == 'both'): start_time = time.time() mcf90.mcsolve_f90(H, psi0, tlist, c_ops, e_ops, ntraj=ntraj, options=opts) mcf90_time = time.time() - start_time print("mcsolve_f90 solutiton took", mcf90_time, "s") if (solver == 'mc' or solver == 'both'): start_time = time.time() qt.mcsolve(H, psi0, tlist, c_ops, e_ops, ntraj=ntraj, options=opts, progress_bar=False) mc_time = time.time() - start_time print("mcsolve solutiton took", mc_time, "s") return mcf90_time, mc_time
def setup(N): xmin = -5 xmax = 5 x0 = 0.3 p0 = -0.2 sigma0 = 1 dx = (xmax - xmin) / N pmin = -np.pi / dx pmax = np.pi / dx dp = (pmax - pmin) / N samplepoints_x = np.linspace(xmin, xmax, N, endpoint=False) samplepoints_p = np.linspace(pmin, pmax, N, endpoint=False) x = qt.Qobj(np.diag(samplepoints_x)) row0 = [ sum([p * np.exp(-1j * p * dxji) for p in samplepoints_p]) * dp * dx / (2 * np.pi) for dxji in samplepoints_x - xmin ] row0 = np.array(row0) col0 = row0.conj() a = np.zeros([N, N], dtype=complex) for i in range(N): a[i, i:] = row0[:N - i] a[i:, i] = col0[:N - i] p = qt.Qobj(a) Hkin = p**2 Vx = 2 * x**2 def gaussianstate(x0, p0, sigma0): alpha = 1. / (np.pi**(1 / 4) * np.sqrt(sigma0)) * np.sqrt(dx) data = alpha * np.exp(1j * p0 * (samplepoints_x - x0 / 2) - (samplepoints_x - x0)**2 / (2 * sigma0**2)) return qt.Qobj(data) psi0 = gaussianstate(x0, p0, sigma0) J = [x + 1j * p] options = qt.Options() options.nsteps = 1000000 options.atol = 1e-8 options.rtol = 1e-6 options.rhs_reuse = True return psi0, Hkin, Vx, J, x, options
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 test_compatibility_with_solver(solve): e_ops = [getattr(qutip, 'sigma' + x)() for x in 'xyzmp'] h = qutip.sigmax() state = qutip.basis(2, 0) times = np.linspace(0, 10, 101) options = qutip.Options(store_states=True) result = solve(h, state, times, e_ops=e_ops, options=options) direct, states = result.expect, result.states indirect = qutip.expect(e_ops, states) assert len(direct) == len(indirect) for direct_, indirect_ in zip(direct, indirect): assert len(direct_) == len(indirect_) assert isinstance(direct_, np.ndarray) assert isinstance(indirect_, np.ndarray) assert direct_.dtype == indirect_.dtype np.testing.assert_allclose(direct_, indirect_, atol=1e-12)
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 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 simulate_dynamics_me(H, initial_state, duration, steps=200, mode='states'): """ A function to simulate the dynamics of a spin system given initial state and Hamiltonian using Master equation. == IN == ** initial_state, qu.qobj: Ket vector representing initial state as a qutip qobj ** H, qu.qobj: Hamiltonian operator as a qutip qobj ** duration, float: Integration time interval in us ** steps, int: Number of timestep ** mode, str: What information should be returned by the simulation? > 'states' - solver object returns states > 'samestate' - solver object returns expectation values for all spins having the same state == OUT == ** solver, qu.solver: QuTiP solver object which encodes information about run """ # First, check to make sure that the ket and H are on the same size Hilbert space if (H.N != initial_state.N) or (H.s != initial_state.s): raise ValueError('H and initial_state are not the same shape. Operators act on different Hilbert spaces.') # Check if the mode entered is valid mode_list = ['states', 'samestate'] if not mode in mode_list: raise ValueError('Invalid mode specified.') e_ops = [] if mode == 'states': pass elif mode == 'samestate': for ii in range(int(2*H.s+1)): basis_state = qu.basis(int(2*H.s+1), ii) for jj in range(H.N): if jj == 0: collapse_op = basis_state * basis_state.dag() else: collapse_op = qu.tensor(collapse_op, basis_state * basis_state.dag()) e_ops.append(collapse_op) # Run simulation # Pass option to allow 2000 time steps options = qu.Options(nsteps=1e9) #some large number solver = qu.mesolve(H.operator, initial_state.rho, tlist=np.linspace(0,duration,steps), e_ops=e_ops, options=options) return solver