Суммарное расстояние пролога между списком идентификаторов узлов

#prolog #instantiation-error

#пролог #создание экземпляра-ошибка

Вопрос:

 node(1,22,44).
node(2,43,53).
node(3,23,12).

distance(Id1,Id2,D) :-
    node(Id1,X1,Y1),
    node(Id2,X2,Y2),
    D is sqrt((X2-X1)^2   (Y2-Y1)^2).

distancePath([X,Y],D) :-
    distance(X,Y,D).
distancePath([H,X|T],Distance) :-
    distancePath([X|T],Rest),
    distance(H,X,D),
    Aux is Rest   D,
    Distance is Distance   Aux.

  

У меня какая-то проблема с distancePath, потому что, когда я запускаю distancePath([1,2,3],Distance). , он выдает мне «Ошибка создания экземпляра в аргументе 2 из (is) / 2», может кто-нибудь мне помочь?

Ответ №1:

Distance is Distance Aux. не имеет особого смысла. Переменные неизменяемы, это означает, что после установки переменная сохранит то же значение в этой ветви оценки пролога. Кроме того, Distance не ограничено, отсюда и ошибка.

На самом деле у вас уже есть значение для Distance : это Aux так как это расстояние для Rest списка плюс расстояние D :

 distancePath([X,Y], D) :-
    distance(X,Y,D).

distancePath([H,X|T], Aug) :-
    distancePath([X|T],Rest),
    distance(H,X,D),
    Aux is Rest   D.  

Затем это дает нам:

 ?- distancePath([1,2,3], D).
D = 68.4652982294199 ;
false.
  

Однако вышеприведенное не очень эффективно: оно не использует хвостовую рекурсию, и, кроме того, вы выполняете распаковку конструктора cons несколько раз. Вы можете использовать вспомогательный предикат для повышения эффективности:

 distancePath([X|T], Result) :-
    distancePath(T, X, 0, Result).

distancePath([], _, D, D).
distancePath([J|T], I, Di, Do) :-
    distance(I, J, Dd),
    D2 is Di   Dd,
    distancePath(T, J, D2, Do).