Esempio n. 1
0
def is_satisfiable(e):
    formula = CNF()
    clauses, _, _ = _tseitin(e)
    for clause in clauses:
        formula.append(clause)
    with Lingeling(bootstrap_with=formula.clauses) as ling:
        return ling.solve()
Esempio n. 2
0
def reduce_board(size: int, rows: [[int]], cols: [[int]]):
    """Reduces the the description of a Nonogram puzzle to a CNF formula

    :param size: The number of cells in each row/column
    :param rows: The hints for each row
    :param cols: The hints for each column
    :return: A CNF object representing the board's possible solutions
    """
    clauses = []

    base = size * size
    for i, row in enumerate(rows):
        uvars = [j + (i * size) + 1 for j in range(size)]
        reduction = reduce_set(size, row, uvars, base)
        clauses += reduction.clauses
        base += len(reduction.auxvars)

    for i, col in enumerate(cols):
        uvars = [i + (j * size) + 1 for j in range(size)]
        reduction = reduce_set(size, col, uvars, base)
        clauses += reduction.clauses
        base += len(reduction.auxvars)

    cnf = CNF()
    for clause in clauses:
        cnf.append(clause)

    return cnf
Esempio n. 3
0
def sample_SR_aux(n, min_cls_len=1, p_binom=0.7, p_geo=0.4):
    """
  Args:
  n: positive integer

  Returns:
  A randomly-generated formula and a clause which makes the formula unsat

  This procedure has no guarantees on the number of clauses in the formula.

  Reference implementation in source code of NeuroSAT:
  https://github.com/dselsam/neurosat/blob/master/python/gen_sr_dimacs.py
  """
    result = CNF()
    with Solver(name="cdl") as S:
        while True:
            k = min_cls_len + np.random.binomial(
                n=1, p=p_binom) + np.random.geometric(p_geo)
            vs = np.random.choice(n, size=min(n, k), replace=False)
            vs = [
                int(v + 1) if random.random() < 0.5 else int(-(v + 1))
                for v in vs
            ]
            S.add_clause(vs)
            if S.solve():
                result.append(vs)
            else:
                break

    return result, vs
Esempio n. 4
0
def sample_SRC_aux(n, u1, c_idx, l_idx, p_geo=0.4, p_binom=0.7):
    """
  Args:
  n: positive integer
  u1: an unsat core
  c_idx: a clause index
  l_idx: a literal index
  
  u1 must become sat if the literal at (c_idx, l_idx) is flipped.

  Note that if result, vs = sample_SR_aux(args...), then result + vs is a valid argument for u1

  Returns: a random formula drawn from n variables containing u1 as an unsat core, and the unsat core
  """
    result = CNF()
    u2 = u1.copy()
    u2.clauses[c_idx][l_idx] = -u2.clauses[c_idx][l_idx]
    with Solver(name="cdl") as S:
        while True:
            S.append_formula(u2)
            k = 1 + np.random.binomial(n=1,
                                       p=p_binom) + np.random.geometric(p_geo)
            vs = np.random.choice(n, size=min(n, k), replace=False)
            vs = [
                int(v + 1) if random.random() < 0.5 else int(-(v + 1))
                for v in vs
            ]
            S.add_clause(vs)
            if S.solve():
                result.append(vs)
            else:
                break
        for cls in u1.clauses:
            result.append(cls)
    return result, u1  # TODO(jesse): output a core clause mask
Esempio n. 5
0
def solve_sudoku_SAT(sudoku, k):
    #############
    # this solution is adjusted from https://github.com/taufanardi/sudoku-sat-solver/blob/master/Sudoku.py
    # what I have done differently:
    # 1. Adjusted so that it can generate to k-sized problem, not just hardcoded k=3 in the original post
    # 2. Refactored the code to make it more readable and splitted into smaller functions instead of chunk of code
    # 3. Rewrited the `add_distinct_clauses` code to make it more robust and easy to understand
    #############
    # make clauses
    clauses = create_clauses(sudoku, k)
    # append clauses to formula
    formula = CNF()
    for c in clauses:
        formula.append(c)
    # solve the SAT problem
    solver = MinisatGH()
    solver.append_formula(formula)
    answer = solver.solve()
    if not answer:
        return None
    # get the solution
    solution = solver.get_model()
    # reformat the solution into a suduko representation
    for i in range(1, k**2 + 1):
        for j in range(1, k**2 + 1):
            sudoku[i - 1][j - 1] = extract_digit_from_solution(
                i, j, solution, k)
    return sudoku
Esempio n. 6
0
def resolver(passo: int,
             conjuntoVertices: bool = False,
             ordemVertices: bool = True):
    """Resolve o caminho eureliano do grafo.

	:param passo: Recebe um array contendo os primeiros passos de cada possível começo do problema
	:param conjuntoVertices: Exibir o uma lista fora de ordem com o conjunto dos vértices que resolvem o problema. (Default value = False)
	:param ordemVertices: Exibir o caminho pelos vértices a ser percorrido para resolver o problema. (Default value = True)

 	"""
    formula = CNF()
    g = Glucose4()
    getClausulas(matriz, formula)
    formula.append([passo])
    g.append_formula(formula)
    print(
        f'O passo inicial para prova é: \33[32m{passo}\33[m, o caminho com ele é \33[34m{g.solve()}\33[m'
    )
    model = g.get_model()
    if model:
        valoracaoValida = valoresValidos(model)
        print(f'Passos válidos: \33[35m{valoracaoValida}\33[m')
        if conjuntoVertices:
            print(
                f'Esse são os conjuntos de vértices usados (fora de ordem): \33[36m{caminhosUsados(model)}\33[m'
            )
        if ordemVertices:
            print(f"Ordem de passagem pelos vértices: ")
            printEmOrdem(valoracaoValida)
    print()
Esempio n. 7
0
def unsat_core_example():
    fmla = CNF()
    fmla.append([1, 2, 3])
    fmla.append([-1, 2, 3])
    fmla.append([2, -3])
    fmla.append([-2, -3])
    fmla.append([-2, 3])
    return fmla
def validate_get_unsat_core_pysat(fmla, result, bad_asms):
    core = CNF(from_clauses=[fmla.clauses[i] for i in result])
    for asm in bad_asms:
        core.append([asm])
    with Solver(name="cdl") as S:
        S.append_formula(core)
        assert S.solve() is False
        print("ok")
 def _mk_iter(self):
     for _ in range(self.num_subproblems):
         fmla = CNF()
         fmla.from_file(self.cnf_path)
         new_units = random.sample(list(range(1, fmla.nv + 1)),
                                   k=self.random_units)
         new_units = [[random.choice([1, -1]) * x] for x in new_units]
         for unit_clause in new_units:
             fmla.append(unit_clause)
         yield fmla
Esempio n. 10
0
def TT_check_all_pysat(KB: 'ClauseTheory', a: 'AtomSet', symbols: 'AtomSet',
                       model: 'AtomSet'):
    formula = CNF()
    for clause in KB:
        arr = []
        arr.extend(clause.get_positive().get_atoms())
        arr.extend(map(lambda x: -x, clause.get_negative().get_atoms()))
        formula.append(arr)
    assumptions = []
    assumptions.extend(model)
    formula.append(list(map(lambda x: -x, a)))
    with Glucose4(bootstrap_with=formula.clauses) as g:
        return not g.solve(assumptions=assumptions)
Esempio n. 11
0
def reduce_set(cells: int, blocks: [int], uvars: [int], nbase: int):
    """Produces a CNF-represented DNF which holds all the possible combinations for a row/col

    :param cells: The length of the row/col
    :param blocks: The hints for this row/col
    :param uvars: The literals to use for variables in this clause
    :param nbase: The base index for the auxiliary variables
    """
    combos = []

    if sum(blocks) + (len(blocks) - 1) > cells:
        raise Exception("The passed block values exceeded the number of cells")

    ogcombo = []
    acc = 0
    for block in blocks:
        ogcombo.append(acc)
        acc += block + 1

    combos.append(ogcombo)

    ccombo = ogcombo.copy()

    lookat = len(blocks) - 1
    while lookat >= 0:
        if blocks[-1] + ccombo[-1] < cells:
            ccombo[lookat] = ccombo[lookat] + 1
            s = ccombo[lookat] + blocks[lookat] + 1
            for i in range(lookat + 1, len(blocks)):
                ccombo[i] = s
                s += blocks[i] + 1
            lookat = len(blocks) - 1
            combos.append(ccombo.copy())
        else:
            lookat -= 1
            s = ccombo[lookat] + blocks[lookat] + 1
            for i in range(lookat + 1, len(blocks)):
                ccombo[i] = s
                s += blocks[i] + 1

    cnf = CNF()
    for combo in combos:
        clause = [
            -v if in_combo(i, combo, blocks) else v
            for i, v in zip(range(cells), uvars)
        ]
        cnf.append(clause)

    return cnf.negate(nbase)
def validate_deserialized_TFDC(tfdc):
    def decode_l_idx(k):
        n_vars = tf.cast(tfdc.n_vars, dtype="int32")
        if k + 1 > n_vars:
            return -(k + 1 - n_vars)
        else:
            return k + 1

    fmla = CNF_of_TFDC(tfdc)

    core = CNF()
    for i in range(len(tfdc.core_clause_mask)):
        if (tfdc.core_clause_mask[i]) == True:
            core.append(fmla.clauses[i])

    core.to_fp(sys.stdout)
    print("")
    print("%%%%%%%% FORMULA %%%%%%%%")
    print("")
    fmla.to_fp(sys.stdout)

    with Solver(name="cdl") as S:
        S.append_formula(core)
        assert S.solve() is False

    with Solver(name="cdl") as S:
        S.append_formula(fmla)
        assert S.solve() is False

    # all variables in the core_var_mask are in the core
    for i in range(len(tfdc.core_var_mask)):
        if tfdc.core_var_mask[i] == True:
            var = i + 1
            flag = False
            for cls in core.clauses:
                for lit in cls:
                    if abs(lit) == var:
                        flag = True
            assert flag

    # all variables in the core are in the core_var_mask
    for cls in core.clauses:
        for lit in cls:
            l_idx = abs(lit) - 1
            assert tfdc.core_var_mask[l_idx] == True

    print("ok")
Esempio n. 13
0
def consistencyCheck(AC, solver, difficulty):
    if solver == "Sat4j":
        f = tempfile.NamedTemporaryFile()
        cnf = CNF()
        for clause in AC:  #AC es conjunto de conjuntos
            #      print(clause[1])
            cnf.append(clause[1])  #añadimos la constraint
        cnf.to_file(f.name)
        starttime = time.time()
        out = os.popen("java -jar org.sat4j.core.jar " + f.name).read()
        f.close()
        reqtime = time.time() - starttime
        time.sleep(reqtime * difficulty)
        if "UNSATISFIABLE" in out:
            #            print("===> AC: " + str(AC) + " - False")
            return False
        else:
            #           print("===> AC: " + str(AC) + " - True")
            return True

    elif solver == "Glucose3":
        g = Glucose3()
        for clause in AC:  #AC es conjunto de conjuntos
            g.add_clause(clause[1])  #añadimos la constraint
        starttime = time.time()
        sol = g.solve()
        reqtime = time.time() - starttime
        time.sleep(reqtime * difficulty)
        return sol
    elif solver == "Choco4":
        f = tempfile.NamedTemporaryFile()
        cnf = CNF()
        for clause in AC:  #AC es conjunto de conjuntos
            cnf.append(clause[1])  #añadimos la constraint
        cnf.to_file(f.name)
        starttime = time.time()
        out = os.popen("java -jar choco4solver.jar " + f.name).read()
        f.close()
        reqtime = time.time() - starttime
        time.sleep(reqtime * difficulty)
        if "UNSATISFIABLE" in out:
            return False
        else:
            return True
    else:
        raise ValueError("Solver not defined")
Esempio n. 14
0
def reduce(x,sat_instance):
    
    sat_instance_reduced = CNF() # Creamos una instancia de la clase CNF donde se almacenaran las clausulas reducidas
    num_vars = sat_instance.nv # Obtenemos el numero de variables de la instancia a reducir
    new_clause_size = int(x) # Obtenemos el X del X-SAT que deseamos reducir
    
    for clause in sat_instance:
        
        clause_size = int(len(clause)) # Obtenemos el tamaño de la clausula en cada iteracion
         
        if new_clause_size == clause_size: # Si el tamaño de la clausula es igual al X-SAT que buscamos resumir entonces agregamos la misma clausula sin modificarla
            
            sat_instance_reduced.append(clause)
        else:
            if new_clause_size > clause_size: # Si el tamaño de X-SAT es mayor que el tamaño de la clausula actual, incrementamos
                
                sat_instance_reduced = increse_one_by_one(clause, num_vars, sat_instance_reduced, new_clause_size) # Reductor
                
                num_vars = sat_instance_reduced.nv
            
            elif new_clause_size < clause_size: # Si el tamaño de X-SAT es menor que el tamaño de la clausula actual, reducimos
                
                # Primero pasamos de SAT a 3-SAT
                num_vars = num_vars + 1 # Creamos la nueva variable positiva 
                
                # Creamos la primera clausula
                new_clause = []
                new_clause.append(clause[0])
                new_clause.append(clause[1])
                new_clause.append(num_vars)
                
                sat_instance_reduced.append(new_clause)
                
                # Creamos todas las clausulas intermedias 
                for i in range(2, clause_size-2, 1):
                    new_clause = []
                    neg_num_vars = num_vars * -1 # Creamos la nueva variable negativa
                    num_vars = num_vars + 1 # Creamos la nueva variable positiva 
                    new_clause.append(neg_num_vars)
                    new_clause.append(clause[i])
                    new_clause.append(num_vars)
                    sat_instance_reduced.append(new_clause)
                
                # Creamos la ultima clausula
                neg_num_vars = num_vars * -1 # Creamos la nueva variable negativa
                new_clause = []
                new_clause.append(neg_num_vars)
                new_clause.append(clause[-2])
                new_clause.append(clause[-1])
                sat_instance_reduced.append(new_clause)

                # Luego de tener todo en 3-SAT reducimos a X-SAT
                sat_instance_reduced = reduce(x, sat_instance_reduced)
                num_vars = sat_instance_reduced.nv
    
    return sat_instance_reduced
def validate_TFDC(tfdc):
    def decode_l_idx(k):
        n_vars = tf.cast(tfdc.n_vars, dtype="int32")
        if k + 1 > n_vars:
            return -(k + 1 - n_vars)
        else:
            return k + 1

    fmla = CNF()
    for _ in range(tfdc.n_clauses):
        fmla.append([])
    for edge in tfdc.CL_idxs:
        fmla.clauses[edge[0]].append(int(decode_l_idx(edge[1])))

    core = CNF()
    for i in range(len(tfdc.core_clause_mask)):
        if tfdc.core_clause_mask[i] == 1:
            core.append(fmla.clauses[i])

    with Solver(name="cdl") as S:
        S.append_formula(core)
        assert S.solve() is False

    with Solver(name="cdl") as S:
        S.append_formula(fmla)
        assert S.solve() is False

    # all variables in the core_var_mask are in the core
    for i in range(len(tfdc.core_var_mask)):
        if tfdc.core_var_mask[i] == 1:
            var = i + 1
            flag = False
            for cls in core.clauses:
                for lit in cls:
                    if abs(lit) == var:
                        flag = True
            assert flag

    # all variables in the core are in the core_var_mask
    for cls in core.clauses:
        for lit in cls:
            l_idx = abs(lit) - 1
            assert tfdc.core_var_mask[l_idx] == 1

    print("ok")
def solve_sudoku_SAT(sudoku, k):
    num_vertices = k ** 4
    vertices, edges = make_sudoku_graph(k)

    number_colors = k ** 2
    formula = CNF()

    # Assign a positive integer for each propositional variable.
    def var_number(i, c):
        return ((i - 1) * number_colors) + c

    flatten_sudoku = np.array(sudoku).reshape(num_vertices)

    # Clause that ensures that each vertex there is one value.
    for i in range(1, num_vertices + 1):
        clause = []

        sudoku_value = int(flatten_sudoku[i - 1])
        not_assigned = sudoku_value == 0

        if not_assigned:
            for c in range(1, number_colors + 1):
                clause.append(var_number(i, c))
        else:
            clause.append(var_number(i, sudoku_value))

        formula.append(clause)

    # Ensure that only one value is assigned.
    for i in range(1, num_vertices + 1):
        for c1 in range(1, number_colors + 1):
            for c2 in range(c1 + 1, number_colors + 1):
                clause = [-1 * var_number(i, c1), -1 * var_number(i, c2)]
                formula.append(clause)

    # Ensure that the rules of sudoku are kept, no adjacent vertices should have the same color/value.
    for (v1, v2) in edges:
        for c in range(1, number_colors + 1):
            clause = [-1 * var_number(v1, c), -1 * var_number(v2, c)]
            formula.append(clause)

    solver = MinisatGH()
    solver.append_formula(formula)
    answer = solver.solve()

    flatten_vertices = np.array(vertices).reshape(num_vertices)

    if answer:
        print("The sudoku is solved.")
        model = solver.get_model()
        print(model)
        for i in range(1, num_vertices + 1):
            for c in range(1, number_colors + 1):
                if var_number(i, c) in model:
                    flatten_vertices[i - 1] = c

        return flatten_vertices.reshape(k**2, k**2).tolist()
    else:
        print("The sudoku has no solution.")
        return None
Esempio n. 17
0
class PySATModel(VariabilityModel):
    @staticmethod
    def get_extension() -> str:
        return 'pysat'

    def __init__(self) -> None:
        #self.r_cnf = CNF()  # ToDo: This should be avoid
        #self.ctc_cnf = CNF()  # ToDo: This should be avoid
        self._cnf = CNF()
        self.variables: dict[str, int] = {}  # feature's name -> id
        self.features: dict[int, str] = {}  # id -> feature's name

    def add_clause(self, clause: list[int]) -> None:
        #self.ctc_cnf.append(clause)
        self._cnf.append(clause)

    def get_all_clauses(self) -> CNF:
        #clauses = CNF()
        #clauses.extend(self.r_cnf.clauses)
        #clauses.extend(self.ctc_cnf.clauses)
        #return clauses
        return self._cnf
Esempio n. 18
0
def sat_to_dimacs_format(SATANSWERS):
    sat_answers = SATANSWERS
    nombre = "sat_dimacs_format_"
    answers_dimacs = []
    sat_cnf = CNF()
    ACTUAL_DIRECTORY = getcwd(
    )  # Get the current directory path (../SAT/Reductor)
    PARENT_DIRECTORY = sep.join(
        ACTUAL_DIRECTORY.split(sep)[1:-1])  # Get the parent directory (../SAT)
    PARENT_DIRECTORY = join(
        sep, PARENT_DIRECTORY)  # Apeend SO separator to access the folder
    X_SAT_directory = join(PARENT_DIRECTORY, "X-SAT")
    for index, answer in enumerate(SATANSWERS):
        num_archivo = str(index)
        nombre_res = nombre + num_archivo
        answer.pop(-1)
        for clause in answer:
            for index, variable in enumerate(clause):
                clause[index] = int(variable)
            sat_cnf.append(clause)
        sat_cnf.to_file(join(X_SAT_directory, nombre_res + ".cnf"))
        sat_cnf = CNF()
    return answers_dimacs
Esempio n. 19
0
def getClausulas(matriz: list[list], formula: CNF, lin: int = 0, col: int = 0):
    for col in range(len(matriz[lin])):
        for lin in range(len(matriz)):
            for auxCol in range(col + 1, len(matriz[lin])):
                formula.append([-matriz[lin][col], -matriz[lin][auxCol]])
            auxForm = [-matriz[lin][col]]
            for auxLin in range(len(matriz)):
                if auxLin != lin:
                    formula.append([-matriz[lin][col], -matriz[auxLin][col]])
                if arestas[lin][0] == arestas[auxLin][1] and arestas[lin][
                        1] == arestas[auxLin][0]:
                    negarLinha(matriz[lin][col], auxLin, col + 1, matriz,
                               formula)
                if arestas[lin][1] == arestas[auxLin][0] and col < len(
                        matriz[lin]) - 1:
                    auxForm.append(matriz[auxLin][col + 1])
            if len(auxForm) > 1:
                formula.append(auxForm)
Esempio n. 20
0
    def encode(self, label, nof_terms):
        """
            Encode the problem of computing a DS of size nof_terms.
        """

        self.nof_terms = nof_terms
        self.nof_samps = len(self.samps)

        enc = CNF()

        # constraint 2
        for j in range(1, self.nof_terms + 1):
            for r in range(1, self.nof_feats + 1):
                enc.append([self.pvar(j, r), self.nvar(j, r)])

        # constraint 3
        if len(self.labels) == 1:  # distinguish one class from all the others
            other_labels = set(self.samps.keys())
        else:  # distinguish the classes under question only
            other_labels = set(self.labels)
        other_labels.remove(label)
        other_labels = sorted(other_labels)
        for j in range(1, self.nof_terms + 1):
            for lb in other_labels:
                for q in self.samps[lb]:
                    cl = []
                    shift = 0
                    for r in range(1, self.nof_feats + 1):
                        if r - 1 in self.data.vmiss[q]:
                            # this feature is missing in q'th sample
                            cl.append(-self.pvar(j, r))
                            cl.append(-self.nvar(j, r))
                            shift += 1
                        else:
                            cl.append(-self.slvar(j, r, q, shift))

                    enc.append(cl)

        # constraint 4
        for j in range(1, self.nof_terms + 1):
            for q in self.samps[label]:
                shift = 0
                for r in range(1, self.nof_feats + 1):
                    if r - 1 in self.data.vmiss[q]:
                        # this feature is missing in q'th sample
                        enc.append([self.pvar(j, r), -self.crvar(j, q + 1)])
                        enc.append([self.nvar(j, r), -self.crvar(j, q + 1)])
                        shift += 1
                    else:
                        enc.append([
                            self.slvar(j, r, q, shift), -self.crvar(j, q + 1)
                        ])

        # symmetry breaking constraints
        if self.options.bsymm:
            self.add_bsymm(enc)

        # constraint 5
        if self.options.accuracy == 100.0:
            for q in self.samps[label]:
                enc.append([
                    self.crvar(j, q + 1) for j in range(1, self.nof_terms + 1)
                ])
        else:
            for q in self.samps[label]:
                cv = self.cvvar(q + 1)
                enc.append([-cv] + [
                    self.crvar(j, q + 1) for j in range(1, self.nof_terms + 1)
                ])

                for j in range(1, self.nof_terms + 1):
                    enc.append([-self.crvar(j, q + 1), cv])

            cnum = int(self.options.accuracy * len(self.samps[label]) / 100.0)
            al = CardEnc.atleast(
                [self.cvvar(q + 1) for q in self.samps[label]],
                bound=cnum,
                top_id=enc.nv,
                encoding=self.options.enc)
            if al:
                enc.extend(al.clauses)

        # at most one value can be chosen for a feature
        for feats in six.itervalues(self.ffmap.dir):
            if len(feats) > 2:
                for j in range(1, self.nof_terms + 1):
                    lits = [-self.pvar(j, r + 1)
                            for r in feats]  # atmost1 can be true
                    onev = CardEnc.atmost(lits,
                                          top_id=enc.nv,
                                          encoding=self.options.enc)
                    enc.extend(onev.clauses)

        # saving comments
        for j in range(1, self.nof_terms + 1):
            for r in range(1, self.nof_feats + 1):
                enc.comments.append('c p({0}, {1}) => v{2}'.format(
                    j, r, self.pvar(j, r)))
                enc.comments.append('c n({0}, {1}) => v{2}'.format(
                    j, r, self.nvar(j, r)))

            for q in range(len(self.data.samps)):
                enc.comments.append('c cr({0}, {1}) => v{2}'.format(
                    j, q + 1, self.crvar(j, q + 1)))

        for n, f in zip(self.data.names[:-1], self.data.feats[:-1]):
            for v in f:
                if self.data.fvmap.dir[(n, v)] > 0:
                    enc.comments.append('c {0} = {1} => positive'.format(n, v))
                else:
                    enc.comments.append('c {0} = {1} => negative'.format(n, v))

        return enc
Esempio n. 21
0
from pysat.formula import CNF
from pysat.solvers import Lingeling

formula = CNF()
formula.append([-1, 2])
formula.append([1, -2])
formula.append([-1, -2])
# formula.append([1, 2])

with Lingeling(bootstrap_with=formula.clauses, with_proof=True) as l:
    if l.solve() == False:
        print(l.get_proof())
Esempio n. 22
0
class ColSAT:
    def __init__(self, g=nx.Graph(), ncolors=10):

        self.ncolors = ncolors
        self.g = g.copy()
        self.cmap = ColMap(g, ncolors)

    def check_coloring(self):
        for n1, n2 in self.g.edges():
            if 'c' not in self.g.node[n1] or 'c' not in self.g.node[n2]:
                return False
            if self.g.node[n1]['c'] == self.g.node[n2]['c']:
                return False
        return True

    def apply_model(self):

        check = set()
        for var in self.model[self.model > 0]:
            node, color = self.cmap.dec(var)
            self.g.node[node]['c'] = color
            if (node, color) in check:
                raise Exception("Two colors for one node???")
            else:
                check.add((node, color))

        self.colored = self.check_coloring()

        if self.colored != self.solved:
            raise Exception("Something went wrong!")

        return self.colored

    def build_cnf(self):

        self.formula = CNF()
        colors = list(range(1, self.ncolors + 1))

        for n1, n2 in self.g.edges():
            for c in colors:
                self.formula.append(
                    [-self.cmap.enc(n1, c), -self.cmap.enc(n2, c)])

        #specials = [28, 194, 242, 355, 387, 397, 468]
        #ii = 1
        #for n in specials:
        #   self.formula.append([self.cmap.enc(n, ii)])
        #  ii += 1

        for n in self.g.nodes():
            #if not n in specials:
            self.formula.append([self.cmap.enc(n, c) for c in colors])
            for c1 in colors:
                for c2 in colors:
                    if c1 < c2:
                        self.formula.append(
                            [-self.cmap.enc(n, c1), -self.cmap.enc(n, c2)])

        return self.formula

    def solve_cnf(self, solver=''):

        triangle = find_triangle(self.g)
        assumptions = []
        if len(triangle) > 0:
            assumptions = [
                self.cmap.enc(triangle[0], 1),
                self.cmap.enc(triangle[1], 2),
                self.cmap.enc(triangle[2], 3)
            ]

        #Glucose3, Glucose4, Lingeling, MapleChrono, MapleCM, Maplesat, Minisat22, MinisatGH
        #with Glucose4(bootstrap_with=self.formula.clauses, with_proof=True) as ms:
        with Lingeling(bootstrap_with=self.formula.clauses) as ms:
            self.solved = ms.solve(assumptions=assumptions)
            if self.solved:
                self.model = np.array(ms.get_model())
                self.apply_model()
            else:
                self.proof = []  #ms.get_proof()
                self.colored = False

        return self.solved
