Search code examples
listmaxclips

How do I find the maximum element from a list in CLIPS?


I am trying to find out the maximum element from a list, e.g.

(deffacts list 
   (list 1 2 3 4 5 6 7 6 5 4 3 2 1))

in CLIPS. How can I do that, in a very simple way, in a defrule?

Also, if I have a template for a patient, with the following slots :

(deftemplate patient
   (slot name)
   (slot age)
   (multislot tens_max)
   (multislot tens_min))

(deffacts data_patient
    (patient (name John) (age 22) (tens_max 13 15 22 11) (tens_min 6 7 14 6))
)

and I want to find out the maximum element from the last multislot, tens_min, how can I do that?

I would appreciate any suggestion.


Solution

  • You can use the max function to find the maximum value of its arguments. You can bind the list of numbers to a multifield variable in the conditions of a rule. The max function however expects separate arguments so you can't just pass it a multifield value. You can use the expand$ function to split a multifield value into separate arguments for a function call. The max function expects at least 2 arguments in CLIPS 6.3 and at least 1 in CLIPS 6.4, so for completeness you would need to handle these cases. You can create a deffunction to handle these edge cases in your code.

             CLIPS (6.31 6/12/19)
    CLIPS> 
    (deffunction my-max ($?values)
       (switch (length$ ?values)
          (case 0 then (return))
          (case 1 then (return (nth$ 1 ?values)))
          (default (return (max (expand$ ?values))))))
    CLIPS> 
    (deffacts list 
       (list 1 2 3 4 5 6 7 6 5 4 3 2 1))
    CLIPS> 
    (defrule list-max
       (list $?values)
       =>
       (printout t "list max = " (my-max ?values) crlf))
    CLIPS> 
    (deftemplate patient
       (slot name)
       (slot age)
       (multislot tens_max)
       (multislot tens_min))
    CLIPS> 
    (deffacts data_patient
        (patient (name John) (age 22) (tens_max 13 15 22 11) (tens_min 6 7 14 6)))
    CLIPS> 
    (defrule patient-max
       (patient (tens_min $?values))
       =>
       (printout t "patient max = " (my-max ?values) crlf))
    CLIPS> (reset)
    CLIPS> (run)
    patient max = 14
    list max = 7
    CLIPS>