def test_discard_quotes_with_as_pyasp_termset(): answers = Answers(('a("b","d")', )).as_pyasp assert next(answers) == TermSet((Atom(predicate='a', args=('"b"', '"d"')), )) answers = Answers(('a("b","d")', )).as_pyasp.discard_quotes assert next(answers) == TermSet((Atom(predicate='a', args=('"b"', '"d"')), ))
def test_as_pyasp_atom(): answers = Answers(('a("b","d")',)).as_pyasp for atom in next(answers): assert atom == Atom(predicate='a', args=('"b"','"d"')) print(atom) answers = Answers(('a(1,"2.3")',)).as_pyasp for atom in next(answers): assert atom == Atom(predicate='a', args=(1,'"2.3"')) print(atom)
def test_discard_quotes_with_as_pyasp_termset_and_careful_parsing(): answers = Answers(('a("b","d")', )).parse_args.as_pyasp.careful_parsing assert next(answers) == TermSet((Atom(predicate='a', args=('"b"', '"d"')), )) answers = Answers( ('a("b","d")', )).parse_args.as_pyasp.discard_quotes.careful_parsing assert next(answers) == TermSet( (Atom(predicate='a', args=('"b"', '"d"')), )) # as_pyasp overrides discard_quotes
def noarg_answers(): return Answers(( '', 'a', 'b c', 'd e f', ))
def simple_answers(): return Answers(( 'a(0) b(1)', 'c(2) d(3)', 'e(4) f(5)', 'g(6) h(7)', ))
def multiple_args(): return Answers(( 'edge(4,"s…lp.") r_e_l(1,2)', 'edge(4,"s…lp.") r_e_l(1,2)', 'edge(4,"s…lp.") r_e_l(1,2)', 'edge(4,"s…lp.") r_e_l(1,2)', 'edge(4,"s…lp.") r_e_l(1,2)', ))
def optimized_answers(): return Answers(( ('edge(4,"s…lp.") r_e_l(1,2)', 1, False, 1), ('edge(4,"s…lp.") r_e_l(1,2)', 1, False, 2), ('edge(4,"s…lp.") r_e_l(1,2)', 2, False, 3), ('edge(4,"s…lp.") r_e_l(1,2)', 3, False, 4), ('edge(4,"s…lp.") r_e_l(1,2)', 4, False, 5), ), with_optimization=True)
def quotes_answers(): return Answers(( 'a("c") b("d","e")', 'a("c") b("d","e")', 'a("c") b("d","e")', 'a("c") b("d","e")', 'a("c") b("d","e")', ))
def test_as_pyasp_termset_frozenset_union(): answers = Answers(('a("b","d")',)).as_pyasp answer_a = next(answers) expected_a = frozenset((Atom(predicate='a',args=('"b"','"d"')),)) assert answer_a == expected_a assert next(answers, None) is None answers = Answers(('b("b","d")',)).as_pyasp answer_b = next(answers) expected_b = frozenset((Atom(predicate='b',args=('"b"','"d"')),)) assert answer_b == expected_b assert next(answers, None) is None assert isinstance(answer_a, TermSet) assert isinstance(answer_b, TermSet) assert answer_a.union(answer_b) == frozenset((Atom(predicate='a',args=('"b"','"d"')), Atom(predicate='b',args=('"b"','"d"')))) # no modification of objects assert answer_a == expected_a assert answer_b == expected_b
def test_as_pyasp_termset_add(): answers = Answers(('a("b","d")',)).as_pyasp answer_a = next(answers) expected_a = frozenset((Atom(predicate='a',args=('"b"','"d"')),)) assert answer_a == expected_a assert next(answers, None) is None answer_a.add(Atom(predicate='b',args=('"b"','"d"'))) expected_a = frozenset((Atom(predicate='a',args=('"b"','"d"')), Atom(predicate='b',args=('"b"','"d"')))) assert answer_a == expected_a
def test_atoms_with_leading_underscore_with_nested(): get_answers = lambda: Answers(('_a("b",_b(c,_d)) _c',)).parse_args # naive parsing (NB: careful parsing should be automatically activated) answers = get_answers() answer_a = next(answers) assert next(answers, None) is None, "there is more than one model" expected_a = frozenset((('_a', ('"b"', ('_b', ('c', '_d')))), ('_c', ()))) assert answer_a == expected_a, (answer_a, type(answer_a)) # careful parsing answers = get_answers().careful_parsing answer_a = next(answers) assert next(answers, None) is None, "there is more than one model" expected_a = frozenset((('_a', ('"b"', ('_b', ('c', '_d')))), ('_c', ()))) assert answer_a == expected_a, answer_a
def test_pyasp_and_nested_atoms(): get_answers = lambda: Answers(('a(b(c,d))',)).parse_args # without as_pyasp answers = get_answers() answer_a = next(answers) assert next(answers, None) is None, "there is more than one model" expected_a = frozenset((('a', (('b', ('c', 'd')),)),)) assert answer_a == expected_a, (answer_a, type(answer_a)) # with as_pyasp answers = get_answers().as_pyasp answer_a = next(answers) assert next(answers, None) is None, "there is more than one model" expected_a = frozenset((Atom('a', (Atom('b', ('c', 'd')),)),)) print('LBTL:', type(answer_a), answer_a) assert answer_a == expected_a, (answer_a, type(answer_a))
def test_atoms_with_leading_underscore(): """needed to test leading underscores in naive parsing ; next test will fall under the case where careful parsing is automatically activated""" get_answers = lambda: Answers(('_a(_b,_c,d) _e',)).parse_args # naive parsing answers = get_answers() answer_a = next(answers) assert next(answers, None) is None, "there is more than one model" expected_a = frozenset((('_a', ('_b', '_c', 'd')), ('_e', ()))) assert answer_a == expected_a, (answer_a, type(answer_a)) # careful parsing answers = get_answers().careful_parsing answer_a = next(answers) assert next(answers, None) is None, "there is more than one model" expected_a = frozenset((('_a', ('_b', '_c', 'd')), ('_e', ()))) assert answer_a == expected_a, answer_a
def solve(files:iter=(), options:iter=[], inline:str=None, subproc_shell:bool=False, print_command:bool=False, nb_model:int=0, time_limit:int=0, constants:dict={}, clean_path:bool=True) -> 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 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 Shortcut to clingo's options: nb_model -- number of model to output (0 for all (default)) 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) run_command = command(files, options, inline, nb_model, time_limit, constants) if print_command: print(run_command) clingo = subprocess.Popen( run_command, stderr = subprocess.PIPE, stdout = subprocess.PIPE, shell=bool(subproc_shell), ) def gen_answers(): stdout = iter(clingo.stdout) while True: cur_line = next(stdout).decode() if cur_line.startswith('Answer: '): yield next(stdout).decode() return Answers(gen_answers(), command=' '.join(run_command))
def test_first_arg_only_with_careful_parsing(): answers = Answers(('p("1,5","2,456",3)',)).first_arg_only.careful_parsing assert next(answers) == {('p', '"1,5"')}
def test_as_pyasp_termset_string(): answers = Answers(('a("b","d")',)).as_pyasp assert str(next(answers)) == 'a("b","d").'
def default_negation_answers(): return Answers(( 'ok -ko', '-occurs(apply(drychem,fire_in(bin)), 2) ok -ko', ))
def many_atoms_answers(): return Answers(( 'a b(4) b(3) a(1) vv(1) vv v(a) v(b)', ))
def test_as_pyasp_termset_termset_by_predicate(): answers = Answers(('a("b","d")',)).as_pyasp.by_predicate assert next(answers) == {'a': TermSet((Atom(predicate='a',args=('"b"','"d"')),))}
def test_first_arg_only(): answers = Answers(('p(1,2,3)',)).first_arg_only assert next(answers) == {('p', 1)}
def test_as_pyasp_termset_frozenset(): answers = Answers(('a("b","d")',)).as_pyasp assert next(answers) == frozenset((Atom(predicate='a',args=('"b"','"d"')),))
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)
def complex_quotes_answers(): return Answers(( 'a("\\"cou\\"cou\\"") b("\\"&\\"&\\"1234\\"\\"&\\"")', # Random gibberish ))