如何在 CLIPS 中尝试所有可能的组合来对多槽字段中的整数求和

How to sum integer in multislot fields trying all the possibile combinations in CLIPS

我遇到这样的情况:

(deftemplate trip
   (multislot place-sequence)
   (multislot days-distribution)
)

(deftemplate travel-banchmark
    (slot name)
    (slot value)
)

(trip (place-sequence milano roma venezia) (days-distribution 1 1 1))
(trip (place-sequence roma milano venezia) (days-distribution 1 1 1))
(travel-banchmark (name travel-duration) (value 5))

现在对于每个旅行事实,我必须断言所有可能的旅行具有不同的天数分布(天数分布的总和需要是 travel-duration(例如 5))

示例:

(trip (place-sequence milano roma venezia) (days-distribution 3 1 1))
(trip (place-sequence milano roma venezia) (days-distribution 1 3 1))
(trip (place-sequence milano roma venezia) (days-distribution 1 1 3))
(trip (place-sequence milano roma venezia) (days-distribution 2 2 1))
(trip (place-sequence milano roma venezia) (days-distribution 1 1 2))
...

是否可以使用规则来做到这一点?我在理解使用基于规则的系统执行此类操作的最佳方法时遇到了一些问题

编辑: 这是我计算多槽内总和的方法,但我仍然无法弄清楚如何计算不同的天数分布

(defrule test
   (travel-banchmark (name travel-duration) (value ?duration))
   ?p <- (trip
       (days-distribution $?d))
       (test (<= (+ 0 (expand$ ?d)) ?duration))
   =>
   ...
)

好的,我找到了问题的答案:

CLIPS> 
(deftemplate trip
   (multislot place-sequence)
   (multislot days-distribution)
)
CLIPS> 
(deftemplate travel-banchmark
    (slot name)
    (slot value)
)
CLIPS> 
(deffacts initial
   (travel-banchmark (name travel-duration) (value 5))
   (trip (place-sequence milano roma venezia) (days-distribution 1 1 1))
)
CLIPS> 
(defrule test
    (travel-banchmark (name travel-duration) (value ?duration))

    ?p <- (trip
    (place-sequence $?cities)
    (days-distribution $?days-distribution))

    (test (< (+ 0 (expand$ ?days-distribution)) ?duration))

    =>

    (retract ?p)

    (loop-for-count (?cnt1 1 (length$ ?days-distribution)) do
        (bind ?new-days-distribution (replace$ ?days-distribution ?cnt1 ?cnt1 (+ (nth$ ?cnt1 ?days-distribution) 1)))

        (assert (trip 
            (place-sequence ?cities)
            (days-distribution ?new-days-distribution))
        )

    )

)
CLIPS>
(defrule clean
    (declare (salience -5))

    ?p <- (trip
    (place-sequence $?cities)
    (days-distribution $?days-distribution))

    ?p2 <- (trip
    (place-sequence $?cities)
    (days-distribution $?days-distribution))

    (test (neq ?p ?p2))
    =>

    (retract ?p)

)
CLIPS> (reset)
CLIPS> (run)
CLIPS> (facts)
f-0     (initial-fact)
f-1     (travel-banchmark (name travel-duration) (value 5))
f-6     (trip (place-sequence milano roma venezia) (days-distribution 2 1 2))
f-7     (trip (place-sequence milano roma venezia) (days-distribution 1 2 2))
f-8     (trip (place-sequence milano roma venezia) (days-distribution 1 1 3))
f-9     (trip (place-sequence milano roma venezia) (days-distribution 2 2 1))
f-10    (trip (place-sequence milano roma venezia) (days-distribution 1 3 1))
f-12    (trip (place-sequence milano roma venezia) (days-distribution 3 1 1))
For a total of 8 facts.
CLIPS> 

您不必使用规则来做所有事情,尤其是在有明显的算法解决方案的情况下。例如,这样做没有意义:

(defrule hello
   ?f <- (count ?c&:(> ?c 0))
   =>
   (printout t "Hello" crlf)
   (retract ?f)
   (assert (count (- ?c 1))))

何时可以做到:

(deffunction hello (?count)
   (loop-for-count ?count (printout t "Hello" crlf)))

使用递归函数调用生成分布非常简单,可以通过触发单个规则来实现,而无需逐步构建解决方案,然后删除中间步骤。

         CLIPS (6.31 6/12/19)
CLIPS> 
(deftemplate trip
   (multislot place-sequence)
   (multislot days-distribution))
CLIPS> 
(deftemplate travel-banchmark
    (slot name)
    (slot value))
CLIPS> 
(deffacts initial
   (travel-banchmark (name travel-duration) (value 5))
   (trip (place-sequence milano roma venezia) (days-distribution)))
CLIPS> 
(deffunction create-distributions (?cc ?cities ?days ?duration $?distribution)
   (bind ?max-alloc (- ?duration ?days (- ?cc 1)))   
   (if (= ?cc 1)
      then
      (assert (trip (place-sequence ?cities) (days-distribution ?distribution ?max-alloc)))
      (return))
   (loop-for-count (?a ?max-alloc)
      (create-distributions (- ?cc 1) ?cities (+ ?days ?a) ?duration ?distribution ?a)))
CLIPS> 
(defrule test
    (travel-banchmark (name travel-duration) (value ?duration))
    ?p <- (trip (place-sequence $?cities) (days-distribution))
    =>
    (bind ?city-count (length$ ?cities))
    (create-distributions ?city-count ?cities 0 ?duration)
    (retract ?p))
CLIPS> (reset)
CLIPS> (run)
CLIPS> (facts)
f-0     (initial-fact)
f-1     (travel-banchmark (name travel-duration) (value 5))
f-3     (trip (place-sequence milano roma venezia) (days-distribution 1 1 3))
f-4     (trip (place-sequence milano roma venezia) (days-distribution 1 2 2))
f-5     (trip (place-sequence milano roma venezia) (days-distribution 1 3 1))
f-6     (trip (place-sequence milano roma venezia) (days-distribution 2 1 2))
f-7     (trip (place-sequence milano roma venezia) (days-distribution 2 2 1))
f-8     (trip (place-sequence milano roma venezia) (days-distribution 3 1 1))
For a total of 8 facts.
CLIPS>