def random_open_mps(l, phys_dim, chi, is_eco=False):
    # Create a random MPS with open boundary condition
    # l: length; d: physical dimension; chi: virtual dimension
    mps = list(range(0, l))
    dims = empty_list(l + 1, 1)
    if is_eco:
        for n in range(0, l):
            if type(phys_dim) is int:
                chi0 = min([phys_dim ** n, chi, phys_dim ** (l - n)])
                chi1 = min([phys_dim ** (n + 1), chi, phys_dim ** (l - n - 1)])
                d = phys_dim
            else:
                chi0 = min([np.prod(phys_dim[:n]), chi, np.prod(phys_dim[n:])])
                chi1 = min([np.prod(phys_dim[:n+1]), chi, np.prod(phys_dim[:n+1])])
                d = phys_dim[n]
            dims[n + 1] = chi1
            mps[n] = np.random.randn(chi0, d, chi1)
    else:
        if type(phys_dim) is int:
            mps[0] = np.random.randn(1, phys_dim, chi)
            mps[l-1] = np.random.randn(chi, phys_dim, 1)
            for n in range(1, l-1):
                mps[n] = np.random.randn(chi, phys_dim, chi)
                dims[n] = chi
            dims[l-1] = chi
        else:
            mps[0] = np.random.randn(1, phys_dim[0], chi)
            mps[l - 1] = np.random.randn(chi, phys_dim[l-1], 1)
            for n in range(1, l - 1):
                mps[n] = np.random.randn(chi, phys_dim[n], chi)
                dims[n] = chi
            dims[l - 1] = chi
    return mps, dims
Beispiel #2
0
def act_umpo_on_mps(mps, mpo, if_conjugate=False):
    mps1 = empty_list(mps.__len__())
    if if_conjugate:  # act on product state (evolve)
        mps1[0] = copy.deepcopy(mpo[0])
        for n in range(1, mps.__len__() - 1):
            mps1[n] = T_module.cont([mpo[n], mps[n - 1]],
                                    [[-1, -3, 1, -4], [-2, 1, -5]])
            s = mps1[n].shape
            mps1[n] = mps1[n].reshape(s[0] * s[1], s[2], s[3] * s[4])
        mps1[-1] = T_module.cont([mpo[-1], mps[-2], mps[-1]],
                                 [[-1, -3, 2, 3], [-2, 2, 1], [1, 3, -4]])
        s = mps1[-1].shape
        mps1[-1] = mps1[-1].reshape(s[0] * s[1], s[2], s[3])
    else:  # act on mps (disentangle)
        mps1[0] = T_module.cont(
            [mps[0].squeeze(), mps[1], mpo[0].squeeze(), mpo[1]],
            [[3, 1], [1, 4, -3], [3, 2], [2, 4, -1, -2]])
        mps1[0] = mps1[0].reshape(1, mpo[1].shape[2],
                                  mpo[1].shape[3] * mps[1].shape[2])
        for n in range(2, mps.__len__() - 1):
            mps1[n - 1] = T_module.cont([mps[n], mpo[n]],
                                        [[-2, 1, -5], [-1, 1, -3, -4]])
            s = mps1[n - 1].shape
            mps1[n - 1] = mps1[n - 1].reshape(s[0] * s[1], s[2], s[3] * s[4])
        mps1[-2] = T_module.cont([mps[-1].squeeze(), mpo[-1]],
                                 [[-2, 1], [-1, 1, -3, -4]])
        s = mps1[-2].shape
        mps1[-2] = mps1[-2].reshape(s[0] * s[1] * s[2], s[3])
        mps1[-2], lm, mps1[-1] = np.linalg.svd(mps1[-2],
                                               full_matrices=False,
                                               compute_uv=True)
        mps1[-2] = mps1[-2].reshape(s[0] * s[1], s[2], lm.size)
        mps1[-1] = np.diag(lm).dot(mps1[-1]).reshape(lm.size, s[3], 1)
    return mps1
