clips: modifying assert's variable in antecedent - clips

I've been trying to modify one variable from one assert in the antecedent, but I haven't been able to do it.
In the consequent I can modify variables, with bind, assignments, etc. but I'd like to do the following:
(defrule test
?h<-(Currentposition ?x ?y)
(not (Explored (+ ?x 1) ?y))
=> (whatever)
So, the problem is that I have a character moving through a map, and I want to explore unknown cells, so I want to go to them, and in order to do so, I mark them as Explored.
In the example, I want to check if the south cell has been explored, how can I do it? I add 1 to x because I move 1 row below, x-> rows, y-> columns
Thanks

Use =, the return value constraint:
(defrule test
?h <- (Currentposition ?x ?y)
(not =(Explored (+ ?x 1) ?y))
=>)

Related

CLIPS check the boundaries of a (read) value

I'm in the process of designing an expert system from a decision tree and one of the tests is to check the wildlife score. The user is asked to enter the wildlife score and 3 possible outcomes are decided.
A score of at least 20 rejects the proposal and ends the program.
A score of more than 10 but less than 20 moves on to test 4 but asserts the outcome will be second-best.
A score of no more than 10 simply moves to test 4.
The read line from the previous test:
(defrule wildlife-score(or(energy-level 2)(energy-level 3))
=> (printout t "What is the wildlife impact score?" crlf)
(assert(wildlife-impact(read))))
The following is where I am having trouble in comparing the read value to the outcome values. Any help would be appreciated.
(defrule reject-wildlife
(wildlife-impact ? (> ?wildlife-impact 20))
=> (assert(reject))
(printout t "Reject - completely unsuitable due to wildlife impact." crlf))
The correct syntax for your comparison is (wildlife-impact ?varname&:(> ?varname 20)).
(defrule reject-wildlife
(wildlife-impact ?score&:(> ?score 20))
=>
(assert (reject))
(printout t "Reject - completely unsuitable due to wildlife impact." crlf))

Is there a way to delay execution in CLIPS

I'm writing a clips code that goes through for loop , and it print facts .
I wanna know if there is a way to delay execution for 10 seconds , after printing the first fact , then another 10 second at the second iteration ?
so is there a delay function like java?
There's nothing built-in that allows you to sleep the CLIPS process for a fix amount of time, but you can write a function which loops for a specified amount of time before returning:
CLIPS>
(deffunction pause (?delay)
(bind ?start (time))
(while (< (time) (+ ?start ?delay)) do))
CLIPS> (pause 5)
FALSE
CLIPS>

relation between foldr and append in Scheme

try to figure out how to use "append" in Scheme
the concept of append that I can find like this:
----- part 1: understanding the concept of append in Scheme-----
1) append takes two or more lists and constructs a new list with all of their elements.
2) append requires that its arguments are lists, and makes a list whose elements are the elements of those lists. it concatenates the lists it is given. (It effectively conses the elements of the other lists onto the last list to create the result list.)
3) It only concatenates the top-level structure ==> [Q1] what does it mean "only concatenates the top-level"?
4) however--it doesn't "flatten" nested structures.
==> [Q2] what is "flatten" ? (I saw many places this "flatten" but I didn't figure out yet)
==> [Q3] why append does not "flatten" nested structures.
---------- Part 2: how to using append in Scheme --------------------------------
then I looked around to try to use "append" and I saw other discussion
based on the other discussion, I try this implementation
[code 1]
(define (tst-foldr-append lst)
(foldr
(lambda (element acc) (append acc (list element)))
lst
'())
)
it works, but I am struggling to understand that this part ...(append acc (list element)...
what exactly "append" is doing in code 1, to me, it just flipping.
then why it can't be used other logics e.g.
i) simply just flip or
iii).... cons (acc element).....
[Q4] why it have to be "append" in code 1??? Is that because of something to do with foldr ??
again, sorry for the long question, but I think it is all related.
Q1/2/3: What is this "flattening" thing?
Scheme/Lisp/Racket make it very very easy to use lists. Lists are easy to construct and easy to operate on. As a result, they are often nested. So, for instance
`(a b 34)
denotes a list of three elements: two symbols and a number. However,
`(a (b c) 34)
denotes a list of three elements: a symbol, a list, and a number.
The word "flatten" is used to refer to the operation that turns
`(3 ((b) c) (d (e f)))
into
`(3 b c d e f)
That is, the lists-within-lists are "flattened".
The 'append' function does not flatten lists; it just combines them. So, for instance,
(append `(3 (b c) d) `(a (9)))
would produce
`(3 (b c) d a (9))
Another way of saying it is this: if you apply 'append' to a list of length 3 and a list of length 2, the result will be of length 5.
Q4/5: Foldl really has nothing to do with append. I think I would ask a separate question about foldl if I were you.
Final advice: go check out htdp.org .
Q1: It means that sublists are not recursively appended, only the top-most elements are concatenated, for example:
(append '((1) (2)) '((3) (4)))
=> '((1) (2) (3) (4))
Q2: Related to the previous question, flattening a list gets rid of the sublists:
(flatten '((1) (2) (3) (4)))
=> '(1 2 3 4)
Q3: By design, because append only concatenates two lists, for flattening nested structures use flatten.
Q4: Please read the documentation before asking this kind of questions. append is simply a different procedure, not necessarily related to foldr, but they can be used together; it concatenates a list with an element (if the "element" is a list the result will be a proper list). cons just sticks together two things, no matter their type whereas append always returns a list (proper or improper) as output. For example, for appending one element at the end you can do this:
(append '(1 2) '(3))
=> '(1 2 3)
But these expressions will give different results (tested in Racket):
(append '(1 2) 3)
=> '(1 2 . 3)
(cons '(1 2) '(3))
=> '((1 2) 3)
(cons '(1 2) 3)
=> '((1 2) . 3)
Q5: No, cons will work fine here. You wouldn't be asking any of this if you simply tested each procedure to see how they work. Please understand what you're using by reading the documentation and writing little examples, it's the only way you'll ever learn how to program.

Efficient cartesian product algorithm ignoring terms

Let's say I have sets A_1,...A_n, e.g. [[a b c][d e][f]]. I would like to find Cartesian product of these sets but not including any terms which are supersets of elements of some ignore list.
For instance if my ignore list is [[a e][c]], the result of the Cartesian product would be [[a d f][b d f][b e f]]. Note any term with c is not in there, neither is [a e f].
Of course one way I could do this is to find the full cartesian product and then remove the offending items, but I would like a more efficient way, such that I avoid checking solutions in the first place.
I have an initial solution which involves incrementally building each term in the cart-product, and at each stage I remove any elements from A_i if adding them to the term I am building would cause it to be a superset of any one of the ignores.
This works fine, and is better than the naive solution, but there is still a large amount of redundant checking, which also depeneds on the order in which the sets are presented. E.g. if [f] was in my ignore list, I would still keep trying to create terms until I reach [f] and then discard.
For concreteness, my clojure implementation is
(defn first-elements
"Get the first elements of a set of sets, unless ignored"
[sets ignores in-ignore?]
(loop [product-tuple [] sets sets]
(println "sets " sets)
(cond
(or (nil? sets) (nil? (first sets)))
product-tuple
:else
(if-let [set-op (remove #(in-ignore? product-tuple ignores %) (first sets))]
(if (and (coll? set-op) (empty? set-op))
product-tuple
(recur (conj product-tuple (first set-op)) (next sets)))
product-tuple))))
(defn in-ignore?
"if I add elem to this build will it become a superset of any of the ignores"
[build ignores elem]
(some #(clojure.set/superset? (conj (set build) elem) %) ignores))
(defn cartesian-product-ignore
"All the ways to take one item from each sequence, except for ignore"
[ignores original-sets]
(loop [cart-prod #{} sets original-sets]
(let [firsts (first-elements sets ignores in-ignore?)]
(print "firsts " firsts "-cart-prod " cart-prod " sets " sets "\n")
(cond
(zero? (count firsts))
cart-prod
(= (count sets) (count firsts))
(recur (conj cart-prod firsts) (update-in sets [(dec (count sets))] next))
:else
(recur cart-prod (assoc
(update-in sets [(dec (count firsts))] next)
(count firsts)
(original-sets (count firsts))))))))
I think there are some improvements that can be made over your current approach. But first, let's implement a basic cartisian-product. Then we can adapt it to accept an ignores list. This is easy enough using for and some recursion:
(defn cartesian-product [colls]
(if (empty? colls)
(list ())
(for [e (first colls)
sub-product (cartesian-product (rest colls))]
(cons e sub-product))))
;; Quick test run
(cartesian-product [[:a :b :c] [:d :e] [:f]])
=> ((:a :d :f) (:a :e :f) (:b :d :f) (:b :e :f) (:c :d :f) (:c :e :f))
Good. And since we're using for, we have the advantage of laziness. If you need your result to be something other than a sequence of sequences, it's easy enough to convert it to something else.
Now, the hard part -- implementing the ignore sets. According to your description, your current approach is to remove elements from A_i if adding them to the term you are building would cause that term to become a superset of any of the ignore sets. As your code illustrates, not only is this somewhat inefficient (for example, superset? is worst-case linear time w.r.t. the size of its first parameter), but it also makes the code more complicated than it needs to be.
So let's adopt a different approach. Instead of removing elements from A_i, let's remove any elements we add to a term from the ignore sets. Then we can prune a term if any of the ignore sets are empty. As a bonus, all it requires is a few changes to our previous cartesian-product implementation:
(defn cartesian-product-ignore [ignore-sets colls]
(cond (some empty? ignore-sets) () ; prune
(empty? colls) (list ()) ; base case
:else ; recursive case
(for [e (first colls)
sub-product (cartesian-product-ignore (map (fn [s]
(disj s e))
ignore-sets)
(rest colls))]
(cons e sub-product))))
;; test without any ignore sets
(cartesian-product-ignore [] [[:a :b :c] [:d :e] [:f]])
=> ((:a :d :f) (:a :e :f) (:b :d :f) (:b :e :f) (:c :d :f) (:c :e :f))
;; Now the moment of truth
(cartesian-product-ignore [(set [:a :e]) (set [:c])] [[:a :b :c] [:d :e] [:f]])
=> ((:a :d :f) (:b :d :f) (:b :e :f))
Of course, minor changes may be required to fit your exact needs. For example, you might want to accept ignore sets as a vector or sequence and convert them to sets internally. But that is the essence of the algorithm..
Here a core.logic (naive) approach
(ns testing
(:refer-clojure :exclude [==])
(:use [clojure.core.logic])
)
(run* [q]
(fresh [x y z]
(membero x [:a :b :c])
(membero y [:d :e])
(membero z [:f])
(== q [x y z])
(!= q [:a :e z] )
(!= q [:c y z] )
)
)
==> ([:a :d :f] [:b :d :f] [:b :e :f])
Although it's much more slow than #Nathan_Davis algorithm, 23.263 msecs vs 0.109 msecs
Take a look at clojure.math.combinatorics

Jess and FuzzyJ assistance

I'm trying to learn Jess and FuzzyJ but am having problems getting a simple program to run. I have looked at it for hours and am no quite sure why it doesn't run. If someone could point me in the right direction it would be very much appreciated.
;;;;;;;;;;;;;;;;;;;;;;;;;
Fuzzy Variables
;;;;;;;;;;;;;;;;;;;;;;;;;;
(defglobal ?*income* =
(new nrc.fuzzy.FuzzyVariable "income" 0.0 230000.00 "dollars"))
(defglobal ?*stability* =
(new nrc.fuzzy.FuzzyVariable "stability" 0.0 1.0 "index"))
(defglobal ?*liquidity* =
(new nrc.fuzzy.FuzzyVariable "liquidity" 0.0 1.0 "index"))
(defrule initial-terms
(declare (salience 100))
=>
(import nrc.fuzzy.*)
(load-package nrc.fuzzy.jess.FuzzyFunctions)
;;;;;;;;;;;;;;;;;;;;;
Primary Terms
;;;;;;;;;;;;;;;;;;;;;;;
(?*income* addTerm "low" (new ZFuzzySet 30000.00 80000.00))
(?*income* addTerm "medium" (new PIFuzzySet 100000.00 60000.00))
(?*income* addTerm "high" (new SFuzzySet 80000.00 190000.00))
(?*stability* addTerm "low" (new ZFuzzySet .3 .5))
(?*stability* addTerm "medium" (new PIFuzzySet .6 .4))
(?*stability* addTerm "high" (new SFuzzySet .7 .9))
(?*liquidity* addTerm "low" (new ZFuzzySet .3 .5))
(?*liquidity* addTerm "medium" (new PIFuzzySet .6 .4))
(?*liquidity* addTerm "high" (new SFuzzySet .7 . 9))
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Fuzzy Rules
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defrule rule-1 "low income => liquidity very low"
(theIncome ?x &: (fuzzy-match ?x "low"))
=>
(assert(theLiquidity (new nrc.fuzzy.FuzzyValue ?*liquidity* "very low")))
(defrule rule-2 "high income & high stability => very high liquidity"
(theIncome ?x &: (fuzzy-match ?x "high"))
(theStability ?y (fuzzy-match ?y "high"))
=>
(assert(theLiquidity (new nrc.fuzzy.FuzzyValue ?*liquidity* "very high"))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Defuzzification
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defrule defuzzification-and-display-liquidity
(declare (salience -1))
?f <- (theLiquidity ?z)
=>
(printout t (str-cat "Liquidity: " (?z momentDefuzzify)))
retract( ?f)
(halt))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Start up Rule/Fuzzify
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defrule assert-income-and-stability "initialization"
=>
(printout t "Enter the income(ex. 52000): ")
(bind ?income-value (float (readline t)))
(printout t "Enter the stability index(ex. 0.64): ")
(bind ?stability-value (float(readline t)))
(assert(theIncome
(new nrc.fuzzy.FuzzyValue ?*income*
(new nrc.fuzzy.TriangleFuzzySet
(- ?income-value 3000.0)
?income-value
(+ ?income-value 3000.0)))))
(assert(theStability
(new nrc.fuzzy.FuzzyValue ?*stability*
(new nrc.fuzzy.TriangleFuzzySet
(- ?stability-value 3000.0)
?stability-value
(+ ?stability-value 3000.0))))))
(reset)
(run)
There are many small syntax errors in this program; in general the Jess interpreter does a good job of pointing them out. First of all, in each of your comment blocks, you've got the actual text of the comment... not commented. So add a semicolon to the beginning of the lines like "Fuzzy Variables", for instance.
Second, on the line
(?*liquidity* addTerm "high" (new SFuzzySet .7 . 9))
there ought to be no space after that last decimal point.
Third, the rules rule-1 and rule-2 don't have enough close-parentheses at the end. Any decent programmer's editor able to format Lisp code should be able to help you fix that.
Fourth, on the line
(theStability ?y (fuzzy-match ?y "high"))
you're missing the "&:" before the predicate function -- see the previous line.
Finally, I think, the line
retract( ?f)
is malformed -- should be (retract ?f) .

Resources