コード例 #1
0
ファイル: answers.py プロジェクト: Nedgang/clyngor
 def __init__(self, solver, statistics: callable = (lambda: {})):
     assert clyngor.have_clingo_module()
     super().__init__(())
     self._solver = solver
     self._statistics = lambda s=solver: json.dumps(
         s.statistics, sort_keys=True, indent=4, separators=(',', ': '))
     assert callable(self._statistics)
コード例 #2
0
ファイル: answers.py プロジェクト: ArnaudBelcour/clyngor
 def __init__(self, solver, statistics: callable = (lambda: {})):
     assert clyngor.have_clingo_module()
     super().__init__(self.__compute_answers(),
                      with_optimization=True,
                      command='[clingo module call]')
     self._solver = solver
     self._statistics = lambda s=solver: s.statistics
     assert callable(self._statistics)
コード例 #3
0
ファイル: test_api.py プロジェクト: ArnaudBelcour/clyngor
def test_syntax_error():
    assert not clyngor.have_clingo_module()
    with pytest.raises(clyngor.ASPSyntaxError) as excinfo:
        tuple(clyngor.solve((), inline='invalid', force_tempfile=True))
    assert excinfo.value.filename.startswith('/tmp/tmp')
    assert excinfo.value.lineno == 2
    assert excinfo.value.offset == 1
    assert excinfo.value.payload['char_end'] == 2
    assert excinfo.value.msg.startswith('unexpected EOF in file /tmp/tmp')
    assert excinfo.value.msg.endswith(' at line 2 and column 1-2')
コード例 #4
0
ファイル: test_api.py プロジェクト: ArnaudBelcour/clyngor
def test_undefined_warning():
    assert not clyngor.have_clingo_module()
    with pytest.raises(clyngor.ASPWarning) as excinfo:
        tuple(clyngor.solve((), inline='b:- c.', error_on_warning=True, force_tempfile=True))
    assert excinfo.value.atom == 'c'
    assert len(excinfo.value.args) == 1
    start = "atom 'c' does not occur in any rule head in file /tmp/tmp"
    assert excinfo.value.args[0].startswith(start)
    assert excinfo.value.args[0].endswith(" at line 1 and column 5-6")

    # NB: the following should NOT raise any error (default value)
    tuple(clyngor.solve((), inline='b:- c.', error_on_warning=False))
    tuple(clyngor.solve((), inline='b:- c.'))
コード例 #5
0
def solve(files: iter = (),
          options: iter = [],
          inline: str = None,
          decoders: iter = (),
          subproc_shell: bool = False,
          print_command: bool = False,
          nb_model: int = 0,
          time_limit: int = 0,
          constants: dict = {},
          clean_path: bool = True,
          stats: bool = True,
          clingo_bin_path: str = None,
          error_on_warning: bool = False,
          force_tempfile: bool = False,
          delete_tempfile: bool = True,
          use_clingo_module: bool = True,
          grounding_observers: iter = (),
          propagators: iter = (),
          solver_conf: object = None,
          running_sequence: callable = _default_running_sequence,
          programs: iter = (['base', ()], ),
          return_raw_output: bool = False) -> iter:
    """Run the solver on given files, with given options, and return
    an Answers instance yielding answer sets.

    files -- iterable of files feeding the solver
    options -- string or iterable of options for clingo
    inline -- ASP source code to feed the solver with
    decoders -- iterable of decoders to apply on ASP (see clyngor.decoder)
    subproc_shell -- use shell=True in subprocess call (NB: you should not)
    print_command -- print full command to stdout before running it
    clean_path -- clean the path of given files before using them
    stats -- will ask clingo for all stats, instead of just the minimal ones
    clingo_bin_path -- the path to the clingo binary
    error_on_warning -- raise an ASPWarning when encountering a clingo warning
    use_clingo_module -- will use the clingo module (if available)
    force_tempfile -- use tempfile, even if only inline code is given
    delete_tempfile -- delete used tempfiles
    return_raw_output -- don't parse anything, just return iterators over stdout
                         and stderr, without using clingo module

    The following options needs the propagator support and/or python clingo module:
    grounding_observers -- iterable of observers to add to the grounding process
    propagators -- iterable of propagators to add to the solving process
    solver_conf -- clingo.Configuration instance, given to the running_sequence
    running_sequence -- If given, must be a callable taking programs,
                        files and Configuration, returning both clingo.Control
                        and clingo.SolveHandle instances.
    programs -- programs to feed the running sequence with.

    Shortcut to clingo's options:
    nb_model -- number of model to output (0 for all (default), None to disable)
    time_limit -- zero or number of seconds to wait before interrupting solving
    constants -- mapping name -> value of constants for the grounding

    """
    files = [files] if isinstance(files, str) else files
    files = tuple(map(cleaned_path, files) if clean_path else files)
    stdin_feed = None  # data to send to stdin
    use_clingo_module = use_clingo_module and clyngor.have_clingo_module(
    ) and not return_raw_output
    if use_clingo_module:
        # the clingo API do not handle stdin feeding
        force_tempfile = True
    if inline and not files and not force_tempfile:  # avoid tempfile if possible
        stdin_feed, inline = inline, None
    elif inline:
        with tempfile.NamedTemporaryFile(mode='w', delete=False) as fd:
            fd.write(inline)
            tempfile_to_del = fd.name
            files = tuple(files) + (tempfile_to_del, )
            assert files, fd.name
    run_command = command(files,
                          options,
                          inline,
                          nb_model,
                          time_limit,
                          constants,
                          stats,
                          clingo_bin_path=clingo_bin_path)

    if print_command:
        print(run_command)

    if not files and not inline and not stdin_feed:
        # in this case, clingo will wait for stdin input, which will never come
        # so better not call clingo at all, because answer is obvious: one empty model.
        return Answers((), command=' '.join(run_command))

    if use_clingo_module:
        if time_limit != 0 or constants:
            raise ValueError("Options 'time_limit' and 'constants' are not "
                             "handled when used with python clingo module.")
        if solver_conf:
            raise NotImplementedError(
                "Solver configuration handling is currently"
                "not implemented")
        options = list(
            shlex.split(options) if isinstance(options, str) else options)
        ctl = clyngor.clingo_module.Control(options)
        main = running_sequence(programs=programs,
                                files=files,
                                nb_model=nb_model,
                                propagators=propagators,
                                observers=grounding_observers,
                                generator=True)
        return main(ctl)
    else:
        clingo = subprocess.Popen(
            run_command,
            stdin=subprocess.PIPE if stdin_feed else None,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            shell=bool(subproc_shell),
        )
        if stdin_feed:
            clingo.stdin.write(stdin_feed.encode())
            clingo.stdin.close()
        stdout = (line.decode() for line in clingo.stdout)
        stderr = (line.decode() for line in clingo.stderr)
        if return_raw_output: return ''.join(stdout), ''.join(stderr)
        statistics = {}

        # remove the tempfile after the work.
        on_end = lambda: (clingo.stderr.close(), clingo.stdout.close())
        if inline and tempfile_to_del and delete_tempfile:
            on_end = lambda: (os.remove(tempfile_to_del), clingo.stderr.close(
            ), clingo.stdout.close())

        return Answers(_gen_answers(stdout, stderr, statistics,
                                    error_on_warning),
                       command=' '.join(run_command),
                       on_end=on_end,
                       decoders=decoders,
                       statistics=statistics,
                       with_optimization=True)
コード例 #6
0
def onlyif_no_clingo_module(func):
    return pytest.mark.skipif(
        clyngor.have_clingo_module(),
        reason="Require official clingo module to NOT be available")(func)