Skip to content

Redefine BMF as exact factorization; fix BicliqueCover semantics; add BMF → BicliqueCover#1056

Open
GiggleLiu wants to merge 2 commits intomainfrom
bmf-exact-biclique-cover
Open

Redefine BMF as exact factorization; fix BicliqueCover semantics; add BMF → BicliqueCover#1056
GiggleLiu wants to merge 2 commits intomainfrom
bmf-exact-biclique-cover

Conversation

@GiggleLiu
Copy link
Copy Markdown
Contributor

@GiggleLiu GiggleLiu commented Apr 18, 2026

Summary

Two aligned changes; the second only works after the first.

Change 1 — Redefine BMF from approximate factorization (minimize Hamming distance, every config feasible) to exact factorization: infeasible when B ⊙ C ≠ A, else minimize |B|_1 + |C|_1 (total factor size). Matches the classical problem (Monson–Pullman–Rees 1995) and restores the Boolean-rank interpretation.

  • Update BMF → ILP to the equality-constrained formulation: drop error variables e_{i,j}, pin w_{i,j} = A_{i,j}, change objective to min Σ b_{i,r} + Σ c_{r,j}. Overhead shrinks by m·n variables and m·n constraints.
  • Fix the pre-existing BMF canonical example: the committed optimal_config was not actually an exact factorization (verified by hand: Hamming distance 2). Replaced with a genuine exact factorization that makes test_bmf_paper_example and model_specs_are_optimal consistent.

Change 2 — Fix BicliqueCover semantics to the classical sub-biclique form, then add the trivial BMF → BicliqueCover reduction.

  • is_valid_cover now also requires every biclique's L_b × R_b ⊆ E(G). Previously the code only checked edge coverage — the OR-cover variant — which disagreed with the struct's docstring and with the paper's ILP constraint x_{l,b} + y_{r,b} ≤ 1 for non-edges (the paper was already describing the stronger form; the code was underconstrained).
  • BicliqueCover → ILP now emits the matching non-edge constraint.
  • Canonical BicliqueCover example switched from the OR-cover optimum (total size 5) to the correct sub-biclique optimum (total size 6), matching the paper's worked example.
  • New BMF → BicliqueCover reduction: matrix-to-biadjacency + rank passthrough, with extract_solution transposing the right-vertex half from vertex-major to biclique-row-major. Trivial under the fixed semantics.
  • Paper updated: BicliqueCover problem-def now states the sub-biclique requirement explicitly; new reduction-rule("BMF", "BicliqueCover") entry added.

Julia parity fixtures dropped for both BMF (old Hamming-distance semantics) and BicliqueCover (Julia ProblemReductions package has the same OR-cover bug — its is_biclique only checks non-emptiness). The corresponding Rust parity tests are removed and the Julia generator has notes explaining the divergence. The upstream Julia package will need the same fix separately.

Test plan

  • cargo build --lib clean
  • cargo clippy --all-targets -- -D warnings clean
  • cargo test --lib — 4951 pass
  • cargo test --lib --features example-db — 5050 pass (includes model_specs_are_self_consistent and model_specs_are_optimal for the updated canonical specs)
  • cargo test --test main — 75 integration tests pass
  • make export-schemas and make paper rebuild cleanly
  • End-to-end: pred path BMF BicliqueCover returns a 1-hop path; pred create --example BMFpred evaluate gives Min(8) for the exact config and Min(None) for infeasible configs

🤖 Generated with Claude Code

The Rust BMF model previously minimized Hamming distance between A and B*C
(approximate factorization). This redefines it to the classical exact form:
feasible iff B*C = A, infeasible otherwise, with objective = total number of
1s in B and C (Monson-Pullman-Rees 1995).

Model changes (src/models/algebraic/bmf.rs):
- evaluate() returns Min(None) when B*C != A, else Min(Some(|B|_1 + |C|_1))
- Add total_factor_size() helper
- Fix canonical example: the previous optimal_config was not actually exact
  (verified by hand: Hamming distance 2, not 0). New config is a true exact
  factorization with total factor size 8.

