Prolog: Find all equilateral triangles which are built from DB points - list

I'm new to Prolog and my task requires finding all equilateral triangles which are built from DB points. As a result, I'm getting identical points of the triangles. I do not understand what the problem is. Help me pls!
:- dynamic
point/3.
%?Point_Sign, ?Abscissa, ?Ordinate
db_filling:-
point(_,_,_),!.
db_filling:-
assert(point(a,1,1)),
assert(point(b,1,2)),
assert(point(c,1,3)),
assert(point(d,2,2)),
assert(point(e,3,3)),
assert(point(f,-1,1)),
assert(point(g,-2,1)),
assert(point(h,-2,2)),
assert(point(i,-3,3)),
assert(point(j,-3,-1)),
assert(point(k,-3,-2)),
assert(point(l,-3,-3)),
assert(point(n,-1,-1)),
assert(point(m,-3,0)),
assert(point(o,3,0)),
assert(point(p,0,3)).
% +List
points_main(Xs):-
db_filling,
findall(Xs1,equilateral_triangles(Xs1),Xs).
% +Points
equilateral_triangles([P1,P2,P3]):-
point(P1,X1,Y1),
point(P2,X2,Y2),
point(P3,X3,Y3),
L1 is sqrt((X2 - X1)^2 + (Y2 - Y1)^2),
L2 is sqrt((X3 - X2)^2 + (Y3 - Y2)^2),
L3 is sqrt((X1 - X3)^2 + (Y1 - Y3)^2),
L1 = L2,
L2 = L3.
Result:
?- points_main(Res).
Res = [[a, a, a], [b, b, b], [c, c, c], [d, d, d], [e, e, e], [f, f, f], [g, g|...], [h|...], [...|...]|...].

You have a couple of fundamental issues here.
From memory, the two-dimensional coordinates of an equilateral triangle cannot all be integers. You must have at least one irrational number. Computers are not good at representing irrational numbers.
So, you're also confusing real maths with computer maths. You can't simply get the sqrt and check for equality.
To illustrate I produced these three points:
point(j1,0,0).
point(j2,1,0).
point(j3,0.5,0.866025403784439). % 1/2 & sqrt(3)/2
That's an equilateral triangle.
When I run that with your code, the lengths that get produced are like this:
[1.0,1.0000000000000004,1.0000000000000004]
They are all effectively 1.0, but of course 1.0000000000000004 is not 1.0. So, even this doesn't comeback as a equal.
So you are really forced to check the confidence as an epsilon to say two numbers are equal.
Here's what I did to do that:
points_main(Xs):-
findall(Xs1,equilateral_triangles(Xs1),Xs).
equilateral_triangles([P1,P2,P3]):-
point(P1,X1,Y1),
point(P2,X2,Y2),
P1 \= P2,
point(P3,X3,Y3),
P1 \= P3,
P2 \= P3,
L12 is sqrt((X2 - X1)^2 + (Y2 - Y1)^2),
L23 is sqrt((X3 - X2)^2 + (Y3 - Y2)^2),
L31 is sqrt((X1 - X3)^2 + (Y1 - Y3)^2),
D1223 is abs(L12 - L23),
D1223<0.00000001,
D2331 is abs(L23 - L31),
D2331<0.00000001,
D3112 is abs(L31 - L12),
D3112<0.00000001.
Now, if I run that against my points above I get this:
?- points_main(Xs).
Xs = [[j1, j2, j3], [j1, j3, j2], [j2, j1, j3], [j2, j3, j1], [j3, j1, j2], [j3, j2, j1]].
All combinations of the above three points - so, yes, they are all equilateral triangles.
If I run against your original points, as expected, there are no equilateral triangles.
A few side notes.
(1) I removed all of the assert code. It wasn't helpful nor necessary to get your code working.
(2) you could define my j3 point as point(j3,0.5,X) :- X is sqrt(3)/2. and your original maths would work. However, this is just lucky. When dealing will floating-point numbers you can never be sure that two numbers are equal even though they should be.
(3) I introduced P1 \= P2, etc, to prevent the points unifying to themselves. That's why you got [a,a,a],... etc.

