Skip to content

Fix #129: Add MultivariateQuadratic model#594

Open
isPANN wants to merge 10 commits intomainfrom
issue-129-multivariate-quadratic
Open

Fix #129: Add MultivariateQuadratic model#594
isPANN wants to merge 10 commits intomainfrom
issue-129-multivariate-quadratic

Conversation

@isPANN
Copy link
Collaborator

@isPANN isPANN commented Mar 12, 2026

Summary

  • Add MultivariateQuadratic satisfaction problem model (system of quadratic polynomial equations over finite field F_q)
  • Core problem in post-quantum cryptography and algebraic cryptanalysis

Fixes #129

@codecov
Copy link

codecov bot commented Mar 12, 2026

Codecov Report

❌ Patch coverage is 98.13665% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 96.78%. Comparing base (63bbdf9) to head (fd3ab91).
⚠️ Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
src/models/algebraic/multivariate_quadratic.rs 91.89% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #594      +/-   ##
==========================================
+ Coverage   96.72%   96.78%   +0.05%     
==========================================
  Files         224      228       +4     
  Lines       29867    30080     +213     
==========================================
+ Hits        28890    29113     +223     
+ Misses        977      967      -10     

☔ 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.

isPANN and others added 2 commits March 12, 2026 19:49
@isPANN
Copy link
Collaborator Author

isPANN commented Mar 12, 2026

Implementation Summary

Changes

  • src/models/algebraic/multivariate_quadratic.rs — Core model: MultivariateQuadratic struct + QuadraticPoly polynomial representation, Problem (Metric=bool) + SatisfactionProblem trait impls, finite field arithmetic (mod q)
  • src/unit_tests/models/algebraic/multivariate_quadratic.rs — 8 unit tests: F_2 evaluation (YES/NO instances from issue), F_3 larger field, brute-force solving, serialization round-trip, empty equations
  • src/models/algebraic/mod.rs, src/models/mod.rs — Module registration and re-exports
  • problemreductions-cli/src/dispatch.rs — CLI deserialization/serialization dispatch
  • problemreductions-cli/src/problem_name.rs — "MQ" alias
  • problemreductions-cli/src/commands/create.rs — Excluded from CLI create (complex equation input, like CircuitSAT)
  • docs/src/reductions/problem_schemas.json — Regenerated with new schema

Deviations from Plan

  • None

Open Questions

  • None

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a new MultivariateQuadratic (MQ) problem model — a system of quadratic polynomial equations over a finite field F_q — to the problem reductions library. The MQ problem is fundamental in post-quantum cryptography and is NP-complete over F_2. The implementation follows the existing codebase patterns for model registration, CLI integration, and testing.

Changes:

  • New MultivariateQuadratic and QuadraticPoly types with evaluate logic, Problem/SatisfactionProblem trait implementations, schema registration, and variant declaration.
  • CLI integration: dispatch for load/serialize, alias registration (MQ), and explicit bail for CLI creation (complex input structure).
  • Comprehensive unit tests covering F_2 and F_3 fields, brute-force solving, serialization, edge cases (empty equations, contradictory systems).

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/models/algebraic/multivariate_quadratic.rs Core model: QuadraticPoly, MultivariateQuadratic, Problem/SatisfactionProblem impls, schema registration, variants
src/models/algebraic/mod.rs Module declaration and re-export of new types
src/models/mod.rs Re-export MultivariateQuadratic and QuadraticPoly from top-level models
problemreductions-cli/src/dispatch.rs CLI dispatch for loading and serializing MQ instances
problemreductions-cli/src/problem_name.rs Alias MQMultivariateQuadratic
problemreductions-cli/src/commands/create.rs Bail for CLI creation (complex input)
docs/src/reductions/problem_schemas.json Schema entry for documentation
src/unit_tests/models/algebraic/multivariate_quadratic.rs Unit tests for the new model

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +97 to +102
pub fn new(field_size: usize, num_variables: usize, equations: Vec<QuadraticPoly>) -> Self {
Self {
field_size,
num_variables,
equations,
}
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The constructor does not validate that field_size >= 2. A field_size of 0 will cause a division-by-zero panic in QuadraticPoly::evaluate (via % q), and field_size of 1 produces a trivial/degenerate field. Other model constructors in this codebase validate their inputs (e.g., Knapsack::new asserts matching lengths). Consider adding assert!(field_size >= 2, "field_size must be at least 2") here.

Copilot uses AI. Check for mistakes.
Comment on lines +42 to +50
let mut result = self.constant % q;
for &((j, k), coeff) in &self.quadratic_terms {
result =
(result + coeff % q * (config[j] as u64 % q) % q * (config[k] as u64 % q) % q) % q;
}
for &(j, coeff) in &self.linear_terms {
result = (result + coeff % q * (config[j] as u64 % q) % q) % q;
}
result
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The modular arithmetic here is incorrect due to operator precedence. In Rust, * and % have the same precedence and are left-associative, so coeff % q * (config[j] as u64 % q) % q * (config[k] as u64 % q) % q parses as:

((((coeff % q) * (config[j] as u64 % q)) % q) * (config[k] as u64 % q)) % q

While this happens to produce the correct mathematical result, the addition step is problematic: result + <quadratic_term_value> is computed before the final % q, but result could be up to q-1 and the quadratic term value up to q-1, so their sum could be up to 2*(q-1), which is fine for u64. However, the expression is extremely fragile and hard to reason about.

More importantly, the expression coeff % q * (config[j] as u64 % q) could overflow u64 when q is large (e.g., close to u32::MAX or larger), since both operands can be up to q-1 and their product up to (q-1)^2. Consider using explicit parentheses and intermediate variables for clarity and to make overflow behavior obvious. For example, compute each multiplication followed by a modulus operation with explicit grouping.

Suggested change
let mut result = self.constant % q;
for &((j, k), coeff) in &self.quadratic_terms {
result =
(result + coeff % q * (config[j] as u64 % q) % q * (config[k] as u64 % q) % q) % q;
}
for &(j, coeff) in &self.linear_terms {
result = (result + coeff % q * (config[j] as u64 % q) % q) % q;
}
result
let q128 = q as u128;
let mut result = (self.constant % q) as u128;
for &((j, k), coeff) in &self.quadratic_terms {
let coeff_mod = (coeff % q) as u128;
let xj = (config[j] as u64 % q) as u128;
let xk = (config[k] as u64 % q) as u128;
let term = (((coeff_mod * xj) % q128) * xk) % q128;
result = (result + term) % q128;
}
for &(j, coeff) in &self.linear_terms {
let coeff_mod = (coeff % q) as u128;
let xj = (config[j] as u64 % q) as u128;
let term = (coeff_mod * xj) % q128;
result = (result + term) % q128;
}
(result % q128) as u64

Copilot uses AI. Check for mistakes.
GiggleLiu and others added 3 commits March 12, 2026 21:17
Address Copilot review comments:
- Add assert!(field_size >= 2) in MultivariateQuadratic::new() to
  prevent division-by-zero panic from field_size=0
- Use u128 intermediate arithmetic in QuadraticPoly::evaluate() to
  prevent u64 overflow when field_size is large

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Serde's derive(Deserialize) bypassed the field_size >= 2 assertion in
MultivariateQuadratic::new(), allowing invalid instances to be loaded
from JSON. Use #[serde(try_from)] with a raw helper struct to enforce
the invariant on both construction and deserialization paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@zazabap
Copy link
Collaborator

zazabap commented Mar 13, 2026

Implementation Summary

Changes

  • src/models/algebraic/multivariate_quadratic.rs — New model: MultivariateQuadratic struct and QuadraticPoly helper, implementing SatisfactionProblem (Metric = bool). Supports arbitrary finite fields F_q with brute-force solving via dims() returning vec![q; n].
  • src/models/algebraic/mod.rs — Register module, re-export MultivariateQuadratic and QuadraticPoly
  • src/models/mod.rs — Add to top-level re-exports
  • src/unit_tests/models/algebraic/multivariate_quadratic.rs — 18 unit tests: creation, evaluation over F_2 and F_3, solver (satisfiable + unsatisfiable), serialization round-trip, edge cases (empty equations, zero variables)
  • problemreductions-cli/src/dispatch.rsdeser_sat and try_ser match arms
  • problemreductions-cli/src/problem_name.rs — Lowercase alias multivariatequadratic and short alias MQ
  • problemreductions-cli/src/commands/create.rs — Marked as "via reduction only" (complex input structure)
  • problemreductions-cli/src/cli.rs — Added to help table
  • docs/paper/reductions.typdisplay-name entry and problem-def with definition, background, and example

Deviations from Plan

  • No plan file was created (PR Fix #129: Add MultivariateQuadratic model #594 already existed). Implementation followed the add-model skill steps directly.
  • Complexity declared as field_size^num_variables (brute-force bound). The Lokshtanov et al. 2017 bound (2^{0.8765n} for F_2) could be a future variant-specific refinement.
  • Not added to prelude (matches pattern: ILP and CVP are also not in prelude).

Open Questions

  • The MQ problem is currently an orphan node (no reduction rules connect it to the graph). A future [Rule] issue for MQ <-> SAT over F_2 would integrate it.

- Add display-name and problem-def entry in docs/paper/reductions.typ
- Add MQ to CLI help table (via reduction only)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@zazabap
Copy link
Collaborator

zazabap commented Mar 13, 2026

Implementation Summary (completion pass)

Changes Added

  • docs/paper/reductions.typ — Added display-name entry ("MultivariateQuadratic": [Multivariate Quadratic]) and problem-def block with formal definition, background (post-quantum cryptography, Groebner basis), and worked example over F_2
  • problemreductions-cli/src/cli.rs — Added MQ to the "Flags by problem type" help table as "(via reduction only)"

Deviations from Plan

  • None. This commit completes the existing implementation which was missing paper documentation and CLI help table entry.

Open Questions

  • MQ is currently an orphan node in the reduction graph. A future [Rule] issue for MQ <-> SAT over F_2 would integrate it.

GiggleLiu and others added 2 commits March 13, 2026 19:14
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@GiggleLiu
Copy link
Contributor

Review Pipeline Report

Check Result
Merge conflicts 2 files resolved (CLI dispatch + problem names)
Copilot comments 0 actionable (approved, issues already fixed)
Issue/human comments 3 checked, 0 new fixes needed
CI green (Test, Clippy, Coverage all pass)
Agentic test passed — model creation, evaluation, brute force, serialization, CLI all work
Board review-agentic → In Review

Agentic Test Highlights

  • All 9 unit tests pass
  • BruteForce correctly finds all 3 solutions for F_2 test system
  • JSON serialization round-trips cleanly
  • CLI show, solve --solver brute-force, evaluate, inspect all recognize MQ
  • Deserialization correctly rejects field_size < 2

Known Limitations (expected for [Model] PR)

  • MQ not in prelude (follow-up)
  • No reduction rules yet (orphan node — per issue [Model] MultivariateQuadratic #129 comment, reduction rule will be a separate PR)
  • CLI create MQ not supported (listed as "via reduction only")

🤖 Generated by review-pipeline

- Remove `field_size` field from struct; hardcode F_2
- Change QuadraticPoly: quadratic_terms to Vec<(usize, usize)>,
  linear_terms to Vec<usize>, constant to bool
- Simplify evaluate() to use XOR/AND (mod 2 arithmetic)
- Rename getter num_vars() to num_variables(); remove field_size()
- Update dims() to return vec![2; n] (hardcoded F_2)
- Remove F_3 test; add constant-equation test
- Update declare_variants! complexity to "1.6181^num_variables"
- Update problem_schemas.json and paper definition
- Remove serde TryFrom validation (no longer needed without field_size)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@GiggleLiu GiggleLiu mentioned this pull request Mar 13, 2026
3 tasks
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.

[Model] MultivariateQuadratic

4 participants