示例#1
0
def isoBFS(G):

    table = {}

    isoTool.setGraph(G)

    todo = [ (0,0,[]) ]

    best = bestKnown
    bestList = []
    hitTotal = 0

    def end(signal=None, func=None):
        print
        print "Considered:", hitTotal
        print best
        print '\n'.join(str(x) for x in bestList)

        print hitCount
        if signal:
            import sys
            sys.exit()

    import signal
    signal.signal(signal.SIGINT, end)

    sortCount = 0
    # Main BFS loop
    while len(todo) > 0:
        hitTotal += 1
        #print todo
        (cost, depth, cons) = heappop(todo)
        #(cost, depth, cons) = todo.pop()
        #print todo
        #print c
        #print triList
        
        #verb = False
        #if getConsList(cons) == ['m', 'm', '1bec f08dccc 707af4d', '[]']:
        #    print "yep"
        #    print cons
        #    print calcSize(cons)
        #    verb = True
        #    #exit()

        #print "cons:", c
        # Add in all of the edges needed for G
        c = cons
        while c!= []:
            ta = c[1]
            addEdge(G, (ta[1],ta[2]))
            c = c[3]

        #th = isoTool.getHash()  # doesn't have a performance impact
        th = 1
        #print "considering:", cons
        currentSize, usedSet = calcSize(cons)
        #if best != -1 and calcSize(cons)[0] > best:
        if best != -1 and currentSize > best:
            # strip off the edges added at this stage of the BFS
            c = cons
            while c!= []:
                ta = c[1]
                delEdge(G, (ta[1],ta[2]))
                c = c[3]
            continue


        edgeCache = {}
        # loop across all of the tripples to check where to continue the search

        for t in getAllTripples(G):
            e1 = sortPair([t[0], t[2]])
            e2 = sortPair([t[1], t[2]])

            #print "tripple:", t, e1, e2

            #print "calling left:"
            if edgeCache.has_key(e1):
                h1, leafList1 = edgeCache[e1]
            else:
                addEdge(G,e1)
                h1 = isoTool.getHash()
                leafList1 = extraLeafCheck(G,topDepth,e1)
                #leaf1, cons1 = leafCheck(G)
                edgeCache[e1] = h1, leafList1
                delEdge(G,e1)
                

            #print "calling right:"
            if edgeCache.has_key(e2):
                h2, leafList2 = edgeCache[e2]
            else:
                addEdge(G,e2)
                h2 = isoTool.getHash()
                #if h1 != h2:
                leafList2 = extraLeafCheck(G,topDepth,e2)
                    #leaf2, cons2 = leafCheck(G)
                edgeCache[e2] = h2, leafList2
                delEdge(G,e2)

            #print "leafList1:", leafList1
            #print "leafList2:", leafList2

            #for leaf1, cons1 in leafList1:
            #    for leaf2, cons2 in leafList2:
            for leafNode1 in leafList1:
                for leafNode2 in leafList2:
                    haveCons = False
                    #if h1 == h2 or (leafNode1[0] and leafNode1[0] == leafNode2[0]):
                    if h1 == h2:
                        leftBranch = ('m', [], [], [])
                        #if leafNode1[0] in ('4', '5', 'h'):
                        if leafNode1[0]:
                            rightBranch = leafNode1
                            haveCons = True
                            h = h1, h2
                            #h = False
                        else:
                            rightBranch = []
                            h = h1
                        # uhm.  Not sure about this.  Seems like a big change:
                        #nt = t[:]
                        nt = t[1], t[0], t[2]
                    elif leafNode1[0] and leafNode2[0]:
                        leftBranch = leafNode1
                        rightBranch = leafNode2
                        nt = t[:]
                        haveCons = True
                        h = sortPair((h1,h2))
                        #h = False
                    elif leafNode1[0]:
                        leftBranch = leafNode1
                        rightBranch = []
                        nt = t[:]
                        h = h2
                    elif leafNode2[0]:
                        leftBranch = leafNode2
                        rightBranch = []
                        nt = t[1], t[0], t[2]
                        h = h1
                    else:
                        continue

                    newCons = insertBranch(cons,[False, nt, leftBranch, rightBranch])
                    #newSize, used = calcSize(newCons)
                    newSize, used = calcSize([False, nt, leftBranch, rightBranch], usedSet)
                    newSize = newSize + currentSize - 1
                    #if newSize2+currentSize-1 != newSize or used != used2:
                    #    print "fail"
                    #    print cons
                    #    print newCons
                    #    print [False, nt, leftBranch, rightBranch]
                    #    print
                    #    print currentSize, usedSet
                    #    print newSize, used
                    #    print newSize2, used2
                    #    exit()
                    score = newSize
                    #score = 1.0/newSize
                    #score = (depth+1)/(newSize**2*1.0)
                    #score = (newSize**2*1.0)/(depth+1)
                    #print newCons
                    #print getConsList(newCons)

                    #print "result:", (h,used,newSize)
                    #print "in table:", (h,used,newSize) in table

                    if (h,used,newSize) not in table:
                        table[(h,used,newSize)] = True

                        print "remaining:", len(todo), "best:", best, "size:", newSize, "score:", score, "cons:", getConsList(newCons)
                        if haveCons: # we have a construction
                            if best == -1 or newSize < best:
                                best = newSize
                                bestList = []
                            if newSize == best:
                                #bestList.append((c, t, code, (leaf1, leaf2), (cons1, cons2),used))
                                bestList.append(newCons)

                        elif best == -1 or newSize <= best:
                            heappush(todo, (score,depth+1,newCons))
                            #todo.append((score,depth+1,newCons))
                            #todo.insert(0, (score,depth+1,newCons))
                

        # strip off the edges added at this stage of the BFS
        c = cons
        while c!= []:
            ta = c[1]
            delEdge(G, (ta[1],ta[2]))
            c = c[3]

        #table[th] = True


    end()
示例#2
0
def isoBFS(G):

    table = {}

    isoTool.setGraph(G)

    todo = [(0, 0, [])]

    best = bestKnown
    bestList = []
    hitTotal = 0

    def end(signal=None, func=None):
        print
        print "Considered:", hitTotal
        print best
        print '\n'.join(str(x) for x in bestList)

        print hitCount
        if signal:
            import sys
            sys.exit()

    import signal
    signal.signal(signal.SIGINT, end)

    sortCount = 0
    # Main BFS loop
    while len(todo) > 0:
        hitTotal += 1
        #print todo
        (cost, depth, cons) = heappop(todo)
        #(cost, depth, cons) = todo.pop()
        #print todo
        #print c
        #print triList

        #verb = False
        #if getConsList(cons) == ['m', 'm', '1bec f08dccc 707af4d', '[]']:
        #    print "yep"
        #    print cons
        #    print calcSize(cons)
        #    verb = True
        #    #exit()

        #print "cons:", c
        # Add in all of the edges needed for G
        c = cons
        while c != []:
            ta = c[1]
            addEdge(G, (ta[1], ta[2]))
            c = c[3]

        #th = isoTool.getHash()  # doesn't have a performance impact
        th = 1
        #print "considering:", cons
        currentSize, usedSet = calcSize(cons)
        #if best != -1 and calcSize(cons)[0] > best:
        if best != -1 and currentSize > best:
            # strip off the edges added at this stage of the BFS
            c = cons
            while c != []:
                ta = c[1]
                delEdge(G, (ta[1], ta[2]))
                c = c[3]
            continue

        edgeCache = {}
        # loop across all of the tripples to check where to continue the search

        for t in getAllTripples(G):
            e1 = sortPair([t[0], t[2]])
            e2 = sortPair([t[1], t[2]])

            #print "tripple:", t, e1, e2

            #print "calling left:"
            if edgeCache.has_key(e1):
                h1, leafList1 = edgeCache[e1]
            else:
                addEdge(G, e1)
                h1 = isoTool.getHash()
                leafList1 = extraLeafCheck(G, topDepth, e1)
                #leaf1, cons1 = leafCheck(G)
                edgeCache[e1] = h1, leafList1
                delEdge(G, e1)

            #print "calling right:"
            if edgeCache.has_key(e2):
                h2, leafList2 = edgeCache[e2]
            else:
                addEdge(G, e2)
                h2 = isoTool.getHash()
                #if h1 != h2:
                leafList2 = extraLeafCheck(G, topDepth, e2)
                #leaf2, cons2 = leafCheck(G)
                edgeCache[e2] = h2, leafList2
                delEdge(G, e2)

            #print "leafList1:", leafList1
            #print "leafList2:", leafList2

            #for leaf1, cons1 in leafList1:
            #    for leaf2, cons2 in leafList2:
            for leafNode1 in leafList1:
                for leafNode2 in leafList2:
                    haveCons = False
                    #if h1 == h2 or (leafNode1[0] and leafNode1[0] == leafNode2[0]):
                    if h1 == h2:
                        leftBranch = ('m', [], [], [])
                        #if leafNode1[0] in ('4', '5', 'h'):
                        if leafNode1[0]:
                            rightBranch = leafNode1
                            haveCons = True
                            h = h1, h2
                            #h = False
                        else:
                            rightBranch = []
                            h = h1
                        # uhm.  Not sure about this.  Seems like a big change:
                        #nt = t[:]
                        nt = t[1], t[0], t[2]
                    elif leafNode1[0] and leafNode2[0]:
                        leftBranch = leafNode1
                        rightBranch = leafNode2
                        nt = t[:]
                        haveCons = True
                        h = sortPair((h1, h2))
                        #h = False
                    elif leafNode1[0]:
                        leftBranch = leafNode1
                        rightBranch = []
                        nt = t[:]
                        h = h2
                    elif leafNode2[0]:
                        leftBranch = leafNode2
                        rightBranch = []
                        nt = t[1], t[0], t[2]
                        h = h1
                    else:
                        continue

                    newCons = insertBranch(
                        cons, [False, nt, leftBranch, rightBranch])
                    #newSize, used = calcSize(newCons)
                    newSize, used = calcSize(
                        [False, nt, leftBranch, rightBranch], usedSet)
                    newSize = newSize + currentSize - 1
                    #if newSize2+currentSize-1 != newSize or used != used2:
                    #    print "fail"
                    #    print cons
                    #    print newCons
                    #    print [False, nt, leftBranch, rightBranch]
                    #    print
                    #    print currentSize, usedSet
                    #    print newSize, used
                    #    print newSize2, used2
                    #    exit()
                    score = newSize
                    #score = 1.0/newSize
                    #score = (depth+1)/(newSize**2*1.0)
                    #score = (newSize**2*1.0)/(depth+1)
                    #print newCons
                    #print getConsList(newCons)

                    #print "result:", (h,used,newSize)
                    #print "in table:", (h,used,newSize) in table

                    if (h, used, newSize) not in table:
                        table[(h, used, newSize)] = True

                        print "remaining:", len(
                            todo
                        ), "best:", best, "size:", newSize, "score:", score, "cons:", getConsList(
                            newCons)
                        if haveCons:  # we have a construction
                            if best == -1 or newSize < best:
                                best = newSize
                                bestList = []
                            if newSize == best:
                                #bestList.append((c, t, code, (leaf1, leaf2), (cons1, cons2),used))
                                bestList.append(newCons)

                        elif best == -1 or newSize <= best:
                            heappush(todo, (score, depth + 1, newCons))
                            #todo.append((score,depth+1,newCons))
                            #todo.insert(0, (score,depth+1,newCons))

        # strip off the edges added at this stage of the BFS
        c = cons
        while c != []:
            ta = c[1]
            delEdge(G, (ta[1], ta[2]))
            c = c[3]

        #table[th] = True

    end()
示例#3
0
def extraLeafCheck(G, depth, ne = None, nKiteEdges=None):
    global hitCount

    # do a depth limited search for a construction.
    # So we take both edges of a triple, and both of the resulting graphs are leafs

    # depth is how many more times we can recurse before finding a leaf.

    # bigTable is a global cache of graphs and depths, but we can only cache negative results.
    # caching on graph isomorphism here doesn't work.
    # You cache a result.  Then you pull that result from the cache later for a new graph.
    # But the indicies are wrong, so your construction is wrong when you sum the graphs.  
    # To make this work, you would have to map back and forth between
    # the canonical indicies and your working indices.

    #h1 = -1


    # depth is part of the hash because just because a graph isn't a leaf at depth 4, doesn't mean it's not a leaf at depth 3
    h1 = isoTool.getHash()
    if (h1, depth) in bigTable:
    #    print "Cache hit:", h1, bigTable[h1]
        hitCount += 1
        return bigTable[(h1, depth)]

    # test if this graph is a leaf.  I.E. contains a 4-clique, 5-wheel, or h graph
    l = leafCheck(G,ne,nKiteEdges)

    # return if we have a leaf, or we have hit our depth limit.
    if l[0] or depth <= 2:  # leafCheck takes care of depth <= 2
        #bigTable[h1] = [l]  # FIXME I think we can cache the negative result here for depth
        return [l]

    # edgeCache caches a result for when an edge participates in multiple tripples.
    edgeCache = {}
    
    retList = []  # we need to return all possible solutions
    usedSets = [] # a list of sets of graphs used for each of the solutions in retLest

    kiteEdges = getKiteEdges(G) # performance optimization

    for t in getAllTripples(G):
        e1 = sortPair([t[0], t[2]])
        e2 = sortPair([t[1], t[2]])

        #print "elc tripple:", t, e1, e2

        # Basic recursive check on the edges

        if edgeCache.has_key(e1):
            r1 = edgeCache[e1]
        else:
            addEdge(G,e1)
            r1 = extraLeafCheck(G,depth-1,e1,kiteEdges)
            delEdge(G,e1)
            edgeCache[e1] = r1
            

        if edgeCache.has_key(e2):
            r2 = edgeCache[e2]
        else:
            addEdge(G,e2)
            r2 = extraLeafCheck(G,depth-1,e2,kiteEdges)
            delEdge(G,e2)
            edgeCache[e2] = r2
        
        # to make this arbitrary depth:
        # leaf1 and leaf2 become lists
        # is that it?
        # Oh, and we are going to need edges for all returns

        # loop across the results
        for l1 in r1:
            for l2 in r2:
                # Found a pair of results that are good.
                # non-good results are in the ret-list? We don't just return empty?
                if l1[0] and l2[0]:
                    #print "t:", t
                    #print "derp1:", l1
                    #print "derp2:", l2


                    #print G
                    #print "big1:", r1
                    #print "big2:", r2
                    #exit()

                    # get the subgraph generated by the hajos sum of the leaf graphs
                    # r is presumably our standard search node quad.  Whatever that is.
                    # this reduces our found construction to a subgraph construction
                    r = getCombinedCons(G, t, l1, l2)

                    # might be able to optimize the above.  We always call it, so we might 
                    # not need to recurse.  In fact, it's kind of goofy that this gets called recursively.

                    #if r[0] == '1bec   e0328 4f4d838':
                    #    print r
                    #    exit()

                    # Do some optimzation to reduce the size of our results

                    # use calcSize to get the set of graphs used in the construction
                    used = calcSize(r)[1]
                    # calcSize doesn't include the root graph in the set, so add it
                    used = used.union([r[0]])

                    # Check if we have already seen a result that uses a subset of the
                    # graphs that we are using.
                    okay = True
                    for s in usedSets:
                        if s.issubset(used):
                            okay = False
                            break
                    
                    # now the other side of the above.  Go through the list, and kill any previous results that
                    # are supersets of the current result.
                    if okay:
                        #this is going to be hacky.
                        #filter the retList if the new construction is a subset of 
                        # any of the constructions in the retlist.
                        newUsed = []
                        newRet = []
                        for i in xrange(len(retList)):
                            s = usedSets[i]
                            if not used.issubset(s):    
                                newUsed.append(s)
                                newRet.append(retList[i])
                        retList = newRet
                        usedSets = newUsed
                        

                        retList.append(r)
                        usedSets.append(used)

    #print "elc ret:", retList
    if retList:
        return retList  # we have a result, we can return it.
                        # unfortunately, our search node format does not cover returning usedSets as well.
    else:
        bigTable[(h1,depth)] = [(False,)] # only cache on failure
        return [(False,)]
示例#4
0
def extraLeafCheck(G, depth, ne=None, nKiteEdges=None):
    global hitCount

    # do a depth limited search for a construction.
    # So we take both edges of a triple, and both of the resulting graphs are leafs

    # depth is how many more times we can recurse before finding a leaf.

    # bigTable is a global cache of graphs and depths, but we can only cache negative results.
    # caching on graph isomorphism here doesn't work.
    # You cache a result.  Then you pull that result from the cache later for a new graph.
    # But the indicies are wrong, so your construction is wrong when you sum the graphs.
    # To make this work, you would have to map back and forth between
    # the canonical indicies and your working indices.

    #h1 = -1

    # depth is part of the hash because just because a graph isn't a leaf at depth 4, doesn't mean it's not a leaf at depth 3
    h1 = isoTool.getHash()
    if (h1, depth) in bigTable:
        #    print "Cache hit:", h1, bigTable[h1]
        hitCount += 1
        return bigTable[(h1, depth)]

    # test if this graph is a leaf.  I.E. contains a 4-clique, 5-wheel, or h graph
    l = leafCheck(G, ne, nKiteEdges)

    # return if we have a leaf, or we have hit our depth limit.
    if l[0] or depth <= 2:  # leafCheck takes care of depth <= 2
        #bigTable[h1] = [l]  # FIXME I think we can cache the negative result here for depth
        return [l]

    # edgeCache caches a result for when an edge participates in multiple tripples.
    edgeCache = {}

    retList = []  # we need to return all possible solutions
    usedSets = [
    ]  # a list of sets of graphs used for each of the solutions in retLest

    kiteEdges = getKiteEdges(G)  # performance optimization

    for t in getAllTripples(G):
        e1 = sortPair([t[0], t[2]])
        e2 = sortPair([t[1], t[2]])

        #print "elc tripple:", t, e1, e2

        # Basic recursive check on the edges

        if edgeCache.has_key(e1):
            r1 = edgeCache[e1]
        else:
            addEdge(G, e1)
            r1 = extraLeafCheck(G, depth - 1, e1, kiteEdges)
            delEdge(G, e1)
            edgeCache[e1] = r1

        if edgeCache.has_key(e2):
            r2 = edgeCache[e2]
        else:
            addEdge(G, e2)
            r2 = extraLeafCheck(G, depth - 1, e2, kiteEdges)
            delEdge(G, e2)
            edgeCache[e2] = r2

        # to make this arbitrary depth:
        # leaf1 and leaf2 become lists
        # is that it?
        # Oh, and we are going to need edges for all returns

        # loop across the results
        for l1 in r1:
            for l2 in r2:
                # Found a pair of results that are good.
                # non-good results are in the ret-list? We don't just return empty?
                if l1[0] and l2[0]:
                    #print "t:", t
                    #print "derp1:", l1
                    #print "derp2:", l2

                    #print G
                    #print "big1:", r1
                    #print "big2:", r2
                    #exit()

                    # get the subgraph generated by the hajos sum of the leaf graphs
                    # r is presumably our standard search node quad.  Whatever that is.
                    # this reduces our found construction to a subgraph construction
                    r = getCombinedCons(G, t, l1, l2)

                    # might be able to optimize the above.  We always call it, so we might
                    # not need to recurse.  In fact, it's kind of goofy that this gets called recursively.

                    #if r[0] == '1bec   e0328 4f4d838':
                    #    print r
                    #    exit()

                    # Do some optimzation to reduce the size of our results

                    # use calcSize to get the set of graphs used in the construction
                    used = calcSize(r)[1]
                    # calcSize doesn't include the root graph in the set, so add it
                    used = used.union([r[0]])

                    # Check if we have already seen a result that uses a subset of the
                    # graphs that we are using.
                    okay = True
                    for s in usedSets:
                        if s.issubset(used):
                            okay = False
                            break

                    # now the other side of the above.  Go through the list, and kill any previous results that
                    # are supersets of the current result.
                    if okay:
                        #this is going to be hacky.
                        #filter the retList if the new construction is a subset of
                        # any of the constructions in the retlist.
                        newUsed = []
                        newRet = []
                        for i in xrange(len(retList)):
                            s = usedSets[i]
                            if not used.issubset(s):
                                newUsed.append(s)
                                newRet.append(retList[i])
                        retList = newRet
                        usedSets = newUsed

                        retList.append(r)
                        usedSets.append(used)

    #print "elc ret:", retList
    if retList:
        return retList  # we have a result, we can return it.
        # unfortunately, our search node format does not cover returning usedSets as well.
    else:
        bigTable[(h1, depth)] = [(False, )]  # only cache on failure
        return [(False, )]