Beispiel #1
0
    def init(self, bootstrap_with):
        """
            This method serves for initializing the hitting set solver with a
            given list of sets to hit. Concretely, the hitting set problem is
            encoded into partial MaxSAT as outlined above, which is then fed
            either to a MaxSAT solver or an MCS enumerator.

            :param bootstrap_with: input set of sets to hit
            :type bootstrap_with: iterable(iterable(obj))
        """

        # formula encoding the sets to hit
        formula = WCNF()

        # hard clauses
        for to_hit in bootstrap_with:
            to_hit = list(map(lambda obj: self.idpool.id(obj), to_hit))

            formula.append(to_hit)

        # soft clauses
        for obj_id in six.iterkeys(self.idpool.id2obj):
            formula.append([-obj_id], weight=1)

        if self.htype == 'rc2':
            # using the RC2-A options from MaxSAT evaluation 2018
            self.oracle = RC2(formula,
                              solver=self.solver,
                              adapt=False,
                              exhaust=True,
                              trim=5)
        elif self.htype == 'lbx':
            self.oracle = LBX(formula, solver_name=self.solver, use_cld=True)
        else:
            self.oracle = MCSls(formula, solver_name=self.solver, use_cld=True)
Beispiel #2
0
    def run_solver(self):
        start_time = time.time()
        with RC2(self.wcnf, solver='mc') as rc2:
            while True:
                ans = rc2.compute()
                if ans is None:
                    print('break no answer')
                    break
                ans = [self.convert_integer_to_letters(x) for x in ans]
                # print(ans)
                counter = 0
                for x in ans:
                    if x.startswith('~') and 'gate' in x:
                        counter = counter + 1
                        rc2.add_clause(
                            [abs(self.convert_letters_to_integer(x))])

                if counter > 0 and self.min_card > counter:
                    self.min_card = counter

                if self.min_card + 2 < counter:
                    print('break min card:', self.min_card)
                    print('number of comp: ', counter)
                    break

                self.number_of_diagnoses = self.number_of_diagnoses + 1
                current_time = time.time()

                if (current_time - start_time) / 60 >= 0.5:
                    print('finish run')
                    break
            self.time = current_time - start_time
Beispiel #3
0
    def optimize(self, enc):
        """
            Try to optimize the solution with a MaxSAT solver.
        """

        # a dummy model (everything is deselected)
        model = [-v for v in range(enc.nv)]
        all_vars = set()

        # MaxSAT formula to work with
        formula = WCNF()

        # hard clauses
        for cl in enc.clauses:
            formula.append(cl)

        for j in range(1, self.nof_terms + 1):
            for r in range(1, self.nof_feats + 1):
                formula.append([-self.dvar1(j, r)], 1)
                formula.append([-self.dvar0(j, r)], 1)
                all_vars.add(self.dvar1(j, r))
                all_vars.add(self.dvar0(j, r))

        if self.options.approx:
            hitman = LBX(formula,
                         use_cld=self.options.use_cld,
                         solver_name=self.options.solver)

            hses = []
            for i, hs in enumerate(hitman.enumerate()):
                hitman.block(hs)
                hses.append(hs)

                if i + 1 == self.options.approx:
                    break

            hs = list(
                map(lambda v: -formula.soft[v - 1][0],
                    min(hses, key=lambda x: len(x))))
            hitman.delete()
        else:
            hitman = RC2(formula,
                         solver=self.options.solver,
                         adapt=True,
                         exhaust=True,
                         incr=False,
                         minz=False,
                         trim=self.options.trim)

            hs = list(
                filter(lambda v: v > 0 and v in all_vars, hitman.compute()))
            hitman.delete()

        # filling the model with the right values
        for e in hs:
            model[e - 1] = e

        return model
 def __solveWncf(self, wcnf):
     '''
     This method launches the SAT solver.
     :param wcnf: formulas
     :return:
     '''
     solver = RC2(wcnf, solver=self.__solver)
     self.__model=solver.compute()
     self.__total_time=time.time()
Beispiel #5
0
    def init(self, bootstrap_with, weights=None):
        """
            This method serves for initializing the hitting set solver with a
            given list of sets to hit. Concretely, the hitting set problem is
            encoded into partial MaxSAT as outlined above, which is then fed
            either to a MaxSAT solver or an MCS enumerator.

            An additional optional parameter is ``weights``, which can be used
            to specify non-unit weights for the target objects in the sets to
            hit. This only works if ``'sorted'`` enumeration of hitting sets
            is applied.

            :param bootstrap_with: input set of sets to hit
            :param weights: weights of the objects in case the problem is weighted
            :type bootstrap_with: iterable(iterable(obj))
            :type weights: dict(obj)
        """

        # formula encoding the sets to hit
        formula = WCNF()

        # hard clauses
        for to_hit in bootstrap_with:
            to_hit = list(map(lambda obj: self.idpool.id(obj), to_hit))

            formula.append(to_hit)

        # soft clauses
        for obj_id in six.iterkeys(self.idpool.id2obj):
            formula.append(
                [-obj_id],
                weight=1 if not weights else weights[self.idpool.obj(obj_id)])

        if self.htype == 'rc2':
            if not weights or min(weights.values()) == max(weights.values()):
                self.oracle = RC2(formula,
                                  solver=self.solver,
                                  adapt=self.adapt,
                                  exhaust=self.exhaust,
                                  minz=self.minz,
                                  trim=self.trim)
            else:
                self.oracle = RC2Stratified(formula,
                                            solver=self.solver,
                                            adapt=self.adapt,
                                            exhaust=self.exhaust,
                                            minz=self.minz,
                                            nohard=True,
                                            trim=self.trim)
        elif self.htype == 'lbx':
            self.oracle = LBX(formula,
                              solver_name=self.solver,
                              use_cld=self.usecld)
        else:
            self.oracle = MCSls(formula,
                                solver_name=self.solver,
                                use_cld=self.usecld)
Beispiel #6
0
    def optimize(self, enc):
        """
            Try to optimize the solution with a MaxSAT solver.
        """

        # all d0 and d1 variables (for computing the complement --- MSS)
        all_vars = set([])

        # MaxSAT formula to work with
        formula = WCNF()

        # hard clauses
        for cl in enc.clauses:
            formula.append(cl)

        for j in range(1, self.nof_terms + 1):
            for r in range(1, self.nof_feats + 1):
                formula.append([-self.dvar1(j, r)], 1)
                formula.append([-self.dvar0(j, r)], 1)

                all_vars.add(self.dvar1(j, r))
                all_vars.add(self.dvar0(j, r))

        if self.options.approx:
            hitman = LBX(formula, use_cld=self.options.use_cld,
                    solver_name=self.options.solver)

            hses = []
            for i, hs in enumerate(hitman.enumerate()):
                hitman.block(hs)
                hses.append(hs)

                if i + 1 == self.options.approx:
                    break

            hs = list(map(lambda v: -formula.soft[v - 1][0], min(hses, key=lambda x: len(x))))
            hitman.delete()
        else:
            hitman = RC2(formula, solver=self.options.solver, adapt=True,
                    exhaust=True, incr=False, minz=False, trim=self.options.trim)

            hs = list(filter(lambda v: v > 0 and v in all_vars, hitman.compute()))
            hitman.delete()

        return sorted([-v for v in all_vars.difference(set(hs))])
Beispiel #7
0
    def init(self, bootstrap_with, costs):
        """
            This method serves for initializing the hitting set solver with a
            given list of sets to hit. Concretely, the hitting set problem is
            encoded into partial MaxSAT as outlined above, which is then fed
            either to a MaxSAT solver or an MCS enumerator.

            :param bootstrap_with: input set of sets to hit
            :type bootstrap_with: iterable(iterable(obj))
        """

        # formula encoding the sets to hit
        formula = WCNF()

        # hard clauses
        for to_hit in bootstrap_with:
            to_hit = list(map(lambda obj: self.idpool.id(obj), to_hit))

            formula.append(to_hit)

        # soft clauses
        for obj_id in six.iterkeys(self.idpool.id2obj):
            # this is saying that not including a clause is given a weight of x
            # maxSAT is MAXIMISING the sum of satisfied soft clauses, so to minimise sum,
            # we want to weight *not* including something (hence the -obj_id)

            # this means words such as <PAD> should be given a *higher* weight, so the
            # solver decides that NOT including <PAD> is more worth it than not including
            # a more "meaningful" word
            cost = costs[obj_id - 1]
            formula.append([-obj_id], weight=cost)

        if self.htype == 'rc2':
            # using the RC2-A options from MaxSAT evaluation 2018
            self.oracle = RC2(formula,
                              solver=self.solver,
                              adapt=False,
                              exhaust=True,
                              trim=5)
        elif self.htype == 'lbx':
            self.oracle = LBX(formula, solver_name=self.solver, use_cld=True)
        else:
            self.oracle = MCSls(formula, solver_name=self.solver, use_cld=True)
Beispiel #8
0
    def grow_maxsat(self, f, A, HS):
        remaining, weights = None, None
        wcnf = WCNF()

        # HARD clauses
        wcnf.extend(self.cnf.clauses)
        wcnf.extend([[l] for l in HS])

        # SOFT clauses to grow
        if self.params.interpretation is Interpretation.INITIAL:
            remaining = list(self.I0 - HS)
        elif self.params.interpretation is Interpretation.ACTUAL:
            remaining = list(self.I - HS)
        elif self.params.interpretation is Interpretation.FULL:
            remaining = list(self.Iend - HS)
        elif self.params.interpretation is Interpretation.FINAL:
            remaining = list(A - HS)

        remaining_clauses = [[l] for l in remaining]

        if self.params.maxsat_weighing is Weighing.POSITIVE:
            weights = [f(l) for l in remaining]
        elif self.params.maxsat_weighing is Weighing.INVERSE:
            max_weight = max(f(l) for l in remaining) + 1
            weights = [max_weight - f(l) for l in remaining]
        elif self.params.maxsat_weighing is Weighing.UNIFORM:
            weights = [1] * len(remaining)

        # cost is associated for assigning a truth value to literal not in
        # contrary to A.
        wcnf.extend(clauses=remaining_clauses, weights=weights)

        # solve the MAXSAT problem
        with RC2(wcnf) as s:
            if self.params.maxsat_polarity and hasattr(s, 'oracle'):
                s.oracle.set_phases(literals=list(self.Iend))

            t_model = s.compute()

            return set(t_model)
def solve_weighted_max_sat(n: int,
                           model: MaxSatModel,
                           context: Clause,
                           num_sol,
                           prev_sol=[]):
    """
    Solves a MaxSatModel and tries to return num_sol optimal solutions
    """
    c = WCNF()
    c.nv = n
    for w, clause in model:
        # c.append(list(map(int, list(clause))), weight=w)
        if w != 0 and len(clause) > 0:
            c.append(list(map(int, list(clause))), weight=w)
    if context and len(context) > 0:
        # c.append(list(map(int, list(context))), weight=None)
        # c.append(list(map(int, list(context))))

        c.hard.extend([[int(c)] for c in context])
    s = RC2(c)
    sol = []
    cst = -1

    for m in s.enumerate():
        # while len(m) < n:
        #     m.append(len(m) + 1)

        if cst < 0:
            cst = s.cost
        # print(s.cost, cst, len(sol), num_sol)
        if s.cost > cst or len(sol) >= num_sol:
            break
        m = [v > 0 for v in m]
        if m not in prev_sol:
            sol.append(m)
        if len(sol) >= num_sol:
            break
    if num_sol == 1 and sol:
        return sol[0], cst
    return sol, cst
