在序言中实现十字路口逻辑
implement crossroads logic in prolog
我想写一个程序,检查是否允许汽车 drive/turn 在十字路口。
汽车由颜色(例如蓝色、灰色、红色)标识,汽车的位置由罗盘方向(北、东、南、西)定义。
检查是否允许驾驶的功能是allow(Color).
(例如allow(blue).
)
这是我的实际代码:
% crossroads priority check
% define cars, positions, and directions
% carPosition(Color, Position, Direction).
% Case A
carPosition(blue, north, right).
carPosition(red, east, straight).
carPosition(grey, west, left).
% define right and straight neighbours
% neighbours(Position, RightNeighbour, StraightNeighbour).
neighbours(north, west, south).
neighbours(west, south, east).
neighbours(south, east, north).
neighbours(east, north, west).
% check if turn is allowed
allowed(Color) :-
% Check right turns
carPosition(Color, _, right);
% Check left turns
(carPosition(Color, Position, left),
neighbours(Position, RightNeighbour, StraightNeighbour),
aggregate_all(count, carPosition(_, StraightNeighbour, _), CountStraight),
aggregate_all(count, carPosition(_, RightNeighbour, _), CountRight),
(CountStraight + CountRight) < 1 );
% Check straight turns
(carPosition(Color, Position, straight),
neighbours(Position, RightNeighbour, _),
aggregate_all(count, carPosition(_, RightNeighbour, _), CountRight),
(CountRight < 1 )).
在此示例(案例 A)中,allow(red).
和 allow(grey).
的答案符合预期
false.
但是 allow(blue).
returns:
true;
false.
这个错误从何而来,如何避免?
您的评论几乎暗示了问题所在。如果一辆车可以右转、左转或直行,您可以定义它是允许的。
如果allow(red)
和allow(grey)
所有这些选项都被选中,它们都是错误的,因此立即打印错误。
在 allow(blue)
的情况下,首先检查第一个选项并将其评估为 true,并打印出来。但是,这次 Prolog 知道还有未检查的选项,等待您请求进一步计算。
Prolog 然后检查后两个选项,这两个选项的计算结果为 false,因为蓝色汽车既不想左转也不想直行。
由于 Prolog 无法知道每辆汽车只有一个方向愿望,它不能在第一个结果后中止计算,因为在其他情况下,需要额外的解决方案。
有两种简单的方法可以解决这个问题:
在每个选项后使用cut-goal (!)。请注意,这可能会改变语义(比较 link 中的红色与绿色切割)。在你的例子中,它是红色的,因为它改变了语义。
% Check right turns
carPosition(Color, _, right),!;
% Check left turns
(carPosition(Color, Position, left),!,…
之后,查询allowed(X).
最多会产生一个结果。这种行为很可能是不希望的。
在查询中使用 cut 运算符。这样做的好处是它不改变程序本身,它让谓词的用户决定是否请求多个答案。
allowed(blue),!.
PS:您的程序中似乎存在语法错误。我不得不删除第一个 allowed
目标中的括号。
我想写一个程序,检查是否允许汽车 drive/turn 在十字路口。
汽车由颜色(例如蓝色、灰色、红色)标识,汽车的位置由罗盘方向(北、东、南、西)定义。
检查是否允许驾驶的功能是allow(Color).
(例如allow(blue).
)
这是我的实际代码:
% crossroads priority check
% define cars, positions, and directions
% carPosition(Color, Position, Direction).
% Case A
carPosition(blue, north, right).
carPosition(red, east, straight).
carPosition(grey, west, left).
% define right and straight neighbours
% neighbours(Position, RightNeighbour, StraightNeighbour).
neighbours(north, west, south).
neighbours(west, south, east).
neighbours(south, east, north).
neighbours(east, north, west).
% check if turn is allowed
allowed(Color) :-
% Check right turns
carPosition(Color, _, right);
% Check left turns
(carPosition(Color, Position, left),
neighbours(Position, RightNeighbour, StraightNeighbour),
aggregate_all(count, carPosition(_, StraightNeighbour, _), CountStraight),
aggregate_all(count, carPosition(_, RightNeighbour, _), CountRight),
(CountStraight + CountRight) < 1 );
% Check straight turns
(carPosition(Color, Position, straight),
neighbours(Position, RightNeighbour, _),
aggregate_all(count, carPosition(_, RightNeighbour, _), CountRight),
(CountRight < 1 )).
在此示例(案例 A)中,allow(red).
和 allow(grey).
的答案符合预期
false.
但是 allow(blue).
returns:
true;
false.
这个错误从何而来,如何避免?
您的评论几乎暗示了问题所在。如果一辆车可以右转、左转或直行,您可以定义它是允许的。
如果allow(red)
和allow(grey)
所有这些选项都被选中,它们都是错误的,因此立即打印错误。
在 allow(blue)
的情况下,首先检查第一个选项并将其评估为 true,并打印出来。但是,这次 Prolog 知道还有未检查的选项,等待您请求进一步计算。
Prolog 然后检查后两个选项,这两个选项的计算结果为 false,因为蓝色汽车既不想左转也不想直行。
由于 Prolog 无法知道每辆汽车只有一个方向愿望,它不能在第一个结果后中止计算,因为在其他情况下,需要额外的解决方案。
有两种简单的方法可以解决这个问题:
在每个选项后使用cut-goal (!)。请注意,这可能会改变语义(比较 link 中的红色与绿色切割)。在你的例子中,它是红色的,因为它改变了语义。
% Check right turns carPosition(Color, _, right),!; % Check left turns (carPosition(Color, Position, left),!,…
之后,查询
allowed(X).
最多会产生一个结果。这种行为很可能是不希望的。在查询中使用 cut 运算符。这样做的好处是它不改变程序本身,它让谓词的用户决定是否请求多个答案。
allowed(blue),!.
PS:您的程序中似乎存在语法错误。我不得不删除第一个 allowed
目标中的括号。