List of mathematical operations in Prolog - list

I've created a list of a mathematic expression such as [1,+,2,-,3] and I'm trying to get this evaluated as 1+2-3 i.e 0. However, I'm having trouble implementing this.
Here is the code I've tried:
test(List, Atom) :-
atomic_list_concat(List, '', Val),
Atom is Val.
Any help would be much appreciated.

I think you should implement a parser which converts given list into syntax tree.
you should convert
[1,+,2,-,3]
into
-(+(1,2),3)
?- A is -(+(1,2),3).
A = 0.
Parser is often developed by using DCG.
You may consider about operators priority(* is stronger than +) and which direction the tree extends
I.E. you should decide
[a,+,b,+,c]
is converted into
+(a,+(b,c))
or
+(+(a,b),c)
I'm sorry for my bad English!

The problem with using atomic_list_concat is that the result is a single atom, not a term. So Prolog doesn't know how to "execute" it using is/2.
You can convert the atom to a term using term_to_atom/2:
eval_exp(List, Result) :-
atomic_list_concat(List, '', Atom), % This relates a list to an atom
term_to_atom(Term, Atom), % This relates an atom to term
Result is Term. % This evaluates a term

Related

Write a predicate sqrt_list(NumberList, ResultList) to the list of pairs consisting of a number and its square root

Write a predicate sqrt_list(NumberList, ResultList) that binds ResultList to the list of pairs consisting of a number and its square root, for each number in NumberList.
For example:
?- sqrt_list([1,4,9], Result).
Result = [[1,1.0], [4,2.0], [9,3.0]]. % expected
Using the meta-predicate maplist/3 in combination with library(lambda):
:- use_module(library(lambda)).
list_withsqrts(Es, Xss) :-
maplist(\E^[E,S]^(S is sqrt(E)), Es, Xss).
Sample query:
?- list_withsqrts([1,4,9], Xss).
Xss = [[1,1.0], [4,2.0], [9,3.0]].
A few notes:
Using fixed-length lists instead of compound terms of the same arity is generally regarded as bad coding style.
Finding good relation names is an important Prolog programming skill. In above code I used list_withsqrts instead of sqrt_list. Not famous, but arguably somewhat better...
keep dividing the original list into sublist, taking one number as head and rest as a tail. repeat the same and Note that the Prolog built-in function sqrt computes the square root and that it needs to be evaluated using is to actually do the computation:
example:
?- X is sqrt(5).
X = 2.23606797749979.
then add each result to the resultList head with numberList. as,
ResultHead=[Head|[SquareRoot]]

prolog predicate returns facts(?)

First of all, if the answer to my question is here or here
I couldn't find it so please don't kill me.
I want to write a Prolog predicate which returns a list of this form:
(list[elem, elem2], list[elem3, elem4], list[elem5, elem6]).
now I can think of several ways to return a list of this form:
([elem, elem2], [elem3, elem4],[elem5, elem6]).
but how do I make the word "list" appear there as well? what is it even? a fact? another predicate?
Thanks in advance!
You can create a compound term using the standard =../3 built-in predicate. For example:
| ?- Term =.. [list, [1,2,3]].
Term = list([1,2,3])
yes
But note that the syntax that you're trying to use, list[elem5, elem6], is not valid. Are you trying to mimic an array representation? If so, maybe use instead list(elem5, elem6)? For example:
| ?- Term =.. [list, elem5, elem6].
Term = list(elem5, elem6)
yes

Return from Prolog predicate

