3

我有一个序言程序。但现在我对prolog不是很熟悉。所以从这里寻求帮助。

下面的 Prolog 程序确定了汽车保险的保险费。保险费取决于车辆的马力和驾驶员的年龄。

calculateCarInsurance(PS,Insurance) :-
   PS < 60 , Insurance = 100.
calculateCarInsurance(PS,Insurance) :-
   PS >= 60 , PS < 100 , Insurance = 200.
calculateCarInsurance(PS,Insurance) :-
   PS >= 100 , Insurance = 300.
isInRiskyGroup(Age) :- Age < 25.
calculateCarInsurance(PS,Age,_) :- Age < 18 , fail.
calculateCarInsurance(PS,Age,Insurance) :-
   Age >= 18 , isInRiskyGroup(Age) ,
   calculateCarInsurance(PS,I2) ,
   Insurance is I2 * 2.
calculateCarInsurance(PS,Age,Insurance) :-
   not(isInRiskyGroup(Age)) ,
   calculateCarInsurance(PS,Insurance).

现在需要 a) 使用 Green Cuts 优化程序。b) 通过删除不需要的谓词,将 Green Cuts 更改为 Red Cuts。程序的行为应该是相同的。

我已经了解序言程序,但可以通过绿色切割进行优化。谢谢,谁能详细解释a,b。谢谢

4

1 回答 1

5

让我们从基础开始。cut 运算符是!并且总是成功的。切口不能回溯过去——它就像一扇单向门。另一种看待它的方式是,它让您致力于您迄今为止所做的决定。

剪辑的用法分为几类。根据定义,绿色剪辑是完全不改变程序运行时语义的剪辑。绿切只是程序员告诉 Prolog 你已经知道你没有解决方案的一种方式。如果 Prolog 不知道没有更多的解决方案,它会询问您是否需要另一个解决方案,然后每次都失败。例如,看看这个实现min/3

min1(X, Y, X) :- X < Y.
min1(X, Y, Y) :- Y <= X.

?- min1(3, 4, X).
X = 3 ;
false.

看看 Prolog 是如何问我是否需要另一个解决方案,然后失败了?这证明堆栈上有一个额外的选择点。我们可以通过削减来消除它:

min2(X, Y, X) :- X < Y, !.
min2(X, Y, Y) :- Y =< X.

现在,当我们询问 Prolog 时,min2/3我们只会得到一个答案:

?- min2(3, 4, X).
X = 3.

看,没有提示,只有一个解决方案。

现在,与红色切割相比,绿色切割的原因在于行为或推理没有真正的变化。只是 Prolog 无法知道这一点X < Y并且Y =< X是相互排斥的——绿色切割是我们告诉 Prolog 的方式,一旦你确定 X 小于 Y,检查 Y 是否小于 X 就没有意义了。这会从堆栈中删除选择点,以获得技术性。这有时是一个重要的优化,因为 Prolog 花费大量时间回溯,而花费在尝试不可能的情况上的时间被浪费了。

红色切割是一种有些不同的动物。红色切割是任何确实以超逻辑方式改变行为的切割。为了向您展示红色切割的示例,您可以尝试完全消除第二个测试min/3

min3(X, Y, X) :- X < Y, !.
min3(_, Y, Y).

你可能会这样想,“当我们到达第二个子句时,我们知道 X 不小于 Y,所以没有必要检查 Y 是否小于或等于 X。” 乍一看这似乎是合理的,您会发现它似乎具有与 相同的行为min2/3,知道有一个像以前一样的解决方案:

?- min3(3, 4, X).
X = 3.

?- min3(4, 3, X).
X = 3.

然而,因为我们已经消除了一些逻辑,所以我们向涉及回溯的细微错误敞开了大门。将min/3其视为三个实体之间的关系,我们可以用来min3/3制造虚假信息:min1/3min2/3

?- min1(3, 100, 100).
false.

?- min2(3, 100, 100).
false.

?- min3(3, 100, 100).
true.

100 不是 3 和 100 中的最小值,但min3/3如果第三个不是变量,则可以肯定具有相同第二个两个值的任何内容。换句话说,我们在使用红色剪辑时min3/3假设我们永远不会在第三个位置出现值。我们假设我们将使用第三个参数作为“out”参数。

让我们利用这些知识来看看你的家庭作业。我首先想到的是,前两条规则中存在同样的重叠条件逻辑:

calculateCarInsurance(PS,Insurance) :-
   PS < 60, ...
calculateCarInsurance(PS,Insurance) :-
   PS >= 60, ...

最起码,我们可以在PS < 60commit之后加上一个绿切:如果PS小于60,那真的不可能也超过60,所以那里的绿切是绝对无害的。

我会提醒人们永远不想添加红色削减。当您需要使用 Prolog 的推理使其按您想要的方式工作时,它们有时是必要的。在这种情况下,您可能会注意到calculateCarInsurance可能会返回多个解决方案。你可能不想要这种行为,你可能想要承诺你得到的第一个行为。在这种情况下,您可以在所有规则主体的末尾添加一个切口calculateCarInsurance。然后,无论 Prolog 能找到多少解决方案,您都会得到一个解决方案。这会改变程序的逻辑行为,但根据您的要求可能是可取的。这也可能产生同样的负面影响min3/3,如果我们想验证保险结果,calculateCarInsurance可能会确认它永远不会产生的计算。

我希望这足以让你走上正轨。

于 2013-01-18T04:30:37.050 回答