示例#1
0
def get_constraint(idpool: IDPool, id2varmap,
                   constraint: tConstraint) -> CNFPlus:
    """ Generate formula for a given cardinality constraint"""
    validate_constraint(constraint)
    lits = []
    for ta in constraint.tas:
        t1 = tuple((constraint.course_name, ta))
        if t1 not in id2varmap.keys():
            id1 = idpool.id(t1)
            id2varmap[t1] = id1
        else:
            id1 = id2varmap[t1]
        lits.append(id1)

    if constraint.type == tCardType.GREATEROREQUALS:
        if (constraint.bound == 1):
            cnf = CNFPlus()
            cnf.append(lits)
        elif (constraint.bound > len(lits)):
            msg = "Num TAs available for constraint:" + constraint.con_str + "is more than the bound in the constraint. \
            Changing the bound to " + str(len(lits)) + ".\n"
            print(msg, file=sys.stderr)
            constraint.bound = len(lits)

        cnf = CardEnc.atleast(lits, vpool=idpool, bound=constraint.bound)
    elif constraint.type == tCardType.LESSOREQUALS:
        cnf = CardEnc.atmost(lits, vpool=idpool, bound=constraint.bound)
    return cnf
示例#2
0
    def dominating_subset(self, k=1):
        """
        Check if there exists a vertex cover of, at most, k-vertices.
        Accepts as params:
        - n_color: number of color to check
        - verbose: whether or not print the process
        """
        if not self.edges():
            return []

        logging.info('\nCodifying SAT Solver...')
        solver = Solver(name='cd')
        vpool = IDPool()
        vertices_ids = [vpool.id(vertex) for vertex in self.vertices()]

        logging.info(' -> Codifying: Every vertex must be accessible')
        for vertex in self.vertices():
            solver.add_clause([vpool.id(vertex)] + [
                vpool.id(adjacent_vertex) for adjacent_vertex in self[vertex]
            ])

        logging.info(' -> Codifying: At most', k,
                     'vertices should be selected')

        cnf = CardEnc.atmost(lits=vertices_ids, bound=k, vpool=vpool)
        solver.append_formula(cnf)

        logging.info('Running SAT Solver...')
        return solver.solve()
示例#3
0
文件: fm.py 项目: sschnug/pysat
    def relax_core(self):
        """
            Relax and bound the core.
        """

        if len(self.core) > 1:
            # relaxing
            rels = []

            for clid in self.core:
                self.topv += 1
                rels.append(self.topv)
                self.soft[clid].append(self.topv)

            # creating a new cardinality constraint
            am1 = CardEnc.atmost(lits=rels,
                                 top_id=self.topv,
                                 encoding=self.cenc)

            for cl in am1.clauses:
                self.hard.append(cl)

            # only if minicard
            # (for other solvers am1.atmosts should be empty)
            for am in am1.atmosts:
                self.atm1.append(am)

            self.topv = am1.nv

        elif len(self.core) == 1:  # unit core => simply negate the clause
            self.remove_unit_core()
示例#4
0
def prepare_hitman(pixels, inputs, intervals, htype):
    """
        Initialize a hitting set enumerator.
    """

    if not pixels:
        pixels = sorted(range(len(inputs)))

    # new Hitman object
    h = Hitman(htype=htype)

    # first variables should be related with the elements of the sets to hit
    # that is why we are adding soft clauses first
    for p in pixels:
        for v in range(intervals):
            var = h.idpool.id(tuple([inputs[p], v]))
            h.oracle.add_clause([-var], 1)

    # at most one value per pixel can be selected
    for p in pixels:
        lits = [h.idpool.id(tuple([inputs[p], v])) for v in range(intervals)]
        cnf = CardEnc.atmost(lits, encoding=EncType.pairwise)

        for cl in cnf.clauses:
            h.oracle.add_clause(cl)

    return h
