def refineColors(G: graph): a = dict() aPrev = dict() neighbours = generateNeighbourList(G) # define a number that gives a color that has not yet been chosen nextColor = 0 # Fill a with colors related to the degree of the vertex for v in G.V(): a[v] = len(neighbours[v]) nextColor = max(a[v] + 1, nextColor) # while the colors still change after an iteration while aPrev != a: aPrev = a a = dict() nbColors = getNeighbourColors(neighbours, aPrev) # for each vertex u in G.V() for i in range(len(G.V())): u = G.V()[i] # initialize nc, the new color of u nc = a.get(u, aPrev[u]) # create a set "same" that will contain all vertices v that are "equal" to the current vertex u same = set() # for every unchecked vertex v for v in G.V()[i + 1 :]: # if the vertices were "equal" and not exactly the same if u != v and aPrev[u] == aPrev[v]: # Check if they are still "equal" if not haveSameNeighbours(u, v, nbColors): # they are not equal anymore, if we haven't updated nc already, do it now if nc == aPrev[u]: nc = nextColor nextColor += 1 else: # they are still equal, add the vertex to our "same" set same.add(v) # update the a[v] of every v in same for v in same: # If nc and a[v] (or the previous a[v]) differ, change a[v] if nc != a.get(v, aPrev[v]): a[v] = nc a[u] = nc # set the colornums for v in a: v.colornum = a[v] return a
def countTreeAutomorphismsRS(G, visualize=False): p = generatePartitions(G) n = generateNeighbourList(G) degrees = dict() for v in G.V(): degree = len(n[v]) degreeSet = degrees.get(degree, 0) if degreeSet: degreeSet.add(v) else: degrees[degree] = {v} colorOf = dict() for color in p: for v in color: colorOf[v] = color queue = [] done = set() automorphisms = 1 for c in p: if len(c) == 1: queue.append((pickFromSet(c), None)) break if not queue: for c in p: if len(c) == 2: r, l = c if True or l in n[r]: queue.append((r, None)) break while queue: vertex, parent = queue[-1] color = colorOf[vertex] del queue[-1] for v in n[vertex] - done: if v not in done: queue.append((v, vertex)) done |= colorOf[v] if parent: automorphisms *= math.factorial(len(n[parent] & color))**(len(colorOf[parent])) else: automorphisms *= math.factorial(len(color)) if visualize: drawProgress(G, vertex, color, done, queue) done |= color if visualize: drawProgress(G, None, set(), done, queue) return automorphisms
def generatePartitions(G, usecolors=False): neighbours = generateNeighbourList(G) p = [] pSplit = [] degrees = dict() for v in G.V(): degree = len(neighbours[v]) if degrees.get(degree, -1) == -1: degrees[degree] = {v} else: degrees[degree].add(v) if usecolors: p = generatePfromColors(G) pSplit = generatePfromColors(G) else: for k in degrees: p.append(degrees[k]) pSplit.append(degrees[k]) w = set(range(len(p))) while w: #print("w: ", w) #print("wl: ", [(c, len(p[c])) for c in w]) aN = w.pop() a = p[aN] nbs = set() for va in a: nbs |= neighbours[va] # print("nbs: ", nbs) for color in pSplit: x = nbs & color # print("nbs & color: ", x) if x: for yN in range(len(p)): if len(p[yN]) > 1: y = p[yN] both = x & y ynotx = y - x if both and ynotx: p[yN] = both p.append(ynotx) if yN in w: w.add(len(p) - 1) else: if len(both) <= len(ynotx): w.add(yN) else: w.add(len(p) - 1) return p
def refineColorsv2(G: graph, useColornums=False): # a is a dict that contains a vertex as key and a color as value a = dict() # the old a, from the previous iteration aPrev = dict() # aRev (a reversed) contains a color as key and a set of vertices that have that color as value aRev = dict() # the a reversed dict of the previous iteration aRevPrev = dict() # generate a dict of vertex -> vertices that contains all the neighbours of the key vertex neighbours = generateNeighbourList(G) # define a number that gives a color that has not yet been chosen nextColor = 0 # Fill a with colors related to the degree of the vertex for v in G.V(): # color of v = the degree of v (number of neighbours) if not useColornums: a[v] = len(neighbours[v]) else: a[v] = v.colornum addToRevDict(aRev, a[v], v) # make sure nextColor is always higher than the highest color that was already used nextColor = max(a[v] + 1, nextColor) # while the colors still change after an iteration while aPrev != a: # set the Prev dicts to the previous values of a and aRev and reset a and aRev aPrev = a aRevPrev = aRev a = dict() aRev = dict() nbColors = getNeighbourColors(neighbours, aPrev) # pus all the vertices that we have already refined in the set done so we won't have to check them again done = set() # for each vertex u in G.V() for u in G.V(): # if u has already been refined earlier in this iteration, skip it now if u in done: continue # initialize nc, the new color of u nc = a.get(u, aPrev[u]) # create a set "same" that will contain all vertices v that are "equal" to the current vertex u same = set() # for every vertex v that was equal for v in aRevPrev[aPrev[u]]: # if the vertices were "equal" and not exactly the same if u != v: # Check if they are still "equal" if not haveSameNeighbours(u, v, nbColors): # they are not equal anymore, if we haven't updated nc already, do it now if nc == aPrev[u]: nc = nextColor nextColor += 1 else: # they are still equal, add the vertex to our "same" set same.add(v) # update the a[v] of every v in same for v in same: # If nc and a[v] (or the previous a[v]) differ, change a[v] if nc != a.get(v, aPrev[v]): a[v] = nc addToRevDict(aRev, nc, v) done.add(v) a[u] = nc addToRevDict(aRev, nc, u) # set the colornums for v in a: v.colornum = a[v] return a
def countTreeAutomorphismsLS(G, visualize=False): p = generatePartitions(G) n = generateNeighbourList(G) degrees = dict() for v in G.V(): degree = len(n[v]) degreeSet = degrees.get(degree, 0) if degreeSet: degreeSet.add(v) else: degrees[degree] = {v} colorOf = dict() for color in p: for v in color: colorOf[v] = color queue = [] done = set() for color in p: if len(color) > 1 and color <= degrees[1]: queue.append(color) done = done | color automorphisms = 1 while queue: # is not empty newQueue = [] for color in queue: v = pickFromSet(color) if visualize: drawProgress(G, v, color, done, queue) parent = None for neighbour in n[v]: if len(n[neighbour] & color) > 1 : parent = neighbour break if parent is None: unvisitedNeighbours = n[v] - done if len(unvisitedNeighbours) == 1: parent = unvisitedNeighbours.pop() elif len(unvisitedNeighbours) > 1: newQueue.append(color) continue if parent: if len(colorOf[parent]) > 1 and parent not in done: newQueue.append(colorOf[parent]) automorphisms *= math.factorial(len(n[parent] & color))**(len(colorOf[parent])) done |= color else: if len(color) == 2 and len(color&n[v]) == 1: automorphisms *= 2 queue = newQueue for c in queue: done |= c if visualize: drawProgress(G, None, set(), done, queue) return automorphisms