CLIPS 顺序处理文件中的数据行

CLIPS processing data rows in file sequentially

我正在使用(模糊)CLIPS 版本 6.31

我正在尝试为动态过程构建一个实时控制系统。该过程由多个电子设备监控,这些设备将数据写入文件。

我想从文件中读取数据,并根据数据做决定。

我设想的工作流程如下:

  1. 阅读嵌入领域知识的规则文件(rules.clp)
  2. 打开包含记录的测量数据的文件(measurements.dat)
  3. 对于读取文件中的每一行:使用 defrule 调用自定义函数来处理行数据并根据行断言事实(如果条件匹配)。
  4. (运行)?我不确定 run 是否可以多次调用?
  5. 继续下一行...(继续到 EOF)然后关闭文件

如何使用 CLIPS 执行此工作流程 - 无需人工干预?

假设rules.clp包含这样的内容:

(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))

并且 measurements.dat 包含以下内容:

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

你可以用这段代码重新定义main来处理数据:

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;
  }

此数据的输出将是:

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

您可以类似地完全在 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>