Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

just a few details in permutation.py #38156

Merged
merged 1 commit into from
Jun 9, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 73 additions & 72 deletions src/sage/combinat/permutation.py
Original file line number Diff line number Diff line change
Expand Up @@ -463,17 +463,17 @@ def __classcall_private__(cls, l, check=True):

# if l is a pair of standard tableaux or a pair of lists
elif isinstance(l, (tuple, list)) and len(l) == 2 and \
all(isinstance(x, Tableau) for x in l):
all(isinstance(x, Tableau) for x in l):
return RSK_inverse(*l, output='permutation')
elif isinstance(l, (tuple, list)) and len(l) == 2 and \
all(isinstance(x, list) for x in l):
P,Q = (Tableau(_) for _ in l)
all(isinstance(x, list) for x in l):
P, Q = (Tableau(_) for _ in l)
return RSK_inverse(P, Q, 'permutation')
# if it's a tuple or nonempty list of tuples, also assume cycle
# notation
elif isinstance(l, tuple) or \
(isinstance(l, list) and l and
all(isinstance(x, tuple) for x in l)):
all(isinstance(x, tuple) for x in l)):
if l and (isinstance(l[0], (int, Integer)) or len(l[0]) > 0):
if isinstance(l[0], tuple):
n = max(max(x) for x in l)
Expand Down Expand Up @@ -683,8 +683,8 @@ def _latex_(self):
return " ".join(f"{let}_{{{i}}}" for i in redword)
if display == "twoline":
return r"\begin{{pmatrix}} {} \\ {} \end{{pmatrix}}".format(
" & ".join("%s" % i for i in range(1, len(self._list)+1)),
" & ".join("%s" % i for i in self._list))
" & ".join("%s" % i for i in range(1, len(self._list)+1)),
" & ".join("%s" % i for i in self._list))
if display == "list":
return repr(self._list)
if display == "cycle":
Expand Down Expand Up @@ -1068,20 +1068,20 @@ def _to_cycles_set(self, singletons=True):

if not singletons:
# remove the fixed points
L = {i+1 for i,pi in enumerate(p) if pi != i+1}
L = {i for i, pi in enumerate(p, start=1) if pi != i}
else:
L = set(range(1,len(p)+1))
L = set(range(1, len(p) + 1))

# Go through until we've considered every remaining number
while L:
# take the first remaining element
cycleFirst = L.pop()
next = p[cycleFirst-1]
next = p[cycleFirst - 1]
cycle = [cycleFirst]
while next != cycleFirst:
cycle.append(next)
L.remove(next)
next = p[next-1]
next = p[next - 1]
# add the cycle
cycles.append(tuple(cycle))

Expand Down Expand Up @@ -1109,7 +1109,7 @@ def _to_cycles_list(self, singletons=True):

if not singletons:
# remove the fixed points
L = [i + 1 for i, pi in enumerate(p) if pi != i + 1]
L = [i for i, pi in enumerate(p, start=1) if pi != i]
else:
L = list(range(1, len(p) + 1))

Expand All @@ -1125,7 +1125,7 @@ def _to_cycles_list(self, singletons=True):
cycle.append(next)
# remove next from L
# we use a binary search to find it
L.pop(bisect_left(L,next))
L.pop(bisect_left(L, next))
next = p[next-1]
# add the cycle
cycles.append(tuple(cycle))
Expand Down Expand Up @@ -1164,7 +1164,7 @@ def signature(self) -> Integer:
sage: Permutation([]).sign()
1
"""
return (-1)**(len(self)-len(self.to_cycles()))
return (-1)**(len(self) - len(self.to_cycles()))

# one can also use sign as an alias for signature
sign = signature
Expand Down Expand Up @@ -1592,7 +1592,7 @@ def merge_and_countv(ivA_A, ivB_B):
else:
C.extend(B[j:])
ivC.extend(ivB[j:])
return ivC,C
return ivC, C

def base_case(L):
s = sorted(L)
Expand Down Expand Up @@ -1628,7 +1628,7 @@ def inversions(self) -> list:
"""
p = self[:]
n = len(p)
return [(i+1,j+1) for i in range(n-1) for j in range(i+1,n)
return [(i+1, j+1) for i in range(n-1) for j in range(i+1, n)
if p[i] > p[j]]

def stack_sort(self) -> Permutation:
Expand Down Expand Up @@ -1917,7 +1917,7 @@ def absolute_length(self) -> Integer:
"""
return self.size() - len(self.cycle_type())

@combinatorial_map(order=2,name='inverse')
@combinatorial_map(order=2, name='inverse')
def inverse(self) -> Permutation:
r"""
Return the inverse of ``self``.
Expand All @@ -1932,8 +1932,8 @@ def inverse(self) -> Permutation:
[3, 1, 5, 2, 4]
"""
w = list(range(len(self)))
for i, j in enumerate(self):
w[j - 1] = i + 1
for i, j in enumerate(self, start=1):
w[j - 1] = i
return Permutations()(w)

__invert__ = inverse
Expand Down Expand Up @@ -3081,7 +3081,6 @@ def number_of_fixed_points(self) -> Integer:
sage: Permutation([1,2,3,4]).number_of_fixed_points()
4
"""

return len(self.fixed_points())

def is_derangement(self) -> bool:
Expand Down Expand Up @@ -3778,7 +3777,7 @@ def weak_excedences(self) -> list:
sage: Permutation([1,4,3,2,5]).weak_excedences()
[1, 4, 3, 5]
"""
return [pi for i, pi in enumerate(self) if pi >= i + 1]
return [pi for i, pi in enumerate(self, start=1) if pi >= i]

def bruhat_inversions(self) -> list:
r"""
Expand Down Expand Up @@ -5370,7 +5369,7 @@ def shifted_shuffle(self, other):
True
"""
return self.shifted_concatenation(other, "right").\
right_permutohedron_interval(self.shifted_concatenation(other, "left"))
right_permutohedron_interval(self.shifted_concatenation(other, "left"))

def nth_roots(self, n):
r"""
Expand Down Expand Up @@ -5480,8 +5479,8 @@ def rewind(L, n):
b = True
poss = [P.identity()]
for pa in partition:
poss = [p*q for p in poss
for q in merging_cycles([rewind(cycles[m][i-1], n//len(pa)) for i in pa])]
poss = [p*q for p in poss
for q in merging_cycles([rewind(cycles[m][i-1], n//len(pa)) for i in pa])]
possibilities[i] += poss
if not b:
return
Expand Down Expand Up @@ -5613,6 +5612,7 @@ def number_of_nth_roots(self, n):

return result


def _tableau_contribution(T):
r"""
Get the number of SYT of shape(``T``).
Expand Down Expand Up @@ -5856,21 +5856,21 @@ def __classcall_private__(cls, n=None, k=None, **kwargs):
if len(a) == 1 and a[0] != 1:
a = a[0]
if a in StandardPermutations_all():
if a == [1,2]:
if a == [1, 2]:
return StandardPermutations_avoiding_12(n)
elif a == [2,1]:
elif a == [2, 1]:
return StandardPermutations_avoiding_21(n)
elif a == [1,2,3]:
elif a == [1, 2, 3]:
return StandardPermutations_avoiding_123(n)
elif a == [1,3,2]:
elif a == [1, 3, 2]:
return StandardPermutations_avoiding_132(n)
elif a == [2,1,3]:
elif a == [2, 1, 3]:
return StandardPermutations_avoiding_213(n)
elif a == [2,3,1]:
elif a == [2, 3, 1]:
return StandardPermutations_avoiding_231(n)
elif a == [3,1,2]:
elif a == [3, 1, 2]:
return StandardPermutations_avoiding_312(n)
elif a == [3,2,1]:
elif a == [3, 2, 1]:
return StandardPermutations_avoiding_321(n)
else:
return StandardPermutations_avoiding_generic(n, (a,))
Expand Down Expand Up @@ -5970,36 +5970,36 @@ class options(GlobalOptions):
NAME = 'Permutations'
module = 'sage.combinat.permutation'
display = {'default': "list",
'description': "Specifies how the permutations should be printed",
'values': {'list': "the permutations are displayed in list notation"
" (aka 1-line notation)",
'cycle': "the permutations are displayed in cycle notation"
" (i. e., as products of disjoint cycles)",
'singleton': "the permutations are displayed in cycle notation"
" with singleton cycles shown as well",
'reduced_word': "the permutations are displayed as reduced words"},
'alias': {'word': "reduced_word", 'reduced_expression': "reduced_word"},
'case_sensitive': False}
latex = {'default': "list",
'description': "Specifies how the permutations should be latexed",
'values': {'list': "latex as a list in one-line notation",
'twoline': "latex in two-line notation",
'cycle': "latex in cycle notation",
'singleton': "latex in cycle notation with singleton cycles shown as well",
'reduced_word': "latex as reduced words"},
'alias': {'word': "reduced_word", 'reduced_expression': "reduced_word", 'oneline': "list"},
'description': "Specifies how the permutations should be printed",
'values': {'list': "the permutations are displayed in list notation"
" (aka 1-line notation)",
'cycle': "the permutations are displayed in cycle notation"
" (i. e., as products of disjoint cycles)",
'singleton': "the permutations are displayed in cycle notation"
" with singleton cycles shown as well",
'reduced_word': "the permutations are displayed as reduced words"},
'alias': {'word': "reduced_word", 'reduced_expression': "reduced_word"},
'case_sensitive': False}
latex = {'default': "list",
'description': "Specifies how the permutations should be latexed",
'values': {'list': "latex as a list in one-line notation",
'twoline': "latex in two-line notation",
'cycle': "latex in cycle notation",
'singleton': "latex in cycle notation with singleton cycles shown as well",
'reduced_word': "latex as reduced words"},
'alias': {'word': "reduced_word", 'reduced_expression': "reduced_word", 'oneline': "list"},
'case_sensitive': False}
latex_empty_str = {'default': "1",
'description': 'The LaTeX representation of a reduced word when said word is empty',
'checker': lambda char: isinstance(char,str)}
'description': 'The LaTeX representation of a reduced word when said word is empty',
'checker': lambda char: isinstance(char, str)}
generator_name = {'default': "s",
'description': "the letter used in latexing the reduced word",
'checker': lambda char: isinstance(char,str)}
'description': "the letter used in latexing the reduced word",
'checker': lambda char: isinstance(char, str)}
mult = {'default': "l2r",
'description': "The multiplication of permutations",
'values': {'l2r': r"left to right: `(p_1 \cdot p_2)(x) = p_2(p_1(x))`",
'r2l': r"right to left: `(p_1 \cdot p_2)(x) = p_1(p_2(x))`"},
'case_sensitive': False}
'description': "The multiplication of permutations",
'values': {'l2r': r"left to right: `(p_1 \cdot p_2)(x) = p_2(p_1(x))`",
'r2l': r"right to left: `(p_1 \cdot p_2)(x) = p_1(p_2(x))`"},
'case_sensitive': False}


class Permutations_nk(Permutations):
Expand Down Expand Up @@ -6082,7 +6082,8 @@ def __iter__(self) -> Iterator[Permutation]:
sage: [p for p in Permutations(3,4)]
[]
"""
for x in itertools.permutations(range(1,self.n+1), int(self._k)):
for x in itertools.permutations(range(1, self.n + 1),
int(self._k)):
yield self.element_class(self, x, check=False)

def cardinality(self) -> Integer:
Expand Down Expand Up @@ -7751,8 +7752,8 @@ def inverse(self):
[4, 2, 1, 3]
"""
w = list(range(len(self)))
for i, j in enumerate(self):
w[j - 1] = i + 1
for i, j in enumerate(self, start=1):
w[j - 1] = i
return self.__class__(self.parent(), w)

__invert__ = inverse
Expand Down Expand Up @@ -7868,8 +7869,8 @@ def from_rank(n, rank):
"""
# Find the factoradic of rank
factoradic = [None] * n
for j in range(1,n+1):
factoradic[n-j] = Integer(rank % j)
for j in range(1, n + 1):
factoradic[n - j] = Integer(rank % j)
rank = int(rank) // j

return from_lehmer_code(factoradic, Permutations(n))
Expand All @@ -7896,8 +7897,8 @@ def from_inversion_vector(iv, parent=None):
"""
p = iv[:]
open_spots = list(range(len(iv)))
for i, ivi in enumerate(iv):
p[open_spots.pop(ivi)] = i + 1
for i, ivi in enumerate(iv, start=1):
p[open_spots.pop(ivi)] = i

if parent is None:
parent = Permutations()
Expand Down Expand Up @@ -8182,16 +8183,16 @@ def bistochastic_as_sum_of_permutations(M, check=True):

while G.size() > 0:
matching = G.matching(use_edge_labels=True)
matching = [(min(u,v), max(u, v), w) for u,v,w in matching]
matching = [(min(u, v), max(u, v), w) for u, v, w in matching]

# This minimum is strictly larger than 0
minimum = min([x[2] for x in matching])

for (u,v,l) in matching:
for u, v, l in matching:
if minimum == l:
G.delete_edge((u,v,l))
G.delete_edge((u, v, l))
else:
G.set_edge_label(u,v,l-minimum)
G.set_edge_label(u, v, l - minimum)

matching.sort(key=lambda x: x[0])
value += minimum * CFM(P([x[1]-n+1 for x in matching]))
Expand Down Expand Up @@ -8481,9 +8482,9 @@ def descents_composition_last(dc):
raise TypeError("The argument must be of type Composition")
s = 0
res = []
for i in reversed(range(len(dc))):
res = list(range(s+1,s+dc[i]+1)) + res
s += dc[i]
for dci in reversed(dc):
res = list(range(s + 1, s + dci + 1)) + res
s += dci

return Permutations()(res)

Expand Down Expand Up @@ -8756,7 +8757,7 @@ def from_major_code(mc, final_descent=False):
# the letter i into the word w^(i+1) in such a way that
# maj(w^i)-maj(w^(i+1)) = mc[i]

for i in reversed(range(1,len(mc))):
for i in reversed(range(1, len(mc))):
# Lemma 2.2 in Skandera

# Get the descents of w and place them in reverse order
Expand Down
Loading