Moteur D'Inférence

Pendant mes études, j’ai du codé un moteur d’inférence en java… j’en ai fait une version Python beaucoup plus épuré que ce que j’avais pu faire à l’époque. C’est un chaînage avant. Avec cet outil, on peut construire un système expert capable de déduction depuis une base de fait en se basant sur des règles définis par l’utilisateur.

#!/usr/bin/env python3
# coding: utf8

import logging

# construction du logger
LOGGER = logging.getLogger()
#LOGGER.setLevel(logging.WARNING)
LOGGER.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s :: %(module)s :: %(levelname)s :: %(message)s')

stream_handler = logging.StreamHandler()
stream_handler.setFormatter(formatter)
LOGGER.addHandler(stream_handler)


class regle () :
  """
    Les règles sont constitué d'un ensemble de faits appelé prémisse dont la conséquence est appelé la conclusion.
  """
  def __init__ (self,Premisse,Conclusion):
    self.Premisse=Premisse
    self.Conclusion=Conclusion

  def aff (self) :
    return str(self.Premisse) + ' donne ' + self.Conclusion

  def __str__(self):
    return str(self.Premisse) + ' donne ' + self.Conclusion


class Brain () :
  """
  Le moteur d'inférence.
  """

  def __init__ (self):
    self.BaseDeFait=[]
    self.BaseDeRegle=[]

  def present(self, Premisse):
    """
    Dit si une prémisse est présente dans l'ensemble.
    """
    # utilise les fonctions ensembliste pour faire le test
    # A dans B
    S1 = set(self.BaseDeFait)
    S2 = set(Premisse)
    if S1.intersection(S2) == S2 :
        return True
    else :
        return False

  def AjoutDeFait (self,Fait):
    """
    Ajout un fait à la base de fait.
    """
    self.BaseDeFait.append(Fait)

  def AjoutDeRegle (self,Regle):
    """
    Ajout une règle à la base de règle
    """
    self.BaseDeRegle.append(Regle)

  def Analyse (self) :
    """
    Analyse la base de fait et déduit de nouveau fait en fonction de la base de règle.
    """
    ConclusionAjouter = 1
    LOGGER.debug("Début de la boucle d'analyse.")
    while (len(self.BaseDeRegle) > 0 and ConclusionAjouter > 0 ):
        LOGGER.debug("La base de règle contient %d règles.", len(self.BaseDeRegle))
        RegleMarquee = []
        ConclusionAjouter = 0

        LOGGER.debug("Recherche des règles valide.")
        for Regle in self.BaseDeRegle :
            if (self.present(Regle.Premisse)):
                self.AjoutDeFait(Regle.Conclusion)
                RegleMarquee.append(Regle)
                ConclusionAjouter += 1
                LOGGER.debug("Règle valide : %s.",Regle)

        if ConclusionAjouter > 0:
            LOGGER.debug("Suppression des règles utilisées de la base de règle.")
            for Regle in RegleMarquee :
                self.BaseDeRegle.remove(Regle)
                LOGGER.debug("Règle supprimée : %s.",Regle)

        if ConclusionAjouter == 0:
            LOGGER.debug("Aucune règle n'a été ajouté. L'analyse des règles est terminées.")
        else:
            LOGGER.debug("%d nouveaux fait ont été ajouté à la base de fait. L'analyse doit reprendre.", ConclusionAjouter)
    LOGGER.debug("Fin de la boucle d'analyse.")

  def aff(self) :
    return (self.BaseDeFait)

if __name__ == '__main__' :
    db=Brain()

    db.AjoutDeFait('a')
    db.AjoutDeFait('c')
    db.AjoutDeFait('f')

    db.AjoutDeRegle(regle([],'Z')) # une regle sans premisse est toujours vrai
    db.AjoutDeRegle(regle(['a','c'],'e'))
    db.AjoutDeRegle(regle(['e','g','f'],'h'))
    db.AjoutDeRegle(regle(['c','f'],'d'))
    db.AjoutDeRegle(regle(['d','e'],'g'))
    db.AjoutDeRegle(regle(['j','k'],'m')) # regle non réalisable dans le cas présent
    db.AjoutDeRegle(regle(['a','h','e'],'l'))

    print("Base de fait", db.aff())
    db.Analyse()
    print("Base de fait après Analyse : ", db.aff())

Ce moteur pourrait être intégré à une carte électronique (NodeMCU) prenant en charge le python (micropython) afin d’utiliser les capteurs relié à la dite carte comme base de fait.

Si fumé + élévation de la température (calcul de la dérivé seconde [accélération] de la température) alors il y a probablement un incendie.