Beispiel #1
0
 def output(self):
     # to get output state
     if self.state is None:
         msg = 'please input somthing'
         raise TypeError(msg)
     else:
         dim = self.state.shape[0]
         if self.evol is None:
             self.evol = eyex(dim)
         if typex(self.state) == 'bra':
             msg = 'state should not a bra vector'
             raise TypeError(msg)
         elif typex(self.state) == 'ket':
             if self.post is None:
                 return (dotx(self.evol, self.state))
             else:  # with post-selected
                 if typex(self.post) != 'bra':
                     msg = 'post state must be a bra vector'
                     raise TypeError(msg)
                 else:
                     return (dotx(self.post, self.evol, self.state))
         else:  # state is an oper
             if self.post is None:
                 return (dotx(self.evol, self.state, daggx(self.evol)))
             else:  # with post-selected
                 if typex(self.post) != 'bra':
                     msg = 'post state must be a bra vector'
                     raise TypeError(msg)
                 else:
                     pp = dotx(self.evol, self.state, dagg(self.evol))
                     return (dotx(self.post, pp, dagg(self.post)))
Beispiel #2
0
def operx(x):
    """
    to convert a bra or ket vector into oper
    """
    if typex(x) == 'oper':
        return qx(x)
    elif typex(x) == 'bra':
        return qx(dotx(daggx(x), x))
    else:
        return qx(dotx(x, daggx(x)))
Beispiel #3
0
def _sic_d(d):
    """
    construct sic povm for d ≥ 5
    a set of povm elements can be calculated by
    acting the Displacement operateros on
    the fiducial vectors
    """
    pov = []
    for i in _Dd_(d):
       dat = dotx(i,_f_vectors_(d))
       pov.append(dotx(dat,daggx(dat)))
    return pov
Beispiel #4
0
def position(d, x):
    """ to generate position state
    ie., X|x> = x|x>
    Parameters
    -----------
    x: position coordinate, real number
    d: number of dimensions
    """
    ground = obasis(d, 0)
    power = -0.5 * dotx(raising(d),raising(d)) + \
            sqrt(2) * x * raising(d)
    exponential = expx(power)
    position = exp(-x**2 / 2) / (pi**(1. / 4)) * dotx(exponential, ground)
    position = normx(position)
    return qx(position)
Beispiel #5
0
def gtrace(a,b):
    """
    To get trace distance between a and b
    See:  Nielsen & Chuang, "Quantum Computation and Quantum Information"
    
    Input
    ---------
    a : density matrix or state vector
    b : the same as a

    Result
    ---------
    fidelity : float
    """
    # check if they are quantum object
    if isqx(a) and isqx(b):
       a = operx(a)
       b = operx(b)
       if a.shape != b.shape:
          raise TypeError('a and b do not have the same dimensions.')

       diff = a - b
       diff = dotx(daggx(diff),diff)
       # get eigenvalues of sparse matrix
       vals, vecs= eigh(diff)
       return float(real(0.5 * np.sum(sqrt(np.abs(vals)))))
    else:
       msg = 'a or b is not a quantum object'
       raise TypeError(msg)
Beispiel #6
0
def l2normx(x):
    """
    to calculate norm 2 of a vector or trace operater
    >>> l2norm = <psi|psi>
    >>> l2morm = √tr(Aˆ†*A)
    """
    if typex(x) != 'oper':
        x = operx(x)  #get oper x
    return np.sqrt(tracex(dotx(daggx(x), x)))
Beispiel #7
0
def _Djkd_(j,k,d):
    # a displacement opertator Djk
    # PRX 5, 041006 (2015)
  
    w = np.exp(2*np.pi*1j/float(d))
    data = 0.0
    for m in range (d):
        data += w**(j*k/2.)*w**(j*m)*\
               dotx(obasis(d,(k+m) % d),daggx(obasis(d,m)))
    return data
Beispiel #8
0
def _stoke_base():
    """
    to define four stock parameters
    there are defined to be H, V, D, R
    see: PRA.64.052312

    Return:
    -------
    stoke povm 
    """
    # default
    u = obasis(2,0)
    d = obasis(2,1)
    h = dotx(u,daggx(u))
    v = dotx(d,daggx(d))
    d = dotx(normx(u-d),daggx(normx(u-d)))
    r = dotx(normx(u-1j*d),daggx(normx(u-1j*d)))
    m = [h,v,d,r]
    return m
