Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
181 views
unlisted
ubuntu2004
a

��c2p�@s�ddlmZddlmZddlmZddlmZddlm	Z	ddl
mZddlZ
ddlmZdd	lmZd
d�ZGdd
�d
e�ZdS)�)�deepcopy)�
FreeModule)�ZZ)�lcm)�flatten)�
cached_methodN)�	Signature)�KLevelGraphcCs>|jdkrtd��t�|jgttd|jd��gg|jdg�S)z�
    The smooth (i.e. one vertex) LevelGraph in the stratum (sig).

    INPUT:

    sig (Signature): signature of the stratum.

    OUTPUT:

    LevelGraph: The smooth graph in the stratum.
    �z0The signature is not for an abelian differentialr)	�k�
ValueError�
LevelGraph�
fromPOlist�g�list�range�n�sig)r�r�C/home/user/Introduction lectures/admcycles/diffstrata/levelgraph.py�	smooth_LGs

$�rcsDeZdZdZd;�fdd�	Zed<dd��Zedd��Zd	d
�Zdd�Z	d
d�Z
dd�Zedd��Z
edd��Zedd��Zedd��Zedd��Zdd�Z�fdd�Z�fdd �Zd=d"d#�Zed$d%��Zd>d&d'�Zed?d(d)��Zed@d*d+��ZedAd,d-��Zd.d/�ZdB�fd0d1�	ZdCd3d4�ZdD�fd5d6�	ZdEd7d8�ZdFd9d:�Z �Z!S)Gr
a�
    Create a (stable) level graph.

    ..NOTE::

        This is a low-level class and should NEVER be invoced directly!
        Preferably, EmbeddedLevelGraphs should be used and these should be
        generated automatically by Stratum (or GeneralisedStratum).

    .. NOTE::

        We don't inherit from stgraph/StableGraph anymore, as LevelGraphs
        should be static objects!

    Extends admcycles stgraph to represent a level graph as a stgraph,
    i.e. a list of genera, a list of legs and a list of edges, plus a list of
    poleorders for each leg and a list of levels for each vertex.

    Note that the class will warn if the data is not admissible, i.e. if the
    graph is not stable or the pole orders at separating nodes across levels do
    not add up to -2 or -1 on the same level (unless this is suppressed with
    quiet=True).

    INPUT:

    genera : list
    List of genera of the vertices of length m.

    legs : list
    List of length m, where ith entry is list of legs attached to vertex i.
    By convention, legs are unique positive integers.

    edges : list
    List of edges of the graph. Each edge is a 2-tuple of legs.

    poleorders : dictionary
    Dictionary of the form leg number : poleorder

    levels : list
    List of length m, where the ith entry corresponds to the level of
    vertex i.
    By convention, top level is 0 and levels go down by 1, in particular
    they are NEGATIVE numbers!

    quiet : optional boolean (default = False)
    Suppresses most error messages.

    ALTERNATIVELY, the pole orders can be supplied as a list by calling
    LevelGraph.fromPOlist:

    poleorders : list
    List of order of the zero (+) or pole (-) at each leg. The ith element
    of the list corresponds to the order at the leg with the marking i+1
    (because lists start at 0 and the legs are positive integers).

    EXAMPLES:

    Creating a level graph with three components on different levels of genus 1,
    3 and 0. The bottom level has a horizontal node.::

        sage: from admcycles.diffstrata import *
        sage: G = LevelGraph.fromPOlist([1,3,0],[[1,2],[3,4,5],[6,7,8,9]],[(2,3),(5,6),(7,8)],[2,-2,0,6,-2,0,-1,-1,0],[-2,-1,0]); G  #  doctest: +SKIP
        LevelGraph([1, 3, 0],[[1, 2], [3, 4, 5], [6, 7, 8, 9]],[(3, 2), (6, 5), (7, 8)],{1: 2, 2: -2, 3: 0, 4: 6, 5: -2, 6: 0, 7: -1, 8: -1, 9: 0},[-2, -1, 0],True)

    or alternatively::

        sage: LevelGraph([1, 3, 0],[[1, 2], [3, 4, 5], [6, 7, 8, 9]],[(3, 2), (6, 5), (7, 8)],{1: 2, 2: -2, 3: 0, 4: 6, 5: -2, 6: 0, 7: -1, 8: -1, 9: 0},[-2, -1, 0],quiet=True)
        LevelGraph([1, 3, 0],[[1, 2], [3, 4, 5], [6, 7, 8, 9]],[(3, 2), (6, 5), (7, 8)],{1: 2, 2: -2, 3: 0, 4: 6, 5: -2, 6: 0, 7: -1, 8: -1, 9: 0},[-2, -1, 0],True)

    We get a warning if the graph has non-stable components: (not any more ;-))::

        sage: G = LevelGraph.fromPOlist([1,3,0,0],[[1,2],[3,4,5],[6,7,8,9],[10]],[(2,3),(5,6),(7,8),(9,10)],[2,-2,0,6,-2,0,-1,-1,0,-2],[-3,-2,0,-1]); G  # doctest: +SKIP
        Warning: Component 3 is not stable: g = 0 but only 1 leg(s)!
        Warning: Graph not stable!
        LevelGraph([1, 3, 0, 0],[[1, 2], [3, 4, 5], [6, 7, 8, 9], [10]],[(3, 2), (6, 5), (7, 8), (9, 10)],{1: 2, 2: -2, 3: 0, 4: 6, 5: -2, 6: 0, 7: -1, 8: -1, 9: 0, 10: -2},[-3, -2, 0, -1],True)
    Fc	s&t��|||||d|�|��|_dS)Nr
)�super�__init__�_gen_prongs�prongs)�self�genera�legs�edges�
poleorders�levels�quiet��	__class__rrrns�zLevelGraph.__init__csntt|���t��t��kr@tdtt���dtt�������fdd�tt���D�}|||||||�S)zy
        This gives a LevelGraph where the poleorders are given as a list, not
        directly as a dictionary.
        z4Numbers of legs and pole orders do not agree! Legs: z Pole orders: csi|]}�|�|�qSrr��.0�i��poleordersaslistZ
