1from numpy.testing import assert_, run_module_suite, assert_allclose
2import numpy as np
3
4from qutip.qip.device.processor import Processor
5from qutip.qip.noise import (
6    Noise, RelaxationNoise, DecoherenceNoise, ControlAmpNoise, RandomNoise)
7from qutip.operators import qeye, sigmaz, sigmax, sigmay, destroy, identity
8from qutip.tensor import tensor
9from qutip.qobjevo import QobjEvo
10from qutip.states import basis
11from qutip.metrics import fidelity
12from qutip.tensor import tensor
13from qutip.qip.pulse import Pulse
14
15
16class DriftNoise(Noise):
17    def __init__(self, op):
18        self.qobj = op
19
20    def get_noisy_dynamics(self, dims, pulses, systematic_noise):
21        systematic_noise.add_coherent_noise(self.qobj, 0, coeff=True)
22        # test the backward compatibility
23        return pulses
24
25
26class TestNoise:
27    def test_decoherence_noise(self):
28        """
29        Test for the decoherence noise
30        """
31        tlist = np.array([1, 2, 3, 4, 5, 6])
32        coeff = np.array([1, 1, 1, 1, 1, 1])
33
34        # Time-dependent
35        decnoise = DecoherenceNoise(
36            sigmaz(), coeff=coeff, tlist=tlist, targets=[1])
37        dims = [2] * 2
38        pulses, systematic_noise = decnoise.get_noisy_dynamics(dims=dims)
39        noisy_qu, c_ops = systematic_noise.get_noisy_qobjevo(dims=dims)
40        assert_allclose(c_ops[0].ops[0].qobj, tensor(qeye(2), sigmaz()))
41        assert_allclose(c_ops[0].ops[0].coeff, coeff)
42        assert_allclose(c_ops[0].tlist, tlist)
43
44        # Time-indenpendent and all qubits
45        decnoise = DecoherenceNoise(sigmax(), all_qubits=True)
46        pulses, systematic_noise = decnoise.get_noisy_dynamics(dims=dims)
47        noisy_qu, c_ops = systematic_noise.get_noisy_qobjevo(dims=dims)
48        c_ops = [qu.cte for qu in c_ops]
49        assert_(tensor([qeye(2), sigmax()]) in c_ops)
50        assert_(tensor([sigmax(), qeye(2)]) in c_ops)
51
52        # Time-denpendent and all qubits
53        decnoise = DecoherenceNoise(
54            sigmax(), all_qubits=True, coeff=coeff*2, tlist=tlist)
55        pulses, systematic_noise = decnoise.get_noisy_dynamics(dims=dims)
56        noisy_qu, c_ops = systematic_noise.get_noisy_qobjevo(dims=dims)
57        assert_allclose(c_ops[0].ops[0].qobj, tensor(sigmax(), qeye(2)))
58        assert_allclose(c_ops[0].ops[0].coeff, coeff*2)
59        assert_allclose(c_ops[0].tlist, tlist)
60        assert_allclose(c_ops[1].ops[0].qobj, tensor(qeye(2), sigmax()))
61
62    def test_relaxation_noise(self):
63        """
64        Test for the relaxation noise
65        """
66        # only t1
67        a = destroy(2)
68        dims = [2] * 3
69        relnoise = RelaxationNoise(t1=[1., 1., 1.], t2=None)
70        systematic_noise = Pulse(None, None, label="system")
71        pulses, systematic_noise = relnoise.get_noisy_dynamics(
72            dims=dims, systematic_noise=systematic_noise)
73        noisy_qu, c_ops = systematic_noise.get_noisy_qobjevo(dims=dims)
74        assert_(len(c_ops) == 3)
75        assert_allclose(c_ops[1].cte, tensor([qeye(2), a, qeye(2)]))
76
77        # no relaxation
78        dims = [2] * 2
79        relnoise = RelaxationNoise(t1=None, t2=None)
80        systematic_noise = Pulse(None, None, label="system")
81        pulses, systematic_noise = relnoise.get_noisy_dynamics(
82            dims=dims, systematic_noise=systematic_noise)
83        noisy_qu, c_ops = systematic_noise.get_noisy_qobjevo(dims=dims)
84        assert_(len(c_ops) == 0)
85
86        # only t2
87        relnoise = RelaxationNoise(t1=None, t2=[0.2, 0.7])
88        systematic_noise = Pulse(None, None, label="system")
89        pulses, systematic_noise = relnoise.get_noisy_dynamics(
90            dims=dims, systematic_noise=systematic_noise)
91        noisy_qu, c_ops = systematic_noise.get_noisy_qobjevo(dims=dims)
92        assert_(len(c_ops) == 2)
93
94        # t1+t2 and systematic_noise = None
95        relnoise = RelaxationNoise(t1=[1., 1.], t2=[0.5, 0.5])
96        pulses, systematic_noise = relnoise.get_noisy_dynamics(dims=dims)
97        noisy_qu, c_ops = systematic_noise.get_noisy_qobjevo(dims=dims)
98        assert_(len(c_ops) == 4)
99
100    def test_control_amplitude_noise(self):
101        """
102        Test for the control amplitude noise
103        """
104        tlist = np.array([1, 2, 3, 4, 5, 6])
105        coeff = np.array([1, 1, 1, 1, 1, 1])
106
107        # use proc_qobjevo
108        pulses = [Pulse(sigmaz(), 0, tlist, coeff)]
109        connoise = ControlAmpNoise(coeff=coeff, tlist=tlist)
110        noisy_pulses, systematic_noise = \
111            connoise.get_noisy_dynamics(pulses=pulses)
112        assert_allclose(pulses[0].coherent_noise[0].qobj, sigmaz())
113        assert_allclose(noisy_pulses[0].coherent_noise[0].coeff, coeff)
114
115    def test_random_noise(self):
116        """
117        Test for the white noise
118        """
119        tlist = np.array([1, 2, 3, 4, 5, 6])
120        coeff = np.array([1, 1, 1, 1, 1, 1])
121        dummy_qobjevo = QobjEvo(sigmaz(), tlist=tlist)
122        mean = 0.
123        std = 0.5
124        pulses = [Pulse(sigmaz(), 0, tlist, coeff),
125                  Pulse(sigmax(), 0, tlist, coeff*2),
126                  Pulse(sigmay(), 0, tlist, coeff*3)]
127
128        # random noise with operators from proc_qobjevo
129        gaussnoise = RandomNoise(
130            dt=0.1, rand_gen=np.random.normal, loc=mean, scale=std)
131        noisy_pulses, systematic_noise = \
132            gaussnoise.get_noisy_dynamics(pulses=pulses)
133        assert_allclose(noisy_pulses[2].qobj, sigmay())
134        assert_allclose(noisy_pulses[1].coherent_noise[0].qobj, sigmax())
135        assert_allclose(
136            len(noisy_pulses[0].coherent_noise[0].tlist),
137            len(noisy_pulses[0].coherent_noise[0].coeff))
138
139        # random noise with dt and other random number generator
140        pulses = [Pulse(sigmaz(), 0, tlist, coeff),
141                  Pulse(sigmax(), 0, tlist, coeff*2),
142                  Pulse(sigmay(), 0, tlist, coeff*3)]
143        gaussnoise = RandomNoise(lam=0.1, dt=0.2, rand_gen=np.random.poisson)
144        assert_(gaussnoise.rand_gen is np.random.poisson)
145        noisy_pulses, systematic_noise = \
146            gaussnoise.get_noisy_dynamics(pulses=pulses)
147        assert_allclose(
148            noisy_pulses[0].coherent_noise[0].tlist,
149            np.linspace(1, 6, int(5/0.2) + 1))
150        assert_allclose(
151            noisy_pulses[1].coherent_noise[0].tlist,
152            np.linspace(1, 6, int(5/0.2) + 1))
153        assert_allclose(
154            noisy_pulses[2].coherent_noise[0].tlist,
155            np.linspace(1, 6, int(5/0.2) + 1))
156
157    def test_user_defined_noise(self):
158        """
159        Test for the user-defined noise object
160        """
161        dr_noise = DriftNoise(sigmax())
162        proc = Processor(1)
163        proc.add_noise(dr_noise)
164        tlist = np.array([0, np.pi/2.])
165        proc.add_pulse(Pulse(identity(2), 0, tlist, False))
166        result = proc.run_state(init_state=basis(2, 0))
167        assert_allclose(
168            fidelity(result.states[-1], basis(2, 1)), 1, rtol=1.0e-6)
169