Beispiel #9
0
def squeezed(d, alpha, beta):
    """ to generate squeezed state
    Parameters
    ----------
    alpha: complex number
    d: number of dimensions
    """
    ground = obasis(d, 0)
    squeezed = dotx(displacement(d, alpha), squeezing(d, beta), ground)
    squeezed = normx(squeezed)
    return qx(squeezed)
Beispiel #10
0
def coherent(d, alpha):
    """ to generate coherent state
    Parameters
    ----------
    alpha: complex number
    d: number of dimensions
    """
    ground = obasis(d, 0)
    coherent = dotx(displacement(d, alpha), ground)
    coherent = normx(coherent)
    return qx(coherent)
Beispiel #11
0
def _sic_2():
    u = obasis(2,0)
    d = obasis(2,1)
    p1 = u
    p2 = 1/sqrt(3.)*u + sqrt(2/3.)*d
    p3 = 1/sqrt(3.)*u + sqrt(2/3.)*exp(1j*2*pi/3.)*d
    p4 = 1/sqrt(3.)*u + sqrt(2/3.)*exp(1j*4*pi/3.)*d
    p = [p1,p2,p3,p4]
    pp = []
    for i in p:
        pp.append(dotx(i,daggx(i)))
    return pp
Beispiel #12
0
    def _pro_time_(self):
        if self.state is None:
            msg = 'please input somthing'
            raise TypeError(msg)
        else:
            # turn state into oper
            if typex(self.state) != 'oper':
                instate = operx(self.state)
            else:
                instate = self.state

            dims = shapex(instate)[0]
            # check args
            if self.args == None:
                return tracex(dotx(instate, self.args))
            elif self.args[0] == 'Pauli':
                pov = _pauli(int(np.log2(dims)))
            elif self.args[0] == 'Stoke':
                pov = _stoke(int(np.log2(dims)))
            elif self.args[0] == 'MUB':
                pov = _mub(dims)
            elif self.args[0] == 'SIC':
                pov = _sic(dims)
            else:  #arbitary POVMs
                if len(self.args) == 1 and \
                   isinstance(self.args[0],(list,np.ndarray)):
                    # e.g. args = [m1,m2,...mn]
                    pov = self.args[0]
                else:
                    pov = self.args

            # now calculate probability
            pr = []
            start = time.time()  # starting time
            for i in range(len(pov)):
                pr.append(tracex(dotx(instate, pov[i])))
            end = time.time()  # stoping time
            dtime = (end - start)  # time need to calcualte all proba.
            return pr, dtime
Beispiel #13
0
def normx(x):
    """
    to normalize x
    use the Frobeius norm
    >>> |psi>/sqrt(<psi|psi>) # for vector states
    >>> (Aˆ†*A)/tr(Aˆ†*A) # for oper
    """
    if typex(x) != 'oper':
        return x / np.sqrt(l2normx(x))
    else:
        if x.shape[0] == x.shape[1]:
            return dotx(daggx(x), x) / l2normx(x)**2
        else:
            raise TypeError('not a square matrix')
Beispiel #14
0
def get_pqurec(state, post_state, p0, theta, niter, dim):
    """
   to get pure quantum state 
   Eqs. (16,17) in the main text
   >>>             (P+ - P- + 2P1)
       Re[psi]_n = ---------------   (16)
                   psi_til(1+delta_n) 

   >>>                PL - PR
       Im[psi]_n = ---------------   (17)
                   psi_til(1+deta_n)
   """

    #p0 = abs(sum(state))**2/dim
    niter = int(niter * p0 / 3.)
    temp_rs = np.zeros((niter, 6, dim))
    psi_til = abs(np.sum(dotx(post_state, state)))
    prob = get_prob(state, post_state, theta, dim)

    for i in range(niter):
        temp_rs[i, :, :] = get_bisection(state, prob, dim)

    ave_rs = np.zeros((6, dim))
    for i in range(6):
        for j in range(dim):
            ave_rs[i, j] = cdf(temp_rs[:, i, j])

    rtemp = np.zeros(dim)
    itemp = np.zeros(dim)
    rnorm = 0.0
    for i in range(dim):
        rtemp[i] = (ave_rs[2,i]-ave_rs[3,i]+2*ave_rs[1,i])/\
                   (psi_til*post_state[0,i])
        itemp[i] = (ave_rs[4,i]-ave_rs[5,i])/\
                   (psi_til*post_state[0,i])
        rnorm += rtemp[i]**2 + itemp[i]**2

    rtemp /= sqrt(rnorm)
    itemp /= sqrt(rnorm)

    restate = np.zeros((dim, dim), dtype=complex)
    for i in range(dim):
        for j in range(dim):
            restate[i,j] = (rtemp[i]+1j*itemp[i])*\
                        (rtemp[j]-1j*itemp[j])
    return restate
