Beispiel #1
0
    def test_3qb(self):
        from_np = self.from_numpy
        to_np = self.to_numpy

        wf = from_np(get_random_wf(np, 3))
        rho = make_density_matrix(wf)

        o1 = partial_trace_wf_keep_first(wf, 1)
        s1 = partial_trace(rho, retain_qubits=[0])
        assert np.allclose(to_np(o1), to_np(s1))

        o1 = partial_trace_wf_keep_first(wf, 2)
        s1 = partial_trace(rho, retain_qubits=[0, 1])
        assert np.allclose(to_np(o1), to_np(s1))
Beispiel #2
0
    def test_work_for_mixed_case_ndim(self):
        mep = self.mep
        mep_reduced = self.mep_reduced
        from_np = self.from_numpy
        to_np = self.to_numpy
        rho1 = to_np(partial_trace(from_np(mep), (0,)))
        rho2 = to_np(partial_trace(from_np(mep), (1,)))
        assert np.array_equal(rho1, mep_reduced)
        assert np.array_equal(rho2, mep_reduced)

        rho_cpx = self.rho_cpx
        rho_0 = self.rho_cpx_0
        rho_1 = self.rho_cpx_1
        assert np.array_equal(rho_0, to_np(partial_trace(from_np(rho_cpx), (0,))))
        assert np.array_equal(rho_1, to_np(partial_trace(from_np(rho_cpx), (1,))))
Beispiel #3
0
    def test_nd_retain_qbs_order_does_not_matter(self):
        from_np = self.from_numpy
        to_np = self.to_numpy

        nqb = 4
        dim = 2 ** nqb
        qbs_tokeep = np.array([1, 2, 3])
        qbs_tokeep_shuffled = qbs_tokeep.copy()
        while np.array_equal(qbs_tokeep_shuffled, qbs_tokeep):
            np.random.shuffle(qbs_tokeep_shuffled)

        rho = np.random.rand(dim, dim) + 1j * np.random.rand(dim, dim)
        rho = from_np(rho)
        assert np.allclose(
            to_np(partial_trace(rho, retain_qubits=qbs_tokeep)),
            to_np(partial_trace(rho, retain_qubits=qbs_tokeep_shuffled)),
        )
Beispiel #4
0
    def test_cupy_thread_dim_limit(self):
        # It is import to test when the thread dim is larger then 32 for cuda
        # code. This happens when there are more than 6 qubits to keep.
        # Note: 2 ** 5 = 32, 2 ** 6 = 64.
        # See the implementation for cuda for details.
        import numpy
        to_np = self.to_numpy

        wf = self.from_numpy(get_random_wf(numpy, 7))
        rho = make_density_matrix(wf)
        # Before boundary
        o1 = partial_trace_wf_keep_first(wf, 5)
        s1 = partial_trace(rho, retain_qubits=list(range(5)))
        assert numpy.allclose(to_np(o1), to_np(s1))

        # After boundary
        o1 = partial_trace_wf_keep_first(wf, 6)
        s1 = partial_trace(rho, retain_qubits=list(range(6)))
        assert numpy.allclose(to_np(o1), to_np(s1))
Beispiel #5
0
    def test_trivial_case_ndim(self):
        rand = np.random.rand
        from_np = self.from_numpy
        to_np = self.to_numpy
        rho = rand(2, 2) + 1j * rand(2, 2)

        assert np.array_equal(
            rho, to_np(partial_trace(from_np(rho), retain_qubits=[0]))
        )

        rho2 = from_np(rand(4, 4) + 1j * rand(4, 4))
        assert np.allclose(
            to_np(rho2), to_np(partial_trace(rho2, retain_qubits=[1, 0]))
        )

        # lastly, test if all qubits are killed
        assert np.allclose(
            np.trace(to_np(rho2)), to_np(partial_trace(rho2, retain_qubits=[]))
        )
