how can I put all the pairs in a one list?
I have -
pair([H|T], [H,E]) :- member(E, T).
pair([_|T], P) :- pair(T, P).
and I want the answer will be a list of pairs.
so I try -
listPairs([],[Res1]):-
Res1=[].
listPairs(L,[Res2]):-
L=[H|T],
append(pair([H|T],[Res2]),listPairs(T,[Res2])).
but I miss something of the lists..
because it is not compile.
I don't really see what you aim to do with append/2. You can definitely not put goals that should be called in the append/3 because in that case, they will be seen as functors.
You can however easily use the findall/3 predicate which is implemented in nearly all Prolog systems (well at least all I have seen that are actively used):
listPairs(L,Pairs) :-
findall(Pair,pair(L,Pair),Pairs).
findall/3 works as follows:
findall(Format,Goal,List).
Here you specify a Goal (here pair(L,Pair)) and Prolog will call the Goal. Each time the Goal succeed, Prolog will suspend the interpreter and add en element formatted as Format to the List. When the Goal fails, the list of all Formats is returned.
If I run the query, I get:
?- listPairs([1,a,2,'5'],Pairs).
Pairs = [[1, a], [1, 2], [1, '5'], [a, 2], [a, '5'], [2, '5']].
Note that L must be grounded (as list, meaning without uninstantiated tail, an uninstantiated element is fine), since otherwise the number of pair/2 elements that you will generate is infinite and thus you will run out of global stack (or memory in general).
Related
I am programming in Prolog looking from any given number (F), to multiply the even elements of a list; keeping those values that are not, developed the following and in fact the program "compiles" without any error but when entering values it only returns "false", where could I be wrong ?:
% base case
evenproduct(_,[],[]) :- !.
% recursive case
evenproduct(F,[X|Xs], [Y|Ys]) :-
Y is F*X,
X mod 2 =:= 0,
evenproduct(F, Xs, Ys), !.
Thanks!!
You shouldn't use cuts (the ! goal). Cuts are an advanced Prolog concept that are only useful once you are a much more advanced Prolog programmer. Before that, cuts will only confuse you. Also, cuts will usually not make your program succeed more often, but they will make it fail more often. Your problem is that your program fails too often! Cuts might be part of your problem.
Also, it's not quite correct that your program always returns false. Look, it does work for some inputs:
?- evenproduct(3, [2, 4, 6], Ys).
Ys = [6, 12, 18].
Namely, if the given list only contains even numbers, your program works exactly as intended. Good job so far!
What you now need to do is to also make this succeed for the case where one of the numbers in the list is odd. There is one main way of making a Prolog program succeed more often: Adding more clauses to some predicate.
Your definition of evenproduct/3 has two clauses so far. Maybe all the list processing predicates you've seen so far have always had exactly two clauses, one for "the base case" and one for "the recursive case". But it's perfectly fine, and often very necessary, to have several non-recursive or several recursive clauses. In your case, you can add the following clause to your program to make it work:
evenproduct(F,[X|Xs], [Y|Ys]) :-
Y = X,
X mod 2 =:= 1,
evenproduct(F, Xs, Ys).
So now you will have three clauses in total, one non-recursive and two recursive ones.
And now odd numbers are accepted as well:
?- evenproduct(3, [1, 2, 3, 7, 11, 22], Ys).
Ys = [1, 6, 3, 7, 11, 66] ;
false.
I have this issue in Prolog where I'm creating a list, and sometimes predicates that contribute to this list creation return an empty list, []. In the end I end up with a list that looks like [[1, 2, 3], []] for example, when I'd rather it be [[1, 2, 3]].
How do I stop that empty list when I return it from being put with the rest of the list? My logic programming isn't terrible strong, but in other languages I'd simply say, if not empty: append, otherwise don't do anything.
Is this possible in Prolog?
EDIT: To put it in an example, say I have the following predicate:
put_together(Value1, Value2, Result) :-
Result = [Value1, Value2].
I call put_together(1, 2, Result). and get Result = [1, 2] as expected. But if I call, put_together(1, [], Result). I get Result = [1, []] which I don't want, I'd rather have the final empty list gone, which would be simply [1].
DCGs are often a good way to describe lists in Prolog. This makes reasoning about lists a lot easier. You should try it in your use case.
For example, to "put together" (see below for why this is not a good view of the matter) two lists, as you say it, you can use:
lists_together(Ls1, Ls2) -->
list(Ls1),
list(Ls2).
list([]) --> [].
list([L|Ls]) --> [L], list(Ls).
Sample cases:
?- phrase(lists_together([a,b,c], [d,e]), Ts).
Ts = [a, b, c, d, e].
?- phrase(lists_together([a,b,c], []), Ts).
Ts = [a, b, c].
This is completely general and works in all directions. Try for example the most general query, or iterative deepening etc. I therefore avoid an imperative name like put_..., which would indicate that it works only in one direction. Instead, I use a more declarative name that does justice to the multiple directions in which this relation holds.
However, in your case, it seems that you are somehow, and involuntarily, mixing terms of different kinds. To denote pairs, do not use [A,B] (which is .(A, .(B, []))), but rather use terms like A-B.
So, to relate such pairs to their components, use for example:
key_value_pair(Key, Value, Key-Value).
If possible, I'd recommend changing your predicates so that you always return lists of lists, and always compose them with append/3. That way, you can absorb empty lists as-if they were zeros in a sum and stop worrying about empty lists being corner cases.
DCG's, as mention in mat's answer, are a possible way to consistently use lists.
my question comes up because of this question
Can you write between/3 in pure prolog?
would it be possible to make between/3 and the third argument is a list so if you ask
between(2,6,X).
it comes
X=[2,3,4,5,6]
and not like
X=2
X=3
X=4
....
I can’t figure out how this must work (all my solutions don’t work..)
I’m a Prolog beginner so I have no idea..
sorry for the bad English..
Thanks for your help :)
Start by going to the library and getting a good book, for example "The Art of Prolog" by Sterling and Shapiro.
Two ways:
?- findall(X, between(2, 6, X), Xs).
Xs = [2, 3, 4, 5, 6].
You should also take a look at bagof/3 and setof/3.
For a direct way, numlist/3, see for example the SWI-Prolog implementation. Without argument checking it comes down to:
numlist(U, U, List) :- !,
List = [U].
numlist(L, U, [L|Ns]) :-
L2 is L+1,
numlist(L2, U, Ns).
There are several ways to break the predicate as it stands.
?- numlist(1,0,L).
will not terminate. You need to either check the arguments before passing them to this particular version of numlist/3:
must_be(integer, L),
must_be(integer, U),
L =< U
These checks are incorporated in the library predicate numlist/3 from the linked SWI-Prolog implementation.
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].
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!