1. Summary
  2. Files
  3. Support
  4. Report Spam
  5. Create account
  6. Log in

Create Relations Between Facts

Task

I want to create an association between two or more facts.

The easiest way to associate two facts with each other is to use a symbolic link. This requires a unique identity slot (think of it as a Primary Key in a database table) that can be used as a reference to the fact and one, or more, slots (a Foreign Key in a database table) that contains the identity or identites of the associated facts.

Solution

Consider this template

CLIPS> (deftemplate employee
  (slot id (default-dynamic (gensym)))
  (multislot co-workers)
  (slot name)
  (slot company))

and this collection of facts using it

CLIPS> (deffacts start
  (employee (name "Michael Scott") (company "Dunder Mifflin Inc"))
  (employee (name "Jim Halpert") (company "Dunder Mifflin Inc"))
  (employee (name "Dwight Schrute") (company "Dunder Mifflin Inc"))
  (employee (name "Robert Vance") (company "Vance Refrigeration")))

To create a graph that represents the co-worker relationships between all employees we can use this rule that finds and links employees that work together (based on company name)

(defrule associate-co-workers
  ?e1 <- (employee (id ?id1) (company ?company) (co-workers $?co-workers1))
  ?e2 <- (employee (id ?id2&~?id1) (company ?company) (co-workers $?co-workers2))
  (test (and (not (member$ ?id2 $?co-workers1))
             (not (member$ ?id1 $?co-workers2))))
  =>
  (modify ?e1 (co-workers $?co-workers1 ?id2))
  (modify ?e2 (co-workers $?co-workers2 ?id1)))

Once the structure has been created, the symbolic links can be used to match facts that are related

CLIPS> (deffunction get-employee-fact-by-id (?id)
  (nth$ 1 (find-fact ((?fact employee))
                     (eq ?fact:id ?id))))
CLIPS> (defrule print-co-workers
  ?employee <- (employee (name ?name) (company ?company) (co-workers $?co-workers&:(> (length$ $?co-workers) 0)))
  =>
  (printout t ?name " works with ")
  (progn$ (?co-worker $?co-workers)
    (printout t (fact-slot-value (get-employee-fact-by-id ?co-worker) name) ", "))
  (printout t "at " ?company crlf))
CLIPS> (reset)
CLIPS> (run)
Dwight Schrute works with Jim Halpert, Michael Scott, at Dunder Mifflin Inc
Michael Scott works with Jim Halpert, Dwight Schrute, at Dunder Mifflin Inc
Jim Halpert works with Dwight Schrute, Michael Scott, at Dunder Mifflin Inc
CLIPS>