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

��c���@sHdZddlmZddlZddlmZddlmZddlmZddl	m
Z
ddlmZdd	l
mZdd
lmZddlmZddlmZd
dlmZmZmZmZmZd
dlmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'd
dl(m)Z)d
dl*m+Z+m,Z,m-Z-m.Z.d
dl/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7de,fdd�Z8de,fdd�Z9ede,fdd��Z:de,fdd�Z;de,fdd�Z<de,fdd�Z=de,fd d!�Z>de,fd"d#�Z?d$d%�Z@de,fd&d'�ZAd(d)�ZBdhd*d+�ZCd,d-�ZDed.d/��ZEd0d1�ZFed2d3��ZGede,fd4d5��ZHede,fd6d7��ZIed8d9��ZJede,fd:d;��ZKede,fd<d=��ZLede,fd>d?��ZMde,fd@dA�ZNede,fdBdC��ZOdDdE�ZPee,fdFdG��ZQee,fdHdI��ZRedJdK��ZSedLdM��ZTdNdO�ZUede,fdPdQ��ZVde,fdRdS�ZWe,fdTdU�ZXedVdW��ZYdXdY�ZZde,fdZd[�Z[de,fd\d]�Z\ede,fd^d_��Z]d`da�Z^dbdc�Z_ddde�Z`dfdg�ZadS)iz9
Faber-Zagier relations and pairing in tautological ring
�)�copyN)�cached_function)�span)�ZZ)�QQ)�matrix)�floor)�
Partitions)�IntegerVectors)�Permutations�)�multiply�insertion_pullback�kappa_multiple�psi_multiple�	get_marks)�
all_strata�
num_strata�contraction_table�unpurify_map�single_stratum�autom_count�graph_count_automorphisms�R�X�Graph�num_of_stratum�graph_isomorphic��socle_evaluation)�	MODULI_SM�	MODULI_ST�MODULI_SMALL�dim_form)�get_memory_usage�dprint�remove_duplicates�subsequences�A_list�B_list�aut�simplify_sparse�cCsTt|t|�|�}||}t||||�t||||�t||||�t||||�dS�N)r#�lenrrr)�g�r1�markings�moduli_type�r3�r2r,r,�:/home/user/Introduction lectures/admcycles/DR/relations.py�gorenstein_precomputesr6cs�t�t����}||}t�|���}t�|����t�|���}���fdd�t|�D���fdd�t|�D�}t||k�}	t|�D]n}
t��D]`}|	r�|
|kr�|||
||
|<q�t||
||�|����t��fdd�t|�D��||
|<q�q�|S)a$
    Return the pairing matrix for the given genus, degree, markings and
    moduli type.

    EXAMPLES::

        sage: from admcycles.DR import pairing_matrix
        sage: pairing_matrix(1, 1, (1, 1))
        [[1/4, 1/6, 1/12, 2], [1/6, 1/12, 0, 2], [1/12, 0, -1/12, 2], [2, 2, 2, 0]]
    csg|]}t|�����qSr,r��.0�i�r/r1r2r,r5�
<listcomp>1s��z"pairing_matrix.<locals>.<listcomp>csg|]}dd�t��D��qS)cSsg|]}d�qS�rr,�r8�i2r,r,r5r;3�z-pairing_matrix.<locals>.<listcomp>.<listcomp>)�range�r8�i1)�ngens2r,r5r;3r?csg|]}�|�|�qSr,r,�r8�k��L�socle_evaluationsr,r5r;;s��r#r.rr@�boolr
�sum)r/r0r1r2r3r4�ngens1�ngens3�pairings�symrBr>r,)rGr/r1r2rCrHr5�pairing_matrix!s(��rPc
s�t�t����}||}t�|���}���fdd�t|�D���fdd�|D�}	t||kob|�k�}
tt|��D]z}tt���D]h}|
r�||kr�|	|||	||<q�t||||�|�|����t��fdd�t|�D��|	||<q�qr|	S)Ncsg|]}t|�����qSr,rr7r:r,r5r;Gs��z%pairing_submatrix.<locals>.<listcomp>csg|]}dd��D��qS)cSsg|]}d�qSr<r,r=r,r,r5r;Ir?z0pairing_submatrix.<locals>.<listcomp>.<listcomp>r,rA)�S2r,r5r;Ir?csg|]}�|�|�qSr,r,rDrFr,r5r;Qs�rI)
�S1rQr/r0r1r2r3r4rMrNrOrBr>r,)rGrQr/r1r2rHr5�pairing_submatrix@s$��rScCs*t||||�}|��t|d�t|�S)aX
    This function returns the predicted rank of the codimension r grading
    of the tautological ring of the moduli space of stable genus g curves
    with marked points labeled by the multiset marked_points.

    g and r should be nonnegative integers and marked_points should be a
    tuple of positive integers.

    The parameter moduli_type determines which moduli space to use:
    - MODULI_ST: all stable curves (this is the default)
    - MODULI_CT: curves of compact type
    - MODULI_RT: curves with rational tails
    - MODULI_SM: smooth curves

    EXAMPLES::

        sage: from admcycles.DR import betti

    Check rank R^3(bar{M}_2) = 1::

        sage: betti(2, 3)
        1

    Check rank R^2(bar{M}_{2,3}) = 44::

        sage: betti(2, 2, (1,2,3))  # long time
        44

    Check rank R^2(bar{M}_{2,3})^{S_3} = 20::

        sage: betti(2, 2, (1,1,1))  # long time
        20

    Check rank R^2(bar{M}_{2,3})^{S_2} = 32 (S_2 interchanging markings 1 and 2)::

        sage: betti(2, 2, (1,1,2))  # long time
        32

    Check rank R^2(M^c_4) = rank R^3(M^c_4) = 6::

        sage: from admcycles.DR import MODULI_CT, MODULI_RT, MODULI_SM
        sage: betti(4, 2, (), MODULI_CT)
        6
        sage: betti(4, 3, (), MODULI_CT)  # long time
        6

    We can use this to check that rank R^8(M^rt_{17,2})^(S_2)=122 < R^9(M^rt_{17,2})^(S_2) = 123.
    Indeed, betti(17,8,(1,1),MODULI_RT) = 122 and betti(17,9,(1,1),MODULI_RT)=123
    Similarly, we have rank R^9(M_{20,1}) = 75 < rank R^10(M_{20,1}) = 76
    Indeed, betti(20,9,(1,),MODULI_SM) = 75 and betti(20,10,(1,),MODULI_SM) = 76.
    r)�list_all_FZ�reverser.�compute_rank)r/�r�
marked_pointsr2rGr,r,r5�bettiVs4rYc	Csht||||�t|t|�|�}||}t||||�}t||||�}tt|�t|�||||�}t|���S)a�
    This function returns the rank of the codimension r grading of the
    Gorenstein quotient of the tautological ring of the moduli space of genus g
    curves with marked points labeled by the multiset marked_points.

    g and r should be nonnegative integers and marked_points should be a
    tuple of positive integers.

    The parameter moduli_type determines which moduli space to use:
    - MODULI_ST: all stable curves (this is the default)
    - MODULI_CT: curves of compact type
    - MODULI_RT: curves with rational tails

    EXAMPLES::

        sage: from admcycles.DR.relations import gorenstein

    Check rank Gor^3(bar{M}_{3}) = 10::

        sage: gorenstein(3, 3)  # long time
        10

    Check rank Gor^2(bar{M}_{2,2}) = 14::

        sage: gorenstein(2, 2, (1,2))  # long time
        14

    Check rank Gor^2(bar{M}_{2,2})^{S_2} = 11::

        sage: gorenstein(2, 2, (1,1))  # long time
        11

    Check rank Gor^2(M^c_{4}) = 6::

        sage: from admcycles.DR import MODULI_CT, MODULI_RT

        sage: gorenstein(4, 2, (), MODULI_CT)  # long time
        6

    Check rank Gor^4(M^rt_{8,2}) = 22::

        sage: gorenstein(8, 4, (1,2), MODULI_RT)  # long time
        22
    )r6r#r.�good_generator_listrS�tupler�rank)	r/rWrXr2r3r4rRrQ�Mr,r,r5�
gorenstein�s-�r^cs0ddlm}m}|d��|�tt���t|���t����krDdSt��|��}|d|�g}t��t	�d�|��}����fdd�t
�����D�D]>}	g}
|	D]}|
�||d|dg�q�t|
�}
|�|
�q�t
���d��D]>}	g}
|	D]}|
�||d|dg�q�t|
�}
|�|
�q�|d|t|��|d	��|�tt����tk�r^td��D�]��t��|��}|D�]�}
t|
d
�}dd�|D�D�]�}d
}t|
j���D]6}t|
j||fd�|
j||fk�r�d}�q�q�|�r�|
j|dfd�d
���dk�r�q�|
�|��t������k�r@�q�t���ttd�d����}dd�tt|��D�}tt|��D]4}t|
j�}|�|||�t|��|��||<�q������fdd�t
������D�}|t
����d��7}|D]T}g}|D]2}|d}||dk�r|�|||dg��qt|�}|�|��q��q��q|�qd|d|t|��|d|t|��|d	��|�tt���t|�}t|�}|d||�|d|�d}i}t|�D]*\}}|D]}|d|||df<�qؐq�|�rt|||�\}}t|||�}|d||�||S)z�
    EXAMPLES::

        sage: from admcycles.DR.relations import recursive_betti
        sage: recursive_betti(2, 3)  # not tested
        ?
    r)r%�dsavez'Start recursive_betti (%s,%s,%s,%s): %srz%s gensc	s"g|]}t|��t�d����qSr<��unsymmetrize_vecr�r8�br)r/r2�nrWr,r5r;�s�z#recursive_betti.<locals>.<listcomp>z%s gens, %s rels so farz(Middle recursive_betti (%s,%s,%s,%s): %sTcSsg|]}|d�qSr<r,�r8�orbitr,r,r5r;�r?F�cSsg|]}d�qS������r,�r8�numr,r,r5r;�sc	s&g|]}t|���t�d����qSr<r`rb)�d�g2r2rW�r0r,r5r;s�
�riz%s gens, %s relszsparse-%s-gens-%s-relsz%s gens, %s distinct relszsparse-%s-distinct-relszsparse-answer-%s)�utilsr%r_rr$r.r#r�symmetrize_mapr�choose_basic_rels�appendr+�interior_derived_relsr r@rrr]�ncolsr�degreer[r�replace_vertex_with_graphrr&�	enumerate�choose_orders_sparse�compute_rank_sparse)r/rWr1r2r%r_�ngen�	relationsZpartial_sym_map�rel�rel2�x�strata�G�
vertex_orbitsr9�good�j�strata2�which_gen_listrk�G_copy�rel_list�rel0�relation�nrelsr\�DZreli�	row_order�	col_orderr,)rlr/rmr2rdrWrnr5�recursive_betti�s��
�
�


&

�
�

�����
r�cCstt||||����S)al
    EXAMPLES::

        sage: from admcycles.DR.relations import FZ_rels
        sage: FZ_rels(2, 2)
        [
        (1, 0, 0, 0, 0, 0, -1/20, -1/480),
        (0, 1, 0, 0, 0, 0, -5/24, -1/96),
        (0, 0, 1, 0, 0, 0, -1/24, 0),
        (0, 0, 0, 1, 0, 0, -1/24, 0),
        (0, 0, 0, 0, 1, 0, -1, -1/12),
        (0, 0, 0, 0, 0, 1, -1, -1/24)
        ]
    )r�	FZ_matrix�basis�r/rWr1r2r,r,r5�FZ_rels%sr�cCstt||||��S)a]
    EXAMPLES::

        sage: from admcycles.DR.relations import FZ_matrix
        sage: from admcycles.DR.moduli import MODULI_SM, MODULI_RT, MODULI_CT, MODULI_ST
        sage: FZ_matrix(2, 2)
        [     60     -60      84       0       6       0       0       0]
        [ 473760 -100512   33984  -10080    6624  -10080    -288     -72]
        [ 115920  -12240   13536   -5040    1584   -5040    -144     -36]
        [      0       0     102     -30       0       0      -3       0]
        [      0       0      30      42       0       0      -3       0]
        [      0       0       0       0      66     -60      -6      -3]
        [      0       0       0       0      15       6     -21    -3/2]

        sage: FZ_matrix(2, 2, (1,), MODULI_CT)
        [     30     -30      30       0      42       0       0       0]
        [ 441000  -78120   61200 -138600   37296   -7920  -42840    1368]
        [ 204120  -27864  -39312   98280   20304    9072  -37800   -3672]
        [      0       0     -30      30       0      42       0       0]
        [  71820   -7020    9720  -41580    9288   -3240  -18900     756]
        [  13860    -900   -2520   16380    2520    3528  -16380   -1764]
        [      0       0       0       0      66     -30     -30      -6]
        [      0       0       0       0      15      21     -15     -21]
        [      0       0       0       0      15     -15      21     -21]

        sage: FZ_matrix(3, 2, (1, 2), MODULI_RT)
        [-251370   27162  -34020  -34020  145530   18900  145530   18036  -69930]
        [ -56700    4860   10584   -7560  -49140   -7560   41580   -8424   34020]
        [ -56700    4860   -7560   10584   41580   -7560  -49140   -8424   34020]
        [  -6930     450    1260    1260   -8190    1764   -8190     900   -6930]
        [  -6930     450    -900    -900    6930     900    6930     900   -6930]

        sage: FZ_matrix(3, 2, (1, 1), MODULI_SM)
        [-125685   13581  -34020  145530    9450]
        [ -56700    4860    3024   -7560   -7560]
        [  -3465     225    1260   -8190     882]
        [  -3465     225    -900    6930     450]
    )rrTr�r,r,r5r�8s'r�cCs<dd�}t|||d|d�}t|||d|d�}||�||�kS)aJ
    Check whether computing the FZ-relations via Pixton's 3-spin formula and
    by using new relations give the same result.

    TESTS::

        sage: import itertools
        sage: from admcycles.DR import FZ_methods_sanity_check, MODULI_SM, MODULI_RT, MODULI_CT, MODULI_ST
        sage: gn = [(0, 5), (1, 1), (1, 2), (1, 3), (2, 2), (3, 0), (4, 1)]
        sage: degrees = [0, 1, 2, 3]
        sage: moduli = [MODULI_SM, MODULI_RT, MODULI_CT, MODULI_ST]
        sage: for (g, n), r, moduli_type in itertools.product(gn, degrees, moduli):  # long time
        ....:     if not FZ_methods_sanity_check(g, r, n, moduli_type):
        ....:         print("ERROR: g={}, r={}, n={}, moduli_type={}".format(g, r, n, moduli_type))

        sage: all(FZ_methods_sanity_check(9, i, 0, MODULI_SM) for i in range(10))  # long time
        True
    cSs<|��t|���D]"\}}|��r|�t|��Sq|Sr-)�
echelonizerw�rows�is_zero�matrix_from_rowsr@)r]r9rWr,r,r5�echelon_without_zerosus
z6FZ_methods_sanity_check.<locals>.echelon_without_zerosrTF)�rels_matrix)r/rWrdr2r�Zspin3�newrelsr,r,r5�FZ_methods_sanity_checkbsr�cCsZtt||||��}|tkr,|t||||�7}|sVt||||�}|�dd�t|�D��|S)NcSsg|]}d�qSr<r,r7r,r,r5r;�r?zlist_all_FZ.<locals>.<listcomp>)r�interior_FZr �boundary_FZrrrr@)r/rWr1r2r{rzr,r,r5rT�srTcCsft|ttd|d���}g}ttd|d�}d|d<td|d�D]}||d|f<qB|D]�}	t|j�}
|d|d<|	dD]}|dt|7<q|td|d�D],}d|	d|dddt|d|f<q�t|�}|
�||�|�	|	|
g�qXg}
g}|D]^}|d�
�d}|D] }t|d|��rd}�q<�q|�r|�	|d�|
�	|d��q|
S)	Nr�ri)rrr)rrTF)�
FZ_param_listr[r@rrrr]rrvrr�compute_invariantr)r��vr/rlrd�paramsZgraph_paramsr]r9�pr�r�ZG_pZparams_reducedZgraphs_seenr~r��GGr,r,r5�reduced_FZ_param_list�s:
*
r�c	sp|dkrgSg}td|�}dd�t|�D�}|D]}||dd7<q2g�t|�D]&}||dkrX��|d||g�qXt|dd�D]�}t|d|dt���D]�}dd�t|d�D�g}tt���D]L}|�t||d�|d�|dd����d	d�|d
D�|d
<q�tj|�D]8�|�t	�d�t	��fdd�tt���D��f��q.q�q�|S)z�
    EXAMPLES::

        sage: from admcycles.DR.relations import FZ_param_list
        sage: FZ_param_list(3, ())
        [((3,), ()), ((1, 1, 1), ()), ((1,), ())]
    rr<cSsg|]}d�qSr<r,r7r,r,r5r;�r?z!FZ_param_list.<locals>.<listcomp>rr�cSs&g|]}tdd�|D��st|��qS)css|]}|ddkVqdS)rgr�Nr,�r8�lr,r,r5�	<genexpr>�r?�+FZ_param_list.<locals>.<listcomp>.<genexpr>)�any�list�r8�sigmar,r,r5r;�s�)�lengthcSs0g|](}tdd�|D��dkrdd�|D��qS)css|]}|ddkrdVqdS)rgrrNr,r�r,r,r5r��r?r�rcSsg|]}|d�qS�rr,rDr,r,r5r;�r?z,FZ_param_list.<locals>.<listcomp>.<listcomp>)rKr�r,r,r5r;�s�rics(g|] }�|dt�|d�f�qS�rr)r[rD��SZ
markings_bestr,r5r;�s�
�)
�maxr@rrr
r.r	r��	itertools�productr[)	rdr1Z
final_list�mmmZmarkings_groupedr9r�Zn_vec�S_listr,r�r5r��s0 �
�r�cCs8||d}|dkrdS|ddkr,t|St|SdS)Nrgr)r(r))�m�termrdr,r,r5�C_coeff�sr�cCs^t��}|d}|d|krZ|ddkrP|d|dt||�td||�7}|d7}q|S)Nr�rgri�����)r�zeror�)r9r��parity�totalrEr,r,r5�dual_C_coeff�s(
r�cCsD|��}g}td|d�D] }t||�D]}|�|�q*qt|�S)Nr)rur@rrr[)�Fr��target_partitionr9r�r,r,r5�poly_to_partition�sr�c		Cst��}tdd�|D��}td|d�D]�}tttt|���t|�|�D]�}t|��|�t|t|�|d��|�t|���}tt|�|�D]"}|t	||||||�9}q�tt|��D] }||vr�q�|t	d||�9}q�||7}qJq(dt|�t|�|t
t|��}|S)Ncss|]}|dkrdVqdS)rNr,r7r,r,r5r��r?zkappa_coeff.<locals>.<genexpr>rrri)rr�rKr@rr�r.�binomial�	factorialr�r*)	r�Zkappa_0r�r�Znum_onesr9Z	injectionr�r�r,r,r5�kappa_coeff�s,"�
� �
�r�cCs|t|||||�}g}|��}td|d�D]N}	|�d|j|	dfd|�|	�d|j|	df|j|	dfdf�q*g}
g}t|�D]~}	d}t|�D]T}
|	dks�||
|
dks�||
|
dkr�|
|dkr�|dks�||
||kr�|
}q�|�|�|
�||�q�tt|
�|�}dd�td|>�D�}|D]D}d}t|�D]$}	||	dk�rB|d||	>7}�qB||||<�q2|S)Nrr�rricSsg|]}d�qSr<r,r7r,r,r5r;r?z#FZ_kappa_factor.<locals>.<listcomp>)r�num_verticesr@rrr]ru�FZ_kappa_factor2r[)rkr�r/rWr1r2r�rG�nvr9�LL�tau�minir�Zfactor_dictZ
factor_vecZ
parity_keyr�r,r,r5�FZ_kappa_factors6"��L
r�c	Cs�t|||||�}|��}|��}td�|}	g}
|D]}|
�t|d��q4tj|
�}dd�t|	�D�}
g}|D]�}|�g�td|d�D]h}|j	d|f|dkr�td|d�D]>}|j	||fdkr�|d�|d|j	||fdf�q�q�q�qp|D]�}d}d}tt
|��D]h}tt
||��D]P}|t||||||d�9}||||td�|||d>N}�q(�q|
||7<q�|
S)Nr�rcSsg|]}d�qSr<r,r7r,r,r5r;(r?z%FZ_marking_factor.<locals>.<listcomp>rri)rr��	num_edgesrrrrr�r�r@r]r.r�)rk�marking_vecr/rWr1r2r�r��ne�num_paritiesZPPP_list�marksZPPP�marking_factorsZincident_verticesZ	mark_typerEr9�permsr�Zmarking_factorZmarks_index�countr,r,r5�FZ_marking_factorsB

