• Aucun résultat trouvé

Algorithme d’exploration et de recherche d’optimum : vers un

3.2 Construction et exécution d’un plan opportuniste

3.2.2 Algorithme d’exploration et de recherche d’optimum : vers un

Dans le but d’effectuer un meilleur choix lors de l’exécution du plan généré par la transformation du graphe RFC par la grammaire de graphes, un algorithme d’exploration va explorer le graphe généré afin de proposer d’exécuter les branches les plus intéressantes suivant le cas.

3.2.2.1 Fonctionnement haut niveau

En s’inspirant d’un algorithme de recherche de plus court chemin [Dijkstra 1959], il va être possible d’explorer le graphe et de déterminer le meilleur chemin d’exécution à exécuter. Le principe est donc de démarrer d’un nœud de départ connu et d’atteindre le nœud de fin du plan en empruntant le plus court

che-min. La particularité présente ici est que certaines branches devront être traitées de

manière particulière : en effet, dans le cas où il y a un ou des opérateurs par dans le graphe, une recherche sera effectuée sur chaque branche sortante du nœud par. En effet, l’exécution de chaque branche sortante d’un nœud par étant obligatoire pour remplir le besoin initial, il est nécessaire de trouver un chemin optimisé pour chaque branche qui sera exécutée en parallèle des autres. Cela permettra également de calculer le coût total de l’exécution en parallèle des différentes branches. Cepen-dant, le principe de recherche demeure similaire étant donné que le point de départ des branches parallèles est indiqué par un nœud par connu et la jointure (nœud de fin de l’algorithme) de ces branches est indiquée par un nœud join. Dans le cas de branches parallèles imbriquées dans une branche parallèle le cas sera récursivement similaire.

L’algorithme ne comporte pas d’heuristique spécifique afin de guider les choix d’exploration. En effet, étant donné que les graphes à explorer auront une pro-fondeur et une largeur limitée de par la complexité de chaque graphe géré par le système, une recherche de chemin optimal est intéressante. Cela permet d’avoir la certitude que l’algorithme a trouvé le meilleur plan parmi les différentes possibilités sans avoir un impact fort en terme d’exécution de l’algorithme comme on pourra le constater dans le Chapitre 4.

3.2.2.2 Algorithme haut-niveau

Le graphe généré par la grammaire de graphe est noté G = (N, A) où : • l’ensemble N est l’ensemble fini des nœuds (sommets) de G

• l’ensemble A est l’ensemble des arcs de G tel que si (n1, n2) ∈ A, alors il existe un arc depuis le nœud n1 ∈ N vers le nœud n2 ∈ N dans G

• la fonction cout est définie sur N × N dans R et qui à un couple (n1, n2) associe un coût positif cout(n1, n2) de l’arc reliant n1 à n2 (et +∞ s’il n’y a pas d’arc reliant n1 à n2). Dans notre cas, si n1 représente un service, le coût de l’arc sera celui d’exécution du service en question.

Le coût d’un chemin entre deux nœuds (sommets) est la somme du coût des arcs qui le composent. Un cas particulier sera à traiter en présence de branches parallèles. Le but de l’algorithme est donc de trouver un chemin d’exécution de moindre coût depuis un sommet de départ (ndeb) et un sommet d’arrivée (nf in) appartenant à N et prédéterminés.

Pour ce faire l’algorithme fonctionne en construisant un sous-graphe P de ma-nière à ce que le coût total entre un sommet n de P depuis ndebsoit connu et minimal dans G. Le coût total connu, (cumulatif depuis le nœud de départ jusqu’à un nœud

n), est noté c(n). Au commencement, P ne contient que le nœud de départ ndeb et

le coût de ce nœud jusqu’à lui-même (qui est nul). A chaque étape d’exploration des arcs vont être ajoutés à P :

1. en identifiant les arcs ai= (ni1, ni2) dans P × G

2. en choisissant l’arc aj = (ni1, ni2) dans P ×G qui ait le coût minimum depuis

