我正在尝试实现一个元组/对的队列,以便与SWI-Prolog中的AI一起使用。目标是首先用数据填充结构,然后评估每个元素。每个唯一(X,Y)对应仅评估一次。
目前,问题是我的实现不是队列而是堆栈。函数dequeue也过早地评估为false。这是我正在使用的代码的简化部分。
:- dynamic([queue/1, destination/2]).
enqueue(X, Y):-
retract(queue(List)),
\+member((X, Y), List),
assert(queue([(X, Y)|List])).
enqueue(_,_).
dequeue:-
retract(queue([(X, Y)|List])),
retractall(destination(_, _)),
assert(queue(List)),
assert(destination(X, Y)).
.........................下面的实际代码................... ..........
add_to_list_of_dest(X, Y):-
retract(list_of_dest(Stuff)),
\+member((X, Y), Stuff),
assert(list_of_dest([(X, Y)|Stuff])),
format("List of Dest Added : (~d, ", X),
format("~d)~n", Y).
add_to_list_of_dest(X, Y):-
format("Duplicate Element Not Added : (~d, ", X),
format("~d)~n", Y).
choose_destination:-
current_pos(X, Y),
destination(DestX, DestY),
\+(X = DestX),
\+(Y = DestY),
format("Choosing Desination : Currently Travelling~n").
choose_destination:-
retract(list_of_dest([(X, Y)|Stuff])),
retractall(destination(_, _)),
assert(list_of_dest(Stuff)),
assert(destination(X, Y)),
format("Choosing Desination : (~d, ", X),
format("~d)~n", Y).
答案 0 :(得分:2)
@ChristianF的答案很好(+1),虽然附加到列表的末尾对于大队列来说会变得很麻烦。众所周知的替代方案使用两个堆栈。这样做会给你O(1)插入和摊销O(1)弹出。技巧是具有输入堆栈和输出堆栈。假设输出堆栈的顺序正确,只需返回顶部项目,当它为非空时弹出。如果为空,则取出输入堆栈并将其反转到输出堆栈。
% empty_queue(-Queue) is det.
empty_queue(queue([], [])).
% enqueue(+Item, +Queue, -NewQueue) is det.
enqueue(Item, queue(InStack, OutStack), queue([Item|InStack], OutStack)).
% dequeue(+Queue, -Item, -NewQueue) is det.
% Handle the case where the output stack is ready to be used.
dequeue(queue(InStack, [Top|OutStack]), Top, queue(InStack, OutStack)).
% Handle the case where the input and output stacks must be swapped.
dequeue(queue(InStack, []), Top, OutStack) :-
reverse(InStack, NewOutStack),
dequeue(queue([], NewOutStack), Top, OutStack).
您可以利用Prolog的非确定性来制作具有两种调用约定的单个谓词。这使其与append/3
:
% queue(+Item, +QueueWithoutItem, -QueueWithItem) is det.
queue(Item, QueueWithoutItem, QueueWithItem) :-
nonvar(Item), nonvar(QueueWithoutItem),
enqueue(Item, QueueWithoutItem, QueueWithItem).
% queue(-Item, -QueueWithoutItem, +QueueWithItem) is semidet.
queue(Item, QueueWithoutItem, QueueWithItem) :-
nonvar(QueueWithItem),
dequeue(QueueWithItem, Item, QueueWithoutItem).
答案 1 :(得分:1)
如果您知道列表,建立队列真的不难:
%% enqueue(+Queue, +Element, -NewQueue)
enqueue(L, E, L2) :- append(L, [E], L2).
%% dequeue(+Queue, -Element, -NewQueue)
dequeue([H|T], H, T).
使用示例:
?- enqueue([], (2,3), L), enqueue(L, (4,5), L2), dequeue(L2, _Ignore, L3).
L = [ (2, 3)],
L2 = [ (2, 3), (4, 5)],
_Ignore = (2, 3),
L3 = [ (4, 5)].
答案 2 :(得分:1)
您可以使用difference_list,它附加在O(1)中:
init_queue(U-U).
en_queue(Q, Elem, New_Q) :-
append_dl(Q, [Elem|U]-U, New_Q).
de_queue([H|T]-U, H, T-U).
check_queue(Elem, Q) :-
Q = A-[],
member(Elem, A).
append_dl(A-B, B-C, A-C).