Skip to content

Optional node set for the dominant-chamber fold and Borel–Weil–Bott - #8

Merged
pbelmans merged 6 commits into
mainfrom
levi-fold
Aug 13, 2026
Merged

Optional node set for the dominant-chamber fold and Borel–Weil–Bott#8
pbelmans merged 6 commits into
mainfrom
levi-fold

Conversation

@pbelmans

@pbelmans pbelmans commented Aug 12, 2026

Copy link
Copy Markdown
Member

Requested by HomogeneousTools/PartialFlagVarieties.jl#21: reflecting in only a subset S of the simple roots, so a weight can be folded into the dominant chamber of a Levi subgroup rather than of the whole group.

API

An optional trailing nodes argument, defaulting to nothing, which means all of them, on

  • conjugate_dominant_weight
  • conjugate_dominant_weight_with_elem
  • conjugate_dominant_weight_with_length
  • borel_weil_bott
  • is_singular

Everything routes through the two existing kernels _fold_dominant! and _fold_dominant_with_word!. They still scan 1:R and now test membership in nodes, rather than iterating over the node list. That matters for two reasons:

  • every index into the coordinate vector and the Cartan matrix still provably lies in range, so a caller-supplied node can never read past the end under @inbounds. Indexing a caller-supplied node list did exactly that: under the default --check-bounds=auto an out-of-range node silently returned a garbage weight, and only --check-bounds=yes — which Pkg.test() forces, so the suite is blind to it — threw. It is now an ArgumentError, checked once at the public boundary;
  • nodes may be any container supporting in: tuple, vector, range or Set. Duplicates are harmless.

nothing marks the full fold, and being a singleton type its membership test const-folds away, so there is one code path and the hot one is unchanged.

For borel_weil_bott the singularity test is restricted to nodes as well, which makes it the relative statement along G/B → G/P_I with nodes the nodes unmarked in I. Note ρ = ρ_G stays the right shift even in the restricted case, since ρ_G - ρ_S pairs to zero with every coroot in S and is therefore W_S-invariant; that is recorded in the docstring.

No regression on the default path

_fold_dominant! is the kernel every cohomology, dimension and Euler-characteristic call funnels through downstream, so the default path was measured, not assumed. 2000 random E₈ weights, minimum of a @benchmark:

min median
main 0.3145 ms 0.3492 ms
this branch, 4 runs 0.3141 – 0.3284 ms 0.3491 – 0.3525 ms

Straddles the main figure, and results are identical. The nodes === nothing test const-folds after inlining, as the comment on the kernel claims.

Tests

Full suite green, doctests green. 1000 new assertions in three testsets, over types A, B, C, D, G₂, F₄, E₆:

  • the restricted fold agrees with the same fold carried out inside the sub-root-system via sub_dynkin_type_with_ordering — the ground truth for the whole change;
  • the result is S-dominant, the fold is idempotent, the word from _with_elem lies in S, has length equal to _with_length, and replaying it reproduces the folded weight;
  • coordinates at nodes not adjacent to S are untouched;
  • restricted borel_weil_bott matches the absolute statement inside the sub-diagram, degree and weight, including agreement on when it vanishes;
  • any node container giving the same answer as a tuple, and an out-of-range node throwing from all five entry points;
  • is_singular(λ + ρ, S) against the ground truth of pairing λ + ρ with every positive root of the subsystem, and against borel_weil_bott(λ, S) === nothing, plus the implication that singular for S forces singular for G;
  • weights regular for G but singular for S and vice versa, and the degenerate empty node set.

is_singular restricted to nodes is exactly the vanishing criterion of the relative borel_weil_bott, and the tests pin those two against each other.

Follow-up, not in this PR

  • Once this is on main, PartialFlagVarieties.jl can delete its local _fold_dominant_in and call borel_weil_bott(λ, S) directly, and its Semisimple compat bound moves to the release carrying this.

@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

ℹ️ You can also turn on project coverage checks and project coverage reporting on Pull Request comment

Thanks for integrating Codecov - We've got you covered ☂️

Scanning 1:R and testing membership keeps every index into the coordinate
vector and the Cartan matrix provably in range, so an out-of-range node can no
longer read past the end under @inbounds, and any container supporting `in` is
accepted. `nothing` marks the full fold, whose membership test const-folds away.
Every fold goes through _fold_dominant! or _fold_dominant_with_word!, so
checking there rather than at each caller means a future entry point taking a
node set cannot reach a fold without the check. Free on the default path,
where the check specializes to nothing.
@pbelmans
pbelmans merged commit 75d6ead into main Aug 13, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant