0
votes

I am using (Fuzzy)CLIPS ver 6.31

I am trying to build a real time control system for a dynamic process. The process is being monitored by several electronic devices, which write the data to file.

I want to read the data from the file, and make decisions based on the data.

The workflow I envisage, is as follows:

  1. Read the rules file that embeds the domain knowledge (rules.clp)
  2. Open the file containing the recorded measurement data (measurements.dat)
  3. For each row in the read file: use a defrule calling a custom function to process row data and assert fact based on row (if criteria matched).
  4. (Run)? I'm not sure if run can be called more than once?
  5. Proceed to next row ... (continue to EOF) then close file

How can I use CLIPS to carry out this workflow - which requires no manual intervention?

1
Have you considered using CLIPS APIs for this? Instead of reading the file with CLIPS logic, you could use a compatible programming language which reads the lines and asserts them into CLIPS as facts. In this way you can use CLIPS rules to implement the reasoning while the IO and other related things are dealt in an imperative programming language.noxdafox
@noxdafox What you describe, is exactly what I'm aiming of doing. My idea is to rewrite the main() function in main.c and do the file reading, fact assertion etc. from there - however, I haven't seen any examples doing this. Are there any online resources that you can guide me to?Homunculus Reticulli
The Advanced Programming Guide remains the best reference material available. You can also integrate CLIPS in other programming languages through its language bindings. You can check clipspy or clipsgo. Keep in mind that those bindings target CLIPS and not FuzzyCLIPS so you might encounter some challenges.noxdafox

1 Answers

1
votes

Suppose rules.clp contains this content:

(deftemplate points 
   (slot x1)
   (slot y1)
   (slot x2)
   (slot y2))
   
(defrule print-length
   (points (x1 ?x1)
           (y1 ?y1)
           (x2 ?x2)
           (y2 ?y2))
   =>
   (bind ?length (sqrt (+  (** (- ?x2 ?x1) 2)
                           (** (- ?y2 ?y1) 2))))
   (printout t "Length is " ?length crlf))

And measurements.dat contains this content:

3 4 0 0
8 3 -3 2
9 4 1 0
0 8 0 2

You can redefine main with this code to process the data:

int main(
  int argc,
  char *argv[])
  {
   void *theEnv;
   FILE *theFile;
   int x1, y1, x2, y2;
   char buffer[256];
   int rv;

   theEnv = CreateEnvironment();

   EnvLoad(theEnv,"rules.clp");
   
   theFile = fopen("measurements.dat","r");
   
   if (theFile == NULL) return -1;
   
   while (fscanf(theFile,"%d %d %d %d",&x1,&y1,&x2,&y2) == 4)
     {
      sprintf(buffer,"(points (x1 %d) (y1 %d) (x2 %d) (y2 %d))",x1,y1,x2,y2);
      EnvAssertString(theEnv,buffer);
      EnvRun(theEnv,-1);
     }
    
   fclose(theFile);
         
   return 0;
  }

The output from this data will be:

Length is 5.0
Length is 11.0453610171873
Length is 8.94427190999916
Length is 6.0

You can similarly process the data totally within CLIPS:

         CLIPS (6.31 6/12/19)
CLIPS> (load rules.clp)
Defining deftemplate: points
Defining defrule: print-length +j+j
TRUE
CLIPS> 
(defrule open-file
   =>
   (assert (input (open "measurements.dat" input "r"))))
CLIPS> 
(defrule get-data
   (declare (salience -10))
   ?f <- (input TRUE)
   =>
   (retract ?f)
   (bind ?line (readline input))
   (if (eq ?line EOF)
      then
      (close input)
      else
      (bind ?points (explode$ ?line))
      (assert (points (x1 (nth$ 1 ?points))
                      (y1 (nth$ 2 ?points))
                      (x2 (nth$ 3 ?points))
                      (y2 (nth$ 4 ?points))))
      (assert (input TRUE))))
CLIPS> (run)
Length is 5.0
Length is 11.0453610171873
Length is 8.94427190999916
Length is 6.0
CLIPS>