Recursive list creation - list

I'm stuck on this issue with lists in SWI-prolog.
In Prolog a variable can be written once, so i can't deal with this problem.
check(Parameter, [H | T], Result) :-
get_res(Parameter, H, Res),
check(Res, T, Result).
So, predicate check/3 takes a parameter, a list and gives me the final result.
get_res/3 gives me a middle result i use as an input for the recursive case of check/3.
So in Result i must have Res for each recursive call.
I tried to use append([Parameter], [], Result) before the recursive call but the first time succeeds, then it fails because Result can't be rewritten.
I know i also need a base case, it may could be check(_, [], []).
But I'm not even sure on that

For recursively appending your results to the output, you can modify the code as :
check(_,[],[]).
check(Parameter, [H | T], [Res|Result]) :-
get_res(Parameter, H, Res),
check(Res, T, Result).
Base case is also important in this situation to have a correctly working function. When you are calling check/3, make sure the argument for the Result is a variable s.t. this can work correctly.

Related

how do I implement a transpose predicate the right way (Prolog)?

I am making a program that solves a puzzle. but I need to make a predicate that returns the transpose given a matrix(list of lists) and I can't use the predefined one. but whatever I do I can't get the predicate to work backwards without getting a stack limit exceeded, ex: trans([[1,2],[3,4]],X). returns [[1,3],[2,4]] but trans(X,[[1,3],[2,4]]). exceeds the stack limit.
here is the trans predicate:
trans(M,M1):-
length(M,L),
trans1(0,L,M,R).
trans1(N,N,_,[]).
trans1(I,N,M,M1):-
I1 is I+1,
column(M,I1,C),
trans1(I1,N,M,M2).
and here is the column predicate that I used:
row([H|_],1,H):-!.
row([_|T],I,X) :-
I1 is I-1,
row(T,I1,X).
column([],_,[]).
column([H|T], I, [R|X]):-
row(H, I, R),
column(T,I,X).
any idea how I can use trans give the list if I give its transpose?
Many years ago, I wrote my own transpose/2, as a part of my IL project. Here it is:
% row/columns transposition
%
transpose_col_row([], []).
transpose_col_row([U], B) :- gen(U, B).
transpose_col_row([H|T], R) :- transpose_col_row(T, TC), splash(H, TC, R).
gen([H|T], [[H]|RT]) :- gen(T,RT).
gen([], []).
splash([], [], []).
splash([H|T], [R|K], [[H|R]|U]) :-
splash(T,K,U).
Despite the code doesn't use anything complicated, it's not too easy to understand what it does, and, like your own, or SWI-Prolog library(clpfd) implementation, it is not 'reversible'.
Your code has many problems you need to solve (note: singletons warnings are errors, really), but assuming you can nail them down, and get a working trans(M,T), you could use a simple 'hack', swapping arguments after checking instantiation:
trans_rev(M,T) :- var(M) -> trans(T,M) ; trans(M,T).
Let's try with my own implementation, that is
transpose_col_row_rev(M,T) :-
var(M) -> transpose_col_row(T,M) ; transpose_col_row(M,T).
?- transpose_col_row_rev([[1,2]],T).
T = [[1], [2]]
?- transpose_col_row_rev(M,$T).
M = [[1, 2]],
T = [[1], [2]]
You can re-assemble the predicate by looking at the publicly available, free (as in beer), open-source SWI-Prolog code. Why people don't do that more often is a mystery to me. It is very easy, but still more difficult than someone just dumping the working code on you I guess.
First, here is the (somewhat cryptic) implementation of transpose/2 in library(clpfd):
lists_transpose([], []).
lists_transpose([L|Ls], Ts) :-
maplist(same_length(L), Ls),
foldl(transpose_, L, Ts, [L|Ls], _).
transpose_(_, Fs, Lists0, Lists) :-
maplist(list_first_rest, Lists0, Fs, Lists).
list_first_rest([L|Ls], L, Ls).
This uses a predicate same_length/2. It is defined in library(lists) and looks like this:
same_length([], []).
same_length([_|T1], [_|T2]) :-
same_length(T1, T2).
Pretty straight-forward.
Then it uses maplist and foldl. Are there allowed or not? If not, you can rewrite maplist(same_length(L), Ls) as:
all_same_length([], L).
all_same_length([X|Xs], L) :-
same_length(X, L),
all_same_length(Xs, L).
Stupid code that shouldn't be written manually but well.
You can then replace maplist(same_length(L), Ls) with all_same_length(Ls, L).
This leaves you with the foldl(transpose_, L, Ts, [L|Ls], _). This is the "cryptic" bit; this qualification was maybe meant as a compliment to the person who wrote it.
Either way, a fold written like this that ignores the last argument (the result) can be re-written as a loop not too different from the maplist above. The transpose_/4 used in the fold has a maplist in its definition, but I showed already how to do that.
Since this looks like homework I will let you figure it out on your own.
Cheat code: if you look far enough into the history of the library (all on github!) you might get super lucky and find a pre-foldl implementation of the same transpose.