def mps_ghz_state(num):
    d = 2
    mps = empty_list(num)
    mps[0] = np.eye(d) / np.sqrt(2)
    mps[0] = mps[0].reshape(1, d, d)
    for n in range(1, num-1):
        mps[n] = delta_tensor(d, 3)
    mps[num-1] = np.eye(d).reshape(d, d, 1)
    return mps
def artificial_open_mps(l, d, chi,):
    """
    Generate an open MPS randomly
    :param l:  length of MPS
    :param d: dimension on the physical bonds
    :param chi: dimension of inner bonds
    :param is_eco: use economic dimensions
    :return:  MPS
    """
    # Create a random MPS with open boundary condition
    # l: length; d: physical dimension; chi: virtual dimension
    temp_mps_up_0 = np.zeros((1, d, chi))
    temp_mps_up_end = np.zeros((chi, d, 1))
    temp_mps_up = np.zeros((chi,d,chi))
    temp_mps_down_0 = np.zeros((1, d, chi))
    temp_mps_down_end = np.zeros((chi, d, 1))
    temp_mps_down = np.zeros((chi,d,chi))
    R = 0.0001
    if d==2:
        temp_mps_up_0[0, :, 0] = np.array([1,0])
        temp_mps_up_end[0, :, 0] = np.array([1,0])
        temp_mps_up[0, :, 0] = np.array([1,0])

        temp_mps_down_0[0, :, 0] = np.array([0, 1])
        temp_mps_down_end[0, :, 0] = np.array([0, 1])
        temp_mps_down[0, :, 0] = np.array([0, 1])
    elif d==3:
        temp_mps_up_0[0, :, 0] = np.array([1, 0, 0])
        temp_mps_up_end[0, :, 0] = np.array([1, 0, 0])
        temp_mps_up[0, :, 0] = np.array([1, 0, 0])

        temp_mps_down_0[0, :, 0] = np.array([0, 0, 1])
        temp_mps_down_end[0, :, 0] = np.array([0, 0, 1])
        temp_mps_down[0, :, 0] = np.array([0, 0, 1])

    mps = list(range(0, l))
    dims = empty_list(l + 1, 1)
    mps[0] = temp_mps_up_0 + R*np.random.randn(1, d, chi)
    if np.mod(l,2)==0:
        mps[l-1] = temp_mps_down_end + R*np.random.randn(chi, d, 1)
    else:
        mps[l-1] = temp_mps_up_end + R*np.random.randn(chi, d, 1)

    for n in range(1, l - 1):
        if np.mod(n, 2) == 0:
            mps[n] = temp_mps_up+ R * np.random.randn(chi, d, chi)
        elif np.mod(n, 2)==1:
            mps[n] = temp_mps_down + R *np.random.randn(chi, d, chi)
        dims[n] = chi
    dims[l - 1] = chi
    return mps, dims
def random_open_mps(l, d, chi, is_eco=False):
    """
    Generate an open MPS randomly
    :param l:  length of MPS
    :param d: dimension on the physical bonds
    :param chi: dimension of inner bonds
    :param is_eco: use economic dimensions
    :return:  MPS
    Example:
        >>>M = random_open_mps(3, 2, 3)
        >>>print(M[0])
          [[[-2.5679364  -1.12846181  0.12026503]
            [ 1.23217514  0.58611443  0.66304506]]]
        >>>print(M[1])
          [[[ 0.02140644 -0.2359836   1.41704847]
            [ 0.42441594  0.11000762 -0.23754322]]

            [[ 0.42759564  0.32495413 -0.81798019]
             [-0.54115541  0.63275244 -0.31163543]]

            [[-1.11706565  0.36694417 -1.67561183]
             [-0.37247627  0.85373283  0.99919477]]]
        >>>print(M[2])
          [[[-1.01253065]
            [-0.82606855]]

           [[ 0.524324  ]
            [ 0.52489905]]

           [[ 0.68181659]
            [-0.62746486]]]
    """
    # Create a random MPS with open boundary condition
    # l: length; d: physical dimension; chi: virtual dimension
    mps = list(range(0, l))
    dims = empty_list(l + 1, 1)
    if is_eco:
        for n in range(0, l):
            chi0 = min([d ** n, chi, d ** (l - n)])
            chi1 = min([d ** (n + 1), chi, d ** (l - n - 1)])
            dims[n + 1] = chi1
            mps[n] = np.random.randn(chi0, d, chi1)
    else:
        mps[0] = np.random.randn(1, d, chi)
        mps[l-1] = np.random.randn(chi, d, 1)
        for n in range(1, l-1):
            mps[n] = np.random.randn(chi, d, chi)
            dims[n] = chi
        dims[l-1] = chi
    return mps, dims
