def __init__(self, edges, loops, kappa): ''' Construct a Labeled Stable Graph -- the canonical representative of the labeled stable graph given by edges, loops and kappa, where: - ``edges`` -- tuple of triples, where a triple (v1,v2,m) means that the vertices v1 and v2 are connected by m edges - ``loops`` -- tuple, where an integer loops[i] is the number of loops associated to the vertex i - ``kappa`` -- tuple of tuples, a partition of stratum into subpartitions, where kappa[i] is a subpartition of orders of zeroes associated to the vertex i Lists can be used instead of tuples, as they will be automatically converted to be immutable. ''' if not edges: graph = Graph(weighted=True, loops=False, multiedges=False) graph.add_vertex() else: graph = Graph(list(edges), loops=False, multiedges=False, weighted=True) self.edges, self.loops, self.kappa, self.graph = canonical( graph.edges(), loops, kappa, graph) self.genera = [(sum(self.kappa[v]) - 2 * self.vertex_deg(v) - 4 * self.loops[v] + 4) / ZZ(4) for v in self.graph.vertices()]
class StrataWithSageGraph(object): def __init__(self, strataG): self.strataG = strataG self.sageG = Graph([list(range(1, strataG.num_vertices() + 1)), []], multiedges=True, loops=True) self.edge_label_to_edge = dict() self.vertex_to_marks = { v: [] for v in range(1, self.strataG.num_vertices() + 1) } self._has_marks = False for e in range(1, strataG.num_edges() + 1): edge_done = False if self.strataG.M[0, e] != 0: #it is a half edge for v in range(1, strataG.num_vertices() + 1): if self.strataG.M[v, e][0] == 1: self.vertex_to_marks[v].append((e, self.strataG.M[0, e])) edge_done = True self._has_marks = True break else: #it is a whole edge vert_touching_e = [] for v in range(1, strataG.num_vertices() + 1): if strataG.M[v, e][0] == 2: #add a loop self.sageG.add_edge((v, v, e)) self.edge_label_to_edge[e] = (v, v, e) edge_done = True break if strataG.M[v, e][0] == 1: vert_touching_e.append(v) if len(vert_touching_e) == 2: break if edge_done: continue if len(vert_touching_e) == 2: self.sageG.add_edge( (vert_touching_e[0], vert_touching_e[1], e)) self.edge_label_to_edge[e] = (vert_touching_e[0], vert_touching_e[1], e) else: raise Exception("Unexpected here!") def has_marks(self): return self._has_marks def marks_on_v(self, v): return self.vertex_to_marks[v] def edges_incident(self, v): for v1, v2, e in self.sageG.edges_incident(v): yield e def edges_labels_between_vertex_sets(self, vs1, vs2): #problem here when overlap........ result = [] for v1, v2, e in self.sageG.edges(): if v1 in vs1 and v2 in vs2: result.append(e) elif v1 in vs2 and v2 in vs1: result.append(e) return result #some probably garbage... #v1sedges = set() #v2sedges = set() #for v1 in vs1: # for e in self.edges_incident(v1): # v1sedges.add(e) #for v2 in vs2: # for e in self.edges_incident(v2): # v2sedges.add(e) #return v1sedges.intersection(v2sedges) def edges(self): """ Returns a list of triples! """ return self.sageG.edges() def vertices(self): return self.sageG.vertices() def num_vertices(self): return self.strataG.num_vertices() def v_genus(self, v): """ Returns the genus of the vertex v. """ return self.strataG.M[v, 0][0] def subgraph(self, vertices, edge_labels): #print self.edge_label_to_edge #print self.sageG.edges() return self.sageG.subgraph( vertices, [self.edge_label_to_edge[l] for l in edge_labels]) def edge_is_incident(self, e, v): #print "is_inc", e,v #print self.strataG #print return self.strataG.M[v, e][0] > 0 def is_loop(self, e): v1, v2, ep = self.edge_label_to_edge[e] return v1 == v2
class StrataWithSageGraph(object): def __init__(self, strataG): self.strataG = strataG self.sageG = Graph([range(1,strataG.num_vertices()+1),[]], multiedges=True, loops = True) self.edge_label_to_edge = dict() self.vertex_to_marks = {v:[] for v in range(1, self.strataG.num_vertices()+1)} self._has_marks = False for e in range(1, strataG.num_edges()+1): edge_done = False if self.strataG.M[0,e] != 0: #it is a half edge for v in range(1, strataG.num_vertices()+1): if self.strataG.M[v,e][0] == 1: self.vertex_to_marks[v].append((e,self.strataG.M[0,e])) edge_done = True self._has_marks = True break else: #it is a whole edge vert_touching_e = [] for v in range(1, strataG.num_vertices()+1): if strataG.M[v,e][0] == 2: #add a loop self.sageG.add_edge( (v,v,e) ) self.edge_label_to_edge[e] = (v,v,e) edge_done = True break if strataG.M[v,e][0] == 1: vert_touching_e.append(v) if len(vert_touching_e) == 2: break if edge_done: continue if len(vert_touching_e) == 2: self.sageG.add_edge( (vert_touching_e[0], vert_touching_e[1],e) ) self.edge_label_to_edge[e] = (vert_touching_e[0], vert_touching_e[1],e) else: raise Exception("Unexpected here!") def has_marks(self): return self._has_marks def marks_on_v(self,v): return self.vertex_to_marks[v] def edges_incident(self,v): for v1,v2,e in self.sageG.edges_incident(v): yield e def edges_labels_between_vertex_sets(self,vs1,vs2): #problem here when overlap........ result = [] for v1,v2, e in self.sageG.edges(): if v1 in vs1 and v2 in vs2: result.append(e) elif v1 in vs2 and v2 in vs1: result.append(e) return result #some probably garbage... #v1sedges = set() #v2sedges = set() #for v1 in vs1: # for e in self.edges_incident(v1): # v1sedges.add(e) #for v2 in vs2: # for e in self.edges_incident(v2): # v2sedges.add(e) #return v1sedges.intersection(v2sedges) def edges(self): """ Returns a list of triples! """ return self.sageG.edges() def vertices(self): return self.sageG.vertices() def num_vertices(self): return self.strataG.num_vertices() def v_genus(self,v): """ Returns the genus of the vertex v. """ return self.strataG.M[v,0][0] def subgraph(self,vertices, edge_labels): #print self.edge_label_to_edge #print self.sageG.edges() return self.sageG.subgraph(vertices, [self.edge_label_to_edge[l] for l in edge_labels]) def edge_is_incident(self,e,v): #print "is_inc", e,v #print self.strataG #print return self.strataG.M[v,e][0] > 0 def is_loop(self, e): v1,v2, ep = self.edge_label_to_edge[e] return v1==v2