https://github.com/emarberg/virtual-permutations
Tip revision: e45c307a4731bedf4fcb0393d5ddb69ea863f63a authored by Eric Marberg on 23 March 2020, 06:38:45 UTC
fixed typo
fixed typo
Tip revision: e45c307
tex.py
import argparse
import itertools
import os
import time
import sys
from virtual import VirtualInvolution, VirtualPermutation
if sys.version_info < (3, 0):
major, minor = sys.version_info.major, sys.version_info.minor
sys.stdout.write("\nSorry, requires Python 3. ")
sys.stdout.write("(This is Python %s.%s.)\n\n" % (major, minor))
sys.exit(1)
class TexMixin:
"""
Mixin class with some helper functions for string formatting.
"""
def write(self, force):
self._tex()
if not force and os.path.isfile(self.path):
print ("* Aborting: file `%s` exists. Delete this or use `-f` flag to regenerate." % self.path)
return False
with open(self.path, 'w') as f:
f.write('\n'.join(self.lines))
return True
def tex_char(self, ch):
y, i, j = self.y, self.i, self.j
if ch == i:
return 'i'
if ch == j:
return 'j'
if ch == y(i):
return 'y_i'
if ch == y(j):
return 'y_j'
if ch == -i:
return "i'"
if ch == -j:
return "j'"
if ch == -y(i):
return "y_{i'}"
if ch == -y(j):
return "y_{j'}"
p, q = VirtualPermutation.CYCLE_CHARS
if ch == p:
return 'P'
if ch == q:
return 'Q'
r = VirtualPermutation.FIXED_CHAR
if ch == r:
return 'R'
def tex_list(self, pi):
tup = tuple(self.tex_char(c) for c in pi)
return '\\dash '.join(('',) + tup + ('',))
def tex_order(self):
y, i, j = self.y, self.i, self.j
order = []
for a in range(1, 1 + y.rank):
if a == i == y(i):
order.append('y_i = i')
elif a == j == y(j):
order.append('j = y_j')
else:
order.append(self.tex_char(a))
return ' < '.join(order)
def tex_cycles(self, z):
y, i, j = self.y, self.i, self.j
k, l = y(i), y(j)
cyc = {tuple(sorted([a, z(a)])) for a in (i, j, k, l)}
pos_cyc = ['(%s,%s)' % (self.tex_char(a), self.tex_char(b)) for a, b in cyc]
neg_cyc = ['(%s,%s)' % (self.tex_char(-a), self.tex_char(-b)) for a, b in cyc]
return '\\{%s\\}' % ','.join(pos_cyc), '\\{%s\\}' % ','.join(neg_cyc)
def _tex_properties(self, order, tuples, letter='Z'):
def ch(a):
return self.tex_char(a)
prop1 = sorted({
"$(wt)^{-1} = \\dash %s \\dash %s \\dash$" % (ch(b), ch(a))
for a, b, c, d in tuples if order[a] < order[b]
} | {
"$(wt)^{-1} = \\dash %s \\dash %s \\dash$" % (ch(d), ch(c))
for a, b, c, d in tuples if order[c] < order[d]
})
prop2 = sorted({
"$(wt)^{-1} \\neq \\dash %s \\dash %s \\dash %s \\dash$ and $(wt)^{-1}\\neq \\dash %s \\dash %s \\dash %s \\dash$"
% (ch(b), ch(c), ch(a), ch(b), ch(d), ch(a))
for a, b, c, d in tuples if order[a] < order[c] < order[d] < order[b]
} | {
"$(wt)^{-1} \\neq \\dash %s \\dash %s \\dash %s \\dash$" % (ch(b), ch(c), ch(a))
for a, b, c, d in tuples if order[a] < order[c] == order[d] < order[b]
})
prop3 = sorted({
"$(wt)^{-1} = \\dash %s \\dash %s \\dash$" % (ch(a), ch(d))
for a, b, c, d in tuples if order[a] < order[c] and order[b] < order[d]
})
def j(v):
if len(v) == 0:
return '(no condition).'
if len(' and '.join(v).split('and')) > 2:
par = ['\\text{' + c + '}' for c in v]
return '$\\begin{cases}' + '\\text{ and }\\\\\n'.join(par) + '.\\end{cases}$'
else:
return ' and '.join(v) + '.'
self.lines += ['\\begin{enumerate}']
self.lines += ['\\item[](%s1) $\\Leftrightarrow$ ' % letter + j(prop1)]
self.lines += ['\\item[](%s2) $\\Leftrightarrow$ ' % letter + j(prop2)]
self.lines += ['\\item[](%s3) $\\Leftrightarrow$ ' % letter + j(prop3)]
self.lines += ['\\end{enumerate}']
def _tex_process_reasons(self, reasons):
mapping = {
VirtualInvolution.REASON_B1: '(T)',
VirtualInvolution.REASON_B2: '(U)',
VirtualInvolution.REASON_F1: '(Y3)',
VirtualInvolution.REASON_F2: '(Y2)',
VirtualInvolution.REASON_F3: '(Y3)',
VirtualInvolution.REASON_F4: '(Y3)',
VirtualInvolution.REASON_C1: '(Y1)',
VirtualInvolution.REASON_C2: '(Y3)',
VirtualInvolution.REASON_C3: '(Y2)',
VirtualInvolution.REASON_C4: '(Y2)',
}
reason, data = reasons[0]
if reason not in [VirtualInvolution.REASON_B1, VirtualInvolution.REASON_B2]:
if reason == VirtualInvolution.REASON_C1:
a, b = data
a, b = self.tex_char(a), self.tex_char(b)
return mapping[reason] + ' fails for $(a,b)=(%s,%s)$' % (a, b)
else:
a, b, c, d = data
a, b, c, d = self.tex_char(a), self.tex_char(b), self.tex_char(c), self.tex_char(d)
return mapping[reason] + ' fails for $(a,b)=(%s,%s)$ and $(a\',b\')=(%s,%s)$' % (a, b, c, d)
else:
return mapping[reason] + ' fails'
class CoveringPropertyTexWriter(TexMixin):
def __init__(self, path=None):
directory = os.path.dirname(os.path.abspath(__file__))
self.path = path if path else os.path.join(directory, 'tex/covering-property.tex')
self.lines = None
self.y = None
self.i = None
self.j = None
def _tex(self):
self.lines = ["""
\\documentclass[10pt]{article}
\\usepackage{amsmath,amssymb,amsthm,fullpage,hyperref}
\\usepackage[margin=0.75in]{geometry}
\\usepackage[shortlabels]{enumitem}
\\theoremstyle{definition}
\\newtheorem*{theorem}{Theorem}
\\theoremstyle{definition}
\\newtheorem{lemma}{Lemma}
\\def\\dash{\\text{\\hspace{0.5mm}---\\hspace{0.5mm}}}
\\def\\Fix{\\mathrm{Fix}}
\\def\\Cyc{\\mathrm{Cyc}}
\\def\\ZZ{\\mathbb{Z}}
\\begin{document}
\\title{Computer-generated proof of affine involution covering property}
\\author{Eric MARBERG \\and Yifeng ZHANG}
\\maketitle
\\tableofcontents
\\section{Setup}
Let $n$ be a positive integer.
For the definition of the affine symmetric group $\\tilde S_n$, see \\cite{M}.
Fix an affine permutation $w \\in \\tilde S_n$ and an involution $y =y^{-1} \\in\\tilde S_n$.
We set $y_a = y(a)$ for $a \\in \\ZZ$ and define
\\[\\Cyc(y) = \\{ (a,b) \\in \\ZZ\\times\\ZZ : a \\leq b = y_a\\}.\\]
As a shorthand, we write $w^{-1} = \\dash a\\dash b\\dash c \\dash \\cdots\\dash d \\dash$
to mean that $w_a < w_b < w_c < \\dots < w_d$.
\\begin{lemma}\\label{lem-1}
One has $w \\in \\mathcal{A}(y)$
if and only if for all $(a,b),(a',b') \\in \\Cyc(y)$, the following properties hold:
\\begin{enumerate}
\\item[(Y1)] If $a < b$ then $w^{-1} = \\dash b \\dash a \\dash$.
\\item[(Y2)] If $a < a' \\leq b' < b$ then $w^{-1} \\neq \\dash b \\dash a' \\dash a \\dash$
and $w^{-1}\\neq \\dash b \\dash b' \\dash a \\dash.$
\\item[(Y3)] If $a < a'$ and $b < b'$ then $w^{-1} = \\dash a \\dash b' \\dash.$
\\end{enumerate}
\\end{lemma}
\\begin{proof}
This is equivalent to \\cite[Theorem 7.6]{M}.
\\end{proof}
Fix integers $i < j$ that are not congruent modulo $n$.
Let $t=t_{ij} \\in \\tilde S_n$ denote the reflection
that interchanges $i$ and $j$ while fixing all integers not congruent to
$i$ or $j$ modulo $n$.
Write $\\lessdot$ for the covering relation in the Bruhat order on $\\tilde S_n$.
\\begin{lemma}
One has $w \\lessdot wt$
if and only if the following property holds:
\\begin{enumerate}
\\item[(T)] $w^{-1} = \\dash i \\dash j \\dash$ but if $i<e<j$
then $w^{-1} \\neq \\dash i \\dash e \\dash j\\dash$.
\\end{enumerate}
Moreover, if $i\'$ and $j\'$ are integers with $i-i\' = j-j\' \\in n\\ZZ$,
then property (T) is equivalent to the following:
\\begin{enumerate}
\\item[(U)] $w^{-1} = \\dash i\' \\dash j\' \\dash$ but if $i\'<e<j\'$
then $w^{-1} \\neq \\dash i\' \\dash e \\dash j\'\\dash$.
\\end{enumerate}
\\end{lemma}
\\begin{proof}
This is equivalent to \\cite[Proposition 8.3.6]{BB}.
\\end{proof}
Recall the definition of the operator $\\tau^n_{ij}$ from \\cite[\\S8]{M} and
let $z = z^{-1} = \\tau^n_{ij}(y) \\in \\tilde S_n$.
\\begin{theorem}
Assume $\\{i, y_i\\} + n \\ZZ$ and $\\{j,y_j\\} + n \\ZZ$ are disjoint.
If $y \\neq z$, $w \\in \\mathcal{A}(y)$, and $w\\lessdot wt$, then $wt \\in \\mathcal{A}(z)$.
\\end{theorem}
The proof of this statement occupies the rest of this computer-generated document.
\\begin{proof}
Assume that $\\{i, y_i\\} + n \\ZZ$ and $\\{j,y_j\\} + n \\ZZ$ are disjoint
and that $y \\neq z$ and $w \\in \\mathcal{A}(y)$ and $w\\lessdot wt$.
Observe that if $i \\neq y_i$ then the sets $i + n\\ZZ$ and $y_i + n \\ZZ$ are disjoint,
and that if $j \\neq y_j$ then the sets $j + n\\ZZ$ and $y_j + n\\ZZ$ are disjoint.
To show that $wt \\in \\mathcal{A}(z)$, it suffices by Lemma~\\ref{lem-1} to check that if
$(a,b),(a',b') \\in \\Cyc(z)$ then the following properties hold:
\\begin{enumerate}
\\item[(Z1)] If $a < b$ then $(wt)^{-1} = \\dash b \\dash a \\dash$.
\\item[(Z2)] If $a < a' \\leq b' < b$ then $(wt)^{-1} \\neq \\dash b \\dash a' \\dash a \\dash$
and $(wt)^{-1}\\neq \\dash b \\dash b' \\dash a.$
\\item[(Z3)] If $a < a'$ and $b < b'$ then $(wt)^{-1} = \\dash a \\dash b' \\dash.$
\\end{enumerate}
Let $E = \\{i, j, y_i, y_j\\}$.
Then $w_a = (wt)_a$ and $y_a = z_a$ for all integers $a \\notin E + n\\ZZ$,
and we may decompose $\\Cyc(z)$ as a disjoint union of four subsets
$
\\Cyc(z) = \\Cyc^1(z) \\sqcup \\Cyc^2(z) \\sqcup \\Cyc^3(z)
$
where
\\[
\\begin{aligned}
\\Cyc^1(z) &= \\{ (a,b) \\in \\Cyc(z): a,b \\in E\\},\\\\
\\Cyc^2(z) &= \\{ (a,b) \\in \\Cyc(y): a,b \\notin E + n\\ZZ\\} =
\\{ (a,b) \\in \\Cyc(z): a,b \\notin E + n\\ZZ\\},\\\\
\\Cyc^3(z) &= \\{ (a+mn,b+mn): 0 \\neq m \\in \\ZZ\\text{ and }(a,b)\\in \\Cyc^1(z)\\}.
\\end{aligned}
\\]
When $(a,b),(a',b') \\in \\Cyc^2(z)\\subset \\Cyc(y)$,
properties (Z1)-(Z3) are equivalent to (Y1)-(Y3)
and therefore hold since $w \\in \\mathcal{A}(y)$.
It remains to check properties (Z1)-(Z3) in the following cases:
\\begin{itemize}
\\item[(i)] When $(a,b),(a',b') \\in \\Cyc^1(z)$.
\\item[(ii)] When one of the pairs $(a,b)$, $(a',b')$ belongs to $\\Cyc^1(z)$
while the other belongs to $\\Cyc^2(z)$.
\\item[(iii)] When $(a,b) \\in \\Cyc^1(z)$ and $(a',b') \\in \\Cyc^3(z)$,
or $(a',b') \\in \\Cyc^1(z)$ and $(a,b) \\in \\Cyc^3(z)$.
\\end{itemize}
Since we assume $z = \\tau^n_{ij}(y) \\neq y$,
there are twelve possibilities for the relative orders of $i$, $j$, $y_i$, and $y_j$.
We examine each of these possibilities in turn and check directly that
properties (Z1)-(Z3) hold in cases (i), (ii), and (iii).
"""]
for y in VirtualInvolution.all(maximum_size=4, mimimal_type=True):
for i, j in itertools.combinations(range(1, y.rank + 1), 2):
if y.tau(i, j) != y:
self.y = y
self.i = i
self.j = j
self._tex_involution_analysis()
self.lines += ["""
\\section{Conclusion}
It follows from this exhaustive case analysis
that properties (Z1)-(Z3) hold for all pairs $(a,b),(a\',b\') \\in \\Cyc(z)$.
We conclude by Lemma~\\ref{lem-1} that $wt \\in \\mathcal{A}(z)$.
This completes the proof of the theorem.
\\end{proof}
\\begin{thebibliography}{99}
\\bibitem{BB} A. Bj\\"orner and F. Brenti,
\\emph{Combinatorics of Coxeter groups},
Graduate Texts in Mathematics 231, Springer, New York, 2005.
\\bibitem{M} E. Marberg,
On some actions of the $0$-Hecke monoids of affine symmetric groups,
\\emph{J. Combin. Theory Ser. A} \\textbf{161} (2019), 178--219.
\\end{thebibliography}
\\end{document}
"""]
def _tex_involution_analysis(self):
self.lines += ['\\section{Case: $%s$}' % self.tex_order()]
self.lines += ['Suppose $y$ is such that $%s$.' % self.tex_order()]
z = self.y.tau(self.i, self.j)
z_cyc, neg_z_cyc = self.tex_cycles(z)
self.lines += ['Then $z = \\tau^n_{ij}(y)$ has $\\Cyc^1(z) = %s.$' % z_cyc]
self.lines += ['\\subsection{Subcase (i)}']
base = tuple(sorted(self.y.involution))
valid, invalid = [], []
for pi in itertools.permutations(base):
errors = self._tex_invalid_atom_analysis(base, pi)
if errors:
invalid += errors
else:
valid += [pi]
invalid = [line for line, _ in sorted(invalid, key=lambda pair: pair[1])]
assert len(valid) == 1
pi = valid[0]
self.lines += ['We must have $w^{-1} = %s$' % self.tex_list(pi)]
self.lines += ['since no other ordering is possible:']
self.lines += ['\\begin{enumerate}'] + invalid + ['\\end{enumerate}']
all_mirror, all_double, all_single = VirtualPermutation.maximal_extensions(pi)
virtual = VirtualPermutation(pi, all_mirror, all_double, all_single)
required_ascents = {(self.i, self.j)}
invalid_dictionary = self.y.get_invalid_configurations(virtual, required_ascents)
mirror = {e: all_mirror[e] - set(invalid_dictionary[e].keys()) for e in all_mirror}
double = {e: all_double[e] - set(invalid_dictionary[e].keys()) for e in all_double}
single = {e: all_single[e] - set(invalid_dictionary[e].keys()) for e in all_single}
w = VirtualPermutation(pi, mirror, double, single)
wt = w.transpose(self.i, self.j)
assert z.is_virtual_atom(wt)
self.lines += ['Hence if $%s$ then \\begin{enumerate}\\item[] $(wt)^{-1} = %s$. \\end{enumerate}' % (self.tex_order(), self.tex_list(wt.permutation))]
self.lines += ['When $(a,b),(a\',b\')\\in\\Cyc^1(z)= %s$,' % z_cyc]
self.lines += ['properties (Z1)-(Z3) are equivalent to the following conditions which all hold in this case:']
order = {b: i for i, b in enumerate(base)}
cyc = {(i, z(i)) for i in range(1, z.rank + 1) if i <= z(i)}
tuples = [(a, b, c, d) for a, b in cyc for c, d in cyc]
self._tex_properties(order, tuples)
self.lines += ['Thus properties (Z1)-(Z3) hold whenever $(a,b)$, $(a\',b\')$ are as in case (i) and $%s$.' % self.tex_order()]
y, i, j = self.y, self.i, self.j
subset = '\\{i,j' + (',y_i' if y(i) != i else '') + (',y_j' if y(j) != j else '') + '\\}'
c = self.tex_char(VirtualPermutation.FIXED_CHAR)
self.lines += ['\\subsection{Subcase (ii)}']
self.lines += ['Suppose $%s$ is an integer such that $(%s,%s) \\in \\Cyc^2(z)\\subset\\Cyc(y)$, so that ' % (c, c, c)]
self.lines += ['$%s = y_%s = z_%s \\notin %s + n\\mathbb{Z}$.' % (c, c, c, subset)]
self._tex_list_extensions_single(w, invalid_dictionary, all_single)
p, q = VirtualPermutation.CYCLE_CHARS
p, q = self.tex_char(p), self.tex_char(q)
self.lines += ['Next suppose $%s < %s$ are integers with $(%s, %s) \\in \\Cyc^2(z)\\subset\\Cyc(y)$, so that ' % (p, q, p, q)]
self.lines += ['$%s = y_{%s} = z_{%s}$ and $%s,%s\\notin %s + n\\ZZ$.' % (q, p, p, p, q, subset)]
self._tex_list_extensions_double(w, invalid_dictionary, all_double)
self.lines += ['We conclude that properties (Z1)-(Z3) hold whenever $(a,b)$, $(a\',b\')$ are as in cases (i) or (ii) and $%s$.' % self.tex_order()]
_i, _j = self.tex_char(-self.i), self.tex_char(-self.j)
self.lines += ['\\subsection{Subcase (iii)}']
self.lines += ['Suppose $%s$ and $%s$ are integers such that' % (_i, _j)]
self.lines += ['$0\\neq i - %s = j - %s \\in n\\ZZ$,' % (_i, _j)]
self.lines += ['so that $w(i) - w(%s) = w(j) - w(%s) = i - %s$.' % (_i, _j, _i)]
self._tex_list_extensions_mirror(w, invalid_dictionary, all_mirror)
self.lines += ['We conclude that properties (Z1)-(Z3) hold for all ']
self.lines += ['$(a,b),(a\',b\') \\in \\Cyc(z)$ when $%s$.' % self.tex_order()]
def _tex_invalid_atom_analysis(self, base, pi):
virtual = VirtualPermutation(pi, {}, {}, {})
invalid_dictionary = self.y.get_invalid_configurations(virtual, required_ascents={(self.i, self.j)})
if invalid_dictionary:
assert list(invalid_dictionary) == [base]
assert pi in invalid_dictionary[base]
reasons = invalid_dictionary[base][pi]
prop = self._tex_process_reasons(reasons)
return [('\\item If $w^{-1} = %s$ then %s.' % (self.tex_list(pi), prop), prop)]
else:
return []
SINGLE = 0
DOUBLE = 1
MIRROR = 2
def _tex_list_extensions_single(self, w, invalid_dict, all_dict):
self._tex_list_extensions(w, invalid_dict, all_dict, w.single_extensions, self.SINGLE)
def _tex_list_extensions_double(self, w, invalid_dict, all_dict):
self._tex_list_extensions(w, invalid_dict, all_dict, w.double_extensions, self.DOUBLE)
def _tex_list_extensions_mirror(self, w, invalid_dict, all_dict):
self._tex_list_extensions(w, invalid_dict, all_dict, w.mirror_extensions, self.MIRROR)
def _tex_list_extensions(self, w, invalid_dictionary, all_dict, valid_dict, option):
start = [base for base in set(invalid_dictionary) & set(all_dict) if valid_dict[base]]
end = [base for base in set(invalid_dictionary) & set(all_dict) if not valid_dict[base]]
self.lines += ['\\begin{enumerate}']
for index, base in enumerate(start + end):
order = ' < '.join(self.tex_char(a) for a in base)
item = '$%s$.' % (index + 1)
if valid_dict[base]:
self.lines += ['\\item[%s] Suppose $%s$.' % (item, order)]
else:
self.lines += ['\\item[%s] It cannot happen that $%s$ since:' % (item, order)]
self.lines += ['\\begin{enumerate}[(a)]']
items = {
pi: self._tex_process_reasons(reasons)
for pi, reasons in invalid_dictionary[base].items()
}
for pi, prop in sorted(items.items(), key=lambda pair: pair[1]):
self.lines += ['\\item If $w^{-1} = %s$ then %s.' % (self.tex_list(pi), prop)]
self.lines += ['\\end{enumerate}']
if valid_dict[base]:
self.lines += ['Thus if $%s$ then one of the following holds:' % order]
self.lines += ['\\begin{enumerate}']
for pi in valid_dict[base]:
i, j = self.i, self. j
t = {i: j, j: i, -i: -j, -j: -i}
sigma = tuple(t.get(x, x) for x in pi)
p, q = self.tex_list(pi), self.tex_list(sigma)
self.lines += ['\\item[$\\bullet$] $w^{-1} = %s$ and $(wt)^{-1} = %s$.' % (p, q)]
self.lines += ['\\end{enumerate}']
plural = len(valid_dict[base]) > 1
self._tex_conclusions(base, plural, option)
self.lines += ['\\end{enumerate}']
def _tex_conclusions(self, base, plural, option):
if option == self.SINGLE:
self._tex_single_conclusions(base, plural)
elif option == self.DOUBLE:
self._tex_double_conclusions(base, plural)
elif option == self.MIRROR:
self._tex_mirror_conclusions(base, plural)
else:
raise NotImplementedError
def _tex_single_conclusions(self, base, plural):
z = self.y.tau(self.i, self.j)
order = {b: i for i, b in enumerate(base)}
cyc_a = {(VirtualPermutation.FIXED_CHAR, VirtualPermutation.FIXED_CHAR)}
cyc_b = {(i, z(i)) for i in range(1, z.rank + 1) if order[i] <= order[z(i)]}
tuples = [(a, b, c, d) for a, b in cyc_a for c, d in cyc_b]
tuples += [(c, d, a, b) for a, b in cyc_a for c, d in cyc_b]
z_cyc, _ = self.tex_cycles(z)
c = self.tex_char(VirtualPermutation.FIXED_CHAR)
self.lines += ['When $(a,b)= (%s,%s)$ and $(a\',b\')\\in \\Cyc^1(z)=%s$ or vice versa,' % (c, c, z_cyc)]
self.lines += ['properties (Z1)-(Z3) correspond to the following conditions which']
self.lines += ['hold in each of the available cases for $wt$:']
self._tex_properties(order, tuples)
def _tex_double_conclusions(self, base, plural):
z = self.y.tau(self.i, self.j)
order = {b: i for i, b in enumerate(base)}
cyc_a = {VirtualPermutation.CYCLE_CHARS}
cyc_b = {(i, z(i)) for i in range(1, z.rank + 1) if order[i] <= order[z(i)]}
tuples = [(a, b, c, d) for a, b in cyc_a for c, d in cyc_b]
tuples += [(c, d, a, b) for a, b in cyc_a for c, d in cyc_b]
z_cyc, _ = self.tex_cycles(z)
p, q = VirtualPermutation.CYCLE_CHARS
p, q = self.tex_char(p), self.tex_char(q)
self.lines += ['When $(a,b)= (%s,%s)$ and $(a\',b\')\\in \\Cyc^1(z)=%s$ or vice versa,' % (p, q, z_cyc)]
self.lines += ['properties (Z1)-(Z3) correspond to the following conditions which']
self.lines += ['hold in each of the available cases for $wt$:']
self._tex_properties(order, tuples)
def _tex_mirror_conclusions(self, base, plural):
z = self.y.tau(self.i, self.j)
order = {b: i for i, b in enumerate(base)}
cyc_a = {(i, z(i)) for i in range(1, z.rank + 1) if i <= z(i)}
cyc_b = {(-i, -z(i)) for i in range(1, z.rank + 1) if i <= z(i)}
tuples = [(a, b, c, d) for a, b in cyc_a for c, d in cyc_b]
tuples += [(a, b, c, d) for a, b in cyc_b for c, d in cyc_a]
z_cyc, neg_z_cyc = self.tex_cycles(z)
self.lines += ['When $(a,b)\\in\\Cyc^1(z)=%s$ and $(a\',b\')\\in%s$,' % (z_cyc, neg_z_cyc)]
self.lines += ['properties (Z1)-(Z3) correspond to the following conditions which']
self.lines += ['hold in each of the available cases for $wt$:']
self._tex_properties(order, tuples)
class TogglingPropertyTexWriter(TexMixin):
def __init__(self, path=None):
directory = os.path.dirname(os.path.abspath(__file__))
self.path = path if path else os.path.join(directory, 'tex/toggling-property.tex')
self.lines = None
self.y = None
self.i = None
self.j = None
self.w = None
def _tex(self):
self.lines = ["""
\\documentclass[10pt]{article}
\\usepackage{amsmath,amssymb,amsthm,fullpage,hyperref}
\\usepackage[margin=0.75in]{geometry}
\\usepackage[shortlabels]{enumitem}
\\theoremstyle{definition}
\\newtheorem*{theorem}{Theorem}
\\theoremstyle{definition}
\\newtheorem{lemma}{Lemma}
\\def\\dash{\\text{\\hspace{0.5mm}---\\hspace{0.5mm}}}
\\def\\Fix{\\mathrm{Fix}}
\\def\\Cyc{\\mathrm{Cyc}}
\\def\\ZZ{\\mathbb{Z}}
\\def\\cA{\\mathcal{A}}
\\begin{document}
\\title{Computer-generated proof of affine involution toggling property}
\\author{Eric MARBERG \\and Yifeng ZHANG}
\\maketitle
\\tableofcontents
\\section{Setup}
Let $n$ be a positive integer.
For the definition of the affine symmetric group $\\tilde S_n$, see \\cite{M}.
Fix an affine permutation $w \\in \\tilde S_n$ and an involution $y =y^{-1} \\in\\tilde S_n$.
We set $y_a = y(a)$ for $a \\in \\ZZ$ and define
\\[\\Cyc(y) = \\{ (a,b) \\in \\ZZ\\times\\ZZ : a \\leq b = y_a\\}.\\]
As a shorthand, we write $w^{-1} = \\dash a\\dash b\\dash c \\dash \\cdots\\dash d \\dash$
to mean that $w_a < w_b < w_c < \\dots < w_d$.
\\begin{lemma}\\label{lem-1}
One has $w \\in \\cA(y)$
if and only if for all $(a,b),(a',b') \\in \\Cyc(y)$, the following properties hold:
\\begin{enumerate}
\\item[(Y1)] If $a < b$ then $w^{-1} = \\dash b \\dash a \\dash$.
\\item[(Y2)] If $a < a' \\leq b' < b$ then $w^{-1} \\neq \\dash b \\dash a' \\dash a \\dash$
and $w^{-1}\\neq \\dash b \\dash b' \\dash a \\dash.$
\\item[(Y3)] If $a < a'$ and $b < b'$ then $w^{-1} = \\dash a \\dash b' \\dash.$
\\end{enumerate}
\\end{lemma}
\\begin{proof}
This is equivalent to \\cite[Theorem 7.6]{M}.
\\end{proof}
Fix integers $i < j$ that are not congruent modulo $n$.
Let $t_{ij} \\in \\tilde S_n$ be the reflection
that interchanges $i$ and $j$ while fixing all integers not congruent to
$i$ or $j$ modulo $n$.
Write $\\lessdot$ for the covering relation in the Bruhat order on $\\tilde S_n$.
\\begin{lemma}\\label{lem-2}
One has $w \\lessdot wt_{ij}$
if and only if the following property holds:
\\begin{enumerate}
\\item[(T)] $w^{-1} = \\dash i \\dash j \\dash$ but if $i<e<j$
then $w^{-1} \\neq \\dash i \\dash e \\dash j\\dash$.
\\end{enumerate}
Moreover, if $i'$ and $j'$ are integers with $i-i' = j-j' \\in n\\ZZ$,
then property (T) is equivalent to the following:
\\begin{enumerate}
\\item[(U)] $w^{-1} = \\dash i' \\dash j' \\dash$ but if $i'<e<j'$
then $w^{-1} \\neq \\dash i' \\dash e \\dash j'\\dash$.
\\end{enumerate}
\\end{lemma}
\\begin{proof}
This is equivalent to \\cite[Proposition 8.3.6]{BB}.
\\end{proof}
Recall the definition of the operator $\\tau^n_{ij}$ from \\cite[\\S8]{M} and
let $z = z^{-1} = \\tau^n_{ij}(y) \\in \\tilde S_n$.
\\begin{lemma}\\label{lem-3}
Suppose $w \\in \\cA(y)$ and $w \\lessdot wt_{ij}$ and $y = \\tau^n_{ij}(y)$.
Then one of the following cases occurs:
\\begin{enumerate}
\\item[(A1)] $i < j = y_j < y_i$ and $w^{-1} = \\dash y_i \\dash i \\dash j \\dash$.
\\item[(A2)] $i < j < y_j < y_i$ and $w^{-1} = \\dash y_j \\dash y_i \\dash i \\dash j \\dash$.
\\item[(A3)] $i < y_j < j < y_i$ and $w^{-1} = \\dash y_i \\dash i \\dash j \\dash y_j \\dash$.
\\item[(B1)] $y_j < i = y_i < j$ and $w^{-1} = \\dash i \\dash j \\dash y_j \\dash$.
\\item[(B2)] $y_j < i < y_i < j$ and $w^{-1} = \\dash y_i \\dash i \\dash j \\dash y_j \\dash$.
\\item[(B3)] $y_j < y_i < i < j$ and $w^{-1} = \\dash i \\dash j \\dash y_j \\dash y_i \\dash$.
\\item[(C1)] $i < j < y_j < y_i$ and $w^{-1} = \\dash y_i \\dash i \\dash y_j \\dash j \\dash$.
\\item[(C2)] $y_j < y_i < i < j$ and $w^{-1} = \\dash i \\dash y_i \\dash j \\dash y_j \\dash$.
\\end{enumerate}
\\end{lemma}
\\begin{proof}
By definition,
the only way one can have $y = \\tau^n_{ij}(y)$
outside the given cases is if
$y_j = i < j = y_i$ or $y_j < i < j < y_i$, but then
any element $w \\in \\cA(y)$ has
$w^{-1} = \\dash j \\dash i \\dash$ by Lemma~\\ref{lem-1}
so it cannot hold that $w\\lessdot wt_{ij}$.
When $y$ corresponds to the one of the given cases,
the possibilities for $w \\in \\cA(y)$ with $w\\lessdot wt_{ij}$
are completely determined by Lemmas~\\ref{lem-1} and \\ref{lem-2}.
\\end{proof}
\\begin{theorem}
Suppose $w \\in \\cA(y)$ and $w \\lessdot wt_{ij}$ and $y = \\tau^n_{ij}(y)$.
Define
\\[
k = \\begin{cases}
j &\\text{in cases (A1)-(A3)} \\\\
y_j &\\text{in cases (B1)-(B3) and (C1)-(C2)}
\\end{cases}
\\quad\\text{and}\\quad
l = \\begin{cases}
y_i &\\text{in cases (A1)-(A3) and (C1)-(C2)} \\\\
i &\\text{in cases (B1)-(B3).}
\\end{cases}
\\]
Then $k<l \\notin k + n\\ZZ$ and $w \\neq w t_{ij} t_{kl} \\in \\cA(y)$.
\\end{theorem}
The proof of this statement occupies the rest of this computer-generated document.
\\begin{proof}
By hypothesis, we are in one of the eight cases in Lemma~\\ref{lem-3}.
The sets $\\{i,y_i\\} + n\\ZZ$ and $\\{j,y_j\\} + n \\ZZ$ are therefore disjoint.
Note that if $i \\neq y_i$ then the sets $i + n\\ZZ$ and $y_i + n \\ZZ$ are disjoint,
and that if $j \\neq y_j$ then the sets $j + n\\ZZ$ and $y_j + n\\ZZ$ are disjoint.
Let $v = wt_{ij}t_{kl}$.
To show that $v \\in \\cA(y)$, it suffices by Lemma~\\ref{lem-1}
to check that if $(a,b),(a',b') \\in \\Cyc(y)$ then the following properties hold:
\\begin{enumerate}
\\item[(V1)] If $a < b$ then $v^{-1} = \\dash b \\dash a \\dash$.
\\item[(V2)] If $a < a' \\leq b' < b$ then $v^{-1} \\neq \\dash b \\dash a' \\dash a \\dash$
and $v^{-1}\\neq \\dash b \\dash b' \\dash a \\dash.$
\\item[(V3)] If $a < a'$ and $b < b'$ then $v^{-1} = \\dash a \\dash b' \\dash.$
\\end{enumerate}
Let $E = \\{i, j, y_i, y_j\\}$.
Then $v_a = w_a$ for all integers $a \\notin E + n\\ZZ$,
and
$
\\Cyc(y) = \\Cyc^1(y) \\sqcup \\Cyc^2(y) \\sqcup \\Cyc^3(y)
$
where
\\[
\\begin{aligned}
\\Cyc^1(y) &= \\{ (a,b) \\in \\Cyc(y): a,b \\in E\\},\\\\
\\Cyc^2(y) &= \\{ (a,b) \\in \\Cyc(y): a,b \\notin E + n\\ZZ\\},\\\\
\\Cyc^3(y) &= \\{ (a+mn,b+mn): 0 \\neq m \\in \\ZZ\\text{ and }(a,b)\\in \\Cyc^1(y)\\}.
\\end{aligned}
\\]
When $(a,b),(a',b') \\in \\Cyc^2(y)$,
properties (V1)-(V3) are equivalent to (Y1)-(Y3)
and therefore hold since $w \\in \\cA(y)$.
It remains to check properties (V1)-(V3) in the following cases:
\\begin{itemize}
\\item[(i)] When $(a,b),(a',b') \\in \\Cyc^1(y)$.
\\item[(ii)] When one of the pairs $(a,b)$, $(a',b')$ belongs to $\\Cyc^1(y)$ while the other belongs to $\\Cyc^2(y)$.
\\item[(iii)] When $(a,b) \\in \\Cyc^1(y)$ and $(a',b') \\in \\Cyc^3(y)$.
\\end{itemize}
We check directly that properties (V1)-(V3) hold in cases (i), (ii), and (iii)
for each of the eight cases in Lemma~\\ref{lem-3}.
"""]
for case, y, i, j, w in self._get_cases():
self.y = y
self.i = i
self.j = j
self.w = w
self._tex_analysis(case)
self.lines += ["""
\\section{Conclusion}
It follows from this exhaustive case analysis
that properties (V1)-(V3) hold for all pairs $(a,b),(a\',b\') \\in \\Cyc(y)$.
We conclude by Lemma~\\ref{lem-1} that $wt_{ij}t_{kl} \\in \\cA(y)$.
This completes the proof of the theorem.
\\end{proof}
\\begin{thebibliography}{99}
\\bibitem{BB} A. Bj\\"orner and F. Brenti,
\\emph{Combinatorics of Coxeter groups},
Graduate Texts in Mathematics 231, Springer, New York, 2005.
\\bibitem{M} E. Marberg,
On some actions of the $0$-Hecke monoids of affine symmetric groups,
\\emph{J. Combin. Theory Ser. A} \\textbf{161} (2019), 178--219.
\\end{thebibliography}
\\end{document}
"""]
@classmethod
def _get_cases(cls):
cases = []
for y in VirtualInvolution.all(maximum_size=4, mimimal_type=True):
for i, j in itertools.combinations(range(1, y.rank + 1), 2):
if y.tau(i, j) == y:
for w in y.get_virtual_atoms(required_ascents={(i, j)}):
cases += [(y, i, j, w)]
dictionary = {}
for y, i, j, w in cases:
case = None
if i < j == y(j) < y(i) and w(y(i)) < w(i) < w(j):
case = 'A1'
elif i < j < y(j) < y(i) and w(y(j)) < w(y(i)) < w(i) < w(j):
case = 'A2'
elif i < y(j) < j < y(i) and w(y(i)) < w(i) < w(j) < w(y(j)):
case = 'A3'
elif y(j) < i == y(i) < j and w(i) < w(j) < w(y(j)):
case = 'B1'
elif y(j) < i < y(i) < j and w(y(i)) < w(i) < w(j) < w(y(j)):
case = 'B2'
elif y(j) < y(i) < i < j and w(i) < w(j) < w(y(j)) < w(y(i)):
case = 'B3'
elif i < j < y(j) < y(i) and w(y(i)) < w(i) < w(y(j)) < w(j):
case = 'C1'
elif y(j) < y(i) < i < j and w(i) < w(y(i)) < w(j) < w(y(j)):
case = 'C2'
assert case is not None
dictionary[case] = (y, i, j, w)
assert set(dictionary.keys()) == {'A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2'}
for case in sorted(dictionary):
y, i, j, w = dictionary[case]
yield case, y, i, j, w
def _tex_analysis(self, case):
y, i, j, w = self.y, self.i, self.j, self.w
k, l = y.toggle(w, i, j)
v = w.transpose(i, j).transpose(k, l)
assert k < l
assert y.is_virtual_atom(v)
y_cyc, _ = self.tex_cycles(y)
all_mirror, all_double, all_single = VirtualPermutation.maximal_extensions(w.permutation)
virtual = VirtualPermutation(w.permutation, all_mirror, all_double, all_single)
required_ascents = {(self.i, self.j)}
invalid = y.get_invalid_configurations(virtual, required_ascents)
assert w.mirror_extensions == {e: all_mirror[e] - set(invalid[e].keys()) for e in all_mirror}
assert w.double_extensions == {e: all_double[e] - set(invalid[e].keys()) for e in all_double}
assert w.single_extensions == {e: all_single[e] - set(invalid[e].keys()) for e in all_single}
self.lines += ['\\section{Case %s}' % case]
self.lines += ['Suppose $%s$ and $w^{-1} = %s$ so that $k=%s < %s=l$.' % (self.tex_order(), self.tex_list(w.permutation), self.tex_char(k), self.tex_char(l))]
self.lines += ['\\subsection{Subcase (i)}']
self.lines += ['In this case $v = wt_{ij}t_{kl}$ is such that']
self.lines += ['\\begin{enumerate}\\item[]$v^{-1} = %s$.\\end{enumerate}' % self.tex_list(v.permutation)]
self.lines += ['When $(a,b),(a\',b\')\\in\\Cyc^1(y)= %s$,' % y_cyc]
self.lines += ['properties (V1)-(V3) are equivalent to the following conditions which evidently hold:']
order = {b: i for i, b in enumerate(w.base)}
cyc = {(i, y(i)) for i in range(1, y.rank + 1) if i <= y(i)}
tuples = [(a, b, c, d) for a, b in cyc for c, d in cyc]
self._tex_properties(order, tuples)
self.lines += ['Thus properties (V1)-(V3) hold whenever']
self.lines += ['$(a,b)$, $(a\',b\')$ are as in case (i) and $%s$.' % self.tex_order()]
c = self.tex_char(VirtualPermutation.FIXED_CHAR)
subset = '\\{i,j' + (',y_i' if y(i) != i else '') + (',y_j' if y(j) != j else '') + '\\}'
self.lines += ['\\subsection{Subcase (ii)}']
self.lines += ['Suppose $%s$ is an integer such that $(%s,%s) \\in \\Cyc^2(y)$, so that ' % (c, c, c)]
self.lines += ['$%s = y_%s \\notin %s + n\\mathbb{Z}$.' % (c, c, subset)]
self._tex_list_extensions_single(invalid, all_single)
p, q = VirtualPermutation.CYCLE_CHARS
p, q = self.tex_char(p), self.tex_char(q)
self.lines += ['Next suppose $%s < %s$ are integers with $(%s, %s) \\in \\Cyc^2(y)$, so that ' % (p, q, p, q)]
self.lines += ['$%s = y_{%s}$ and $%s,%s\\notin %s + n\\ZZ$.' % (q, p, p, q, subset)]
self._tex_list_extensions_double(invalid, all_double)
self.lines += ['We conclude that properties (V1)-(V3) hold whenever']
self.lines += ['$(a,b)$, $(a\',b\')$ are as in cases (i) or (ii) and $%s$.' % self.tex_order()]
_i, _j = self.tex_char(-i), self.tex_char(-j)
self.lines += ['\\subsection{Subcase (iii)}']
self.lines += ['Suppose $%s$ and $%s$ are integers such that' % (_i, _j)]
self.lines += ['$0\\neq i - %s = j - %s \\in n\\ZZ$,' % (_i, _j)]
self.lines += ['so that $w(i) - w(%s) = w(j) - w(%s) = i - %s$.' % (_i, _j, _i)]
self._tex_list_extensions_mirror(invalid, all_mirror)
self.lines += ['We conclude that properties (V1)-(V3) hold for all']
self.lines += ['$(a,b),(a\',b\') \\in \\Cyc(y)$ when $%s$.' % self.tex_order()]
SINGLE = 0
DOUBLE = 1
MIRROR = 2
def _tex_list_extensions_single(self, invalid_dict, all_dict):
self._tex_list_extensions(invalid_dict, all_dict, self.w.single_extensions, self.SINGLE)
def _tex_list_extensions_double(self, invalid_dict, all_dict):
self._tex_list_extensions(invalid_dict, all_dict, self.w.double_extensions, self.DOUBLE)
def _tex_list_extensions_mirror(self, invalid_dict, all_dict):
self._tex_list_extensions(invalid_dict, all_dict, self.w.mirror_extensions, self.MIRROR)
def _tex_list_extensions(self, invalid_dictionary, all_dict, valid_dict, option):
y, i, j, w = self.y, self.i, self.j, self.w
start = [base for base in set(invalid_dictionary) & set(all_dict) if valid_dict[base]]
end = [base for base in set(invalid_dictionary) & set(all_dict) if not valid_dict[base]]
self.lines += ['\\begin{enumerate}']
for index, base in enumerate(start + end):
order = ' < '.join(self.tex_char(a) for a in base)
item = '$%s$.' % (index + 1)
if valid_dict[base]:
self.lines += ['\\item[%s] Suppose $%s$.' % (item, order)]
else:
self.lines += ['\\item[%s] It cannot happen that $%s$ since:' % (item, order)]
self.lines += ['\\begin{enumerate}[(a)]']
items = {
pi: self._tex_process_reasons(reasons)
for pi, reasons in invalid_dictionary[base].items()
}
for pi, prop in sorted(items.items(), key=lambda pair: pair[1]):
self.lines += ['\\item If $w^{-1} = %s$ then %s.' % (self.tex_list(pi), prop)]
self.lines += ['\\end{enumerate}']
if valid_dict[base]:
k, l = y.toggle(w, i, j)
self.lines += ['Recall that $(k,l) = (%s,%s)$.' % (self.tex_char(k), self.tex_char(l))]
self.lines += ['We conclude that if $%s$ and then one of the following holds:' % (order)]
self.lines += ['\\begin{enumerate}']
for pi in valid_dict[base]:
t = {i: j, j: i, -i: -j, -j: -i}
sigma = tuple(t.get(x, x) for x in pi)
t = {k: l, l: k, -k: -l, -l: -k}
sigma = tuple(t.get(x, x) for x in sigma)
p, q = self.tex_list(pi), self.tex_list(sigma)
self.lines += ['\\item[$\\bullet$] $w^{-1} = %s$ and $v^{-1} = %s$.' % (p, q)]
self.lines += ['\\end{enumerate}']
plural = len(valid_dict[base]) > 1
self._tex_conclusions(base, plural, option)
self.lines += ['\\end{enumerate}']
def _tex_conclusions(self, base, plural, option):
if option == self.SINGLE:
self._tex_single_conclusions(base, plural)
elif option == self.DOUBLE:
self._tex_double_conclusions(base, plural)
elif option == self.MIRROR:
self._tex_mirror_conclusions(base, plural)
else:
raise NotImplementedError
def _tex_single_conclusions(self, base, plural):
y = self.y
order = {b: i for i, b in enumerate(base)}
cyc_a = {(VirtualPermutation.FIXED_CHAR, VirtualPermutation.FIXED_CHAR)}
cyc_b = {(i, y(i)) for i in range(1, y.rank + 1) if order[i] <= order[y(i)]}
tuples = [(a, b, c, d) for a, b in cyc_a for c, d in cyc_b]
tuples += [(c, d, a, b) for a, b in cyc_a for c, d in cyc_b]
y_cyc, _ = self.tex_cycles(y)
c = self.tex_char(VirtualPermutation.FIXED_CHAR)
self.lines += ['When $(a,b)= (%s, %s)$ and $(a\',b\')\\in \\Cyc^1(y)=%s$ or vice versa,' % (c, c, y_cyc)]
self.lines += ['properties (V1)-(V3) correspond to the following conditions which hold in']
self.lines += ['each of the available cases for $v$:']
self._tex_properties(order, tuples)
def _tex_double_conclusions(self, base, plural):
y = self.y
order = {b: i for i, b in enumerate(base)}
cyc_a = {VirtualPermutation.CYCLE_CHARS}
cyc_b = {(i, y(i)) for i in range(1, y.rank + 1) if order[i] <= order[y(i)]}
tuples = [(a, b, c, d) for a, b in cyc_a for c, d in cyc_b]
tuples += [(c, d, a, b) for a, b in cyc_a for c, d in cyc_b]
y_cyc, _ = self.tex_cycles(y)
p, q = VirtualPermutation.CYCLE_CHARS
p, q = self.tex_char(p), self.tex_char(q)
self.lines += ['When $(a,b)= (%s,%s)$ and $(a\',b\')\\in \\Cyc^1(y)=%s$ or vice versa,' % (p, q, y_cyc)]
self.lines += ['properties (V1)-(V3) correspond to the following conditions which hold in']
self.lines += ['each of the available cases for $v$:']
self._tex_properties(order, tuples)
def _tex_mirror_conclusions(self, base, plural):
y = self.y
order = {b: i for i, b in enumerate(base)}
cyc_a = {(i, y(i)) for i in range(1, y.rank + 1) if i <= y(i)}
cyc_b = {(-i, -y(i)) for i in range(1, y.rank + 1) if i <= y(i)}
tuples = [(a, b, c, d) for a, b in cyc_a for c, d in cyc_b]
y_cyc, neg_y_cyc = self.tex_cycles(y)
self.lines += ['When $(a,b)\\in\\Cyc^1(y)=%s$ and $(a\',b\')\\in%s$,' % (y_cyc, neg_y_cyc)]
self.lines += ['properties (V1)-(V3) correspond to the following conditions which hold in']
self.lines += ['each of the available cases for $v$:']
self._tex_properties(order, tuples, letter='V')
def get_arguments():
parser = argparse.ArgumentParser()
parser.add_argument(
'-f',
dest='force',
action='store_true',
help='force overwrite of TeX files'
)
return parser.parse_args()
if __name__ == '__main__':
start = time.time()
force = get_arguments().force
sys.stdout.write('\nGenerating TeX files:\n\n')
writer = CoveringPropertyTexWriter()
if writer.write(force):
sys.stdout.write('* Wrote proof of covering property to `%s`.\n' % writer.path)
writer = TogglingPropertyTexWriter()
if writer.write(force):
sys.stdout.write('* Wrote proof of toggling property to `%s`.\n' % writer.path)
stop = time.time()
sys.stdout.write('\nDuration: %s seconds\n\n' % (stop - start))