def match_toric_2D(lattice_size, anyon_positions):
    """ Uses perfect matching to return a matching to fix the 2D TORIC code from the given positions of '-1' stabilizer outcomes in the code. 

    Assumptions:
    -----------
    Perfect measurement, meaning there must be an even number of anyons. 

    Parameters:
    ----------
    lattice_size -- size of the code.
    anyon_positions -- List of all '-1' stabilizer outcomes in the code. E.g. [[x0,y0],[x1,y1],..]. 

    Returns:
    -------
    The perfect matching, a list of paired anyon positions.

    """

    nodes_list = anyon_positions
    n_nodes = len(nodes_list)

    if n_nodes == 0:
        return []

    m = 2 * lattice_size

    graphArray = []

    ##fully connect the nodes within the 2D layer
    ## node numbering starts at 0

    for i in range(n_nodes - 1):
        (p0, p1) = nodes_list[i]

        for j in range(n_nodes - i - 1):
            (q0, q1) = nodes_list[j + i + 1]

            w0 = (p0 - q0) % m
            w1 = (p1 - q1) % m
            weight = min([w0, m - w0]) + min([w1, m - w1])

            graphArray += [[i, j + i + 1, weight]]

    n_edges = len(graphArray)

    ## PERFORM MATCHING
    ## Use the blossom5 perfect matching algorithm to return a matching

    matching = pm.getMatching(n_nodes, graphArray)

    ## REFORMAT MATCHING
    matching_pairs = [[i, matching[i]] for i in range(n_nodes)
                      if matching[i] > i]
    points = [] if len(matching_pairs) == 0 else [[nodes_list[i] for i in x]
                                                  for x in matching_pairs]

    return points
def match_toric_2D(lattice_size,anyon_positions):

    """ Uses perfect matching to return a matching to fix the 2D TORIC code from the given positions of '-1' stabilizer outcomes in the code. 

    Assumptions:
    -----------
    Perfect measurement, meaning there must be an even number of anyons. 

    Parameters:
    ----------
    lattice_size -- size of the code.
    anyon_positions -- List of all '-1' stabilizer outcomes in the code. E.g. [[x0,y0],[x1,y1],..]. 

    Returns:
    -------
    The perfect matching, a list of paired anyon positions.

    """
    
    nodes_list=anyon_positions
    n_nodes=len(nodes_list)

    if n_nodes==0:
        return []
    
    m=2*lattice_size   
 
    graphArray=[]

    ##fully connect the nodes within the 2D layer
    ## node numbering starts at 0 

    for i in range(n_nodes-1):
        (p0,p1)=nodes_list[i]
        
        for j in range(n_nodes-i-1):
            (q0,q1)=nodes_list[j+i+1]

            w0=(p0-q0)%m
            w1=(p1-q1)%m
            weight=min([w0,m-w0])+min([w1,m-w1])
                                    
            graphArray+=[[i,j+i+1,weight]]

    n_edges=len(graphArray)

    ## PERFORM MATCHING
    ## Use the blossom5 perfect matching algorithm to return a matching

    matching=pm.getMatching(n_nodes,graphArray)

    
    ## REFORMAT MATCHING
    matching_pairs=[[i,matching[i]] for i in range(n_nodes) if matching[i]>i]
    points=[] if len(matching_pairs)==0 else [[nodes_list[i] for i in x] for x in matching_pairs]
  
    return points
Ejemplo n.º 3
0
def get_matching_blossom5(graph):
    """
    Uses the BlossomV algorithm to get the matchings. A list of combinations of all the anyons and their respective weights are feeded to the blossom5 algorithm. To apply the matchings, we walk from each matching vertex to where their paths meet perpendicualarly, flipping the edges on the way over.
    """

    edges = []  # Get all possible edges between the anyons and their weights

    def edge_func(edges, e0, e1, weight):
        edges.append([e0, e1, weight])

    all_anyons, nxgraph = get_graph_edges(graph, edge_func, edges)

    output = pm.getMatching(len(all_anyons), edges) if all_anyons != [] else []
    return [[all_anyons[i0], all_anyons[i1]] for i0, i1 in enumerate(output) if i0 > i1]