示例#5
0
def test_atmostk():
    for l in range(5, 10):
        for k in range(2, l):
            for e in encs:
                cnf = CardEnc.atmost(lits=list(range(1, l + 1)), bound=k, encoding=getattr(EncType, e))

                # enumerating all models
                with MinisatGH(bootstrap_with=cnf) as solver:
                    for num, model in enumerate(solver.enum_models(), 1):
                        solver.add_clause([-l for l in model[:l]])

                assert num == sum([bincoeff(l, o + 1) for o in range(k)]) + 1, 'wrong number of models for AtMost-{0}-of-{1} ({2})'.format(k, l, e)
示例#6
0
    def to_cnf(self, x_vars, cnf):

        y_vars = [cnf.nv + i + 1 for i in range(self.out_dim)]
        cnf.nv = max(y_vars)

        for i in range(self.out_dim):
            C_i = -(self.sigma[i] /
                    self.alpha[i]) * self.gamma[i] + self.mu[i] - self.b[i]
            if self.alpha[i] > 0:
                C_i = np.ceil(C_i)
            elif self.alpha[i] < 0:
                C_i = np.floor(C_i)

            print(self.sigma[i], self.alpha[i], self.gamma[i], self.mu[i],
                  self.b[i])
            print(C_i)
            print(np.sum(self.A[i]))

            C_ = np.ceil(C_i / 2 + np.sum(self.A[i]) / 2)

            n_nega = sum(self.A[i] > 0)

            print(C_, n_nega)

            D = int(C_ + n_nega)

            print(D)

            lits = [x if a > 0 else -x for (x, a) in zip(x_vars, self.A[i])]

            amo = CardEnc.atmost(lits, D - 1, cnf.nv, EncType.seqcounter)

            r = amo.nv  # TODO: Check assumption that this is "r(n, D)" of AAAI paper

            print("Adding", len(amo.clauses), "AMO clauses")

            cnf.extend(amo.clauses)
            cnf.append([-r, y_vars[i]])
            cnf.append([r, -y_vars[i]])

            # ale = CardEnc.atleast(lits, D, cnf.nv, EncType.seqcounter)

            # r = ale.nv # TODO: Check assumption that this is "r(n, D)" of AAAI paper

            # print("Adding", len(ale.clauses), "ALE clauses")

            print(len(cnf.clauses))

            # cnf.extend(ale.clauses)
            # cnf.append([-r,  y_vars[i]])
            # cnf.append([ r, -y_vars[i]])
        return y_vars
示例#7
0
 def atmost(self, lits, bound=1, encoding=EncType.seqcounter):
     """
         **Added in SugarRush**\n
         Uses :meth:`pysat.card.CardEnc.atmost`.
         Adds automatic bookkeeping of literals.
     """
     cnf = CardEnc.atmost(lits=lits,
                          bound=bound,
                          encoding=encoding,
                          top_id=self._top_id())
     clauses = cnf.clauses
     self._add_lits_from(clauses)
     return clauses
示例#8
0
    def generate_medic_clauses(self):
        clauses = []

        for turn in range(self.num_turns):
            lits = [
                self.vpool.id((turn, row, col, IMMUNE_RECENTLY))
                for row in range(self.height) for col in range(self.width)
            ]
            clauses.extend(
                CardEnc.atmost(lits, bound=self.num_medics,
                               vpool=self.vpool).clauses)
        # TODO check case of 0 medics
        if self.num_medics == 0:
            return clauses

        for turn in range(self.num_turns - 1):
            for num_healthy in range(self.width * self.height):
                for healthy_tiles in itertools.combinations(
                        self.tiles, num_healthy):
                    sick_tiles = [
                        tile for tile in self.tiles
                        if tile not in healthy_tiles
                    ]
                    clause = []

                    for row, col in healthy_tiles:
                        clause.append(-self.vpool.id((turn, row, col,
                                                      HEALTHY)))

                    for row, col in sick_tiles:
                        clause.append(self.vpool.id((turn, row, col, HEALTHY)))

                    lits = [
                        self.vpool.id((turn + 1, row, col, IMMUNE_RECENTLY))
                        for row, col in healthy_tiles
                    ]
                    equals_clauses = CardEnc.equals(lits,
                                                    bound=min(
                                                        self.num_medics,
                                                        num_healthy),
                                                    vpool=self.vpool).clauses
                    for sub_clause in equals_clauses:
                        temp_clause = deepcopy(clause)
                        temp_clause += sub_clause
                        clauses.append(temp_clause)

        return clauses
