I am wondering how to solve basic linear equation with one unknown.
I tried doing it by string splitting in order to get everything i need to solve the equation, but i am sure there is a better way.
solve(5 + X = 10).
X = 5.
solve(5+8 = Ans).
Ans = 13.
This is the thing I'm trying to solve. I want to use solve/1.
Thank you in advance.
You could write:
:- use_module(library(clpfd)).
solve(X+Y=Z):-X+Y#=Z.
Some examples:
?- solve(5+X=10).
X = 5.
?- solve(5+8=ANS).
ANS = 13.
To solve it without libraries you could write:
solve(S):-var(S),throw("instatiation error").
solve(X+Y=Z):-(var(X),var(Y);var(X),var(Z);
var(Y),var(Z)),throw("instatiation error").
solve(X+Y=Z):-nonvar(Z),nonvar(Y),L is Z-Y,X=L.
solve(X+Y=Z):-nonvar(Z),nonvar(X),L is Z-X,Y=L.
solve(X+Y=Z):-nonvar(X),nonvar(Y),L is X+Y,Z=L.
and again the examples:
?- solve(5+X=10).
X = 5 ;
false.
?- solve(5+8=Ans).
Ans = 13.
Related
I'm trying to make a factorial code in prolog but am getting error of out of local stack, that is, it is stuck in infinite loop. I can't understand how.
Here is my code:
fact(0,1).
fact(1,1).
fact(X,Y):- X\==0, A=X-1, fact(A,Z), Y=X*Z.
Where am I going wrong?
It is the A=X-1, and later the Y=X*Z. The great thing about the Prolog top level is that you can easily try out what your code does:
?- A = X-1.
A = X-1.
?- A = 5-1.
A = 5-1.
Apparently, Prolog is mocking us :). The = operator is used for unification; if you want to do arithmetic, you must use is/2:
?- is(A, -(5, 1)).
A = 4.
usually written as:
?- A is 5-1.
A = 4.
This just to show you that an expression is a term, and is evaluates the term in its second argument:
?- Expr = X-1, X = 3, Result is Expr.
Expr = 3-1,
X = 3,
Result = 2.
To your definition for factorial: it should work if you fix the arithmetic. Note that it would be cleaner if the condition for X at the beginning says X > 1 instead of X \== 0: what does your current program do for fact(1,F), and how many answers do you get?
I'm trying to define the function int(?X) in prolog which is a non-zero integer number generator which works like this:
?- int(X). X = 1 ; X = -1 ; X = 2 ; X = -2 ;
I tried the following with no luck:
int(X):- positives(Y), Y is abs(X).
positives(1).
positives(X):- positives(Y), X is Y+1.
but I'm getting the following error:
ERROR: is/2: Arguments are not sufficiently instantiated
How can I make this work? Thanks!
There is an easy way to find and correct such problems.
Step one: Put clpfd constraints in your program. To do this, simply1 replace (is)/2 by the CLP(FD) constraint (#=)/2, i.e.:
int(X) :- positives(Y), Y #= abs(X).
positives(1).
positives(X):- positives(Y), X #= Y+1.
Step two: The query now completes without errors, and shows you what you are describing:
?- int(X).
X in -1\/1 ;
X in -2\/2 ;
X in -3\/3 ;
X in -4\/4 .
So, from the above, you see that what you are describing is not sufficient to obtain ground solutions: There is still a certain degree of freedom in your relations.
Step three: To actually fix the problem, we think about what we actually want to describe. Here is a start:
int(X) :- positives(Y), ( X #= Y ; X #= -Y).
Step four: We try it out:
?- int(X).
X = 1 ;
X = -1 ;
X = 2 ;
X = -2 ;
X = 3 ;
etc.
Seems to work OK, except for the fact that natural numbers are actually never negative. I leave fixing this discrepancy between the title of your question and the relation you are describing as an exercise for you.
TL;DR: When reasoning over integers, use your system's CLP(FD) constraints, then take it from there.
I am assuming that you have already put :- use_module(library(clpfd)). somewhere in your initial file, so that you can use CLP(FD) constraints in all your programs.
I'd like to assert facts about all members of a List in prolog, and have any resulting unification retained. As an example, I'd like to assert that each list member is equal to five, but none of the below constructs does this:
?- L=[X,Y,Z], forall(member(E,L), E=5).
L = [_h27057686,_h27057704,_h27057722]
X = _h27057686
Y = _h27057704
Z = _h27057722
yes
?- L=[X,Y,Z], foreach(member(E,L), E=5).
L = [_h27057686,_h27057704,_h27057722]
X = _h27057686
Y = _h27057704
Z = _h27057722
yes
I would like a way to pose the query such that X=5,Y=5, and Z=5.
There is a lot of terminology that you might be getting wrong, or I am misunderstanding you.
"Equal to" is not the same as "could unify", or "unify", but it depends how you mean it.
With SWI-Prolog, from the top level:
?- X == 5.
false. % the free variable X is not the integer 5
?- unifiable(X, 5, U).
U = [X=5]. % you could unify X with 5, then X will be 5
?- X = 5.
X = 5. % X unifies with 5 (and is now bound to the integer 5)
The comment by CapelliC already has the answer that you are most likely after: given a list of variables (either free or not), make so that each variable in the list is bound to the integer 5. This is best done by unification (the third query above). The maplist simply applies the unification to each element of the list.
PS. In case you are wondering how to read the maplist(=(5), L):
These three are equivalent:
maplist(=(5), [X,Y,Z])
maplist(=, [5,5,5], [X,Y,Z])
X=5, Y=5, Z=5
And of course X=5 is the same as =(X,5).
I am trying to generate all integers (natural numbers) smaller than a limit, let's say 10.
I have a predicate nat(X) which produces all numbers from 0 to infinity.
Now my problem is, if I do:
nat10(X) :- nat(X), X =< 10.
This will never terminate, as it tries to find other solutions with nat(X) until infinity.
I need a construct that let's me fail the whole predicate if one subgoal fails. How would I go about doing that?
Depending upon the problem being solved, you might want to consider constraint logic programming over finite domains (CLPFD).
But in this context, you need just prevent Prolog from backtracking if X > 10. The current predicate nat10/1 has no such constraint, so we'll add it:
nat10(X) :- nat(X), ( X > 10 -> !, fail ; true ).
So if X > 10, we do a cut (!) to prevent backtracking to nat(X) (thus avoiding generating natural numbers above 10 infinitely) and then simply fail. Otherwise, we succeed (true).
| ?- nat10(X).
X = 1 ? ;
X = 2 ? ;
...
X = 9 ? ;
X = 10 ? ;
(3 ms) no
| ?-
If you can use clpfd, then this answer is for you!
:- use_module(library(clpfd)).
Simply try:
nat10(X) :-
X in 0..10,
indomain(X).
just started programming with prolog and I'm having a few issues. The function I have is supposed to take a value X and copy it N number of times into M. My function returns a list of N number of memory locations. Here's the code, any ideas?
duple(N,_,M):- length(M,Q), N is Q.
duple(N,X,M):- append(X,M,Q), duple(N,X,Q).
Those are not memory adresses. Those are free variables. What you see is their internal names in your prolog system of choice. Then, as #chac pointed out (+1 btw), the third clause is not really making sense! Maybe you can try to tell us what you meant so that we can bring light about how to do it correctly.
I'm going to give you two implementations of your predicate to try to show you correct Prolog syntax:
duple1(N, X, L) :-
length(L, N),
maplist(=(X), L).
Here, in your duple1/3 predicate, we tell prolog that the length of the resulting list L is N, and then we tell it that each element of L should be unified with X for the predicate to hold.
Another to do that would be to build the resulting list "manually" through recursion:
duple2(0, _X, []).
duple2(N, X, [X|L]) :-
N > 0,
NewN is N - 1,
duple1(NewN, X, L).
Though, note that because we use >/2, is and -/2, ie arithmetic, we prevent prolog from using this predicate in several ways, such as:
?- duple1(X, Y, [xyz, xyz]).
X = 2,
Y = xyz.
This worked before, in our first predicate!
Hope this was of some help.
I suppose you call your predicate, for instance, in this way:
?- duple(3,xyz,L).
and you get
L = [_G289, _G292, _G295] ;
ERROR: Out of global stack
If you try
?- length(X,Y).
X = [],
Y = 0 ;
X = [_G299],
Y = 1 ;
X = [_G299, _G302],
Y = 2 ;
X = [_G299, _G302, _G305],
Y = 3 ;
X = [_G299, _G302, _G305, _G308],
Y = 4 .
...
you can see what's happening:
your query will match the specified *M*, displaying a list of M uninstantiated variables (memory locations), then continue backtracking and generating evee longer lists 'til there is stack space. Your second rule will never fire (and I don't really understand its purpose).
A generator is easier to write in this way:
duple(N,X,M) :- findall(X,between(1,N,_),M).
test:
?- duple(3,xyz,L).
L = [xyz, xyz, xyz].