Prolog, issues with base case failing - recursion

I'm currently writing a prolog A* search function, and ran into an issue with one of my queries. So I decided to manually test the base case, as that's where the trace was failing.
addAChild([Child],[],[Child]):-
write(woo empty).
I manually ran:
addAChild([c(1,1,p(1,2)),[]],[],A).
but it just fails.
Any help would be appreciated.

[Child] (a 1-element list) cannot unify with [c(1,1,p(1,2)),[]] (a 2-elements list).
That's why it is failing.
You can manually test in the interactive interpreter that those two terms fail to unify:
?- addAChild([Child],[],[Child]) = addAChild([c(1,1,p(1,2)),[]],[],A).
false.
and then you can inspect recursively which part is failing.
The term name (addAChild) and the arity (3) is the same, so we can rule off this issue.
Then proceed to unify each argument:
?- [Child] = A.
A = [Child].
?- [] = [].
true.
?- [Child] = [c(1,1,p(1,2)),[]].
false.

Related

How to list the clauses inside a module in SWI-Prolog?

SWI-Prolog has for example the library(dcgbasics) for use with DCGs.
While referencing the module is easy with use_module/1, e.g.
:- use_module(library(dcg/basics)).
trying to use listing/1 with it is not so easy.
?- listing(dcg:_).
true.
?- listing(dcgbasics:_).
true.
?- basics:listing.
true.
What is the correct way to get a listing of the clauses in library(dcg/basics)?
Follow up after answer given.
To list a specific clause, e.g. blanks//0 the query is
?- listing(dcg_basics:blanks).
blanks(A, B) :-
blank(A, C),
!,
D=C,
blanks(D, B).
blanks(A, A).
true.
Use either:
?- dcg_basics:listing.
Or:
?- listing(dcg_basics:_).
The first argument of use_module/1-2 is a file specification, not a module name. But listing the module contents requires the actual module name, which may be different (as it is the case here) from the module file basename. But how to find the module name from the file specification? In the particular case of SWI-Prolog:
?- absolute_file_name(library(dcg/basics), Path, [extensions([pl])]),
module_property(Module, file(Path)).
Path = '/Users/pmoura/lib/swipl/library/dcg/basics.pl',
Module = dcg_basics.

Mirror binary tree in Prolog

What I have...
tree(nil).
tree(b(Left,_,Right)) :-
tree(Left),
tree(Right).
mirror(b(Left,Head,Right), NewTree) :-
mirror(Left,NewLeft),
mirror(Right,NewRight),
NewTree = b(NewRight,Head,NewLeft).
What I'm querying...
mirror(b(nil,a,b(nil,b,nil)), Result).
Expected result
Result = b(b(nil,b,nil),a,nil).
The tree b(Left,Right,Head) is the first argument of mirror, NewTree is the goal. mirror(Left,NewLeft) recurses through the left side and yields the goal NewLeft, same for Right. NewTree is the tree b(NewRight,Head,NewLeft).
I'm not sure why this isn't working could someone please help.
Based on your current code
tree(nil).
tree(b(Left,_,Right)) :-
tree(Left),
tree(Right).
mirror(b(Left,Head,Right), NewTree) :-
mirror(Left,NewLeft),
mirror(Right,NewRight),
NewTree = b(NewRight,Head,NewLeft).
you are very close.
As noted in a comment by Steven
You're missing the base case for mirror/2. What should NewTree be when the input tree is nil?
is very helpful.
Before getting to the full working predicate lets clear up a other things.
The predicate for tree is not needed.
tree(nil).
tree(b(Left,_,Right)) :-
tree(Left),
tree(Right).
I don't know if you are showing this to shows us that you know how a tree works or what but for others reading this predicate it is not needed for the answer.
That leaves only
mirror(b(Left,Head,Right), NewTree) :-
mirror(Left,NewLeft),
mirror(Right,NewRight),
NewTree = b(NewRight,Head,NewLeft).
A standard style with using a variable that works like an input and output with several usages is for the starting one, append a 0, then for each succeeding use increase the appended number and for the result append nothing.
mirror(b(Left0,Head,Right0), NewTree) :-
mirror(Left0,Left),
mirror(Right0,Right),
NewTree = b(Right,Head,Left).
Next =/2 is just doing unification. This can be refactored as such
mirror(b(Left0,Head,Right0), b(Right,Head,Left)) :-
mirror(Left0,Left),
mirror(Right0,Right).
Now back to your problem
Since a tree is a recursive structure, it can be processed with with recursion. Predicates that work on recursive data structures need a base clause and a clause to do the recursion. You already have a clause to do the recursion but just need a base clause.
If you use the SWI-Prolog gui tracer on your code for the query
mirror(b(nil,a,b(nil,b,nil)), Result).
you will see
that when one of the branches is just nil there is no mirror/2 rule to handle this case.
Adding
mirror(nil,nil).
will solve your problem.
?- mirror(b(nil,a,b(nil,b,nil)), Result).
Result = b(b(nil, b, nil), a, nil).
The entire predicate.
mirror(nil,nil).
mirror(b(Left0,Head,Right0), b(Right,Head,Left)) :-
mirror(Left0,Left),
mirror(Right0,Right).

