API reference

All exported functions, grouped by task. Only user-facing functions are listed; backend helpers are internal.

Grothendieck–Witt classes

Constructing stable and unstable classes and combining them with the Grothendieck–Witt ring operations.

MotivicHomotopy.GWClassType
GWClass(M)

The isomorphism class of the nondegenerate symmetric bilinear form with Gram matrix M, as an element of the Grothendieck–Witt ring $\text{GW}(k)$ of a field (or finite étale algebra over a field) of characteristic not 2.

Given a basis $e_1, …, e_n$ of a $k$-vector space $V$, a symmetric bilinear form $β : V × V → k$ is encoded by its Gram matrix $(β(e_i, e_j))_{i,j}$; a change of basis replaces the Gram matrix by a congruent one, so a symmetric matrix determines the form up to congruence. The constructor checks that M is symmetric, nondegenerate, and defined over a supported coefficient ring, and errors otherwise.

Supported Gram matrices:

  • an Oscar matrix (MatElem) over QQ, a finite field of odd characteristic, or a finite étale algebra (a zero-dimensional MPolyQuoRing with nondegenerate trace form);
  • a plain Julia matrix of real or complex numbers, stored as Matrix{Float64} or Matrix{ComplexF64} — these play the role of forms over $\mathbb{R}$ and $\mathbb{C}$.

Equality == compares Gram matrices literally (same base ring, same entries). Mathematical equality in $\text{GW}(k)$ is tested with is_isomorphic_form.

The Gram matrix, coefficient algebra, and base field are recovered with gw_matrix, gw_algebra, and gw_base_field; a diagonal representative with diagonal_class. Further invariants: form_rank, form_signature, integral_discriminant, hasse_witt_invariant, anisotropic_dimension, anisotropic_part, sum_decomposition, is_isotropic_form, is_anisotropic_form.

Examples

julia> beta = GWClass(QQ[2 1; 1 3])
[2   1]
[1   3]

julia> gw_matrix(beta)
[2   1]
[1   3]

julia> gw_base_field(beta)
Rational field

julia> GWClass([0.0 1.0; 1.0 0.0])    # a form over the real numbers
2×2 Matrix{Float64}:
 0.0  1.0
 1.0  0.0
source
MotivicHomotopy.gw_algebraMethod
gw_algebra(beta)

The coefficient algebra over which a GWClass or GWuClass is defined — a field or a finite étale algebra over a field. Over $\mathbb{R}$ / $\mathbb{C}$ (float-backed classes) this returns the type Float64 / ComplexF64.

Examples

julia> gw_algebra(GWClass(QQ[2 1; 1 3]))
Rational field

See also gw_base_field, gw_matrix.

source
MotivicHomotopy.gw_base_fieldMethod
gw_base_field(beta)

The base field of a GWClass or GWuClass, when the class is defined over a field. For a class over an étale algebra this checks that the zero ideal is prime (i.e. the algebra is a field) and errors otherwise; for a class that already lives over QQ or a finite field it returns that field. Over $\mathbb{R}$ / $\mathbb{C}$ (float-backed classes) it returns the type Float64 / ComplexF64.

Examples

julia> gw_base_field(GWClass(QQ[2 1; 1 3]))
Rational field

See also gw_algebra.

source
MotivicHomotopy.gw_direct_sumMethod
gw_direct_sum(beta, gamma)

The direct (block) sum of two classes over the same base field — addition in the Grothendieck–Witt ring. For two GWClass inputs the result has the block-diagonal Gram matrix; for two GWuClass inputs the Gram matrices are block-summed and the scalars multiplied. beta + gamma is an alias.

Examples

julia> beta1 = GWClass(QQ[1 2; 2 3]);

julia> beta2 = GWClass(QQ[3 4; 4 5]);

julia> gw_direct_sum(beta1, beta2)
[1   2   0   0]
[2   3   0   0]
[0   0   3   4]
[0   0   4   5]

julia> gw_direct_sum(GWuClass(QQ[2 1; 1 2]), GWuClass(QQ[1 2; 2 6]))
([2 1 0 0; 1 2 0 0; 0 0 1 2; 0 0 2 6], 6)

See also gw_tensor_product, divisorial_sum.

source
MotivicHomotopy.gw_matrixMethod
gw_matrix(beta)

The Gram matrix of a GWClass or GWuClass: a symmetric matrix over the coefficient algebra of the class (MatElem for exact fields and étale algebras, Matrix{Float64} / Matrix{ComplexF64} over $\mathbb{R}$ / $\mathbb{C}$).

Examples

julia> beta = GWClass(QQ[2 1; 1 3]);

julia> gw_matrix(beta)
[2   1]
[1   3]

See also gw_scalar, gw_algebra, gw_base_field.

source
MotivicHomotopy.gw_tensor_productMethod
gw_tensor_product(beta, gamma)

The tensor product of two GWClasses over the same base field — multiplication in the Grothendieck–Witt ring. The resulting Gram matrix is the Kronecker product of the two Gram matrices. beta * gamma is an alias.

Examples

julia> beta1 = GWClass(QQ[1 2; 2 3]);

julia> beta2 = GWClass(QQ[3 4; 4 5]);

julia> gw_tensor_product(beta1, beta2)
[3    4    6    8]
[4    5    8   10]
[6    8    9   12]
[8   10   12   15]

See also gw_direct_sum.

source
MotivicHomotopy.GWuClassType
GWuClass(M)
GWuClass(M, a)
GWuClass(beta)
GWuClass(beta, a)

An element of the unstable Grothendieck–Witt group $\text{GW}^u(k) = \text{GW}(k) ×_{k^×/(k^×)^2} k^×$ of a field (or finite étale algebra) of characteristic not 2: the data of a GWClass together with a nonzero scalar whose square class agrees with the determinant of the Gram matrix.

The constructor takes a symmetric matrix M (or an existing GWClass beta) and optionally a scalar a; when the scalar is omitted, the determinant of the Gram matrix is used. Over $\mathbb{Q}$, $\mathbb{R}$, and finite fields of odd characteristic the constructor verifies that a agrees with the determinant up to squares and errors otherwise. Over an arbitrary finite étale algebra this verification is not possible; any nonzero scalar is accepted and a warning is printed when it differs from the determinant — the user must check the square-class condition by hand.

