Skip to content

Add MaximumClique<SimpleGraph, One> variant with weight cast and reductions#1055

Merged
GiggleLiu merged 5 commits intomainfrom
bmf-biclique-cover
Apr 21, 2026
Merged

Add MaximumClique<SimpleGraph, One> variant with weight cast and reductions#1055
GiggleLiu merged 5 commits intomainfrom
bmf-biclique-cover

Conversation

@GiggleLiu
Copy link
Copy Markdown
Contributor

Summary

  • Register MaximumClique<SimpleGraph, One> variant so reduction paths from MIS<SimpleGraph, One> no longer require unnecessary weight promotion to i32 before reaching MaximumClique.
  • Add maximumclique_casts.rs covering the new One variant and ensure round-tripping from MIS to MaxClique works without weight promotion.
  • Consolidate three duplicate complement_edges implementations into graph_helpers::complement_edges (DRY).

Test plan

  • `make test` passes
  • `make clippy` reports no warnings
  • `pred path MaximumIndependentSet MaximumClique` resolves without forcing an `i32` detour for unit-weight inputs

…ctions

Register the One (unit weight) variant for MaximumClique so reduction paths
from MIS/SimpleGraph/One no longer require unnecessary weight promotion to
i32 before reaching MaxClique. Consolidate complement_edges into graph_helpers
to eliminate 3 duplicate copies (DRY).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@GiggleLiu
Copy link
Copy Markdown
Contributor Author

Agentic Review Report

