コード例 #1
0
    def main(self, ctl: Control, files: Sequence[str]):
        '''
        The main function implementing incremental solving.
        '''
        if not files:
            files = ["-"]
        for file_ in files:
            ctl.load(file_)
        ctl.add("check", ["t"], "#external query(t).")

        conf = self._conf
        step = 0
        ret: Optional[SolveResult] = None

        while ((conf.imax is None or step < conf.imax)
               and (ret is None or step < conf.imin or
                    ((conf.istop == "SAT" and not ret.satisfiable) or
                     (conf.istop == "UNSAT" and not ret.unsatisfiable) or
                     (conf.istop == "UNKNOWN" and not ret.unknown)))):
            parts = []
            parts.append(("check", [Number(step)]))
            if step > 0:
                ctl.release_external(Function("query", [Number(step - 1)]))
                parts.append(("step", [Number(step)]))
            else:
                parts.append(("base", []))
            ctl.ground(parts)

            ctl.assign_external(Function("query", [Number(step)]), True)
            ret, step = cast(SolveResult, ctl.solve()), step + 1
コード例 #2
0
 def acyc_edge(self, node_u: int, node_v: int,
               condition: Sequence[int]) -> None:
     self._output(
         "edge",
         [Number(node_u),
          Number(node_v),
          self._lit_tuple(condition)])
コード例 #3
0
 def theory_atom(self, atom_id_or_zero: int, term_id: int,
                 elements: Sequence[int]) -> None:
     tuple_e_id = self._tuple("theory_element_tuple",
                              self._step_data.theory_element_tuples,
                              elements, _lit)
     self._output("theory_atom",
                  [Number(atom_id_or_zero),
                   Number(term_id), tuple_e_id])
コード例 #4
0
 def heuristic(self, atom: int, type_: HeuristicType, bias: int,
               priority: int, condition: Sequence[int]) -> None:
     type_name = str(type_).replace('HeuristicType.',
                                    '').lower().rstrip('_')
     condition_lit = self._lit_tuple(condition)
     self._output("heuristic", [
         Number(atom),
         Function(type_name),
         Number(bias),
         Number(priority), condition_lit
     ])
コード例 #5
0
 def product_and_infra_agent_connector(
     self, source_agent: Number, target_agent: Number
 ) -> Symbol:
     src_agent_number = source_agent.number
     tgt_agent_number = target_agent.number
     # Since clingo doesn't support Boolean return, we are returning
     # Number(1) for true, and Number(0) for false.
     if tgt_agent_number * 3 + 200 < src_agent_number:
         return Number(1)
     else:
         return Number(0)
コード例 #6
0
    def calculate_sccs(self) -> None:
        '''
        Trigger computation of SCCs.

        SCCs can only be computed if the Reifier has been initialized with
        `calculate_sccs=True`, This function is called automatically if
        `reify_steps=True` has been set when initializing the Reifier.
        '''
        for idx, scc in enumerate(self._step_data.graph.tarjan()):
            for atm in scc:
                self._output('scc', [Number(idx), Number(atm)])
コード例 #7
0
 def theory_atom_with_guard(self, atom_id_or_zero: int, term_id: int,
                            elements: Sequence[int], operator_id: int,
                            right_hand_side_id: int) -> None:
     tuple_id = self._tuple("theory_element_tuple",
                            self._step_data.theory_element_tuples, elements,
                            _lit)
     self._output("theory_atom", [
         Number(atom_id_or_zero),
         Number(term_id), tuple_id,
         Number(operator_id),
         Number(right_hand_side_id)
     ])
コード例 #8
0
 def theory_term_compound(self, term_id: int, name_id_or_type: int,
                          arguments: Sequence[int]) -> None:
     names = {-1: "tuple", -2: "set", -3: "list"}
     if name_id_or_type in names:
         name = "theory_sequence"
         value = Function(names[name_id_or_type])
     else:
         name = "theory_function"
         value = Number(name_id_or_type)
     tuple_id = self._tuple("theory_tuple", self._step_data.theory_tuples,
                            arguments, _theory, True)
     self._output(name, [Number(term_id), value, tuple_id])
