def measure(state): confs = list(itertools.product([0, 1], repeat=2)) probabilities = [] for m0, m1 in confs: P = qt.tensor([ qt.basis(2, m0).proj(), qt.basis(2, m1).proj(), qt.Qobj(np.eye(2)) ]) probabilities.append(np.real((state.dag() * P * state).full()[0][0])) return np.random.choice([0, 1, 2, 3], p=probabilities)
def transmon_hamiltonian(Ec=0.386, EjEc=45, nstates=8, ng=0.0, T=10.0): """Transmon Hamiltonian Args: Ec: capacitive energy EjEc: ratio `Ej` / `Ec` nstates: defines the maximum and minimum states for the basis. The truncated basis will have a total of ``2*nstates + 1`` states ng: offset charge T: gate duration """ Ej = EjEc * Ec n = np.arange(-nstates, nstates + 1) up = np.diag(np.ones(2 * nstates), k=-1) do = up.T H0 = qutip.Qobj(np.diag(4 * Ec * (n - ng)**2) - Ej * (up + do) / 2.0) H1 = qutip.Qobj(-2 * np.diag(n)) return [H0, [H1, eps0]]
def random_haar_effect(d, k=None, n=1, real=False): r""" Generates a Haar distributed random POVM effect of Hilbert space dimension $d$, as if it were part of a POVM of $k$ elements, with mixedness $n$. """ k = k if type(k) != type(None) else (d**2 if not real else int(d*(d+1)/2)) X = random_ginibre(d, n, real=real) W = X @ X.conjugate().T Y = random_ginibre(d, (k-1)*n, real=real) S = W + Y @ Y.conjugate().T S = sc.linalg.fractional_matrix_power(S, -1/2) return qt.Qobj(S @ W @ S.conjugate().T)
def plot_ST_bloch_sphere(self): mat = self.solver_obj.get_all_density_matrices()[:, 1:3, 1:3] k = np.linspace(0, len(mat) - 1, 100, dtype=np.int) b = qt.Bloch() b.xlabel = ['S', 'T'] b.ylabel = ['S+iT', 'S-iT'] b.zlabel = ['01', '10'] b.add_states(qt.Qobj(list(mat[0]))) b.add_states(qt.Qobj(list(mat[-1]))) x = [] y = [] z = [] for i in k: x.append(qt.expect(qt.sigmax(), qt.Qobj(list(mat[i])))) y.append(qt.expect(qt.sigmay(), qt.Qobj(list(mat[i])))) z.append(qt.expect(qt.sigmaz(), qt.Qobj(list(mat[i])))) b.add_points([x, y, z], meth='l') b.show()
def LMG_interaction_term(num_spins, g_value=1., total_j=None, symmetry_sector='first'): """Interaction term of the LMG Hamiltonian. Given in the standard form - g / 4N * Sx^2 """ if total_j is None: total_j = num_spins / 2 Jx_squared = Jx_operator(num_spins, total_j)**2 op = -g_value / (4 * num_spins) * Jx_squared if symmetry_sector == 'full': return op elif symmetry_sector == 'first': return qutip.Qobj(op.full()[::2, ::2]) elif symmetry_sector == 'second': return qutip.Qobj(op.full()[1::2, 1::2]) else: raise ValueError('Only accepted values are `full`, `first`, `second`.')
def to_majorana_basis(op, m): N = len(m) terms = [] for n in range(N + 1): if n == 0: terms.append(op.tr() / m[0].shape[0]) else: for pr in combinations(list(range(N)), n): s = reduce(lambda x, y: x * y, [m[p] for p in pr]) terms.append((s.dag() * op).tr() * 2**(n - 2)) return qt.Qobj(np.array(terms))
def get_partial_trace_mid(self, rho, n): """ calculates partial trace of middle n sites :param rho: full density matrix :param n: block size :return: reduced density matrix """ kept_sites = self.get_keep_indices(n) qutip_dm = qutip.Qobj(rho, dims=[[2] * self.N] * 2) reduced_dm_via_qutip = qutip_dm.ptrace(kept_sites).full() return reduced_dm_via_qutip
def pauli_S1(): '''Define pauli spin matrices for spin 1''' identity = qutip.qeye(3) sx = qutip.jmat(1, 'x') sy = qutip.jmat(1, 'y') sz = qutip.jmat(1, 'z') szPseudoHalf = qutip.Qobj( -1.0 * sz[1:, 1:]) # Take the effective two level system bit out of the S1 sz return identity, sx, sy, sz, szPseudoHalf
def coin_op(theta, xi): if type(theta) == np.ndarray: theta = theta[0] if type(xi) == np.ndarray: xi = xi[0] matrix = np.zeros((2, 2), dtype=np.complex128) matrix[0, 0] = np.cos(theta) * np.exp(1.j * xi) matrix[0, 1] = np.sin(theta) matrix[1, 0] = -np.sin(theta) matrix[1, 1] = np.cos(theta) * np.exp(-1.j * xi) return qutip.Qobj(matrix)
def test_two_level_detuning_positive(self): DETUNING = 10 f_dict = {'coupled_levels': [[0, 1]], 'detuning': DETUNING, 'detuning_positive': False} oba = ob_atom.OBAtom(num_states=2, fields=[f_dict]) H_Delta_test = qu.Qobj([[0., 0.], [0., 2*np.pi*DETUNING]]) np.testing.assert_array_almost_equal(oba.H_Delta.data.toarray(), H_Delta_test.data.toarray())
def random_altered_unitary_gate(delta,alpha,theta,beta,value): if delta == 0.0 and alpha == 0.0 and theta == math.pi and value == True: angles = ['delta','alpha','beta'] else: angles = ['delta','alpha','theta','beta'] altered_variable = choice(angles) if altered_variable == 'delta': delta = uniform(0.0,2.0*math.pi) if altered_variable == 'alpha': alpha = uniform(0.0,2.0*math.pi) if altered_variable == 'theta': theta = uniform(0.0,2.0*math.pi) if altered_variable == 'beta': beta = uniform(0.0,2.0*math.pi) gate = qt.Qobj(qt.phasegate(delta)*qt.rz(alpha)*qt.ry(theta)*qt.rz(beta)) if value == True: gate = gate *qt.Qobj([[0,1],[1,0]]) else: gate = gate return gate
def convert_opstring_to_qobj( operator: str, subsystem: Union["QubitBaseClass", "Oscillator"], evecs: Optional[np.ndarray], ) -> qt.Qobj: dim = subsystem.truncated_dim if evecs is None: _, evecs = subsystem.eigensys(evals_count=dim) operator_matrixelements = subsystem.matrixelement_table(operator, evecs=evecs) return qt.Qobj(inpt=operator_matrixelements)
def test_cell_periodic_parts(self): lattice = _crow_lattice(2, np.pi / 4) eigensystems = zip(lattice.get_dispersion()[1].T, lattice.cell_periodic_parts()[1]) hamiltonians = lattice.bulk_Hamiltonians()[1] for hamiltonian, system in zip(hamiltonians, eigensystems): for eigenvalue, eigenstate in zip(*system): eigenstate = qutip.Qobj(eigenstate) np.testing.assert_allclose((hamiltonian * eigenstate).full(), (eigenvalue * eigenstate).full(), atol=1e-12)
def trans_comp_to_pauli(self, rho_comp): """ Converts a rho in the computational basis, or comp basis vector or Qobj of rho in computational basis to Pauli basis. """ if(rho_comp.shape[0] == self.n_states): basis_decomposition = np.ravel(rho_comp.full()) if (type(rho_comp) == qt.Qobj) else np.ravel(rho_comp) else: basis_decomposition = rho_comp return qt.Qobj(np.reshape(self.basis_comp_to_pauli_trafo_matrix.dot(basis_decomposition), [self.n_states, self.n_states]), dims=self.qt_dims)
def load_fiducial(d): r""" Loads a Weyl-Heisenberg covariant SIC-POVM fiducial state of dimension $d$ from the repository provided here: http://www.physics.umb.edu/Research/QBism/solutions.html. """ f = pkg_resources.resource_stream(__name__, "sic_povms/d%d.txt" % d) fiducial = [] for line in f: if line.strip() != "": re, im = [float(v) for v in line.split()] fiducial.append(re + 1j * im) return qt.Qobj(np.array(fiducial)).unit()
def custom_gate(self, qubit, gate): """ Applies a custom gate to the qubit. Args: qubit(Qubit): Qubit to which the gate is applied. gate(np.ndarray): 2x2 array of the gate. """ gate = qutip.Qobj(gate) qubit_collection, name = qubit.qubit qubit_collection.apply_single_gate(gate, name)
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) H = p**2 + 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 return psi0, H, x, J, options
def test_complex_control_rejection(): """Test that complex controls are rejected""" H0 = qutip.Qobj(0.5 * np.diag([-1, 1])) H1 = qutip.Qobj(np.mat([[1, 2], [3, 4]])) psi0 = qutip.Qobj(np.array([1, 0])) psi1 = qutip.Qobj(np.array([0, 1])) def eps0(t, args): return 0.2 * np.exp(1j * t) 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' ) H = [H0, [H1, eps0]] objectives = [krotov.Objective(initial_state=psi0, target=psi1, H=H)] pulse_options = {H[1][1]: dict(lambda_a=5, update_shape=S)} tlist = np.linspace(0, 5, 500) with pytest.raises(ValueError) as exc_info: krotov.optimize_pulses( objectives, pulse_options, tlist, propagator=krotov.propagators.expm, chi_constructor=krotov.functionals.chis_re, iter_stop=0, ) assert 'all controls must be real-valued' in str(exc_info.value) def S2(t): """Shape function for the field update""" return 2.0 * krotov.shapes.flattop( t, t_start=0, t_stop=5, t_rise=0.3, t_fall=0.3, func='sinsq' )
def perm_mat(Q, order): dims, perm = qt.permute._perm_inds(Q.dims[0], order) nzs = Q.data.nonzero()[0] wh = np.where(perm == nzs)[0] data = np.ones(len(wh), dtype=int) cols = perm[wh].T[0] perm_matrix = sp.coo_matrix((data, (wh, cols)), shape=(Q.shape[0], Q.shape[0]), dtype=int) perm_matrix = qt.Qobj(perm_matrix.tocsr().todense()) perm_matrix.dims = [Q.dims[0], Q.dims[0]] return perm_matrix
def test_operator_between_cells(self): lattice_412 = qutip.Lattice1d(num_cell=4, boundary="periodic", cell_num_site=1, cell_site_dof=[2]) op = qutip.sigmax() op_sp = lattice_412.operator_at_cells(op, cells=[1, 2]) aop_sp = np.zeros((8, 8), dtype=complex) aop_sp[2:4, 2:4] = aop_sp[4:6, 4:6] = op.full() sv_op_sp = qutip.Qobj(aop_sp, dims=[[4, 2], [4, 2]]) assert op_sp == sv_op_sp
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 update_symbol_basis(self): n = len(self.vocabulary) for i in range(n): for j in range(n): term = n*self.cross_counts[i][j]/(self.counts[i]*self.counts[j]) if term == 0: self.concordance_matrix[i][j] = 0 else: self.concordance_matrix[i][j] = cmath.log(n*self.cross_counts[i][j]/(self.counts[i]*self.counts[j])) self.left_basis, self.diag, self.right_basis = np.linalg.svd(self.concordance_matrix) for i in range(n): self.symbol_basis[self.vocabulary[i]] = (self.diag[i]**2) * qt.tensor(qt.Qobj(self.left_basis[i]), qt.Qobj(self.right_basis[i]))
def _x_recalc_couplings(self, hamiltonian): """ Updates coupling terms based of beta_i-beta_j due to change in RI""" hamiltonian = np.array(hamiltonian) dims = self.dims for row in range(dims): for col in range(dims): if row != col and hamiltonian[row, col] != 0: db = hamiltonian[row, row] - hamiltonian[col, col] cij = hamiltonian[row, col] ceff = np.sqrt((db / 2)**2 + cij**2) hamiltonian[row, col] = ceff return qt.Qobj(hamiltonian)
def pro_avfid_superoperator_compsubspace_phasecorrected(U, L1, phases): """ Average process (gate) fidelity in the qubit computational subspace for two qutrits Leakage has to be taken into account, see Woods & Gambetta The phase is corrected with Z rotations considering both transmons as qubits """ Ucorrection = qtp.Qobj( [[np.exp(-1j * np.deg2rad(phases[0])), 0, 0, 0, 0, 0, 0, 0, 0], [0, np.exp(-1j * np.deg2rad(phases[1])), 0, 0, 0, 0, 0, 0, 0], [0, 0, np.exp(-1j * np.deg2rad(phases[0])), 0, 0, 0, 0, 0, 0], [0, 0, 0, np.exp(-1j * np.deg2rad(phases[2])), 0, 0, 0, 0, 0], [ 0, 0, 0, 0, np.exp(-1j * np.deg2rad(phases[3] - phases[-1])), 0, 0, 0, 0 ], [0, 0, 0, 0, 0, np.exp(-1j * np.deg2rad(phases[2])), 0, 0, 0], [0, 0, 0, 0, 0, 0, np.exp(-1j * np.deg2rad(phases[0])), 0, 0], [0, 0, 0, 0, 0, 0, 0, np.exp(-1j * np.deg2rad(phases[1])), 0], [0, 0, 0, 0, 0, 0, 0, 0, np.exp(-1j * np.deg2rad(phases[0]))]], type='oper', dims=[[3, 3], [3, 3]]) if U.type == 'oper': U = Ucorrection * U inner = U.dag() * U_target part_idx = [0, 1, 3, 4] # only computational subspace ptrace = 0 for i in part_idx: ptrace += inner[i, i] dim = 4 # 2 qubits comp subspace return np.real( ((np.abs(ptrace))**2 + dim * (1 - L1)) / (dim * (dim + 1))) elif U.type == 'super': U = qtp.to_super(Ucorrection) * U kraus_form = qtp.to_kraus(U) dim = 4 # 2 qubits in the computational subspace part_idx = [0, 1, 3, 4] # only computational subspace psum = 0 for A_k in kraus_form: ptrace = 0 inner = U_target_diffdims.dag( ) * A_k # otherwise dimension mismatch for i in part_idx: ptrace += inner[i, i] psum += (np.abs(ptrace))**2 return np.real((dim * (1 - L1) + psum) / (dim * (dim + 1)))
def g_0n(D, Num_max, NFock): """ returns a D-squeezed 0-ancilla """ r = np.log(1 / D) psi0 = qt.squeeze(NFock, r) * qt.basis(NFock, 0) psi = qt.Qobj() for n in np.arange(-Num_max, Num_max + 1): psi += np.exp(-2 * np.pi * D**2 * n**2) * qt.displace( NFock, n * np.sqrt(2 * np.pi)) * psi0 return psi.unit()
def kraus(self): if self._kraus is None: # compute kraus operators by doing Cholesky decomp of the POVM # elements. requires sksparse module from sksparse.cholmod import cholesky d = self._povm_elements[0].data.shape[0] reg = 1e-12 * scipy.sparse.identity(d) self._kraus = [ qt.Qobj(cholesky(a.data + reg).L()).dag() for a in self.povm_elements ] return self._kraus
def depolarizing_single_qubit(rho,p,c): # apply depolarizing to c'th qubit c with parameter p of state rho # Create Kraus operators A_0 = np.sqrt((1-3*p/4))*qt.identity(2) A_1 = np.sqrt(p/4)*qt.Qobj([[0,1], [1,0]]) A_2 = np.sqrt(p/4)*qt.Qobj([[0,-1j], [1j,0]]) A_3 = np.sqrt(p/4)*qt.Qobj([[1,0], [0,-1]]) # Collect Kraus operators kraus_terms = [A_0,A_1,A_2,A_3] # Apply Kraus operators to state rho rho_new = [] for ii in range(0,len(kraus_terms)): rho_new.append(apply_gate(rho,kraus_terms[ii],[c])) return sum(rho_new)
def _remove_global_phase(qobj): """ Return a new Qobj with the gauge fixed for the global phase. Explicitly, we set the first non-zero element to be purely real-positive. """ flat = qobj.full().flat.copy() for phase in flat: if phase != 0: # Fix the gauge for any global phase. flat = flat * np.exp(-1j * np.angle(phase)) break return qutip.Qobj(flat.reshape(qobj.shape), dims=qobj.dims)
def _ket_expaned_dims(qubit_state, expanded_dims): all_qubit_basis = list(product([0, 1], repeat=len(expanded_dims))) old_dims = qubit_state.dims[0] expanded_qubit_state = np.zeros(reduce(mul, expanded_dims, 1), dtype=np.complex128) for basis_state in all_qubit_basis: old_ind = np.ravel_multi_index(basis_state, old_dims) new_ind = np.ravel_multi_index(basis_state, expanded_dims) expanded_qubit_state[new_ind] = qubit_state[old_ind, 0] expanded_qubit_state.reshape((reduce(mul, expanded_dims, 1), 1)) return qutip.Qobj(expanded_qubit_state, dims=[expanded_dims, [1] * len(expanded_dims)])
def H(self, nlev=None): """The cavity Hamiltonian in its eigenbasis. Parameters ---------- nlev : int, optional The number of cavity eigenstates if different from `self.nlev`. Returns ------- :class:`qutip.Qobj` The Hamiltonian operator. """ return qt.Qobj(np.diag(self.levels(nlev=nlev)))