I have a predicate, which is true, if passed such list of pairs, for instance:
translatable([(dog,perro)], [(perro,hund)], [(dog,hund)])
Means - if "dog" translates to "perro", and "perro" translates to "hund", then it is true that "dog" translates to "hund".
Here follows full code. Returns/suggests first member of pair - given ((a, b), a) returns true, given ((a, b), X) returns X = a:
first((First, _), First).
Similar to "first", but for second pair member:
second((_, Second), Second).
This returns true if translatable word exists in list of tuples, and saves translation to Translation: (dog, Translation, [(bed,cama),(dog,perro)]
translation_exists(Word, Translation, [H|T]) :-
first(H, Word), second(H, Translation), !;
translation_exists(Word, Translation, T).
And resulting:
translatable(EnglishSpanish, SpanishGerman, EnglishGerman) :-
forall(member(Pair, EnglishGerman), (
first(Pair, Word),
second(Pair, ResultTranslation),
translation_exists(Word, Translation, EnglishSpanish),
translation_exists(Translation, ResultTranslation, SpanishGerman)
)).
This code returns true/false correctly.
But why, given
translatable([(dog,perro)], [(perro,hund)], X).
It does not returns X = [(dog,hund)]?
EDIT
To be more specific, actual goal is:
to find out if LAST dictionary has translatable pairs (and them only).
Daniel, thanks a lot, I have adopted your suggested member function - great simplification, thank you! This is all the code I have now:
lastIsTranslatable(_, _, []).
lastIsTranslatable(EngSpan, SpanGerm, [(Eng, Germ) | T]) :-
member((Eng, Span), EngSpan),
member((Span, Germ), SpanGerm),
% this is to protect endless [(dog,hund), (dog, hund), ...]
not(member((Eng, Germ), T)),
lastIsTranslatable(EngSpan, SpanGerm, T),
!.
And still, this works great finding True & False:
lastIsTranslatable([(a,b)], [(b,c)], [(a,c)]).
lastIsTranslatable([(a,b)], [(b,c)], [(a,no)]).
But for
lastIsTranslatable([(a,b)], [(b,c)], X).
result is X= [], then, after hitting ";" - false. Why?
Well, running with trace option, I see execution is failing on
not(member((Eng, Germ), T))
But otherwise resulting X will be endlessly filled with (a,c), (a,c)... Maybe there is better way to protect from duplicates?
The reason, basically, is that because EnglishGerman is uninstantiated, member/2 is free to come up with possible lists for it:
?- member((perro,X), List).
member((perro,X), List).
List = [ (perro, X)|_G18493911] ;
List = [_G18493910, (perro, X)|_G18493914] ;
List = [_G18493910, _G18493913, (perro, X)|_G18493917] ;
List = [_G18493910, _G18493913, _G18493916, (perro, X)|_G18493920]
...
This is the most direct issue, but even if you change the flow of data I think you'll still have problems:
translatable1(EnglishSpanish, SpanishGerman, EnglishGerman) :-
member((English,Spanish), EnglishSpanish),
member((Spanish,German), SpanishGerman),
member((English,German), EnglishGerman).
Note that I have foregone your first/2 and second/2 predicates in favor of pattern matching; I think this reads more clearly.
Aside: If you know your list is concrete and you don't want to generate multiple solutions, you can use memberchk/2 to verify that an element exists instead of member/2; it's cheaper and deterministic.
This works better (you get solutions, anyway) but still you get a lot more solutions than you need:
?- translatable1([(dog,perro)], [(perro,hund)], X).
X = [ (dog, hund)|_G18493925] ;
X = [_G18493924, (dog, hund)|_G18493928] ;
X = [_G18493924, _G18493927, (dog, hund)|_G18493931] a
Something which we know that our code does not know is that the cardinality of the result set should be less than or equal to the lowest cardinality of our inputs; if I have fifteen English-Spanish words and twelve Spanish-German words, I can't have more than twelve words in my English-German result. The reason our code doesn't know that is because it is trying to behave like math: our code is basically saying "for every element of English-Spanish, if there exists a matching element of Spanish-German, that is also an element of English-German." This does not tell us how to construct English-German! It only tells us a fact about English-German that we can verify with English-Spanish and Spanish-German! So it's cool, but it isn't quite enough to compute English-German.
Aside: it's conventional in Prolog to use a-b instead of (a,b); it's too easy to lull yourself into believing that Prolog has tuples when it doesn't and the operator precedence can get confusing.
So, how do we tell Prolog how to compute English-German? There are probably lots of ways but I would prefer to use select/3 because our set cardinality constraints (as well as a general sense that it will converge/halt) will emerge naturally from a computation that "uses up" the input sets as it goes.
translatable2([], _, []).
translatable2(_, [], []).
translatable2([Eng-Span|EngSpanRem], SpanGerm, EngGerm) :-
(select(Span-Germ, SpanGerm, SpanGermRem) ->
translatable2(EngSpanRem, SpanGermRem, EngGermRem),
EngGerm = [Eng-Germ|EngGermRem]
;
translatable2(EngSpanRem, SpanGerm, EngGerm)
).
The base cases should be obvious; if we are out of English-Spanish or Spanish-German, there's nothing left to compute. Then the inductive case peels the first item off the English-Spanish list and searches for a Spanish-German translation that matches. If it finds one, it uses it to build the result; otherwise, it just recurs on the remaining English-Spanish list. This way, on each iteration we at least discard an English-Spanish translation from that list, and we discard Spanish-German translations as they are used. So it seems intuitively likely that this will work and terminate without producing a bunch of extra choice points.
It seems to do the trick:
?- translatable2([dog-perro], [perro-hund], X).
X = [dog-hund] ;
X = [dog-hund].
The extra result there is because we hit both terminal cases because both lists became []; this isn't attractive but it isn't anything to worry about really either.
Now one thing that sucks about this solution is that it treats the first two parameters as in-parameters and the last one as an out-parameter and there isn't really anything you can do about this. I don't know if this is an issue for you; translatable/1 should not have this limitation, but because member((Spanish,German), SpanishGerman) happens before member((English,German), EnglishGerman) it winds up generating an infinitely large list, searching in effect for the missing Spanish-German translation.
Still, it feels like it should be possible to come up with a general purpose predicate that works as long as you supply any two of these inputs. I can do that if I know that all three lists are complete and in the same order:
translatable3([], [], []).
translatable3([X-Y|XYs], [Y-Z|YZs], [X-Z|XZs]) :-
translatable3(XYs, YZs, XZs).
And you can see it work like so:
?- translatable3([dog-perro], [perro-hund], X).
X = [dog-hund].
?- translatable3([dog-perro], X, [dog-hund]).
X = [perro-hund].
?- translatable3(X, [perro-hund], [dog-hund]).
X = [dog-perro].
But I don't know enough about your constraints to know if that could be a legitimate answer. My suspicion is no, because languages don't work that way, but who knows?
Anyway, that's three different approaches; I hope one of them is helpful to you!

a challenging list question on prolog

I am new on prolog. Can you help me to solve this problem, please.
exam(math, paul).
exam(phys, paul).
exam(cmpe, sofia).
exam(bio, george).
I want to implement the predicate otherExam(L, N). L is a lesson, and N is the list of all lessons (except L) haved by student of L.
otherExam(math,X). returns [phys]
otherExam(cmpe,X). returns []
otherExam(chem,X). returns false (no such lesson)
otherExam(math,[phys]) returns true
otherExam(X,[phys]). returns math
I haved stucked with this problem. If you help me, I will be very happy :))
check findall/3 and select/3
findall/3 is used to get all the possible results from a query
for example, findall(X,ancestor(X,paul),L) will find all X such as X is an ancestor of paul and will put them in the list L