def match_toric_2D(lattice_size, anyon_positions):

    nodes_list = anyon_positions
    n_nodes = len(nodes_list)

    if n_nodes == 0:
        return []

    m = 2 * lattice_size

    graphArray = []

    ##fully connect the nodes within the 2D layer
    ## node numbering starts at 0

    for i in range(n_nodes - 1):
        (p0, p1) = nodes_list[i]

        for j in range(n_nodes - i - 1):
            (q0, q1) = nodes_list[j + i + 1]

            w0 = (p0 - q0) % m
            w1 = (p1 - q1) % m
            weight = min([w0, m - w0]) + min([w1, m - w1])

            graphArray += [[i, j + i + 1, weight]]

    n_edges = len(graphArray)

    ################ MATCHING ###################

    matching = pm.getMatching(n_nodes, graphArray)

    #############################################

    matching_pairs = [[i, matching[i]] for i in range(n_nodes)
                      if matching[i] > i]
    points = [] if len(matching_pairs) == 0 else [[nodes_list[i] for i in x]
                                                  for x in matching_pairs]

    return points
def match_toric_2D(lattice_size,anyon_positions):

    
    nodes_list=anyon_positions
    n_nodes=len(nodes_list)

    if n_nodes==0:
        return []
    
    m=2*lattice_size   
 
    graphArray=[]

    ##fully connect the nodes within the 2D layer
    ## node numbering starts at 0 

    for i in range(n_nodes-1):
        (p0,p1)=nodes_list[i]
        
        for j in range(n_nodes-i-1):
            (q0,q1)=nodes_list[j+i+1]

            w0=(p0-q0)%m
            w1=(p1-q1)%m
            weight=min([w0,m-w0])+min([w1,m-w1])
                                    
            graphArray+=[[i,j+i+1,weight]]

    n_edges=len(graphArray)

################ MATCHING ###################

    matching=pm.getMatching(n_nodes,graphArray)

#############################################

    matching_pairs=[[i,matching[i]] for i in range(n_nodes) if matching[i]>i]
    points=[] if len(matching_pairs)==0 else [[nodes_list[i] for i in x] for x in matching_pairs]
  
    return points
def match_planar_2D(lattice_size,stabilizer_type,anyon_positions):


    if anyon_positions==[]:
        matching=[]
        return matching
    
    N_nodes=len(anyon_positions)
    #N_edges=N_nodes*(N_nodes-1)/2


#    graphStr=str(N_nodes*2)+' '+str(N_edges*2+N_nodes)+'\n'

    if N_nodes==0:
        return []

    node_index = []
    count = 0

    graphArray = []


    for i in range(N_nodes-1):
        (p0,p1)=anyon_positions[i]
        
        for j in range(N_nodes-i-1):
            indexj = j+i+1
            (q0,q1)= anyon_positions[j+i+1]
            weight=abs(p0-q0)+abs(p1-q1)
            graphArray+=[[i,indexj,weight]]
            #newline=str(i)+' '+str(i+j+1)+' '+str(weight)+'\n'
            #graphStr+=newline

    # for every node, create a boundary node and joining edge
    boundary_node_positions=[]
    
    for i in range(N_nodes):

        (p0,p1)=anyon_positions[i]
        
        if stabilizer_type=="star":
            (b0,b1)=(p0,-1 if p1<lattice_size else 2*lattice_size+1)
        elif stabilizer_type=="plaquette":
            (b0,b1)=(-1 if p0<lattice_size else 2*lattice_size+1,p1)
        else:
            print "stabilizer_type must be either **star** or **plaquette**"
            return 0
        
        boundary_node_positions+=[[b0,b1]]

        #add edge to graph
        weight=abs(p0-b0)+abs(p1-b1)
        graphArray+=[[i,i+N_nodes,weight]]
        #newline=str(i)+' '+str(i+N_nodes)+' '+str(weight)+'\n'
        #graphStr+=newline

    
    # fully connect boundary nodes with weight 0
    N_boundary_nodes=len(boundary_node_positions)

    for i in range(N_boundary_nodes-1):
        for j in range(N_boundary_nodes-i-1):
            graphArray+=[[i+N_nodes,i+N_nodes+j+1,0]]
            
            #newline=str(i+N_nodes)+' '+str(i+N_nodes+j+1)+' '+str(0)+'\n'
            #graphStr+=newline
    



