コード例 #1
0
ファイル: test_opb.py プロジェクト: marcvinyals/cnfgen
 def test_one_leq(self) :
     opb="""\
     * #variable= 5 #constraint= 1
     *
     -1 x1 -1 x2 -1 x3 -1 x4 -1 x5 >= -2;
     """
     F=CNF()
     F.add_less_or_equal(["a","b","c","d","e"],2)
     self.assertCnfEqualsOPB(F,opb)
コード例 #2
0
ファイル: test_opb.py プロジェクト: StephanGocht/cnfgen
 def test_one_leq(self):
     opb = """\
     * #variable= 5 #constraint= 1
     *
     -1 x1 -1 x2 -1 x3 -1 x4 -1 x5 >= -2;
     """
     F = CNF()
     F.add_less_or_equal(["a", "b", "c", "d", "e"], 2)
     self.assertCnfEqualsOPB(F, opb)
コード例 #3
0
def VertexCover(G, d):
    F = CNF()

    def D(v):
        return "x_{{{0}}}".format(v)

    def N(v):
        return tuple(sorted([e for e in G.edges(v)]))

    # Fix the vertex order
    V = enumerate_vertices(G)

    # Create variables
    for v in V:
        F.add_variable(D(v))

    # Not too many true variables
    F.add_less_or_equal([D(v) for v in V], d)

    # Every edge must have a true D variable
    for e in G.edges():
        F.add_clause([(True, D(v)) for v in e])

    return F
コード例 #4
0
def DominatingSetOPB(G,d,tiling,seed):
    F=CNF()

    def D(v):
        return "x_{{{0}}}".format(v)

    def N(v):
        return tuple(sorted([ v ] + [ u for u in G.neighbors(v) ]))

    # Fix the vertex order
    V=enumerate_vertices(G)

    #avgdegree=sum(len(set(N(v))) for v in V)/len(V)
    #d=len(V)/(avgdegree+1)
    
    # Create variables
    for v in V:
        F.add_variable(D(v))

    # Not too many true variables
    if not tiling:
        F.add_less_or_equal([D(v) for v in V],d)

    # Every neighborhood must have a true D variable
    neighborhoods = sorted( set(N(v) for v in V) )
    for N in neighborhoods:
        if tiling:
            F.add_equal_to([D(v) for v in N], 1)
        else:
            F.add_clause([(True,D(v)) for v in N])

    # Set some vertex to true
    if seed:
        F.add_clause([(True,D(V[0]))])
        
    return F
コード例 #5
0
ファイル: vertexcover.py プロジェクト: marcvinyals/cnfgen
def VertexCover(G,d):
    F=CNF()

    def D(v):
        return "x_{{{0}}}".format(v)

    def N(v):
        return tuple(sorted([ e for e in G.edges(v) ]))

    # Fix the vertex order
    V=enumerate_vertices(G)

    # Create variables
    for v in V:
        F.add_variable(D(v))

    # Not too many true variables
    F.add_less_or_equal([D(v) for v in V],d)

    # Every edge must have a true D variable
    for e in G.edges():
        F.add_clause([ (True,D(v)) for v in e])
        
    return F
