define predicate prolog by requirements - prolog

I have to define a predicate p(X, Y), where Y = f(X) where
How could I define the predicate, according to this requirements?

Almost the same way it's written there, three cases for Y's value given different X conditions:
f(X, Y) :- X < 4, Y is X ^ 2 - 1.
f(X, Y) :- X >= 4, X =< 6, Y is sqrt(X) + 1.
f(X, Y) :- X > 6, Y is 9 - X.
or the middle case
f(X, Y) :- between(4, 6, X), Y is sqrt(X) + 1.
which I had originally and find more readable, but changes the behaviour for that case, which is a tradeoff.
Then:
:- f(3, Y).
Y = 8
( zcompare/3 hints at a way to get rid of the choice points without using cut !, but only if you restrict to integers ).

Another way that doesn't leave choice points behind...
f(X,Y) :- X < 4 -> Y is X^2 - 1 ;
X =< 6 -> Y is sqrt(X) + 1 ;
Y is 9 - X .

Related

Generate all pairs that sum to given number

I'm trying to generate all pairs X, Y that sum to given number Z using the following predicates:
genN(0).
genN(X) :-
genN(Xprev),
X is Xprev + 1.
sum2(X, Y, Z) :-
X + Y =:= Z.
allSum2(X, Y, Z) :-
genN(X),
X < Z,
genN(Y),
Y < Z,
sum2(X, Y, Z).
I'm using
genN to generate all natural numbers
sum2 checks if given 3 numbers X, Y, Z then X + Y = Z.
Then the logic of allSum2 is to
generate all pairs X and Y such that X and Y are smaller than Z and
to check if they sum up to Z.
Unfortunately I get stuck in generating infinitely many Ys and I do not understand why.
Can someone explain it to me?

Prolog print numbers from 1 to N?

Assume the user gives an input N to the function, how would I print these numbers from 1 to N (recursively or other wise).
example
print_numbers(40).
->1
->2
->…
->40
You want to print numbers from 1 to N so print_numbers(N) can be translated in print_numbers(1, N).
Now what is print_numbers from X to Y ?
print_numbers from X to Y is print(X) and print_numbers from X+1 to N!
In Prolog, you will get :
print_numbers(N) :-
print_numbers(1, N).
% general case X must be lower than Y
print_numbers(X, Y) :-
X =< Y,
writeln(X),
X1 is X + 1,
print_numbers(X1, Y).
Using between/3 and forall/2:
?- forall(between(1, 40, X), writeln(X))
1
2
3
...
39
40
true.

Get Prolog to give all possibilities for arithmetic

I was wondering whether in prolog it is possible to get it to brute force all the possible calculations for something like this:
6 is Z + Q
Z = 1 Q = 5
Z = 2 Q = 4
Z = 3 Q = 3
I suggest to use, if your Prolog support it, a Finite Domain solver.
I usually use GProlog and I can obtain what you ask with something like
fd_domain([A, B], 1, 100),
6 #= A + B,
fd_labeling([A, B]),
where fd_domain/3 set the domain for variables A and B (from 1 to 100), 6 #= A + B set the constraint (A + B is 6) and fd_labelling/1 get all possibles calculations.
In Swi-Prolog is a little different.
First of all, you have to load the CLP(FD) library with
:- use_module(library(clpfd)).
To set the variables and the domain, you can write
Vars = [A, B],
Vars ins 1..100,
Setting the constraint is equal
6 #= A + B,
and to get all possible combinations, you can write
label(Vars),
The generate-and-test approach also works. Of course, you still need some constraints, for example:
?- between(1, 6, X), % X is an integer between 1 and 6
between(1, 6, Y), % Y is an integer between 1 and 6
X =< Y, % X is not larger than Y
X + Y =:= 6. % the sum is 6
X = 1, Y = 5 ;
X = 2, Y = 4 ;
X = Y, Y = 3 ;
false.
The order of the subqueries is significant, so you could as well call it generate-then-test. If you are not afraid to hard-code some of the constraints, there might be ways to avoid generating some of the values, and make some of the tests unnecessary, for example:
?- between(1, 6, X), % X is an integer between 1 and 6
between(X, 6, Y), % Y is an integer between X and 6
X + Y =:= 6. % the sum is 6
X = 1, Y = 5 ;
X = 2, Y = 4 ;
X = Y, Y = 3 ;
false.
You should realize that going down that road far enough is about the same as implementing a constraint solver like CLP(FD) for example.

