diff --git a/doc/reviewer/java-ignore-crossvalidation.md b/doc/reviewer/java-ignore-crossvalidation.md new file mode 100644 index 0000000..3ace6fc --- /dev/null +++ b/doc/reviewer/java-ignore-crossvalidation.md @@ -0,0 +1,127 @@ +# 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`. | + +--- + +## 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.