32.5.2. CLIPS File Structure

The structure of the CLIPS file is as follows:

  1. Global variables

  2. Sub-functions

  3. UDF


Note:  The numerical values and the UDF functions are not relevant and must be adapted.

Also, the order of the global variable definitions (defglobal) and the functions (deffunction) are important because they first must be defined before being used.


;    1. GLOBAL VARIABLES.

;   1.1. Parameters of the UDF's FA and FB.
(defglobal
         ; Parameter A0 of FA.
           ?*A0* = 1.23E+3
         ; Parameter A1 of FA.
           ?*A1* = 1.007
         ; Parameter A2 of FA.
           ?*A2* = 0.00236
         ; Parameter A3 of FA.
           ?*A3* = -4.687E-2
         ; Parameter A4 of FA.
           ?*A4* = -9.7423E-6
         ; Parameter B0 of FB.
           ?*B0* = 151.2
         ; Parameter B1 of FB.
           ?*B1* = 9.876E+4
 )
;   1.2. U values and associated data
(defglobal
         ; Number of points
           ?*nX* = 2000
         ; Length of the interval
           ?*deltaX* = 0.0005428414207103552
         ; Minimum value of X
           ?*xMin* = 0.
         ; Maximum value of X
           ?*xMax* = (+ ?*xMin* (* (- ?*nX* 1) ?*deltaX*))
         ; U values corresponding to the multi-ramp function
         ; NOTE THE FOLLOWING STATEMENT HAS BEEN TRUNCATED 
           ?*UValues* = (create$ 1000.0 999.9999705323207 999.99988212 …)
         ; Number of U values in ?*UValues* (for test)
           ?*nUValues* = (length ?*UValues*)
         ; Estimated range of UValue (for test)
           ?*UValueMax* = 1000.
           ?*UValueMin* = 900.
 )
;   1.3.Interval values
(defglobal
         ; Interval index corresponding to X
           ?*i* = 0
         ; X values of interval
           ?*X1* = 0.
           ?*X2* = 0.
         ; U values of interval
           ?*U1* = 0.
           ?*U2* = 0.
 )
 
;   1.4. Working variables.
(defglobal 
         ; Error code.  In case of error, always return this with
         ; the value T; in case of success, don’t return this variable.
           ?*Error* = F
         ; Flag to execute huge test only once
           ?*TestValidData* = F
 )
;   2. SUB-FUNCTIONS 

;   2.1. Sub-functions to manage the error.
(deffunction InitError () (bind ?*Error* F))
(deffunction DeclareError () (bind ?*Error* T))

;   2.2. Sub-function to check the validity of U values: number
;        of values, type and order to magnitude.
;        It is not need to call it from all UDF, and this test is
;        done only once.
;        The call to this sub-function can be commented in the UDF
;        once you are sure the U values validity.
(deffunction IsDataValid ()
  ; Return if the test is already done.
  (if (eq ?*TestValidData* T) then (return))
  ;Do the test
  (bind ?*TestValidData* T)
  ; Check the number of data in UValues.
  (if (neq ?*nX* ?*nUValues*) then
    (printout t "Data are not valid: number of values in ?*UValues* ("
                (length ?*UValues*) ")" crlf
                "are not the expected one ?*nX* (" ?*nX* ")." crlf
     )
    (DeclareError)
   )
  ;Check if the values in UValues are numeric values and ranged 
  ;between UValueMin and UValueMax.
  (loop-for-count (?i 1 ?*nUValues*) do
    (bind ?U (nth$ ?i ?*UValues*))
    (if (eq (numberp ?U) FALSE) then
      (printout t "Data are not valid: the value " ?i " (" ?U ")" crlf
                  "in ?*nUValues* is not a number ." crlf
       )
      (DeclareError)
     else
      (if (or (< ?U ?*UValueMin*) (> ?U ?*UValueMax*)) then
        (printout t "Data are not valid: the value " ?i " (" ?U ") in 
                   ?*nUValues*" crlf "is out of expected range ["
                   ?*UValueMin* ", " ?*UValueMax*"]." crlf
         )
        (DeclareError)
       )
     )
   )
  (if (eq ?*Error* T ) then 
    (bind ?*TestValidData* F) ; Other process have to do the test
   )
 )
;   2.3. Sub-function to check if X is valid
;       (ranged between xMin and xMax).
(deffunction IsXValid (?X)
  (if (or (< ?X ?*xMin*) (> ?X ?*xMax*)) then
    (DeclareError)
    (printout t "Error in IsXValid: " crlf
                "    ?X=" ?X " is not ranged between xMin="
                ?*xMin* " and xMax=" ?*xMax* crlf
     )
   )
 )
;   2.4. Sub-function to get the interval index
(deffunction GetIntervalValues (?X)
  (bind ?*i* (+ 1 (integer (/ (- ?X ?*xMin*) ?*deltaX*))))
  ; If X is the last point equal to xMax then, I equal nX-1
  (if (eq ?*i* ?*nX*) then (bind ?*i* (- ?*i* 1)))
  ; U and X at beginning of the interval i.
  (bind ?*U1* (nth ?*i* ?*UValues*))
  (bind ?*X1* (+ ?*xMin* (* (- ?*i* 1) ?*deltaX*)))
  ; U and X at end of the interval i.
  (bind ?*U2* (nth (+ ?*i* 1) ?*UValues*))
  (bind ?*X2* (+ ?*xMin* (* ?*i* ?*deltaX*)))
 )

;   2.5. Sub-function to get the U values
(deffunction GetTValue ( ?X)
  (bind ?p (/ (- ?*U2* ?*U1*) ?*deltaX*))
  (bind ?q (/ (- (* ?*U1* ?*X2*) (* ?*U2* ?*X1*)) ?*deltaX*))
  (bind ?R (+ (* ?p ?X) ?q))
  ?R
 )
;   3. UDF CALLED FROM POLYFLOW.
;   Those functions must return ?*Error* = T if its evaluation fails.

;   3.1. UDF for the function FA(X)
(deffunction FA (?X)
; Initialize the error code.
  (InitError)
; Check if data are valid.
: Already check during setup of UDF, commented in order to do not call it.
  (IsDataValid)
; Check if X is valid
  (IsXValid ?X)
  (if (eq ?*Error* T) then
     (printout t "Error in FA(X) UDF, see above message." crlf)
     (return ?*Error*)  ; Return a non-numeric value
   )
  (GetIntervalValues ?X)
  (bind ?U (GetTValue ?X))
; R = A0 + U*(A1 + U*(A2 + U*(A3 + U*A4)))
  (bind ?R (+ ?*A0* 
              (* ?U (+ ?*A1* 
               (* ?U (+ ?*A2*
                (* ?U (+ ?*A3*
                 (* ?U ?*A4*)
   ))))))))
  ?R  ; Return a numeric value
)

;   3.2. UDF for the function FB(X)
(deffunction FB (?X)
; Initialize the error code.
  (InitError)
; Check if X is valid
  (IsXValid ?X)
  (if (eq ?*Error* T) then
     (printout t "Error in FB(X) UDF, see above message." crlf)
     (return ?*Error*)  ; Return a non-numeric value
   )
  (GetIntervalValues ?X)
  (bind ?U (GetTValue ?X))
; R = B1 * (U – B0)
  (bind ?R (* ?*B1* (- ?U ?*B0*)))
  ?R  ; Return a numeric value
)