From 9b9f0a0b8ea7e5c9db54a25fb97e455db9c16a60 Mon Sep 17 00:00:00 2001 From: Luca Framba Date: Sat, 9 Sep 2023 11:54:02 +0200 Subject: [PATCH 1/6] Small doc specification --- docs/optimality.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/optimality.rst b/docs/optimality.rst index e5aff1c6b..8158cb90c 100644 --- a/docs/optimality.rst +++ b/docs/optimality.rst @@ -11,7 +11,7 @@ Optimality Quality Metrics =============== -The UP library defines a set of "Quality Metrics" to express the objective functions to be optimized. Such metrics are defined in the `unified_planning.model.metrics` package and are described below. +The UP library defines a set of "Quality Metrics" to express the objective functions to be optimized. Such metrics are defined in the `unified_planning.model.metrics` file and are described below. - **MinimizeSequentialPlanLength** is used to optimize the number of steps in the resulting plans. From d72d22adcba844a5c640dee829d832f015c3172f Mon Sep 17 00:00:00 2001 From: Luca Framba Date: Sat, 9 Sep 2023 11:58:54 +0200 Subject: [PATCH 2/6] Added plan format to PDDLReader.parse_plan --- unified_planning/io/pddl_reader.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/unified_planning/io/pddl_reader.py b/unified_planning/io/pddl_reader.py index b17bf79f2..cc89496e9 100644 --- a/unified_planning/io/pddl_reader.py +++ b/unified_planning/io/pddl_reader.py @@ -1687,6 +1687,11 @@ def parse_plan( """ Takes a problem, a filename and optionally a map of renaming and returns the plan parsed from the file. + The format of the file must be: + ``(action-name param1 param2 ... paramN)`` in each line for SequentialPlans + ``start-time: (action-name param1 param2 ... paramN) [duration]`` in each line for TimeTriggeredPlans, + where ``[duration]`` is optional and not specified for InstantaneousActions. + :param problem: The up.model.problem.Problem instance for which the plan is generated. :param plan_filename: The path of the file in which the plan is written. :param get_item_named: A function that takes a name and returns the original up.model element instance @@ -1719,6 +1724,11 @@ def parse_plan_string( """ Takes a problem, a string and optionally a map of renaming and returns the plan parsed from the string. + The format of the file must be: + ``(action-name param1 param2 ... paramN)`` in each line for SequentialPlans + ``start-time: (action-name param1 param2 ... paramN) [duration]`` in each line for TimeTriggeredPlans, + where ``[duration]`` is optional and not specified for InstantaneousActions. + :param problem: The up.model.problem.Problem instance for which the plan is generated. :param plan_str: The plan in string. :param get_item_named: A function that takes a name and returns the original up.model element instance From 5a811f1de42146a7e2cb608e76586e088bf3090d Mon Sep 17 00:00:00 2001 From: Luca Framba Date: Sat, 9 Sep 2023 12:26:13 +0200 Subject: [PATCH 3/6] Fixed doc warning --- unified_planning/io/pddl_reader.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unified_planning/io/pddl_reader.py b/unified_planning/io/pddl_reader.py index cc89496e9..17fab80a9 100644 --- a/unified_planning/io/pddl_reader.py +++ b/unified_planning/io/pddl_reader.py @@ -1688,7 +1688,7 @@ def parse_plan( Takes a problem, a filename and optionally a map of renaming and returns the plan parsed from the file. The format of the file must be: - ``(action-name param1 param2 ... paramN)`` in each line for SequentialPlans + ``(action-name param1 param2 ... paramN)`` in each line for SequentialPlans ``start-time: (action-name param1 param2 ... paramN) [duration]`` in each line for TimeTriggeredPlans, where ``[duration]`` is optional and not specified for InstantaneousActions. @@ -1725,7 +1725,7 @@ def parse_plan_string( Takes a problem, a string and optionally a map of renaming and returns the plan parsed from the string. The format of the file must be: - ``(action-name param1 param2 ... paramN)`` in each line for SequentialPlans + ``(action-name param1 param2 ... paramN)`` in each line for SequentialPlans ``start-time: (action-name param1 param2 ... paramN) [duration]`` in each line for TimeTriggeredPlans, where ``[duration]`` is optional and not specified for InstantaneousActions. From 18a171bf5750101a518bfed0ed83ec8ccf66968e Mon Sep 17 00:00:00 2001 From: Luca Framba Date: Mon, 11 Sep 2023 14:00:07 +0200 Subject: [PATCH 4/6] Added a notebook on plan parsing and conversion between plans; still needs textual part --- docs/notebooks/12-plan-conversion.ipynb | 452 ++++++++++++++++++++++++ 1 file changed, 452 insertions(+) create mode 100644 docs/notebooks/12-plan-conversion.ipynb diff --git a/docs/notebooks/12-plan-conversion.ipynb b/docs/notebooks/12-plan-conversion.ipynb new file mode 100644 index 000000000..d75a41774 --- /dev/null +++ b/docs/notebooks/12-plan-conversion.ipynb @@ -0,0 +1,452 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "vXUqFpLObzhb" + }, + "source": [ + "## Plan Parsing and Conversion\n", + "\n", + "This python notebook shows how to use the unified planning library to parse a plan and how to convert plans from one type to another. \n", + "\n", + "[![Open In GitHub](https://img.shields.io/badge/see-Github-579aca?logo=github)](https:///github.com/aiplan4eu/unified-planning/blob/master/docs/notebooks/12-plan-parsing-conversion.ipynb)\n", + "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/aiplan4eu/unified-planning/blob/master/docs/notebooks/12-plan-parsing-conversion.ipynb)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "t8dCcpf7mivV" + }, + "source": [ + "### Setup\n", + "\n", + "For this example there are no planners needed." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "BoqALxJWdfl8", + "outputId": "299282e7-07f5-46df-e607-47da781dca50", + "scrolled": true, + "tags": [ + "remove_from_CI" + ] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Defaulting to user installation because normal site-packages is not writeable\n", + "Requirement already satisfied: unified-planning in /home/framba/.local/lib/python3.10/site-packages (1.0.0.79.dev1)\n", + "Requirement already satisfied: ConfigSpace in /home/framba/.local/lib/python3.10/site-packages (from unified-planning) (0.7.1)\n", + "Requirement already satisfied: networkx in /home/framba/.local/lib/python3.10/site-packages (from unified-planning) (2.8.3)\n", + "Requirement already satisfied: pyparsing in /home/framba/.local/lib/python3.10/site-packages (from unified-planning) (3.0.9)\n", + "Requirement already satisfied: numpy in /home/framba/.local/lib/python3.10/site-packages (from ConfigSpace->unified-planning) (1.24.1)\n", + "Requirement already satisfied: scipy in /home/framba/.local/lib/python3.10/site-packages (from ConfigSpace->unified-planning) (1.8.1)\n", + "Requirement already satisfied: typing-extensions in /home/framba/.local/lib/python3.10/site-packages (from ConfigSpace->unified-planning) (4.7.1)\n", + "Requirement already satisfied: more-itertools in /usr/lib/python3/dist-packages (from ConfigSpace->unified-planning) (8.10.0)\n" + ] + } + ], + "source": [ + "!pip install --pre unified-planning" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "iNHFHxQKnKIp" + }, + "source": [ + "We are now ready to use the Unified-Planning library!" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "xI2BGgmvdsek" + }, + "source": [ + "### Demo\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "xn5l-SVxufFA" + }, + "source": [ + "We start importing the shortcuts." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "id": "otZVSku3idJC" + }, + "outputs": [], + "source": [ + "from unified_planning.shortcuts import *" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "M9DCTuoSu2vh" + }, + "source": [ + "Now we start to model a problem involving three numeric variables $c_0$, $c_1$ and $c_2$ that can be increased and decreased. The goal of this problem is to change the variables values such that $c_0 < c_1 < c_2$. We name with value the lifted fluent that lets us access to the value of a given counter $c$.\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "nBaUofy3Ko7V" + }, + "source": [ + "\n", + "#### Creating the fluent\n", + "\n", + "First, we define the `UserTypes` and the `Fluents`." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "id": "e5BWi6wyuqyB" + }, + "outputs": [], + "source": [ + "Human = UserType('Human')\n", + "Supervisor = UserType('Supervisor', Human)\n", + "Worker = UserType('Worker', Human)\n", + "\n", + "Location = UserType('Location')\n", + "\n", + "is_supervisor_at = Fluent('is_supervisor_at', s=Supervisor, pos=Location)\n", + "is_worker_at = Fluent('is_worker_at', w=Worker, pos=Location)\n", + "\n", + "is_fixed = Fluent('is_fixed', l=Location)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "5sJwsWGy3-K5" + }, + "source": [ + "#### Creating the actions\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "id": "J-cU6CvL0-Pv" + }, + "outputs": [], + "source": [ + "move_supervisor = InstantaneousAction('move_supervisor', supervisor=Supervisor, l_from=Location, l_to=Location)\n", + "supervisor = move_supervisor.supervisor\n", + "l_from = move_supervisor.l_from\n", + "l_to = move_supervisor.l_to\n", + "move_supervisor.add_precondition(Not(Equals(l_from, l_to)))\n", + "move_supervisor.add_precondition(is_supervisor_at(supervisor, l_from))\n", + "move_supervisor.add_effect(is_supervisor_at(supervisor, l_from), False)\n", + "move_supervisor.add_effect(is_supervisor_at(supervisor, l_to), True)\n", + "\n", + "move_worker = InstantaneousAction('move_worker', worker=Worker, l_from=Location, l_to=Location)\n", + "worker = move_worker.worker\n", + "l_from = move_worker.l_from\n", + "l_to = move_worker.l_to\n", + "move_worker.add_precondition(Not(Equals(l_from, l_to)))\n", + "move_worker.add_precondition(is_worker_at(worker, l_from))\n", + "move_worker.add_effect(is_worker_at(worker, l_from), False)\n", + "move_worker.add_effect(is_worker_at(worker, l_to), True)\n", + "\n", + "fix_location = InstantaneousAction('fix_location', loc=Location, supervisor=Supervisor, worker=Worker)\n", + "loc = fix_location.loc\n", + "supervisor = fix_location.supervisor\n", + "worker = fix_location.worker\n", + "fix_location.add_precondition(is_supervisor_at(supervisor, loc))\n", + "fix_location.add_precondition(is_worker_at(worker, loc))\n", + "fix_location.add_effect(is_fixed(loc), True)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "aMMtRDVovvuM" + }, + "source": [ + "Finally, we can create a `Problem` that encompasses the fluents and the actions, and puts them together with concrete objects, an initial state and a goal. Note here that we do not need to specify all values for each object. These are set to 0 using the default intial value parameter.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "vEDxcqkLvm9d", + "outputId": "aae981f7-dac8-4a2e-e02a-0619edefd271", + "scrolled": true + }, + "outputs": [], + "source": [ + "problem = Problem('problem')\n", + "\n", + "problem.add_fluent(is_supervisor_at, default_initial_value=False)\n", + "problem.add_fluent(is_worker_at, default_initial_value=False)\n", + "problem.add_fluent(is_fixed, default_initial_value=False)\n", + "\n", + "s0 = Object('s0', Supervisor)\n", + "w0 = Object('w0', Worker)\n", + "l0 = Object('l0', Location)\n", + "l1 = Object('l1', Location)\n", + "l2 = Object('l2', Location)\n", + "\n", + "problem.add_objects((s0, w0, l0, l1, l2))\n", + "\n", + "problem.add_action(move_supervisor)\n", + "problem.add_action(move_worker)\n", + "problem.add_action(fix_location)\n", + "\n", + "var_loc = Variable('l', Location)\n", + "problem.add_goal(Forall(is_fixed(var_loc), var_loc))\n", + "problem.set_initial_value(is_supervisor_at(s0, l0), True)\n", + "problem.set_initial_value(is_worker_at(w0, l0), True)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Pfo5MK-4FIs4" + }, + "source": [ + "\n", + "Now we see how we can generate another, larger problem, much more compactly using a more programmatic definition\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "v62jmabZCyZr", + "outputId": "e44cd067-6ceb-4db1-b939-34c79248f64c" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "SequentialPlan:\n", + " fix_location(l0, s0, w0)\n", + " move_supervisor(s0, l0, l1)\n", + " move_worker(w0, l0, l1)\n", + " fix_location(l1, s0, w0)\n", + " move_supervisor(s0, l1, l2)\n", + " move_worker(w0, l1, l2)\n", + " fix_location(l2, s0, w0)\n" + ] + } + ], + "source": [ + "from unified_planning.io import PDDLReader\n", + "\n", + "plan_str = \"\"\"(fix_location l0 s0 w0)\n", + "(move_supervisor s0 l0 l1)\n", + "(move_worker w0 l0 l1)\n", + "(fix_location l1 s0 w0)\n", + "(move_supervisor s0 l1 l2)\n", + "(move_worker w0 l1 l2)\n", + "(fix_location l2 s0 w0)\n", + "\"\"\"\n", + "\n", + "reader = PDDLReader()\n", + "sequential_plan = reader.parse_plan_string(problem, plan_str)\n", + "print(sequential_plan)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "z3l0y9kaKMII" + }, + "source": [ + "#### Solving the small and the parametric problem\n", + "\n", + "The unified_planning can either select among the available planners one which is suited for the task at hand (looking at the problem kind), or use the user defined planning. In what follows we first attempt to solve the small problem with three counters and ask the UP to use a specific planning system (ENHSP), and then one with N=9 counters (problem p2) asking the UP to automatically select the engine\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "frcEeD-oKO2m", + "outputId": "1ea9a630-db3f-47d8-b011-85e97be31203" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "PartialOrderPlan:\n", + " actions:\n", + " 0) fix_location(l0, s0, w0)\n", + " 1) move_supervisor(s0, l0, l1)\n", + " 2) move_worker(w0, l0, l1)\n", + " 3) fix_location(l1, s0, w0)\n", + " 4) move_worker(w0, l1, l2)\n", + " 5) move_supervisor(s0, l1, l2)\n", + " 6) fix_location(l2, s0, w0)\n", + " constraints:\n", + " 0 < 1 ,2\n", + " 1 < 3\n", + " 2 < 3\n", + " 3 < 4 ,5\n", + " 5 < 6\n", + " 4 < 6\n" + ] + } + ], + "source": [ + "from unified_planning.plans import PlanKind\n", + "\n", + "partial_order_plan = sequential_plan.convert_to(PlanKind.PARTIAL_ORDER_PLAN, problem)\n", + "\n", + "print(partial_order_plan)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "1Xz-IqYoE56M", + "outputId": "8a4b48ec-06e7-41f4-837d-c4c2c0564d14" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "SequentialPlan:\n", + " fix_location(l0, s0, w0)\n", + " move_worker(w0, l0, l1)\n", + " move_supervisor(s0, l0, l1)\n", + " fix_location(l1, s0, w0)\n", + " move_supervisor(s0, l1, l2)\n", + " move_worker(w0, l1, l2)\n", + " fix_location(l2, s0, w0)\n", + "1\n", + "SequentialPlan:\n", + " fix_location(l0, s0, w0)\n", + " move_worker(w0, l0, l1)\n", + " move_supervisor(s0, l0, l1)\n", + " fix_location(l1, s0, w0)\n", + " move_worker(w0, l1, l2)\n", + " move_supervisor(s0, l1, l2)\n", + " fix_location(l2, s0, w0)\n", + "2\n", + "SequentialPlan:\n", + " fix_location(l0, s0, w0)\n", + " move_supervisor(s0, l0, l1)\n", + " move_worker(w0, l0, l1)\n", + " fix_location(l1, s0, w0)\n", + " move_supervisor(s0, l1, l2)\n", + " move_worker(w0, l1, l2)\n", + " fix_location(l2, s0, w0)\n", + "3\n", + "SequentialPlan:\n", + " fix_location(l0, s0, w0)\n", + " move_supervisor(s0, l0, l1)\n", + " move_worker(w0, l0, l1)\n", + " fix_location(l1, s0, w0)\n", + " move_worker(w0, l1, l2)\n", + " move_supervisor(s0, l1, l2)\n", + " fix_location(l2, s0, w0)\n" + ] + } + ], + "source": [ + "for i, sorted_plan in enumerate(partial_order_plan.all_sequential_plans()):\n", + " print(i)\n", + " print(sorted_plan)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "YGfAogQpHZY-" + }, + "source": [ + "Now let us create a problem medium-sized problem, set up a minimisation function as minimize the number of actions, and see how this can be solved optimally." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "v41WrIcmH1eJ", + "outputId": "e80e8b7b-dfb1-4d88-84a2-856c0ba9a50f" + }, + "outputs": [], + "source": [ + "\n" + ] + } + ], + "metadata": { + "celltoolbar": "Tags", + "colab": { + "name": "Plan Parsing and Conversion", + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} From 1ad207312a766629e85af3c1298a28f299845033 Mon Sep 17 00:00:00 2001 From: Luca Framba Date: Mon, 11 Sep 2023 15:00:42 +0200 Subject: [PATCH 5/6] Added notebook description --- docs/notebooks/08-sequential-simulator.ipynb | 2 +- docs/notebooks/12-plan-conversion.ipynb | 97 +++++++++----------- 2 files changed, 44 insertions(+), 55 deletions(-) diff --git a/docs/notebooks/08-sequential-simulator.ipynb b/docs/notebooks/08-sequential-simulator.ipynb index 3cf727888..1d0a310fd 100644 --- a/docs/notebooks/08-sequential-simulator.ipynb +++ b/docs/notebooks/08-sequential-simulator.ipynb @@ -563,7 +563,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.6" + "version": "3.10.12" }, "vscode": { "interpreter": { diff --git a/docs/notebooks/12-plan-conversion.ipynb b/docs/notebooks/12-plan-conversion.ipynb index d75a41774..8594330fc 100644 --- a/docs/notebooks/12-plan-conversion.ipynb +++ b/docs/notebooks/12-plan-conversion.ipynb @@ -22,7 +22,7 @@ "source": [ "### Setup\n", "\n", - "For this example there are no planners needed." + "For this example there are no planners needed, so the library can be installed" ] }, { @@ -34,28 +34,12 @@ }, "id": "BoqALxJWdfl8", "outputId": "299282e7-07f5-46df-e607-47da781dca50", - "scrolled": true, + "scrolled": false, "tags": [ "remove_from_CI" ] }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Defaulting to user installation because normal site-packages is not writeable\n", - "Requirement already satisfied: unified-planning in /home/framba/.local/lib/python3.10/site-packages (1.0.0.79.dev1)\n", - "Requirement already satisfied: ConfigSpace in /home/framba/.local/lib/python3.10/site-packages (from unified-planning) (0.7.1)\n", - "Requirement already satisfied: networkx in /home/framba/.local/lib/python3.10/site-packages (from unified-planning) (2.8.3)\n", - "Requirement already satisfied: pyparsing in /home/framba/.local/lib/python3.10/site-packages (from unified-planning) (3.0.9)\n", - "Requirement already satisfied: numpy in /home/framba/.local/lib/python3.10/site-packages (from ConfigSpace->unified-planning) (1.24.1)\n", - "Requirement already satisfied: scipy in /home/framba/.local/lib/python3.10/site-packages (from ConfigSpace->unified-planning) (1.8.1)\n", - "Requirement already satisfied: typing-extensions in /home/framba/.local/lib/python3.10/site-packages (from ConfigSpace->unified-planning) (4.7.1)\n", - "Requirement already satisfied: more-itertools in /usr/lib/python3/dist-packages (from ConfigSpace->unified-planning) (8.10.0)\n" - ] - } - ], + "outputs": [], "source": [ "!pip install --pre unified-planning" ] @@ -66,7 +50,7 @@ "id": "iNHFHxQKnKIp" }, "source": [ - "We are now ready to use the Unified-Planning library!" + "We are now ready to use the Unified-Planning library and to modify plans!" ] }, { @@ -104,9 +88,11 @@ "id": "M9DCTuoSu2vh" }, "source": [ - "Now we start to model a problem involving three numeric variables $c_0$, $c_1$ and $c_2$ that can be increased and decreased. The goal of this problem is to change the variables values such that $c_0 < c_1 < c_2$. We name with value the lifted fluent that lets us access to the value of a given counter $c$.\n", + "Now we create a problem that models a world where there are a number of locations to be fixed. To fix a location, both a worker and a supervisor are needed.\n", "\n", - "\n" + "The workers and the supervisors can move between locations freely and independently.\n", + "\n", + "The idea of the deordering is that the order in which the supervisors and the workers move in-between locations does not matter, they just have to arrive both in a location before it can be fixed." ] }, { @@ -116,9 +102,9 @@ }, "source": [ "\n", - "#### Creating the fluent\n", + "#### Creating the fluents\n", "\n", - "First, we define the `UserTypes` and the `Fluents`." + "First, we define the `UserTypes`, and the `Fluents`." ] }, { @@ -129,9 +115,8 @@ }, "outputs": [], "source": [ - "Human = UserType('Human')\n", - "Supervisor = UserType('Supervisor', Human)\n", - "Worker = UserType('Worker', Human)\n", + "Supervisor = UserType('Supervisor')\n", + "Worker = UserType('Worker')\n", "\n", "Location = UserType('Location')\n", "\n", @@ -147,7 +132,9 @@ "id": "5sJwsWGy3-K5" }, "source": [ - "#### Creating the actions\n" + "#### Creating the actions\n", + "\n", + "One to move a Supervisor, one to move a Worker and one to fix a Location." ] }, { @@ -191,7 +178,11 @@ "id": "aMMtRDVovvuM" }, "source": [ - "Finally, we can create a `Problem` that encompasses the fluents and the actions, and puts them together with concrete objects, an initial state and a goal. Note here that we do not need to specify all values for each object. These are set to 0 using the default intial value parameter.\n" + "Finally, we can create a `Problem` that encompasses the fluents and the actions, and puts them together with concrete objects, an initial state and a goal. \n", + "\n", + "The goal is that every location is fixed at the end.\n", + "\n", + "Both the supervisor and the worker start at location 'l0'.\n" ] }, { @@ -225,10 +216,11 @@ "problem.add_action(move_worker)\n", "problem.add_action(fix_location)\n", "\n", - "var_loc = Variable('l', Location)\n", - "problem.add_goal(Forall(is_fixed(var_loc), var_loc))\n", "problem.set_initial_value(is_supervisor_at(s0, l0), True)\n", - "problem.set_initial_value(is_worker_at(w0, l0), True)\n" + "problem.set_initial_value(is_worker_at(w0, l0), True)\n", + "\n", + "var_loc = Variable('l', Location)\n", + "problem.add_goal(Forall(is_fixed(var_loc), var_loc))" ] }, { @@ -238,8 +230,7 @@ }, "source": [ "\n", - "Now we see how we can generate another, larger problem, much more compactly using a more programmatic definition\n", - "\n" + "Now we specify a valid plan in a format parsable by the PDDLReader; the accepted formats are in the PDDLReader.parse_plan (or parse_plan_string) methods" ] }, { @@ -257,7 +248,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "SequentialPlan:\n", + "Parsed plan: SequentialPlan:\n", " fix_location(l0, s0, w0)\n", " move_supervisor(s0, l0, l1)\n", " move_worker(w0, l0, l1)\n", @@ -282,7 +273,7 @@ "\n", "reader = PDDLReader()\n", "sequential_plan = reader.parse_plan_string(problem, plan_str)\n", - "print(sequential_plan)" + "print(\"Parsed plan: \", sequential_plan)" ] }, { @@ -291,9 +282,13 @@ "id": "z3l0y9kaKMII" }, "source": [ - "#### Solving the small and the parametric problem\n", + "#### Converting the SequentialPlan to a PartialOrderPlan\n", + "\n", + "Now we use the `Plan.convert_to` method, that allows conversion from a `PlanKind` to another `PlanKind`.\n", "\n", - "The unified_planning can either select among the available planners one which is suited for the task at hand (looking at the problem kind), or use the user defined planning. In what follows we first attempt to solve the small problem with three counters and ask the UP to use a specific planning system (ENHSP), and then one with N=9 counters (problem p2) asking the UP to automatically select the engine\n" + "Few conversions are implemented at the moment, also because some conversions do not make sense at all!\n", + "\n", + "The most interesting currently implemented is the conversion between `Sequential` an `PartialOrder` plans; it's important to specify that the conversion is not the most general possible." ] }, { @@ -338,6 +333,15 @@ "print(partial_order_plan)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As we can see from the print above, location `l0` must be fixed before the supervisor and the worker both move to location `l1`, (constraint `0 < 1, 2`) but both the move actions must be performed before fixing the location `l1` (constraints `1 < 3` and `2 < 3`). Same for `l1` and `l2`.\n", + "\n", + "The following code shows a special feature of the `PartialOrderPlan`, where we can get an Iterator over all the `SequentialPlans` that follow the ordering enforced by the `PartialOrderPlan` constraints." + ] + }, { "cell_type": "code", "execution_count": 8, @@ -404,22 +408,7 @@ "id": "YGfAogQpHZY-" }, "source": [ - "Now let us create a problem medium-sized problem, set up a minimisation function as minimize the number of actions, and see how this can be solved optimally." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "v41WrIcmH1eJ", - "outputId": "e80e8b7b-dfb1-4d88-84a2-856c0ba9a50f" - }, - "outputs": [], - "source": [ - "\n" + "In the 4 plans above the order of the move_supervisor and move_worker between the 3 locations are mixed up!" ] } ], From a7a88a82eb7f260877bcd68dfb3aea728cccd9ed Mon Sep 17 00:00:00 2001 From: Luca Framba Date: Wed, 13 Sep 2023 10:09:28 +0200 Subject: [PATCH 6/6] Added new notebook to examples --- docs/examples.rst | 17 +++++++++++++++++ ...n.ipynb => 12-plan-parsing-conversion.ipynb} | 0 2 files changed, 17 insertions(+) rename docs/notebooks/{12-plan-conversion.ipynb => 12-plan-parsing-conversion.ipynb} (100%) diff --git a/docs/examples.rst b/docs/examples.rst index 5262e03cc..c4b1d016c 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -245,6 +245,23 @@ In this notebook we show how to parse a problem from PDDL in the unified_plannin a unified_planning problem in PDDL. +Plan Parsing and Conversion +--------------------------- + + +.. image:: https://img.shields.io/badge/see-Github-579aca?logo=github + :target: https:///github.com/aiplan4eu/unified-planning/blob/master/docs/notebooks/12-plan-parsing-conversion.ipynb + :alt: Open In GitHub + + +.. image:: https://colab.research.google.com/assets/colab-badge.svg + :target: https://colab.research.google.com/github/aiplan4eu/unified-planning/blob/master/docs/notebooks/12-plan-parsing-conversion.ipynb + :alt: Open In Colab + + +In this notebook we show how to parse a plan from a file (or a string) and how to convert a plan from a format to another. + + MA-PDDL Writer -------------- diff --git a/docs/notebooks/12-plan-conversion.ipynb b/docs/notebooks/12-plan-parsing-conversion.ipynb similarity index 100% rename from docs/notebooks/12-plan-conversion.ipynb rename to docs/notebooks/12-plan-parsing-conversion.ipynb