Single cycle permutations - prolog

Let's take a permutation of numbers {1,2,3,4} which has only one cycle in it. For example it can be: (2,3,4,1). I was wondering, how can I generate all such permutations using Prolog?
I know how to generate all permutations using select.
But I can't come up with an idea for how to generate only the one-cycle (i.e. single cycle) permutations.
Could someone give me a small prompt or advice?

My comment was intended as a hint for producing directly the single cycle permutations, rather than generating all permutations and filtering out the ones that consist of a single cycle.
We should perhaps clarify that two representations of permutations are frequently used. xyz writes "I know how [to] generate all permutation[s]," presumably meaning something like the code I gave in this 2006 forum post. Here all permutations are represented according to the way a list rearranges the items in some "standard order" list.
Obviously there are N! permutations of all kinds. How many of these are single cycle permutations? That question is easily answered by contemplating the other form useful for permutations, namely as a product of disjoint cycles. We need to distinguish between a cycle like (1,2,3,4) and the identity permutation [1,2,3,4]. Indeed the cycle (1,2,3,4) maps 1 to 2, 2 to 3, 3 to 4, and 4 back to 1, so rather than the identity permutation it would be [2,3,4,1] in its list representation.
Now a cycle loops back on itself, so it is arbitrary where we choose to begin the cycle notation. If we start at 1, for example, then the cycle is determined by the ordering of the following N-1 items. This shows there are (N-1)! permutations of N things that form a single cycle (necessarily of length N). Thus we can generate all single cycle permutations in cycle form easily enough, and the problem then reduces to converting from that cycle form to the list form of a permutation. [Note that in part Mog tackled the conversion going in the other direction: given a permutation as list, ferret out a cycle contained in that permutation (and see if it is full length).]
Here's my code for generating all the one-cycle list permutations of a given "standard order" list, oneCycle(Identity,Permuted):
oneCycle([H|T],P) :-
permute(T,S),
oneCycle2permute([H|S],[H|T],P).
permute([ ],[ ]) :- !.
permute(L,[H|T]) :-
omit(H,L,Z),
permute(Z,T).
omit(H,[H|T],T).
omit(X,[H|T],[H|Z]) :-
omit(X,T,Z).
oneCycle2permute(_,[ ],[ ]) :- !.
oneCycle2permute(C,[I|Is],[P|Ps]) :-
mapCycle(C,I,P),
oneCycle2permute(C,Is,Ps).
mapCycle([X],X,X) :- !.
mapCycle([H|T],X,Y) :-
mapCycleAux(H,T,X,Y).
mapCycleAux(Y,[X],X,Y) :- !.
mapCycleAux(X,[Y|_],X,Y) :- !.
mapCycleAux(_,[X,Y|_],X,Y) :- !.
mapCycleAux(H,[_|T],X,Y) :-
mapCycleAux(H,T,X,Y).

