Ce notebook configure automatiquement l’environnement pour la serie de notebooks sur la Planification Automatique.
Objectifs d’apprentissage
A la fin de ce notebook, vous saurez : 1. Installer et verifier les bibliotheques principales (unified-planning, OR-Tools) 2. Configurer Fast Downward via Docker pour la planification optimale 3. Comprendre la structure de la serie de notebooks 4. Resoudre un problème de planification simple avec PDDL
Prerequis
Python 3.9+ installe
Docker installe (pour Fast Downward)
Connaissances basiques en Python
Duree estimee : 20 minutes
1. Detection de l’environnement
Commencons par detecter le système d’exploitation et la configuration Python.
# Detection de l'environnementimport sysimport osimport platformimport subprocessimport shutilfrom pathlib import Path# Informations systemeOS_NAME = platform.system() # 'Windows', 'Linux', 'Darwin'OS_VERSION = platform.version()PYTHON_VERSION = sys.version_infoIS_WINDOWS = OS_NAME =='Windows'IS_LINUX = OS_NAME =='Linux'IS_MAC = OS_NAME =='Darwin'print(f"Systeme d'exploitation: {OS_NAME}")print(f"Version Python: {PYTHON_VERSION.major}.{PYTHON_VERSION.minor}.{PYTHON_VERSION.micro}")# Chemin portable (relatif au marqueur du depot) — ne leake pas le chemin absolu machine_cwd_parts = Path.cwd().partsif"MyIA.AI.Notebooks"in _cwd_parts: _repo_rel = Path(*_cwd_parts[_cwd_parts.index("MyIA.AI.Notebooks"):]).as_posix()else: _repo_rel = os.getcwd()print(f"Repertoire de travail: {_repo_rel}")print(f"Executable Python: {sys.executable}")
Systeme d'exploitation: Windows
Version Python: 3.13.13
Repertoire de travail: MyIA.AI.Notebooks/SymbolicAI/Planners/00-Environment
Executable Python: <USER_PATH>\AppData\Local\Programs\Python\Python313\python.exe
Interpretation : Detection de l’environnement
Sortie obtenue : le système est Windows, et la cellule imprime la version Python détectée.
Le pre-requis (3.9+) est ce qui a une valeur pedagogique : il ne bouge pas d’une machine a l’autre. La version detectee, elle, change a chaque montee de version — la recopier ici la mettrait en contradiction avec la sortie d’a-cote des le prochain bump (#9434).
Points cles : 1. La version detectee satisfait le pre-requis 3.9+ : toutes les bibliotheques de planification de la serie sont compatibles 2. Windows necessite une attention particuliere pour les chemins Docker (C:\ → /c/) 3. Le repertoire de travail est correctement positionne dans la serie Planners
Note technique : La detection automatique de l’OS permet d’adapter les commandes Docker (conversion des chemins Windows vers WSL/Git Bash).
2. Technologies de planification
Cette serie utilise plusieurs technologies complementaires :
Technologie
Description
Usage dans la serie
unified-planning
Bibliotheque Python unifiee pour la planification
Interface PDDL, modèles
Fast Downward
Planificateur optimal (IPC winner)
Resolution, heuristiques
OR-Tools
Suite d’optimisation Google
CP-SAT, scheduling
2.1 Fast Downward
Fast Downward est un système de planification automatisée open-source developpe en C++. Il implemente différents algorithmes de planification bases sur la recherche heuristique :
A* avec heuristiques admissibles (optimal)
Greedy Best-First Search (satisficing)
LAMA (gagnant IPC multiple fois)
2.2 Google OR-Tools
OR-Tools est une suite open-source de logiciels d’optimisation :
Programmation par contraintes (CP-SAT)
Optimisation lineaire et en nombres entiers
Planification de routes (VRP)
Ordonnancement (scheduling)
2.3 unified-planning
unified-planning est une bibliotheque Python qui fournit une interface unifiee pour différents planificateurs :
Ecriture de modèles PDDL en Python
Connexion a plusieurs solveurs (Fast Downward, ENHSP, etc.)
Simulation et validation de plans
3. Installation des dependances Python
Nous installons les bibliotheques Python necessaires pour la planification.
# Installation des dependances Pythondef install_package(package_name, import_name=None):"""Installe un package s'il n'est pas deja installe."""if import_name isNone: import_name = package_nametry:__import__(import_name)returnTrueexceptImportError:print(f"Installation de {package_name}...") result = subprocess.run( [sys.executable, '-m', 'pip', 'install', package_name, '-q'], capture_output=True, text=True )if result.returncode ==0:print(f" {package_name} installe avec succes")returnTrueelse:print(f" Echec installation {package_name}: {result.stderr}")returnFalse# Packages essentiels pour la planificationPACKAGES = [ ('unified-planning', 'unified_planning'), ('up-fast-downward', 'up_fast_downward'), # Plugin Fast Downward ('ortools', 'ortools'), ('numpy', 'numpy'), ('matplotlib', 'matplotlib'), ('networkx', 'networkx'), ('graphviz', 'graphviz'),]print("Verification et installation des dependances Python...")print("="*50)for pkg_name, import_name in PACKAGES: install_package(pkg_name, import_name)print("="*50)print("Installation des dependances Python terminee.")
Verification et installation des dependances Python...
==================================================
==================================================
Installation des dependances Python terminee.
Interpretation : Installation des dependances
Sortie obtenue : Tous les packages sont déjà installes sur le système.
Package
Statut
Usage dans la serie
unified-planning
Déjà installe
API Python pour PDDL
up-fast-downward
Déjà installe
Plugin Fast Downward
ortools
Déjà installe
Optimisation CP-SAT
numpy
Déjà installe
Calculs numériques
matplotlib
Déjà installe
Visualisations
networkx
Déjà installe
Graphes d’etats
graphviz
Déjà installe
Visualisation PDDL
Points cles : 1. L’installation silencieuse (-q) evite d’inonder la sortie avec les details 2. La verification prealable evite de reinstaller des packages déjà presents 3. Tous les outils necessaires pour la serie sont maintenant disponibles
Note technique : Les packages sont installes dans l’environnement Python global. Pour un environnement isole, utilisez venv ou conda env.
3.1 Verification de unified-planning
# Verification de unified-planningtry:import unified_planning as upfrom unified_planning.shortcuts import*print(f"unified-planning version: {up.__version__}") UP_OK =TrueexceptImportErroras e:print(f"ERREUR: unified-planning non installe: {e}")print("Solution: pip install unified-planning") UP_OK =False
unified-planning version: 1.3.0
Interpretation : Verification unified-planning
Sortie obtenue : La bibliotheque unified-planning est installee en version 1.3.0.
Composant
Version
Signification
unified-planning
1.3.0
Interface Python pour la planification
Points cles : 1. Unified-planning fournit une API Python unifiee pour plusieurs planificateurs 2. Il permet de définir des problemes PDDL programmatiquement sans ecrire de fichiers 3. Les raccourcis from unified_planning.shortcuts import * simplifient la modelisation
Note technique : La version 1.3.0 est stable et supporte la plupart des planificateurs modernes (Fast Downward, ENHSP, pyperplan).
Sortie obtenue : OR-Tools CP-SAT est correctement installe.
Composant
Statut
Usage
OR-Tools CP-SAT
OK
Solveur de programmation par contraintes
Points cles : 1. OR-Tools sera utilise pour les problemes de planification par contraintes (notebook 7) 2. CP-SAT est un solveur moderne et performant pour les problemes mixtes entiers 3. Il permet de modeliser des problemes de scheduling, VRP, et planification temporelle
Note technique : OR-Tools est developpe par Google et utilise en production dans de nombreux systèmes industriels.
4. Configuration Docker pour Fast Downward
Fast Downward est un planificateur C++ qui necessite une compilation. Pour simplifier l’installation et assurer la compatibilite multi-plateforme, nous utilisons Docker avec l’image officielle.
Avantages de l’approche Docker
Aspect
Native
Docker
Installation
Complexe (CMake, g++)
Simple (pull image)
Compatibilite
Linux/WSL uniquement
Toutes plateformes
Reproductibilite
Variable
Garantie
Maintenance
Manuelle
Automatique
# Verification de Dockerdef check_docker():"""Verifie si Docker est disponible et operationnel."""try: result = subprocess.run( ['docker', '--version'], capture_output=True, text=True, timeout=10 )if result.returncode ==0:returnTrue, result.stdout.strip()returnFalse, result.stderrexceptFileNotFoundError:returnFalse, "Docker non installe"except subprocess.TimeoutExpired:returnFalse, "Timeout"exceptExceptionas e:returnFalse, str(e)DOCKER_OK, DOCKER_INFO = check_docker()if DOCKER_OK:print(f"Docker disponible: {DOCKER_INFO}")else:print(f"Docker non disponible: {DOCKER_INFO}")
Docker disponible: Docker version 29.5.2, build 79eb04c
Interpretation : Verification Docker
Sortie obtenue : Docker est disponible et operationnel sur cette machine.
Composant
Statut
Signification
Docker
OK
Moteur de conteneurisation installe et fonctionnel
Version
29.5.2
Version recente et stable
Points cles : 1. Docker permet d’executer Fast Downward dans un environnement isole 2. L’image Docker aiplanning/fast-downward n’est plus disponible publiquement 3. Le plugin up-fast-downward sera utilise a la place pour la planification
Note technique : Si Docker n’est pas disponible, unified-planning peut fonctionner avec d’autres solveurs (pyperplan, ENHSP) mais Fast Downward necessite soit Docker, soit une compilation native.
4.1 Telechargement de l’image Fast Downward
L’image Docker jsboige/coursia-fast-downward contient Fast Downward pre-compile avec un serveur API HTTP sur le port 8200.
# Telechargement et lancement de l'image Fast Downward# Image Docker avec serveur API Fast Downward (port 8200)# Reference: docker-configurations/services/planners-downward/FAST_DOWNWARD_IMAGE ="jsboige/coursia-fast-downward:latest"FD_API_PORT =8200FD_CONTAINER_NAME ="coursia-fast-downward"def pull_fast_downward():"""Telecharge l'image Docker Fast Downward."""ifnot DOCKER_OK:print("Docker non disponible - impossible de telecharger l'image")returnFalseprint(f"Telechargement de l'image {FAST_DOWNWARD_IMAGE}...")print("(Ceci peut prendre quelques minutes lors de la premiere execution)") result = subprocess.run( ['docker', 'pull', FAST_DOWNWARD_IMAGE], capture_output=True, text=True, timeout=300 )if result.returncode ==0:print("Image Fast Downward telechargee avec succes")returnTrueelse:print(f"Erreur lors du telechargement: {result.stderr}")returnFalsedef start_fd_container():"""Demarre le conteneur Fast Downward en mode serveur API."""ifnot DOCKER_OK:returnFalse# Verifier si le conteneur tourne deja (chemin rapide : reutiliser) result = subprocess.run( ['docker', 'ps', '-q', '-f', f'name={FD_CONTAINER_NAME}'], capture_output=True, text=True )if result.stdout.strip():print(f"Conteneur {FD_CONTAINER_NAME} deja en cours d'execution")returnTrue# Supprimer tout conteneur existant (arrete ou en erreur) avant relancement# Evite "container name already in use" quand le conteneur est Exited subprocess.run(['docker', 'rm', '-f', FD_CONTAINER_NAME], capture_output=True, text=True, timeout=10)# Lancer le conteneur en mode detacheimport timeimport urllib.request cmd = ['docker', 'run', '-d', '--name', FD_CONTAINER_NAME,'-p', f'{FD_API_PORT}:{FD_API_PORT}', FAST_DOWNWARD_IMAGE ] result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)if result.returncode !=0:print(f"Erreur lancement conteneur: {result.stderr}")returnFalse# Attendre que le serveur soit pretfor attempt inrange(15): time.sleep(1)try: resp = urllib.request.urlopen(f'http://localhost:{FD_API_PORT}/health', timeout=3)if resp.status ==200:print(f"Conteneur Fast Downward demarre (port {FD_API_PORT})")returnTrueexceptException:passprint("Timeout: le conteneur n'a pas repondu dans les 15s")returnFalse# Verifier si l'image existe dejadef check_image_exists(image_name):"""Verifie si une image Docker existe localement.""" result = subprocess.run( ['docker', 'images', '-q', image_name], capture_output=True, text=True )returnbool(result.stdout.strip())if DOCKER_OK:if check_image_exists(FAST_DOWNWARD_IMAGE):print(f"Image {FAST_DOWNWARD_IMAGE} deja presente localement")else: pull_fast_downward() FD_DOCKER_OK = start_fd_container()else: FD_DOCKER_OK =Falseprint("Note: Fast Downward via Docker ne sera pas disponible.")print("Vous pourrez utiliser unified-planning avec d'autres solveurs.")
Telechargement de l'image jsboige/coursia-fast-downward:latest...
(Ceci peut prendre quelques minutes lors de la premiere execution)
Erreur lors du telechargement: failed to connect to the docker API at npipe:////./pipe/dockerDesktopLinuxEngine; check if the path is correct and if the daemon is running: open //./pipe/dockerDesktopLinuxEngine: The system cannot find the file specified.
Erreur lancement conteneur: failed to connect to the docker API at npipe:////./pipe/dockerDesktopLinuxEngine; check if the path is correct and if the daemon is running: open //./pipe/dockerDesktopLinuxEngine: The system cannot find the file specified.
4.2 Fonction utilitaire pour Fast Downward Docker
Cette fonction permet d’executer Fast Downward via l’API HTTP du conteneur Docker.
# Fonction utilitaire pour executer Fast Downward via l'API Dockerimport jsonimport urllib.requestdef run_fast_downward_docker(domain_pddl: str, problem_pddl: str, search_config: str="astar(lmcut())", timeout: int=60) ->dict:""" Execute Fast Downward via l'API HTTP du conteneur Docker. Args: domain_pddl: Contenu du fichier domaine PDDL problem_pddl: Contenu du fichier probleme PDDL search_config: Configuration de recherche (defaut: A* avec LM-cut) timeout: Timeout en secondes Returns: dict avec 'success', 'plan', 'error', 'time' """ifnot DOCKER_OK ornot FD_DOCKER_OK:return {"success": False, "error": "Fast Downward Docker non disponible"}import time start_time = time.time() payload = json.dumps({"domain": domain_pddl,"problem": problem_pddl,"search": search_config, }).encode("utf-8") url =f"http://localhost:{FD_API_PORT}/plan" req = urllib.request.Request( url, data=payload, headers={"Content-Type": "application/json"}, method="POST" )try:with urllib.request.urlopen(req, timeout=timeout) as resp: elapsed = time.time() - start_time data = json.loads(resp.read().decode("utf-8"))if data.get("returncode") ==0:return {"success": True,"plan": data.get("stdout", ""),"error": None,"time": elapsed,"search": data.get("search", search_config), }else:return {"success": False,"plan": None,"error": data.get("stderr", "") or data.get("stdout", ""),"time": elapsed,"returncode": data.get("returncode"), }except urllib.error.URLError as e: elapsed = time.time() - start_timereturn {"success": False, "error": f"Connection erreur: {e}", "time": elapsed}exceptExceptionas e: elapsed = time.time() - start_timereturn {"success": False, "error": str(e), "time": elapsed}print("Fonction run_fast_downward_docker() prete (API HTTP)")
Fonction run_fast_downward_docker() prete (API HTTP)
5. Resume de l’environnement
Verifions que tous les composants sont correctement installes.
# Resume de l'environnementprint("="*60)print("RESUME DE L'ENVIRONNEMENT PLANIFICATION")print("="*60)print(f"Plateforme: {OS_NAME}")print(f"Python: {PYTHON_VERSION.major}.{PYTHON_VERSION.minor}.{PYTHON_VERSION.micro}")print("-"*60)print(f"unified-planning: {'OK'if UP_OK else'MANQUANT (REQUIS)'}")print(f"OR-Tools: {'OK'if ORTOOLS_OK else'MANQUANT (REQUIS)'}")print(f"Docker: {'OK'if DOCKER_OK else'Non disponible'}")print(f"Fast Downward: {'OK (Docker)'if FD_DOCKER_OK else'Non disponible'}")print("="*60)if UP_OK and ORTOOLS_OK:print("\nEnvironnement pret pour les notebooks de planification.")if FD_DOCKER_OK:print("Fast Downward disponible pour la planification optimale.")else:print("Note: Fast Downward non disponible via Docker.")print("Vous pourrez utiliser d'autres solveurs avec unified-planning.")else:print("\nATTENTION: Installez les dependances manquantes.")print("Commande: pip install unified-planning ortools")
============================================================
RESUME DE L'ENVIRONNEMENT PLANIFICATION
============================================================
Plateforme: Windows
Python: 3.13.7
------------------------------------------------------------
unified-planning: OK
OR-Tools: OK
Docker: OK
Fast Downward: Non disponible
============================================================
Environnement pret pour les notebooks de planification.
Note: Fast Downward non disponible via Docker.
Vous pourrez utiliser d'autres solveurs avec unified-planning.
6. Premier exemple concret : Blocks World
Maintenant que l’environnement est configure, appliquons nos connaissances a un problème classique de planification. Le Blocks World est le “Hello World” de la planification automatique.
Pourquoi Blocks World ?
Ce problème presente tous les concepts fondamentaux de la planification : - Etats discrets : configurations des blocs - Actions avec preconditions : ne peut pas prendre un bloc si la main est pleine - Buts a atteindre : configuration cible définie - Espace de recherche : plusieurs sequences possibles
Nous allons définir ce problème en PDDL, puis le resoudre avec unified-planning.
6. Premier exemple : Blocks World
Le Blocks World est le problème classique de planification. Il consiste a empiler des blocs pour atteindre une configuration cible.
Scénario
Etat initial : Les blocs A, B, C sont sur la table
Sortie obtenue : Le domaine est défini avec 4 actions et 5 predicats.
Élément
Type
Signification
block
Type
Objets manipulables (blocs)
on(?x ?y)
Predicat
Le bloc x est sur le bloc y
ontable(?x)
Predicat
Le bloc x est sur la table
clear(?x)
Predicat
Rien n’est sur le bloc x
handempty
Predicat
La main est vide
holding(?x)
Predicat
Le bloc x est dans la main
Actions disponibles : 1. pick-up(?x) : Prendre un bloc depuis la table (precondition: bloc libre, main vide) 2. put-down(?x) : Poser un bloc sur la table (precondition: bloc tenu) 3. stack(?x ?y) : Empiler x sur y (precondition: x tenu, y libre) 4. unstack(?x ?y) : Depiler x de y (precondition: x sur y, main vide, x libre)
Note technique : La syntaxe PDDL utilise des listes prefixees (opérateur arg1 arg2...). Les predicats definissent les etats atomiques possibles, et les actions specifient comment les changer via des preconditions et des effets.
6.2 Definition du problème PDDL
Le problème définit les objets spécifiques, l’etat initial et le but a atteindre.
# Definition du probleme PDDL# Etat initial: A, B, C sur la table# Objectif: A sur B, B sur C (tour de 3 blocs)PROBLEM_PDDL ="""(define (problem blocks-tower) (:domain blocks) (:objects a b c - block) (:init (ontable a) (ontable b) (ontable c) (clear a) (clear b) (clear c) (handempty) ) (:goal (and (on a b) (on b c))))"""print("Probleme PDDL defini: blocks-tower")print("Etat initial: A, B, C sur la table")print("Objectif: A sur B, B sur C")
Probleme PDDL defini: blocks-tower
Etat initial: A, B, C sur la table
Objectif: A sur B, B sur C
Interpretation : Definition du problème PDDL
Sortie obtenue : Le problème est instancie avec 3 blocs et un but a atteindre.
Élément
Valeur
Signification
Objets
a, b, c
Trois blocs manipulables
Etat initial
Tous sur table
Configuration de depart
But
A sur B, B sur C
Tour A-B-C a construire
Transformation requise : - Etat initial : 3 blocs separes sur la table - Etat final : Tour de 3 blocs (C a la base, B au milieu, A au sommet)
Complexite : - Nombre d’etats possibles : ~1024 (configurations avec 3 blocs) - Actions disponibles : 4 types, parametrables - Plan optimal : 4 actions
Note technique : Le problème PDDL reference le domaine blocks et instancie les predicats pour les objets spécifiques a, b, c. L’etat initial decrit la configuration de depart, et le but decrit la configuration cible.
6.3 Resolution avec unified-planning
Nous utilisons unified-planning pour modeliser et resoudre le problème de maniere programmatique en Python.
# Resolution avec unified-planningif UP_OK:from unified_planning.shortcuts import*# Creer le probleme en premier problem = Problem('blocks-tower')# Recuperer l'environnement du probleme env = problem.environment# Definir les types via l'environnement Block = env.type_manager.UserType('Block')# Definir les predicats en utilisant des arguments nommes (kwargs)# Cela cree automatiquement les Parameter avec le bon environnement on = Fluent('on', BoolType(), x=Block, y=Block, environment=env) ontable = Fluent('ontable', BoolType(), x=Block, environment=env) clear = Fluent('clear', BoolType(), x=Block, environment=env) handempty = Fluent('handempty', BoolType(), environment=env) holding = Fluent('holding', BoolType(), x=Block, environment=env)# Ajouter les objets a = Object('a', Block) b = Object('b', Block) c = Object('c', Block) problem.add_objects([a, b, c])# Definir l'etat initial problem.set_initial_value(ontable(a), True) problem.set_initial_value(ontable(b), True) problem.set_initial_value(ontable(c), True) problem.set_initial_value(clear(a), True) problem.set_initial_value(clear(b), True) problem.set_initial_value(clear(c), True) problem.set_initial_value(handempty, True)# Definir le but problem.add_goal(on(a, b)) problem.add_goal(on(b, c))# Definir les actions# IMPORTANT: InstantaneousAction prend des Types, pas des Variables# Utiliser action.parameter('name') pour recuperer la variable# pick-up: prendre un bloc de la table pick_up = InstantaneousAction('pick-up', x=Block) x = pick_up.parameter('x') pick_up.add_precondition(clear(x)) pick_up.add_precondition(ontable(x)) pick_up.add_precondition(handempty) pick_up.add_effect(ontable(x), False) pick_up.add_effect(clear(x), False) pick_up.add_effect(handempty, False) pick_up.add_effect(holding(x), True) problem.add_action(pick_up)# put-down: poser un bloc sur la table put_down = InstantaneousAction('put-down', x=Block) x = put_down.parameter('x') put_down.add_precondition(holding(x)) put_down.add_effect(holding(x), False) put_down.add_effect(clear(x), True) put_down.add_effect(handempty, True) put_down.add_effect(ontable(x), True) problem.add_action(put_down)# stack: empiler un bloc sur un autre stack = InstantaneousAction('stack', x=Block, y=Block) x = stack.parameter('x') y = stack.parameter('y') stack.add_precondition(holding(x)) stack.add_precondition(clear(y)) stack.add_effect(holding(x), False) stack.add_effect(clear(y), False) stack.add_effect(clear(x), True) stack.add_effect(handempty, True) stack.add_effect(on(x, y), True) problem.add_action(stack)print("Probleme cree avec unified-planning")print(f"Objets: {[o.name for o in problem.all_objects]}")print(f"Actions: {[a.name for a in problem.actions]}")print(f"Buts: {[str(g) for g in problem.goals]}")else:print("unified-planning non disponible")
Probleme cree avec unified-planning
Objets: ['a', 'b', 'c']
Actions: ['pick-up', 'put-down', 'stack']
Buts: ['on(a, b)', 'on(b, c)']
Interpretation : Modelisation avec unified-planning
Sortie obtenue : Le problème est correctement modelise en Python avec 3 objets, 3 actions et 2 buts.
Concept Python
Concept PDDL
Signification
UserType('Block')
Type block
Type d’objets
Fluent('on', ...)
Predicat on
Etat atomique
InstantaneousAction
Action :action
Opération elementaire
add_precondition()
:precondition
Condition d’exécution
add_effect()
:effect
Changement d’etat
Structure du problème : - Objets : a, b, c (instances du type Block) - Fluents : on, ontable, clear, handempty, holding (etats booléens) - Actions : pick-up, put-down, stack (unstack n’est pas inclus dans cette implementation) - Buts : on(a, b) ET on(b, c)
Points cles : 1. L’API Python permet de définir le problème sans ecrire de fichiers PDDL 2. Les actions sont définies avec des paramètres typés 3. Les preconditions et effets sont exprimés logiquement
Note technique : L’action unstack n’est pas necessaire pour ce problème spécifique car on part d’une configuration ou tous les blocs sont sur la table. Elle serait utile si on partait d’une configuration ou des blocs sont déjà empilés.
6.4 Resolution du problème
Utilisons un planificateur pour trouver une solution.
# Resolution avec un planificateur reel (pyperplan)if UP_OK:from unified_planning.engines import PlanGenerationResultStatus# Desactiver les messages de credits pour plus de clartefrom unified_planning.shortcuts import OneshotPlanner, get_environment get_environment().credits_stream =None# Afficher le probleme creeprint("Probleme de planification Blocks World cree avec succes")print(f" - Objets: {[o.name for o in problem.all_objects]}")print(f" - Actions: {[a.name for a in problem.actions]}")print(f" - Buts: {[str(g) for g in problem.goals]}")# Invocation REELLE du planificateur pyperplan# (pyperplan est installe et utilise dans toute la serie Planners-1..6)print("\n"+"="*60)print("PLANIFICATION AUTOMATIQUE")print("="*60)print("\nResolution du probleme avec le planificateur pyperplan...")try:with OneshotPlanner(name='pyperplan') as planner: result = planner.solve(problem)if result.status in (PlanGenerationResultStatus.SOLVED_SATISFICING, PlanGenerationResultStatus.SOLVED_OPTIMALLY): plan_actions =list(result.plan.actions)print(f"Statut : {result.status.name}")print(f"\nPlan trouve ({len(plan_actions)} actions) :")print("="*40)for i, action inenumerate(plan_actions, start=1):print(f" {i}. {action}")print("="*40)print(f"Longueur du plan : {len(plan_actions)} actions")else:print(f"Aucune solution trouvee (statut : {result.status.name})")exceptExceptionas e:print(f"Erreur lors de la resolution : {e}")print("Verifiez que pyperplan est installe : pip install pyperplan")else:print("unified-planning non disponible")
Probleme de planification Blocks World cree avec succes
- Objets: ['a', 'b', 'c']
- Actions: ['pick-up', 'put-down', 'stack']
- Buts: ['on(a, b)', 'on(b, c)']
============================================================
PLANIFICATION AUTOMATIQUE
============================================================
Resolution du probleme avec le planificateur pyperplan...
Statut : SOLVED_SATISFICING
Plan trouve (4 actions) :
========================================
1. pick-up(b)
2. stack(b, c)
3. pick-up(a)
4. stack(a, b)
========================================
Longueur du plan : 4 actions
Interpretation du résultat
Le planificateur trouve une sequence d’actions pour passer de l’etat initial a l’etat but :
Étape
Action
Effet
1
pick-up(b)
Main tient B
2
stack(b, c)
Empile B sur C
3
pick-up(a)
Main tient A
4
stack(a, b)
Empile A sur B
Résultat : Tour A-B-C avec C a la base et A au sommet.
Note : Les planificateurs PDDL optimisent généralement la longueur du plan (nombre d’actions). Le plan ci-dessus est optimal (4 actions). L’ordre des actions peut varier selon l’heuristique utilisee, mais la longueur minimale reste la même.
7. Structure de la serie
Cette serie comprend 15+ notebooks organises en 5 parties progressives :
Partie 0 : Environnement (00-Environment/)
#
Notebook
Contenu
Duree
0
Setup
Installation, Docker, premier exemple
20 min
Partie 1 : Fondations (01-Foundation/)
#
Notebook
Contenu
Duree
1
Introduction
Histoire, concepts, PDDL
30 min
2
PDDL-Basics
Syntaxe PDDL : domaines, problèmes, typage
45 min
3
State-Space
Espaces d’etats, graphes
30 min
Partie 2 : Planification Classique (02-Classical/)
#
Notebook
Contenu
Duree
4
Fast-Downward
A*, GBFS, LAMA
45 min
5
Heuristics
h-add, h-max, h-FF, LM-cut
45 min
6
Domains
Domaines IPC (Blocks, Logistics, Gripper)
45 min
Partie 3 : Planification Avancee (03-Advanced/)
#
Notebook
Contenu
Duree
7
OR-Tools
CP-SAT, contraintes, scheduling
45 min
8
Temporal
Durations, parallelisme
45 min
9
HTN
Planification hiérarchique, SHOP2
45 min
Partie 4 : Neuro-Symbolique (04-NeuroSymbolic/)
#
Notebook
Contenu
Duree
10
LLM-Planning
LLMs, prompting, plan repair
45 min
11
Unified-Planning
Interface multi-solveurs
45 min
12
LOOP
Learning to Plan
45 min
8. Points cles a retenir
Concepts fondamentaux
Concept
Definition
Etat
Configuration du monde a un instant donne
Action
Transition entre etats (preconditions + effets)
Plan
Sequence d’actions menant de l’etat initial au but
Heuristique
Estimation du cout pour atteindre le but
PDDL
Langage standard pour decrire problemes de planification
Technologies
Technologie
Usage
unified-planning
Modelisation Python, interface unifiee
Fast Downward
Planification optimale (A*, heuristiques)
OR-Tools
Optimisation CP-SAT, scheduling
Docker
Conteneurisation pour Fast Downward
Prochaines étapes
L’environnement est maintenant configure. Voici la suite de la serie :
Planners-1-Introduction : Histoire de la planification, concepts fondamentaux
Planners-2-PDDL-Basics : Syntaxe PDDL detaillee avec exemples
Planners-3-State-Space : Espaces d’etats et recherche
Ce notebook a configure l’environnement complet pour la serie de planification automatique.
Resume des acquis
Competence
Statut
Notebook correspondant
Installation des bibliotheques
OK
Ce notebook (0)
Comprehension de PDDL
Intro
Notebook 1-2
Modelisation Python
Intro
Notebook 2
Resolution de problemes
A venir
Notebook 4-6
Technologies maitrisees
Technologie
Version
Usage principal
unified-planning
1.3.0
Modelisation PDDL en Python
OR-Tools
Latest
Planification par contraintes
Docker
29.5.2
Conteneurisation Fast Downward
Python
3.13
Langage principal
Prochaines étapes
Planners-1-Introduction : Decouvrir l’histoire et les concepts de la planification
Planners-2-PDDL-Basics : Apprendre la syntaxe PDDL en detail
Planners-3-State-Space : Comprendre les espaces d’etats et la recherche
Point cle : La planification automatique est un domaine de l’IA qui consiste a trouver des sequences d’actions pour atteindre des buts. C’est la base de nombreux systèmes : robots, logistique, jeux video, etc.
Exercice : Verification de l’environnement de planification
Verifiez que votre environnement est correctement configure avant de passer aux notebooks suivants.
Étape 1 : Verifier les imports Importez les bibliotheques principales et affichez leurs versions.
Étape 2 : Créer un problème minimal Créez un problème de planification minimal avec unified_planning : 1 fluent, 1 action, 1 objectif.
Étape 3 : Resoudre le problème Utilisez OneshotPlanner avec pyperplan et affichez le plan obtenu.
# TODO etudiant : verification de l'environnement# Etape 1 : verifier les importsimport unified_planning as upprint(f"unified-planning version : {up.__version__}")# TODO etudiant : verifier aussi networkx et matplotlib# import networkx# import matplotlib# Etape 2 : creer un probleme minimal (decommenter et completer)# from unified_planning.shortcuts import *# problem = Problem("mon_premier_probleme")# TODO etudiant : ajouter un fluent, une action, un etat initial et un objectif# Etape 3 : resoudre (decommenter quand le probleme est defini)# with OneshotPlanner(name="pyperplan") as planner:# result = planner.solve(problem)# print(f"Statut : {result.status}")# print(f"Plan : {result.plan}")pass# Remplacer par votre implementation