Vous êtes sur la page 1sur 7

IA 2

Travaux Pratiques 1
SATPLAN
Arnaud Lequen

1 Gripper
Dans cette partie, on s’intéresse au problème de planification classique suivant. Un robot peut se déplacer
d’une pièce à l’autre, et saisir des balles avec sa pince. Initialement, toutes les balles se trouvent dans la
même pièce. Le but est de lui faire déplacer une balle dans la seconde pièce.

Dans cette partie, on considère le cas où on a :


— Trois balles, appelées A, B et C
— Deux pièces, G et D
— Un seul robot, que l’on appelle robby.
On cherche à déplacer la balle B dans la pièce de droite D.

1.1 Représentation STRIPS du problème


On modéllise, dans un premier temps, le problème dans le langage STRIPS vu en cours. Ainsi, avant de
passer à l’implémentation avec TouIST, on décrit le problème au papier et au crayon. Il s’agit de donner :
— Un ensemble F de fluents permettant de décrire tous les états possibles du monde ;
— L’état initial I et le but B, qui sont des ensembles de fluents ;
— L’ensemble O des opérateurs utilisables.

1.1.1 Description du monde


On décrit F de la manière suivante :

F = {at_ball_X_R | X est une balle, R une pièce} ∪ (1)


{at_robby_R | R une pièce} ∪ (2)
{carry_X | X une balle} ∪ (3)
{hand_free} (4)
Où les fluents de (1) décrivent la salle dans laquelle les balles sont posées au sol, les fluents de (2) la
position de robby, les fluents de (3) les balles tenues par robby, et le fluent hand_free décrit le fait que
robby ne tient pas de balle.

1
Questions
1. A l’aide de la définition de F , décrivez formellement, au papier et au crayon, l’état initial I présenté
sur l’image plus haut.
2. Idem pour le but G.

1.1.2 Description des opérateurs


Comme précédemment, on donne une première description de O :

O = {move_R_S | R, S des pièces} ∪ (5)


{pick_X_R | X une balle, R une pièce} ∪ (6)
{drop_X_R | X une balle, R une pièce} (7)

Les opérateurs de (5) permettent à robby de se déplacer d’une pièce à l’autre, ceux de (6) de saisir une
balle si sa pince est vide, et ceux de (7) de poser une balle si possible.
Il s’agit ensuite de décrire chacun de ces opérateurs. Par exemple, pour un opérateur move_R_S de (5),
on aurait :
• Prec(move_R_S) = {at_robby_R}
• Add(move_R_S) = {at_robby_S}
• Del(move_R_S) = {at_robby_R}
Questions
1. Décrivez les opérateurs de la forme pick_X_R.
2. Idem pour les opérateurs de la forme drop_X_R.

1.2 Encodage avec TouIST


Dans cette section, on se propose d’utiliser TouIST (voir annexe) pour résoudre le problème de planifica-
tion présenté précédemment, à l’aide d’une compilation vers le problème SAT. Pour ce faire, il faut fournir
à TouIST :
— L’encodage du problème de planification
— Un ensemble de règles permettant de résoudre le problème

L’encodage du problème en lui-même requiert les composants suivants :


— L’ensemble de fluents F
— L’état initial I
— Le but G
— La description des opérateurs possibles
— Un horizon length
L’horizon est un entier décrivant la longueur maximale d’un plan que l’algorithme va rechercher.

Voici l’ensemble du code associé à un robot dans une seule pièce, avec une seule balle. Le but pour le
robot est simplement de saisir une balle. Cette base vous est fournie dans le fichier tp1_base.zip

2
;; Horizon
$length = 1

;; Fluents, etats initiaux et finaux


$F = [F_at_ball_ballA_roomG, F_at_robby_roomG, F_carry_ballA, F_hand_free]

$I = [F_hand_free, F_at_robby_roomG, F_at_ball_ballA_roomG]


$G = [F_carry_ballA]

;; Operateurs et definitions
$O = [A_pick_ballA_roomG, A_drop_ballA_roomG]

$Cond(A_pick_ballA_roomG) = [F_hand_free, F_at_ball_ballA_roomG,


F_at_robby_roomG]
$Add(A_pick_ballA_roomG) = [F_carry_ballA]
$Del(A_pick_ballA_roomG) = [F_hand_free, F_at_ball_ballA_roomG]

$Cond(A_drop_ballA_roomG) = [F_carry_ballA, F_at_robby_roomG]