sortedlegsrr�
<dictcomp>�s�z)LevelGraph.fromPOlist.<locals>.<dictcomp>)�sortedr�lenr�reprr)�clsrrrr(r r!Z
poleorderdictrr'rrts
��
�
�zLevelGraph.fromPOlistcCs.|jjdksJ�||j|j|j|j|jdd�S)Nr
T�r!)rrrrrrr )r-ZkLGrrr�fromKLevelGraph�s
�zLevelGraph.fromKLevelGraphcCsd|��dS)NzLevelGraph(�))�input_as_string�rrrr�__repr__�szLevelGraph.__repr__cCstt|��S�N)�hashr,r2rrr�__hash__�szLevelGraph.__hash__cCsFdt|j�dt|j�dt|j�dt|j�dt|j�S)NzLevelGraph � �r,rrrrr r2rrr�__str__�s�����zLevelGraph.__str__cCsFt|j�dt|j�dt|j�dt|j�dt|j�dS)zX
        return a string that can be given as argument to __init__ to give self
        �,z,Truer8r2rrrr1�s������zLevelGraph.input_as_stringcCst|j���Sr4)rr�itemsr2rrr�prongs_list�szLevelGraph.prongs_listcCsD|�|d�|�|d�kr.|�|d�dS|�|d�dSdS)zO
        The prong order is the pole order of the higher-level pole +1
        rr
N)�
levelofleg�
orderatleg�r�errr�prong�szLevelGraph.prongcCs |dkrdS|dkrdSdSdS)Nr�polezmarked point�zeror)r�orderrrr�
_pointtype�s
zLevelGraph._pointtypecst�fdd����D��S)zO
        Returns True iff at least one of the MARKED POINTS is a pole.
        c3s|]}��|�dkVqdS)rN�r>�r%�lr2rr�	<genexpr>��z,LevelGraph.is_meromorphic.<locals>.<genexpr>)�any�
list_markingsr2rr2r�is_meromorphic�szLevelGraph.is_meromorphiccCs8d}d}|�|�D] }|�|�|kr|�|�}|}q|S)z^
        Returns the leg with the highest order free pole at v, -1 if no poles found.
        r�����)rLr>)r�vZminorder�legrHrrr�highestorderpole�s
zLevelGraph.highestorderpolecs�fdd��jD�S)z�
        Generate the dictionary edge : prong order.
        The prong order is the pole order of the higher-level pole +1
        csi|]}|��|��qSr�rA�r%r@r2rrr)�rJz*LevelGraph._gen_prongs.<locals>.<dictcomp>)rr2rr2rr�szLevelGraph._gen_prongscs|�t��||��S)aD
        Extract the subgraph of self (as a LevelGraph) consisting of vertices
        (as list of indices) and edges (as list of edges).

        Returns the levelgraph consisting of vertices, edges and all legs on
        vertices (of self) with their original poleorders and the original
        level structure.
        )r/r�extract)r�verticesrr"rrrT�s	�zLevelGraph.extractcs|�t��|��S)z�
        Returns the LevelGraph associated to a subgraph of underlying_graph
        (with the level structure induced by self)
        )r/r�levelGraph_from_subgraph)r�Gr"rrrV�s
