Пример #1
0
def _incremental(ctl: Control):
    ctl.add('step0', [], 'a :- b. b :- a. {a;b}.')
    ctl.ground([('step0', [])])
    ctl.solve()
    ctl.add('step1', [], 'c :- d. d :- c. {c;d}.')
    ctl.ground([('step1', [])])
    ctl.solve()
Пример #2
0
def test_basic_example():
    "Example taken from clingo module documentation: https://potassco.org/clingo/python-api/5.5/clingo/index.html"
    from clingo.symbol import Number
    from clingo.control import Control

    class Context:
        def inc(self, x):
            return Number(x.number + 1)

        def seq(self, x, y):
            return [x, y]

    def on_model(m):
        print(repr(m), m, dir(m))
        assert False, "Clingo module seems to have python support. Some test on the output model are to be done (just be sure there is a `a` atom). Model: " + repr(
            m)
        assert clyngor.have_python_support()

    ctl = Control()
    try:
        ctl.add("base", [], "a. #script(python) #end.")
    except RuntimeError as err:  # case where python support is not implemented
        assert err.args == (
            '<block>:1:4-25: error: python support not available\n', )
        assert not clyngor.have_python_support()
    else:  # python support available
        ctl.ground([("base", [])], context=Context())
        ctl.solve(on_model=on_model)
Пример #3
0
def eval_term_sym(s: str) -> Symbol:
    """
    Evaluate the given theory term and return its string representation.
    """
    ctl = Control()
    ctl.add(
        "base", [], f"""
#theory test {{
    t {{
    +  : 3, unary;
    -  : 3, unary;
    ?  : 3, unary;
    ?  : 3, binary, left;
    ** : 2, binary, right;
    *  : 1, binary, left;
    /  : 1, binary, left;
    \\ : 1, binary, left;
    +  : 0, binary, left;
    -  : 0, binary, left
    }};
    &a/0 : t, head
}}.
&a {{{s}}}.
""")
    ctl.ground([("base", [])])
    for x in ctl.theory_atoms:
        return evaluate(x.elements[0].terms[0])
    assert False
Пример #4
0
def run(files: Sequence[str], parts: Parts, assign: Externals = ()):
    '''
    Loads the given files into a control object, grounds the given program
    parts, and assign the given externals to the given truth values.
    '''
    ctl = Control()

    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}'))
    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")
Пример #6
0
def reify_program(prg: str,
                  calculate_sccs: bool = False,
                  reify_steps: bool = False) -> List[Symbol]:
    '''
    Reify the given program and return the reified symbols.

    Parameters
    ----------
    prg
        The program to reify in form of a string.
    calculate_sccs
        Whether to calculate SCCs of the reified program.
    reify_steps
        Whether to add a step number to the reified facts.

    Returns
    -------
    A list of symbols containing the reified facts.
    '''
    ret: List[Symbol] = []
    ctl = Control()
    reifier = Reifier(ret.append, calculate_sccs, reify_steps)
    ctl.register_observer(reifier)
    ctl.add("base", [], prg)
    ctl.ground([('base', [])])
    if calculate_sccs and not reify_steps:
        reifier.calculate_sccs()

    return ret
Пример #7
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
Пример #8
0
 def run(self):
     '''
     Runs the example.
     '''
     ctl = Control()
     ctl.load("example.lp")
     ctl.ground([("base", [])], context=self)
     ctl.solve(on_model=print)
Пример #9
0
def _assume(ctl: Control):
    ctl.add("base", [], '{a;b}.')
    ctl.ground([('base', [])])

    lit_a = cast(SymbolicAtom, ctl.symbolic_atoms[Function("a")]).literal
    lit_b = cast(SymbolicAtom, ctl.symbolic_atoms[Function("b")]).literal
    ctl.solve(assumptions=[lit_a, lit_b])
    ctl.solve(assumptions=[-lit_a, -lit_b])
Пример #10
0
 def main(self, ctl: Control, files: Sequence[str]):
     '''
     Main function of the application.
     '''
     for path in files:
         ctl.load(path)
     if not files:
         ctl.load("-")
     ctl.ground([("base", [])], context=self)
     ctl.solve()
Пример #11
0
class Checker:
    """
    Class wrapping a solver to perform the second level check.
    """
    _ctl: Control
    _map: List[Tuple[int, int]]

    def __init__(self):
        self._ctl = Control()
        self._map = []

    def backend(self) -> Backend:
        """
        Return the backend of the underlying solver.
        """
        return self._ctl.backend()

    def add(self, guess_lit: int, check_lit: int):
        """
        Map the given solver literal to the corresponding program literal in
        the checker.
        """
        self._map.append((guess_lit, check_lit))

    def ground(self, check: Sequence[ast.AST]):
        """
        Ground the check program.
        """
        with ProgramBuilder(self._ctl) as bld:
            for stm in check:
                bld.add(stm)

        self._ctl.ground([("base", [])])

    def check(self, control: PropagateControl) -> bool:
        """
        Return true if the check program is unsatisfiable w.r.t. to the atoms
        of the guess program.

        The truth values of the atoms of the guess program are stored in the
        assignment of the given control object.
        """
        assignment = control.assignment

        assumptions = []
        for guess_lit, check_lit in self._map:
            guess_truth = assignment.value(guess_lit)
            assumptions.append(check_lit if guess_truth else -check_lit)

        ret = cast(SolveResult, self._ctl.solve(assumptions))
        if ret.unsatisfiable is not None:
            return ret.unsatisfiable

        raise RuntimeError("search interrupted")
Пример #12
0
    def approximate(self, prg: str, expected_res):
        '''
        Auxiliary function to test approximate.
        '''
        ctl = Control()
        ctl.add("base", [], prg)
        ctl.ground([("base", [])])
        res = approximate(ctl)
        if res:
            sorted_res = (sorted([str(s) for s in res[0]]),
                          sorted([str(s) for s in res[1]]))
        else:
            sorted_res = None

        self.assertEqual(sorted_res, expected_res)
Пример #13
0
    def main(self, ctl: Control, files: Sequence[str]):
        """
        The main function called with a Control object and a list of files
        passed on the command line.
        """
        if not files:
            files = ["-"]

        check: List[ast.AST] = []
        with ProgramBuilder(ctl) as bld:
            trans = Transformer(bld, check)
            parse_files(files, trans.add)

        ctl.register_propagator(CheckPropagator(check))

        ctl.ground([("base", [])])
        ctl.solve()
Пример #14
0
    def main(self, ctl: Control, files):
        prg = Program()
        ctl.register_observer(ProgramObserver(prg))

        for f in files:
            ctl.load(f)
        if not files:
            ctl.load('-')

        ctl.ground([("base", [])])

        fct, ukn = well_founded(prg)
        print('Facts:')
        print(f'{" ".join(map(str, fct))}')
        print('Unknown:')
        print(f'{" ".join(map(str, ukn))}')

        ctl.solve()
Пример #15
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")
Пример #16
0
 def __call__(self, ctl: Control):
     ctl.add('base', [], self._prg)  # nocoverage
     ctl.ground([('base', [])])  # nocoverage
     ctl.solve()  # nocoverage