-Define a predicate to display all multiples of - logic

i have ERROR in this code in prolog can you help me?
div(X):- X mod 3 =:= 0.

div(X):- X mod 3 =:= 0 ...
div(X):- X mod 3 =:=1 ...
2 mod 3 is not 0 or 1, so there is no way to do div(2), so it fails.
Maybe you wanted
X mod 3 =:= 0 % remainder 0
X mod 3 =\= 0 % remainder not 0
?

Related

Argument is not instantiated, need it to start at zero but also be able to change it

Whenever I run my code, I get an error that the arguments are not instantiated.
ads(X,Z):- mod(X,2) =:= 0, Z is Z+X.
ads(X,Z) :- mod(N,2) =\= 0,Z is Z.
sum_of_nums(0,0,0).
sum_of_nums(X,Y,Z) :- X=<Y, ad(X,Z), sum_of_nums(X+1,Y,Z).
I want to be able to add numbers from X to Y but only the even ones. Don't know why it doesn't work.
First, there are some tiny errors, your compiler should indicate, like the unnecessary singleton variables in the second clause. After repairing this, and replacing ads by ad we have:
ad(X,Z):- mod(X,2) =:= 0, Z is Z+X.
ad(X,Z) :- mod(X,2) =\= 0,Z is Z.
sum_of_nums(0,0,0).
sum_of_nums(X,Y,Z) :- X=<Y, ad(X,Z), sum_of_nums(X+1,Y,Z).
?- sum_of_nums(1,2,S).
error(instantiation_error,(is)/2).
To locate this error, I will insert some goals false such that the
resulting program still produces this instantiation error.
ad(X,Z):- mod(X,2) =:= 0, Z is Z+X, false.
ad(X,Z) :- false, mod(X,2) =\= 0,Z is Z.
sum_of_nums(0,0,0) :- false.
sum_of_nums(X,Y,Z) :- X=<Y, ad(X,Z), false, sum_of_nums(X+1,Y,Z).
?- sum_of_nums(1,2,S).
error(instantiation_error,(is)/2).
Therefore, you have an error in this part already.
It's the Z is Z+X. On the right hand side of (is)/2 you always
need to have variables that are instantiated (known). And Z is not
known.
Variables are a bit different in Prolog. You cannot reassign them.
And also, writing this in Prolog directly doesn't really show what the
language is good at.
sum_of(X, Y, 0) :-
X > Y.
sum_of(X1, Y, Z1) :-
X1 =< Y,
( X1 mod 2 =:= 0 -> S = X1 ; S = 0 ),
X2 is X1+1,
sum_of(X2, Y, Z2),
Z1 is Z2+S.
A more idiomatic way would be:
?- between(1,6,N).
N = 1
; N = 2
; N = 3
; N = 4
; N = 5
; N = 6.
?- between(1,6,N), N mod 2 =:= 0.
N = 2
; N = 4
; N = 6.
?- findall(N, ( between(1,6,N), N mod 2 =:= 0 ), Ns).
Ns = [2,4,6].
?- findall(N, ( between(1,6,N), N mod 2 =:= 0 ), Ns), sum_list(Ns,Sum).
Ns = [2,4,6], Sum = 12.
sum_of(X,Y,Sum) :-
findall(N, ( between(X,Y,N), N mod 2 =:= 0 ), Ns),
sum_list(Ns,Sum).

List split in Prolog

Getting error in Prolog.
I want the 1st list to have positive numbers divisible by 2 and 2nd list to have negative number divisible by 3.
This is the code I've written so far but I'm getting the output as 'false'
split([],[],[]).
split([X|L],[X|L1],L2):- X >=0, X mod 2 =:= 0, split(L,L1,L2).
split([X|L],L1,[X|L2]):- X<0, X mod 3 =:= 0, split(L,L1,L2).
test case - split([1,-2,-3,4,-17,3],L1,L2).
output - false
Can someone please tell me where am I going wrong?
You did not specify a clause for values that are not positive and dividable by two, or negative and dividable by three. In that case you probably do not want to include it in any list, so:
split([],[],[]).
split([X|L],[X|L1],L2):-
X >= 0,
X mod 2 =:= 0,
split(L,L1,L2).
split([X|L],L1,[X|L2]):-
X < 0,
X mod 3 =:= 0,
split(L,L1,L2).
split([X|L], L1, L2) :-
\+ ((X >= 0, X mod 2 =:= 0); (X < 0, X mod 3 =:= 0)),
split(L, L1, L2).

Finding all cube roots with a number as a limit

I want to find all of the cube roots that their cubes + their remainder add up to a number to user inputs. So for example, the query:
?- smallerCube(X,20).
Would give the result:
1 remainder 19
2 remainder 12
Since 1^3 = 1 (remainder 19), 2^3 = 8(remainder 12) and 3^3 = 27 which is bigger than the initial input of 20, and hence it's not being calculated here.
So far this is my code:
cubeLess(X,B,R) :-
X =< B,
X1 is X*X*X,
R is B-X1.
smallerCube(X,B) :- int(X),
X2 is X*X*X,
X2 =< B,
cubeLess(X2,B,R),
write(X), write(' rest '), writeln(R).
int(1).
int(N) :- int(N1), N is N1+1.
I use cubeLess to get the remainder, int to generate numbers from 1 onward.
However, when I run the following query:
?- smallerCube(X,130)
I get the following weird result:
1 rest 129
X = 1
2 rest -382
X = 2
3 rest -19553
X = 3 ;
Why did it work for X=1, but gave negative results for X=2,3?
Use clpfd!
:- use_module(library(clpfd)).
No need to worry about using clpfd for the 1st time—you'll get the meaning in a moment for sure!
smallerCube_(X, Remainder, Maximum) :-
X #>= 0,
Remainder #>= 0,
Remainder + X^3 #= Maximum.
First, the most general query of smallerCube_/3:
?- smallerCube_(X, Remainder, 20).
X in 1..2, _A in 1..8, Remainder in 12..19, X^3 #= _A, Remainder+_A #= 20.
One answer—two solutions: let's see them separated!
?- smallerCube_(X, Remainder, 20), indomain(X).
X = 1, Remainder = 19 % 20 #= 1^3 + 19
; X = 2, Remainder = 12. % 20 #= 2^3 + 12
Here's the second query the OP wanted to run:
?- smallerCube_(X, Remainder, 130), indomain(X).
X = 1, Remainder = 129 % 130 #= 1^3 + 129
; X = 2, Remainder = 122 % 130 #= 2^3 + 122
; X = 3, Remainder = 103 % ...
; X = 4, Remainder = 66 % ...
; X = 5, Remainder = 5. % 130 #= 5^3 + 5
Done! So what's next? Of course, that is up to you, so:
Why not re-invest the time clpfd saved you?
Why not read
this very compact CLP(FD) primer
as a jumpstart?

Find an input to the system to achieve desired output

I have the following equation:
y(t) = x(t) and not x(t-1)
x, y are boolean variables
t is discrete time
which is an edge detector.
I further know that
y(0) = 0
y(1) = 0
y(2) = 1
y(3) = 0
y(4) = 0
and initial conditions
x(0) = 1
x(4) = 0
I would like to solve the equation so that i find satisfactory values for x(1), x(2), x(3). For this example I expect one of the solutions to be:
x(1) = 0
x(2) = 1
x(3) = 1
I am Prolog beginner, but I think that Prolog is exactly the thing usable for solving tasks like this. I would write the expected output and initial conditions as facts:
y(0,0).
y(1,0).
y(2,1).
y(3,0).
y(4,0).
x(0,1).
x(4,0).
and the equation self as a predicate. How to rewrite the equation as a Prolog predicate and how to query for x ? Is it possible to obtain all soulutions?
Many thanks for every idea!
Best wishes.
After reading the 1st answer
There is a mistake in the constraints (if I use this term well).
The equation (system) as stimulated by x(t) will give particular y(t)
x(t): 1 0 1 0 0
y(t): X 0 1 0 0
t : 0 1 2 3 4
where X means "we do not know" because x(-1) needs to be known for y(0) computation.
The task is to compute x(t) for t in 1..4 when y(t) is known.
x(0) and x(4) can be requested to have particular values or not. This only affects the number of solutions, but it is not crucial for the essence of the task, as I think.
For given
y(t): X 0 1 0 0
t : 0 1 2 3 4
there are imho two solutions:
S1:
x(t): 1 0 1 0 0
y(t): X 0 1 0 0
t : 0 1 2 3 4
S2:
x(t): 1 0 1 1 0
y(t): X 0 1 0 0
t : 0 1 2 3 4
If there are no initial/final constraints for x(t) there are at least these solutions in addition:
S3:
x(t): 1 0 1 1 1
y(t): X 0 1 0 0
t : 0 1 2 3 4
S4:
x(t): 0 0 1 0 0
y(t): X 0 1 0 0
t : 0 1 2 3 4
S5:
x(t): 0 0 1 1 0
y(t): X 0 1 0 0
t : 0 1 2 3 4
S6:
x(t): 0 0 1 1 1
y(t): X 0 1 0 0
t : 0 1 2 3 4
I would like to solve this even for longer series and for more complicated equations, this example is very simplified.
Consider using a constraint solver over Boolean variables or finite domains. For example, with SWI-Prolog:
:- use_module(library(clpfd)).
edge(Xs, Ys) :-
Xs = [X0,X1,X2,X3,X4],
Ys = [_Y0,Y1,Y2,Y3,Y4],
Xs ins 0..1,
Ys ins 0..1,
X0 = 1,
X4 = 0,
Ys = [0,0,1,0,0],
Y1 #= X1 #/\ Y1 #\= X0,
Y2 #= X2 #/\ Y2 #\= X1,
Y3 #= X3 #/\ Y3 #\= X2,
Y4 #= X4 #/\ Y4 #\= X3.
I get:
?- edge(Xs, Ys).
false.
So assuming I understood and modeled this correctly, your constraints do not admit a solution. When I comment out the last constraint, I get a unique solution:
?- edge(Xs, Ys).
Xs = [1, 0, 1, 0, 0],
Ys = [0, 0, 1, 0, 0].
It is clear from this that no Y4 can satisfy the final constraint with these given Xs, since it would have to be both 0 and distinct from 0 (the final two elements in Xs). You can use label/1 to enumerate all concrete solutions when there are still variables in your answers (which is not the case above).

OR condition in Prolog

I want to check whether a number is divisible by one of 3, 5, or 7.
How could I write a rule something like -
isDivide(N) :- N mod 3 =:= 0 OR N mod 5 =:= 0 OR N mod 7 =:= 0.
isDivide(N) :- N mod 3 =:= 0.
isDivide(N) :- N mod 5 =:= 0.
isDivide(N) :- N mod 7 =:= 0.
alternatively:
isDivide(N) :-
N mod 3 =:= 0
; N mod 5 =:= 0
; N mod 7 =:= 0.
Note that ; is not at the end of the line but at the beginning of the next line.
This is purely a matter of style but it's strongly recommended to follow it.

Resources