Prolog lists and parameters and return values

I'm new to prolog and I just can't figure this out.
I'm trying to build a simple program that receives a list of predicates, searches for a specific predicate in the list, and applies a function to that predicate's parameters.
Something along these lines:
?- program([pred1(a,b,p), pred2(d,b,p), pred2 (a,c,p)]).
program (list1) :-
search(pred2(X,Y,p),list1).
doSomething (X,Y) % with the X and Y returned from search function, both of them.
Basically, I want to use all values that would return from an objective search(pred2(X,Y,p),list1) and use them on another function.
Okay, I tried some stuff in prolog and came to this:
member(X, [X | _]).
member(X, [_ | R]) :- member(X, R).
prog(L1,Out) :- member(pred2(X,Y), L1).
?- prog ([(pred1(a,b),pred2(c,b),pred2(d,a)],Out).
It gives true 2 times as it is supposed to, but I wanted to get Out = [c,b] and Out = [d,a]. How I can achieve this?
Regarding Oak's answer: I get that it isn't a procedural language but I can't figure out how to access values and use them in prolog. Your example wasn't that helpful.
For starters, I would avoiding calling these things "functions". Prolog is not a procedural language, and rules / predicates are not functions.
Basically, when you use a rule you're really asking Prolog, "give me all the values which will satisfy this rule". The rule, by itself, does not return anything.
So say you had the following in a procedural language:
f(g(3))
How would you do it in Prolog? You would need to write some predicate f(X,Y) and some predicate g(X,Y), and then you would need to use the query f(3,Y), g(Y,Z) - which means to ask Prolog to find you values for Y and Z which will satisfy this. Z is what you're interested in.
the best way to approach these filter & project requirements in prolog in my opinion is to write your filter expression such that it takes one argument and succeeds if the input argument passes the filter -
iseven(Num) :- 0 is Num % 2 .
Then write the the projection code as taking one argument that is the input, and one that is the output -
triple(NumIn, NumOut) :- NumOut is NumIn * 3 .
Then tie them together -
triple_evens(NumIn, NumOut) :- iseven(NumIn), triple(NumIn, NumOut).
Then to run this on every member of a list, we should use findall -
triple_evens_in_list(Lin, Lout) :-
findall(Num, ( member(NumL, Lin),
triple_evens(NumL, Num)
), LOut).
This could be generalized to take as arguments the name of the filter & map predicates of course. And it could be compressed down to one stmt too in the form -
findall(Num, ( member(M, List), 0 is M % 2, Num is M * 3 ), ListOut).