Prolog输出为真后为假

时间:2018-12-23 07:59:55

标签: prolog prolog-toplevel

我有一个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).

truefalse之后给了我。但是我不想要这个。我只想要true,为什么它在false之后给出true?为什么给出两个输出?

2 个答案:

答案 0 :(得分:2)

您对route/2谓词的定义不是确定性的。如果左目标分离成功,则右目标也可能成功。即析取表示一个选择点:

?- route(newyork,washington,7).
true ;
false.

当您键入;时,您正在向Prolog寻求替代解决方案。 Prolog引擎回溯到选择点并尝试正确的目标。由于此目标失败,Prolog顶层会打印false,以告知您找不到替代解决方案。

答案 1 :(得分:1)

  

它给我truefalse之后的所有内容。但我不要这个。我只需要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]元谓词来评估一次呼叫。在那种情况下,谓词要么成功(并统一变量),要么不成功(并失败)。此外,该谓词当然仍然有可能引发错误或陷入无限循环。