diff --git a/src/sage/geometry/mixed_tat_graph.py b/src/sage/geometry/mixed_tat_graph.py
new file mode 100644
index 00000000000..b72d5ce996a
--- /dev/null
+++ b/src/sage/geometry/mixed_tat_graph.py
@@ -0,0 +1,308 @@
+r"""
+Mixed t\^ete-\`a-t\^ete graphs.
+
+
+
+
+
+- Pablo Portilla (2019)
+"""
+
+#*****************************************************************************
+# Copyright (C) 2016 Pablo Portilla
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+# http://www.gnu.org/licenses/
+#*****************************************************************************
+
+from sage.structure.sage_object import SageObject
+from sage.structure.unique_representation import UniqueRepresentation
+from sage.structure.unique_representation import CachedRepresentation
+from sage.groups.perm_gps.permgroup_element import PermutationGroupElement
+from sage.rings.integer_ring import ZZ
+from sage.misc.cachefunc import cached_method
+from sage.misc.flatten import flatten
+from copy import copy
+from sage.geometry.ribbon_graph import *
+from sage.functions.other import floor
+from sage.rings.rational import Rational
+from sage.matrix.matrix_space import MatrixSpace
+from sage.geometry.tat_graph import *
+
+def _find(l, k):
+ r"""
+ Return the two coordinates of the element ``k`` in the list of
+ lists ``l``.
+
+ INPUT:
+
+ - ``l`` -- a list of lists
+ - ``k`` -- a candidate to be in a list in ``l``
+
+ OUTPUT:
+
+ A list with two integers describing the position of the first
+ instance of `k`` in ``l``.
+
+ TESTS::
+
+ sage: from sage.geometry.ribbon_graph import _find
+ sage: A = [[2,3,4],[4,5,2],[8,7]]
+ sage: _find(A,2)
+ [0, 0]
+ sage: _find(A,7)
+ [2, 1]
+ sage: _find(A,5)
+ [1, 1]
+ sage: _find(A,-1)
+ Traceback (most recent call last):
+ ...
+ ValueError: element -1 not found
+ """
+ for i,lst in enumerate(l):
+ if k in lst:
+ return [i, lst.index(k)]
+ raise ValueError("element {} not found".format(k))
+
+
+class MixedTatGraph(SageObject):
+ r"""
+
+
+ INPUT:
+
+ - ``list_ribbon`` -- a list of nested ribbon graphs.
+ - ``metric`` -- a list of as many rational numbers as darts has the first
+ element of``ribbon``.
+ - ``relative_boundary=[]`` -- a subset of ``ribbon.boundary()`` that
+ constitutes the relative boundary components of ``ribbon``. It is, by
+ default, initialized to an empty list (for defining pure t\^ete-\`a-t\^ete graphs)
+
+ Alternatively, one can pass in 2 integers and this will construct
+ a bipartite t\^ete-\`a-t\^ete graph which realizes the corresponding
+ Brieskorn-Pham singularity.
+
+
+ EXAMPLES:
+
+ sage: T33 = bipartite_tat_graph(3,3); T33
+ Tete-a-tete graph of order 3 on a ribbon graph of genus 1 and 3 boundary components.
+ sage: T33.sigma()
+ (1,2,3)(4,5,6)(7,8,9)(10,11,12)(13,14,15)(16,17,18)
+ sage: T33.rho()
+ (1,12)(2,15)(3,18)(4,11)(5,14)(6,17)(7,10)(8,13)(9,16)
+ sage: print(T33.metric())
+ [1/4, 1/4, 1/4, 1/4, 1/4, 1/4, 1/4, 1/4, 1/4, 1/4, 1/4, 1/4, 1/4, 1/4, 1/4, 1/4, 1/4, 1/4]
+ sage: T33._relative_boundary
+ []
+ sage: B33 = blow_up(T33, 1,1/8); B33 ; B33._relative_boundary
+ Relative t\^ete-\`a-t\^ete graph of order 3 on a ribbon graph of genus 1 and 6 boundary components; where 3 boundary components are part of the relative boundary and might be permuted by the automorphism induced.
+ [[19, 24, 23, 22, 21, 20], [25, 30, 29, 28, 27, 26], [31, 36, 35, 34, 33, 32]]
+ sage: T517=bipartite_tat_graph(5,17);T517
+ Tete-a-tete graph of order 85 on a ribbon graph of genus 32 and 1 boundary components.
+ """
+ def __init__(self, list_ribbon, metric, relative_boundary=[]):
+ r"""
+ Initialize ``self``.
+ """
+ for i in range(len(relative_boundary)):
+ assert relative_boundary[i] in ribbon.boundary()
+
+ assert check_tat_property(ribbon, metric, relative_boundary) == True
+ self._ribbon = ribbon
+ self._metric = metric
+ self._sigma = ribbon._sigma
+ self._rho = ribbon._rho
+ self._boundary = self._ribbon.boundary()
+ self._relative_boundary = relative_boundary
+ self._basis = self._ribbon.homology_basis()
+ self._mu = 2*self._ribbon.genus() + self._ribbon.number_boundaries()-1
+
+
+ def _repr_(self):
+ r"""
+ Return basic information about the mixed t\^ete-\`a-t\^ete graph in string
+ format.
+
+ EXAMPLES:
+
+ Example of a relative t\^ete-\`a-t\^ete graph::
+
+ sage: s0 = PermutationGroupElement('(1,2,3)(4,5,6)(7,8,9)(10,11,12)(13,14,15)(16,17,18)')
+ sage: r0 = PermutationGroupElement('(1,9)(2,11)(3,4)(5,14)(6,7)(8,17)(10,18)(12,13)(15,16)')
+ sage: R0 = RibbonGraph(s0,r0)
+ sage: m0 = 6*[1/8,3/8,1/8];
+ sage: perm_bound = [[1, 9, 7, 6, 4, 3], [10, 18, 16, 15, 13, 12]]
+ sage: T0 = TatGraph(R0,m0,relative_boundary = perm_bound); T0
+ Relative t\^ete-\`a-t\^ete graph of order 6 on a ribbon graph of genus 1 and 3 boundary components; where 2 boundary components are part of the relative boundary and might be permuted by the automorphism induced.
+
+ Example of a pure t\^ete-\`a-t\^ete graph::
+
+ sage: T23 = bipartite_tat_graph(2,3); T23
+ Tete-a-tete graph of order 6 on a ribbon graph of genus 1 and 1 boundary components.
+ """
+ if not self._relative_boundary:
+ return "Tete-a-tete graph of order {} on a ribbon graph of genus {} and {} boundary components.".format(self.order(), self._ribbon.genus(), self._ribbon.number_boundaries())
+ else:
+ return "Relative t\^ete-\`a-t\^ete graph of order {} on a ribbon graph of genus {} and {} boundary components; where {} boundary components are part of the relative boundary and might be permuted by the automorphism induced.".format(self.order(), self._ribbon.genus(), self._ribbon.number_boundaries(), len(self._relative_boundary))
+
+ def sigma(self):
+ r"""
+ Return the permutation `\sigma` of ``self._ribbon``.
+
+ EXAMPLES::
+
+ sage: s1 = PermutationGroupElement('(1,3,5)(2,4,6)')
+ sage: r1 = PermutationGroupElement('(1,2)(3,4)(5,6)')
+ sage: R = RibbonGraph(s1, r1)
+ sage: m = 6*[1/2]
+ sage: T = TatGraph(R,m)
+ sage: T.sigma()
+ (1,3,5)(2,4,6)
+ """
+ return self._ribbon.sigma()
+
+ def rho(self):
+ r"""
+ Return the permutation `\rho` of ``self._ribbon``.
+
+ EXAMPLES::
+
+ sage: s1 = PermutationGroupElement('(1,3,5)(2,4,6)')
+ sage: r1 = PermutationGroupElement('(1,2)(3,4)(5,6)')
+ sage: R = RibbonGraph(s1, r1)
+ sage: m = 6*[1/2]
+ sage: T = TatGraph(R,m)
+ sage: T.rho()
+ (1,2)(3,4)(5,6)
+ """
+ return self._ribbon.rho()
+
+ def metric(self):
+ r"""
+ Return a vector containing the metric of the graph where the `i`th
+ (starting at `0`) value of the vector corresponds to the dart `i+1`.
+
+ EXAMPLES::
+
+ sage: T23 = bipartite_tat_graph(2,3); T23.metric()
+ [1/4, 1/4, 1/4, 1/4, 1/4, 1/4, 1/4, 1/4, 1/4, 1/4, 1/4, 1/4]
+ """
+ return self._metric
+
+ def ribbon(self):
+ r"""
+ Return the underlying ribbon graph of the t\^ete-\`a-t\^ete graph ``self``.
+
+ EXAMPLES::
+
+ sage: T23 = bipartite_tat_graph(2,3); T23.ribbon(); T23.ribbon().sigma(); T23.ribbon().rho()
+ Ribbon graph of genus 1 and 1 boundary components
+ (1,2,3)(4,5,6)(7,8)(9,10)(11,12)
+ (1,8)(2,10)(3,12)(4,7)(5,9)(6,11)
+ """
+ return self._ribbon
+
+
+ def action_homology(self):
+ r"""
+ Return matrix representing the action of the t\^ete-\`a-t\^ete automorphism
+ on the first homology group.
+
+ OUTPUT:
+
+ - Return a `self._mu() \times self._mu()` matrix that represents
+ the action of the t\^ete-\`a-t\^ete automorphism on the first homology group
+ with respect to the basis self._ribbon.homology_basis(). This
+ matrix has only `0`, `1` and `-1` as entries.
+
+ EXAMPLES::
+
+ sage: T34 = bipartite_tat_graph(3,4); T34
+ Tete-a-tete graph of order 12 on a ribbon graph of genus 3 and 1 boundary components.
+ sage: T34._ribbon.homology_basis()
+ [[[6, 17], [18, 2], [1, 15], [14, 5]],
+ [[7, 20], [21, 3], [1, 15], [14, 5]],
+ [[8, 23], [24, 4], [1, 15], [14, 5]],
+ [[10, 16], [18, 2], [1, 15], [13, 9]],
+ [[11, 19], [21, 3], [1, 15], [13, 9]],
+ [[12, 22], [24, 4], [1, 15], [13, 9]]]
+ sage: T34.action_homology(); T34.order(); T34.action_homology()**12
+ [ 0 0 0 1 -1 0]
+ [ 0 0 0 1 0 -1]
+ [ 0 0 0 1 0 0]
+ [-1 1 0 1 -1 0]
+ [-1 0 1 1 0 -1]
+ [-1 0 0 1 0 0]
+ 12
+ [1 0 0 0 0 0]
+ [0 1 0 0 0 0]
+ [0 0 1 0 0 0]
+ [0 0 0 1 0 0]
+ [0 0 0 0 1 0]
+ [0 0 0 0 0 1]
+
+ sage: T33 = bipartite_tat_graph(3,3); T33
+ Tete-a-tete graph of order 3 on a ribbon graph of genus 1 and 3 boundary components.
+ sage: T33.action_homology(); T33.order(); T33.action_homology()**3
+ [ 0 0 1 -1]
+ [ 0 0 1 0]
+ [-1 1 1 -1]
+ [-1 0 1 0]
+ 3
+ [1 0 0 0]
+ [0 1 0 0]
+ [0 0 1 0]
+ [0 0 0 1]
+ sage: BT33 = blow_up(T33, 0, 1/8)
+ sage: BT33.action_homology(); BT33.action_homology()**3
+ [ 0 -1 1 1 0 0 0]
+ [ 0 0 1 0 0 -1 0]
+ [ 0 0 0 -1 0 0 1]
+ [ 0 0 1 1 -1 0 0]
+ [ 0 0 1 0 0 0 0]
+ [ 1 0 0 -1 0 0 0]
+ [ 0 0 1 1 0 0 0]
+ [1 0 0 0 0 0 0]
+ [0 1 0 0 0 0 0]
+ [0 0 1 0 0 0 0]
+ [0 0 0 1 0 0 0]
+ [0 0 0 0 1 0 0]
+ [0 0 0 0 0 1 0]
+ [0 0 0 0 0 0 1]
+
+
+ """
+ #Set the space of matrices that we will be working on and
+ #a copy of the zero matrix that will be modified to get
+ #the action of the monodromy.
+ M = MatrixSpace(ZZ, self._mu, self._mu)
+ T = copy(M.zero_matrix())
+
+ #we run along all the darts of each of the elements of the
+ #basis of the homology. We check which is their image; if they
+ #intersect with positive orientation (with respect to the fixed
+ #orientation of homology_basis) then we set a +1 in the corresponding
+ #column, if they intersect with negative orientation, a -1.
+ for i in range (self._mu):
+ for j in range (self._mu):
+ for k in range (len(self._basis[i])):
+ if (safewalk(self._ribbon,
+ self._metric,
+ self._basis[i][k][0],
+ self._relative_boundary)
+ == self._basis[j][0][0]):
+ T[i,j] = 1
+ elif (safewalk(self._ribbon,
+ self._metric,
+ self._basis[i][k][0],
+ self._relative_boundary)
+ == self._basis[j][0][1]):
+
+ T[i,j] = -1
+ return T
+
+