Можем ли мы считать факты с одинаковыми значениями в Джесс? - PullRequest
0 голосов
/ 12 февраля 2012

Используя Джесса в качестве движка правил, мы можем утверждать, что какой-то свидетель видел человека в каком-то месте и со временем:

(deffacts witnesses
    (witness Batman Gotham 18)
    (witness Hulk NYC 19)
    (witness Batman Gotham 2)
    (witness Superman Chicago 22)
    (witness Batman Gotham 10)
)

С правилом я хочу знать, видели ли несколько свидетелей одного и того же человека в одном и том же месте, не считая времени.

В документации Jess мы получили этот пример для подсчета сотрудников, создающих библиотеки по 100 КБ и более:

(defrule count-highly-paid-employees
    ?c <- (accumulate (bind ?count 0)                        ;; initializer
    (bind ?count (+ ?count 1))                    ;; action
    ?count                                        ;; result
    (employee (salary ?s&:(> ?s 100000)))) ;; CE
    =>
    (printout t ?c " employees make more than $100000/year." crlf))

Итак, я основал свой код на предыдущем примере:

(defrule count-witnesses
    (is-lost ?plost)
    (witness ?pseen ?place ?time)
    ?c <- (accumulate (bind ?count 0)
    (bind ?count (+ ?count 1))
    ?count
    (test ())  ; conditional element of accumulate
    (test (= ?plost ?pseen))
    (test (>= ?count 3))
    =>
    (assert (place-seen ?place))
)

С помощью приведенной выше инструкции '(deffacts)' и правила двигатель должен подтвердить факт

(place-seen Gotham)

потому что мы видели Бэтмена три раза в Готэме.

Я понятия не имею, как использовать условную часть (CE) в части «накопить». Могу ли я использовать «тест», чтобы сохранить факты с одним и тем же человеком и местом?

Есть идеи, как этого добиться?

Спасибо!


Примечание: синтакс "накапливать" равен

(accumulate <initializer> <action> <result> <conditional element>)

1 Ответ

1 голос
/ 12 февраля 2012

Я собираюсь пропустить материал о ?plost, поскольку вы точно не объясните, что это такое;Вы можете добавить это обратно в себя, если вам нужно.

Основное правило, которое (почти) делает то, что вы хотите, заключается в следующем.Часть СЕ, которую вы не получили, - это просто образец, который мы хотим накопить;здесь он сопоставляет факты с тем же человеком, свидетелем которого является то же место, что и факт, сопоставленный с первым человеком:

(defrule count-witnesses
  ;; Given that some person ?person was seen in place ?place
  (witness ?person ?place ?)  
  ;; Count all the sightings of that person in that place  
  ?c <- (accumulate (bind ?count 0)
                    (bind ?count (+ ?count 1))
                    ?count
                    (witness ?person ?place ?))
  ;; Don't fire unless the count is at least 3
  (test (>= ?c 3))
  =>
  (assert (place-seen ?person ?place))
)

Теперь единственная проблема с этим правилом состоит в том, что оно срабатывает три разаdeffacts, один раз за каждый факт Бэтмена / Готэма.Мы можем остановить это, изменив первый шаблон, чтобы он соответствовал только самому раннему обнаружению человека в данном месте:

(defrule count-witnesses
  ;; Given that some person ?person was seen in place ?place, and there is no other 
  ;; sighting of the same person at the same place at an earlier time
  (witness ?person ?place ?t1)    
  (not (witness ?person ?place ?t2&:(< ?t2 ?t1)))
  ;; Count all the sightings of that person in that place  
  ?c <- (accumulate (bind ?count 0)
                    (bind ?count (+ ?count 1))
                    ?count
                    (witness ?person ?place ?))
  ;; Don't fire unless the count is at least 3
  (test (>= ?c 3))
  =>
  (assert (place-seen ?person ?place))
)
...