# Reconstruction of Algebraic Forms#

This module reconstructs algebraic forms from the values of their invariants. Given a set of (classical) invariants, it returns a form that attains this values as invariants (up to scaling).

AUTHORS:

• Jesper Noordsij (2018-06): initial version

sage.rings.invariants.reconstruction.binary_cubic_coefficients_from_invariants(discriminant, invariant_choice='default')[source]#

Reconstruct a binary cubic from the value of its discriminant.

INPUT:

• discriminant – The value of the discriminant of the binary cubic.

• invariant_choice – The type of invariants provided. The accepted options are 'discriminant' and 'default', which are the same. No other options are implemented.

OUTPUT:

A set of coefficients of a binary cubic, whose discriminant is equal to the given discriminant up to a scaling.

EXAMPLES:

sage: from sage.rings.invariants.reconstruction import binary_cubic_coefficients_from_invariants
sage: coeffs = binary_cubic_coefficients_from_invariants(1)
sage: coeffs
(0, 1, -1, 0)
sage: R.<x> = QQ[]
sage: R(coeffs).discriminant()                                                  # needs sage.libs.pari
1

>>> from sage.all import *
>>> from sage.rings.invariants.reconstruction import binary_cubic_coefficients_from_invariants
>>> coeffs = binary_cubic_coefficients_from_invariants(Integer(1))
>>> coeffs
(0, 1, -1, 0)
>>> R = QQ['x']; (x,) = R._first_ngens(1)
>>> R(coeffs).discriminant()                                                  # needs sage.libs.pari
1


The two non-equivalent cubics $$x^3$$ and $$x^2*z$$ with discriminant 0 can’t be distinguished based on their discriminant, hence an error is raised:

sage: binary_cubic_coefficients_from_invariants(0)
Traceback (most recent call last):
...
ValueError: no unique reconstruction possible for binary cubics with a double root

>>> from sage.all import *
>>> binary_cubic_coefficients_from_invariants(Integer(0))
Traceback (most recent call last):
...
ValueError: no unique reconstruction possible for binary cubics with a double root


Reconstruct a binary quadratic from the value of its discriminant.

INPUT:

• discriminant – The value of the discriminant of the binary quadratic.

• invariant_choice – The type of invariants provided. The accepted options are 'discriminant' and 'default', which are the same. No other options are implemented.

OUTPUT:

A set of coefficients of a binary quadratic, whose discriminant is equal to the given discriminant up to a scaling.

EXAMPLES:

sage: from sage.rings.invariants.reconstruction import binary_quadratic_coefficients_from_invariants
sage: quadratic = invariant_theory.binary_form_from_invariants(2, [24])  # indirect doctest
Binary quadratic with coefficients (1, -6, 0)
24
(1, 0, 0)

>>> from sage.all import *
>>> quadratic = invariant_theory.binary_form_from_invariants(Integer(2), [Integer(24)])  # indirect doctest
Binary quadratic with coefficients (1, -6, 0)
24
(1, 0, 0)

sage.rings.invariants.reconstruction.binary_quintic_coefficients_from_invariants(invariants, K=None, invariant_choice='default', scaling='none')[source]#

Reconstruct a binary quintic from the values of its (Clebsch) invariants.

INPUT:

• invariants – A list or tuple of values of the three or four invariants. The default option requires the Clebsch invariants $$A$$, $$B$$, $$C$$ and $$R$$ of the binary quintic.

• K – The field over which the quintic is defined.

• invariant_choice – The type of invariants provided. The accepted options are 'clebsch' and 'default', which are the same. No other options are implemented.

• scaling – How the coefficients should be scaled. The accepted values are 'none' for no scaling, 'normalized' to scale in such a way that the resulting coefficients are independent of the scaling of the input invariants and 'coprime' which scales the input invariants by dividing them by their gcd.

OUTPUT:

A set of coefficients of a binary quintic, whose invariants are equal to the given invariants up to a scaling.

EXAMPLES:

First we check the general case, where the invariant $$M$$ is non-zero:

sage: R.<x0, x1> = QQ[]
sage: p = 3*x1^5 + 6*x1^4*x0 + 3*x1^3*x0^2 + 4*x1^2*x0^3 - 5*x1*x0^4 + 4*x0^5
sage: quintic = invariant_theory.binary_quintic(p, x0, x1)
sage: invs = quintic.clebsch_invariants(as_tuple=True)
sage: reconstructed = invariant_theory.binary_form_from_invariants(  # indirect doctest
....:     5, invs, variables=quintic.variables())
sage: reconstructed
Binary quintic with coefficients (9592267437341790539005557/244140625000000,
2149296928207625556323004064707/610351562500000000,
11149651890347700974453304786783/76293945312500000,
122650775751894638395648891202734239/47683715820312500000,
323996630945706528474286334593218447/11920928955078125000,
1504506503644608395841632538558481466127/14901161193847656250000)

