Understanding how the member function works - prolog

I am working on a Prolog program. I am given a bunch of facts in the form fan(name, list of novels liked). I am writing program that will tell the names of the books that three people, sally, mark and rob have in common without repeating the names of the book. I understand how to get the intersection between two people (shown below), but I don't know how to proceed from here.
mutual_novels(Book) :-
fan(sally,S),
fan(mark,M),
fan(rob,R),
novel(Book, _),
member(Book,P),
member(Book,R).

You're on the good way, Prolog will unify directly the Book variable, so you only have to add one member clause more:
mutual_novels(Book) :-
fan(sally,S),
fan(mark,M),
fan(rob,R),
novel(Book, _),
member(Book,S),
member(Book,R),
member(Book,M).
The predicate will give you only the instances Book that assert it (member of the three lists at the same time).

Related

Returning List of possible answers

I have an assignment to make a "simple" chatbot and my main problem now is in a predicate that receives a list of atoms (Ex: ["good","morning"]) and should return a list of possible answers that are already defined in structures. Also the predicate needs to filter for keywords and only return answer that contain keywords from the list given.
I have tried checking if an element from the list is already defined in any of the defined answers. If yes it would concat to the returning list.
(This concat predicate was defined by the teacher and its basically the append/3 already defined).
ans("Hello there", 0).
ans("Hello",0).
ans("Hi",0).
ans("Good Morning",0).
ans("Good Afternoon",0).
ans("Good Night",0).
answer([], List).
answer([H|T], List):- ans(H, _), concat(List, H, List), answer([T], List).
When I run this with answer(["good"],List) and it runs to a infinite (I assume its a infinite loop because it takes a long time to run and give me an error saying that there no space left in stack)
In this case the output should be ["Good Morning", "Good Afternoon", "Good Night"].
I appreciate all the help I can get.
We've got a lot of issues here, starting with your question.
Without concat/3 and how you are calling your code, it really isn't possible for anyone to solve your problems. None of your predicates take a single argument, but you are saying the code goes into an infinite loop if you call it with one. So the best we can do is speculate until you improve your question with the missing detail.
Here's my speculated assumptions: concat/3 is probably append/3. You are calling answer(["good"], Ans).
Looking at your code, concat(List, H, List) looks very wrong to me, for two reasons:
You are trying to mutate List, which is not possible in Prolog (variables cannot change once bound).
You are supplying a non-list in H to be concatenated to List.
Another problem is that List never receives an initial binding, so most likely you have to call this predicate with an argument of [], which means you are treating it as both an input and an output value.
I think your intuition is on the right track here: it should be possible for you to find things by prefix using append/3. Unfortunately, SWI-Prolog does not store strings as lists any more, so there is another predicate you have to use: string_concat/3.
I don't think you can get the return value you want here easily. I think you need to use findall/3 or one of its friends to get multiple solutions, and if you are supplying a list of possible prefixes, you are going to get a list of lists of possible solutions. Perhaps I'm missing something obvious here. Anyway, this is the solution I found:
answer([], []).
answer([H|T], [Answers|R]) :-
findall(Answer,
(ans(Answer, _), string_concat(H, _, Answer)),
Answers),
answer(T, R).
This gives me the following output:
?- answer(["Good"], L).
L = [["Good Morning", "Good Afternoon", "Good Night"]].
Please correct your question so we can be more helpful to you!

Prolog Predicates Exam Questions

I'm studying for an Artificial Intelligence exam and struggling to understand how to answer certain questions focusing on Predicates. The two questions in particular are:
Define a predicate which behaves as follows -
?- stage_name(billie, Name).
Name = rose
yes
?- stage_name(jenna,Name).
Name = clara
yes
Write a predicate that takes two argument and is true if both actors are on the same show. Thus
?-same_show(david,clara).
is true, whilst
?-same_continent(elisabeth,skippy).
is not
I don't really understand how I would answer these questions, and I'm finding very little Prolog information online. I would appreciate some help. Apologies for the formatting.
1:
stage_name(billie,rose).
stage_name(jenna,Name) :- Name=clara.
Explanation:
Given a query, Prolog looks for an appropriate predicate according to the input parameters and the name and "executes" it. The result is either true/false if no output parameter is given. In this case there is one (Name) which can be seen from the leading capital letter. Note that there are two possible ways to implement this. The former is probably the most common (predicates of this form are called "facts" whereas predicates such as the lower are called "rules").
2:
As mentioned in my comment, I don't really understand the connection between the two given predicates. Also it feels like there is something missing such as a facts that determine which person is on which show...
Assuming such facts are missing, I would write the Prolog program as follows:
onShow(david, s1).
onShow(clara, s1).
onShow(bernie, s2).
same_show(P1, P2) :- onShow(P1,X), onShow(P2,X).
Explanation:
The predicate is only true if both P1 and P2 visit the same show X.
Hints:
A "comma" represents a logical AND operator. Having different rules with the same name and parameter count represents logical OR. Edit: As Boris mentioned in a comment, this is not exactly true. This association simply helped me to understand the connection between "Logical Predicates" and "Prolog Predicates".
Visit SWISH to test your Prolog programs.