Beispiel #15
0
def _sic_3():
    b0 = obasis(3,0)
    b1 = obasis(3,1)
    b2 = obasis(3,2)
    p1 = b0
    p2 = 0.5*b0 + 1j*sqrt(3.)/2.*b1
    p3 = 0.5*b0 - 1j*sqrt(3.)/2.*b1
    p4 = 0.5*b0 + 0.5*b1 + 1/sqrt(2.)*b2
    p5 = 0.5*b0 + 0.5*b1 + exp(2j*pi/3.)/sqrt(2.)*b2
    p6 = 0.5*b0 + 0.5*b1 + exp(-2j*pi/3.)/sqrt(2.)*b2
    p7 = 0.5*b0 - 0.5*b1 + 1/sqrt(2.)*b2
    p8 = 0.5*b0 - 0.5*b1 + exp(2j*pi/3.)/sqrt(2.)*b2
    p9 = 0.5*b0 - 0.5*b1 + exp(-2j*pi/3.)/sqrt(2.)*b2
    p = [p1,p2,p3,p4,p5,p6,p7,p8,p9]
    pp = []
    for i in p:
        pp.append(dotx(i,daggx(i)))
    return pp
Beispiel #16
0
def random(d):
    """ to generate a random state
    Parameters:
    ----------
    d: dimension

    Return: random state

    """
    rpsi = np.zeros((d, 1))
    ipsi = np.zeros((d, 1))
    for i in range(d):
        rpsi[i, 0] = randunit()
        ipsi[i, 0] = randunit()
    ppsi = rpsi + 1j * ipsi
    ppsi = normx(ppsi)
    M = haar(d)
    prime = dotx((eyex(d) + M), ppsi)
    prime = normx(prime)
    return qx(prime)
Beispiel #17
0
def add_random_noise(psi, m=0.0, st=0.0):
    """ to generate 1 perturbed random state from psi
    Parameters:
    ----------
    d: dims
    m: mean
    st: standard derivative
    """
    if isqx(psi):
        dim = psi.shape[0]
        per = [randnormal(m, st, dim) + 1j * randnormal(m, st, dim)]
        if typex(psi) == 'ket':
            per = daggx(per)  #to get ket
        elif typex(psi) == 'oper':
            per = dotx(daggx(per), per)

        psi = psi + per
        psi = normx(psi)
        return qx(psi)
    else:
        msg = 'psi is not a quantum object'
        raise TypeError(msg)
Beispiel #18
0
def gfide(a,b):
    """
    To get fidelity of a and b
    See: Nielsen & Chuang, "Quantum Computation and Quantum Information"
    
    Input
    ---------
    a : density matrix or state vector
    b : the same as a

    Result
    ---------
    fidelity : float
    """

    # check if they are quantum onject
    if isqx(a) and isqx(b):
       if typex(a) != 'oper':
          sqrtma = operx(a)
          if typex(b) != 'oper':
             b = operx(b)
       
       else:
          if typex(b) != 'oper':
             #swap a and b
             return gfide(b,a)
          sqrtma = sqrtx(a)

       if sqrtma.shape != b.shape:
          raise TypeError('Density matrices do not have same dimensions.')
    
       eig_vals, eig_vecs = eigh(dotx(sqrtma,b,sqrtma)) 
       return float(real(sum(sqrt(eig_vals[eig_vals > 0]))))
    else:
        msg = ' a or b is not a quantum object'
        raise TypeError(msg)
Beispiel #19
0
def _pauli_eigens():
    """
    to get eigenstate of pauli matrices
    there are 3 bases: {0, 1}, {plus, minus}, {L, R}

    Return:
    -------
    Pauli eigenstate POVM set
    """
    u = obasis(2,0)
    d = obasis(2,1)
    h = dotx(u,daggx(u))
    v = dotx(d,daggx(d))
    p = dotx(normx(u+d),daggx(normx(u+d)))
    m = dotx(normx(u-d),daggx(normx(u-d)))
    l = dotx(normx(u+1j*d),daggx(normx(u+1j*d)))
    r = dotx(normx(u-1j*d),daggx(normx(u-1j*d)))
    m = [h,v,p,m,l,r]
    return m