$Add(A_drop_ballA_roomG) = [F_hand_free, F_at_ball_ballA_roomG]
$Del(A_drop_ballA_roomG) = [F_carry_ballA]

Questions

1. Ouvrez le fichier tp1_base.touistl. Complétez-le de sorte à ce qu’il contienne les cinq règles pré-
sentées dans la figure ci-dessous. Les trois premières et la dernière sont déjà encodées dans le fichier,
et vous sont décrites ci-dessous.
(a) (Expliquer la contrainte encodée par la première règle)
(b) Si une action a est appliquée à la i-ème étape du plan, alors ses préconditions sont satisfaites à
l’état précédent, et ses effets sont appliqués à l’état courant.
(c) Un fluent f ne peut être détruit (i.e. passer de vrai à faux) à la i-ème étape que si une action qui
le détruit a été exécutée.
(d) Un fluent f ne peut être établi (i.e. passer de faux à vrai) à la i-ème étape que si une action qui
l’établit a été exécutée.
(e) Deux actions effectuées à la même étape du plan ne sont pas en concurrence sur leur préconditions
et effets négatifs.
Indication : A une étape i, si une action a2 ̸= a1 détruit un fluent f trouvé dans les préconditions
de a1 , alors a1 et a2 ne peuvent pas s’exécuter à l’étape i simultanément.

2. Votre fichier contient, de même, le code ci-dessus. Pour rappel, il décrit une version simplifiée du
problème qui nous intéresse. A l’aide de TouIST, trouvez un plan au problème.
Astuce : Si vous utilisez la version de TouIST avec interface, le logiciel vous permet de filtrer les
variables par nom et par valeur dans le modèle. Sur l’écran de présentation des modèles, déco-
chez "False" et entrez "A_" dans la barre de recherche, afin de ne sélectionner que les variables
représentant des actions effectuées.

3. Encodez le problème de planification précédent avec TouIST. On se permettra d’oublier la balle C.


Remarque importante : la version GUI de TouIST n’est pas en mesure de supporter un problème
aussi complexe, et a de fort risque de planter lorsque la formule devient trop conséquente. Pour
cette question, et les suivantes, il vous faudra utiliser la version ligne de commande de TouIST.

3
4. Résolvez le problème de planification.

5. Changez le but afin que les deux balles soient dans la pièce de droite.

6. Demandez à TouIST de résoudre le problème, en changeant les entrées nécessaires.

2 Parking
On se propose maintenant d’étudier le problème suivant. Des voitures sont initialement garées en double-
file dans une certaine configuration. On cherche à leur donner une autre configuration, en les déplaçant une
à une, éventuellement à l’aide de la place de stationnement libre.

Chaque voiture peut être soit garée sur une place de stationnement, soit garée contre une autre voiture.
Il n’est pas possible de garer de voitures en triple-file. De même, une voiture ne peut être déplacée que si :
1. elle est garée en double-file, ou
2. elle est garée contre le trottoir, et aucune voiture n’est garée en double-file contre elle.
Avant de procéder à l’encodage du problème avec TouIST, on le décrit au travers du langage STRIPS,
au papier et au crayon. On propose l’ensemble de fluents suivants :
F = {at_curb_C | C est une voiture} ∪ (8)
{at_curb_num_C_P | C une voiture, P un emplacement} ∪ (9)
{behind_car_C_D | C, D des voitures} ∪ (10)
{car_clear_C | C une voiture} ∪ (11)
{curb_clear_P | P un emplacement} (12)

4
Où l’on a la sémantique suivante :
— at_curb_C : la voiture C est garée sur un emplacement
— at_curb_num_C_P : la voiture C est à l’emplacement P
— behind_car_C_D : la voiture C est contre le trottoir, et la voiture D est garé à côté
— car_clear_C : il n’y a pas de voiture à côté de la voiture C
— curb_clear_P : l’emplacement de parking P est libre

L’ensemble d’opérateurs est alors le suivant :

O = {move_car_to_car_C_D_E | C, D, E des voitures} ∪


{move_car_to_curb_C_D_P | C, D des voitures, P un emplacement} ∪
{move_curb_to_curb_C_P_Q | C une voiture, P, Q des emplacements} ∪
{move_curb_to_car_C_P_D | C, D des voitures, P un emplacement}

Où move_car_to_car déplace une voiture C garée contre une autre voiture D vers une autre voiture E,
move_car_to_curb déplace une voiture C garée contre une autre voiture D vers un emplacement libre contre
le trottoir P, etc.