Prolog: generate queries out of DCG

I currently have a small Prolog database containing a few people and some predicates for relations. For example:
female(anna).
female(susan).
male(john).
male(timmy).
siblings(anna, susan).
siblings(anna, john).
siblings(susan, john).
sibling(X, Y) :- siblings(X, Y) ; siblings(Y, X).
%X is brother of Y
brother(X, Y) :- male(X), sibling(X, Y).
and I have a DCG which can determine valid questions like
"who is the brother of john", which also works well.
question --> ip, verb, article, noun, pronoun, name.
Now I want my program to make a call to my family-database out of noun and name like this:
noun(X, name).
Which in the example then should be
brother(X, anna).
and then return the answer as a natural-language answer like:
"the brother of anna is john"
Defining the grammer for the answer sentence is no problem either. The only thing I don't know is, how to make the call from my DCG to my database and to get the right values filled into it. I looked around for quite some time now - perhaps I don't know the right search terms - and couldnt find something related to this.
I hope you guys have some good ideas ! :)
Thank you.
Invoking Prolog predicates from DCGs
Regular way: Use {}/1
Use the nonterminal {}//1 to call arbitrary Prolog goals from within DCGs.
For example:
verb --> [V], { verb(V) }.
This defines a nonterminal verb//1. This DCG describes a list consisting of the element V such that verb(V) holds, where verb/1 is a normal Prolog predicate.
In a sense even more regular: Use DCGs throughout!
Note that there is a second way to do this, which is in a sense even easier to understand: You can simply turn everything into DCG nonterminals!
For example, you could say:
female(anna) --> [].
female(susan) --> [].
male(john) --> [].
male(timmy) --> [].
You could then simply use these nonterminals directly. You could define a term_expansion/2 rule that does such a transformation automatically.
In your specific case, using {}/1 is likely preferable, because you already have existing Prolog facts and. But there are definitely cases where using DCGs throughout is preferable.
EDIT: From your comment, I see your question is a bit more involved.
The question is rather about:
Constructing Prolog goals from sentences
This is extremely straight-forward: Essentially, you only need to describe the relation between the Prolog goals you want and the corresponding sentences.
We do this by introducing a new argument to the DCG, and that argument will denote the Prolog goal that needs to be executed to answer the sentence. In your example, you want to relate the sentence "Who is the brother of susan?", to a call of the Prolog predicate brother(X, susan). You already have a nonterminal sentence//0 that describes such sentences. You only need to make explicit the goal that such sentences correspond to. For example:
sentence_goal(noun(X, name)) --> ip, v, a, noun, p, name.
This is only used to illustrate the principle; I'm not claiming that this is already the full solution. The point is simply to show that you can reason about Prolog goals in exactly the same way as about all other terms.
You can then invoke the actual goals in two phases:
first, relate the given sentence to the goal, using this new nonterminal sentence_goal//1
simply call the goal, using call/1 or invoking it directly.
For example:
?- phrase(sentence_goal(Goal), Sentence), Goal.
In your case, all that remains is relating such sentences to the Prolog goals you want to invoke, such as brother_of/2 etc.
None of this needs any side-effects (write/1)! Instead, concentrate on describing the relations between sentences and goals, and let the Prolog toplevel do the printing for you.

In Prolog how can I cut redundant answers

