def test_strips_analysis(): problem = generate_strips_blocksworld_problem() assert is_strips_problem(problem) lang = problem.language clear, on, ontable, handempty, holding = lang.get('clear', 'on', 'ontable', 'handempty', 'holding') x = lang.variable('x', 'object') phi = clear(x) & ~ontable(x) assert not is_conjunction_of_positive_atoms(clear(x) & ~ontable(x)) assert is_strips_effect_set([DelEffect(ontable(x)), DelEffect(clear(x))]) assert is_strips_effect_set([DelEffect(ontable(x)), DelEffect(ontable(x))]) # Not strips, as it has an effect with conditions: assert not is_strips_effect_set( [DelEffect(ontable(x), clear(x)), AddEffect(ontable(x))]) # Not strips, as it has two contradictory effects: assert not is_strips_effect_set( [DelEffect(ontable(x)), AddEffect(ontable(x))]) problem = generate_fstrips_counters_problem(ncounters=3) assert not is_strips_problem(problem) inc = problem.get_action('increment') assert not is_strips_effect_set(inc.effects)
def test_cost_function_identification(): problem = generate_fstrips_counters_problem(ncounters=3) functions = identify_cost_related_functions(problem) assert functions == set() problem = parse_benchmark_instance("agricola-opt18-strips:p01.pddl") functions = identify_cost_related_functions(problem) assert functions == {"group_worker_cost"}
def test_counters(): problem = generate_fstrips_counters_problem(ncounters=3) lang = problem.language value, c1 = lang.get('value', 'c1') # More than testing some particular property, here we want to test that the generator can run correctly assert is_and(problem.goal) and len(problem.goal.subformulas) == 2 assert problem.init[value(c1)] == 0
def test_cost_function_identification(): problem = generate_fstrips_counters_problem(ncounters=3) functions = identify_cost_related_functions(problem) assert functions == set() instance_file, domain_file = collect_strips_benchmarks(["agricola-opt18-strips:p01.pddl"])[0] problem = reader().read_problem(domain_file, instance_file) functions = identify_cost_related_functions(problem) assert functions == {"group_worker_cost"}
def test_on_counters(): counters = generate_fstrips_counters_problem(ncounters=3) # Optimal plan is a length-3 sequence with 'increment(c2)', 'increment(c3)', 'increment(c3)' assert run_on_problem(counters, reachability="none", max_horizon=1, grounding='none') is None,\ "Not solvable in 1 timestep" assert run_on_problem(counters, reachability="none", max_horizon=2, grounding='none') is None, \ "Not solvable in 2 timesteps" plan = run_on_problem(counters, reachability="none", max_horizon=3, grounding='none') assert len(plan) == 3 and plan.count('(increment c3)') == 2 and plan.count('(increment c2)') == 1
def test_sort_domain_retrieval(): problem = generate_fstrips_counters_problem(ncounters=6) lang = problem.language assert len(list(lang.get("counter").domain())) == 6 assert len(list(lang.get( "val").domain())) == 13, "Val must range from 0 to 12, both included" with pytest.raises(err.TarskiError): lang.Integer.domain() # Domain too large to iterate over it
def test_requirements_string(): problem = parcprinter.create_small_task() # action costs should be required if there is a metric defined. assert sorted(get_requirements_string(problem)) == [':action-costs', ':equality', ':numeric-fluents', ':typing'] problem, loc, clear, b1, table = get_bw_elements() assert sorted(get_requirements_string(problem)) == [':equality', ':typing'] problem = generate_fstrips_counters_problem() assert sorted(get_requirements_string(problem)) == [':equality', ':numeric-fluents', ':typing']
def test_simplifier(): problem = generate_fstrips_counters_problem(ncounters=3) lang = problem.language value, max_int, counter, val_t, c1 = lang.get('value', 'max_int', 'counter', 'val', 'c1') x = lang.variable('x', counter) two, three, six = [lang.constant(c, val_t) for c in (2, 3, 6)] s = Simplify(problem, problem.init) assert symref(s.simplify_expression(x)) == symref(x) assert symref(s.simplify_expression(value(c1) < max_int())) == symref( value(c1) < six) # max_int evaluates to 6 assert s.simplify_expression(two < max_int()) is True assert s.simplify_expression(two > three) is False # conjunction evaluates to false because of first conjunct: falseconj = land(two > three, value(c1) < max_int()) assert s.simplify_expression(falseconj) is False assert s.simplify_expression(neg(falseconj)) is True # first conjunct gets removed: assert str(s.simplify_expression(land( two < three, value(c1) < max_int()))) == '<(value(c1),6)' # first disjunct gets removed because it is false assert str(s.simplify_expression(lor( two > three, value(c1) < max_int()))) == '<(value(c1),6)' assert str(s.simplify_expression(forall( x, value(x) < max_int()))) == 'forall x : (<(value(x),6))' assert s.simplify_expression(forall(x, two + three <= 6)) is True inc = problem.get_action('increment') simp = s.simplify_action(inc) assert str(simp.precondition) == '<(value(c),6)' assert str(simp.effects) == str(inc.effects) eff = UniversalEffect(x, [value(x) << three]) assert str( s.simplify_effect(eff)) == '(T -> forall (x) : ((T -> value(x) := 3)))' simp = s.simplify() assert str(simp.get_action('increment').precondition) == '<(value(c),6)' # Make sure there is no mention to the compiled away "max_int" symbol in the language assert not simp.language.has_function("max_int") # Make sure there is no mention to the compiled away "max_int" symbol in the initial state exts = list(simp.init.list_all_extensions().keys()) assert ('max_int', 'val') not in exts
def test_sort_id_assignment_on_lang_with_intervals(): problem = generate_fstrips_counters_problem(ncounters=6) lang = problem.language sortmap = compute_direct_sort_map(lang) cards = {s.name: len(objs) for s, objs in sortmap.items()} assert cards == { 'object': 0, 'counter': 6 } # Make sure 'object' doesn't include integer constants bounds, ids = compute_sort_id_assignment(lang) assert bounds[lang.Object] == bounds[lang.get('counter')] == (0, 6)
def test_requirements_string(): problem = parcprinter.create_small_task() # action costs should be required if there is a metric defined, but if "total-cost" is the only arithmetic # function, we don't print the ':numeric-fluents' requirement assert sorted(get_requirements_string(problem)) == [ ':action-costs', ':equality', ':typing' ] problem, loc, clear, b1, table = get_bw_elements() assert sorted(get_requirements_string(problem)) == [':equality', ':typing'] problem = generate_fstrips_counters_problem() assert sorted(get_requirements_string(problem)) == [ ':equality', ':numeric-fluents', ':typing' ]
def test_simplification_of_ex_quantification(): problem = generate_fstrips_counters_problem(ncounters=3) lang = problem.language value, max_int, counter, val_t, c1 = lang.get('value', 'max_int', 'counter', 'val', 'c1') x = lang.variable('x', counter) z = lang.variable('z', counter) two, three, six = [lang.constant(c, val_t) for c in (2, 3, 6)] phi = exists(z, land(x == z, top, value(z) < six)) assert simplify_existential_quantification(phi, inplace=False) == land(top, value(x) < six), \ "z has been replaced by x and removed from the quantification list, thus removing the quantifier" phi = exists(x, z, land(x == z, z == x, value(z) < six, flat=True)) assert simplify_existential_quantification(phi, inplace=False) == exists(x, value(x) < six), \ "The circular substitution dependency has been treated appropriately and only one substitution performed"
def test_simplification_pruning(): problem = generate_fstrips_counters_problem(ncounters=3) lang = problem.language value, max_int, counter, val_t, c1 = lang.get('value', 'max_int', 'counter', 'val', 'c1') three, six = [lang.constant(c, val_t) for c in (3, 6)] s = Simplify(problem, problem.init) a = problem.get_action('decrement') a.precondition = (three > six) # increment action must be pruned because its precondition is are statically inapplicable: assert len(s.simplify().actions) == 1 a = problem.get_action('increment') a.effects[0].condition = (three > six) # increment action must be pruned because all its effects are statically inapplicable: assert len(s.simplify().actions) == 0