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
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_ceil(edge_vars) # F.add_exactly_half_floor would work the same return F
def SubsetCardinalityFormula(B, equalities=False): r"""SubsetCardinalityFormula Consider a bipartite graph :math:`B`. The CNF claims that at least half of the edges incident to each of the vertices on left side of :math:`B` must be zero, while at least half of the edges incident to each vertex on the left side must be one. Variants of these formula on specific families of bipartite graphs have been studied in [1]_, [2]_ and [3]_, and turned out to be difficult for resolution based SAT-solvers. Each variable of the formula is denoted as :math:`x_{i,j}` where :math:`\{i,j\}` is an edge of the bipartite graph. The clauses of the CNF encode the following constraints on the edge variables. For every left vertex i with neighborhood :math:`\Gamma(i)` .. math:: \sum_{j \in \Gamma(i)} x_{i,j} \geq \frac{|\Gamma(i)|}{2} For every right vertex j with neighborhood :math:`\Gamma(j)` .. math:: \sum_{i \in \Gamma(j)} x_{i,j} \leq \frac{|\Gamma(j)|}{2}. If the ``equalities`` flag is true, the constraints are instead represented by equations. .. math:: \sum_{j \in \Gamma(i)} x_{i,j} = \left\lceil \frac{|\Gamma(i)|}{2} \right\rceil .. math:: \sum_{i \in \Gamma(j)} x_{i,j} = \left\lfloor \frac{|\Gamma(j)|}{2} \right\rfloor . Parameters ---------- B : networkx.Graph the graph vertices must have the 'bipartite' attribute set. Left vertices must have it set to 0 and the right ones to 1. A KeyException is raised otherwise. equalities : boolean use equations instead of inequalities to express the cardinality constraints. (default: False) Returns ------- A CNF object References ---------- .. [1] Mladen Miksa and Jakob Nordstrom Long proofs of (seemingly) simple formulas Theory and Applications of Satisfiability Testing--SAT 2014 (2014) .. [2] Ivor Spence sgen1: A generator of small but difficult satisfiability benchmarks Journal of Experimental Algorithmics (2010) .. [3] Allen Van Gelder and Ivor Spence Zero-One Designs Produce Small Hard SAT Instances Theory and Applications of Satisfiability Testing--SAT 2010(2010) """ Left, Right = bipartite_sets(B) ssc = CNF() ssc.header = "Subset cardinality formula for graph {0}\n".format(B.name) ssc.mode_strict() def var_name(u, v): """Compute the variable names.""" if u <= v: return 'x_{{{0},{1}}}'.format(u, v) else: return 'x_{{{0},{1}}}'.format(v, u) for u in Left: for v in neighbors(B, u): ssc.add_variable(var_name(u, v)) for u in Left: edge_vars = [var_name(u, v) for v in neighbors(B, u)] if equalities: ssc.add_exactly_half_ceil(edge_vars) else: ssc.add_loose_majority(edge_vars) for v in Right: edge_vars = [var_name(u, v) for u in neighbors(B, v)] if equalities: ssc.add_exactly_half_floor(edge_vars) else: ssc.add_loose_minority(edge_vars) return ssc