################ MATCHING ###################
        
    matching=pm.getMatching(2*N_nodes,graphArray)

#############################################

    matching_pairs=[[i,matching[i]] for i in range(2*N_nodes) if matching[i]>i]
  
    all_positions=anyon_positions+boundary_node_positions    

    points=[] if len(matching_pairs) == 0 else [[all_positions[i] for i in x] for x in matching_pairs]

    return points
def match_toric_3D(lattice_size,anyon_positions,weights):

    #tp0 = time.time()

    nodes_list=[item for sublist in anyon_positions for item in sublist]
    n_nodes=len(nodes_list)

    
    if n_nodes==0:
        return []
    
    m=2*lattice_size
    wT,wS=weights
 
    graphArray=[]

    ##fully connect the nodes within the 2D layer
    ## node numbering starts at 0 



    
    time_lookup={}
    for t in range(10):
        time_lookup[t]=t*wT

     
    weight_lookup = {}
    for i in range(m): 
        weight_lookup[i]={}
        for j in range(m):
            diff = abs(i-j)
            weight_lookup[i][j] = min([diff,m-diff])*wS
    
    n_nodes_minus_1 = n_nodes-1

    for i in range(n_nodes_minus_1):
        (pt,p0,p1)=nodes_list[i]
      
        i_plus_1 = i+1
        
        
        for j in range(n_nodes_minus_1 - i):
            indexj = j+i_plus_1
            (qt,q0,q1)=nodes_list[indexj]

 
            wt=(qt-pt)
            if wt>=8: break
            # the list of nodes is ordered by time so break as soon as difference between pt and qt is >=10


     #           w0=(q0-p0)%m
      #          w1=(q1-p1)%m
       #         weight=(min([w0,m-w0])+min([w1,m-w1]))*wS+wt*wT
                
            weight = weight_lookup[q0][p0]+weight_lookup[q1][p1]+time_lookup[wt]
            graphArray+=[[i,indexj,weight]]

    n_edges=len(graphArray)

 #   tp1 = time.time()
  #  print 'generate matching graph ',tp1-tp0
################ MATCHING ###################

    matching=pm.getMatching(n_nodes,graphArray)

    #############################################

    matching_pairs=[[i,matching[i]] for i in range(n_nodes) if matching[i]>i]
    points=[] if len(matching_pairs)==0 else [[nodes_list[i] for i in x] for x in matching_pairs]
   # tp2 = time.time()
    #print 'perfect matching ', tp2 - tp1

    return points
def match_planar_2D(lattice_size,stabilizer_type,anyon_positions):


    if anyon_positions==[]:
        matching=[]
        return matching
    
    N_nodes=len(anyon_positions)
    #N_edges=N_nodes*(N_nodes-1)/2


#    graphStr=str(N_nodes*2)+' '+str(N_edges*2+N_nodes)+'\n'

    if N_nodes==0:
        return []

    node_index = []
    count = 0

    graphArray = []


    for i in range(N_nodes-1):
        (p0,p1)=anyon_positions[i]
        
        for j in range(N_nodes-i-1):
            indexj = j+i+1
            (q0,q1)= anyon_positions[j+i+1]
            weight=abs(p0-q0)+abs(p1-q1)
            graphArray+=[[i,indexj,weight]]
            #newline=str(i)+' '+str(i+j+1)+' '+str(weight)+'\n'
            #graphStr+=newline

    # for every node, create a boundary node and joining edge
    boundary_node_positions=[]
    
    for i in range(N_nodes):

        (p0,p1)=anyon_positions[i]
        
        if stabilizer_type=="star":
            (b0,b1)=(p0,-1 if p1<lattice_size else 2*lattice_size+1)
        elif stabilizer_type=="plaquette":
            (b0,b1)=(-1 if p0<lattice_size else 2*lattice_size+1,p1)
        else:
            print "stabilizer_type must be either **star** or **plaquette**"
            return 0
        
        boundary_node_positions+=[[b0,b1]]

        #add edge to graph
        weight=abs(p0-b0)+abs(p1-b1)
        graphArray+=[[i,i+N_nodes,weight]]
        #newline=str(i)+' '+str(i+N_nodes)+' '+str(weight)+'\n'
        #graphStr+=newline

    
    # fully connect boundary nodes with weight 0
    N_boundary_nodes=len(boundary_node_positions)

    for i in range(N_boundary_nodes-1):
        for j in range(N_boundary_nodes-i-1):
            graphArray+=[[i+N_nodes,i+N_nodes+j+1,0]]
            
            #newline=str(i+N_nodes)+' '+str(i+N_nodes+j+1)+' '+str(0)+'\n'
            #graphStr+=newline
    



