Is there an equality operator for the test funcion in CLIPS? Also, how do nested or's work? - logical-operators

Good morning everyone!
As part of my thesis for my masters, I am trying to write some code in CLIPS for predicting the taste 37 subjects have perceived and compare it to the actual-known flavors that we had given them on the experiment. We have used an array of 122 EMG leads and recorded brain activity while they were experiencing each taste.
I used WEKA to create a hierarchical tree of the leads so that I'll keep only the most important ones which are related to brain areas for perceiving taste, leading down to 20.
Based on the tree from WEKA I'm trying to create this smart system for making predictions about what taste might a new subject experience, only with us "looking" in their EMG activity.
So...
I use the following rule to find among my facts, those which fulfill the following:
(test (or (or(eq ?L7 -5);Meaning that: test if L7 is either -5, -4, -4, -2, 2
(eq ?L7 -4)
(eq ?L7 -3)
(eq ?L7 -2)
(eq ?L7 2))
;OR
( (eq ?L7 -1);or test weather
(or(eq ?L120 -5) ;L7 is -1 AND L120 is -5 or
(eq ?L120 -4) ;L7 is -1 AND L120 is -4 or
(eq ?L120 -3) ;L7 is -1 AND L120 is -3 or
(eq ?L120 -1) ;L7 is -1 AND L120 is -1 or
(eq ?L120 1) ;L7 is -1 AND L120 is 1 or
(eq ?L120 2) ;L7 is -1 AND L120 is 2 or
(eq ?L120 3) ;L7 is -1 AND L120 is 3 or
(eq ?L120 4) ;L7 is -1 AND L120 is 4 or
(eq ?L120 5)) ;L7 is -1 AND L120 is 5
)
;OR
( (eq ?L7 0) ;OR weather
(eq ?L60 -4) ;L7 is 0 and L60 is -4
)
...etc...
What I get from this when I run it is a message saying:
[EXPRNPSR1] A function name must be a symbol
ERROR:
(defrule MAIN::rule1
(declare (salience 60))
(?f <- (facts (id ?id) (L7 ?L7) (L20 ?L20) (L23 ?L23) (L26 ?L26) ;other parameters follow ...
(test (or (or (eq ?L7 -5) (eq ?L7 -4) (eq ?L7 -3) (eq ?L7 -2) (eq ?L7 2)) ((
And there it stops, obviously implying that my syntax for nested or's in the test function are not correctly used.
Also I wonder about the "test weather equal function". I have used in the past
(test (<= ?L7 2))
and I know it works, but it didn't work for "==" (aka equal). The next best thing I found was "eq" function.
Still no luck.
I am sorry for my silly questions, but I'm new in CLIPS (and generally I'm a doctor not a programmer (yet!)), so any help would be appreciated.
So what am I doing wrong? How should the syntax be for what I'm stating in the ;comments of my code?
Thank you in advance!
Can you please help?

The error message shows the point at which the error occurred:
CLIPS (6.30 3/17/15)
CLIPS>
(deftemplate facts
(slot id)
(slot L7)
(slot L20)
(slot L23)
(slot L26))
CLIPS>
(defrule MAIN::rule1
(declare (salience 60))
?f <- (facts (id ?id) (L7 ?L7) (L20 ?L20) (L23 ?L23) (L26 ?L26))
(test (or (or (eq ?L7 -5)
(eq ?L7 -4)
(eq ?L7 -3)
(eq ?L7 -2)
(eq ?L7 2))
(())))
=>)
[EXPRNPSR1] A function name must be a symbol
ERROR:
(defrule MAIN::rule1
(declare (salience 60))
?f <- (facts (id ?id) (L7 ?L7) (L20 ?L20) (L23 ?L23) (L26 ?L26))
(test (or (or (eq ?L7 -5) (eq ?L7 -4) (eq ?L7 -3) (eq ?L7 -2) (eq ?L7 2)) ((
CLIPS>
In this case, the error occurs at the point where two left parentheses "((" are encountered. Unlike languages which allow infix operators and use parentheses to specify precedence, you can't use additional parentheses in CLIPS. So (+ 3 4) is valid syntax, but ((+ 3 4)) is not. Since the final ( is the last token parsed, the error message indicates that it was expecting that token to be a function name.
For numeric equality comparisons, use the = function.

Related

COND clause with test only

When COND is given only one test clause and nothing else at all it always returns the test result:
CL-USER> (cond (t))
T
CL-USER> (cond ((> 5 10)))
NIL
Isn't COND just a way to write IF statements?
This doesn't hold for this as when rewriting COND with test only:
CL-USER> (if (> 5 1))
error while parsing arguments to DESTRUCTURING-BIND:
too few elements in
((> 5 1))
to satisfy lambda list
(SB-IMPL::TEST SB-IMPL::THEN &OPTIONAL SB-IMPL::ELSE):
between 2 and 3 expected, but got 1
If it is this way then how does COND exactly transform every clause into IF version?
When COND is given only one test clause and nothing else at all it always returns the test result:
That's right. According to the HyperSpec entry on cond:
results---the values of the forms in the first clause whose test-form yields true, or the primary value of the test-form if there are no forms in that clause, or else nil if no test-form yields true.
Isn't COND just a way to write IF statements?
Well, cond is declared to be a macro, and if to be a special operator, so you can think of it that way, although the expansion of cond isn't defined specifically. But if is defined with syntax that requires a then-part, whereas cond isn't. Here's what a cond clause with no forms expands to (in SBCL):
CL-USER> (pprint (macroexpand '(cond ((+ 2 3)))))
(LET ((#:G1013 (+ 2 3)))
(IF #:G1013
#:G1013
(COND)))
The value of the form is saved in a value and then used as the then-part. When there are forms in the clause, they're wrapped in a progn (which returns the value of its last form):
CL-USER> (pprint (macroexpand
'(cond
((= 2 3) 42 78)
((+ 2 3))
((= 4 5) (print 'something-else)))))
(IF (= 2 3)
(PROGN 42 78)
(COND ((+ 2 3)) ((= 4 5) (PRINT 'SOMETHING-ELSE))))

Common lisp workin with list

my task is to count all element within a list, which have duplicates, eg
( 2 2 (3 3) 4 (3)) will result in 2 (because only 2 and 3 have duplicates)
Searchdeep - just returns a nill if WHAT isn't find in list WHERE
Count2 - go through the single elements and sub-lists
If it finds atom he will use SEARCHDEEP to figure out does it have duplicates, then list OUT will be checked (to make sure if this atom was not already counted (e.g. like ( 3 3 3), which should return 1, not 2)
, increase counter and add atom to the OUT list.
However, i don't understand why, but it constantly returns only 1. I think it is some kind of logical mistake or wrong use of function.
My code is:
(SETQ OUT NIL)
(SETQ X (LIST 2 -3 (LIST 4 3 0 2) (LIST 4 -4) (LIST 2 (LIST 2 0 2))-5))
(SETQ count 0)
(DEFUN SEARCHDEEP (WHAT WHERE) (COND
((NULL WHERE) NIL)
(T (OR
(COND
((ATOM (CAR WHERE)) (EQUAL WHAT (CAR WHERE)))
(T (SEARCHDEEP WHAT (CAR WHERE)))
)
(SEARCHDEEP WHAT (CDR WHERE))
)
)
)
)
(DEFUN Count2 ( input)
(print input)
(COND
((NULL input) NIL)
(T
(or
(COND
((ATOM (CAR input))
(COND
(
(and ;if
(SEARCHDEEP (CAR INPUT) (CDR INPUT))
(NOT (SEARCHDEEP (CAR INPUT) OUT))
)
(and ;do
(Setq Count (+ count 1))
(SETQ OUT (append OUT (LIST (CAR INPUT))))
(Count2 (CDR input))
)
)
(t (Count2 (CDR input)))
)
)
(T (Count2 (CAR input)))
)
(Count2 (CDR input))
)
)
)
)
(Count2 x)
(print count)
First, your code has some big style issues. Don't write in uppercase (some, like myself, like to write symbols in uppercase in comments and in text outside of code, but the code itself should be written in lowercase), and don't put parentheses on their own lines. So the SEARCHDEEP function should look more like
(defun search-deep (what where)
(cond ((null where) nil)
(t (or (cond ((atom (car where)) (equal what (car where)))
(t (searchdeep what (car where))))
(searchdeep what (cdr where))))))
You also should not use SETQ to define variables. Use DEFPARAMETER or DEFVAR instead, although in this case you should not use global variables in the first place. You should name global variables with asterisks around the name (*X* instead of x, but use a more descriptive name).
For the problem itself, I would start by writing a function to traverse a tree.
(defun traverse-tree (function tree)
"Traverse TREE, calling FUNCTION on every atom."
(typecase tree
(atom (funcall function tree))
(list (dolist (item tree)
(traverse-tree function item))))
(values))
Notice that TYPECASE is more readable than COND in this case. You should also use the mapping or looping constructs provided by the language instead of writing recursive loops yourself. The (values) at the end says that the function will not return anything.
(let ((tree '(2 -3 (4 3 0 2) (4 -4) (2 (2 0 2)) -5)))
(traverse-tree (lambda (item)
(format t "~a " item))
tree))
; 2 -3 4 3 0 2 4 -4 2 2 0 2 -5
; No values
If you were traversing trees a lot, you could hide that function behind a DO-TREE macro
(defmacro do-tree ((var tree &optional result) &body body)
`(progn (traverse-tree (lambda (,var)
,#body)
,tree)
,result))
(let ((tree '(2 -3 (4 3 0 2) (4 -4) (2 (2 0 2)) -5)))
(do-tree (item tree)
(format t "~a " item)))
; 2 -3 4 3 0 2 4 -4 2 2 0 2 -5
;=> NIL
Using this, we can write a function that counts every element in the tree, returning an alist. I'll use a hash table to keep track of the counts. If you're only interested in counting numbers that will stay in a small range, you might want to use a vector instead.
(defun tree-count-elements (tree &key (test 'eql))
"Count each item in TREE. Returns an alist in
form ((item1 . count1) ... (itemn . countn))"
(let ((table (make-hash-table :test test)))
(do-tree (item tree)
(incf (gethash item table 0)))
(loop for value being the hash-value in table using (hash-key key)
collect (cons key value))))
(let ((tree '(2 -3 (4 3 0 2) (4 -4) (2 (2 0 2)) -5)))
(tree-count-elements tree))
;=> ((2 . 5) (-3 . 1) (4 . 2) (3 . 1) (0 . 2) (-4 . 1) (-5 . 1))
The function takes a keyword argument for the TEST to use with the hash table. For numbers or characters, EQL works.
Now you can use the standard COUNT-IF-function to count the elements that occur more than once.
(let ((tree '(2 -3 (4 3 0 2) (4 -4) (2 (2 0 2)) -5)))
(count-if (lambda (item)
(> item 1))
(tree-count-elements tree)
:key #'cdr))
;=> 3

Racket - Applying a Boolean to a list of lists

I have a function that utilizes a Boolean to replace the first number in a list with 1, regardless of its value:
f({(0, 1, 0), (0, 0, 1), (1, 0, 0), ...}) = {(1, 1, 0), (1, 0, 1), (1, 0, 0), ...}
So far I have
(define (procB set)
(map (λ (lst1) ((number? (first lst1)) (cons 1 (rest lst1)))) set))
The trouble is when the function is applied to the remaining parts of the set. I get the standard error
application: not a procedure;
expected a procedure that can be applied to arguments
given: #t
I get that it isn't working because there is a Boolean (given: #t), but I am not quite sure how to fix it.
You should use an if expression to test if the first value is a number - and if it is not, what should we do? we could leave it alone. Also you seem to have a couple of misplaced parentheses, this should fix the bugs:
(define (procB set)
(map (λ (lst1)
(if (number? (first lst1))
(cons 1 (rest lst1))
lst1))
set))
Now it works as expected:
(procB '((0 1 0) (0 0 1) (1 0 0)))
=> '((1 1 0) (1 0 1) (1 0 0))
Just to be sure... if the sublists can only contain numbers, then the if expression is superfluous, all you have to do inside the lambda is (cons 1 (rest lst1)).
It looks to me like you're missing an if. In your lambda in the map, (number? (first lst1)) will resolve to #t. It will then try to apply the procedure #t to (cons 1 (rest lst1)) which gives you the error you're seeing. I suspect you want your lambda to be closer to
(lambda (lst1)
(if (number? (first lst1))
; then cons 1 with the rest
; else don't replace with a 1

Common LISP Using Equals Predicate in Cond

In Common LISP I am attempting to provide a list and create an array:
(defun make (hand)
(make-array '(5 2)
:initial-contents
hand))
(defparameter array(make '((3 H)(2 H)(11 D)(8 C)(5 D))))
This seems to work fine. Where I am tripping up is working with this array.
I want to compare the 2nd field in each position of the array.
ie.
H eq H? Yes.
H eq D? No. End.
I am unsure how to do this. I tried:
(cond ((eq 'aref hand 1 1) 'aref hand 0 1) (t)))
This did not work. Any help would be appreciated.
eq takes two parameters:
(eq 'h 'h)
=> T
(eq 'h 'd)
=> NIL
aref takes a number of parameters, depending on the rank of the array- in your case, three:
(aref hand 1 1)
=> H
(aref hand 0 1)
=> H
What you want is to give the latter as arguments to the former:
(eq (aref hand 1 1) (aref hand 0 1))
=> T
cond allows you to check a set of conditions and return a value according to the first condition that is true: (cond (condition-1 value-1) (condition-2 value-2) ...)
(cond ((eq (aref hand 1 1) (aref hand 0 1))
"first and second are the same")
((eq (aref hand 2 1) (aref hand 0 1))
"first and third are the same")
(t
"this is always true"))
=> "first and second are the same"

Invalid function mod within lisp to recursively add sum positive integers that are multiples of certain numbers

I am trying to write function that sums all positive integers less than or
equal to 200 and are multiples of 6 and 7.
What I have is the following:
(defun sumFunction(current sum)
(if (/= current 200)
(if ((eq (mod current 6) 0) or (eq (mod current 7) 0))
(setf sum (+ sum current))
(sumFunction (+ current 1) sum)
)
(sumFunction ((+ current 1) sum)
)
)
It is giving me the following error:
Error handler called recursively (:INVALID-FUNCTION NIL IF ""
"~S is invalid as a function."
(EQ (MOD CURRENT 3) 0))
I am unsure of why there is any errors.
If I follow the logic it should return the result I need.
Any help is much appreciated!
Thanks
There are two syntax errors in your code, and there are also some other issues which do not match Lisp style. Please refer to the corrected code below.
(defun sumFunction(current sum)
(if (/= current 200)
(if (or (eq (mod current 6) 0) (eq (mod current 7) 0))
(sumFunction (+ current 1) (+ current sum))
(sumFunction (+ current 1) sum))
sum))
Here is the result.
(sumFunction 20 0)
;=> 5731

Resources