def test_ComplexSingleApply(self): """ Composite system, operator on Hilbert space. """ tol = 1e-12 rho_list = list(map(rand_dm, [2, 3, 2, 3, 2])) rho_input = tensor(rho_list) single_op = rand_unitary(3) analytic_result = rho_list analytic_result[1] = single_op * analytic_result[1] * single_op.dag() analytic_result[3] = single_op * analytic_result[3] * single_op.dag() analytic_result = tensor(analytic_result) naive_result = subsystem_apply(rho_input, single_op, [False, True, False, True, False], reference=True) naive_diff = (analytic_result - naive_result).data.todense() naive_diff_norm = norm(naive_diff) assert_( naive_diff_norm < tol, msg="ComplexSingle: naive_diff_norm {} " "is beyond tolerance {}".format(naive_diff_norm, tol), ) efficient_result = subsystem_apply(rho_input, single_op, [False, True, False, True, False]) efficient_diff = (efficient_result - analytic_result).data.todense() efficient_diff_norm = norm(efficient_diff) assert_( efficient_diff_norm < tol, msg="ComplexSingle: efficient_diff_norm {} " "is beyond tolerance {}".format(efficient_diff_norm, tol), )
def testExpandGate3toN_permutation(self): """ gates: expand 3 to 3 with permuTation (using toffoli) """ for _p in itertools.permutations([0, 1, 2]): controls, target = [_p[0], _p[1]], _p[2] controls = [1, 2] target = 0 p = [1, 2, 3] p[controls[0]] = 0 p[controls[1]] = 1 p[target] = 2 U = toffoli(N=3, controls=controls, target=target) ops = [basis(2, 0).dag(), basis(2, 0).dag(), identity(2)] P = tensor(ops[p[0]], ops[p[1]], ops[p[2]]) assert_(P * U * P.dag() == identity(2)) ops = [basis(2, 1).dag(), basis(2, 0).dag(), identity(2)] P = tensor(ops[p[0]], ops[p[1]], ops[p[2]]) assert_(P * U * P.dag() == identity(2)) ops = [basis(2, 0).dag(), basis(2, 1).dag(), identity(2)] P = tensor(ops[p[0]], ops[p[1]], ops[p[2]]) assert_(P * U * P.dag() == identity(2)) ops = [basis(2, 1).dag(), basis(2, 1).dag(), identity(2)] P = tensor(ops[p[0]], ops[p[1]], ops[p[2]]) assert_(P * U * P.dag() == sigmax())
def cnot(N=None, control=None, target=None): """ Quantum object representing the CNOT gate. Returns ------- cnot_gate : qobj Quantum object representation of CNOT gate Examples -------- >>> cnot() 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 1.+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 1.+0.j 0.+0.j]] """ if not N is None and not control is None and not target is None: return gate_expand_2toN(cnot(), N, control, target) else: uu = tensor(basis(2), basis(2)) ud = tensor(basis(2), basis(2, 1)) du = tensor(basis(2, 1), basis(2)) dd = tensor(basis(2, 1), basis(2, 1)) Q = uu * uu.dag() + ud * ud.dag() + dd * du.dag() + du * dd.dag() return Qobj(Q)
def test_ComplexSuperApply(self): """ Superoperator: Efficient numerics and reference return same result, acting on non-composite system """ rho_list = list(map(rand_dm, [2, 3, 2, 3, 2])) rho_input = tensor(rho_list) superop = kraus_to_super(rand_kraus_map(3)) analytic_result = rho_list analytic_result[1] = Qobj(vec2mat(superop.data.todense() * mat2vec(analytic_result[1].data.todense()))) analytic_result[3] = Qobj(vec2mat(superop.data.todense() * mat2vec(analytic_result[3].data.todense()))) analytic_result = tensor(analytic_result) naive_result = subsystem_apply(rho_input, superop, [False, True, False, True, False], reference=True) naive_diff = (analytic_result - naive_result).data.todense() assert_(norm(naive_diff) < 1e-12) efficient_result = subsystem_apply(rho_input, superop, [False, True, False, True, False]) efficient_diff = (efficient_result - analytic_result).data.todense() assert_(norm(efficient_diff) < 1e-12)
def entangling_power(U): """ Calculate the entangling power of a two-qubit gate U, which is zero of nonentangling gates and 1 and 2/9 for maximally entangling gates. Parameters ---------- U : qobj Qobj instance representing a two-qubit gate. Returns ------- ep : float The entanglement power of U (real number between 0 and 1) References: Explorations in Quantum Computing, Colin P. Williams (Springer, 2011) """ if not U.isoper: raise Exception("U must be an operator.") if U.dims != [[2, 2], [2, 2]]: raise Exception("U must be a two-qubit gate.") a = (tensor(U, U).dag() * swap(N=4, targets=[1, 3]) * tensor(U, U) * swap(N=4, targets=[1, 3])) b = (tensor(swap() * U, swap() * U).dag() * swap(N=4, targets=[1, 3]) * tensor(swap() * U, swap() * U) * swap(N=4, targets=[1, 3])) return 5.0/9 - 1.0/36 * (a.tr() + b.tr()).real
def _jc_liouvillian(N): from qutip.tensor import tensor from qutip.operators import destroy, qeye from qutip.superoperator import liouvillian wc = 1.0 * 2 * np.pi # cavity frequency wa = 1.0 * 2 * np.pi # atom frequency g = 0.05 * 2 * np.pi # coupling strength kappa = 0.005 # cavity dissipation rate gamma = 0.05 # atom dissipation rate n_th_a = 1 # temperature in frequency units use_rwa = 0 # operators a = tensor(destroy(N), qeye(2)) sm = tensor(qeye(N), destroy(2)) # Hamiltonian if use_rwa: H = wc * a.dag() * a + wa * sm.dag() * sm + g * (a.dag() * sm + a * sm.dag()) else: H = wc * a.dag() * a + wa * sm.dag() * sm + g * (a.dag() + a) * (sm + sm.dag()) c_op_list = [] rate = kappa * (1 + n_th_a) if rate > 0.0: c_op_list.append(np.sqrt(rate) * a) rate = kappa * n_th_a if rate > 0.0: c_op_list.append(np.sqrt(rate) * a.dag()) rate = gamma if rate > 0.0: c_op_list.append(np.sqrt(rate) * sm) return liouvillian(H, c_op_list)
def testExpandGate2toNSwap(self): """ gates: expand 2 to N (using swap) """ a, b = np.random.rand(), np.random.rand() k1 = (a * basis(2, 0) + b * basis(2, 1)).unit() c, d = np.random.rand(), np.random.rand() k2 = (c * basis(2, 0) + d * basis(2, 1)).unit() N = 6 kets = [rand_ket(2) for k in range(N)] for m in range(N): for n in set(range(N)) - {m}: psi_in = tensor([k1 if k == m else k2 if k == n else kets[k] for k in range(N)]) psi_out = tensor([k2 if k == m else k1 if k == n else kets[k] for k in range(N)]) targets = [m, n] G = swap(N, targets) psi_out = G * psi_in assert_((psi_out - G * psi_in).norm() < 1e-12)
def cnot(): """ Quantum object representing the CNOT gate. Returns ------- cnot_gate : qobj Quantum object representation of CNOT gate Examples -------- >>> cnot() 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 1.+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 1.+0.j 0.+0.j]] """ uu = tensor(basis(2),basis(2)) ud = tensor(basis(2),basis(2,1)) du = tensor(basis(2,1),basis(2)) dd = tensor(basis(2,1),basis(2,1)) Q = uu * uu.dag() + ud * ud.dag() + dd * du.dag() + du * dd.dag() return Qobj(Q)
def _subsystem_apply_reference(state, channel, mask): if isket(state): state = ket2dm(state) if isoper(channel): full_oper = tensor([channel if mask[j] else qeye(state.dims[0][j]) for j in range(len(state.dims[0]))]) return full_oper * state * full_oper.dag() else: # Go to Choi, then Kraus # chan_mat = array(channel.data.todense()) choi_matrix = super_to_choi(channel) vals, vecs = eig(choi_matrix.full()) vecs = list(map(array, zip(*vecs))) kraus_list = [sqrt(vals[j]) * vec2mat(vecs[j]) for j in range(len(vals))] # Kraus operators to be padded with identities: k_qubit_kraus_list = product(kraus_list, repeat=sum(mask)) rho_out = Qobj(inpt=zeros(state.shape), dims=state.dims) for operator_iter in k_qubit_kraus_list: operator_iter = iter(operator_iter) op_iter_list = [next(operator_iter).conj().T if mask[j] else qeye(state.dims[0][j]) for j in range(len(state.dims[0]))] full_oper = tensor(list(map(Qobj, op_iter_list))) rho_out = rho_out + full_oper * state * full_oper.dag() return Qobj(rho_out)
def testExpandGate1toN(self): """ gates: expand 1 to N """ N = 7 for g in [rx, ry, rz, phasegate]: theta = np.random.rand() * 2 * 3.1415 a, b = np.random.rand(), np.random.rand() psi1 = (a * basis(2, 0) + b * basis(2, 1)).unit() psi2 = g(theta) * psi1 psi_rand_list = [rand_ket(2) for k in range(N)] for m in range(N): psi_in = tensor([psi1 if k == m else psi_rand_list[k] for k in range(N)]) psi_out = tensor([psi2 if k == m else psi_rand_list[k] for k in range(N)]) G = g(theta, N, m) psi_res = G * psi_in assert_((psi_out - psi_res).norm() < 1e-12)
def controlled_gate(U, N=2, control=0, target=1, control_value=1): """ Create an N-qubit controlled gate from a single-qubit gate U with the given control and target qubits. Parameters ---------- U : Qobj Arbitrary single-qubit gate. N : integer The number of qubits in the target space. control : integer The index of the first control qubit. target : integer The index of the target qubit. control_value : integer (1) The state of the control qubit that activates the gate U. Returns ------- result : qobj Quantum object representing the controlled-U gate. """ if [N, control, target] == [2, 0, 1]: return (tensor(fock_dm(2, control_value), U) + tensor(fock_dm(2, 1 - control_value), identity(2))) else: U2 = controlled_gate(U, control_value=control_value) return gate_expand_2toN(U2, N=N, control=control, target=target)
def choi_to_stinespring(q_oper, thresh=1e-10): # TODO: document! kU, kV = _generalized_kraus(q_oper, thresh=thresh) assert(len(kU) == len(kV)) dK = len(kU) dL = kU[0].shape[0] dR = kV[0].shape[1] # Also remember the dims breakout. out_dims, in_dims = q_oper.dims out_left, out_right = out_dims in_left, in_right = in_dims A = Qobj(zeros((dK * dL, dL)), dims=[out_left + [dK], out_right + [1]]) B = Qobj(zeros((dK * dR, dR)), dims=[in_left + [dK], in_right + [1]]) for idx_kraus, (KL, KR) in enumerate(zip(kU, kV)): A += tensor(KL, basis(dK, idx_kraus)) B += tensor(KR, basis(dK, idx_kraus)) # There is no input (right) Kraus index, so strip that off. del A.dims[1][-1] del B.dims[1][-1] return A, B
def __init__(self,N,state=None): #construct register intial state if state==None: reg=tensor([basis(2) for k in range(N)]) if isinstance(state,str): state=_reg_str2array(state,N) reg=tensor([basis(2,state[k]) for k in state]) Qobj.__init__(self, reg.data, reg.dims, reg.shape, reg.type, reg.isherm, fast=False)
def __init__(self, N, state=None): # construct register intial state if state is None: reg = tensor([basis(2) for k in range(N)]) elif isinstance(state, str): state = _reg_str2array(state, N) reg = tensor([basis(2, k) for k in state]) else: raise ValueError("state must be a string") Qobj.__init__(self, reg.data, reg.dims, reg.isherm)
def __init__(self, N, correct_global_phase=True, sx=None, sz=None, sxsy=None): """ Parameters ---------- sx: Integer/List The delta for each of the qubits in the system. sz: Integer/List The epsilon for each of the qubits in the system. sxsy: Integer/List The interaction strength for each of the qubit pair in the system. """ super(SpinChain, self).__init__(N, correct_global_phase) self.sx_ops = [tensor([sigmax() if m == n else identity(2) for n in range(N)]) for m in range(N)] self.sz_ops = [tensor([sigmaz() if m == n else identity(2) for n in range(N)]) for m in range(N)] self.sxsy_ops = [] for n in range(N - 1): x = [identity(2)] * N x[n] = x[n + 1] = sigmax() y = [identity(2)] * N y[n] = y[n + 1] = sigmay() self.sxsy_ops.append(tensor(x) + tensor(y)) if sx is None: self.sx_coeff = [0.25 * 2 * np.pi] * N elif not isinstance(sx, list): self.sx_coeff = [sx * 2 * np.pi] * N else: self.sx_coeff = sx if sz is None: self.sz_coeff = [1.0 * 2 * np.pi] * N elif not isinstance(sz, list): self.sz_coeff = [sz * 2 * np.pi] * N else: self.sz_coeff = sz if sxsy is None: self.sxsy_coeff = [0.1 * 2 * np.pi] * (N - 1) elif not isinstance(sxsy, list): self.sxsy_coeff = [sxsy * 2 * np.pi] * (N - 1) else: self.sxsy_coeff = sxsy
def testExpandGate3toN(self): """ gates: expand 3 to N (using toffoli, fredkin, and random 3 qubit gate) """ a, b = np.random.rand(), np.random.rand() psi1 = (a * basis(2, 0) + b * basis(2, 1)).unit() c, d = np.random.rand(), np.random.rand() psi2 = (c * basis(2, 0) + d * basis(2, 1)).unit() e, f = np.random.rand(), np.random.rand() psi3 = (e * basis(2, 0) + f * basis(2, 1)).unit() N = 4 psi_rand_list = [rand_ket(2) for k in range(N)] _rand_gate_U = tensor([rand_herm(2, density=1) for k in range(3)]) def _rand_3qubit_gate(N=None, controls=None, k=None): if N is None: return _rand_gate_U else: return gate_expand_3toN(_rand_gate_U, N, controls, k) for g in [fredkin, toffoli, _rand_3qubit_gate]: psi_ref_in = tensor(psi1, psi2, psi3) psi_ref_out = g() * psi_ref_in for m in range(N): for n in set(range(N)) - {m}: for k in set(range(N)) - {m, n}: psi_list = [psi_rand_list[p] for p in range(N)] psi_list[m] = psi1 psi_list[n] = psi2 psi_list[k] = psi3 psi_in = tensor(psi_list) if g == fredkin: targets = [n, k] G = g(N, control=m, targets=targets) else: controls = [m, n] G = g(N, controls, k) psi_out = G * psi_in o1 = psi_out.overlap(psi_in) o2 = psi_ref_out.overlap(psi_ref_in) assert_(abs(o1 - o2) < 1e-12)
def bell_state(state='00'): """ Returns the Bell state: |B00> = 1 / sqrt(2)*[|0>|0>+|1>|1>] |B01> = 1 / sqrt(2)*[|0>|0>-|1>|1>] |B10> = 1 / sqrt(2)*[|0>|1>+|1>|0>] |B11> = 1 / sqrt(2)*[|0>|1>-|1>|0>] Returns ------- Bell_state : qobj Bell state """ if state == '00': Bell_state = tensor( basis(2), basis(2))+tensor(basis(2, 1), basis(2, 1)) elif state == '01': Bell_state = tensor( basis(2), basis(2))-tensor(basis(2, 1), basis(2, 1)) elif state == '10': Bell_state = tensor( basis(2), basis(2, 1))+tensor(basis(2, 1), basis(2)) elif state == '11': Bell_state = tensor( basis(2), basis(2, 1))-tensor(basis(2, 1), basis(2)) return Bell_state.unit()
def bell_state11(): """ Returns the B11 Bell state: |B11>=1/sqrt(2)*[|0>|1>-|1>|0>] Returns ------- B11 : qobj B11 Bell state """ B=tensor(basis(2),basis(2,1))-tensor(basis(2,1),basis(2)) return B.unit()
def test_QobjPermute(): "Qobj permute" A = basis(5, 0) B = basis(5, 4) C = basis(5, 2) psi = tensor(A, B, C) psi2 = psi.permute([2, 0, 1]) assert_(psi2 == tensor(C, A, B)) A = fock_dm(5, 0) B = fock_dm(5, 4) C = fock_dm(5, 2) rho = tensor(A, B, C) rho2 = rho.permute([2, 0, 1]) assert_(rho2 == tensor(C, A, B)) for ii in range(3): A = rand_ket(5) B = rand_ket(5) C = rand_ket(5) psi = tensor(A, B, C) psi2 = psi.permute([1, 0, 2]) assert_(psi2 == tensor(B, A, C)) for ii in range(3): A = rand_dm(5) B = rand_dm(5) C = rand_dm(5) rho = tensor(A, B, C) rho2 = rho.permute([1, 0, 2]) assert_(rho2 == tensor(B, A, C))
def bell_state10(): """ Returns the B10 Bell state: |B10>=1/sqrt(2)*[|0>|1>+|1>|0>] Returns ------- B10 : qobj B10 Bell state """ B=tensor(basis(2),basis(2,1))+tensor(basis(2,1),basis(2)) return B.unit()
def _spin_hamiltonian(N): from qutip.tensor import tensor from qutip.operators import qeye, sigmax, sigmay, sigmaz # array of spin energy splittings and coupling strengths. here we use # uniform parameters, but in general we don't have too h = 1.0 * 2 * np.pi * np.ones(N) Jz = 0.1 * 2 * np.pi * np.ones(N) Jx = 0.1 * 2 * np.pi * np.ones(N) Jy = 0.1 * 2 * np.pi * np.ones(N) # dephasing rate gamma = 0.01 * np.ones(N) si = qeye(2) sx = sigmax() sy = sigmay() sz = sigmaz() sx_list = [] sy_list = [] sz_list = [] for n in range(N): op_list = [] for m in range(N): op_list.append(si) op_list[n] = sx sx_list.append(tensor(op_list)) op_list[n] = sy sy_list.append(tensor(op_list)) op_list[n] = sz sz_list.append(tensor(op_list)) # construct the hamiltonian H = 0 # energy splitting terms for n in range(N): H += - 0.5 * h[n] * sz_list[n] # interaction terms for n in range(N-1): H += - 0.5 * Jx[n] * sx_list[n] * sx_list[n+1] H += - 0.5 * Jy[n] * sy_list[n] * sy_list[n+1] H += - 0.5 * Jz[n] * sz_list[n] * sz_list[n+1] return H
def gate_expand_1toN(U, N, target): """ Create a Qobj representing a one-qubit gate that act on a system with N qubits. Parameters ---------- U : Qobj The one-qubit gate N : integer The number of qubits in the target space. target : integer The index of the target qubit. Returns ------- gate : qobj Quantum object representation of N-qubit gate. """ if N < 1: raise ValueError("integer N must be larger or equal to 1") if target >= N: raise ValueError("target must be integer < integer N") return tensor([identity(2)] * (target) + [U] + [identity(2)] * (N - target - 1))
def qeye(N): """ Identity operator Parameters ---------- N : int or list of ints 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. Returns ------- oper : qobj Identity operator Qobj. Examples -------- >>> qeye(3) Quantum object: dims = [[3], [3]], \ shape = [3, 3], type = oper, isHerm = True Qobj data = [[ 1. 0. 0.] [ 0. 1. 0.] [ 0. 0. 1.]] """ if isinstance(N, list): return tensor(*[identity(n) for n in N]) N = int(N) if N < 0: raise ValueError("N must be integer N>=0") return Qobj(fast_identity(N), isherm=True, isunitary=True)
def qpt(U, op_basis_list): """ Calculate the quantum process tomography chi matrix for a given (possibly nonunitary) transformation matrix U, which transforms a density matrix in vector form according to: vec(rho) = U * vec(rho0) or rho = vec2mat(U * mat2vec(rho0)) U can be calculated for an open quantum system using the QuTiP propagator function. """ E_ops = [] # loop over all index permutations for inds in index_permutations([len(op_list) for op_list in op_basis_list]): # loop over all composite systems E_op_list = [op_basis_list[k][inds[k]] for k in range(len(op_basis_list))] E_ops.append(tensor(E_op_list)) EE_ops = [spre(E1) * spost(E2.dag()) for E1 in E_ops for E2 in E_ops] M = hstack([mat2vec(EE.full()) for EE in EE_ops]) Uvec = mat2vec(U.full()) chi_vec = la.solve(M, Uvec) return vec2mat(chi_vec)
def concurrence(rho): """ Calculate the concurrence entanglement measure for a two-qubit state. Parameters ---------- rho : qobj Density matrix for two-qubits. Returns ------- concur : float Concurrence """ if rho.dims != [[2, 2], [2, 2]]: raise Exception("Density matrix must be tensor product of two qubits.") sysy = tensor(sigmay(), sigmay()) rho_tilde = (rho * sysy) * (rho.conj() * sysy) evals = rho_tilde.eigenenergies() # abs to avoid problems with sqrt for very small negative numbers evals = abs(sort(real(evals))) lsum = sqrt(evals[3]) - sqrt(evals[2]) - sqrt(evals[1]) - sqrt(evals[0]) return max(0, lsum)
def qubit_states(N=1, states=[0]): """ Function to define initial state of the qubits. Parameters ---------- N: Integer Number of qubits in the register. states: List Initial state of each qubit. Returns ---------- qstates: Qobj List of qubits. """ state_list = [] for i in range(N): if N > len(states) and i >= len(states): state_list.append(0) else: state_list.append(states[i]) return tensor(alpha * basis(2, 0) + sqrt(1 - alpha**2) * basis(2, 1) for alpha in state_list)
def ghz_state(N=3): """ Returns the N-qubit GHZ-state. Parameters ---------- N : int (default=3) Number of qubits in state Returns ------- G : qobj N-qubit GHZ-state """ state=tensor([basis(2) for k in range(N)])+tensor([basis(2,1) for k in range(N)]) return state/np.sqrt(2)
def gate_expand_2toN(U, N, control=None, target=None, targets=None): """ Create a Qobj representing a two-qubit gate that act on a system with N qubits. Parameters ---------- U : Qobj The two-qubit gate N : integer The number of qubits in the target space. control : integer The index of the control qubit. target : integer The index of the target qubit. targets : list List of target qubits. Returns ------- gate : qobj Quantum object representation of N-qubit gate. """ if targets is not None: control, target = targets if control is None or target is None: raise ValueError("Specify value of control and target") if N < 2: raise ValueError("integer N must be larger or equal to 2") if control >= N or target >= N: raise ValueError("control and not target must be integer < integer N") if control == target: raise ValueError("target and not control cannot be equal") p = list(range(N)) if target == 0 and control == 1: p[control], p[target] = p[target], p[control] elif target == 0: p[1], p[target] = p[target], p[1] p[1], p[control] = p[control], p[1] else: p[1], p[target] = p[target], p[1] p[0], p[control] = p[control], p[0] return tensor([U] + [identity(2)] * (N - 2)).permute(p)
def test_isherm_skew(): """ mul and tensor of skew-Hermitian operators report ``isherm = True``. """ iH = 1j * rand_herm(5) assert_(not iH.isherm) assert_((iH * iH).isherm) assert_(tensor(iH, iH).isherm)
def testSwapGate(self): """ gates: swap gate """ a, b = np.random.rand(), np.random.rand() psi1 = (a * basis(2, 0) + b * basis(2, 1)).unit() c, d = np.random.rand(), np.random.rand() psi2 = (c * basis(2, 0) + d * basis(2, 1)).unit() psi_in = tensor(psi1, psi2) psi_out = tensor(psi2, psi1) psi_res = swap() * psi_in assert_((psi_out - psi_res).norm() < 1e-12) psi_res = swap() * swap() * psi_in assert_((psi_in - psi_res).norm() < 1e-12)
def test_projection(): """ Test Qobj: Projection operator """ for kk in range(10): N = 5 K = tensor(rand_ket(N, 0.75), rand_ket(N, 0.75)) B = K.dag() ans = K * K.dag() out1 = K.proj() out2 = B.proj() assert_(out1 == ans) assert_(out2 == ans)
def test_composite_vec(): """ Composite: Tests compositing states and density operators. """ k1 = rand_ket(5) k2 = rand_ket(7) r1 = operator_to_vector(ket2dm(k1)) r2 = operator_to_vector(ket2dm(k2)) r3 = operator_to_vector(rand_dm(3)) r4 = operator_to_vector(rand_dm(4)) assert composite(k1, k2) == tensor(k1, k2) assert composite(r3, r4) == super_tensor(r3, r4) assert composite(k1, r4) == super_tensor(r1, r4) assert composite(r3, k2) == super_tensor(r3, r2)
def test_composite_oper(): """ Composite: Tests compositing unitaries and superoperators. """ U1 = rand_unitary(3) U2 = rand_unitary(5) S1 = to_super(U1) S2 = to_super(U2) S3 = rand_super(4) S4 = rand_super(7) assert composite(U1, U2) == tensor(U1, U2) assert composite(S3, S4) == super_tensor(S3, S4) assert composite(U1, S4) == super_tensor(S1, S4) assert composite(S3, U2) == super_tensor(S3, S2)
def test_BraType(): "Qobj bra type" psi = basis(2, 1).dag() assert not psi.isket assert psi.isbra assert not psi.isoper assert not psi.issuper psi = tensor(basis(2, 1).dag(), basis(2, 0).dag()) assert not psi.isket assert psi.isbra assert not psi.isoper assert not psi.issuper
def simple(eflag=True,time=pi/dr): # # evolve and system subject to the time-dependent hamiltonian # c_op_list = [] if eflag: c_op_list.append(sqrt(gamma)*tensor(sm,qeye(2))) output = [] timelist = linspace(0,time,1000) rho0 = ps0 * ps0.dag() for tlist in chunks(timelist, 100): out = mesolve(Hs,rho0,tlist,c_op_list,[],args) output += out.states rho0 = output[-1] return output
def test_KetType(): "Qobj ket type" psi = basis(2, 1) assert_(psi.isket) assert_(not psi.isbra) assert_(not psi.isoper) assert_(not psi.issuper) psi = tensor(basis(2, 1), basis(2, 0)) assert_(psi.isket) assert_(not psi.isbra) assert_(not psi.isoper) assert_(not psi.issuper)
def test_KetType(): "Qobj ket type" psi = basis(2, 1) assert psi.isket assert not psi.isbra assert not psi.isoper assert not psi.issuper psi = tensor(basis(2, 1), basis(2, 0)) assert psi.isket assert not psi.isbra assert not psi.isoper assert not psi.issuper
def test_BraType(): "Qobj bra type" psi = basis(2, 1).dag() assert_equal(psi.isket, False) assert_equal(psi.isbra, True) assert_equal(psi.isoper, False) assert_equal(psi.issuper, False) psi = tensor(basis(2, 1).dag(), basis(2, 0).dag()) assert_equal(psi.isket, False) assert_equal(psi.isbra, True) assert_equal(psi.isoper, False) assert_equal(psi.issuper, False)
def qstate(string): r"""Creates a tensor product for a set of qubits in either the 'up' :math:`\lvert0\rangle` or 'down' :math:`\lvert1\rangle` state. Parameters ---------- string : str String containing 'u' or 'd' for each qubit (ex. 'ududd') Returns ------- qstate : qobj Qobj for tensor product corresponding to input string. Notes ----- Look at ket and bra for more general functions creating multiparticle states. Examples -------- >>> qstate('udu') # doctest: +SKIP Quantum object: dims = [[2, 2, 2], [1, 1, 1]], shape = [8, 1], type = ket Qobj data = [[ 0.] [ 0.] [ 0.] [ 0.] [ 0.] [ 1.] [ 0.] [ 0.]] """ n = len(string) if n != (string.count('u') + string.count('d')): raise TypeError('String input to QSTATE must consist ' + 'of "u" and "d" elements only') else: up = basis(2, 1) dn = basis(2, 0) lst = [] for k in range(n): if string[k] == 'u': lst.append(up) else: lst.append(dn) return tensor(lst)
def dst_measurement(state1, state2, sample_size=1): """destructive swap test""" N = len(state1.dims[0]) if len(state2.dims[0]) != N: raise ValueError("Dimensions of states dismatch.") statein = tensor(state1, state2) stateout = statein.transform( gate_sequence_product(bell_prep(N, True).propagators())) prob = com_measure(stateout) result_in_number = np.random.choice(4**N, sample_size, p=prob) mresult = [ state_index_number(stateout.dims[0], result) for result in result_in_number ] return mresult # raw output
def concurrence(rho): """ Calculate the concurrence entanglement measure for a two-qubit state. Parameters ---------- state : qobj Ket, bra, or density matrix for a two-qubit state. Returns ------- concur : float Concurrence References ---------- .. [1] http://en.wikipedia.org/wiki/Concurrence_(quantum_computing) """ if rho.isket and rho.dims != [[2, 2], [1, 1]]: raise Exception("Ket must be tensor product of two qubits.") elif rho.isbra and rho.dims != [[1, 1], [2, 2]]: raise Exception("Bra must be tensor product of two qubits.") elif rho.isoper and rho.dims != [[2, 2], [2, 2]]: raise Exception("Density matrix must be tensor product of two qubits.") if rho.isket or rho.isbra: rho = ket2dm(rho) sysy = tensor(sigmay(), sigmay()) rho_tilde = (rho * sysy) * (rho.conj() * sysy) evals = rho_tilde.eigenenergies() # abs to avoid problems with sqrt for very small negative numbers evals = abs(sort(real(evals))) lsum = sqrt(evals[3]) - sqrt(evals[2]) - sqrt(evals[1]) - sqrt(evals[0]) return max(0, lsum)
def test_molmer_sorensen(self): """ gate: test for the molmer_sorensen gate """ assert_allclose(molmer_sorensen(np.pi, targets=[0, 1]), Qobj(-1j * np.array([[0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0]]), dims=[[2, 2], [2, 2]]), atol=1e-15) assert_allclose(molmer_sorensen(2 * np.pi, targets=[0, 1]), Qobj(-np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]), dims=[[2, 2], [2, 2]]), atol=1e-15) assert_allclose( molmer_sorensen(np.pi / 2, N=4, targets=[1, 2]), tensor([identity(2), molmer_sorensen(np.pi / 2), identity(2)]))
def qstate(string): """Creates a tensor product for a set of qubits in either the 'up' :math:`|0>` or 'down' :math:`|1>` state. Parameters ---------- string : str String containing 'u' or 'd' for each qubit (ex. 'ududd') Returns ------- qstate : qobj Qobj for tensor product corresponding to input string. Examples -------- >>> qstate('udu') Quantum object: dims = [[2, 2, 2], [1, 1, 1]], shape = [8, 1], type = ket Qobj data = [[ 0.] [ 0.] [ 0.] [ 0.] [ 0.] [ 1.] [ 0.] [ 0.]] """ n = len(string) if n != (string.count('u') + string.count('d')): raise TypeError( 'String input to QSTATE must consist of "u" and "d" elements only') else: up = basis(2, 1) dn = basis(2, 0) lst = [] for k in range(n): if string[k] == 'u': lst.append(up) else: lst.append(dn) return tensor(lst)
def state_number_qobj(dims, state): """ Return a Qobj representation of a quantum state specified by the state array `state`. Example: >>> state_number_qobj([2,2,2], [1,0,1]) Quantum object: dims = [[2, 2, 2], [1, 1, 1]], shape = [8, 1], type = ket Qobj data = [[ 0.] [ 0.] [ 0.] [ 0.] [ 0.] [ 1.] [ 0.] [ 0.]] """ return tensor([fock(dims[i], s) for i, s in enumerate(state)])
def TestRelaxationNoise(self): """ Test for the relaxation noise """ a = destroy(2) relnoise = RelaxationNoise(t1=[1., 1., 1.], t2=None) noise_list = relnoise.get_noise(3) assert_(len(noise_list) == 3) assert_allclose(noise_list[1], tensor([qeye(2), a, qeye(2)])) relnoise = RelaxationNoise(t1=None, t2=None) noise_list = relnoise.get_noise(2) assert_(len(noise_list) == 0) relnoise = RelaxationNoise(t1=None, t2=[0.2, 0.7]) noise_list = relnoise.get_noise(2) assert_(len(noise_list) == 2) relnoise = RelaxationNoise(t1=[1., 1.], t2=[0.5, 0.5]) noise_list = relnoise.get_noise(2) assert_(len(noise_list) == 4)
def exper(eflag=True,cflag=True,time=pi/dr): # # evolve and system subject to the time-dependent hamiltonian # c_op_list = [] gamma = 0.001 if eflag: c_op_list.append(sqrt(gamma)*tensor(sm,qeye(2),qeye(2))) output = [] timelist = linspace(0,time,1000) rho0 = p0 * p0.dag() for tlist in chunks(timelist, 100): out = mesolve(Ht,rho0,tlist,c_op_list,[],args) output += out.states if cflag: rho0 = correct(output[-1]) else: rho0 = output[-1] return output
def bell_state(state='00'): r""" Returns the selected Bell state: .. math:: \begin{aligned} \lvert B_{00}\rangle &= \frac1{\sqrt2}(\lvert00\rangle+\lvert11\rangle)\\ \lvert B_{01}\rangle &= \frac1{\sqrt2}(\lvert00\rangle-\lvert11\rangle)\\ \lvert B_{10}\rangle &= \frac1{\sqrt2}(\lvert01\rangle+\lvert10\rangle)\\ \lvert B_{11}\rangle &= \frac1{\sqrt2}(\lvert01\rangle-\lvert10\rangle)\\ \end{aligned} Returns ------- Bell_state : qobj Bell state """ if state == '00': Bell_state = tensor(basis(2), basis(2)) + tensor( basis(2, 1), basis(2, 1)) elif state == '01': Bell_state = tensor(basis(2), basis(2)) - tensor( basis(2, 1), basis(2, 1)) elif state == '10': Bell_state = tensor(basis(2), basis(2, 1)) + tensor( basis(2, 1), basis(2)) elif state == '11': Bell_state = tensor(basis(2), basis(2, 1)) - tensor( basis(2, 1), basis(2)) return Bell_state.unit()
def test_relaxation_noise(self): """ Test for the relaxation noise """ # only t1 a = destroy(2) dims = [2] * 3 relnoise = RelaxationNoise(t1=[1., 1., 1.], t2=None) systematic_noise = Pulse(None, None, label="system") pulses, systematic_noise = relnoise.get_noisy_dynamics( dims=dims, systematic_noise=systematic_noise) noisy_qu, c_ops = systematic_noise.get_noisy_qobjevo(dims=dims) assert_(len(c_ops) == 3) assert_allclose(c_ops[1].cte, tensor([qeye(2), a, qeye(2)])) # no relaxation dims = [2] * 2 relnoise = RelaxationNoise(t1=None, t2=None) systematic_noise = Pulse(None, None, label="system") pulses, systematic_noise = relnoise.get_noisy_dynamics( dims=dims, systematic_noise=systematic_noise) noisy_qu, c_ops = systematic_noise.get_noisy_qobjevo(dims=dims) assert_(len(c_ops) == 0) # only t2 relnoise = RelaxationNoise(t1=None, t2=[0.2, 0.7]) systematic_noise = Pulse(None, None, label="system") pulses, systematic_noise = relnoise.get_noisy_dynamics( dims=dims, systematic_noise=systematic_noise) noisy_qu, c_ops = systematic_noise.get_noisy_qobjevo(dims=dims) assert_(len(c_ops) == 2) # t1+t2 and systematic_noise = None relnoise = RelaxationNoise(t1=[1., 1.], t2=[0.5, 0.5]) pulses, systematic_noise = relnoise.get_noisy_dynamics(dims=dims) noisy_qu, c_ops = systematic_noise.get_noisy_qobjevo(dims=dims) assert_(len(c_ops) == 4)
def _spectrum_pi(H, wlist, c_ops, a_op, b_op, use_pinv=False): """ Internal function for calculating the spectrum of the correlation function :math:`\left<A(\\tau)B(0)\\right>`. """ L = H if issuper(H) else liouvillian(H, c_ops) tr_mat = tensor([qeye(n) for n in L.dims[0][0]]) N = np.prod(L.dims[0][0]) A = L.full() b = spre(b_op).full() a = spre(a_op).full() tr_vec = np.transpose(mat2vec(tr_mat.full())) rho_ss = steadystate(L) rho = np.transpose(mat2vec(rho_ss.full())) I = np.identity(N * N) P = np.kron(np.transpose(rho), tr_vec) Q = I - P spectrum = np.zeros(len(wlist)) for idx, w in enumerate(wlist): if use_pinv: MMR = np.linalg.pinv(-1.0j * w * I + A) else: MMR = np.dot(Q, np.linalg.solve(-1.0j * w * I + A, Q)) s = np.dot(tr_vec, np.dot(a, np.dot(MMR, np.dot(b, np.transpose(rho))))) spectrum[idx] = -2 * np.real(s[0, 0]) return spectrum
def state_number_qobj(dims, state): """ Return a Qobj representation of a quantum state specified by the state array `state`. Example: >>> state_number_qobj([2, 2, 2], [1, 0, 1]) # doctest: +SKIP Quantum object: dims = [[2, 2, 2], [1, 1, 1]], \ shape = [8, 1], type = ket Qobj data = [[ 0.] [ 0.] [ 0.] [ 0.] [ 0.] [ 1.] [ 0.] [ 0.]] Parameters ---------- dims : list or array The quantum state dimensions array, as it would appear in a Qobj. state : list State number array. Returns ------- state : :class:`qutip.Qobj.qobj` The state as a :class:`qutip.Qobj.qobj` instance. """ assert len(state) == len(dims) return tensor([fock(d, s) for d, s in zip(dims, state)])
def qzero(N): """ Zero operator Parameters ---------- N : int or list of ints 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. Returns ------- qzero : qobj Zero operator Qobj. """ if isinstance(N, list): return tensor(*[qzero(n) for n in N]) N = int(N) if (not isinstance(N, (int, np.integer))) or N < 0: raise ValueError("N must be integer N>=0") return Qobj(sp.csr_matrix((N, N), dtype=complex), isherm=True)
def test_multi_qubits(self): N = 3 H_d = tensor([sigmaz()]*3) H_c = [] # test empty ctrls num_tslots = 30 evo_time = 10 test = OptPulseProcessor(N, H_d, H_c) test.add_ctrl(tensor([sigmax(), sigmax()]), cyclic_permutation=True) # test periodically adding ctrls sx = sigmax() iden = identity(2) assert_(Qobj(tensor([sx, iden, sx])) in test.ctrls) assert_(Qobj(tensor([iden, sx, sx])) in test.ctrls) assert_(Qobj(tensor([sx, sx, iden])) in test.ctrls) test.add_ctrl(sigmax(), cyclic_permutation=True) test.add_ctrl(sigmay(), cyclic_permutation=True) # test pulse genration for cnot gate, with kwargs qc = [tensor([identity(2), cnot()])] test.load_circuit(qc, num_tslots=num_tslots, evo_time=evo_time, min_fid_err=1.0e-6) rho0 = qubit_states(3, [1, 1, 1]) rho1 = qubit_states(3, [1, 1, 0]) result = test.run_state( rho0, options=Options(store_states=True)) print(result.states[-1]) print(rho1) assert_(fidelity(result.states[-1], rho1) > 1-1.0e-6) # test save and read coeffs test.save_coeff("qutip_test_multi_qubits.txt") test2 = OptPulseProcessor(N, H_d, H_c) test2.drift = test.drift test2.ctrls = test.ctrls test2.read_coeff("qutip_test_multi_qubits.txt") os.remove("qutip_test_multi_qubits.txt") assert_(np.max((test.coeffs-test2.coeffs)**2) < 1.0e-13) result = test2.run_state(rho0,) assert_(fidelity(result.states[-1], rho1) > 1-1.0e-6)
def ket(seq, dim=2): """ Produces a multiparticle ket state for a list or string, where each element stands for state of the respective particle. Parameters ---------- seq : str / list of ints or characters Each element defines state of the respective particle. (e.g. [1,1,0,1] or a string "1101"). For qubits it is also possible to use the following conventions: - 'g'/'e' (ground and excited state) - 'u'/'d' (spin up and down) - 'H'/'V' (horizontal and vertical polarization) Note: for dimension > 9 you need to use a list. dim : int (default: 2) / list of ints Space dimension for each particle: int if there are the same, list if they are different. Returns ------- ket : qobj Examples -------- >>> ket("10") Quantum object: dims = [[2, 2], [1, 1]], shape = [4, 1], type = ket Qobj data = [[ 0.] [ 0.] [ 1.] [ 0.]] >>> ket("Hue") Quantum object: dims = [[2, 2, 2], [1, 1, 1]], shape = [8, 1], type = ket Qobj data = [[ 0.] [ 1.] [ 0.] [ 0.] [ 0.] [ 0.] [ 0.] [ 0.]] >>> ket("12", 3) Quantum object: dims = [[3, 3], [1, 1]], shape = [9, 1], type = ket Qobj data = [[ 0.] [ 0.] [ 0.] [ 0.] [ 0.] [ 1.] [ 0.] [ 0.] [ 0.]] >>> ket("31", [5, 2]) Quantum object: dims = [[5, 2], [1, 1]], shape = [10, 1], type = ket Qobj data = [[ 0.] [ 0.] [ 0.] [ 0.] [ 0.] [ 0.] [ 0.] [ 1.] [ 0.] [ 0.]] """ if isinstance(dim, int): dim = [dim] * len(seq) return tensor([basis(dim[i], _character_to_qudit(x)) for i, x in enumerate(seq)])
def spectrum_pi(H, wlist, c_ops, a_op, b_op, use_pinv=False): """ Calculate the spectrum corresponding to a correlation function :math:`\left<A(\\tau)B(0)\\right>`, i.e., the Fourier transform of the correlation function: .. math:: S(\omega) = \int_{-\infty}^{\infty} \left<A(\\tau)B(0)\\right> e^{-i\omega\\tau} d\\tau. Parameters ---------- H : :class:`qutip.qobj` system Hamiltonian. wlist : *list* / *array* list of frequencies for :math:`\\omega`. c_ops : list of :class:`qutip.qobj` list of collapse operators. a_op : :class:`qutip.qobj` operator A. b_op : :class:`qutip.qobj` operator B. Returns ------- s_vec: *array* An *array* with spectrum :math:`S(\omega)` for the frequencies specified in `wlist`. """ L = H if issuper(H) else liouvillian_fast(H, c_ops) tr_mat = tensor([qeye(n) for n in L.dims[0][0]]) N = prod(L.dims[0][0]) A = L.full() b = spre(b_op).full() a = spre(a_op).full() tr_vec = transpose(mat2vec(tr_mat.full())) rho_ss = steadystate(L) rho = transpose(mat2vec(rho_ss.full())) I = np.identity(N * N) P = np.kron(transpose(rho), tr_vec) Q = I - P s_vec = np.zeros(len(wlist)) for idx, w in enumerate(wlist): if use_pinv: MMR = numpy.linalg.pinv(-1.0j * w * I + A) else: MMR = np.dot(Q, np.linalg.solve(-1.0j * w * I + A, Q)) s = np.dot(tr_vec, np.dot(a, np.dot(MMR, np.dot(b, transpose(rho))))) s_vec[idx] = -2 * np.real(s[0, 0]) return s_vec
def set_up_ops(self, N): super(CircularSpinChain, self).set_up_ops(N) operator = tensor([sigmax(), sigmax()]) + tensor([sigmay(), sigmay()]) self.pulses.append( Pulse(operator, [N-1, 0], spline_kind=self.spline_kind)) self.pulse_dict["g" + str(N-1)] = len(self.pulses) - 1
def test_QobjPermute(): "Qobj permute" A = basis(3, 0) B = basis(5, 4) C = basis(4, 2) psi = tensor(A, B, C) psi2 = psi.permute([2, 0, 1]) assert_(psi2 == tensor(C, A, B)) psi_bra = psi.dag() psi2_bra = psi_bra.permute([2, 0, 1]) assert_(psi2_bra == tensor(C, A, B).dag()) A = fock_dm(3, 0) B = fock_dm(5, 4) C = fock_dm(4, 2) rho = tensor(A, B, C) rho2 = rho.permute([2, 0, 1]) assert_(rho2 == tensor(C, A, B)) for ii in range(3): A = rand_ket(3) B = rand_ket(4) C = rand_ket(5) psi = tensor(A, B, C) psi2 = psi.permute([1, 0, 2]) assert_(psi2 == tensor(B, A, C)) psi_bra = psi.dag() psi2_bra = psi_bra.permute([1, 0, 2]) assert_(psi2_bra == tensor(B, A, C).dag()) for ii in range(3): A = rand_dm(3) B = rand_dm(4) C = rand_dm(5) rho = tensor(A, B, C) rho2 = rho.permute([1, 0, 2]) assert_(rho2 == tensor(B, A, C)) rho_vec = operator_to_vector(rho) rho2_vec = rho_vec.permute([[1, 0, 2],[4,3,5]]) assert_(rho2_vec == operator_to_vector(tensor(B, A, C))) rho_vec_bra = operator_to_vector(rho).dag() rho2_vec_bra = rho_vec_bra.permute([[1, 0, 2],[4,3,5]]) assert_(rho2_vec_bra == operator_to_vector(tensor(B, A, C)).dag()) for ii in range(3): super_dims = [3, 5, 4] U = rand_unitary(np.prod(super_dims), density=0.02, dims=[super_dims, super_dims]) Unew = U.permute([2,1,0]) S_tens = to_super(U) S_tens_new = to_super(Unew) assert_(S_tens_new == S_tens.permute([[2,1,0],[5,4,3]]))
def gate_expand_3toN(U, N, controls=[0, 1], target=2): """ Create a Qobj representing a three-qubit gate that act on a system with N qubits. Parameters ---------- U : Qobj The three-qubit gate N : integer The number of qubits in the target space. controls : list The list of the control qubits. target : integer The index of the target qubit. Returns ------- gate : qobj Quantum object representation of N-qubit gate. """ if N < 3: raise ValueError("integer N must be larger or equal to 3") if controls[0] >= N or controls[1] >= N or target >= N: raise ValueError("control and not target is None." " Must be integer < integer N") if (controls[0] == target or controls[1] == target or controls[0] == controls[1]): raise ValueError("controls[0], controls[1], and target" " cannot be equal") p = list(range(N)) p1 = list(range(N)) p2 = list(range(N)) if controls[0] <= 2 and controls[1] <= 2 and target <= 2: p[controls[0]] = 0 p[controls[1]] = 1 p[target] = 2 # # N > 3 cases # elif controls[0] == 0 and controls[1] == 1: p[2], p[target] = p[target], p[2] elif controls[0] == 0 and target == 2: p[1], p[controls[1]] = p[controls[1]], p[1] elif controls[1] == 1 and target == 2: p[0], p[controls[0]] = p[controls[0]], p[0] elif controls[0] == 1 and controls[1] == 0: p[controls[1]], p[controls[0]] = p[controls[0]], p[controls[1]] p2[2], p2[target] = p2[target], p2[2] p = [p2[p[k]] for k in range(N)] elif controls[0] == 2 and target == 0: p[target], p[controls[0]] = p[controls[0]], p[target] p1[1], p1[controls[1]] = p1[controls[1]], p1[1] p = [p1[p[k]] for k in range(N)] elif controls[1] == 2 and target == 1: p[target], p[controls[1]] = p[controls[1]], p[target] p1[0], p1[controls[0]] = p1[controls[0]], p1[0] p = [p1[p[k]] for k in range(N)] elif controls[0] == 1 and controls[1] == 2: # controls[0] -> controls[1] -> target -> outside p[0], p[1] = p[1], p[0] p[0], p[2] = p[2], p[0] p[0], p[target] = p[target], p[0] elif controls[0] == 2 and target == 1: # controls[0] -> target -> controls[1] -> outside p[0], p[2] = p[2], p[0] p[0], p[1] = p[1], p[0] p[0], p[controls[1]] = p[controls[1]], p[0] elif controls[1] == 0 and controls[0] == 2: # controls[1] -> controls[0] -> target -> outside p[1], p[0] = p[0], p[1] p[1], p[2] = p[2], p[1] p[1], p[target] = p[target], p[1] elif controls[1] == 2 and target == 0: # controls[1] -> target -> controls[0] -> outside p[1], p[2] = p[2], p[1] p[1], p[0] = p[0], p[1] p[1], p[controls[0]] = p[controls[0]], p[1] elif target == 1 and controls[1] == 0: # target -> controls[1] -> controls[0] -> outside p[2], p[1] = p[1], p[2] p[2], p[0] = p[0], p[2] p[2], p[controls[0]] = p[controls[0]], p[2] elif target == 0 and controls[0] == 1: # target -> controls[0] -> controls[1] -> outside p[2], p[0] = p[0], p[2] p[2], p[1] = p[1], p[2] p[2], p[controls[1]] = p[controls[1]], p[2] elif controls[0] == 0 and controls[1] == 2: # controls[0] -> self, controls[1] -> target -> outside p[1], p[2] = p[2], p[1] p[1], p[target] = p[target], p[1] elif controls[1] == 1 and controls[0] == 2: # controls[1] -> self, controls[0] -> target -> outside p[0], p[2] = p[2], p[0] p[0], p[target] = p[target], p[0] elif target == 2 and controls[0] == 1: # target -> self, controls[0] -> controls[1] -> outside p[0], p[1] = p[1], p[0] p[0], p[controls[1]] = p[controls[1]], p[0] # # N > 4 cases # elif controls[0] == 1 and controls[1] > 2 and target > 2: # controls[0] -> controls[1] -> outside, target -> outside p[0], p[1] = p[1], p[0] p[0], p[controls[1]] = p[controls[1]], p[0] p[2], p[target] = p[target], p[2] elif controls[0] == 2 and controls[1] > 2 and target > 2: # controls[0] -> target -> outside, controls[1] -> outside p[0], p[2] = p[2], p[0] p[0], p[target] = p[target], p[0] p[1], p[controls[1]] = p[controls[1]], p[1] elif controls[1] == 2 and controls[0] > 2 and target > 2: # controls[1] -> target -> outside, controls[0] -> outside p[1], p[2] = p[2], p[1] p[1], p[target] = p[target], p[1] p[0], p[controls[0]] = p[controls[0]], p[0] else: p[0], p[controls[0]] = p[controls[0]], p[0] p1[1], p1[controls[1]] = p1[controls[1]], p1[1] p2[2], p2[target] = p2[target], p2[2] p = [p[p1[p2[k]]] for k in range(N)] return tensor([U] + [identity(2)] * (N - 3)).permute(p)
def test_CheckMulType(): "Qobj multiplication type" # ket-bra and bra-ket multiplication psi = basis(5) dm = psi * psi.dag() assert dm.isoper assert dm.isherm nrm = psi.dag() * psi assert np.prod(nrm.shape) == 1 assert abs(nrm)[0, 0] == 1 # operator-operator multiplication H1 = rand_herm(3) H2 = rand_herm(3) out = H1 * H2 assert out.isoper out = H1 * H1 assert out.isoper assert out.isherm out = H2 * H2 assert out.isoper assert out.isherm U = rand_unitary(5) out = U.dag() * U assert out.isoper assert out.isherm N = num(5) out = N * N assert out.isoper assert out.isherm # operator-ket and bra-operator multiplication op = sigmax() ket1 = basis(2) ket2 = op * ket1 assert ket2.isket bra1 = basis(2).dag() bra2 = bra1 * op assert bra2.isbra assert bra2.dag() == ket2 # bra and ket multiplication with different dims zero = basis(2, 0) zero_log = tensor(zero, zero, zero) op1 = zero_log * zero.dag() op2 = zero * zero_log.dag() assert op1 == op2.dag() # superoperator-operket and operbra-superoperator multiplication sop = to_super(sigmax()) opket1 = operator_to_vector(fock_dm(2)) opket2 = sop * opket1 assert opket2.isoperket opbra1 = operator_to_vector(fock_dm(2)).dag() opbra2 = opbra1 * sop assert opbra2.isoperbra assert opbra2.dag() == opket2
def test_known_iscptp(self): """ Superoperator: ishp, iscp, istp and iscptp known cases. """ def case(qobj, shouldhp, shouldcp, shouldtp): hp = qobj.ishp cp = qobj.iscp tp = qobj.istp cptp = qobj.iscptp shouldcptp = shouldcp and shouldtp if (hp == shouldhp and cp == shouldcp and tp == shouldtp and cptp == shouldcptp): return fails = [] if hp != shouldhp: fails.append(("ishp", shouldhp, hp)) if tp != shouldtp: fails.append(("istp", shouldtp, tp)) if cp != shouldcp: fails.append(("iscp", shouldcp, cp)) if cptp != shouldcptp: fails.append(("iscptp", shouldcptp, cptp)) raise AssertionError("Expected {}.".format(" and ".join([ "{} == {} (got {})".format(fail, expected, got) for fail, expected, got in fails ]))) # Conjugation by a creation operator should # have be CP (and hence HP), but not TP. a = create(2).dag() S = sprepost(a, a.dag()) case(S, True, True, False) # A single off-diagonal element should not be CP, # nor even HP. S = sprepost(a, a) case(S, False, False, False) # Check that unitaries are CPTP and HP. case(identity(2), True, True, True) case(sigmax(), True, True, True) # Check that unitaries on bipartite systems are CPTP and HP. case(tensor(sigmax(), identity(2)), True, True, True) # Check that a linear combination of bipartitie unitaries is CPTP and HP. S = (to_super(tensor(sigmax(), identity(2))) + to_super(tensor(identity(2), sigmay()))) / 2 case(S, True, True, True) # The partial transpose map, whose Choi matrix is SWAP, is TP # and HP but not CP (one negative eigenvalue). W = Qobj(swap(), type='super', superrep='choi') case(W, True, False, True) # Subnormalized maps (representing erasure channels, for instance) # can be CP but not TP. subnorm_map = Qobj(identity(4) * 0.9, type='super', superrep='super') case(subnorm_map, True, True, False) # Check that things which aren't even operators aren't identified as # CPTP. case(basis(2), False, False, False)
def test_expand_operator(self): """ gate : expand qubits operator to a N qubits system. """ # oper size is N, no expansion oper = tensor(sigmax(), sigmay()) assert_allclose(expand_operator(oper=oper, targets=[0, 1], N=2), oper) assert_allclose(expand_operator(oper=oper, targets=[1, 0], N=2), tensor(sigmay(), sigmax())) # random single qubit gate test, integer as target r = rand_unitary(2) assert_allclose(expand_operator(r, 3, 0), tensor([r, identity(2), identity(2)])) assert_allclose(expand_operator(r, 3, 1), tensor([identity(2), r, identity(2)])) assert_allclose(expand_operator(r, 3, 2), tensor([identity(2), identity(2), r])) # random 2qubits gate test, list as target r2 = rand_unitary(4) r2.dims = [[2, 2], [2, 2]] assert_allclose(expand_operator(r2, 3, [2, 1]), tensor([identity(2), r2.permute([1, 0])])) assert_allclose(expand_operator(r2, 3, [0, 1]), tensor([r2, identity(2)])) assert_allclose(expand_operator(r2, 3, [0, 2]), tensor([r2, identity(2)]).permute([0, 2, 1])) # cnot expantion, qubit 2 control qubit 0 assert_allclose( expand_operator(cnot(), 3, [2, 0]), Qobj([[1., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 1., 0., 0.], [0., 0., 1., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 1.], [0., 0., 0., 0., 1., 0., 0., 0.], [0., 1., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 1., 0.], [0., 0., 0., 1., 0., 0., 0., 0.]], dims=[[2, 2, 2], [2, 2, 2]])) # test expansion with cyclic permutation result = expand_operator(tensor([sigmaz(), sigmax()]), N=3, targets=[2, 0], cyclic_permutation=True) mat1 = tensor(sigmax(), qeye(2), sigmaz()) mat2 = tensor(sigmaz(), sigmax(), qeye(2)) mat3 = tensor(qeye(2), sigmaz(), sigmax()) assert_(mat1 in result) assert_(mat2 in result) assert_(mat3 in result) # test for dimensions other than 2 mat3 = rand_dm(3, density=1.) oper = tensor([sigmax(), mat3]) N = 4 dims = [2, 2, 3, 4] result = expand_operator(oper, N, targets=[0, 2], dims=dims) assert_array_equal(result.dims[0], dims) dims = [3, 2, 4, 2] result = expand_operator(oper, N, targets=[3, 0], dims=dims) assert_array_equal(result.dims[0], dims) dims = [3, 2, 4, 2] result = expand_operator(oper, N, targets=[1, 0], dims=dims) assert_array_equal(result.dims[0], dims)