def test_QobjFull(): "Qobj full" data = np.random.random( (15, 15)) + 1j * np.random.random((15, 15)) - (0.5 + 0.5j) A = Qobj(data) b = A.full() assert_(np.all(b - data == 0))
def test_QobjDivision(): "Qobj division" data = _random_not_singular(5) q = Qobj(data) randN = 10 * np.random.random() q = q / randN assert np.allclose(q.full(), data / randN)
def steadystate_nonlinear(L_func, rho0, args={}, maxiter=10, random_initial_state=False, tol=1e-6, itertol=1e-5, use_umfpack=True, verbose=False): """ Steady state for the evolution subject to the nonlinear Liouvillian (which depends on the density matrix). .. note:: Experimental. Not at all certain that the inverse power method works for state-dependent Liouvillian operators. """ use_solver(assumeSortedIndices=True, useUmfpack=use_umfpack) if random_initial_state: rhoss = rand_dm(rho0.shape[0], 1.0, dims=rho0.dims) elif isket(rho0): rhoss = ket2dm(rho0) else: rhoss = Qobj(rho0) v = mat2vec(rhoss.full()) n = prod(rhoss.shape) tr_vec = sp.eye(rhoss.shape[0], rhoss.shape[0], format='coo') tr_vec = tr_vec.reshape((1, n)) it = 0 while it < maxiter: L = L_func(rhoss, args) L = L.data.tocsc() - (tol**2) * sp.eye(n, n, format='csc') L.sort_indices() v = spsolve(L, v, use_umfpack=use_umfpack) v = v / la.norm(v, np.inf) data = v / sum(tr_vec.dot(v)) data = reshape(data, (rhoss.shape[0], rhoss.shape[1])).T rhoss.data = sp.csr_matrix(data) it += 1 if la.norm(L * v, np.inf) <= tol: break if it >= maxiter: raise ValueError('Failed to find steady state after ' + str(maxiter) + ' iterations') rhoss = 0.5 * (rhoss + rhoss.dag()) return rhoss.tidyup() if qset.auto_tidyup else rhoss
def test_QobjNorm(): "Qobj norm" # vector L2-norm test N = 20 x = np.random.random(N) + 1j * np.random.random(N) A = Qobj(x) assert_equal(np.abs(A.norm() - la.norm(A.data.data, 2)) < 1e-12, True) # vector max (inf) norm test assert_equal(np.abs(A.norm("max") - la.norm(A.data.data, np.inf)) < 1e-12, True) # operator frobius norm x = np.random.random((N, N)) + 1j * np.random.random((N, N)) A = Qobj(x) assert_equal(np.abs(A.norm("fro") - la.norm(A.full(), "fro")) < 1e-12, True)
def steadystate_nonlinear(L_func, rho0, args={}, maxiter=10, random_initial_state=False, tol=1e-6, itertol=1e-5, use_umfpack=True, verbose=False): """ Steady state for the evolution subject to the nonlinear Liouvillian (which depends on the density matrix). .. note:: Experimental. Not at all certain that the inverse power method works for state-dependent Liouvillian operators. """ use_solver(assumeSortedIndices=True, useUmfpack=use_umfpack) if random_initial_state: rhoss = rand_dm(rho0.shape[0], 1.0, dims=rho0.dims) elif isket(rho0): rhoss = ket2dm(rho0) else: rhoss = Qobj(rho0) v = mat2vec(rhoss.full()) n = prod(rhoss.shape) tr_vec = sp.eye(rhoss.shape[0], rhoss.shape[0], format='coo') tr_vec = tr_vec.reshape((1, n)) it = 0 while it < maxiter: L = L_func(rhoss, args) L = L.data.tocsc() - (tol ** 2) * sp.eye(n, n, format='csc') L.sort_indices() v = spsolve(L, v, use_umfpack=use_umfpack) v = v / la.norm(v, np.inf) data = v / sum(tr_vec.dot(v)) data = reshape(data, (rhoss.shape[0], rhoss.shape[1])).T rhoss.data = sp.csr_matrix(data) it += 1 if la.norm(L * v, np.inf) <= tol: break if it >= maxiter: raise ValueError('Failed to find steady state after ' + str(maxiter) + ' iterations') rhoss = 0.5 * (rhoss + rhoss.dag()) return rhoss.tidyup() if qset.auto_tidyup else rhoss
def test_QobjNorm(): "Qobj norm" # vector L2-norm test N = 20 x = np.random.random(N) + 1j * np.random.random(N) A = Qobj(x) assert_equal(np.abs(A.norm() - la.norm(A.data.data, 2)) < 1e-12, True) # vector max (inf) norm test assert_equal( np.abs(A.norm('max') - la.norm(A.data.data, np.inf)) < 1e-12, True) # operator frobius norm x = np.random.random((N, N)) + 1j * np.random.random((N, N)) A = Qobj(x) assert_equal( np.abs(A.norm('fro') - la.norm(A.full(), 'fro')) < 1e-12, True)
def test_QobjNorm(): "Qobj norm" # vector L2-norm test N = 20 x = np.random.random(N) + 1j * np.random.random(N) A = Qobj(x) assert np.abs(A.norm() - la.norm(A.data.data, 2)) < 1e-12 # vector max (inf) norm test assert np.abs(A.norm('max') - la.norm(A.data.data, np.inf)) < 1e-12 # operator frobius norm x = np.random.random((N, N)) + 1j * np.random.random((N, N)) A = Qobj(x) assert np.abs(A.norm('fro') - la.norm(A.full(), 'fro')) < 1e-12 # operator trace norm a = rand_herm(10, 0.25) assert np.allclose(a.norm(), (a * a.dag()).sqrtm().tr().real) b = rand_herm(10, 0.25) - 1j * rand_herm(10, 0.25) assert np.allclose(b.norm(), (b * b.dag()).sqrtm().tr().real)
def test_QobjNorm(): "Qobj norm" # vector L2-norm test N = 20 x = np.random.random(N) + 1j * np.random.random(N) A = Qobj(x) assert_equal(np.abs(A.norm() - la.norm(A.data.data, 2)) < 1e-12, True) # vector max (inf) norm test assert_equal( np.abs(A.norm('max') - la.norm(A.data.data, np.inf)) < 1e-12, True) # operator frobius norm x = np.random.random((N, N)) + 1j * np.random.random((N, N)) A = Qobj(x) assert_equal( np.abs(A.norm('fro') - la.norm(A.full(), 'fro')) < 1e-12, True) # operator trace norm a = rand_herm(10,0.25) assert_almost_equal(a.norm(), (a*a.dag()).sqrtm().tr().real) b = rand_herm(10,0.25) - 1j*rand_herm(10,0.25) assert_almost_equal(b.norm(), (b*b.dag()).sqrtm().tr().real)
def test_QobjData(): "Qobj data" N = 10 data1 = _random_not_singular(N) q1 = Qobj(data1) # check if data is a csr_matrix if originally array assert sp.isspmatrix_csr(q1.data) # check if dense ouput is exactly equal to original data assert np.all(q1.full() == data1) data2 = _random_not_singular(N) data2 = sp.csr_matrix(data2) q2 = Qobj(data2) # check if data is a csr_matrix if originally csr_matrix assert sp.isspmatrix_csr(q2.data) data3 = 1 q3 = Qobj(data3) # check if data is a csr_matrix if originally int assert sp.isspmatrix_csr(q3.data)
def _compute_prop_grad(self, k, j, compute_prop=True): """ Calculate the gradient of propagator wrt the control amplitude in the timeslot. Returns: [prop], prop_grad """ dyn = self.parent dyn._ensure_decomp_curr(k) if compute_prop: prop = self._compute_propagator(k) if dyn.oper_dtype == Qobj: # put control dyn_gen in combined dg diagonal basis cdg = (dyn._get_dyn_gen_eigenvectors_adj(k) * dyn._get_phased_ctrl_dyn_gen(k, j) * dyn._dyn_gen_eigenvectors[k]) # multiply (elementwise) by timeslice and factor matrix cdg = Qobj(np.multiply(cdg.full() * dyn.tau[k], dyn._dyn_gen_factormatrix[k]), dims=dyn.dyn_dims) # Return to canonical basis prop_grad = (dyn._dyn_gen_eigenvectors[k] * cdg * dyn._get_dyn_gen_eigenvectors_adj(k)) else: # put control dyn_gen in combined dg diagonal basis cdg = dyn._get_dyn_gen_eigenvectors_adj(k).dot( dyn._get_phased_ctrl_dyn_gen(k, j)).dot( dyn._dyn_gen_eigenvectors[k]) # multiply (elementwise) by timeslice and factor matrix cdg = np.multiply(cdg * dyn.tau[k], dyn._dyn_gen_factormatrix[k]) # Return to canonical basis prop_grad = dyn._dyn_gen_eigenvectors[k].dot(cdg).dot( dyn._get_dyn_gen_eigenvectors_adj(k)) if compute_prop: return prop, prop_grad else: return prop_grad
def test_QobjFull(): "Qobj full" data = _random_not_singular(15) A = Qobj(data) b = A.full() assert np.all(b - data == 0)
def krylovsolve( H: Qobj, psi0: Qobj, tlist: np.array, krylov_dim: int, e_ops=None, options=None, progress_bar: bool = None, sparse: bool = False, ): """ Time evolution of state vectors for time independent Hamiltonians. Evolve the state vector ("psi0") finding an approximation for the time evolution operator of Hamiltonian ("H") by obtaining the projection of the time evolution operator on a set of small dimensional Krylov subspaces (m << dim(H)). The output is either the state vector or the expectation values of supplied operators ("e_ops") at arbitrary points at ("tlist"). **Additional options** Additional options to krylovsolve can be set with the following: * "store_states": stores states even though expectation values are requested via the "e_ops" argument. * "store_final_state": store final state even though expectation values are requested via the "e_ops" argument. Parameters ---------- H : :class:`qutip.Qobj` System Hamiltonian. psi0 : :class: `qutip.Qobj` Initial state vector (ket). tlist : None / *list* / *array* List of times on which to evolve the initial state. If None, nothing happens but the code won't break. krylov_dim: int Dimension of Krylov approximation subspaces used for the time evolution approximation. e_ops : None / list of :class:`qutip.Qobj` Single operator or list of operators for which to evaluate expectation values. options : Options Instance of ODE solver options, as well as krylov parameters. atol: controls (approximately) the error desired for the final solution. (Defaults to 1e-8) nsteps: maximum number of krylov's internal number of Lanczos iterations. (Defaults to 10000) progress_bar : None / BaseProgressBar Optional instance of BaseProgressBar, or a subclass thereof, for showing the progress of the simulation. sparse : bool (default False) Use np.array to represent system Hamiltonians. If True, scipy sparse arrays are used instead. Returns ------- result: :class:`qutip.solver.Result` An instance of the class :class:`qutip.solver.Result`, which contains either an *array* `result.expect` of expectation values for the times `tlist`, or an *array* `result.states` of state vectors corresponding to the times `tlist` [if `e_ops` is an empty list]. """ # check the physics _check_inputs(H, psi0, krylov_dim) # check extra inputs e_ops, e_ops_dict = _check_e_ops(e_ops) pbar = _check_progress_bar(progress_bar) # transform inputs type from Qobj to np.ndarray/csr_matrix if sparse: _H = H.get_data() # (fast_) csr_matrix else: _H = H.full().copy() # np.ndarray _psi = psi0.full().copy() _psi = _psi / np.linalg.norm(_psi) # create internal variable and output containers if options is None: options = Options(nsteps=10000) krylov_results = Result() krylov_results.solver = "krylovsolve" # handle particular cases of an empty tlist or single element n_tlist_steps = len(tlist) if n_tlist_steps < 1: return krylov_results if n_tlist_steps == 1: # if tlist has only one element, return it krylov_results = particular_tlist_or_happy_breakdown( tlist, n_tlist_steps, options, psi0, e_ops, krylov_results, pbar) # this will also raise a warning return krylov_results tf = tlist[-1] t0 = tlist[0] # optimization step using Lanczos, then reuse it for the first partition dim_m = krylov_dim krylov_basis, T_m = lanczos_algorithm(_H, _psi, krylov_dim=dim_m, sparse=sparse) # check if a happy breakdown occurred if T_m.shape[0] < krylov_dim + 1: if T_m.shape[0] == 1: # this means that the state does not evolve in time, it lies in a # symmetry of H subspace. Thus, theres no work to be done. krylov_results = particular_tlist_or_happy_breakdown( tlist, n_tlist_steps, options, psi0, e_ops, krylov_results, pbar, happy_breakdown=True, ) return krylov_results else: # no optimization is required, convergence is guaranteed. delta_t = tf - t0 n_timesteps = 1 else: # calculate optimal number of internal timesteps. delta_t = _optimize_lanczos_timestep_size(T_m, krylov_basis=krylov_basis, tlist=tlist, options=options) n_timesteps = int(ceil((tf - t0) / delta_t)) if n_timesteps >= options.nsteps: raise Exception( f"Optimization requires a number {n_timesteps} of lanczos iterations, " f"which exceeds the defined allowed number {options.nsteps}. This can " "be increased via the 'Options.nsteps' property.") partitions = _make_partitions(tlist=tlist, n_timesteps=n_timesteps) if progress_bar: pbar.start(len(partitions)) # update parameters regarding e_ops krylov_results, expt_callback, options, n_expt_op = _e_ops_outputs( krylov_results, e_ops, n_tlist_steps, options) # parameters for the lazy iteration evolve tlist psi_norm = np.linalg.norm(_psi) last_t = t0 for idx, partition in enumerate(partitions): evolved_states = _evolve_krylov_tlist( H=_H, psi0=_psi, krylov_dim=dim_m, tlist=partition, t0=last_t, psi_norm=psi_norm, krylov_basis=krylov_basis, T_m=T_m, sparse=sparse, ) if idx == 0: krylov_basis = None T_m = None t_idx = 0 _psi = evolved_states[-1] psi_norm = np.linalg.norm(_psi) last_t = partition[-1] # apply qobj to each evolved state, remove repeated tail elements qobj_evolved_states = [ Qobj(state, dims=psi0.dims) for state in evolved_states[1:-1] ] krylov_results = _expectation_values( e_ops, n_expt_op, expt_callback, krylov_results, qobj_evolved_states, partitions, idx, t_idx, options, ) t_idx += len(partition[1:-1]) pbar.update(idx) pbar.finished() if e_ops_dict: krylov_results.expect = { e: krylov_results.expect[n] for n, e in enumerate(e_ops_dict.keys()) } return krylov_results