Accessors: gw_matrix, gw_scalar, gw_algebra, gw_base_field, and stable_part for the underlying $\text{GW}(k)$-class. Operations: gw_direct_sum (alias +) and divisorial_sum. Equality == compares the Gram matrix and the scalar literally; use is_isomorphic_form for equality in $\text{GW}^u(k)$.

Examples

julia> M = QQ[0 1; 1 0];

julia> alpha = GWuClass(M, -4)
([0 1; 1 0], -4)

julia> gw_scalar(alpha)
-4

julia> GWuClass(M)               # scalar defaults to det(M)
([0 1; 1 0], -1)

julia> GWuClass(GWClass(M), -9)
([0 1; 1 0], -9)
source
MotivicHomotopy.divisorial_sumMethod
divisorial_sum(class_list, root_list)

The divisorial sum of a list of unstable local degrees with respect to the divisor of roots at which they were computed.

For a pointed rational function $f/g : \mathbb{P}^1_k → \mathbb{P}^1_k$ with zeros $r_1, …, r_n$ and unstable local $\mathbb{A}^1$-degrees $β_1, …, β_n$ at those zeros, the global unstable degree is not the gw_direct_sum of the local degrees: the local-to-global formula of Igieobo et al. [I+24] weights the sum by the configuration of the zeros. Concretely, the Gram matrices are block-summed while the scalar picks up the factor $∏_{i<j} (r_i - r_j)^{2 m_i m_j}$ (with $m_i$ the rank of $β_i$) on top of the product of the scalars.

class_list is a vector of GWuClasses over a common base field and root_list the corresponding vector of base-field elements.

Examples

The local degrees of $(x^2 + x - 2)/(3x + 5)$ at its zeros −2 and 1 are $(⟨1/3⟩, 1/3)$ and $(⟨8/3⟩, 8/3)$; their divisorial sum recovers the global unstable degree:

julia> alpha = GWuClass(matrix(QQ, 1, 1, [1//3]));

julia> beta = GWuClass(matrix(QQ, 1, 1, [8//3]));

julia> divisorial_sum([alpha, beta], [-2, 1])
([1//3 0; 0 8//3], 8)

References

  • [I+24] J. Igieobo et al., Motivic configurations on the line, Advances in Mathematics 482 (2025), 110637.

See also global_unstable_A1_degree, local_unstable_A1_degree.

source
MotivicHomotopy.gw_scalarMethod
gw_scalar(beta::GWuClass)

The $k^×$-factor of an unstable Grothendieck–Witt class: the nonzero scalar that, together with the Gram matrix, determines the class. It is an element of the coefficient algebra of beta.

Examples

julia> gw_scalar(GWuClass(QQ[0 1; 1 0], -4))
-4

See also GWuClass, gw_matrix, stable_part.

source
MotivicHomotopy.stable_partMethod
stable_part(beta::GWuClass)

The image of an unstable Grothendieck–Witt class under the projection $\text{GW}^u(k) → \text{GW}(k)$: the GWClass with the same Gram matrix, forgetting the scalar.

Examples

julia> stable_part(GWuClass(QQ[0 1; 1 0], -4))
[0   1]
[1   0]

See also GWuClass, gw_scalar.

source

Working with forms

Building standard forms, diagonalizing them, extracting simplified representatives, and computing the Witt (sum) decomposition and anisotropic part.

MotivicHomotopy.diagonal_formMethod
diagonal_form(kk, (a₁, …, aₙ))
diagonal_form(kk, a₁, a₂, …)

The GWClass of the diagonal form $⟨a_1, …, a_n⟩$ over the field or finite étale algebra kk: the block sum of the rank-one forms $⟨a_i⟩ : k × k → k$, $(x, y) ↦ a_i x y$. A single entry produces a rank-one form. For forms over $\mathbb{R}$ / $\mathbb{C}$ pass Float64 / ComplexF64 as kk.

Examples

julia> diagonal_form(QQ, (3, 5, 7))
[3   0   0]
[0   5   0]
[0   0   7]

julia> diagonal_form(GF(29), 5//13)
[16]

julia> diagonal_form(Float64, 2)
1×1 Matrix{Float64}:
 2.0

See also hyperbolic_form, pfister_form, diagonal_unstable_form, diagonal_entries.

source
MotivicHomotopy.diagonal_unstable_formMethod
diagonal_unstable_form(kk, (a₁, …, aₙ))
diagonal_unstable_form(kk, a₁, a₂, …)

The GWuClass represented by the diagonal form $⟨a_1, …, a_n⟩$ over the field or finite étale algebra kk, with scalar the determinant $a_1 ⋯ a_n$. See diagonal_form for the stable counterpart.

Examples

julia> diagonal_unstable_form(QQ, (3, 5, 7))
([3 0 0; 0 5 0; 0 0 7], 105)
source
MotivicHomotopy.hyperbolic_formMethod
hyperbolic_form(kk)
hyperbolic_form(kk, n)

The GWClass of the hyperbolic form $\mathbb{H} = ⟨1, -1⟩$ over the field or finite étale algebra kk, or of the totally hyperbolic form $(n/2)·\mathbb{H}$ when an (even) rank n is specified. Odd n is an error.

Examples

julia> hyperbolic_form(GF(7))
[1   0]
[0   6]

julia> hyperbolic_form(Float64, 4)
4×4 Matrix{Float64}:
 1.0   0.0  0.0   0.0
 0.0  -1.0  0.0   0.0
 0.0   0.0  1.0   0.0
 0.0   0.0  0.0  -1.0

See also diagonal_form, hyperbolic_unstable_form, sum_decomposition.

source
MotivicHomotopy.hyperbolic_unstable_formMethod
hyperbolic_unstable_form(kk)
hyperbolic_unstable_form(kk, n)

The GWuClass represented by the hyperbolic form $\mathbb{H} = ⟨1, -1⟩$ (or the totally hyperbolic form of even rank n) over the field or finite étale algebra kk, with scalar its determinant. See hyperbolic_form for the stable counterpart.

Examples

julia> hyperbolic_unstable_form(GF(7))
([1 0; 0 6], 6)
source
MotivicHomotopy.pfister_formMethod
pfister_form(kk, (a₁, …, aₙ))
pfister_form(kk, a₁, a₂, …)

The GWClass of the Pfister form $⟨⟨a_1, …, a_n⟩⟩$ over the field kk: the rank-$2^n$ tensor product $⟨1, -a_1⟩ ⊗ ⋯ ⊗ ⟨1, -a_n⟩$. A single entry produces a one-fold Pfister form.

Examples

julia> pfister_form(QQ, (2, 6))
[1    0    0    0]
[0   -6    0    0]
[0    0   -2    0]
[0    0    0   12]

julia> pfister_form(GF(13), -2//3)
[1   0]
[0   5]

See also diagonal_form, gw_tensor_product.

source
MotivicHomotopy.diagonalize_via_congruenceMethod
diagonalize_via_congruence(M)

A diagonal matrix congruent to the symmetric matrix M, computed by symmetric Gaussian elimination (simultaneous row and column operations). M may be defined over a field, a finite étale algebra, or as a Matrix{Float64} / Matrix{ComplexF64} for $\mathbb{R}$ / $\mathbb{C}$. The order (and scaling) of the diagonal entries is an artifact of the algorithm and is not normalized; use diagonal_class for square-class-reduced entries.

Over étale algebras that are not domains the elimination is performed fraction-free (rows and columns are scaled by the pivot instead of divided), so the result is congruent but its entries may carry square factors.

Examples

julia> diagonalize_via_congruence(QQ[0 2; 2 0])
[4    0]
[0   -1]

julia> S, (y,) = polynomial_ring(QQ, ["y"]);

julia> A, _ = quo(S, ideal(S, [y^2 - 1]));

julia> diagonalize_via_congruence(A[A(1) A(2); A(2) A(y)])
[1       0]
[0   y - 4]

See also diagonal_class, diagonal_entries.

source
MotivicHomotopy.diagonal_classMethod
diagonal_class(beta)

A class isomorphic to beta with a diagonal Gram matrix, with simplified diagonal entries: over $\mathbb{Q}$ each entry is replaced by its squarefree integral representative; over a finite field entries become 1 or a fixed nonsquare; over $\mathbb{R}$ entries become ±1 and over $\mathbb{C}$ they become 1. For a GWuClass the stable part is diagonalized and the scalar carried through unchanged.

The result is cached on beta, so repeated calls are free. Note that sum_decomposition overwrites this cache with its own representative, so the value returned by diagonal_class can change after a call to sum_decomposition.

Examples

julia> beta = GWClass(QQ[9 1 7 4; 1 10 3 2; 7 3 6 7; 4 2 7 5]);

julia> diagonal_class(beta)
[1    0     0     0]
[0   89     0     0]
[0    0   445     0]
[0    0     0   -55]

See also diagonalize_via_congruence, diagonal_entries.

source
MotivicHomotopy.diagonal_entriesMethod
diagonal_entries(beta::GWClass)

The entries $a_1, …, a_n$ such that $β ≅ ⟨a_1, …, a_n⟩$, obtained by diagonalizing the Gram matrix via congruence (without square-class simplification) and reading off the diagonal. If beta is already diagonal the entries are returned as-is.

Examples

julia> diagonal_entries(GWClass(QQ[3 0 0; 0 2 0; 0 0 7]))
3-element Vector{QQFieldElem}:
 3
 2
 7

julia> diagonal_entries(GWClass([0.0 0.0 1.0; 0.0 1.0 0.0; 1.0 0.0 0.0]))
3-element Vector{Float64}:
  2.0
  1.0
 -0.5

See also diagonal_class, diagonalize_via_congruence.

source
MotivicHomotopy.anisotropic_partMethod
anisotropic_part(beta::GWClass)
anisotropic_part(A)

The anisotropic part of a symmetric bilinear form over $\mathbb{Q}$, $\mathbb{R}$, $\mathbb{C}$, or a finite field of odd characteristic: the (unique up to isomorphism) anisotropic form $β_a$ in the Witt decomposition $β ≅ β_a ⊕ n·\mathbb{H}$.

Over $\mathbb{C}$, $\mathbb{R}$, and finite fields this is a short computation from the rank, signature, or discriminant. Over $\mathbb{Q}$ it uses the number-field algorithms of Koprowski–Rothkegel [KR23]: ranks ≥ 4 are peeled off by signs of the signature, rank 3 via a CRT-constructed splitting element, and the rank-2 base case via a Hilbert-symbol exponent system solved over GF(2).

Examples

julia> anisotropic_part(diagonal_form(QQ, (3, -3, 2, 5, 1, -9)))
[2   0]
[0   5]

References

  • [KR23] P. Koprowski and B. Rothkegel, The anisotropic part of a quadratic form over a number field, Journal of Symbolic Computation, 2023.

See also anisotropic_dimension, gw_witt_index, sum_decomposition.

source
MotivicHomotopy.sum_decompositionMethod
sum_decomposition(beta)

A simplified diagonal representative of a GWClass or GWuClass over $\mathbb{Q}$, $\mathbb{R}$, $\mathbb{C}$, or a finite field of odd characteristic: the class rewritten as its anisotropic_part plus gw_witt_index-many hyperbolic forms. For an unstable class the decomposition is applied to the stable part and the scalar kept. Over $\mathbb{R}$ this reflects the classification of a form by its rank and signature ([L05, II Proposition 3.5]).

The result overwrites the diagonal_class cache slot on beta, so a later diagonal_class call returns this representative.

Examples

julia> gamma = GWClass(QQ[1 2 3; 2 4 5; 3 5 6]);

julia> sum_decomposition(gamma)
[1   0    0]
[0   1    0]
[0   0   -1]

julia> delta = GWClass(GF(13)[9 1 7 4; 1 10 3 2; 7 3 6 7; 4 2 7 5]);

julia> sum_decomposition(delta)
[1   0   0    0]
[0   8   0    0]
[0   0   1    0]
[0   0   0   12]

References

  • [L05] T. Y. Lam, Introduction to quadratic forms over fields, American Mathematical Society, 2005.

See also sum_decomposition_string, anisotropic_part, gw_witt_index.

source
MotivicHomotopy.sum_decomposition_stringMethod
sum_decomposition_string(beta)

A human-readable string for the sum_decomposition of a GWClass or GWuClass: hyperbolic summands are written H (with a multiplicity prefix) and rank-one summands <a>. For an unstable class the result is the pair "(decomposition, scalar)".

Examples

julia> sum_decomposition_string(GWClass(QQ[1 2 3; 2 4 5; 3 5 6]))
"H + <1>"

julia> sum_decomposition_string(GWClass(GF(13)[9 1 7 4; 1 10 3 2; 7 3 6 7; 4 2 7 5]))
"H + <1> + <-5>"

See also sum_decomposition.

source

Invariants and classification

Numerical and arithmetic invariants of a form (rank, signature, discriminant, Hilbert symbols, Hasse–Witt invariants, anisotropic dimension, Witt index), the isotropy predicates, and the isomorphism test that classifies forms up to equivalence.

MotivicHomotopy.form_rankMethod
form_rank(beta::GWClass)
form_rank(M)

The rank of a symmetric bilinear form. On a GWClass (which is nondegenerate by construction) this is the size of the Gram matrix; on a raw matrix it is the matrix rank, so degenerate directions are not counted.

Examples

julia> form_rank(diagonal_form(QQ, (3, 5, 7, 11)))
4

See also form_signature, anisotropic_dimension.

source
MotivicHomotopy.form_signatureMethod
form_signature(beta::GWClass)

The signature of a symmetric bilinear form over $\mathbb{Q}$ or $\mathbb{R}$: after diagonalizing, the number of positive diagonal entries minus the number of negative ones. Together with the rank it classifies forms over $\mathbb{R}$; over $\mathbb{Q}$ it is one of the invariants entering is_isomorphic_form.

Examples

julia> form_signature(GWClass([0.0 0.0 1.0; 0.0 1.0 0.0; 1.0 0.0 0.0]))
1

julia> form_signature(diagonal_form(QQ, (1, -1, 1)))
1

See also form_rank, integral_discriminant, is_isomorphic_form.

source
MotivicHomotopy.hasse_witt_invariantMethod
hasse_witt_invariant(beta::GWClass, p)
hasse_witt_invariant(L::AbstractVector, p)

The Hasse–Witt invariant at the prime p of a form over $\mathbb{Q}$: for a diagonalization $⟨a_1, …, a_n⟩$, the product $∏_{i<j} (a_i, a_j)_p$ of pairwise Hilbert symbols (see hilbert_symbol_padic). The list variant takes the diagonal entries directly.

The invariant equals 1 for all but finitely many primes — for p not dividing any entry of a squarefree diagonal representative it is automatically 1 — so only the relevant_primes need checking.

Examples

julia> beta = GWClass(QQ[1 4 7; 4 3 -1; 7 -1 5]);

julia> hasse_witt_invariant(beta, 7)
1

julia> hasse_witt_invariant([6, 7, 22], 2)
-1

See also hilbert_symbol_padic, relevant_primes, is_isomorphic_form.

source
MotivicHomotopy.integral_discriminantMethod
integral_discriminant(beta::GWClass)

A squarefree integral representative of the discriminant of a form over $\mathbb{Q}$: the square class of the determinant of any Gram matrix representing beta, normalized to a squarefree integer. The discriminant is one of the invariants classifying rational forms (see is_isomorphic_form).

Examples

julia> beta = GWClass(QQ[1 4 7; 4 3 -1; 7 -1 5]);

julia> integral_discriminant(beta)
-269

See also form_signature, hasse_witt_invariant.

source
MotivicHomotopy.relevant_primesMethod
relevant_primes(beta::GWClass)

A finite list of primes containing every prime at which the Hasse–Witt invariant of the rational form beta can be nontrivial. The Hasse–Witt invariants of a form equal 1 at all but finitely many primes ([S73, IV §3.3]); since they are products of Hilbert symbols of the diagonal entries, it suffices to take the primes dividing the entries of a squarefree diagonal representative.

Examples

julia> relevant_primes(diagonal_form(QQ, (6, 7, 22)))
4-element Vector{ZZRingElem}:
 2
 3
 7
 11

References

  • [S73] J. P. Serre, A course in arithmetic, Springer-Verlag, 1973.

See also hasse_witt_invariant.

source
MotivicHomotopy.hilbert_symbol_padicMethod
hilbert_symbol_padic(a, b, p)

The Hilbert symbol $(a, b)_p$ of two nonzero rational numbers, viewed as elements of $\mathbb{Q}_p$:

$(a, b)_p = 1$ if $z^2 = ax^2 + by^2$ has a nonzero solution over $\mathbb{Q}_p$, and $-1$ otherwise ([S73, Chapter III]).

Products of Hilbert symbols compute the hasse_witt_invariant, a key step in classifying rational forms and certifying their (an)isotropy.

The name carries the _padic suffix because Oscar itself exports hilbert_symbol (which this function calls internally).

Examples

$z^2 = 2x^2 + y^2$ has the solution $(1, 0, 3)$ mod 7, hence a 7-adic solution by Hensel's lemma, while $z^2 = 7x^2 + 3y^2$ has no nonzero solution mod 7:

julia> hilbert_symbol_padic(2, 1, 7)
1

julia> hilbert_symbol_padic(7, 3, 7)
-1

julia> hilbert_symbol_padic(2, 2, 2)
1

julia> hilbert_symbol_padic(2, 3, 2)
-1

References

  • [S73] J. P. Serre, A course in arithmetic, Springer-Verlag, 1973.

See also hilbert_symbol_real, hasse_witt_invariant.

source
MotivicHomotopy.hilbert_symbol_realMethod
hilbert_symbol_real(a, b)

The Hilbert symbol $(a, b)_{\mathbb{R}}$ of two nonzero rational numbers viewed as real numbers: $-1$ if $z^2 = ax^2 + by^2$ has no nonzero real solution — which happens exactly when both a and b are negative — and $1$ otherwise ([S73, Chapter III]).

Examples

julia> hilbert_symbol_real(-3, -2//3)
-1

julia> hilbert_symbol_real(3, -5)
1

References

  • [S73] J. P. Serre, A course in arithmetic, Springer-Verlag, 1973.

See also hilbert_symbol_padic, form_signature.

source
MotivicHomotopy.padic_valuationMethod
padic_valuation(a, p)

The $p$-adic valuation of a nonzero integer or rational number a: the integer $n$ with $a = u·p^n$ for a unit $u$ of $\mathbb{Z}_p$. Errors on $a = 0$.

Examples

$363/7 = 3·11^2/7$, so the 11-adic valuation is 2:

julia> padic_valuation(363//7, 11)
2
source
MotivicHomotopy.anisotropic_dimensionMethod
anisotropic_dimension(beta::GWClass)
anisotropic_dimension(A)

The anisotropic dimension of a symmetric bilinear form over $\mathbb{Q}$, $\mathbb{R}$, $\mathbb{C}$, or a finite field of odd characteristic. By the Witt decomposition theorem any nondegenerate form decomposes uniquely as $β ≅ n·\mathbb{H} ⊕ β_a$ with $β_a$ anisotropic; the anisotropic dimension is the rank of $β_a$.

Over $\mathbb{Q}$ it is the maximum of the anisotropic dimensions over all completions: $\lvert \text{signature} \rvert$ at the real place and anisotropic_dimension_qqp at 2 and the relevant_primes ([KC18, Algorithm 9]).

Examples

julia> anisotropic_dimension(diagonal_form(QQ, (1, -1, 2)))
1

References

  • [KC18] P. Koprowski and A. Czogała, Computing with quadratic forms over number fields, Journal of Symbolic Computation, 2018.

See also gw_witt_index, anisotropic_part, is_anisotropic_form.

source
MotivicHomotopy.anisotropic_dimension_qqpMethod
anisotropic_dimension_qqp(beta::GWClass, p)

The anisotropic dimension of a rational form over the $p$-adic completion $\mathbb{Q}_p$: the rank of the anisotropic part of beta base-changed to $\mathbb{Q}_p$. Every form of rank ≥ 5 over $\mathbb{Q}_p$ is isotropic, so the result is always 0, 1, 2, 3, or 4. This implements [KC18, Algorithm 8].

Examples

julia> anisotropic_dimension_qqp(diagonal_form(QQ, (1, -1, 2)), 2)
1

References

  • [KC18] P. Koprowski and A. Czogała, Computing with quadratic forms over number fields, Journal of Symbolic Computation, 2018.

See also anisotropic_dimension.

source
MotivicHomotopy.gw_witt_indexMethod
gw_witt_index(beta::GWClass)

The Witt index of a form over $\mathbb{Q}$, $\mathbb{R}$, $\mathbb{C}$, or a finite field of odd characteristic: the number $n$ of hyperbolic summands in the Witt decomposition $β ≅ n·\mathbb{H} ⊕ β_a$ ([L05, I.4.3]), computed as (rank − anisotropic dimension)/2.

The name carries the gw_ prefix because Oscar exports witt_index.

Examples

julia> gw_witt_index(diagonal_form(QQ, (1, -1, 2)))
1

References

  • [L05] T. Y. Lam, Introduction to quadratic forms over fields, American Mathematical Society, 2005.

See also anisotropic_dimension, sum_decomposition.

source
MotivicHomotopy.is_anisotropic_formMethod
is_anisotropic_form(beta::GWClass)
is_anisotropic_form(A)

Whether a symmetric bilinear form over $\mathbb{Q}$, $\mathbb{R}$, $\mathbb{C}$, or a finite field of odd characteristic is anisotropic, i.e. has no nonzero vector $v$ with $β(v, v) = 0$. Computed as the statement that the anisotropic dimension equals the dimension of the form.

What this takes per field: over $\mathbb{C}$ only rank-one forms are anisotropic; over $\mathbb{R}$ a form is anisotropic iff its diagonal entries are all positive or all negative; over $\mathbb{Q}$ the Hasse–Minkowski principle ([L05, VI.3.1]) reduces the question to the completions (forms of rank ≥ 5 over $\mathbb{Q}_p$ are always isotropic ([S73, IV Theorem 6]), so only finitely many invariant computations are needed); over a finite field a nondegenerate form is anisotropic iff its rank is ≤ 2 and it is not hyperbolic.

Examples

julia> is_anisotropic_form(GWClass(ComplexF64[2 0; 0 5]))
false

julia> is_anisotropic_form(GWClass([3.0 0 0; 0 5 0; 0 0 7]))
true

julia> is_anisotropic_form(GWClass(GF(7)[1 0 0; 0 1 0; 0 0 1]))
false

References

  • [L05] T. Y. Lam, Introduction to quadratic forms over fields, American Mathematical Society, 2005.
  • [S73] J. P. Serre, A course in arithmetic, Springer-Verlag, 1973.

See also is_isotropic_form, anisotropic_dimension, anisotropic_part.

source
MotivicHomotopy.is_isotropic_formMethod
is_isotropic_form(beta::GWClass)
is_isotropic_form(A)

Whether a symmetric bilinear form over $\mathbb{Q}$, $\mathbb{R}$, $\mathbb{C}$, or a finite field of odd characteristic is isotropic — the negation of is_anisotropic_form; see there for the per-field criteria.

Examples

julia> is_isotropic_form(diagonal_form(QQ, (1, -1)))
true

julia> is_isotropic_form(GWClass(GF(7)[3 0; 0 3]))
false

See also gw_witt_index, anisotropic_dimension.

source
MotivicHomotopy.is_isomorphic_formMethod
is_isomorphic_form(alpha, beta; linear_tolerance = 1e-6)

Whether two Grothendieck–Witt classes (or unstable classes, or raw symmetric matrices) over $\mathbb{Q}$, $\mathbb{R}$, $\mathbb{C}$, or a finite field of odd characteristic represent the same element of $\text{GW}(k)$ (resp. $\text{GW}^u(k)$). This is the mathematical notion of equality; == on classes compares Gram matrices literally.

The classification used per field:

  • $\mathbb{C}$ (and any quadratically closed field): rank alone, since every nonzero element is a square.
  • $\mathbb{R}$: rank and signature (Sylvester's law of inertia).
  • $\mathbb{Q}$: rank, signature, discriminant, and the Hasse–Witt invariants at all relevant_primes — by the Hasse–Minkowski principle forms over $\mathbb{Q}$ are isomorphic iff they are isomorphic over every completion ([S73, IV Thm. 7]; [L05, VI.3.3]). Each Hasse–Witt invariant is a product of values of a symbol on the diagonal entries ([MH73, III.5.4]).
  • finite fields: rank and the square class of the discriminant.

For GWuClasses the fibered-product structure of $\text{GW}^u(k)$ reduces the test to: stable parts isomorphic and $k^×$-factors equal. Over $\mathbb{Q}$ and finite fields the scalars must agree exactly; over $\mathbb{R}$ and $\mathbb{C}$ they are considered equal when the absolute value of their difference is below linear_tolerance (default 1e-6).

Examples

julia> alpha = GWClass(ComplexF64[2 3 1; 3 -1 0; 1 0 0]);

julia> beta = GWClass(ComplexF64[2 4 -1; 4 5 7; -1 7 9]);

julia> is_isomorphic_form(alpha, beta)
true

julia> is_isomorphic_form(GWClass(QQ[1 4 7; 4 3 2; 7 2 -1]),
                          GWClass(QQ[0 0 1; 0 2 7; 1 7 3]))
false

julia> u1 = GWuClass(QQ[2 3 1; 3 -1 0; 1 0 0], 1);

julia> u2 = GWuClass(QQ[2 3 1; 3 -1 0; 1 0 0], 4);

julia> is_isomorphic_form(u1, u2)    # same stable part, scalars 1 ≠ 4 in ℚ×
false

References

  • [S73] J. P. Serre, A course in arithmetic, Springer-Verlag, 1973.
  • [L05] T. Y. Lam, Introduction to quadratic forms over fields, American Mathematical Society, 2005.
  • [MH73] J. Milnor and D. Husemoller, Symmetric bilinear forms, Springer-Verlag, 1973.

See also form_rank, form_signature, integral_discriminant, hasse_witt_invariant.

source

Computing $\mathbb{A}^1$-degrees

The local and global $\mathbb{A}^1$-Brouwer degrees, both stable and unstable.

MotivicHomotopy.global_A1_degreeMethod
global_A1_degree(F)

The global $\mathbb{A}^1$-Brouwer degree of an endomorphism of affine space $f = (f_1, …, f_n) : \mathbb{A}^n_k → \mathbb{A}^n_k$ with isolated zeros, as a GWClass in $\text{GW}(k)$. F is a vector of $n$ polynomials in $n$ variables over a field $k$ of characteristic not 2.

The $\mathbb{A}^1$-Brouwer degree, first defined by Morel [M12], is an algebro-geometric enrichment of the classical topological Brouwer degree. Using the tools of motivic homotopy theory one associates to an endomorphism of affine space the isomorphism class of a nondegenerate symmetric bilinear form whose invariants encode geometric data about how the morphism transforms space: its rank recovers the degree of the associated complex map, and its signature the degree of the associated real map. Such a form appears in the work of Eisenbud–Levine [EL77] and Khimshiashvili [K77], whose signature computes the local degree of a smooth map of real manifolds even where the Jacobian vanishes; this was shown to agree with Morel's degree by Kass–Wickelgren [KW19]. A related form attached to a complete intersection, due to Scheja–Storch [SS76], was aligned with the $\mathbb{A}^1$-degree in [BW23]. Following Brazelton–McKean–Pauli [BMP23], the degree is computed here as a multivariate Bézoutian bilinear form.

Following McKean [M21] one may read the degree $\deg^{\mathbb{A}^1}(f)$ as a quadratically enriched intersection multiplicity of the hypersurfaces $V(f_1) ∩ ⋯ ∩ V(f_n)$. It equals the sum of the local_A1_degrees over the points of the zero locus $V(f)$.

The Gram matrix is expressed in a standard-monomial basis; an equivalent form in a different basis represents the same class, so compare results with is_isomorphic_form rather than entrywise.

Base field

  • $\mathbb{Q}$ and finite fields of odd characteristic — the form is computed exactly.
  • $\mathbb{C}$ — a symmetric bilinear form over $\mathbb{C}$ is determined by its rank, so the degree is simply the identity form of rank equal to the $\mathbb{C}$-dimension of the coordinate algebra $k[x_1,…,x_n]/(f_1,…,f_n)$ — the number of zeros counted with multiplicity. This dimension is a discrete invariant equal to the rank of the degree computed over $\mathbb{Q}$, so it is obtained from the exact computation with no numerical root-finding.
  • $\mathbb{R}$ — compute the degree over $\mathbb{Q}$ and base-change the resulting Gram matrix to $\mathbb{R}$ (its form_signature is the real degree); real input is not accepted directly.

Examples

For $z ↦ z^2$ the degree is a rank-2 form of signature 0: the complex map $\mathbb{C}$$\mathbb{C}$ has degree 2, while the real map $\mathbb{R}$$\mathbb{R}$ has degree 0.

julia> S, (x,) = polynomial_ring(QQ, ["x"]);

julia> beta = global_A1_degree([x^2 + 1])
[0   1]
[1   0]

julia> form_rank(beta), form_signature(beta)
(2, 0)

The cubic $y = x(x-1)(x+1)$ meeting the $x$-axis, read as an enriched count of intersection points: rank 3 (three complex intersections) and signature 1 (the signed real count).

julia> S, (x, y) = polynomial_ring(QQ, ["x", "y"]);

julia> f = [x^3 - x^2 - y, y];

julia> global_A1_degree(f)
[0    0    1]
[0    1   -1]
[1   -1    0]

julia> form_signature(global_A1_degree(f))
1

The global degree is the sum of the local degrees over the zero locus $V(f) = \{(1,0), (0,0)\}$:

julia> d1 = local_A1_degree(f, ideal(S, [x - 1, y]));

julia> d2 = local_A1_degree(f, ideal(S, [x, y]));

julia> is_isomorphic_form(global_A1_degree(f), gw_direct_sum(d1, d2))
true

References

  • [M12] F. Morel, $\mathbb{A}^1$-algebraic topology over a field, Springer Lecture Notes in Mathematics, 2012.
  • [EL77] D. Eisenbud and H. Levine, An algebraic formula for the degree of a C∞ map germ, Annals of Mathematics, 1977.
  • [K77] G. Khimshiashvili, The local degree of a smooth mapping, Sakharth. SSR Mecn. Akad. Moambe, 1977.
  • [SS76] G. Scheja and U. Storch, Über Spurfunktionen bei vollständigen Durchschnitten, J. Reine Angew. Math., 1975.
  • [KW19] J. L. Kass and K. Wickelgren, The class of Eisenbud–Khimshiashvili–Levine is the local $\mathbb{A}^1$-Brouwer degree, Duke Mathematical Journal, 2019.
  • [BW23] T. Bachmann and K. Wickelgren, Euler classes: six-functors formalism, dualities, integrality and linear subspaces of complete intersections, J. Inst. Math. Jussieu, 2023.
  • [BMP23] T. Brazelton, S. McKean, and S. Pauli, Bézoutians and the $\mathbb{A}^1$-degree, Algebra & Number Theory, 2023.
  • [M21] S. McKean, An arithmetic enrichment of Bézout's Theorem, Mathematische Annalen, 2021.

See also local_A1_degree, global_unstable_A1_degree, sum_decomposition.

source
MotivicHomotopy.global_unstable_A1_degreeMethod
global_unstable_A1_degree(q)
global_unstable_A1_degree(f, g)

The global unstable $\mathbb{A}^1$-Brouwer degree of a pointed rational function $f/g : \mathbb{P}^1_k → \mathbb{P}^1_k$ — pointed meaning $(f/g)(∞) = ∞$, i.e. $\deg f > \deg g$ — as a GWuClass in the unstable Grothendieck–Witt group $\text{GW}^u(k) = \text{GW}(k) ×_{k^×/(k^×)^2} k^×$.

Morel's $\mathbb{A}^1$-Brouwer degree generalizes the classical Brouwer degree by assigning to an endomorphism of the motivic sphere a class in the Grothendieck–Witt ring. That degree map is an isomorphism in dimensions two and above, but in dimension one it is only surjective [M12]; there, a computation of Morel [M12] and Cazanave [C12] refines it to an isomorphism $[\mathbb{P}^1_k, \mathbb{P}^1_k] ≅ \text{GW}^u(k)$ onto the unstable group, which records not only the stable class but also a $k^×$-scalar. Building on Cazanave's work, Kass–Wickelgren [KW20] and Igieobo et al. [I+24] give an explicit bilinear form representing the degree of $f/g$ in both the local and global settings, a variant of the Bézoutian form (Cazanave [C12, Thm. 3.6]).

Unlike the stable degree, the global unstable degree is not the sum of the local_unstable_A1_degrees at the zeros of $f/g$: it is their divisorial_sum [I+24], which weights each zero's contribution by the configuration of the whole divisor of zeros.

Input and base field

q is an element of the fraction field of a one-variable polynomial ring over $\mathbb{Q}$ or a finite field of odd characteristic (a plain polynomial is treated as $f/1$); the two-argument form supplies numerator and denominator separately. If $f$ and $g$ share a common factor it is cancelled and the reduced function checked for pointedness before the degree is computed. Over $\mathbb{R}$, compute over $\mathbb{Q}$ and base-change.

Over $\mathbb{C}$ — the one case that needs numerical computation, since the class carries a $k^×$-scalar and so the actual complex roots must be found — pass two HomotopyContinuation expressions f, g. Roots of f and g closer than the linear_tolerance keyword (default 1e-6) are treated as a common factor and cancelled.

Examples

A degree-5 pointed rational function; its rank equals the number of zeros of $f/g$ counted with multiplicity over $\mathbb{C}$:

julia> S, (x,) = polynomial_ring(QQ, ["x"]);

julia> q = (x^5 - 6*x^4 + 11*x^3 - 2*x^2 - 12*x + 8) // (x^4 - 5*x^2 + 7*x + 1);

julia> global_unstable_A1_degree(q)
([-68 38 11 -14 1; 38 -63 63 -29 7; 11 63 -84 39 -5; -14 -29 39 -16 0; 1 7 -5 0 1], -53240)

The divisorial sum of the local degrees at the zeros $-1, 1, 2$ recovers the global degree:

julia> degs = [local_unstable_A1_degree(q, r) for r in [-1, 1, 2]];

julia> is_isomorphic_form(divisorial_sum(degs, [-1, 1, 2]),
                          global_unstable_A1_degree(q))
true

The same computation over $\mathbb{C}$ with HomotopyContinuation input:

julia> import HomotopyContinuation; HomotopyContinuation.@var x;

julia> global_unstable_A1_degree((x-1)*(x-2)*(x-3), (x-1)*(x-4))
(ComplexF64[1.0 + 0.0im 0.0 + 0.0im; 0.0 + 0.0im 1.0 + 0.0im], -1.9999999999999987 + 3.337899271044116e-15im)

References

  • [M12] F. Morel, $\mathbb{A}^1$-algebraic topology over a field, Springer Lecture Notes in Mathematics, 2012.
  • [C12] C. Cazanave, Algebraic homotopy classes of rational functions, Annales Scientifiques de l'École Normale Supérieure, 2012.
  • [KW20] J. L. Kass and K. Wickelgren, A classical proof that the algebraic homotopy class of a rational function is the residue pairing, Linear Algebra and its Applications, 2020.
  • [I+24] J. Igieobo et al., Motivic configurations on the line, Advances in Mathematics 482 (2025), 110637.

See also local_unstable_A1_degree, divisorial_sum, global_A1_degree.

source
MotivicHomotopy.local_A1_degreeMethod
local_A1_degree(F, p)

The local $\mathbb{A}^1$-Brouwer degree of an endomorphism of affine space $f = (f_1, …, f_n) : \mathbb{A}^n_k → \mathbb{A}^n_k$ at an isolated zero, as a GWClass in $\text{GW}(k)$. F is a vector of $n$ polynomials in $n$ variables over a field of characteristic not 2, and p is the prime ideal of a point in the zero locus $V(f)$.

The local degree is the class of the Bézoutian bilinear form on the local algebra $Q_p(f) = k[x_1,…,x_n]_{\mathfrak{m}_p}/(f_1,…,f_n)$ at the point (see local_algebra_basis). Summed over the points of $V(f)$ it recovers the global_A1_degree; see there for the background and references.

The base field is handled as for the global degree: exactly over $\mathbb{Q}$ and finite fields of odd characteristic; over $\mathbb{C}$ the class is the identity form of rank equal to the $\mathbb{C}$-dimension of $Q_p(f)$ (the multiplicity of the zero), obtained from the exact computation; over $\mathbb{R}$, compute over $\mathbb{Q}$ and base-change.

Examples

julia> S, (x, y) = polynomial_ring(QQ, ["x", "y"]);

julia> f = [x^3 - x^2 - y, y];

julia> d1 = local_A1_degree(f, ideal(S, [x - 1, y]))
[1]

julia> d2 = local_A1_degree(f, ideal(S, [x, y]))
[ 1   -1]
[-1    0]

julia> is_isomorphic_form(global_A1_degree(f), gw_direct_sum(d1, d2))
true

See also global_A1_degree, local_unstable_A1_degree, local_algebra_basis.

source
MotivicHomotopy.local_algebra_basisMethod
local_algebra_basis(L, p)

A monomial basis of the local algebra $Q_p(f) = k[x_1,…,x_n]_{\mathfrak{m}_p}/(f)$ of an endomorphism of affine space at an isolated zero: L is the list of polynomials $f = (f_1, …, f_n)$ and p the prime ideal of the zero. The local algebra is realized as $k[x]/(I : (I : p^∞))$ ([S02, Proposition 2.5]) and its standard monomials are returned.

Examples

julia> S, (x, y) = polynomial_ring(QQ, ["x", "y"]);

julia> local_algebra_basis([x^2 + 1 - y, y], ideal(S, [x^2 + 1, y]))
2-element Vector{QQMPolyRingElem}:
 x
 1

References

  • [S02] B. Sturmfels, Solving Systems of Polynomial Equations, American Mathematical Society, 2002.

See also local_A1_degree.

source
MotivicHomotopy.local_unstable_A1_degreeMethod
local_unstable_A1_degree(q, r)
local_unstable_A1_degree(f, g, r)

The local unstable $\mathbb{A}^1$-Brouwer degree of a pointed rational function $f/g : \mathbb{P}^1_k → \mathbb{P}^1_k$ at a zero r in the base field, as a GWuClass in $\text{GW}^u(k)$. If r is a zero of multiplicity $m$, the result is the $m × m$ antidiagonal form with entry the value of $(u - r)^m · g/f$ at $r$.

Input shapes match global_unstable_A1_degree (see there for background and references): a fraction or polynomial plus the root, or numerator and denominator separately; the numerical $\mathbb{C}$ path takes two HomotopyContinuation expressions and a number. Non-reduced input is reduced (and re-checked for pointedness) first.

Examples

julia> S, (x,) = polynomial_ring(QQ, ["x"]);

julia> local_unstable_A1_degree((x^2 + x - 2) // (3*x + 5), -2)
([1//3], 1//3)

See also global_unstable_A1_degree, divisorial_sum, local_A1_degree.

source

Étale algebras and transfer

Multiplication matrices, trace and norm of an étale algebra, and the transfer (corestriction) of a Grothendieck–Witt class.

MotivicHomotopy.algebra_normMethod
algebra_norm(A, a)
algebra_norm(S, I, b)

The norm over $k$ of an element of a finite-dimensional $k$-algebra: the determinant of its multiplication_matrix. Accepts the same input shapes as multiplication_matrix.

Examples

julia> S, (x, y) = polynomial_ring(QQ, ["x", "y"]);

julia> I = ideal(S, [x^2 + y^2 + 1, 3*x + 2]);

julia> A, _ = quo(S, I);

julia> algebra_norm(A, 1 + y*x^2)
937//729

See also multiplication_matrix, algebra_trace.

source
MotivicHomotopy.algebra_traceMethod
algebra_trace(A, a)
algebra_trace(S, I, b)

The trace over $k$ of an element of a finite-dimensional $k$-algebra: the trace of its multiplication_matrix. Accepts the same input shapes as multiplication_matrix (a quotient ring and an element, or a polynomial ring, ideal, and element).

Examples

julia> S, (x, y) = polynomial_ring(QQ, ["x", "y"]);

julia> I = ideal(S, [x^2 + y^2 + 1, 3*x + 2]);

julia> algebra_trace(S, I, 1 + y*x^2)
2

See also multiplication_matrix, algebra_norm, transfer_gw.

source
MotivicHomotopy.multiplication_matrixMethod
multiplication_matrix(A, a)
multiplication_matrix(S, I, b)

The matrix, over the coefficient field $k$, of multiplication by an element on a monomial basis of a finite-dimensional $k$-algebra. The algebra is given either directly as a quotient ring A (an MPolyQuoRing) with a an element coercible into it, or as a polynomial ring S with an ideal I and b an element of S (the algebra then being $S/I$). The basis is the standard monomials in ascending order.

Examples

julia> S, (x, y) = polynomial_ring(QQ, ["x", "y"]);

julia> I = ideal(S, [x^2 + y^2 + 1, 3*x + 2]);

julia> A, _ = quo(S, I);

julia> multiplication_matrix(A, 1 + y*x^2)
[   1   -52//81]
[4//9         1]

See also algebra_trace, algebra_norm.

source
MotivicHomotopy.transfer_gwMethod
transfer_gw(beta::GWClass)

The image of a Grothendieck–Witt class over a finite étale algebra $L/k$ under the canonical transfer map $\text{GW}(L) → \text{GW}(k)$, computed by diagonalizing over $L$ and applying the trace form: the result is the diagonal form over $k$ whose entries are the traces (algebra_trace) of the diagonal entries.

Note

If the trace of a diagonal entry vanishes, the would-be output is degenerate and the constructor errors.

Examples

julia> S, (t,) = polynomial_ring(QQ, ["t"]);

julia> A, _ = quo(S, ideal(S, [t^2 - 1]));

julia> beta = GWClass(A[A(1) A(2); A(2) A(t)]);

julia> transfer_gw(beta)
[2    0]
[0   -8]

See also algebra_trace, GWClass.

source