>>> from sage.all import *
>>> R = QQ['x0, x1']; (x0, x1,) = R._first_ngens(2)
>>> p = Integer(3)*x1**Integer(5) + Integer(6)*x1**Integer(4)*x0 + Integer(3)*x1**Integer(3)*x0**Integer(2) + Integer(4)*x1**Integer(2)*x0**Integer(3) - Integer(5)*x1*x0**Integer(4) + Integer(4)*x0**Integer(5)
>>> quintic = invariant_theory.binary_quintic(p, x0, x1)
>>> invs = quintic.clebsch_invariants(as_tuple=True)
>>> reconstructed = invariant_theory.binary_form_from_invariants(  # indirect doctest
...     Integer(5), invs, variables=quintic.variables())
>>> reconstructed
Binary quintic with coefficients (9592267437341790539005557/244140625000000,
2149296928207625556323004064707/610351562500000000,
11149651890347700974453304786783/76293945312500000,
122650775751894638395648891202734239/47683715820312500000,
323996630945706528474286334593218447/11920928955078125000,
1504506503644608395841632538558481466127/14901161193847656250000)


We can see that the invariants of the reconstructed form match the ones of the original form by scaling the invariants $$B$$ and $$C$$:

sage: scale = invs[0]/reconstructed.A_invariant()
sage: invs[1] == reconstructed.B_invariant()*scale^2
True
sage: invs[2] == reconstructed.C_invariant()*scale^3
True

>>> from sage.all import *
>>> scale = invs[Integer(0)]/reconstructed.A_invariant()
>>> invs[Integer(1)] == reconstructed.B_invariant()*scale**Integer(2)
True
>>> invs[Integer(2)] == reconstructed.C_invariant()*scale**Integer(3)
True


If we compare the form obtained by this reconstruction to the one found by letting the covariants $$\alpha$$ and $$\beta$$ be the coordinates of the form, we find the forms are the same up to a power of the determinant of $$\alpha$$ and $$\beta$$:

sage: alpha = quintic.alpha_covariant()
sage: beta = quintic.beta_covariant()
sage: g = matrix([[alpha(x0=1,x1=0), alpha(x0=0,x1=1)],
....:             [beta(x0=1,x1=0), beta(x0=0,x1=1)]])^-1
sage: transformed = tuple([g.determinant()^-5*x
....:                      for x in quintic.transformed(g).coeffs()])
sage: transformed == reconstructed.coeffs()
True

>>> from sage.all import *
>>> alpha = quintic.alpha_covariant()
>>> beta = quintic.beta_covariant()
>>> g = matrix([[alpha(x0=Integer(1),x1=Integer(0)), alpha(x0=Integer(0),x1=Integer(1))],
...             [beta(x0=Integer(1),x1=Integer(0)), beta(x0=Integer(0),x1=Integer(1))]])**-Integer(1)
>>> transformed = tuple([g.determinant()**-Integer(5)*x
...                      for x in quintic.transformed(g).coeffs()])
>>> transformed == reconstructed.coeffs()
True


This can also be seen by computing the $$\alpha$$ covariant of the obtained form:

sage: reconstructed.alpha_covariant().coefficient(x1)
0
sage: reconstructed.alpha_covariant().coefficient(x0) != 0
True

>>> from sage.all import *
>>> reconstructed.alpha_covariant().coefficient(x1)
0
>>> reconstructed.alpha_covariant().coefficient(x0) != Integer(0)
True


If the invariant $$M$$ vanishes, then the coefficients are computed in a different way:

sage: [A,B,C] = [3,1,2]
sage: M = 2*A*B - 3*C
sage: M
0
sage: from sage.rings.invariants.reconstruction import binary_quintic_coefficients_from_invariants
sage: reconstructed = binary_quintic_coefficients_from_invariants([A,B,C])
sage: reconstructed
(-66741943359375/2097152,
-125141143798828125/134217728,
0,
52793920040130615234375/34359738368,
19797720015048980712890625/1099511627776,
-4454487003386020660400390625/17592186044416)
sage: newform = sum([ reconstructed[i]*x0^i*x1^(5-i) for i in range(6) ])
sage: newquintic = invariant_theory.binary_quintic(newform, x0, x1)
sage: scale = 3/newquintic.A_invariant()
sage: [3, newquintic.B_invariant()*scale^2, newquintic.C_invariant()*scale^3]
[3, 1, 2]

>>> from sage.all import *
>>> [A,B,C] = [Integer(3),Integer(1),Integer(2)]
>>> M = Integer(2)*A*B - Integer(3)*C
>>> M
0
>>> from sage.rings.invariants.reconstruction import binary_quintic_coefficients_from_invariants
>>> reconstructed = binary_quintic_coefficients_from_invariants([A,B,C])
>>> reconstructed
(-66741943359375/2097152,
-125141143798828125/134217728,
0,
52793920040130615234375/34359738368,
19797720015048980712890625/1099511627776,
-4454487003386020660400390625/17592186044416)
>>> newform = sum([ reconstructed[i]*x0**i*x1**(Integer(5)-i) for i in range(Integer(6)) ])
>>> newquintic = invariant_theory.binary_quintic(newform, x0, x1)
>>> scale = Integer(3)/newquintic.A_invariant()
>>> [Integer(3), newquintic.B_invariant()*scale**Integer(2), newquintic.C_invariant()*scale**Integer(3)]
[3, 1, 2]


Several special cases:

sage: quintic = invariant_theory.binary_quintic(x0^5 - x1^5, x0, x1)
sage: invs = quintic.clebsch_invariants(as_tuple=True)
sage: binary_quintic_coefficients_from_invariants(invs)
(1, 0, 0, 0, 0, 1)
sage: quintic = invariant_theory.binary_quintic(x0*x1*(x0^3-x1^3), x0, x1)
sage: invs = quintic.clebsch_invariants(as_tuple=True)
sage: binary_quintic_coefficients_from_invariants(invs)
(0, 1, 0, 0, 1, 0)
sage: quintic = invariant_theory.binary_quintic(x0^5 + 10*x0^3*x1^2 - 15*x0*x1^4, x0, x1)
sage: invs = quintic.clebsch_invariants(as_tuple=True)
sage: binary_quintic_coefficients_from_invariants(invs)
(1, 0, 10, 0, -15, 0)
sage: quintic = invariant_theory.binary_quintic(x0^2*(x0^3 + x1^3), x0, x1)
sage: invs = quintic.clebsch_invariants(as_tuple=True)
sage: binary_quintic_coefficients_from_invariants(invs)
(1, 0, 0, 1, 0, 0)
sage: quintic = invariant_theory.binary_quintic(x0*(x0^4 + x1^4), x0, x1)
sage: invs = quintic.clebsch_invariants(as_tuple=True)
sage: binary_quintic_coefficients_from_invariants(invs)
(1, 0, 0, 0, 1, 0)

>>> from sage.all import *
>>> quintic = invariant_theory.binary_quintic(x0**Integer(5) - x1**Integer(5), x0, x1)
>>> invs = quintic.clebsch_invariants(as_tuple=True)
>>> binary_quintic_coefficients_from_invariants(invs)
(1, 0, 0, 0, 0, 1)
>>> quintic = invariant_theory.binary_quintic(x0*x1*(x0**Integer(3)-x1**Integer(3)), x0, x1)
>>> invs = quintic.clebsch_invariants(as_tuple=True)
>>> binary_quintic_coefficients_from_invariants(invs)
(0, 1, 0, 0, 1, 0)
>>> quintic = invariant_theory.binary_quintic(x0**Integer(5) + Integer(10)*x0**Integer(3)*x1**Integer(2) - Integer(15)*x0*x1**Integer(4), x0, x1)
>>> invs = quintic.clebsch_invariants(as_tuple=True)
>>> binary_quintic_coefficients_from_invariants(invs)
(1, 0, 10, 0, -15, 0)
>>> quintic = invariant_theory.binary_quintic(x0**Integer(2)*(x0**Integer(3) + x1**Integer(3)), x0, x1)
>>> invs = quintic.clebsch_invariants(as_tuple=True)
>>> binary_quintic_coefficients_from_invariants(invs)
(1, 0, 0, 1, 0, 0)
>>> quintic = invariant_theory.binary_quintic(x0*(x0**Integer(4) + x1**Integer(4)), x0, x1)
>>> invs = quintic.clebsch_invariants(as_tuple=True)
>>> binary_quintic_coefficients_from_invariants(invs)
(1, 0, 0, 0, 1, 0)


For fields of characteristic 2, 3 or 5, there is no reconstruction implemented. This is part of Issue #26786.:

sage: binary_quintic_coefficients_from_invariants([3,1,2], K=GF(5))
Traceback (most recent call last):
...
NotImplementedError: no reconstruction of binary quintics implemented
for fields of characteristic 2, 3 or 5

>>> from sage.all import *
>>> binary_quintic_coefficients_from_invariants([Integer(3),Integer(1),Integer(2)], K=GF(Integer(5)))
Traceback (most recent call last):
...
NotImplementedError: no reconstruction of binary quintics implemented
for fields of characteristic 2, 3 or 5