Skip to content

Commit

Permalink
TMP COMMIT
Browse files Browse the repository at this point in the history
  • Loading branch information
videlec committed Jul 20, 2023
1 parent fe56696 commit beb8e9e
Show file tree
Hide file tree
Showing 2 changed files with 246 additions and 16 deletions.
124 changes: 124 additions & 0 deletions veerer/linear_family.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
r"""
Linear family of coordinates on a veering triangulation
"""


if sage is not None:
from sage.structure.element import get_coercion_model
cm = get_coercion_model()
else:
cm = None


def subspace_are_equal(subspace1, subspace2):
if subspace1.ncols() != subspace2.ncols():
raise ValueError

n = subspace1.nrows()
if n != subspace2.nrows():
return False

base_ring = cm.common_parent(subspace1.base_ring(), subspace2.base_ring())
mat = matrix(base_ring, n + 1, subspace1.ncols())
mat[:n] = subspace1
for v in subspace2.rows():
mat[n] = v
r = mat.rank()
if r < n:
raise RuntimeError('matrices where expected to be full rank')
if r > n:
return False
return True


class VeeringTriangulationLinearFamily(VeeringTriangulation):
__slots__ = ['_equations']

def __init__(self, triangulation, colouring, subspace, check=True):
VeeringTriangulation.__init__(triangulation, colouring)
self._subspace = subspace
if check:
self._check(ValueError)

def __str__(self):
return "LinearFamily\n {}\n{}".format(self._vt, self._Gx)

def __repr__(self):
return str(self)

def _check(self, error=ValueError):
subspace = self._subspace
if subspace.ncols() != self.num_edges():
raise error('subspace matrix has wrong dimension')
if subspace.rank() != subspace.nrows():
raise error('subspace matrix is not of full rank')
# test that elements satisfy the switch condition
for v in subspace.rows():
self._set_switch_conditions(self._tt_check, v, VERTICAL)

def __eq__(self, other):
if type(self) is not type(other):
raise TypeError
test = (VeeringTriangulation.__eq__(self, other) and
self._subspace.nrows() != other._subspace.nrows())
if not test:
return False

return subspace_are_equal(self._subspace, other._subspace)

def __ne__(self, other):
if type(self) is not type(other):
raise TypeError
test = (VeeringTriangulation.__eq__(self, other) and
self._subspace.nrows() != other._subspace.nrows())
if not test:
return True

return not subspace_are_equal(self._subspace, other._subspace)

def dimension(self):
r"""
Return the dimension of the linear family.
"""
return self._subspace.nrows()

def is_core(self):
r"""
Test whether this linear family is core.
It is core, if the dimension of the polytope given by the train-track
and non-negativity conditions is full dimensional in the subspace.
"""

def relabel(self, p):
pass

def iso_sig(self):
pass

# TODO: change to canonicalize ? Since we also need to canonicalize the subspace
# it is not only about labels
def set_canonical_labels(self):
pass

def is_isomorphic_to(self, other, certificate=False):
pass

def flip(self, e, col, check=True):
pass

def geometric_polytope(self, x_low_bound=0, y_low_bound=0, hw_bound=0):
pass

def geometric_flips(self):
pass


class VeeringTriangulationLinearFamilies:
r"""
A collection of linear families.
"""
@staticmethod
def L_shaped_surface(a1, a2, b1, b2, t1=0, t2=0):
vt, s, t = VeeringTriangulations.L_shaped_surface(a1, a2, b1, b2, t1, t2)
return VeeringTriangulationLinearFamily(vt, matrix([s, t]))
138 changes: 122 additions & 16 deletions veerer/veering_triangulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ def ppl_cone_from_hashable(args):
return P


def serialize_matrix(mat):
# if we have a number field!?
if mat.base_ring() not in [ZZ, QQ]:
raise NotImplementedError
return '_'.join(map(str, mat.list()))


