Menu

How to implement collections (e.g. list) in CLIPS and how to interrogate such a collection

Help
2021-03-03
2021-03-03
  • Neil Osborne

    Neil Osborne - 2021-03-03

    I am using fuzzyCLIPS 6.31 and I want to have a fact that is a collection (of other facts). Currently, I have something like this:

    (deftemplate person "attributes of a person"
       (multislot name (type STRING) )
       (slot age (type FLOAT) (range 0.0 129.9) (default 0) )
       (slot gender (type SYMBOL) (allowed-symbols male female) )
       ; .. other attributes
    )
    
    (def template people "collection of people"
        ; terminating char separated string of string representation of person
        ; e.g. "John Frederick Handel, 42.5, male, ....;Homer Jay Simpson, 45.2, male, ..."
        (slot members (type STRING) )
    )
    
    (defrule make-person-and-add-to-group
        ; make a person fact
        ; amend previously asserted people fact by adding "stringified" person to people fact
    )
    
    (defrule predict-a-riot 
        ; IF we have (fuzzy) "too" many males in a group AND
        ; the males are above the age of 'X' AND
        ; some other salient facts
        ; => THEN
        ; assert riot prediction with CF
    )
    

    This could be an example of a simplistic expert system that attempt to predict the likelihood of a riot breaking out, based on some simplistic input variables and heuristics.

    I have the following questions:

    1. Is "stringifying" facts (concatenating and then parsing/groking the resulting string) a good/acceptable way of dealing with lists (or collections) of facts ?
    2. How does one access and manipulate the string held in a slot of a fact?
     
  • Gary Riley

    Gary Riley - 2021-03-03

    Create a unique id for each person fact and store that in your collection rather than the content of the fact.

             CLIPS (6.31 6/12/19)
    CLIPS> 
    (deftemplate person
       (slot id (type SYMBOL))
       (slot name (type STRING))
       (slot age (type INTEGER) (range 0 130) (default 0))
       (slot gender (type SYMBOL) (allowed-symbols male female)))
    CLIPS> 
    (deftemplate people 
       (multislot members (type SYMBOL)))
    CLIPS>    
    (deffacts initial
       (people)
       (add-person))
    CLIPS> 
    (deffunction add-person ()
       (printout t "Name: ")
       (bind ?name (readline))
       (printout t "Age: ")
       (bind ?age (read))
       (printout t "Gender: ")
       (bind ?gender (read))
       (bind ?id (gensym*))
       (assert (person (id ?id)
                       (name ?name)
                       (age ?age)
                       (gender ?gender)))
       (return ?id))
    CLIPS>                    
    (defrule make-person-and-add-to-group
       ?p <- (people (members $?people))
       ?a <- (add-person)
       =>
       (retract ?a)
       (printout t "Add Person? ")
       (bind ?response (lowcase (read)))
       (if (or (eq ?response y) (eq ?response yes))
          then
          (bind ?id (add-person))
          (modify ?p (members ?id ?people))
          (assert (add-person))))
    CLIPS> (reset)
    CLIPS> (run)
    Add Person? yes
    Name: Fred Smith
    Age: 38
    Gender: male
    Add Person? yes
    Name: Sally Jones
    Age: 23
    Gender: female
    Add Person? no
    CLIPS> (facts)
    f-0     (initial-fact)
    f-3     (person (id gen1) (name "Fred Smith") (age 38) (gender male))
    f-6     (person (id gen2) (name "Sally Jones") (age 23) (gender female))
    f-7     (people (members gen2 gen1))
    For a total of 4 facts.
    CLIPS> 
    

    The general pattern then for doing something to each member of the collection is:

    (defrule for-each-person
       (people (members $? ?id $?))
       (person (id ?id)
               (name ?name)
               (age ?age)
               (gender ?gender))
       =>
       ;; Action
       )
    
     

Log in to post a comment.