class TestDump(unittest.TestCase):

    def setUp(self):
        self.solver = Solver()

    def test_max_glue_missing(self):
        self.assertRaises(TypeError,
                          self.solver.start_getting_small_clauses, 4)

    def test_one_dump(self):
        with open("tests/test.cnf", "r") as x:
            for line in x:
                line = line.strip()
                if "p" in line or "c" in line:
                    continue

                out = [int(x) for x in line.split()[:-1]]
                self.solver.add_clause(out)

        res, _ = self.solver.solve()
        self.assertEqual(res, True)

        self.solver.start_getting_small_clauses(4, max_glue=10)
        x = self.solver.get_next_small_clause()
        self.assertNotEquals(x, None)
        self.solver.end_getting_small_clauses()
Beispiel #2
0
def solve_trace(data,
                dropout=[False for i in range(176)],
                cfl=300000,
                wr_dropout=1.0):
    keyschedule = aes_key_schedule(10)
    weight_restrictions = restrict_hw_in_aes_ks_fuzzy(data,
                                                      dropout=dropout,
                                                      wr_dropout=wr_dropout)
    solver = Solver(confl_limit=cfl)
    for clause in keyschedule:
        solver.add_clause(clause)
    for clause in weight_restrictions:
        solver.add_clause(clause)
    print("Number of clauses: ",
          len(keyschedule) + len(weight_restrictions))
    sat, sol = 0, 1
    try:
        sat, sol = solver.solve()
    except:
        sat = None
    if (not sat):
        print("No success satisfying system.")
        return (False, None)
    #convert solution to keyschedule byte values
    byte_arr = np.array(
        [convert_to_byte(sol[i:i + 8]) for i in range(1, 176 * 8, 8)],
        dtype=np.uint8)
    return (True, byte_arr)
Beispiel #3
0
def obtain_labels(num_test_cases):
    row_solution = []
    num_sat = 0
    # Loop through the test cases
    for i in range(1, num_test_cases + 1):
        # Initialize the solver
        s = Solver()
        file = os.path.join(base_dir, f"test_case_{i}.cnf")
        # Obtain the CNF formula of the test case
        _, _, cnf = read_data(file)
        # Pass the CNF into the solver
        for row in cnf:
            s.add_clause(row)
        start = time.perf_counter()
        # Solve the CNF
        sat, _ = s.solve()
        # Obtain the number of satisfiable formulas
        if sat:
            num_sat += 1
        # Record time taken for single test case
        time_taken = time.perf_counter() - start
        # Store the results
        row_solution.append([i, sat, time_taken])
    # Save the results
    with open(os.path.join(base_dir, 'labels.csv'), 'w',
              newline='') as csvfile:
        spamwriter = csv.writer(csvfile,
                                delimiter=' ',
                                quotechar='|',
                                quoting=csv.QUOTE_MINIMAL)
        for row in row_solution:
            spamwriter.writerow(row)
    return num_sat
Beispiel #4
0
class TestDump(unittest.TestCase):
    def setUp(self):
        self.solver = Solver()

    def test_max_glue_missing(self):
        self.assertRaises(TypeError, self.solver.start_getting_small_clauses,
                          4)

    def test_one_dump(self):
        with open("tests/test.cnf", "r") as x:
            for line in x:
                line = line.strip()
                if "p" in line or "c" in line:
                    continue

                out = [int(x) for x in line.split()[:-1]]
                self.solver.add_clause(out)

        res, _ = self.solver.solve()
        self.assertEqual(res, True)

        self.solver.start_getting_small_clauses(4, max_glue=10)
        x = self.solver.get_next_small_clause()
        self.assertNotEquals(x, None)
        self.solver.end_getting_small_clauses()
Beispiel #5
0
 def test_cnf3(self):
     solver = Solver()
     for cl in clauses3:
         solver.add_clause(cl)
     res, solution = solver.solve()
     self.assertEqual(res, True)
     self.assertTrue(check_solution(clauses3, solution))
Beispiel #6
0
    def test_cnf1_confl_limit(self):
        for lim in range(1, 20):
            solver = Solver(confl_limit=lim)
            for cl in clauses1:
                solver.add_clause(cl)

            res, solution = solver.solve()
            self.assertTrue(res == None or check_solution(clauses1, solution))
Beispiel #7
0
 def cryptominisat_solve(self):
     s = Solver()
     for clause in self.clauses:
         s.add_clause(clause)
     sat, solution = s.solve()
     if sat:
         return solution
     else:
         return 'UNSAT'
