Пример #1
0
    def parity(self, state):
        '''
        +1 if even, -1 if odd 
        '''
        if isinstance(state, int):
            state = qu.basis_vec(i=state, dim=np.prod(self._dims))

        occ = self.state_occs(state)
        assert np.logical_or(occ == 0.0, occ == 1.0).all()
        par = np.sum(occ) % 2
        return {0.0: 1, 1.0: -1}[par]
Пример #2
0
 def test_basis_vec_sparse(self):
     x = basis_vec(4, 100, sparse=True)
     assert x[4, 0] == 1.
     assert x.nnz == 1
     assert x.dtype == complex
Пример #3
0
 def test_basis_vec(self):
     x = basis_vec(1, 2)
     assert_allclose(x, np.matrix([[0.], [1.]]))
     x = basis_vec(1, 2, qtype='b')
     assert_allclose(x, np.matrix([[0., 1.]]))
Пример #4
0
def one_qubit_U_matrices(qlattice, empt_face_coo):
    '''
    TODO: check parity more intelligently

    U matrix for lifting states from 'Fock' space
    to 'Stab' subspace of Simulator space.

    empt_face_coo: tuple (x,y) 
        location of empty face corresponding to the loop
        stabilizer operator.
    '''
    assert qlattice._faces[empt_face_coo] is None

    X, Y, Z = (qu.pauli(mu) for mu in ['x','y','z'])
    opmap = {'X':X, 'Y':Y, 'Z':Z}
    
    #number of fermionic/qubit DOF
    Nfermi = qlattice._Nfermi 
    Nqubit = qlattice._Nsites
    
    #dimensions of simulator space [2,2,...]
    sim_space_dims = qlattice._sim_dims
    code_space_dims = qlattice._encoded_dims
    
    #sites and action-string of stabilizer operator
    stab_data = qlattice.loop_stabilizer_data(*empt_face_coo)

    arrays = [opmap[Q] for Q in stab_data['opstring']]

    #(this is only for one-face-qubit stabilizers)
    assert len(arrays) == 4+1

    inds = stab_data['inds']

    # stabilizer = qu.ikron(  ops=arrays, 
    #                         dims=sim_space_dims,
    #                         inds=inds)

    #action on just the face qubit, either X or Y
    face_op = arrays[4]
    elx, evx = qu.eigh(face_op)
    #diagonalized the face qubit        
    eigenfaces = {-1 : evx[:,0],
                  +1 : evx[:,1]}

    #II..ZZZZ..III parity-check the vertices of face-loop
    corner_parity_op = qu.ikron(ops=arrays[:4],
                                dims=code_space_dims,
                                inds=inds[:4])

    #get all the stabilizer eigenvectors
    Uplus = np.zeros((2**Nqubit, 2**Nfermi))
    Uplus_dagger = np.zeros((2**Nfermi, 2**Nqubit))

    for i in range(2**Nfermi):

        vertex_state_i = qu.basis_vec(i=i, dim=2**Nfermi)
        
        sign = qu.expec(corner_parity_op,
                        vertex_state_i)

        face_state_i = eigenfaces[int(sign)].reshape(-1,1)
        
        full_state_i = vertex_state_i & face_state_i

        Uplus[:,i] = full_state_i.flatten()
        Uplus_dagger[i,:] = full_state_i.H.flatten()

    # if not tensorize:
    return qu.qu(Uplus), qu.qu(Uplus_dagger)