Prolog, working with recursion [duplicate]

I wanted to write evaluating predicate in Prolog for arithmetics and I found this:
eval(A+B,CV):-eval(A,AV),eval(B,BV),CV is AV+BV.
eval(A-B,CV):-eval(A,AV),eval(B,BV),CV is AV-BV.
eval(A*B,CV):-eval(A,AV),eval(B,BV),CV is AV*BV.
eval(Num,Num):-number(Num).
Which is great but not very DRY.
I've also found this:
:- op(100,fy,neg), op(200,yfx,and), op(300,yfx,or).
positive(Formula) :-
atom(Formula).
positive(Formula) :-
Formula =.. [_,Left,Right],
positive(Left),
positive(Right).
?- positive((p or q) and (q or r)).
Yes
?- positive(p and (neg q or r)).
No
Operator is here matched with _ and arguments are matched with Left and Right.
So I came up with this:
eval(Formula, Value) :-
Formula =.. [Op, L, R], Value is Op(L,R).
It would be DRY as hell if only it worked but it gives Syntax error: Operator expected instead.
Is there a way in Prolog to apply operator to arguments in such a case?
Your almost DRY solution does not work for several reasons:
Formula =.. [Op, L, R] refers to binary operators only. You certainly want to refer to numbers too.
The arguments L and R are not considered at all.
Op(L,R) is not valid Prolog syntax.
on the plus side, your attempt produces a clean instantiation error for a variable, whereas positive/1 would fail and eval/2 loops which is at least better than failing.
Since your operators are practically identical to those used by (is)/2 you might want to check first and only then reuse (is)/2.
eval2(E, R) :-
isexpr(E),
R is E.
isexpr(BinOp) :-
BinOp =.. [F,L,R],
admissibleop(F),
isexpr(L),
isexpr(R).
isexpr(N) :-
number(N).
admissibleop(*).
admissibleop(+).
% admissibleop(/).
admissibleop(-).
Note that number/1 fails for a variable - which leads to many erroneous programs. A safe alternative would be
t_number(N) :-
functor(N,_,0),
number(N).

issues regarding prolog backtracking to find other solution

