Prolog 如何使用切割操作符?

Prolog 如何使用切割操作符?,prolog,prolog-cut,Prolog,Prolog Cut,我一直在学习,我遇到了一个问题。我从教程中理解了切割运算符,但我正在尝试解决一个问题,但我无法理解解决方案 问题: 如果车的颜色是红色,是意大利制造的,那么它就是法拉利。如果它是红色的,但在德国(或任何其他国家制造,可能不止一个),那就是奔驰。如果它不是红色的,而且很大,那就是福特。如果不是红色的,也不是很大的,那就是丰田 即: red & Italy: Ferrari red & Germany (or not Italy): Benz not red & big: f

我一直在学习,我遇到了一个问题。我从教程中理解了切割运算符,但我正在尝试解决一个问题,但我无法理解解决方案

问题:

如果车的颜色是红色,是意大利制造的,那么它就是法拉利。如果它是红色的,但在德国(或任何其他国家制造,可能不止一个),那就是奔驰。如果它不是红色的,而且很大,那就是福特。如果不是红色的,也不是很大的,那就是丰田

即:

red & Italy: Ferrari
red & Germany (or not Italy): Benz
not red & big: ford
not red & not big: Toyota
给定特定汽车对象的一些事实:

color(cx, red).
speed(cx, 220).
make(cx, italy).
type(cx, sport).
我想编写一个谓词
brand(X,name)
,它将返回特定汽车对象的品牌,如:

brand(X, ferrari):-
   color(X,red), make(X,T), T=italy.
brand(X, benz) :-
   color(X,red), not(make(X,italy)).
brand(X, ford) :-
   not(color(X,red)), size(X,big).
brand(X, toyota) :-
   not(color(X,red)), not(size(X,big)).
问题是我如何(在哪里)在这里使用cut操作符,这样它就不会检查相同的属性(例如:这里“make”)两次了?我似乎无法对这件事保持清醒

如果我检查红色,然后检查品牌,如果品牌不是意大利,我如何为汽车对象“ck”的一组事实编写
品牌(X,品牌名称)
,这样它就不会再次检查品牌?对我来说,这似乎是不可能的。

简短的回答:

几乎总是使用
/0将导致有效解决方案的丢失

请始终记住,Prolog程序通常比其他语言的程序更通用。特别是,请记住,用户可以随时发布最一般的查询,在您的情况下是:

?- brand(X, Y).
如果您有
/0
在此定义中,则是,您可能会“只检查一次”,但另一方面,您将无法生成所有有效答案

一个好的解决方法是使用
if\u3
from。例如,在您的案例中,您可以将事实写为:

color(cx, red, true). speed(cx, 220, true). make(cx, italy, true). type(cx, sport, true). 颜色(cx、红色、真)。 速度(cx,220,真)。 使(cx,意大利,真实)。 类型(cx、sport、true)。 现在你可以写:

car_type(C, Type) :- if_(color(C,red), if_(make(C, italy), Type=ferrari, Type=bentz), if_(type(C, big), Type=ford, Type=toyota)). 车辆类型(C,类型):- 如果(颜色C,红色), 如果(制造(C,意大利),型号=法拉利,型号=本茨), 如果(C型,大型,福特型,丰田型))。 重要的是,即使存在多个解决方案,最通用的查询仍然有效:

?- car_type(C, Type). C = cx, Type = ferrari. ?车辆类型(C型)。 C=cx, 类型=法拉利。 简短的回答是:

几乎总是使用
/0将导致有效解决方案的丢失

请始终记住,Prolog程序通常比其他语言的程序更通用。特别是,请记住,用户可以随时发布最一般的查询,在您的情况下是:

?- brand(X, Y).
如果您有
/0
在此定义中,则是,您可能会“只检查一次”,但另一方面,您将无法生成所有有效答案

一个好的解决方法是使用
if\u3
from。例如,在您的案例中,您可以将事实写为:

color(cx, red, true). speed(cx, 220, true). make(cx, italy, true). type(cx, sport, true). 颜色(cx、红色、真)。 速度(cx,220,真)。 使(cx,意大利,真实)。 类型(cx、sport、true)。 现在你可以写:

car_type(C, Type) :- if_(color(C,red), if_(make(C, italy), Type=ferrari, Type=bentz), if_(type(C, big), Type=ford, Type=toyota)). 车辆类型(C,类型):- 如果(颜色C,红色), 如果(制造(C,意大利),型号=法拉利,型号=本茨), 如果(C型,大型,福特型,丰田型))。 重要的是,即使存在多个解决方案,最通用的查询仍然有效:

?- car_type(C, Type). C = cx, Type = ferrari. ?车辆类型(C型)。 C=cx, 类型=法拉利。
我认为
品牌(X,法拉利):-颜色(X,红色),!,make(X,T),T=意大利。
可以理解为“红色汽车成为法拉利的唯一方式是在意大利制造。”希望这对我不是prolog方面的专家有所帮助。请特别注意。我认为
品牌(X,法拉利):-颜色(X,红色),!,make(X,T),T=italy。
可以理解为“红色汽车成为法拉利的唯一途径是在意大利制造”。希望这能帮助我,我不是prolog方面的专家。请特别注意。感谢您的回答,但我正在尝试学习如何使用cut,在我的具体示例中,我无法改变事实,以包括“true”。假设我从一个文件中读到了一堆事实,没有像brand(X,Y)这样的一般查询。假设查询的形式总是brand(cx,name),其中cx是提供事实的对象。我希望谓词
brand(X,name)
返回
cx
的品牌名称,如奔驰、法拉利等。查询时使用
one次/1
提交第一个解决方案,但不要打乱整个程序:
?-one次(brand(cx,name)).
保持关系的通用性是一种很好的做法,这样可以在需要时向各个方向查询关系。我认为我们的观点并不一致。我正在学习切割(和否定)的主题。我想知道这段代码中cut的用法和副作用(陷阱)。我不想要完美的解决方案。请阅读本页右侧菜单中“链接”和“相关”中显示的现有答案和其他答案。使用
一次/1
可以解决眼前的问题。如果您还有任何问题,请提交一个新问题,我将在那里回答。特别是,如果您想更多地了解
可能存在的陷阱和副作用/0
,请提出一个关于他们的问题,因为您在本问题中没有提到这些问题。一般来说,
/0
不是解决问题的好方法。查看if-then-else,然后,理想情况下,将其概括为使用
if\u3
。您还需要定义
false
的情况!谢谢你的回答,但我正在努力学习如何使用cut,在我的具体示例中,我无法更改事实以包含“true”。假设我从一个文件中读到了一堆事实,没有像brand(X,Y)这样的一般查询。假设查询的形式总是brand(cx,name),其中cx是提供事实的对象。我希望谓词
brand(X,name)
返回
cx
的品牌名称,如奔驰、法拉利等。在查询时使用
one次/1
承诺第一个解决方案,但不要打乱整个程序:
?-one次(brand(cx,name))。
保留您之间关系的一般性是一个很好的做法,例如