def solve_weighted_max_sat_file(wcnf_file,
                                context: Clause,
                                num_sol,
                                prev_sol=[]) -> Optional[Instance]:
    """
    Solves a MaxSatModel file and tries to return num_sol optimal solutions
    """
    wcnf = WCNF(wcnf_file)
    if len(context) > 0:
        wcnf.hard.extend(list(map(int, list(context))), weight=None)
    s = RC2(wcnf)
    model = []
    cst = -1
    for m in s.enumerate():
        if cst < 0:
            cst = s.cost
        if s.cost > cst or len(model) >= num_sol:
            break
        m = [v > 0 for v in m]
        if np.array(m) not in prev_sol:
            model.append(np.array(m))
    return model
Beispiel #11
0
 def __createWCNFWithMinimization(self, cnf):
     '''
     This function creates the WCNF object and solves it.
     Variables are weighted, it's a MaxSAT problem.
     :param cnf (list)
     :return:
     '''
     # thanks to pysat library
     self.__wcnf = WCNFPlus()
     self.__wcnf.extend(cnf)
     # most of the traces should be clustered
     self.__minimizingUnclusteredTraces()
     # minimizing BOOLEAN_VAR_COMMON_T variables
     self.__minimizingCommonTransitions()
     # minimizing BOOLEAN_VAR_diff_TRACE_CENTROIDS variables
     self.__minimizingDiff()
     #
     self.__maxTransitionsPerClusterAtMost(
         self.__vars.getFunction(BOOLEAN_VAR_K_CONTAINS_T))
     # RC2 is a MaxSAT algorithm
     solver = RC2(self.__wcnf, solver="mc")
     solver.compute()
     self.__endComputationTime = time.time()
     self.__model = solver.model
Beispiel #12
0
    def _disjoint(self, formula, solver, adapt, exhaust, minz, trim):
        """
            This method constitutes the preliminary step of the implicit
            hitting set paradigm of Forqes. Namely, it enumerates all the
            disjoint *minimal correction subsets* (MCSes) of the formula,
            which will be later used to bootstrap the hitting set solver.

            Note that the MaxSAT solver in use is :class:`.RC2`. As a result,
            all the input parameters of the method, namely, ``formula``,
            ``solver``, ``adapt``, `exhaust``, ``minz``, and ``trim`` -
            represent the input and the options for the RC2 solver.

            :param formula: input formula
            :param solver: SAT solver name
            :param adapt: detect and adapt AtMost1 constraints
            :param exhaust: exhaust unsatisfiable cores
            :param minz: apply heuristic core minimization
            :param trim: trim unsatisfiable cores at most this number of times

            :type formula: :class:`.WCNF`
            :type solver: str
            :type adapt: bool
            :type exhaust: bool
            :type minz: bool
            :type trim: int
        """

        # these will store disjoint MCSes
        # (unit-size MCSes are stored separately)
        to_hit, units = [], []

        with RC2(formula,
                 solver=solver,
                 adapt=adapt,
                 exhaust=exhaust,
                 minz=minz,
                 trim=trim,
                 verbose=0) as oracle:

            # iterating over MaxSAT solutions
            while True:
                # a new MaxSAT model
                model = oracle.compute()

                if model is None:
                    # no model => no more disjoint MCSes
                    break

                # extracting the MCS corresponding to the model
                falsified = list(
                    filter(lambda l: model[abs(l) - 1] == -l, self.sels))

                # unit size or not?
                if len(falsified) > 1:
                    to_hit.append(falsified)
                else:
                    units.append(falsified[0])

                # blocking the MCS;
                # next time, all these clauses will be satisfied
                for l in falsified:
                    oracle.add_clause([l])

                # reporting the MCS
                if self.verbose > 3:
                    print('c mcs: {0} 0'.format(' '.join(
                        [str(self.smap[s]) for s in falsified])))

            # RC2 will be destroyed next; let's keep the oracle time
            self.disj_time = oracle.oracle_time()

        return to_hit, units
Beispiel #13
0
def compute(input_path, encoding, mode, typee):
    # Pairwise ATMostOne Encoding. This will allow no new variable use for the encoding.
    # One to one mapping with the original input dimacs
    def pairwise_amo(varset, new_var):
        amo = []
        for i in range(len(varset)):
            for j in range(i + 1, len(varset)):
                wcnf_dimacs.append([new_var, -varset[i], -varset[j]])
        return 0

    # Linear AtMostOne Encoding Function: Commander Var
    def linear_amo(varset, new_var):
        vset_size = len(varset)
        cls_var = c_vars[-1]
        if vset_size <= 4:
            pairwise_amo(varset, cls_var)
            return new_var
        varset.reverse()
        l1 = varset.pop()
        l2 = varset.pop()
        l3 = varset.pop()
        pairwise_amo([l1, l2, l3], cls_var)
        # Commander variable constraint
        new_var += 1
        wcnf_dimacs.append([cls_var, -l1, new_var])
        wcnf_dimacs.append([cls_var, -l2, new_var])
        wcnf_dimacs.append([cls_var, -l3, new_var])
        # uep constraint
        wcnf_dimacs.append([cls_var, -new_var, l1, l2, l3])
        varset.append(new_var)
        return linear_amo(varset, new_var)

    # Lograthemic (Bitwise) encoding of the AtMostOne constraints
    # Unfinished: buggy
    def bitwise_amo(varset, aux_var):
        n = len(varset)
        aux_var += 1
        m = int(math.ceil(math.log(n, 2)))
        log_varset = list(range(aux_var, aux_var + m + 1))
        cls_var = c_vars[-1]
        aux_var += m - 1
        for i in range(n):
            for j in range(m):
                if (i & (1 << j)):
                    wcnf_dimacs.append([cls_var, -varset[i], log_varset[j]])
                else:
                    wcnf_dimacs.append([cls_var, -varset[i], -log_varset[j]])
        return aux_var

    # Filename input
    input_filename = input_path.split("/")[-1]
    hash_object = hashlib.md5(input_filename.encode())
    if mode == 1:
        print("c Input filename: ", input_filename)
        if encoding == 1:
            print("c Encoding used for AMO: Binary Encoding")
        elif encoding == 2:
            print("c Encoding used for AMO: LOG Encoding")
        else:
            print("c Encoding used for AMO: Linear Encoding")

    # Global variables
    wcnf_dimacs = []
    input_horn_cls_count = 0
    p_line_seen = 0
    c_vars = []

    # [START parse_dimacs]
    if not os.path.exists(input_path):
        if mode == 2:
            print_rline(input_filename, 0, 0, 0, 0, 0, 0)
        if mode == 3:
            print("E")
        else:
            print("File path {} does not exist.".format(input_path))
        sys.exit()
    with open(input_path) as cnf_file:
        for line in cnf_file:
            line = line.strip()
            if not line:
                if (mode == 2 or mode == 3):
                    continue
                else:
                    print(
                        "There is an empty line in the input file. Ignoring.")
            elif line[0] == "c":
                continue
            elif line[0] == "p":
                if p_line_seen > 0:
                    ERR(mode, 1, input_filename, [0])
                else:
                    p_line_seen = 1
                # Extract the number of variables and initialize the graph with it
                no_of_vars = int(line.split()[2])
                no_of_cls = int(line.split()[3])
                aux_var = no_of_vars + 1
                # [START variables]
            else:
                if p_line_seen != 1:
                    ERR(mode, 5, input_filename, [0])
                # Take all integers in the line and remove the tralling zero
                constraints = []
                for lit in line.split():
                    try:
                        ilit = int(lit)
                        if ilit > no_of_vars:
                            ERR(mode, 2, input_filename, line)
                        constraints.append(ilit)
                    except ValueError:
                        ERR(mode, 3, input_filename, line)
                del constraints[-1]
                constraint_size = len(constraints)
                input_horn_cls_count += horn_cls(constraints)
                # [START constraints]
                # cnf = CardEnc.atmost(lits=constraints, encoding=EncType.pairwise)
                c_vars.append(aux_var)
                if encoding == 1:
                    pairwise_amo(constraints, aux_var)
                    aux_var += 1
                elif encoding == 2:
                    aux_var = bitwise_amo(constraints, aux_var)
                    aux_var += 1
                else:
                    aux_var = linear_amo(constraints, aux_var)
                    aux_var += 1
                # [END constraints]

    if no_of_cls != (len(c_vars)):
        ERR(mode, 4, input_filename, [0])
    if mode == 1:
        print("Number if vars: ", no_of_vars)
        print("Total no.of clauses: ", no_of_cls)
        print("Total horn clause count in input fml: ", input_horn_cls_count)
    if no_of_cls == 0:
        if mode == 1:
            print("Total clause count is 0. No work day :) ")
        elif mode == 3:
            print("S")
        else:
            print_rline(input_filename, no_of_vars, no_of_cls, 0, 0, 0, 0)
        sys.exit(0)
    if no_of_cls == input_horn_cls_count:
        if mode == 1:
            print("Every clause is already Horn. No work day :) ")
        elif mode == 3:
            print("S")
        else:
            print_rline(input_filename, no_of_vars, no_of_cls,
                        input_horn_cls_count, 0, 0, 0)
        sys.exit(0)

    if (typee != 1):
        print("x " + str(no_of_vars) + ' ' + str(no_of_cls))

    # [END parse_dimacs] :

    # Choose the top value for the maxsat
    top = no_of_cls * 100

    # [START create wcnf file]
    #maxsat_path = "/tmp/" + hash_object.hexdigest() + ".wcnf"
    maxsat_path = "/tmp/" + input_filename + ".wcnf"
    #print (maxsat_path)
    #print ("No.of aux var: ", aux_var)
    with open(maxsat_path, "w") as out:
        out.write("p wcnf " + str(aux_var - 1) + " " +
                  str(len(wcnf_dimacs) + len(c_vars)) + " " + str(top) + "\n")
        for cls in wcnf_dimacs:
            out.write(str(top) + " ")
            for l in cls:
                out.write(str(l) + " ")
            out.write(str(0) + "\n")
        for lit in c_vars:
            out.write(str(1) + " " + str(-lit) + " " + str(0) + "\n")

    # [END wcnf file]

    # [START MAX-SAT]
    if (typee == 1):
        wcnf = WCNF(from_file=maxsat_path)
    else:
        cmd1 = [
            "timeout", "20", "../Open-WBO-Inc/open-wbo-inc_static",
            "-no-complete", "-ca=1", "-c=100000", "-algorithm=6", maxsat_path
        ]
        subprocess.call(cmd1)
    # [END MAX-SAT]

    if mode == 1:
        print("Solving...\n")

    # [START print_solution]
    if (typee == 1):
        with RC2(wcnf) as rc2:
            opt_model = rc2.compute()
            maxcost = no_of_cls - rc2.cost
            p_rhorn = (maxcost / no_of_cls) * 100
            if mode == 1:
                print("The model is: ", opt_model)
                print("The Maximum cost is: ", maxcost)
                print("Percentage of RHorn in total: {0:.2f}".format(p_rhorn))
                print("Total no.of horn clauses in input fml: ",
                      input_horn_cls_count)
            if input_horn_cls_count > 0:
                p_rincr_horn = ((maxcost - input_horn_cls_count) /
                                input_horn_cls_count) * 100
            else:
                p_rincr_horn = 10000
            if mode == 1:
                print(
                    "Percenatge increase in Horn cls wrt input horn count: {0:.2f}"
                    .format(p_rincr_horn))
                print("Program took in total: " +
                      str("{0:.2f}".format(time.time() - start_time)) + " s")

            if mode == 2:
                print_rline(
                    input_filename,
                    no_of_vars,
                    no_of_cls,
                    input_horn_cls_count,
                    maxcost,
                    p_rhorn,
                    p_rincr_horn,
                )
            if (mode == 3):
                # take first number of clauses integers
                cls_model = opt_model[-no_of_cls:]
                print(str(cls_model)[1:-1])

            # for m in rc2.enumerate():
            #    print('model {0} has cost {1}'.format(m, rc2.cost))
        # [END print_solution]
        ## Try to delete the file ##
        try:
            print("Nachoo...")
            # print ("c Deleting file: " + maxsat_path)
        #    os.remove(maxsat_path)
        except OSError as e:  ## if failed, report it back to the user ##
            print("c Error: %s - %s." % (e.filename, e.strerror))
