Build-verified attempt to port the Java EuclideanCyclicConvergenceTest (cathead, "circular hole edge" φ = π−0.1). - ✅ GREEN `CyclicCircularEdge_PhiEntersGradient_CatHead`: solver-free cross-validation that the circular-edge φ target enters the cyclic edge gradient exactly (ΔG_e = −Δφ_e at 1e-12; no other component moves). - ⏸️ DISABLED `CyclicCircularEdge_CatHead_JavaXVal`: the full Java convergence assertion (α_opp+α_opp = π−0.1), kept with golden semantics. Auto-activates once the edge-DOF Hessian lands. Build-verification finding: `newton_euclidean` -> `euclidean_hessian` throws "edge DOFs are not supported" — the cyclic full solve is blocked by a missing edge-DOF Euclidean Hessian (gradient supports edge DOFs, analytic Hessian does not). Spherical convergence (Tier-1 #2) is already covered by test_newton_solver. Documented in doc/reviewer/java-ignore-crossvalidation.md. All 13 EuclideanFunctional tests pass (1 disabled). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
191 lines
12 KiB
Markdown
191 lines
12 KiB
Markdown
# Cross-validation potential of the Java `@Ignore`d tests
|
||
|
||
> **Purpose.** The upstream Java library (`de.varylab.discreteconformal`) has
|
||
> 22 test files with `@Ignore`d tests. This document classifies them by *why*
|
||
> they are ignored and by their *cross-validation value for the C++ port*, so
|
||
> that the highest-value golden oracles get ported first.
|
||
>
|
||
> **Created:** 2026-05-29 (external-reviewer pass). See also
|
||
> `doc/reviewer/java-port-audit.md` and PR #27 (`tests/java-golden-oracles`).
|
||
|
||
---
|
||
|
||
## 1 — Two root causes for `@Ignore`
|
||
|
||
| Cause | Count | Meaning for the C++ port |
|
||
|---|---|---|
|
||
| **`requires ARM64 PETSc native lib`** (class-level) | 15 files | **Not a logic problem.** Java solves via PETSc/TAO (native lib) which does not run on ARM64. The C++ port uses **Eigen** (no PETSc) and *can* run these scenarios — **iff** the feature is ported **and** the Java test carries a hard-coded expected value. |
|
||
| **Logic / known-issue** (method-level) | ~8 methods | Mostly mark **Java gaps** (no Hessian, layout unfinished) or **ARM64 FP flakiness**. Usually **not** reliable oracles. |
|
||
|
||
A critical distinction: PR #27 cross-validates **functional evaluations**
|
||
(energy/gradient — no solver, so no PETSc needed). The **full-solve** golden
|
||
values exist **only** as hard-coded vectors recorded from a historical x86
|
||
PETSc run — and those live exclusively in `HyperIdealConvergenceTest`.
|
||
|
||
---
|
||
|
||
## 2 — Already locked by PR #27 (do not duplicate)
|
||
|
||
`tests/java-golden-oracles` pins, bit-for-bit (1e-12), against compiled Java:
|
||
- `HyperIdealGoldenJava` — Clausen/Л/ImLi₂, ζ₁₃/₁₄/₁₅/ζ, both tetrahedron-volume formulas.
|
||
- `EuclideanGoldenJava` / `SphericalGoldenJava` — angle formulas, β relations, Л energy terms, **small full-mesh oracles** on a tetrahedron (gradient `Θ−Σα`, `ΔE = E(x)−E(0)`).
|
||
- `SphericalGoldenJava.FullMeshEdgeDofGradient` — edge-DOF gradient.
|
||
- `PeriodMatrix.NormalizeModulus_GoldenJava` — τ-reduction fold convention.
|
||
|
||
These cover the **unit math cores** and **functional evaluation**. They do
|
||
**not** cover **solver/convergence** or **full uniformization**.
|
||
|
||
---
|
||
|
||
## 3 — Priority ranking for new cross-validation
|
||
|
||
### 🟢 HIGH — real golden oracle, feature already in C++
|
||
|
||
| Item | Java source | Oracle | Blocker / effort |
|
||
|---|---|---|---|
|
||
| **HyperIdeal Lawson convergence** | `HyperIdealConvergenceTest.testHyperIdealConvergence` | **hard-coded golden u\*** (perfectly symmetric — robust to DOF order) | needs a **low-level half-edge generator** (`make_lawson_square_tiled`); CGAL `add_face` cannot build it (multi-edges, see §5). Effort: medium (1–2 d). |
|
||
|
||
Golden solution (Lawson square-tiled, BLMVM, tol 1e-10), 22 DOFs:
|
||
```
|
||
vertices (×4, θ=2π) : 1.1462158341786262
|
||
edges (×12, θ=π/2) : 1.7627471737467797 / …7866 (symmetric pair)
|
||
edges (×6, θ=π aux): 2.633915794495759
|
||
```
|
||
Assertion strategy: because the values are symmetric per DOF-class, assert
|
||
*per class* (every vertex DOF ≈ 1.14621…, every π/2-edge ≈ 1.76274…, every
|
||
π-edge ≈ 2.63391…) to 1e-6 — **no DOF-order fidelity required**.
|
||
|
||
### 🟡 MEDIUM — golden/strong oracle, needs asset or near-term phase
|
||
|
||
| Item | Java source | Oracle | Blocker |
|
||
|---|---|---|---|
|
||
| **Genus-1 uniformization** | `UniformizerTest.testGenus1` (Wente, 1240 V) | angle-sum = 2π + vertex count (self-consistency) | needs `wente.obj` asset + a "load OBJ → uniformize" path; C++ Euclidean solver exists. |
|
||
| **HyperIdeal Lawson + branch points** | `…WithBranchPoints` | hard-coded golden u\* (near-symmetric — DOF order matters more) | same generator as HIGH + branch-point variant. |
|
||
| **HyperIdeal layout** | `HyperIdealLayoutTest` | layout positions | needs the generator + `layout.hpp` hyper-ideal path exercised. |
|
||
| **Euclidean big-model scale** | `EuclideanUnwrapperPetscTest.testStaticUnwrapBigModel` | mostly self-check | scale/robustness cross-check; low oracle strength. |
|
||
|
||
### 🔵 LATER — feature not yet in C++ (Phase 9d.2 / 10c / 13 / 11)
|
||
|
||
| Item | Java source | Maps to |
|
||
|---|---|---|
|
||
| Genus-2 uniformization | `UniformizerTest.testGenus2` (Lawson 2498) | Phase 10c / 13 |
|
||
| HyperIdeal hyperelliptic convergence | `…HyperEllipticCurveLawson` (has golden u\*) | Phase 13 |
|
||
| Hyperbolic disk uniformization | `HyperbolicDiskUniformizationTest` | Phase 10c (gated on holonomy bug) |
|
||
| Möbius centring (grad/Hessian/convergence golden) | `MobiusCenteringFunctionalTest` | Phase 9d.4 |
|
||
| Quasi-isothermic suite (SinCondition, SNES, Utility, Layout, ConformalStructure) | `…quasiisothermic.*` | Phase 10e |
|
||
| Schottky uniformisation | `SchottkyUtilityTest` | Phase 11a |
|
||
| Circle-domain (multiply-connected) | `CircleDomainUnwrapperTest` | Phase 11c |
|
||
| Electrostatic-sphere baseline | `ElectrostaticSphereFunctionalTest` | Phase 10c′ (optional) |
|
||
|
||
### ⚪ NON-ORACLE — do **not** port as cross-validation
|
||
|
||
| Item | Why it is not an oracle |
|
||
|---|---|
|
||
| `HyperIdealFunctionalTest.testHessian` (`@Ignore@Override`, empty) | Java has **no** HyperIdeal Hessian (`hasHessian()==false`). C++ *adds* it (block-FD, Phase 9b) → validate against C++ FD, not Java. Documents the C++ delta. |
|
||
| `ElectrostaticSphereFunctionalTest.testHessian` | same — Hessian not implemented in Java. |
|
||
| `HyperbolicLayoutTest.testDoLayout` | throws `"Not implemented correctly yet!"` — **Java itself unfinished**; no reference to validate against. |
|
||
| `SurfaceCurveUtilityTest.testCreateSurfaceCurves` | known issue: non-deterministic edge count on ARM64 — **flaky**, not a stable oracle. |
|
||
| `HyperbolicCyclicConvergenceTest.testEuclideanConvergence` | known issue: ARM64 FP accumulation, angle sum outside 1e-8 — **flaky**. |
|
||
| `HyperIdealUtilityTest.testZeta13` | asserts ζ₁₃(0.1,0.1,0.1)=0.1, which looks **wrong**; the other volume/ζ tests already run and are ported. Verify the correct value before any use. |
|
||
| `HyperIdealPluginTest` | plugin/TAO-application wiring, not pure math. |
|
||
| `TwoHoleExample.testLetterB` | demo/example, no assertion of record. |
|
||
| `SphericalUnwrapperTest` PETSc variants | the **MTJ** variants (not ignored) already cover the same cases on `cathead`. |
|
||
|
||
---
|
||
|
||
## 3b — Effort-adjusted tiering (2026-05-29 inventory)
|
||
|
||
> A broader scan (not just `@Ignore`d tests) revealed that the §3 ranking was
|
||
> **effort-blind**: cheaper, equally-valuable oracles exist than the Lawson
|
||
> generator. Re-tiered by **value / cost**:
|
||
|
||
| Tier | Oracle | Mesh / asset | Solver | Golden | C++ status | Cost |
|
||
|---|---|---|---|---|---|---|
|
||
| **1** | `EuclideanCyclicConvergenceTest` | `cathead.obj` *(already in C++)* | MTJ BiCGstab (no PETSc) | `α_opp+α_opp = π−0.1` @1e-12 (per-edge φ target) | `euclidean_functional` ✅, `phi_e` ✅, cathead ✅ | **near-zero** |
|
||
| **1** | `SphericalConvergenceTest` | octahedron | MTJ Newton (no PETSc) | self-consistency (const. curvature) | spherical ✅, `make_octahedron_face` ✅ | low |
|
||
| **2** | Wente genus-1 uniformization | `wente_torus02.obj` + `wente_uniformization.xml` | — (stored result) | exact `IsometryPSL2R` uniformizing-group generators | holonomy/`MobiusMap` ✅; **needs XML reader** | medium |
|
||
| **2** | `regular_uniformization.xml` | (stored) | — | uniformization data | needs XML reader | medium |
|
||
| **3** | HyperIdeal Lawson convergence (3 golden vectors) | combinatorial `createLawsonSquareTiled` | — (hard-coded u\*) | symmetric u\* | needs **low-level half-edge generator** (§5) | high |
|
||
| **4** | genus-2 (`genus2.xml`/`lawson2498.obj`), holomorphic forms (`HolomorphicEuclideanUniformization_*.xml`), Schottky (`genus2.xml`), hyperelliptic | assets present in Java | — | various | Phases 10a/10c/11/13 | future |
|
||
|
||
**Key correction:** the Lawson generator (originally flagged HIGH) is actually
|
||
**Tier 3** — higher effort than Tier 1/2. Cheapest first wins:
|
||
|
||
1. **Tier 1 — `EuclideanCyclicConvergenceTest` on cathead** (asset already
|
||
present; the C++ edge gradient `G_e = α_opp(f⁺)+α_opp(f⁻) − φ_e` makes the
|
||
Java assertion `α_opp+α_opp = π−0.1` exactly the converged `G_e = 0`
|
||
condition with `phi_e = π−0.1`). Fails if the solver ignores a non-default
|
||
`φ`, so it is a genuine check, not a tautology.
|
||
2. **Tier 1 — `SphericalConvergenceTest`** on the octahedron.
|
||
3. **Tier 2 — Wente genus-1 uniformization** (needs a small `UniformizationData`
|
||
XML reader; strongest deterministic pipeline oracle that maps to landed C++).
|
||
4. **Tier 3 — Lawson generator** (only after Tiers 1–2).
|
||
|
||
### Build-verification finding (2026-05-29) — Tier 1 cyclic is blocked
|
||
|
||
Attempting the Tier-1 `EuclideanCyclicConvergenceTest` port **build-verified** a
|
||
blocker: `newton_euclidean` calls `euclidean_hessian`, which throws
|
||
*"edge DOFs are not supported (only the vertex-block cotangent Laplacian is
|
||
implemented)"*. The cyclic functional needs **vertex + edge** DOFs, so the full
|
||
Newton solve is **not yet possible** in C++ — the *gradient* supports edge DOFs,
|
||
the *analytic Hessian* does not. (This is also why PR #27 cross-validated only
|
||
the cyclic *evaluation*, never a solve.)
|
||
|
||
**Landed in this PR instead** (`test_euclidean_functional.cpp`):
|
||
- ✅ `CyclicCircularEdge_PhiEntersGradient_CatHead` (**GREEN**) — solver-free
|
||
cross-validation that the circular-edge φ target enters the cyclic gradient
|
||
exactly (`ΔG_e = −Δφ_e` at 1e-12, no other component moves). This is the
|
||
evaluation-level prerequisite of the convergence oracle.
|
||
- ⏸️ `DISABLED_CyclicCircularEdge_CatHead_JavaXVal` — the full Java convergence
|
||
assertion (`α_opp+α_opp = π−0.1`), kept in-code with the golden semantics; it
|
||
auto-activates (drop `DISABLED_`) once the edge-DOF Hessian lands.
|
||
|
||
**New prerequisite for Tier-1 cyclic:** an **edge-DOF Euclidean Hessian** (the
|
||
cyclic Hessian over vertex + edge variables, cf. Java `getNonZeroPattern`). Spherical
|
||
convergence (Tier-1 #2) turned out to be **already covered** by
|
||
`test_newton_solver` (`Spherical_ConvergesFromPerturbation` et al. on the
|
||
spherical tetrahedron), and `make_octahedron_face()` is a single face, not a
|
||
closed octahedron — so Tier-1 #2 adds little. → the next genuinely-new
|
||
cross-validation target is **Tier 2 (Wente uniformization XML)** or implementing
|
||
the edge-DOF Hessian to unblock the cyclic convergence oracle.
|
||
|
||
### Other generators in the Java tree
|
||
`HyperellipticCurveGenerator` (→ Phase 13), `SchottkyGenerator` (→ Phase 11a),
|
||
`FunctionalTest.createOctahedron/createTetrahedron` (trivial — C++ has
|
||
`make_octahedron_face` / `make_tetrahedron`).
|
||
|
||
---
|
||
|
||
## 4 — Recommended order of work
|
||
|
||
1. **Port `make_lawson_square_tiled()`** (low-level half-edge; see §5) →
|
||
unblocks the single HIGH oracle and the MED branch-point variant in one go.
|
||
2. Add `HyperIdealLawsonGoldenJava` test using the **per-class symmetric**
|
||
assertion above (robust, no DOF-order matching).
|
||
3. Add `wente.obj` asset → genus-1 uniformization self-consistency (MED).
|
||
4. Defer LATER items to their phases; revisit golden vectors then
|
||
(branch-point and hyperelliptic golden u\* are already recorded in the
|
||
Java tests and can be reused verbatim once the generator exists).
|
||
|
||
---
|
||
|
||
## 5 — Why the Lawson mesh needs a low-level generator
|
||
|
||
`HyperIdealGenerator.createLawsonSquareTiledBase()` builds a **genus-2**
|
||
surface with **4 vertices and 12 edges** (24 half-edges), then triangulates
|
||
6 quad faces (adding 6 diagonal "aux" edges, θ=π; the 12 originals get θ=π/2).
|
||
|
||
With only 4 vertices and 12 edges, **most vertex pairs carry more than one
|
||
edge** (multi-edges). CGAL `Surface_mesh::add_face` and polygon-soup builders
|
||
key edges by their endpoint vertex pair and therefore **cannot represent
|
||
multi-edges** — they would either fail or glue the surface into the wrong
|
||
topology. Java sidesteps this with explicit half-edge IDs and
|
||
`linkOppositeEdge` / `linkNextEdge`.
|
||
|
||
The C++ port must replicate this with the **low-level half-edge API**
|
||
(`add_vertex`, `add_edge`, and explicit `set_next` / `set_target` /
|
||
`set_face` connectivity), mirroring the exact opposite/next links from
|
||
`createLawsonSquareTiledBase()` (edges 0–23). The symmetric golden vector
|
||
then makes the resulting test robust even though CGAL's DOF ordering differs
|
||
from Java's.
|