예제 #1
0
def isMinSep(S, G):
    """Check whether S is a minimal separator of G.
    A set of vertices S is a minimal separator of G
    if and only if there are at least two full components
    associated with S in G.
    See Lemma 1 of [BT02Listing].
    """
    n_of_full_comps = 0
    for (Sd, C) in pv.getBlocks(G, S):
        if Sd == S:
            n_of_full_comps += 1
            if n_of_full_comps == 2:
                return True
    return False
예제 #2
0
def isPMC(P, G, boundVal):
    """Check whether P is a pmc in G.
    If yes, the number of nonedges in G[P]
    is also returned.
    See Theorem 8 of [BT02Listing].
    """
    nj = len(P)
    J = G.subgraph(P)
    fs = nj * (nj - 1) / 2 - J.number_of_edges()
    if fs > boundVal:
        return False, -1
    for (N, C) in pv.getBlocks(G, P):
        if N == P:
            return False, -1
        pv.cliquify(J, N)
    if nj * (nj - 1) == 2 * J.number_of_edges(
    ):  #checking whether J became a clique.
        return True, fs
    return (False, -1)
예제 #3
0
def oneMoreVertex(G, a, S_cur, S_next, P_cur, boundVal):
    """See Algorithm ONE_MORE_VERTEX in [BT02Listing].
    """
    P_next = set()
    P_next_temp = set()
    for (pmc, dummy) in P_cur:
        if pmc in P_next_temp:
            continue
        ispmc, fs = isPMC(pmc, G, boundVal)
        if ispmc:
            P_next.add((pmc, fs))
            P_next_temp.add(pmc)
        else:
            pmca = frozenset(pmc.union(set([a])))
            if pmca in P_next_temp:
                continue
            ispmc, fs = isPMC(pmca, G, boundVal)
            if ispmc:
                P_next.add((pmca, fs))
                P_next_temp.add(pmca)
    for s in S_next:
        sa = frozenset(s.union(set([a])))
        if not sa in P_next_temp:
            ispmc, fs = isPMC(sa, G, boundVal)
            if ispmc:
                P_next.add((sa, fs))
                P_next_temp.add(sa)
        if a not in s and not s in S_cur:
            blocks = list(pv.getBlocks(G, s))
            for t in S_next:
                for (Sd, C) in blocks:
                    if Sd == s:
                        stc = frozenset(s.union(t.intersection(C)))
                        if stc in P_next_temp:
                            continue
                        ispmc, fs = isPMC(stc, G, boundVal)
                        if ispmc:
                            P_next.add((stc, fs))
                            P_next_temp.add(stc)
    return P_next
예제 #4
0
def computeBPnPB(G, B, bids, P, S):
    """Computess BP and PB.
    B is the dictionary of blocks where bids is its indices sorted based
    on the block size, 
    P is the list of pmcs and S is the dictionary of minimal
    separators.  
    BP[i] is the dictionary of pmcs associated with the block B[i].
    PB[(p,b)] is the dictionary of blocks which are associated to P[p]
    and which are subsets of B[b].
    """
    BP = {}
    PB = {}
    for i in xrange(0, len(B)):
        BP[i] = []
    for p in xrange(0, len(P)):
        Pp = P[p][0]
        lenPp = len(Pp)
        b = len(B) - 1
        pBlocks = list(pv.getBlocks(G, Pp))
        while b >= 0:
            bb = bids[b]
            (s, C) = B[bb]
            Ss = S[s][0]
            lenSs = len(Ss)
            if lenPp <= lenSs:
                b -= 1
                continue
            if Ss.issubset(Pp) and Pp.issubset(Ss.union(C)):
                BP[bb].append(p)
                PB[(p, bb)] = []
                for (Sd, Cd) in pBlocks:
                    SdCd = Sd.union(Cd)
                    if len(SdCd) >= lenSs + len(C):
                        continue
                    if SdCd.issubset(Ss.union(C)):
                        PB[(p, bb)].append(getBlockId(Sd, Cd, S, B, bids))
            b = b - 1
    return BP, PB
예제 #5
0
def computeSepBlocks(G):
    """Computes the following:
    1. S <dictionary>: the minimal separators of G.
        S[i] = (s, blocks, fs), where s is the set of 
        minimal separator, blocks are the ids of blocks 
        associated with s, and fs is the fill-in size of s.
    2. B <dictionary>: contains the full blocks associated with minimal separators.
        B[i] = (s, C) denotes the block where s is the index to S and C is the 
        actual component.
    4. bids <list>: block indices (in B) sorted in nondecreasing order based
        on the number of vertices in the blokcs.
    5. Sim <set>: contains the inclusion-wise minimal separators (indices from S).  
    See Algorithm AllMinSep in [BBC00Generating].
    """
    #INITIALIZATION step in the algorithm.
    S = {}  #Minimal separators
    B = {}  #Blocks
    S_temp = set()
    sid = 0  #separator id.
    bid = 0  #full block id.
    Sim = set()
    for v in G.nodes():
        N = set([v])
        N.update(G.neighbors(v))
        for (Sd, Cd) in pv.getBlocks(G, N):
            if Sd in S_temp:
                continue
            fs = pv.fillSize(G, Sd)
            B[bid] = (sid, Cd)
            blocks = [bid]
            bid += 1
            for (Td, Dd) in pv.getBlocks(G, Sd.union(Cd)):
                if Td != Sd:  #we only need full blocks.
                    continue
                B[bid] = (sid, Dd)
                blocks.append(bid)
                bid += 1
            S[sid] = (Sd, blocks, fs)
            S_temp.add(frozenset(Sd))
            updateSim(Sim, S, Sd, sid)
            sid += 1
    #GENERATION step in the algorithm.
    counter = 0
    while counter != len(S):
        (Sd, blocks_dummy, fs_dummy) = S[counter]
        for x in Sd:
            T = set(G.neighbors(x)).union(Sd)
            for (Td, Dd) in pv.getBlocks(G, T):
                if Td in S_temp:
                    continue
                fs = pv.fillSize(G, Td)
                B[bid] = (sid, Dd)
                blocks = [bid]
                bid += 1
                for Ud, Ed in pv.getBlocks(G, Td.union(Dd)):
                    if Ud != Td:
                        continue
                    B[bid] = (sid, Ed)
                    blocks.append(bid)
                    bid += 1
                S[sid] = (Td, blocks, fs)
                updateSim(Sim, S, Td, sid)
                S_temp.add(frozenset(Td))
                sid += 1
        counter += 1
    bids = sorted([bid for bid in B.keys()],
                  key=lambda x: len(S[B[x][0]][0]) + len(B[x][1]))
    return S, B, bids, Sim