Skip to content

feat(Counterexamples): a finite free group scheme of order four not killed by four#41748

Open
j2d9w5xtjn-png wants to merge 5 commits into
leanprover-community:masterfrom
j2d9w5xtjn-png:grothendieck-power-counterexample
Open

feat(Counterexamples): a finite free group scheme of order four not killed by four#41748
j2d9w5xtjn-png wants to merge 5 commits into
leanprover-community:masterfrom
j2d9w5xtjn-png:grothendieck-power-counterexample

Conversation

@j2d9w5xtjn-png

@j2d9w5xtjn-png j2d9w5xtjn-png commented Jul 14, 2026

Copy link
Copy Markdown

Once #40500 (affine group scheme ↔ Hopf algebra correspondence) lands, the group-scheme formulation can be restated through that API for a cleaner statement.


This PR adds a Counterexamples/ file resolving a question of Grothendieck in the negative.

Statement

Grothendieck asked whether a finite locally free group scheme of order n is killed by n. Deligne proved this holds for commutative group schemes. This file gives a counterexample in the non-commutative case.

Over the base ring R = ℤ[a, b] / (a³, b³, a²b + 2), the coordinate algebra

A = R[U, V] / (U² − abU + b²V, V² − a²V)

is a Hopf algebra, finite free of rank four over R, whose associated affine group scheme has order four but is not killed by four. Concretely, the fourth convolution power of the identity is not the convolution unit:

`Counterexample.GrothendieckPower.counterexample :
   Nontrivial R ∧ Module.Free R A ∧ Module.Finite R A ∧ Module.finrank R A = 4 ∧
     powerMap 4 ≠ (Algebra.ofId R A).comp counit`

Background

  • Grothendieck's question: is a finite locally free group scheme of order n killed by n? (Recorded as open in Tate, Finite flat group schemes, §3.8.)
  • Deligne's theorem: yes for commutative group schemes (Oort–Tate, Group schemes of prime order, §1).
  • This construction answers the general (non-commutative) question negatively.

Proof sketch

  1. The base ring R has 2b ≠ 0; this is certified by an explicit faithful R-module M = ℤ/4 × ℤ/4 × (ℤ/2)⁵ with a, b acting by explicit additive endomorphisms.
  2. A is built as two nested QuadraticAlgebras, hence finite free of rank four.
  3. With lambda = (1 + aU)(1 + bV), one checks lambda is group-like and the given Δ(U), Δ(V) extend to a bialgebra comultiplication.
  4. powerMap n sends U to (1 + lambda + ⋯ + lambdaⁿ⁻¹)·U; at n = 4 this is 2bUV ≠ 0.
  5. The eighth power map is the convolution unit, so the seventh gives an antipode: A is a Hopf algebra of order four not killed by four. (Consistency with Deligne: A is not cocommutative — not_isCocomm.)

Disclosure

As stated in the module docstring, and per mathlib policy: the construction of this group scheme and its formalization were carried out with the AI assistants Codex (OpenAI) and Claude (Anthropic), under the direction of the author, who takes responsibility for the contribution.

…illed by four

Add a counterexample to Grothendieck's question of whether a finite
locally free group scheme of order n is killed by n. Deligne proved
this holds for commutative group schemes; this file gives a
non-commutative counterexample.

Over R = ℤ[a,b]/(a³,b³,a²b+2), the rank-four free Hopf algebra
A = R[U,V]/(U²-abU+b²V, V²-a²V) has a group scheme of order four whose
fourth convolution power map is not the convolution unit (it sends U to
2bUV ≠ 0), while the eighth power map is the unit.

Disclosure: the construction of this group scheme and its formalization
were carried out with the AI assistants Codex (OpenAI) and Claude
(Anthropic), under the direction of the author. This is also stated in
the module docstring.
@github-actions github-actions Bot added the new-contributor This PR was made by a contributor with at most 5 merged PRs. Welcome to the community! label Jul 14, 2026
@github-actions

Copy link
Copy Markdown

Welcome new contributor!

Thank you for contributing to Mathlib! If you haven't done so already, please review our contribution guidelines, as well as the style guide and naming conventions. In particular, we kindly remind contributors that we have guidelines regarding the use of AI when making pull requests.

