Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prolog Beginner: How to unify with arithmetic comparison operators or how to get a set var to range of values

Tags:

prolog

clpfd

I am new to Prolog. I need to write an integer adder that will add numbers between 0-9 to other numbers 0-9 and produce a solution 0-18. This is what I want to do:

% pseudo code
add(in1, in2, out) :-
    in1 < 10,
    in2 < 10,
    out < 18.

I would like to be able to call it like this:

To check if it is a valid addition:

?- add(1,2,3).
true.
?- add(1,2,4).
false.

With one missing variable:

?- add(X,2,3).
X = 1.
?- add(1,4,X).
X = 5.

With multiple missing variables:

?- add(X,Y,Z).
% Some output that would make sense.  Some examples could be:
X=1, Y=1, Z=2 ;
X=2, Y=1, Z=3 ......

I realize that this is probably a pretty simplistic question and it is probably very straightforward. However, according to the Prolog tutorial I am using:

"Unlike unification Arithmetic Comparison Operators operators cannot be used to give values to a variable. The can only be evaluated when every term on each side have been instantiated."

like image 254
sixtyfootersdude Avatar asked Jun 05 '10 16:06

sixtyfootersdude


1 Answers

All modern Prolog systems provide finite domain constraints, which are true relations that can (in contrast to more low-level arithmetic predicates like is/2 and >/2) be used in all directions. In SWI-Prolog:

:- use_module(library(clpfd)).

plus(X, Y, Z) :-
        [X,Y] ins 0..9,
        X + Y #= Z.

Results for your examples:

?- plus(1,2,3).
true.

?- plus(1,2,4).
false.

?- plus(X,2,3).
X = 1.

?- plus(1,4,X).
X = 5.

?- plus(X,Y,Z).
X in 0..9,
X+Y#=Z,
Y in 0..9,
Z in 0..18.

Since the predicate can be used in all directions, it does no longer make sense to call it "add/3", as that would imply a direction, but the predicate truly describes when the relation holds and is thus more general.

like image 92
mat Avatar answered Sep 23 '22 21:09

mat