home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / ckscripts / rule-engine < prev    next >
Lisp/Scheme  |  2020-01-01  |  8KB  |  376 lines

  1. # From: "Dat Nguyen" <thucdat@hotmail.com>
  2. # Subject: Module rule-engine
  3. # Date: Wed, 19 May 2004 01:16:37 -0400
  4. #
  5. # Animal Taxonomy is a favorite subject of specialized rule-based programming 
  6. # languages. With some creative construction, C-Kermit can solve that problem 
  7. # in the same manner. The cheetah.kr script exposes the same look and feel of 
  8. # many rule-based programs. Many configuration problems in computer 
  9. # administration and network should be solvable similarly, provided the rule 
  10. # set can be identified.
  11. #
  12. # This demonstration comes in two modules: rule-engine and cheetah.
  13. # To run the demonstration, tell Kermit to TAKE the cheetah module.
  14. #
  15. # Here is rule-engine:
  16.  
  17. define say {
  18.     echo \%1
  19.     return 1
  20. }
  21.  
  22. define askContent {
  23.     local \%v
  24.     ask \%v {[\%1]: }
  25.     _asg \%1 \%v
  26.     return \%1
  27. }
  28.  
  29. define askYesNo {
  30.     local ans
  31.     while true {
  32.         ask ans {\%1 (y|n): }
  33.         if \find(y,\m(ans)) return 1
  34.         if \find(n,\m(ans)) return 0
  35.     }
  36. }
  37.  
  38. define askANumber {
  39.     local \%n
  40.     while true {
  41.         echo Enter a Value
  42.         ask \%n {[\%1]: }
  43.         if numeric \%n return \%n
  44.     }
  45. }
  46.  
  47. define disableRule {
  48.     local \%i
  49.     for \%i 1 \v(argc)-1 1 {
  50.         asg RuleDatabase \m(RuleDatabase)\&_[\%i]|
  51.         incr RuleNumber
  52.     }
  53. }
  54.  
  55. define enableRule {
  56.     local \%i
  57.     for \%i 1 \v(argc)-1 1 {
  58.         asg RuleDatabase \freplace(\m(RuleDatabase),|\&_[\%i]|,|)
  59.         decr RuleNumber
  60.     }
  61. }
  62.  
  63. define availableRule {
  64.     if \find(\%1,\m(RuleDatabase)) return 0
  65.     disableRule {\%1}
  66.     return 1
  67. }
  68.  
  69. define eligibleRule {
  70.     (! \find(\%1,\m(RuleDatabase)))
  71. }
  72.  
  73. define clearRuleDatabase {
  74.     asg RuleDatabase |
  75.     (setq  RuleNumber 0)
  76. }
  77.  
  78. define addFact {
  79.     local \%i
  80.     for \%i 1 \v(argc)-1 1 {
  81.         if \find(\&_[\%i],\m(FactDatabase)) continue
  82.         asg FactDatabase \m(FactDatabase)\&_[\%i]|
  83.         incr FactNumber
  84.     }
  85.     # showFact
  86. }
  87.  
  88. define addATrueFact {
  89. # \%1 Name of the Boolean fact
  90. # \%2 Value of Boolean fact
  91. # Overwrite previous value
  92.     local \%s \%w \%f
  93.     asg \%s \fword(\%1,1)_\fword(\%1,2)
  94.     asg \%w \freplace(\%1,{\fword(\%1,1) \fword(\%1,2) })
  95.     _asg \%s |\%w|
  96.     addFact {\%s}
  97.     return 1
  98. }
  99.  
  100. define addAlsoTrueFact {
  101.     local \%s \%w \%f
  102.     asg \%s \fword(\%1,1)_\fword(\%1,2)_also
  103.     asg \%w \freplace(\%1,{\fword(\%1,1) \fword(\%1,2) })
  104.     _asg \%s \m(\%s)|\%w|
  105.     addFact {\%s}
  106.     return 1
  107. }
  108.  
  109. define addTrueFact {
  110. # add and initialize with True
  111.     _asg \%1 1
  112.     addFact {\%1}
  113. }
  114.  
  115. define addFalseFact {
  116.     _asg \%1 0
  117.     # add and initialize with False
  118.     addFact {\%1}
  119. }
  120.  
  121. define addValueFact {
  122.     if \find(\%1,\m(FactDatabase)) return \m(\%1)
  123.     _asg \%1 \fsexpr(askANumber '(\%1))
  124.     addFact {\%1}
  125.     return \m(\%1)
  126. }
  127.  
  128. define addcontentFact {
  129.     if \find(\%1,\m(FactDatabase)) return \m(\%1)
  130.     _asg \%1 \fsexpr(askContent '(\%1))
  131.     addFact {\%1}
  132.     return \m(\%1)
  133. }
  134.  
  135. define removeFact {
  136.     local \%i
  137.     for \%i 1 \v(argc)-1 1 {
  138.         asg FactDatabase \freplace(\m(FactDatabase),|\&_[\%i]|,|)
  139.         decr FactNumber
  140.     }
  141. #   showFact
  142. }
  143.  
  144. define isItTrueThat {
  145. # Use for fact that can have only one of two possible value.
  146. # a buble can be either ON of OFF
  147.     local \%s \%w \%f
  148.     asg \%s \fword(\%1,1)_\fword(\%1,2)
  149.     asg \%w \freplace(\%1,{\fword(\%1,1) \fword(\%1,2) })
  150.     asg \%f \find(\%s,\m(FactDatabase))
  151.     if \%f {
  152.         # term in factdatabase
  153.         if \find(|\%w|,\m(\%s)) return 1
  154.         return 0
  155.     } else {
  156.         # term not in factdatabase
  157.         local \%a
  158.         asg \%a \fsexpr(askYesNo '(\%1))
  159.         if \%a {
  160.             _asg \%s |\%w|
  161.             # save fact only when not in database before
  162.             if not \%f addFact {\%s}
  163.         }
  164.         return \%a
  165.     }
  166. }
  167.  
  168. define isTrueFact {
  169. # This responds with the content of the fact (True or False)
  170.     if \find(\%1,\m(FactDatabase)) return \m(\%1)
  171.     _asg \%1 \fsexpr(askYesNo '(\%1))
  172.     addFact {\%1}
  173.     return \m(\%1)
  174. }
  175.  
  176. define gotFact {
  177. # This gives user a chance to create a state fact with y(yes) or n(no)
  178.     if \find(\%1,\m(FactDatabase)) return 1
  179.     echo \%1
  180.     local \%a
  181.     asg \%a \fexec(askYesNo)
  182.     if \%a {    # yes, create fact
  183.         addFact {\%1}
  184.     }
  185.     return \%a
  186. }
  187.  
  188. define hasFact {
  189. # This does not expect user to respond
  190.     (\find(\%1,\m(FactDatabase)))
  191. }
  192.  
  193. define anyFact {
  194.     (FactNumber)
  195. }
  196.  
  197. define removeAllFact {
  198.     asg FactDatabase |
  199.     (setq FactNumber 0)
  200. }
  201.  
  202. define showFact {
  203.     show mac FactDatabase
  204.     show mac FactNumber
  205. }
  206.  
  207. define addGoal {
  208.     local \%i
  209.     for \%i 1 \v(argc)-1 1 {
  210.         asg GoalDatabase \m(GoalDatabase)\&_[\%i]|
  211.         incr GoalNumber
  212.     }
  213. #   showGoal
  214. }
  215.  
  216. define removeGoal {
  217.     local \%i
  218.     for \%i 1 \v(argc)-1 1 {
  219.         asg GoalDatabase \freplace(\m(GoalDatabase),|\&_[\%i]|,|)
  220.         decr GoalNumber
  221.     }
  222. #   showGoal
  223. }
  224.  
  225. define allGoalDone {
  226.     (! GoalNumber)
  227. }
  228.  
  229. define hasGoal {
  230.     (\find(\%1,\m(GoalDatabase)))
  231. }
  232.  
  233. define removeAllGoal {
  234.     asg GoalDatabase |
  235.     (setq GoalNumber 0)
  236. }
  237.  
  238. define showGoal {
  239.     show mac GoalDatabase
  240.     show mac GoalNumber
  241. }
  242.  
  243. define fireRule {
  244.     local \&e[] \%n \%i \%f
  245.     asg \%n \fsplit(\%1,&e,{ })
  246.     while true {
  247.         for \%i 1 \%n 1 {
  248.             if define \m(\&e[\%i]) {
  249.                 asg \%f \fexec(\&e[\%i])
  250.                 # if rule was fired, reevaluate all rules 
  251.                 if > \%f 0 {
  252.                     asg firedRules \m(firedRules)|\&e[\%i]
  253.                     echo \&e[\%i] was fired
  254.                     if = 2 \%f END
  255.                     break
  256.                 }
  257.             }
  258.         }
  259.         if not \%f break            # no rule was fired
  260.         if = 1 \fexec(allGoalDone) break    # all goals achieved
  261.     }
  262.     echo
  263.     echo {That's all there is}
  264.     echo
  265. }
  266.  
  267. define rule_sample {
  268.     (if (hasGoal 'Goal_xxx)
  269.       (if (hasFact 'Fact_yyy)
  270.         (if (not (hasGoal 'Goal_zzz))
  271.           (.
  272.            (removeGoal 'Goal_xxx)    # Goal achieved
  273.            (removeFact 'Fact_yyy)       # Fact changed
  274.            (addGoal 'Fact_www)          # New goal
  275.            (addFact 'Fact_yyy)          # New fact
  276.            (1)
  277.            )
  278.          (0)
  279.          )
  280.        (0)
  281.        )
  282.      (0)
  283.      )
  284. }
  285. define mutual_exclude {
  286.     local \%i \%s
  287.     asg \%s +
  288.     for \%i 1 \v(argc)-1 1 {
  289.         asg \%s \%s\&_[\%i]+
  290.     }
  291.     _asg \v(macro)_term \m(\v(macro)_term)|\%s
  292. }
  293.  
  294. define addThisFact {
  295.     asg allTheFacts \m(allTheFacts)|\%1
  296.     registerThisFact {\%1} 1 0
  297. }
  298.  
  299. define excludeThisFact {
  300.     asg allTheFacts \freplace(\m(allTheFacts),|\%1|,|)
  301.     registerThisFact {\%1} 0 1
  302. }
  303.  
  304. define showAllFacts {
  305.     local \%i \&w[]
  306.     for \%i 1 \fsplit(\m(allTheFacts),&w,|) 1 {
  307.         echo \&w[\%i]
  308.     }
  309. }
  310.  
  311. define clearAllFacts {
  312.     asg allTheFacts 
  313. }
  314.  
  315. define registerThisFact {
  316.     local \%i \%k \%n \&w[] \%f
  317.     asg \%n \fsplit(\m(mutual_exclude_term),&w,|)
  318.     if \%n {
  319.         local \%m \&e[]
  320.         # There is mutual exclusive fact
  321.         asg \%f \farraylook(^+\%1+*,&w)
  322.         if > \%f 0 {
  323.             asg \%m \fsplit(\&w[\%f],&e,{+})
  324.             # This is a mutual exclusive fact
  325.             if \%2 {
  326.                 # This is a true fact, turn off all others
  327.                 for \%i 1 \%m 1 {
  328.                     _asg \&e[\%i] \%3
  329.                 }                
  330.             } else {
  331.                 # This is a false fact, turn off only for boolean fact
  332.                 if = 2 \%m {
  333.                     # This is a boolean fact
  334.                     for \%i 1 \%m 1 {
  335.                         _asg \&e[\%i] \%3
  336.                     }                
  337.                 }
  338.             }
  339.         }
  340.     }
  341.     _asg \%1 \%2
  342. }
  343.  
  344. define consultUser {
  345.     asg consult_user 1
  346. }
  347.  
  348. define donotConsultUser {
  349.     asg consult_user 0
  350. }
  351. donotConsultUser
  352.  
  353. define isThisFactTrue {
  354.     if define \m(\%1) return \m(\%1)
  355.     local \%a
  356.     if == \m(consult_user) 1 {
  357.         asg \%a \fsexpr(askYesNo '(\%1))
  358.     } else {
  359.         asg \%a 0
  360.     }
  361.     if \find(+\%1+,\m(mutual_exclude_term)) {
  362.         # term with mutual exclusion
  363.         if = 1 \%a {
  364.             addThisFact {\%1}
  365.         } else {
  366.             excludeThisFact {\%1}
  367.         }
  368.     } else {
  369.         # term withOUT mutual exclusion
  370.         _asg \%1 \%a
  371.     }
  372.     return \%a
  373. }
  374.  
  375. # \farraylook(oofa*,&a)
  376.