使用 Jess 解决过河难题
Solving river crossing puzzle using Jess
起初我解决了一个无限循环的问题,我通过向我的 CONSTRAIN 模块添加一个规则来解决这个问题。
我已经考虑了所有限制因素,但似乎由于某种原因所有事实都被删除了......
到目前为止这是我的代码:
;;MAIN Module
(deftemplate state
(slot farmer-position)
(slot fox-position)
(slot goat-position)
(slot cabbage-position)
(slot id)
(slot prev-state (default nil))
(multislot move (default nil)))
(deftemplate finished
(slot value))
(deffacts initial-facts
(state (farmer-position s1)
(fox-position s1)
(goat-position s1)
(cabbage-position s1)
(id 0))
(opp s1 s2)
(opp s2 s1))
;;CONSTARIN Modle
(defmodule CONSTRAIN)
(defrule CONSTRAIN::fox-goat
(declare (auto-focus true))
?p<-(MAIN::state (fox-position ?f) (goat-position ?f) (farmer-position
~?f))
=>
(retract ?p))
(defrule CONSTRAIN::goat-cabbge
(declare (auto-focus true))
?p<-(MAIN::state (goat-position ?f) (cabbage-position ?f) (farmer-
position ~?f))
=>
(retract ?p))
(defrule CONSTRAIN::no-doubles
(declare (auto-focus true))
?p1<-(MAIN::state (farmer-position ?s1) (fox-position ?s2) (goat-
position ?s3) (cabbage-position ?s4) (id ?id1))
?p2<-(MAIN::state (farmer-position ?s1) (fox-position ?s2) (goat-
position ?s3) (cabbage-position ?s4) (id ?id2&:(> ?id2 ?id1)))
=>
(retract ?p2))
(defrule CONSTRAIN::stop-exc
(declare (auto-focus true))
?p1<-(MAIN::state (farmer-position s2) (fox-position s2) (goat-position
s2) (cabbage-position s2))
=>
(assert (MAIN::finished (value yes))))
;;MOVE Module
(defmodule MOVE)
(defrule MOVE::move-fox
?p<-(MAIN::state (farmer-position ?old) (fox-position ?old) (id ?id))
(not (MAIN::finished (value yes)))
(opp ?old ?new)
=>
(duplicate ?p (farmer-position ?new)
(fox-position ?new)
(prev-state ?p)
(id (+ ?id 1))
(move fox ?new)))
(defrule MOVE::move-goat
?p<-(MAIN::state (farmer-position ?old) (goat-position ?old) (id ?id))
(not (MAIN::finished (value yes)))
(opp ?old ?new)
=>
(duplicate ?p (farmer-position ?new)
(goat-position ?new)
(prev-state ?p)
(id (+ ?id 1))
(move goat ?new)))
(defrule MOVE::move-cabbage
?p<-(MAIN::state (farmer-position ?old) (cabbage-position ?old) (id ?
id))
(not (MAIN::finished (value yes)))
(opp ?old ?new)
=>
(duplicate ?p (farmer-position ?new)
(cabbage-position ?new)
(prev-state ?p)
(id (+ ?id 1))
(move cabbage ?new)))
;;RUN
(reset)
(watch all)
(focus MOVE)
(run)
(facts)
这是我的输出:
<== Focus MAIN
==> Focus MOVE
FIRE 1 MOVE::move-fox f-1,, f-2
==> f-4 (MAIN::state (farmer-position s2) (fox-position s2) (goat-position
s1) (cabbage-position s1) (id 1) (prev-state <Fact-1>) (move fox s2))
==> Activation: CONSTRAIN::goat-cabbge : f-4
==> Activation: MOVE::move-fox : f-4,, f-3
<== Focus MOVE
==> Focus CONSTRAIN
FIRE 2 CONSTRAIN::goat-cabbge f-4
<== f-4 (MAIN::state (farmer-position s2) (fox-position s2) (goat-position
s1) (cabbage-position s1) (id 1) (prev-state <Fact-1>) (move fox s2))
<== Activation: MOVE::move-fox : f-4,, f-3
<== Focus CONSTRAIN
==> Focus MOVE
FIRE 3 MOVE::move-cabbage f-1,, f-2
==> f-5 (MAIN::state (farmer-position s2) (fox-position s1) (goat-position
s1) (cabbage-position s2) (id 1) (prev-state <Fact-1>) (move cabbage s2))
==> Activation: CONSTRAIN::fox-goat : f-5
==> Activation: MOVE::move-cabbage : f-5,, f-3
<== Focus MOVE
==> Focus CONSTRAIN
FIRE 4 CONSTRAIN::fox-goat f-5
<== f-5 (MAIN::state (farmer-position s2) (fox-position s1) (goat-position
s1) (cabbage-position s2) (id 1) (prev-state <Fact-1>) (move cabbage s2))
<== Activation: MOVE::move-cabbage : f-5,, f-3
<== Focus CONSTRAIN
==> Focus MOVE
FIRE 5 MOVE::move-goat f-1,, f-2
==> f-6 (MAIN::state (farmer-position s2) (fox-position s1) (goat-position
s2) (cabbage-position s1) (id 1) (prev-state <Fact-1>) (move goat s2))
==> Activation: MOVE::move-goat : f-6,, f-3
FIRE 6 MOVE::move-goat f-6,, f-3
==> f-7 (MAIN::state (farmer-position s1) (fox-position s1) (goat-position
s1) (cabbage-position s1) (id 2) (prev-state <Fact-6>) (move goat s1))
==> Activation: CONSTRAIN::no-doubles : f-1, f-7
==> Activation: MOVE::move-fox : f-7,, f-2
==> Activation: MOVE::move-goat : f-7,, f-2
==> Activation: MOVE::move-cabbage : f-7,, f-2
<== Focus MOVE
==> Focus CONSTRAIN
FIRE 7 CONSTRAIN::no-doubles f-1, f-7
<== f-7 (MAIN::state (farmer-position s1) (fox-position s1) (goat-position
s1) (cabbage-position s1) (id 2) (prev-state <Fact-6>) (move goat s1))
<== Activation: MOVE::move-fox : f-7,, f-2
<== Activation: MOVE::move-goat : f-7,, f-2
<== Activation: MOVE::move-cabbage : f-7,, f-2
<== Focus CONSTRAIN
==> Focus MOVE
<== Focus MOVE
==> Focus MAIN
<== Focus MAIN
For a total of 0 facts in module MOVE.
事实 f-6 没有被收回。唯一有效的第一步是农夫带着山羊过河,这就是 f-6 代表的移动。你没有让农民单独过河的规则,所以对于 f-6 的农民来说,唯一有效的举动是带着山羊回到河对岸,这会让你回到初始位置。由于f-1所代表的初始位置与f-7相同,规则no-doubles收回f-7并且没有剩余的有效移动。
如果您从 http://www.jessrules.com/jess/download.shtml 下载 Jess,过河示例的代码可以在文件 dilemma.clp.
的示例目录中找到
起初我解决了一个无限循环的问题,我通过向我的 CONSTRAIN 模块添加一个规则来解决这个问题。 我已经考虑了所有限制因素,但似乎由于某种原因所有事实都被删除了...... 到目前为止这是我的代码:
;;MAIN Module
(deftemplate state
(slot farmer-position)
(slot fox-position)
(slot goat-position)
(slot cabbage-position)
(slot id)
(slot prev-state (default nil))
(multislot move (default nil)))
(deftemplate finished
(slot value))
(deffacts initial-facts
(state (farmer-position s1)
(fox-position s1)
(goat-position s1)
(cabbage-position s1)
(id 0))
(opp s1 s2)
(opp s2 s1))
;;CONSTARIN Modle
(defmodule CONSTRAIN)
(defrule CONSTRAIN::fox-goat
(declare (auto-focus true))
?p<-(MAIN::state (fox-position ?f) (goat-position ?f) (farmer-position
~?f))
=>
(retract ?p))
(defrule CONSTRAIN::goat-cabbge
(declare (auto-focus true))
?p<-(MAIN::state (goat-position ?f) (cabbage-position ?f) (farmer-
position ~?f))
=>
(retract ?p))
(defrule CONSTRAIN::no-doubles
(declare (auto-focus true))
?p1<-(MAIN::state (farmer-position ?s1) (fox-position ?s2) (goat-
position ?s3) (cabbage-position ?s4) (id ?id1))
?p2<-(MAIN::state (farmer-position ?s1) (fox-position ?s2) (goat-
position ?s3) (cabbage-position ?s4) (id ?id2&:(> ?id2 ?id1)))
=>
(retract ?p2))
(defrule CONSTRAIN::stop-exc
(declare (auto-focus true))
?p1<-(MAIN::state (farmer-position s2) (fox-position s2) (goat-position
s2) (cabbage-position s2))
=>
(assert (MAIN::finished (value yes))))
;;MOVE Module
(defmodule MOVE)
(defrule MOVE::move-fox
?p<-(MAIN::state (farmer-position ?old) (fox-position ?old) (id ?id))
(not (MAIN::finished (value yes)))
(opp ?old ?new)
=>
(duplicate ?p (farmer-position ?new)
(fox-position ?new)
(prev-state ?p)
(id (+ ?id 1))
(move fox ?new)))
(defrule MOVE::move-goat
?p<-(MAIN::state (farmer-position ?old) (goat-position ?old) (id ?id))
(not (MAIN::finished (value yes)))
(opp ?old ?new)
=>
(duplicate ?p (farmer-position ?new)
(goat-position ?new)
(prev-state ?p)
(id (+ ?id 1))
(move goat ?new)))
(defrule MOVE::move-cabbage
?p<-(MAIN::state (farmer-position ?old) (cabbage-position ?old) (id ?
id))
(not (MAIN::finished (value yes)))
(opp ?old ?new)
=>
(duplicate ?p (farmer-position ?new)
(cabbage-position ?new)
(prev-state ?p)
(id (+ ?id 1))
(move cabbage ?new)))
;;RUN
(reset)
(watch all)
(focus MOVE)
(run)
(facts)
这是我的输出:
<== Focus MAIN
==> Focus MOVE
FIRE 1 MOVE::move-fox f-1,, f-2
==> f-4 (MAIN::state (farmer-position s2) (fox-position s2) (goat-position
s1) (cabbage-position s1) (id 1) (prev-state <Fact-1>) (move fox s2))
==> Activation: CONSTRAIN::goat-cabbge : f-4
==> Activation: MOVE::move-fox : f-4,, f-3
<== Focus MOVE
==> Focus CONSTRAIN
FIRE 2 CONSTRAIN::goat-cabbge f-4
<== f-4 (MAIN::state (farmer-position s2) (fox-position s2) (goat-position
s1) (cabbage-position s1) (id 1) (prev-state <Fact-1>) (move fox s2))
<== Activation: MOVE::move-fox : f-4,, f-3
<== Focus CONSTRAIN
==> Focus MOVE
FIRE 3 MOVE::move-cabbage f-1,, f-2
==> f-5 (MAIN::state (farmer-position s2) (fox-position s1) (goat-position
s1) (cabbage-position s2) (id 1) (prev-state <Fact-1>) (move cabbage s2))
==> Activation: CONSTRAIN::fox-goat : f-5
==> Activation: MOVE::move-cabbage : f-5,, f-3
<== Focus MOVE
==> Focus CONSTRAIN
FIRE 4 CONSTRAIN::fox-goat f-5
<== f-5 (MAIN::state (farmer-position s2) (fox-position s1) (goat-position
s1) (cabbage-position s2) (id 1) (prev-state <Fact-1>) (move cabbage s2))
<== Activation: MOVE::move-cabbage : f-5,, f-3
<== Focus CONSTRAIN
==> Focus MOVE
FIRE 5 MOVE::move-goat f-1,, f-2
==> f-6 (MAIN::state (farmer-position s2) (fox-position s1) (goat-position
s2) (cabbage-position s1) (id 1) (prev-state <Fact-1>) (move goat s2))
==> Activation: MOVE::move-goat : f-6,, f-3
FIRE 6 MOVE::move-goat f-6,, f-3
==> f-7 (MAIN::state (farmer-position s1) (fox-position s1) (goat-position
s1) (cabbage-position s1) (id 2) (prev-state <Fact-6>) (move goat s1))
==> Activation: CONSTRAIN::no-doubles : f-1, f-7
==> Activation: MOVE::move-fox : f-7,, f-2
==> Activation: MOVE::move-goat : f-7,, f-2
==> Activation: MOVE::move-cabbage : f-7,, f-2
<== Focus MOVE
==> Focus CONSTRAIN
FIRE 7 CONSTRAIN::no-doubles f-1, f-7
<== f-7 (MAIN::state (farmer-position s1) (fox-position s1) (goat-position
s1) (cabbage-position s1) (id 2) (prev-state <Fact-6>) (move goat s1))
<== Activation: MOVE::move-fox : f-7,, f-2
<== Activation: MOVE::move-goat : f-7,, f-2
<== Activation: MOVE::move-cabbage : f-7,, f-2
<== Focus CONSTRAIN
==> Focus MOVE
<== Focus MOVE
==> Focus MAIN
<== Focus MAIN
For a total of 0 facts in module MOVE.
事实 f-6 没有被收回。唯一有效的第一步是农夫带着山羊过河,这就是 f-6 代表的移动。你没有让农民单独过河的规则,所以对于 f-6 的农民来说,唯一有效的举动是带着山羊回到河对岸,这会让你回到初始位置。由于f-1所代表的初始位置与f-7相同,规则no-doubles收回f-7并且没有剩余的有效移动。
如果您从 http://www.jessrules.com/jess/download.shtml 下载 Jess,过河示例的代码可以在文件 dilemma.clp.
的示例目录中找到