Open
Conversation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #622 +/- ##
==========================================
+ Coverage 96.81% 96.83% +0.01%
==========================================
Files 244 246 +2
Lines 31650 31801 +151
==========================================
+ Hits 30642 30793 +151
Misses 1008 1008 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
- Add QuadraticAssignment model in src/models/algebraic/ - Register in CLI (dispatch, aliases, create command) - Add unit tests (creation, evaluation, solver, serialization) - Add paper entry with CeTZ example diagram - Regenerate problem schemas Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add out-of-range location index test - Add rectangular case test (n < m) - Add #[should_panic] tests for constructor validation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Collaborator
Author
Implementation SummaryChanges
Deviations from Plan
Open Questions
|
There was a problem hiding this comment.
Pull request overview
Adds a new algebraic optimization model for the Quadratic Assignment Problem (QAP) and wires it into the library, CLI, and docs so it can be created/serialized/solved via existing infrastructure.
Changes:
- Introduces
QuadraticAssignmentmodel with schema registration, variant declaration, and unit tests. - Exposes QAP through crate re-exports/prelude and CLI (alias resolution, dispatch load/serialize,
pred createsupport). - Updates documentation outputs (schemas JSON + paper) to include the new problem.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
src/models/algebraic/quadratic_assignment.rs |
New QAP model implementation, schema registration, and variant declaration. |
src/unit_tests/models/algebraic/quadratic_assignment.rs |
Unit tests for construction, evaluation, serialization, and brute-force solving. |
src/models/algebraic/mod.rs |
Adds the new module + re-export from algebraic. |
src/models/mod.rs |
Re-exports QuadraticAssignment from top-level models. |
src/lib.rs |
Adds QuadraticAssignment to the crate prelude. |
problemreductions-cli/src/problem_name.rs |
Adds QAP alias and resolves qap/quadraticassignment. |
problemreductions-cli/src/dispatch.rs |
Enables CLI load/serialize for QuadraticAssignment. |
problemreductions-cli/src/commands/create.rs |
Adds pred create QAP handling and --distance-matrix parsing. |
problemreductions-cli/src/cli.rs |
Documents QAP flags and adds the --distance-matrix CLI argument. |
docs/src/reductions/problem_schemas.json |
Adds schema entry for QuadraticAssignment. |
docs/paper/reductions.typ |
Adds QAP display name and a new problem definition section. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
docs/paper/reductions.typ
Outdated
| Given $n$ facilities and $m$ locations ($n <= m$), a flow matrix $C in ZZ^(n times n)$ representing flows between facilities, and a distance matrix $D in ZZ^(m times m)$ representing distances between locations, find an injective assignment $f: {1, dots, n} -> {1, dots, m}$ that minimizes | ||
| $ sum_(i != j) C_(i j) dot D_(f(i), f(j)). $ | ||
| ][ | ||
| The Quadratic Assignment Problem was introduced by Koopmans and Beckmann (1957) to model the optimal placement of economic activities (facilities) across geographic locations, minimizing total transportation cost weighted by inter-facility flows. It is NP-hard, as shown by Sahni and Gonzalez (1976) via reduction from the Hamiltonian Circuit problem. QAP is widely regarded as one of the hardest combinatorial optimization problems: even moderate instances ($n > 20$) challenge state-of-the-art exact solvers. Best exact approaches use branch-and-bound with Gilmore--Lawler bounds or Dreyfus--Wagner-like dynamic programming; the best known general algorithm runs in $O^*(n!)$ by exhaustive enumeration of all permutations#footnote[No algorithm significantly improving on brute-force permutation enumeration is known for general QAP.]. |
Comment on lines
+390
to
+405
| { | ||
| "name": "QuadraticAssignment", | ||
| "description": "Minimize total cost of assigning facilities to locations", | ||
| "fields": [ | ||
| { | ||
| "name": "cost_matrix", | ||
| "type_name": "Vec<Vec<i64>>", | ||
| "description": "Flow/cost matrix between facilities" | ||
| }, | ||
| { | ||
| "name": "distance_matrix", | ||
| "type_name": "Vec<Vec<i64>>", | ||
| "description": "Distance matrix between locations" | ||
| } | ||
| ] | ||
| }, |
| module_path: module_path!(), | ||
| description: "Minimize total cost of assigning facilities to locations", | ||
| fields: &[ | ||
| FieldInfo { name: "cost_matrix", type_name: "Vec<Vec<i64>>", description: "Flow/cost matrix between facilities" }, |
Comment on lines
+121
to
+146
| fn evaluate(&self, config: &[usize]) -> SolutionSize<i64> { | ||
| let n = self.num_facilities(); | ||
| let m = self.num_locations(); | ||
|
|
||
| // Check that all assignments are valid locations | ||
| for &loc in config.iter().take(n) { | ||
| if loc >= m { | ||
| return SolutionSize::Invalid; | ||
| } | ||
| } | ||
|
|
||
| // Check injectivity: no two facilities assigned to the same location | ||
| let mut used = std::collections::HashSet::new(); | ||
| for &loc in config.iter().take(n) { | ||
| if !used.insert(loc) { | ||
| return SolutionSize::Invalid; | ||
| } | ||
| } | ||
|
|
||
| // Compute objective: sum_{i != j} cost_matrix[i][j] * distance_matrix[config[i]][config[j]] | ||
| let mut total: i64 = 0; | ||
| for i in 0..n { | ||
| for j in 0..n { | ||
| if i != j { | ||
| total += self.cost_matrix[i][j] * self.distance_matrix[config[i]][config[j]]; | ||
| } |
Comment on lines
+133
to
+137
| let mut used = std::collections::HashSet::new(); | ||
| for &loc in config.iter().take(n) { | ||
| if !used.insert(loc) { | ||
| return SolutionSize::Invalid; | ||
| } |
| /// | ||
| /// f(p) = sum_{i != j} C[i][j] * D[p(i)][p(j)] | ||
| /// | ||
| /// where p is a permutation mapping facilities to locations. |
Comment on lines
+269
to
+294
| // QuadraticAssignment | ||
| "QuadraticAssignment" => { | ||
| let cost_str = args.matrix.as_deref().ok_or_else(|| { | ||
| anyhow::anyhow!( | ||
| "QuadraticAssignment requires --matrix (cost) and --distance-matrix\n\n\ | ||
| Usage: pred create QAP --matrix \"0,5;5,0\" --distance-matrix \"0,1;1,0\"" | ||
| ) | ||
| })?; | ||
| let dist_str = args.distance_matrix.as_deref().ok_or_else(|| { | ||
| anyhow::anyhow!( | ||
| "QuadraticAssignment requires --distance-matrix\n\n\ | ||
| Usage: pred create QAP --matrix \"0,5;5,0\" --distance-matrix \"0,1;1,0\"" | ||
| ) | ||
| })?; | ||
| let cost_matrix = parse_i64_matrix(cost_str).context("Invalid cost matrix")?; | ||
| let distance_matrix = parse_i64_matrix(dist_str).context("Invalid distance matrix")?; | ||
| ( | ||
| ser( | ||
| problemreductions::models::algebraic::QuadraticAssignment::new( | ||
| cost_matrix, | ||
| distance_matrix, | ||
| ), | ||
| )?, | ||
| resolved_variant.clone(), | ||
| ) | ||
| } |
Comment on lines
+925
to
+936
| s.split(';') | ||
| .map(|row| { | ||
| row.trim() | ||
| .split(',') | ||
| .map(|v| { | ||
| v.trim() | ||
| .parse::<i64>() | ||
| .map_err(|e| anyhow::anyhow!("Invalid matrix value: {}", e)) | ||
| }) | ||
| .collect() | ||
| }) | ||
| .collect() |
- Fix Dreyfus-Wagner reference in paper (not applicable to QAP, replaced with cutting-plane methods) - Add config length check in evaluate() to return Invalid instead of panicking - Replace HashSet with Vec<bool> for faster injectivity checking - Fix doc wording: "permutation" -> "injective mapping" for rectangular case - Add input validation in CLI create to surface errors instead of panicking - Improve parse_i64_matrix with row/col context in errors and ragged matrix detection - Regenerate problem_schemas.json after merge - Add tests for config length mismatch Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Collaborator
Author
Review Pipeline Report
Copilot Comments Addressed
🤖 Generated by review-pipeline |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add factorial() function support to the expression parser (both proc macro and runtime) and all Expr match sites (eval, display, canonical, big_o, analysis). Change QuadraticAssignment's declare_variants! complexity from "num_facilities ^ num_facilities" to "factorial(num_facilities)". Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ssignment # Conflicts: # docs/paper/reductions.typ # problemreductions-cli/src/cli.rs # problemreductions-cli/src/commands/create.rs # problemreductions-cli/src/dispatch.rs # problemreductions-cli/src/problem_name.rs # problemreductions-macros/src/parser.rs # src/expr.rs # src/lib.rs # src/unit_tests/trait_consistency.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
src/models/algebraic/Fixes #300