Accueil > Divers > Drools : Manipulation de l’ordre de déclenchement des règles

Drools : Manipulation de l’ordre de déclenchement des règles

Dans l’article précédent (http://blog.viseo-bt.com/drools-mise-a-jour-de-faits-et-boucles-infinies/), nous avions découvert l’utilisation des attributs dans une règle pour éviter les boucles infinies et la mise à jour de faits dans la mémoire de travail.

Nous avions à la fin 3 règles : 2 règles pour augmenter le nombre de pros et de cons et une règle pour déterminer si un client était solvable ou non.

Cette dernière règle doit forcément être déclenchée en dernier, pour que le raisonnement soit correct. Et nous voyons dans notre résultat affiché dans la console que c’était bien le cas.

Nous pouvons supposer que c’est parce que c’était la dernière règle écrite dans notre fichier de règles. Mais si nous modifions l’ordre des règles, si nous passions notre règle « a droit à un prêt » au tout début, qu’est-ce qui se passe ?

Chez moi, voici ce qui s’affiche :

 

Règle « a un CDI » déclenchée !

Le dossier 1 est solvable

Règle « a un bon salaire » déclenchée !

Le dossier 1 est solvable

Dossier n°1:

      -Pros = 3

      -Cons = 0

Dossier n°1:

Solvabilité du client = true

 

La règle « a droit à un prêt » se déclenche une fois après la règle « a un CDI » et une fois après « a un bon salaire ». Autrement dit, l’ordre d’écriture des règles dans le fichier n’est pas respecté.

Conclusion : Drools n’attribue pas d’ordre précis lors du chargement des règles dans la mémoire de travail.

Alors comment dire à Drools que certaines règles doivent être déclenchées avant d’autres ?

Je vous présente ici 3 manières pour le faire.

1-     Utilisation de la priorité

Drools permet d’affecter une priorité à chacune des règles grâce à l’attribut salience. Ce sont les règles qui ont la plus haute priorité qui seront déclenchées en premier.

Ici, nous voulons d’abord déclencher nos règles qui définissent le nombre de pros et de cons, donc les règles « a un CDI » et « a un bon salaire ». Nous leur donnerons une priorité 150.

Exemple pour la règle « a un CDI »:

rule "a un CDI"
lock-on-active true
salience 150 
    when
        personne: Personne( $numDossierPersonne:numDossier  )
        c: Caracteristique( numDossier == $numDossierPersonne, nom == 'CDI' , valeur ==1  )
    then
        personne.setPros(personne.getPros()+1);
        System.out.println("Règle \"a un CDI\" déclenchée !");
   	  update(personne);
end

En affectant une priorité inférieure à la règle « a droit à un prêt » (exemple salience 100), nous sommes sûrs qu’elle sera déclenchée en dernier, quel que soit son emplacement dans le fichier de règles.

2-     Utilisation de l’agenda-group

Drools permet de définir des groupes de règles, à déclencher l’un après l’autre, via un attribut agenda-group. Dans le vocabulaire Drools, l’agenda est l’ensemble des règles qui peuvent être déclenchées à partir d’un ensemble de faits, une fois qu’elles ont été évaluées. A chaque changement de fait, l’agenda est mis à jour.

Nos 2 règles « a un CDI » et « a un bon salaire » feront partir du groupe « regles_base » et notre règle « a droit à un prêt » appartiendra au groupe « regles_finales ».

Pour la règle « a droit à un prêt », nous avons donc:

rule "a droit à un prêt"
agenda-group "regles_finales"
    when
        personne: Personne( $numDossierPersonne:numDossier, pros > cons  )
    then
        personne.setSolvable(true);
        System.out.println("Le dossier "+ $numDossierPersonne+" est solvable");
End

L’avantage de l’utilisation de salience est qu’on ne modifie pas la manière dont on déclenche les règles, un simple fireAllRules() suffit.

Ici, c’est un tout peu plus compliqué : il faut appeler les groupes dans l’ordre que l’on souhaite. On aura alors dans notre main, à la place d’un fireAllRules() :

    kSession.getAgenda().getAgendaGroup("regles_base").setFocus();
	kSession.fireAllRules();
		
	kSession.getAgenda().getAgendaGroup("regles_finales").setFocus();
	kSession.fireAllRules();

Et voilà, nous avons deux groupes de règles bien définis, évalués quand il le faut. Si il y a énormément de règles, les diviser en groupe accélèrera ainsi le raisonnement.

Et une petite astuce pour la fin de ce paragraphe : comme un groupe de règles doit forcément être évalué lors d’un raisonnement, on peut utiliser l’attribut auto-focus sur une règle pour mettre le focus directement sur le groupe auquel appartient la règle.

Exemple pour la règle « a un CDI »:

rule "a un CDI"
lock-on-active true
auto-focus 
 agenda-group "regles_base"
    when
     …

Dans la méthode main, on aura donc simplement :

 

kSession.getAgenda().getAgendaGroup("regles_finales").setFocus();
kSession.fireAllRules();

3-     Utilisation d’un filtre sur les règles

Dans un contexte plus particulier, nous pouvons faire un filtre sur les règles à déclencher, à l’aide d’un AgendaFilter.

Par exemple, si nous voulons évaluer toutes les règles sauf celles qui commencent par « a droit », nous procédons avec le code suivant :

// Utilisation d'un AgendaFilter
		AgendaFilter filter = new AgendaFilter() {

			@Override
			public boolean accept(Match m) {
				if(!m.getRule().getName().startsWith("a droit"))
					return true;
				else 
					return false;
			}
		};
		
		kSession.fireAllRules(filter);

Ici, seules les règles « a un CDI » et « a un bon salaire » seront donc évaluées.

Nous pouvons nous servir de cette méthode si on ne veut faire aucune modification sur le fichier de règles.

 

En résumé, Drools prévoit plusieurs manières de gérer les règles et c’est bien cette souplesse que j’ai apprécié en l’utilisant.

 

Conclusion

Par cette série de 3 articles, j’ai partagé avec vous quelques astuces, de base mais indispensables, pour mieux comprendre Drools et exploiter sa puissance.

N’hésitez pas à refaire un tour dans les articles précédents si besoin :

Article n°1 : Démarrer avec Drools (http://blog.viseo-bt.com/demarrer-avec-drools-et-autres-astuces/)

Article n°2 : Mise à jour de faits et boucles infinies (http://blog.viseo-bt.com/drools-mise-a-jour-de-faits-et-boucles-infinies/)

Categories: Divers Tags:
  1. Benjamin
    31/08/2016 à 23:08 | #1

    Merci pour ces articles simples, clairs et précis

  1. Pas encore de trackbacks


sept × 6 =