I am new to clips and I have not idea how to iterate through lists correctly and to add them together and put the sum on the same position. I have two lists defined as facts and I want to create a list that will have the sums of the lists of the elements on the same position. Ex: (deffacts lists (list 1 2 3 4) (list 1 2 3 4) ) And the result should be : (listSum 2 4 6 8)
Any help or advice is welcomed. Thank you!
Here's a function that will merge two lists:
CLIPS (6.31 6/12/19)
CLIPS>
(deffunction add-merge (?m1 ?m2)
;; Get the lengths of the multifields
(bind ?l1 (length$ ?m1))
(bind ?l2 (length$ ?m2))
;; Swap values if the first multifield is not the largest
(if (> ?l2 ?l1)
then
(bind ?tmp ?l1)
(bind ?l1 ?l2)
(bind ?l2 ?tmp)
(bind ?tmp ?m1)
(bind ?m1 ?m2)
(bind ?m2 ?tmp))
;; Merge the values
(bind ?rv (create$))
(loop-for-count (?i ?l2)
(bind ?rv (create$ ?rv (+ (nth$ ?i ?m1) (nth$ ?i ?m2)))))
(loop-for-count (?i (+ ?l2 1) ?l1)
(bind ?rv (create$ ?rv (nth$ ?i ?m1))))
?rv)
CLIPS> (add-merge (create$ 1 2 3 4) (create$ 5 6 7 8))
(6 8 10 12)
CLIPS>
With the default settings in CLIPS, you can't have duplicate facts, so if you want two lists with the same values you need to create a slot that will contain a unique value for each list:
CLIPS>
(deftemplate list
(slot id (default-dynamic (gensym*)))
(multislot values))
CLIPS>
(deffacts lists
(list (id l1) (values 1 2 3 4))
(list (id l2) (values 1 2 3 4)))
CLIPS>
Then you can create a rule which will merge two lists:
CLIPS>
(defrule merge
(sum-lists ?l1 ?l2)
(list (id ?l1) (values $?v1))
(list (id ?l2) (values $?v2))
=>
(assert (list (values (add-merge ?v1 ?v2)))))
CLIPS> (reset)
CLIPS> (assert (sum-lists l1 l2))
<Fact-3>
CLIPS> (run)
CLIPS> (facts)
f-0 (initial-fact)
f-1 (list (id l1) (values 1 2 3 4))
f-2 (list (id l2) (values 1 2 3 4))
f-3 (sum-lists l1 l2)
f-4 (list (id gen1) (values 2 4 6 8))
For a total of 5 facts.
CLIPS>