I'm learning Prolog and trying to create a program to check if a triangle is equilateral.
Here is my code
equilateral(point2d(X1,Y1),point2d(X2,Y2),point2d(X3,Y3)):-
((X2-X1)*(X2-X1) + (Y2-Y1)*(Y2-Y1)) =:= ((X3-X2)*(X3-X2) + (Y3-Y2)*(Y3-Y2)),
((X3-X2)*(X3-X2) + (Y3-Y2)*(Y3-Y2)) =:= ((X3-X1)*(X3-X1) + (Y3-Y1)*(Y3-Y1)).
When I run equilateral(point2d(2,3),point2d(6,3),point2d(4,3+sqrt(12))).
, the result gave false, I know that three points (2,3) (6,3) (4,3+sqrt(12)) make a equilateral triangle (already checked by hand). Please let me know what I'm I missing?
Comparing floating-point numbers for equality is often hazardous. In your specific case, if you trace the query you will get:
| ?- trace.
The debugger will first creep -- showing everything (trace)
yes
{trace}
| ?- equilateral(point2d(2,3),point2d(6,3),point2d(4,3+sqrt(12))).
1 1 Call: equilateral(point2d(2,3),point2d(6,3),point2d(4,3+sqrt(12))) ?
2 2 Call: (6-2)*(6-2)+(3-3)*(3-3)=:=(4-6)*(4-6)+(3+sqrt(12)-3)*(3+sqrt(12)-3) ?
2 2 Fail: (6-2)*(6-2)+(3-3)*(3-3)=:=(4-6)*(4-6)+(3+sqrt(12)-3)*(3+sqrt(12)-3) ?
1 1 Fail: equilateral(point2d(2,3),point2d(6,3),point2d(4,3+sqrt(12))) ?
If you separately evaluate the =:=/2
arguments you can see why the query is failing:
| ?- X is (6-2)*(6-2)+(3-3)*(3-3).
X = 16
yes
| ?- X is (4-6)*(4-6)+(3+sqrt(12)-3)*(3+sqrt(12)-3).
X = 15.999999999999998
yes
Usually, you consider two floating-point values the same if they are equal or if they are close. What's a good definition of close depends on the application and several standard definitions are available (e.g. approximate equality, essential equality, or tolerance equality). I strongly recommend that you find and read a good introduction to floating-point arithmetic.
P.S. Logtalk, which you can run with most Prolog systems, provides library support for four different equality tests: https://logtalk.org/library/number_0.html Using one of these library predicates will allow you to get a working definition for your equilateral/3
predicate.