Combining predicates in Prolog

I have to make a predicate reverseeven(List, Reversed), that will reverse a list ONLY if the list has an even number of elements, and will return the empty list if it does not.
I have a function that determines whether the list has an even number of elements and a reverse function:
evenlength([_,_]).
evenlength([_,_|X]):-
evenlength(X).
reverse([_,_],R).
reverse([H|T], R):-
reverse(T,ReverseT), append(ReverseT, [H], R).
But I'm unsure of how to combine the two.
You can't "combine" predicates, but you can have a logical conjunction between two (or more) predicates which will succeed only if both of them succeed:
reverseEven(List, Reversed) :-
evenlength(List), % This must succeed
reverse(List, Reversed). % and this one in order this case to succeed
reverseEven(_, []). % this will succeed otherwise
The above is not the most efficient implementation (you can utilize the cut ! operator after the check for the even length for example). But it shows the idea.
Update
By the way, your reverse predicate should look like this:
reverse([],[]). % Empty list is a reverse of empty list
reverse([H|T], R):-
reverse(T,ReverseT), append(ReverseT, [H], R).
Update 2 Thanks #Lurker. The above code will produce two answers. The first one will be correct. If we ask Prolog to search further it will find another answer which is empty list, as the second clause is always true. In order to solve this, we can explicitly check that the length of the list is not even using the negation operator, or what I find more elegant is just to add another clause for the empty list, and for the non-even checking just use the existing evenlength with the list with extra element:
reverseEven([], []).
reverseEven(List, Reversed) :-
evenlength(List), % This must succeed
reverse(List, Reversed). % and this one in order this case to succeed
reverseEven([H|T], []) :-
evenlength([H|[H|T]]).

Prolog removing all variables and duplicates

I need a query, which will remove me all variables and duplicates from list.
Example:
?- L = [1,2,3,X,Y,3,2], my_awesome_predicate(L, Res).
Then, Res should be: [1,2,3].
I don't care about order (it could be [2,3,1], [3,2,1] or whatever).
Unfortunately, I have a task in which I have to care about efficiency, so my main question is - can it be done faster? Currently, I have the following code:
remove_variables([], []).
remove_variables([H|List], Res):- var(H), !, remove_variables(List, Res).
remove_variables([H|List], [H|Res]):- remove_variables(List, Res).
my_awesome_predicate([], []).
my_awesome_predicate(List, Res):-
sort(List, Sorted),
remove_variables(Sorted, Res).
If you are using SWI then you can improve a little further with this code:
my_awesome_predicate(List, Res):-
sort(List, MRes),
remove_variables(MRes, Res).
remove_variables([Var|Tail], NTail):-
var(Var),
!,
remove_variables(Tail, NTail).
remove_variables(Res, Res).
as it seems that SWI's sort will leave unbounded variables first (don't know if this behavior is a standard among other prolog's), so you can stop removing variables once you find the first non-variable.
Reading a bit SWI's documentation, it's stated that:
4.7.1 Standard Order of Terms
Comparison and unification of arbitrary terms. Terms are ordered in
the so called ``standard order''. This order is defined as follows:
1. Variables < Numbers < Atoms < Strings < Compound Terms
so it seems safe to stop removing elements when you find the first non-variable...
awesome([],[]).
awesome([H|T],R):- var(H), !, awesome(T,R).
awesome([H|T],R):- awesome(T,[H],R).
awesome([],R,R).
awesome([H|T],A,R):- memberchk(H,A) -> awesome(T,A,R) ; awesome(T,[H|A],R).
Something like this? Theoretically it is quadratic, but your lists are very short and this code is very simple, so might get optimized by the compiler better.
If you append your resulting lists, better change it to work with difference lists, putting the output directly into the resulting list being built:
awesome([],Z,Z).
awesome([H|T],R,Z):- var(H), !, awesome(T,R,Z).
awesome([H|T],R,Z):- R=[H|Y], awesome(T,[H],Y,Z).
awesome([],_,Z,Z).
awesome([H|T],A,R,Z):- memberchk(H,A) -> awesome(T,A,R,Z)
; R=[H|Y], awesome(T,[H|A],Y,Z).
memberchk/2 of course weeds out variables as well as duplicates.
This is an old question but for the reference there is another nice and short solution using setof.
my_awesome_predicate(L, Res) :-
setof(X, (member(X, L), ground(X)), Res).
Res contains the solution without variables with the terms ordered by their first appearance.
?- my_awesome_predicate([1,2,3,X,Y,3,2], Res).
Res = [1, 2, 3].

How do I get the sum of given numbers in prolog?

I'm new to prolog and I'm doing some exercises for practice. So I'm trying to get the sum of the given numbers in a list. I'm trying to use this:
my_last(X, [X]).
my_last(X, [_|L]) :- my_last(X, L).
(from here)
as my guide. So this is my code for getting the sum:
listsum(X, []).
listsum(X, [H|L]):-
X is H + listsum(X, L).
when I compile it, it says
practice.pl:3: evaluable listsum(_G139,_G140) does not exist
practice.pl:2: Singleton variables: [X]
then when I try listsum(0, [1,2,3]). it returns false.
I still don't understand much about prolog, and list and recursion in prolog.
Arithmetic
As you already discovered, arithmetic can be handled in Prolog with the (is)/2 operator. It's because in Prolog, everything is only symbolic calculus: things don't have a meaning by default, so the unification (=)/2 wouldn't know that (+)/2 refers to the addition for example.
Now, your problem is that you use a regular predicate inside of (is)/2 (here it's your recursive call). Since (is)/2 only performs arithmetic, it doens't evaluate the predicate call. It doesn't even recognize it since it's not an arithmetic function.
The fix here would be to affect the result of the recursive call to a variable and then use it in the (is)/2 call:
listsum(X,[]).
listsum(Result, [Head|Tail]) :-
listsum(SumOfTail, Tail),
Result is Head + SumOfTail.
Base case correctness
But if you test that code you will not get the desired result. The reason is that you have another problem, in your base case. The sum of the empty list isn't "anything", as you stated by writing
listsum(X,[]).
(X is a free variable, hence can be anything).
Instead, it's 0:
listsum(0, []).
The resulting code is:
listsum(0, []).
listsum(Result, [Head|Tail]) :-
listsum(SumOfTail, Tail),
Result is Head + SumOfTail.
Order of arguments
Now, as a sidenote, in Prolog a convention is that output variables should be put at the end of the predicate while input variables should be put at the start of the predicate, so to behave as wanted we could refactor as follows:
listsum([], 0).
listsum([Head|Tail], Result) :-
listsum(Tail, SumOfTail),
Result is Head + SumOfTail.
Tail Call Optimization
Now, we can still improve this predicate with more advanced techniques. For example we could introduce tail calls so that Tail Call Optimization (googlable) could be performed, thanks to an idiom of declarative programming called an accumulator:
listsum(List, Sum) :-
listsum(List, 0, Sum).
listsum([], Accumulator, Accumulator).
listsum([Head|Tail], Accumulator, Result) :-
NewAccumulator is Accumulator + Head,
listsum(Tail, NewAccumulator, Result).
The idea behind that is to update an intermediate result at each step of the recursion (by adding the value of the current head of the list to it) and then just state that when the list is empty this intermediate value is the final value.
Getting more general programs
As you may have noted in Prolog, quite often predicates can be used in several ways. For example, length/2 can be used to discover the length of a list:
?- length([1, 2, 3], Length).
Length = 3.
or to build a skeleton list with free variables of a desired length:
?- length(List, 3).
List = [_G519, _G522, _G525].
Here though, you might have noted that you can't ask Prolog what are the lists which have a sum that is 6:
?- listsum(L, 6).
ERROR: is/2: Arguments are not sufficiently instantiated
That's because, to "go backwards", Prolog would have to solve an equation when comes the call to the (is)/2 operator. And while yours is simple (only additions), arithmetic isn't solvable this way in the general case.
To overcome that problem, constraint programming can be used. A very nice library is available for SWI, clpfd.
The syntax here would be:
:- use_module(library(clpfd)).
listsum(List, Sum) :-
listsum(List, 0, Sum).
listsum([], Accumulator, Accumulator).
listsum([Head|Tail], Accumulator, Result) :-
NewAccumulator #= Accumulator + Head,
listsum(Tail, NewAccumulator, Result).
Now we can use our predicate in this other way we wished we could use it:
?- listsum(L, 6).
L = [6] ;
L = [_G1598, _G1601],
_G1598+_G1601#=6 ;
L = [_G1712, _G1715, _G1718],
_G1712+_G1715#=_G1728,
_G1728+_G1718#=6 . % Here I interrupted the answer but it would not terminate.
We could even ask for all the solutions to the problem:
?- listsum(L, X).
L = [],
X = 0 ;
L = [X],
X in inf..sup ;
L = [_G2649, _G2652],
_G2649+_G2652#=X . % Here I interrupted the answer but it would not terminate
I just mentionned that so that you realize that quite often the use of (is)/2 should be avoided and use of constraint programming should be preferred to get the most general programs.
If possible, use clpfd instead of plain old (is)/2 (and friends).
clpfd offers a logically pure predicate sum/3 that could fit your needs!

Reaching end of list in prolog

I've been given the question:
Define a predicate ordered/1, which checks if a list of integers is correctly in ascending order. For example, the goal ordered([1,3,7,11]) should succeed, as should the goal ordered([1,3,3,7]), whereas the goal ordered([1,7,3,9]) should fail.
So far I have this:
ordered([]).
ordered([N, M|Ns]):-
append(M, Ns, Tail),
ordered(Tail),
N =< M.
But it fails on every list.
I have deduced that the reason it fails is because it reaches the end number in the list then tries to compare that number against an empty list. Obviously this fails because you can't compare an integer to an empty list. Even if you could and it, say, returned 0 for an empty list, it would still return false as the number would be greater than 0, not less than.
I can't find a solution... Any ideas? Thanks, Jon.
Edit
So, some slightly amended code:
ordered([]).
ordered([N]):-
N >= 0.
ordered([N, M|Ns]):-
append(M, Ns, Tail),
ordered(Tail),
N =< M.
This now works for ordered([1]), but bigger lists still don't run correctly.
Should I include something like ordered([N, M|Ns]) in the definition?
(assuming this is homework, I hesitate to give a complete solution).
Looking at your code, try to find out how it would unify ?- ordered([1]).
Run this query mentally (or using trace/0) and see what it does, step by step, and how it computes its result.
Also, please try to get "returns a value" out of your mind when thinking prolog. Prolog predicates don't return anything.
I think your solution is not also tail-recursion-friendly.
Think something like that would do:
ordered([]) :-!.
ordered([_]):-!.
ordered([A,B|T]) :-
A =< B,
!,
ordered([B|T]).
If you are using SICStus Prolog,
my previous answer will not work, as the
clpfd library in SICStus Prolog
does not offer the library predicate
chain/3 included with
SWI-Prolog's clpfd library.
:- use_module(library(clpfd)).
:- assert(clpfd:full_answer).
Don't panic! Simply implement predicate ordered/1 like this:
ordered([]).
ordered([X|Xs]) :-
ordered_prev(Xs,X).
ordered_prev([] ,_ ).
ordered_prev([X1|Xs],X0) :-
X0 #=< X1,
ordered_prev(Xs,X1).
Let's see it in action with SICStus Prolog 4.3.2.
Here's the most general query:
?- ordered(Xs).
Xs = []
; Xs = [_A]
; Xs = [_A,_B], _A#=<_B, _A in inf..sup, _B in inf..sup
; Xs = [_A,_B,_C], _A#=<_B, _B#=<_C, _A in inf..sup, _B in inf..sup, _C in inf..sup
... % an infinity of solutions follows: omitted for the sake of brevity.
And here are the queries the OP suggested:
?- ordered([1,3,7,11]).
yes % succeeds deterministically
?- ordered([1,3,3,7]).
yes % succeeds deterministically
?- ordered([1,7,3,9]).
no
Note that both succeeding queries in above example did not leave any useless choicepoints behind, thanks to first argument indexing.
If your Prolog system supports clpfd, check if it offers the library predicate clpfd:chain/2.
:- use_module(library(clpfd)).
If so, simply write:
?- chain([1,3,7,11],#<).
true.
?- chain([1,3,3,7],#=<).
true.
?- chain([1,3,3,7],#<).
false.
?- chain([1,7,3,9],#<).
false.
You're quite right: according to your code there are only two possible ways a list can be ordered:
It's empty
The first two items are in the correct order, and the rest of the list is ordered
Those are certainly both correct statements, but what about the list [3]? Isn't that ordered too? Obviously a list with only one element is ordered, yet you have no provision for expressing that: it fits neither your base case nor your recursive case.
The single-element list is another case hiding here that you haven't addressed yet. Since this is independent of the two rules you've already defined, you might want to consider a way to address this special case separately.
Well that, in the end, was rediculously easy to fix.
Here is the correct code.
ordered([]).
ordered([N, M|Ns]):-
append([M], Ns, Tail),
ordered(Tail),
N =< M.
ordered([M]).
ordered([M]). deals with the single-element list as described above.
The real root of my problem was not including [] around the M in the append function.
Whats the ettiquette regarding awarding the correct answer? You've both helped muchly.
Jon
Don't use append/3.
edit1 to satisfy #false. In order to make it tail recursive friendly it has to eliminate backtracking. This is tail-recursive and only slight variation on #Xonix:
ordered([X|[]]):-!.
ordered([X,Y|Ys]) :-
X =< Y,
!,
ordered([Y|Ys]).
edit2 Take it a step further to eliminate lists that have less than two elements
ordered([X,Y|[]]):- X =< Y,!.
ordered([X,Y|Ys]) :-
X =< Y,
!,
ordered([Y|Ys]).