How to generate only rotationally-unique permutations?
John O'Hagan
research at johnohagan.com
Sat May 19 01:23:37 EDT 2012
To revisit a question which I'm sure none of you remember from when I posted it
a year or so ago - there were no takers at the time - I'd like to try again with
a more concise statement of the problem:
How to generate only the distinct permutations of a sequence which are not
rotationally equivalent to any others? More precisely, to generate only the most
"left-packed" of each group of rotationally equivalent permutations, such that
for each permutation p:
p == min(p[i:] + p[:i] for i in range(len(p)) if p[i - 1] == max(p))
At the moment I'm generating all the distinct permutations and filtering the
ones which fail this test, but the inefficiency bothers me and slows down the
program I'm feeding the results to..
Below is some code which removes the maxima from a sequence, permutes it using
some permuting function, and tries to reinsert the maxima in such a way as to
comply with the above requirement:
from itertools import combinations_with_replacement as cwr
def rot_uniq_perms(seq, permfunc):
ma = max(seq)
maxnum = seq.count(ma) - 1
nonmax = [i for i in seq if i != ma]
if nonmax:
for perm in permfunc(nonmax):
perm = perm + [ma]
if maxnum:
inserts = [i for i in range(1, len(perm))
if perm[i] >= perm[0]]
insert_combs = cwr(inserts, maxnum)
for points in insert_combs:
result = perm[:]
for point in reversed(points):
result.insert(point, ma)
if result[:point + 1] > result[point + 1:]:
break
else:
yield result
else:
yield perm
else:
yield seq
This is the most success I've had so far, but unfortunately still generates
2-3% false positives.
I'm also trying a similar approach using the minima instead, which is
intended to generates only the minimum of each rotationally equivalent
group such that:
p == min(p[i:] + p[:i] for i in range(len(p)))
but so far, despite seeming simpler, I've had difficulty getting my head around
it, and it performs far worse than the above code.
I'm looking for any method which would guarantee rotational uniqueness. I
also get the feeling I'm barking up the wrong tree. Any suggestion?
Thanks,
--
John
More information about the Python-list
mailing list