Beispiel #6
0
    def test_1d_and_ndim_work_the_same(self):
        from_np = self.from_numpy
        to_np = self.to_numpy

        nqb = 4
        dim = 2 ** nqb
        qb_to_keep = 2
        rho = np.random.rand(dim, dim) + 1j * np.random.rand(dim, dim)
        rho = from_np(rho)
        assert np.allclose(
            to_np(partial_trace_1d(rho, retain_qubit=qb_to_keep)),
            to_np(partial_trace(rho, retain_qubits=(qb_to_keep,))),
        )
Beispiel #7
0
    def test_work_for_randommat_ndim(self):
        from_np = self.from_numpy
        to_np = self.to_numpy

        nqb = 4
        dim = 2 ** nqb
        qbs_tokeep = [1, 2]
        rho = np.random.rand(dim, dim) + 1j * np.random.rand(dim, dim)
        rho_tmp = from_np(rho)

        def get_shouldbe1(arho):
            arho = arho.reshape([2] * nqb * 2)
            # retains [1, 2]
            # [0,1,2,3, 4,5,6,7] -> [0,1,2, 4,5,6]  (trace 3, 7)
            arho = np.trace(arho, axis1=3, axis2=7)
            # [0,1,2, 4,5,6] -> [1,2, 5,6]  (trace 0, 3)
            arho = np.trace(arho, axis1=0, axis2=3)
            return arho.reshape(4, 4)

        assert np.allclose(
            to_np(partial_trace(rho_tmp, retain_qubits=qbs_tokeep)), get_shouldbe1(rho)
        )

        qbs_tokeep = [0, 3]

        def get_shouldbe2(arho):
            arho = arho.reshape([2] * nqb * 2)
            # retains [0, 3]
            # [0,1,2,3, 4,5,6,7] -> [0,1,3, 4,5,7]  (trace 2, 6)
            arho = np.trace(arho, axis1=2, axis2=6)
            # [0,1,3, 4,5,7] -> [0,3, 4,7]  (trace 1, 4)
            arho = np.trace(arho, axis1=1, axis2=4)
            return arho.reshape(4, 4)

        assert np.allclose(
            to_np(partial_trace(rho_tmp, retain_qubits=qbs_tokeep)), get_shouldbe2(rho)
        )
Beispiel #8
0
    def test_work_for_pure_states_ndim(self):
        from_np = self.from_numpy
        to_np = self.to_numpy

        plus_minus = self.plus_minus
        plus = self.plus
        minus = self.minus
        plus_to_test = partial_trace(from_np(plus_minus), retain_qubits=(0,))
        minus_to_test = partial_trace(from_np(plus_minus), retain_qubits=(1,))

        assert np.array_equal(plus, to_np(plus_to_test))
        assert np.array_equal(minus, to_np(minus_to_test))

        plus_plus_minus = self.ppmm
        p_1 = partial_trace(from_np(plus_plus_minus), retain_qubits=(0,))
        p_2 = partial_trace(from_np(plus_plus_minus), retain_qubits=(1,))
        m_1 = partial_trace(from_np(plus_plus_minus), retain_qubits=(2,))
        m_2 = partial_trace(from_np(plus_plus_minus), retain_qubits=(3,))

        assert np.array_equal(to_np(p_1), plus)
        assert np.array_equal(to_np(p_2), plus)
        assert np.array_equal(to_np(m_1), minus)
        assert np.array_equal(to_np(m_2), minus)
Beispiel #9
0
 def get_shouldbe(arho, retain):
     arho = from_np(arho)
     arho = partial_trace(arho, retain_qubits=retain)
     return to_np(arho)
Beispiel #10
0
 def ptwfs(iwf, retain_qubits):
     iwf = make_density_matrix(iwf)
     out = [partial_trace(iwf[i], retain_qubits) for i in range(iwf.shape[0])]
     out = [to_np(o) for o in out]
     return np.asarray(out)