def fredkin(N=None, control=0, targets=[1, 2]): """Quantum object representing the Fredkin gate. Returns ------- fredkin_gate : qobj Quantum object representation of Fredkin gate. Examples -------- >>> fredkin() Quantum object: dims = [[2, 2, 2], [2, 2, 2]], \ shape = [8, 8], type = oper, isHerm = True Qobj data = [[ 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j] [ 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j] [ 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j] [ 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j] [ 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j] [ 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j] [ 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j] [ 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j]] """ if [control, targets[0], targets[1]] != [0, 1, 2] and N is None: N = 3 if N is not None: return gate_expand_3toN(fredkin(), N, [control, targets[0]], targets[1]) else: return Qobj([[1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1]], dims=[[2, 2, 2], [2, 2, 2]])
def num(N, offset=0): """Quantum object for number operator. Parameters ---------- N : int The dimension of the Hilbert space. offset : int (default 0) The lowest number state that is included in the finite number state representation of the operator. Returns ------- oper: qobj Qobj for number operator. Examples -------- >>> num(4) # doctest: +SKIP Quantum object: dims = [[4], [4]], \ shape = [4, 4], type = oper, isHerm = True Qobj data = [[0 0 0 0] [0 1 0 0] [0 0 2 0] [0 0 0 3]] """ if offset == 0: data = np.arange(1, N, dtype=complex) ind = np.arange(1, N, dtype=np.int32) ptr = np.array([0] + list(range(0, N)), dtype=np.int32) ptr[-1] = N - 1 else: data = np.arange(offset, offset + N, dtype=complex) ind = np.arange(N, dtype=np.int32) ptr = np.arange(N + 1, dtype=np.int32) ptr[-1] = N return Qobj(fast_csr_matrix((data, ind, ptr), shape=(N, N)), isherm=True)
def enr_fock(dims, excitations, state): """ Generate the Fock state representation in a excitation-number restricted state space. The `dims` argument is a list of integers that define the number of quantums states of each component of a composite quantum system, and the `excitations` specifies the maximum number of excitations for the basis states that are to be included in the state space. The `state` argument is a tuple of integers that specifies the state (in the number basis representation) for which to generate the Fock state representation. Parameters ---------- dims : list A list of the dimensions of each subsystem of a composite quantum system. excitations : integer The maximum number of excitations that are to be included in the state space. state : list of integers The state in the number basis representation. Returns ------- ket : Qobj A Qobj instance that represent a Fock state in the exication-number- restricted state space defined by `dims` and `exciations`. """ nstates, state2idx, idx2state = enr_state_dictionaries(dims, excitations) data = sp.lil_matrix((nstates, 1), dtype=np.complex) try: data[state2idx[tuple(state)], 0] = 1 except: raise ValueError("The state tuple %s is not in the restricted " "state space" % str(tuple(state))) return Qobj(data, dims=[dims, 1])
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 qeye(dimensions): """ Identity operator. Parameters ---------- dimensions : (int) or (list of int) or (list of list of int) Dimension of Hilbert space. If provided as a list of ints, then the dimension is the product over this list, but the ``dims`` property of the new Qobj are set to this list. This can produce either `oper` or `super` depending on the passed `dimensions`. Returns ------- oper : qobj Identity operator Qobj. Examples -------- >>> qeye(3) # doctest: +SKIP Quantum object: dims = [[3], [3]], shape = (3, 3), type = oper, \ isherm = True Qobj data = [[ 1. 0. 0.] [ 0. 1. 0.] [ 0. 0. 1.]] >>> qeye([2,2]) # doctest: +SKIP Quantum object: dims = [[2, 2], [2, 2]], shape = (4, 4), type = oper, \ isherm = True Qobj data = [[1. 0. 0. 0.] [0. 1. 0. 0.] [0. 0. 1. 0.] [0. 0. 0. 1.]] """ size, dimensions = _implicit_tensor_dimensions(dimensions) return Qobj(fast_identity(size), dims=dimensions, isherm=True, isunitary=True)
def fredkin(N=None, control1=None, control2=None, target=None): """Quantum object representing the Fredkin gate. Returns ------- fred_gate : qobj Quantum object representation of Fredkin gate. Examples -------- >>> fredkin() Quantum object: dims = [[2, 2, 2], [2, 2, 2]], \ shape = [8, 8], type = oper, isHerm = True Qobj data = [[ 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j] [ 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j] [ 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j] [ 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j] [ 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j] [ 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j] [ 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j] [ 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j]] """ if (not N is None and not control1 is None and not control2 is None and not target is None): return gate_expand_3toN(fredkin(), N, control1, control2, target) else: uuu = qstate('uuu') uud = qstate('uud') udu = qstate('udu') udd = qstate('udd') duu = qstate('duu') dud = qstate('dud') ddu = qstate('ddu') ddd = qstate('ddd') Q = ddd * ddd.dag() + ddu * ddu.dag() + dud * dud.dag() + \ duu * duu.dag() + udd * udd.dag() + uud * udu.dag() + \ udu * uud.dag() + uuu * uuu.dag() return Qobj(Q)
def enr_thermal_dm(dims, excitations, n): """ Generate the density operator for a thermal state in the excitation-number- restricted state space defined by the `dims` and `exciations` arguments. See the documentation for enr_fock for a more detailed description of these arguments. The temperature of each mode in dims is specified by the average number of excitatons `n`. Parameters ---------- dims : list A list of the dimensions of each subsystem of a composite quantum system. excitations : integer The maximum number of excitations that are to be included in the state space. n : integer The average number of exciations in the thermal state. `n` can be a float (which then applies to each mode), or a list/array of the same length as dims, in which each element corresponds specifies the temperature of the corresponding mode. Returns ------- dm : Qobj Thermal state density matrix. """ nstates, state2idx, idx2state = enr_state_dictionaries(dims, excitations) if not isinstance(n, (list, np.ndarray)): n = np.ones(len(dims)) * n else: n = np.asarray(n) diags = [np.prod((n / (n + 1))**np.array(state)) for state in idx2state] diags /= np.sum(diags) data = sp.spdiags(diags, 0, nstates, nstates, format='csr') return Qobj(data, dims=[dims, dims])
def toffoli(N=None, controls=[0, 1], target=2): """Quantum object representing the Toffoli gate. Returns ------- toff_gate : qobj Quantum object representation of Toffoli gate. Examples -------- >>> toffoli() Quantum object: dims = [[2, 2, 2], [2, 2, 2]], \ shape = [8, 8], type = oper, isHerm = True Qobj data = [[ 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j] [ 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j] [ 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j] [ 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j] [ 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j] [ 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j] [ 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j] [ 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j]] """ if [controls[0], controls[1], target] != [0, 1, 2] and N is None: N = 3 if N is not None: return gate_expand_3toN(toffoli(), N, controls, target) else: return Qobj([[1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 1, 0]], dims=[[2, 2, 2], [2, 2, 2]])
def snot(N=None, target=0): """Quantum object representing the SNOT (Hadamard) gate. Returns ------- snot_gate : qobj Quantum object representation of SNOT gate. Examples -------- >>> snot() # doctest: +SKIP Quantum object: dims = [[2], [2]], \ shape = [2, 2], type = oper, isHerm = True Qobj data = [[ 0.70710678+0.j 0.70710678+0.j] [ 0.70710678+0.j -0.70710678+0.j]] """ if N is not None: return gate_expand_1toN(snot(), N, target) return 1 / np.sqrt(2.0) * Qobj([[1, 1], [1, -1]])
def destroy_x(states): """ Destruction (lowering) operator for atomic excitations. Parameters ---------- states : array List of states of the Hilbert space. Returns ------- oper : qobj Qobj for destruction operator for atomic excitations. """ nstates = len(states) sigma = np.eye(nstates) for i in range(nstates): for j in range(nstates): sigma[i, j] = _destroy_excitons(states[i, 0], states[i, 1], states[j, 0], states[j, 1]) return Qobj(sp.csr_matrix(sigma, dtype=complex), isherm=False)
def _super_tofrom_choi(q_oper): """ We exploit that the basis transformation between Choi and supermatrix representations squares to the identity, so that if we munge Qobj.type, we can use the same function. Since this function doesn't respect :attr:`Qobj.type`, we mark it as private; only those functions which wrap this in a way so as to preserve type should be called externally. """ data = q_oper.data.toarray() dims = q_oper.dims new_dims = [[dims[1][1], dims[0][1]], [dims[1][0], dims[0][0]]] d0 = np.prod(np.ravel(new_dims[0])) d1 = np.prod(np.ravel(new_dims[1])) s0 = np.prod(dims[0][0]) s1 = np.prod(dims[1][1]) return Qobj(dims=new_dims, inpt=data.reshape([s0, s1, s0, s1]).transpose(3, 1, 2, 0).reshape( (d0, d1)))
def _steadystate_direct_dense(L): """ Direct solver that use numpy dense matrices. Suitable for small system, with a few states. """ if settings.debug: print('Starting direct dense solver...') dims = L.dims[0] n = prod(L.dims[0][0]) b = np.zeros(n**2) b[0] = 1.0 L = L.data.todense() L[0, :] = np.diag(np.ones(n)).reshape((1, n**2)) v = np.linalg.solve(L, b) data = vec2mat(v) data = 0.5 * (data + data.conj().T) return Qobj(data, dims=dims, isherm=True)
def maximally_mixed_dm(N): """ Returns the maximally mixed density matrix for a Hilbert space of dimension N. Parameters ---------- N : int Number of basis states in Hilbert space. Returns ------- dm : qobj Thermal state density matrix. """ if (not isinstance(N, (int, np.int64))) or N <= 0: raise ValueError("N must be integer N > 0") dm = sp.spdiags(np.ones(N, dtype=complex)/float(N), 0, N, N, format='csr') return Qobj(dm, isherm=True)
def _steadystate_power(L, maxiter=10, tol=1e-6, itertol=1e-5): """ Inverse power method for steady state solving. """ if settings.debug: print('Starting iterative power method Solver...') use_solver(assumeSortedIndices=True) rhoss = Qobj() sflag = issuper(L) if sflag: rhoss.dims = L.dims[0] else: rhoss.dims = [L.dims[0], 1] n = prod(rhoss.shape) L = L.data.tocsc() - (tol**2) * sp.eye(n, n, format='csc') L.sort_indices() v = mat2vec(rand_dm(rhoss.shape[0], 0.5 / rhoss.shape[0] + 0.5).full()) it = 0 while (la.norm(L * v, np.inf) > tol) and (it < maxiter): v = spsolve(L, v) v = v / la.norm(v, np.inf) it += 1 if it >= maxiter: raise Exception('Failed to find steady state after ' + str(maxiter) + ' iterations') # normalise according to type of problem if sflag: trow = sp.eye(rhoss.shape[0], rhoss.shape[0], format='coo') trow = sp_reshape(trow, (1, n)) data = v / sum(trow.dot(v)) else: data = data / la.norm(v) data = sp.csr_matrix(vec2mat(data)) rhoss.data = 0.5 * (data + data.conj().T) rhoss.isherm = True return rhoss.tidyup() if settings.auto_tidyup else rhoss
def test_NonSquareKrausSuperChoi(self): """ Superoperator: Convert non-square Kraus operator to Super + Choi matrix and back. """ zero = asarray([[1], [0]], dtype=complex) one = asarray([[0], [1]], dtype=complex) zero_log = kron(kron(zero, zero), zero) one_log = kron(kron(one, one), one) # non-square Kraus operator (isometry) kraus = Qobj(zero_log @ zero.T + one_log @ one.T) super = sprepost(kraus, kraus.dag()) choi = to_choi(super) op1 = to_kraus(super) op2 = to_kraus(choi) op3 = to_super(choi) assert choi.type == "super" and choi.superrep == "choi" assert super.type == "super" and super.superrep == "super" assert (op1[0] - kraus).norm() < tol assert (op2[0] - kraus).norm() < tol assert (op3 - super).norm() < tol
def sprepost(A, B): """Superoperator formed from pre-multiplication by operator A and post- multiplication of operator B. Parameters ---------- A : Qobj Quantum operator for pre-multiplication. B : Qobj Quantum operator for post-multiplication. Returns -------- super : Qobj Superoperator formed from input quantum objects. """ dims = [[_drop_projected_dims(A.dims[0]), _drop_projected_dims(B.dims[1])], [_drop_projected_dims(A.dims[1]), _drop_projected_dims(B.dims[0])]] data = sp.kron(B.data.T, A.data, format='csr') return Qobj(data, dims=dims, superrep='super')
def chi_to_choi(q_oper): """ Converts a Chi matrix to a Choi matrix. NOTE: this is only supported for qubits right now. Need to extend to Heisenberg-Weyl for other subsystem dimensions. """ nq = _nq(q_oper.dims) B = _pauli_basis(nq) # Force the basis change to match the dimensions of # the input. B.dims = q_oper.dims # We normally should not multiply objects of different # superreps, so Qobj warns about that. Here, however, we're actively # converting between, so the superrep of B is irrelevant. # To suppress warnings, we pretend that B is also a chi. B.superrep = 'chi' # The Chi matrix has tr(chi) == d², so we need to divide out # by that to get back to the Choi form. return Qobj((B * q_oper * B.dag()) / q_oper.shape[0], superrep='choi')
def _add_common_result_attribs(self, result, st_time, end_time): """ Update the result object attributes which are common to all optimisers and outcomes """ dyn = self.dynamics result.num_iter = self.num_iter result.num_fid_func_calls = self.num_fid_func_calls result.wall_time = end_time - st_time result.fid_err = dyn.fid_computer.get_fid_err() result.grad_norm_final = dyn.fid_computer.grad_norm result.final_amps = dyn.ctrl_amps final_evo = dyn.full_evo if isinstance(final_evo, Qobj): result.evo_full_final = final_evo else: result.evo_full_final = Qobj(final_evo, dims=dyn.sys_dims) # *** update stats *** if self.stats is not None: self.stats.wall_time_optim_end = end_time self.stats.calculate() result.stats = copy.copy(self.stats)
def extract(self, idx_or_label): """ Extract a Qobj representing specified ADO from a full representation of the ADO states. Parameters ---------- idx : int or label The index of the ADO to extract. If an ADO label, e.g. ``(0, 1, 0, ...)`` is supplied instead, then the ADO is extracted by label instead. Returns ------- Qobj A :obj:`Qobj` representing the state of the specified ADO. """ if isinstance(idx_or_label, int): idx = idx_or_label else: idx = self._ados.idx(idx_or_label) return Qobj(self._ado_state[idx, :].T, dims=self.rho.dims)
def _get_aug_mat(self, k, j): """ Generate the matrix [[A, E], [0, A]] where A is the overall dynamics generator E is the control dynamics generator for a given timeslot and control returns this augmented matrix """ dyn = self.parent dg = dyn._get_phased_dyn_gen(k) if dyn.oper_dtype == Qobj: A = dg.data * dyn.tau[k] E = dyn._get_phased_ctrl_dyn_gen(k, j).data * dyn.tau[k] Z = sp.csr_matrix(dg.data.shape) aug = Qobj(sp.vstack([sp.hstack([A, E]), sp.hstack([Z, A])])) else: A = dg * dyn.tau[k] E = dyn._get_phased_ctrl_dyn_gen(k, j) * dyn.tau[k] Z = np.zeros(dg.shape) aug = np.vstack([np.hstack([A, E]), np.hstack([Z, A])]) return aug
def get_states(self, nstep, ntraj): if debug: print(inspect.stack()[0][3]) from scipy.sparse import csr_matrix if (odeconfig.options.average_states): states = np.array([Qobj()] * nstep) if (self.sparse_dms): # averaged sparse density matrices for i in range(nstep): qtf90.qutraj_run.get_rho_sparse(i + 1) val = qtf90.qutraj_run.csr_val col = qtf90.qutraj_run.csr_col - 1 ptr = qtf90.qutraj_run.csr_ptr - 1 m = qtf90.qutraj_run.csr_nrows k = qtf90.qutraj_run.csr_ncols states[i] = Qobj(csr_matrix((val, col, ptr), (m, k)).toarray(), dims=self.dm_dims, shape=self.dm_shape) else: # averaged dense density matrices for i in range(nstep): states[i] = Qobj(qtf90.qutraj_run.sol[0, i, :, :], dims=self.dm_dims, shape=self.dm_shape) else: # all trajectories as kets if (ntraj == 1): states = np.array([Qobj()] * nstep) for i in range(nstep): states[i] = Qobj(numpy.matrix( qtf90.qutraj_run.sol[0, 0, i, :]).transpose(), dims=self.psi0_dims, shape=self.psi0_shape) else: states = np.array([np.array([Qobj()] * nstep)] * ntraj) for traj in range(ntraj): for i in range(nstep): states[traj][i] = Qobj(numpy.matrix( qtf90.qutraj_run.sol[0, traj, i, :]).transpose(), dims=self.psi0_dims, shape=self.psi0_shape) return states
def qzero(dimensions): """ Zero operator. Parameters ---------- dimensions : (int) or (list of int) or (list of list of int) Dimension of Hilbert space. If provided as a list of ints, then the dimension is the product over this list, but the ``dims`` property of the new Qobj are set to this list. This can produce either `oper` or `super` depending on the passed `dimensions`. Returns ------- qzero : qobj Zero operator Qobj. """ size, dimensions = _implicit_tensor_dimensions(dimensions) # A sparse matrix with no data is equal to a zero matrix. return Qobj(fast_csr_matrix(shape=(size, size), dtype=complex), dims=dimensions, isherm=True)
def _steadystate_direct_dense(L): """ Direct solver that use numpy dense matrices. Suitable for small system, with a few states. """ if settings.debug: print('Starting direct dense solver...') dims = L.dims[0] n = prod(L.dims[0][0]) b = np.zeros(n**2) b[0] = ss_args['weight'] L = L.data.todense() L[0, :] = np.diag(ss_args['weight'] * np.ones(n)).reshape((1, n**2)) _dense_start = time.time() v = np.linalg.solve(L, b) _dense_end = time.time() ss_args['info']['solution_time'] = _dense_end - _dense_start data = vec2mat(v) data = 0.5 * (data + data.conj().T) return Qobj(data, dims=dims, isherm=True)
def spre(A): """Superoperator formed from pre-multiplication by operator A. Parameters ---------- A : qobj Quantum operator for pre-multiplication. Returns -------- super :qobj Superoperator formed from input quantum object. """ if not isinstance(A, Qobj): raise TypeError('Input is not a quantum object') if not A.isoper: raise TypeError('Input is not a quantum operator') S = Qobj(isherm=A.isherm, superrep='super') S.dims = [[A.dims[0], A.dims[1]], [A.dims[0], A.dims[1]]] S.data = sp.kron(sp.identity(np.prod(A.shape[1])), A.data, format='csr') return S
def _partial_transpose_reference(rho, mask): """ This is a reference implementation that explicitly loops over all states and performs the transpose. It's slow but easy to understand and useful for testing. """ A_pt = np.zeros(rho.shape, dtype=complex) for psi_A in state_number_enumerate(rho.dims[0]): m = state_number_index(rho.dims[0], psi_A) for psi_B in state_number_enumerate(rho.dims[1]): n = state_number_index(rho.dims[1], psi_B) m_pt = state_number_index( rho.dims[1], np.choose(mask, [psi_A, psi_B])) n_pt = state_number_index( rho.dims[0], np.choose(mask, [psi_B, psi_A])) A_pt[m_pt, n_pt] = rho.data[m, n] return Qobj(A_pt, dims=rho.dims)
def destroy_a_1(states): """ Destruction (lowering) operator for photonic excitations. Parameters ---------- states : list/array List of states of the Hilbert space. Returns ------- oper : qobj Qobj for destruction operator for photonic excitations. """ nstates = len(states) a = np.eye(nstates) for i in range(nstates): for j in range(nstates): a[i, j] = _destroy_photons_1(states[i, 0], states[i, 1], states[i, 2], states[i, 3], states[j, 0], states[j, 1], states[j, 2], states[j, 3]) return Qobj(sp.csr_matrix(a, dtype=complex), isherm=False)
def spost(A): """Superoperator formed from post-multiplication by operator A Parameters ---------- A : qobj Quantum operator for post multiplication. Returns ------- super : qobj Superoperator formed from input qauntum object. """ if not isinstance(A, Qobj): raise TypeError('Input is not a quantum object') if not A.isoper: raise TypeError('Input is not a quantum operator') S = Qobj(isherm=A.isherm, superrep='super') S.dims = [[A.dims[0], A.dims[1]], [A.dims[0], A.dims[1]]] S.data = zcsr_kron(A.data.T, fast_identity(np.prod(A.shape[0]))) return S
def snot(): """Quantum object representing the SNOT (Hadamard) gate. Returns ------- snot_gate : qobj Quantum object representation of SNOT (Hadamard) gate. Examples -------- >>> snot() Quantum object: dims = [[2], [2]], \ shape = [2, 2], type = oper, isHerm = True Qobj data = [[ 0.70710678+0.j 0.70710678+0.j] [ 0.70710678+0.j -0.70710678+0.j]] """ u = qstate('u') d = qstate('d') Q = 1.0 / sqrt(2.0) * (d * d.dag() + u * d.dag() + d * u.dag() - u * u.dag()) return Qobj(Q)
def destroy(N, offset=0): '''Destruction (lowering) operator. Parameters ---------- N : int Dimension of Hilbert space. offset : int (default 0) The lowest number state that is included in the finite number state representation of the operator. Returns ------- oper : qobj Qobj for lowering operator. Examples -------- >>> destroy(4) Quantum object: dims = [[4], [4]], \ shape = [4, 4], type = oper, isHerm = False Qobj data = [[ 0.00000000+0.j 1.00000000+0.j 0.00000000+0.j 0.00000000+0.j] [ 0.00000000+0.j 0.00000000+0.j 1.41421356+0.j 0.00000000+0.j] [ 0.00000000+0.j 0.00000000+0.j 0.00000000+0.j 1.73205081+0.j] [ 0.00000000+0.j 0.00000000+0.j 0.00000000+0.j 0.00000000+0.j]] ''' if not isinstance(N, (int, np.integer)): # raise error if N not integer raise ValueError("Hilbert space dimension must be integer value") return Qobj(sp.spdiags(np.sqrt(range(offset, N + offset)), 1, N, N, format='csr'), isherm=False)
def swapalpha(alpha, N=None, targets=[0, 1]): """ Quantum object representing the SWAPalpha gate. Returns ------- swapalpha_gate : qobj Quantum object representation of SWAPalpha gate Examples -------- >>> swapalpha(alpha) Quantum object: dims = [[2, 2], [2, 2]], \ shape = [4, 4], type = oper, isHerm = True Qobj data = [[ 1.+0.j 0.+0.j 0.+0.j 0.+0.j] [ 0.+0.j 0.5*(1 + exp(j*pi*alpha) 0.5*(1 - exp(j*pi*alpha) 0.+0.j] [ 0.+0.j 0.5*(1 - exp(j*pi*alpha) 0.5*(1 + exp(j*pi*alpha) 0.+0.j] [ 0.+0.j 0.+0.j 0.+0.j 1.+0.j]] """ if (targets[0] == 1 and targets[1] == 0) and N is None: N = 2 if N is not None: return gate_expand_2toN(cnot(), N, targets=targets) else: return Qobj([[1, 0, 0, 0], [ 0, 0.5 * (1 + np.exp(1.0j * np.pi * alpha)), 0.5 * (1 - np.exp(1.0j * np.pi * alpha)), 0 ], [ 0, 0.5 * (1 - np.exp(1.0j * np.pi * alpha)), 0.5 * (1 + np.exp(1.0j * np.pi * alpha)), 0 ], [0, 0, 0, 1]], dims=[[2, 2], [2, 2]])