I am beginner of Prolog.
what I have is a function traverse a list and return true when it satisfies the condition.
for example, check_version checks if the package version met the condition(eg. the version satisfies the condition such as greater than or less than the specific version) and check_all checks takes a list of versions and conditions to check one by one.
package('python', '2.6.5').
package('python', '2.5.4').
package('python', '1.5.2').
package('python', '3.1.0').
check_version(Pac, Ver, Cmp, V):-
package(Pac, V),
cmp_version(V, Ver, Cmp).
check_all( Pac, [], [], V):-
package(Pac, V).
check_all(Pac, [Ver], [Cmp], V):-
check_version(Pac, Ver, Cmp, V).
check_all(Pac, [Ver|VerS], [Cmp|CmpS], V):-
check_version(Pac, Ver, Cmp, V),
check_all(Pac, VerS, CmpS, V).
The problem I have is when try to find other solutions, it gives me duplicate solution.
I get:
check_all('python', ['3.0','2.4'], [lt,ge], V).
V = '2.6.5' ;
V = '2.6.5' ;
V = '2.5.4' ;
V = '2.5.4' .
expected:
check_all('python', ['3.0','2.4'], [lt,ge], V).
V = '2.6.5' ;
V = '2.5.4' .
I used trace to track it, and the problem I found, when it try to find another solution it back tracks and will return fail until find the right solution. Like the example above, apparently, it will return true for V='2.6.5' at first and take that to back track and run the functions, and we expect it returns false and then when it reach the beginning it run package('python', V) and V will take another value.
...
Exit: (7) check_all(python, ['3.0', '2.4'], [lt, ge], '2.6.5') ? creep
V = '2.6.5'
...
Fail: (9) check_version(python, '2.4', ge, '2.6.5') ? creep
Redo: (8) check_all(python, ['2.4'], [ge], '2.6.5') ? creep
Call: (9) check_version(python, '2.4', ge, '2.6.5') ? creep
Call: (10) package(python, '2.6.5') ? creep
Exit: (10) package(python, '2.6.5') ? creep
when back tracking, in check_all, it fails at check_all as we expected, but it returns true when it backtracks check_version and run package(python, '2.6.5') as V=2.6.5 a new value. so it return true again when V=2.6.5. is there any way to solve this problem?
To localize your problem, first reduce the size of your input. A single element suffices:
?- check_all('python', ['3.0'], [lt], V).
Now, which rules apply for a single element?
Both rules apply! So remove the more specialized one.
There is also another way how to localize such a problem. Simply compare the rules to each other and try to figure out a case where they both apply. The last rule applies for VerS = [] when also the first applies.
Applying a predicate to each element of a list is best done by a predicate that has the list as its first argument. Without going into detail, this makes the predicate succeed when the iteration is complete, if the argument is a list and not a variable (i.e. when it is an input argument). You should have two clauses: one to deal with the empty list and one for the general case:
foo([]). % succeed
foo([X|Xs]) :-
/* apply a predicate to X */
foo(Xs). % apply predicate to the rest of the list
An important thing here is that you don't need a third clause that deals with lists with one element only, since a list with one element is actually a list with an element and an empty list as its tail:
?- [a] == [a|[]].
true.
?- [a] = [a|[]].
true.
Another important thing is that there is nothing you should be doing in the base case, empty list (at least for your example).
To the problem now: your inputs are
the package name
two lists holding pairs of arguments to a predicate you have defined elsewhere (cmp_version/3). This is your list of conditions.
Implementation:
Known packages are available as facts: they can be enumerated by backtracking.
Conditions are an input arguments, provided as a list: you need to apply the condition to each element of the list(s).
The predicate:
check_all([], [], _, _).
check_all([V|Vs], [C|Cs], Name, Version) :-
package(Name, V), % enumerate all known packages by backtracking
cmp_version(Version, V, Cmp), % condition
check_all(Vs, Cs, Name, Version). % apply condition to the rest of the list(s)
You should read the documentation of maplist. You can express the query for example as:
?- maplist(check_version(python), ['3.0', '2.4'], [lt, ge], Versions).
where you have defined a predicate check_version/4 that looks something like:
check_version(Name, V, Cmp, Version) :-
package(Name, Version),
cmp_version(Version, V, Cmp).
As a side note, maplist will reorder its arguments to make it behave like the explicit iteration above.
EDIT
Naming issues, after #mat's comments: one very useful naming convention is to use a name that has descriptive one-word names for the arguments, delimited by underscores. For example, package/2 becomes package_version/2 since its first argument is the package and the second one the version.

Prolog recursion overflow

fact(1,1):-!.
fact(N,F):-
N1=N-1,
fact(N1,F1),
F=F1*N.
It leads to the stackoverflow(not the site)! It shouldn't because of the cut(!). Does it work in SWI-Prolog?
Please note that both definitions (the OP's and pad's) do not terminate for a query like fact(0,N). But also fact(1,2) does not terminate. It should fail. And for fact(N, F) it gives only one correct answer, but there should be infinitely many. Using cuts for such purpose is very tricky. The cleanest way to fix this is to add the goal N > 0 to the rule and have a fact fact(0,1). There is an even better way, provided you use SWI-Prolog: Use library(clpfd). In the documentation, you find n_factorial/2 already defined. It can be used for queries like:
?- n_factorial(47, F).
F = 258623241511168180642964355153611979969197632389120000000000
; false.
?- n_factorial(N, 1).
N = 0
; N = 1
; false.
?- n_factorial(N, 3).
false.

Resources