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

��c�Z�@s\ddlmZddlmZddlmZddlZddlZddl	Zddl
mZGdd�de�ZdS)�)�
SageObject)�
cached_method)�QQN)�hash_AGc@sPeZdZdZd@dd�Zedd��Zdd�Zd	d
�Zdd�Z	d
d�Z
dd�Zdd�Zdd�Z
edd��Zedd��Zedd��Zedd��Zedd��Zedd ��Zed!d"��Zed#d$��Zed%d&��Zd'd(�Zed)d*��Zed+d,��Zed-d.��Zed/d0��ZedAd1d2��ZedBd3d4��ZedCd5d6��Z d7d8�Z!d9d:�Z"dDd<d=�Z#dEd>d?�Z$dS)F�AdditiveGeneratora
    Product of Psi classes on an EmbeddedLevelGraph (of a stratum X).

    The information of a product of psi-class on an EmbeddedLevelGraph, i.e. a
    leg_dict and an enhanced_profile, where leg_dict is a dictionary on the legs
    leg -> exponent of the LevelGraph associated to the enhanced profile, i.e.
    (profile,index) or None if we refer to the class of the graph.

    We (implicitly) work inside some stratum X, where the enhanced profile
    makes sense.

    This class should be considered constant (hashable)!
    Nc	Cs�||_t||�|_t|d�|df|_||_|jj|�|_i|_|durr|D]"}|jj	�
|jj	�|��|j|<qNi|_|jD]D}z|j|j|�
|�Wq~ty�|g|j|j|<Yq~0q~dS)a�
        AdditiveGenerator for psi polynomial given by leg_dict on graph
        corresponding to enh_profile in X.

        Args:
            X (GeneralisedStratum): enveloping stratum

            enh_profile (tuple): enhanced profile (in X)

            leg_dict (dict, optional): dictionary leg of enh_profile -> exponent
            encoding a psi monomial. Defaults to None.
        r�N)�_Xr�_hash�tuple�_enh_profile�	_leg_dict�lookup_graph�_G�_level_dict�LG�level_number�
levelofleg�_inv_level_dict�append�KeyError)�self�X�enh_profile�leg_dict�l�leg�r�J/home/user/Introduction lectures/admcycles/diffstrata/additivegenerator.py�__init__s"
�
zAdditiveGenerator.__init__cCs6|ddurd}nt|d�}|||d|df|�S)z�
        AdditiveGenerator from a hash generated with hash_AG.

        Args:
            X (GeneralisedStratum): Enveloping stratum.
            hash (tuple): hash from hash_AG

        Returns:
            AdditiveGenerator: AG from hash.
        rNr�)�dict)�clsr�hashrrrr�	from_hash?szAdditiveGenerator.from_hashcCs
t|j�S�N)r"r	�rrrr�__hash__QszAdditiveGenerator.__hash__cCs*z|j|jkWSty$tYS0dSr$)r	�AttributeError�NotImplemented�r�otherrrr�__eq__TszAdditiveGenerator.__eq__cCsd|j|j|jfS)Nz2AdditiveGenerator(X=%r,enh_profile=%r,leg_dict=%r))rrrr%rrr�__repr__Zs�zAdditiveGenerator.__repr__cCsLd}|jdur8|jD]"}|d||j||j|f7}q|d|jf7}|S)N�z,Psi class %r with exponent %r on level %r * zGraph %r)rrr)r�strrrrr�__str__as

�zAdditiveGenerator.__str__cs�z(|j|jks|j|jkr tWS|j�Wnty>tYS0|jdurPi�n|j��durbi���fdd�t��t��BD�}|j�|j|�S)a?
        Multiply to psi products on the same graph (add dictionaries).

        Args:
            other (AdditiveGenerator): Product of psi classes on same graph.

        Returns:
            AdditiveGenerator: Product of psi classes on same graph.

        EXAMPLES::


            Also works without legs.

        Ncs&i|]}|��|d���|d��qS)r)�get��.0r�Zother_leg_dictZ
