Miao Ren Lei
Miao Ren Lei

Reputation: 1

Defglobal variable not working in my defrule in JESS

I have the following deffacts.

(deffacts students
    (student-information
        (id-number 2014567)
        (course BSCS)
        (year 2)
        (semester 2)
        (subjects-taken CS111 Math103 Math101 Engl111n PE101)))

(deffacts curriculum
    (prospectus-information 
        (curriculum-name BSCS)
        (1st-year-1st-sem-subjects CS111 Bio101 Math103 Math101 Engl111n PE101))

In this application, I ask the user for a student-id and if it does exists in my working memory, it acquires the student-id and binds its information in global variables such as ?*id*, ?*course*, ?*year*. I have this rule that checks what subjects the student were not able to take.

(defrule check-back-subject
    (phase check-back)
    (prospectus-information (curriculum-name ?*course*)
                            (1st-year-1st-sem-subjects $?subjec))
   ?x <- (student-information (id-number ?*id*)) 
    =>
    (bind ?subject ?subjec)
    (foreach ?subj ?subject 
        (if 
            (member$ ?subj ?x.subjects-taken)
        then 
            (printout t "Student took: " ?subj crlf)
        else
            (assert (back-subject ?subj))
            (printout t "Student did not take: " ?subj crlf))))

However, this rule does not do its job because of the global variables. When I replaced ?*course* with BSCS like this:

(prospectus-information (curriculum-name BSCS)

and replace ?*id* with 2014567 like this

?x <- (student-information (id-number 2014567)) 

The rule does its job and it outputs perfectly the subjects student-2014567 were not able to take. But this kind of rule is not efficient, what if I have 10 students, then that would mean I would have 10 rules for each student. Why does the code not work with my defglobal variables? I also made sure defglobal-reset is false.

Lastly, can a program written purely in JESS have an executable file? Thank you.

Upvotes: 0

Views: 155

Answers (1)

laune
laune

Reputation: 31290

Careful reading of the Jess manual arrives at this sentence: *"If you match to a defglobal with a pattern like (foo ?x), the match will only consider the value of the defglobal when the fact is asserted."*. This means that you cannot do what you want to do the way you planned to do it.

The usual paradigm or design pattern for this kind of task is to use a lookup, a fact containing input data (your student id), which is then matched with facts residing in Working Memory.

(deftemplate lookupId (slot id))

You can locate the student-information:

(defrule locate-student
   (lookupId (id ?id))
   (student-information (id ?id))
=>
(printout t "Found student" crlf))

And you can combine this with the curriculum data:

(defrule locate-student
   (lookupId (id ?id))
   (student-information (id ?id)
                        (course ?course)
                        (subjects-taken $?taken))
   (prospectus-information (curriculum-name ?course)
                           (1st-year-1st-sem-subjects $?subjects))
=>
   (printout t "Student took: " (intersection$ $?taken $?subjects) crlf)
   (printout t "Student flunked: " (complement$ $?taken $?subjects) crlf))

As for the question whether a Jess program can "have an executable file", the answer is "no". (I'm of course assuming that you mean whether a program writting in Jess can be compiled and linked like a C program.) You may, of course, create a (relatively simple) Java program that executes a Jess program, and you can wrap all into a .jar, which will result in an executable entity.

Upvotes: 1

Related Questions