Beispiel #14
0
    print('        com       : complete')
    print('        prf       : preferred')
    print('        stb       : stable')

if __name__ == '__main__':
    if len(sys.argv) < 4:
        print_usage()
        sys.exit(1)
    filename = sys.argv[1]
    mode = sys.argv[2]
    semantics = sys.argv[3]
    strong = True
    if len(sys.argv) > 4:
        if sys.argv[4] != "strong":
            strong = False
    solver = RC2(WCNF())
    if semantics not in ['adm', 'com', 'prf', 'stb']:
        print('Semantics', semantics, 'not supported.')
        sys.exit(1)
    if (semantics == 'com' or semantics == 'prf') and mode == 'cred':
        semantics = 'adm'
    if mode == 'strict' or mode == 'nonstrict':
        args, atts, enfs = parse_af_and_enfs(filename, mode)
        af = AF(args, atts, mode, semantics, enfs=enfs)
        enforce_extension(af, mode, semantics, solver, strong).print(af.int_to_arg)
    elif mode == 'cred' or mode == 'skept':
        args, atts, pos_enfs, neg_enfs = parse_af_and_enfs(filename, mode)
        af = AF(args, atts, mode, semantics, pos_enfs=pos_enfs, neg_enfs=neg_enfs)
        enforce_status(af, mode, semantics, solver, strong).print(af.int_to_arg)
    else:
        print('Mode', mode, 'not supported.')
Beispiel #15
0
    def init(self, bootstrap_with, weights=None, subject_to=[]):
        """
            This method serves for initializing the hitting set solver with a
            given list of sets to hit. Concretely, the hitting set problem is
            encoded into partial MaxSAT as outlined above, which is then fed
            either to a MaxSAT solver or an MCS enumerator.

            An additional optional parameter is ``weights``, which can be used
            to specify non-unit weights for the target objects in the sets to
            hit. This only works if ``'sorted'`` enumeration of hitting sets
            is applied.

            Another optional parameter is available, namely, ``subject_to``.
            It can be used to specify arbitrary hard constraints that must be
            respected when computing hitting sets of the given sets. Note that
            ``subject_to`` should be an iterable containing pure clauses
            and/or native AtMostK constraints. Finally, note that these hard
            constraints must be defined over the set of signed atomic objects,
            i.e. instances of class :class:`.Atom`.

            :param bootstrap_with: input set of sets to hit
            :param weights: weights of the objects in case the problem is weighted
            :param subject_to: hard constraints (either clauses or native AtMostK constraints)
            :type bootstrap_with: iterable(iterable(obj))
            :type weights: dict(obj)
            :type subject_to: iterable(iterable(Atom))
        """

        # formula encoding the sets to hit
        formula = WCNFPlus()

        # hard clauses
        for to_hit in bootstrap_with:
            to_hit = list(map(lambda obj: self.idpool.id(obj), to_hit))

            formula.append(to_hit)

        # additional hard constraints
        for cl in subject_to:
            if not len(cl) == 2 or not type(cl[0]) in (list, tuple, set):
                # this is a pure clause
                formula.append(list(map(lambda a: self.idpool.id(a.obj) * (2 * a.sign - 1), cl)))
            else:
                # this is a native AtMostK constraint
                formula.append([list(map(lambda a: self.idpool.id(a.obj) * (2 * a.sign - 1), cl[0])), cl[1]], is_atmost=True)

        # soft clauses
        for obj_id in six.iterkeys(self.idpool.id2obj):
            formula.append([-obj_id],
                    weight=1 if not weights else weights[self.idpool.obj(obj_id)])

        if self.htype == 'rc2':
            if not weights or min(weights.values()) == max(weights.values()):
                self.oracle = RC2(formula, solver=self.solver, adapt=self.adapt,
                        exhaust=self.exhaust, minz=self.minz, trim=self.trim)
            else:
                self.oracle = RC2Stratified(formula, solver=self.solver,
                        adapt=self.adapt, exhaust=self.exhaust, minz=self.minz,
                        nohard=True, trim=self.trim)
        elif self.htype == 'lbx':
            self.oracle = LBX(formula, solver_name=self.solver,
                    use_cld=self.usecld)
        else:
            self.oracle = MCSls(formula, solver_name=self.solver,
                    use_cld=self.usecld)
Beispiel #16
0
    def compute(self):
        """
            Compute a smallest size decision set.
        """

        self.cost = 0

        # iterative over the number of literals
        nof_lits = 2
        self.time = 0.0

        # depending on this option, we compute either one class or all of them
        if self.options.to_compute == 'best':
            computed = len(self.data.feats[-1])
            self.labels = sorted(self.samps.keys())
        elif self.options.to_compute == 'all':
            computed = 0
            self.labels = sorted(self.samps.keys())
        else:
            to_compute = self.options.to_compute.split(',')
            computed = len(self.data.feats[-1]) - len(to_compute)
            self.labels = [
                self.data.fvmap.dir[self.data.names[-1], c] for c in to_compute
            ]

        while True:
            for label in self.labels:
                if self.covrs[label]:
                    continue

                # resetting the pool of ids
                self.reset_idpool()

                # the main part is encoding
                enc = self.encode(label, nof_lits=nof_lits)

                if self.options.verb:
                    print(
                        'c1 # of lits: {0}; enc: {1}v, {2}h, {3}s; (class = {4})'
                        .format(nof_lits, enc.nv, len(enc.hard), len(enc.soft),
                                self.data.fvmap.opp[label][1]))

                if self.options.pdump:
                    fname = 'formula.{0}@{1}.wcnf'.format(
                        os.getpid(), socket.gethostname())
                    enc.to_file(fname)

                with RC2(enc,
                         solver=self.options.solver,
                         adapt=self.options.am1,
                         exhaust=self.options.exhaust,
                         minz=self.options.minz,
                         trim=self.options.trim) as rc2:
                    model = rc2.compute()

                    if model:
                        model = [0] + model

                        self.extract_cover(label, model)

                        computed += 1
                        if computed >= len(self.data.feats[-1]):
                            self.stime = resource.getrusage(
                                resource.RUSAGE_SELF
                            ).ru_utime - self.init_stime
                            self.ctime = resource.getrusage(
                                resource.RUSAGE_CHILDREN
                            ).ru_utime - self.init_ctime
                            self.time = self.stime + self.ctime

                            return self.covrs

            else:
                nof_lits *= 2
Beispiel #17
0
def make_twosat_model_from_np(
    constraints,
    F,
    zero_vars,
    na_vars,
    eps=None,
    heuristic_setting=None,
    compact_formulation=True,
):

    if eps is None:
        eps = 1 / (len(zero_vars) + len(na_vars))

    if heuristic_setting is None:
        rc2 = RC2(WCNF())
    else:
        assert len(heuristic_setting) == 5
        rc2 = RC2(
            WCNF(),
            adapt=heuristic_setting[0],
            exhaust=heuristic_setting[1],
            incr=heuristic_setting[2],
            minz=heuristic_setting[3],
            trim=heuristic_setting[4],
        )

    if not compact_formulation:
        # hard constraints Z_a,p or Z_b,q
        for constr_ind in range(constraints[0].shape[0]):
            constraint = constraints[0][constr_ind]
            a, p, b, q = constraint.flat
            # print(constraint, F.shape)
            # print(a, p, b, q)
            rc2.add_clause([F[a, p], F[b, q]])
        if len(constraints) >= 2:
            # hard constraints Z_a,p or Z_b,q or -Z_c,d
            for constr_ind in range(constraints[1].shape[0]):
                constraint = constraints[1][constr_ind]
                a, p, b, q, c, d = constraint.flat
                # print(a, p, b, q, c, d)
                rc2.add_clause([F[a, p], F[b, q], -F[c, d]])
    else:
        # hard constraints Z_a,p or (sign) b_pq
        for constr_ind in range(constraints[0].shape[0]):
            constraint = constraints[0][constr_ind]
            row, col, b_pq, sign = constraint.flat
            rc2.add_clause([F[row, col], sign * b_pq])
        if len(constraints) >= 2:
            # hard constraints Z_a,p or Z_b,q or -Z_c,d
            for constr_ind in range(constraints[1].shape[0]):
                constraint = constraints[1][constr_ind]
                row, col, c_pq0, c_pq1 = constraint.flat
                # if Z_rc is True at least one of p, q should become active
                # E.g., c_pq0 be False
                rc2.add_clause([-F[row, col], -c_pq0, -c_pq1])
                # if c_pq0 is False then Z_rc has to be flipped
                rc2.add_clause([F[row, col], c_pq0])

    # soft constraints for zero variables
    for var in zero_vars:
        rc2.add_clause([-var], weight=1)

    if eps > 0:
        # soft constraints for zero variables
        for var in na_vars:
            rc2.add_clause([-var], weight=eps)

    return rc2
def get_instances():
    """returns array of instance names, array of corresponding n"""
    instance_data = np.genfromtxt('m2s_nqubits.csv',
                                  delimiter=',',
                                  skip_header=1,
                                  dtype=str)  # path of csv file
    return instance_data[:, 0], instance_data[:, 1]


if __name__ == '__main__':
    instance_names, instance_n_bits_str = get_instances()
    runtimes = np.zeros(10000)

    n = 20
    n_shifted = n - 5  # n_shifted runs from 0 to 15 instead of 5 to 20

    for loop, i in enumerate(range(n_shifted * 10000, (n_shifted + 1) *
                                   10000)):  # 10000 instances per value of n
        instance_name = instance_names[i]
        wcnf = WCNF(from_file='./../../instances_wcnf/' + instance_name +
                    '.txt')
        with RC2(wcnf) as rc2:
            rc2.compute()
            runtime = rc2.oracle_time()
        runtimes[loop] = runtime

    with open("adam_runtimes_" + str(n) + ".txt",
              "ab") as f:  # saves runtimes to .txt file
        f.write(b"\n")
        np.savetxt(f, runtimes)
Beispiel #19
0
from pysat.formula import WCNF
from pysat.examples.rc2 import RC2
# clauses = [[1], [-1], [-2]]

