I have a proof(meta-interpreter) in prolog :
solvept(true,true):- !.
solvept((A,B),(ProofA,ProofB)):-
!, solvept(A,ProofA), solvept(B,ProofB).
solvept(A,(A:-Proof)):-
clause(A,B), solvept(B,Proof).
with this KB :
son(aa,bb).
son(bb,cc).
son(rr,tt).
OK, now I want count the number of ground facts.
Who can help me?
Some hints: the clause/2 standard predicate returns the atom true in its second argument for facts. There's also a ground/1 standard predicate that allows you to test if a term is ground. Finally, you need some extra arguments to actually count the number of ground facts used during a proof. This number is initially zero and it's incremented every time you use a ground fact. Try to use an accumulator to implement the counting. Consider reporting back your implementation attempts.
Related
Looking at the code below:
multiple(X,0).
multiple(X,Y) :- lt(0,X), lt(0,Y), diff(Y,X,D), multiple(X,D).
There happens to be something wrong. For your reference:
lt/2 is whether the first argument is less than the second.
diff/3 is whether the third argument is equal to the first argument minus the second.
lt/2 and diff/3 are defined correctly.
Is there a logical mistake in the definition? Is assuming that 0 is the multiple of every number problematic or is the logical mistake somewhere else? I get correct answers but the query goes to infinite loop I think.
EDIT:
here are the other definitions.
natNum(0).
natNum(s(X)) :- natNum(X).
lt(0,s(X)) :- natNum(X).
lt(s(X),s(Y)) :- lt(X,Y).
sum(0,X,X).
sum(s(X),Y,s(Z)) :- sum(X,Y,Z).
diff(X,Y,Z) :- sum(Z,Y,X).
?- multiple(X, s(s(s(s(s(s(0))))))).
where s(0) is 1, s(s(0)) is 2 etc. It gives all the desired answers for X but after the last answer, it gets stuck. I assume in an infinite recursive loop?
What is happening in your program? Does it loop forever, or does it only take some time since you haven't updated your hardware in recent decades? We cannot tell. (Actually, we could tell by looking at your program, but that is much too complex for the moment).
What we can do with ease is narrow down the source of this costly effort. And this, without a deep understanding of your program. Let's start with the query:
?- multiple(X, s(s(s(s(s(s(0))))))).
X = s(0)
; X = s(s(0))
; X = s(s(s(0)))
; X = s(s(s(s(s(s(0))))))
; loops. % or takes too long
Isn't there an easier way to do this? All this semicolon typing. Instead, simply add false to your query. In this manner the solutions found are no longer shown and we can concentrate on this annoying looping. And, if we're at it, you can also add false goals into your program! By such goals the number of inferences might be reduced (or stays the same). And if the resulting fragment (called a failure-slice) is looping, then this is a reason why your original program loops:
multiple(_X,0) :- false.
multiple(X,Y) :- lt(0,X), false, lt(0,Y), diff(Y,X,D), multiple(X,D).
natNum(0) :- false.
natNum(s(X)) :- natNum(X), false.
lt(0,s(X)) :- natNum(X), false.
lt(s(X),s(Y)) :- false, lt(X,Y).
?- multiple(X, s(s(s(s(s(s(0))))))), false.
loops.
Do your recognize your program? Only those parts remained that are needed for a loop. And, actually in this case, we have an infinite loop.
To fix this, we need to modify something in the remaining, visible part. I'd go for lt/2 whose first clause can be generalized to lt(0, s(_)).
But wait! Why is it OK to generalize away the requirement that we have a natural number? Look at the fact multiple(X,0). which you have written. You have not demanded that X is a natural number either. This kind of over-generalizations often appears in Prolog programs. They improve termination properties at a relatively low price: Sometimes they are too general but all terms that additionally fit into the generalization are not natural numbers. They are terms like any or [a,b,c], so if they appear somewhere you know that they do not belong to the solutions.
So the idea was to put false goals into your program such that the resulting program (failure-slice) still loops. In the worst case you put false at a wrong place and the program terminates. By trial-and-error you get a minimal failure-slice. All those things that are now stroked through are irrelevant! In particular diff/3. So no need to understand it (for the moment). It suffices to look at the remaining program.
I am currently trying to understand the basics of prolog.
I have a knowledge base like this:
p(a).
p(X) :- p(X).
If I enter the query p(b), the unification with the fact fails and the rule p(X) :- p(X) is used which leads the unification with the fact to fail again. Why is the rule applied over and over again after that? Couldn't prolog return false at this point?
After a certain time I get the message "Time limit exceeded".
I'm not quite sure why prolog uses the rule over and over again, but since it is, I don't understand why I get a different error message as in the following case.
To be clear, I do understand that "p(X) if p(X)" is an unreasonable rule, but I would like to understand what exactly happens there.
If I have a knowledge base like this:
p(X) :- p(X).
p(a).
There is no chance to come to a result even with p(a) because the fact is below the rule and the rule is called over and over again. For this variant I receive a different error message almost instantly "ERROR: Out of local stack" which is comprehensible.
Now my question - what is the difference between those cases?
Why am I receiving different error messages and why is prolog not returning false after the first application of the rule in the above case? My idea would be that in the above case the procedure is kind of restarted each time the rule gets called and in the below case the same procedure calls the rule over and over again. I would be grateful if somebody could elaborate this.
Update: If I query p(a). to the 2nd KB as said I receive "Out of local stack", but if I query p(b). to the same KB I get "Time limit exceeded". This is even more confusing to me, shouldn't the constant be irrelevant for the infinite loop?
Let us first consider the following program fragment that both examples have in common:
p(X) :- p(X).
As you correctly point out, it is obvious that no particular solutions are described by this fragment in isolation. Declaratively, we can read it as: "p(X) holds if p(X) holds". OK, so we cannot deduce any concrete solution from only this clause.
This explains why p(b) cannot hold if only this fragment is considered. Additionally, p(a) does not imply p(b) either, so no matter where you put the fact p(a), you will never derive p(b) from these two clauses.
Procedurally, Prolog still attempts to find cases where p(X) holds. So, if you post ?- p(X). as a query, Prolog will try to find a resolution refutation, disregarding what it has "already tried". For this reason, it will try to prove p(X) over and over. Prolog's default resolution strategy, SLDNF resolution, keeps no memory of which branches have already been tried, and also for this reason can be implemented very efficiently, with little overhead compared to other programming languages.
The difference between an infinite deduction attempt and an out of local stack error error can only be understood procedurally, by taking into account how Prolog executes these fragments.
Prolog systems typically apply an optimization that is called tail call optimization. This is applicable if no more choice-points remain, and means that it can discard (or reuse) existing stack frames.
The key difference between your two examples is obviously where you add the fact: Either before or after the recursive clause.
In your case, if the recursive clause comes last, then no more choice-points remain at the time the goal p(X) is invoked. For this reason, an existing stack frame can be reused or discarded.
On the other hand, if you write the recursive clause first, and then query ?- q(X). (or ?- q(a).), then both clauses are applicable, and Prolog remembers this by creating a choice-point. When the recursive goal is invoked, the choice-point still exists, and therefore the stack frames pile up until they exceed the available limits.
If you query ?- p(b)., then argument indexing detects that p(a) is not applicable, and again only the recursive clause applies, independent of whether you write it before or after the fact. This explains the difference between querying p(X) (or p(a)) and p(b) (or other queries). Note that Prolog implementations differ regarding the strength of their indexing mechanisms. In any case, you should expect your Prolog system to index at least on the outermost functor and arity of the first argument. If necessary, more complex indexing schemes can be constructed manually on top of this mechanism. Modern Prolog systems provide JIT indexing, deep indexing and other mechanisms, and so they often automatically detect the exact subset of clauses that are applicable.
Note that there is a special form of resolution called SLG resolution, which you can use to improve termination properties of your programs in such cases. For example, in SWI-Prolog, you can enable SLG resolution by adding the following directives before your program:
:- use_module(library(tabling)).
:- table p/1.
With these directives, we obtain:
?- p(X).
X = a.
?- p(b).
false.
This coincides with the declarative semantics you expect from your definitions. Several other Prolog systems provide similar facilities.
It should be easy to grasp the concept of infinite loop by studying how standard repeat/0 is implemented:
repeat.
repeat :- repeat.
This creates an infinite number of choice points. First clause, repeat., simply allows for a one time execution. The second clause, repeat :- repeat. makes it infinitely deep recursion.
Adding any number of parameters:
repeat(_, _, ..., _).
repeat(Param1, Param2, ..., ParamN) :- repeat(Param1, Param2, ..., ParamN).
You may have bodies added to these clauses and have parameters of the first class having meaningful names depending on what you are trying to archive. If bodies won't contain cuts, direct or inherited from predicates used, this will be an infinite loop too just as repeat/0.
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.
% expensiveComp(+A,-Result)
% otherRule(+Arg1,Arg2+,-Result)
% r(+A,+B,C)
r(A,B,C) :-
expensiveComp(A,Result),
otherRule(Result,B,C).
If r is called multiple times with the same value for A will expensiveComp necessarily be reevaluated each time r is called, or are there circumstances under which Prolog would just bind a cached value to Result?
Are some implementations of Prolog better at knowing when they don't need to reevaluate a rule?
There's a number of Prolog implementations which feature support for different kinds of memoization, commonly called "tabling" in Prolog-lingo: b-prolog, yap, xsb.
I need to define a predicate calculator/2 that takes a list of English arithmetic expressions and yields a numerical result. The system should be able to handle numbers 1-20.
Example executions:
?- calculator([three,times,two],Total).
Total=6
yes
?- calculator([twenty,times,three,plus,five,divided_by,two], Total).
Total = 32.5
This is an extremely hard task for somebody who said "This is my first time experiencing prolog and I don't even know where to start."
I'll give you some things to start, but you really need to work through some Prolog tutorials (I've found 'Learn Prolog Now', mentioned by #mbratch in the comments, very good) to be able to do the task.
First, you can define some Prolog facts about number names (since you only have to handle only numbers 1-20, you can simply enumerate all he possibilities):
number(one, 1).
number(two, 2).
...
number(twenty, 20).
Then you can define some predicates that work for just two numbers:
calculator([A, plus, B], Result) :-
number(A, ValA), number(B, ValB), Result is ValA + ValB.
calculator([A, times, B], Result) :-
number(A, ValA), number(B, ValB), Result is ValA * ValB.
Judging from your example precedence rules of the operators are not used. Then if the list contains more than 2 numbers (more than 3 entries), you can apply above predicates to the first three list entries, and proceed recursively.
Hope you can continue from here after working through some Prolog tutorials.