$
���r�c	Cs�t|�}td|�}dd�t|�D�}|D]}||dd7<q*g}|D]}|�t||��qLtj|�}i}tjdd�t|�D��D]}	d|t|	�<q�|D�]}
dd�t|�D�}t|�D]:}t|�D],}t|
||�D]}
||�|d�q�q�q�d}dd�t|�D�}	t�	�}t|�D]n}|t
||�9}|	|t||�7<|	|td	�;<|tt||�||dt
||d��9}�q |t|	�||7<q�|S)
Nr<cSsg|]}d�qSr<r,r7r,r,r5r;Cr?z$FZ_kappa_factor2.<locals>.<listcomp>rcSsg|]}d�qS)r�r,r7r,r,r5r;Kr?rcSsg|]}g�qSr,r,�r8r�r,r,r5r;Nr?cSsg|]}d�qSr<r,r7r,r,r5r;Tr?r�)r.r�r@rrr
r�r�r[r�oner*rKr�r�)rGr�r�r�Z
sigma_groupedr9r�r��
kappa_factorsr��
assignmentZassigned_sigmar�rEZ
sigma_autsZkappa_factorr,r,r5r�?s<

"�
r�c	Cs2t|||||�}|��}td�|}|��}g}	td|d�D]z}
|jd|
fdkr>|	�|
g�td|d�D]H}|j||
fdkr�|	d�|�|j||
fddkrn|	d�|�qnq>dd�t|�D�}tjdd�|	D��D�]J}
d}tt	|	��D]@}|
|dkr�|d|	|dd>N}|d|	|dd>N}q�d}tt	|	��D]�}|	|d|	|dk�r�|t
|j|	|d|	|dfd|j|	|d|	|dfd|
|td��9}nX|t
|j|	|d|	|dfd|j|	|d|	|dfd|
|td��9}�qH|||7<q�|S)Nr�rrricSsg|]}d�qSr<r,r7r,r,r5r;or?z#FZ_hedge_factor.<locals>.<listcomp>cSsg|]}ddg�qSr�r,r7r,r,r5r;pr?)rr�rr�r@r]rrr�r�r.r�)rkr/rWr1r2r�r�r�r��	edge_listrEr9�
hedge_factorsZ
edge_paritiesr�Zhedge_factorr,r,r5�FZ_hedge_factor`s>$.�$.�
r�cCs�|d}|d}t|||||�}|��}	t|||||�}
td�|��}td�|	}t||||||�}
t||||||�}t|||||�}t��}t	|�D]F}|
|dkr�q�t	|�D]*}||
||||||A|j
A7}q�q�|||
}|S)a�
    EXAMPLES::

        sage: from admcycles.DR.graph import num_strata
        sage: from admcycles.DR.moduli import MODULI_ST
        sage: from admcycles.DR.relations import FZ_coeff
        sage: [FZ_coeff(i, ((3,), ()), 2, 2, (), MODULI_ST) for i in range(num_strata(2, 2))]
        [60, -60, 84, 0, 6, 0, 0, 0]
        sage: [FZ_coeff(i, ((1, 1, 1), ()), 2, 2, (), MODULI_ST) for i in range(num_strata(2, 2))]
        [473760, -100512, 33984, -10080, 6624, -10080, -288, -72]
        sage: [FZ_coeff(i, ((1,), ()), 2, 2, (), MODULI_ST) for i in range(num_strata(2, 2))]
        [115920, -12240, 13536, -5040, 1584, -5040, -144, -36]
    rrr�)rr�rr�h1r�r�r�r�r@�
target_parity)rk�FZ_paramr/rWr1r2r�r�r�r�Z
graph_autsZ	h1_factorr�r�r�r�r�r9r�r,r,r5�FZ_coeff�s,��
r�cs^t�����}g}td��d��}|D],������fdd�t|�D�}|�|�q,|S)a
    EXAMPLES::

        sage: from admcycles.DR.relations import interior_FZ
        sage: interior_FZ(2, 2)
        [[60, -60, 84, 0, 6, 0, 0, 0],
         [473760, -100512, 33984, -10080, 6624, -10080, -288, -72],
         [115920, -12240, 13536, -5040, 1584, -5040, -144, -36]]
    rgrc	sg|]}t|�������qSr,)r�r7�r�r/r1r2rWr,r5r;�s�zinterior_FZ.<locals>.<listcomp>)rr�r@rr)r/rWr1r2rzr{ZFZplr�r,r�r5r��s�r�c
Csd||d|}|dkr gStd||||tt���d|}t||||�}g}t|d�D]�}||drpq^t|�D]�}	tdd�|	D��r�qx|dkr�t|	�d|fff}
nt|	�d	f}
g}t|�D],}t||
||||�}
|
dkr�|�	||
g�q�|�	|�qxq^td
||||tt���|S)NrgrrzStart FZ (%s,%s,%s,%s): %sr�r�css|]}|ddkVqdS)rgrNr,r�r,r,r5r��r?z"possibly_new_FZ.<locals>.<genexpr>r,zEnd FZ (%s,%s,%s,%s): %s)
r%rr$rr@r	r�r[r�rr)r/rWrdr2r�r1rzr{r9r�r�r�r��coeffr,r,r5�possibly_new_FZ�s8��r�cCs |tkrgSt||||�}t|�}g}td|�D�]�}t||||�}|D�]�}	t|	d�}
dd�|
D�D�]�}d}t|	j���D]0}
t|	j||
fd�|	j||
fkr~d}q�q~|rf|	j|dfd}d|||dkr�qf|	�|�}t	|||�||kr�qft|||t
td|d��|�}dd�tt|��D�}tt|��D]4}t|	j�}|�|||�t
|||||�||<�q>t|	|||d|||d�}d}|D]x}dg|}tt|��D]H}||d	k�r�|||t|||||t
td|d��|�7<�q�|�|�|d7}�q�qfqHq0|S)
a
    EXAMPLES::

        sage: from admcycles.DR.relations import boundary_FZ
        sage: boundary_FZ(2, 2)
        [[0, 0, 102, -30, 0, 0, -3, 0],
         [0, 0, 30, 42, 0, 0, -3, 0],
         [0, 0, 0, 0, 66, -60, -6, -3],
         [0, 0, 0, 0, 15, 6, -21, -3/2]]
    rTcSsg|]}|d�qSr<r,rer,r,r5r;�r?zboundary_FZ.<locals>.<listcomp>rFrgcSsg|]}d�qSrhr,rjr,r,r5r;r?ri)r rr.r@rr]rtrrur#r[rrvrr�r�rr)r/rWr1r2�
generatorsrzr{rnrr�r�r9r�r�rmrlr�r�rkr�ZrFZplZcccccr�r�r,r,r5r��s`

