Does SWI-Prolog have a way to read scientific notation? - prolog

Does SWI-Prolog have a way to read scientific notation? I couldn't find anything here or in the document. For example, is there a way to read 7.33E-05 besides hard-parsing it?
Thank you!

One option to read numbers like 7.33E-05 is by using "read_term" predicate family, e.g.:
read_term_from_atom('7.33E-05', N, [])
should parse and save 7.33E-05 into variable N.

Here's an example use of the scientific notation:
?- X = 7.33E-05, Y = 6.4E-03, Z = X+Y, Y > X.
X = 7.33e-5,
Y = 0.0064,
Z = 7.33e-5+0.0064.
To actually do simple math use:
?- use_module(library(clpr)).
?- X = 7.33E-05, Y = 6.4E-03, {Z=X+Y}.
X = 7.33e-5,
Y = 0.0064,
Z = 0.0064733

Related

Order of unknowns in Prolog constraint logic programming (clpr)

I have:
:-use_module(library(clpr)).
comp(X, Y, Z):-
{X = Y * Z, Y = Z, Y > 0, Z > 0}.
Which with the query:
?-comp(X,3,Z).
Yields:
X = 9.0,
Z = 3.0
as expected. But why doesn't
comp(9,Y,Z).
also give me values for Y and Z? What I get is instead:
{Z>0.0,Y=Z,9-Y*Z=0.0},
{9-Y*Z=0.0},
{9-Y*Z=0.0}
Thanks!
Probably a weakness of the used CLP(R) that quadratic case doesn't work so well. After Y = Z, it is evident that X = Y**2, and then with X = 9 and Y > 0, you should easily get Y = 3. Which CLP(R) do you use?
A CLP(R) need not only support linear equalities and inequalities. Using for example Gröbner Basis algorithm a CLP(R) could do more, even algebraically. Some computer algebra system can do that easily.
So I guess its not a problem of Prolog per se, rather of the library. Strictly speaking CLP(X) only indicates a domain X. For the domain R of real numbers there is wide variety of potential equation and inequation solvers.
Better with constraints over finite domains using this module:
:-use_module(library(clpfd)).
comp(X, Y, Z):-
X #= Y * Z, Y #= Z, Y #> 0, Z #> 0.
With
comp(9,Y,Z).
I get:
Y = Z, Z = 3

Recursive addition in Prolog with Peano numbers doesn't work

I'm currently trying to practice some Prolog. I just started and I'm facing a problem I don't quite understand. I want to determine recursively if one Peano number is the double of another one. I tried to solve it like this:
isDouble(0, X,X).
isDouble(s(Peano1), Peano1, Peano2) :-
isDouble(Peano1, s(Peano1), Peano2).
For some reason it doesn't work. Does anyone know why?
You don't need three arguments to define such a predicate. Just consider what relation it should describe: a relation between a number and its double. Hence you only need two arguments and two rules describing the two possibilities. Either the number is zero, then its double is zero as well. Otherwise you have a difference of two s/2 for the double in every recursion but only one for the number:
nat_double(0,0).
nat_double(s(X),s(s(Y))) :-
nat_double(X,Y).
This yields the desired results:
?- nat_double(X,Y).
X = Y, Y = 0 ; % X=0, Y=0
X = s(0), % X=1
Y = s(s(0)) ; % Y=2
X = s(s(0)), % X=2
Y = s(s(s(s(0)))) ; % Y=4
X = s(s(s(0))), % X=3
Y = s(s(s(s(s(s(0)))))) ; % Y=6
X = s(s(s(s(0)))), % X=4
Y = s(s(s(s(s(s(s(s(0)))))))) ; % Y=8
.
.
.
Or if you want to test a pair as suggested in the comments:
?- nat_double(s(s(0)),s(s(s(s(0))))).
true.
EDIT:
If you insist on the interface isDouble/3, as your comment suggests, then you could define it as a calling predicate for nat_double/2 like so:
isDouble(X,X,Y) :-
nat_double(X,Y).
That yields the desired result for your example:
?- isDouble(s(s(0)),s(s(0)),s(s(s(s(0))))).
true.