The reason you get odd results is that your
...
point(P1,X1,Y1),
point(P2,X2,Y2),
point(P3,X3,Y3),
...
is producing the Cartesian Product of your set of points. If you had just 4 points defined, this would produced 43 (64) possible results.
Since you are talking triangles here, where for a given 3 points A, B, and C, whether the triangle they describe is labelled ABC, ACB, BAC, BCA, CAB, CBA is irrelevant: they all describe exactly the same triangle, so what your are looking for are combinations: a selection of items from a set where order is not important, so {a,b,c] and {c,b,a] are the same combination.
In Prolog, getting combinations is easy:
combination( [] , [] ) .
combination( [H|T] , [H|T2] ) :- combination(T,T2).
combination( [_|T] , T2 ) :- combination(T,T2).
The only caveat is that the 2nd argument to combination/2 must be seeded as a list of the desired length. To draw combinations of 3 things from a set of 5 things is as easy as:
combination( [a,b,c,d,e] , [X,Y,Z] ).
Once you have that, getting the set of points from which to draw is easy, too, using findall/3 or setof/3:
setof( p(P,X:Y) , point(P,X,Y) , Ps ) ,
The one tricky thing is that floating point arithmetic leaves much to be desired, what with floating point jitter and all. This is how I'm computing distance:
%-----------------------------------------------------------------------
% computes the distance between two points on the Cartesian plane.
% the distance, D, is returned as an integer with an implied scale of 5,
% so the distance 1.23456789 is returned as 123457 (rounded up)
% ----------------------------------------------------------------------
distance( X1:Y1 , X2:Y2 , D ) :-
V is sqrt( (X2-X1)^2 + (Y2-Y1)^2 ) ,
D is round( 100000 * V )
.
Putting it together, we get this (https://swish.swi-prolog.org/p/zHAfMTtA.pl):
equilateral_triangle( T ) :-
setof( p(P,X:Y) , point(P,X,Y) , Ps ) ,
combination(Ps,[A,B,C]),
equilateral_triangle(A,B,C,T)
.
%--------------------------------------------------------------------------------
% combination( +Set, +Combination )
%
% Takes a set (a list of distinct things) of M things and produces
% on backtracking all the combinations of M things taken N at a time.
%
% Combination, the 2nd argument MUST be initialize as a list of the desired
% length. For example, to get all the combination of 8 things taken 3 at a time,
% you'd say something like this:
%
% ?- length(C,3), combination([a,b,c,d,e],C).
%
% And get back
%
% C = [a, b, c]
% C = [a, b, d]
% C = [a, b, e]
% C = [a, c, d]
% C = [a, c, e]
% C = [a, d, e]
% C = [b, c, d]
% C = [b, c, e]
% C = [b, d, e]
% C = [c, d, e]
%
%--------------------------------------------------------------------------------
combination( [] , [] ) .
combination( [H|T] , [H|T2] ) :- combination(T,T2).
combination( [_|T] , T2 ) :- combination(T,T2).
%--------------------------------------------------------------
% 3 points comprise an equilateral triangle if the triangle
% that they describe has legs of equal length
%--------------------------------------------------------------
equilateral_triangle( p(A,Pa), p(B,Pb), p(C,Pc) , t(A,B,C) ) :-
distance(Pa,Pb,D),
distance(Pb,Pc,D),
distance(Pc,Pa,D).
%-----------------------------------------------------------------------
% computes the distance between two points on the Cartesian plane.
% the distance, D, is returned as an integer with an implied scale of 5,
% so the distance 1.23456789 is returned as 123457 (rounded up)
% ----------------------------------------------------------------------
distance( X1:Y1 , X2:Y2 , D ) :-
V is sqrt( (X2-X1)^2 + (Y2-Y1)^2 ) ,
D is round( 100000 * V )
.
point( a , 0 , 0 ) .
point( b , 5 , 0 ) .
point( c , 2.5 , 4.33012701892 ) .
point( d , 1 , 1 ) .
point( e , 6 , 1 ) .
point( f , 3.5 , 5.33012701892 ) .

Related

Why does Prolog skip all further if statements in recursion if one of them fails?

The point of the program is to calculate the sum of all even numbers in a list of integers.
is_even(Q):- Q mod 2 =:= 0.
sum_even([],0).
sum_even([A|L],X) :- sum_even(L,X1) -> is_even(A) -> X is X1 + A .
Whenever the is_even predicate succeeds there is no problem, it normally goes back to calculate the sum. However when the number is not even and is_even checks it, it fails, goes back to the recursion and fails everything that follows, doesn't even check if the number is even anymore and just returns false. In a list full of even numbers it works as intended, it returns the sum of all numbers in the list. This here is the trace of the code
Using an accumulator with tail-end recursion is fastest:
is_even(N) :-
N mod 2 =:= 0.
sum_even(Lst, Sum) :-
sum_even_(Lst, 0, Sum).
sum_even_([], Sum, Sum).
sum_even_([H|T], Upto, Sum) :-
( is_even(H) ->
Upto1 is Upto + H
; Upto1 = Upto
),
sum_even_(T, Upto1, Sum).
sum_even_slow([], 0).
sum_even_slow([H|T], Sum) :-
sum_even_slow(T, Sum0),
( is_even(H) ->
Sum is Sum0 + H
; Sum = Sum0
).
Performance comparison in swi-prolog:
?- numlist(1, 1_000_000, L), time(sum_even(L, Sum)).
% 4,000,002 inferences, 0.765 CPU in 0.759 seconds (101% CPU, 5228211 Lips)
Sum = 250000500000.
?- numlist(1, 1_000_000, L), time(sum_even_slow(L, Sum)).
% 4,000,001 inferences, 4.062 CPU in 4.023 seconds (101% CPU, 984755 Lips)
Sum = 250000500000.
add_even(X, Buffer, Sum) :-
(0 =:= X mod 2 ->
Sum is Buffer + X
; Sum = Buffer).
Used with foldl(add_even, Nums, 0, Sum) is about as fast as brebs' tail recursion. Using SWISH Online:
?- numlist(1, 1_000_000, _L), time(sum_even(_L, Sum)).
4,000,002 inferences, 0.699 CPU in 0.699 seconds (100% CPU, 5724382 Lips)
Sum = 250000500000
?- numlist(1, 1_000_000, _L), time(foldl(add_even, _L, 0, Sum)).
4,000,002 inferences, 0.712 CPU in 0.712 seconds (100% CPU, 5621314 Lips)
Sum = 250000500000
(I am curious, if they both do exactly 4,000,002 inferences how come the sum_even seems to get higher LIPS throughput and finish slightly faster?)
The reason that this
is_even(Q):- Q mod 2 =:= 0.
sum_even([],0).
sum_even([A|L],X) :- sum_even(L,X1) -> is_even(A) -> X is X1 + A .
fails when there's odd numbers in the list is that '->'/2, the "implies" operator, is a soft cut. It eliminates the choice point. That means that backtracking into it fails, thus unwinding the whole thing and failing the entire predicate.
Your code is roughly equivalent to
sum_even([],0).
sum_even([A|L],X) :- sum_even(L,X1), !, is_even(A), !, X is X1 + A .
You need to
Eliminate the '->'/2 — it's not necessary the ',' operator is the AND operator, and
Provide an alternative to handle the case when an item is odd.
For instance, you could say this:
is_even( Q ) :- Q mod 2 =:= 0.
sum_even( [] , 0 ) .
sum_even( [A|L] , X ) :-
sum_even(L,X1),
( is_even(A) ->
X is X1 + A
;
X is X1
) .
Or something like this:
is_even( Q ) :- Q mod 2 =:= 0.
sum_even( [] , 0 ) .
sum_even( [A|L] , X ) :-
sum_even(L,X1),
add_even(A,X1,X) .
add_even(X,Y,Z) :- is_even(X), !, Z is X + Y .
add_even(_,Z,Z) .
But the easiest, faster way is to use a helper predicate that carries the extra state. The above predicates will die with a stack overflow given a sufficiently long list. This will not: Prolog has TRO (tail recursion optimization) built in, which effectively turns the recursive call into iteration by reusing the stack frame, so it can handle recursion of any depth:
sum_even( Xs , S ) :- sum_even(Xs,0,S) .
sum_even( [] , S , S ) .
sum_even( [X|Xs] , T , S ) :- is_even(X), !, T1 is T+X, sum_even(Xs,T1,S) .
is_even( Q ) :- Q mod 2 =:= 0.

How does the length of list predicate work

I know there are some topics already about this. But I still dont get it.
Could be somebody describe step by step how:
length1([],0).
length1([X|Xs],N) :-length1(Xs,M), N is M+1.
works? I put traces on but I still have no idea.
Thanks!
Let's walk through an example:
?- length1([a, b, c], N).
First Prolog tries to unify with the first rule, but [a, b, c] doesn't match []. So it tries to unify with the second rule, and we get:
length1([a|[b, c]], N) :-
length1([b, c], M), % We do this first
N is M + 1. % We can't solve this yet because we don't know what M is
So we've matched [a, b, c] to [a|[b,c]], which is part of the list syntax. We can't work out what N is yet, but we've got to do the middle line first, which unifies with the same rule:
length1([b|[c]], M) :-
length1([c], L),
M is L + 1.
As before, we need to do the middle line to work out what M is.
length1([c|[]], L) :-
length1([], K),
L is K + 1.
We still can't work it out, but now our middle line unifies with the first rule:
length1([], 0). % So now we know what K is!
We've unified K with 0, so now we can start going back up:
length1([c|[]], 1) :-
length1([], 0),
1 is 0 + 1. % L is K + 1
length1([b|[c]], 2) :-
length1([c], 1),
2 is 1 + 1. % M is L + 1
length1([a|[b, c]], 3) :-
length1([b, c], 2),
3 is 2 + 1. % N is M + 1
So we exit our recursion with N unified to 3:
?- length1([a, b, c], N).
N = 3.
List-processing predicates in Prolog are almost always going to have two clauses, because the list type is defined inductively as:
A list is either:
Empty: [], or
An item, plus a list: [X|Xs]
Inductive data structures often have predicates whose definitions break down into the same cases as the structure itself. In the case of length, the inductive definition looks like:
The length of a list is either:
0 for empty lists, or
1 + the length of the rest of the list
And that's exactly what you have here in the Prolog code:
length1([], 0).
says that the length of the empty list is zero. This is your base case. A better second clause would be:
length1([_|Xs], N1) :- length1(Xs, N), N1 is N+1
This says, supposing you have a list with some item (we don't care about what it is) and a tail of a list, the length of this list is N1, where N1 is 1 + the length of the tail of the list.
It works badly. Here is how it is supposed to work:
?- length([], N).
N = 0.
?- length([_,_], N).
N = 2.
?- length(L, 0).
L = [].
?- length(L, 2).
L = [_5494, _5500].
?- length(L, N).
L = [],
N = 0 ;
L = [_5524],
N = 1 ;
L = [_5524, _5530],
N = 2 .
?- L = [_|L], length(L, N).
ERROR: Type error: `list' expected, found `#(S_1,[S_1=[_6396|S_1]])' (a cyclic)
ERROR: In:
ERROR: [12] throw(error(type_error(list,...),context(...,_6460)))
ERROR: [9] <user>
ERROR:
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.
... and here is how the version from your question works:
?- length1([], N).
N = 0. % OK
?- length1([_,_], N).
N = 2. % OK
?- length1(L, 0).
L = [] ; % does not terminate!
^CAction (h for help) ? abort
% Execution Aborted
?- length1(L, 2).
L = [_9566, _9572] ; % does not terminate
^CAction (h for help) ? abort
% Execution Aborted
?- length1(L, N).
L = [],
N = 0 ;
L = [_9602],
N = 1 ;
L = [_9602, _9608],
N = 2 . % OK
?- L = [_|L], length1(L, N).
ERROR: Stack limit (1.0Gb) exceeded
ERROR: Stack sizes: local: 1.0Gb, global: 37Kb, trail: 1Kb
ERROR: Stack depth: 11,180,538, last-call: 0%, Choice points: 3
ERROR: Probable infinite recursion (cycle):
ERROR: [11,180,538] user:length1([cyclic list], _9792)
ERROR: [11,180,537] user:length1([cyclic list], _9818)
The last one looks the same, but the built-in length/2 throws a type error instead of exceeding the stack.
There is another problem with length1/2, it uses up the stack if the list is too long, because every recursive step must be left on the stack with the current definition.
?- length(L, 10 000 000). % make a long list, works
L = [_984, _990, _996, _1002, _1008, _1014, _1020, _1026, _1032|...].
?- length(L, 10 000 000), length(L, N). % how long is the long list?
L = [_1258, _1264, _1270, _1276, _1282, _1288, _1294, _1300, _1306|...],
N = 10000000.
?- length(L, 10 000 000), length1(L, N). % how long is the list? too long!
ERROR: Stack limit (1.0Gb) exceeded
ERROR: Stack sizes: local: 0.5Gb, global: 0.2Gb, trail: 1Kb
ERROR: Stack depth: 5,592,186, last-call: 0%, Choice points: 3
ERROR: Possible non-terminating recursion:
ERROR: [5,592,186] user:length1([length:4,407,825], _60000944)
ERROR: [5,592,185] user:length1([length:4,407,826], _60000970)
Moreover:
?- time( length(L, 1 000) ).
% 2 inferences, 0.000 CPU in 0.000 seconds (86% CPU, 46417 Lips)
L = [_886, _892, _898, _904, _910, _916, _922, _928, _934|...].
?- time( length(L, 10 000) ).
% 2 inferences, 0.001 CPU in 0.001 seconds (99% CPU, 3495 Lips)
L = [_888, _894, _900, _906, _912, _918, _924, _930, _936|...].
?- time( length1(L, 1 000) ).
% 501,499 inferences, 0.067 CPU in 0.067 seconds (100% CPU, 7511131 Lips)
L = [_878, _884, _890, _896, _902, _908, _914, _920, _926|...] .
?- time( length1(L, 10 000) ).
% 50,014,999 inferences, 4.938 CPU in 4.941 seconds (100% CPU, 10128365 Lips)
L = [_876, _882, _888, _894, _900, _906, _912, _918, _924|...] .
It takes too long to make bigger lists using length1/2 so this is why I am showing it with such a short list. But you might notice that a list 10 times longer makes your length1/2 run 100 times longer. You should ask whoever showed you this code what that means.
Why am I writing this? Not sure. I think it is irresponsible to show students shitty code. On the other hand, this is a popular question (in the sense that many people before you have asked the exact same thing).

How to simplify algebra equations represented as list of list

With Prolog I want to simplify algebra expression represented as as list of list:
algebra equation
f = 3x+2
list of list
[[3,1],[2,0]]
3 and 2 are coefficients
1 and 0 are exponents
That should be obvious.
I am looking for some tips or suggestions on how to code the simplifications for this example:
f = 3x+2x+1+2
[[3,1],[2,1],[1,0],[2,0]]
simplified:
f = 5x+3
[[5,1],[3,0]]
I have tried some built in functions but did not get the proper idea about how to use them.
One liner, similar to what's proposed by joel76:
simplify(I,O) :-
bagof([S,E],L^(bagof(C,member([C,E],I),L),sum_list(L,S)),O).
The inner bagof collects C (coefficients) given E (exponents), the resulting list L is summed into S, and paired with E becomes [S,E], an element (monomial) of O.
If you omit the universal quantification specifier (that is L^) you get single monomials on backtracking.
You can solve your problem in this way:
simplify(_,_,S,S,[]):- !.
simplify(L,I,Sum,NTot,[[I,S]|T]):-
Sum =< NTot,
findall(X,member([X,I],L),LO),
length(LO,N),
S1 is Sum + N,
sum_list(LO,S),
I1 is I+1,
simplify(L,I1,S1,NTot,T).
write_function([]).
write_function([[D,V]|T]):-
write(' + '),write(V),write('x^'),write(D),
write_function(T).
test:-
L = [[3,1],[2,1],[1,0],[2,0]],
length(L,N),
simplify(L,0,0,N,LO),
LO = [[D,V]|T],
write('f='),write(V),write('x^'),write(D),
write_function(T).
The main predicate is simplify/5 which uses findall/3 to find all the coefficients with the same degree and then sums them using sum_list/2. Then you can write the result in a fancy way using write_function/1.
In SWI-Prolog You can use aggregate :
pred(>, [_,X], [_,Y]) :- X > Y.
pred(<, [_,X], [_,Y]) :- X < Y.
pred(=, [_,X], [_,X]).
simplify(In, Out) :-
aggregate(set([S,X]), aggregate(sum(P), member([P,X], In), S), Temp),
predsort(pred, Temp, Out).
For example :
?- simplify([[3,1],[2,1],[1,0],[2,0]], Out).
Out = [[5, 1], [3, 0]] ;
false.

Give as a solution every different number in a list of lists

I need to do a predicate, select(ListOfLists, X) that returns as a solution every different number in a list of lists, starting with the numbers that are alone in a list, for example:
select([[1,2,3],[1,2],[4],[3]],X).
Would return:
X = 4 ;
X = 3 ;
X = 2 ;
X = 1
Order doesn't matter as long as the numbers that are alone in the list are shown first.
To do this, first I coded 2 other predicates, which are:
%OrderedList is Lists ordered by size.
orderListsBySize(Lists, OrderedLists).
Example: orderListsBySize([[1,2],[6],[3,4,5]], L). ->L = [[6], [1,2], [3,4,5]]
And
%ListsWithoutX is Lists without the X elements
removeFromLists(X, Lists, ListsWithoutX).
Example: removeFromLists(1,[[1,2],[3],[4,1,5]],L). -> L = [[2],[3],[4,5]]
Both predicates work.
Then, to do the select(ListOfLists, X) predicate, I tried the following:
select([[X|[]]|_], X). select(L1,S) :-
orderListsBySize(L1, [[X|XS]|LS]),
length(XS, A),
A == 0,
select([[X|[]]|M], S),
removeFromLists(X, [XS|LS], M).
select([[X|_]|_], X).
But it doesn't work.
It's not a hard exercise to do in other languages, the problem is that it's still hard for me to understand how prolog works. I appreaciate any help, thanks!
You could start with:
select2(ListOfLists,Element):-
length(List,_Len),
member(List,ListOfLists),
member(Element,List).
Which will return all the answers, but then get stuck in a loop looking for ever bigger lists.
This can be averted using the :-use_module(library(clpfd)). and defining a fd_length/2 which wont keep looking for bigger lists then exist in the list of lists.
fd_length(L, N) :-
N #>= 0,
fd_length(L, N, 0).
fd_length([], N, N0) :-
N #= N0.
fd_length([_|L], N, N0) :-
N1 is N0+1,
N #>= N1,
fd_length(L, N, N1).
select(ListOfLists,Element):-
maplist(length,ListOfLists,Lengths),
sort(Lengths,SortedLength),
last(SortedLength,Biggest),
Biggest #>= Len,
fd_length(List,Len),
member(List,ListOfLists),
member(Element,List).
Example Query:
?-select([[1,2,3],[1,2],[4],[3]],X).
X = 4
X = 3
X = 1
X = 2
X = 1
X = 2
X = 3
false
If you want unique solutions, you could enclose in a setof/3 and then call member/2 again.

Arithmetic on Two Lists Prolog

So I have a HW problem I've been working on for a couple days and I'm stuck on the last part. In Prolog, I'm supposed to write a function that takes in two lists
((x1, x2, …, xn), (y1, y2, …yn) )
and finds the distance between both. The output is the result of the math done on the list.
Formula: sqrt((x1-y1)(x1-y1) + (x2-y2)(x2-y2) + … + (xn-yn)*(xn-yn))
Here's what I have so far:
distance([],[], 0).
distance([Ha|Ta],[Hb|Tb], Sum) :-
distance(Ta,Tb, Rest),
Sum is sqrt( (Ha-Hb)*(Ha-Hb)) + Rest.
Prolog has lists, not arrays.
Your code doesn't implement the formula shown, because sqrt must be computed after the sum of products. In the code below, I introduce also an accumulator, making the loop tail recursive (more efficient).
distance(Xs, Ys, Dist) :-
distance(Xs, Ys, 0, Dist).
distance([], [], Acc, Dist) :-
Dist is sqrt(Acc).
distance([X|Xs], [Y|Ys], Acc, Dist) :-
Sum is (Y-X)*(Y-X) + Acc,
distance(Xs, Ys, Sum, Dist).
Depending on your Prolog library, the code could be simpler:
distance(Xs, Ys, Dist) :-
foldl(distpoint, Xs, Ys, 0, Sq),
Dist is sqrt(Sq).
distpoint(X, Y, S, D) :- D is S+(Y-X)*(Y-X).
It is quite near. Off the top of my head, just sum the squares (distance_aux) and then return the square root of the accumulated sum:
distance(L1, L2, D) :-
distance_aux(L1, L2, SQSUM),
D is sqrt(SQSUM).
distance_aux([],[],0).
distance_aux([Ha|Ta],[Hb|Tb], Sum) :-
distance_aux(Ta,Tb, Rest),
Sum is (Ha-Hb)*(Ha-Hb) + Rest.
You can also add the simplified rule distance([], [], 0)., although it is not necessary.
The formula you have given squares the entire summation, rather than squaring each individual couple - which is what you are doing in your code. Using an auxiliary solves that issue:
distance_sum([], [], 0).
distance_sum([Ha|Ta], [Hb|Tb], Sum) :-
distance_sum(Ta, Tb, Rest),
Sum is ((Ha-Hb) * (Ha-Hb)) + Rest.
distance(A, B, Sum) :- distance_sum(A, B, DSum), Sum is sqrt(DSum).
So an example would be:
distance([1,2,3], [4,5,6], Sum).
Sum = 5.196152422706632.
Working:
sqrt( (1-4)*(1-4) + (2-5)*(2-5) + (3-6)*(3-6) )
sqrt( 3*3 + 3*3 + 3*3 )
sqrt( 27 )
5.19615