コード例 #6
0
ファイル: dominatingset.py プロジェクト: marcvinyals/cnfgen
def DominatingSet(G,d, alternative = False):
    r"""Generates the clauses for a dominating set for G of size <= d

    The formula encodes the fact that the graph :math:`G` has
    a dominating set of size :math:`d`. This means that it is possible
    to pick at most :math:`d` vertices in :math:`V(G)` so that all remaining
    vertices have distance at most one from the selected ones.

    Parameters
    ----------
    G : networkx.Graph
        a simple undirected graph
    d : a positive int
        the size limit for the dominating set
    alternative : bool
        use an alternative construction that 
        is provably hard from resolution proofs.

    Returns
    -------
    CNF
       the CNF encoding for dominating of size :math:`\leq d` for graph :math:`G`

    """
    F=CNF()

    if not isinstance(d,int) or d<1:
        ValueError("Parameter \"d\" is expected to be a positive integer")
    
    # Describe the formula
    name="{}-dominating set".format(d)
    
    if hasattr(G,'name'):
        F.header=name+" of graph:\n"+G.name+".\n\n"+F.header
    else:
        F.header=name+".\n\n"+F.header

    # Fix the vertex order
    V=enumerate_vertices(G)
    

    def D(v):
        return "x_{{{0}}}".format(v)

    def M(v,i):
        return "g_{{{0},{1}}}".format(v,i)

    def N(v):
        return tuple(sorted([ v ] + [ u for u in G.neighbors(v) ]))
    
    # Create variables
    for v in V:
        F.add_variable(D(v))
    for i,v in product(range(1,d+1),V):
        F.add_variable(M(v,i))
    
    # No two (active) vertices map to the same index
    if alternative:
        for u,v in combinations(V,2):
            for i in range(1,d+1):
                F.add_clause( [ (False,D(u)),(False,D(v)), (False,M(u,i)), (False,M(v,i))    ])
    else:
        for i in range(1,d+1):
            F.add_less_or_equal([M(v,i) for v in V],1)
                
    # (Active) Vertices in the sequence are not repeated
    if alternative:
        for v in V:
            for i,j in combinations(range(1,d+1),2):
                F.add_clause([(False,D(v)),(False,M(v,i)),(False,M(v,j))])
    else:
        for i,j in combinations_with_replacement(range(1,d+1),2):
            i,j = min(i,j),max(i,j)
            for u,v in combinations(V,2):
                u,v = max(u,v),min(u,v)
                F.add_clause([(False,M(u,i)),(False,M(v,j))])

    # D(v) = M(v,1) or M(v,2) or ... or M(v,d)        
    if not alternative:
        for i,v in product(range(1,d+1),V):
            F.add_clause([(False,M(v,i)),(True,D(v))])
    for v in V:
        F.add_clause([(False,D(v))] + [(True,M(v,i)) for i in range(1,d+1)])
    
        
    # Every neighborhood must have a true D variable
    neighborhoods = sorted( set(N(v) for v in V) )
    for N in neighborhoods:
        F.add_clause([ (True,D(v)) for v in N])
        
    return F
コード例 #7
0
ファイル: dominatingset.py プロジェクト: StephanGocht/cnfgen
def DominatingSet(G, d, alternative=False):
    r"""Generates the clauses for a dominating set for G of size <= d

    The formula encodes the fact that the graph :math:`G` has
    a dominating set of size :math:`d`. This means that it is possible
    to pick at most :math:`d` vertices in :math:`V(G)` so that all remaining
    vertices have distance at most one from the selected ones.

    Parameters
    ----------
    G : networkx.Graph
        a simple undirected graph
    d : a positive int
        the size limit for the dominating set
    alternative : bool
        use an alternative construction that 
        is provably hard from resolution proofs.

    Returns
    -------
    CNF
       the CNF encoding for dominating of size :math:`\leq d` for graph :math:`G`

    """
    F = CNF()

    if not isinstance(d, int) or d < 1:
        ValueError("Parameter \"d\" is expected to be a positive integer")

    # Describe the formula
    name = "{}-dominating set".format(d)

    if hasattr(G, 'name'):
        F.header = name + " of graph:\n" + G.name + ".\n\n" + F.header
    else:
        F.header = name + ".\n\n" + F.header

    # Fix the vertex order
    V = enumerate_vertices(G)

    def D(v):
        return "x_{{{0}}}".format(v)

    def M(v, i):
        return "g_{{{0},{1}}}".format(v, i)

    def N(v):
        return tuple(sorted([v] + [u for u in G.neighbors(v)]))

    # Create variables
    for v in V:
        F.add_variable(D(v))
    for i, v in product(list(range(1, d + 1)), V):
        F.add_variable(M(v, i))

    # No two (active) vertices map to the same index
    if alternative:
        for u, v in combinations(V, 2):
            for i in range(1, d + 1):
                F.add_clause([(False, D(u)), (False, D(v)), (False, M(u, i)),
                              (False, M(v, i))])
    else:
        for i in range(1, d + 1):
            F.add_less_or_equal([M(v, i) for v in V], 1)

    # (Active) Vertices in the sequence are not repeated
    if alternative:
        for v in V:
            for i, j in combinations(list(range(1, d + 1)), 2):
                F.add_clause([(False, D(v)), (False, M(v, i)), (False, M(v,
                                                                         j))])
    else:
        for i, j in combinations_with_replacement(list(range(1, d + 1)), 2):
            i, j = min(i, j), max(i, j)
            for u, v in combinations(V, 2):
                u, v = max(u, v), min(u, v)
                F.add_clause([(False, M(u, i)), (False, M(v, j))])

    # D(v) = M(v,1) or M(v,2) or ... or M(v,d)
    if not alternative:
        for i, v in product(list(range(1, d + 1)), V):
            F.add_clause([(False, M(v, i)), (True, D(v))])
    for v in V:
        F.add_clause([(False, D(v))] + [(True, M(v, i))
                                        for i in range(1, d + 1)])

    # Every neighborhood must have a true D variable
    neighborhoods = sorted(set(N(v) for v in V))
    for N in neighborhoods:
        F.add_clause([(True, D(v)) for v in N])

    return F