# clauses = [(-8, 2, -3), (1, 6, -19), (9, -15, 11), (4, -5, 16), (14, -17, -10), (-13, -7, 18), (-15, -8, -5), (13, 1, 2), (-20, 17, 12), (-10, -7, -14), (-9, 3, 18), (6, -19, -11), (12, -9, -7), (-11, 20, -10), (-2, -8, 5), (-18, 19, 3), (16, -1, 14), (-4, -15, -17), (-6, -20, 3), (-19, -15, 11), (-4, -18, 8), (-1, 9, 2), (-17, 14, 12), (-5, 13, 7), (14, 8, -6), (-13, -17, -15), (-11, -1, -5), (-9, 12, 18), (7, -16, 20), (19, 4, -3), (-11, 10, -8), (3, -9, -5), (-7, 13, 6), (17, -19, -4), (15, 14, -18), (-12, -1, 20), (10, -3, -16), (17, 12, 4), (7, 20, 1), (-18, 6, 14), (-5, 19, 8), (-9, -13, 15), (20, 18, 10), (5, -6, 15), (19, 1, -17), (4, -3, -13), (7, -11, -12), (8, 14, 16), (-7, 19, 3), (18, 2, -4), (8, 9, 10), (16, 5, -17), (1, 6, -20), (15, 11, 12), (18, 17, 13), (-3, 12, -2), (16, -10, 1), (15, 8, -9), (-20, -19, -5), (-6, 14, 7), (12, -4, -17), (8, -2, -9), (5, -11, -1), (16, -6, -20), (18, 7, -15), (14, -3, -13), (-8, 12, -3), (14, -19, -6), (-16, -5, 7), (-13, 10, -1), (17, 18, 11), (-4, -9, -2), (19, 3, 1), (-6, 2, -11), (5, -10, 8), (4, 7, -16), (20, 12, 13), (-18, -15, 17), (-11, 6, -16), (-15, -9, -13), (19, 4, -10), (-2, 12, 5), (18, 3, -8), (14, 17, 20), (17, 19, -16), (-1, 2, 10), (6, -14, 11), (-9, -4, -13), (15, -20, -7), (18, -5, 3), (1, -8, -9), (7, 2, 3), (-19, -6, 11), (-18, -4, -10), (-17, -20, -16), (5, -13, 12), (12, 14, -19), (-16, 1, -5), (7, 8, 18), (6, 15, 9)]
# clauses = [(-17, 1, 3), (18, 14, 4), (2, -7, -12), (-6, 11, 20), (8, -9, -10), (16, 13, -19), (-16, -10, 1), (-18, -19, -13), (-20, 7, 3), (-15, 14, 8), (-17, -4, 2), (-12, 6, -11), (15, 13, 8), (-17, 16, -4), (20, -10, 5), (9, 12, -3), (-2, -11, 7), (-14, -6, -19), (19, -15, -11), (-7, 13, -1), (8, 6, 10), (14, -3, 5), (20, 2, 18), (12, 4, 9), (11, 19, 5), (8, -16, -12), (6, -18, -14), (2, -4, -7), (13, 10, 15), (-9, -20, 17), (9, -20, 10), (-17, 7, -6), (3, -8, 1), (5, 18, 2), (-15, -12, 16), (-14, -4, 11), (13, 7, -6), (9, 10, 8), (-12, 14, 4), (-11, -17, -20), (-15, -16, 5), (-18, 19, 1), (-13, -3, 8), (6, -2, 7), (11, 18, -20), (-5, -10, -16), (-12, 4, 9), (-1, -15, 14), (16, 18, -5), (10, 8, -17), (-6, 2, -19), (-1, -15, -3), (11, -12, 20), (-9, -4, 14), (18, 5, -20), (12, -10, 7), (3, 9, -14), (-15, 2, -16), (-17, 11, 4), (6, -13, -19), (-20, -16, 3), (-5, -7, 11), (-17, -13, 2), (-9, 8, -12), (15, -4, -19), (1, -6, 18), (-16, 7, 14), (5, 18, -10), (13, -6, 11), (-19, 4, -12), (-20, 8, 2), (1, -9, 17), (-8, -6, -2), (-5, 19, -4), (-7, -17, 3), (12, -1, -10), (-14, 16, -20), (-11, 18, 9), (-20, -17, 11), (-12, 3, -14), (19, 9, 13), (-18, -2, 6), (-5, -4, -1), (10, 15, -7), (4, -13, -3), (11, -12, 16), (-5, 17, 20), (1, -14, -10), (2, -6, 18), (-8, -15, 19), (17, -19, 1), (-16, 9, -5), (14, -13, -10), (-4, -8, 20), (12, 15, 6), (-11, 3, 18), (-18, 12, 1), (-5, -2, -4), (16, 11, -9), (-17, -6, 13)]
# clauses = [(-4, -12, 8), (10, 18, -1), (-20, -5, -13), (15, 3, -7), (-14, -6, -11), (-2, -9, 16), (11, -4, 14), (-15, -7, -6), (-1, -18, -5), (8, -12, 16), (-20, -13, 3), (-10, -9, -19), (10, -19, -14), (-5, -12, -3), (11, -4, -20), (9, 17, 18), (-7, 16, 15), (13, -1, -2), (7, 8, -10), (18, -16, -2), (17, -19, 20), (-3, -6, 13), (11, -15, 1), (5, -14, -9), (-4, -9, -16), (-5, -3, 1), (-10, -19, 15), (-7, 17, -6), (12, -2, -11), (8, 13, -14), (10, -17, 15), (8, -9, -12), (11, -7, 18), (-6, 1, -16), (3, -2, -14), (-13, -5, -20), (-12, -14, -20), (7, 3, 2), (-6, 11, 9), (5, 18, 16), (4, 10, -13), (8, -1, 19), (15, -9, -8), (3, -6, 20), (7, -19, -13), (4, 18, -1), (-16, 10, 17), (11, -5, 2), (-20, -15, 3), (18, 11, -14), (-6, -19, 4), (-7, -17, -5), (-13, 10, 2), (-1, 9, 16), (-5, 12, -15), (10, 20, -17), (1, -18, -3), (-11, -13, 8), (14, 19, -16), (6, -7, 2), (-8, -12, -1), (-5, -14, 15), (-2, 11, 18), (-17, 6, 7), (-9, -20, -16), (13, -19, 4), (20, -9, -11), (18, 3, -15), (6, -19, 17), (-2, 7, -14), (-8, -5, -4), (-16, 10, -13), (-8, -1, 9), (11, -7, -4), (15, 19, 12), (2, 16, 3), (-14, 18, -17), (-6, 13, -20), (14, 5, 7), (4, -15, -1), (-19, -12, -10), (13, -9, -16), (-11, -6, 18), (2, 17, 20), (-9, 15, -12), (-4, 6, 10), (13, 18, -1), (-20, -3, -7), (2, -17, -11), (19, 5, 8), (19, 8, -10), (-18, -3, 20), (7, 4, 16), (15, 17, -9), (-1, 13, 14), (2, -11, -5), (-12, -1, -14), (20, -5, 7), (-2, -3, 6), (19, 9, -11)]
# clauses = [(1, 2, 3), (-2, -1, 3), (1, -3, 2), (1, 2, -3), (1, -2, -3), (2, -3, 1), (-3, 1, -2), (-2, 3, -1), (-3, -1, -2), (-1, -2, 3), (2, -3, 1), (-1, -2, 3), (2, -1, -3), (-3, 1, 2), (2, 3, -1), (1, 3, -2), (3, -2, 1), (2, 3, 1), (-1, -3, -2), (-2, 3, 1), (-2, 1, 3), (1, 2, 3), (-3, 2, 1), (-3, -2, 1), (-1, 3, -2), (2, 3, -1), (-2, -3, 1), (-2, -1, 3), (-2, 1, 3), (-2, -3, -1), (2, -3, 1), (-1, -3, 2), (-1, 2, 3), (-3, -1, 2), (-2, 1, -3), (-1, -2, 3), (-2, -3, -1), (3, -1, 2), (-2, 3, 1), (-2, 1, -3), (2, -3, -1), (3, -2, -1), (-1, -3, -2), (-1, 2, 3), (-2, 1, 3), (1, -3, -2), (2, 1, -3), (-3, -1, 2), (-3, -2, 1), (-3, -1, -2), (2, 1, -3), (1, 3, 2), (1, -2, 3), (-3, 2, -1), (1, -2, 3), (-1, 2, -3), (-2, -1, 3), (-3, 1, -2), (-2, 3, 1), (-1, -2, -3), (2, 3, 1), (-2, 1, -3), (-2, -1, -3), (2, 1, -3), (-2, -1, 3), (1, 2, -3), (-1, -2, 3), (-3, -2, -1), (-2, -1, -3), (2, 3, 1), (1, -3, -2), (-1, 2, 3), (-1, -3, 2), (-1, -3, 2), (3, 1, 2), (-2, -1, 3), (3, -1, -2), (-1, -3, -2), (-1, 3, -2), (2, -3, -1), (1, 3, 2), (3, -1, -2), (2, 3, 1), (2, 1, -3), (2, -1, 3), (3, 2, 1), (-1, -3, 2), (-3, 2, 1), (-1, -3, -2), (-2, 3, -1), (2, -1, -3), (3, -1, 2), (-3, 2, 1), (3, -2, -1), (-1, -3, -2), (2, -1, -3), (-3, 2, -1), (-3, 2, 1), (-1, 3, 2), (-3, -2, 1)]