Beispiel #20
0
def squeezing(d, beta):
    power = 0.5 * (conj(beta)*dotx(lowering(d),lowering(d))\
            - beta*dotx(raising(d),raising(d)))
    M = expx(power)
    return M
Beispiel #21
0
def get_prob(state, post_state, theta, dim):
    """
   to get probabilities P0,P1,....PL,PR
   >>> P_k = trace(rho_out * POVM_k) 

   Parameters
   ----------
   state (oper or ket): input state
   post_state (bra): post-selected state
   theta (real): angle
   dim(int): dimesion  
   """
    if typex(state) == 'oper':
        e_theta = 1 - np.cos(pi * theta)
        temp_prob = np.zeros((3, dim, dim), dtype=complex)
        rho = np.zeros((4, dim, dim), dtype=complex)
        prob = np.zeros((6, dim, dim), dtype=complex)
        for x in range(dim):
            for p in range(dim):
                # temp_prob_0: sum_{x,y}
                for tx in range(dim):
                    for y in range(dim):
                        temp_prob[0,x,p] += state[tx,y]*\
                                            np.exp(1j*2.0*pi*(y-tx)*p/dim)*\
                                            post_state[0,y]*post_state[0,tx]
                # temp_prob_1: sum_y
                for y in range(dim):
                    temp_prob[1,x,p] += state[x,y]*\
                                        np.exp(1j*2.0*pi*(y-x)*p/dim)*\
                                        post_state[0,x]*post_state[0,y]
                # temp_prob_2: sum_{x,x}
                temp_prob[2, x, p] = state[x, x] * post_state[0, x]**2
        # rho_00: pointer_state_00
        rho[0,:,:] = (temp_prob[0,:,:] - \
                      e_theta*2*np.real(temp_prob[1,:,:]) + \
                      e_theta**2 * temp_prob[2,:,:]) / 2.0
        # rho_10: pointer_state_10
        rho[1,:,:] = (temp_prob[1,:,:] - \
                      e_theta * temp_prob[2,:,:]) * \
                      np.sin(pi * theta) / 2.0
        # rho_01
        rho[2, :, :] = np.conj(rho[1, :, :])
        # rho_11
        rho[3, :, :] = temp_prob[2, :, :] * np.sin(pi * theta)**2 / 2.0
        #probabilities
        prob[0,:,:] = np.real((rho[0,:,:]+rho[1,:,:]\
                    +rho[2,:,:]+rho[3,:,:])/2.0) #Prob.+
        prob[1,:,:] = (rho[0,:,:]-rho[1,:,:]\
                    -rho[2,:,:]+rho[3,:,:])/2.0 #Prob.-
        prob[2,:,:] = (rho[0,:,:]-1j*rho[1,:,:]\
                    +1j*rho[2,:,:]+rho[3,:,:])/2.0 #Prob.L
        prob[3,:,:] = (rho[0,:,:]+1j*rho[1,:,:]\
                    -1j*rho[2,:,:]+rho[3,:,:])/2.0 #Prob.R
        prob[4, :, :] = rho[0, :, :]  #Prob. 0
        prob[5, :, :] = rho[3, :, :]  #Prob. 1
        return np.real(prob)
    else:  #for pure state
        prob = np.zeros((6, dim), dtype=complex)

        rpsi = np.real(state)
        ipsi = np.imag(state)

        psi_til = abs(dotx(post_state, state)[0, 0])  #scala
        psi_abs2 = abs(state)**2  #ket: calculate |\psi'_n|^2

        #calculate probabilities
        prob[0,:]= (psi_til**2 - 2.0*post_state[0,:]*psi_til*rpsi[:,0]+\
                post_state[0,:]**2*psi_abs2[:,0])/(2.0) #P(0)
        prob[1, :] = (post_state[0, :]**2 * psi_abs2[:, 0]) / (2.0)  #P(1)
        prob[2, :] = (psi_til**2) / (4.0)  #P(+)
        prob[3,:]= (psi_til**2-4.0*psi_til*post_state[0,:]*rpsi[:,0]+\
                4.0*post_state[0,:]**2*psi_abs2[:,0])/(4.0) #P(-)
        prob[4,:]= (psi_til**2 - 2.0*psi_til*post_state[0,:]*rpsi[:,0]+\
                2.0*psi_til*post_state[0,:]*ipsi[:,0]+\
                2.0*post_state[0,:]**2*psi_abs2[:,0])/(4.0) #P(L)
        prob[5,:]= (psi_til**2 - 2.0*psi_til*post_state[0,:]*rpsi[:,0]-\
                2.0*psi_til*post_state[0,:]*ipsi[:,0]+\
                2.0*post_state[0,:]**2*psi_abs2[:,0])/(4.0) #P(R)
        return np.real(prob)
