Related
I'm new to prolog and I've been having trouble with some homework.
On some part of my code I have to generate subsets of a given set on backtracking. Meaning, the code should try for a subset, and when it fails the next condition, try the next subset. I have done some research and the default function subset won't backtrack because as explained in this question both arguments are input arguments. So I built a custom one, which still isn't backtracking. Can you give me a hint on what I'm failing on? Here's my code:
numNutrients(8).
product(milk,[2,4,6]).
product(porkChops,[1,8]).
product(yoghurt,[3,1]).
product(honey,[5,7]).
product(plastic,[3,5,2]).
product(magic,[5,7,8]).
nutrientlist(N,L):-findall(I,between(1,N,I),L).
subset2([],[]):-!.
subset2([X|T],[X|T2]):-
subset2(T,T2).
subset2([_|T],[T2]):-
subset2(T,T2).
shopping(K,L):-
numNutrients(J),
nutrientlist(J,N),
findall(P,product(P,_),Z),
subset2(X,Z),
length(X,T),
T =< K,
covers(X,N),
L = X.
covers(_,[]):-!.
covers([X|L],N):-
product(X,M),
subset2(M,N),
subtract(N,M,T),
covers(L,T).
main:-
shopping(5,L),
write(L).
The problem is on predicate shopping(K,L). When it gets to predicate subset2, it gives the whole set, which has length 6 (not 5), then fails and doesn't backtrack. Since all previous predicates can't backtrack it just fails.
So, why doesn't subset2 backtrack?
Thank you for your time.
Primary focus: subset2/2
First, let us focus only on the predicate that shows different properties from those you expect.
In your case, this is only subset2/2, defined by you as:
subset2([], []) :- !.
subset2([X|T], [X|T2]) :-
subset2(T, T2).
subset2([_|T], [T2]) :-
subset2(T, T2).
I will now use declarative debugging to locate the cause of the problem.
For this method to apply, I remove the !/0, because declarative debugging works best on pure and monotonic logic programs. See logical-purity for more information. Thus, we shall work on:
subset2([], []).
subset2([X|T], [X|T2]) :-
subset2(T, T2).
subset2([_|T], [T2]) :-
subset2(T, T2).
Test cases
Let us first construct a test case that yields unintended answers. For example:
?- subset2([a], [a,b]).
false.
That obviously not intended. Can we generalize the test case? Yes:
?- subset2([a], [a,b|_]).
false.
So, we have now an infinite family of examples that yield wrong results.
Exercise: Are there also cases where the program is too general, i.e., test cases that succeed although they should fail?
Locating mistakes
Why have we seen unintended failure in the cases above? To locate these mistakes, let us generalize the program.
For example:
subset2(_, []).
subset2([_|T], [_|T2]) :-
subset2(T, T2).
subset2(_, [T2]) :-
subset2(T, T2).
Even with this massive generalization, we still have:
?- subset2([a], [a,b|_]).
false.
That is, we have many cases where we expect the query to succeed, but it fails. This means that the remaining program, even though it is a massive generalization of the original program, is still too specific.
Correcting the program
To make the shown cases succeed, we have to either:
add clauses that describe the cases we need
or change the existing clauses to cover these cases too.
For example, a way out would be to add the following clause to the database:
subset2([a], [a,b|_]).
We could even generalize it to:
subset2([a], [a|_]).
Adding either or both of these clauses to the program would make the query succeed:
?- subset2([a], [a,b|_]).
true.
However, that is of course not the general definition of subset2/2 we are looking for, since it would for example still fail in cases like:
?- subset2([x], [x,y|_]).
false.
Therefore, let us go with the other option, and correct the existing definition. In particular, let us consider the last clause of the generalized program:
subset2(_, [T2]) :-
subset2(T, T2).
Note that this only holds if the second argument is a list with exactly one element which is subject to further constraints. This seems way too specific!
Therefore, I recommend you start by changing this clause so that it at least makes the test cases collected so far all succeed. Then, add the necessary specializations to make it succeed precisely for the intended cases.
I have some program about a graph with black and white vertices:
black(root).
black(v1).
black(v3).
black(v4).
edge(root,root).
edge(v1,root).
edge(v2,v1).
edge(v3,v1).
edge(v4,v3).
edge(v5,v2).
edge(v5,v4).
edge(v6,v5).
vertex(X) :- edge(X,_).
vertex(X) :- edge(_,X).
white(X) :-
vertex(X),
not(black(X)).
foo(root).
foo(X) :-
edge(X,Y),
black(Y),
foo(Y).
when I run the goal foo(X) I get a problem:
If I remove the fact edge(root,root) the program find some solutions (6 different solutions). Otherwise, I get infinite solutions and all are X=root.
Why does this happen?
First a quick answer which shows you a bit how a Prolog programmer looks at your program, the explanation to it is below. Your program does not terminate, because the following failure-slice does not terminate:
black(root).
black(v1) :- false.
black(v3) :- false.
black(v4) :- false.
edge(root,root).
edge(v1,root) :- false.
edge(v2,v1) :- false.
edge(v3,v1) :- false.
edge(v4,v3) :- false.
edge(v5,v2) :- false.
edge(v5,v4) :- false.
edge(v6,v5) :- false.
foo(root) :- false.
foo(X) :- X = root, Y = root,
edge(X,Y),
black(Y),
foo(Y), false.
All through-striken text is irrelevant to understand non-termination. As you can see the remainder is relatively short and thus fast to grasp.
Prolog is not able to detect this loop directly. However, you can use closure0/3 defined here for this purpose:
edge_toblack(X, Y) :-
edge(X, Y),
black(Y).
foo(X) :-
closure0(edge_toblack, X,root).
Now for the details.
Before answering your question why this happens, let's take a step back. We need first to find a good way to observe the problem. The goal foo(X) does produce answers, actually only X = root. So maybe you are just impatient waiting Prolog to finish? By asking the query foo(X), false instead, we get rid of these irritating, eye-straining answers, and we will just wait to get false as an answer back.
Still we cannot be sure about the non-termination property of the program. But we can narrow down the actual reason by inserting goals false (and also (=)/2). In the above failure-slice I have inserted the maximum. If you are just starting, simply add one false and then reload the program and retry the query. With some experience you will soon be able to identify such parts rapidly. So now we only have to understand
foo(root) :-
edge(root,root), % always true
black(root), % always true
foo(root), false.
or even shorter
foo(root) :-
foo(root).
Prolog's very simple but efficient execution mechanism does not detect such loops. There are essentially several ways out:
add loop detection manually. This is typically very prone to errors
use closure0/3 - see above
write your own meta-interpreter to detect loops in general
use a language extension like tabling, offered in B-Prolog or XSB-Prolog.
I'm trying to write a program that can check if the student program can fulfill a certain goal or not. I can do that part. Now, I want to check if the student program actually contains unnecessary code or not. For solving this case, I think I need to know if the student program contains facts that do not contribute to the specified goal. However, I cannot figure it out, how to find facts that do not contribute to the goal.
To make it easier to understand, let's consider a simpler example. In this example, the specified goal is: is john the grandfather of tomy?
father(john, jim).
father(jim, tomy).
father(john, david).
father(bruce, anne).
mother(mary, jim).
grandfather(A,B) :- father(A, X), father(X,B).
goal:- grandfather(john, tomy).
Actually the goal can be satisfied by the following facts only:
father(john, jim).
father(jim, tomy).
And the things that I want to know is which facts that actually do not contribute to the goal. The answer would be all the following facts:
father(john, david).
father(bruce, anne).
mother(mary, jim).
Any help is really appreciated.
Thanks
Your question cannot be directly answered in Prolog, but you can answer it manually by using a failure-slice. Simply add false goals into your program and always test whether goal still succeeds. Here is the minimal program I obtained.
father(john, jim).
father(jim, tomy).
father(john, david) :- false.
father(bruce, anne) :- false.
mother(mary, jim) :- false.
grandfather(A,B) :- father(A, X), father(X,B).
goal:- grandfather(john, tomy).
Every time you insert a goal false into a pure, monotonic program, you know for sure that the set of solutions is reduced (or stays the same). So finding such a slice involves about as many trials as there are places to set such goals. Sometimes you might want to add goals X = term to narrow down the program even further.
Failure slices are particularly useful when you want to understand the termination properties of a program, see failure-slice for more.
Unbelievably, there is a partial solution to this problem here. To reproduce the relevant portion here is substantial code, so let me make it clear that this is not my own work, I am just including the work here in case the website above goes missing in the future.
First, you need a meta-circular interpreter:
mi_circ(true).
mi_circ((A,B)) :-
mi_circ(A),
mi_circ(B).
mi_circ(clause(A,B)) :-
clause(A,B).
mi_circ(A \= B) :-
A \= B.
mi_circ(G) :-
G \= true,
G \= (_,_),
G \= (_\=_),
G \= clause(_,_),
clause(G, Body),
mi_circ(Body).
This works for \=/2 and clause/2. To generalize this pattern to all built-in predicates, we can use predicate_property/2 to identify them as such for calling them directly:
provable(true, _) :- !.
provable((G1,G2), Defs) :- !,
provable(G1, Defs),
provable(G2, Defs).
provable(BI, _) :-
predicate_property(BI, built_in),
!,
call(BI).
provable(Goal, Defs) :-
member(Def, Defs),
copy_term(Def, Goal-Body),
provable(Body, Defs).
This gives you a reified meta-interpreter, meaning you can pass provable/2 a goal and a set of definitions and it will tell you whether the definitions supplied are sufficient to prove the goal. I bet you can taste how close we are to the final solution now!
With the following additional definitions, we can use this MI to identify redundant facts in some predicate definitions:
redundant(Functor/Arity, Reds) :-
functor(Term, Functor, Arity),
findall(Term-Body, clause(Term, Body), Defs),
setof(Red, Defs^redundant_(Defs, Red), Reds).
redundant_(Defs, Fact) :-
select(Fact-true, Defs, Rest),
once(provable(Fact, Rest)).
This is using select/3 to portion out one definition at a time and see if the predicate is still provable. By doing that across all the definitions you can get the set of all unnecessary rules.
Given the definitions:
as([]).
as([a]). % redundant
as([a,a]). % redundant
as([A|As]) :-
A = a, % test built-in =/2
5 is 2 + 3, % test built-in is/2
1 > 0, % test built-in >/2
as(As).
we can ask for facts which are deducible from all (respective) remaining clauses and hence redundant:
?- redundant(as/1, Reds).
Reds = [as([a]), as([a, a])]
Alas, this does not work out-of-the-box on your problem, but I do think that with some study you could find a way to apply this technique to it and come up with something. For instance, you could create a meta-interpreter that takes a list of facts to check and perform the same sort of remove-one-then-prove loop to find them.
Hope this helps and is at least interesting.
Another option is to modify and use a unit testing framework that does predicate clause coverage. Define a unit test with the goal for which you want to find out which clauses don't contribute to it. The modifying bit, if necessary, will be to modify the coverage report to also identify those clauses. Just as an example of what I mean, in case it's not clear, consider the following output of the Logtalk lgtunit tool using one of the examples in the Logtalk distribution:
?- {ack(tester)}.
%
% tests started at 2013/6/5, 19:54:9
% running tests from object tests
% file: /Users/pmoura/logtalk/examples/ack/tests.lgt
% ack_1: success
% ack_2: success
% ack_3: success
% 3 tests: 0 skipped, 3 passed, 0 failed
% completed tests from object tests
% ack: ack/3 - [1,2,3] (3/3)
% 1 unit declared in the test file containing 3 clauses
% 1 unit covered containing 3 clauses
% 3 out of 3 clauses covered, 100,000000% coverage
% tests ended at 2013/6/5, 19:54:9
%
true.
The line:
% ack: ack/3 - [1,2,3] (3/3)
shows which clauses were used by the three unit tests for the ack/3 predicate.
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.
I have a database of facts like this:
li(a,2).
li(b,3).
li(b,1).
li(c,2).
li(d,1).
li(d,1).
I need to write a predicate more(+Let) that succeeds if it exists more than one fact li(Let,_).
For example the queries more(b) and more(d) will succeed, but more(a) and more(c) will not.
My idea was to check if li(Let,_) succeeds more than once, but I do not know how to do it.
Try findall/3:
findall(X, li(d,X), L), length(L,N), N>1.
Abstracting the d out and making a predicate is trivial. Right? :)
If you don't want to use any of the predicates like findall, you can change the representation of your knowledge - bring it down one level, so to speak:
my_knowledge(li, [a-2,b-3,b-1,c-2,d-1,d-1]).
and then you can use SWI Prolog's predicate select/3 to handle it:
select_knowledge(kn, key, R):-
my_knowledge(kn,L),
select_key(L,key,R).
select_key(L,K,R):-
select(K-X,L,L1) -> R=[X|R1], select_key(L1,K,R1)
; R = [].
You can rewrite the last predicate as basic recursion over lists, and then tweak it to stop after getting first N results.
more_than_once(Goal) :-
\+ \+ call_nth(Goal,2).
With call_nth/2 as defined in this answer.
The big advantage of this solution compared to the other solutions proposed is that it will succeed rapidly even if there is a very large sequence of answers. In fact, it will even succeed for an infinite sequence of answers:
?- more_than_once(repeat).
true.
?- more_than_once(between(1,100000,_)).
true.
(The implementation of call_nth/2 uses some non-standard, low-level built-ins of SWI. It is possible to avoid that, but with even more headache.)
SWI-Prolog has library(aggregate).
:- [library(aggregate)].
more(Key) :- aggregate_all(count, li(Key, _), C), C > 1.
test:
?- more(b).
true.
?- more(a).
false.
It's not very easy to learn, but useful to handle such common tasks. If you have a very large code base, then findall (and aggregate as well, that uses findall inside) could be inefficient, building a list only to count its elements.
Then you could use a side effect based predicate: in this related answer you'll find such utility. For max efficiency, see the comments, where is explained how to use nb_setval/nb_getval...