def testScatteringProbability(self): """ Asserts that pi pulse in TLS has P0 ~ 0 and P0+P1+P2 ~ 1 """ w0 = 1.0 * 2 * np.pi gamma = 1.0 sm = np.sqrt(gamma) * destroy(2) pulseArea = np.pi pulseLength = 0.2 / gamma RabiFreq = pulseArea / (2 * pulseLength) psi0 = basis(2, 0) tlist = np.geomspace(gamma, 10 * gamma, 40) - gamma # Define TLS Hamiltonian H0S = w0 * create(2) * destroy(2) H1S1 = lambda t, args: \ RabiFreq * 1j * np.exp(-1j * w0 * t) * (t < pulseLength) H1S2 = lambda t, args: \ RabiFreq * -1j * np.exp(1j * w0 * t) * (t < pulseLength) Htls = [H0S, [sm.dag(), H1S1], [sm, H1S2]] # Run the test P0 = scattering_probability(Htls, psi0, 0, [sm], tlist) P1 = scattering_probability(Htls, psi0, 1, [sm], tlist) P2 = scattering_probability(Htls, psi0, 2, [sm], tlist) assert_(P0 < 1e-3) assert_(np.abs(P0 + P1 + P2 - 1) < 1e-3)
def _opto_liouvillian(N): from qutip.tensor import tensor from qutip.operators import destroy, qeye from qutip.superoperator import liouvillian Nc = 5 # Number of cavity states Nm = N # Number of mech states kappa = 0.3 # Cavity damping rate E = 0.1 # Driving Amplitude g0 = 2.4 * kappa # Coupling strength Qm = 1e4 # Mech quality factor gamma = 1 / Qm # Mech damping rate n_th = 1 # Mech bath temperature delta = -0.43 # Detuning a = tensor(destroy(Nc), qeye(Nm)) b = tensor(qeye(Nc), destroy(Nm)) num_b = b.dag() * b num_a = a.dag() * a H = -delta * (num_a) + num_b + g0 * (b.dag() + b) * num_a + E * (a.dag() + a) cc = np.sqrt(kappa) * a cm = np.sqrt(gamma * (1.0 + n_th)) * b cp = np.sqrt(gamma * n_th) * b.dag() c_ops = [cc, cm, cp] return liouvillian(H, c_ops)
def testScatteringAmplitude(self): """ Asserts that a 2pi pulse in TLS has ~0 amplitude after pulse """ w0 = 1.0 * 2 * np.pi gamma = 1.0 sm = np.sqrt(gamma) * destroy(2) pulseArea = 2 * np.pi pulseLength = 0.2 / gamma RabiFreq = pulseArea / (2 * pulseLength) psi0 = basis(2, 0) T = 50 tlist = np.linspace(0, 1 / gamma, T) # Define TLS Hamiltonian H0S = w0 * create(2) * destroy(2) H1S1 = lambda t, args: \ RabiFreq * 1j * np.exp(-1j * w0 * t) * (t < pulseLength) H1S2 = lambda t, args: \ RabiFreq * -1j * np.exp(1j * w0 * t) * (t < pulseLength) Htls = [H0S, [sm.dag(), H1S1], [sm, H1S2]] # Run the test state = temporal_scattered_state(Htls, psi0, 1, [sm], tlist) basisVec = temporal_basis_vector([[40]], T) amplitude = np.abs((basisVec.dag() * state).full().item()) assert_(amplitude < 1e-3)
def set_up_ops(self, N): """ Generate the Hamiltonians for the spinchain model and save them in the attribute `ctrls`. Parameters ---------- N: int The number of qubits in the system. """ # single qubit terms self.a = tensor([destroy(self.num_levels)] + [identity(2) for n in range(N)]) self.ctrls.append(self.a.dag() * self.a) self.ctrls += [ tensor([identity(self.num_levels)] + [sigmax() if m == n else identity(2) for n in range(N)]) for m in range(N) ] self.ctrls += [ tensor([identity(self.num_levels)] + [sigmaz() if m == n else identity(2) for n in range(N)]) for m in range(N) ] # interaction terms for n in range(N): sm = tensor( [identity(self.num_levels)] + [destroy(2) if m == n else identity(2) for m in range(N)]) self.ctrls.append(self.a.dag() * sm + self.a * sm.dag()) self.psi_proj = tensor([basis(self.num_levels, 0)] + [identity(2) for n in range(N)])
def test_sp_bandwidth(): "Sparse: Bandwidth" # Bandwidth test 1 A = create(25) + destroy(25) + qeye(25) band = sp_bandwidth(A.data) assert_equal(band[0], 3) assert_equal(band[1] == band[2] == 1, 1) # Bandwidth test 2 A = np.array([[1, 0, 0, 0, 1, 0, 0, 0], [0, 1, 1, 0, 0, 1, 0, 1], [0, 1, 1, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0, 1, 0], [1, 0, 1, 0, 1, 0, 0, 0], [0, 1, 0, 0, 0, 1, 0, 1], [0, 0, 0, 1, 0, 0, 1, 0], [0, 1, 0, 0, 0, 1, 0, 1]], dtype=np.int32) A = sp.csr_matrix(A) out1 = sp_bandwidth(A) assert_equal(out1[0], 13) assert_equal(out1[1] == out1[2] == 6, 1) # Bandwidth test 3 perm = reverse_cuthill_mckee(A) B = sp_permute(A, perm, perm) out2 = sp_bandwidth(B) assert_equal(out2[0], 5) assert_equal(out2[1] == out2[2] == 2, 1) # Asymmetric bandwidth test A = destroy(25) + qeye(25) out1 = sp_bandwidth(A.data) assert_equal(out1[0], 2) assert_equal(out1[1], 0) assert_equal(out1[2], 1)
def set_up_ops(self, num_qubits): """ Generate the Hamiltonians for the spinchain model and save them in the attribute `ctrls`. Parameters ---------- num_qubits: int The number of qubits in the system. """ # single qubit terms for m in range(num_qubits): self.add_control(sigmax(), [m + 1], label="sx" + str(m)) for m in range(num_qubits): self.add_control(sigmaz(), [m + 1], label="sz" + str(m)) # coupling terms a = tensor([destroy(self.num_levels)] + [identity(2) for n in range(num_qubits)]) for n in range(num_qubits): sm = tensor([identity(self.num_levels)] + [ destroy(2) if m == n else identity(2) for m in range(num_qubits) ]) self.add_control(a.dag() * sm + a * sm.dag(), list(range(num_qubits + 1)), label="g" + str(n))
def set_up_ops(self, N): """ Generate the Hamiltonians for the circuitqed model and save them in the attribute `ctrls`. Parameters ---------- N: int The number of qubits in the system. """ # single qubit terms for m in range(N): self.pulses.append( Pulse(sigmax(), [m + 1], spline_kind=self.spline_kind)) for m in range(N): self.pulses.append( Pulse(sigmaz(), [m + 1], spline_kind=self.spline_kind)) # coupling terms a = tensor([destroy(self.num_levels)] + [identity(2) for n in range(N)]) for n in range(N): sm = tensor( [identity(self.num_levels)] + [destroy(2) if m == n else identity(2) for m in range(N)]) self.pulses.append( Pulse(a.dag() * sm + a * sm.dag(), list(range(N + 1)), spline_kind=self.spline_kind))
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 test_sp_bandwidth(): "Sparse: Bandwidth" # Bandwidth test 1 A = create(25)+destroy(25)+qeye(25) band = sp_bandwidth(A.data) assert_equal(band[0], 3) assert_equal(band[1] == band[2] == 1, 1) # Bandwidth test 2 A = np.array([[1, 0, 0, 0, 1, 0, 0, 0], [0, 1, 1, 0, 0, 1, 0, 1], [0, 1, 1, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0, 1, 0], [1, 0, 1, 0, 1, 0, 0, 0], [0, 1, 0, 0, 0, 1, 0, 1], [0, 0, 0, 1, 0, 0, 1, 0], [0, 1, 0, 0, 0, 1, 0, 1]], dtype=np.int32) A = sp.csr_matrix(A) out1 = sp_bandwidth(A) assert_equal(out1[0], 13) assert_equal(out1[1] == out1[2] == 6, 1) # Bandwidth test 3 perm = reverse_cuthill_mckee(A) B = sp_permute(A, perm, perm) out2 = sp_bandwidth(B) assert_equal(out2[0], 5) assert_equal(out2[1] == out2[2] == 2, 1) # Asymmetric bandwidth test A = destroy(25)+qeye(25) out1 = sp_bandwidth(A.data) assert_equal(out1[0], 2) assert_equal(out1[1], 0) assert_equal(out1[2], 1)
def set_up_ops(self, N): """ Generate the Hamiltonians for the spinchain model and save them in the attribute `ctrls`. Parameters ---------- N: int The number of qubits in the system. """ # single qubit terms self.a = tensor(destroy(self.num_levels)) self.pulses.append( Pulse(self.a.dag() * self.a, [0], spline_kind=self.spline_kind)) for m in range(N): self.pulses.append( Pulse(sigmax(), [m + 1], spline_kind=self.spline_kind)) for m in range(N): self.pulses.append( Pulse(sigmaz(), [m + 1], spline_kind=self.spline_kind)) # interaction terms a_full = tensor([destroy(self.num_levels)] + [identity(2) for n in range(N)]) for n in range(N): sm = tensor( [identity(self.num_levels)] + [destroy(2) if m == n else identity(2) for m in range(N)]) self.pulses.append( Pulse(a_full.dag() * sm + a_full * sm.dag(), list(range(N + 1)), spline_kind=self.spline_kind)) self.psi_proj = tensor([basis(self.num_levels, 0)] + [identity(2) for n in range(N)])
def TestNoise(self): """ Test for Processor with noise """ # setup and fidelity without noise init_state = qubit_states(2, [0, 0, 0, 0]) tlist = np.array([0., np.pi/2.]) a = destroy(2) proc = Processor(N=2) proc.add_control(sigmax(), targets=1) proc.pulses[0].tlist = tlist proc.pulses[0].coeff = np.array([1]) result = proc.run_state(init_state=init_state) assert_allclose( fidelity(result.states[-1], qubit_states(2, [0, 1, 0, 0])), 1, rtol=1.e-7) # decoherence noise dec_noise = DecoherenceNoise([0.25*a], targets=1) proc.add_noise(dec_noise) result = proc.run_state(init_state=init_state) assert_allclose( fidelity(result.states[-1], qubit_states(2, [0, 1, 0, 0])), 0.981852, rtol=1.e-3) # white random noise proc.noise = [] white_noise = RandomNoise(0.2, np.random.normal, loc=0.1, scale=0.1) proc.add_noise(white_noise) result = proc.run_state(init_state=init_state)
def test_QobjHerm(): "Qobj Hermicity" N = 10 data = np.random.random((N, N)) + 1j * np.random.random( (N, N)) - (0.5 + 0.5j) q = Qobj(data) assert_equal(q.isherm, False) data = data + data.conj().T q = Qobj(data) assert_(q.isherm) q_a = destroy(5) assert_(not q_a.isherm) q_ad = create(5) assert_(not q_ad.isherm) # test addition of two nonhermitian operators adding up to a hermitian one q_x = q_a + q_ad assert_(q_x.isherm) # isherm use the _isherm cache from q_a + q_ad q_x._isherm = None # reset _isherm cache assert_(q_x.isherm) # recalculate _isherm # test addition of one hermitan and one nonhermitian operator q = q_x + q_a assert_(not q.isherm) q._isherm = None assert_(not q.isherm) # test addition of two hermitan operators q = q_x + q_x assert_(q.isherm) q._isherm = None assert_(q.isherm)
def rand_super(dim=5): H = rand_herm(dim) return propagator( H, np.random.rand(), [create(dim), destroy(dim), jmat(float(dim - 1) / 2.0, 'z')])
def test_QobjHerm(): "Qobj Hermicity" N = 10 data = np.random.random( (N, N)) + 1j * np.random.random((N, N)) - (0.5 + 0.5j) q = Qobj(data) assert_equal(q.isherm, False) data = data + data.conj().T q = Qobj(data) assert_(q.isherm) q_a = destroy(5) assert_(not q_a.isherm) q_ad = create(5) assert_(not q_ad.isherm) # test addition of two nonhermitian operators adding up to a hermitian one q_x = q_a + q_ad assert_(q_x.isherm) # isherm use the _isherm cache from q_a + q_ad q_x._isherm = None # reset _isherm cache assert_(q_x.isherm) # recalculate _isherm # test addition of one hermitan and one nonhermitian operator q = q_x + q_a assert_(not q.isherm) q._isherm = None assert_(not q.isherm) # test addition of two hermitan operators q = q_x + q_x assert_(q.isherm) q._isherm = None assert_(q.isherm)
def TestRelaxationNoise(self): """ Test for the relaxation noise """ a = destroy(2) relnoise = RelaxationNoise(t1=[1., 1., 1.], t2=None) noisy_qu, c_ops = relnoise.get_noisy_dynamics(3).get_noisy_qobjevo( dims=3) assert_(len(c_ops) == 3) assert_allclose(c_ops[1].cte, tensor([qeye(2), a, qeye(2)])) relnoise = RelaxationNoise(t1=None, t2=None) noisy_qu, c_ops = relnoise.get_noisy_dynamics(2).get_noisy_qobjevo( dims=2) assert_(len(c_ops) == 0) relnoise = RelaxationNoise(t1=None, t2=[0.2, 0.7]) noisy_qu, c_ops = relnoise.get_noisy_dynamics(2).get_noisy_qobjevo( dims=2) assert_(len(c_ops) == 2) relnoise = RelaxationNoise(t1=[1., 1.], t2=[0.5, 0.5]) noisy_qu, c_ops = relnoise.get_noisy_dynamics(2).get_noisy_qobjevo( dims=2) assert_(len(c_ops) == 4)
def rand_super(N=5, dims=None): """ Returns a randomly drawn superoperator acting on operators acting on N dimensions. Parameters ---------- N : int Square root of the dimension of the superoperator to be returned. dims : list Dimensions of quantum object. Used for specifying tensor structure. Default is dims=[[[N],[N]], [[N],[N]]]. """ if dims is not None: # TODO: check! pass else: dims = [[[N], [N]], [[N], [N]]] H = rand_herm(N) S = propagator( H, np.random.rand(), [create(N), destroy(N), jmat(float(N - 1) / 2.0, 'z')]) S.dims = dims return S
def coherent(N,alpha): """Generates a coherent state with eigenvalue alpha. Constructed using displacement operator on vacuum state. Parameters ---------- N : int Number of Fock states in Hilbert space. alpha : float/complex Eigenvalue of coherent state. Returns ------- state : qobj Qobj quantum object for coherent state Examples -------- >>> coherent(5,0.25j) Quantum object: dims = [[5], [1]], shape = [5, 1], type = ket Qobj data = [[ 9.69233235e-01+0.j ] [ 0.00000000e+00+0.24230831j] [ -4.28344935e-02+0.j ] [ 0.00000000e+00-0.00618204j] [ 7.80904967e-04+0.j ]] """ x=basis(N,0) a=destroy(N) D=(alpha*a.dag()-conj(alpha)*a).expm() return D*x
def coherent(N, alpha, method='operator'): """Generates a coherent state with eigenvalue alpha. Constructed using displacement operator on vacuum state. Parameters ---------- N : int Number of Fock states in Hilbert space. alpha : float/complex Eigenvalue of coherent state. method : string {'operator', 'analytic'} Method for generating coherent state. Returns ------- state : qobj Qobj quantum object for coherent state Examples -------- >>> coherent(5,0.25j) Quantum object: dims = [[5], [1]], shape = [5, 1], type = ket Qobj data = [[ 9.69233235e-01+0.j ] [ 0.00000000e+00+0.24230831j] [ -4.28344935e-02+0.j ] [ 0.00000000e+00-0.00618204j] [ 7.80904967e-04+0.j ]] Notes ----- Select method 'operator' (default) or 'analytic'. With the 'operator' method, the coherent state is generated by displacing the vacuum state using the displacement operator defined in the truncated Hilbert space of size 'N'. This method guarantees that the resulting state is normalized. With 'analytic' method the coherent state is generated using the analytical formula for the coherent state coefficients in the Fock basis. THIS METHOD DOES NOT GUARANTEE THAT THE STATE IS NORMALIZED if truncated to a small number of Fock states, but would in that case give more accurate coefficients. """ if method == "operator": x=basis(N,0) a=destroy(N) D=(alpha*a.dag()-conj(alpha)*a).expm() return D*x elif method == "analytic": data = np.zeros([N,1],dtype=complex) n = arange(N) data[:,0] = np.exp(-(abs(alpha)**2)/2.0)*(alpha**(n))/_sqrt_factorial(n) return Qobj(data) else: raise TypeError("The method option can only take values 'operator' or 'analytic'")
def get_noisy_dynamics(self, dims): """ Return a list of Pulse object with only trivial ideal pulse (H=0) but non-trivial relaxation noise. Parameters ---------- dims: list, optional The dimension of the components system, the default value is [2,2...,2] for qubits system. Returns ------- lindblad_noise: list of :class:`qutip.qip.Pulse` A list of Pulse object with only trivial ideal pulse (H=0) but non-trivial relaxation noise. """ if isinstance(dims, list): # for d in dims: # if d != 2: # raise ValueError( # "Relaxation noise is defined only for qubits system") N = len(dims) else: N = dims self.t1 = self._T_to_list(self.t1, len(dims)) self.t2 = self._T_to_list(self.t2, len(dims)) if len(self.t1) != len(dims) or len(self.t2) != len(dims): raise ValueError("Length of t1 or t2 does not match N, " "len(t1)={}, len(t2)={}".format( len(self.t1), len(self.t2))) lindblad_noise = Pulse(None, None) if self.targets is None: targets = range(N) else: targets = self.targets for qu_ind in targets: if dims[qu_ind] != 2: continue t1 = self.t1[qu_ind] t2 = self.t2[qu_ind] if t1 is not None: op = 1 / np.sqrt(t1) * destroy(2) lindblad_noise.add_lindblad_noise(op, qu_ind, coeff=True) if t2 is not None: # Keep the total dephasing ~ exp(-t/t2) if t1 is not None: if 2 * t1 < t2: raise ValueError("t1={}, t2={} does not fulfill " "2*t1>t2".format(t1, t2)) T2_eff = 1. / (1. / t2 - 1. / 2. / t1) else: T2_eff = t2 op = 1 / np.sqrt(2 * T2_eff) * sigmaz() lindblad_noise.add_lindblad_noise(op, qu_ind, coeff=True) return lindblad_noise
def test_SuperChoiSuper(self): """ Superoperator: Converting superoperator to Choi matrix and back. """ h_5 = rand_herm(5) superoperator = propagator(h_5, scipy.rand(), [create(5), destroy(5), jmat(2, 'z')]) choi_matrix = super_to_choi(superoperator) test_supe = choi_to_super(choi_matrix) assert_((test_supe - superoperator).norm() < 1e-12)
def test_standard(self): base = _random_not_singular(10) assert not Qobj(base).isherm assert Qobj(base + base.conj().T).isherm q_a = destroy(5) assert not q_a.isherm q_ad = create(5) assert not q_ad.isherm
def test_ChoiKrausChoi(self): """ Superoperator: Converting superoperator to Choi matrix and back. """ h_5 = rand_herm(5) superoperator = propagator(h_5, scipy.rand(), [create(5), destroy(5), jmat(2, 'z')]) choi_matrix = super_to_choi(superoperator) kraus_ops = choi_to_kraus(choi_matrix) test_choi = kraus_to_choi(kraus_ops) assert_((test_choi - choi_matrix).norm() < 1e-12)
def test_SuperChoiSuper(self): """ Superoperator: Converting superoperator to Choi matrix and back. """ h_5 = rand_herm(5) superoperator = propagator( h_5, scipy.rand(), [create(5), destroy(5), jmat(2, 'z')]) choi_matrix = super_to_choi(superoperator) test_supe = choi_to_super(choi_matrix) assert_((test_supe - superoperator).norm() < 1e-12)
def test_ChoiKrausChoi(self): """ Superoperator: Converting superoperator to Choi matrix and back. """ h_5 = rand_herm(5) superoperator = propagator( h_5, scipy.rand(), [create(5), destroy(5), jmat(2, 'z')]) choi_matrix = super_to_choi(superoperator) kraus_ops = choi_to_kraus(choi_matrix) test_choi = kraus_to_choi(kraus_ops) assert_((test_choi - choi_matrix).norm() < 1e-12)
def get_noise(self, N, dims=None): """ Return the quantum objects representing the noise. Parameters ---------- N: int The number of component systems. dims: list, optional The dimension of the components system, the default value is [2,2...,2] for qubits system. Returns ------- qobjevo_list: list A list of :class:`qutip.Qobj` or :class:`qutip.QobjEvo` representing the decoherence noise. """ if dims is None: dims = [2] * N self.t1 = self._T_to_list(self.t1, N) self.t2 = self._T_to_list(self.t2, N) if len(self.t1) != N or len(self.t2) != N: raise ValueError("Length of t1 or t2 does not match N, " "len(t1)={}, len(t2)={}".format( len(self.t1), len(self.t2))) qobjevo_list = [] for qu_ind in range(N): t1 = self.t1[qu_ind] t2 = self.t2[qu_ind] if t1 is not None: qobjevo_list.append( expand_operator(1 / np.sqrt(t1) * destroy(2), N, qu_ind, dims=dims)) if t2 is not None: # Keep the total dephasing ~ exp(-t/t2) if t1 is not None: if 2 * t1 < t2: raise ValueError("t1={}, t2={} does not fulfill " "2*t1>t2".format(t1, t2)) T2_eff = 1. / (1. / t2 - 1. / 2. / t1) else: T2_eff = t2 qobjevo_list.append( expand_operator(1 / np.sqrt(2 * T2_eff) * sigmaz(), N, qu_ind, dims=dims)) return qobjevo_list
def TestChooseSolver(self): # setup and fidelity without noise init_state = qubit_states(2, [0, 0, 0, 0]) tlist = np.array([0., np.pi/2.]) a = destroy(2) proc = Processor(N=2) proc.add_control(sigmax(), targets=1) proc.pulses[0].tlist = tlist proc.pulses[0].coeff = np.array([1]) result = proc.run_state(init_state=init_state, solver="mcsolve") assert_allclose( fidelity(result.states[-1], qubit_states(2, [0, 1, 0, 0])), 1, rtol=1.e-7)
def testOperatorKet(self): """ expect: operator and ket """ N = 10 op_N = num(N) op_a = destroy(N) for n in range(N): e = expect(op_N, fock(N, n)) assert_(e == n) assert_(type(e) == float) e = expect(op_a, fock(N, n)) assert_(e == 0) assert_(type(e) == complex)
def testOperatorDensityMatrix(self): """ expect: operator and density matrix """ N = 10 op_N = num(N) op_a = destroy(N) for n in range(N): e = expect(op_N, fock_dm(N, n)) assert_(e == n) assert_(type(e) == float) e = expect(op_a, fock_dm(N, n)) assert_(e == 0) assert_(type(e) == complex)
def test_addition(self): q_a, q_ad = destroy(5), create(5) # test addition of two nonhermitian operators adding up to be hermitian q_x = q_a + q_ad assert_hermicity(q_x, True) # test addition of one hermitan and one nonhermitian operator q = q_x + q_a assert_hermicity(q, False) # test addition of two hermitan operators q = q_x + q_x assert_hermicity(q, True)
def set_up_ops(self, N): """ Generate the Hamiltonians for the spinchain model and save them in the attribute `ctrls`. Parameters ---------- N: int The number of qubits in the system. """ self.pulse_dict = {} index = 0 # single qubit terms for m in range(N): self.pulses.append( Pulse(sigmax(), [m + 1], spline_kind=self.spline_kind)) self.pulse_dict["sx" + str(m)] = index index += 1 for m in range(N): self.pulses.append( Pulse(sigmaz(), [m + 1], spline_kind=self.spline_kind)) self.pulse_dict["sz" + str(m)] = index index += 1 # coupling terms a = tensor([destroy(self.num_levels)] + [identity(2) for n in range(N)]) for n in range(N): sm = tensor( [identity(self.num_levels)] + [destroy(2) if m == n else identity(2) for m in range(N)]) self.pulses.append( Pulse(a.dag() * sm + a * sm.dag(), list(range(N + 1)), spline_kind=self.spline_kind)) self.pulse_dict["g" + str(n)] = index index += 1
def _opto_liouvillian(N): from qutip.tensor import tensor from qutip.operators import destroy, qeye from qutip.superoperator import liouvillian Nc = 5 # Number of cavity states Nm = N # Number of mech states kappa = 0.3 # Cavity damping rate E = 0.1 # Driving Amplitude g0 = 2.4*kappa # Coupling strength Qm = 1e4 # Mech quality factor gamma = 1/Qm # Mech damping rate n_th = 1 # Mech bath temperature delta = -0.43 # Detuning a = tensor(destroy(Nc), qeye(Nm)) b = tensor(qeye(Nc), destroy(Nm)) num_b = b.dag()*b num_a = a.dag()*a H = -delta*(num_a)+num_b+g0*(b.dag()+b)*num_a+E*(a.dag()+a) cc = np.sqrt(kappa)*a cm = np.sqrt(gamma*(1.0 + n_th))*b cp = np.sqrt(gamma*n_th)*b.dag() c_ops = [cc,cm,cp] return liouvillian(H, c_ops)
def test_id_with_T1_T2(self): """ Test for identity evolution with relaxation t1 and t2 """ # setup a = destroy(2) Hadamard = hadamard_transform(1) ex_state = basis(2, 1) mines_state = (basis(2, 1) - basis(2, 0)).unit() end_time = 2. tlist = np.arange(0, end_time + 0.02, 0.02) t1 = 1. t2 = 0.5 # test t1 test = Processor(1, t1=t1) # zero ham evolution test.add_pulse(Pulse(identity(2), 0, tlist, False)) result = test.run_state(ex_state, e_ops=[a.dag() * a]) assert_allclose(result.expect[0][-1], np.exp(-1. / t1 * end_time), rtol=1e-5, err_msg="Error in t1 time simulation") # test t2 test = Processor(1, t2=t2) test.add_pulse(Pulse(identity(2), 0, tlist, False)) result = test.run_state(init_state=mines_state, e_ops=[Hadamard * a.dag() * a * Hadamard]) assert_allclose(result.expect[0][-1], np.exp(-1. / t2 * end_time) * 0.5 + 0.5, rtol=1e-5, err_msg="Error in t2 time simulation") # test t1 and t2 t1 = np.random.rand(1) + 0.5 t2 = np.random.rand(1) * 0.5 + 0.5 test = Processor(1, t1=t1, t2=t2) test.add_pulse(Pulse(identity(2), 0, tlist, False)) result = test.run_state(init_state=mines_state, e_ops=[Hadamard * a.dag() * a * Hadamard]) assert_allclose(result.expect[0][-1], np.exp(-1. / t2 * end_time) * 0.5 + 0.5, rtol=1e-5, err_msg="Error in t1 & t2 simulation, " "with t1={} and t2={}".format(t1, t2))
def test_QobjUnitaryOper(): "Qobj unitarity" # Check some standard operators Sx = sigmax() Sy = sigmay() assert_unitarity(qeye(4), True) assert_unitarity(Sx, True) assert_unitarity(Sy, True) assert_unitarity(sigmam(), False) assert_unitarity(destroy(10), False) # Check multiplcation of unitary is unitary assert_unitarity(Sx * Sy, True) # Check some other operations clear unitarity assert_unitarity(Sx + Sy, False) assert_unitarity(4 * Sx, False) assert_unitarity(Sx * 4, False) assert_unitarity(4 + Sx, False) assert_unitarity(Sx + 4, False)
def test_QobjUnitaryOper(): "Qobj unitarity" # Check some standard operators Sx = sigmax() Sy = sigmay() assert_unitarity(qeye(4), True, "qeye(4) should be unitary.") assert_unitarity(Sx, True, "sigmax() should be unitary.") assert_unitarity(Sy, True, "sigmax() should be unitary.") assert_unitarity(sigmam(), False, "sigmam() should NOT be unitary.") assert_unitarity(destroy(10), False, "destroy(10) should NOT be unitary.") # Check multiplcation of unitary is unitary assert_unitarity(Sx*Sy, True, "sigmax()*sigmay() should be unitary.") # Check some other operations clear unitarity assert_unitarity(Sx+Sy, False, "sigmax()+sigmay() should NOT be unitary.") assert_unitarity(4*Sx, False, "4*sigmax() should NOT be unitary.") assert_unitarity(Sx*4, False, "sigmax()*4 should NOT be unitary.") assert_unitarity(4+Sx, False, "4+sigmax() should NOT be unitary.") assert_unitarity(Sx+4, False, "sigmax()+4 should NOT be unitary.")
def test_T1_T2(self): # setup a = destroy(2) Hadamard = hadamard_transform(1) ex_state = basis(2, 1) mines_state = (basis(2, 1)-basis(2, 0)).unit() end_time = 2. tlist = np.arange(0, end_time + 0.02, 0.02) H_d = 10.*sigmaz() t1 = 1. t2 = 0.5 # test t1 test = OptPulseProcessor(1, drift=H_d, t1=t1) test.tlist = tlist result = test.run_state(ex_state, e_ops=[a.dag()*a]) assert_allclose( result.expect[0][-1], np.exp(-1./t1*end_time), rtol=1e-5, err_msg="Error in t1 time simulation") # test t2 test = OptPulseProcessor(1, t2=t2) test.tlist = tlist result = test.run_state( rho0=mines_state, e_ops=[Hadamard*a.dag()*a*Hadamard]) assert_allclose( result.expect[0][-1], np.exp(-1./t2*end_time)*0.5+0.5, rtol=1e-5, err_msg="Error in t2 time simulation") # test t1 and t2 t1 = np.random.rand(1) + 0.5 t2 = np.random.rand(1) * 0.5 + 0.5 test = OptPulseProcessor(1, t1=t1, t2=t2) test.tlist = tlist result = test.run_state( rho0=mines_state, e_ops=[Hadamard*a.dag()*a*Hadamard]) assert_allclose( result.expect[0][-1], np.exp(-1./t2*end_time)*0.5+0.5, rtol=1e-5, err_msg="Error in t1 & t2 simulation, " "with t1={} and t2={}".format(t1, t2))
def testWaveguideSplit(self): """ Checks that a trivial splitting of a waveguide collapse operator like [sm] -> [sm/sqrt2, sm/sqrt2] doesn't affect the normalization or result """ gamma = 1.0 sm = np.sqrt(gamma) * destroy(2) pulseArea = np.pi pulseLength = 0.2 / gamma RabiFreq = pulseArea / (2 * pulseLength) psi0 = basis(2, 0) tlist = np.geomspace(gamma, 10 * gamma, 40) - gamma # Define TLS Hamiltonian with rotating frame transformation Htls = [[sm.dag() + sm, lambda t, args: RabiFreq * (t < pulseLength)]] # Run the test c_ops = [sm] c_ops_split = [sm / np.sqrt(2), sm / np.sqrt(2)] P1 = scattering_probability(Htls, psi0, 1, c_ops, tlist) P1_split = scattering_probability(Htls, psi0, 1, c_ops_split, tlist) tolerance = 1e-7 assert_(1 - tolerance < P1 / P1_split < 1 + tolerance)
def test_QobjHerm(): "Qobj Hermicity" N = 10 data = np.random.random( (N, N)) + 1j * np.random.random((N, N)) - (0.5 + 0.5j) q = Qobj(data) assert_equal(q.isherm, False) data = data + data.conj().T q = Qobj(data) assert_(q.isherm) q_a = destroy(5) assert_(not q_a.isherm) q_ad = create(5) assert_(not q_ad.isherm) # test addition of two nonhermitian operators adding up to a hermitian one q_x = q_a + q_ad assert_hermicity(q_x, True) # test addition of one hermitan and one nonhermitian operator q = q_x + q_a assert_hermicity(q, False) # test addition of two hermitan operators q = q_x + q_x assert_hermicity(q, True) # Test multiplication of two Hermitian operators. # This results in a skew-Hermitian operator, so # we're checking here that __mul__ doesn't set wrong # metadata. q = sigmax() * sigmay() assert_hermicity(q, False, "Expected iZ = X * Y to be skew-Hermitian.") # Similarly, we need to check that -Z = X * iY is correctly # identified as Hermitian. q = sigmax() * (1j * sigmay()) assert_hermicity(q, True, "Expected -Z = X * iY to be Hermitian.")
def rand_super(N=5, dims=None): """ Returns a randomly drawn superoperator acting on operators acting on N dimensions. Parameters ---------- N : int Square root of the dimension of the superoperator to be returned. dims : list Dimensions of quantum object. Used for specifying tensor structure. Default is dims=[[[N],[N]], [[N],[N]]]. """ if dims is not None: # TODO: check! pass else: dims = [[[N], [N]], [[N], [N]]] H = rand_herm(N) S = propagator(H, np.random.rand(), [create(N), destroy(N), jmat(float(N - 1) / 2.0, "z")]) S.dims = dims return S
def testOperatorStateList(self): """ expect: operator and state list """ N = 10 op = num(N) res = expect(op, [fock(N, n) for n in range(N)]) assert_(all(res == range(N))) assert_(isinstance(res, np.ndarray) and res.dtype == np.float64) res = expect(op, [fock_dm(N, n) for n in range(N)]) assert_(all(res == range(N))) assert_(isinstance(res, np.ndarray) and res.dtype == np.float64) op = destroy(N) res = expect(op, [fock(N, n) for n in range(N)]) assert_(all(res == np.zeros(N))) assert_(isinstance(res, np.ndarray) and res.dtype == np.complex128) res = expect(op, [fock_dm(N, n) for n in range(N)]) assert_(all(res == np.zeros(N))) assert_(isinstance(res, np.ndarray) and res.dtype == np.complex128)
def rand_super(dim=5): H = rand_herm(dim) return propagator(H, np.random.rand(), [ create(dim), destroy(dim), jmat(float(dim - 1) / 2.0, 'z') ])
def coherent(N, alpha, offset=0, method='operator'): """Generates a coherent state with eigenvalue alpha. Constructed using displacement operator on vacuum state. Parameters ---------- N : int Number of Fock states in Hilbert space. alpha : float/complex Eigenvalue of coherent state. offset : int (default 0) The lowest number state that is included in the finite number state representation of the state. Using a non-zero offset will make the default method 'analytic'. method : string {'operator', 'analytic'} Method for generating coherent state. Returns ------- state : qobj Qobj quantum object for coherent state Examples -------- >>> coherent(5,0.25j) Quantum object: dims = [[5], [1]], shape = [5, 1], type = ket Qobj data = [[ 9.69233235e-01+0.j ] [ 0.00000000e+00+0.24230831j] [ -4.28344935e-02+0.j ] [ 0.00000000e+00-0.00618204j] [ 7.80904967e-04+0.j ]] Notes ----- Select method 'operator' (default) or 'analytic'. With the 'operator' method, the coherent state is generated by displacing the vacuum state using the displacement operator defined in the truncated Hilbert space of size 'N'. This method guarantees that the resulting state is normalized. With 'analytic' method the coherent state is generated using the analytical formula for the coherent state coefficients in the Fock basis. This method does not guarantee that the state is normalized if truncated to a small number of Fock states, but would in that case give more accurate coefficients. """ if method == "operator" and offset == 0: x = basis(N, 0) a = destroy(N) D = (alpha * a.dag() - conj(alpha) * a).expm() return D * x elif method == "analytic" or offset > 0: sqrtn = np.sqrt(np.arange(offset, offset+N, dtype=complex)) sqrtn[0] = 1 # Get rid of divide by zero warning data = alpha/sqrtn if offset == 0: data[0] = np.exp(-abs(alpha)**2 / 2.0) else: s = np.prod(np.sqrt(np.arange(1, offset + 1))) # sqrt factorial data[0] = np.exp(-abs(alpha)**2 / 2.0) * alpha**(offset) / s np.cumprod(data, out=sqrtn) # Reuse sqrtn array return Qobj(sqrtn) else: raise TypeError( "The method option can only take values 'operator' or 'analytic'")
def rand_super(): h_5 = rand_herm(5) return propagator(h_5, scipy.rand(), [ create(5), destroy(5), jmat(2, 'z') ])