示例#9
0
def test_atmost1():
    encs = list(
        filter(lambda name: not name.startswith('__') and name != 'native',
               dir(EncType)))
    for l in range(10, 20):
        for e in encs:
            cnf = CardEnc.atmost(lits=list(range(1, l + 1)),
                                 bound=1,
                                 encoding=getattr(EncType, e))

            # enumerating all models
            with MinisatGH(bootstrap_with=cnf) as solver:
                for num, model in enumerate(solver.enum_models(), 1):
                    solver.add_clause([-l for l in model[:l]])

            assert num == l + 1, 'wrong number of models for AtMost-1-of-{0} ({1})'.format(
                l, e)
示例#10
0
文件: fm.py 项目: RafalLopaciuk/PUPL
    def relax_core(self):
        """
            Relax and bound the core.

            After unsatisfiable core splitting, this method is called. If the
            core contains only one clause, i.e. this clause cannot be satisfied
            together with the hard clauses of the formula, the formula gets
            augmented with the negation of the clause (see
            :func:`remove_unit_core`).

            Otherwise (if the core contains more than one clause), every clause
            :math:`c` of the core is *relaxed*. This means a new *relaxation
            literal* is added to the clause, i.e. :math:`c\gets c\\vee r`,
            where :math:`r` is a fresh (unused) relaxation variable. After the
            clauses get relaxed, a new cardinality encoding is added to the
            formula enforcing the sum of the new relaxation variables to be not
            greater than 1, :math:`\sum_{c\in\phi}{r\leq 1}`, where
            :math:`\phi` denotes the unsatisfiable core.
        """

        if len(self.core) > 1:
            # relaxing
            rels = []

            for clid in self.core:
                self.topv += 1
                rels.append(self.topv)
                self.soft[clid].append(self.topv)

            # creating a new cardinality constraint
            am1 = CardEnc.atmost(lits=rels,
                                 top_id=self.topv,
                                 encoding=self.cenc)

            for cl in am1.clauses:
                self.hard.append(cl)

            # only if minicard
            # (for other solvers am1.atmosts should be empty)
            for am in am1.atmosts:
                self.atm1.append(am)

            self.topv = am1.nv

        elif len(self.core) == 1:  # unit core => simply negate the clause
            self.remove_unit_core()
示例#11
0
def test_atmost():
    vp = IDPool()
    n = 20
    b = 50
    assert n <= b

    lits = [vp.id(v) for v in range(1, n + 1)]
    top = vp.top

    G = CardEnc.atmost(lits, b, vpool=vp)

    assert len(G.clauses) == 0

    try:
        assert vp.top >= top
    except AssertionError as e:
        print(f"\nvp.top = {vp.top} (expected >= {top})\n")
        raise e
