Skip to content

Commit f394f23

Browse files
zazabapclaudeGiggleLiu
authored
Fix #402: Add SubsetSum model (#602)
* Add plan for #402: SubsetSum model * Implement #402: Add SubsetSum model - Add SubsetSum satisfaction problem to src/models/misc/ - Binary variables: x_i = 1 if element i is in the subset - Evaluates true iff selected subset sums to target B - Complexity: 2^(n/2) via Horowitz-Sahni meet-in-the-middle - CLI: pred create SubsetSum --sizes 3,7,1,8,2,4 --target 11 - 15 unit tests covering basic, edge cases, brute force, serialization - Regenerated problem schemas JSON Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: remove plan file after implementation * Regenerate reduction_graph.json and problem_schemas.json Address Copilot review comment: ensure SubsetSum appears in both generated JSON docs files. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add CLI format hints and example for SubsetSum Fix type_format_hint() to handle Vec<i64> and i64 types, and add SubsetSum entry to example_for() so `pred create SubsetSum` shows a helpful usage example. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: regenerate corrupted reduction_graph.json and apply rustfmt - Fix corrupted reduction_graph.json that had stdout text mixed into the file - Apply rustfmt formatting to two example files Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: GiggleLiu <cacate0129@gmail.com>
1 parent 6cc8cb6 commit f394f23

14 files changed

Lines changed: 123 additions & 117 deletions