def ones_open_mps(l, d, chi, is_eco=False):
    """
    Generate an open MPS with all elements are 1
    :param l:  length of MPS
    :param d: dimension on the physical bonds
    :param chi: dimension of inner bonds
    :return:  MPS
    Example:
        >>>M = ones_open_mps(3, 2, 3)
        >>>print(M[0])
          [[[1.  1.  1.]
            [1.  1.  1.]]]
        >>>print(M[1])
          [[[1.  1.  1.]
            [1.  1.  1.]]

            [[1.  1.  1.]
             [1.  1.  1.]]

            [[1.  1.  1.]
             [1.  1.  1.]]]
        >>>print(M[2])
          [[[1.]
            [1.]]

           [[1.]
            [1.]]

           [[1.]
            [1.]]]
    """
    mps = list(range(0, l))
    dims = empty_list(l + 1, 1)
    if is_eco:
        for n in range(0, l):
            chi0 = min([d ** n, chi, d ** (l - n)])
            chi1 = min([d ** (n + 1), chi, d ** (l - n - 1)])
            dims[n + 1] = chi1
            mps[n] = np.random.randn(chi0, d, chi1)
    else:
        mps[0] = np.random.randn(1, d, chi)
        mps[l - 1] = np.random.randn(chi, d, 1)
        for n in range(1, l - 1):
            mps[n] = np.random.randn(chi, d, chi)
            dims[n] = chi
        dims[l-1] = chi
    return mps, dims
def tensor_zn(shape, way):
    dim = len(shape)
    print(dim)
    ind = empty_list(dim, 0)
    shape = np.array(shape).reshape(-1, )
    tensor = np.zeros(shape)
    while ind[-1] != shape[-1]:
        if sum(ind) % 2 == 0:
            if way is 'randn':
                tensor[tuple(ind)] = np.random.randn()
            elif way is 'one':
                tensor[tuple(ind)] = 1
        ind[0] += 1
        for n in range(0, dim - 1):
            if ind[n] == shape[n]:
                ind[n] = 0
                ind[n + 1] += 1
    return tensor
def mpd_of_ghz(num):
    d = 2
    mpd = empty_list(num)
    mpd[0] = np.eye(d)
    mat = np.zeros((4, 4))
    mat[:, 0] = np.array([1, 0, 0, 0])
    mat[:, 1] = np.array([0, 0, 0, 1])
    mat[:, 2] = np.array([0, 1, 0, 0])
    mat[:, 3] = np.array([0, 0, 1, 0])
    mat = mat.reshape([d, d, d, d])
    for n in range(1, num-1):
        mpd[n] = copy.deepcopy(mat)
    mpd[num-1] = np.zeros((4, 4))
    mpd[num-1][:, 0] = np.array([1, 0, 0, 1]) / np.sqrt(2)
    mpd[num-1][:, 1] = np.array([1, 0, 0, -1]) / np.sqrt(2)
    mpd[num-1][:, 2] = np.array([0, 1, 0, 0])
    mpd[num-1][:, 3] = np.array([0, 0, 1, 0])
    mpd[num - 1] = mpd[num-1].reshape([d, d, d, d])
    return mpd