示例#12
0
文件: ex2.py 项目: AlexTuisov/HW2
    def hadar_dynamics(self):
        clauses = []

        for t in range(self.num_observations):
            clauses.extend(
                CardEnc.atmost(self.__get_I0_predicates(t),
                               bound=self.medics,
                               vpool=self.pool).clauses)

        if self.medics == 0:
            return clauses

        for t in range(self.num_observations - 1):
            for num_healthy in range(self.cols * self.rows):
                for healthy_tiles in itertools.combinations(
                        self.tiles, num_healthy):
                    sick_tiles = [
                        tile for tile in self.tiles
                        if tile not in healthy_tiles
                    ]
                    clause = []

                    for i, j in healthy_tiles:
                        clause.append(-self.obj2id[f"H_{i}_{j}^{t}"])

                    for i, j in sick_tiles:
                        clause.append(self.obj2id[f"H_{i}_{j}^{t}"])

                    lits = [
                        self.obj2id[f"I0_{i}_{j}^{t + 1}"]
                        for i, j in healthy_tiles
                    ]
                    equals_clauses = CardEnc.equals(lits,
                                                    bound=min(
                                                        self.medics,
                                                        num_healthy),
                                                    vpool=self.pool).clauses
                    for sub_clause in equals_clauses:
                        temp_clause = copy.deepcopy(clause)
                        temp_clause += sub_clause
                        clauses.append(temp_clause)

        return CNF(from_clauses=clauses)
示例#13
0
文件: ex2.py 项目: AlexTuisov/HW2
    def naveh_dynamics(self):
        clauses = []

        for t in range(1, self.num_observations):
            clauses.extend(
                CardEnc.atmost(self.__get_Q0_predicates(t),
                               bound=self.police,
                               vpool=self.pool).clauses)

        if self.police == 0:
            return clauses

        for t in range(self.num_observations - 1):
            for num_sick in range(self.cols * self.rows):
                for sick_tiles in itertools.combinations(self.tiles, num_sick):
                    healthy_tiles = [
                        tile for tile in self.tiles if tile not in sick_tiles
                    ]
                    for sick_state_perm in itertools.combinations_with_replacement(
                            self.possible_sick_states(t), num_sick):
                        clause = []

                        for (i, j), state in zip(sick_tiles, sick_state_perm):
                            clause.append(-self.obj2id[f"{state}_{i}_{j}^{t}"])
                        for i, j in healthy_tiles:
                            for state in self.possible_sick_states(t):
                                clause.append(
                                    self.obj2id[f"{state}_{i}_{j}^{t}"])

                        equals_clauses = CardEnc.equals(
                            lits=self.__get_Q0_predicates(t + 1),
                            bound=min(self.police, num_sick),
                            vpool=self.pool).clauses
                        for sub_clause in equals_clauses:
                            temp_clause = copy.deepcopy(clause)
                            temp_clause += sub_clause
                            clauses.append(temp_clause)

        return CNF(from_clauses=clauses)
示例#14
0
from pysat.formula import IDPool
from pysat.card import CardEnc

vp = IDPool()
n = 20
b = 50
assert n <= b

lits = [vp.id(v) for v in range(1, n + 1)]
top = vp.top

G = CardEnc.atmost(lits, b, vpool=vp)

assert len(G.clauses) == 0

try:
    assert vp.top >= top
except AssertionError as e:
    print(f"\nvp.top = {vp.top} (expected >= {top})\n")
    raise e