################ MATCHING ###################
        
    matching=pm.getMatching(2*N_nodes,graphArray)

#############################################

    matching_pairs=[[i,matching[i]] for i in range(2*N_nodes) if matching[i]>i]
  
    all_positions=anyon_positions+boundary_node_positions    

    points=[] if len(matching_pairs) == 0 else [[all_positions[i] for i in x] for x in matching_pairs]

    return points
def match_toric_3D(lattice_size,anyon_positions,weights):

    #tp0 = time.time()

    nodes_list=[item for sublist in anyon_positions for item in sublist]
    n_nodes=len(nodes_list)

    
    if n_nodes==0:
        return []
    
    m=2*lattice_size
    wT,wS=weights
 
    graphArray=[]

    ##fully connect the nodes within the 2D layer
    ## node numbering starts at 0 



    
    time_lookup={}
    for t in range(10):
        time_lookup[t]=t*wT

     
    weight_lookup = {}
    for i in range(m): 
        weight_lookup[i]={}
        for j in range(m):
            diff = abs(i-j)
            weight_lookup[i][j] = min([diff,m-diff])*wS
    
    n_nodes_minus_1 = n_nodes-1

    for i in range(n_nodes_minus_1):
        (pt,p0,p1)=nodes_list[i]
      
        i_plus_1 = i+1
        
        
        for j in range(n_nodes_minus_1 - i):
            indexj = j+i_plus_1
            (qt,q0,q1)=nodes_list[indexj]

 
            wt=(qt-pt)
            if wt>=8: break
            # the list of nodes is ordered by time so break as soon as difference between pt and qt is >=10


     #           w0=(q0-p0)%m
      #          w1=(q1-p1)%m
       #         weight=(min([w0,m-w0])+min([w1,m-w1]))*wS+wt*wT
                
            weight = weight_lookup[q0][p0]+weight_lookup[q1][p1]+time_lookup[wt]
            graphArray+=[[i,indexj,weight]]

    n_edges=len(graphArray)

 #   tp1 = time.time()
  #  print 'generate matching graph ',tp1-tp0
################ MATCHING ###################

    matching=pm.getMatching(n_nodes,graphArray)

    #############################################

    matching_pairs=[[i,matching[i]] for i in range(n_nodes) if matching[i]>i]
    points=[] if len(matching_pairs)==0 else [[nodes_list[i] for i in x] for x in matching_pairs]
   # tp2 = time.time()
    #print 'perfect matching ', tp2 - tp1

    return points