$
�

��
��
r�cs�|r4�dkrtd�dStt��t������}|St������}t�����}��kr��dkr~�����fdd�|D�}n�����fdd�|D�}||}	t��t�����}
ttt|	�|
dd�}t	|	�D]"\}��D]\}}
|
|||f<q�q�|S)	a�
    Returns a matrix containing all FZ-relations for given ``g``, ``r``, ``n``, ``moduli_type``.
    The relations are invariant under the symmetry action on the first ``symm`` points.
    When ``usespin`` is True the relations are computed using Pixton's 3-spin formula.
    When ``usespin`` is False the relations are computed by deriving old relations and
    combining them with (possibly) new relations.

    TESTS::

      sage: from admcycles.DR import rels_matrix
      sage: sum(rels_matrix(2, 2, 4, 2, 1, False).echelon_form().column(-1))  # long time
      38
      sage: from admcycles.DR import rels_matrix, MODULI_RT, betti
      sage: def betti2(g, n, r):
      ....:     M = rels_matrix(g, r, n, n, MODULI_RT, False)
      ....:     return M.ncols() - M.rank()
      sage: [betti2(5, 2, i) for i in range(6)]  # long time
      [1, 3, 6, 6, 3, 1]
      sage: [betti(5, i, (1, 1), MODULI_RT) for i in range(6)]  # long time
      [1, 3, 6, 6, 3, 1]

    Check for https://gitlab.com/modulispaces/admcycles/-/issues/105::

        sage: from admcycles.DR import MODULI_ST
        sage: rels_matrix(9, 3, 0, 0, MODULI_ST, False).ncols()
        356
    rz'FZ_matrix not implemented with symmetryNc	s"g|]}t|��t������qSr,r`�r8r��r/r2rdrW�symmr,r5r;@s��zrels_matrix.<locals>.<listcomp>c