Beispiel #22
0
def _sic_4():
    b0 = obasis(4,0)
    b1 = obasis(4,1)
    b2 = obasis(4,2)
    b3 = obasis(4,3)
    c5 = sqrt(5.)
    mcc5 = 1.0/c5
    ct110 = sqrt(-110.+50.*c5)
    ct290 = sqrt(-290.+130.*c5)
    c5t2c5 = sqrt(5.-2.*c5)

    p1 = b0
    p2 = mcc5*b0 + 2.0*mcc5*b1
    p3 = mcc5*b0 + 2.0/(5.+sqrt(5.))*b1 + sqrt(0.5+0.5*mcc5)*b2
    p4 = mcc5*b0 + 2.0/(5.+sqrt(5.))*b1 + \
         sqrt(2.5-5.5*mcc5)*b2 + sqrt(6.0/c5-2.)*b3

    t5c4c5 = -5.+4.*c5
    mt4c5 = 10.-4.*c5
    ct10 = sqrt(-10.+10.*c5)

    sq1 = sqrt(t5c4c5-2.*ct110)+1j*c5t2c5
    sq2 = sqrt(mt4c5-ct290)-1j*sqrt(2.*c5+ct10)
    p5 = mcc5*b0 + (1j/2.-0.5/c5)*b1 + 0.5/c5*sq1*b2 + 0.5/c5*sq2*b3

    sq3 = -sqrt(t5c4c5+2.*ct110)+1j*c5t2c5
    sq4 = sqrt(mt4c5+ct290)+1j*sqrt(2.*c5-ct10)
    p6 = mcc5*b0 + (1j/2.-0.5/c5)*b1 + 0.5/c5*sq3*b2 + 0.5/c5*sq4*b3
    p7 = conjx(p6)
    p8 = conjx(p5)

    mc2c10 = 1./(2.*sqrt(10.))
    btc5 = 3.-c5
    c5tc5 = sqrt(5.-c5)
    nc3c5 = 5.+3.*c5
    nb1 = btc5 + 1j*ct10
    nb2 = -c5tc5 -1j*sqrt(nc3c5+4.*ct110)
    nb3 = sqrt(2.*c5-ct10)-1j*sqrt(mt4c5+ct290)
    p9 = mcc5*b0 + 1./(4.*c5)*nb1*b1 + mc2c10*nb2*b2 + 0.5/c5*nb3*b3
    nb2 = -c5tc5 +1j*sqrt(nc3c5-4.*ct110)
    nb3 = -sqrt(2.*c5+ct10)+1j*sqrt(mt4c5-ct290)
    p10 = mcc5*b0 + 1./(4.*c5)*nb1*b1 + mc2c10*nb2*b2 + 0.5/c5*nb3*b3

    p11 = conjx(p9)
    p12 = conjx(p10)

    t5c3c5 = -5.+3.*c5
    ncc5 = 5.+c5
    ct58 = sqrt(-58.+26.*c5)

    nb1 = -2.-ct10+1j*(c5tc5)**2
    nb2 = sqrt(t5c3c5+2.*ct290)+1j*sqrt(ncc5-4.*ct290)
    nb3 = -sqrt(mt4c5-ct290)+1j*sqrt(2.*c5-5.*ct58)
    p13 = mcc5*b0 + 1./(4.*c5)*nb1*b1 + mc2c10*nb2*b2 + 0.5/c5*nb3*b3

    nb1 = -2.+ct10+1j*c5tc5**2
    nb2 = sqrt(t5c3c5-2.*ct290)-1j*sqrt(ncc5+4.*ct290)###
    nb3 = -sqrt(mt4c5+ct290)+1j*sqrt(2.*c5+5.*ct58)
    p14 = mcc5*b0 + 1./(4.*c5)*nb1*b1 + mc2c10*nb2*b2 + 0.5/c5*nb3*b3

    p15 = conjx(p14)
    p16 = conjx(p13)

    p = [p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,\
         p12,p13,p14,p15,p16]
    pp = []
    for i in p:
        pp.append(dotx(i,daggx(i)))
    return pp