ndeb à nj2 en passant par tous les chemins créés menant à ce nœud, le coût est noté cout(ndeb, nf in).

L’algorithme prend fin quand P devient un arbre couvrant de G, ou que le plus court chemin jusqu’au nœud d’arrivée est trouvé.

L’algorithme haut-niveau peut donc s’écrire comme présenté ci-dessous dans l’Algorithme 1 :

Entrées : G = (N, A) un graphe avec pondération positive cout des arcs / nœuds,

ndeb et nf in des sommets de N considérés comme nœud de départ et nœud de fin du chemin à trouver, connus à l’avance.

La particularité de l’algorithme par rapport à un algorithme de recherche de chemin "classique" réside dans la présence potentielle de nœuds par qui vont impli-quer une recherche de chemin supplémentaire à effectuer sur chaque arc sortant du nœud parallèle jusqu’au nœud de jointure correspondant.

3.2.2.3 Implémentation et pseudo-code

L’implémentation et pseudo-code de l’algorithme utilisé dans le cas d’utilisation sont fournis en Annexe C. L’implémentation considère trois paramètres de qos dif-férents : le temps d’exécution qos0, le coût monétaire qos1 et le coût énergétique

qos2. Une structure particulière est définie pour stocker le coût cumulatif calculé depuis le nœud de départ ainsi qu’un tas trié afin de récupérer à chaque itération le nœud avec le coût cumulatif moindre.

Dans l’implémentation de l’algorithme, ce dernier produit également une liste de nœuds sélectionnés parmi les nœuds du graphe. Ce sont les nœuds qui devront être exécutés. Dans le cas où aucun chemin n’a pu être obtenu, cela indique qu’il n’est pas possible d’exécuter ce plan d’exécution.

3.2.2.4 Particularité avec nœuds parallèles et de calcul temporel L’algorithme présenté est un algorithme de recherche d’optimum. Cependant, dans le cas particulier où l’on cherche à optimiser le temps d’exécution du plan

3.2. Construction et exécution d’un plan opportuniste 81

Algorithm 1 Recherche d’optimum (meilleur plan d’exécution)

P := ∅

∀a ∈ N, c(a) := +∞

c(ndeb) := 0

while ∃a ∈ N / a 6∈ P avec le coût le plus bas depuis ndeb et que a 6= nf in do Choix de ce sommet a hors de P de plus petit coût cumulatif (distance) c(a) Mettre a dans P

if a n’est pas un opérateur par then

for Pour chaque sommet b hors de P voisin de a do

x := min(c(b), c(a) + cout(a, b))

if x < c(b) then

c(b) := x

Prédécesseur de b := a dans un meilleur chemin end if

end for else

Sauvegarde de c(a)

c(joina) := ∞

for Pour chaque sommet b hors de P voisin de a do

Nouvelle recherche avec : ndeb:= b et nf in := joina

Récupération du coût de b jusqu’à joina pour la branche explorée avec résultat de l’exploration : c(b, joina)

Mise à jour de c(joina) en fonction des paramètres considérés avec la valeur déjà connue de c(joina) (ou 0 si première exploration jusqu’au

join) et le résultat de l’exploration de la branche : c(joina) := c(joina) +

cout(b, joina) end for

c(joina) := c(joina) + c(a) end if

généré et que le graphe comporte des branches parallèles, le plan trouvé par l’al-gorithme sera un optimum local mais n’est pas garanti comme étant un optimum global. En effet, la particularité liée au calcul en coût temporel avec les branches parallèles implique que pour être certain de trouver l’optimum global il faut consi-dérer toutes les possibilités combinatoires, toutes branches confondues car le coût total d’exécution d’une branche parallèle se base sur le maximum des coûts tem-porels unitaires de chaque branche. Cependant, dès lors que d’autres paramètres sont considérés (coût monétaire et / ou énergétique par exemple), le résultat trouvé sera l’optimum global. En effet, étant donné que le coût sera incrémental et cumu-latif entre les branches, les minimums locaux trouvés par branches constitueront un minimum global une fois cumulés.