s*g|]"}t|��t���t������qSr,��partial_unsymmetrize_vecrr�r�r,r5r;Cs�
�T)�sparse)
�printrrTr�derived_relsr�rrr.rw)r/rWrdr�r2�usespinr|ZdrelsZpnrelsZallrelsrzr9r��cr,r�r5r�s.��r�cCs|dkrgStd||||tt���g}t|�D�]�}t|||�|k�rt||||�}|D]�}t||||�D]�}	t|d�|	�d�}
|
|kr�t	|||t
||
�t
||�|�}nt|�}t||�D]6}t||	||||||
|d�}|	|dkr�|
d7}
q�|�
t|��qnqZq0|tk�r@|dk�r,|dk�s@|dkr0|dk�s@q0t|||t�}|t|||�}
|D�]�}t||||
d|�D�]l}t|d�|�d�}t||
d|
d|�D�]6}	t|d�|	�d�}
|
|k�r�t	|||t
||
�t
||�t�}nt|�}t|
d�D]:}t||	||||||
td�}|	|dk�r
|
d7}
�q
|}
t||d||||
d|
|d�}|ddk�r�|
d7}
t|||
�D]F}t|||d||||
||
|d�}||ddk�r�|
d7}
�q�|�
t|���q��q��qbq0td||||tt���t|�}|S)z�
    Returns a list of relations that are derived from relations with
    less points by pulling back along the forgetfulmap that forgets a point.
    rz(Start pullback_derived (%s,%s,%s,%s): %srFrgTz&End pullback_derived (%s,%s,%s,%s): %s)r%rr$r@r#rqr'r�r�r�rrrrrr+r!r"r&)r/rWrdr�r2�answer�n0Z
basic_relsr|�vec�
local_symmr}r9rE�vec2Zlocal_symm2r,r,r5�pullback_derived_relsPs|�
��
0


��� ��r�cs�td�|��tt���tt�|�|���}t|�D�]n�t||�d���|krpt�|t���t�|���������fdd�t	�����D�}|t������7}|D]�}t|�d�D]�}t
|�D]�}	t|�|���D]�}
t|�}�}t���D]F}
t|
|
�D]2}t|t���|
d�|����}|d7}�q�q|	D]"}
t
||
�|����}||
7}�qN�|k�r��fdd�|D�}|�t|��q�q�q�q�q4td�|��tt���t|�}|S)z�
    Returns a list of relations that are derived from relations with
    lower codimension by multlication with psi- and kappa-classes.
    z(Start interior_derived (%s,%s,%s,%s): %src
s*g|]"}t|��t���t������qSr,r�)r8r�)r/r�r2rdrnr,r5r;�r?z)interior_derived_rels.<locals>.<listcomp>rcs g|]}�|d|dg�qSr�r,)r8�y)�symm_mapr,r5r;�r?z&End interior_derived (%s,%s,%s,%s): %s)r%rr$rr�r@r�rprrqr	r
rrrrr+r&)r/rWrdr�r2r�Z
pullback_relsr|r9r�r�r}�rcurr��mmr,)r/r�r2rdrnr�r5rs�sF�$��
�rsc	Cs�t||||�}|�d�d}g}|D]x}t|j�}	td|	j���D]B}
|	jd|
fddkrBt||	jd|
fd|�|	jd|
f<qB|�t|	||||��q$|S)z�
    Returns the map for symmetrizing a stratum by replacing its ``markings`` with ``symm_markings``.
    Requires ``symm_markings`` to be more symmetrized than ``markings``.
    rr�r)	rr�rr]r@rtrrrr)r/rWr1�
symm_markingsr2�gens�difr�r�r�r9r,r,r5rp�s
*rpcs���d��|�d�}t����|kr0td�dS�d|krn������fdd�t��t��d�|��D�St�����}i}tt|��D]�}||��vr�q�d||<||}	td|	j�	��D]"}
|	jd|
fddkr�|
}q�q�td|	j�	��D]�}
|	jd|
fddkr�t
|	j�}|jd|
fd7<|jd|fd8<t|�����}
|
|��v�rr||
d||
<q�d||
<q�q�t���|��}dd�tt
��|���D�}|��D] }|||�|||g��q�|S)	a|
    Returns map that replaces a stratum with ``markings`` by a linear
    combination of strata with ``symm_markings``.

    This function is an inverse of :func:`symmetrize_map`. The coefficient of
    each stratum in the output is the size of its orbit under the corresponding
    symmetric action.  Requires ``symm_markings`` to be more symmetrized than
    ``markings``.
    rzthis should not be happening?rics(g|] }t|���t��d����qSr�r�)r8�us�r/r1r2rdrWZtarget_symmr,r5r;�r?z,partial_unsymmetrize_map.<locals>.<listcomp>rr�cSsg|]}g�qSr,r,r7r,r,r5r;�r?)r�r.r��partial_unsymmetrize_maprrr@�keysr]rtrrrprrr)r/rWr1r�r2r�r��orbitsr9r�r�Zpt2r�rkr��resultrEr,r�r5r��sB

2
r�cCs�||kr|St|||||�}g}|D]^}d}	||dD]}
|	|
d7}	q8||dD]*}
|�|
d|d|
dt|	�g�qVq$t|�}|S)z^
    Applies partial_symmetrize_map to a relation to calculate its unsymmetrized version.
    rr)r�rrrr+)r�r/rWr1r�r2�	unsym_mapr�r~r*r�r,r,r5r��s*r�cCsttdd�|D��}t|||tt|�t|��|�}dd�tt||||��D�}tt|��D]}|||�|�qX|S)z|
    Does the same as partial_unsymmetrize_map but is faster.
    Only works for unsymmetrizing from complete symmetry.
    cSsg|]}d�qSr�r,r7r,r,r5r;r?z$unsymmetrize_map.<locals>.<listcomp>cSsg|]}g�qSr,r,r7r,r,r5r;r?)r[rprr.r@rrr)r/rWr1r2Z	markings2Zsym_map�mapr9r,r,r5�unsymmetrize_mapsrc
