filebindclips

How can I open the file correctly in CLIPS?


I had a task to wrote a function which receives as a parameter the name of a file containing the coefficients of a system of linear equations specified in the form of a rectangular matrix. Using acceptable transformations, bring the system to a triangular appearance. Write the result to a file.

   (bind ?input (open ?input-filename "r"))
   (bind ?output (open ?output-filename "w"))
   (if (not ?input)
      then
      (printout t "Error of opening " ?input-filename crlf)
      (return))
   
   (bind ?matrix (create$))
   (while (not (eq (readline ?input) EOF))
      (bind ?line (readline ?input))
      (if (neq ?line nil)
         then
         (bind ?row (create$))
         (bind ?token "")
         (bind ?len (str-length ?line))
         (loop-for-count (?i 1 (+ 1 ?len)) do
            (bind ?char (str-index ?line ?i))
            (if (str-compare ?char " ")
               then
               (if (neq ?token "")
                  then
                  (bind ?number (string-to-field ?token))
                  (if (numberp ?number)
                     then
                     (bind ?row (create$ ?row ?number))
                     (bind ?token "")))
               else
               (bind ?token (str-cat ?token ?char))))
         (if (neq (length$ ?row) 0)
            then
            (bind ?matrix (create$ ?matrix ?row)))))
   
   (bind ?num-rows (length$ ?matrix))
   (bind ?num-cols (length$ (first$ ?matrix)))

   (loop-for-count (?i 1 (+ 1 ?num-cols)) do
      (loop-for-count (?j ?i (- ?num-rows 1)) do
         (bind ?pivot-row (nth$ ?j ?matrix))
         (bind ?pivot (nth$ ?i ?pivot-row))
         (if (neq ?pivot 0)
            then
            (loop-for-count (?k (+ ?j 1) ?num-rows) do
               (bind ?current-row (nth$ ?k ?matrix))
               (bind ?factor (/ (nth$ ?i ?current-row) ?pivot))
               (bind ?scaled-row (create$))
               (loop-for-count (?l 1 (+ 1 ?num-cols)) do
                  (bind ?new-value (- (* (nth$ ?l ?pivot-row) ?factor) (nth$ ?l ?current-row)))
                  (bind ?scaled-row (create$ ?scaled-row ?new-value)))
               
               (replace$ ?matrix ?k ?k ?scaled-row)
            )
         )
      )
   )

   (foreach ?row ?matrix do
      (bind ?result "")
      (loop-for-count (?i 1 (+ 1 (length$ ?row))) do
         (bind ?element (nth$ ?i ?row))
         (if (neq ?i 1) then (bind ?result (str-cat ?result " "))) 
         (bind ?result (str-cat ?result ?element)) 
      )
      (printout ?output ?result crlf)
   )

   (close ?input) 
   (close ?output) 
)

And this is the error:

`CLIPS\> (solve-system "file1" "file3")
\[ROUTER1\] Logical name 'TRUE' was not recognized by any routers.
\[PRCCODE4\] Execution halted during the actions of deffunction 'solve-system'.
FALSE`

How can I fix this?

I tried to not bind files but I don't know how to fix that. Also I thought that the problem may be in the names of files but it wasn't.


Solution

  • Per the Basic Programming Guide, the syntax for the open function is

    (open <file-name> <logical-name> [<mode>])
    

    and the syntax for the readline function is

    (readline [<logical-name>])
    

    In your code, you are calling open like this:

    (bind ?input (open ?input-filename "r"))
    

    What you think is the <mode> argument is actually the <logical-name> argument and the <mode> argument is left unspecified. If the file exists, then it will be opened and associated with the logical name "r". The return value of the open call will be TRUE and assigned to the variable ?input.

    In your code, you call the readline function like this:

    (readline ?input)
    

    The variable ?input is set to TRUE which is passed as the logical name to readline which is what's causing the error message because that name is not associated with an open file. If you had passed "r" instead, the call would have worked.

    What you need to do is specify a logical name in your open call:

    (bind ?input (open ?input-filename in "r"))
    

    Then use that same name in your readline call:

    (readline in)