Using logical operators in CLIPS - expert-system

I am trying to define a greater than rule in CLIPS but it doesn't seem to be working. Any idea on how I can fix it. The problem seems to be occurring at defrule btwn100and120.
(defrule part-credits
(or (current-part "a")
(current-part "b")
(current-part "c"))
=>
(bind ?reply (get-text-from-user "How many points did you achieve?"))
(assert (part-credits ?reply))
)
(defrule btwn100and120
(part-credits => 100)
(part-credits <= 120)
=>
(bind ?reply (get-text-from-user "Did you Part A before the changes? (y/n)"))
(assert (btwn100and120 ?reply))
)

Use the test function to make numerical comparisons. Also, note that CLIPS uses prefix notation for mathematical operators. Here is a simplified rule that does what you want:
(defrule MAIN::btwn100and120
(part-credits ?val)
(test (<= ?val 120))
(test (>= ?val 100))
=>
(printout t "Value " ?val " is in range." crlf)
)
And here is a test of the rule:
CLIPS> (watch facts)
CLIPS> (watch activations)
CLIPS> (assert (part-credits 99))
==> f-0 (part-credits 99)
<Fact-0>
CLIPS> (assert (part-credits 110))
==> f-1 (part-credits 110)
==> Activation 0 btwn100and120: f-1
<Fact-1>
CLIPS> (run)
Value 110 is in range.
CLIPS>

Related

How can I convert this list of numbers and symbols into a string?

