Prolog - How to limit variable list length - list

I am having trouble generating all lists that meet certain criteria.
city(new_york, 47).
city(chicago, 100).
all_unique([]).
all_unique([H|T]) :- H = [] ; (not(member(H, T)), all_unique(T)).
cities([Head|Tail]) :-
length(Tail, L),
L < 2,
city(Head, _A),
(Tail = [] ; cities(Tail)).
When I issue the query cities(L), I want it to generate all lists of cities with a maximum length of 2 and no repetition. What it does now is return all possible lists and then keep trying lists that obviously don't meet the criteria.
?- cities(L).
L = [new_york] ;
L = [chicago] ;
L = [new_york, new_york] ;
L = [new_york, chicago] ;
L = [chicago, new_york] ;
L = [chicago, chicago] ;
ERROR: Out of global stack
?-
How do I tell Prolog not to try lists that are too long or have repeated items?

Your definition of all_unique/1 is better based on prolog-dif:
all_unique([]).
all_unique([E|Es]) :-
maplist(dif(E), Es),
all_unique(Es).
Based on meta-predicate maplist/2 you can define cities/1 like this:
city_(new_york, 47).
city_(chicago, 100).
city(C) :-
city_(C, _).
cities(List) :-
length(Ref, 2),
append(List, _, Ref),
all_unique(List),
maplist(city, List).
Sample query:
?- cities(Xs).
Xs = [] ;
Xs = [new_york] ;
Xs = [chicago] ;
Xs = [new_york, chicago] ;
Xs = [chicago, new_york] ;
false. % terminates universally

Related

How to get all consecutive sublists/subsets in Prolog?

I would like to solve a simple problem, but even through I tried many different approaches, I couldn't find a solution for it. I am using SICStus Prolog (if that matters), and I want to get all sublists/subsets (I don't know which term is correct for this) of a list, which contains elements in succession. For example, if I have the list [1, 2, 3, 4], calling the sl/2 predicate as sl([1, 2, 3, 4], R)., the expected result is:
? - sl([1, 2, 3, 4], R).
R = [] ? ;
R = [1] ? ;
R = [1, 2] ? ;
R = [1, 2, 3] ? ;
R = [1, 2, 3, 4] ? ;
R = [2] ? ;
R = [2, 3] ? ;
R = [2, 3, 4] ? ;
R = [3] ? ;
R = [3, 4] ? ;
R = [4] ? ;
no
The best result I could reach until now is:
sl([], []).
sl([X|Xs], [X|Ys]) :-
sl(Xs, Ys).
sl([_|Xs], Ys) :-
sl(Xs, Ys).
But this also gives me the following unwanted results in addition:
R = [1,2,4] ? ;
R = [1,3,4] ? ;
R = [1,3] ? ;
R = [1,4] ? ;
R = [2,4] ? ;
How should I modify my predicates so I can get the desired result?
When writing a predicate in Prolog, you need to think about what the predicate means, or what relation it is defining. The reason your predicate gives non-solutions is that you are mixing meanings in your predicate clauses. They don't all really mean the same thing.
You have the predicate sl/2 which is intended to mean "sublist" (or "subsequence") but, more than that, means a sublist per the description you provided, which is a contiguous sublist (cannot have any "gaps" in it).
Now we can break down your clauses:
sl([], []).
This says the empty list is a contiguous sublist of the empty list. This is true, so is a valid fact.
sl([X|Xs], [X|Ys]) :-
sl(Xs, Ys).
This says that [X|Ys] is a contiguous sublist of [X|Xs] if Ys is a contiguous sublist of Xs. This relation is not true. What would really be true here would be: [X|Ys] is a contiguous sublist of [X|Xs] if Ys is a contiguous prefix sublist of Xs. That is, not only does Ys need to be a sublist of Xs, but it needs to be only from the start of the list and not somewhere within this list. This is a clue that you'll need another predicate since the meaning of the relation is different.
Your final clause says that Ys is a sublist of [_|Xs] if Ys is a sublist of Xs. This appears to be true.
If we simply adjust to the above updated definitions, we get:
subseq([], []).
subseq([_|Xs], Ys) :-
subseq(Xs, Ys).
subseq([X|Xs], [X|Ys]) :-
prefix_subseq(Xs, Ys).
prefix_subseq(_, []).
prefix_subseq([X|Xs], [X|Ys]) :-
prefix_subseq(Xs, Ys).
I offered the prefix_subseq/2 definition above without explanation, but I think you can figure it out.
This now yields:
| ?- subseq([a,b,c,d], R).
R = [a] ? a
R = [a,b]
R = [a,b,c]
R = [a,b,c,d]
R = [b]
R = [b,c]
R = [b,c,d]
R = [c]
R = [c,d]
R = [d]
R = []
(1 ms) yes
An interesting, compact way of defining your sublist (or subsequence) would be using the append/2 predicate:
subseq(L, R) :- append([_, R, _], L).
This says that L is the result of appending lists _, R, and _. The minor flaw in this simple implementation is that you'll get R = [] more than once since it satisfies the append([_, R, _], L) rule in more than one way.
Taking a fresh look at the definition, you can use a DCG to define a subsequence, as a DCG is perfect for dealing with sequences:
% Empty list is a valid subsequence
subseq([]) --> ... .
% Subsequence is any sequence, followed by sequence we want, followed by any sequence
subseq(S) --> ..., non_empty_seq(S), ... .
% Definition of any sequence
... --> [] | [_], ... .
% non-empty sequence we want to capture
non_empty_seq([X]) --> [X].
non_empty_seq([X|T]) --> [X], non_empty_seq(T).
And you can call it with phrase/2:
| ?- phrase(subseq(S), [a,b,c,d]).
S = [] ? ;
S = [a] ? ;
S = [a,b] ? ;
S = [a,b,c] ? ;
S = [a,b,c,d] ? ;
S = [b] ? ;
S = [b,c] ? ;
S = [b,c,d] ? ;
S = [c] ? ;
S = [c,d] ? ;
S = [d] ? ;
no
We can reswizzle this definition a little and make use of a common seq//1 definition to make it more compact:
subseq([]) --> seq(_) .
subseq([X|Xs]) --> seq(_), [X], seq(Xs), seq(_).
% alternatively: seq(_), seq([X|Xs]), seq(_).
seq([]) --> [].
seq([X|Xs]) --> [X], seq(Xs).

What does this code mean and do?

I am completely new to Prolog and I can't understand this piece of code. How would you read these 4 clauses? What do they do?
a([]).
a([_|L]):-b(L).
b([_]).
b([_|L]):-a(L).
Thank you.
As #repeat suggested in his comment, run a general query, and here's what you get:
| ?- a(Xs).
Xs = [] ? ;
Xs = [_,_] ? ;
Xs = [_,_] ? ;
Xs = [_,_,_,_] ? ;
Xs = [_,_,_,_] ? ;
Xs = [_,_,_,_,_,_] ? ;
Xs = [_,_,_,_,_,_] ? ;
...
And:
| ?- b(Xs).
Xs = [_] ? ;
Xs = [_] ? ;
Xs = [_,_,_] ? ;
Xs = [_,_,_] ? ;
Xs = [_,_,_,_,_] ? ;
Xs = [_,_,_,_,_] ? ;
Xs = [_,_,_,_,_,_,_] ? ;
Xs = [_,_,_,_,_,_,_] ? ;
...
So a(Xs) succeeds if Xs is a list containing an even number of elements, and b(Xs) succeeds if Xs is a list containing an odd number of arguments. As you can see, a/1 and b/1 succeed twice in each case except a([]). which succeeds only once. So it is not an efficient predicate for determining list length parity.
Let's rewrite these with more descriptive names:
even([]).
even([_|L]) :- odd(L).
odd([_]).
odd([_|L]) :- even(L).
Now let's "read" what they say:
[] is an even list
[_|L] is an even list if L is an odd list
[_] is an odd list
[_|L] is an odd list if L is an even list
These sound logical, but why do even/1 and odd/1 succeed twice with the exception of even([])? If you look at the definition of odd/1, there are two ways for [_] to succeed. One is via the odd([_]). clause. The second is by the second odd/1, since you would have:
odd([_|[]]) :- even([]). % [_] == [_|[]]
Since both even/1 and odd/1 calls (with the exception of even([]).) eventually recurse down to a call to odd([_]), you'll get two solutions.
One way to eliminate the ambiguity in the logic is to refactor them a little. Consider the following recursive rules:
A list of at least 2 elements has an even number of elements if the tail of the list, after the first 2, is also even.
A list of at least 2 elements has an odd number of elements if the tail of the list, after the first 2, is also odd.
Translating these rules to Prolog, including the base cases as before:
even([]).
even([_,_|L]) :- even(L).
odd([_]).
odd([_,_|L]) :- odd(L).
Now the results will be:
| ?- even(Xs).
Xs = [] ? ;
Xs = [_,_] ? ;
Xs = [_,_,_,_] ? ;
Xs = [_,_,_,_,_,_] ? ;
...
And
| ?- odd(Xs).
Xs = [_] ? ;
Xs = [_,_,_] ? ;
Xs = [_,_,_,_,_] ? ;
...
Following CapelliC's suggestion of using a DCG, similar rules can be written:
even --> [] | [_,_], even.
odd --> [_] | [_,_], odd.
With results:
| ?- phrase(even, L).
L = [] ? ;
L = [_,_] ? ;
L = [_,_,_,_] ? ;
...
And
| ?- phrase(odd, L).
L = [_] ? ;
L = [_,_,_] ? ;
L = [_,_,_,_,_] ? ;
...
Following #false's suggestion, an even more direct "fix" to the original code would be to eliminate the redundant base case for odd([_]). since it's already covered by the base case for even([]). This is also a little simpler than the above solution since it takes advantage of the interdependency between the even/1 and odd/1 predicates (in the above solution, even/1 and odd/1 stand on their own).
even([]).
even([_|L]) :- odd(L).
odd([_|L]) :- even(L).
Or, in DCG:
even --> [] | [_], odd.
odd --> [_], even.
the argument schema is important:
a) the list is clearly a counter, since we never consider the content.
b) just a suggestion: read logic as productions, or as DCG
a-->[];[_],b.
b-->[_];[_],a.
to be called - for instance
?- phrase(a, [w,h,a,t]).

How can I compare two lists in prolog, returning true if the second list is made of every other element of list one?

I would solve it by comparing the first index of the first list and adding 2 to the index. But I do not know how to check for indexes in prolog.
Also, I would create a counter that ignores what is in the list when the counter is an odd number (if we start to count from 0).
Can you help me?
Example:
everyOther([1,2,3,4,5],[1,3,5]) is true, but everyOther([1,2,3,4,5],[1,2,3]) is not.
We present three logically-pure definitions even though you only need one—variatio delectat:)
Two mutually recursive predicates list_oddies/2 and skipHead_oddies/2:
list_oddies([],[]).
list_oddies([X|Xs],[X|Ys]) :-
skipHead_oddies(Xs,Ys).
skipHead_oddies([],[]).
skipHead_oddies([_|Xs],Ys) :-
list_oddies(Xs,Ys).
The recursive list_oddies/2 and the non-recursive list_headless/2:
list_oddies([],[]).
list_oddies([X|Xs0],[X|Ys]) :-
list_headless(Xs0,Xs),
list_oddies(Xs,Ys).
list_headless([],[]).
list_headless([_|Xs],Xs).
A "one-liner" which uses meta-predicate foldl/4 in combination with Prolog lambdas:
:- use_module(library(lambda)).
list_oddies(As,Bs) :-
foldl(\X^(I-L)^(J-R)^(J is -I,( J < 0 -> L = [X|R] ; L = R )),As,1-Bs,_-[]).
All three implementations avoid the creation of useless choicepoints, but they do it differently:
#1 and #2 use first-argument indexing.
#3 uses (->)/2 and (;)/2 in a logically safe way—using (<)/2 as the condition.
Let's have a look at the queries #WouterBeek gave in his answer!
?- list_oddies([],[]),
list_oddies([a],[a]),
list_oddies([a,b],[a]),
list_oddies([a,b,c],[a,c]),
list_oddies([a,b,c,d],[a,c]),
list_oddies([a,b,c,d,e],[a,c,e]),
list_oddies([a,b,c,d,e,f],[a,c,e]),
list_oddies([a,b,c,d,e,f,g],[a,c,e,g]),
list_oddies([a,b,c,d,e,f,g,h],[a,c,e,g]).
true. % all succeed deterministically
Thanks to logical-purity, we get logically sound answers—even with the most general query:
?- list_oddies(Xs,Ys).
Xs = [], Ys = []
; Xs = [_A], Ys = [_A]
; Xs = [_A,_B], Ys = [_A]
; Xs = [_A,_B,_C], Ys = [_A,_C]
; Xs = [_A,_B,_C,_D], Ys = [_A,_C]
; Xs = [_A,_B,_C,_D,_E], Ys = [_A,_C,_E]
; Xs = [_A,_B,_C,_D,_E,_F], Ys = [_A,_C,_E]
; Xs = [_A,_B,_C,_D,_E,_F,_G], Ys = [_A,_C,_E,_G]
; Xs = [_A,_B,_C,_D,_E,_F,_G,_H], Ys = [_A,_C,_E,_G]
...
There are two base cases and one recursive case:
From an empty list you cannot take any odd elements.
From a list of length 1 the only element it contains is an odd element.
For lists of length >2 we take the first element but not the second one; the rest of the list is handled in recursion.
The code looks as follows:
odd_ones([], []).
odd_ones([X], [X]):- !.
odd_ones([X,_|T1], [X|T2]):-
odd_ones(T1, T2).
Notice that in Prolog we do not need to maintain an explicit index that has to be incremented etc. We simply use matching: [] matches the empty list, [X] matches a singleton list, and [X,_|T] matches a list of length >2. The | separates the first two elements in the list from the rest of the list (called the "tail" of the list). _ denotes an unnamed variable; we are not interested in even elements.
Also notice the cut (!) which removes the idle choicepoint for the second base case.
Example of use:
?- odd_ones([], X).
X = [].
?- odd_ones([a], X).
X = [a].
?- odd_ones([a,b], X).
X = [a].
?- odd_ones([a,b,c], X).
X = [a, c].
?- odd_ones([a,b,c,d], X).
X = [a, c].
?- odd_ones([a,b,c,d,e], X).
X = [a, c, e].

