Search code examples
prologgeometric-arc

Check if triangle is equilateral in Prolog


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?


Solution

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