def test_extract_plan(): op1 = Operator("op1", [], ["a"], []) op2 = Operator("op2", ["a"], ["b"], []) op3 = Operator("op3", ["a", "b"], ["c"], []) op4 = Operator("op4", [], ["a", "b"], []) expected = [ (["not-a-0", "a-1"], [op1], [op1]), (["not-a-0", "a-1", "b-0", "b-1"], [op1, op2], [op1]), ( ["not-a-0", "a-1", "not-b-0", "not-b-1", "a-2", "b-2"], [op1, op2], [op1, op2], ), ([], [op1], []), ( [ "a-0", "not-b-0", "not-c-0", "a-1", "b-1", "not-c-1", "a-2", "b-2", "c-2" ], [op1, op2, op3], [op2, op3], ), (["not-a-0, not-b-0", "a-1", "b-1"], [op1, op4], [op4]), ] for valuation, operators, plan in expected: extracted_plan = sat._extract_plan(operators, valuation) assert extracted_plan == plan
def test_compute_landmark_costs(): op1 = Operator("op1", set(), {"A", "C"}, set()) op2 = Operator("op2", set(), {"B", "C"}, set()) op3 = Operator("op3", set(), {"D"}, set()) task = Task("task1", set(), set(), set(), [op1, op2, op3]) costs = landmarks.compute_landmark_costs(task, ["A", "C", "D"]) print(costs) expected = {"A": 0.5, "C": 0.5, "D": 1} assert expected == costs
def _get_simple_task_always_true(): """ Simple test task with one operator needed. """ op1 = Operator("op1", {}, {"var2"}, set()) op2 = Operator("op2", {"var1"}, set(), set()) op3 = Operator("op3", {"var2"}, {"var1"}, set()) init = frozenset(["var1"]) goals = frozenset(["var1", "var2"]) task1 = Task("task1", {"var1", "var2", "var3"}, init, goals, [op1, op2, op3]) return task1
def _get_simple_task_at_goal(): """ Goal is already reached in the initial state. """ op1 = Operator("op1", {"var1"}, {"var2"}, set()) op2 = Operator("op2", {"var1"}, set(), set()) op3 = Operator("op3", {"var2"}, {"var1"}, set()) init = frozenset(["var1"]) goals = frozenset(["var1"]) task1 = Task("task1", {"var1", "var2", "var3"}, init, goals, [op1, op2, op3]) return task1
def _get_simple_task_unsolvable(): """ Unsolvable task. """ op1 = Operator("op1", {"var1"}, {"var2"}, set()) op2 = Operator("op2", {"var1"}, set(), set()) op3 = Operator("op3", {"var2"}, {"var1"}, set()) init = frozenset(["var1"]) goals = frozenset(["var1", "var3"]) task1 = Task("task1", {"var1", "var2", "var3"}, init, goals, [op1, op2, op3]) return task1
def _get_simple_task(): """ Task with a goal with two facts and an operator with no effect. """ op1 = Operator("op1", {"var1"}, {"var2"}, set()) op2 = Operator("op2", {"var1"}, set(), set()) op3 = Operator("op3", {"var2"}, {"var1"}, set()) init = frozenset(["var1"]) goals = frozenset(["var1", "var2"]) task1 = Task("task1", {"var1", "var2", "var3"}, init, goals, [op1, op2, op3]) return task1
def test_relaxation_heuristic_constructor(): op1 = Operator("op1", {"A"}, {"B"}, set()) op2 = Operator("op2", {"B"}, {"C"}, set()) init = frozenset(["A"]) goals = frozenset(["C"]) task = Task("task1", {"A", "B", "C"}, init, goals, [op1, op2]) rh = hAddHeuristic(task) rop1 = RelaxedOperator(op1.name, ["A"], ["B"]) assert len(rh.operators) == 2 assert len(rh.facts) == 3 assert rh.facts["A"].precondition_of[0].name == rop1.name
def _get_intermediate_task2(): """ Intermediate task """ op1 = Operator("op1", {"v1"}, {"v2"}, set()) op2 = Operator("op2", {"v2"}, {"v3"}, set()) op3 = Operator("op3", {"v3"}, {"v4", "v5"}, set()) op4 = Operator("op4", {"v7", "v5"}, {"g"}, set()) op7 = Operator("op7", {"v4"}, {"v7"}, set()) op5 = Operator("op5", {"v2"}, {"v6"}, set()) op6 = Operator("op6", {"v6"}, {"v5"}, set()) init = frozenset(["v1"]) goals = frozenset(["g"]) task1 = Task( "task1", {"v1", "v2", "v3", "v4", "v5", "v6", "v7", "g"}, init, goals, [op1, op2, op3, op4, op5, op6, op7], ) return task1
def _get_intermediate_task(): """ Intermediate test task with four operators needed. """ op1 = Operator("op1", {"v1"}, {"v2"}, set()) op2 = Operator("op2", {"v2"}, {"v3"}, set()) op3 = Operator("op3", {"v3"}, {"v4", "v5"}, set()) op4 = Operator("op4", {"v4", "v5"}, {"g"}, set()) op5 = Operator("op5", {"v2"}, {"v6"}, set()) op6 = Operator("op6", {"v6"}, {"v5"}, set()) init = frozenset(["v1"]) goals = frozenset(["g"]) task1 = Task( "task1", {"v1", "v2", "v3", "v4", "v5", "v6", "g"}, init, goals, [op1, op2, op3, op4, op5, op6], ) return task1
def test_sat_solve(): op1 = Operator("op1", set(), {"a"}, set()) op2 = Operator("op2", set("a"), set("b"), set()) op3 = Operator("op3", set(), {"a", "b", "c"}, set()) op4 = Operator("op4", {"b"}, {"c"}, set()) op5 = Operator("op5", {"b", "c"}, {"d"}, set()) op6 = Operator("op6", {"d"}, {"e", "f"}, set()) op7 = Operator("op7", {"a", "c", "f"}, {"g"}, set()) task0 = Task("task0", {"a"}, {"a"}, {"a"}, [op1, op2]) task1 = Task("task1", {"a"}, set(), {"a"}, [op1, op2]) task2 = Task("task2", {"a", "b"}, set(), {"b"}, [op1, op2]) task3 = Task("task3", {"a", "b", "c"}, set(), {"c"}, [op1, op2]) task4 = Task("task4", {"a", "b", "c"}, set(), {"c"}, [op1, op2, op3]) task5 = Task("task5", {"a", "b", "c"}, set(), {"c"}, [op1, op2, op4]) task6 = Task("task6", {"a", "b", "c", "d"}, {"a"}, {"d"}, [op2, op4, op5]) task7 = Task("task7c", {"a", "b", "c", "d"}, {"a"}, {"d"}, [op3, op5]) task8 = Task( "task8", {"a", "b", "c", "d", "e", "f", "g"}, {"a"}, {"g"}, [op2, op3, op4, op5, op6, op7], ) op_facts = Operator( "op_facts", set(), { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", }, set(), ) task_facts = Task( "task_facts", { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", }, set(), {"v", "w"}, [op_facts], ) op_delete_pre = Operator("delete_pre", {"a"}, {"b"}, {"a"}) task_op_delete_pre = Task("op_delete_pre", {"a", "b"}, {"a"}, {"b"}, [op_delete_pre]) # Miconic: prob00.pddl (2 floors, 1 person): # <Op (depart f1 p0), PRE: frozenset({'(lift-at f1)', '(boarded p0)'}), # ADD: frozenset({'(served p0)'}), DEL: frozenset({'(boarded p0)'})>, # <Op (board f0 p0), PRE: frozenset({'(lift-at f0)'}), # ADD: frozenset({'(boarded p0)'}), DEL: frozenset()>, # <Op (up f0 f1), PRE: frozenset({'(lift-at f0)'}), # ADD: frozenset({'(lift-at f1)'}), DEL: frozenset({'(lift-at f0)'})>] op_depart = Operator("depart", {"high", "boarded"}, {"served"}, {"boarded"}) op_board = Operator("board", {"low"}, {"boarded"}, set()) op_up = Operator("up", {"low"}, {"high"}, {"low"}) task_simple_miconic = Task( "miconic-simple", {"low", "high", "boarded", "served"}, {"low"}, {"served"}, [op_depart, op_board, op_up], ) expected = [ (task0, []), (task1, [op1]), (task2, [op1, op2]), (task3, None), (task4, [op3]), (task5, [op1, op2, op4]), (task6, [op2, op4, op5]), (task7, [op3, op5]), (task_facts, [op_facts]), (task_op_delete_pre, [op_delete_pre]), (task_simple_miconic, [op_board, op_up, op_depart]), ] for task, plan in expected: assert sat.sat_solve(task, max_steps=5) == plan
""" Tests for the task.py module """ from pyperplan.task import Operator, Task import pytest s1 = frozenset(["var1"]) s2 = frozenset(["var2"]) s3 = frozenset(["var1", "var2"]) op1 = Operator("op1", {"var1"}, {"var2"}, set()) op2 = Operator("op1", {"var1"}, set(), set()) op3 = Operator("op1", {"var2"}, {"var1"}, set()) # Operator that makes var2 true and false op4 = Operator("op1", {"var1"}, {"var2"}, {"var2"}) init = frozenset(["var1"]) goals = frozenset(["var1", "var2"]) task1 = Task("task1", {"var1", "var2", "var3"}, init, goals, [op1, op2, op3]) def test_op_applicable1(): assert op1.applicable(s1) def test_op_applicable2(): assert not op1.applicable(s2) def test_op_applicable3():
import pytest from pyperplan import tools from pyperplan.search import minisat, sat from pyperplan.task import Operator, Task logging.basicConfig( level=logging.DEBUG, format="%(asctime)s %(levelname)-8s %(message)s", stream=sys.stdout, ) fact1 = "at-station" op1 = Operator("op1", set(), {"a"}, set()) op2 = Operator("op2", set(), set(), {"c"}) op3 = Operator("op3", ["d"], ["a"], []) op4 = Operator("op4", [], ["b"], []) task1 = Task("task1", {"a"}, set(), {"a"}, [op1]) task2 = Task("task2", {"a", "d"}, {"d"}, {"a"}, [op1, op3]) task3 = Task("task3", {"a", "b"}, set(), {"a", "b"}, [op1, op4]) task4 = Task("task4", {"a", "d"}, {"d"}, {"a"}, [op3]) task5 = Task("trivial", {"a"}, {"a"}, {"a"}, []) def sort_formula(formula): # Move all literals to the front and all subformulas to the back. strings = [part for part in formula if isinstance(part, str)] lists = [part for part in formula if isinstance(part, list)]
def test_collect_facts(): op1 = Operator("op1", {"var1"}, {}, {"var3"}) op2 = Operator("op2", {"var2"}, {"var3"}, {}) op3 = Operator("op3", {}, {"var1"}, {"var4"}) assert {"var1", "var2", "var3", "var4"} == grounding._collect_facts([op1, op2, op3])
def test_heuristics(): # simple task: two operators have to be applied task1 = Task( "task1", {"A", "B", "C"}, frozenset({"A"}), frozenset({"C", "B"}), [ Operator("op1", {"A"}, {"B"}, set()), Operator("op2", {"B"}, {"C"}, set()), Operator("op3", {"B"}, {"A"}, set()), ], ) # initial state is part of the goal state: one operator has to be applied task2 = Task( "task2", {"A", "B", "C"}, frozenset(["A", "B"]), frozenset(["B", "C"]), [ Operator("op1", {"A"}, {"B"}, set()), Operator("op2", {"B"}, {"C"}, set()) ], ) # task with one operator with two preconditions task3 = Task( "task3", {"A", "B", "C"}, frozenset(["A", "B"]), frozenset(["C"]), [Operator("op1", {"A", "B"}, {"C"}, set())], ) # task with one operator with two effects task4 = Task( "task4", {"A", "B", "C"}, frozenset(["A"]), frozenset(["C", "B"]), [Operator("op1", {"A"}, {"B", "C"}, set())], ) # task with one operator with equal precondition and effect, task4b = Task( "task4b", {"A", "B", "C"}, frozenset(["A"]), frozenset(["C", "B"]), [Operator("op1", {"A"}, {"A", "B", "C"}, set())], ) # task with one operator with several effects, # 2 operators have to be applied task5 = Task( "task5", {"A", "B", "C", "D", "E", "F"}, ["A"], ["E", "F"], [ Operator("op1", {"A"}, {"B", "C", "D", "E"}, set()), Operator("op2", {"C"}, {"F"}, set()), ], ) # task with one operator with several preconditions task6 = Task( "task6", {"A", "B", "C", "D", "E"}, ["A"], ["E"], [ Operator("op1", {"A"}, {"B"}, set()), Operator("op2", {"B"}, {"C"}, set()), Operator("op3", {"A"}, {"D"}, set()), Operator("op4", {"A", "C", "B", "D"}, {"E"}, set()), ], ) # task with empty initial state: no operator can be applied task7 = Task( "task7", {"A", "B", "C"}, [], ["C"], [ Operator("op1", {"A"}, {"B"}, set()), Operator("op2", {"B"}, {"C"}, set()) ], ) # task with initial state = goal state: no operator has to be applied task8 = Task( "task8", {"A", "B", "C"}, ["C"], ["C"], [ Operator("op1", {"A"}, {"B"}, set()), Operator("op2", {"B"}, {"C"}, set()) ], ) # task with operator with empty precondition task9 = Task( "task9", {"A", "B", "C"}, [], ["C"], [ Operator("op1", {}, {"B"}, set()), Operator("op2", {"B"}, {"C"}, set()) ], ) # a more complex task task10 = Task( "task10", {"v1", "v2", "v3", "v4", "v5", "v6", "g"}, ["v1"], ["g"], [ Operator("op1", {"v1"}, {"v2"}, set()), Operator("op2", {"v2"}, {"v3"}, set()), Operator("op3", {"v3"}, {"v4", "v5"}, set()), Operator("op4", {"v4", "v5"}, {"g"}, set()), Operator("op5", {"v2"}, {"v6"}, set()), Operator("op6", {"v6"}, {"v5"}, set()), ], ) # another complex task task12 = Task( "task12", {"A", "B", "C", "D", "E", "F", "G", "H", "I"}, ["A", "B"], ["F", "G", "H"], [ Operator("op1", {"A"}, {"C"}, set()), Operator("op2", {"C", "D"}, {"F"}, set()), Operator("op3", {"D", "E"}, {"G", "H"}, set()), Operator("op4", {"B"}, {"D", "E"}, set()), Operator("op5", {"I"}, {"H"}, set()), ], ) # task with no goal: task13 = Task( "task13", {"A", "B", "C"}, ["A", "B"], [], [Operator("op1", {"A", "B"}, {"C"}, set())], ) # task with no reachable goal: task14 = Task( "task14", {"A", "B", "C"}, ["A"], ["B", "C"], [Operator("op1", {"A"}, {"B"}, set())], ) # columns: landmarks lm_costs h expected = [ (task1, {"B", "C"}, { "B": 1, "C": 1 }, 2), (task2, {"B", "C"}, { "B": 1, "C": 1 }, 1), (task3, {"C"}, { "C": 1 }, 1), (task4, {"B", "C"}, { "B": 0.5, "C": 0.5 }, 1), ] for task, expected_landmarks, expected_lmc, exptected_h in expected: assert landmarks.get_landmarks(task) == expected_landmarks assert (landmarks.compute_landmark_costs( task, expected_landmarks) == expected_lmc) assert (landmarks.LandmarkHeuristic(task)(make_root_node( task.initial_state)) == exptected_h)
def test_landmarks1(): op1 = Operator("op1", set(), {"A"}, set()) op2 = Operator("op2", {"A"}, {"B"}, set()) task = Task("task1", {"A", "B"}, set(), {"B"}, [op1, op2]) assert landmarks.get_landmarks(task) == {"A", "B"}
def test_relaxed_task(): op1 = Operator("op1", {"A"}, {"A", "C"}, {"B", "C"}) task = Task("task1", set(), set(), set(), [op1]) relaxed_task = landmarks._get_relaxed_task(task) assert len(relaxed_task.operators[0].del_effects) == 0
rh = hAddHeuristic(task) rop1 = RelaxedOperator(op1.name, ["A"], ["B"]) assert len(rh.operators) == 2 assert len(rh.facts) == 3 assert rh.facts["A"].precondition_of[0].name == rop1.name # simple task: two operators have to be applied task1 = Task( "task1", {"A", "B", "C"}, ["A"], ["C", "B"], [ Operator("op1", {"A"}, {"B"}, set()), Operator("op2", {"B"}, {"C"}, set()), Operator("op3", {"B"}, {"A"}, set()), ], ) # initial state is part of the goal state: one operator has to be applied task2 = Task( "task2", {"A", "B", "C"}, ["A", "B"], ["B", "C"], [ Operator("op1", {"A"}, {"B"}, set()), Operator("op2", {"B"}, {"C"}, set()) ],