self_leg_dictrr�
<dictcomp>�s�z-AdditiveGenerator.__mul__.<locals>.<dictcomp>)rrr(rr'�set�additive_generator)rr*�new_leg_dictrr3r�__mul__js


�zAdditiveGenerator.__mul__cCs|�|�dSr$)r8r)rrr�__rmul__�szAdditiveGenerator.__rmul__cCs
|�|�Sr$)�pow)r�nrrr�__pow__�szAdditiveGenerator.__pow__cCs|jSr$)rr%rrrr�szAdditiveGenerator.enh_profilecCs |jdurdSt|j���SdS)z7
        Sum of powers of psi classes of self.
        Nr)r�sum�valuesr%rrr�
psi_degree�s
zAdditiveGenerator.psi_degreecCsf|j|j��krdS|jdkr"dSt|jd�D]0}|�|�dksFJ�|�|�|�|�kr0dSq0dS)z�
        Check if, on any level, the psi degree is higher than the dimension.

        Returns:
            bool: False if the class is 0 for dim reasons, True otherwise.
        FrTr)�degreer�dim�codim�range�	level_dim�degree_on_level�rrrrr�	dim_check�s	
��zAdditiveGenerator.dim_checkcCst|jd�S)zz
        The codimension of the graph (number of levels)

        Returns:
            int: length of the profile
        r)�lenrr%rrrrB�szAdditiveGenerator.codimcCs|j|jS)z
        Degree of class, i.e. codimension of graph + psi-degree

        Returns:
            int: codim + psi_degree
        )rBr?r%rrrr@�s	zAdditiveGenerator.degreecCs|jSr$�rr%rrrr�szAdditiveGenerator.leg_dictcCs|jS)z5
        The dictionary mapping leg -> level
        )rr%rrr�
level_dict�szAdditiveGenerator.level_dictcCs|jS)z�
        The dictionary mapping level -> list of legs on level.

        Returns:
            dict: level -> list of legs.
        )rr%rrr�inv_level_dict�sz AdditiveGenerator.inv_level_dictcsZ|t�jd�vr"td|�f��zt�fdd��j|D��WStyTYdS0dS)a.
        Total degree of psi classes on level.

        Args:
            level (int): (relative) level number (i.e. 0...codim)

        Raises:
            RuntimeError: Raised for level number out of range.

        Returns:
            int: sum of exponents of psis appearing on this level.
        rzIllegal level number: %r on %rc3s|]}�j|VqdSr$rI�r2rr%rr�	<genexpr>�s�z4AdditiveGenerator.degree_on_level.<locals>.<genexpr>rN)rCrB�RuntimeErrorr=rr)r�levelrr%rrE�s
��
z!AdditiveGenerator.degree_on_levelcCs|j�|�S)z�
        Level of underlying graph.

        Args:
            level_number (int): (relative) level number (0...codim)

        Returns:
            LevelStratum: Stratum at level level_number of self._G.
        )rrOrFrrrrO�s
zAdditiveGenerator.levelcCs|j�|�}|��S)z�
        Dimension of level level_number.

        Args:
            level_number (int): (relative) level number (i.e. 0...codim)

        Returns:
            int: dimension of GeneralisedLevelStratum
        )rrOrA)rrrOrrrrDszAdditiveGenerator.level_dimcCs�z|jWSty�d}|jjj��D]}||9}q(|j\}}d}|D]}||jj|j	9}qHt
|�t
|t|jj��}||_|jYS0dS)z�
        The stack factor, that is the product of the prongs of the underlying graph
        divided by the product of the ells of the BICs and the automorphisms.

        Returns:
            QQ: stack factor
        rN)
Z
_stack_factorr'rr�prongsr>rr�bics�ellrrH�
automorphisms)r�prod�k�p�_Z	bic_contr�i�stack_factorrrrrYs	



�zAdditiveGenerator.stack_factorcCstjj�|jd|fg�S)zU
        Helper method, returns [(1,self)] as default input to ELGTautClass.
        r)�	admcycles�
diffstrata�elgtautclass�ELGTautClassrr%rrr�as_taut0s�zAdditiveGenerator.as_tautcCs|j�|j|�S)a
        Check if ambient_enh_profile is an ambient graph, i.e. self is a degeneration
        of ambient_enh_profile.

        INPUT:

        ambient_enh_profile: tuple
        An enhanced profile.

        OUTPUT:

        True if there exists a leg map, False otherwise.
        )r�is_degenerationr)rZambient_enh_profilerrr�
is_in_ambient8szAdditiveGenerator.is_in_ambientcCsN|dur|jj}d}n|jj|�}|dkr.|S|j�|��|�|d|�|�S)a
        Recursively calculate the n-th power of self (in amb), caching all results.

        Args:
            n (int): exponent
            amb (tuple, optional): enhanced profile. Defaults to None.

        Returns:
            ELGTautClass: self^n in CH(amb)
        N�rrrr)r�ONE�taut_from_graph�intersectionr^r:)rr;�ambrbrrrr:IszAdditiveGenerator.powcCs:g}|�|||�D]}|�|j�qtjjj|j|dd�S)ar
        exp(c * self) in CH(amb), calculated via exp_list.

        Args:
            c (QQ): coefficient
            amb (tuple, optional): enhanced profile. Defaults to None.
            stop (int, optional): cut-off. Defaults to None.

        Returns:
            ELGTautClass: the tautological class associated to the
                graded list exp_list.
        F)�reduce)�exp_list�extend�psi_listrZr[r\r]r)r�cre�stopZ
new_taut_list�Trrr�exp^s�zAdditiveGenerator.expc	Cs�t|�}|dur|jj}d}n|jj|�}|g}|}td�}td�}|durZ|j��d}||kr�||jjkr�|d7}|||9}|�||�}|�||�qZ|S)at
        Calculate exp(c * self) in CH(amb).

        We calculate exp as a sum of powers (using self.pow, i.e. cached)
        and check at each step if the power vanishes (if yes, we obviously stop).

        The result is returned as a list consisting of the graded pieces.

        Optionally, one may specify the cut-off degree using stop (by
        default this is dim + 1).

        Args:
            c (QQ): coefficient
            amb (tuple, optional): enhanced profile. Defaults to None.
            stop (int, optional): cut-off. Defaults to None.

        Returns:
            list: list of ELGTautClasses
        Nrarr)rrrbrcrA�ZEROr:r)	rrjrerkrb�e�f�coeffrUrrrrgss"zAdditiveGenerator.exp_listcs�|jdur*tjj�|jd|j�|�fg�S|j�|j|�}|durTt	d�||jf�g}t
d�t
t|��}|D]4��fdd�|j��D�}|�
||j�||�f�qptjj�|j|�SdS)a�
        Pull back self to the graph associated to deg_enh_profile.

        Note that this returns an ELGTautClass as there could be several maps.

        More precisely, we return the sum over the pulled back classes divided
        by the number of undegeneration maps.

        Args:
            deg_enh_profile (tuple): enhanced profile of graph to pull back to.

        Raises:
            RuntimeError: raised if deg_enh_profile is not a degeneration of the
                underlying graph of self.

        Returns:
            ELGTautClass: sum of pullbacks of self to deg_enh_profile for each
                undegeneration map divided by the number of such maps.

        Nrz/Pullback failed: %r is not a degeneration of %rcsi|]\}}�||�qSrr)r2rro��leg_maprrr4�s
�z/AdditiveGenerator.pull_back.<locals>.<dictcomp>)rrZr[r\r]rr6�explicit_leg_mapsrrNrrH�itemsr)rZdeg_enh_profile�leg_mapsriZ
aut_factorr7rrrr�	pull_back�s2
���
����zAdditiveGenerator.pull_backcsL��|���j�z ���fdd��j|D�}WntyFi}Yn0|S)z�
        The psi classes on level l of self.

        Args:
            l (int): level, i.e. 0,...,codim

        Returns:
            dict: psi dictionary on self.level(l).smooth_LG
        cs$i|]}�j�j|�j|�qSr)�dmp_invrrL��EG�Lrrrr4�s�z3AdditiveGenerator.psis_on_level.<locals>.<dictcomp>)rO�	smooth_LGrKr)rr�psisrryr�
psis_on_level�s

�

zAdditiveGenerator.psis_on_levelFc
Cs|j|j��kr6|r|r2td||j|j��f�dSg}t|jd�D]b}|�|�|�|�krptd||f��|�	|�}|j
|�|�|||d�}|dkr�dS|�|�qHd}|D]}	||	9}q�|�std�td�t|�td|�td	|j
�td
||j
�td�|j
|S)a�
        Evaluate self (cap with the fundamental class of self._X).

        Note that this gives 0 if self is not a top-degree class.

        Evaluation works by taking the product of the evaluation of each level
        (i.e. evaluating, for each level, the psi monomial on this level) and
        multiplying this with the stack factor.

        The psi monomials on the levels are evaluated using admcycles (after
        removing residue conditions).

        Raises a RuntimeError if there are inconsistencies with the psi degrees
        on the levels.

        INPUT:

        quiet: boolean (optional)
        If set to true, then get no output. Defaults to False.

        warnings_only: boolean (optional)
        If set to true, then output warnings. Defaults to False.

        admcycles_output: boolean (optional)
        If set to true, prints debugging info (used when evaluating levels). Defaults to False.

        OUTPUT:

        the integral of self on X as a rational number.
        z4Warning: %r is not of top degree: %r (instead of %r)rrz(%r is of top degree, but not on level %r)r}�quiet�
warnings_only�admcycles_outputz4----------------------------------------------------z#Contribution of Additive generator:z#Product of level-wise integrals: %rzStack factor: %rz	Total: %r)r@rrA�printrCrBrErDrNrO�evaluater~rrY)
rrr�r��
level_listrr{�valuerTrVrrrr��sD �
�
�
zAdditiveGenerator.evaluatecs��jj}|j}t�fdd�t�jd�D��r>tjj|gd�St|j	�dkr��j
jgkr�tjj|�j
d�}tj�|g�}�j
jdj}�j
jdj}tj�|d|�}tjj|||gd�}	|	Sg}
g}t�jd�D]B}��|�}
��|��|
�}|
�|���|�|�|�|���qԈjtj�|�}t|
�D]\}}|�|||�}�q2|�r��j��}�jj|dd	�}|jj}tj�||j �}|S)
ak
        Transform self into an admcycles prodtautclass on the underlying stgraph of self.

        Note that this gives the pushforward to M_g,n in the sense that we multiply with
        Strataclass and remove all residue conditions.

        Returns:
            prodtautclass: the prodtautclass of self, multiplied with the Strataclasses of
                the levels and all residue conditions removed.

        EXAMPLES::

            sage: from admcycles.diffstrata import *
            sage: X=Stratum((2,))
            sage: X.additive_generator(((),0)).to_prodtautclass()
            Outer graph : [2] [[1]] []
            Vertex 0 :
            Graph :      [2] [[1]] []
            Polynomial : -7/24*(kappa_1)_0 + 79/24*psi_1
            <BLANKLINE>
            <BLANKLINE>
            Vertex 0 :
            Graph :      [1] [[1, 3, 4]] [(3, 4)]
            Polynomial : -1/48
            <BLANKLINE>
            <BLANKLINE>
            Vertex 0 :
            Graph :      [1, 1] [[3], [1, 4]] [(3, 4)]
            Polynomial : -19/24
            sage: from admcycles.stratarecursion import Strataclass
            sage: X=GeneralisedStratum([Signature((4,-2,-2))], res_cond=[[(0,1)], [(0,2)]])
            sage: (X.additive_generator(((),0)).to_prodtautclass().pushforward() - Strataclass(1, 1, [4,-2,-2], res_cond=[2])).is_zero()
            True


        TESTS::

            sage: from admcycles import diffstrata, psiclass
            sage: X = diffstrata.generalisedstratum.GeneralisedStratum(sig_list = [diffstrata.sig.Signature(tuple([8,-3,-2,-3]))], res_cond = [[(0,1)],[(0,2)]])
            sage: X.psi(1).evaluate()
            9
            sage: v = X.ONE.to_prodtautclass().pushforward()
            sage: (v*psiclass(1,1,4)).evaluate()
            9

        We noticed the problem that the markings of the prodtautclass of an AdditiveGenerator are usually not the standard one,
        and hence its pushforward to M_g,n is not comparable to that of other AdditiveGenerator. Thus we solve this
        by adding the keyword "relabel"::

            sage: X=diffstrata.generalisedstratum.Stratum((4,-2))
            sage: X.additive_generator(((1,),0)).to_prodtautclass(relabel=True)
            Outer graph : [1, 0] [[3, 4], [1, 2, 5, 6]] [(3, 5), (4, 6)]
            Vertex 0 :
            Graph :      [1] [[1, 2]] []
            Polynomial : 1/2
            Vertex 1 :
            Graph :      [0] [[1, 2, 3, 4]] []
            Polynomial : psi_4
            <BLANKLINE>
            <BLANKLINE>
            Vertex 0 :
            Graph :      [1] [[1, 2]] []
            Polynomial : 1/2
            Vertex 1 :
            Graph :      [0, 0] [[2, 3, 9], [1, 4, 12]] [(9, 12)]
            Polynomial : 3
            <BLANKLINE>
            <BLANKLINE>
            Vertex 0 :
            Graph :      [1] [[1, 2]] []
            Polynomial : 1/2
            Vertex 1 :
            Graph :      [0, 0] [[3, 4, 9], [1, 2, 12]] [(9, 12)]
            Polynomial : -3


        We fixed the problem that when the ELGTautClass arised from removing residue conditions of a level stratum has only one term, the
        original algorithm would break down. We can test it::

            sage: X=diffstrata.generalisedstratum.GeneralisedStratum([diffstrata.sig.Signature((0,-1,-1)),diffstrata.sig.Signature((0,-1,-1))], res_cond=[[(0,1),(1,1)]])
            sage: X.additive_generator(((),0)).to_prodtautclass()
            Outer graph : [0, 0] [[1, 2, 3], [4, 5, 6]] []
            Vertex 0 :
            Graph :      [0] [[1, 2, 3]] []
            Polynomial : 1
            Vertex 1 :
            Graph :      [0] [[1, 2, 3]] []
            Polynomial : 1

        c3s|]}��|���VqdSr$)rO�zeroStratumClassr1r%rrrM}s�z5AdditiveGenerator.to_prodtautclass.<locals>.<genexpr>r)�terms)�psir)�protautF)�tidyup)!rr�stgraph�anyrCrBrZ�
prodtautclassrH�generar�res_cond�
decstratumr�	tautclass�	_sig_list�sig�g�stratarecursion�Strataclassr~rO�remove_res_condr�to_prodtautclass�verticesonlevel�internal_level_numberrY�	enumerate�factor_pullback�standard_markings�relabelr�)rr�rr�Zadm_psisZ
adm_psis_tautr�r�Z
stratum_class�result�alpha�verticesrr}rlrT�ptcZstandard_legdict�newEmbLGrr%rr� s<[�

z"AdditiveGenerator.to_prodtautclass)N)N)NN)NN)FFF)F)%�__name__�
__module__�__qualname__�__doc__r�classmethodr#r&r+r,r/r8r9r<�propertyrr?rrGrBr@rrJrKrErOrDrYr^r`r:rmrgrwr~r�r�rrrrrsd
!
	"

	

	




	





'*�
Ar)
�sage.structure.sage_objectr�sage.misc.cachefuncr�sage.rings.rational_fieldr�admcycles.admcyclesrZ�admcycles.stratarecursion�!admcycles.diffstrata.elgtautclass�admcycles.diffstrata.auxiliaryrrrrrr�<module>s