def relabel_on_edges(ep, r, n, m):
r"""
INPUT:
Expand Down Expand Up @@ -90,6 +97,7 @@ def relabel_on_edges(ep, r, n, m):
return rr


# TODO: better to make something topological (ie no equations)
class VeeringTriangulation(Triangulation):
r"""
Veering triangulation.
Expand Down Expand Up @@ -584,6 +592,9 @@ def forgot_backward_flippable_colour(self):
self._colouring[e] = self._colouring[ep[e]] = GREEN

def __eq__(self, other):
r"""
Equality test.
"""
if type(self) != type(other):
raise TypeError
return Triangulation.__eq__(self, other) and self._colouring == other._colouring
Expand All @@ -593,6 +604,24 @@ def __ne__(self, other):
raise TypeError
return Triangulation.__ne__(self, other) or self._colouring != other._colouring

def gl2r_plane(self, s, t):
r"""
Return the GL(2,R)-plane generated by the triangulations with vectors s and t
"""
switch = self.switch_matrix()
switch2 = matrix(switch.base_ring(), switch.nrows() + 2, switch.ncols())
switch2[:switch.nrows()] = switch
i = switch.nrows()
r = switch.rank()
for v in matrix([s, t]).right_kernel_matrix().rows():
switch2[i] = v
if switch2.rank() == r + 1:
i += 1
r += 1
if i == switch2.nrows():
break
LinearFamily

def to_core(self, slope=VERTICAL):
r"""
Change the colour of each forward (reps. backward) flippable edge in
Expand Down Expand Up @@ -1207,7 +1236,7 @@ def mostly_sloped_edges(self, slope):
else:
raise ValueError

def relabel(self, p, Lx=None, Gx=None):
def relabel(self, p):
r"""
Relabel inplace this veering triangulation according to the permutation ``p``.
Expand Down Expand Up @@ -1278,16 +1307,17 @@ def relabel(self, p, Lx=None, Gx=None):
if not perm_check(p, n):
raise ValueError('invalid relabelling permutation')

if Lx:
raise NotImplementedError
if Gx:

# TODO: to be moved
if self._equations is not None:
n = self.num_half_edges()
m = self.num_edges()
rr = relabel_on_edges(self._ep, p, n, m)

for c in perm_cycles(rr, False, m):
for i in range(1, len(c)):
Gx.swap_columns(c[0], c[i])
self._equations.swap_columns(c[0], c[i])

Triangulation.relabel(self, p)
perm_on_list(p, self._colouring)