Linear equation with one unknown using Prolog

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.

Simple Prolog program - Unsure about results

Completely new to Prolog (SWI-Prolog in this case) so apologies for this very basic question. I have a simple program below.
loves(vincent,mia).
loves(marsellus,mia).
loves(pumpkin,honey_bunny).
loves(honey_bunny,pumpkin).
jealous(X, Y):- loves(X,Z), loves(Y,Z).
I'm a little confused as to the results of the following query:
?- jealous(vincent, X).
X = vincent ;
X = marsellus.
Perhaps I'm just not accustomed to the unification process of Prolog, but shouldn't the answer just be marsellus? Why is vincent included here as a valid result?
Also, as a followup question: Am I correct in that in order to get a result of all the 'jealous' people, I would write a query such as jealous(X, Y). ?
If so, can someone explain the following result of said query?
?- jealous(X, Y).
X = Y, Y = vincent ;
X = vincent,
Y = marsellus ;
X = marsellus,
Y = vincent ;
X = Y, Y = marsellus ;
X = Y, Y = pumpkin ;
X = Y, Y = honey_bunny.
Any help would be greatly appreciated. Thanks!
For your first question, I can see how the output makes sense.
You're asking for a list of people that love the same person that Vincent loves.
Since both Vincent and Marsellus love Mia, the list is {Vincent, Marsellus}, as you are getting.
I'm not sure of the syntax for Prolog but you'd want something like:
jealous(X, Y):- loves(X,Z), loves(Y,Z), X \== Y.
to remove those cases where X and Y refer to the same person, using whatever symbol in Prolog meaning "not equal to" if it's not \==.
It's a little hard to be jealous of yourself unless you're suffering from some sort of split-personality disorder and, if you are, you could argue it's not yourself you're actually jealous of, self becoming a rather fluid concept in those circumstances.
The second question output also makes sense, after a bit of thought, and is related to the same problem as described above. Looking at the output slightly reformatted:
X = Y, Y = vincent ;
X = vincent, Y = marsellus ;
X = marsellus, Y = vincent ;
X = Y, Y = marsellus ;
X = Y, Y = pumpkin ;
X = Y, Y = honey_bunny.
These are the jealousy ouputs, with the X = Y meaning exactly that, X and Y are the same, with Y being specified as the second item on each line. It can be rewritten as:
X = vincent, Y = vincent ;
X = vincent, Y = marsellus ;
X = marsellus, Y = vincent ;
X = marsellus, Y = marsellus ;
X = pumpkin, Y = pumpkin ;
X = honey_bunny, Y = honey_bunny.
In other words, similar to the first question, everyone is jealous of themselves, as well as any other people who may love a given target.
I suspect that, if you modify the jealousy detector as suggested, all that self-loathing may just disappear, and the world will be a happier place.
Well, other than for Vincent and Marsellus, who obviously still dislike each other, and who are both suffering from unrequited love. The world can sometimes be such a harsh place :-)

SICStus Prolog making product/3 rule from sum/3

First of all, this is a homework question, so please just give me a hint!
%Here is a rule that defines sum/3 that returns yes if Z is sum of X and Y
sum(X,Y,Z) :-
Z is X + Y.
%How can I make product/3
product(X,Y,Z) :- % based on sum/3 above?
Also, how can write a query on product such that it returns the answer of X * Y and not that it's merely true?
Consider that in mathematics:
x * 0 = 0
x * y = x + x * (y - 1)
That should help you write your rules.
As for a query, you can use something like this to get a result like this:
?- product(5, 3, Result).
Result = 15 ?
yes
In short, if you have an unbound variable in a query, it tries to find a value for that variable such that the predicate succeeds.

Resources