We use a review queue to manage reviews. If your PR does not appear there, it is probably because it is not successfully building (i.e., it doesn't have a green checkmark), has the awaiting-author tag, or another reason described in the Lifecycle of a PR. The review dashboard has a dedicated webpage which shows whether your PR is on the review queue, and (if not), why.

If you haven't already done so, please come to https://leanprover.zulipchat.com/, introduce yourself, and mention your new PR.

Thank you again for joining our community.

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown

PR summary d223a56548

Import changes for modified files

No significant changes to the import graph

Import changes for all files
Files Import difference

Declarations diff (regex)

+ A
+ B
+ M
+ P
+ R
+ U
+ U_relation
+ V
+ V_relation
+ WitnessRing
+ a
+ aA
+ aB
+ aEnd
+ aEnd_bEnd_comm
+ aEnd_cube
+ aEnd_sq_mul_bEnd
+ a_cube
+ aaT
+ aaT_smul
+ affineGroupScheme
+ affineGroupScheme_X
+ algHom_ext
+ antipode_left_identity
+ antipode_right_identity
+ ap
+ aw
+ aw_cube
+ b
+ bA
+ bB
+ bEnd
+ bEnd_cube
+ b_cube
+ baseIdeal
+ baseIdeal_le_ker_evalWitness
+ base_relation
+ bbT
+ bbT_smul
+ bialgebra_comulAlgHom
+ bialgebra_counitAlgHom
+ bp
+ bw
+ bw_cube
+ coeffU
+ coeffV
+ comul
+ comulB
+ comulB_V
+ comulB_aB
+ comulB_bB
+ comulB_bB_sq
+ comulB_neg
+ comulOuter
+ comul_U
+ comul_U_formula
+ comul_aA
+ comul_bA
+ comul_coassoc
+ comul_lambda
+ comul_v
+ comul_v_formula
+ coordinateHopfAlgebra
+ counit
+ counitB
+ counitB_V
+ counitOuter
+ counit_U
+ counit_lambda
+ counit_left
+ counit_right
+ counit_v
+ counterexample
+ deltaU
+ deltaU_root_mul
+ deltaV
+ delta_lambda
+ delta_relations
+ double
+ double_reduce
+ evalWitness
+ exists_hopfAlgebra_not_killed_by_finrank
+ finrank_A
+ finrank_A_over_B
+ finrank_B
+ four_eq_zero
+ generators_commute
+ geomSum
+ geomSum_eight
+ geomSum_four
+ geomSum_mul_lambda_add_one
+ geomSum_succ
+ geomSum_zero
+ instAlgebraBR
+ instAlgebraBT
+ instBialgebra
+ instHopfAlgebra
+ instance : Algebra R A
+ instance : IsMulCommutative WitnessRing
+ instance : Module.Finite R A
+ instance : Module.Free R A
+ instance : Nontrivial R := ⟨⟨(2 : R) * b, 0, two_b_ne_zero⟩⟩
+ instance : Nontrivial WitnessRing := ⟨⟨(2 : WitnessRing) * bw, 0, two_bw_ne_zero⟩⟩
+ isGroupLikeElem_lambda
+ lambda
+ lambda_eq_one_add_theta
+ lambda_pow_four
+ law_lambda_generic
+ law_relations_generic
+ left
+ left_lambda
+ l₁
+ l₂
+ mapped_relations
+ monPowMap
+ monPowMap_affineGroupScheme_four_ne
+ monPowMap_op_four_ne
+ monPowMap_op_unop_hom
+ not_isCocomm
+ orderOf_universalPoint
+ powerMap
+ powerMap_U
+ powerMap_eight
+ powerMap_eight_U
+ powerMap_eight_v
+ powerMap_four_U
+ powerMap_four_U_ne_zero
+ powerMap_four_v
+ powerMap_lambda
+ powerMap_one_apply
+ powerMap_seven_mul_universalPoint
+ powerMap_succ_U
+ powerMap_succ_lambda
+ powerMap_succ_v
+ powerMap_v
+ powerMap_zero_apply
+ quadratic_lift_omega
+ r_smul_mul
+ reduce
+ reduce_double
+ right
+ right_aA
+ right_bA
+ right_lambda
+ theta
+ theta_identities_generic
+ theta_sq
+ two_b_U_v_ne_zero
+ two_b_ne_zero
+ two_bw_ne_zero
+ two_mul_bEnd_ne_zero
+ two_theta
+ universalPoint
+ universalPoint_mul_powerMap_seven
+ universalPoint_pow_eight
+ universalPoint_pow_four_ne_one
+ u₁
+ u₂
+ v
+ v_relation
+ v₁
+ v₂
+ witnessHom
+ witnessHom_b
+ witness_relation
+ zero_smul_A
+ zero_smul_T

You can run this locally as follows
## from your `mathlib4` directory:
git clone https://github.com/leanprover-community/mathlib-ci.git ../mathlib-ci

## summary with just the declaration names:
../mathlib-ci/scripts/pr_summary/declarations_diff.sh <optional_commit>

## more verbose report:
../mathlib-ci/scripts/pr_summary/declarations_diff.sh long <optional_commit>

The doc-module for scripts/pr_summary/declarations_diff.sh in the mathlib-ci repository contains some details about this script.

Declarations diff (Lean)

Lean-aware diff — post-build, computed from the Lean environment (commit d223a56).

  • +0 new declarations
  • −0 removed declarations

No declaration differences.


No changes to strong technical debt.

No changes to weak technical debt.

Current commit d223a56548
Reference commit 383070160f

This script lives in the mathlib-ci repository. To run it locally, from your mathlib4 directory:

git clone https://github.com/leanprover-community/mathlib-ci.git ../mathlib-ci
../mathlib-ci/scripts/reporting/technical-debt-metrics.sh pr_summary
  • The relative value is the weighted sum of the differences with weight given by the inverse of the current value of the statistic.
  • The absolute value is the relative value divided by the total sum of the inverses of the current values (i.e. the weighted average of the differences).

@metakunt metakunt added the LLM-generated PRs with substantial input from LLMs - review accordingly label Jul 14, 2026
@metakunt

Copy link
Copy Markdown
Collaborator

Comment thread Counterexamples/GrothendieckPower.lean
Address review feedback: the docstrings referred to `Spec A`, but the
file works entirely on the algebra side and never uses
`AlgebraicGeometry.Spec`. Reword them to name the actual object (the
group object `op A` in `(CommAlgCat R)ᵒᵖ`) and explain the
identification with the affine group scheme, noting that Mathlib does
not yet connect commutative Hopf algebras to group objects in
`AlgebraicGeometry.Scheme`.
Comment thread Counterexamples/GrothendieckPower.lean Outdated
Comment on lines +331 to +335
noncomputable instance : IsScalarTower R B B where
smul_assoc r x y := by
change (r • x) * y = r • (x * y)
rw [Algebra.smul_def r x, Algebra.smul_def r (x * y)]
exact mul_assoc _ _ _

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread Counterexamples/GrothendieckPower.lean
Address review feedback: the hand-written `IsScalarTower R B B` (and,
it turns out, three more) are already provided by Mathlib. The `R B B`
and `R A A` towers follow from the general `IsScalarTower.right`, and
the `R B A` tower and `SMulCommClass R A A` follow from
`QuadraticAlgebra`'s component-wise instances. Only the explicit
`Algebra R A` construction is kept.

@riccardobrasca riccardobrasca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can ask your LLM to try to use grind as much as possible, it should simplify a couple of proofs.

Comment thread Counterexamples/GrothendieckPower.lean Outdated
change (algebraMap B A V) ^ 2 = algebraMap R A (a ^ 2) * algebraMap B A V
rw [← map_pow, V_relation, map_mul, IsScalarTower.algebraMap_apply R B A]

instance : Nontrivial B :=

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Various instances about QuadraticAlgebra should be available in general. For example we have QuadraticAlgebra.instNontrivial, so it is enough enough to add Nontrivial R.

Comment thread Counterexamples/GrothendieckPower.lean Outdated
simp only [hu₁, hu₂, hv₁, hb, h4]
ring_nf
simp only [hv₁, ha, hb, h4]
linear_combination

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does grind help here?

@riccardobrasca

riccardobrasca commented Jul 14, 2026

Copy link
Copy Markdown
Member

I think it makes sense to wait for #40500 to be merged, as then one can probably write a cleaner statement. Maybe making this PR depending on #40500 is a good idea?

cc @YaelDillies

Comment thread Counterexamples/GrothendieckPower.lean Outdated
Comment thread Counterexamples/GrothendieckPower.lean Outdated
Comment thread Counterexamples/GrothendieckPower.lean Outdated
Comment thread Counterexamples/GrothendieckPower.lean Outdated
Comment thread Counterexamples/GrothendieckPower.lean Outdated
Add `exists_hopfAlgebra_not_killed_by_finrank`, an existence statement
that spells out the negative answer to Grothendieck's question directly:
there is a nontrivial commutative ring and a commutative Hopf algebra,
free of finite rank, whose convolution power map at the exponent equal
to its rank is not the convolution unit.

Also address reviewer feedback:
* `reduce` is now a `RingHom` (`ZMod.castHom` directly) rather than an
  `AddMonoidHom`;
* clarify in the `aEnd`/`bEnd` docstrings that `a`, `b` are the two
  generators of the base ring;
* state `aEnd_bEnd_comm` as `Commute`;
* use hypothesis binders instead of `∀ ∈` in `generators_commute`;
* drop the hand-written `Nontrivial B`/`Nontrivial A` instances, which
  follow from `QuadraticAlgebra.instNontrivial` and `Nontrivial R`;
* make `ap`, `bp` abbreviations.
@mathlib-dependent-issues mathlib-dependent-issues Bot added the blocked-by-other-PR This PR depends on another PR (this label is automatically managed by a bot) label Jul 14, 2026
@mathlib-dependent-issues

Copy link
Copy Markdown

This PR/issue depends on:

@riccardobrasca

Copy link
Copy Markdown
Member

@j2d9w5xtjn-png can you please mark "resolved" the comments that are taken into account? Thanks!

Following riccardobrasca's review: definitions that are just an existing
object (`QuadraticAlgebra.omega`, an `algebraMap` image) are turned into
`abbrev`s, so no unfolding is needed. `a` and `b` are kept as `def`, since
making them reducible unfolds them to `Ideal.Quotient.mk baseIdeal _` and
prevents the `a_cube`/`b_cube`/`base_relation` simp lemmas from matching.
The now-redundant `rfl` in `algHom_ext` is removed.

@riccardobrasca riccardobrasca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have to stop now, I will finish the review later.

I am also thinking about a generalization of your construction, there is maybe a nice little construction here.

private theorem r_smul_mul (r : R) (x y : A) : r • x * y = r • (x * y) := by
ext <;> simp [V, aB, bB, pow_two]

noncomputable instance : Algebra R A :=

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already in mathlib as QuadraticAlgebra.instAlgebra. Having it here creates a diamond. I think you can just remove it and add

instance : IsScalarTower R B A :=
    IsScalarTower.of_algebraMap_eq (R := R) (S := B) (A := A) fun _ ↦ rfl


/-- The pointwise `n`-th power map of a monoid object in a cartesian monoidal category. For
a group scheme, this is the morphism `x ↦ xⁿ`, which is not in general a homomorphism. -/
def monPowMap {C : Type*} [Category C] [CartesianMonoidalCategory C] (M : C) [MonObj M] :

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can just use CategoryTheory.Hom.monoid and the usual power.

Comment on lines +638 to +641
calc
comulB aB = algebraMap R (A ⊗[R] A) a := comulB.commutes a
_ = a • (1 : A ⊗[R] A) := Algebra.algebraMap_eq_smul_one a
_ = aaT := aaT_smul.symm

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
calc
comulB aB = algebraMap R (A ⊗[R] A) a := comulB.commutes a
_ = a • (1 : A ⊗[R] A) := Algebra.algebraMap_eq_smul_one a
_ = aaT := aaT_smul.symm
rw [comulB.commutes, Algebra.algebraMap_eq_smul_one, ← aaT_smul]

Comment on lines +644 to +647
calc
comulB bB = algebraMap R (A ⊗[R] A) b := comulB.commutes b
_ = b • (1 : A ⊗[R] A) := Algebra.algebraMap_eq_smul_one b
_ = bbT := bbT_smul.symm

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
calc
comulB bB = algebraMap R (A ⊗[R] A) b := comulB.commutes b
_ = b • (1 : A ⊗[R] A) := Algebra.algebraMap_eq_smul_one b
_ = bbT := bbT_smul.symm
rw [comulB.commutes, Algebra.algebraMap_eq_smul_one, ← bbT_smul]

Comment on lines +664 to +677
have hc : comulB (-(bB ^ 2) * V) = -(bbT ^ 2) * deltaV := by
have hn : comulB (-(bB ^ 2)) = -(comulB bB ^ 2) := by
calc
comulB (-(bB ^ 2)) = -comulB (bB ^ 2) := comulB_neg _
_ = -(comulB bB ^ 2) := congr_arg Neg.neg comulB_bB_sq
calc
comulB (-(bB ^ 2) * V) = comulB (-(bB ^ 2)) * comulB V := comulB.map_mul _ _
_ = -(comulB bB ^ 2) * comulB V := by rw [hn]
_ = -(bbT ^ 2) * deltaV := by rw [comulB_bB, comulB_V]
have hl : comulB (aB * bB) = aaT * bbT := by
calc
comulB (aB * bB) = comulB aB * comulB bB := comulB.map_mul _ _
_ = aaT * bbT := by rw [comulB_aB, comulB_bB]
rw [hc, hl]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
have hc : comulB (-(bB ^ 2) * V) = -(bbT ^ 2) * deltaV := by
have hn : comulB (-(bB ^ 2)) = -(comulB bB ^ 2) := by
calc
comulB (-(bB ^ 2)) = -comulB (bB ^ 2) := comulB_neg _
_ = -(comulB bB ^ 2) := congr_arg Neg.neg comulB_bB_sq
calc
comulB (-(bB ^ 2) * V) = comulB (-(bB ^ 2)) * comulB V := comulB.map_mul _ _
_ = -(comulB bB ^ 2) * comulB V := by rw [hn]
_ = -(bbT ^ 2) * deltaV := by rw [comulB_bB, comulB_V]
have hl : comulB (aB * bB) = aaT * bbT := by
calc
comulB (aB * bB) = comulB aB * comulB bB := comulB.map_mul _ _
_ = aaT * bbT := by rw [comulB_aB, comulB_bB]
rw [hc, hl]
rw [map_mul, map_neg, map_pow, map_mul, comulB_aB, comulB_bB, comulB_V]

Comment on lines +720 to +723
calc
comul bA = algebraMap R (A ⊗[R] A) b := comul.commutes b
_ = b • (1 : A ⊗[R] A) := Algebra.algebraMap_eq_smul_one b
_ = bbT := bbT_smul.symm

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
calc
comul bA = algebraMap R (A ⊗[R] A) b := comul.commutes b
_ = b • (1 : A ⊗[R] A) := Algebra.algebraMap_eq_smul_one b
_ = bbT := bbT_smul.symm
rw [comul.commutes, Algebra.algebraMap_eq_smul_one, ← bbT_smul]

Comment on lines +726 to +729
have hone : left (1 : A) = 1 := left.map_one
unfold lambda l₁
simp only [map_mul, map_add]
rw [hone]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
have hone : left (1 : A) = 1 := left.map_one
unfold lambda l₁
simp only [map_mul, map_add]
rw [hone]
simp only [lambda, map_mul, map_add, map_one]

Comment on lines +732 to +735
have hone : right (1 : A) = 1 := right.map_one
unfold lambda l₂
simp only [map_mul, map_add]
rw [hone, right_aA, right_bA]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
have hone : right (1 : A) = 1 := right.map_one
unfold lambda l₂
simp only [map_mul, map_add]
rw [hone, right_aA, right_bA]
simp only [lambda, map_mul, map_add, map_one, right_aA, right_bA]

Comment on lines +738 to +743
rw [left_lambda, right_lambda]
have hone : comul (1 : A) = 1 := comul.map_one
unfold lambda
simp only [map_mul, map_add]
rw [hone, comul_aA, comul_bA, comul_U, comul_v]
exact delta_lambda

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
rw [left_lambda, right_lambda]
have hone : comul (1 : A) = 1 := comul.map_one
unfold lambda
simp only [map_mul, map_add]
rw [hone, comul_aA, comul_bA, comul_U, comul_v]
exact delta_lambda
rw [left_lambda, right_lambda]
simpa [lambda, map_mul, map_add, comul_aA, comul_bA, comul_U, comul_v] using delta_lambda

Comment on lines +937 to +941
@[simp] theorem powerMap_one_apply (x : A) : powerMap 1 x = x := by
calc
powerMap 1 x = universalPoint.ofConv x :=
congr_arg (fun f : WithConv (A →ₐ[R] A) ↦ f.ofConv x) (pow_one universalPoint)
_ = x := rfl

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@[simp] theorem powerMap_one_apply (x : A) : powerMap 1 x = x := by
calc
powerMap 1 x = universalPoint.ofConv x :=
congr_arg (fun f : WithConv (A →ₐ[R] A) ↦ f.ofConv x) (pow_one universalPoint)
_ = x := rfl
@[simp] theorem powerMap_one_apply (x : A) : powerMap 1 x = x :=
congr_arg (fun f : WithConv (A →ₐ[R] A) ↦ f.ofConv x) (pow_one universalPoint)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

blocked-by-other-PR This PR depends on another PR (this label is automatically managed by a bot) LLM-generated PRs with substantial input from LLMs - review accordingly new-contributor This PR was made by a contributor with at most 5 merged PRs. Welcome to the community!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants