我有一个prolog程序,用于表示两个州之间的航班及其费用。
我的程序是这样的:
flight(newyork,washington,7). %its mean that there is a flight between both washington and newyork, newyork and washington with cost 7.
flight(lasvegas,losangeles,4).
flight(california,arizona,8).
route(A,B,C):-
flight(A,B,C);flight(B,A,C). %there is a route if there is a flight between A and B with cost C `OR` B and A with cost C.
现在,当我编写这样的查询时:
?-route(washington,newyork,7).
它给了我true
。该查询对我有用。
但是当我编写此查询时:
?-route(newyork,washington,7).
它true
和false
之后给了我。但是我不想要这个。我只想要true
,为什么它在false
之后给出true
?为什么给出两个输出?
答案 0 :(得分:2)
您对route/2
谓词的定义不是确定性的。如果左目标分离成功,则右目标也可能成功。即析取表示一个选择点:
?- route(newyork,washington,7).
true ;
false.
当您键入;
时,您正在向Prolog寻求替代解决方案。 Prolog引擎回溯到选择点并尝试正确的目标。由于此目标失败,Prolog顶层会打印false
,以告知您找不到替代解决方案。
答案 1 :(得分:1)
它给我
true
和false
之后的所有内容。但我不要这个。我只需要true
,为什么它在false
之后给出true
?为什么给出两个输出?
因为Prolog具有内置的回溯功能。提出第一个解决方案后,它将报告该解决方案,但随后它将回溯以寻找另一个解决方案。
根据确切的查询,Prolog可以事先知道没有回溯选项。 Prolog评估自顶向下的谓词的事实/条款,因此这意味着,例如,如果谓词在最后一个子句中成功(并且没有递归调用),则它肯定知道它已穷举搜索所有选项。
您在这里写:
route(A, B, C):-
flight(A, B, C);
flight(B, A, C).
因此,这意味着如果您呼叫route(newyork, washington, 7).
,它将首先呼叫flight(newyork, washington, 7)
。此操作成功(甚至是第一个flight/3
事实),但是仍然有一些方法可以解决成功:也许还有另一个flight(newyork, washington, 7)
的事实,所以这可能给true
带来第二次机会。
然而,大多数Prolog系统都具有高级查找策略,以确保这是唯一以flight/3
作为第一个参数的newyork
事实,因此现代Prolog系统通常会事先知道没有希望找到另一个flight/3
事实,但这并不意味着我们完成了。
您在route/3
子句flight(B, A, C)
的主体中定义了内容,因此Prolog将开始搜索flight/3
,但位置会交换。因此,它将在报告第一个解决方案后继续查询,并调用flight(washington, newyork, 7)
以希望找到另一个解决方案。
如果查询使用变量,这将非常有用,因为在建议的解决方案中,分配给变量的值可能(通常是)不同,因此可以使用作为搜索工具。
您可以使用once/1 [swi-doc]元谓词来评估一次呼叫。在那种情况下,谓词要么成功(并统一变量),要么不成功(并失败)。此外,该谓词当然仍然有可能引发错误或陷入无限循环。