示例#15
0
def make_formula(n_police, n_medics, n_rows, n_cols, n_time):
    states = {'U', 'H', 'S', 'I', 'Q'}
    variables = {}
    formula = CNF()
    var_pool = IDPool()
    for t in range(n_time):
        for r in range(n_rows):
            for c in range(n_cols):
                for s in states:
                    variables[(r, c), t,
                              s] = var_pool.id(f'({r}, {c}), {t}, {s}')
                variables[(r, c), t, 'P'] = var_pool.id(
                    f'({r}, {c}), {t}, P')  # Police were used
                variables[(r, c), t, 'M'] = var_pool.id(
                    f'({r}, {c}), {t}, M')  # Medics were used
                variables[(r, c), t, 'SS'] = var_pool.id(
                    f'({r}, {c}), {t}, SS')  # Stayed sick from last time
    for t in range(n_time):
        formula.extend(
            CardEnc.atmost([
                variables[(r, c), t, 'P'] for r in range(n_rows)
                for c in range(n_cols)
            ],
                           bound=n_police,
                           vpool=var_pool))
        formula.extend(
            CardEnc.atmost([
                variables[(r, c), t, 'M'] for r in range(n_rows)
                for c in range(n_cols)
            ],
                           bound=n_medics,
                           vpool=var_pool))
        for r in range(n_rows):
            for c in range(n_cols):
                formula.extend(
                    CardEnc.equals([variables[(r, c), t, s] for s in states],
                                   vpool=var_pool))
                if t > 0:
                    formula.extend(
                        req_equiv([
                            -variables[(r, c), t - 1, 'Q'], variables[(r, c),
                                                                      t, 'Q']
                        ], [variables[(r, c), t, 'P']]))
                    formula.extend(
                        req_equiv([
                            -variables[(r, c), t - 1, 'I'], variables[(r, c),
                                                                      t, 'I']
                        ], [variables[(r, c), t, 'M']]))
                    formula.extend(
                        req_equiv([
                            variables[(r, c), t - 1, 'S'], variables[(r, c), t,
                                                                     'S']
                        ], [variables[(r, c), t, 'SS']]))
                    nearby_sick_condition = []
                    for r_, c_ in nearby(r, c, n_rows, n_cols):
                        nearby_sick_condition.append(variables[(r_, c_), t,
                                                               'SS'])
                        formula.extend(
                            req_imply([
                                variables[(r, c), t, 'SS'],
                                variables[(r_, c_), t - 1, 'H']
                            ], [
                                variables[(r_, c_), t, 'S'],
                                variables[(r_, c_), t, 'I']
                            ]))
                        # formula.extend(req_imply([variables[(r, c), t, 'SS']], [-variables[(r_, c_), t, 'H']]))
                    formula.extend(
                        req_imply([
                            variables[(r, c), t - 1, 'H'], variables[(r, c), t,
                                                                     'S']
                        ], nearby_sick_condition))
                if t + 1 < n_time:
                    formula.extend(
                        req_equiv([variables[(r, c), t, 'U']],
                                  [variables[(r, c), t + 1, 'U']]))
                    formula.extend(
                        req_imply([variables[(r, c), t, 'I']],
                                  [variables[(r, c), t + 1, 'I']]))
                    formula.extend(
                        req_imply([variables[(r, c), t + 1, 'S']], [
                            variables[(r, c), t, 'S'], variables[(r, c), t,
                                                                 'H']
                        ]))
                    formula.extend(
                        req_imply([variables[(r, c), t + 1, 'Q']], [
                            variables[(r, c), t, 'Q'], variables[(r, c), t,
                                                                 'S']
                        ]))
                if t == 0:
                    formula.append([-variables[(r, c), t, 'Q']])
                    formula.append([-variables[(r, c), t, 'I']])
                    if t + 1 < n_time:
                        formula.extend(
                            req_imply([variables[(r, c), t, 'S']], [
                                variables[(r, c), t + 1, 'S'],
                                variables[(r, c), t + 1, 'Q']
                            ]))
                        formula.extend(
                            req_imply([variables[(r, c), t, 'Q']],
                                      [variables[(r, c), t + 1, 'Q']]))
                    if t + 2 < n_time:
                        formula.extend(
                            req_imply([
                                variables[(r, c), t, 'S'],
                                variables[(r, c), t + 1, 'S']
                            ], [
                                variables[(r, c), t + 2, 'S'],
                                variables[(r, c), t + 2, 'Q']
                            ]))
                        formula.extend(
                            req_imply([
                                variables[(r, c), t, 'S'],
                                variables[(r, c), t + 1, 'Q']
                            ], [variables[(r, c), t + 2, 'Q']]))
                        formula.extend(
                            req_imply([variables[(r, c), t, 'Q']],
                                      [variables[(r, c), t + 2, 'H']]))
                    if t + 3 < n_time:
                        formula.extend(
                            req_imply([
                                variables[(r, c), t,
                                          'S'], variables[(r, c), t + 1, 'S'],
                                variables[(r, c), t + 2, 'S']
                            ], [variables[(r, c), t + 3, 'H']]))
                if 0 < t and t + 1 < n_time:
                    formula.extend(
                        req_imply([
                            -variables[(r, c), t - 1, 'S'], variables[(r, c),
                                                                      t, 'S']
                        ], [
                            variables[(r, c), t + 1, 'S'],
                            variables[(r, c), t + 1, 'Q']
                        ]))
                    formula.extend(
                        req_imply([
                            -variables[(r, c), t - 1, 'Q'], variables[(r, c),
                                                                      t, 'Q']
                        ], [variables[(r, c), t + 1, 'Q']]))
                if 0 < t and t + 2 < n_time:
                    formula.extend(
                        req_imply([
                            -variables[(r, c), t - 1, 'S'],
                            variables[(r, c), t, 'S'], variables[(r, c), t + 1,
                                                                 'S']
                        ], [
                            variables[(r, c), t + 2, 'S'],
                            variables[(r, c), t + 2, 'Q']
                        ]))
                    formula.extend(
                        req_imply([
                            -variables[(r, c), t - 1, 'S'],
                            variables[(r, c), t, 'S'], variables[(r, c), t + 1,
                                                                 'Q']
                        ], [variables[(r, c), t + 2, 'Q']]))
                    formula.extend(
                        req_imply([
                            -variables[(r, c), t - 1, 'Q'], variables[(r, c),
                                                                      t, 'Q']
                        ], [variables[(r, c), t + 2, 'H']]))
                if 0 < t and t + 3 < n_time:
                    formula.extend(
                        req_imply([
                            -variables[(r, c), t - 1, 'S'], variables[(r, c),
                                                                      t, 'S'],
                            variables[(r, c), t + 1,
                                      'S'], variables[(r, c), t + 2, 'S']
                        ], [variables[(r, c), t + 3, 'H']]))
    return var_pool, formula
