6

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.

rnso
  • 23,686
  • 25
  • 112
  • 234
  • 5
    you should use integer division '//' – CapelliC Jul 05 '16 at 09:23
  • That gives only rounded integers. Can I get answer to some reasonable decimal places, like 4-5? – rnso Jul 05 '16 at 09:48
  • 1
    Scale all inputs by 10000 and then post all constraints on them. Scale back the results if needed. – mat Jul 05 '16 at 10:06
  • I am getting it now. I can use: mydecimal(Num, Dec, Out):- Out is round(10^Dec * Num)/10^D. Can modify to have an expression in place of Num. Why does Prolog avoid some stuff which is very basic in other programming languages? – rnso Jul 05 '16 at 10:08
  • Use clpfd: `Out #= 10^D * N`. – mat Jul 05 '16 at 10:11
  • The "FD" in "CLPFD" means "Finite Domains". The domain of real numbers, even over a finite interval, is infinite. – lurker Jul 05 '16 at 10:42
  • 1
    That's probably the reason why real numbers are a poor match for beings and machines that are inherently finite and we need to make do with what we can. For example, in SWI-Prolog and YAP, the "Finite Domains" can grow up to the amount of available RAM. For the numbers that arise in most Prolog applications I have seen, that's sufficient to multiply them by as large as factor as you need to carry out all computations over *integers*, using CLP(FD) constraints, even if you later treat these numbers as decimals and insert a decimal point somewhere when you display them. – mat Jul 05 '16 at 10:48
  • What is best method to use floating point in Prolog? (I am not focusing on CLPFD). – rnso Jul 05 '16 at 10:52
  • 2
    As I said, the best method is to **not** use floating point numbers. You cannot trust the results, since the programming languages offer **no way** to inspect the crucial details that are essential when reasoning with floating point numbers. Use **rational numbers**, **integers** or ask, pay or wait for better formats (like decimals). Integers suffice for almost all use cases. In many cases, you can simply mulitply all numbers suitably and work over integers throughout most of your program. Use CLP(FD) constraints to reason over integers. – mat Jul 05 '16 at 10:57
  • 1
    *What is best method to use floating point in Prolog?* That question is probably to broad for a single answer. If all you need to do is take some floating point number and compute a new result with them, functionally, then that can be done in Prolog with a numeric expression as in any other language and using `is/2`, for example, to yield a result. But general floating point numbers don't fit well within the relational aspects of Prolog. – lurker Jul 05 '16 at 11:09
  • @mso: you could have a look at ECLiPSe http://eclipseclp.org which supports floating point interval arithmetics. – jschimpf Jul 06 '16 at 09:48

1 Answers1

1

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.