Related
let say i have the following facts :
book(65).
own(named('Peter'), 65).
now got the query as a list of clauses :
[what(A), own(named('Peter'), A)]
or
[who(X), book(A), own(X, A)] .
how do I make a rule that accept this list and return the result. Keep in mind that the question could be Why,When,Who...
I went the usual way :
query_lst([]).
%% query_lst([what(Q)|T], Q) :- query_lst(T).
query_lst([H|T]) :- write('?- '),writeln(H),
call(H), query_lst(T).
but this does not allow binding of Q in wh(Q) to the answer which could be in any of the facts that are called by call()
Additional complication I did not forsee is that the query :
(what(A), own(named('Peter'), A).
would fail, because there is no what(X), fact in the DB.
I have to just bind somehow the variable A /that is in what()/ to query_lst(Goals,A) and of course remove what(X) from the list /which i can do with select/3 /
any idea how to bind list-Wh-var to query_lst result ?
my current solution (assumes Q is first element):
query_lst([G|Gs],Res) :- G =.. [Q,Res], member(Q,[what,why,who,when]), lst2conj(Gs,Conj), call(Conj).
Simply convert the list of goals into a conjunction and call it:
list_to_conjunction([], true).
list_to_conjunction([Goal| Goals], Conjunction) :-
list_to_conjunction(Goals, Goal, Conjunction).
list_to_conjunction([], Conjunction, Conjunction).
list_to_conjunction([Next| Goals], Goal, (Goal,Conjunction)) :-
list_to_conjunction(Goals, Next, Conjunction).
Then:
query_list(Goals) :-
list_to_conjunction(Goals, Conjunction),
call(Conjunction).
You got an answer, but it was an answer to your question, not to what you really wanted. Also, you edited your question after you accepted that answer, which isn't very helpful. Typically it's better to open a new question when you have... a new question.
Here is an answer to what you seem to want, which is not exactly what you asked. You have lists of the form [WhPart | Rest] where the WhPart is a wh-word with a variable, and the Rest is a list of goals. You want to execute these goals and get the variable in the wh-term bound.
The good news is that, since the variable in the wh-word also occurs in the goals, it will be bound if you execute them. No extra work is needed. Executing the goals is enough. If the wh-part is really at the start of the list, you can do the whole thing like this:
query([_WhPart | Body]) :-
call_body(Body).
call_body([]).
call_body([Goal | Goals]) :-
call(Goal),
call_body(Goals).
For example:
?- query([who(X), book(A), own(X, A)]).
X = named('Peter'),
A = 65.
?- query([what(A), own(named('Peter'), A)]).
A = 65.
As you can see, there is no need to convert the query to a conjunctive goal: Executing the queries in sequence is exactly the same as executing their conjunction.
Also, it doesn't actually matter which wh-word is used; the only thing that really matters is the variable contained within the term. For this reason the above version does no checking at all, and the _WhPart could be anything. If you want to check that it is a valid term, you can do the following:
query([WhPart | Body]) :-
wh(WhPart),
call_body(Body).
wh(who(_X)).
wh(what(_X)).
wh(when(_X)).
This buys you some "type checking":
?- query([foo(A), own(named('Peter'), A)]).
false.
But not a lot, since you don't know if the wh-word actually fits what is being asked:
?- query([when(A), own(named('Peter'), A)]).
A = 65.
Given a list of lists of integers, e.g. [[3,10],[3,10,2],[5],[5,2],[5,3],[5,3,2],[5,3,10]], I want to go over each sublist and count how many of them sum to 15. In this case that would be 1, for the sublist [3,10,2].
I am aware of the predicate aggregate_all/3, but I'm having trouble writing a predicate to check each element of the list, what I have now is something like
fifteens([X|Xs]) :-
sum_list(X, 15),
fifteens(Xs).
and within another predicate I have:
aggregate_all(count, fifteens(Combinations), Value).
where Combinations is the list of lists of integers in question.
I know my fifteens predicate is flawed since it's saying that all elements of the nested list must sum to 15, but to fix this how do I take out each element of Combinations and check those individually? Do I even need to? Thanks.
First of all your fifteens/2 predicate has no because for empty list and thus it will always fails because due to the recursion eventually fifteens([]) will be called and fail.
Also you need to change completely the definition of fifteens, currently even if you add base case, it says check ALL elements-sublists to see if they sum to 15. That's Ok but I don't see how you could use it with aggregate.
To use aggregate/3 you need to express with fifteens/2, something like: for every part of my combinations list check separately each sublist i.e each member:
ifteens(L) :-
member(X,L),
sum_list(X, 15).
Now trying:
?- aggregate_all(count, ifteens([[3,10],[3,10,2],[5],[5,2],[5,3],[5,3,2],[5,3,10]]), Value).
Value = 1.
This is a job for ... foldl/4. Functional programming idioms in logic programming languages? Yes, we can!
First, summing the summable values of a list:
sum_them(List,Sum) :-
foldl(sum_goal,List,0,Sum).
sum_goal(Element,FromLeft,ToRight) :-
must_be(number,Element),
must_be(number,FromLeft),
ToRight is Element+FromLeft.
Then, counting the ones that sum to 15:
count_them(List,Count) :-
foldl(count_goal,List,0,Count).
count_goal(Element,FromLeft,ToRight) :-
must_be(list(number),Element),
must_be(number,FromLeft),
sum_them(Element,15) -> succ(FromLeft,ToRight) ; FromLeft = ToRight.
Does it work? Let's write some unit tests:
:- begin_tests(fifteen_with_foldl).
test("first test",true(R==1)) :-
count_them([[3,10],[3,10,2],[5],[5,2],[5,3],[5,3,2],[5,3,10]],R).
test("test on empty",true(R==0)) :-
count_them([],R).
test("test with 2 hist",true(R==2)) :-
count_them([[15],[],[1,1,1,1,1,10]],R).
:- end_tests(fifteen_with_foldl).
And so:
% PL-Unit: fifteen_with_foldl ... done
% All 3 tests passed
true.
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!
I'm traying to learn the basics of logic programming.
I solved some exercises, and now I'm having trouble on creating a function that take two arguments, a list of non empty lists whose elements concatenated together form the second argument.
By the time I created a function that concat the elements of a list of lists:
concat([[]|L],L3):- concat(L,L3).
concat([[Head|L1]|L2],[Head|L3]):- concat([L1|L2],L3),!.
Now, what I need to know is how to take the return value of that function and compare it with a list (the second argument of the function).
This is one approach that will allow down to single elements in a sublist, but not an empty sublist:
concat([[L]], [L]).
concat([[H],L|T], [H|R]) :- concat([L|T], R).
concat([[H1,H2|T]|LT], [H1|RT]) :- concat([[H2|T]|LT], RT).
The method here to avoid an empty list is to call out two head elements in the recursive clause, and a solitary element list in the base case. This prevents empty sublists from succeeding, as requested in the comments of the original post.
If you have a variable, Y that is already instantiated, and you want to know if it is the result of concatenating the list of lists, LL, you simply query:
concat(LL, Y).
This will be true if Y is the concatenation of list LL and false if it is not. You don't have to "return and compare" (as, for example, in C, you might say, concat(LL) == Y, or concat(LL, X); if (X == Y)...). This is because concat is a relation defined between the two arguments and it determine if the query can be made true by following the stated rules (clauses of the predicate).
If you already obtained a result and want to determine if it's unifiable to another variable, Z, then you can say:
concat(X, Y), Y = Z.
Note that, in Prolog, concat(X, Y) == Z is not correct to determine if the result of the predicate is equal to Z because it is not a function that returns a value.
Prolog doesn't have functions or return values in the sense of a procedural programming language. It has predicates, which assert a relationship. It has terms, which include variables which comes with some strictures:
All variables are local, and
A variable, once assigned a value, ceases to be variable. That's why it's called unification.
So....
If you want a predicate that will take two lists and produce their concatenation, you'll need to pass it a 3rd variable. You might invoke it like this:
concat([a,b],[c,d],X).
which asserts that X is the concatenation of [a,b] and [c,d]. Prolog's inference engine will then evaluate the truth or falseness of the assertion.
Most recursive problems has a few special cases and a more general case. The implementation of such a concat/3 predicate might look something like this (annotated to explain what it's doing).
First, we have one special (and terminating) case: If the left-hand list is empty, the concatenation is simply the right-hand list.
concat( [] , Bs , Bs ).
Next, we have the one general case: if the left-hand list is non-empty, we need to prepend it to the concatentation that we're building (and then recurse down.)
concat( [A|As] , Bs , [A|Cs] ) :-
concat(As,Bs,Cs).
That's all there is two it. You'll also notice that it's bi-directional: it's perfectly happy to split lists apart as well. Invoking it like this:
concat( Prefix , Suffix, [a,b,c,d] ).
will, on backtracking, produce all the possible ways that [a,b,c,d] could be split into a prefix and suffix:
Prefix Suffix
--------- ---------
[] [a,b,c,d]
[a] [b,c,d]
[a,b] [c,d]
[a,b,c] [d]
[a,b,c,d] []
You just need the base case
concat([],[]).
concat([[]|L],L3):- concat(L,L3).
concat([[Head|L1]|L2],[Head|L3]):- concat([L1|L2],L3).
It also works for empty (sub)lists.
I've removed the useless cut.
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).