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|...], [...|...]|...].
CodePudding user response:
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 good a 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.