Reputation: 2122
I am having trouble writing a Prolog predicate that returns the variable values for some arithmetic.
For example, the function should return what x and y can be from the equation: 12 = 3x + 2y.
Currently my code can only work the other way around:
foo(S,X,Y) :-
S is 3*X+2*Y.
Any ideas?
Upvotes: 2
Views: 1244
Reputation: 18726
Depending on the modeling domain you're in, use one of the following:
clpfd for integers
clpq for arbitrary precision rational numbers
clpr for limited-precision "real numbers", typically approximated by floating-point values
clpb for Boolean values
Here's how you can handle integers with clpfd:
:- use_module(library(clpfd)).
foo(S,X,Y) :-
S #= 3*X+2*Y.
Let's look at some sample queries!
First up: ground queries.
?- foo(1,23,-34).
true.
?- foo(1,23,-2).
false.
Next up: some queries with one-variable.
?- foo(X,1,2). X = 7. ?- foo(1,X,2). X = -1. ?- foo(1,23,X). X = -34. ?- foo(1,2,X). false.
Then, a query with one variable used in multiple places:
?- foo(X,X,X). X = 0.
At last: some more general queries.
?- foo(S,X,2).
S#=3*X+4.
?- foo(S,X,Y).
S#=3*X+2*Y.
For arbitrary-precision rational numbers, use clpq:
:- use_module(library(clpq)).
?- foo(X,X,X).
X = 0.
?- foo(1,2,X). % a similar query failed with clp(FD)
X = -5 rdiv 2. % arbitrary-precision solution
?- foo(S,X,Y).
{Y=1 rdiv 2*S-3 rdiv 2*X}.
For relations over floating-point numbers, use clpr:
:- use_module(library(clpr)).
foo(S,X,Y) :-
{ S = 3*X+2*Y }.
Sample queries:
?- foo(1,2,X). % a similar query failed with clp(FD)
X = -2.5 ; % and had an arbitrary-precision solution with clp(Q)
false.
?- foo(X,X,X).
X = 0.0 ;
false.
Upvotes: 2
Reputation:
You could go along using the var/1 predicate to check whether an argument is output:
foo(S, X, Y) :- var(X), !, X is (S-2*Y)/3.
foo(S, X, Y) :- var(Y), !, Y is (S-3*X)/2.
foo(S, X, Y) :- S is 3*X+2*Y.
Here is an example run with SWI-Prolog:
?- foo(S, 1, 2).
S = 7.
?- foo(7, X, 2).
X = 1.
?- foo(7, 1, Y).
Y = 2.
Best Regards
Upvotes: 0