Uses of non-ground facts in Prolog? - prolog

In Prolog you can write a ground fact as:
lost(jen).
You can also write a non-ground fact as:
lost(X).
Does this makes any sense? Could you show me a practical/real example where non ground facts are used?
Thanks,

Another case, avoiding lists, is where most cases are "true" and you just want to exclude some few cases that are false. So you deliberately fail thoses cases, then let everything else pass through.
Then you can do, say...
inhabited(antarctica) :- !, fail.
% all the other continents are inhabited
inhabited(_).

Well, you can have other things in facts besides atoms, for example you can have lists. Once you've done that, you may want to know about a one-element list, and you can have
oneelement([X]).
Likewise, say you want to compare what is the last element in a list
lastelement([X],X).
lastelement([_|Remainder],X) :- lastelement(Remainder,X).
The very useful member predicate is defined as
member([X|_],X).
member([_|Remainder],X) :- member(Remainder,X).
Each of these uses a non-ground fact as its base case, by matching a special form that's more specific than just lost(X)

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 subBag(x, y) tests whether x, considered as a bag, is a subbag of y

I currently working on some prolog problems, one is "subBag(x, y) tests whether x, considered as a bag, is a subbag of y". My code doesn't work at all and always true. Here is my code.
delete(X,[],[]).
delete(X,[X|T],T).
delete(X,[H|T],[H|Result]):-
delete(X,T,Result).
subBag([],[]).
subBag([],[H|T]).
subBag([X|S],[H|T]):-
member(X,[H|T]),
delete(X,[H|T],Result),
subBag(S,Result).
Thank you.
What is a subbag? I take that to mean, all the items in the subbag are present in at least the same quantities as they are in the containing bag. To state it inductively, let's break it into two cases: the case where I have an empty list. Is that a subbag? Yes, of any list:
subbag([], Bag) :- is_list(Bag).
Now, the inductive case. Let's break the subbag into an item and the rest of the subbag. If this item can be removed from the containing bag, and the rest form a subbag of the remainder from the containing bag, then we have a subbag. Like so:
subbag([X|Subbag], Bag) :-
select(X, Bag, RemainingBag),
subbag(Subbag, RemainingBag).
The magic predicate select/3 is a hugely useful utility here, allowing you in one statement to say X is in Bag, and the rest of the bag is in RemainingBag. This kind of situation seems to come up all the time in processing lists in Prolog. (Note that in the SWI Prolog documentation, there is often a little orange :- icon next to the name, which will take you to the source code for that predicate, in case you've been given a stupid requirement not to use a built-in predicate by a clueless professor.)
I want to warn you that the efficiency of this solution is not great, but I actually think the nature of this problem might just be that way. The number of solutions you'll obtain from an query (like subbag(X, [1,2,3,4,5])) is going to be large; I found it to be essentially the number of permutations of a set, using the OEIS (sequence A000522).
I dont understand completely how your code should work, but i think that there is for sure too much splitting into head and tail in places where it is not necessary.
Maybe this predicate will help you to solve your problem.
isSublist(Sublist,List) :-
append([_,Sublist,_],List).
This predicate uses append/2 build-in predicate, read about it here

Prolog - Return result instead of printing in algorithm

I know there is technically no 'return' in Prolog but I did not know how to formulate the question otherwise.
I found some sample code of an algorithm for finding routes between metro stations. It works well, however it is supposed to just print the result so it makes it hard to be extended or to do a findall/3 for example.
% direct routes
findRoute(X,Y,Lines,Output) :-
line(Line,Stations),
\+ member(Line,Lines),
member(X,Stations),
member(Y,Stations),
append(Output,[[X,Line,Y]],NewOutput),
print(NewOutput).
% needs intermediate stop
findRoute(X,Y,Lines,Output) :-
line(Line,Stations),
\+ member(Line,Lines),
member(X,Stations),
member(Intermediate,Stations),
X\=Intermediate,Intermediate\=Y,
append(Output,[[X,Line,Intermediate]],NewOutput),
findRoute(Intermediate,Y,[Line|Lines],NewOutput).
line is a predicate with an atom and a list containing the stations.
For ex: line(s1, [first_stop, second_stop, third_stop])
So what I am trying to do is get rid of that print at line 11 and add an extra variable to my rule to store the result for later use. However I failed miserably because no matter what I try it either enters infinite loop or returns false.
Now:
?- findRoute(first_stop, third_stop, [], []).
% prints [[first_stop,s1,third_stop]]
Want:
?- findRoute(first_stop, third_stop, [], R).
% [[first_stop,s1,third_stop]] is stored in R
Like you, I also see this pattern frequently among Prolog beginners, especially if they are using bad books and other material:
solve :-
.... some goals ...
compute(A),
write(A).
Almost every line in the above is problematic, for the following reasons:
"solve" is imperative. This does not make sense in a declarative languague like Prolog, because you can use predicates in several directions.
"compute" is also imperative.
write/1 is a side-effect, and its output is only available on the system terminal. This gives us no easy way to actually test the predicate.
Such patterns should always simply look similar to:
solution(S) :-
condition1(...),
condition2(...),
condition_n(S).
where condition1 etc. are simply pure goals that describe what it means that S is a solution.
When querying
?- solution(S).
then bindings for S will automatically be printed on the toplevel. Let the toplevel do the printing for you!
In your case, there is a straight-forward fix: Simply make NewOutput one of the arguments, and remove the final side-effect:
route(X, Y, Lines, Output, NewOutput) :-
line(Line, Stations),
\+ member(Line, Lines),
member(X, Stations),
member(Y, Stations),
append(Output, [[X,Line,Y]], NewOutput).
Note also that I have changed the name to just route/5, because the predicate makes sense also if the arguments are all already instantiated, which is useful for testing etc.
Moreover, when describing lists, you will often benefit a lot from using dcg notation.
The code will look similar to this:
route(S, S, _) --> []. % case 1: already there
route(S0, S, Lines) --> % case 2: needs intermediate stop
{ line_stations(Line, Stations0),
maplist(dif(Line), Lines),
select(S0, Stations0, Stations),
member(S1, Stations) },
[link(S0,Line,S1)],
route(S1, S, [Line|Lines]).
Conveniently, you can use this to describe the concatenation of lists without needing append/3 so much. I have also made a few other changes to enhance purity and readability, and I leave figuring out the exact differences as an easy exercise.
You call this using the DCG interface predicate phrase/2, using:
?- phrase(route(X,Y,[]), Rs).
where Rs is the found route. Note also that I am using terms of the form link/3 to denote the links of the route. It is good practice to use dedicated terms when the arity is known. Lists are for example good if you do not know beforehand how many elements you need to represent.

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 list membership, multiple results returned

I have a standard procedure for determining membership of a list:
member(X, [X|_]).
member(X, [_|T]) :- member(X, T).
What I don't understand is why when I pose the following query:
?- member(a,[a,b]).
The result is
True;
False.
I would have thought that on satisfying the goal using the first rule (as a is the head of the list) True would be returned and that would be the end of if. It seems as if it is then attempting to satisfy the goal using the second rule and failing?
Prolog interpreter is SWI-Prolog.
Let's consider a similar query first: [Edit: Do this without adding your own definition ; member/2 is already defined]
?- member(a,[b,a]).
true.
In this case you get the optimal answer: There is exactly one solution. But when exchanging the elements in the list we get:
?- member(a,[a,b]).
true
; false.
Logically, both are just the affirmation that the query is true.
The reason for the difference is that in the second query the answer true is given immediately upon finding a as element of the list. The remaining list [b] does not contain a fitting element, but this is not yet examined. Only upon request (hitting SPACE or ;) the rest of the list is tried with the result that there is no further solution.
Essentially, this little difference gives you a hint when a computation is completely finished and when there is still some work to do. For simple queries this does not make a difference, but in more complex queries these open alternatives (choicepoints) may accumulate and use up memory.
Older toplevels always asked if you want to see a further solution, even if there was none.
Edit:
The ability to avoid asking for the next answer, if there is none, is extremely dependent on the very implementation details. Even within the same system, and the same program loaded you might get different results. In this case, however, I was using SWI's built-in definition for member/2 whereas you used your own definition, which overwrites the built-in definition.
SWI uses the following definition as built-in which is logically equivalent to yours but makes avoiding unnecessary choice points easier to SWI — but many other systems cannot profit from this:
member(B, [C|A]) :-
member_(A, B, C).
member_(_, A, A).
member_([C|A], B, _) :-
member_(A, B, C).
To make things even more complex: Many Prologs have a different toplevel that does never ask for further answers when the query does not contain a variable. So in those systems (like YAP) you get a wrong impression.
Try the following query to see this:
?- member(X,[1]).
X = 1.
SWI is again able to determine that this is the only answer. But YAP, e.g., is not.
Are you using the ";" operator after the first result then pushing return? I believe this is asking the query to look for more results and as there are none it is coming up as false.
Do you know about Prolog's cut - !?
If you change member(X, [X|_]). to member(X, [X|_]) :- !. Prolog will not try to find another solution after the first one.

Resources