在 Prolog 数组中进行有序插入的意外行为

Unexpected behaviour doing ordered insertion in array in Prolog

我需要使用需要按升序排序的数组来实现队列。每个项目都是图的一个节点,我正在使用 A* 算法进行探索,即:

nodo(S, ListaAzioniPerS, C, S)

其中 S 是节点的标识符,ListaAzioniPerS 到达该节点的路径,C 是到这里的成本,S 是它的启发式。我需要按我称为 F

C+S 的总和来排序它们

为此,我尝试通过以下代码进行有序插入:

orderedInsert(X, [], [X]).
orderedInsert(nodo(S, ListaAzioniPerS, C, S),
              [nodo(S1, ListaAzioniPerS1, C1, S1)|Rest],
              [nodo(S, ListaAzioniPerS, C, S), nodo(S1, ListaAzioniPerS1, C1, S1)|Rest]) :-
  F is C + S,
  F1 is C1 + S1,
  F < F1,
  !.
%orderedInsert(nodo(S, ListaAzioniPerS, C, S),
%              [nodo(S1, ListaAzioniPerS1, C1, S1)|Rest],
%       [nodo(S, ListaAzioniPerS, C, S), nodo(S1, ListaAzioniPerS1, C1, S1)|Rest]) :-
%  F is C + S,
%  F1 is C1 + S1,
%  F == F1,
%  C < C1,
%  !.
orderedInsert(X, [Y|Rest0], [Y|Rest]) :-
  orderedInsert(X, Rest0, Rest).

(有一个评论部分在 F==F1 的情况下进行考试,所以他们会按 C 订购,但因为我已经搞砸了,所以我只是评论了它)

现在,出于某种原因,即使我用第二个参数调用 orderedInsert/3 一个非空列表,它也只与第一个函子匹配! 但这还不是全部,结果总是在列表末尾追加... 这是这一行的一个简单示例 orderedInsert(nodo(nodo1, listaAzioniPerS, 1, 1), [nodo(nodo2, listaAzioniPerS1, 2, 1)], X).

[trace] 7 ?- orderedInsert(nodo(nodo1, listaAzioniPerS, 1, 1), [nodo(nodo2, listaAzioniPerS1, 2, 1)], X).
 * Call: (8) orderedInsert(nodo(nodo1, listaAzioniPerS, 1, 1), [nodo(nodo2, listaAzioniPerS1, 2, 1)], _2026) ? creep
   Call: (9) length([nodo(nodo2, listaAzioniPerS1, 2, 1)], 0) ? creep
   Fail: (9) length([nodo(nodo2, listaAzioniPerS1, 2, 1)], 0) ? creep
 * Redo: (8) orderedInsert(nodo(nodo1, listaAzioniPerS, 1, 1), [nodo(nodo2, listaAzioniPerS1, 2, 1)], _2026) ? creep
 * Call: (9) orderedInsert(nodo(nodo1, listaAzioniPerS, 1, 1), [], _2278) ? creep
   Call: (10) length([], 0) ? creep
   Exit: (10) length([], 0) ? creep
 * Exit: (9) orderedInsert(nodo(nodo1, listaAzioniPerS, 1, 1), [], [nodo(nodo1, listaAzioniPerS, 1, 1)]) ? creep
 * Exit: (8) orderedInsert(nodo(nodo1, listaAzioniPerS, 1, 1), [nodo(nodo2, listaAzioniPerS1, 2, 1)], [nodo(nodo2, listaAzioniPerS1, 2, 1), nodo(nodo1, listaAzioniPerS, 1, 1)]) ? creep
X = [nodo(nodo2, listaAzioniPerS1, 2, 1), nodo(nodo1, listaAzioniPerS, 1, 1)] .

跟踪虽然执行对我没有任何帮助(实际上它让我怀疑我是否完全理解序言)。 知道我哪里错了吗?

使用 SWI Prolog。

您的问题是变量 S 和 S1 的重复使用。 您可以将它们更改为 - 例如 -

orderedInsert(nodo(N, ListaAzioniPerS, C, S),
              [nodo(N1, ListaAzioniPerS1, C1, S1)|Rest],
              [nodo(N, ListaAzioniPerS, C, S), nodo(N1, ListaAzioniPerS1, C1, S1)|Rest]) :-
  F is C + S,
  F1 is C1 + S1,
  F < F1,
  !.

您的代码将起作用。顺便说一句,你可以减少一点混乱:

orderedInsert(nodo(N, ListaAzioniPerS, C, S),
              [nodo(N1, ListaAzioniPerS1, C1, S1)|Rest],
              [nodo(N, ListaAzioniPerS, C, S), nodo(N1, ListaAzioniPerS1, C1, S1)|Rest]) :-
  C + S < C1 + S1,
  !.