Couldn't you use the function for generating all permutations, and filter out the ones that aren't 'one-cycle permutations'? (Since I'm not at all clear on what 'one-cycle permutations' are, I'm afraid I can't help with writing that filter.)

one-cycle([H|T], Permutation) :-
permutation([H|T], Permutation),
cycle(H, [H], [H|T], Permutation, Cycle),
length(Cycle, CycleLength),
length([H|T], ListLength),
CycleLength =:= ListLength.
The cycle/5 predicate builds the cycle corresponding to the first argument you pass it. the second argument is an accumulator, initialized to [FirstArgument], the third and fourth one are the original List and Permutation, the last one is the result (the list containing the elements of the cycle).
cycle(Current, Acc, List, Permutation, Cycle) :-
The call to corresponds/4 retrieves the item that took the place of the first argument in the permutation :
corresponds(Current, List, Permutation, R),
If this item is in the cycle we're building, it means we're done building the cycle, so we unify Cycle and the accumulator (Acc).
( member(R, Acc)
-> Cycle = Acc
If not, we go on by calling recursively our predicate with the corresponding item we found and we add it to the accumulator, so that our building cycle now holds it :
; cycle(R, [R|Acc], List, Permutation, Cycle)).
corresponds(N, [N|_], [R|_], R) :-
!.
corresponds(N, [_|L], [_|P], R) :-
corresponds(N, L, P, R).
Usage :
?- one-cycle([1, 2, 3, 4], P).
P = [2, 3, 4, 1] ;
P = [3, 1, 4, 2] ;
P = [3, 4, 2, 1] ;
P = [2, 4, 1, 3] ;
P = [4, 1, 2, 3] ;
P = [4, 3, 1, 2] ;
false.

Thanks to the discussion in the answer by hardmath I was able to understand what it was all about.
It seems the solution is quite simply to replace the input list's tail with its permutation to form a cycle description, then transform that into its list representation by paring up each element with its next and sorting on the first component to get the list of the second components as the result list:
single_cycled_permutation([A|B], R) :-
permutation(B, P),
cycle_pairs(A, A, P, CP),
sort( CP, SCP),
maplist( pair, SCP, _, R).
pair( X-Y, X, Y).
cycle_pairs( A, X, [Y|Z], [X-Y|W]) :-
cycle_pairs(A, Y, Z , W ).
cycle_pairs( A, X, [ ], [X-A] ).
To easier see the cycles simply remove the last goal in single_cycled_permutation:
single_cycled_pairs([A|B], SCP) :-
permutation(B, P),
cycle_pairs(A, A, P, CP),
sort( CP, SCP).
Testing:
21 ?- forall( single_cycled_pairs([1,2,3,4], SCP),
(maplist(pair,SCP,_,R), write((SCP,R)), nl)).
[1-2,2-3,3-4,4-1],[2,3,4,1]
[1-2,2-4,3-1,4-3],[2,4,1,3]
[1-3,2-4,3-2,4-1],[3,4,2,1]
[1-3,2-1,3-4,4-2],[3,1,4,2]
[1-4,2-3,3-1,4-2],[4,3,1,2]
[1-4,2-1,3-2,4-3],[4,1,2,3]
true.
See also:
Cyclic permutation
Cycles and fixed points

Related

How to check how many elements you've already consumed in Prolog DCGs

Say I have these DCGs:
zorbs([H|T]) --> zorb(H), zorbs(T).
zorbs([]) --> [].
zorb(a) --> [1,2].
zorb(b) --> [3].
zorb(c) --> [6,1,2,2].
I can do this:
?- phrase(zorbs(X), [1,2,3,6,1,2,2]).
X = [a, b, c] .
I can also "reverse" this by doing:
phrase(zorbs([a,b,c]), X).
X = [1, 2, 3, 6, 1, 2, 2].
Now, what I want to do is find a list of numbers with length less than 4 (for example) which these elements "parse" into, returning the rest.
So, for example, given [a,b,c], which would normally relate to [1, 2, 3, 6, 1, 2, 2], I want it to relate to [1, 2, 3] (which has length less than 4) and also give the remainder that couldn't be "reversed," so [c]. I don't really know where to start, as it seems there's no way to reason about the number of elements you've already consumed in a DCG.
Here's a sort-of solution:
X in 0..4,
indomain(X),
Q = [_|_],
prefix(Q, [a,b,c]),
length(A, X),
phrase(zorbs(Q), A).
but I think this is very inefficient, because I think it basically iterates up from nothing, and I want to find the solution with the biggest Q.
There is no direct way how to do this in this case. So your approach is essentially what can be done. That is, you are enumerating all possible solutions and (what you have not shown) selecting them accordingly.
Questions about the biggest and the like include some quantification that you cannot express directly in first order logic.
However, sometimes you can use a couple of tricks.
Sometimes, a partial list like [a,b,c|_] may be helpful.
?- Xs = [_,_,_,_|_], phrase(zorbs(Xs),[1,2,3,6,1,2,2]).
false.
So here we have proven that there is no list of length 4 or longer that corresponds to that sequence. That is, we have proven this for infinitely many lists!
And sometimes, using phrase/3 in place of phrase/2 may help. Say, you have a number sequence that doesn't parse, and you want to know how far it can parse:
?- Ys0 = [1,2,3,6,1,2,7], phrase(zorbs(Xs),Ys0,Ys).
Ys0 = [1,2,3,6,1,2,7], Xs = [], Ys = [1,2,3,6,1,2,7]
; Ys0 = [1,2,3,6,1,2,7], Xs = "a", Ys = [3,6,1,2,7]
; Ys0 = [1,2,3,6,1,2,7], Xs = "ab", Ys = [6,1,2,7]
; false.
(This is with the two DCG-rules exchanged)
Can use:
% Like "between", but counts down instead of up
count_down(High, Low, N) :-
integer(High),
integer(Low),
count_down_(High, Low, N).
count_down_(H, L, N) :-
compare(C, H, L),
count_down_comp_(C, H, L, N).
count_down_comp_('=', _H, L, N) :-
% All equal, final
N = L.
% Accept H as the counting-down value
count_down_comp_('>', H, _L, H).
count_down_comp_('>', H, L, N) :-
H0 is H - 1,
% Decrement H towards L, and loop
count_down_(H0, L, N).
... and then start with:
count_down(4, 1, Len), length(Lst, Len), phrase...
Another method is to use freeze to limit a list's length, element-by-element:
max_len_freeze(Lst, MaxLen) :-
compare(C, MaxLen, 0),
max_len_freeze_comp_(C, Lst, MaxLen).
max_len_freeze_comp_('=', [], 0).
max_len_freeze_comp_('>', [_|Lst], MaxLen) :-
succ(MaxLen0, MaxLen),
!,
freeze(Lst, max_len_freeze(Lst, MaxLen0)).
max_len_freeze_comp_('>', [], _).
... and then start with:
max_len_freeze(Lst, 4), phrase...
This will work to find the longest list (maximum length 4) first, since your DCG is greedy (i.e. matching [H|T] before []).

PROLOG program semantic and exercise

First of all I have a doubt about the semantic of a program , for example :
length([],0).
length([_|L],N):-
length(L,N0),
N is N0 + 1.
The first instruction means the base case , or it has other meanings ?
I have to write a prolog program that, given a number, returns a list of numbers from 0 to the given number.
For example, when the input is 5, the output is [0,1,2,3,4,5].
I'm looking for a solution of this problem but I do not know how to start.
There is a predicate in SWI-Prologs library that does almost what you need to do. It is called numlist/3. You can use it with lower and upper boundary:
?- numlist(1, 5, L).
L = [1, 2, 3, 4, 5].
And here the implementation:
numlist(L, U, Ns) :-
must_be(integer, L),
must_be(integer, U),
L =< U,
numlist_(L, U, Ns).
numlist_(U, U, List) :-
!,
List = [U].
numlist_(L, U, [L|Ns]) :-
L2 is L+1,
numlist_(L2, U, Ns).
You can get rid of the upper half of this completely, and lose one argument (your Lower is just 1).
If you play with this a bit you should be able to figure it out.

Prolog - dividing list into n-elements sections

I have a predict which gets first N elements:
nfirst(N, _, Lnew) :- N =< 0, Lnew = [].
nfirst(_, [], []).
nfirst(N, [X|Y], [X|Y1]) :- N1 is N - 1, nfirst(N1, Y, Y1).
It works:
% nfirst(3,[1,2,3,4,5,6],X).
% X = [1, 2, 3]
I need a predict for divide list like below:
% divide([a,b,c,d,e,f,g,h],[3,2,1,2],X).
% X = [[a,b,c],[d,e],[f],[g,h]]
The best way is using nfirst.
Very similar question to the one I answered here. Again, the trick is to use append/3 plus length/2 to "bite off" a chunk of list, per my comment above:
split_at(N, List, [H|[T]]) :- append(H, T, List), length(H, N).
If you run that, you'll see this:
?- split_at(4, [1,2,3,4,5,6,7,8], X).
X = [[1, 2, 3, 4], [5, 6, 7, 8]] ;
So this is the backbone of your program, and now you just need the usual recursive stuff around it. First, the base case, which says, if I'm out of list, I should be out of split locations, and thus out of result:
divide([], [], []).
Note that explicit base cases like this make your program more correct than something like divide([], _, _) because they will cause you to fail if you get too many split locations for your list size.
Now the recursive case is not difficult, but because split_at/3 puts two things together in a list (probably a bad choice, you could make split_at/4 as an improvement) you have to take them out, and it clouds the logic a bit here while making (IMO) a nicer API on its own.
divide(List, [Split|Splits], [Chunk|Rest]) :-
split_at(Split, List, [Chunk, Remainder]),
divide(Remainder, Splits, Rest).
This should be fairly straightforward: we're just taking a Split location, using it to chop up the List, and repeating the processing on what's left over. It seems to work as you expect:
?- divide([a,b,c,d,e,f,g,h],[3,2,1,2],X).
X = [[a, b, c], [d, e], [f], [g, h]] ;
false.
Hope this helps! Compare to the other answer, it may illuminate things.

Finding the largest even number in list

The point of this program is supposed to be to find the largest even number inside a list. For example, the query:
? - evenmax([1, 3, 9, 16, 25, -5, 18], X]
X = 18.
The way I thought to do this is to separate the list into two, one with just odd numbers and one with just even numbers. However, after doing that, I legitimately have no idea how to take the even-number list specifically and find the maximum integer in that.
Here is what I currently have:
seperate_list([], [], []).
separate_list([X|Xs], [X|Even], Odd) :-
0 is X mod 2,
separate_list(Xs, Even, Odd).
separate_list([X|Xs], Even, [X|Odd]) :-
1 is X mod 2,
separate_list(Xs, Even, Odd).
find_max([X|Xs], A, Max).
X > A,
find_max(Xs,X,Max).
find_max([X|Xs],A,Max) :-
X =< A,
find_max(Xs,A,Max).
find_max([],A,A).
I am still a newcomer to Prolog, so please bear with me...and I appreciate the help.
You could do it in one go. You can find the first even number in the list, then use this as seed and find the largest even number in the rest of the list.
But if you don't insist on doing it in a single traversal through the list, you can first collect all even numbers, then sort descending and take the first element of the sorted list.
evenmax(List, M) :-
include(even, List, Even),
sort(Even, Sorted),
reverse(Sorted, [M|_]).
even(E) :-
E rem 2 =:= 0.
If you want to see how include/2 is implemented, you can look here. Basically, this is a generalized and optimized version of the separate_list/3 that you have already defined in your question. sort/2 is a built-in, and reverse/2 is a library predicate, implementation is here.
There are many other ways to achieve the same, but for starters this should be good enough. You should ask more specific questions if you want more specific answers, for example:
What if the list has free variables?
What if you want to sort in decreasing order instead of sorting and then reversing?
How to do it in a single go?
and so on.
Sorry but... if you need the maximum (even) value... why don't you simply scan the list, memorizing the maximum (even) value?
The real problem that I see is: wich value return when there aren't even values.
In the following example I've used -1000 as minumum value (in case of no even values)
evenmax([], -1000). % or a adeguate minimum value
evenmax([H | T], EM) :-
K is H mod 2,
K == 0,
evenmax(T, EM0),
EM is max(H, EM0).
evenmax([H | T], EM) :-
K is H mod 2,
K == 1,
evenmax(T, EM).
-- EDIT --
Boris is right: the preceding is a bad solution.
Following his suggestions (thanks!) I've completely rewritten my solution. A little longer but (IMHO) a much better
evenmaxH([], 1, EM, EM).
evenmaxH([H | T], 0, _, EM) :-
0 =:= H mod 2,
evenmaxH(T, 1, H, EM).
evenmaxH([H | T], 1, M0, EM) :-
0 =:= H mod 2,
M1 is max(M0, H),
evenmaxH(T, 1, M1, EM).
evenmaxH([H | T], Found, M, EM) :-
1 =:= H mod 2,
evenmaxH(T, Found, M, EM).
evenmax(L, EM) :-
evenmaxH(L, 0, 0, EM).
I define evenmax like there is no member of list L which is even and is greater than X:
memb([X|_], X).
memb([_|T], X) :- memb(T,X).
even(X) :- R is X mod 2, R == 0.
evenmax(L, X) :- memb(L, X), even(X), not((memb(L, Y), even(Y), Y > X)), !.
There are already a number of good answers, but none that actually answers this part of your question:
I legitimately have no idea how to take the even-number list
specifically and find the maximum integer in that
Given your predicate definitions, it would be simply this:
evenmax(List, EvenMax) :-
separate_list(List, Evens, _Odds),
find_max(Evens, EvenMax).
For this find_max/2 you also need to add a tiny definition:
find_max([X|Xs], Max) :-
find_max(Xs, X, Max).
Finally, you have some typos in your code above: seperate vs. separate, and a . instead of :- in a clause head.

Prolog: recursive list construction

I'm having problem constructing a list of lists in my prolog program.
I have a predicate which gives me back a single case of a row. I have to group all the cases of this row and transform them into a list of lists. I can access them just fine but when I exit, all I'll get is the first element.
Here's the code:
sudoku3to2 :- s3to2(1).
s3to2(Line) :-
Line < 9,
Line1 is Line+1,
s3getLine(Line,0,[L]),
assert(sudoku2(Y,L])),
s3to2(Line1).
s3to2(9).
s3getLine(Line,X, , ) :-
X < 9,
X1 is X + 1,
sudoku3(Line,X, ),
s3getLine(Line,X1, , ).
s3getLine(Line,9,L,L).
sudoku3/3 will return the element at the X,Y coordinate. When I get to s3getLine(Line,9,L,L) I'll start going back. I want to keep all the elements I've gathered and not just the first one. And I'm really having trouble constructing the proper predicate calls.
findall/3 is the 'list constructor' more easily understood.
It's a builtin that list all solutions found, shaping the elements with a specified pattern. Here the pattern is really just the variable we are interested to.
I use between/3 to obtaing a correctly ordered matrix, without regard to sudoku3 rules order.
sudoku3(1, 1, a).
sudoku3(1, 2, b).
sudoku3(2, 1, c).
sudoku3(2, 2, d).
mat(M) :-
W = 2,
findall(Row,
(between(1, W, R),
findall(V, (between(1, W, C), sudoku3(R, C, V)), Row)
), M).
Result:
?- mat(M).
M = [[a, b], [c, d]].
You should change W=9.
HTH

Resources