Note: PR head (1e17e9df) was opened against ff8ae70e; origin/main has since advanced to 9ff62f0d (#1056). A rebase/merge of main will be needed before final merge.

Note: This PR is not tracked on the project board (no card in Review pool). Review was performed manually per explicit request; no board transitions were applied.

Structural Check

Rule Checklist

# Check Status
1 Rule file exists (src/rules/maximumclique_casts.rs) PASS
2 #[reduction(...)] macro present (via impl_variant_reduction!) PASS
3 ReductionResult impl (via ReductionAutoCast) PASS
4 ReduceTo impl present PASS
5 #[cfg(test)] mod tests #[path] link FAIL — no link in file
6 Test file src/unit_tests/rules/maximumclique_casts.rs FAIL — missing
7 Closed-loop test present FAIL
8 Registered in src/rules/mod.rs PASS (line 74)
9 Canonical rule example registered N/A — weight-cast rules follow the same no-example convention as maximumindependentset_casts.rs
10 Paper reduction-rule entry ACCEPTABLE — existing MIS↔MaxClique paper entries (docs/paper/reductions.typ lines 11103, 12694) cover both weight variants; cast edges are auto-filtered from the paper like existing MIS casts

Build / Test / Clippy

  • cargo build --lib: PASS
  • cargo clippy --lib --all-targets: PASS
  • cargo test --lib: FAIL — 1 failing test:
    • rules::analysis::tests::test_find_dominated_rules_returns_known_set
  • Directly-related tests (maximum_clique model tests, maximumclique_maximumindependentset, maximumindependentset_maximumclique, kcoloring_partitionintocliques): PASS.

Mathematical Correctness

  • maximumclique_casts.rs (<SimpleGraph,One> → <SimpleGraph,i32>): identity graph, weights cast One → 1i32. Reduction is weight-preserving, extract_solution is identity, witness round-trip verified on a worked K3 example. OK.
  • maximumclique_maximumindependentset.rs <One> branch (lines 67–73): takes the complement graph. On P5 (5 vertices, 4 edges), complement has 10 − 4 = 6 edges; identity extract maps clique config back to IS config. OK.
  • graph_helpers::complement_edges (new consolidated helper at src/rules/graph_helpers.rs:62-73): emits (u,v) for u<v with !graph.has_edge(u,v). For P4 (edges (0,1),(1,2),(2,3)) produces (0,2),(0,3),(1,3) — 3 edges = C(4,2) − 3. Correct.

Overhead Verification

  • maximumclique_casts.rs: identity overhead (num_vertices, num_edges). Preserves graph and vertex count. Exact.
  • Complement-graph rules (MC↔MIS and KColoring→PartitionIntoCliques): num_edges = "num_vertices*(num_vertices - 1)/2 - num_edges". Matches C(n,2) − m. Correct.

Blocker — B1 (CI-breaking)

rules::analysis::tests::test_find_dominated_rules_returns_known_set rejects the newly-registered edge MaximumClique<SimpleGraph,One> → MaximumClique<SimpleGraph,i32> in src/rules/maximumclique_casts.rs:12-18:

Unexpected dominated rule:
  MaximumClique {graph: "SimpleGraph", weight: "One"}
    -> MaximumClique {graph: "SimpleGraph", weight: "i32"}
  dominated by:
  MC<SG,One> -> MIS<SG,One> -> MIS<SG,i32> -> MC<SG,i32>

The path MC<SG,One> → MIS<SG,One> → MIS<SG,i32> → MC<SG,i32> already existed on this branch and dominates the new direct cast edge.

Fix options (in order of preference):

  • (a) Delete the cast edge in maximumclique_casts.rs (and consider deleting the now-empty file and its mod line). This preserves the stated PR goal — the <One> variant node, plus cast-free MIS paths — because the cast-less MC<SG,One>→MC<SG,i32> path is still reachable via MIS. Project convention per .claude/CLAUDE.md: "there is only one primitive reduction registration for each exact source/target variant pair."
  • (b) Allow-list the edge in src/unit_tests/rules/analysis.rs with justification. Less aligned with project policy.

Other Structural Issues

  • M1. Cast file has no #[cfg(test)] mod tests link. Consistent with existing maximumindependentset_casts.rs, but obsolete if B1 is fixed by deletion.
  • M2. No direct <One>-endpoint closed-loop tests for the two reduction variants at maximumclique_maximumindependentset.rs:67-73 and maximumindependentset_maximumclique.rs:67-73; coverage is incidental through the existing <i32> suite exercising the shared helper.

Verdict: NEEDS CHANGES (blocker B1).


Quality Check

Design Principles

  • DRY: PASS — three formerly-duplicated complement_edges call sites (kcoloring_partitionintocliques.rs, maximumclique_maximumindependentset.rs, maximumindependentset_maximumclique.rs) are all consolidated into a single helper graph_helpers::complement_edges (src/rules/graph_helpers.rs:62-73). Extracted reduce_clique_to_is/reduce_is_to_clique helpers factor out the body shared between i32 and One variants.
  • KISS: PASS — maximumclique_casts.rs (18 lines) mirrors the pattern in maximumindependentset_casts.rs. No unnecessary abstraction.
  • HC / LC: PASS — complement_edges lives in graph_helpers.rs alongside edges_to_cycle_order. Signature is clean.

Behavior Preservation of Refactor

All three prior complement_edges implementations were bit-identical: for u in 0..n { for v in (u+1)..n { if !graph.has_edge(u, v) { edges.push((u, v)); } } }. The unified helper copies this verbatim. Semantics preserved for all three call sites (kcoloring_partitionintocliques.rs:45, maximumclique_maximumindependentset.rs:39, maximumindependentset_maximumclique.rs:39).

HCI

  • pred path MaximumIndependentSet MaximumClique now resolves to a single-step direct path on the <SimpleGraph, One> endpoint — no i32 detour. Confirmed empirically. Primary stated PR goal achieved.
  • pred list shows MaximumClique/SimpleGraph/One as default (*) and MaximumClique/SimpleGraph/i32 as secondary, consistent with MaximumIndependentSet presentation.

Test Quality

  • Existing closed-loop tests for both MC↔MIS directions continue to exercise the refactored helper path via the <SimpleGraph, i32> endpoint.
  • Missing tests:
    • No closed-loop test for MaximumClique<SimpleGraph, One> → MaximumIndependentSet<SimpleGraph, One> (new reduction variant).
    • No closed-loop test for MaximumIndependentSet<SimpleGraph, One> → MaximumClique<SimpleGraph, One> (new reduction variant).
    • No test file for maximumclique_casts.rs (matches maximumindependentset_casts.rs precedent, but becomes moot if B1 is fixed by deletion).
  • Model-side: src/unit_tests/models/graph/maximum_clique.rs is not updated to exercise One-weighted evaluation/solving.

Issues

  • [important] Missing closed-loop tests for the two new <SimpleGraph, One> reduction endpoints (both directions). A 5-vertex path-graph test mirroring the existing i32 tests is sufficient.
  • [important] Missing model-level test covering the new default MaximumClique<SimpleGraph, One> variant with One weights.
  • [minor] reduce_clique_to_is / reduce_is_to_clique declare W: WeightElement + Clone + DefaultClone + Default are redundant since WeightElement: Clone + Default + 'static. Simplify to W: WeightElement. (maximumclique_maximumindependentset.rs:36, maximumindependentset_maximumclique.rs:36.)
  • [minor] src/rules/kcoloring_partitionintocliques.rs:32 places the use super::graph_helpers::complement_edges; below the impl ReductionResult block rather than grouping with the other use statements at the top.
  • [nit] Consider making complement_edges generic over G: Graph for consistency with edges_to_cycle_order; all current callers pass &SimpleGraph so no immediate functional gain.

Agentic Feature Tests

Run inline by review-pipeline after the dedicated subagent exited without a final report.

# Command Result
1 cargo build -p problemreductions-cli --bin pred PASS
2 pred list | grep -i clique PASSMaximumClique/SimpleGraph/One * listed as default, MaximumClique/SimpleGraph/i32 shown as secondary
3 pred show MaximumClique PASS — shows the new default variant; outgoing reductions → MaximumIndependentSet/SimpleGraph/One and → MaximumClique/SimpleGraph/i32; incoming MaximumIndependentSet/SimpleGraph/One →
4a pred path MaximumIndependentSet MaximumClique PASS — 1-step path MIS/SG/One → MaximumClique/SG/One; no i32 detour
4b pred path MaximumClique MaximumIndependentSet PASS — 1-step path MaximumClique/SG/One → MIS/SG/One; no i32 detour
5 pred create --example MaximumClique FAIL — No canonical model example exists for MaximumClique/SimpleGraph/One. Pre-existing gap, not a regression: no MaximumClique example exists in src/example_db/model_builders.rs on main either (empty grep). Worth filing separately.
6 pred create MaximumClique --graph 0-1,1-2,2-3,3-4,4-0 --num-vertices 5 --weights 1,1,1,1,1 PASS — created instance, weight: "One" selected automatically
7 pred solve /tmp/mc5.json PASS — solution [1,0,0,0,1] (max clique of size 2 on 5-cycle; correct — no triangles in C5)

Assessment. CLI-facing functionality works as advertised: the new <One> variant becomes the default for MaximumClique, and reduction paths between MIS and MaxClique now stay in unit-weight without the i32 promotion detour. One pre-existing gap (no canonical example for MaximumClique in example_db) surfaced during testing but is unrelated to this PR.


Combined Verdict

  • Blocker: B1 — cargo test --lib fails on rules::analysis::tests::test_find_dominated_rules_returns_known_set because the new cast edge MaximumClique<SG,One> → MaximumClique<SG,i32> is dominated by the existing MC→MIS→MIS→MC path. Preferred fix: delete the cast edge (and likely the now-empty maximumclique_casts.rs). The <One> variant plus cast-free MIS paths are preserved.
  • Important: Add closed-loop tests for the two new <SimpleGraph, One> MC↔MIS reduction endpoints and a model-level test for MaximumClique<SG,One>.
  • Minor / nit: redundant trait bounds, use placement, possible generalization of complement_edges, pre-existing lack of canonical MaximumClique example.
  • Good: DRY consolidation of complement_edges is clean and behavior-preserving; HCI goal (no i32 detour for MIS↔MaxClique on unit weights) is confirmed.

Generated by review-pipeline (run manually — PR is not on the project board).

GiggleLiu and others added 2 commits April 21, 2026 21:10
The `MaximumClique<SG,One> → MaximumClique<SG,i32>` direct cast is
dominated by the existing `MC<SG,One> → MIS<SG,One> → MIS<SG,i32>
→ MC<SG,i32>` path, which the redundancy-sanity test flags in
`rules::analysis::tests::test_find_dominated_rules_returns_known_set`.
Remove the cast entirely (and its now-empty `maximumclique_casts.rs`);
the cast-less `<One> → <i32>` path is still reachable via MIS, so
`pred path MaximumIndependentSet MaximumClique` stays on `One` without
the `i32` detour.

Also:
- add `<One>` closed-loop tests for both MC↔MIS reduction directions
  and a `MaximumClique<SG,One>` model-level evaluate/solve test,
- drop the redundant `Clone + Default` bounds on
  `reduce_clique_to_is`/`reduce_is_to_clique` (already implied by
  `WeightElement`),
- move the stray `use super::graph_helpers::complement_edges;` in
  `kcoloring_partitionintocliques.rs` up with the other imports.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The test `canonical_rule_examples_cover_exactly_authored_direct_reductions`
requires every registered `#[reduction]` edge to have a matching
canonical `RuleExampleSpec`. The new `<SimpleGraph, One>` edges for
`MaximumClique ↔ MaximumIndependentSet` had no corresponding example
entries, so the test failed in CI (Code Coverage + Test jobs).

Add parallel `_one` variants of the existing i32 examples, reusing the
same P4/P5 graph shapes and solutions (the target configs are identical
because the reduction is vertex-identity).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 21, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.92%. Comparing base (9ff62f0) to head (59982df).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1055   +/-   ##
=======================================
  Coverage   97.92%   97.92%           
=======================================
  Files         966      966           
  Lines       99972   100043   +71     
=======================================
+ Hits        97896    97967   +71     
  Misses       2076     2076           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

GiggleLiu and others added 2 commits April 21, 2026 22:38
`canonical_rule_examples_cover_exactly_authored_direct_reductions`
requires one `RuleExampleSpec` per `#[reduction]` edge, so we now have
i32 and One examples for both MC↔MIS directions. But the paper's
`load-example("MaximumIndependentSet", "MaximumClique")` and
`load-example("MaximumClique", "MaximumIndependentSet")` calls with no
variant filter become ambiguous and the paper build panics in CI's
Build paper step.

Pin both direct `load-example` calls and the matching `reduction-rule`
`example-*-variant` kwargs to `(graph: "SimpleGraph", weight: "i32")`
to preserve the pre-PR behavior (i32 was the only example before).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@GiggleLiu GiggleLiu merged commit b3b18f1 into main Apr 21, 2026
5 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