Find an input to the system to achieve desired output - prolog

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).

Related

-Define a predicate to display all multiples of

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
?

How to solve this puzzle in Prolog? (robbery)

Three suspects are involved in a robbery, Alice, Bob, Carl. At least one of them are guilty.
Here are the conditions:
If A is guilty, he has exactly 1 accomplice.
If B is guilty, he has exactly 2 accomplices.
Who are guilty?
How can I write a Prolog script to solve this problem which guilty(X) gives the gangs?
Here is a solution using clpb :
:- use_module(library(clpb)).
solve(A,B,C) :-
% there is a least one guilty
sat(A + B + C),
% If A is guilty, he has exactly 1 accomplice.
sat(A =< B # C),
% if B is guilty, he has exactly 2 accomplices.
sat(B =< A * C),
% Assigns truth values to the variables such that all constraints are satisfied.
labeling([A,B,C]).
Now we get :
?- solve(A,B,C).
A = B, B = 0,
C = 1 ;
A = C, C = 1,
B = 0.
The answer A = B, B = 0, C = 1 means that C is guilty the other one that A and C are guilties.
Let's encode the state of our world as three numbers, A, B, and C.
Each number will be either 1 (guilty) or 0 (innocent).
The conditions are:
at_least_one(A,B,C):- 0 < A+B+C.
one_accomplice(A,B,C):- A == 1 -> 1 is ....... ; true.
two_accomplices(A,B,C):- B == 1 -> ....... ; true.
The three rules holding together is
ok(A,B,C):- at_least_one(A,B,C),
one_accomplice(A,B,C),
...... .
Now we can find out the gangs, as
the_guilty([A,B,C]):-
( A = 0 ; A = 1 ),
....
....
ok( ..... ).
The last thing is to report the three given numbers as names of people. We know that the first number is for "Alice", the second is for "Bob", etc.
Prolog is easy.

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.

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?

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