Questions
1. Comme précédemment, formalisez deux opérateurs du problème, de votre choix, dans le langage
STRIPS.
2. Modélisez sous TouIST le problème présenté dans l’image ci-dessus.
— Indication : Créez un script Python permettant de calculer toutes les combinaisons possibles d’ob-
jets, et créant le code TouIST. Voir Annexe B.

5
Annexe A : Prise en main de TouIST
TouIST (Toulouse Integrated Satisfiability Tool) permet d’encoder des problèmes formulés en logique
propositionelle 1 , à l’aide d’un langage riche. Ce dernier permet, entre autres, de quantifier des connecteurs
logiques sur des ensembles finis. Par exemple, la formule propositionnelle suivante
^ _ ^ ^
(pi,j,n → ¬pi,j,m )
i∈[1..9] j∈[1..9] n∈[1..9] m∈[1..9]
m̸=n

peut être encodée par TouIST de la façon suivante :

bigand $i in [1..9]:
bigor $j in [1..9]:
bigand $n,$m in [1..9],[1..9] when $m != $n:
p($i,$j,$n) => not p($i,$j,$m)
end
end
end

Le logiciel peut être téléchargé au lien suivant :

https://github.com/touist/touist/releases

TouIST dispose d’une interface graphique en Java (qui intègre l’outil de ligne de commande). Elle peut
être téléchargée sur la page des versions et est disponible pour Linux, Windows et macOS. Deux options sont
disponibles : le plain jar pour toute plate-forme ou la version native non signée pour macOS et Windows 2 .
Sous macOS Sierra, la version native de TouIST.app affichera un message d’erreur. Vous devez exécuter
sudo spctl -master-disable qui activera l’application.
Sous Windows 10, le fichier natif TouIST.exe ne peut être ouvert que si la fonction SmartScreen de
Windows Defender est désactivée. Vous pouvez toujours utiliser la version jar.

Afin de tester si votre installation fonctionne, vous pouvez lancer TouIST et son interface Java, entrer la
ligne suivante, représentant la formule p ∨ q, et vérifier, en appuyant sur le bouton "Solve" en bas à droite,
que le logiciel parvient à trouver trois modèles différents.

p or q

Pour ce TP, nous travaillerons rapidement avec des formules beaucoup trop conséquentes pour être gérées
par l’interface TouIST. Ainsi, nous aurons recourt à TouIST en ligne de commande. Une fois installé, un
ficher de type .touistl peut être exécuté et résolu avec la commande suivante :

touist tp1.touistl --solve

Les fichiers .touistl peuvent être ouverts avec n’importe quel éditeur de texte. Il existe un plugin pour
VSCode permettant d’avoir la coloration syntaxique.

1. TouIST propose aussi d’encoder des problèmes de type QBF ou SMT


2. Attention ! Sous Windows et Mac, TouIST.jar ne fonctionne qu’avec Java <= 8

6
Annexe B : Automatisation de l’écriture des fluents et opérateurs
Le script Python suivant écrit, sur la sortie standard, le code TouIST associé à toutes les actions de la
forme move_R_S, telles que décrites dans la Section 1.1.2. Afin de rediriger l’entrée dans un fichier, vous
pouvez par exemple, sous Linux, utiliser la commande python generator.py > actions, pour rediriger la
sortie vers un fichier actions. Il ne reste plus ensuite qu’à effectuer un copier-coller des données du problème
dans TouIST.
A noter que la fonction product de la bibliothèque Itertools peut prendre n’importe quel nombre d’en-
sembles en arguments. Dans un même script Python, vous pouvez aussi automatiser l’écriture des ensembles
F et O.
Il reste toutefois nécessaire de spécifier les ensembles I et G manuellement.

import itertools as it

fluents = set()
operators = set()

rooms = ['roomG', 'roomD']

# Creation des fluents


for r in rooms:
fluents.add(f'F_at_robby_{r}')

print(f"$F = [{', '.join(fluents)}]")


print()

# Creation des operateurs


# move_R_S
for r, s in it.product(rooms, rooms):
if r == s:
continue
op_name = f"A_move_{r}_{s}"
operators.add(op_name)
print(f"$Cond({op_name}) = [F_at_robby_{r}]")
print(f"$Add({op_name}) = [F_at_robby_{s}]")
print(f"$Del({op_name}) = [F_at_robby_{r}]")
print()

print(f"$O = [{', '.join(operators)}]")

Vous aimerez peut-être aussi