Пример #5
0
def three_qubit_U_matrix(qlattice, qstabs=None):
    '''
    TODO: 
    *define SX_vert (vertices acted on by Z-stabilizer)
    '''
    sectors = {1.0: 0,  -1.0: 1}
    X, Y, Z, I = (qu.pauli(mu) for mu in ['x','y','z','i'])
    opmap = {'X': X, 'Y':Y, 'Z':Z, 'I':I}

    face_dims = [2]*3 #dimensions of face-qubit subspace


    if qstabs==None:

        qstab_A = loopStabOperator( vert_inds=[1,2,5,4],
                                    face_op_str='XYI',
                                    face_inds=[12,13,14])  

        qstab_B = loopStabOperator( vert_inds=[3,4,7,6],
                                    face_op_str='YXY',
                                    face_inds=[12,13,14])  
        
        qstab_C = loopStabOperator( vert_inds=[7,8,11,10],
                                    face_op_str='IYX',
                                    face_inds=[12,13,14])                                                                 
    

    SA = qu.kron(*[opmap[Q] for Q in qstab_A.face_op_str])
    SB = qu.kron(*[opmap[Q] for Q in qstab_B.face_op_str])
    SC = qu.kron(*[opmap[Q] for Q in qstab_C.face_op_str])
    # SA, SB, SC = X&Y&I, Y&X&Y, I&Y&X 

    eigfaces = np.ndarray(shape=face_dims, dtype=object)


    for signA, indA in sectors.items():

        eva, Ua = qu.eigh(SA)
        Ua_sector = Ua[:,eva==signA] #8x4

        Qb = Ua_sector.H @ SB @ Ua_sector
        # Qc = Ua_sector.H @ SC @ Ua_sector
        
        evb, Ub = qu.eigh(Qb)

        for signB, indB in sectors.items():

            Ub_sector = Ub[:, np.isclose(evb,signB)] #4x2

            #SC on b-eigenspace
            Qc = Ub_sector.H @ Ua_sector.H @ SC @ Ua_sector @ Ub_sector #2x2
            
            evc, Uc = qu.eigh(Qc)

            for signC, indC in sectors.items():
                
                #should be in a 1-dimensional subspace now
                vec = Uc[:,np.isclose(evc,signC)]

                #vector in 8-dim face qubit space
                face_vec = Ua_sector @ Ub_sector @ vec

                assert np.allclose(SA@face_vec, signA*face_vec)
                assert np.allclose(SB@face_vec, signB*face_vec)
                assert np.allclose(SC@face_vec, signC*face_vec)
                
                eigfaces[indA,indB,indC] = face_vec


    Nfermi, Nqubit = qlattice._Nfermi, qlattice._Nsites
    code_dims = [2]*Nfermi #vertices 
    qub_dims = [2]*Nqubit #vertices&faces


    #######
    qindices_A = qstab_A.vert_inds
    qindices_B = qstab_B.vert_inds
    qindices_C = qstab_C.vert_inds
    #######

    #parts of stabilizers acting only on vertex qubits
    SA_vert = qu.ikron(ops=[Z,Z,Z,Z], inds=qindices_A,
                    dims=code_dims)

    SB_vert = qu.ikron(ops=[Z,Z,Z,Z], inds=qindices_B,
                        dims=code_dims)
    
    SC_vert = qu.ikron(ops=[Z,Z,Z,Z], inds=qindices_C,
                        dims=code_dims)
                    
    Uplus = np.ndarray(shape=(2**Nqubit, 2**Nfermi))

    print('here')
    for k in range(2**Nfermi):
        print(k%10)
        #state of vertex qubits, all local z-eigenstates
        vertex_state = qu.basis_vec(i=k, dim=2**Nfermi)

        secA = sectors[qu.expec(SA_vert, vertex_state)]
        secB = sectors[qu.expec(SB_vert, vertex_state)]
        secC = sectors[qu.expec(SC_vert, vertex_state)]

        face_state = eigfaces[secA, secB, secC] 

        full_state = vertex_state & face_state

        #"stable" eigenstate written in qubit basis
        Uplus[:,k] = full_state.flatten()

        #full_state should be +1 eigenstate of all stabilizers
        assert np.allclose((SA_vert&SA) @ full_state, full_state)
        assert np.allclose((SB_vert&SB) @ full_state, full_state)
        assert np.allclose((SC_vert&SC) @ full_state, full_state)

    return qu.qu(Uplus)
Пример #6
0
def two_qubit_U_matrix(qlattice):
    '''
    TODO: generalize :/

    Find the joint +1 stabilizer eigenbasis.

    Return
    -------
     Uplus: qarray, shape = (2**Nqubit, 2**Nfermi)
        Rectangular matrix, contains stabilizer eigenstates
        written in the computational basis of the full 
        'simulator' qubit space
    
    Params
    ------
    qlattice: spinlessQubitLattice object
    '''
    
    X, Y, Z, I = (qu.pauli(mu) for mu in ['x','y','z','i'])
    sector = {1.0: 0,  -1.0: 1}

    #ndarray of joint stabilizer eigenstates 
    #(in 2-face-qubit subspace)
    eigenfaces = two_qubit_eigsectors()
    
    #########################
    qindices_A = [1,4,5,2]
    qindices_B = [3,6,7,4]
    SA, SB = X&Y, Y&X
    #########################

    Nfermi, Nqubit = qlattice._Nfermi, qlattice._Nsites
    code_dims = [2]*Nfermi
    qub_dims = [2]*Nqubit


    #parts of stabilizers acting on VERTEX qubits
    SA_vert = qu.ikron(ops=[Z,Z,Z,Z], inds=qindices_A,
                    dims=code_dims)
    SB_vert = qu.ikron(ops=[Z,Z,Z,Z], inds=qindices_B,
                        dims=code_dims)

    Uplus = np.ndarray(shape=(2**Nqubit, 2**Nfermi))


    for k in range(2**Nfermi):
        vertex_state = qu.basis_vec(i=k, dim=2**Nfermi)

        sgnA = qu.expec(SA_vert, vertex_state)
        sgnB = qu.expec(SB_vert, vertex_state)

        assert np.isclose(np.abs(sgnA), 1)
        assert np.isclose(np.abs(sgnB), 1)

        # face_state = eigfaces[sector[sgnA], sector[sgnB]]
        face_state = eigenfaces[sector[sgnA], sector[sgnB]]

        full_state = vertex_state & face_state
        Uplus[:,k] = full_state.flatten()

        #can i use kron like this?
        assert np.allclose((SA_vert&SA)@full_state, full_state)
        assert np.allclose((SB_vert&SB)@full_state, full_state)
    

    return qu.qu(Uplus)