BMF -> ILP reduction (src/rules/bmf_ilp.rs):
- Drop error variables e_{i,j} and their |A - w| inequalities
- Pin w_{i,j} = A_{i,j} (exact reconstruction)
- Objective changes from sum e_{i,j} to sum b_{i,r} + sum c_{r,j}
- Overhead shrinks: num_vars drops by m*n, num_constraints drops by m*n

BMF -> BicliqueCover reduction intentionally NOT added: the codebase's
BicliqueCover is the OR-cover variant (allows bicliques to cover non-edges),
which is strictly weaker than exact BMF. A closed-loop reduction would
extract invalid (non-exact) BMF configs. The classical equivalence with
biclique cover requires the stronger "sub-biclique-of-G" definition that
BicliqueCover does not currently enforce.

Julia parity fixture for BMF is removed (tests/data/jl/bmf.json) — the old
file encoded Hamming-distance semantics that no longer apply. Related
generator code in scripts/jl/generate_testdata.jl is commented out with a
note explaining the semantics change.

Paper (docs/paper/reductions.typ) is updated: BMF problem definition now
states exact factorization and |B|_1 + |C|_1 objective; BMF -> ILP rule
replaces the error-variable construction with the equality-constrained
formulation. Mentions the Boolean rank / biclique cover number equivalence
in the Extra Remark section.

Two incidental cargo fmt cleanups are included in
partition_into_paths_of_length_2.rs, maximumindependentset_triangular.rs,
and reduction_graph.rs.

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

codecov bot commented Apr 18, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.92%. Comparing base (ff8ae70) to head (3a37e70).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1056   +/-   ##
=======================================
  Coverage   97.92%   97.92%           
=======================================
  Files         964      966    +2     
  Lines       99872    99933   +61     
=======================================
+ Hits        97796    97857   +61     
  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.

BicliqueCover's `is_valid_cover` previously checked only that every graph
edge is covered by some biclique — it did not forbid a biclique from
containing a non-edge of G. That's the OR-cover / cover-by-rectangles
variant, which disagrees with the docstring (and with the textbook
definition). It's also why the earlier attempt at BMF → BicliqueCover was
unsound: a 2×2 identity at rank 1 was infeasible for exact BMF but
"feasible" for OR-cover via the K_{2,2} pseudo-biclique.

Changes:

- `BicliqueCover::is_valid_cover` now also requires every biclique's
  `L_b × R_b` to be a subset of E(G). This aligns implementation with the
  docstring and with the paper's constraint `x_{l,b} + y_{r,b} ≤ 1 for
  non-edges` (which the paper already described but the code didn't
  enforce).

- `BicliqueCover → ILP` adds the `x + y ≤ 1` constraint for every non-edge
  and every biclique, matching the paper.

- `test_biclique_problem` updated: `[1,1,1,1]` on a graph with only edge
  (0,0) now evaluates to `Min(None)` (it's a pseudo-biclique covering
  non-edges).

- Canonical BicliqueCover example switched from the OR-cover optimum
  (total size 5) to the correct sub-biclique optimum (total size 6),
  matching the paper's worked example exactly.

- Julia parity fixture `tests/data/jl/biclique_cover.json` and its Rust
  parity test are dropped; the Julia package (Go6Cf) has the same
  OR-cover bug so its fixture would disagree with the fixed Rust
  semantics. Generator note explains the divergence.

- New `BMF → BicliqueCover` reduction: matrix-to-biadjacency, rank
  passthrough, with `extract_solution` transposing the right-vertex half
  from vertex-major to biclique-row-major. Verified by closed-loop tests
  on all-ones rank-1, identity rank-2, and an infeasibility test on
  identity rank-1 (both problems now infeasible, consistent).

- Paper updated: BicliqueCover problem-def now states the sub-biclique
  requirement explicitly; new `reduction-rule("BMF", "BicliqueCover")`
  entry added with the Monson–Pullman–Rees equivalence and the variable
  layout transpose.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@GiggleLiu GiggleLiu changed the title Redefine BMF as exact Boolean matrix factorization Redefine BMF as exact factorization; fix BicliqueCover semantics; add BMF → BicliqueCover Apr 18, 2026
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