Prolog sum distance between list of nodes ids

98 views Asked by At
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.

I have some kind of problem on the distancePath because when i run distancePath([1,2,3],Distance). it give me "Instantiation error in argument 2 of (is)/2" can someone help me?

1

There are 1 answers

0
willeM_ Van Onsem On BEST ANSWER

Distance is Distance + Aux. does not make much sense. Variables are immutable, this means once set the variable will keep the same value in that branch of the Prolog evaluation. Furthermore Distance is unbounded, hence the error.

You actually already have the value for Distance: it is Aux since it is the distance for the Rest of the list, plus the distance 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.

This then gives us:

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

The above is however not very efficient: it does not make use of tail recursion, and furthermore you perform unpacking of the cons constructor multiple times. You can make use of a helper predicate to boost efficiency:

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).