pythonclipsclipspy

CLIPS/Clipspy codes run rule multiple times


I have written codes to create an expert system in risk analyses and create GUI. I use clipspy library in python. at the beginning, in a page I get my answers and then assert facts. in each page I saved facts in ".fct" file. In a different page, I load saved facts and use them in a rule. But most my facts use same template. Because of this, my each rule work multiple times using each templated facts.

You can find my codes below:

 from PyQt5.QtWidgets import *
 from Py_Risk_Belirleme_pg2 import Ui_Form
 from Risk_Belirleme_Page3 import third_page
 import clips

 class second_page(QWidget):
    def __init__(self):
    super().__init__()
    self.second_page_startup = Ui_Form()
    self.second_page_startup.setupUi(self)
    self.second_page_startup.Pb_Syf2_Devam.clicked.connect(self.create_clips_environment_2)

    def create_clips_environment_2(self):
    
        # Create a new CLIPS environment
        env = clips. Environment()
        probolity = """(deftemplate probolity
                    (slot name (type SYMBOL))
                    (slot number (type NUMBER)))"""
        env.build(probolity)
        olasilik = env.find_template("probolity")
    
        severity = """(deftemplate severity
                            (slot name (type SYMBOL))
                            (slot number (type NUMBER)))"""
        env.build(severity)
        siddet = env.find_template("severity")
    
        if ((question15_answer and question15_1_answer and question15_2_answer) == "Evet") and question15_3_answer =="Hayır":
            siddet.assert_fact(name = clips.Symbol('risk5.1'), number = 2)
            olasilik.assert_fact(name = clips.Symbol('olasılık5.1'), number = 1)
    
        elif (question15_answer and question15_1_answer and question15_2_answer and question15_3_answer) == "Evet" :
    
            siddet.assert_fact(name = clips.Symbol('risk5.1'), number = 2)
            olasilik.assert_fact(name = clips.Symbol('olasılık5.1'), number = 3)
    
        elif ((question15_answer and question15_1_answer) == "Evet") and ((question15_2_answer and question15_3_answer) =="Hayır") :
            siddet.assert_fact(name = clips.Symbol('risk5.1'), number = 2)
            olasilik.assert_fact(name = clips.Symbol('olasılık5.1'), number = 2)
    
        elif ((question15_answer and question15_1_answer and question15_3_answer) == "Evet") and (question15_2_answer =="Hayır") :
            siddet.assert_fact(name = clips.Symbol('risk5.1'), number = 2)
            olasilik.assert_fact(name = clips.Symbol('olasılık5.1'), number = 2)
        else:
            siddet.assert_fact(name = clips.Symbol('risk5.1'), number = 3.5)
            olasilik.assert_fact(name = clips.Symbol('olasılık5.1'), number = 3)
    
        env.save_facts('myfacts1.fct')

these are where I assertes facts and saves facts. Below are where I start analyses.