Beispiel #8
0
class TestableSolver:
    def __init__(self):
        self.solver = Solver()

    def solve(self, assumptions=[]):
        return self.solver.solve(assumptions)

    @staticmethod
    def to_var(row, column, value):
        return row * 9 * 9 + column * 9 + value + 1

    # return a tuple (row, column, value)
    @staticmethod
    def from_var(var):
        v = var - 1
        row = v // (9 * 9)
        column = (v - row * 9 * 9) // 9
        value = v - row * 9 * 9 - column * 9
        return row, column, value

    # helper function: one and only one literal can be true
    def exactly_one(self, literals):
        # at least once
        self.solver.add_clause(literals)

        for i in literals:
            for j in range(i + 1, len(literals)):
                self.solver.add_clause([-literals[i], -literals[j]])

    # adds the rule, that for each position, only one value can be true
    def add_uniqueness(self, rows, columns):
        for r in range(rows):
            for c in range(columns):
                lit = [self.to_var(r, c, v) for v in range(9)]
                self.exactly_one(lit)

    # adds the rule, that for each rule, the values 1..9 exist
    def add_row_rule(self, row):
        for v in range(9):
            lit = [self.to_var(row, c, v) for c in range(9)]
            self.exactly_one(lit)

    # adds the rule, that for each column, the values 0..8 exist
    def add_column_rule(self, column):
        for v in range(9):
            lit = [self.to_var(r, column, v) for r in range(9)]
            self.exactly_one(lit)

    # adds the rule, that for each box, the values 0..8 exist
    def add_box_rule(self, column, row):
        for v in range(9):
            lit = [
                self.to_var(row + (i // 3), column + (i % 3), v)
                for i in range(9)
            ]
            self.exactly_one(lit)
Beispiel #9
0
 def pyCrypto(self):
     if PyCryptoSat_Import_Successful:
         s = Solver()
         numOfClauses = len(self.clauseList)
         for i in range(numOfClauses):
             s.add_clause(self.clauseList.popleft)
         sat, solution = s.solve()
         if sat:
             return (sat, solution)
     return (sat, None)
Beispiel #10
0
class TestSolve(unittest.TestCase):
    def setUp(self):
        self.solver = Solver(threads=2)

    def test_wrong_args(self):
        self.assertRaises(TypeError, self.solver.add_clause, 'A')
        self.assertRaises(TypeError, self.solver.add_clause, 1)
        self.assertRaises(TypeError, self.solver.add_clause, 1.0)
        self.assertRaises(TypeError, self.solver.add_clause, object())
        self.assertRaises(TypeError, self.solver.add_clause, ['a'])
        self.assertRaises(TypeError, self.solver.add_clause,
                          [[1, 2], [3, None]])
        self.assertRaises(ValueError, self.solver.add_clause, [1, 0])

    def test_no_clauses(self):
        for n in range(7):
            self.assertEqual(self.solver.solve([]), (True, (None, )))

    def test_cnf1(self):
        for cl in clauses1:
            self.solver.add_clause(cl)
        res, solution = self.solver.solve()
        self.assertEqual(res, True)
        self.assertTrue(check_solution(clauses1, solution))

    def test_bad_iter(self):
        class Liar:
            def __iter__(self):
                return None

        self.assertRaises(TypeError, self.solver.add_clause, Liar())

    def test_cnf2(self):
        for cl in clauses2:
            self.solver.add_clause(cl)
        self.assertEqual(self.solver.solve(), (False, None))

    def test_cnf3(self):
        for cl in clauses3:
            self.solver.add_clause(cl)
        res, solution = self.solver.solve()
        self.assertEqual(res, True)
        self.assertTrue(check_solution(clauses3, solution))

    def test_cnf1_confl_limit(self):
        for lim in range(1, 20):
            self.setUp()
            for cl in clauses1:
                self.solver.add_clause(cl)

            res, solution = self.solver.solve()
            self.assertTrue(res == None or check_solution(clauses1, solution))
class TestSolve(unittest.TestCase):
    def setUp(self) :
        self.solver = Solver(threads = 2)

    def test_wrong_args(self):
        self.assertRaises(TypeError, self.solver.add_clause, 'A')
        self.assertRaises(TypeError, self.solver.add_clause, 1)
        self.assertRaises(TypeError, self.solver.add_clause, 1.0)
        self.assertRaises(TypeError, self.solver.add_clause, object())
        self.assertRaises(TypeError, self.solver.add_clause, ['a'])
        self.assertRaises(TypeError, self.solver.add_clause, [[1, 2], [3, None]])
        self.assertRaises(ValueError, self.solver.add_clause, [1, 0])

    def test_no_clauses(self):
        for n in range(7):
            self.assertEqual(self.solver.solve([]), (True, (None,)))

    def test_cnf1(self):
        for cl in clauses1:
            self.solver.add_clause(cl)
        res, solution = self.solver.solve()
        self.assertEqual(res, True)
        self.assertTrue(check_solution(clauses1, solution))

    def test_bad_iter(self):
        class Liar:
            def __iter__(self): return None
        self.assertRaises(TypeError, self.solver.add_clause, Liar())

    def test_cnf2(self):
        for cl in clauses2:
            self.solver.add_clause(cl)
        self.assertEqual(self.solver.solve(), (False, None))

    def test_cnf3(self):
        for cl in clauses3:
            self.solver.add_clause(cl)
        res, solution = self.solver.solve()
        self.assertEqual(res, True)
        self.assertTrue(check_solution(clauses3, solution))

    def test_cnf1_confl_limit(self):
        for lim in range(1, 20):
            self.setUp()
            for cl in clauses1:
                self.solver.add_clause(cl)

            res, solution = self.solver.solve()
            self.assertTrue(res == None or check_solution(clauses1, solution))
Beispiel #12
0
    def is_system_uniquely_satisfiable(self, system, n):
        """
        Tests unique satisfiable by banning all zero solution
        :param system: 
        :param n: 
        :return: 
        """
        if not system:
            return False

        # Prep solver
        solver = Solver()
        for clause in system:
            solver.add_xor_clause(clause, False)

        # Ban all zero
        solver.add_clause(range(1, n + 1))

        sat, sol = solver.solve()

        # print "Found system is {0}".format(sat)

        return not sat
Beispiel #13
0
class ProgramSolver():
    def __init__(self,filename):
        self.s = Solver(threads = 3)
        self.tt = 0

        h2v = {} # hole 2 variable
                
        self.maximum_variable = -1
        with open(filename,'r') as f:
            for l in f:
                if len(l) > len('c hole ') and l[:len('c hole ')] == 'c hole ':
                    ms = re.findall(r'(\d+) \- (\d+)', l)[0]
                    assert int(ms[0]) == int(ms[1])
                    ms = int(ms[0])
                    n = int(re.findall(r'H__\S+_(\S+)\s',l)[0])
                    h2v[n] = ms
                elif len(l) > 0 and not 'c' in l and not 'p' in l:
                    vs = re.findall(r'(\-?\d+)',l)
                    assert vs[-1] == '0'
                    clause = [int(v) for v in vs[:-1] ]
                    self.maximum_variable = max([self.maximum_variable] +
                                                [abs(v) for v in clause ])
                    self.s.add_clause(clause)
        print "Loaded",filename," with",len(h2v),"holes"
        # convert the tape index into a sat variable
        self.tape2variable = [ v for h,v in sorted(h2v.items()) ]
        
        # converts a sat variable to a tape index
        self.variable2tape = dict([ (v,h) for h,v in h2v.items() ])



    def generate_variable(self):
        self.maximum_variable += 1
        return self.maximum_variable
    
    def random_projection(self):
        self.s.add_xor_clause([v for v in self.variable2tape if random.random() > 0.5 ],random.random() > 0.5)
        
    def try_solving(self,assumptions = None):
        print "About to run solver ==  ==  ==  > "
        start_time = time.time()
        if assumptions != None:
            result = self.s.solve(assumptions)
        else:
            result = self.s.solve()
        dt = (time.time() - start_time)
        self.tt += dt
        print "Ran solver in time",dt
        if result[0]:
            bindings = {}
            for v in range(len(result[1])):
                if v in self.variable2tape:
                    bindings[v] = result[1][v]
            print "Satisfiable."
            return bindings
        else:
            print "Unsatisfiable."
            return False

    def uniqueness_clause(self,tape):
        p,bit_mask = parse_tape(tape)
        clause = []
        for j in range(len(tape)):
            if bit_mask[j] == 1:
                # jth tape position
                v = self.tape2variable[j]
                if tape[j] == 1: v = -v
                clause += [v]
        return clause
        
    def is_solution_unique(self,tape):
        d = self.generate_variable()
        clause = [d] + self.uniqueness_clause(tape)
        print "uniqueness clause",clause
        self.s.add_clause(clause)
        result = self.try_solving([-d])
        self.s.add_clause([d]) # make the clause documents they satisfied
        if result:
            tp = self.holes2tape(result)
            print "alternative:",parse_tape(tp)
            print "alternative tape:",tp
            return False
        else:
            return True
                

    def holes2tape(self,result):
        return [ (1 if result[v] else 0) for v in self.tape2variable ]

    def try_sampling(self,subspace_dimension):
        for j in range(subspace_dimension):
            self.random_projection()
        result = self.try_solving()
        if result:
            print "Random projection satisfied"
            tp = self.holes2tape(result)
            print parse_tape(tp)[0]
            if self.is_solution_unique(tp):
                print "Unique. Accepted."
            else:
                print "Sample rejected"

    def adaptive_sample(self):
        subspace_dimension = 1
        result = self.try_solving()
        if result:
            print "Formula satisfied"
            for j in range(subspace_dimension):
                self.random_projection()
            while True:
                print "\n\niterating:"
                result = self.try_solving()
                if result:
                    print "Satisfied %d constraints" % subspace_dimension
                    tp = self.holes2tape(result)
                    print parse_tape(tp)
                    print "tape = ",tp
                    if self.is_solution_unique(tp):
                        print "UNIQUE"
                        print "<<< ==  ==  == >>>"
                    self.random_projection()
                    subspace_dimension += 1
                else:
                    print "Rejected %d projections" % subspace_dimension
                    print "total time = ",self.tt
                    break


    def enumerate_solutions(self):
        solutions = []
        result = self.try_solving()
        d = self.generate_variable()
        logZ = float('-inf')
        while result:
            tp = self.holes2tape(result)
            program,mask = parse_tape(tp)
            solutions = solutions + [program]
            specified = sum(mask)
            logZ = lse(logZ, -specified * 0.693)
            print "Enumerated program", program, "with", specified, "specified bits."
            self.s.add_clause([d] + self.uniqueness_clause(tp))
            result = self.try_solving([-d])
        print "log(z) = ",logZ, "\t1/p = ", math.exp(-logZ)
        return solutions
Beispiel #14
0
class CryptoMiniSat(SatSolver):
    r"""
    CryptoMiniSat Solver.

    INPUT:

    - ``verbosity`` -- an integer between 0 and 15 (default: 0). Verbosity.

    - ``confl_limit`` -- an integer (default: ``None``). Abort after this many
      conflicts. If set to ``None``, never aborts.

    - ``threads`` -- an integer (default: None). The number of thread to
      use. If set to ``None``, the number of threads used corresponds to the
      number of cpus.

    EXAMPLES::

        sage: from sage.sat.solvers.cryptominisat import CryptoMiniSat
        sage: solver = CryptoMiniSat()                                  # optional - cryptominisat
    """
    def __init__(self, verbosity=0, confl_limit=None, threads=None):
        r"""
        Constuct a new CryptoMiniSat instance.

        See the documentation class for the description of inputs.

        EXAMPLES::

            sage: from sage.sat.solvers.cryptominisat import CryptoMiniSat
            sage: solver = CryptoMiniSat(threads=1)                     # optional - cryptominisat
        """
        if threads is None:
            from sage.parallel.ncpus import ncpus
            threads = ncpus()
        if confl_limit is None:
            from sys import maxint
            confl_limit = maxint
        try:
            from pycryptosat import Solver
        except ImportError:
            from sage.misc.package import PackageNotFoundError
            raise PackageNotFoundError("cryptominisat")
        self._solver = Solver(verbose=int(verbosity), confl_limit=int(confl_limit), threads=int(threads))
        self._nvars = 0
        self._clauses = []

    def var(self, decision=None):
        r"""
        Return a *new* variable.

        INPUT:

        - ``decision`` -- accepted for compatibility with other solvers, ignored.

        EXAMPLES::

            sage: from sage.sat.solvers.cryptominisat import CryptoMiniSat
            sage: solver = CryptoMiniSat()                                  # optional - cryptominisat
            sage: solver.var()                                              # optional - cryptominisat
            1

            sage: solver.add_clause((-1,2,-4))                              # optional - cryptominisat
            sage: solver.var()                                              # optional - cryptominisat
            5
        """
        return self._nvars + 1

    def nvars(self):
        r"""
        Return the number of variables. Note that for compatibility with DIMACS
        convention, the number of variables corresponds to the maximal index of
        the variables used. 
        
        EXAMPLES::

            sage: from sage.sat.solvers.cryptominisat import CryptoMiniSat
            sage: solver = CryptoMiniSat()                                  # optional - cryptominisat
            sage: solver.nvars()                                            # optional - cryptominisat
            0

        If a variable with intermediate index is not used, it is still
        considered as a variable::

            sage: solver.add_clause((1,-2,4))                               # optional - cryptominisat
            sage: solver.nvars()                                            # optional - cryptominisat
            4
        """
        return self._nvars

    def add_clause(self, lits):
        r"""
        Add a new clause to set of clauses.

        INPUT:

        - ``lits`` -- a tuple of nonzero integers.

        .. note::

            If any element ``e`` in ``lits`` has ``abs(e)`` greater
            than the number of variables generated so far, then new
            variables are created automatically.

        EXAMPLES::

            sage: from sage.sat.solvers.cryptominisat import CryptoMiniSat
            sage: solver = CryptoMiniSat()                                  # optional - cryptominisat
            sage: solver.add_clause((1, -2 , 3))                            # optional - cryptominisat
        """
        if 0 in lits:
            raise ValueError("0 should not appear in the clause: {}".format(lits))
        # cryptominisat does not handle Sage integers
        lits = tuple(int(i) for i in lits)
        self._nvars = max(self._nvars, max(abs(i) for i in lits))
        self._solver.add_clause(lits)
        self._clauses.append((lits, False, None))

    def add_xor_clause(self, lits, rhs=True):
        r"""
        Add a new XOR clause to set of clauses.

        INPUT:

        - ``lits`` -- a tuple of positive integers.

        - ``rhs`` -- boolean (default: ``True``). Whether this XOR clause should
          be evaluated to ``True`` or ``False``.

        EXAMPLES::

            sage: from sage.sat.solvers.cryptominisat import CryptoMiniSat
            sage: solver = CryptoMiniSat()                                  # optional - cryptominisat
            sage: solver.add_xor_clause((1, 2 , 3), False)                  # optional - cryptominisat
        """
        if 0 in lits:
            raise ValueError("0 should not appear in the clause: {}".format(lits))
        # cryptominisat does not handle Sage integers
        lits = tuple(int(i) for i in lits)
        self._nvars = max(self._nvars, max(abs(i) for i in lits))
        self._solver.add_xor_clause(lits, rhs)
        self._clauses.append((lits, True, rhs))

    def __call__(self, assumptions=None):
        r"""
        Solve this instance.

        OUTPUT:

        - If this instance is SAT: A tuple of length ``nvars()+1``
          where the ``i``-th entry holds an assignment for the
          ``i``-th variables (the ``0``-th entry is always ``None``).

        - If this instance is UNSAT: ``False``.

        EXAMPLES::

            sage: from sage.sat.solvers.cryptominisat import CryptoMiniSat
            sage: solver = CryptoMiniSat()                                  # optional - cryptominisat
            sage: solver.add_clause((1,2))                                  # optional - cryptominisat
            sage: solver.add_clause((-1,2))                                 # optional - cryptominisat
            sage: solver.add_clause((-1,-2))                                # optional - cryptominisat
            sage: solver()                                                  # optional - cryptominisat
            (None, False, True)

            sage: solver.add_clause((1,-2))                                 # optional - cryptominisat
            sage: solver()                                                  # optional - cryptominisat
            False
        """
        satisfiable, assignments = self._solver.solve()
        if satisfiable:
            return assignments
        else:
            return False

    def __repr__(self):
        r"""
        TESTS::

            sage: from sage.sat.solvers.cryptominisat import CryptoMiniSat
            sage: solver = CryptoMiniSat()                                  # optional - cryptominisat
            sage: solver                                                    # optional - cryptominisat
            CryptoMiniSat solver: 0 variables, 0 clauses.
        """
        return "CryptoMiniSat solver: {} variables, {} clauses.".format(self.nvars(), len(self.clauses()))

    def clauses(self, filename=None):
        r"""
        Return original clauses.

        INPUT:

        - ``filename`` -- if not ``None`` clauses are written to ``filename`` in
          DIMACS format (default: ``None``)

        OUTPUT:

            If ``filename`` is ``None`` then a list of ``lits, is_xor, rhs``
            tuples is returned, where ``lits`` is a tuple of literals,
            ``is_xor`` is always ``False`` and ``rhs`` is always ``None``.

            If ``filename`` points to a writable file, then the list of original
            clauses is written to that file in DIMACS format.

        EXAMPLES::

            sage: from sage.sat.solvers import CryptoMiniSat
            sage: solver = CryptoMiniSat()                              # optional - cryptominisat
            sage: solver.add_clause((1,2,3,4,5,6,7,8,-9))               # optional - cryptominisat
            sage: solver.add_xor_clause((1,2,3,4,5,6,7,8,9), rhs=True)  # optional - cryptominisat
            sage: solver.clauses()                                      # optional - cryptominisat
            [((1, 2, 3, 4, 5, 6, 7, 8, -9), False, None),
            ((1, 2, 3, 4, 5, 6, 7, 8, 9), True, True)]

        DIMACS format output::

            sage: from sage.sat.solvers import CryptoMiniSat
            sage: solver = CryptoMiniSat()                      # optional - cryptominisat
            sage: solver.add_clause((1, 2, 4))                  # optional - cryptominisat
            sage: solver.add_clause((1, 2, -4))                 # optional - cryptominisat
            sage: fn = tmp_filename()                           # optional - cryptominisat
            sage: solver.clauses(fn)                            # optional - cryptominisat
            sage: print(open(fn).read())                        # optional - cryptominisat
            p cnf 4 2
            1 2 4 0
            1 2 -4 0
            <BLANKLINE>

        Note that in cryptominisat, the DIMACS standard format is augmented with
        the following extension: having an ``x`` in front of a line makes that
        line an XOR clause::

            sage: solver.add_xor_clause((1,2,3), rhs=True)      # optional - cryptominisat
            sage: solver.clauses(fn)                            # optional - cryptominisat
            sage: print(open(fn).read())                        # optional - cryptominisat
            p cnf 4 3
            1 2 4 0
            1 2 -4 0
            x1 2 3 0
            <BLANKLINE>

        Note that inverting an xor-clause is equivalent to inverting one of the
        variables::

            sage: solver.add_xor_clause((1,2,5),rhs=False)      # optional - cryptominisat
            sage: solver.clauses(fn)                            # optional - cryptominisat
            sage: print(open(fn).read())                        # optional - cryptominisat
            p cnf 5 4
            1 2 4 0
            1 2 -4 0
            x1 2 3 0
            x1 2 -5 0
            <BLANKLINE> 
        """
        if filename is None:
            return self._clauses
        else:
            from sage.sat.solvers.dimacs import DIMACS
            DIMACS.render_dimacs(self._clauses, filename, self.nvars())
Beispiel #15
0
class TestSolve(unittest.TestCase):
    def setUp(self):
        self.solver = Solver(threads=2)

    def test_wrong_args(self):
        self.assertRaises(TypeError, self.solver.add_clause, 'A')
        self.assertRaises(TypeError, self.solver.add_clause, 1)
        self.assertRaises(TypeError, self.solver.add_clause, 1.0)
        self.assertRaises(TypeError, self.solver.add_clause, object())
        self.assertRaises(TypeError, self.solver.add_clause, ['a'])
        self.assertRaises(TypeError, self.solver.add_clause,
                          [[1, 2], [3, None]])
        self.assertRaises(ValueError, self.solver.add_clause, [1, 0])

    def test_no_clauses(self):
        for _ in range(7):
            self.assertEqual(self.solver.solve([]), (True, (None, )))

    def test_cnf1(self):
        for cl in clauses1:
            self.solver.add_clause(cl)
        res, solution = self.solver.solve()
        self.assertEqual(res, True)
        self.assertTrue(check_solution(clauses1, solution))

    def test_add_clauses(self):
        self.solver.add_clauses([[1], [-1]])
        res, solution = self.solver.solve()
        self.assertEqual(res, False)

    def test_add_clauses_wrong_zero(self):
        self.assertRaises(TypeError, self.solver.add_clause, [[1, 0], [-1]])

    def test_add_clauses_array_SAT(self):
        cls = array('i', [1, 2, 0, 1, 2, 0])
        self.solver.add_clauses(cls)
        res, solution = self.solver.solve()
        self.assertEqual(res, True)

    def test_add_clauses_array_UNSAT(self):
        cls = array('i', [-1, 0, 1, 0])
        self.solver.add_clauses(cls)
        res, solution = self.solver.solve()
        self.assertEqual(res, False)

    def test_add_clauses_array_unterminated(self):
        cls = array('i', [1, 2, 0, 1, 2])
        self.assertRaises(ValueError, self.solver.add_clause, cls)

    def test_bad_iter(self):
        class Liar:
            def __iter__(self):
                return None

        self.assertRaises(TypeError, self.solver.add_clause, Liar())

    def test_get_conflict(self):
        self.solver.add_clauses([[-1], [2], [3], [-4]])
        assume = [-2, 3, 4]

        res, model = self.solver.solve(assumptions=assume)
        self.assertEqual(res, False)

        confl = self.solver.get_conflict()
        self.assertEqual(isinstance(confl, list), True)
        self.assertNotIn(3, confl)

        if 2 in confl:
            self.assertIn(2, confl)
        elif -4 in confl:
            self.assertIn(-4, confl)
        else:
            self.assertEqual(False,
                             True,
                             msg="Either -2 or 4 should be conflicting!")

        assume = [2, 4]
        res, model = self.solver.solve(assumptions=assume)
        self.assertEqual(res, False)

        confl = self.solver.get_conflict()
        self.assertEqual(isinstance(confl, list), True)
        self.assertNotIn(2, confl)
        self.assertIn(-4, confl)

    def test_cnf2(self):
        for cl in clauses2:
            self.solver.add_clause(cl)
        self.assertEqual(self.solver.solve(), (False, None))

    def test_cnf3(self):
        for cl in clauses3:
            self.solver.add_clause(cl)
        res, solution = self.solver.solve()
        self.assertEqual(res, True)
        self.assertTrue(check_solution(clauses3, solution))

    def test_cnf1_confl_limit(self):
        for _ in range(1, 20):
            self.setUp()
            for cl in clauses1:
                self.solver.add_clause(cl)

            res, solution = self.solver.solve()
            self.assertTrue(res is None or check_solution(clauses1, solution))

    def test_by_re_curse(self):
        self.solver.add_clause([-1, -2, 3])
        res, _ = self.solver.solve()
        self.assertEqual(res, True)

        self.solver.add_clause([-5, 1])
        self.solver.add_clause([4, -3])
        self.solver.add_clause([2, 3, 5])
        res, _ = self.solver.solve()
        self.assertEqual(res, True)
Beispiel #16
0
class ProgramSolver():
    def __init__(self, filename):
        self.s = Solver(threads=3)
        self.tt = 0

        h2v = {}  # hole 2 variable

        self.maximum_variable = -1
        with open(filename, 'r') as f:
            for l in f:
                if len(l) > len('c hole ') and l[:len('c hole ')] == 'c hole ':
                    ms = re.findall(r'(\d+) \- (\d+)', l)[0]
                    assert int(ms[0]) == int(ms[1])
                    ms = int(ms[0])
                    n = int(re.findall(r'H__\S+_(\S+)\s', l)[0])
                    h2v[n] = ms
                elif len(l) > 0 and not 'c' in l and not 'p' in l:
                    vs = re.findall(r'(\-?\d+)', l)
                    assert vs[-1] == '0'
                    clause = [int(v) for v in vs[:-1]]
                    self.maximum_variable = max([self.maximum_variable] +
                                                [abs(v) for v in clause])
                    self.s.add_clause(clause)
        print "Loaded", filename, " with", len(h2v), "holes"
        # convert the tape index into a sat variable
        self.tape2variable = [v for h, v in sorted(h2v.items())]

        # converts a sat variable to a tape index
        self.variable2tape = dict([(v, h) for h, v in h2v.items()])

    def generate_variable(self):
        self.maximum_variable += 1
        return self.maximum_variable

    def random_projection(self):
        self.s.add_xor_clause(
            [v for v in self.variable2tape if random.random() > 0.5],
            random.random() > 0.5)

    def try_solving(self, assumptions=None):
        print "About to run solver ==  ==  ==  > "
        start_time = time.time()
        if assumptions != None:
            result = self.s.solve(assumptions)
        else:
            result = self.s.solve()
        dt = (time.time() - start_time)
        self.tt += dt
        print "Ran solver in time", dt
        if result[0]:
            bindings = {}
            for v in range(len(result[1])):
                if v in self.variable2tape:
                    bindings[v] = result[1][v]
            print "Satisfiable."
            return bindings
        else:
            print "Unsatisfiable."
            return False

    def uniqueness_clause(self, tape):
        p, bit_mask = parse_tape(tape)
        clause = []
        for j in range(len(tape)):
            if bit_mask[j] == 1:
                # jth tape position
                v = self.tape2variable[j]
                if tape[j] == 1: v = -v
                clause += [v]
        return clause

    def is_solution_unique(self, tape):
        d = self.generate_variable()
        clause = [d] + self.uniqueness_clause(tape)
        print "uniqueness clause", clause
        self.s.add_clause(clause)
        result = self.try_solving([-d])
        self.s.add_clause([d])  # make the clause documents they satisfied
        if result:
            tp = self.holes2tape(result)
            print "alternative:", parse_tape(tp)
            print "alternative tape:", tp
            return False
        else:
            return True

    def holes2tape(self, result):
        return [(1 if result[v] else 0) for v in self.tape2variable]

    def try_sampling(self, subspace_dimension):
        for j in range(subspace_dimension):
            self.random_projection()
        result = self.try_solving()
        if result:
            print "Random projection satisfied"
            tp = self.holes2tape(result)
            print parse_tape(tp)[0]
            if self.is_solution_unique(tp):
                print "Unique. Accepted."
            else:
                print "Sample rejected"

    def adaptive_sample(self):
        subspace_dimension = 1
        result = self.try_solving()
        if result:
            print "Formula satisfied"
            for j in range(subspace_dimension):
                self.random_projection()
            while True:
                print "\n\niterating:"
                result = self.try_solving()
                if result:
                    print "Satisfied %d constraints" % subspace_dimension
                    tp = self.holes2tape(result)
                    print parse_tape(tp)
                    print "tape = ", tp
                    if self.is_solution_unique(tp):
                        print "UNIQUE"
                        print "<<< ==  ==  == >>>"
                    self.random_projection()
                    subspace_dimension += 1
                else:
                    print "Rejected %d projections" % subspace_dimension
                    print "total time = ", self.tt
                    break

    def enumerate_solutions(self):
        solutions = []
        result = self.try_solving()
        d = self.generate_variable()
        logZ = float('-inf')
        while result:
            tp = self.holes2tape(result)
            program, mask = parse_tape(tp)
            solutions = solutions + [program]
            specified = sum(mask)
            logZ = lse(logZ, -specified * 0.693)
            print "Enumerated program", program, "with", specified, "specified bits."
            self.s.add_clause([d] + self.uniqueness_clause(tp))
            result = self.try_solving([-d])
        print "log(z) = ", logZ, "\t1/p = ", math.exp(-logZ)
        return solutions
 def solve_sat(self):
     solver = Solver()
     for clause in self.formula:
         solver.add_clause(clause)
     sat, assignments = solver.solve()
     return sat
class TestSolve(unittest.TestCase):
    def setUp(self):
        self.solver = Solver(threads=2)

    def test_wrong_args(self):
        self.assertRaises(TypeError, self.solver.add_clause, 'A')
        self.assertRaises(TypeError, self.solver.add_clause, 1)
        self.assertRaises(TypeError, self.solver.add_clause, 1.0)
        self.assertRaises(TypeError, self.solver.add_clause, object())
        self.assertRaises(TypeError, self.solver.add_clause, ['a'])
        self.assertRaises(TypeError, self.solver.add_clause,
                          [[1, 2], [3, None]])
        self.assertRaises(ValueError, self.solver.add_clause, [1, 0])

    def test_no_clauses(self):
        for _ in range(7):
            self.assertEqual(self.solver.solve([]), (True, (None, )))

    def test_cnf1(self):
        for cl in clauses1:
            self.solver.add_clause(cl)
        res, solution = self.solver.solve()
        self.assertEqual(res, True)
        self.assertTrue(check_solution(clauses1, solution))

    def test_add_clauses(self):
        self.solver.add_clauses([[1], [-1]])
        res, solution = self.solver.solve()
        self.assertEqual(res, False)

    def test_add_clauses_wrong_zero(self):
        self.assertRaises(TypeError, self.solver.add_clause, [[1, 0], [-1]])

    def test_add_clauses_array_SAT(self):
        cls = array('i', [1, 2, 0, 1, 2, 0])
        self.solver.add_clauses(cls)
        res, solution = self.solver.solve()
        self.assertEqual(res, True)

    def test_add_clauses_array_UNSAT(self):
        cls = array('i', [-1, 0, 1, 0])
        self.solver.add_clauses(cls)
        res, solution = self.solver.solve()
        self.assertEqual(res, False)

    def test_add_clauses_array_unterminated(self):
        cls = array('i', [1, 2, 0, 1, 2])
        self.assertRaises(ValueError, self.solver.add_clause, cls)

    def test_bad_iter(self):
        class Liar:
            def __iter__(self):
                return None

        self.assertRaises(TypeError, self.solver.add_clause, Liar())

    def test_cnf2(self):
        for cl in clauses2:
            self.solver.add_clause(cl)
        self.assertEqual(self.solver.solve(), (False, None))

    def test_cnf3(self):
        for cl in clauses3:
            self.solver.add_clause(cl)
        res, solution = self.solver.solve()
        self.assertEqual(res, True)
        self.assertTrue(check_solution(clauses3, solution))

    def test_cnf1_confl_limit(self):
        for _ in range(1, 20):
            self.setUp()
            for cl in clauses1:
                self.solver.add_clause(cl)

            res, solution = self.solver.solve()
            self.assertTrue(res is None or check_solution(clauses1, solution))

    def test_by_re_curse(self):
        self.solver.add_clause([-1, -2, 3])
        res, _ = self.solver.solve()
        self.assertEqual(res, True)

        self.solver.add_clause([-5, 1])
        self.solver.add_clause([4, -3])
        self.solver.add_clause([2, 3, 5])
        res, _ = self.solver.solve()
        self.assertEqual(res, True)
Beispiel #19
0
def solve_or(model):
    s = Solver()
    for clause in model.clauses:
        s.add_clause(clause)
    return s.solve()
Beispiel #20
0
class TestSolve(unittest.TestCase):

    def setUp(self):
        self.solver = Solver(threads=2)

    def test_wrong_args(self):
        self.assertRaises(TypeError, self.solver.add_clause, 'A')
        self.assertRaises(TypeError, self.solver.add_clause, 1)
        self.assertRaises(TypeError, self.solver.add_clause, 1.0)
        self.assertRaises(TypeError, self.solver.add_clause, object())
        self.assertRaises(TypeError, self.solver.add_clause, ['a'])
        self.assertRaises(
            TypeError, self.solver.add_clause, [[1, 2], [3, None]])
        self.assertRaises(ValueError, self.solver.add_clause, [1, 0])

    def test_no_clauses(self):
        for _ in range(7):
            self.assertEqual(self.solver.solve([]), (True, (None,)))

    def test_cnf1(self):
        for cl in clauses1:
            self.solver.add_clause(cl)
        res, solution = self.solver.solve()
        self.assertEqual(res, True)
        self.assertTrue(check_solution(clauses1, solution))

    def test_add_clauses(self):
        self.solver.add_clauses([[1], [-1]])
        res, solution = self.solver.solve()
        self.assertEqual(res, False)

    def test_add_clauses_wrong_zero(self):
        self.assertRaises(TypeError, self.solver.add_clause, [[1, 0], [-1]])

    def test_add_clauses_array_SAT(self):
        cls = array('i', [1, 2, 0, 1, 2, 0])
        self.solver.add_clauses(cls)
        res, solution = self.solver.solve()
        self.assertEqual(res, True)

    def test_add_clauses_array_UNSAT(self):
        cls = array('i', [-1, 0, 1, 0])
        self.solver.add_clauses(cls)
        res, solution = self.solver.solve()
        self.assertEqual(res, False)

    def test_add_clauses_array_unterminated(self):
        cls = array('i', [1, 2, 0, 1, 2])
        self.assertRaises(ValueError, self.solver.add_clause, cls)

    def test_bad_iter(self):
        class Liar:

            def __iter__(self):
                return None
        self.assertRaises(TypeError, self.solver.add_clause, Liar())

    def test_get_conflict(self):
        self.solver.add_clauses([[-1], [2], [3], [-4]])
        assume = [-2, 3, 4]

        res, model = self.solver.solve(assumptions=assume)
        self.assertEqual(res, False)

        confl = self.solver.get_conflict()
        self.assertEqual(isinstance(confl, list), True)
        self.assertNotIn(3, confl)

        if 2 in confl:
            self.assertIn(2, confl)
        elif -4 in confl:
            self.assertIn(-4, confl)
        else:
            self.assertEqual(False, True, msg="Either -2 or 4 should be conflicting!")

        assume = [2, 4]
        res, model = self.solver.solve(assumptions=assume)
        self.assertEqual(res, False)

        confl = self.solver.get_conflict()
        self.assertEqual(isinstance(confl, list), True)
        self.assertNotIn(2, confl)
        self.assertIn(-4, confl)

    def test_cnf2(self):
        for cl in clauses2:
            self.solver.add_clause(cl)
        self.assertEqual(self.solver.solve(), (False, None))

    def test_cnf3(self):
        for cl in clauses3:
            self.solver.add_clause(cl)
        res, solution = self.solver.solve()
        self.assertEqual(res, True)
        self.assertTrue(check_solution(clauses3, solution))

    def test_cnf1_confl_limit(self):
        for _ in range(1, 20):
            self.setUp()
            for cl in clauses1:
                self.solver.add_clause(cl)

            res, solution = self.solver.solve()
            self.assertTrue(res is None or check_solution(clauses1, solution))

    def test_by_re_curse(self):
        self.solver.add_clause([-1, -2, 3])
        res, _ = self.solver.solve()
        self.assertEqual(res, True)

        self.solver.add_clause([-5, 1])
        self.solver.add_clause([4, -3])
        self.solver.add_clause([2, 3, 5])
        res, _ = self.solver.solve()
        self.assertEqual(res, True)
Beispiel #21
0
 def test_cnf2(self):
     solver = Solver()
     for cl in clauses2:
         solver.add_clause(cl)
     self.assertEqual(solver.solve(), (False, None))