Csdt||||�}g}|D]@}t||d�}||dD]}	|�|	|dt|�g�q6qt|�}|S)Nrr)rr.rrrr+)
r�r/rWr1r2rr�r~r*r�r,r,r5rasrac
s�td|�|�tt���t||���kr,gSt||�}tt|�||���}�tkrV|Std��D�]"�t	|�|��}|D�]}t
|d�}	dd�|	D�D�]�}
d}t|j���D]0}t
|j|
|fd�|j|
|fkr�d}q�q�|r�d�t|j���D]8}|j|
|fddkr�|jd|fddkr��d7�q�|j|
dfd�d���dk�rZq�|�|
��t������k�r|q�t	���t�����}
d	d�tt|
��D�}tt|
��D]4}t|j�}|�|
|
|�t||�|��||<�q�������fd
d�t������D�}|t�������7}|D]L}g}|D]*\}}||dk�r>|�|||g��q>t|�}|�|��q2q�qxq`t|�}td|�|�tt���|S)
z�
    Returns a list of relations that are derived from relations with
    lower genus, codimension, and/or number of points.
    This is done by taking a Graph and inserting a relation at a vertex.
    zStart derived (%s,%s,%s,%s): %srTcSsg|]}|d�qSr<r,rer,r,r5r;7r?z derived_rels.<locals>.<listcomp>rFrgcSsg|]}d�qSrhr,rjr,r,r5r;Jsc
s.g|]&}t|���t���t������qSr,r�rb�rlrmZ	localsymmr2rWrnr,r5r;Qr?rizEnd derived (%s,%s,%s,%s): %s)r%rr$r#rrrsr r@rrr]rtrrur.rrvrrqrrr+r&)r/rWrdr�r2r1r�rr�r�r9r�r�r�r�rkr�r�r�r��x0�x1r,rr5r�%sp�


$,

�
�

�*

�r�cCs�d|||dkrgSt||tdd�t|�D��|�}|tkrd|t||t�krddd�t|�D�}nt||||�}|szgStd||||tt	���t
|||||�}t|�}td||�i}t|�D]&}	||	D]}
|
d||	|
df<q�q�|dk�rt|||�\}}t
|||�}
td	|
�nd}
g}tt|��}g}tt|��D]n}||D]}
|
d|||
df<�qL|�|�|d7}t
|||�|
k�r�|�||�|
d7}
td	|
��q@td
||||tt	���td||||||
�|S)a�
    Return a basis of new relations of the tautological ring invariant under symmetry.

    EXAMPLES::

        sage: from admcycles.DR.moduli import MODULI_SM, MODULI_RT, MODULI_CT, MODULI_ST
        sage: from admcycles.DR.relations import choose_basic_rels
        sage: choose_basic_rels(2, 2, 0, MODULI_ST)
        [[[0, 115920],
          [1, -12240],
          [2, 13536],
          [3, -5040],
          [4, 1584],
          [5, -5040],
          [6, -144],
          [7, -36]]]
    rgrcSsg|]}d�qSr�r,r7r,r,r5r;ur?z%choose_basic_rels.<locals>.<listcomp>cSsg|]}|dgg�qSr�r,r7r,r,r5r;wr?z"Start basic_rels (%s,%s,%s,%s): %sz%s gens, %s oldrelsrzrank %sz End basic_rels (%s,%s,%s,%s): %sz%s,%s,%s,%s: rank %s)rr[r@r"r#r r�r%rr$r�r.rxryr�rr)r/rWrdr2Zsym_ngenZsym_possible_relsZ
previous_relsr�r�r9r~r�r�Z
previous_rankr�r�r,r,r5rq`sT �

�
�rqc
sPd}t|�}t|�}dd�t|�D�}dd�t|�D��t|�D]}||||<q@t|�D]}|�||<qZdd�t|�D�}dd�t|�D�}	|D]0}
||
d�|
d�|	|
d�|
d�q�|D�]~}g}||D]}|�|�q�|s�q�|d7}|j�fdd	�d
�|d}g}
|	|D]"}||||k�r"|
�|��q"|dd�D]�}|||ft|||f�}|
D]�}||f|v�r�d|||f<||�|�|	|�|�|||f||||f8<|||fdk�rv|�||f�||�|�|	|�|��qv�qR|
D]0}|�||f�||�|�|	|�|��qq�|S)z�
    Return the rank of the sparse matrix ``D`` given as a dictionary.

    EXAMPLES::

        sage: from admcycles.DR.relations import compute_rank_sparse
        sage: compute_rank_sparse({(0, 1): 1, (1, 0): 2}, [0 ,1], [0, 1])
        2
    rcSsg|]}d�qSrhr,r7r,r,r5r;�r?z'compute_rank_sparse.<locals>.<listcomp>cSsg|]}d�qSrhr,r7r,r,r5r;�r?cSsg|]
}t��qSr,��setr7r,r,r5r;�r?cSsg|]
}t��qSr,rr7r,r,r5r;�r?rcs�|Sr-r,�r~�Zcol_order_rankr,r5�<lambda>�r?z%compute_rank_sparse.<locals>.<lambda>��keyN)r.r@�addrr�sortr�pop�remove)r�r�r�r��nrowsrtZrow_order_rankr9Zrow_contentsZcol_contentsr~r�r��T�iirE�ratr,r
r5ry�sX

 rycCstt||||��Sr-)r.rq)r/rWrdr2r,r,r5�num_new_rels�src	Cspt||||�t|t|�|�}||}ttt||||���}tt||||��}t||||||�}t|��	��
�S)aG
    Return the kernel of the pairing in degree ``r``.

    EXAMPLES::

        sage: from admcycles.DR.relations import goren_rels
        sage: goren_rels(3, 2)  # long time
        [
        (1, 0, 0, -41/21, 4/35, 0, 0, 0, -5/42, 41/504, 1/105, -11/140, 1/5040),
        (0, 1, 0, -89/7, -11/35, 0, 0, 0, -5/7, 103/168, -1/7, -47/70, -1/140),
        (0, 0, 1, -1, -7/5, 0, 0, 0, 0, 0, -1/10, 0, 0),
        (0, 0, 0, 0, 0, 1, 0, 0, 0, -1/24, 0, 0, 0),
        (0, 0, 0, 0, 0, 0, 1, 0, 0, -1/24, 0, 0, 0),
        (0, 0, 0, 0, 0, 0, 0, 1, -2, 1, -7/5, -7/5, -1/10)
        ]
    )r6r#r.r[r@rrZrSr�kernelr�)	r/rWr1r2r3r4rRrQr]r,r,r5�
goren_rels�srcCs2t||||�}g}t|�}t|�D�]}||}d}	td|j���D]�}
|j|
dfd}d}td|d�D]H}|j|
df|dkr�d||kr�d}	q�|||j|
df|7}ql|	s��qtd|j���D]0}
||j|
|
fd7}||j|
|
fd7}q�|dkrD||krDd}	�qqD|	r"|�|�q"|S)at
    Return a subset of indices whose corresponding strata generate
    the ``r``-th degree part of the tautological ring.

    EXAMPLES::

        sage: from admcycles.DR.moduli import MODULI_SM, MODULI_RT, MODULI_CT, MODULI_ST
        sage: from admcycles.DR.relations import good_generator_list
        sage: good_generator_list(3, 1, (), MODULI_ST)
        [0, 1, 2]
        sage: good_generator_list(3, 2, (), MODULI_ST)
        [1, 3, 4, 8, 9, 10, 11, 12]
        sage: good_generator_list(3, 3, (), MODULI_ST)
        [9, 22, 30, 31, 32, 35, 36, 37, 38, 39]
        sage: good_generator_list(3, 4, (), MODULI_ST)
        [86, 87, 109, 110, 111, 112, 113, 114, 117, 118, 119, 120]
        sage: good_generator_list(3, 5, (), MODULI_ST)
        [237, 238, 239, 257, 258, 259, 260, 261]
        sage: good_generator_list(3, 6, (), MODULI_ST)
        [373, 374, 375, 376, 377]
    TrrrgFr�)rr.r@r]rrtrr)r/rWr1r2r�Z	good_gens�ngensrkr�r�r9�codimrlr�r,r,r5rZ�s2"rZcs�dd�t|�D��dd�t|�D��|D],}�|dd7<�|dd7<q(tt|��}tt|��}|j�fdd�d�|j�fd	d�d�||fS)
NcSsg|]}d�qSr<r,r7r,r,r5r;1r?z(choose_orders_sparse.<locals>.<listcomp>cSsg|]}d�qSr<r,r�r,r,r5r;2r?rrcs�|Sr-r,r	��row_numsr,r5r8r?z&choose_orders_sparse.<locals>.<lambda>rcs�|Sr-r,r	��col_numsr,r5r9r?)r@r�r)r�rrtr
r�r�r,�rrr5rx0srxcs�t|�}|dkrggfSt|d�}dd�t|�D��dd�t|�D��t|�D]B}t|�D]4}|||dkr\�|d7<�|d7<q\qPtt|��}tt|��}|j�fdd�d�|j�fd	d�d�||fS)
NrcSsg|]}d�qSr<r,r7r,r,r5r;Br?z!choose_orders.<locals>.<listcomp>cSsg|]}d�qSr<r,r�r,r,r5r;Cr?rcs�|Sr-r,r	rr,r5rKr?zchoose_orders.<locals>.<lambda>rcs�|Sr-r,r	rr,r5rLr?)r.r@r�r)rGr��colsr9r�r�r�r,rr5�
choose_orders=s r!c	s�d}tt���D]ԉ��fdd�tt�d��D�}|s:q|d7}|d���fdd�t�dt���D�}|dd�D]F}��|���}|D]$}�|||�|�8<q�qxt�dt���D]}d�|�<q�q|S)a;
    Return the rank of the matrix ``L`` given as a list of lists.

    EXAMPLES::

        sage: from admcycles.DR.relations import compute_rank
        sage: compute_rank([[1, 2], [3, 4]])
        2
        sage: compute_rank([[1, 2], [2, 4]])
        1
        sage: compute_rank([[0, 0], [0, 0]])
        0
    rcs g|]}��|dkr|�qSr<r,r��rGr9r,r5r;br?z compute_rank.<locals>.<listcomp>rcs g|]}�|�dkr|�qSr<r,�r8r�rGr�r,r5r;gs�N�r@r.)rGr�r�rrErrr,�rGr9r�r5rVRs "$rVc
	s�d}tt|��D]�}||���fdd�|D�}|s6q|d7}|d���fdd�||dd�D�}|dd�D]F}��|���}|D]$}	�|	||�|	�8<q�qr|D]}	d�|	�<q�q|S)Nrcs g|]}��|dkr|�qSr<r,r�r"r,r5r;vr?z!compute_rank2.<locals>.<listcomp>rcs g|]}�|�dkr|�qSr<r,r#r$r,r5r;{s�r%)
rGr�r�r��irowr�rrErrr,r&r5�
compute_rank2rs  $r()r,)b�__doc__rr��sage.misc.cachefuncr�sage.modules.free_moduler�sage.rings.integer_ringr�sage.rings.rational_fieldr�sage.matrix.constructorr�sage.functions.otherr�sage.combinat.partitionr	�sage.combinat.integer_vectorr
�sage.combinat.permutationr�algebrar
rrrr�graphrrrrrrrrrrrr�
evaluationr�modulir r!r"r#ror$r%r&r'r(r)r*r+r6rPrSrYr^r�r�r�r�rTr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�rsrpr�r�rrar�rqryrrrZrxr!rVr(r,r,r,r5�<module>s�8(	97_*
 
$


	
 
 !' 79@&

.
;
E:1