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 cubicinvariant_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
from sage.rings.invariants.reconstruction import binary_cubic_coefficients_from_invariants coeffs = binary_cubic_coefficients_from_invariants(1) coeffs R.<x> = QQ[] R(coeffs).discriminant() # needs sage.libs.pari
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
binary_cubic_coefficients_from_invariants(0)
- sage.rings.invariants.reconstruction.binary_quadratic_coefficients_from_invariants(discriminant, invariant_choice='default')[source]¶
Reconstruct a binary quadratic from the value of its discriminant.
INPUT:
discriminant
– the value of the discriminant of the binary quadraticinvariant_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 sage: quadratic Binary quadratic with coefficients (1, -6, 0) sage: quadratic.discriminant() 24 sage: binary_quadratic_coefficients_from_invariants(0) (1, 0, 0)
>>> from sage.all import * >>> from sage.rings.invariants.reconstruction import binary_quadratic_coefficients_from_invariants >>> quadratic = invariant_theory.binary_form_from_invariants(Integer(2), [Integer(24)]) # indirect doctest >>> quadratic Binary quadratic with coefficients (1, -6, 0) >>> quadratic.discriminant() 24 >>> binary_quadratic_coefficients_from_invariants(Integer(0)) (1, 0, 0)
from sage.rings.invariants.reconstruction import binary_quadratic_coefficients_from_invariants quadratic = invariant_theory.binary_form_from_invariants(2, [24]) # indirect doctest quadratic quadratic.discriminant() binary_quadratic_coefficients_from_invariants(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
– 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 definedinvariant_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 nonzero:
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)
R.<x0, x1> = QQ[] 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 quintic = invariant_theory.binary_quintic(p, x0, x1) invs = quintic.clebsch_invariants(as_tuple=True) reconstructed = invariant_theory.binary_form_from_invariants( # indirect doctest 5, invs, variables=quintic.variables()) reconstructed
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
scale = invs[0]/reconstructed.A_invariant() invs[1] == reconstructed.B_invariant()*scale^2 invs[2] == reconstructed.C_invariant()*scale^3
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
alpha = quintic.alpha_covariant() beta = quintic.beta_covariant() g = matrix([[alpha(x0=1,x1=0), alpha(x0=0,x1=1)], [beta(x0=1,x1=0), beta(x0=0,x1=1)]])^-1 transformed = tuple([g.determinant()^-5*x for x in quintic.transformed(g).coeffs()]) transformed == reconstructed.coeffs()
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
reconstructed.alpha_covariant().coefficient(x1) reconstructed.alpha_covariant().coefficient(x0) != 0
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]
[A,B,C] = [3,1,2] M = 2*A*B - 3*C M from sage.rings.invariants.reconstruction import binary_quintic_coefficients_from_invariants reconstructed = binary_quintic_coefficients_from_invariants([A,B,C]) reconstructed newform = sum([ reconstructed[i]*x0^i*x1^(5-i) for i in range(6) ]) newquintic = invariant_theory.binary_quintic(newform, x0, x1) scale = 3/newquintic.A_invariant() [3, newquintic.B_invariant()*scale^2, newquintic.C_invariant()*scale^3]
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)
quintic = invariant_theory.binary_quintic(x0^5 - x1^5, x0, x1) invs = quintic.clebsch_invariants(as_tuple=True) binary_quintic_coefficients_from_invariants(invs) quintic = invariant_theory.binary_quintic(x0*x1*(x0^3-x1^3), x0, x1) invs = quintic.clebsch_invariants(as_tuple=True) binary_quintic_coefficients_from_invariants(invs) quintic = invariant_theory.binary_quintic(x0^5 + 10*x0^3*x1^2 - 15*x0*x1^4, x0, x1) invs = quintic.clebsch_invariants(as_tuple=True) binary_quintic_coefficients_from_invariants(invs) quintic = invariant_theory.binary_quintic(x0^2*(x0^3 + x1^3), x0, x1) invs = quintic.clebsch_invariants(as_tuple=True) binary_quintic_coefficients_from_invariants(invs) quintic = invariant_theory.binary_quintic(x0*(x0^4 + x1^4), x0, x1) invs = quintic.clebsch_invariants(as_tuple=True) binary_quintic_coefficients_from_invariants(invs)
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
binary_quintic_coefficients_from_invariants([3,1,2], K=GF(5))