# clauses = [(-6, -9, 5), (-8, 7, 10), (2, -4, -3), (-5, -4, -6), (9, 10, 2), (-3, 1, 7), (10, 9, 7), (1, -2, -4), (6, -3, -5), (7, -10, -9), (6, 2, -3), (1, 5, 4), (-6, -9, -1), (7, -8, -3), (-2, -4, 5), (9, 5, 8), (-7, 10, 1), (4, -2, -6), (10, 4, -5), (6, 3, -2), (1, 9, -8), (-4, -1, 6), (-10, 5, -2), (8, 7, 9), (-3, 7, -6), (-9, -5, -4), (-2, 8, -1), (-1, 8, 3), (6, -2, -7), (-10, 4, -5), (10, 3, -7), (4, 8, 1), (-9, -2, -5), (1, 6, 4), (3, -7, 8), (-5, 2, -10), (1, 3, -8), (-4, 2, 10), (-6, -5, -7), (-5, -4, -9), (-10, 2, -7), (3, -8, -1), (1, -2, -9), (-6, -7, -10), (4, 8, -3), (-1, -3, 9), (-5, 6, 10), (4, -2, 8), (-2, 1, 7), (-5, 6, -3), (10, 4, -8), (10, -4, -2), (-9, 5, 8), (7, -3, -6), (-7, 8, -2), (9, -10, 1), (6, 3, -5), (-9, 2, -5), (1, -4, -8), (-10, -3, -6), (4, -10, 9), (-7, -1, -6), (-5, 8, 2), (7, -6, 1), (4, -3, 5), (-9, -8, 10), (-4, -7, -3), (6, 5, 9), (-10, -8, -1), (-2, 1, 10), (3, 8, 9), (-5, -6, -7), (1, 3, -6), (4, -8, 10), (-7, 5, 2), (-8, -4, -3), (9, -10, 2), (-5, 7, -1), (-5, 6, -10), (8, -9, 4), (7, 1, 3), (7, 6, -1), (-3, 2, 8), (4, 9, 10), (2, -9, -10), (3, 1, -8), (-6, 7, -4), (5, -10, 1), (-4, 8, 2), (6, -3, -7), (-10, -7, 1), (-5, -3, 2), (9, -6, -4), (1, 2, 8), (9, -10, -3), (-7, 6, -4), (-4, 6, 5), (7, 1, 9), (-3, 8, -2), (-1, 3, -2), (-7, -6, -10), (-9, 5, -8), (-5, 6, 7), (-10, -8, -3), (9, 2, -1), (6, -4, -3), (-10, 8, -1), (9, 2, 5), (1, 10, 4), (2, -5, -8), (3, -9, 6), (9, 2, -4), (3, -5, 10), (7, -8, -1), (2, 6, -9), (8, 10, -7), (3, -4, -5), (-10, -9, 3), (1, -7, 4), (6, 5, 2), (3, -8, 7), (-9, -10, 6), (4, -2, 1), (10, 7, 3), (-4, -6, 2), (-8, -1, 9), (6, 8, -2), (-3, 4, 7), (5, 9, -10), (-3, 2, -9), (-1, 8, -4), (-7, -10, 6), (-7, -9, -5), (8, 4, 10), (-1, 3, -2), (4, 1, 7), (6, -5, -3), (-2, 10, 9), (-3, 4, 6), (-2, -10, -5), (-9, 7, -8), (-4, 1, -5), (10, 3, 8), (-6, -2, -9), (-7, -5, -1), (-2, 4, -9), (10, 3, -6), (6, -2, 4), (-8, -9, 3), (-7, -10, 1), (-10, 5, -9), (-1, 3, 2), (-6, 7, -4), (9, 6, 10), (-7, -2, -1), (-5, 4, 8), (-4, -5, 1), (-3, -6, -8), (7, -2, 9), (1, -9, -8), (-10, -2, 4), (3, -7, 5), (-7, 4, 9), (2, -5, -8), (3, -10, 6), (-7, -6, -5), (3, -10, -9), (-4, -1, -2), (6, -3, 5), (-1, -10, 9), (7, 2, -4), (-3, -6, -8), (-1, 7, -5), (-4, 2, 10), (9, -5, -10), (6, 1, 8), (3, -7, 4), (-6, -9, 1), (-10, -3, -7), (-8, -2, 4), (5, 3, -7), (-9, 8, -6), (2, -4, 10), (-8, 7, 6), (-3, 5, 1), (4, 9, 2), (10, -1, 5), (4, 8, -3), (-9, -2, -7), (-10, 5, -8), (1, 3, 7), (9, 2, -6), (-5, 10, -1), (-2, -4, -9), (3, 7, -6), (8, 10, -7), (-9, 5, 3), (-6, 2, -4), (7, 1, -4), (8, 6, 2), (-5, 10, -9), (-10, -6, -7), (2, -4, 8), (9, -3, 1), (9, 2, 8), (-10, 7, 1), (-3, 6, 5), (4, 7, -9), (5, -3, 6), (10, 2, 8), (5, -1, 8), (-2, 10, -3), (4, 9, 7), (-10, -9, -2), (-7, 4, -6), (3, -1, 5), (5, -10, -7), (6, -2, 4), (-3, -9, -8), (-4, 1, 7), (-9, -2, 3), (8, 5, -10), (-4, -10, 2), (-1, -3, -7), (-6, -8, -9), (-3, -6, 1), (-8, -9, 10), (-2, -4, 5), (5, -3, 9), (-2, -7, 10), (4, -1, -6), (-6, -10, -1), (-2, -7, -9), (5, 4, -3), (7, 2, -10), (9, -8, -4), (3, 1, -5), (3, 10, 6), (-7, -1, -8), (-4, -2, -9), (-7, -6, 2), (-10, 1, 8), (4, 9, -3), (-10, 1, 4), (-8, 9, -5), (-6, -7, 2), (-8, 9, -7), (3, -5, 10), (-1, -6, -2), (3, -1, 7), (-2, -8, 6), (-9, 10, -4), (-3, -10, -6), (-1, 4, 7), (8, -9, -5), (3, 1, 5), (-8, -2, 7), (9, -4, -10), (-2, 10, -1), (-3, 5, 7), (6, -4, 8), (1, -4, -8), (-10, 9, 2), (5, -7, 3), (2, -4, 8), (7, -9, 3), (-10, -6, -5), (-4, -10, -3), (1, 5, 7), (8, 9, -2), (-6, -4, -7), (-3, -8, -9), (-5, 10, -1), (-2, -3, -8), (10, 6, 5), (4, -9, -1), (-2, 1, 10), (8, 7, 6), (9, 5, -4), (6, -5, 9), (-8, 10, -4), (-3, -2, -7), (9, 5, -2), (4, 1, 7), (-8, 10, 3), (7, 9, -1), (-3, -2, 6), (-5, 4, -10), (-3, -2, 9), (4, 10, -1), (-5, -8, 6), (-9, 1, 10), (-2, -7, -8), (-4, -6, -5), (10, -5, 6), (8, 9, -3), (-1, 7, 2), (5, 7, 9), (6, 8, 4), (10, 3, -2), (5, -8, 2), (1, -7, 9), (-6, 10, -4), (-7, 1, 2), (9, -5, -8), (-3, -6, -4), (-9, -4, -7), (-2, 6, 5), (10, 1, 8), (-7, 9, 1), (10, 5, -4), (-6, 3, 8), (-3, 7, 2), (4, 6, 10), (5, 8, 9), (-2, -6, 8), (3, -4, -5), (-9, -10, -7), (-9, -1, 8), (5, -3, -7), (-10, -6, 2), (7, -10, 2), (-5, -9, 3), (4, -1, -6), (9, 7, 2), (-5, -4, 3), (6, 1, -8), (3, 4, 2), (-8, 7, -10), (-9, 1, 5), (-6, -2, 9), (-3, 10, -7), (-1, -8, 5), (9, 6, 4), (-3, 5, 2), (-1, -10, -7), (-7, -2, 4), (8, -9, 6), (10, -1, -5), (1, -9, -4), (3, -7, 8), (10, -2, 5), (6, 7, -10), (4, -5, 1), (9, -8, -3), (1, -10, -9), (8, -4, -3), (2, -7, -5), (6, 2, 8), (10, 4, -1), (9, 3, -7), (8, 3, -7), (4, -5, -9), (2, 6, 1), (-6, 2, -4), (-9, -8, 7), (-5, -3, -10), (10, 1, 7), (-5, -4, 9), (-2, -3, 6), (-8, -3, -4), (6, -9, -5), (-1, -2, 7), (-8, -4, -9), (6, 2, -3), (-10, 5, 7), (-10, 2, -5), (-4, 1, -8), (-7, -6, -9), (7, -1, -5), (-6, -2, 9), (-8, 4, 10), (-5, 1, 10), (3, 6, 4), (-9, -7, 2), (-7, 2, 1), (6, 10, 4), (5, -8, 3), (1, 5, 2), (-7, -10, 8), (-4, 9, -6), (10, 2, -8), (-4, 1, -3), (-6, -9, 5), (10, -3, 5), (-8, 6, -9), (-1, 4, -2), (-9, 10, 5), (-1, -2, -3), (-8, 6, -4), (5, 8, 7), (-9, 10, -3), (-1, 2, -6), (-8, 6, -5), (9, 3, -4), (1, -2, 10), (10, -9, -4), (1, 6, -7), (-5, 3, -2), (-3, -5, -4), (-6, -7, -10), (1, -8, 2), (6, -9, -8), (-3, 1, -7), (-5, -10, 2), (7, -10, 6), (-1, -8, -2), (-3, 9, 5), (9, -6, -5), (7, -10, -3), (-2, 1, 4), (4, -3, 7), (8, -10, -2), (-6, -9, 5), (-10, -8, 7), (4, -9, 5), (-3, -2, -6), (10, 6, -3), (4, 2, 1), (9, 5, 7), (-1, -3, -7), (-9, -6, 5), (-2, -8, -10), (10, 1, -6), (-4, 2, -9), (3, -8, 7), (-8, -1, -2), (-7, -6, 10), (-3, -5, -9), (-6, -1, 9), (-2, -4, -10), (-3, 7, -8), (-6, 8, 2), (-4, -5, -3), (-7, -10, 9), (-4, 5, 6), (-10, -8, 3), (9, -7, 1), (7, -1, 2), (-8, -5, 6), (4, 10, 9), (2, 7, 6), (-3, -1, 5), (9, 10, 4), (5, 8, -4), (-7, 9, 3), (1, 10, -2), (-1, -10, -4), (-5, -3, -2), (7, -8, -6), (-10, -7, 6), (5, 3, 4), (-1, 8, 9), (7, -5, 4), (8, 6, 9), (-10, -3, -2), (2, -9, -8), (-10, -3, 7), (5, -6, 4), (-7, 9, -5), (-6, -4, 2), (-10, -8, -3), (-3, -8, -10), (7, -5, -2), (4, -1, -6), (-9, -3, 2), (-8, 1, -5), (-10, 4, -7), (4, -3, 9), (-10, -7, 8), (-5, 2, -6), (4, -3, -8), (5, 9, 1), (-10, 2, -6), (5, -3, 4), (7, -9, 8), (-10, -6, 1), (6, 7, -2), (4, -5, -9), (8, -10, -3), (10, -1, 4), (5, -7, -8), (6, 9, -3), (-7, 8, 1), (4, 5, 9), (-3, 6, -10), (-5, 4, -2), (8, -7, 6), (-3, 10, -1), (-5, -10, 2), (-8, -9, 4), (-6, -1, 3), (-9, 8, 4), (2, -6, 7), (-1, -10, 5), (1, -10, -9), (-5, 2, 6), (8, -7, -4), (8, -5, 6), (-1, 2, 7)]

