def match_planar_3D(lattice_size,stabilizer_type,anyon_positions,time_space_weights,boundary_weight = 1.11 ,special_weights=[1,1,1],print_graph=False): ## specify matching parameters max_time_separation = 15 [wS,wT]=time_space_weights wB = wS if boundary_weight == 1.11 else boundary_weight [w1,w2,w3]=special_weights total_time=len(anyon_positions) nodes_list=[item for sublist in anyon_positions for item in sublist] n_nodes=len(nodes_list) if n_nodes==0: return [] node_index=[] count=0 for x in anyon_positions: node_index+=[[count+i for i in range(len(x))]] count+=len(x) b_node_index=[[index+n_nodes for index in t] for t in node_index] all_boundary_nodes=[] all_boundary_nodes2=[] ## LOOKUP TABLES m = 2*lattice_size +1 weight_lookup={} for p in range(-1,m+1): weight_lookup[p]={} for q in range(-1,m+1): weight_lookup[p][q]=abs(p-q) nodes1 = [] nodes2 = [] weights = [] ## PART 1: Complete 2 copies of the graph between all real nodes for i in range(n_nodes -1): (pt,p0,p1)=nodes_list[i] for j in range(i+1,n_nodes): (qt,q0,q1)=nodes_list[j] wt=(qt-pt) if wt>=max_time_separation: break wx = weight_lookup[q0][p0] wy = weight_lookup[q1][p1] weight = (wS*(wx+wy)+wt*wT) if (wt,wx,wy) in [(1,2,0),(1,0,2)]: weight *= w1 elif (wt,wx,wy) == (1,0,0): weight *= w2 elif (wt,wx,wy) in [(0,2,0),(0,0,2)]: weight *=w3 #weight = weight_lookup[q0][p0]+weight_lookup[q1][p1]+wt*wT nodes1 +=[i,i+n_nodes] nodes2 +=[j,j+n_nodes] weights+=[weight,weight] ## PART 2: Link each node to its equivalent in the second graph boundary_nodes_list=[] for i in range(n_nodes): (pt,p0,p1)=nodes_list[i] if stabilizer_type =="star": (bt,b0,b1)=(pt,p0,-1 if p1<lattice_size else m) elif stabilizer_type=="plaquette": (bt,b0,b1)=(pt,-1 if p0<lattice_size else m,p1) else: print "stabilizer_type must be either *star* or *plaquette*" sys.exit(0) boundary_nodes_list+=[(bt,b0,b1)] weight = weight_lookup[p0][b0]+weight_lookup[p1][b1] nodes1+=[i] nodes2+=[i+n_nodes] weights+=[int(weight*wB/wS)] if print_graph==True: print zip(nodes1,nodes2,weights) # print 't0 = ', t0 # print 't1 = ', time.time()-tt1 # print 't2 = ', t22 # print 't3 = ', t3 n_edges=len(nodes1) ################ MATCHING ################### #tt4 = time.time() # matching=pm.getMatching(2*n_nodes,graphArray) matching = pm.getMatching_fast(2*n_nodes,nodes1,nodes2,weights) # print 'matching ', time.time()-tt4 ############################################# if print_graph==True: print "Matching" print matching matching_pairs=[[i,matching[i]] for i in range(2*n_nodes) if matching[i]>i] all_positions=nodes_list+boundary_nodes_list points=[] if len(matching_pairs)==0 else [[all_positions[i] for i in x] for x in matching_pairs] return points
def match_planar_3D(lattice_size, stabilizer_type, anyon_positions, time_space_weights=[1, 1], boundary_weight=-1, print_graph=False): """ Finds a matching to fix the errors in a 3D planar code given the positions of '-1' stabilizer outcomes Parameters: ----------- lattice_size -- The dimension of the code stabilizer_type -- defines the stabilizer basis, can take the value "star" or "plaquette" anyon_positions -- A list of the locations of all '-1' value stabilizers in the 3D parity lattice. [[x0,y0,t0],[x1,y1,t1],...] time_space_weights -- The multiplicative weighting that should be assigned to graph edges in the [space,time] dimensions. Default: [1,1] boundary_weight -- multiplicative weight to be assigned to edges matching to the boundary. if no boundary_weight specified, set boundary_weight = space_weight print_graph -- Set to True to print the constructed graph. Default: False. Returns: -------- A list containing all the input anyon positions grouped into pairs. [[[x0,y0,t0],[x1,y1,t1]],[[x2,y2,t2],... """ max_time_separation = 15 # This determines the maximum time separation of edges that are added to the graph [wS, wT] = time_space_weights wB = wS if boundary_weight == -1 else boundary_weight #if boundary weight not specifiedm, let wB=wS total_time = len(anyon_positions) nodes_list = [item for sublist in anyon_positions for item in sublist] n_nodes = len(nodes_list) # exclude edge case where no anyons exist. if n_nodes == 0: return [] node_index = [] count = 0 for x in anyon_positions: node_index += [[count + i for i in range(len(x))]] count += len(x) b_node_index = [[index + n_nodes for index in t] for t in node_index] all_boundary_nodes = [] all_boundary_nodes2 = [] ## LOOKUP TABLES m = 2 * lattice_size + 1 weight_lookup = {} for p in range(-1, m + 1): weight_lookup[p] = {} for q in range(-1, m + 1): weight_lookup[p][q] = wS * abs(p - q) ## CONSTRUCT GRAPH ## create a graph containing all possible matchings between pairs of anyons (given constraints) ## This is represented as three lists: nodes1 = [] nodes2 = [] weights = [] ## PART 1: Complete graph between all real nodes for i in range(n_nodes - 1): (pt, p0, p1) = nodes_list[i] for j in range(i + 1, n_nodes): (qt, q0, q1) = nodes_list[j] wt = (qt - pt) if wt >= max_time_separation: break weight = weight_lookup[q0][p0] + weight_lookup[q1][p1] + wt * wT nodes1 += [i] nodes2 += [j] weights += [weight] ## PART 2: Generate list of boundary nodes linked to each real node boundary_nodes_list = [] for i in range(n_nodes): (pt, p0, p1) = nodes_list[i] if stabilizer_type == "star": (bt, b0, b1) = (pt, p0, -1 if p1 < lattice_size else m) elif stabilizer_type == "plaquette": (bt, b0, b1) = (pt, -1 if p0 < lattice_size else m, p1) else: print "stabilizer_type must be either *star* or *plaquette*" sys.exit(0) weight = weight_lookup[p0][b0] + weight_lookup[p1][b1] nodes1 += [i] nodes2 += [i + n_nodes] weights += [int(weight * wB / wS)] boundary_nodes_list += [(bt, b0, b1)] ## PART 3: Complete graph between all boundary nodes for i in range(n_nodes - 1): (pt, p0, p1) = boundary_nodes_list[i] for j in range(i + 1, n_nodes): (qt, q0, q1) = boundary_nodes_list[j] wt = (qt - pt) if wt >= 5: break nodes1 += [n_nodes + i] nodes2 += [n_nodes + j] weights += [0] if print_graph == True: print zip(nodes1, nodes2, weights) n_edges = len(nodes1) ## MAKE MATCHING. ## Call the blossom5 perfect matching algorithm to return a matching. ## The form of the returned variable <matching> is a list of pairs of node numbers. matching = pm.getMatching_fast(2 * n_nodes, nodes1, nodes2, weights) if print_graph == True: print "Matching" print matching ## REFORMAT MATCHING PAIRS ## Take <matching> and turn it into a list of paired anyon positions. matching_pairs = [[i, matching[i]] for i in range(2 * n_nodes) if matching[i] > i] all_positions = nodes_list + boundary_nodes_list points = [] if len(matching_pairs) == 0 else [ [all_positions[i] for i in x] for x in matching_pairs ] return points
def match_planar_3D(lattice_size,stabilizer_type,anyon_positions,time_space_weights,boundary_weight = 1,print_graph=False): max_time_separation = 15 t00 = time.time() total_time=len(anyon_positions) nodes_list=[item for sublist in anyon_positions for item in sublist] n_nodes=len(nodes_list) [wS,wT]=time_space_weights wB = wS if boundary_weight == 1 else boundary_weight if n_nodes==0: return [] node_index=[] count=0 for x in anyon_positions: node_index+=[[count+i for i in range(len(x))]] count+=len(x) b_node_index=[[index+n_nodes for index in t] for t in node_index] all_boundary_nodes=[] boundary_node=None ## LOOKUP TABLES m = 2*lattice_size +1 weight_lookup={} for p in range(-1,m+1): weight_lookup[p]={} for q in range(-1,m+1): weight_lookup[p][q]=wS*abs(p-q) #------------------------------------------------------------ nodes1 = [] nodes2 = [] weights = [] ## PART 1: Complete graph between all real nodes for i in range(n_nodes -1): (pt,p0,p1)=nodes_list[i] for j in range(i+1,n_nodes): (qt,q0,q1)=nodes_list[j] wt=(qt-pt) if wt>=max_time_separation: break weight = weight_lookup[q0][p0]+weight_lookup[q1][p1]+wt*wT nodes1 +=[i] nodes2 +=[j] weights+=[weight] #------------------------------------- ## PART 2: Create boundary node for each for t in range(total_time): n_list_t=anyon_positions[t] n_nodes_t=len(n_list_t) n_index_t=node_index[t] b_index_t=b_node_index[t] n_nodes_t_minus1 = n_nodes_t - 1 # for every node, create a boundary node and joining edge boundary_node_positions_t=[] if stabilizer_type == "star": for i in range(n_nodes_t): (pt,p0,p1)=n_list_t[i] (bt,b0,b1)=(t,p0,-1 if p1<lattice_size else m) boundary_node_positions_t+=[[bt,b0,b1]] #weight=sW*(abs(p0-b0)+abs(p1-b1)) weight = weight_lookup[p0][b0]+weight_lookup[p1][b1] nodes1+=[n_index_t[i]] nodes2+=[b_index_t[i]] weights+=[int(weight*wB/wS)] if i==0: if isinstance(boundary_node,int): boundary_node_update=b_index_t[0] nodes1+=[boundary_node_update] nodes2+=[boundary_node] weights+=[0] boundary_node=copy.copy(boundary_node_update) else: boundary_node=copy.copy(b_index_t[0]) elif stabilizer_type=="plaquette": for i in range(n_nodes_t): (pt,p0,p1)=n_list_t[i] (bt,b0,b1)=(t,-1 if p0<lattice_size else m,p1) boundary_node_positions_t+=[[bt,b0,b1]] weight = weight_lookup[p0][b0]+weight_lookup[p1][b1] # graphArray+=[[n_index_t[i],b_index_t[i],weight]] nodes1+=[n_index_t[i]] nodes2+=[b_index_t[i]] weights+=[int(weight*wB/wS)] if i==0: if isinstance(boundary_node,int): boundary_node_update=b_index_t[0] # graphArray+=[[boundary_node_update,boundary_node,0]] nodes1+=[boundary_node_update] nodes2+=[boundary_node] weights+=[0] boundary_node=copy.copy(boundary_node_update) else: boundary_node=copy.copy(b_index_t[0]) else: print "stabilizer_type must be either **star** or **plaquette**" return 0 ## save one boundary node to connect to other layers all_boundary_nodes+=boundary_node_positions_t #boundary_nodes_positions_t= #[[pt,p0,-1 if p1<lattice_size else 2*lattice_size+1] for [pt,p0,p1] in node_list_t] #if stabilizer_type=="star" else [[pt,-1 if p0<lattice_size else 2*lattice_size,p1]] tt2 = time.time() # fully connect boundary nodes with weight 0 for i in range(n_nodes_t-1): # for j in range(n_nodes_t-i-1): for j in range(i+1,n_nodes_t): # graphArray+=[[b_index_t[i],b_index_t[i+j+1],0]] nodes1+=[b_index_t[i]] #nodes2+=[b_index_t[i+j+1]] nodes2+=[b_index_t[j]] weights+=[0] # t22 += time.time()-tt2 if print_graph==True: print zip(nodes1,nodes2,weights) # print 't0 = ', t0 # print 't1 = ', time.time()-tt1 # print 't2 = ', t22 # print 't3 = ', t3 n_edges=len(nodes1) ################ MATCHING ################### #tt4 = time.time() # matching=pm.getMatching(2*n_nodes,graphArray) matching = pm.getMatching_fast(2*n_nodes,nodes1,nodes2,weights) # print 'matching ', time.time()-tt4 ############################################# if print_graph==True: print "Matching" print matching matching_pairs=[[i,matching[i]] for i in range(2*n_nodes) if matching[i]>i] all_positions=nodes_list+all_boundary_nodes points=[] if len(matching_pairs)==0 else [[all_positions[i] for i in x] for x in matching_pairs] return points
def match_planar_3D(lattice_size,stabilizer_type,anyon_positions,time_space_weights=[1,1],boundary_weight = -1 ,print_graph=False): """ Finds a matching to fix the errors in a 3D planar code given the positions of '-1' stabilizer outcomes Parameters: ----------- lattice_size -- The dimension of the code stabilizer_type -- defines the stabilizer basis, can take the value "star" or "plaquette" anyon_positions -- A list of the locations of all '-1' value stabilizers in the 3D parity lattice. [[x0,y0,t0],[x1,y1,t1],...] time_space_weights -- The multiplicative weighting that should be assigned to graph edges in the [space,time] dimensions. Default: [1,1] boundary_weight -- multiplicative weight to be assigned to edges matching to the boundary. if no boundary_weight specified, set boundary_weight = space_weight print_graph -- Set to True to print the constructed graph. Default: False. Returns: -------- A list containing all the input anyon positions grouped into pairs. [[[x0,y0,t0],[x1,y1,t1]],[[x2,y2,t2],... """ max_time_separation = 15 # This determines the maximum time separation of edges that are added to the graph [wS,wT]=time_space_weights wB = wS if boundary_weight == -1 else boundary_weight #if boundary weight not specifiedm, let wB=wS total_time=len(anyon_positions) nodes_list=[item for sublist in anyon_positions for item in sublist] n_nodes=len(nodes_list) # exclude edge case where no anyons exist. if n_nodes==0: return [] node_index=[] count=0 for x in anyon_positions: node_index+=[[count+i for i in range(len(x))]] count+=len(x) b_node_index=[[index+n_nodes for index in t] for t in node_index] all_boundary_nodes=[] all_boundary_nodes2=[] ## LOOKUP TABLES m = 2*lattice_size +1 weight_lookup={} for p in range(-1,m+1): weight_lookup[p]={} for q in range(-1,m+1): weight_lookup[p][q]=wS*abs(p-q) ## CONSTRUCT GRAPH ## create a graph containing all possible matchings between pairs of anyons (given constraints) ## This is represented as three lists: nodes1 = [] nodes2 = [] weights = [] ## PART 1: Complete graph between all real nodes for i in range(n_nodes -1): (pt,p0,p1)=nodes_list[i] for j in range(i+1,n_nodes): (qt,q0,q1)=nodes_list[j] wt=(qt-pt) if wt>=max_time_separation: break weight = weight_lookup[q0][p0]+weight_lookup[q1][p1]+wt*wT nodes1 +=[i] nodes2 +=[j] weights+=[weight] ## PART 2: Generate list of boundary nodes linked to each real node boundary_nodes_list = [] for i in range(n_nodes): (pt,p0,p1)=nodes_list[i] if stabilizer_type =="star": (bt,b0,b1)=(pt,p0,-1 if p1<lattice_size else m) elif stabilizer_type=="plaquette": (bt,b0,b1)=(pt,-1 if p0<lattice_size else m,p1) else: print "stabilizer_type must be either *star* or *plaquette*" sys.exit(0) weight = weight_lookup[p0][b0]+weight_lookup[p1][b1] nodes1+=[i] nodes2+=[i+n_nodes] weights+=[int(weight*wB/wS)] boundary_nodes_list+=[(bt,b0,b1)] ## PART 3: Complete graph between all boundary nodes for i in range(n_nodes -1): (pt,p0,p1)=boundary_nodes_list[i] for j in range(i+1,n_nodes): (qt,q0,q1)=boundary_nodes_list[j] wt=(qt-pt) if wt>=5: break nodes1 +=[n_nodes+i] nodes2 +=[n_nodes+j] weights+=[0] if print_graph==True: print zip(nodes1,nodes2,weights) n_edges=len(nodes1) ## MAKE MATCHING. ## Call the blossom5 perfect matching algorithm to return a matching. ## The form of the returned variable <matching> is a list of pairs of node numbers. matching = pm.getMatching_fast(2*n_nodes,nodes1,nodes2,weights) if print_graph==True: print "Matching" print matching ## REFORMAT MATCHING PAIRS ## Take <matching> and turn it into a list of paired anyon positions. matching_pairs=[[i,matching[i]] for i in range(2*n_nodes) if matching[i]>i] all_positions=nodes_list+boundary_nodes_list points=[] if len(matching_pairs)==0 else [[all_positions[i] for i in x] for x in matching_pairs] return points