【问题标题】:Prolog, Why does my predicate print the output of `write()` multiple times?Prolog,为什么我的谓词多次打印`write()`的输出?
【发布时间】:2013-11-08 00:24:09
【问题描述】:

我很难理解我的谓词 fly(....) 正在输出什么。当我查阅此文件并询问控制台(SWI-Prolog)flight(city1, city2, A, B) 时,它会打印出A=9 B=10。我认为这是 A 和 B 的单一值。所以我想用输出来完成我想要完成的事情;飞行计划员。但似乎当我在谓词中使用相同的问题 (flight(city1, city2, A, B)) 时,它会返回一个列表。直到我尝试写 S 和/或 E 时我才意识到这一点。我在下面的代码中打印[1,2,3],因为我很困惑为什么当我只写S,而不是后面的任何内容时,输出只是列表中的每个值,而不是逗号或空格分隔。所以我决定看看它如何写一个明确定义的列表[1,2,3] 并打印出来。

我收到的输出

8 ?- fly(city1, city4, 0, 24).
   14[1,2,3]9[1,2,3]
   false.

write(S), write([1,2,3]), 似乎被调用了两次,这是为什么呢?

另外,为什么我在控制台中获得了 AB 的单个值,但在调用它时却没有在我的谓词中?

代码逐字:

% I have no idea what I'm doing.
% Author: Skeeter

% Total of 5 cities
city(city1).
city(city2).
city(city3).
city(city4).
city(city5).

% List of flights
% flight( StartCity, EndCity, DepartureTime, ArrivalTime)
% city1 departures
flight( city1, city2, 09, 10).
flight( city1, city2, 10, 11).
flight( city1, city3, 12, 13).
flight( city1, city4, 14, 15).
flight( city1, city5, 16, 17).
% city2 departures
flight( city2, city1, 09, 10).
flight( city2, city1, 10, 11).
flight( city2, city3, 12, 13).
flight( city2, city4, 14, 15).
flight( city2, city5, 16, 17).
% city3 departures
flight( city3, city1, 09, 10).
flight( city3, city2, 10, 11).
flight( city3, city2, 12, 13).
flight( city3, city4, 14, 15).
flight( city3, city5, 16, 17).
% city4 departures
flight( city4, city1, 09, 10).
flight( city4, city2, 10, 11).
flight( city4, city3, 12, 13).
flight( city4, city3, 14, 15).
flight( city4, city5, 16, 17).
% city5 departures
flight( city5, city1, 09, 10).
flight( city5, city2, 10, 11).
flight( city5, city3, 12, 13).
flight( city5, city4, 14, 15).
flight( city5, city4, 16, 17).

% city1 arrivals
flight( city2, city1, 09, 10).
flight( city2, city1, 10, 11).
flight( city3, city1, 12, 13).
flight( city4, city1, 14, 15).
flight( city5, city1, 16, 17).
% city2 arrivals
flight( city1, city2, 09, 10).
flight( city1, city2, 10, 11).
flight( city3, city2, 12, 13).
flight( city4, city2, 14, 15).
flight( city5, city2, 16, 17).
% city3 arrivals
flight( city1, city3, 09, 10).
flight( city2, city3, 10, 11).
flight( city2, city3, 12, 13).
flight( city4, city3, 14, 15).
flight( city5, city3, 16, 17).
% city4 arrivals
flight( city1, city4, 09, 10).
flight( city2, city4, 10, 11).
flight( city3, city4, 12, 13).
flight( city3, city4, 14, 15).
flight( city5, city4, 16, 17).
% city5 arrivals
flight( city1, city5, 09, 10).
flight( city2, city5, 10, 11).
flight( city3, city5, 12, 13).
flight( city4, city5, 14, 15).
flight( city4, city5, 16, 17).

% is H1 later than X?
isLater(H1, [X|Y]) :-
H1 > X.


fly(CityFrom, CityTo, StartTime, EndTime) :-
flight(CityFrom, CityTo, S, E),
write(S), write([1,2,3]),
isLater(StartTime, S),
isLater(EndTime, E).

【问题讨论】:

  • 为什么isLater 的第二个参数是一个列表?
  • 有一次我认为 S 是一个列表,但我没有意识到 prolog 在执行时会回溯。
  • 如果传递的不是列表,则会出现不匹配、失败和回溯。在这种情况下,您只有一个 isLater 子句,因此它只是失败了(没有什么可回溯的)。您可以通过为每个案例添加子句来允许列表和非列表案例。

标签: prolog


【解决方案1】:

fly(city1, city2, A, B) 内部的程序流程是这样的:

  • 致电flight(city1, city2, S, E)。这会返回 S=9E=10
  • 致电write(9)
  • 致电isLater(A, 9)。这个失败了,因为9不能和[X|Y]统一,触发回溯。
  • 回溯到flight(city1, city2, S, E)。这次它返回S=10E=11
  • 致电write(10)
  • 同样,isLater(A, 10) 失败。它不能再回溯了,因为它已经尝试了flight(city1, city2, _, _) 的所有替代方案,所以在这一点上,fly 失败了。

基本上,问题在于您在确定它是有效解决方案之前就编写了S,因此您最终也会打印出一堆非解决方案。你可能想在你的isLater 检查之后移动它。 (这里更大的问题是 isLater 期待一个列表,但你给它一个整数......)

请注意,在控制台中输入 flight(city1, city2, A, B). 也会返回多个值 - 在显示第一个解决方案后,只需按“;” (而不是回车键)来询问下一个。

【讨论】:

  • 是的,我没有意识到我必须点击(在我的案例空间中)“;”从控制台获得更多输出。当我弄清楚这一点时,它变得更有意义了。也感谢您的回复,它为我清除了它。
猜你喜欢
  • 2018-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多