�z#LevelGraph.levelGraph_from_subgraphNcs����rtd�dS��|�}��|�}g}g}g}i}t|�D]d\�}	|t��|	��g7}|��fdd�t|d�D��tt	�fdd�|dD���}
||
g7}q@g}��
|d�jd	d
�D]D}|dd�D]2}
|
ddkr�qЈ�|
d
�|kr�|�
|�q�q�q���
|�}|��}|D]�}�j||d��r4�qg}|D]�}|d
|v�s\|d|v�r<|d
|v�rt|d}
n|d
}
|d}d|v�r�|�d�\}}t|�}n|d}|||g7}�q<|�r||g7}�qtjj�|||�S)a
        Return the LevelStratum at (relative) level l.

        INPUT:

        l (int): relative level number (0,...,codim)

        excluded_poles (tuple, defaults to None): a list of poles (legs of the graph,
        that are marked points of the stratum!) to be ignored for r-GRC.

        OUTPUT:

        LevelStratum: the LevelStratum, i.e.

        * a list of Signatures (one for each vertex on the level)
        * a list of residue conditions, i.e. a list [res_1,...,res_r]
          where each res_k is a list of tuples [(i_1,j_1),...,(i_n,j_n)]
          where each tuple (i,j) refers to the point j (i.e. index) on the
          component i and such that the residues at these points add up
          to 0.
        * a dictionary of legs, i.e. n -> (i,j) where n is the original
          number of the point (on the LevelGraph self) and i is the
          number of the component, j the index of the point in the signature tuple.

        Note that LevelStratum is a GeneralisedStratum together with
        a leg dictionary.
        z>Error: Cannot extract levels of a graph with horizontal edges!Ncsg|]\}}|�|ff�qSrr)r%�jr)r&rr�
