How to create rules of divisibility in Clips? - artificial-intelligence

I'm very new to Clips Expert System, I would like to know if some of you can help to implement rules of divisibility for numbers 7, 11 and 13.
This is what I used for divisibility of 2 but I can't do the same for 7, 11 and 13
;Facts for divisibility of 2
(deffacts lastnumbers
(firstnum 0)
(secondnum 2)
(thirdnum 4)
(fourthnum 6)
(fifth 8))
I'm trying to get the out like this:
Number 886782 is divisible by 13
Thanks in advance.

In general, you cannot determine if one number is evenly divisible by another just looking at the last digit of the dividend. Instead look at the remainder of the integer division and if it's zero, then the dividend was evenly divisible by the divisor.
CLIPS (6.31 6/12/19)
CLIPS>
(defrule get-dividend
(not (dividend ?))
=>
(printout t "Dividend? ")
(assert (dividend (read))))
CLIPS>
(defrule get-divisor
(dividend ?dividend&:(integerp ?dividend))
(not (divisor ?))
=>
(printout t "Divisor? ")
(assert (divisor (read))))
CLIPS>
(defrule bad-response
(or ?f <- (dividend ?d)
?f <- (divisor ?d))
(test (not (integerp ?d)))
=>
(retract ?f))
CLIPS>
(defrule is-divisible
(dividend ?dividend&:(integerp ?dividend))
(divisor ?divisor&:(integerp ?divisor))
=>
(printout t "Dividend " ?dividend " is"
(if (= (mod ?dividend ?divisor) 0)
then " "
else " not ")
"divisible by " ?divisor crlf))
CLIPS> (reset)
CLIPS> (run)
Dividend? 17
Divisor? 3
Dividend 17 is not divisible by 3
CLIPS> (reset)
CLIPS> (run)
Dividend? 886782
Divisor? 13
Dividend 886782 is divisible by 13
CLIPS>

Related

How to convert a list to a one dimensional array (vector) in Common Lisp having the same output either using make-array or coerce?