示例#16
0
文件: ex2.py 项目: AlexTuisov/HW2
def buildClausesAndEffects(b, nRows, nCols, nPolice, nMedics, actionToIndex,
                           atomsToIndex):
    actionClauses = []
    mapIndicesList = buildMapIndices(nRows, nCols)
    DeseaseSpread = AllPossibleInfectionIndices(nRows, nCols)
    actionEffectsAtPreviousT = {}
    for roundT in range(b - 1):
        actionEffectsAtT = {}
        for idx in mapIndicesList:
            for p in range(nPolice):
                actionIndex = actionToIndex[("Q", p, roundT, idx)]
                curClauses, curPre, curAdd, curDel = modelAgentQAction(
                    b, actionIndex, roundT, idx, atomsToIndex)
                actionEffectsAtT[actionIndex] = (curPre, curAdd, curDel)
                actionClauses += curClauses
            for m in range(nMedics):
                actionIndex = actionToIndex[("V", m, roundT, idx)]
                curClauses, curPre, curAdd, curDel = modelAgentVAction(
                    b, actionIndex, roundT, idx, atomsToIndex)
                actionEffectsAtT[actionIndex] = (curPre, curAdd, curDel)
                actionClauses += curClauses
        for idx in mapIndicesList:  # at most 1 quarantine and at most 1 vaccination in each place in the map
            qvars = [
                actionToIndex[("Q", p, roundT, idx)] for p in range(nPolice)
            ]
            ivars = [
                actionToIndex[("V", m, roundT, idx)] for m in range(nMedics)
            ]
            actionClauses += CardEnc.atmost(lits=qvars,
                                            encoding=EncType.pairwise,
                                            bound=1).clauses
            actionClauses += CardEnc.atmost(lits=ivars,
                                            encoding=EncType.pairwise,
                                            bound=1).clauses
        for p in range(
                nPolice):  # each police can be used at most once each turn
            qvars = [
                actionToIndex[("Q", p, roundT, idx)] for idx in mapIndicesList
            ]
            actionClauses += CardEnc.atmost(lits=qvars,
                                            encoding=EncType.pairwise,
                                            bound=1).clauses
        for m in range(
                nMedics):  # each medic can be used at most once each turn
            ivars = [
                actionToIndex[("V", m, roundT, idx)] for idx in mapIndicesList
            ]
            actionClauses += CardEnc.atmost(lits=ivars,
                                            encoding=EncType.pairwise,
                                            bound=1).clauses
        for p in range(nPolice):
            actionClauses += [[
                -actionToIndex[("Q", p, roundT, idx)],
                atomsToIndex[("Q", p, roundT)]
            ] for idx in mapIndicesList]
            actionClauses += [[-atomsToIndex[("Q", p, roundT)]] + [
                actionToIndex[("Q", p, roundT, idx)] for idx in mapIndicesList
            ]]
        for m in range(nMedics):
            actionClauses += [[
                -actionToIndex[("V", m, roundT, idx)],
                atomsToIndex[("V", m, roundT)]
            ] for idx in mapIndicesList]
            actionClauses += [[-atomsToIndex[("V", m, roundT)]] + [
                actionToIndex[("V", m, roundT, idx)] for idx in mapIndicesList
            ]]

        for pair in DeseaseSpread:
            actionIndex = actionToIndex[(roundT, pair)]
            curClauses, curPre, curAdd, curDel = ModelInfection(
                b, roundT, pair, atomsToIndex, actionIndex)
            actionEffectsAtT[actionIndex] = (curPre, curAdd, curDel)
            actionClauses += curClauses

        for atom, atomIdx in atomsToIndex.items():
            if atom[0] == roundT:
                add = atomsToIndex[(atom[0] + 1, atom[1], atom[2])]
                cur_state = atom[2]
                actionIdx = actionToIndex[atomIdx]
                actionEffectsAtT[actionToIndex[atomIdx]] = ([atomIdx], [add],
                                                            [])
                actionClauses.append([-actionIdx, atomIdx])
                if cur_state == "H":
                    required = [
                        atomsToIndex[("V", m, roundT)] for m in range(nMedics)
                    ]
                    for req in required:
                        actionClauses.append([req, -actionIdx])
                    row, col = atom[1][0], atom[1][1]
                    for neighbor in [(row - 1, col), (row + 1, col),
                                     (row, col - 1), (row, col + 1)]:
                        if 0 <= neighbor[0] <= nRows - 1 and 0 <= neighbor[
                                1] <= nCols - 1:
                            actionClauses.append([
                                -actionIdx,
                                atomsToIndex[(roundT + 1, neighbor, "Q")],
                                -atomsToIndex[(roundT, neighbor, "S")]
                            ])
                if cur_state == "Q":
                    if roundT >= 1:
                        preC = [
                            atomsToIndex[(roundT, atom[1], "Q")],
                            atomsToIndex[(roundT - 1, atom[1], "Q")]
                        ]
                        clause = [-actionIdx]
                        for pre in preC:
                            clause.append(-pre)
                        actionClauses.append(clause)
                if cur_state == "S":
                    required = [
                        atomsToIndex[("Q", p, roundT)] for p in range(nPolice)
                    ]
                    for req in required:
                        actionClauses.append([req, -actionIdx])
                    if roundT >= 2:
                        preC = [
                            atomsToIndex[(roundT, atom[1], "S")],
                            atomsToIndex[(roundT - 1, atom[1], "S")],
                            atomsToIndex[(roundT - 2, atom[1], "S")]
                        ]
                        clause = [-actionIdx]
                        for pre in preC:
                            clause.append(-pre)
                        actionClauses.append(clause)

        if roundT >= 2:
            for idx in mapIndicesList:
                actionIndex = actionToIndex[("heal", roundT, idx)]
                curClauses, curPre, curAdd, curDel = ModelHealing(
                    roundT, idx, atomsToIndex, actionIndex)
                actionEffectsAtT[actionIndex] = (curPre, curAdd, curDel)
                actionClauses += curClauses

        if roundT >= 1:
            for idx in mapIndicesList:
                actionIndex = actionToIndex[("exitQ", roundT, idx)]
                curClauses, curPre, curAdd, curDel = ModelExitQ(
                    roundT, idx, atomsToIndex, actionIndex)
                actionEffectsAtT[actionIndex] = (curPre, curAdd, curDel)
                actionClauses += curClauses

        interferClauses = BuildInterferClauses(actionEffectsAtT)
        actionClauses += interferClauses
        if roundT >= 1:
            factAchieveClauses = BuildFactAchieveClauses(
                actionEffectsAtPreviousT, atomsToIndex, roundT)
            actionClauses += factAchieveClauses

        actionEffectsAtPreviousT = actionEffectsAtT

    if actionEffectsAtPreviousT != {}:
        factAchieveClauses = BuildFactAchieveClauses(actionEffectsAtPreviousT,
                                                     atomsToIndex, b - 1)
        actionClauses += factAchieveClauses

    return actionClauses