Esempio n. 23
0
def solve_sudoku_SAT(sudoku, k):
    """
        I used the rules described in here 
        http://anytime.cs.umass.edu/aimath06/proceedings/P34.pdf
    """
    k2 = k**2
    N_propositionals = k2**3
    propositions = list(range(1, N_propositionals + 1))

    propositions = np.array(propositions).reshape((k2, k2, k2))
    rules = CNF()

    ## These rules add the values we know to be true
    for i, row in enumerate(sudoku):
        for j, item in enumerate(row):
            props = list(propositions[i, j])
            if item > 0:
                rules.append([int(props[item - 1])])

    ## first rule each entry has a value, if it is set, that value must be True
    for i, row in enumerate(sudoku):
        for j, item in enumerate(row):
            rules.append([int(item) for item in propositions[i, j, :]])

    ## second rule each row value appears once
    for y in range(k2):
        for z in range(k2):
            for x in range(k2 - 1):
                for i in range(x + 1, k2):
                    props = [propositions[x, y, z], propositions[i, y, z]]
                    rules.append([-int(item) for item in props])

    ## third rule each column value appears once
    for x in range(k2):
        for z in range(k2):
            for y in range(k2 - 1):
                for i in range(y + 1, k2):
                    props = [propositions[x, y, z], propositions[x, i, z]]
                    rules.append([-int(item) for item in props])

    ## fourth rule each 3x3 value appears once
    for z in range(k2):  # for all values
        for i in range(k):  # x block
            for j in range(k):  # y block
                for x in range(k):  # x place in block
                    for y in range(k):  # y place in block
                        for l in range(y + 1, k):  # for each
                            props = [
                                propositions[k * i + x, k * j + y, z],
                                propositions[k * i + x, k * j + l, z]
                            ]
                            rules.append([-int(item) for item in props])

                        for l in range(x + 1, k):
                            for m in range(0, k):
                                props = [
                                    propositions[k * i + x, k * j + y, z],
                                    propositions[k * i + l, k * j + m, z]
                                ]
                                rules.append([-int(item) for item in props])

    ## There is at most one number in each entry
    for y in range(k2):
        for x in range(k2):
            for z in range(k2 - 1):
                for i in range(z + 1, k2):
                    props = [propositions[x, y, z], propositions[x, y, i]]
                    rules.append([-int(item) for item in props])

    ## each number appears at least once in row and column and 3x3
    for y in range(k2):
        for z in range(k2):
            rules.append([int(item) for item in propositions[:, y, z]])

    for x in range(k2):
        for z in range(k2):
            rules.append([int(item) for item in propositions[x, :, z]])

    for i in range(k):  # x block
        for j in range(k):  # y block
            for x in range(k):  # x place in block
                for y in range(k):  # y place in block
                    rules.append([
                        int(item)
                        for item in propositions[k * i + x, k * j + y, :]
                    ])

    solver = MinisatGH()
    solver.append_formula(rules)
    answer = solver.solve()
    if answer == True:
        for i, lit in enumerate(solver.get_model()):
            if lit > 0:
                idx = lit - 1
                sudoku[(idx // k2) // k2][(idx // k2) % k2] = (idx % k2) + 1
    else:
        print("Did not find a model!")

    return sudoku
Esempio n. 24
0
            num_atoms = int(line.split()[-2])
        elif line[0] == 'c':
            continue
        else:
            l = list(map(int, line.split()[:-1]))
            clauses.append(l)
    return clauses, num_atoms


def dimacs_to_nnf(
    dimacs_path,
    nnf_path,
    c2d_path='./c2d_linux',
):
    import os
    r, output = subprocess.getstatusoutput(c2d_path + ' -in ' + dimacs_path)
    os.system('mv ' + dimacs_path + '.nnf' + ' ' + nnf_path)
    return output, r


if __name__ == "__main__":
    print(num2triple(triple2num(6, 53, 88)))

    print(box_prop([336, 489, 324, 458], [94, 175, 306, 590]))

    f1 = CNF()
    f1.append([-1, 2])

    print(f1.clauses)
    print(find(f1, 5))
Esempio n. 25
0
    def encode(self, label, nof_lits=1):
        """
            Encode the problem of computing a DS of size nof_lits.
        """

        self.nof_lits = nof_lits
        self.nof_samps = len(self.data.samps)
        self.nof_labls = len(self.labels)

        if len(self.labels) == 1:  # distinguish one class from all the others
            other_labels = set(self.samps.keys())
        else:  # distinguish the classes under question only
            other_labels = set(self.labels)
        other_labels.remove(label)
        other_labels = sorted(other_labels)

        for j in range(1, self.nof_lits + 1):
            for r in range(1, self.nof_feats + 2):
                self.feat(j, r)
        for j in range(1, self.nof_lits + 1):
            self.sign(j)
        for j in range(1, self.nof_lits + 1):
            self.leaf(j)

        enc = CNF()

        # exactly one feature per node (including class/label)
        for j in range(1, self.nof_lits + 1):
            feats = [self.feat(j, r) for r in range(1, self.nof_feats + 2)]
            one = CardEnc.equals(lits=feats,
                                 vpool=self.idpool,
                                 encoding=self.options.enc)
            enc.extend(one)

        # at most one class/label per node
        for j in range(1, self.nof_lits + 1):
            labels = [self.label(j, z) for z in self.labels]
            am1 = CardEnc.atmost(lits=labels,
                                 vpool=self.idpool,
                                 encoding=self.options.enc)
            enc.extend(am1)

            # the model is split,
            # i.e. we currently target only rules for this concrete class
            enc.append([self.label(j, label)])

        # leaf constraints
        enc.append([-self.leaf(1)])  # first node can't be a leaf
        enc.append([self.leaf(self.nof_lits)])  # last node should be a leaf

        # everything is reachable at node 1
        for lb in self.labels:
            for i in self.samps[lb]:
                enc.append([self.reached(1, i + 1)])

        # reachability propagation
        for j in range(1, self.nof_lits):
            for lb in self.labels:
                for i in self.samps[lb]:
                    aij = self.agree(j, i + 1)

                    cl, shift = [], 0
                    for r in range(1, self.nof_feats + 1):
                        if r - 1 in self.data.vmiss[i]:
                            # this feature is missing in i'th sample
                            shift += 1
                        else:
                            # a = self.agree(j, i + 1, r)  # node j agrees with sample i on feature r
                            f = self.feat(j, r)  # feature r decided in node j
                            s = self.sign(j)  # polarity of node j

                            if self.data.samps[i][r - 1 - shift] > 0:
                                a = self.sets1(j, r)
                                if a > enc.nv:
                                    enc.extend([[-a, f], [-a, s], [a, -f, -s]])
                            else:
                                a = self.sets0(j, r)
                                if a > enc.nv:
                                    enc.extend([[-a, f], [-a, -s], [a, -f, s]])

                            cl.append(a)

                    enc.append([-aij] + cl)
                    for l in cl:
                        enc.append([aij, -l])

                    cur = self.reached(j, i +
                                       1)  # node j is reachable for sample i
                    new = self.reached(j + 1, i +
                                       1)  # node j + 1 reachable for sample i

                    enc.append([-new, self.leaf(j), cur])
                    enc.append([-new, self.leaf(j), aij])
                    enc.append([new, -self.leaf(j)])
                    enc.append([new, -cur, -aij])

        # correctness of leafs
        for j in range(1, self.nof_lits + 1):
            for lb in self.labels:
                for i in self.samps[lb]:
                    enc.append([
                        -self.leaf(j), -self.reached(j, i + 1),
                        self.label(j, lb)
                    ])

        # coverage constraints
        for i in self.samps[label]:
            cl = []

            for j in range(1, self.nof_lits + 1):
                cvar = self.covered(j, i + 1)

                enc.append([-cvar, self.leaf(j)])
                enc.append([-cvar, self.reached(j, i + 1)])
                enc.append([cvar, -self.leaf(j), -self.reached(j, i + 1)])

                cl.append(cvar)

            enc.append(cl)

        # symmetry breaking
        if self.options.bsymm:
            self.add_bsymm(enc)

        for v, o in self.idpool.id2obj.items():
            enc.comments.append('c {0} <=> {1}'.format(o, v))

        return enc
Esempio n. 26
0
def make_formula(n_police, n_medics, n_rows, n_cols, n_time):
    states = {'U', 'H', 'S', 'I', 'Q'}
    variables = {}
    formula = CNF()
    var_pool = IDPool()
    for t in range(n_time):
        for r in range(n_rows):
            for c in range(n_cols):
                for s in states:
                    variables[(r, c), t,
                              s] = var_pool.id(f'({r}, {c}), {t}, {s}')
                variables[(r, c), t, 'P'] = var_pool.id(
                    f'({r}, {c}), {t}, P')  # Police were used
                variables[(r, c), t, 'M'] = var_pool.id(
                    f'({r}, {c}), {t}, M')  # Medics were used
                variables[(r, c), t, 'SS'] = var_pool.id(
                    f'({r}, {c}), {t}, SS')  # Stayed sick from last time
    for t in range(n_time):
        formula.extend(
            CardEnc.atmost([
                variables[(r, c), t, 'P'] for r in range(n_rows)
                for c in range(n_cols)
            ],
                           bound=n_police,
                           vpool=var_pool))
        formula.extend(
            CardEnc.atmost([
                variables[(r, c), t, 'M'] for r in range(n_rows)
                for c in range(n_cols)
            ],
                           bound=n_medics,
                           vpool=var_pool))
        for r in range(n_rows):
            for c in range(n_cols):
                formula.extend(
                    CardEnc.equals([variables[(r, c), t, s] for s in states],
                                   vpool=var_pool))
                if t > 0:
                    formula.extend(
                        req_equiv([
                            -variables[(r, c), t - 1, 'Q'], variables[(r, c),
                                                                      t, 'Q']
                        ], [variables[(r, c), t, 'P']]))
                    formula.extend(
                        req_equiv([
                            -variables[(r, c), t - 1, 'I'], variables[(r, c),
                                                                      t, 'I']
                        ], [variables[(r, c), t, 'M']]))
                    formula.extend(
                        req_equiv([
                            variables[(r, c), t - 1, 'S'], variables[(r, c), t,
                                                                     'S']
                        ], [variables[(r, c), t, 'SS']]))
                    nearby_sick_condition = []
                    for r_, c_ in nearby(r, c, n_rows, n_cols):
                        nearby_sick_condition.append(variables[(r_, c_), t,
                                                               'SS'])
                        formula.extend(
                            req_imply([
                                variables[(r, c), t, 'SS'],
                                variables[(r_, c_), t - 1, 'H']
                            ], [
                                variables[(r_, c_), t, 'S'],
                                variables[(r_, c_), t, 'I']
                            ]))
                        # formula.extend(req_imply([variables[(r, c), t, 'SS']], [-variables[(r_, c_), t, 'H']]))
                    formula.extend(
                        req_imply([
                            variables[(r, c), t - 1, 'H'], variables[(r, c), t,
                                                                     'S']
                        ], nearby_sick_condition))
                if t + 1 < n_time:
                    formula.extend(
                        req_equiv([variables[(r, c), t, 'U']],
                                  [variables[(r, c), t + 1, 'U']]))
                    formula.extend(
                        req_imply([variables[(r, c), t, 'I']],
                                  [variables[(r, c), t + 1, 'I']]))
                    formula.extend(
                        req_imply([variables[(r, c), t + 1, 'S']], [
                            variables[(r, c), t, 'S'], variables[(r, c), t,
                                                                 'H']
                        ]))
                    formula.extend(
                        req_imply([variables[(r, c), t + 1, 'Q']], [
                            variables[(r, c), t, 'Q'], variables[(r, c), t,
                                                                 'S']
                        ]))
                if t == 0:
                    formula.append([-variables[(r, c), t, 'Q']])
                    formula.append([-variables[(r, c), t, 'I']])
                    if t + 1 < n_time:
                        formula.extend(
                            req_imply([variables[(r, c), t, 'S']], [
                                variables[(r, c), t + 1, 'S'],
                                variables[(r, c), t + 1, 'Q']
                            ]))
                        formula.extend(
                            req_imply([variables[(r, c), t, 'Q']],
                                      [variables[(r, c), t + 1, 'Q']]))
                    if t + 2 < n_time:
                        formula.extend(
                            req_imply([
                                variables[(r, c), t, 'S'],
                                variables[(r, c), t + 1, 'S']
                            ], [
                                variables[(r, c), t + 2, 'S'],
                                variables[(r, c), t + 2, 'Q']
                            ]))
                        formula.extend(
                            req_imply([
                                variables[(r, c), t, 'S'],
                                variables[(r, c), t + 1, 'Q']
                            ], [variables[(r, c), t + 2, 'Q']]))
                        formula.extend(
                            req_imply([variables[(r, c), t, 'Q']],
                                      [variables[(r, c), t + 2, 'H']]))
                    if t + 3 < n_time:
                        formula.extend(
                            req_imply([
                                variables[(r, c), t,
                                          'S'], variables[(r, c), t + 1, 'S'],
                                variables[(r, c), t + 2, 'S']
                            ], [variables[(r, c), t + 3, 'H']]))
                if 0 < t and t + 1 < n_time:
                    formula.extend(
                        req_imply([
                            -variables[(r, c), t - 1, 'S'], variables[(r, c),
                                                                      t, 'S']
                        ], [
                            variables[(r, c), t + 1, 'S'],
                            variables[(r, c), t + 1, 'Q']
                        ]))
                    formula.extend(
                        req_imply([
                            -variables[(r, c), t - 1, 'Q'], variables[(r, c),
                                                                      t, 'Q']
                        ], [variables[(r, c), t + 1, 'Q']]))
                if 0 < t and t + 2 < n_time:
                    formula.extend(
                        req_imply([
                            -variables[(r, c), t - 1, 'S'],
                            variables[(r, c), t, 'S'], variables[(r, c), t + 1,
                                                                 'S']
                        ], [
                            variables[(r, c), t + 2, 'S'],
                            variables[(r, c), t + 2, 'Q']
                        ]))
                    formula.extend(
                        req_imply([
                            -variables[(r, c), t - 1, 'S'],
                            variables[(r, c), t, 'S'], variables[(r, c), t + 1,
                                                                 'Q']
                        ], [variables[(r, c), t + 2, 'Q']]))
                    formula.extend(
                        req_imply([
                            -variables[(r, c), t - 1, 'Q'], variables[(r, c),
                                                                      t, 'Q']
                        ], [variables[(r, c), t + 2, 'H']]))
                if 0 < t and t + 3 < n_time:
                    formula.extend(
                        req_imply([
                            -variables[(r, c), t - 1, 'S'], variables[(r, c),
                                                                      t, 'S'],
                            variables[(r, c), t + 1,
                                      'S'], variables[(r, c), t + 2, 'S']
                        ], [variables[(r, c), t + 3, 'H']]))
    return var_pool, formula
Esempio n. 27
0
def sample_SRC_aux_test3(core_min=20,
                         core_max=100,
                         ratio_min=5,
                         ratio_max=20,
                         n1=10,
                         n2=100):
    core_sizes = []
    ratios = []
    valid_count = 0
    num_rounds = 200
    with tempfile.TemporaryDirectory() as tmpdir:
        cnfdir = tmpdir + "/"
        cdl = cadical(cnf_dir=cnfdir)
        drat = drat_trim(cnf_dir=cnfdir)
        for _ in range(num_rounds):
            name = str(uuid.uuid4())
            fmla_unsat, fmla_sat, c_idx, l_idx = sample_SR(n1, 2, p_binom=0.3)
            with open(os.path.join(cnfdir, name + ".cnf"), "w") as f:
                fmla_unsat.to_fp(f)
            cdl.set_rootname(name)
            cdl.run()  # compute a proof of unsat for this formula
            cdl.process_output()
            assert cdl.result is False
            cdl.write_proof()

            drat.set_rootname(name)
            drat.run()  # extract an unsat core by calling DRAT-trim

            tsr = parse_drat(drat.opt_path, fmla_unsat.nv)
            var_lemma_counts = lemma_occ(tsr)
            var_del_counts = del_occ(tsr)

            masks = parse_core(drat.core_path, fmla_unsat.nv,
                               len(fmla_unsat.clauses))
            core_clause_mask = masks["core_clause_mask"]
            u = CNF(
            )  # this unsat core should still satisfy the property that it becomes sat if the sign of a single literal is flipped
            for i in range(len(core_clause_mask)):
                if core_clause_mask[i] == 1:
                    u.append(fmla_unsat.clauses[i])
            l_idx = u.clauses[-1].index(
                fmla_unsat.clauses[c_idx][l_idx]
            )  # get new l_idx since DRAT sometimes permutes literals inside clauses

            fmla_src, u = sample_SRC_aux(
                n2, u,
                len(u.clauses) - 1, l_idx
            )  # use this unsat core as the seed to a call to sample_SR_aux, and obtain fmla_src

            core_size = len(u.clauses)

            ratio = float(len(fmla_src.clauses) / core_size)

            core_sizes.append(core_size)
            ratios.append(ratio)

            if core_size <= core_max and core_min <= core_size and ratio <= ratio_max and ratio_min <= ratio:
                valid_count += 1
    print("max/min/mean core size:", np.max(core_sizes), np.min(core_sizes),
          np.mean(core_sizes))
    print("max/min/mean ratios:", np.max(ratios), np.min(ratios),
          np.mean(ratios))
    print("percent valid datapoints: ",
          str(float(valid_count / num_rounds) * 100) + "%")
Esempio n. 28
0
def solve_sudoku_SAT(sudoku, k):

    ### note: this solution assumes that we don't go over 2 digits in the size/numbers (so works up to 9*9 units)

    from pysat.formula import CNF
    from pysat.solvers import MinisatGH

    ## constraint id is calculated as follows: concatenate row num, col num and value, padded two 2 digits

    solver = MinisatGH()
    formula = CNF()

    ## Approach:
    ## We have variables for each possible value in each cell (so rowNum * colNum * potential_values = k*k * k*k * k*k)
    ## for each unit (row, co, box) we add a rule that at least one should be true (a or b or c or ...)
    ## than for each pair in a unit, we add that the two cannot be true at the same time (not a or not b)

    ## adding: one position can't take two values

    for rowInd in range(k * k):
        for colInd in range(k * k):
            for valOne in range(k * k - 1):
                for valTwo in range(valOne + 1, k * k):
                    formula.append([
                        -int(
                            pad_str(rowInd + 1) + pad_str(colInd + 1) +
                            pad_str(valOne + 1)), -int(
                                pad_str(rowInd + 1) + pad_str(colInd + 1) +
                                pad_str(valTwo + 1))
                    ])

    ## adding: row rules
    for rowInd in range(k * k):
        for possible_value in range(k * k):
            ## adding that one should be true
            formula.append([
                int(
                    pad_str(rowInd + 1) + pad_str(colInd + 1) +
                    pad_str(possible_value + 1)) for colInd in range(k * k)
            ])
            ## adding that two cannot be true
            for colIndOne in range(k * k - 1):
                for colIndTwo in range(colIndOne + 1, k * k):
                    formula.append([
                        -int(
                            pad_str(rowInd + 1) + pad_str(colIndOne + 1) +
                            pad_str(possible_value + 1)), -int(
                                pad_str(rowInd + 1) + pad_str(colIndTwo + 1) +
                                pad_str(possible_value + 1))
                    ])

    ## adding: col rules
    for colInd in range(k * k):
        for possible_value in range(k * k):
            ## adding that one should be true
            formula.append([
                int(
                    pad_str(rowInd + 1) + pad_str(colInd + 1) +
                    pad_str(possible_value + 1)) for rowInd in range(k * k)
            ])
            ## adding that two cannot be true
            for rowIndOne in range(k * k - 1):
                for rowIndTwo in range(rowIndOne + 1, k * k):
                    formula.append([
                        -int(
                            pad_str(rowIndOne + 1) + pad_str(colInd + 1) +
                            pad_str(possible_value + 1)), -int(
                                pad_str(rowIndTwo + 1) + pad_str(colInd + 1) +
                                pad_str(possible_value + 1))
                    ])

    ## adding: box rules
    for rowStart in range(0, k * k, k):
        for colStart in range(0, k * k, k):
            ## looping inside box
            for possible_value in range(k * k):

                ## adding that one should be true
                box_ids = []
                for rowInd in range(rowStart, rowStart + k):
                    for colInd in range(colStart, colStart + k):
                        box_ids.append(
                            int(
                                pad_str(rowInd + 1) + pad_str(colInd + 1) +
                                pad_str(possible_value + 1)))
                formula.append(box_ids)

                ## adding that two cannot be true
                for rowIndOne in range(rowStart, rowStart + k):
                    for colIndOne in range(colStart, colStart + k):
                        for rowIndTwo in range(rowIndOne, rowStart + k):
                            for colIndTwo in range(colIndOne, colStart + k):
                                if not (rowIndOne == rowIndTwo
                                        and colIndOne == colIndTwo):
                                    formula.append([
                                        -int(
                                            pad_str(rowIndOne + 1) +
                                            pad_str(colIndOne + 1) +
                                            pad_str(possible_value + 1)), -int(
                                                pad_str(rowIndTwo + 1) +
                                                pad_str(colIndTwo + 1) +
                                                pad_str(possible_value + 1))
                                    ])

    ## Adding the input values as literals
    for rowInd in range(k * k):
        for colInd in range(k * k):
            if sudoku[rowInd][colInd] != 0:
                formula.append([
                    int(
                        pad_str(rowInd + 1) + pad_str(colInd + 1) +
                        pad_str(sudoku[rowInd][colInd]))
                ])

    ## calling the solver
    solver.append_formula(formula)
    answer = solver.solve()
    if not answer:
        return None
    else:
        ### reconstruct sudoku from solution
        for lit in solver.get_model():
            if lit > 0:
                lit_split = [int(x) for x in str(lit)]
                ## appending leading zero if needed, since int conversion removes it
                if len(lit_split) < 6:
                    lit_split = [0] + lit_split
                print(lit_split)

                sudoku[10 * lit_split[0] + lit_split[1] -
                       1][10 * lit_split[2] + lit_split[3] -
                          1] = 10 * lit_split[4] + lit_split[5]
        return sudoku
Esempio n. 29
0
        yield l[i * k:(i + 1) * k]


V = list(group_by(N**2, list(group_by(N**2, V_flat))))

# Index of last solution variable (rest are added by cardinality encodings)
max_problem_var = nv

enc = EncType.ladder

# Encode constraints for each column
for i in range(N**2):
    for v in range(N**2):
        # Atleast-1 clause
        col = [V[i][j][v] for j in range(N**2)]
        F.append(col)
        # Atmost-1 encoding
        card = pysat.card.CardEnc.atmost(lits=col,
                                         top_id=nv,
                                         bound=1,
                                         encoding=enc)
        F.extend(card.clauses)
        nv = card.nv

# Encode constraints for each row
for j in range(N**2):
    for v in range(N**2):
        # Atleast-1 clause
        row = [V[i][j][v] for i in range(N**2)]
        F.append(row)
        # Atmost-1 encoding
Esempio n. 30
0
def gen_src_aux(core_min=20,
                core_max=100,
                ratio_min=5,
                ratio_max=20,
                n1=10,
                n2=100,
                min_cls_len=2,
                cnfdir=None):
    """
  Repeatedly samples formulas from SRC until it finds one which meets the specifications, then returns that formula.

  These parameters need to be tuned before running at scale to ensure that each call to this function rarely needs more than one iteration.

  Args:
  core_min: minimum size of the unsat core of the formula
  core_max: maximum size of the unsat core of the formula
  ratio_min: minimum ratio of formula-size to unsat-core-size
  ratio_max: maximum ratio of formula-size to unsat-core-size
  n1: `n` parameter passed to sample_SR when sampling the unsat core
  n2: `n` parameter passed to sample_SRC when sampling the larger formula containing the unsat core 

  Returns:
  A formula from SRC obeying the constraints given by `core_min`, `core_max`, `ratio_min`, and `ratio_max`.
  """
    # with tempfile.TemporaryDirectory() as cnfdir:
    cdl = cadical(cnf_dir=cnfdir)
    drat = drat_trim(cnf_dir=cnfdir)
    while True:
        name = str(uuid.uuid4())
        fmla_unsat, fmla_sat, c_idx, l_idx = sample_SR(n1,
                                                       min_cls_len,
                                                       p_binom=0.3)
        with open(os.path.join(cnfdir, name + ".cnf"), "w") as f:
            fmla_unsat.to_fp(f)
        cdl.set_rootname(name)
        cdl.run()  # compute a proof of unsat for this formula
        cdl.process_output()
        assert cdl.result is False
        cdl.write_proof()

        drat.set_rootname(name)
        drat.run()  # extract an unsat core by calling DRAT-trim

        tsr = parse_drat(drat.opt_path, fmla_unsat.nv)
        var_lemma_counts = lemma_occ(tsr)
        var_del_counts = del_occ(tsr)

        masks = parse_core(drat.core_path, fmla_unsat.nv,
                           len(fmla_unsat.clauses))
        core_clause_mask = masks["core_clause_mask"]
        u = CNF(
        )  # this unsat core should still satisfy the property that it becomes sat if the sign of a single literal is flipped
        for i in range(len(core_clause_mask)):
            if core_clause_mask[i] == 1:
                u.append(fmla_unsat.clauses[i])
        l_idx = u.clauses[-1].index(
            fmla_unsat.clauses[c_idx][l_idx]
        )  # get new l_idx since DRAT sometimes permutes literals inside clauses

        fmla_src, u = sample_SRC_aux(
            n2, u,
            len(u.clauses) - 1, l_idx
        )  # use this unsat core as the seed to a call to sample_SR_aux, and obtain fmla_src

        core_size = len(u.clauses)

        ratio = float(len(fmla_src.clauses) / core_size)

        # if fmla_src satisfies the constraints, return the TFDC
        if (ratio_min <= ratio and ratio <= ratio_max and core_min <= core_size
                and core_size <= core_max):
            break
        else:
            continue
    return fmla_src