Beispiel #9
0
def deep_mps_qubit(mps, para=None, para_dmrg=None):
    if para is None:
        para = parameters_dmps()
    fid0 = mps.fidelity_log_by_spins_up()
    fid = np.ones((para['num_layers'], ))
    lm_mid = empty_list(para['num_layers'])
    ent = empty_list(para['num_layers'])
    mpo = empty_list(para['num_layers'])
    for n in range(para['num_layers']):
        # mps_chi2 = Mob(length=para_dmrg['l'], d=para_dmrg['d'], chi=para_dmrg['chi'], way='qr', ini_way='r',
        #                operators=para_dmrg['op'], is_parallel=para_dmrg['isParallel'],
        #                is_save_op=para_dmrg['is_save_op'], eig_way=para_dmrg['eigWay'],
        #                is_env_parallel_lmr=para_dmrg['isParallelEnvLMR'])
        # mps_chi2.mps = copy.deepcopy(mps.mps)
        mps_chi2 = copy.deepcopy(mps)
        mps_chi2.truncate_virtual_bonds(chi1=2,
                                        center=mps_chi2.length - 1,
                                        way='full')
        if para['theta'] is None:
            theta = np.arange(0, 1, 1 / para['num_theta'])
            mps_tmp = copy.deepcopy(mps_chi2)
            mps_new = copy.deepcopy(mps_chi2)
            for nn in range(theta.size):
                mpo_tmp = mps_chi2.to_unitary_mpo_qubits(
                    theta[nn], if_trun=False)  # calculate unitary MPO
                mps_data = act_umpo_on_mps(
                    mps.mps, mpo_tmp)  # disentangle MPS to |0...0> by uMPO
                mps_tmp.input_mps(mps_data, if_deepcopy=if_deepcopy
                                  )  # calculate fidelity with b|0...0>
                # Normalize MPS (actually not necessary since umpo is unitary)
                mps_tmp.orthogonalize_mps(0,
                                          mps_tmp.length - 1,
                                          normalize=True,
                                          is_trun=False)
                fid1 = mps_tmp.fidelity_log_by_spins_up()
                if fid1 < fid[n]:
                    mps_new = copy.deepcopy(mps_tmp)
                    mpo[n] = copy.deepcopy(mpo_tmp)
                    fid[n] = fid1
        else:
            mpo[n] = mps_chi2.to_unitary_mpo_qubits(
                para['theta'], if_trun=False)  # calculate unitary MPO
            mps_data = act_umpo_on_mps(
                mps.mps, mpo[n])  # disentangle MPS to |0...0> by uMPO
            mps_new = copy.deepcopy(mps)
            mps_new.input_mps(mps_data, if_deepcopy=if_deepcopy)
            fid[n] = mps_new.fidelity_log_by_spins_up()
        # print('The log-fidelity with |0...0> = ' + str(fid[n]))
        # Truncate the MPS
        mps_new.orthogonalize_mps(mps_new.length - 1,
                                  0,
                                  normalize=True,
                                  is_trun=False)
        mps_new.center = 0
        mps_new.orthogonalize_mps(0,
                                  mps_new.length - 1,
                                  normalize=True,
                                  is_trun=True,
                                  chi=para['chi_overlap'])
        mps_new.center = mps_new.length - 1
        mps_new.calculate_entanglement_entropy()
        lm_mid[n] = mps_new.lm[round(mps_new.length / 2)]
        ent[n] = mps_new.ent.reshape(-1, 1)
        # print('The entanglement entropy of the new MPS =  ')
        # print(ent[n].reshape(1, -1))
        mps = mps_new
    fid1 = np.zeros((fid.size + 1, ))
    fid1[0] = fid0
    fid1[1:] = fid
    return fid1, ent, lm_mid, mpo, mps