Использование логики и в клипах - PullRequest
0 голосов
/ 17 января 2019

Я изменил некоторый код CLIPS / CLIPSpy, чтобы искать, когда в столбце Variable в CSV есть слово Oil Temp и когда продолжительность этого столбца превышает 600 или выше. Правило должно срабатывать дважды в соответствии с CSV, который я использую:
Sample Data

Я получаю следующую ошибку.
Error

Вот мой код в настоящее время. Я думаю, что это терпит неудачу на проверке переменной или логической и проверке.

import sys
from tempfile import mkstemp
import os
import clips


CLIPS_CONSTRUCTS = """
(defglobal ?*oil-too-hot-times* = 0)

(deftemplate oil-is-too-hot-too-long
  (slot Variable (type STRING))  
  (slot Duration (type INTEGER)))

(defrule check-for-hot-oil-too-long-warning
  (oil-is-too-hot-too-long (Variable ?variable) (Duration ?duration))
  (test (?variable Oil Temp))
  (and (>= ?duration 600))
  =>
  (printout t "Warning! Check engine light on!" tab ?*oil-too-hot-times* crlf)) 

"""


def main():
    environment = clips.Environment()

    # use environment.load() to load constructs from a file
    constructs_file, constructs_file_name = mkstemp()
    file = open(constructs_file, 'wb')
    file.write(CLIPS_CONSTRUCTS.encode())
    file.close()

    environment.load(constructs_file_name)
    os.remove(constructs_file_name)

    # enable fact duplication as data has duplicates
    environment.eval("(set-fact-duplication TRUE)")


    # Template facts can be built from their deftemplate
    oil_too_hot_too_long_template = environment.find_template("oil-is-too-hot-too-long")

    for variable, duration in get_data_frames(sys.argv[1]):
        new_fact = oil_too_hot_too_long_template.new_fact()

        # Template facts are represented as dictionaries
        new_fact["Variable"] = variable
        new_fact["Duration"] = int(duration)

        # Add the fact into the environment Knowledge Base
        new_fact.assertit()

    # Fire all the rules which got activated
    environment.run()

def get_data_frames(file_path):
    """Parse a CSV file returning the dataframes."""
    with open(file_path) as data_file:
        return [l.strip().split(",") for i, l in enumerate(data_file) if i > 1]


if __name__ == "__main__":
    main()

1 Ответ

0 голосов
/ 17 января 2019

CLIPS принимает польскую / префиксную нотацию. Поэтому ваше правило должно быть написано следующим образом.

(defrule check-for-hot-oil-too-long-warning
  (oil-is-too-hot-too-long (Variable ?variable) (Duration ?duration))
  (test (and (eq ?variable "Oil Temp") 
             (>= ?duration 600)))
  =>
  (printout t "Warning! Check engine light on!" tab ?*oil-too-hot-times* crlf)) 

Также обратите внимание, что для типа STRING требуются двойные кавычки ".

Тем не менее, я бы посоветовал вам использовать альфа-сетевое согласование движка, которое является более кратким и эффективным.

(defrule check-for-hot-oil-too-long-warning
  (oil-is-too-hot-too-long (Variable "Oil Temp") (Duration ?duration))
  (test (>= ?duration 600))
  =>
  (printout t "Warning! Check engine light on!" tab ?*oil-too-hot-times* crlf)) 

Движок сразу видит, что ваш слот Variable является константой, и может соответствующим образом оптимизировать логику сопоставления. Я не уверен, что он может сделать то же самое в рамках совместного испытания.

...