<listcomp>+s�z1LevelGraph.stratum_from_level.<locals>.<listcomp>rNc3s|]}��|�VqdSr4rF)r%rPr2rrrI-s�z0LevelGraph.stratum_from_level.<locals>.<genexpr>r
T��sort��resr��excluded_poles�edge)�
is_horizontal�print�internal_level_numberZverticesonlevel�	enumerater�legsatvertex�updater�tuple�UG_above_levelr�
levelofvertex�append�connected_components_subgraphs�_redeemed_by_merom_in_comp�split�int�	admcycles�
diffstrata�generalisedstratum�LevelStratum)rrHr_Z
internal_l�vvZ
legs_on_level�sigs�res_condZleg_dictrOZsig_v�eer@�	UG_vertexrW�	conn_comp�cZ
res_cond_cr`�_rPr)r&rr�stratum_from_levelsd


��


�



�zLevelGraph.stratum_from_levelcs���|�dks t��|��dkr$dS��|�}�fdd�|D�}t�fdd�|D��}t|�}|D] }��|�||dkrbdSqbdS)z�
        Check if vertex is inconvenient, i.e.
        * g = 0
        * no simple poles
        * there exists a pole order m_i such that m_i > sum(m_j)-p-1
        Return boolean
        rFcsg|]}��|�dkr|�qS�rrFrGr2rrrY�rJz5LevelGraph.is_inconvenient_vertex.<locals>.<listcomp>csg|]}��|��qSrrFrGr2rrrY�rJr
T)�genusr+Zsimplepolesatvertexre�sumr>)rrO�ll�polesZpolesum�prHrr2r�is_inconvenient_vertexts
 
z!LevelGraph.is_inconvenient_vertexcCsb|durg}|jdd�D]D}|ddkr*q|�|d�D]"}|�|�dkr8||vr8dSq8qdS)z�
        Check if there is a pole in the subgraph G (intended to be a connected
        component above a vertex).

        excluded_poles are ignored (for r-GRC).

        Returns boolean (True = exists a pole)
        NFrZr\r]rT)rUrLr>)rrWr_�wrHrrrrl�s	z%LevelGraph._redeemed_by_merom_in_compc	s(��|�sdS��|����|����fdd���|�D�}t|�dkrT���sTdS���d�}�j���fdd�|�	��D��}|�
��|��}�dur�g�t��fdd���|�D��}|D]P���fd	d�|j
dd
�D�}t|�dkr�dS���rĈj��d�r�|d7}q�|dk�r$dSdS)
a�
        Check if vertex is inconvenient and is not redeemed, i.e.
        * v is inconvenient
        * there are no two separate edges to the same connected component above (i.e. loop above)
        * if meromorphic: v is not connected to higher level marked poles

        We can also pass a tuple (hashing!) of poles that are to be excluded because of
        residue conditions.

        Return boolean
        Fcs4g|],}��|d��kr��|d��kr|�qS�rr
)r=rS�rHrrrrY�s�z0LevelGraph.is_illegal_vertex.<locals>.<listcomp>r
Tcs.g|]&}|ddks&��|d��kr|�qS)r\r]r)ri)r%r�r�rrrY�s�Ncs&g|]}��|�dkr|�vr|�qSr|rFrG)r_rrrrY�s�csPg|]H}|d�kr(|d�jdd�vsH|d�kr|d�jdd�vr|�qS)rr
FrZ)rUrS)rW�v_graphrrrY�s  �rZr^r\)r�rirwZ
edgesatvertexr+rMrh�underlying_graph�subgraph�%connected_component_containing_vertex�
delete_vertexrkrLrrl)	rrOr_rv�
abovegraph�ccrxZ	freepolesZeeGr)rWr_rHrr�r�is_illegal_vertex�s6


�

�

zLevelGraph.is_illegal_vertexc		Cs�|�|�r|d|dkrdS|�|d�}|�|d�}|�|�|�|d��|�|�|d��|f�}|srdS|��r�|�|�|�|d��|�|�|d��|f�d}|D]:}|�|�}|�|�|��}|j	|�
|�|d�r�|d7}q�|dkr�dSdS)a%
        Check if edge is illegal, i.e. if
        * e is horizontal (not loop) and
        * there no simple loop over e
        * there is no "free" pole over each end point

        excluded_poles may be a tuple (hashing!) of poles to be excluded for r-GRC.

        Return boolean
        rr
Fr^r\T)rar=rh�is_cut_edgerw�vertexrM�delete_edger�rlr�)	rr@r_rHr��cutZ
polesfoundrOrWrrr�is_illegal_edge�s`������	������
�
�
zLevelGraph.is_illegal_edgecCsltt|j��D](}|j||d�r|s0td|d�dSq|jD](}|j||d�r>|s`td|d�dSq>dS)z�
        Check if self has illegal vertices or edges.

        excluded_poles may be a tuple (hashing!) of poles to be excluded for r-GRC.

        Return boolean
        r^�Vertexzis illegal!F�EdgeT)rr+rr�rbrr�)rr!r_rOr@rrr�is_legal
s	
zLevelGraph.is_legalcCst|�|�ddi�S)a[
        Squish the horizontal edge e and return the new graph.

        EXAMPLES::

            sage: from admcycles.diffstrata import *
            sage: G = LevelGraph.fromPOlist([1,1], [[1,2],[3,4]], [(2,3)], [1,-1,-1,1],[0,0])
            sage: G.squish_horizontal((2,3))
            LevelGraph([2],[[1, 4]],[],{1: 1, 4: 1},[0],True)
        r!T)r
Z_squish_horizontalr?rrr�squish_horizontal&szLevelGraph.squish_horizontalcs|�t��|||��S)a�
        Squish the level l (and the next lower level!) and return the new graph.
        If addata=True is specified, we additionally return a boolean that tells
        us if a level was squished and the legs that no longer exist.

        More precisely, adddata=True returns a tuple (G,boolean,legs) where
        * G is the (possibly non-contracted) graph and
        * boolean tells us if a level was squished
        * legs is the (possibly empty) list of legs that don't exist anymore

        Implementation:
        At the moment, we remember all the edges (ee) that connect level l to
        level l-1. We then create a new LevelGraph with the same data as self,
        the only difference being that all vertices of level l-1 have now been
        assigned level l. We then remove all (now horizontal!) edges in ee.

        In particular, all points and edges retain their numbering (only the level might have changed).

        WARNING: Level l-1 does not exist anymore afterwards!!!

        Downside: At the moment we get a warning for each edge in ee, as these
        don't have legal pole orders for being horizontal (so checkedgeorders
        complains each time the constructor is called :/).
        )r/r�squish_vertical_slow)rrH�adddatar!r"rrr�3s�zLevelGraph.squish_vertical_slowTcCst|j||d�ddi�S)as
        Squish the level l (and the next lower level!) and return the new graph.

        WARNING: Level l-1 does not exist anymore afterwards!!!

        Args:
            l (int): (internal) level number
            quiet (bool, optional): No output. Defaults to True.

        Returns:
            LevelGraph: new levelgraph with one level less.

        EXAMPLES::

            sage: from admcycles.diffstrata import *
            sage: G = LevelGraph.fromPOlist([1,2], [[1],[2,3,4]], [(1,2)], [0,-2,1,3],[0,-1])
            sage: G.squish_vertical(0)
            LevelGraph([3],[[3, 4]],[],{3: 1, 4: 3},[0],True)
        r.r!T)r
Z_squish_vertical)rrHr!rrr�squish_verticalOszLevelGraph.squish_verticalcs|�t��||��S)af
        Squish all levels except for the k-th.

        Note that delta(1) contracts everything except top-level and that
        the argument is interpreted via internal_level_number

        WARNING: Currently giving an out of range level (e.g.
            0 or >= maxlevel) squishes the entire graph!!!

        Return the corresponding divisor.
        )r/r�delta)rrr!r"rrr�eszLevelGraph.deltac	s�g}|jD],}�fdd�|D�}|r,|��|�|�q
�fdd�|jD�}�fdd�|j��D�}|r�|��dd�t|���D�}t|j||||j	�}|S)Ncsg|]}�|�qSrrr$��legdictrrrYzrJz&LevelGraph.relabel.<locals>.<listcomp>cs$g|]}�|d�|df�qSr�rrSr�rrrY~rJcsi|]\}}�||�qSrr)r%r&rXr�rrr)rJz&LevelGraph.relabel.<locals>.<dictcomp>cSsi|]\}}||�qSrr)r%�a�brrrr)�rJ)
rr[rjrrr;r*r
rr )	rr��tidyup�new_legs�vlegs�list1�	new_edgesZnew_poleordersZnewLGrr�r�relabelws

�zLevelGraph.relabelcsR���rdSt�j�}tt|������fdd�t�j�D��}|sNtd|���fdd�td��	��D�}��|�}|s�td|��fdd�td��	��D�}|s�td|�d	d�|D��|s�td
�����fdd�td��	��D�}��|�}	|�s td�t|	�td
�t|�
|��|�
|�}
|�rD|	�|
�|
�|�fS|	�|
�SdS)av
        This should not be needed! The stack factor should be computed
        using AdditiveGenerator.stack_factor!!!

        Calculate the index of the simple twist group inside the twist group.

        with_degree=True: return a tuple (e,g) where
            * e = index of simple twist in twist
            * g = index of twist group in level rotation group

        r
cs&g|]\}}���|��|��qSr)�basisrA�r%r&r@��MrrrrY�s�z*LevelGraph.twist_group.<locals>.<listcomp>zkernel:cs,g|]$�t���fdd�t�j�D���qS)cs.g|]&\}}��|�����r���|�qSr�Zcrosseslevelrcr�r�)r�rHrrrrY�s��5LevelGraph.twist_group.<locals>.<listcomp>.<listcomp>�r~rdr�r%r��rHrrY�s�z	t-module:csg|]}��|d��qS)T)r�rGr2rrrY�rJzdeltas:cs$g|]�t�fdd��jD���qS)csg|]}��|��qSrrRrS��drrrY�rJr�)rrr�rr�rrY�rJzlcms:cs.g|]&�t����fdd�t�j�D���qS)cs:g|]2\}}��|�����r��d���|�qS)r
r�r�)r�rHrrrrrY�s�r�r�r��r�rrr�rrY�s�zsimple twist group:z
Intersection:N)rar+rrr�	submodulerdrbrZnumberoflevels�intersection�index_in)rr!Zwith_degree�N�KZt_basis�E�deltasZst_basis�SZtw_grrr�r�twist_group�sD


�
�



�

zLevelGraph.twist_group)F)F)N)N)N)N)FN)F)T)F)T)TF)"�__name__�
__module__�__qualname__�__doc__r�classmethodrr/r3r6r9r1rr<rArErMrQrrTrVr{r�rlr�r�r�r�r�r�r�r�r��
__classcell__rrr"rr
!sPL�


	



q

77


r
)�copyr�sage.modules.free_moduler�sage.rings.integer_ringr�sage.arith.functionsr�sage.misc.flattenr�sage.misc.cachefuncr�'admcycles.diffstrata.generalisedstratumro�admcycles.diffstrata.sigrZ admcycles.diffstrata.klevelgraphr	rr
rrrr�<module>s