def match_toric_3D(lattice_size, anyon_positions, weights=[1, 1]):
    """ Uses perfect matching to return a matching to fix the 3D TORIC code from the given positions of '-1' stabilizer outcomes in the code. 

    Parameters:
    ----------
    lattice_size -- size of the code.
    anyon_positions -- List of all '-1' stabilizer outcomes in the code, a space + time coordinate. E.g. [[x0,y0,t0],[x1,y1,t1],..]. 
    weights -- A 2-component list, [space_weight,time_weight] containting multiplicative weightings for space and time dimensions. Default: [1,1]

    Returns:
    -------
    The perfect matching, a list of paired anyon positions.

    """

    # time direction cutoff
    cutoff = 15

    #tp0 = time.time()

    nodes_list = [item for sublist in anyon_positions for item in sublist]
    n_nodes = len(nodes_list)

    if n_nodes == 0:
        return []

    m = 2 * lattice_size
    wT, wS = weights

    graphArray = []

    ##fully connect the nodes within the 2D layer
    ## node numbering starts at 0

    time_lookup = {}
    for t in range(cutoff + 1):
        time_lookup[t] = t * wT

    weight_lookup = {}
    for i in range(m):
        weight_lookup[i] = {}
        for j in range(m):
            diff = abs(i - j)
            weight_lookup[i][j] = min([diff, m - diff]) * wS

    n_nodes_minus_1 = n_nodes - 1

    for i in range(n_nodes_minus_1):
        (pt, p0, p1) = nodes_list[i]

        i_plus_1 = i + 1

        for j in range(n_nodes_minus_1 - i):
            indexj = j + i_plus_1
            (qt, q0, q1) = nodes_list[indexj]

            wt = (qt - pt)
            if wt >= cutoff: break
            # the list of nodes is ordered by time so break as soon as difference between pt and qt is >=10

            weight = weight_lookup[q0][p0] + weight_lookup[q1][
                p1] + time_lookup[wt]
            graphArray += [[i, indexj, weight]]

    n_edges = len(graphArray)

    ## PERFORM MINIMUM WEIGHT MATCHING
    ## Use Blossom5 algorithm to generating a matching

    matching = pm.getMatching(n_nodes, graphArray)

    ## REFORMAT MATCHING

    matching_pairs = [[i, matching[i]] for i in range(n_nodes)
                      if matching[i] > i]
    points = [] if len(matching_pairs) == 0 else [[nodes_list[i] for i in x]
                                                  for x in matching_pairs]

    return points
def match_toric_3D(lattice_size,anyon_positions,weights=[1,1]):

    
    """ Uses perfect matching to return a matching to fix the 3D TORIC code from the given positions of '-1' stabilizer outcomes in the code. 

    Parameters:
    ----------
    lattice_size -- size of the code.
    anyon_positions -- List of all '-1' stabilizer outcomes in the code, a space + time coordinate. E.g. [[x0,y0,t0],[x1,y1,t1],..]. 
    weights -- A 2-component list, [space_weight,time_weight] containting multiplicative weightings for space and time dimensions. Default: [1,1]

    Returns:
    -------
    The perfect matching, a list of paired anyon positions.

    """

    # time direction cutoff
    cutoff = 15

    #tp0 = time.time()

    nodes_list=[item for sublist in anyon_positions for item in sublist]
    n_nodes=len(nodes_list)

    
    if n_nodes==0:
        return []
    
    m=2*lattice_size
    wT,wS=weights
 
    graphArray=[]

    ##fully connect the nodes within the 2D layer
    ## node numbering starts at 0 



    
    time_lookup={}
    for t in range(cutoff+1):
        time_lookup[t]=t*wT

     
    weight_lookup = {}
    for i in range(m): 
        weight_lookup[i]={}
        for j in range(m):
            diff = abs(i-j)
            weight_lookup[i][j] = min([diff,m-diff])*wS
    
    n_nodes_minus_1 = n_nodes-1

    for i in range(n_nodes_minus_1):
        (pt,p0,p1)=nodes_list[i]
      
        i_plus_1 = i+1
        
        
        for j in range(n_nodes_minus_1 - i):
            indexj = j+i_plus_1
            (qt,q0,q1)=nodes_list[indexj]

 
            wt=(qt-pt)
            if wt>=cutoff: break
            # the list of nodes is ordered by time so break as soon as difference between pt and qt is >=10

            weight = weight_lookup[q0][p0]+weight_lookup[q1][p1]+time_lookup[wt]
            graphArray+=[[i,indexj,weight]]

    n_edges=len(graphArray)


    ## PERFORM MINIMUM WEIGHT MATCHING
    ## Use Blossom5 algorithm to generating a matching

    matching=pm.getMatching(n_nodes,graphArray)

    ## REFORMAT MATCHING 

    matching_pairs=[[i,matching[i]] for i in range(n_nodes) if matching[i]>i]
    points=[] if len(matching_pairs)==0 else [[nodes_list[i] for i in x] for x in matching_pairs]

    return points