Search code examples
prologswi-prologclpfd

Why no division in CLP(FD) in Prolog?


I could not find division (/) symbol on this page of CLP(FD): http://www.swi-prolog.org/man/clpfd.html

Also this simple code give error:

:-use_module(library(clpfd)). 
afn(A,B,C):-
    C #= B / A.


?- afn(23, 56, C).
ERROR: Domain error: `clpfd_expression' expected, found `56/23'

Where is the problem and how can this be solved? Thanks.


Solution

  • In ISO Prolog (/)/2 yields a float result. SWI-Prolog is not ISO compliant here, it casts to an integer where possible. But basically (/)/2 is viewed as an operation between machine real numbers, that gives a new approximated machine real number.

    On the other hand CLP(FD) works only with integers. Therefore, I guess, this is the reason that CLP(FD) usually don't support the (/)/2 operator. On the otherhand the div operator (//)/2 from ISO Prolog, works also for CLP(FD). Supported are:

    Expr // Expr Truncated integer division
    Expr div Expr Floored integer division

    Here is an example run:

    Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.4)
    
    ?- use_module(library(clpfd)).
    true.
    
    ?- X #= 100 // Y, Y = 7.
    X = 14,
    Y = 7.
    
    ?- X #= Z // 7, X = 14.
    X = 14,
    Z in 98..104.
    

    If you have a CLP(FD) without the (//)/2 operator, you can simulate it. Instead of X #= Y//Z, you can write X*Z+R #= Y, 0 #=< R, R #< Z. When negative arguments are involved you need a more complex formula.

    Here are some example runs that show that this approach also works:

    ?- X*Y+R #= 100, 0 #=< R, R #< Y, Y = 7.
    X = 14,
    Y = 7,
    R = 2.
    
    ?- X*7+R #= Z, 0 #=< R, R #< 7, X = 14.
    X = 14,
    R in 0..6,
    -98+Z#=R,
    Z in 98..104.