How to write a prolog mathematical Function?

I am trying to convert a math function into prolog, but I keep getting error. Can anyone give me a hint that where is my mistake, please?
I want to convert f (x) = x ˆ 2 + f (x - 1). So I am assuming that this is a recursive procedure. Here is What I have done so far.
function(0,0) :- !.
function(1,1) :- !.
function(X,Y) :-
X1 is ((X * X) + (X - 1)),
function(X1, Y).
I have also tried
function(0,0) :- !.
function(1,1) :- !.
function(X,Y) :-
X1 is (X * X), X2 is (X - 1),
function(X1, N1),
function(X2, N2),
Y is N1 + N2.
Any help is appreciated.
Prolog works using predicate calculus.
A predicate can evaluate to true or false.
You need to write what is true (anything else is assumed false as prolog interpreters will use a closed world assumption).
for your function we can define a predicate:
func(X, Y)
where func is a predicate that evaluates to true if X is x and Y is f(X)
You need to tell prolog when func(X, Y) is true
func(0, 0).
func(X, Y) :- X > 0, U is X - 1, func(U, V), Y is X * X + V.
The above code can be thought of saying
your predicate func is true when X is 0 and Y is 0
This will be your base case. (You only need one since you only have 1 recursive call).
Next is your recursive case:
When is func true for a general X
we need X to be greater than 0
we need the result of f(x-1) which we called V
V is the result of f(X-1) when func(X-1, V) is true
prolog doesn't allow expressions inside predicates so we state U is X-1
Then we put everything together and state Y is X *X + V
Try this:
f(0,0) . % f(0) is 0.
f(X,Y) :- % otherwise...
integer(X) , % - constrain X to be an integer, and
X > 0 , % - constrain X to be positive,
X1 is X-1 , # - then decrement X
f(X1,Y1) , % - compute f(X-1) ,
Y is X*X + Y1 % - and add X*X to that to get the result.
. % Easy!

Understanding prolog [lists]

I am to write a program that does this:
?- pLeap(2,5,X,Y).
X = 2,
Y = 3 ;
X = 3,
Y = 4 ;
X = 4,
Y = 5 ;
X = 5,
Y = 5 ;
false.
(gives all pairs X,X+1 between 2 and 5, plus the special case at the end).
This is supposedly the solution. I don't really understand how it works, could anyone guide me through it?
pLeap(X,X,X,X).
pLeap(L,H,X,Y) :-
L<H,
X is L,
Y is X+1.
pLeap(L,H,X,Y) :-
L=<H,
L1 is L+1,
pLeap(L1,H,X,Y).
I'd do it simply like this:
pLeap(L,H,X,Y) :-
X >= L,
X =< H,
Y is X+1.
Why doesn't it work (ignoring the special case at the end)?
You could use library clpfd for you problem.
:- use_module(library(clpfd)).
pLeap(L,H,X,Y) :-
X in L..H,
Y #= min(H, X+1),
label([X]).
Here is the output:
?- pLeap(2,5,X,Y).
X = 2,
Y = 3 ;
X = 3,
Y = 4 ;
X = 4,
Y = 5 ;
X = 5,
Y = 5.
The >= and =< operators don't instantiate their arguments, and you can only use them once the arguments have already been instantiated.
Put another way, in the given solution, X and Y are given values with is, and the < and =< operators are only used on L and H, whose values are given by the user. (On the given solution, try pLeap(L,H,2,3) and you'll get the same problem as you're having.)
In your case, though, you try to use >= and =< on X, which has no value yet, and so the interpreter complains.

Resources