# clauses = [(-6, -4, 7), (3, 9, -2), (10, -1, -8), (8, -1, -7), (-10, -5, 4), (6, 9, 3), (10, -6, 8), (7, -3, -4), (2, -5, 1), (-6, 9, -1), (-2, -4, -3), (7, -8, -5), (2, 10, -1), (-5, 8, 4), (-3, 9, 7), (-6, 3, 10), (8, 9, -7), (-2, -5, -4), (3, -7, -9), (-2, 10, -1), (-6, 4, 8), (6, 4, 5), (10, 9, -3), (8, -2, 1), (6, 9, -3), (1, -4, -2), (-8, -7, -10), (4, 5, 7), (3, 1, 10), (-2, -9, -6), (10, 2, 7), (-4, 6, -8), (5, -9, -1), (8, 10, 5), (3, 1, 4), (9, -2, -7), (-10, 1, 6), (2, -3, 7), (5, -9, -8), (3, 10, 4), (-7, 1, -8), (5, -2, -6), (-7, 3, -6), (10, 2, -4), (1, -5, -9), (-7, -10, 1), (9, 2, -6), (-3, 4, 5), (-5, -7, 6), (2, 4, 3), (10, 8, -1), (-1, -8, -2), (9, -3, 7), (6, -5, 4), (-3, 2, 6), (-5, -9, 1), (10, -8, -4), (8, 2, 7), (-1, 5, 6), (-9, -3, -10), (7, 2, -9), (10, 4, 6), (1, 5, 3), (-2, -5, -8), (-3, 1, -6), (4, -9, -7), (-7, 1, -8), (3, 5, 10), (6, -2, -4), (10, 3, 9), (-6, -5, -8), (-7, 1, 2), (2, -4, -7), (-9, 10, -3), (-8, -5, 1), (-1, -5, 6), (-9, 10, 3), (8, -4, 2), (-3, -9, -4), (10, -6, -1), (-2, 8, 5), (-2, -9, 1), (4, -3, 8), (6, -7, 5), (1, -3, -8), (4, 5, 9), (-7, 6, 2), (5, -6, -9), (3, 2, -7), (-8, 10, 4), (-8, 6, -4), (-3, -7, -1), (2, -10, 5), (2, -5, -7), (1, 6, 10), (9, 8, 4), (6, 4, 1), (-3, -10, 8), (7, 2, 5), (1, -10, 8), (9, -4, -6), (-2, 3, -5), (10, 7, -6), (-5, 1, 2), (-9, -8, 4), (-9, -8, 2), (-1, -3, -10), (6, -4, -7), (-10, -6, -1), (-8, 3, 7), (4, 9, -2), (-10, -8, 6), (-4, -5, 1), (-3, 7, 9), (8, 4, -6), (-5, -10, -2), (3, 9, -7), (-3, -7, 5), (6, -4, 8), (1, -10, 2), (2, -1, 4), (9, -6, 10), (-3, -7, 5), (6, 4, -1), (-8, -5, 3), (9, -7, -2), (10, 8, 9), (4, -5, -6), (-3, -7, 2), (-9, -2, -5), (10, -4, 6), (-1, 7, 8), (-2, -3, 6), (-9, -8, 5), (4, 7, -1), (-8, -5, -2), (3, 7, 9), (-1, 6, 4), (-7, -5, 1), (-8, 3, 2), (10, -6, 9), (-6, -9, -10), (1, -2, 4), (-3, 7, -5), (-10, 6, -3), (8, 9, 7), (2, -4, 5), (10, 7, -2), (3, -4, -5), (8, 9, -1), (-3, -6, 1), (-7, 2, -10), (4, 5, -9), (10, -4, -9), (7, 3, -5), (1, 2, -8), (-5, 4, 9), (-2, 6, -3), (7, 8, 1), (-6, -8, 3), (10, -7, -9), (-4, -1, 5), (2, 6, 3), (-1, -4, 5), (-10, -8, 9), (5, -2, -3), (-8, -7, 6), (10, 4, 1), (-7, -8, 1), (10, -9, -3), (6, -4, -5), (1, -10, -8), (-5, 9, -2), (3, -6, 7), (3, -9, -7), (-5, -6, 4), (-8, 2, 10), (2, -9, -1), (10, -3, -6), (5, -4, -7), (-2, 5, -4), (-1, 10, 8), (7, 6, 3), (-7, -5, 2), (-4, -3, -10), (6, 9, 8), (-2, -8, -5), (-6, 9, 10), (3, 7, -1), (-6, -2, -3), (10, 8, -1), (-7, 4, -9), (-3, 4, -5), (8, 6, 1), (-10, -9, -7), (-9, 5, -7), (-8, 3, 10), (-4, 2, 1), (5, -7, -8), (-3, -9, -1), (-6, 10, 4), (-2, 8, -7), (1, 9, -6), (3, 4, 5), (-2, 4, 6), (-5, -3, -8), (-1, -7, 9), (-3, -8, 9), (-2, 1, 7), (4, -10, -5), (4, 3, 1), (-7, -9, 6), (-2, -5, 8), (-2, 10, 3), (7, -5, 9), (-8, 6, 1), (2, 10, -3), (1, 4, -7), (8, 6, 5), (-6, -1, 3), (4, -5, -2), (8, 10, -9), (10, 2, 1), (-5, 3, 6), (8, -4, 9), (10, -2, 4), (-3, 9, 1), (8, -5, -6), (4, -9, -8), (7, 6, 1), (-10, 5, -2), (8, -10, 1), (2, 5, -9), (4, 6, 3), (-6, -9, -8), (-4, 10, -2), (-1, -3, -5), (2, -9, 1), (-3, 10, 6), (4, -5, 8), (1, -3, -6), (-2, 4, -9), (-10, -8, -5), (8, -10, -4), (-7, 1, -3), (-5, -9, -2), (7, -9, 6), (-4, 2, 8), (5, -3, 10), (-9, 7, 10), (-1, -8, 3), (2, 5, -4), (-8, -10, -9), (-4, 3, -6), (-7, 1, -2), (9, 3, -6), (10, 1, -2), (7, 5, -8), (-2, 10, 3), (-7, -1, -6), (-5, 9, 8), (8, -5, -7), (9, -2, 10), (-3, -6, 1), (-9, 1, 8), (2, 4, -10), (5, 6, 3), (3, -5, -8), (-6, -4, 10), (-1, 2, 9), (5, -2, 4), (-10, -9, 7), (8, 1, -6), (3, 2, 8), (7, -6, -5), (-1, 4, -9), (4, 8, -2), (7, 9, -1), (-3, -6, 10), (4, 10, -8), (-2, -3, -5), (-6, -7, 1), (4, 1, 5), (9, 6, -2), (-10, -8, 3), (-5, -6, 7), (-8, 2, -9), (3, 1, 10), (2, 7, 3), (8, -4, 10), (1, 5, 9), (-5, 7, 3), (8, 1, 4), (-10, -2, -6), (8, 6, 9), (-4, 7, -3), (1, -5, 2), (-3, -8, -4), (1, 9, 5), (-10, 7, -2), (-4, 6, 7), (-2, -10, -5), (9, 3, 8), (-4, -6, 2), (-5, 3, -1), (7, -10, 8), (4, -7, 8), (-2, -1, -9), (-5, 6, 3), (4, -5, 7), (-9, 2, -8), (-10, -3, -1), (1, -2, -9), (4, 5, 8), (-7, -6, 10), (8, -1, 9), (-5, 3, 10), (4, 2, 6), (10, -9, 6), (7, 4, 5), (8, 2, 3), (-7, 2, -4), (6, -9, 1), (-10, -5, 3), (-10, 7, -2), (-1, -6, -3), (-8, 5, 4), (7, 8, -3), (1, -6, -4), (5, 2, -10), (3, 4, 10), (-8, 5, 1), (-9, 6, 7), (-7, 10, -1), (-2, -5, 6), (3, -8, 4), (-4, 10, -7), (-1, -8, 2), (-6, -5, -9), (10, 9, -8), (-7, 4, -6), (1, -3, -5), (5, -3, -4), (-8, 9, -2), (-6, -10, -7), (6, -1, -7), (-8, -9, 5), (3, -2, 4), (1, -2, 7), (10, 3, -8), (-5, -6, 4), (-4, -7, -2), (-3, 5, -6), (1, -9, 10), (8, 5, -9), (-7, 6, -4), (-10, -3, 1), (6, 8, 5), (4, -10, -1), (7, -3, -2), (4, -2, -3), (7, 1, -8), (-6, -10, -9), (8, -7, -1), (6, -3, 2), (-9, -5, 10), (1, -8, -4), (-9, -7, -6), (2, -3, -5), (8, 10, 7), (-9, -4, -1), (-3, 2, -5), (-8, 4, -7), (10, -9, 6), (-5, -1, 3), (7, -1, 10), (-6, -9, 4), (2, 3, -8), (9, 3, -6), (-8, -4, 10), (1, 5, 2), (2, 7, -1), (-9, 3, 10), (-6, 8, -5), (4, 3, -6), (-8, -2, 1), (-10, -5, 7), (9, -8, 2), (4, 6, -5), (3, 7, -10), (9, 7, -8), (4, -1, 5), (10, -3, 6), (4, -5, 3), (-7, -2, -8), (6, -9, -10), (-5, 3, 8), (-2, -1, -9), (4, -10, -6), (7, 4, -2), (-5, -10, 3), (-9, 1, 6), (-7, -3, 2), (4, 1, 6), (9, -8, -5), (7, -5, 2), (3, 4, 10), (1, 8, -6), (-8, -9, -5), (4, 3, -1), (10, -7, 2), (8, -9, 3), (-4, 1, -10), (5, -6, 2), (-2, -6, 5), (-9, 8, 10), (-3, 7, 1), (5, 6, -7), (4, -8, -1), (3, -9, -2), (1, 8, 6), (-9, 2, -10), (-7, 5, 4), (-1, 8, 3), (5, 9, 10), (-2, 4, 7), (9, -3, -10), (2, -4, 8), (-6, 5, 7), (7, -2, 5), (4, -1, 3), (10, -9, -6), (-4, 1, -9), (5, 2, 7), (-10, -6, -8), (10, -9, -3), (1, 2, -5), (-4, 7, -8), (3, -8, -4), (-2, 7, -9), (-10, 6, -5), (-4, -5, 2), (-1, 8, -6), (-7, 10, 9), (-9, -7, 2), (1, 10, -5), (-3, 6, 8), (9, -7, -6), (2, 3, 1), (-4, -10, -8), (-4, 1, 9), (6, 3, -8), (7, -10, 2), (-2, 1, -6), (-10, -9, 3), (4, 8, 5), (-1, -7, 8), (-3, 4, -6), (10, 9, 2), (-10, 3, 7), (-2, 9, 1), (-8, -6, 5), (-10, -5, -3), (9, 7, 6), (-8, 1, -4), (-1, -5, 6), (-10, -2, 9), (7, 3, -4), (1, 2, 6), (5, 7, -3), (10, 8, 9), (3, 5, 9), (-4, 8, -2), (-1, -6, -10), (8, 7, -3), (-10, -2, 9), (5, 6, 1), (-9, 6, -8), (-3, 10, -5), (7, 2, 4), (2, 5, -6), (-7, 3, 1), (10, 8, -9), (1, 6, -10), (5, 4, 2), (-8, 7, -3), (-1, 3, 9), (-2, 10, -8), (-5, -4, -7), (-3, 10, -5), (7, -6, 9), (-2, -8, 4), (-5, 9, 8), (1, 6, -7), (-10, 3, -2), (-10, 5, -6), (-3, 8, 1), (-9, -7, -2), (-9, -3, -10), (-2, -8, -5)]