コード例 #9
0
def _evaluate(term: TheoryTerm) -> Symbol:
    '''
    Evaluates the operators in a theory term in the same fashion as clingo
    evaluates its arithmetic functions.
    '''
    # tuples
    if term.type == TheoryTermType.Tuple:
        return Tuple_([_evaluate(x) for x in term.arguments])

    # functions and arithmetic operations
    if term.type == TheoryTermType.Function:
        # binary operations
        if term.name in _BOP and len(term.arguments) == 2:
            term_a = _evaluate(term.arguments[0])
            term_b = _evaluate(term.arguments[1])

            if term_a.type != SymbolType.Number or term_b.type != SymbolType.Number:
                raise RuntimeError("Invalid Binary Operation")

            if term.name in ("/", "\\") and term_b.number == 0:
                raise RuntimeError("Division by Zero")

            return Number(_BOP[term.name](term_a.number, term_b.number))

        # unary operations
        if term.name == "-" and len(term.arguments) == 1:
            term_a = _evaluate(term.arguments[0])

            if term_a.type == SymbolType.Number:
                return Number(-term_a.number)

            if term_a.type == SymbolType.Function and term_a.name:
                return Function(term_a.name, term_a.arguments,
                                not term_a.positive)

            raise RuntimeError("Invalid Unary Operation")

        # functions
        return Function(term.name, [_evaluate(x) for x in term.arguments])

    # constants
    if term.type == TheoryTermType.Symbol:
        return Function(term.name)

    # numbers
    if term.type == TheoryTermType.Number:
        return Number(term.number)

    raise RuntimeError("Invalid Syntax")
コード例 #10
0
    def main(self, ctl: Control, files: Sequence[str]):
        '''
        Register the difference constraint propagator, and then ground and
        solve.
        '''
        ctl.register_propagator(self._propagator)
        ctl.add("base", [], THEORY)

        if not files:
            files = ["-"]
        self._rewrite(ctl, files)

        ctl.ground([("base", [])])
        if self._minimize is None:
            ctl.solve(on_model=self._propagator.on_model)
        else:
            ctl.add("bound", ["b", "v"], "&diff(head) { v-0 } <= b.")

            while cast(SolveResult,
                       ctl.solve(on_model=self._on_model)).satisfiable:
                print("Found new bound: {}".format(self._bound))
                if self._bound is None:
                    break
                ctl.ground([
                    ("bound",
                     [Number(cast(int, self._bound) - 1), self._minimize])
                ])

            if self._bound is not None:
                print("Optimum found")
コード例 #11
0
 def weight_rule(self, choice: bool, head: Sequence[int], lower_bound: int,
                 body: Sequence[Tuple[int, int]]) -> None:
     hn = "choice" if choice else "disjunction"
     hd = Function(hn, [self._atom_tuple(head)])
     bd = Function("sum", [self._wlit_tuple(body), Number(lower_bound)])
     self._output("rule", [hd, bd])
     self._add_edges(head, [lit for lit, w in body])
コード例 #12
0
    def _tuple(self,
               name: str,
               snmap: Dict[Sequence[U], int],
               elems: Sequence[U],
               afun: Callable[[Symbol, int, U], Sequence[Symbol]],
               ordered: bool = False) -> Symbol:
        pruned: Sequence[U]
        if ordered:
            pruned = elems
            ident = tuple(elems)
        else:
            seen = set()
            pruned = []
            for elem in elems:
                if elem not in seen:
                    seen.add(elem)
                    pruned.append(elem)
            ident = tuple(sorted(pruned))

        n = len(snmap)
        i = Number(snmap.setdefault(ident, n))
        if n == i.number:
            self._output(name, [i])
            for idx, atm in enumerate(pruned):
                self._output(name, afun(i, idx, atm))
        return i
コード例 #13
0
 def divisors(sym: Symbol) -> Iterator[Symbol]:
     '''
     Return all divisors of the given number.
     '''
     num = sym.number
     for i in range(1, num + 1):
         if num % i == 0:
             yield Number(i)
コード例 #14
0
 def theory_element(self, element_id: int, terms: Sequence[int],
                    condition: Sequence[int]) -> None:
     tuple_id = self._tuple("theory_tuple", self._step_data.theory_tuples,
                            terms, _theory, True)
     condition_id = self._tuple("literal_tuple", self._step_data.lit_tuples,
                                condition, _lit)
     self._output("theory_element",
                  [Number(element_id), tuple_id, condition_id])
コード例 #15
0
 def get_assignment(self) -> List[Tuple[Node, Weight]]:
     '''
     Get the current assignment to integer variables.
     '''
     zero = Number(0)
     adjust = self._potential[zero] if zero in self._potential else 0
     return [(node, adjust - self._potential[node])
             for node in self._potential if node != zero]
コード例 #16
0
 def on_model(self, model: Model):
     '''
     This function should be called when a model has been found to extend it
     with the integer variable assignments.
     '''
     assignment = self._state(model.thread_id).get_assignment()
     model.extend([
         Function("dl", [var, Number(value)]) for var, value in assignment
     ])
コード例 #17
0
 def agent_connector(
     self,
     source_agent: Number,
     target_agent: Number,
     source_level: Number,
     target_level: Number,
 ) -> Symbol:
     src_agent_number = source_agent.number
     tgt_agent_number = target_agent.number
     src_level_number = source_level.number
     tgt_level_number = target_level.number
     # Since clingo doesn't support Boolean return, we are returning
     # Number(1) for true, and Number(0) for false.
     if (
         src_agent_number < tgt_agent_number + 200
         and tgt_agent_number < src_agent_number
         and tgt_level_number < src_level_number
     ):
         return Number(1)
     else:
         return Number(0)
コード例 #18
0
def _set(matches: Sequence[Tuple[str, int]],
         lst: List[Symbol],
         sym,
         append: bool = False,
         default: Symbol = Number(0)) -> bool:
    for match in matches:
        if not sym.match(*match):
            continue
        idx = len(lst) if append else sym.arguments[0].number
        while len(lst) <= idx:
            lst.append(default)
        lst[idx] = sym
        return True
    return False
コード例 #19
0
def copy_symbol(symbol):
    # functions
    if symbol.type == SymbolType.Function:
        return Function(symbol.name,
                        [copy_symbol(x) for x in symbol.arguments])

    # constants
    if symbol.type == SymbolType.String:
        return Function(symbol.name)

    # numbers
    if symbol.type == SymbolType.Number:
        return Number(symbol.number)

    raise RuntimeError("Not a symbol!")
コード例 #20
0
    def main(self, ctl: Control, files: Sequence[str]):
        '''
        Main function implementing branch and bound optimization.
        '''
        if not files:
            files = ["-"]
        for file_ in files:
            ctl.load(file_)
        ctl.add("bound", ["b"], ":- #sum { V,I: _minimize(V,I) } >= b.")

        ctl.ground([("base", [])])
        while cast(SolveResult,
                   ctl.solve(on_model=self._on_model)).satisfiable:
            print("Found new bound: {}".format(self._bound))
            ctl.ground([("bound", [Number(cast(int, self._bound))])])

        if self._bound is not None:
            print("Optimum found")
