List a given number of element in a list prolog - prolog

I am trying to list a given number of elements i have stored in List , my code is as follows
er(Person,List) :- findall(A, descendant(Person, A), List).
when i type the code below into prolog i get all of the elements that match my query.
er(james,X).
What i am trying to achieve is ask prolog to list a given amount of element say for example
er(james,3).
Prolog will only return at most 3 element from the list . I researched a bit and found that i can use findnsols instead of the findall operator but i couldn't find a practical way to implement it in my code .

Well, the obvious way would be to say something like this:
er(P,N,L) :-
findnsols(N,A,descendant(P,A),L)
.
But you seem not to want to do that. You might consider something like this:
er(P,L) :-
var(L),
findall(A,descendant(P,A),L)
.
er(P,L) :-
nonvar(L),
length(L,N),
findnsols(N,A,descendant(P,A),L)
.
If you want all the solutions back, just invoke it like this:
er(james,L).
If you want to limit things, like this:
er(james,[A,B,C]).
or (since length/2 can be generative):
length(5,L) , er(james,L).

Related

How to list more than 1 output on prolog query?

Imagine my siblings, my cousins and me and our total count is 10. So i write this code and when i run it, it just give me 1 output. How can i print all the X values(names) on this query. And if possible how can i change what name comes first or how can i choose as a like what 3rd or 5th name would be ? (My granduncle is my grandfather's brother.)
Here is my code and output
granduncle(T,X) :- brother(T,Z),parent(Z,Y),parent(Y,X).
?- granduncle(john,X).
X=stan
You need to use the collection predicates:
bagof/3
setof/3
and
findall/3
to collect all the solutions into a single list.
For example:
bagof(X,granduncle(john,X),Bag).
will create a list of solutions in Bag.
Then you can slice & dice the list with predicates like:
sort/2
exclude/2
partition/4

Edit Prolog program to output the result of a computation

I've found something about this in other questions, but mine is a bit different.
Given a string, I have to output another string with no adjacent duplicates.
E.g., given [a,a,b,b,c,d,a], my output will be [a,b,c,d,a].
Now, I've wrote the following recursive program to check if a certain given string has adjacent duplicates:
notequal(A,[]).
notequal(A,[X|S]) :- not(A=X).
noadj([]):-!.
noadj([A|S]) :- notequal(A,S), noadj(S).
How would I modify it in order to output what I described? I've tried multiple times but I'm new to prolog and I can't seem to get into its logic.
Of course, I'll need another variable, which would contain an element if notequal is true for that element.
So my idea is to iterate through the list and only add a certain term to the result if it passes the "notequal" test.
I'll edit this: I finally managed to do something like that by adding
noadjlist([X|S],[X|LS]) :- notequal(X,S), noadjlist(S,LS).
noadjlist([X|S],LS) :- noadjlist(S,LS).
noadjlist([],LS):-!.
However, my results are like:
?- noadjlist([1,2,2,3],LS).
LS = [1, 2, 3|_19316] .
why do I get that uninstantiated variable at the end?
noadjlist([],LS):-!.
should be
noadjlist([],[]):-!.

Turning a relation into a fact

I would like to ask a very basic question in prolog. I have a list of lists that looks like [[a_1,a],[a_2,c],[a_3,e,f]]. I would like to create a relation which gets that list and adds an infix to each one of those sublists. For example I would like to insert x as infix: x([[a_1,a]),x([a_2,c]),x([a_3,e,f]]). The goal is to make the relation to be a fact. I was trying to use findall but without any success.
Example:
turn([[a_1,a],[a_2,c],[a_3,e,f]]).
Output:
[x([a_1,a]),x([a_2,c]),x([a_3,e,f])].
How to implement it?
[x([a])] is not, in and of itself, a fact. It's just a different Prolog term form. A fact is a term that is asserted in the database, doesn't represent a predicate, and can be queried. Sounds like you don't want to convert to "facts", but you just want to convert to a different term form.
It would be easy in this case with maplist:
turn_item(X, x(X)).
turn(TermList, NewTermList) :-
maplist(turn_item, TermList, NewTermList).
Then:
| ?- turn([[a_1,a],[a_2,c],[a_3,e,f]], L).
L = [x([a_1,a]),x([a_2,c]),x([a_3,e,f])]
yes

Summing an already outputted list

This is the knowledge base I am working with:
localLib('AHorowitz','Stormbreaker',2).
localLib('AHorowitz','Scorpia',4).
localLib('AHorowitz','Ark Angel',6).
The key for the knowledge base is as follows:
localLib(W,B,C) where
W=Writer
B=Book
C=Acknowledgements
I would like to write a rule that adds up all the acknowledgements of the writer.
This is the code I have written so far:
getAcknowledgement(W,X):- findall(C,localLib(W,_,C),X).
This rule helps me list all the acknowledgements in separate list e.g.
?- getAcknowledgement('AHorowitz',X).
X = [2, 4, 6]
I am now getting stuck on how to add these items. I know of the sum_list built in and though I know it is not correct the thing I want to achieve is this:
getAcknowledgement(W,X):- findall(C,localLib(W,_,C),X).
sum_list(X,[getAcknowledgement]).
/* I would like to sum the output that I receive from the first rule above.
The KB has been simplified in this example to 3 clauses however in reality
there are 1000.*/
How would I go about doing this, any help would be great?
It sounds like you want to find the count of acknowledgements by writer.
bagof/3 is your friend here. It
bagof(+Template, :Goal, -Bag)
Unify Bag with the alternatives of Template. If Goal has free variables besides the one
sharing with Template, bagof/3 will backtrack over the alternatives of these free
variables, unifying Bag with the corresponding alternatives of Template. The construct
+Var^Goal tells bagof/3 not to bind Var in Goal. bagof/3 fails if Goal has no
solutions.
findall/3 is
equivalent to bagof/3 with all free variables bound with the existential operator (^),
except that bagof/3 fails when Goal has no solutions.
So...this should get you the summed count of knowledgements for a given writer, or, if Writer is unbound, on backtracking, it will find the solutions for all writers, one at a time.
acknowledgements_by_writer( Writer , Acknowledgements ) :-
bagof( N , local_lib(Writer,_,N) , Ns ) ,
sum_list(Ns,Acknowledgments).
If you want the overall count of acknowledgements, something like this ought to do you
total_acknowledgements(T) :-
findall(N,local_lib(,,N),Ns),
sum_list(Ns,T).

prolog expanding predicate to iterate for multiple results, combining / resolving result sets

I have a predicate "lookupOptions" which returns one by one some lists (Menus).
I'm trying to get it to satisfy the case of multiple inputs. I can return a single set of options as follows, by reading the head of the "list_places" list.
find_options(Restaurant,Town,Menu) :- lookupOptions(Restaurant,H,Menu), list_places(Town,[H|T])
But, I'm not able to get it to iterate.
I have tried a lot of things, these were my best efforts so far.
a) standard enough iteration, but it wont resolve ...
doStuff(X,[],_).
doStuff(Restaurant,[H|T],_):- lookupOptions(Resturant,H,_), doStuff(Restaurant,T,_).
find_options(Restaurant,Town,Menu) :- doStuff(Restaurant,[H|T],Menu), list_places(Town,[H|T]).
b) expanding the goal predicate ...
find_options(_,Town,[H|T],_)
find_options(Restaurant,Town,Menu) :- find_options(Restaurant,Town,[],Menu).
find_options(Restaurant,Town,X,Menu) :- list_places(Town,X).
find_options(Restaurant,Town,[H|T],Menu) :- lookupOptions(Restaurant,[H],Menu), find_options(Restaurant,Town,T,Menu).
Would either of these work ? if the pattern was written correctly. Or if there was an appropriate cut put in place?
Any help most appreciated ...
It's no clear on what you want iterate. Prolog uses backtracking to examine all alternatives, then you should start backtracking if you are after some alternative, or use the all solutions family.
Now I think you want simply declare there could be more find_options(Restaurant,Town,Menu). Then try replacing the head match [H|T] with this:
find_options(Restaurant,Town,Menu) :-
lookupOptions(Restaurant,H,Menu),
list_places(Town, Places),
member(H, Places).
BTW T is a singleton in your original rule. This could be a hint for the need of generalize it.

Resources