# clauses = [(-3, -2, -1), (6, 10, 7), (5, 4, -8), (-9, -5, 2), (-7, -3, -6), (10, 4, 8), (4, -6, 3), (-5, -8, -1), (-9, -2, 10), (9, -7, 3), (2, -6, 5), (-10, -1, 4), (5, 1, -10), (-3, -9, -8), (-7, -2, -6), (9, 10, -7), (-3, 2, 1), (6, 4, 8), (2, 4, -5), (9, 6, -10), (-3, 8, 7), (2, -4, -6), (-5, 9, 8), (-1, -3, -10), (-2, -9, -5), (-8, -6, -4), (-7, -1, -3), (7, -2, 6), (-9, 8, 1), (-5, 4, -10), (-3, -9, 2), (-6, 4, -10), (-8, 1, 7), (8, -9, 4), (10, 6, -5), (-1, -2, -7), (5, -6, 4), (-9, 8, -7), (-3, -2, 10), (-3, -7, 5), (-6, -9, 1), (-10, -8, 2), (5, 2, 7), (8, -6, -9), (-4, 1, 3), (-10, -8, -4), (3, -6, 2), (-7, 5, 1), (-10, -7, 8), (-2, 6, -4), (-5, -9, -1), (3, -9, -4), (8, -7, -1), (6, 5, -10), (-2, -5, -8), (7, 6, -1), (-9, -4, 3), (-8, -7, 2), (10, -9, 3), (4, 6, 5), (9, 5, -2), (-4, 3, -1), (-10, 7, -6), (8, 1, -6), (10, 4, 2), (7, 5, 3), (6, -5, 10), (3, 9, -7), (2, -1, -4), (-1, 3, -4), (7, -8, 6), (2, 5, -9), (6, -1, 3), (10, -8, -5), (2, -4, -9), (4, 1, -2), (7, -10, -3), (-8, 9, -5), (4, 3, -7), (-9, -2, -10), (5, 8, -6), (-7, -3, 8), (-2, -1, -10), (-4, -9, -5), (-3, -4, 10), (8, -7, -1), (6, -5, -2), (7, 4, 10), (3, 1, 6), (-2, -9, 5), (-6, -10, 2), (5, 7, 4), (-3, 9, -1), (1, -5, 8), (-6, 4, 7), (-3, 10, -2), (6, 5, 8), (-9, 2, 4), (10, -1, -3), (10, 3, -5), (-6, 8, -9), (4, -7, 2), (-2, 6, 8), (7, -10, 1), (4, -3, -5), (5, 8, 1), (-6, -10, 9), (-4, 3, 7), (-4, -9, -1), (2, 5, -7), (10, 3, 6), (2, -9, -7), (6, -5, 3), (-1, 10, 4), (10, -3, -9), (-7, -2, 6), (1, 5, 8), (-2, -6, -9), (-3, 8, -7), (-10, 4, -5), (-5, -1, 3), (2, 9, 10), (-8, 4, -6), (-8, 10, -7), (-5, -2, -6), (3, 9, -1), (1, 7, 5), (6, -2, 8), (3, -9, -4), (-6, 8, 4), (1, 7, 9), (5, -2, -10), (-8, -6, 2), (7, -3, 5), (-9, 4, 10), (2, 10, 7), (8, 1, 6), (-3, -5, 4), (5, -4, -1), (7, -3, -8), (10, 6, 9), (10, -1, 5), (-4, -6, -3), (2, -9, 8), (-1, -5, 9), (-6, -2, 4), (-3, -7, -8), (-4, -9, -2), (10, 8, 3), (5, -1, -7), (1, -3, -4), (-6, 8, 9), (-5, -7, 2), (-7, -9, 8), (-10, -6, -3), (-5, 2, -4), (-5, 10, 3), (8, 7, 2), (4, 6, 9), (9, 7, -10), (-3, -5, -2), (-4, -1, 6), (5, 1, 3), (-8, -10, -9), (-2, -6, 7), (-6, 9, -7), (-2, -4, 3), (8, 5, 1), (4, 1, 10), (6, -3, 7), (-8, -2, -5), (3, -4, 5), (7, -2, 1), (-6, -9, -8), (-5, -8, -1), (-9, 4, -2), (7, -6, 3), (-5, -2, 7), (4, 10, -3), (8, -1, -6), (6, 2, 7), (-5, 10, -4), (-3, 8, -1), (7, -3, -5), (-4, -1, 10), (6, 2, -9), (-1, 9, 8), (10, -3, -7), (5, 4, -2), (8, -7, -10), (6, 9, 5), (2, 3, -1), (-3, -8, 7), (-1, -4, -9), (10, 5, -6), (-4, -9, -5), (-10, 8, 7), (1, -3, 6), (-10, 4, -8), (5, 9, 6), (-2, -3, -1), (-8, 2, 1), (5, 6, -4), (7, 9, 10), (4, -3, 10), (1, 8, 7), (6, -5, 9), (10, 8, 4), (-2, -5, 6), (-3, -7, 1), (6, 3, 1), (-10, 9, -5), (7, -4, -8), (6, -8, -5), (3, 4, -1), (2, 9, 7), (9, 10, -8), (2, 4, -3), (-5, -7, -1), (8, -4, -9), (3, -2, 7), (-5, -1, -6), (-3, -7, 10), (1, -9, 2), (4, 8, -6), (3, -10, 1), (-7, 9, -5), (-4, -2, -6), (6, 7, 2), (10, -9, 5), (-4, 3, 1), (-2, 7, -8), (3, 4, 9), (-1, -6, 5), (-7, 6, -10), (1, -5, -2), (9, 3, -8), (9, -10, 3), (1, -5, -6), (2, -8, 4), (7, 8, -4), (2, 1, -10), (6, 5, 9), (-4, -2, -10), (-1, 9, -5), (3, 7, -8), (-3, -10, -8), (-9, 7, 4), (-2, -5, 6), (3, 10, -5), (6, 8, -9), (-4, 7, -1), (-9, 8, 6), (-10, 4, 7), (-3, -5, -1), (8, -7, -6), (2, -5, -10), (-9, -3, 1), (-8, 2, -4), (6, -1, -7), (-5, -9, -10), (-8, -1, 9), (5, -2, -3), (-10, 6, -7), (3, 4, 7), (-2, 1, -10), (6, -9, -5), (5, 2, -6), (7, -3, 8), (-1, -10, 4), (7, -6, 8), (-10, 2, 5), (9, 4, -1), (9, 1, 8), (4, -6, -7), (10, -2, -5), (-1, 10, 2), (-7, -6, -4), (-5, 9, 8), (-9, 7, 2), (-3, -8, -1), (-5, 6, -10), (3, -4, 8), (1, -10, 5), (-7, 9, 2), (-3, 10, -1), (5, -2, -6), (-9, -7, -8), (-8, -7, -5), (4, 9, 1), (-10, 2, 6), (-3, 9, -7), (-8, -2, 10), (6, 5, -4), (-4, 2, 6), (10, 9, -8), (-5, 1, 3), (-4, 7, 6), (-10, 8, -9), (-5, -1, -2), (-4, -3, -9), (-7, 2, 10), (-6, 5, 8), (10, 1, 7), (-2, 5, 9), (-3, 8, 6), (10, 8, 4), (-5, 2, -6), (-1, -3, -7), (-6, -3, -9), (-1, -8, 10), (7, 4, -5), (-8, -5, -2), (-6, -7, 9), (-4, 10, -3), (6, -3, 7), (4, 2, 9), (-8, 5, -10), (5, 3, 7), (6, 10, 9), (-2, 8, -4), (8, -5, -10), (-2, -9, 1), (7, 4, -6), (-5, -7, 8), (-6, 3, -2), (9, 1, 10), (5, 2, -7), (4, -8, -9), (6, -3, 1), (6, 8, -10), (-4, -2, 1), (7, 5, 9), (-9, 2, 5), (-7, -8, 4), (1, -6, 3), (10, -8, 3), (-4, -2, -7), (9, 6, 1), (7, 6, 8), (9, 2, 3), (-10, -5, -1), (-9, -4, -8), (-10, 1, 6), (2, 7, 3), (-5, 10, 1), (3, -7, 2), (-9, -8, 4), (10, 3, 1), (-6, -9, -2), (-4, 8, 5), (10, 2, -7), (-9, 1, -6), (4, -3, -8), (-2, 7, -5), (-10, 1, 4), (3, -6, -9), (-3, -1, 7), (-6, 8, -9), (2, 4, -10), (-9, -6, -1), (-2, 4, 5), (-10, 8, 7), (-4, 6, -2), (7, 3, -8), (-1, 5, 10), (-2, 5, 6), (3, 8, 7), (1, -10, 9), (-1, 10, -6), (-4, 3, 7), (2, -5, 9), (8, 2, 4), (-6, 1, -9), (-7, -5, -3), (1, 8, 4), (-7, 9, -6), (-10, 2, -3), (-6, -1, 8), (2, -3, 9), (-4, 7, -5), (-6, -7, -3), (2, 10, 9), (5, -8, -1), (2, -4, 7), (-6, -3, 8), (-1, -10, 5), (4, 3, -10), (9, 1, -7), (5, 2, 8), (-7, 2, -5), (-10, 1, 3), (-4, -6, 8), (5, 7, 10), (6, -3, -4), (-2, 1, -9), (5, 4, -9), (-7, -2, -3), (-10, 1, -8), (-2, -8, 4), (5, -7, -1), (-9, -3, -6), (3, -7, 1), (9, 4, -6), (-2, 5, 8), (-2, 6, 5), (10, -8, -7), (-9, -4, 1), (-8, -4, 2), (-7, -9, 6), (10, -1, 5), (4, 7, -3), (-5, 10, 1), (8, 9, -6), (6, 9, -1), (2, -4, -5), (3, 10, 7), (-1, -5, -7), (-10, 3, 8), (6, 4, 9), (-7, -2, 4), (-8, 6, -10), (-5, -1, 9), (-7, -1, 9), (-6, 2, -5), (10, -4, 8), (10, 5, 1), (-8, 2, -7), (3, 6, -9), (-1, 2, -7), (-10, 9, 4), (-3, 8, 5), (-3, 7, 4), (8, 9, 2), (10, 5, -1), (9, -6, -1), (-2, 5, -8), (10, -7, 4), (-5, -8, -10), (-1, -3, 2), (4, -9, 6), (1, 4, 10), (8, 9, -3), (6, -7, 2), (4, -9, -1), (10, -6, 2), (7, -5, -3), (2, 10, 6), (-9, 1, 4), (-8, -5, 3), (2, 4, 5), (10, -9, -7), (6, -8, -1), (2, -8, -3), (-1, -4, -6), (10, 5, -9), (7, -6, -3), (-4, 10, -5), (-1, -2, 8), (3, -8, -7), (6, 2, 10), (-5, 1, -4), (10, -8, -2), (4, 6, -1), (-7, 3, 9), (-10, 4, 9), (-8, -2, 1), (6, -7, -3), (-4, -9, -5), (1, 2, -10), (7, 3, 6), (4, -5, 7), (1, 8, -10), (3, -6, -9), (-1, -9, -6), (-5, -10, -4), (3, 7, 8), (-6, 5, 9), (3, -1, -8), (-10, 7, -2), (-6, -5, 1), (2, 3, 10), (-9, -4, 8), (-3, 9, -7), (-8, 6, -2), (-1, -5, -4), (-2, -7, -9), (5, -8, 3), (-4, 6, -1), (4, 9, 3), (-10, -5, -6), (-2, 7, -1), (7, 10, -2), (3, 1, 4), (8, -6, 5), (8, 9, 1), (2, -10, 5), (3, -4, 7), (-2, -6, -5), (-1, 4, -3)]