I want to convert from a simple list:
'(1 2 3)
To a one dimensional array (vector):
#(1 2 3)
I found this question which is similar but does not cover this problem.
I also managed to find a way to achieve it. Not sure if it is the best:
CL-USER> (coerce '(1 2 3) 'vector)
#(1 2 3)
CL-USER> (type-of *)
(SIMPLE-VECTOR 3)
I wonder if it is possible to use make-array to achieve the same result. I tried:
CL-USER> (make-array '() :initial-contents '(1 2 3))
#0A(1 2 3)
CL-USER> (type-of *)
(SIMPLE-ARRAY T NIL)
This is close, but I do not understand #0A in #0A(1 2 3).
For some reason that I do not understand, this output does not work on further compositions, such as aref:
CL-USER> (aref #0A(1 2 3) 0)
; Evaluation aborted on #<SIMPLE-ERROR "Wrong number of subscripts, ~W, for array of rank ~W." {1003C07793}>.
Is it possible to use make-array to achieve the same result as coerce?
What are the differences between these two approaches?
Is one of them faster or more elegant than the other?
COERCE is fine, you can even specify the element-type if you want:
USER> (coerce '(1 2 3) '(vector fixnum))
#(1 2 3)
USER> (describe *)
#(1 2 3)
[simple specialized vector]
Element-type: FIXNUM
Length: 3
You can do the same with make-array, but you need to give the right dimension. The dimension parameter indicates how many rows, columns, etc. the possibly multi-dimensional array has. It should be a list, but when you only have one dimension, it can just be a number. Both forms here are equivalent:
USER> (make-array 3 :initial-contents '(1 2 3))
#(1 2 3)
USER> (make-array '(3) :initial-contents '(1 2 3))
#(1 2 3)
Usually you would call (length list). The added value compared to coerce is that you can specify the :fill-pointer or :adjustable arguments, something that the type argument of coerce cannot convey.
The printed representation of an array is #nA(), where n is the number of dimensions of the array, where the number and A is omitted if its a vector (n = 1). For example:
USER> (make-array '(10 2) :initial-element 0)
#2A((0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0))
For a given array of dimension n, you access the elements with aref and as many arguments as there are dimensions, in row-major order (the same order you specified the dimensions in make-array).
USER> (aref * 5 1)
0 (0 bits, #x0, #o0, #b0)
In your example, you defined an array of dimension 0, because you wrote '() (a.k.a. just () or nil) as the dimension. This can be used if you need a box to store a single element:
USER> (defparameter *box* (make-array nil :element-type '(mod 8)))
*BOX*
USER> (describe *box*)
#0A0
[simple specialized array]
Element-type: (UNSIGNED-BYTE 4)
Dimensions: NIL
Storage vector: #<(SIMPLE-ARRAY (UNSIGNED-BYTE 4) (1)) {101EA0C59F}>
; No values
USER> (setf (aref *box*) 7)
7 (3 bits, #x7, #o7, #b111)
USER> (incf (aref *box*))
8 (4 bits, #x8, #o10, #b1000)
USER> (aref *box*)
8 (4 bits, #x8, #o10, #b1000)
(as you can see, the values that can be stored in the array are the ones corresponding to the upgraded-element-type, here (unsigned-byte 4); for example, (setf (aref *box*) (expt 2 16)) signals an error)
It looks like :initial-contents had the same result as :initial-element, because with your example the content of the zero-dimensional array was the list (1 2 3)
Is one of them faster or more elegant than the other?
I try to use coerce when possible because it's shorter to write and it looks more descriptive of what I am doing. I don't think it is faster, unless you know in advance the length of the list.

Is there any way to prioritize a rule by its own slot in CLIPS?

Is there anyway to make a rule fire earlier given a specific slot value that a fact may have?
I was wondering if there is anything like dynamic salience but for slot values
Thank you
It's likely there's a more elegant solution to whatever problem you're solving than changing the salience of a rule based on a slot value, but since you can use a global variable for the salience value of a rule, you can dynamically change the salience for a rule by assigning the global a value pulled from a fact slot:
CLIPS (6.31 6/12/19)
CLIPS> (set-salience-evaluation every-cycle)
when-defined
CLIPS>
(defglobal ?*r-1* = 0
?*r-2* = 0)
CLIPS>
(deftemplate rule-priority
(slot rule)
(slot salience))
CLIPS>
(deffacts start
(rule-priority (rule r-1) (salience -10))
(rule-priority (rule r-2) (salience -10))
(prime))
CLIPS>
(defrule assign
(declare (salience 10000))
(rule-priority (rule ?r) (salience ?s))
=>
(eval (str-cat "(bind ?*" ?r "* " ?s ")")))
CLIPS>
(defrule start
?rp <- (rule-priority (rule r-2) (salience ~10))
=>
(modify ?rp (salience 10)))
CLIPS>
(defrule r-1
(declare (salience ?*r-1*))
(prime)
=>)
CLIPS>
(defrule r-2
(declare (salience ?*r-2*))
(prime)
=>)
CLIPS> (reset)
CLIPS> (agenda)
10000 assign: f-2
10000 assign: f-1
0 r-1: f-3
0 r-2: f-3
0 start: f-2
For a total of 5 activations.
CLIPS> (run 2)
CLIPS> (agenda)
0 start: f-2
-10 r-1: f-3
-10 r-2: f-3
For a total of 3 activations.
CLIPS> (run 1)
CLIPS> (agenda)
10000 assign: f-4
-10 r-1: f-3
-10 r-2: f-3
For a total of 3 activations.
CLIPS> (run 1)
CLIPS> (agenda)
10 r-2: f-3
-10 r-1: f-3
For a total of 2 activations.
CLIPS>
You can also dynamically assign the salience of a rule using a deffuction and retrieve the slot value using the fact query functions:
CLIPS> (clear)
CLIPS> (set-salience-evaluation every-cycle)
every-cycle
CLIPS>
(deftemplate rule-priority
(slot rule)
(slot salience))
CLIPS>
(deffunction get-salience (?rule)
(do-for-fact ((?rp rule-priority))
(eq ?rp:rule ?rule)
(return ?rp:salience))
(return 0))
CLIPS>
(deffacts priorities
(rule-priority (rule r-1) (salience -10))
(rule-priority (rule r-2) (salience -10))
(prime))
CLIPS>
(defrule start
?rp <- (rule-priority (rule r-2) (salience ~10))
=>
(modify ?rp (salience 10)))
CLIPS>
(defrule r-1
(declare (salience (get-salience r-1)))
(prime)
=>)
CLIPS>
(defrule r-2
(declare (salience (get-salience r-2)))
(prime)
=>)
CLIPS> (reset)
CLIPS> (agenda)
0 start: f-2
-10 r-1: f-3
-10 r-2: f-3
For a total of 3 activations.
CLIPS> (run 1)
CLIPS> (agenda)
10 r-2: f-3
-10 r-1: f-3
For a total of 2 activations.
CLIPS>

Output specific facts by increasing order of a certain value in CLIPS

I have the following list of facts :
f-0 (initial-fact)
f-1 (fact 1 [input_1] 21)
f-2 (fact 1 [input_2] 28)
f-3 (fact 1 [input_3] 10)
f-4 (fact 1 [input_4] 25)
f-5 (fact 1 Normal Operation!)
f-6 (fact 2 [input_1] 7)
f-7 (fact 2 [input_2] 25)
f-8 (fact 2 [input_3] 13)
f-9 (fact 2 [input_4] 15)
f-10 (fact 2 adder a1 error!)
f-11 (fact 3 [input_1] 11)
f-12 (fact 3 [input_2] 17)
f-13 (fact 3 [input_3] 24)
f-14 (fact 3 [input_4] 31)
f-15 (fact 3 multiplier p1 error!)
Is there a way to somehow choose and print from all these facts the ones that contain only the number and the type of error? For example I want to print in increasing order:
1 Normal Operation!
2 adder a1 error!
3 multiplier p1 error!
Note that I actually have more facts and the order that they are in the fact list is not in increasing order as I have shown. So I have to somehow make it increasing.
CLIPS (6.31 2/3/18)
CLIPS>
(deffacts initial
(fact 1 [input_1] 21)
(fact 1 [input_2] 28)
(fact 1 [input_3] 10)
(fact 1 [input_4] 25)
(fact 1 Normal Operation!)
(fact 2 [input_1] 7)
(fact 2 [input_2] 25)
(fact 2 [input_3] 13)
(fact 2 [input_4] 15)
(fact 2 adder a1 error!)
(fact 3 [input_1] 11)
(fact 3 [input_2] 17)
(fact 3 [input_3] 24)
(fact 3 [input_4] 31)
(fact 3 multiplier p1 error!))
CLIPS>
(deffunction compare-1st (?f1 ?f2)
(> (nth$ 1 (fact-slot-value ?f1 implied))
(nth$ 1 (fact-slot-value ?f2 implied))))
CLIPS>
(defrule print
=>
(bind ?facts
(find-all-facts ((?f fact))
(not (instance-namep (nth$ 2 ?f:implied)))))
(bind ?facts (sort compare-1st ?facts))
(foreach ?f ?facts
(bind ?data (fact-slot-value ?f implied))
(printout t (implode$ (first$ ?data)) " "
(implode$ (rest$ ?data)) crlf)))
CLIPS> (reset)
CLIPS> (run)
1 Normal Operation!
2 adder a1 error!
3 multiplier p1 error!
CLIPS>

Clojure multiply first n elements in sequence by 'x' non recursive

I am a newbie in clojure and came across a problem which says, multiply first n elements in a sequence by some number 'x' (non recursively). So for example
(multiply-n-by-x [1 2 3 4 5] 2 10) => [10 20 30 4 5]
So here i understood that i need to loop over the sequence n times and then stop, but i am unable to do that. If someone could guide me on how to do about it, it would be great.
Same as Shawn's answer but with destructuring and split-at (a bit less redundant):
(defn multiply-n-by-x [s n x]
(let [[s1 s2] (split-at (inc n) s)]
(concat (map #(* x %) s1) s2)))
I think the easy way is :
(defn multiply-n-by-x [seq n m]
(concat (map #(* m %) (take (inc n) seq)) (drop (inc n) seq) )
)
This does what you want:
(defn multiply-n-by-x [sq n x]
(for [i (range (count sq)) ;for i in range 0 to number of elements in sq
:let [element (nth sq i)]] ;bind element to the nth item in sq
(if (<= i n) ;if index below n, return the multiplied element, otherwise return the element as is
(* x element)
element)))
whatever you return inside the for macro gets put into a sequence so the end result is collection.
Lazy sequences capture delayed recursion. take, drop, split and for are lazy constructions. We can avoid them by computing the altered head of the sequence eagerly, as follows:
(defn multiply-n-by-x [coll n x]
(loop [head [], coll coll, n n]
(if (and (seq coll) (>= n 0))
(recur (conj head (* (first coll) x)) (rest coll) (dec n))
(concat head coll))))
For example,
(multiply-n-by-x [1 2 3 4 5] 2 10)
;(10 20 30 4 5)
By the way, the convention in Clojure is to give the count of a slice, not the index of the final element, which is one less.
(range 3)
;(0 1 2)

add value to first list (of lists) matching predicate

I have a list of lists and a value. My goal is a new list of lists, where the value is conjed (new first item) to the first list matching a predicate (eg > to the first item of the list). If no list matches the predicate, I want my value to "begin" a new list at the end of lists.
if my list is: ['(2 3 4) '(4 5 6 7) '(5 6 7)]
and my value: 3
and my predicate: (comp (partial < my-value) first)
then my result should be: ['(2 3 4) '(3 4 5 6 7) '(5 6 7)]
if my value was: 10
my result should be: ['(2 3 4) '(4 5 6 7) '(5 6 7) '(10)]
This problem confuses me, because my imperative mind keeps telling me how easy it should be, but I cannot find an easy (ok, be honest: any) solution. this is my attempt so far:
(defn add-to-first-list-that-matches [func value]
(loop [result []
remaining-lists list-of-lists
value-to-add value]
(if (empty? remaining-lists)
result
(let [current-list (first remaining-lists)
value-matches? (func value-to-add current-list)
new-list (if value-matches? (conj value-to-add current-list) current-list)]
(recur (conj new-list result)
(rest remaining-lists)
(if-not value-matches? value-to-add nil))))))
(it crashes)
please enlighten me with some clojure expression magic :)
btw. I want to solve this as part of the longest-increasing-subsequence problem.
This uses loop-recur.
(defn add-to-ll
[ll pred value]
(loop [[current & unprocessed] ll
processed []]
(cond
(pred current) (concat processed
[(cons value current)]
unprocessed)
(empty? unprocessed) (concat processed
[current]
[[value]])
:else (recur unprocessed
(conj processed current)))))
(def l-l1 [[2 3 4] [4 5 6 7] [5 6 7]])
(add-to-ll l-l1 (comp (partial < 10) first) 10)
=> ([2 3 4] [4 5 6 7] [5 6 7] [10])
(add-to-ll l-l1 (comp (partial < 3) first) 3)
=> ([2 3 4] (3 4 5 6 7) [5 6 7])
You could also use split-with
(defn add-to-ll
[ll pred value]
(let [[first-lists [to-change & rest-lists]] (split-with (complement pred) ll)]
(if to-change
(concat first-lists [(cons value to-change)] rest-lists)
(concat ll [[value]]))))
Performance wise the first solution should run a bit faster.
Ye olde lazy-seq:
(defn add-to-first-match
[pred x coll]
(lazy-seq
(if-let [s (seq coll)]
(let [fst (first s)]
(if (pred fst)
(cons (conj fst x) (rest s))
(cons fst (add-to-first-match pred x (rest s)))))
(cons (list x) nil))))
Note: one could further extract list into an argument and allow for example also vector as element constructor.
(defn find-index
"find index of the first item in s matching predicate `pred`"
[pred s]
(first (keep-indexed (fn [index item]
(if (pred item)
index
nil))
s)))
(defn update-first-match
"update first item in s that matches `pred` using (f item args*)"
[s pred f & args]
(apply update-in s [(or (find-index pred s)
(count s))]
f args))
(def my-lists
['(2 3 4) '(4 5 6 7) '(5 6 7)])
(defn add-to-first-list-less-than
[l n]
(update-first-match l #(< n (first %)) conj n))
;; usage:
(update-first-match my-lists #(< 5 (first %)) conj 5)
;; or
(add-to-first-list-less-than my-lists 5)
Here is my attempt to answer more succinctly using reduce:
(defn add-to-first-list-that-matches
[value lists]
(let [pred (comp (partial < value) first)
[found result] (reduce (fn [[found result] el]
(if (and (not found) (pred el))
[true (conj result (cons value el))]
[found (conj result el)]))
[false []]
lists)]
(if found
result
(conj result (list value)))))
I am using the idiom of a vector in reduce to carry multiple values (a boolean to indicate whether a match has been found, plus the modified data structure we are building up). I was also able to combine the various conditions into a single if per element, plus a final post-condition rather than nested conditions or a multi branch cond.
Here is how it works with your examples:
user> (add-to-first-list-that-matches 3 ['(2 3 4) '(4 5 6 7) '(5 6 7)])
[(2 3 4) (3 4 5 6 7) (5 6 7)]
user> (add-to-first-list-that-matches 10 ['(2 3 4) '(4 5 6 7) '(5 6 7)])
[(2 3 4) (4 5 6 7) (5 6 7) (10)]

Resources