Example #1
0
    def main1():
        print('--------------------main1')
        np.random.seed(123)
        dm = DenMat(8, (2, 2, 2))
        exact_evas = np.array([.1, .3, .3, .1, .2, .1, .6, .7])
        exact_evas /= np.sum(exact_evas)
        print('evas of dm\n', np.sort(exact_evas))
        dm.set_arr_to_rand_den_mat(exact_evas)

        pert = DenMatPertTheory.new_with_separable_dm0(dm, verbose=True)
        # print('evas of dm to 2nd order (after 1 step)\n',
        #       np.sort(pert.evas_of_dm_to_2nd_order),
        #       'sum=', np.sum(pert.evas_of_dm_to_2nd_order))
        # print('evas of dm\n', np.sort(evas))

        # print('evas_of_dm0\n', pert.dm0_eigen_sys[0])
        #
        # print('diag of del_dm in sbasis\n',
        #       np.diag(pert.del_dm_in_sbasis.arr.real))

        # print('del_dm\n', pert.del_dm)
        # dm0 = pert.get_dm0()
        # print('dm0\n', dm0)

        num_steps = 40
        # print('evas_of_dm\n', evas)
        main_test(dm, exact_evas, pert, num_steps)
Example #2
0
 def main():
     num_qbits = 5
     num_up = 2
     dm = DenMat(1 << num_qbits, tuple([2]*num_qbits))
     st = SymNupState(num_up, num_qbits)
     st_vec = st.get_st_vec()
     dm.set_arr_from_st_vec(st_vec)
     ecase = PureStEnt(dm, 'eigen')
     pf = ecase.get_entang_profile()
     # print(',,...', pf)
     ecase.print_entang_profiles([pf, pf], dm.row_shape)
Example #3
0
    def main2():
        print('--------------------main2')
        np.random.seed(123)

        dm1 = DenMat(3, (3,))
        evas1 = np.array([.1, .1, .4])
        evas1 /= np.sum(evas1)
        dm1.set_arr_to_rand_den_mat(evas1)
        # print('dm1\n', dm1)

        dm2 = DenMat(2, (2,))
        evas2 = np.array([.8, .3])
        evas2 /= np.sum(evas2)
        dm2.set_arr_to_rand_den_mat(evas2)
        # print('dm2\n', dm2)

        dm = DenMat.get_kron_prod_of_den_mats([dm1, dm2])
        const = 0
        # const = 1
        dm.add_const_to_diag_of_arr(const)
        dm.normalize_diag_of_arr()
        print('kron evas\n', np.sort(ut.kron_prod([evas1, evas2])))
        exact_evas = np.linalg.eigvalsh(dm.arr)
        print('evas_of_dm\n', exact_evas)

        pert = DenMatPertTheory.new_with_separable_dm0(dm, verbose=True)

        # print('evas of dm to 2nd order (after 1 step)\n',
        #       np.sort(pert.evas_of_dm_to_2nd_order),
        #       'sum=', np.sum(pert.evas_of_dm_to_2nd_order))
        num_steps = 10
        main_test(dm, exact_evas, pert, num_steps)
Example #4
0
    def main3():
        print('--------------------main3')
        num_qbits = 4
        num_up = 2
        dm = DenMat(1 << num_qbits, tuple([2]*num_qbits))
        st = SymNupState(num_up, num_qbits)
        st_vec = st.get_st_vec()
        dm.set_arr_from_st_vec(st_vec)
        # dm.depurify(.1)

        exact_evas = np.linalg.eigvalsh(dm.arr)
        print('evas_of_dm\n', exact_evas, 'sum=', np.sum(exact_evas))

        pert = DenMatPertTheory.new_with_separable_dm0(dm, verbose=True)
        num_steps = 80
        main_test(dm, exact_evas, pert, num_steps)