コード例 #21
0
    def test_theory(self):
        '''
        Test the reified theory class.
        '''
        def get_theory(prg):
            symbols = reify_program(prg)
            thy = ReifiedTheory(symbols)
            return list(thy)

        atm1 = get_theory(THEORY + '&a { f(1+ -2): x } = z. { x }.')[0]
        atm2 = get_theory(THEORY + '&a { f((1,2)): x }. { x }.')[0]
        atm3 = get_theory(THEORY + '&a { f([1,2]): x }. { x }.')[0]
        atm4 = get_theory(THEORY + '&a { f({1,2}): x }. { x }.')[0]
        atm5 = get_theory(THEORY + '&a. { x }.')[0]
        self.assertEqual(str(atm1), '&a { f((1)+(-(2))): literal_tuple(1) } = z')
        self.assertEqual(str(atm2), '&a { f((1,2)): literal_tuple(1) }')
        self.assertEqual(str(atm3), '&a { f([1,2]): literal_tuple(1) }')
        self.assertEqual(str(atm4), '&a { f({1,2}): literal_tuple(1) }')
        self.assertEqual(str(atm5), '&a')

        self.assertEqual(evaluate(atm1.elements[0].terms[0]), Function('f', [Number(-1)]))
        self.assertGreaterEqual(atm1.literal, 1)

        dir1 = get_theory(THEORY + '&b.')[0]
        self.assertEqual(dir1.literal, 0)

        atms = get_theory(THEORY + '&a { 1 }. &a { 2 }. &a { 3 }.')
        self.assertEqual(len(set(atms)), 3)
        self.assertNotEqual(atms[0], atms[1])
        self.assertNotEqual(atms[0] < atms[1],
                            atms[0] > atms[1])

        aele = get_theory(THEORY + '&a { 1; 2; 3 }.')[0]
        self.assertEqual(len(set(aele.elements)), 3)
        self.assertNotEqual(aele.elements[0], aele.elements[1])
        self.assertNotEqual(aele.elements[0] < aele.elements[1],
                            aele.elements[0] > aele.elements[1])

        atup = get_theory(THEORY + '&a { 1,2,3 }.')[0]
        self.assertEqual(len(set(atup.elements[0].terms)), 3)
        self.assertNotEqual(atup.elements[0].terms[0], atup.elements[0].terms[1])
        self.assertNotEqual(atup.elements[0].terms[0] < atup.elements[0].terms[1],
                            atup.elements[0].terms[0] > atup.elements[0].terms[1])
コード例 #22
0
 def theory_term_number(self, term_id: int, number: int) -> None:
     self._output("theory_number", [Number(term_id), Number(number)])
コード例 #23
0
ファイル: test_clingo_module.py プロジェクト: Aluriak/clyngor
 def inc(self, x):
     return Number(x.number + 1)
コード例 #24
0
ファイル: app.py プロジェクト: joshessman-llnl/clingo
    print('  loading files:')
    for file_ in files:
        print(f'  - {file_}')
        ctl.load(file_)

    print('  grounding:')
    for part in parts:
        print(f'  - {part_str(part)}')
        ctl.ground([part])

    if assign:
        print('  assigning externals:')
        for sym, truth in assign:
            print(f'  - {sym}={truth}')
            ctl.assign_external(sym, truth)

    print('  solutions:')
    ctl.solve(on_model=lambda m: print(f'  - {m}'))


print('Exmaple 1:')
run(['chemistry.lp'], [("base", [])])

print('\nExmaple 2:')
run(['chemistry.lp'], [("acid", [Number(42)])])

print('\nExmaple 3:')
run(['chemistry.lp', 'external.lp'], [("base", []), ("acid", [Number(42)])],
    [(Function("d", [Number(1), Number(42)]), True)])
コード例 #25
0
 def assume(self, literals: Sequence[int]) -> None:
     for lit in literals:
         self._output("assume", [Number(lit)])
コード例 #26
0
 def external(self, atom: int, value: TruthValue) -> None:
     value_name = str(value).replace('TruthValue.', '').lower().rstrip('_')
     self._output("external", [Number(atom), Function(value_name)])
コード例 #27
0
 def project(self, atoms: Sequence[int]) -> None:
     for atom in atoms:
         self._output("project", [Number(atom)])
コード例 #28
0
 def output_csp(self, symbol: Symbol, value: int,
                condition: Sequence[int]) -> None:
     self._output(
         "output_csp",
         [symbol, Number(value),
          self._lit_tuple(condition)])
コード例 #29
0
 def theory_term_string(self, term_id: int, name: str) -> None:
     self._output("theory_string", [Number(term_id), String(name)])
コード例 #30
0
 def on_model(self, m):
     state = self._state(m.thread_id)
     m.extend([Function("pref", [Function(name), Function(self._preferences[name].type()), Number(value)])
                   for name, value in state._values.items()])
     if self._mode == "breadth": self._solutions_map[copy(self._dict_to_vector(state._values))] = [copy_symbol(atom) for atom in m.symbols(theory=True,shown=True)]
     elif self._mode == "depth": self._best_known = Solution([copy_symbol(atom) for atom in m.symbols(theory=True,shown=True)],copy(state._values))