import clips
def risk_analizine_basla():


    env = clips.Environment()
    probolity = """(deftemplate probolity
                          (slot name (type SYMBOL))
                          (slot number (type NUMBER)))"""
    env.build(probolity)
    olasilik = env.find_template("probolity")
    
    severity = """(deftemplate severity
                                  (slot name (type SYMBOL))
                                  (slot number (type NUMBER)))"""
    env.build(severity)
    siddet = env.find_template("severity")
    
    env.load_facts('myfacts.fct')
    env.load_facts('myfacts1.fct')
    env.load_facts('myfacts3.fct')
    
    # Open the file in write mode
    file_path = "Risk_Analiz_Raporu.txt"
    env.eval(f'(open "{file_path}" "risk_output" "w")')
    
    # Burada factleri geri çağıracağız
    env.build("""
        (defrule hesaplamaSoru5
        (declare (salience 99))
        (severity (name ?name_risk) (number ?risk1))
        (probolity (name ?name_olasılık) (number ?olasılık1))
        (test (> (str-compare ?name_risk risk5.1) 0))
        (test (> (str-compare ?name_olasılık olasılık5.1) 0))
        (YolGenislıgı ?mevcut)
        =>
           (if (or (>= (* ?risk1 ?olasılık1) 9)(> ?olasılık1 3.5))
           then 
              (if (eq ?mevcut mevcut)
              then 
              (printout "risk_output" "   **** soru 5 deneme****************************************************    " crlf)
              (printout "risk_output" "**** Yayaların takılma sonucu tökezleme ve kayma kazaları için Risk Öncelik Skoru  : " (round (* ?risk1 ?olasılık1)) " 'dur." crlf) 
              (printout "risk_output" "**** Güvenli iş yeri ortamı sağlamak için aşağıda belirtilen tedbirleri alınız   : " crlf)
              (printout "risk_output" "**** Yürüyüş yollarına malzeme bırakılmamalı yada stoklanmamalıdır." crlf)
              (printout "risk_output" "**** Trafik yollarına dökülen döküntü veya ambalajlar hemen temizlenmelidir." crlf)
              (printout "risk_output" "**** Yürüş yolarında ki engeller görünücek şekilde işaretlenmeli, sınırlandırılmalıdır. Çalışanların takılmasını önlyecek şekilde zimin içine alınmalı veya üzerileri kaplanmalıdır. " crlf)
              (printout "risk_output" "**** Yürüyüş yolları belirlenerek sınırları çizilmeli, buralardan kablo kanalı veya boruların geçmemesini sağlanmalıdır." crlf )
              (printout "risk_output" "**** Yürüyüş yollarının aydınlatması ortalama 100 lux olmalıdır" crlf )
              (printout "risk_output" "**** 8 mm ve üzeri katman farklılığı çalışanların tökezlemesine neden olabileceği için bunun üzerindeki her yükseklik bertaraf edilmelidir. "crlf)
              (printout "risk_output" "   **** ****************************************************    " crlf)
        
              else
              (printout "risk_output" "   **** ************soru 5 deneme****************************************    " crlf)
              (printout "risk_output" "**** Yayaların takılma sonucu tökezleme ve kayma kazaları için Risk Öncelik Skoru  : " (round (* ?risk1 ?olasılık1)) " 'dur." crlf) 
              (printout "risk_output" "**** Güvenli iş yeri ortamı sağlamak için aşağıda belirtilen tedbirleri alınız   : " crlf) 
              (printout "risk_output" "**** Yürüyüş yollarına malzeme bırakılmamalı yada stoklanmamalıdır." crlf)
              (printout "risk_output" "**** Trafik yollarına dökülen döküntü veya ambalajlar hemen temizlenmelidir." crlf)
              (printout "risk_output" "**** Yürüş yolarında ki engeller görünücek şekilde işaretlenmeli, sınırlandırılmalıdır. Çalışanların takılmasını önlyecek şekilde zimin içine alınmalı veya üzerileri kaplanmalıdır. " crlf)
              (printout "risk_output" "**** Yürüyüş yolları belirlenerek sınırları çizilmeli, buralardan kablo kanalı veya boruların geçmemesini sağlanmalıdır." crlf )
              (printout "risk_output" "**** Yürüyüş yollarının aydınlatması ortalama 100 lux olmalıdır" crlf )
              (printout "risk_output" "**** 8 mm ve üzeri katman farklılığı çalışanların tökezlemesine neden olabileceği için bunun üzerindeki her yükseklik bertaraf edilmelidir. "crlf)
              (printout "risk_output" "**** Yolların Genişliği için aşağıda belirtilen önleyici tedbirleri alınız  :   "crlf)
              (printout "risk_output" "**** Yaya yolları üzerinde istifleme yapılmayan yerlerden geçmelidir. "crlf)
              (printout "risk_output" "**** Yayaların yapacakları işe, yük taşıma veya sipariş toplama gibi, uygun genişlikte olmalıdır. "crlf)
                (printout "risk_output" "   **** ****************************************************    " crlf))
           else 
           (printout "risk_output" "   **** **soru 5 deneme**************************************************    " crlf)
           (printout "risk_output" "**** Yayaların takılma sonucu tökezleme ve kayma kazaları için Risk Öncelik Skoru  : " (round (* ?risk1 ?olasılık1)) " 'dur." crlf)
           (printout "risk_output" "**** Güvenli iş yeri için gerekli şartlar sağlanmış gözüküyor. Mevcut Durumu Koruyunuz." crlf )
           (printout "risk_output" "**** Genede aşağıdaki tedbirleri almayı sürdürünüz. " crlf)
           (printout "risk_output" "**** Yürüyüş yollarına malzeme bırakılmamalı yada stoklanmamalıdır." crlf)
           (printout "risk_output" "**** Trafik yollarına dökülen döküntü veya ambalajlar hemen temizlenmelidir." crlf)
        (printout "risk_output" "   **** ****************************************************    " crlf))) 
        """)