Example #5
0
    def do_bstrap_with_separable_dm0(dm, num_steps=1, verbose=False):
        """
        This method returns the same thing as the method (found in its
        parent class) DenMatPertTheory.do_bstrap( ). However, their names
        differ by a '_with_separable_dm0' at the end and their inputs are
        different. This one takes as input a density matrix dm and
        calculates dm0_eigen_sys and del_dm from that, assuming that dm0 is
        the Kronecker product of the marginals of dm.

        Parameters
        ----------
        dm : DenMat
        num_steps : int
        verbose : bool

        Returns
        -------
        tuple[np.ndaray, np.ndarray]

        """
        if dm.marginals is None:
            dm.set_marginals()
        esys = dm.get_eigen_sys_of_marginals()
        dm0_eigen_sys = (ut.kron_prod(esys[0]),
                         ut.kron_prod(esys[1]))
        arr = ut.kron_prod([marg.arr for marg in dm.marginals])
        dm0 = DenMat(dm.num_rows, dm.row_shape, arr)
        return DenMatPertTheory.do_bstrap(
            dm0_eigen_sys, dm-dm0, num_steps, verbose)
Example #6
0
    def get_den_mat_with_bound_entang(p):
        """
        This method returns a DenMat with num_rows = 8 and row_shape = (2,
        4) that is known to have bound entanglement.

        https://arxiv.org/abs/quant-ph/9703004

        Parameters
        ----------
        p : float
            a probability, 0 < p < 1

        Returns
        -------
        DenMat

        """
        num_rows = 8
        row_shape = (2, 4)
        a = (1 + p) / 2
        b = np.sqrt(1 - p**2) / 2
        arr1 = np.array([[p, 0, 0, 0, 0, p, 0, 0], [0, p, 0, 0, 0, 0, p, 0],
                         [0, 0, p, 0, 0, 0, 0, p], [0, 0, 0, p, 0, 0, 0, 0],
                         [0, 0, 0, 0, a, 0, 0, b], [p, 0, 0, 0, 0, p, 0, 0],
                         [0, p, 0, 0, 0, 0, p, 0], [0, 0, p, 0, b, 0, 0, a]])
        return DenMat(num_rows, row_shape, arr1 / np.trace(arr1))
Example #7
0
    def get_bell_basis_diag_dm(fid, prob_dict=None):
        """
        This method returns a DenMat which is constructed as a linear
        combination, with coefficients prob_dict, of the Bell basis state
        projection operators. So the den matrix returned is diagonal in the
        Bell basis.

        If prob_dict is not None, use it and ignore value of fid. If
        prob_dict is None, use prob_dict for an "isotropic" Werner state
        with fidelity fid. That is, prob_dict[ "==+"]=fid, prob_dict[x]=(
        1-fid)/3 for all x other than '==+"

        Parameters
        ----------
        fid : float
            fidelity.
        prob_dict : dict[str, float]|None

        Returns
        -------
        DenMat

        """
        if prob_dict:
            assert ut.is_prob_dist(np.array(list(prob_dict.values())))
            assert set(prob_dict.keys()) == TwoQubitState.bell_key_set()
        else:
            assert 0 <= fid <= 1
            prob_dict = {}
            for key in TwoQubitState.bell_key_set():
                if key == '==+':
                    prob_dict[key] = fid
                else:
                    prob_dict[key] = (1 - fid) / 3

        dm = DenMat(4, (2, 2))
        dm.set_arr_to_zero()
        for key in prob_dict.keys():
            st_vec = TwoQubitState.get_bell_basis_st_vec(key)
            dm.arr += np.outer(st_vec, np.conj(st_vec)) * prob_dict[key]
        return dm
Example #8
0
 def main():
     print('4 Bell Basis states**********************')
     for bits_are_equal in [True, False]:
         for mid_sign in ['+', '-']:
             st_vec = OtherStates.get_bell_basis_st_vec(bits_are_equal, mid_sign)
             dm = DenMat(4, (2, 2))
             dm.set_arr_from_st_vec(st_vec)
             ecase = PureStEnt(dm)
             pf = ecase.get_entang_profile()
             print('----------bits_are_equal=', bits_are_equal,
                   ', mid_sign=', mid_sign)
             print("st_vec=\n", st_vec)
             ecase.print_entang_profiles([pf], dm.row_shape)
     print('bound entang state **********************')
     dm_bd = OtherStates.get_den_mat_with_bound_entang(.5)
     num_hidden_states = 5
     num_ab_steps = 30
     ecase = SquashedEnt(dm_bd, num_hidden_states, num_ab_steps,
                         verbose=True)
     pf = ecase.get_entang_profile()
     ecase.print_entang_profiles([pf], dm_bd.row_shape)