docs/paper/examples/maximumindependentset_to_maximumclique.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131
"target": {
3232
"problem": "MaximumClique",
3333
"variant": {
34-
"weight": "i32",
35-
"graph": "SimpleGraph"
34+
"graph": "SimpleGraph",
35+
"weight": "i32"
3636
},
3737
"instance": {
3838
"edges": [

docs/paper/examples/travelingsalesman_to_qubo.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
"source": {
33
"problem": "TravelingSalesman",
44
"variant": {
5-
"weight": "i32",
6-
"graph": "SimpleGraph"
5+
"graph": "SimpleGraph",
6+
"weight": "i32"
77
},
88
"instance": {
99
"num_edges": 3,

examples/detect_unreachable_from_3sat.rs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,7 @@ fn main() {
109109
// Check if ALL variants of this problem are P-time
110110
// (conservative: if any variant could be hard, don't classify as P)
111111
let variants = graph.variants_for(name);
112-
variants.len() == 1
113-
&& variants[0].get(*key).map(|s| s.as_str()) == Some(*val)
112+
variants.len() == 1 && variants[0].get(*key).map(|s| s.as_str()) == Some(*val)
114113
}
115114
}
116115
});
@@ -143,10 +142,7 @@ fn main() {
143142
}
144143

145144
if !p_time.is_empty() {
146-
println!(
147-
"In P — correctly unreachable ({}):",
148-
p_time.len()
149-
);
145+
println!("In P — correctly unreachable ({}):", p_time.len());
150146
for name in &p_time {
151147
println!(" {name}");
152148
}
@@ -165,10 +161,7 @@ fn main() {
165161
}
166162

167163
if !orphans.is_empty() {
168-
println!(
169-
"Orphans — no reductions at all ({}):",
170-
orphans.len()
171-
);
164+
println!("Orphans — no reductions at all ({}):", orphans.len());
172165
for name in &orphans {
173166
println!(" {name}");
174167
}

examples/reduction_binpacking_to_ilp.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@ pub fn run() {
5353

5454
// 5. Extract source solution
5555
let bp_solution = reduction.extract_solution(&ilp_solution);
56-
println!("Source BinPacking solution (bin assignments): {:?}", bp_solution);
56+
println!(
57+
"Source BinPacking solution (bin assignments): {:?}",
58+
bp_solution
59+
);
5760

5861
// 6. Verify
5962
let size = bp.evaluate(&bp_solution);
@@ -76,13 +79,8 @@ pub fn run() {
7679

7780
let source_variant = variant_to_map(BinPacking::<i32>::variant());
7881
let target_variant = variant_to_map(ILP::<bool>::variant());
79-
let overhead = lookup_overhead(
80-
"BinPacking",
81-
&source_variant,
82-
"ILP",
83-
&target_variant,
84-
)
85-
.unwrap_or_default();
82+
let overhead =
83+
lookup_overhead("BinPacking", &source_variant, "ILP", &target_variant).unwrap_or_default();
8684

8785
let data = ReductionData {
8886
source: ProblemSide {

examples/reduction_longestcommonsubsequence_to_ilp.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,13 @@ pub fn run() {
7373

7474
let source_variant = variant_to_map(LongestCommonSubsequence::variant());
7575
let target_variant = variant_to_map(ILP::<bool>::variant());
76-
let overhead =
77-
lookup_overhead("LongestCommonSubsequence", &source_variant, "ILP", &target_variant)
78-
.expect("LCS -> ILP overhead not found");
76+
let overhead = lookup_overhead(
77+
"LongestCommonSubsequence",
78+
&source_variant,
79+
"ILP",
80+
&target_variant,
81+
)
82+
.expect("LCS -> ILP overhead not found");
7983

8084
let data = ReductionData {
8185
source: ProblemSide {

pipeline-output.log

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
3+
The structural reviewer also completed — all 16 model checks and 14 rule checks passed with no critical issues. The pipeline for issue #126 is complete.
4+
5+
```
6+
Pipeline complete:
7+
Issue: #126 [Rule] KSatisfiability to SubsetSum
8+
PR: #599 (https://github.com/CodingThrust/problem-reductions/pull/599)
9+
Status: Implemented, Copilot review requested
10+
Board: Ready -> In Progress -> review-agentic
11+
```

problemreductions-cli/src/cli.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ Flags by problem type:
211211
GraphPartitioning --graph
212212
Factoring --target, --m, --n
213213
BinPacking --sizes, --capacity
214+
SubsetSum --sizes, --target
214215
PaintShop --sequence
215216
MaximumSetPacking --sets [--weights]
216217
MinimumSetCovering --universe, --sets [--weights]

problemreductions-cli/src/commands/create.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::util;
66
use anyhow::{bail, Context, Result};
77
use problemreductions::models::algebraic::{ClosestVectorProblem, BMF};
88
use problemreductions::models::graph::GraphPartitioning;
9-
use problemreductions::models::misc::{BinPacking, LongestCommonSubsequence, PaintShop};
9+
use problemreductions::models::misc::{BinPacking, LongestCommonSubsequence, PaintShop, SubsetSum};
1010
use problemreductions::prelude::*;
1111
use problemreductions::registry::collect_schemas;
1212
use problemreductions::topology::{
@@ -63,6 +63,8 @@ fn type_format_hint(type_name: &str, graph_type: Option<&str>) -> &'static str {
6363
"Vec<Vec<W>>" => "semicolon-separated rows: \"1,0.5;0.5,2\"",
6464
"usize" => "integer",
6565
"u64" => "integer",
66+
"i64" => "integer",
67+
"Vec<i64>" => "comma-separated integers: 3,7,1,8",
6668
_ => "value",
6769
}
6870
}
@@ -88,6 +90,7 @@ fn example_for(canonical: &str, graph_type: Option<&str>) -> &'static str {
8890
"SpinGlass" => "--graph 0-1,1-2 --couplings 1,1",
8991
"KColoring" => "--graph 0-1,1-2,2-0 --k 3",
9092
"Factoring" => "--target 15 --m 4 --n 4",
93+
"SubsetSum" => "--sizes 3,7,1,8,2,4 --target 11",
9194
_ => "",
9295
}
9396
}
@@ -351,6 +354,27 @@ pub fn create(args: &CreateArgs, out: &OutputConfig) -> Result<()> {
351354
}
352355
}
353356

357+
// SubsetSum
358+
"SubsetSum" => {
359+
let sizes_str = args.sizes.as_deref().ok_or_else(|| {
360+
anyhow::anyhow!(
361+
"SubsetSum requires --sizes and --target\n\n\
362+
Usage: pred create SubsetSum --sizes 3,7,1,8,2,4 --target 11"
363+
)
364+
})?;
365+
let target = args.target.ok_or_else(|| {
366+
anyhow::anyhow!(
367+
"SubsetSum requires --target\n\n\
368+
Usage: pred create SubsetSum --sizes 3,7,1,8,2,4 --target 11"
369+
)
370+
})?;
371+
let sizes: Vec<i64> = util::parse_comma_list(sizes_str)?;
372+
(
373+
ser(SubsetSum::new(sizes, target as i64))?,
374+
resolved_variant.clone(),
375+
)
376+
}
377+
354378
// PaintShop
355379
"PaintShop" => {
356380
let seq_str = args.sequence.as_deref().ok_or_else(|| {

review-output.log

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
**PR #594 (Fix #129: Add MultivariateQuadratic model) processed successfully.**
2+
3+
| Check | Result |
4+
|-------|--------|
5+
| Merge conflicts | 2 files resolved |
6+
| Copilot comments | 0 actionable (already fixed) |
7+
| Issue/human comments | 3 checked, 0 fixes needed |
8+
| CI | green |
9+
| Agentic test | passed |
10+
| Board | review-agentic → In Review |

src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ pub mod prelude {
4545
KColoring, MaxCut, MaximalIS, MaximumClique, MaximumIndependentSet, MaximumMatching,
4646
MinimumDominatingSet, MinimumFeedbackVertexSet, MinimumVertexCover, TravelingSalesman,
4747
};
48-
pub use crate::models::misc::{BinPacking, Factoring, Knapsack, LongestCommonSubsequence, PaintShop, SubsetSum};
48+
pub use crate::models::misc::{
49+
BinPacking, Factoring, Knapsack, LongestCommonSubsequence, PaintShop, SubsetSum,
50+
};
4951
pub use crate::models::set::{MaximumSetPacking, MinimumSetCovering};
5052

5153
// Core traits

0 commit comments

Comments
 (0)