问题
I am new to CLIPS and I am having difficulties understanding the language. I am aware of the rather confusing title so I will try to be as clear and precise as I can.
I have a base of facts represented by student entries and I want to find out which city is the most common (appears most frequent) among the enlisted students.
This is my base of facts:
(deftemplate student
(slot name)
(slot city)
(slot age)
(multislot subjects)
(multislot grades)
)
(deffacts students
(student (name John) (city Florida) (age 20) (subjects RRE SSE DDE SRE) (grades D B F F)
(student (name Jesse) (city Miami) (age 21) (subjects RRE SSE DDE SRE) (grades C C D D)
(student (name Sasha) (city Florida) (age 20) (subjects RRE SSE DDE SRE) (grades B A B B)
(student (name Mark) (city Florida) (age 20) (subjects RRE SSE DDE SRE) (grades C C F F)
)
I have been searching for the answer for a couple of days, but CLIPS is not a very popular programming language, so I cannot find questions or answers regarding this matter and the documentation I find is often vague.
I appreciate any answer I get. Cheers!
回答1:
Some languages provide aggregation operators that allow you to collect all facts matching a pattern. That functionality makes it easier to solve this type of problem. CLIPS does not support this functionality, so you must use alternate approaches. Here are two:
CLIPS>
(deftemplate student
(slot name)
(slot city)
(slot age)
(multislot subjects)
(multislot grades))
CLIPS>
(deffacts students
(student (name John) (city Florida) (age 20) (subjects RRE SSE DDE SRE) (grades D B F F))
(student (name Jesse) (city Miami) (age 21) (subjects RRE SSE DDE SRE) (grades C C D D))
(student (name Sasha) (city Florida) (age 20) (subjects RRE SSE DDE SRE) (grades B A B B))
(student (name Mark) (city Florida) (age 20) (subjects RRE SSE DDE SRE) (grades C C F F)))
CLIPS>
(deffunction find_cities_with_most_students_1 ()
(bind ?cities (create$))
(bind ?counted_cities (create$))
(bind ?largest_count 0)
(do-for-all-facts ((?s student)) TRUE
(if (not (member$ ?s:city ?counted_cities))
then
(bind ?counted_cities (create$ ?s:city ?counted_cities))
(bind ?count (length$ (find-all-facts ((?s2 student)) (eq ?s2:city ?s:city))))
(if (= ?count ?largest_count)
then
(bind ?cities (create$ ?s:city ?cities))
else
(if (> ?count ?largest_count)
then
(bind ?largest_count ?count)
(bind ?cities (create$ ?s:city))))))
(return ?cities))
CLIPS>
(defrule largest_count_1
(declare (salience -10))
=>
(bind ?cities (find_cities_with_most_students_1))
(foreach ?c ?cities
(printout t "1 " ?c " has the most students" crlf)))
CLIPS>
(deftemplate city_count
(slot city)
(multislot facts))
CLIPS>
(defrule count_cities_2
(student (city ?city))
(not (city_count (city ?city)))
=>
(assert (city_count (city ?city)
(facts (find-all-facts ((?s student))
(eq ?s:city ?city))))))
CLIPS>
(defrule largest_count_2
(declare (salience -10))
(city_count (city ?city) (facts $?facts))
(not (city_count (city ~?city) (facts $?facts2&:(> (length$ ?facts2) (length$ ?facts)))))
=>
(printout t "2 " ?city " has the most students" crlf))
CLIPS> (watch rules)
CLIPS> (watch facts)
CLIPS> (reset)
<== f-0 (initial-fact)
==> f-0 (initial-fact)
==> f-1 (student (name John) (city Florida) (age 20) (subjects RRE SSE DDE SRE) (grades D B F F))
==> f-2 (student (name Jesse) (city Miami) (age 21) (subjects RRE SSE DDE SRE) (grades C C D D))
==> f-3 (student (name Sasha) (city Florida) (age 20) (subjects RRE SSE DDE SRE) (grades B A B B))
==> f-4 (student (name Mark) (city Florida) (age 20) (subjects RRE SSE DDE SRE) (grades C C F F))
CLIPS> (run)
FIRE 1 count_cities_2: f-4,*
==> f-5 (city_count (city Florida) (facts <Fact-1> <Fact-3> <Fact-4>))
FIRE 2 count_cities_2: f-2,*
==> f-6 (city_count (city Miami) (facts <Fact-2>))
FIRE 3 largest_count_2: f-5,*
2 Florida has the most students
FIRE 4 largest_count_1: *
1 Florida has the most students
CLIPS> (unwatch all)
CLIPS> (reset)
CLIPS> (run)
2 Florida has the most students
1 Florida has the most students
CLIPS>
来源:https://stackoverflow.com/questions/36679051/clips-finding-the-most-common-of-facts-based-on-the-number-of-occurences