Example #9
0
    def check_max_entang_st(st):
        """
        This method checks that the object st of class MaxEntangState does
        indeed carry maximal entanglement. The entanglement is calculated 3
        different ways (von Neumann entropy of 2 partial traces of density
        matrix, and from known value) and the 3 values are checked to agree.

        Parameters
        ----------
        st : MaxEntangState

        Returns
        -------
        None

        """
        dm = DenMat(st.num_rows, st.row_shape)
        st_vec = st.get_st_vec()
        dm.set_arr_from_st_vec(st_vec)
        ent1 = dm.get_partial_tr(set(st.y_axes)).get_entropy()
        ent2 = dm.get_partial_tr(set(st.x_axes)).get_entropy()
        ent3 = np.log(st.num_vals_min)
        assert abs(ent1 - ent2) < 1e-6 and abs(ent1 - ent3) < 1e-6, \
            str(ent1) + ', ' + str(ent2) + ', ' + str(ent3)
Example #10
0
    def get_dm0(self):
        """
        This method returns the unperturbed density matrix dm0. We define
        this method so as to avoid storing dm0.

        Returns
        -------
        DenMat

        """
        evas = self.dm0_eigen_sys[0]
        evec_cols = self.dm0_eigen_sys[1]
        arr = ut.fun_of_herm_arr_from_eigen_sys(lambda x: x, evas, evec_cols)
        num_rows = self.del_dm.num_rows
        row_shape = self.del_dm.row_shape
        return DenMat(num_rows, row_shape, arr)
Example #11
0
    def get_time_reversed_dm(dm):
        """
        This method returns a DenMat which is the time reversed version of a
        DenMat dm for 2 qubits.

        Parameters
        ----------
        dm : DenMat

        Returns
        -------
        DenMat

        """
        assert dm.num_rows == 4
        sigy = np.array([[0, -1j], [1j, 0]])
        dm_sigyy = DenMat(4, (2, 2), arr=ut.kron_prod([sigy, sigy]))
        return dm_sigyy * dm.conj() * dm_sigyy
Example #12
0
    def new_with_separable_dm0(dm, verbose=False):
        """
        This method returns a DenMatPertTheory built from a density matrix
        dm, assuming that dm0 is the Kronecker product of the marginals of dm.

        Parameters
        ----------
        dm : DenMat
        verbose : bool

        Returns
        -------
        DenMatPertTheory

        """
        if dm.marginals is None:
            dm.set_marginals()
        esys = dm.get_eigen_sys_of_marginals()
        dm0_eigen_sys = (ut.kron_prod(esys[0]), ut.kron_prod(esys[1]))
        arr = ut.kron_prod([marg.arr for marg in dm.marginals])
        dm0 = DenMat(dm.num_rows, dm.row_shape, arr)

        return DenMatPertTheory(dm0_eigen_sys, dm - dm0, verbose)
Example #13
0
 def main1():
     print('4 Bell Basis states**********************')
     for key in TwoQubitState.bell_key_set():
         st_vec = TwoQubitState.get_bell_basis_st_vec(key)
         dm = DenMat(4, (2, 2))
         dm.set_arr_from_st_vec(st_vec)
         ecase = PureStEnt(dm)
         pf = ecase.get_entang_profile()
         print('----------key:', key)
         print("st_vec=\n", st_vec)
         ecase.print_entang_profiles([pf], dm.row_shape)
     print("*******************************")
     dm1 = TwoQubitState.get_bell_basis_diag_dm(fid=.7)
     # print('arr=\n', dm1.arr)
     np.random.seed(123)
     dm2 = DenMat(4, (2, 2))
     dm2.set_arr_to_rand_den_mat(np.array([.1, .2, .3, .4]))
     dm3 = DenMat(4, (2, 2))
     dm3.set_arr_to_rand_den_mat(np.array([.1, .1, .1, .7]))
     for dm in [dm1, dm2, dm3]:
         print("----------new dm")
         print("formation_entang=",
               TwoQubitState.get_known_formation_entang(dm))