List as variable/argument in Prolog

I've created a function in Prolog to "turn" a list, e.g. to append the head of a list to the tail like so:
?- turn([a,b,c,d,e], Tlist).
Tlist=[b,c,d,e,a]
Within the context of my program, I'd like to be able to use predefined lists for the rule, such as
alist([a,b,c,d,e,f])
but I get lots of different errors. I've tried the following as arguments:
turn(alist(L),R).
listv(X) :- alist(L), member(X, L).
turn(listv(X),R).
and I understand that each of these are different representations of the list according to Prolog, but I'm not sure which list representation is appropriate to complete the operation on a predefined list.
Thanks!
The predicate turn/2 can easily be defined based on append/3:
turn([A|As],Bs) :-
append(As,[A],Bs).
For specifying some sample lists, we define an auxiliary predicate named_list/2:
named_list(one_to_nine , [1,2,3,4,5,6,7,8,9]).
named_list(a_to_f , [a,b,c,d,e,f]).
named_list(single_digit_primes, [2,3,5,7]).
Let's query!
?- named_list(a_to_f,Xs), turn(Xs,Ys).
Xs = [a,b,c,d,e,f], Ys = [b,c,d,e,f,a]. % succeeds deterministically
?- named_list(a_to_f,Ys), turn(Xs,Ys). % "other" direction
Ys = [a,b,c,d,e,f], Xs = [f,a,b,c,d,e] % succeeds leaving behind choicepoint
; false.
So far, we have used one specific sample list a_to_f in the queries; let's use 'em all!
?- named_list(Name,Xs), turn(Xs,Ys).
Name = one_to_nine , Xs = [1,2,3,4,5,6,7,8,9], Ys = [2,3,4,5,6,7,8,9,1]
; Name = a_to_f , Xs = [a,b,c,d,e,f] , Ys = [b,c,d,e,f,a]
; Name = single_digit_primes, Xs = [2,3,5,7] , Ys = [3,5,7,2].

prolog list of how many times an element occurs in a list?

Well, I have a list, say [a,b,c,c,d], and I want to generate a list [[a,1],[b,1],[c,2],[d,1]]. But I'm having trouble with generating my list. I can count how many times the element occur but not add it into a list:
% count how much the element occurs in the list.
count([], _, 0).
count([A|Tail], A, K) :-
count(Tail, A, K1),
K is K1 + 1.
count([_|Tail], X, K) :-
count(Tail, X, K1),
K is K1 + 0.
% Give back a list with each element and how many times is occur
count_list(L, [], _).
count_list(L, [A|Tail], Out) :-
count(L, A, K),
write(K),
count_list(L, Tail, [K|Out]).
I'm trying to learn Prolog but having some difficulties... Some help will be much appreciated... Thanks in advance!
Let me first refer to a related question "How to count number of element occurrences in a list in Prolog" and to my answer in particular.
In said answer I presented a logically-pure monotone implementation of a predicate named list_counts/2, which basically does what you want. Consider the following query:
?- list_counts([a,b,c,c,d], Xs).
Xs = [a-1,b-1,c-2,d-1]. % succeeds deterministically
?- list_counts([a,b,a,d,a], Xs). % 'a' is spread over the list
Xs = [a-3,b-1,d-1]. % succeeds deterministically
Note that the implementation is monotone and gives logically sound answers even for very general queries like the following one:
?- Xs = [_,_,_,_],list_counts(Xs,[a-N,b-M]).
Xs = [a,a,a,b], N = 3, M = 1 ;
Xs = [a,a,b,a], N = 3, M = 1 ;
Xs = [a,a,b,b], N = M, M = 2 ;
Xs = [a,b,a,a], N = 3, M = 1 ;
Xs = [a,b,a,b], N = M, M = 2 ;
Xs = [a,b,b,a], N = M, M = 2 ;
Xs = [a,b,b,b], N = 1, M = 3 ;
false.
I cannot follow your logic. The easy way would be to use library(aggregate), but here is a recursive definition
count_list([], []).
count_list([H|T], R) :-
count_list(T, C),
update(H, C, R).
update(H, [], [[H,1]]).
update(H, [[H,N]|T], [[H,M]|T]) :- !, M is N+1.
update(H, [S|T], [S|U]) :- update(H, T, U).
the quirk: it build the result in reverse order. Your code, since it uses an accumulator, would give the chance to build in direct order....