# clauses = [(-9, -36, 29), (26, -47, 34), (22, 33, -6), (32, -11, -8), (24, -27, -5), (45, -4, 46), (1, 28, -25), (39, -16, 15), (-20, 10, 13), (12, 43, 18), (40, 2, -23), (17, -21, 14), (41, 48, 38), (49, 35, -19), (-31, 3, -7), (30, -37, 44), (49, -47, -9), (-6, 2, 11), (39, -24, 14), (-30, -20, 41), (31, 28, 16), (42, -10, 15), (-5, 45, -29), (-46, 4, -18), (-8, 12, 3), (38, 44, -1), (-26, 22, 34), (7, -35, -17), (-32, -40, -27), (19, 50, -23), (43, 33, -37), (25, 21, 48), (8, 35, -30), (18, 34, -48), (-13, 29, 11), (-2, -6, -22), (17, 4, 37), (41, -23, -9), (10, 28, -45), (-1, -36, -25), (19, -47, 12), (24, -20, -50), (42, -49, 44), (-5, 38, -3), (-33, -27, -43), (-14, -26, -16), (40, -21, 15), (-7, 39, 46), (-27, 14, 30), (-45, -21, 15), (2, -13, -6), (-22, -25, -46), (-4, -17, 19), (26, -33, 38), (-12, 43, 48), (8, -41, 36), (31, -18, 49), (-39, 3, -29), (-11, -16, -40), (-42, -34, 5), (-32, 23, 35), (-28, 50, 9), (20, -24, 37), (-44, 10, -47), (32, -11, 20), (-37, -50, 38), (-10, -34, -19), (44, -18, 8), (-48, 4, 31), (-30, -43, 39), (2, 47, 33), (26, -7, 15), (-16, 45, -24), (-49, 5, -40), (14, -22, 12), (36, -46, 13), (-9, 17, -25), (-41, 3, 1), (35, 42, -23), (-29, 27, 6), (-7, -9, -35), (-43, 31, -14), (-24, -47, 19), (41, 40, -6), (33, -18, 46), (27, -22, -16), (21, -39, 12), (-28, 20, 11), (36, 30, 48), (-5, -25, -45), (-1, 2, 17), (-3, -49, -50), (-44, -13, 29), (-10, -8, 23), (37, 38, 26), (-32, 4, -34), (-27, 39, -24), (13, -28, 47), (-15, 37, 6), (-35, -3, -11), (8, -31, -18), (-25, -30, 46), (2, -29, 44), (1, 7, -12), (-17, 23, 4), (-49, -33, 34), (-48, -32, 16), (9, 50, -45), (5, 19, -43), (-20, 22, -14), (38, 36, 41), (-42, -26, -10), (-45, 7, 23), (28, 37, 21), (13, -17, 33), (-6, 50, -8), (41, 15, 4), (1, -49, -3), (-2, 35, -29), (-32, -9, -47), (-30, 11, -19), (20, 25, 40), (18, -27, 48), (-16, -12, 46), (42, 38, 10), (-39, 26, 24), (-34, 44, -22), (14, -5, 31), (36, 29, -34), (50, -10, -20), (-11, -5, -38), (30, 44, 45), (-33, -19, 48), (47, -7, -25), (13, -26, -9), (-49, -1, 15), (12, -41, 23), (46, 28, -18), (-39, 43, 31), (-27, 17, 14), (35, -37, -6), (3, -2, -8), (-21, 24, 42), (22, 40, -4), (47, -20, 4), (-24, 19, -37), (-12, 8, 39), (48, -17, -23), (-2, 44, -18), (43, -40, 41), (34, -45, -29), (-46, 27, -28), (-21, -38, -14), (49, -22, -33), (-15, -26, -50), (16, -36, -10), (9, 11, -31), (30, -3, 13), (35, 25, 1), (6, -42, -7), (-34, -27, -45), (33, 10, -24), (31, 28, -36), (-6, -50, -44), (12, 17, 46), (-38, 14, -29), (-47, -32, -37), (1, -18, -20), (4, -19, 25), (13, -15, 49), (5, -48, -43), (-30, -22, -23), (3, -7, 41), (39, 16, 9), (-2, 21, -26), (-42, -8, 40), (-19, 28, -17), (-9, 18, -8), (43, 22, -25), (41, -34, -49), (-10, -13, 35), (31, 5, -36), (32, -33, -2), (39, -30, -16), (46, 15, -24), (50, -1, -12), (20, -40, -23), (44, 7, -27), (-37, 38, 26), (42, -4, -45), (-6, 14, -3), (-11, -21, -29), (-17, -26, -22), (43, -32, 50), (33, -30, -46), (3, 7, 25), (19, -48, 45), (47, -6, 16), (1, -8, -36), (5, 35, 15), (34, 14, -12), (31, -42, -13), (-24, 37, 27), (20, 40, 21), (-9, -10, 41), (-29, -18, -11), (39, 4, 44), (23, 38, -2), (-21, -41, 2), (25, 42, 39), (50, 20, 24), (-46, 37, -4), (6, 13, 44), (-23, -17, 7), (14, 49, -8), (32, -27, 29), (45, 34, -47), (38, -18, 48), (43, 26, 5), (30, -16, -22), (-19, -33, 10), (-36, 28, 15), (31, -35, 9), (12, -11, 3), (49, -43, -6), (-42, 48, -41), (1, 39, 17), (-37, -32, -18), (-7, -35, -34), (19, 26, 29), (36, -47, 3), (30, 25, 14), (-11, -23, 46), (-31, 28, 20), (-16, 9, -13), (27, 15, -40), (-21, 8, 50), (-2, 45, -24), (-10, 44, 5), (4, -12, -22), (-44, 38, 23), (11, -29, -21), (15, 27, -37), (-10, -3, 34), (-49, 43, 14), (-46, 17, -5), (16, 2, 18), (-22, -33, -39), (7, 35, -25), (8, -47, -19), (1, 20, 12), (40, -31, 9), (-32, 13, 45), (24, -36, -30), (-50, -42, 4), (6, 28, -48), (-33, 20, -34), (9, -7, -43), (-2, 46, 13), (24, 42, 38), (17, -12, 36), (-29, -28, -50), (16, 26, -32), (19, -25, -18), (-47, 23, 10), (-30, -31, 22), (-40, 45, 37), (-27, -21, -35), (-44, -49, -41), (48, 11, 1), (-14, -8, -39), (-15, -5, -4), (29, 39, 17), (-31, -23, -47), (5, -2, 18), (15, -25, 45), (-28, 41, 27), (44, -10, -6), (3, 12, 26), (8, -48, -7), (-46, 1, 49), (30, -36, -32), (43, -11, -40), (4, -20, 37), (-21, 42, -38), (14, 35, -50), (-13, -24, -19), (9, -33, -22), (35, -18, -6), (-36, -42, 24), (-11, 26, 14), (1, -33, 50), (39, 34, 9), (7, 25, -28), (-16, 44, 37), (-43, -49, 47), (-40, 23, 22), (5, 12, -4), (-3, -8, 27), (32, -45, -38), (10, 2, 41), (29, 19, -20), (-48, 13, 17), (-46, -21, -31), (48, -5, 37), (-24, 49, -27), (40, -11, 23), (34, 35, -26), (-6, -29, -28), (-45, -1, 22), (-25, 9, -3), (44, 50, 12), (-2, -31, -15), (43, 33, 16), (46, -36, 21), (-38, -19, -47), (-13, 14, -7), (-41, 17, -32), (20, -8, -42), (-39, 4, -30), (-15, -14, -24), (50, -17, -36), (-46, 37, -35), (-27, 19, -33), (-41, 34, -31), (47, 6, -22), (25, 42, 38), (5, -10, 30), (-4, 9, 21), (1, 26, 29), (7, -39, -23), (40, -13, 32), (-45, 12, -43), (28, 49, -48), (16, -8, 2), (3, 11, -20), (48, 40, -26), (-1, -20, -37), (36, 49, 43), (-22, 5, 42), (-4, 38, 29), (18, -3, -28), (46, 24, -10), (35, -44, -30), (6, 25, 39), (-33, 19, 11), (14, -15, 23), (-7, -17, 32), (12, 13, 45), (-31, -50, -41), (34, -8, 2), (9, -47, 27), (49, -19, -39), (-13, 41, 26), (35, -18, 20), (33, 21, 1), (-37, 7, 44), (9, 40, -34), (-10, -14, 5), (-16, -48, 38), (28, 3, -4), (47, -46, 25), (-45, -22, 6), (-24, 36, 8), (-31, 2, -11), (-50, 15, 42), (-32, 27, -43), (-30, 23, -29), (-24, 27, -44), (-4, 16, 42), (38, -28, 47), (-40, -17, -43), (-31, -5, -15), (-19, -26, -46), (9, 50, -48), (-32, -29, 34), (-8, 36, -23), (-45, 10, -7), (-12, 41, 2), (-37, 25, 49), (11, 14, -6), (1, 3, -13), (-39, -22, 35), (-33, 20, 30), (35, 42, -4), (-20, 38, -31), (-36, 15, 16), (-30, 18, 25), (6, 14, 17), (-40, 8, 37), (11, 47, -9), (3, 13, -45), (-27, 12, 32), (21, -22, -10), (46, -26, 29), (-2, 33, 48), (-23, -19, 1), (5, 43, -44), (-41, 28, 7), (-24, 49, -34), (38, -32, 43), (-23, 25, -26), (-13, 33, 12), (42, 30, -40), (3, 46, -18), (-34, -24, -37), (28, 15, -49), (6, -7, 35), (-19, -39, 29), (-17, -22, -16), (8, 11, 2), (45, 41, 21), (-36, -50, 4), (-48, -27, -20), (31, -1, -9), (47, -14, 10), (-4, -7, -50), (46, -27, -6), (-24, 9, -18), (-15, 34, 40), (35, -3, 8), (42, -43, -33), (12, -29, -16), (11, -37, 20), (38, 22, 41), (26, -21, 44), (-13, -45, 39), (10, 25, 48), (36, -49, 17), (47, -14, 30), (-2, 31, -23), (-19, 32, 28), (-12, 27, -36), (6, 1, 29), (34, 45, 14), (2, -24, -19), (-46, -44, -21), (-48, -7, 13), (-40, 35, -25), (17, 23, -39), (30, 50, -42), (-41, 31, -22), (3, -20, 18), (-47, -5, 11), (43, 4, -33), (-15, -38, -10), (-8, 49, 26), (16, -9, 28), (-4, -6, -9), (42, 25, 26), (-44, 22, -28), (-40, -5, -20), (1, -39, 14), (-45, 7, -15), (41, 33, 35), (-16, 13, -36), (-48, 29, 37), (-31, -21, 30), (24, 8, 17), (3, -46, 10), (-19, 50, -12), (23, -11, -38), (-34, 47, -2), (-18, -27, 43), (31, -17, -30), (29, 21, -50), (-36, 28, -32), (-10, 16, -47), (-37, 14, 2), (41, 44, -9), (-1, -5, -49), (48, -7, 11), (23, 22, 43), (-45, 12, 39), (8, -18, 40), (46, -6, -4), (-25, -27, -15), (-3, 38, -34), (-13, 35, -33), (-26, 24, 20), (-10, 36, 39), (11, -38, -50), (24, -33, 43), (22, -16, 45), (37, -19, 6), (27, -35, 14), (13, -3, 48), (21, 15, 26), (-44, 34, 49), (-7, 18, -20), (-23, 46, 29), (28, -25, -30), (-12, -41, 31), (5, -17, -4), (-32, -47, -1), (9, 40, 2), (40, 30, 41), (3, 13, 47), (-48, 21, -22), (-39, -35, 18)]

wcnf = WCNF()
for each in clauses:
    wcnf.append(each, weight=1)

rc2 = RC2(wcnf)
model = rc2.compute()
print(model, rc2.cost)