Ejemplo n.º 1
0
def ExtendedEvenColoringFormula(G,T):
    F = EvenColoringFormula(G)
    F.mode_strict()

    def var_name(u,v,c):
        if u<=v:
            return '{2}_{{{0},{1}}}'.format(u,v,c)
        else:
            return '{2}_{{{0},{1}}}'.format(v,u,c)

    true_vars = [var_name(u,v,'t') for (u,v) in enumerate_edges(G)]
    false_vars = [var_name(u,v,'f') for (u,v) in enumerate_edges(G)]

    for var in true_vars:
        F.add_variable(var)
    for var in false_vars:
        F.add_variable(var)

    for (u, v) in enumerate_edges(G):
        F.add_clause([(True,var_name(u,v,'t')),
                      (False,var_name(u,v,'x'))])
        F.add_clause([(True,var_name(u,v,'f')),
                      (True,var_name(u,v,'x'))])

    F.add_linear(*chain(*[(3,var) for var in true_vars] +
                         [(1,var) for var in false_vars] + [("<=", T)]))

    return F
Ejemplo n.º 2
0
def ExtendedEvenColoringFormula(G, T):
    F = EvenColoringFormula(G)
    F.mode_strict()

    def var_name(u, v, c):
        if u <= v:
            return '{2}_{{{0},{1}}}'.format(u, v, c)
        else:
            return '{2}_{{{0},{1}}}'.format(v, u, c)

    true_vars = [var_name(u, v, 't') for (u, v) in enumerate_edges(G)]
    false_vars = [var_name(u, v, 'f') for (u, v) in enumerate_edges(G)]

    for var in true_vars:
        F.add_variable(var)
    for var in false_vars:
        F.add_variable(var)

    for (u, v) in enumerate_edges(G):
        F.add_clause([(True, var_name(u, v, 't')), (False, var_name(u, v,
                                                                    'x'))])
        F.add_clause([(True, var_name(u, v, 'f')), (True, var_name(u, v,
                                                                   'x'))])

    F.add_linear(*chain(*[(3, var) for var in true_vars] +
                        [(1, var) for var in false_vars] + [("<=", T)]))

    return F
Ejemplo n.º 3
0
def EvenColoringFormula(G):
    """Even coloring formula

    The formula is defined on a graph :math:`G` and claims that it is
    possible to split the edges of the graph in two parts, so that
    each vertex has an equal number of incident edges in each part.

    The formula is defined on graphs where all vertices have even
    degree. The formula is satisfiable only on those graphs with an
    even number of vertices in each connected component [1]_.

    Arguments
    ---------
    G : networkx.Graph 
       a simple undirected graph where all vertices have even degree

    Raises
    ------
    ValueError
       if the graph in input has a vertex with odd degree

    Returns
    -------
    CNF object

    References
    ----------
    .. [1] Locality and Hard SAT-instances, Klas Markstrom
       Journal on Satisfiability, Boolean Modeling and Computation 2 (2006) 221-228

    """
    F = CNF()
    F.mode_strict()
    F.header = "Even coloring formula on graph " + G.name + "\n" + F.header

    def var_name(u, v):
        if u <= v:
            return 'x_{{{0},{1}}}'.format(u, v)
        else:
            return 'x_{{{0},{1}}}'.format(v, u)

    for (u, v) in enumerate_edges(G):
        F.add_variable(var_name(u, v))

    # Defined on both side
    for v in enumerate_vertices(G):

        if G.degree(v) % 2 == 1:
            raise ValueError(
                "Markstrom formulas requires all vertices to have even degree."
            )

        edge_vars = [var_name(u, v) for u in neighbors(G, v)]

        # F.add_exactly_half_floor would work the same
        F.add_exactly_half_ceil(edge_vars)

    return F
Ejemplo n.º 4
0
def EvenColoringFormula(G):
    """Even coloring formula

    The formula is defined on a graph :math:`G` and claims that it is
    possible to split the edges of the graph in two parts, so that
    each vertex has an equal number of incident edges in each part.

    The formula is defined on graphs where all vertices have even
    degree. The formula is satisfiable only on those graphs with an
    even number of vertices in each connected component [1]_.

    Arguments
    ---------
    G : networkx.Graph 
       a simple undirected graph where all vertices have even degree

    Raises
    ------
    ValueError
       if the graph in input has a vertex with odd degree

    Returns
    -------
    CNF object

    References
    ----------
    .. [1] Locality and Hard SAT-instances, Klas Markstrom
       Journal on Satisfiability, Boolean Modeling and Computation 2 (2006) 221-228

    """
    F = CNF()
    F.header = "Even coloring formula on graph " + G.name + "\n" + F.header

    def var_name(u,v):
        if u<=v:
            return 'x_{{{0},{1}}}'.format(u,v)
        else:
            return 'x_{{{0},{1}}}'.format(v,u)
    
    for (u, v) in enumerate_edges(G):
        F.add_variable(var_name(u, v))

    # Defined on both side
    for v in enumerate_vertices(G):

        if G.degree(v) % 2 == 1:
            raise ValueError("Markstrom formulas requires all vertices to have even degree.")

        edge_vars = [ var_name(u,v) for u in neighbors(G,v) ]
        
        for cls in CNF.equal_to_constraint(edge_vars,
                                           len(edge_vars)/2):
            F.add_clause(cls,strict=True)

    return F