示例#17
0
    def generate_police_clauses(self):
        clauses = []

        for turn in range(1, self.num_turns):
            lits = [
                self.vpool.id((turn, row, col, QUARANTINED_1))
                for row in range(self.height) for col in range(self.width)
            ]
            clauses.extend(
                CardEnc.atmost(lits, bound=self.num_police,
                               vpool=self.vpool).clauses)
        # TODO check case of 0 policemen
        if self.num_police == 0:
            return clauses

        for turn in range(self.num_turns - 1):
            for num_sick in range(self.width * self.height):
                for sick_tiles in itertools.combinations(self.tiles, num_sick):
                    healthy_tiles = [
                        tile for tile in self.tiles if tile not in sick_tiles
                    ]
                    # TODO don't iterate over all sick states
                    for sick_state_perm in \
                            itertools.combinations_with_replacement(self.possible_sick_states(turn), num_sick):
                        clause = []

                        for (row, col), state in zip(sick_tiles,
                                                     sick_state_perm):
                            clause.append(-self.vpool.id((turn, row, col,
                                                          state)))
                        for row, col in healthy_tiles:
                            for state in self.possible_sick_states(turn):
                                clause.append(
                                    self.vpool.id((turn, row, col, state)))

                        lits = [
                            self.vpool.id((turn + 1, row, col, QUARANTINED_1))
                            for row, col in sick_tiles
                        ]
                        equals_clauses = CardEnc.equals(
                            lits,
                            bound=min(self.num_police, num_sick),
                            vpool=self.vpool).clauses
                        for sub_clause in equals_clauses:
                            temp_clause = deepcopy(clause)
                            temp_clause += sub_clause
                            clauses.append(temp_clause)

                        # if num_sick <= self.num_police:
                        #     for (row, col) in sick_tiles:
                        #         temp_clause = deepcopy(clause)
                        #         temp_clause.append(self.vpool.id((turn+1, row, col, QUARANTINED_1)))
                        #         clauses.extend(temp_clause)
                        #
                        #     # for (row, col) in healthy_tiles:
                        #     #     temp_clause = deepcopy(clause)
                        #     #     temp_clause.append(-self.vpool.id((turn+1, row, col, QUARANTINED_1)))
                        #     #     clauses.extend(temp_clause)
                        #
                        # else:
                        #     lits = [self.vpool.id((turn+1, row, col, QUARANTINED_1))
                        #             for row in range(self.height)
                        #             for col in range(self.width)]
                        #     equals_clauses = CardEnc.equals(lits, bound=self.num_police, vpool=self.vpool)
                        #
                        #     for sub_clause in equals_clauses.clauses():
                        #         temp_clause = deepcopy(clause)
                        #         temp_clause += sub_clause
                        #         clauses.extend(temp_clause)
        return clauses