Expand Down Expand Up @@ -1780,18 +1810,34 @@ def iso_sig(self, Lx=None, Gx=None):
'GBRGRGBRB_731264580_082375641'
"""
n = self._n
r, (cols, fp, ep) = self.best_relabelling(True)
cols = ''.join(colour_to_char(col) for col in cols)
fp = perm_base64_str(fp)
ep = perm_base64_str(ep)

if Lx is not None or Gx is not None:
if Lx is not None and Gx is not None:
raise ValueError('at most one of Lx or Gx must be set')
if Lx is not None:
mat = Lx
mat_code = 'Lx'
if Gx is not None:
mat = Gx
mat_code = 'Gx'
m = self.num_edges()
r_edges = relabel_on_edges(self._ep, r, n, m)
for c in perm_cycles(rr, False, m):
for i in range(1, len(c)):
mat.swap_columns(c[0], c[i])

if Lx:
R, (cols, fp, ep) = self.best_relabelling(True)
raise NotImplementedError("not implemented for linear equations")
if Gx:
raise NotImplementedError("not implemented for generators")
else:
r, (cols, fp, ep) = self.best_relabelling()
cols = ''.join(colour_to_char(col) for col in cols)
autom = self.automorphisms()
if len(autom) != 1:
# TODO: find the best automorphism
pass

fp = perm_base64_str(fp)
ep = perm_base64_str(ep)
return cols + '_' + fp + '_' + ep + '_' + mat_code + '_' + serialize_matrix(mat)

else:

return cols + '_' + fp + '_' + ep

Expand Down Expand Up @@ -2570,6 +2616,48 @@ def flip_back(self, e, col, check=True):
Triangulation.flip_back(self, e)
self._colouring[e] = self._colouring[E] = col

def switch_matrix(self, slope=VERTICAL):
r"""
Return the matrix of switch conditions.
Each row represents a linear constraints on the edge weights.
EXAMPLES::
sage: from veerer import VeeringTriangulation, HORIZONTAL
sage: import ppl
sage: vt = VeeringTriangulation("(0,1,2)(3,4,5)(6,7,8)(~8,~0,~7)(~6,~1,~5)(~4,~2,~3)", "RRBRRBRRB")
sage: vt.switch_matrix()
[ 1 -1 1 0 0 0 0 0 0]
[ 0 0 0 1 -1 1 0 0 0]
[ 0 0 0 0 0 0 1 -1 1]
[ 1 0 0 0 0 0 0 -1 1]
[ 0 1 0 0 0 -1 -1 0 0]
[ 0 0 1 1 -1 0 0 0 0]
sage: vt.switch_matrix(HORIZONTAL)
[ 1 -1 -1 0 0 0 0 0 0]
[ 0 0 0 1 -1 -1 0 0 0]
[ 0 0 0 0 0 0 1 -1 -1]
[ 1 0 0 0 0 0 0 -1 -1]
[ 0 1 0 0 0 1 -1 0 0]
[ 0 0 1 -1 1 0 0 0 0]
"""
require_package('ppl', 'switch_matrix')
require_package('sage', 'switch_matrix')

from sage.matrix.constructor import matrix
from sage.modules.free_module_element import vector
from sage.rings.integer_ring import ZZ

m = self.num_edges()
cs = ppl.Constraint_System()
x = [ppl.Variable(e) for e in range(m)]
self._set_switch_conditions(cs.insert, x, slope)
switch_mat = matrix(ZZ, len(cs), m)
for i, g in enumerate(cs):
switch_mat[i] = vector(ZZ, g.coefficients())
return switch_mat

def _set_switch_conditions(self, insert, x, slope=VERTICAL):
r"""
These are the linear parts of the train-track equations
Expand All @@ -2583,6 +2671,23 @@ def _set_switch_conditions(self, insert, x, slope=VERTICAL):
- ``slope`` - (default ``VERTICAL``) the slope of the train-track
``HORIZONTAL`` or ``VERTICAL``
EXAMPLES::
sage: from veerer import VeeringTriangulation
sage: import ppl
sage: vt = VeeringTriangulation("(0,1,2)(3,4,5)(6,7,8)(~8,~0,~7)(~6,~1,~5)(~4,~2,~3)", "RRBRRBRRB")
sage: cs = ppl.Constraint_System()
sage: x = [ppl.Variable(e) for e in range(vt.num_edges())]
sage: vt._set_switch_conditions(cs.insert, x)
sage: for g in cs:
....: print(vector(ZZ, g.coefficients()))
(1, -1, 1, 0, 0, 0, 0, 0, 0)
(0, 0, 0, 1, -1, 1, 0, 0, 0)
(0, 0, 0, 0, 0, 0, 1, -1, 1)
(1, 0, 0, 0, 0, 0, 0, -1, 1)
(0, 1, 0, 0, 0, -1, -1, 0, 0)
(0, 0, 1, 1, -1, 0, 0, 0, 0)
"""
if slope == VERTICAL:
LAR = PURPLE
Expand Down Expand Up @@ -3737,7 +3842,8 @@ def random_forward_flip(self, repeat=1):
else:
self.flip_back(e, old_col)

class VeeringTriangulations(object):

class VeeringTriangulations:
@staticmethod
def L_shaped_surface(a1, a2, b1, b2, t1=0, t2=0):
r"""
Expand Down

0 comments on commit beb8e9e

Please sign in to comment.