{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "0RTS5vYyzYbW" }, "source": [ "# Multi-Agent Plan Example\n", "\n", "This notebook will show how to generate a plan POP from a multi-agent problem.\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/10-multiagent-planning.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/10-multiagent-planning.ipynb)" ] }, { "cell_type": "markdown", "metadata": { "id": "Nh1CFk_f0usG" }, "source": [ "## Setup the UP library" ] }, { "cell_type": "markdown", "metadata": { "id": "CG_cqDVE0ynZ" }, "source": [ "We start by installing the library with PIP" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "IlmTj9uq05No", "outputId": "0c5e1f45-68af-4a0c-ca7d-e20c7a44ad38", "scrolled": true, "tags": [ "remove_from_CI" ] }, "outputs": [], "source": [ "!apt install graphviz graphviz-dev\n", "%pip install unified-planning[fmap,plot]" ] }, { "cell_type": "markdown", "metadata": { "id": "BXrh2xPcqHOC" }, "source": [ "## Demo" ] }, { "cell_type": "markdown", "metadata": { "id": "FSlkjirMqKlR" }, "source": [ "In this demo we show how to model a multi-agent planning problem using the Unified Planning library." ] }, { "cell_type": "markdown", "metadata": { "id": "Ku9S8iYnqNaJ" }, "source": [ "Basic imports" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "id": "pgGomDa7qPQP" }, "outputs": [], "source": [ "from unified_planning.shortcuts import *\n", "from unified_planning.model.multi_agent import *\n", "from collections import namedtuple\n", "from unified_planning.io.ma_pddl_writer import MAPDDLWriter" ] }, { "cell_type": "markdown", "metadata": { "id": "3BsXPKZp_vLx" }, "source": [ "## Creating the ma-depot problem" ] }, { "cell_type": "markdown", "metadata": { "id": "iIr-vSldqFZj" }, "source": [ "We define the UserTypes, the Objects, the Fluents and the Actions" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "id": "EkPYPFyuyZaX" }, "outputs": [], "source": [ "#USERTYPEs\n", "place = UserType(\"place\")\n", "locatable = UserType(\"locatable\")\n", "truck = UserType(\"truck\", locatable)\n", "hoist = UserType(\"hoist\", locatable)\n", "surface = UserType(\"surface\", locatable)\n", "pallet = UserType(\"pallet\", surface)\n", "crate = UserType(\"crate\", surface)\n", "pos = Fluent(\"pos\", place=place)\n", "\n", "#FLUENTs\n", "at = Fluent(\"at\", BoolType(), locatable=locatable, place=place)\n", "on = Fluent(\"on\", BoolType(), crate=crate, surface=surface)\n", "In = Fluent(\"in\", BoolType(), crate=crate, truck=truck)\n", "clear = Fluent(\"clear\", BoolType(), surface=surface)\n", "\n", "available = Fluent(\"available\", hoist=hoist)\n", "lifting = Fluent(\"lifting\", hoist=hoist, crate=crate)\n", "driving = Fluent(\"driving\", truck=truck)\n", "\n", "#OBJECTs\n", "truck0 = Object(\"truck0\", truck)\n", "truck1 = Object(\"truck1\", truck)\n", "depot0_place = Object(\"depot0_place\", place)\n", "distributor0_place = Object(\"distributor0_place\", place)\n", "distributor1_place = Object(\"distributor1_place\", place)\n", "crate0 = Object(\"crate0\", crate)\n", "crate1 = Object(\"crate1\", crate)\n", "pallet0 = Object(\"pallet0\", pallet)\n", "pallet1 = Object(\"pallet1\", pallet)\n", "pallet2 = Object(\"pallet2\", pallet)\n", "\n", "hoist0 = Object(\"hoist0\", hoist)\n", "hoist1 = Object(\"hoist1\", hoist)\n", "hoist2 = Object(\"hoist2\", hoist)\n", "\n", "#ACTIONs\n", "drive = InstantaneousAction(\"drive\", x=truck, y=place, z=place)\n", "x = drive.parameter(\"x\")\n", "y = drive.parameter(\"y\")\n", "z = drive.parameter(\"z\")\n", "\n", "drive.add_precondition(pos(y))\n", "drive.add_precondition(at(x, y))\n", "drive.add_precondition(driving(x))\n", "drive.add_effect(pos(z), True)\n", "drive.add_effect(pos(y), False)\n", "drive.add_effect(at(x, z), True)\n", "drive.add_effect(at(x, y), False)\n", "\n", "lift = InstantaneousAction(\"lift\", p=place, x=hoist, y=crate, z=surface)\n", "p = lift.parameter(\"p\")\n", "x = lift.parameter(\"x\")\n", "y = lift.parameter(\"y\")\n", "z = lift.parameter(\"z\")\n", "\n", "lift.add_precondition(pos(p))\n", "lift.add_precondition(at(x, p))\n", "lift.add_precondition(available(x))\n", "lift.add_precondition(at(y, p))\n", "lift.add_precondition(on(y, z))\n", "lift.add_precondition(clear(y))\n", "\n", "lift.add_effect(lifting(x, y), True)\n", "lift.add_effect(clear(z), True)\n", "lift.add_effect(at(y, p), False)\n", "lift.add_effect(clear(y), False)\n", "lift.add_effect(available(x), False)\n", "lift.add_effect(on(y, z), False)\n", "\n", "drop = InstantaneousAction(\"drop\", p=place, x=hoist, y=crate, z=surface)\n", "p = drop.parameter(\"p\")\n", "x = drop.parameter(\"x\")\n", "y = drop.parameter(\"y\")\n", "z = drop.parameter(\"z\")\n", "\n", "drop.add_precondition(pos(p))\n", "drop.add_precondition(at(x, p))\n", "drop.add_precondition(at(z, p))\n", "drop.add_precondition(clear(z))\n", "drop.add_precondition(lifting(x, y))\n", "\n", "drop.add_effect(available(x), True)\n", "drop.add_effect(at(y, p), True)\n", "drop.add_effect(clear(y), True)\n", "drop.add_effect(on(y, z), True)\n", "drop.add_effect(lifting(x, y), False)\n", "drop.add_effect(clear(z), False)\n", "\n", "load = InstantaneousAction(\"load\", p=place, x=hoist, y=crate, z=truck)\n", "p = load.parameter(\"p\")\n", "x = load.parameter(\"x\")\n", "y = load.parameter(\"y\")\n", "z = load.parameter(\"z\")\n", "\n", "load.add_precondition(pos(p))\n", "load.add_precondition(at(x, p))\n", "load.add_precondition(at(z, p))\n", "load.add_precondition(lifting(x, y))\n", "\n", "load.add_effect(In(y, z), True)\n", "load.add_effect(available(x), True)\n", "load.add_effect(lifting(x, y), False)\n", "\n", "unload = InstantaneousAction(\"unload\", p=place, x=hoist, y=crate, z=truck)\n", "p = unload.parameter(\"p\")\n", "x = unload.parameter(\"x\")\n", "y = unload.parameter(\"y\")\n", "z = unload.parameter(\"z\")\n", "\n", "unload.add_precondition(pos(p))\n", "unload.add_precondition(at(x, p))\n", "unload.add_precondition(at(z, p))\n", "unload.add_precondition(available(x))\n", "unload.add_precondition(In(y, z))\n", "\n", "unload.add_effect(lifting(x, y), True)\n", "unload.add_effect(In(y, z), False)\n", "unload.add_effect(available(x), False)" ] }, { "cell_type": "markdown", "metadata": { "id": "QaxTr4A_qkp3" }, "source": [ "The class that represents a multi-agent planning problem is unified_planning.MultiAgentProblem, it contains the set of agents, the objects, an intial value for all the fluents and a goal to be reached by the planner. We create a MultiAgentProblem and five Agents. An Agent is an individual entity with specific fluents and specific actions." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "id": "_TtEx0G_qh_z" }, "outputs": [], "source": [ "problem = MultiAgentProblem(\"depot\")\n", "\n", "depot0_a = Agent(\"depot0_agent\", problem)\n", "distributor0_a = Agent(\"distributor0_agent\", problem)\n", "distributor1_a = Agent(\"distributor1_agent\", problem)\n", "driver0_a = Agent(\"driver0_agent\", problem)\n", "driver1_a = Agent(\"driver1_agent\", problem)" ] }, { "cell_type": "markdown", "metadata": { "id": "PLmaFll6q7Ez" }, "source": [ "We add to the agents the actions they can perform." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "id": "b3sIlmSsq2Ch" }, "outputs": [], "source": [ "driver0_a.add_action(drive)\n", "driver1_a.add_action(drive)\n", "\n", "depot0_a.add_action(lift)\n", "depot0_a.add_action(drop)\n", "depot0_a.add_action(load)\n", "depot0_a.add_action(unload)\n", "\n", "distributor0_a.add_action(lift)\n", "distributor0_a.add_action(drop)\n", "distributor0_a.add_action(load)\n", "distributor0_a.add_action(unload)\n", "\n", "distributor1_a.add_action(lift)\n", "distributor1_a.add_action(drop)\n", "distributor1_a.add_action(load)\n", "distributor1_a.add_action(unload)" ] }, { "cell_type": "markdown", "metadata": { "id": "hYiJISdxrOzd" }, "source": [ "Let's add the fluents that aren't owned by the agents to the `ma_environment`.\n", "Note: Environment fluents are associated to environment’s and not agents’ properties." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "yCkHCOzqrNgi", "outputId": "0ce67f8b-df49-4fe3-ccf5-c13bcbd1ea0c" }, "outputs": [ { "data": { "text/plain": [ "bool clear[surface=surface - locatable]" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "problem.ma_environment.add_fluent(at, default_initial_value=False)\n", "problem.ma_environment.add_fluent(on, default_initial_value=False)\n", "problem.ma_environment.add_fluent(In, default_initial_value=False)\n", "problem.ma_environment.add_fluent(clear, default_initial_value=False)" ] }, { "cell_type": "markdown", "metadata": { "id": "U2zPlprWvqii" }, "source": [ "Let's add the `Fluents` to the `Agents`. Note: An agent's fluent can be of two types, public or private. `Public Fluents` are visible to other agents. In contrast, the `Private Fluents` are not visible from the other agents.\n", "Private fluents are added to the agent via the `add_fluent` or `add_private_fluent` methods and public fluents via the `add_public_fluent` method." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "2S2BhSjfrczD", "outputId": "76283e09-abf8-43a3-b2d0-31d9ddfcc916" }, "outputs": [ { "data": { "text/plain": [ "bool pos[place=place]" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "depot0_a.add_private_fluent(lifting, default_initial_value=False)\n", "depot0_a.add_private_fluent(available, default_initial_value=False)\n", "\n", "distributor0_a.add_private_fluent(lifting, default_initial_value=False)\n", "distributor0_a.add_private_fluent(available, default_initial_value=False)\n", "\n", "distributor1_a.add_private_fluent(lifting, default_initial_value=False)\n", "distributor1_a.add_private_fluent(available, default_initial_value=False)\n", "\n", "driver0_a.add_private_fluent(driving, default_initial_value=False)\n", "driver1_a.add_private_fluent(driving, default_initial_value=False)\n", "\n", "depot0_a.add_public_fluent(pos, default_initial_value=False)\n", "distributor0_a.add_public_fluent(pos, default_initial_value=False)\n", "distributor1_a.add_public_fluent(pos, default_initial_value=False)\n", "driver0_a.add_public_fluent(pos, default_initial_value=False)\n", "driver1_a.add_public_fluent(pos, default_initial_value=False)" ] }, { "cell_type": "markdown", "metadata": { "id": "Zbh0F-Nrv2r1" }, "source": [ "Let's add the agents to the `MultiAgentProblem`." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "id": "VrN3FhSbv16Y" }, "outputs": [], "source": [ "problem.add_agent(depot0_a)\n", "problem.add_agent(distributor0_a)\n", "problem.add_agent(distributor1_a)\n", "problem.add_agent(driver0_a)\n", "problem.add_agent(driver1_a)" ] }, { "cell_type": "markdown", "metadata": { "id": "Z223ZiM-wC6i" }, "source": [ "We add the objects, the initial values and the goals. \n", "Note: `Dot` operator is used to denote agent-specific `Fluents`." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "id": "CEJT-2UPwCKF" }, "outputs": [], "source": [ "#OBJECTs\n", "problem.add_object(crate0)\n", "problem.add_object(crate1)\n", "problem.add_object(truck0)\n", "problem.add_object(truck1)\n", "problem.add_object(depot0_place)\n", "problem.add_object(distributor0_place)\n", "problem.add_object(distributor1_place)\n", "problem.add_object(pallet0)\n", "problem.add_object(pallet1)\n", "problem.add_object(pallet2)\n", "problem.add_object(hoist0)\n", "problem.add_object(hoist1)\n", "problem.add_object(hoist2)\n", "\n", "#INITIAL VALUEs\n", "problem.set_initial_value(at(pallet0, depot0_place), True)\n", "problem.set_initial_value(clear(crate1), True)\n", "problem.set_initial_value(at(pallet1, distributor0_place), True)\n", "problem.set_initial_value(clear(crate0), True)\n", "problem.set_initial_value(at(pallet2, distributor1_place), True)\n", "problem.set_initial_value(clear(pallet2), True)\n", "\n", "problem.set_initial_value(at(truck0, distributor1_place), True)\n", "problem.set_initial_value(at(truck1, depot0_place), True)\n", "problem.set_initial_value(at(hoist0, depot0_place), True)\n", "problem.set_initial_value(at(hoist1, distributor0_place), True)\n", "problem.set_initial_value(at(hoist2, distributor1_place), True)\n", "problem.set_initial_value(at(crate0, distributor0_place), True)\n", "problem.set_initial_value(on(crate0, pallet1), True)\n", "problem.set_initial_value(at(crate1, depot0_place), True)\n", "problem.set_initial_value(on(crate1, pallet0), True)\n", "\n", "problem.set_initial_value(\n", " Dot(driver0_a, pos(distributor1_place)), True\n", ") \n", "problem.set_initial_value(Dot(driver1_a, pos(depot0_place)), True)\n", "problem.set_initial_value(Dot(depot0_a, pos(depot0_place)), True)\n", "problem.set_initial_value(Dot(depot0_a, available(hoist0)), True)\n", "problem.set_initial_value(Dot(distributor0_a, available(hoist1)), True)\n", "problem.set_initial_value(Dot(distributor1_a, available(hoist2)), True)\n", "\n", "problem.set_initial_value(Dot(distributor0_a, pos(distributor0_place)), True)\n", "problem.set_initial_value(Dot(distributor1_a, pos(distributor1_place)), True)\n", "\n", "problem.set_initial_value(Dot(driver0_a, driving(truck0)), True)\n", "problem.set_initial_value(Dot(driver1_a, driving(truck1)), True)\n", "\n", "#GOALs\n", "problem.add_goal(on(crate0, pallet2))\n", "problem.add_goal(on(crate1, pallet1))" ] }, { "cell_type": "markdown", "metadata": { "id": "33sSsdBEYzPA" }, "source": [ "Depot domain explained: https://www.jair.org/index.php/jair/article/view/10351/24754\n", "\n", "Derek Long and Maria Fox. 2003. The 3rd International Planning Competition:\n", "Results and Analysis. J. Artif. Intell. Res. (JAIR) 20 (12 2003)." ] }, { "cell_type": "markdown", "metadata": { "id": "9iv_1wUC1GnN" }, "source": [ "## Solving Multi-Agent Planning Problems" ] }, { "cell_type": "markdown", "metadata": { "id": "KOGieQQD143a" }, "source": [ "The most direct way to solve a planning problem is to select an available planning engine by name and use it to solve the problem. In the following we use fmap to solve the problem and print the plan." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "Ywv3VegrzSdP", "outputId": "b1450d61-809e-41ed-8588-dcc788eea509", "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[96m\u001b[1mNOTE: To disable printing of planning engine credits, add this line to your code: `up.shortcuts.get_environment().credits_stream = None`\n", "\u001b[0m\u001b[96m *** Credits ***\n", "\u001b[0m\u001b[96m * In operation mode `OneshotPlanner` at line 1 of `/tmp/ipykernel_159908/2463263861.py`, \u001b[0m\u001b[96myou are using the following planning engine:\n", "\u001b[0m\u001b[96m * Engine name: FMAP\n", " * Developers: Alejandro Torreño, Oscar Sapena and Eva Onaindia\n", "\u001b[0m\u001b[96m * Description: \u001b[0m\u001b[96mFMAP: A Platform for the Development of Distributed Multi-Agent Planning Systems.\u001b[0m\u001b[96m\n", "\u001b[0m\u001b[96m\n", "\u001b[0mFMAP returned: PartialOrderPlan:\n", " actions:\n", " 0) depot0_agent.lift(depot0_place, hoist0, crate1, pallet0)\n", " 1) distributor0_agent.lift(distributor0_place, hoist1, crate0, pallet1)\n", " 2) depot0_agent.load(depot0_place, hoist0, crate1, truck1)\n", " 3) driver1_agent.drive(truck1, depot0_place, distributor0_place)\n", " 4) distributor0_agent.load(distributor0_place, hoist1, crate0, truck1)\n", " 5) distributor0_agent.unload(distributor0_place, hoist1, crate1, truck1)\n", " 6) distributor0_agent.drop(distributor0_place, hoist1, crate1, pallet1)\n", " 7) driver1_agent.drive(truck1, distributor0_place, distributor1_place)\n", " 8) distributor1_agent.unload(distributor1_place, hoist2, crate0, truck1)\n", " 9) distributor1_agent.drop(distributor1_place, hoist2, crate0, pallet2)\n", " constraints:\n", " 0 < 2\n", " 1 < 2\n", " 2 < 3\n", " 3 < 4\n", " 4 < 5\n", " 5 < 6 ,7\n", " 6 < 8\n", " 7 < 8\n", " 8 < 9\n" ] } ], "source": [ "with OneshotPlanner(problem_kind=problem.kind) as planner:\n", " result = planner.solve(problem)\n", " plan = result.plan\n", " if plan is not None:\n", " print(\"FMAP returned: %s\" % result.plan)\n", " else:\n", " print(\"No plan found.\")" ] }, { "cell_type": "markdown", "metadata": { "id": "l08m2pEZ2EbQ" }, "source": [ "The unified_planning can also automatically select, among the available planners installed on the system, one that is expressive enough for the problem at hand." ] }, { "cell_type": "markdown", "metadata": { "id": "lKD2pzHy5u11" }, "source": [ "The `all_sequential_plans()` method returns all possible `SequentialPlans` that respects the sorting constraints given by this `PartialOrderPlan`" ] }, { "cell_type": "markdown", "metadata": { "id": "U1HjZV7t2Wku" }, "source": [ "We can also show all the possible `sequential plans` of this problem." ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "Qvp3xvf22FNC", "outputId": "3ea5e944-b32b-453b-a3b6-55b274c281bc" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[96m *** Credits ***\n", "\u001b[0m\u001b[96m * In operation mode `OneshotPlanner` at line 1 of `/tmp/ipykernel_159908/3865274623.py`, \u001b[0m\u001b[96myou are using the following planning engine:\n", "\u001b[0m\u001b[96m * Engine name: FMAP\n", " * Developers: Alejandro Torreño, Oscar Sapena and Eva Onaindia\n", "\u001b[0m\u001b[96m * Description: \u001b[0m\u001b[96mFMAP: A Platform for the Development of Distributed Multi-Agent Planning Systems.\u001b[0m\u001b[96m\n", "\u001b[0m\u001b[96m\n", "\u001b[0mAll the possible feasible Sequential Plans are:\n", "0) SequentialPlan:\n", " distributor0_agent.lift(distributor0_place, hoist1, crate0, pallet1)\n", " depot0_agent.lift(depot0_place, hoist0, crate1, pallet0)\n", " depot0_agent.load(depot0_place, hoist0, crate1, truck1)\n", " driver1_agent.drive(truck1, depot0_place, distributor0_place)\n", " distributor0_agent.load(distributor0_place, hoist1, crate0, truck1)\n", " distributor0_agent.unload(distributor0_place, hoist1, crate1, truck1)\n", " driver1_agent.drive(truck1, distributor0_place, distributor1_place)\n", " distributor0_agent.drop(distributor0_place, hoist1, crate1, pallet1)\n", " distributor1_agent.unload(distributor1_place, hoist2, crate0, truck1)\n", " distributor1_agent.drop(distributor1_place, hoist2, crate0, pallet2)\n", "1) SequentialPlan:\n", " distributor0_agent.lift(distributor0_place, hoist1, crate0, pallet1)\n", " depot0_agent.lift(depot0_place, hoist0, crate1, pallet0)\n", " depot0_agent.load(depot0_place, hoist0, crate1, truck1)\n", " driver1_agent.drive(truck1, depot0_place, distributor0_place)\n", " distributor0_agent.load(distributor0_place, hoist1, crate0, truck1)\n", " distributor0_agent.unload(distributor0_place, hoist1, crate1, truck1)\n", " distributor0_agent.drop(distributor0_place, hoist1, crate1, pallet1)\n", " driver1_agent.drive(truck1, distributor0_place, distributor1_place)\n", " distributor1_agent.unload(distributor1_place, hoist2, crate0, truck1)\n", " distributor1_agent.drop(distributor1_place, hoist2, crate0, pallet2)\n", "2) SequentialPlan:\n", " depot0_agent.lift(depot0_place, hoist0, crate1, pallet0)\n", " distributor0_agent.lift(distributor0_place, hoist1, crate0, pallet1)\n", " depot0_agent.load(depot0_place, hoist0, crate1, truck1)\n", " driver1_agent.drive(truck1, depot0_place, distributor0_place)\n", " distributor0_agent.load(distributor0_place, hoist1, crate0, truck1)\n", " distributor0_agent.unload(distributor0_place, hoist1, crate1, truck1)\n", " driver1_agent.drive(truck1, distributor0_place, distributor1_place)\n", " distributor0_agent.drop(distributor0_place, hoist1, crate1, pallet1)\n", " distributor1_agent.unload(distributor1_place, hoist2, crate0, truck1)\n", " distributor1_agent.drop(distributor1_place, hoist2, crate0, pallet2)\n", "3) SequentialPlan:\n", " depot0_agent.lift(depot0_place, hoist0, crate1, pallet0)\n", " distributor0_agent.lift(distributor0_place, hoist1, crate0, pallet1)\n", " depot0_agent.load(depot0_place, hoist0, crate1, truck1)\n", " driver1_agent.drive(truck1, depot0_place, distributor0_place)\n", " distributor0_agent.load(distributor0_place, hoist1, crate0, truck1)\n", " distributor0_agent.unload(distributor0_place, hoist1, crate1, truck1)\n", " distributor0_agent.drop(distributor0_place, hoist1, crate1, pallet1)\n", " driver1_agent.drive(truck1, distributor0_place, distributor1_place)\n", " distributor1_agent.unload(distributor1_place, hoist2, crate0, truck1)\n", " distributor1_agent.drop(distributor1_place, hoist2, crate0, pallet2)\n" ] } ], "source": [ "with OneshotPlanner(problem_kind=problem.kind) as planner:\n", " result = planner.solve(problem)\n", " print(\"All the possible feasible Sequential Plans are:\")\n", " for idx, seq_plan in enumerate(result.plan.all_sequential_plans()):\n", " print(f\"\\n{idx}) {seq_plan}\")" ] }, { "cell_type": "markdown", "metadata": { "id": "hP3oF6z5kNYA" }, "source": [ "### Plot the PartialOrderPlan as a graph" ] }, { "cell_type": "markdown", "metadata": { "id": "WoWHRUGcr6ix" }, "source": [ "We simply use the plot package." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from unified_planning.plot import plot_partial_order_plan" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ignore the code below, it's used to make this notebook also runnable in the Countinuous Intergation." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Redefine the plot package methods imported above to print the plot to a temp file\n", "# if the exception \"could not locate runnable browser\" is raised. This usually happens\n", "# in the Continuous Integration.\n", "\n", "from inspect import getmembers, isfunction\n", "from unified_planning import plot\n", "from functools import partial\n", "import os, uuid, tempfile as tf\n", "\n", "# Define the function that will be executed instead\n", "def _function(original_function, *args, **kwargs):\n", " try:\n", " original_function(*args, **kwargs)\n", " except Exception as e:\n", " if \"could not locate runnable browser\" in str(e):\n", " original_function(*args, **kwargs,\n", " filename=f\"{os.path.join(tf.gettempdir(), str(uuid.uuid1()))}.png\"\n", " )\n", " else:\n", " raise e\n", "\n", "# Iterate over all the functions of the plot package\n", "for function_name, function in getmembers(plot, isfunction):\n", " # Override the original function with the new one\n", " globals()[function_name] = partial(_function, function)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "fb-tzmnhsTVe", "outputId": "a7c16dc7-5976-4aa8-b5a2-94e583257bec", "scrolled": false }, "outputs": [], "source": [ "plot_partial_order_plan(result.plan, figsize=(20, 20), node_size=8000, font_size=10, top_bottom=True)" ] } ], "metadata": { "colab": { "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.6" } }, "nbformat": 4, "nbformat_minor": 1 }