Ejemplo n.º 5
0
def GraphColoringFormula(G,colors,functional=True):
    """Generates the clauses for colorability formula

    The formula encodes the fact that the graph :math:`G` has a coloring
    with color set ``colors``. This means that it is possible to
    assign one among the elements in ``colors``to that each vertex of
    the graph such that no two adjacent vertices get the same color.

    Parameters
    ----------
    G : networkx.Graph
        a simple undirected graph
    colors : list or positive int
        a list of colors or a number of colors

    Returns
    -------
    CNF
       the CNF encoding of the coloring problem on graph ``G``

    """
    col=CNF()
    col.mode_strict()

    if isinstance(colors,int) and colors>=0:
        colors = range(1,colors+1)
    
    if not isinstance(list, collections.Iterable):
        ValueError("Parameter \"colors\" is expected to be a iterable")
    
    # Describe the formula
    name="graph colorability"
    
    if hasattr(G,'name'):
        col.header=name+" of graph:\n"+G.name+".\n\n"+col.header
    else:
        col.header=name+".\n\n"+col.header

    # Fix the vertex order
    V=enumerate_vertices(G)

    # Create the variables
    for vertex in V:
        for color in colors:
            col.add_variable('x_{{{0},{1}}}'.format(vertex,color))
        
    # Each vertex has a color
    for vertex in V:
        clause = []
        for color in colors:
            clause += [(True,'x_{{{0},{1}}}'.format(vertex,color))]
        col.add_clause(clause)
        
        # unique color per vertex
        if functional:
            for (c1,c2) in combinations(colors,2):
                col.add_clause([
                    (False,'x_{{{0},{1}}}'.format(vertex,c1)),
                    (False,'x_{{{0},{1}}}'.format(vertex,c2))])

    # This is a legal coloring
    for (v1,v2) in enumerate_edges(G):
        for c in colors:
            col.add_clause([
                (False,'x_{{{0},{1}}}'.format(v1,c)),
                (False,'x_{{{0},{1}}}'.format(v2,c))])
            
    return col
Ejemplo n.º 6
0
def VertexCover(G,k, alternative = False):
    r"""Generates the clauses for a vertex cover for G of size <= k

    Parameters
    ----------
    G : networkx.Graph
        a simple undirected graph
    k : a positive int
        the size limit for the vertex cover

    Returns
    -------
    CNF
       the CNF encoding for vertex cover of size :math:`\leq k` for graph :math:`G`

    """
    F=CNF()

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

    # Describe the formula
    name="{}-vertex cover".format(k)

    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)
    E=enumerate_edges(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,k+1),V):
        F.add_variable(M(v,i))

    # No two (active) vertices map to the same index
    for i in range(1,k+1):
        for c in CNF.less_or_equal_constraint([M(v,i) for v in V],1):
            F.add_clause(c)

    # (Active) Vertices in the sequence are not repeated
    for i,j in combinations_with_replacement(range(1,k+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,k)
    for i,v in product(range(1,k+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,k+1)])

    # Every neighborhood must have a true D variable
    for v1,v2 in E:
        F.add_clause([(True,D(v1)), (True,D(v2))])

    return F
Ejemplo n.º 7
0
def GraphColoringFormula(G, colors, functional=True):
    """Generates the clauses for colorability formula

    The formula encodes the fact that the graph :math:`G` has a coloring
    with color set ``colors``. This means that it is possible to
    assign one among the elements in ``colors``to that each vertex of
    the graph such that no two adjacent vertices get the same color.

    Parameters
    ----------
    G : networkx.Graph
        a simple undirected graph
    colors : list or positive int
        a list of colors or a number of colors

    Returns
    -------
    CNF
       the CNF encoding of the coloring problem on graph ``G``

    """
    col = CNF()

    if isinstance(colors, int) and colors >= 0:
        colors = range(1, colors + 1)

    if not isinstance(list, collections.Iterable):
        ValueError("Parameter \"colors\" is expected to be a iterable")

    # Describe the formula
    name = "graph colorability"

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

    # Fix the vertex order
    V = enumerate_vertices(G)

    # Each vertex has a color
    for vertex in V:
        clause = []
        for color in colors:
            clause += [(True, 'x_{{{0},{1}}}'.format(vertex, color))]
        col.add_clause(clause)

        # unique color per vertex
        if functional:
            for (c1, c2) in combinations(colors, 2):
                col.add_clause([(False, 'x_{{{0},{1}}}'.format(vertex, c1)),
                                (False, 'x_{{{0},{1}}}'.format(vertex, c2))],
                               strict=True)

    # This is a legal coloring
    for (v1, v2) in enumerate_edges(G):
        for c in colors:
            col.add_clause([(False, 'x_{{{0},{1}}}'.format(v1, c)),
                            (False, 'x_{{{0},{1}}}'.format(v2, c))],
                           strict=True)

    return col