I am working on a dictionary-like program with prolog, and my code goes like this:
define(car,vehicle).
define(car,that).
define(car,has).
define(car,four).
define(car,wheels).
define(wheels,round).
define(wheels,object).
define(wheels,used).
define(wheels,in).
define(wheels,transportation).
defined(X):-define(X,_).
anotherdefined(X):- \+ undefined(X).
undefined(X):- \+define(X,_).
I am trying to write a defined/1 predicate which will give me:
?-defined(X).
X = car ;
X = wheels ;
false.
Yet, my defined/1 gives me X=car. five times (naturally) for everytime it counters define(car,_).
and my anotherdefined/1 gives me only true. What is the method to stop prolog backtracking to the other instances of define(car,_).,and skip to define(wheels,_).?
Edit: I have written the following lines to get the result I want with givedefinedword/1,
listdefined(X):-findall(Y,defined(Y),Z),sort(Z,X).
givedefinedword(X):-listdefined(List),member(X,List).
However since I wanted an efficient predicate (which I will use in many others) it beats the purpose. This predicate does too much process.
Or, Would it be better to use a predicate that modifies the code? say prepares a list of defined words, and modifies it when new definitions are added.
Thanks.
If you change define to relate items and lists, like
definelist(car, [vehicle, that, has, four, wheels]).
% etc.
defined(X) :- definelist(X, _).
then defined will no longer produce duplicates, nor require linear space.
Of course, a query define(X, Y) must now be performed as definelist(X, L), member(Y, L). If you want this to be efficient as well, you may need to duplicate all definitions.
What are you trying to achieve with your program? It seems that you want to have facts in the form:
"A car is a vehicle that has four wheels"
"Wheels are round objects used in transportation" (a bit vague)
How are you going to use these facts? #larsmans suggestion if perfectly fine, if you want to just have your statement as a "sentence". It really depends what you will do with the information though.
Consider structuring the information in your database:
is(car, vehicle).
is(bicycle, vehicle).
is(boat, vehicle).
has(car, wheel(four)).
has(car, motor).
has(bicycle, wheel(two)).
Given this database, you can at least ask a question like, "what vehicles are there?", "does a bicycle have a motor?", or maybe, "how many wheels does a car have?", or "which vehicles have no wheels?"
?- is(X, vehicle).
?- has(bicycle, motor).
?- has(car, wheel(N)).
?- is(X, vehicle), \+ has(X, wheel(_)).
and so on.
Once you have defined your problem better, you can define your data structures better, which will make writing a program to solve your problem easier.

Prolog recursion and building output from recursive calls

I am learning Prolog via http://www.learnprolognow.org and I am having some trouble understanding how to recursively build up a variable with results from another recursive call, as per Practical Session 3.4, question 3. The initial problem is a straight-forward recursive call to determine if a route is feasible. But the follow-on problem asks you to show the actual path to get to the end of the route.
We are given the following knowledge base of travel information:
byCar(auckland,hamilton).
byCar(hamilton,raglan).
byCar(valmont,saarbruecken).
byCar(valmont,metz).
byTrain(metz,frankfurt).
byTrain(saarbruecken,frankfurt).
byTrain(metz,paris).
byTrain(saarbruecken,paris).
byPlane(frankfurt,bangkok).
byPlane(frankfurt,singapore).
byPlane(paris,losAngeles).
byPlane(bangkok,auckland).
byPlane(singapore,auckland).
byPlane(losAngeles,auckland).
Write a predicate travel/2 which determines whether it is possible to
travel from one place to another by chaining together car, train, and
plane journeys. For example, your program should answer yes to the
query travel(valmont,raglan).
I solved this problem with the following code:
travel(From,To) :-
byCar(From,To).
travel(From,To) :-
byTrain(From,To).
travel(From,To) :-
byPlane(From,To).
travel(From,To) :-
byCar(From,NewTo),
travel(NewTo,To).
travel(From,To) :-
byTrain(From,NewTo),
travel(NewTo,To).
travel(From,To) :-
byPlane(From,NewTo),
travel(NewTo,To).
The follow-on problem is:
So, by using travel/2 to query the above database, you can find out
that it is possible to go from Valmont to Raglan. If you are planning
such a voyage, that’s already something useful to know, but you would
probably prefer to have the precise route from Valmont to Raglan.
Write a predicate travel/3 which tells you which route to take when
travelling from one place to another. For example, the program should
respond
X = go(valmont,metz,go(metz,paris,go(paris,losAngeles)))
to the query travel(valmont,losAngeles,X)
I have been struggling to populate X with a series of go(From,To) that show the successive steps of the journey. It looks like a recursive problem but I do not know how one should go about tackling it. This technique seems fundamental to Prolog programming, and I am quite interested in the thinking process to solve this problem and I look forward to any insight you can provide.
I had a go at this. I made one change to your first solution, just to remove some redundancy. I used the predicate connected/2 to generalize the relationship common to all connections appearing in the by_car/2, by_train/2, and by_plane/2 facts:
connected(From, To) :- by_car(From, To).
connected(From, To) :- by_train(From, To).
connected(From, To) :- by_plane(From, To).
Then I defined travel/2 as a recursive relationship over connected/2:
travel(From, To) :-
connected(From, To).
travel(From, To) :-
connected(From, Through),
travel(Through, To).
Turning to travel/3, notice that the final connection in the nested go... terms is a structure go/2, but the rest are go/3s. So we need to populate X with a series of nested go/3 structures that terminate in a go/2. This last is our base condition. Then it is simply a matter of repeating the second clause of travel/2, but including a go/3 in the third argument that will capture the values instantiated to From and Through on each iteration:
travel(From, To, go(From, To)) :-
connected(From, To).
travel(From, To, go(From, Through, Route)) :-
connected(From, Through),
travel(Through, To, Route).

Resources