env.eval(f'(close "{file_path}")')
env.run()
risk_analizine_basla()

this is only one example of my codes. When invoke defrule 'defrule hesaplamaSoru5' uses each tamplated facts. To fıgure out root cause of the problem, I have also code in CLIPS IDE. But as in python, it runs same rule for multiple times.

in my fact list, there are 24 facts and four "severity" and four "probolity " were asserted by using deftamplate. My defrule hesaplamaSoru5 should be invoked by f-13 (severity (name risk5.1) (number 2)) f-14 (probolity (name olasılık5.1) (number 3)). But it use all of the "severity" and "probolity " tamplated facts. So it work four times. What I want is my defrule hesaplamaSoru5 should be run and use only f-13 (severity (name risk5.1) (number 2)) f-14 (probolity (name olasılık5.1) (number 3)) facts.

below whole list of my facts:

    f-1     (yasli 'mevcutDegil')
    f-2     (gocmen 'mevcutDegil')
    f-3     (tehlikeliCalısan 'mevcut')
    f-4     (saglik 'mevcut')
    f-5     (kalabalık 'mevcut')
    f-6     (gurultu 'mevcutDegil')
    f-7     (yogun 'mevcut')
    f-8     (zemin 'kayganDegil')
    f-9     (merdiven 'Mevcut')
    f-10    (rampa 'mevcut')
    f-11    (YolGenislıgı 'Mevcut')
    f-12    (koridor 'gorunurDegil')
    **f-13    (severity (name risk5.1) (number 2))
    f-14    (probolity (name olasılık5.1) (number 3))
    f-15    (severity (name risk1) (number 3))
    f-16    (probolity (name olasılık1) (number 3.5))**
    f-17    (YuklemeNoktaları 'mevcut')
    f-18    (YuklemeGenislik 'belirsiz')
    **f-19    (severity (name risk6.1) (number 2))
    f-20    (probolity (name olasılık6.1) (number 1))**
    f-21    (YuklemeGenislik 'uygun')
    **f-22    (severity (name risk7.1) (number 3))
    f-23    (probolity (name olasılık7.1) (number 4))**
    f-24    (ParkGenislıgi 'mevcutDegil')
    For a total of 24 facts.

Solution

  • If you literally want your rule to apply to just those two facts, you'd rewrite your rule like this:

    (defrule hesaplamaSoru5
       (declare (salience 99))
       (severity (name risk5.1) (number ?risk1))
       (probolity (name olasılık5.1) (number ?olasılık1))
       (YolGenislıgı ?mevcut)
       =>
       ...)
    

    If you want to do a lexicographical comparison such that risk5.1 is selected over risk6.1 and risk6.1 is selected over risk7.1 (risk5.1 < risk6.1 < risk7.1), then write your rule like this:

    (defrule hesaplamaSoru5
       (declare (salience 99))
       (severity (name ?name_risk) (number ?risk1))
       (not (and (severity (name ?name_risk2))
                 (test (< (str-compare ?name_risk2 ?name_risk) 0))))
       (probolity (name ?name_olasılık) (number ?olasılık1))
       (not (and (probolity (name ?name_olasılık2))
                 (test (< (str-compare ?name_olasılık2 ?name_olasılık) 0))))
       (YolGenislıgı ?mevcut)
       =>
       ...)