is there a way too convert a list like this into a normal string?
list->string does not work because it isn't a list of chars.
It is a bit problematic because the list consists of symbols and numbers :/
(list + 4 * 5 - 3 6) //-> "+4*5-36"
Standard Scheme
For numbers:
(number->string 123 10) ; ==> "123"
For symbols:
(symbol->string 'test) ; ==> "test"
So you can check what type it is and use the correct procedure to convert to string. You can use string-append so join more strings together.
(string-append (symbol->string '+)
(number->string 4)
(symbol->string '*)
(number->string 5)
(symbol->string '-)
(number->string 3)
(number->string 6))
; ==> "+4*5-36"
If you make a procedure any->string you can make a one level list to string like this with SRFI-1:
(foldr (lambda (e a) (string-append (any->string e) a))
""
'(+ 4 * 5 - 3 6))
; ==> "+4*5-36"
Racket
Racket has format. If you do (format "~a" data) it will produce a string:
(format "~a" '(+ 4 * 5 - 3 6))
; ==> "(+ 4 * 5 - 3 6)"
Note that the first element of (list + 4 * 5 - 3 6) isn't the symbol + since the variable + gets evaluated to a procedure that adds stuff. eg. (+ 3 4) ; ==> 7 and + ; ==> #<procedure:+> (in racket; implementation specific)
I will show you in mit-scheme:
(define input '(+ 4 * 5 - 3 6))
(fold-right (lambda (x acc)
(string-append ((cond ((number? x) number->string )
((symbol? x) symbol->string ))
(else (error "unknown case" x))
x)
acc))
""
input)
Example:
1 ]=>
(define input '(+ 4 * 5 - 3 6))
;Value: input
...
;Value: "+4*5-36"
In case the list contains more kind of symbolic expressions, apart from numbers and symbols, you extend the cond-statement with other cases.
Also, do not forget to quote the input, otherwise + gets evaluated to a strange value.

Lisp Function fails, although working previously (Draft Sight, SVG to CAD)

We are trying to implement a Draft Sight/AutoCad script that will transform a SVG file into a CAD drawing.
The principal idea is to read the file line by line (performed by ReadSVGData), split the svg definitions by spaces (ReadHTMLItemData), read the individual HTML attributes into a list and based on the type of the SVG item draw a CAD element. So much in regards to the principal...
The unususal part is, that whenever the Html Attributes, like "id="Box_8_0"" are sent to the findchar function, by attrlis function, the script fails, although the same arrangement went well before
Does anybody have a hint where my mistake is hidden?
(defun findchar (FindChar Text)
(setq
;current location in string
coord 1
;Init Return Coordinate
ReturnCoord 0
;Length of Searched Item, to enable string searching
FindCharLen (strlen FindChar)
;Nil Count: Requires as regular expressions like (/t) are identified as two times ascii char 9
NilCnt 0
;Storage of last Char Ascii to identify regular expressions
LastCharAsci -1
)
;iterate the String and break in case of the first occurence
(while (and (<= coord (strlen Text) ) (= ReturnCoord 0))
;Current Character
(setq CurChar (substr Text coord FindCharLen))
;Find Searched String
(if (= FindChar CurChar)
(setq ReturnCoord coord)
)
;Check for regular expression
(if (and (= LastCharAsci 9) (= (ascii CurChar) 9))
(setq NilCnt (+ NilCnt 1))
)
;Update String position and String
(setq LastCharAsci (ascii CurChar))
(setq coord (+ coord 1))
)
;return variable
(- ReturnCoord NilCnt)
)
(defun attrlis (HTMLAttr)
(setq Koordi 0)
(progn
(setq CharLoc (findchar "<" HTMLAttr))
(princ HTMLAttr)
(terpri)
)
(+ Koordi 1)
)
(defun ReadHTMLItemData(HTMLItem)
(setq
coord 1
HTMLItmBgn 1
Attributes 0
CurChar 0
Dictionary 0
)
;(princ HTMLItem)
;(terpri)
(while (<= coord (strlen HTMLItem))
(setq CurChar (substr HTMLItem coord 1))
(if (or (= (ascii CurChar) 32) (= (ascii CurChar) 62))
(progn
(if (> (- coord HTMLItmBgn) 0)
(progn
(setq htmlattr (substr HTMLItem HTMLItmBgn (- coord HTMLItmBgn)))
(setq Result (attrlis htmlattr))
(princ Result)
(setq HTMLItmBgn (+ coord 1))
)
)
)
)
(setq coord (+ coord 1))
)
)
(defun ReadLineContents(Line)
(if (/= Line nil)
(progn
;(princ Line)
;(terpri)
(setq
Bgn (findchar "<" Line)
End (findchar ">" Line)
ItemDef (substr Line (+ Bgn (strlen "<")) End)
)
(ReadHTMLItemData ItemDef)
)
)
)
(defun C:ReadSVGData()
(setq SVGFile (open (getfiled "Select a file" "" "svg" 0) "r"))
(setq Line 1)
(while (/= Line nil)
(setq Line (read-line SVGFile))
(ReadLineContents Line)
)
(close SVGFile)
(princ "Done")
)
Reading the following file:
<svg class="boxview" id="boxview" style="width:1198.56px; height:486.8004px; display:block;" viewBox="0 0 1198.56 486.8004">
<g id="BD_box">
<rect class="box" id="Box_8_0" x="109.21" y="394.119" width="58.512" height="62.184" box="4047"></rect>
</g>
</svg>
EDIT
Change of substring Index, based on satraj's answer
The problem lies in the way the "substr" Autolisp function is used. The start index of substr always starts from index 1 (not from 0). So your code must be changed such that the start index are initialized as 1. The following lines in your code fails.
(setq CurChar (substr HTMLItem coord 1))
(setq htmlattr (substr HTMLItem HTMLItmBgn (- coord HTMLItmBgn)))
Since coord and HTMLItemBgn variables are initialized as 0, the substr function fails.
Also, why not use "vl-string-search" function if you want to find the position of a text in a string? you can get rid of the findchar function.
An Example:
(setq CharLoc (vl-string-search "<" HTMLAttr))
In general, if you want to debug failures in AutoLisp, add the following function to your lisp file and it will print a stack trace in case of failures, which will enable you to locate exact place where the error occured.
(defun *error* (msg)
(vl-bt)
)

variable unbound in lisp when using threading in sbcl lisp

i am writing a program in sbcl to multiply two numbers using add and shift method. while my normal program would run nicely but when i use threads , the program shows no output and no error message. Is there any mistake in code which i should remove.
(use-package :sb-thread)
(defvar *buffer-queue* (make-waitqueue))
(defvar *buffer-lock* (make-mutex :name "buffer-lock"))
(defvar *buffer* (list nil))
(defun writer()
(let ((res 0))
(loop for lpr from 0 to 63
do (let ((end-bit (logand num2 1)))
(with-mutex (*buffer-lock*)
(setf *buffer* (cons end-bit *buffer*))
(setq num2 (ash num2 -1))
(condition-notify *buffer-queue*)
)))))
(defun reader()
(let ((end-bit 0) (res 0))
(with-mutex (*buffer-lock*)
(loop
(condition-wait *buffer-queue* *buffer-lock*)
(loop
(unless *buffer* (return))
(end-bit (car *buffer*))
(setf *buffer* (cdr *buffer*)))))
(if (= end-bit 1)
(setq res (+ res num1)))
(setq num1 (ash num1 1))
(format t "result is ~a.~%" res)
)
)
(let ((num1 (progn
(write-line "Enter first number: ")
(finish-output)
(read)))
(num2 (progn
(write-line "Enter second number: ")
(finish-output)
(read))))
(if (or (= num1 0) (= num2 0))
(write-line "result is 0.0")
(calculator num1 num2))
)
why it is happening?
To figure out what is happenning, I strongly suggest to use (trace writer) and (trace reader) (maybe even (trace calculator)).
I would also suggest to use bordeaux-thread which is simply a shim (bordeaux = shim in french) to make threading works on multiple implementation.

how do I properly execute a program with scheme48?

I'm learning Scheme. I want to build script-fu filters for Gimp, so I was using tinyscheme to execute the scripts I made, but it seems like tinyscheme has a very limited set of functions, functions like max, min and even?, are missing. (I'd like someone to prove me wrong here :( )
Ok, actually, I just want to execute a Scheme script with scheme48. How do I do that?
for example, how do I execute the following file with scheme48?
(define (addx inNum inX)
(if (> (* inNum inX) 999) 0
(+ (* inNum inX) (addx inNum (+ 1 inX)))))
(display
(- (+ (addx 3 1) (addx 5 1)) (addx 15 1)))
I also was not able to run a scheme-script with scheme48 successfully (and I couldn’t find a hint in the manual yet). You may alternatively use Guile (assuming, you are working on linux or something like that):
#!/usr/local/bin/guile -s
!#
(define (addx in-num in-x)
(if (> (* in-num in-x) 999)
0
(+ (* in-num in-x) (addx in-num (+ 1 in-x)))))
(display (- (+ (addx 3 1) (addx 5 1)) (addx 15 1)))
(newline)
Save it and then run:
$chmod u+x test.scm
./test.scm
233168
$
(by the way: Please don’t format Scheme like C).
EDIT
According to a post of Mike Sperber on the Scheme48 mailing list, shebanging will not work. Explicitely invoking Scheme48 is to be done this way:
#!/bin/bash
scheme48 -a batch << EOF
(letrec ((fac (lambda (n)
(if (= n 1)
1
(* n (fac (- n 1)))))))
(fac 5))
EOF
$ ./test.scm
120

How to define a string in Scheme - any string that I choose?

Given that:
(define output "")
or that
(define output "goodInput")
When I run those defines in my code, I get:
ERROR: In procedure memoization:
ERROR: Bad define placement (define output "").
Why is that ?
EDIT:
; Formal function of the code
(define (double->sum myString)
(define myVector 0)
(set! myVector (breaking myString))
(define output "")
(define returnValue (checkLegit myVector)) ; check the number of legitimate characters ,they need to be either numbers or "."
(define flag 0)
(if (not(= returnValue (vector-length myVector))) (set! output "Input error") (set! flag (+ flag 1)))
(define i 0) ; the length of the vector
(define count 0) ; the value of all the numbers in the vector
(if
(= flag 1)
(do ()
((= i (vector-length myVector))) ; run until the end of the vector
(cond
((char=? (vector-ref myVector i) #\.) ; check if we found a dot
(set! output (appending output count)) (set! output (appendingStrings output ".")) (set! count 0)
)
(else (set! count (+ count (char->integer(vector-ref myVector i)) )) (set! count (- count 48))
); end of else
) ; end of cond
(set! i (+ i 1)) ; inc "i" by 1
); end of do
) ; end do
; if flag = 1 , then the input is in a correct form
(if (= flag 1) (set! output (appending output count)))
(if (= flag 1)
output
"Input error")
) ; END
The problem is not in the string definition itself (there are no strange characters, or anything like that), it's in the place within the code where that definition is happening: you're inside a procedure, and the last line in a procedure can not be a define. Try returning something after the definition and it should work fine.
I guess that you've just started writing the procedure, just keep going after the define and write the rest of the code. For the time being, use a placeholder value at the end, so the interpreter won't complain:
(define (double->sum myString)
(define myVector 0)
(set! myVector (breaking myString))
(define output "")
'ok)
Also a matter of style - although it's ok to define-and-set a variable like that, it's more idiomatic to use a let expression for defining local variables. This is what I mean:
(define (double->sum myString)
(let ((myVector (breaking myString))
(output ""))
'ok))
In that way, you won't have to use set!, which mutates the variable and goes against the functional-programming style preferred in Scheme.

Resources