示例#1
0
    def _assert_lt(self, cost):
        """
            The method enforces an upper bound on the cost of the MaxSAT
            solution. This is done by encoding the sum of all soft clause
            selectors with the use the iterative totalizer encoding, i.e.
            :class:`.ITotalizer`. Note that the sum is created once, at the
            beginning. Each of the following calls to this method only enforces
            the upper bound on the created sum by adding the corresponding unit
            size clause. Each such clause is added on the fly with no restart
            of the underlying SAT oracle.

            :param cost: the cost of the next MaxSAT solution is enforced to be
                *lower* than this current cost

            :type cost: int
        """

        if self.tot == None:
            self.tot = ITotalizer(lits=self.sels, ubound=cost-1, top_id=self.topv)
            self.topv = self.tot.top_id

            for cl in self.tot.cnf.clauses:
                self.oracle.add_clause(cl)

        self.oracle.add_clause([-self.tot.rhs[cost-1]])
示例#2
0
 def itotalizer(self, lits, ubound=None):
     """
         **Added in SugarRush**\n
         Uses :meth:`pysat.card.ITotalizer`.
         Adds automatic bookkeeping of literals.
     """
     if ubound is None:
         ubound = len(lits)
     itot = ITotalizer(lits, ubound)
     clauses = itot.cnf.clauses
     bound_vars = itot.rhs
     self._add_lits_from(clauses)
     return clauses, bound_vars
示例#3
0
def calc_sensitivity(model):
    n_eq = 0
    it = ITotalizer(lits=[model['net_map'][n] for n in model['flip_outputs']],
                    top_id=len(model['net_map']),
                    ubound=len(model['inputs']))
    solver = Cadical(bootstrap_with=model['clauses'] + it.cnf.clauses)
    while True:
        if solver.solve(assumptions=[-it.rhs[n_eq]]):
            break
        else:
            n_eq += 1

        if n_eq == len(model['inputs']):
            print('0 sensitivity reached')
            exit()

    model['sensitivity'] = (len(model['inputs']) - n_eq) / len(model['inputs'])
示例#4
0
    def _assert_lt(self, cost):
        """
            The method enforces an upper bound on the cost of the MaxSAT
            solution. For unweighted problems, this is done by encoding the sum
            of all soft clause selectors with the use the iterative totalizer
            encoding, i.e. :class:`.ITotalizer`. Note that the sum is created
            once, at the beginning. Each of the following calls to this method
            only enforces the upper bound on the created sum by adding the
            corresponding unit size clause. For weighted problems, the PB
            encoding given through the :meth:`__init__` method is used.
            Each such clause is added on the fly with no restart of the
            underlying SAT oracle.

            :param cost: the cost of the next MaxSAT solution is enforced to be
                *lower* than this current cost

            :type cost: int
        """

        if self.is_weighted:
            # TODO: use incremental PB encoding
            self.oracle.append_formula(
                PBEnc.leq(self.sels,
                          weights=self.formula.wght,
                          bound=cost - 1,
                          vpool=self.vpool))
        else:

            if self.tot is None:
                self.tot = ITotalizer(lits=self.sels,
                                      ubound=cost - 1,
                                      top_id=self.vpool.top)
                self.vpool.top = self.tot.top_id

                for cl in self.tot.cnf.clauses:
                    self.oracle.add_clause(cl)

            self.oracle.add_clause([-self.tot.rhs[cost - 1]])
示例#5
0
    def create_sum(self, bound=1):
        """
            Create a totalizer object encoding a new cardinality constraint.
            For Minicard, native atmostb constraints is used instead.
        """

        if self.solver != 'mc':  # standard totalizer-based encoding
            # new totalizer sum
            t = ITotalizer(lits=self.rels, ubound=bound, top_id=self.topv)

            # updating top variable id
            self.topv = t.top_id

            # adding its clauses to oracle
            for cl in t.cnf.clauses:
                self.oracle.add_clause(cl)
        else:
            # for minicard, use native cardinality constraints instead of the
            # standard totalizer, i.e. create a new (empty) totalizer sum and
            # fill it with the necessary data supported by minicard
            t = ITotalizer()
            t.lits = self.rels

            self.topv += 1  # a new variable will represent the bound

            # proper initial bound
            t.rhs = [None] * (len(t.lits))
            t.rhs[bound] = self.topv

            # new atmostb constraint instrumented with
            # an implication and represented natively
            rhs = len(t.lits)
            amb = [[-self.topv] * (rhs - bound) + t.lits, rhs]

            # add constraint to the solver
            self.oracle.add_atmost(*amb)

        return t
示例#6
0
    for inp_con in other_inputs:
        c.nodes[f'flip_{inp}_{inp_con}']['gate'] = 'buf'
        c.add_edge(inp_con, f'flip_{inp}_{inp_con}')

    # add output xnor
    c.add_node(f'flip_{inp}_output_xnor', gate='xnor')
    c.add_edge(f'flip_{inp}_out', f'flip_{inp}_output_xnor')
    c.add_edge('out', f'flip_{inp}_output_xnor')
    flip_outputs.append(f'flip_{inp}_output_xnor')

# get dimacs
clauses, net_map = gates2dimacs(c)

# encode sensitivity value
it = ITotalizer(lits=[net_map[n] for n in flip_outputs],
                top_id=len(net_map),
                ubound=len(protected_inputs))
solver = Cadical(bootstrap_with=clauses + it.cnf.clauses)

# find max sensitivity input, check
n_eq = 0
while n_eq < len(protected_inputs):
    if solver.solve(assumptions=[-it.rhs[n_eq]]):
        # get input output
        m = solver.get_model()
        inp = {i: m[net_map[i] - 1] > 0 for i in protected_inputs}
        s = (len(protected_inputs) - n_eq) / len(protected_inputs)
        print(f'found input w/ sensitivity {s}')

        # check input against key
        if all(inp[f'protected_in_{i}_'] == k for i, k in enumerate(key)):