Skip to content

Fix #228: Add MinimumCutIntoBoundedSets model#637

Merged
GiggleLiu merged 10 commits intomainfrom
issue-228-minimum-cut-into-bounded-sets
Mar 19, 2026
Merged

Fix #228: Add MinimumCutIntoBoundedSets model#637
GiggleLiu merged 10 commits intomainfrom
issue-228-minimum-cut-into-bounded-sets

Conversation

@zazabap
Copy link
Copy Markdown
Collaborator

@zazabap zazabap commented Mar 13, 2026

Summary

Add the MinimumCutIntoBoundedSets satisfaction problem (Garey & Johnson ND17). This is a graph partitioning problem that combines minimum s-t cut with balance constraints on partition sizes.

Fixes #228

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.79%. Comparing base (88254a0) to head (da6ea40).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #637      +/-   ##
==========================================
+ Coverage   96.77%   96.79%   +0.01%     
==========================================
  Files         226      228       +2     
  Lines       29919    30136     +217     
==========================================
+ Hits        28955    29171     +216     
- Misses        964      965       +1     

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

zazabap and others added 2 commits March 13, 2026 12:24
@zazabap
Copy link
Copy Markdown
Collaborator Author

zazabap commented Mar 13, 2026

Implementation Summary

Changes

  • src/models/graph/minimum_cut_into_bounded_sets.rs — New model implementing the MinimumCutIntoBoundedSets satisfaction problem (G&J ND17). Parameterized by graph type G and weight type W. Evaluates partition feasibility: source/sink placement, size bounds, and cut weight bound.
  • src/unit_tests/models/graph/minimum_cut_into_bounded_sets.rs — 16 unit tests covering creation, evaluation (YES/NO instances), constraint violations (wrong source/sink, size bound exceeded, wrong config length), serialization round-trip, brute-force solver (satisfying and unsatisfying instances), accessors, and variant metadata.
  • src/models/graph/mod.rs — Module registration and re-export.
  • src/models/mod.rs — Re-export added.
  • src/lib.rs — Added to prelude.
  • problemreductions-cli/src/dispatch.rs — CLI load/serialize dispatch for MinimumCutIntoBoundedSets<SimpleGraph, i32>.
  • problemreductions-cli/src/problem_name.rs — Lowercase alias mapping.
  • problemreductions-cli/src/cli.rs — Added --source, --sink, --size-bound, --cut-bound flags and help table entry.
  • problemreductions-cli/src/commands/create.rs — Creation handler (manual + random) and example_for entry.
  • docs/paper/reductions.typ — Problem definition with formal statement, background, and example.

Deviations from Plan

  • The cut_bound field uses W::Sum type (matching how cut weights are computed) rather than raw W, which is more type-correct.

Open Questions

  • None.

Copy link
Copy Markdown

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

Adds the MinimumCutIntoBoundedSets satisfaction/decision model (Garey & Johnson ND17) to the library, with accompanying unit tests, CLI support for create/load/serialize, and paper documentation updates.

Changes:

  • Introduces MinimumCutIntoBoundedSets<G, W> model with schema registration, variants, and evaluation logic.
  • Adds comprehensive unit tests covering evaluation, serialization, and BruteForce solver behavior.
  • Extends CLI to resolve the new problem name/alias, create instances (including random generation), and load/serialize JSON for the new type; updates paper docs to include the new problem.

Reviewed changes

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

Show a summary per file
File Description
src/models/graph/minimum_cut_into_bounded_sets.rs New model implementation + schema entry + variant declaration + tests module hookup
src/unit_tests/models/graph/minimum_cut_into_bounded_sets.rs New unit tests for the model (evaluation/serialization/solver/variant)
src/models/graph/mod.rs Registers the new graph model module and re-export
src/models/mod.rs Re-exports the new model at the models root
src/lib.rs Adds the model to the public prelude
problemreductions-cli/src/problem_name.rs Adds alias resolution for minimumcutintoboundedsets
problemreductions-cli/src/dispatch.rs Adds JSON load + Any serialization support for the new model
problemreductions-cli/src/commands/create.rs Adds pred create support (explicit and random) for the new model
problemreductions-cli/src/cli.rs Adds new CLI flags for source/sink/size_bound/cut_bound and updates help text
docs/paper/reductions.typ Adds paper definition section + label mapping for the new problem

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

Comment on lines +231 to +251
let source = args
.source
.context("--source is required for MinimumCutIntoBoundedSets")?;
let sink = args
.sink
.context("--sink is required for MinimumCutIntoBoundedSets")?;
let size_bound = args
.size_bound
.context("--size-bound is required for MinimumCutIntoBoundedSets")?;
let cut_bound = args
.cut_bound
.context("--cut-bound is required for MinimumCutIntoBoundedSets")?;
(
ser(MinimumCutIntoBoundedSets::new(
graph,
edge_weights,
source,
sink,
size_bound,
cut_bound,
))?,
"MinimumCutIntoBoundedSets" => {
let (graph, _) = parse_graph(args).map_err(|e| {
anyhow::anyhow!(
"{e}\n\nUsage: pred create MinimumCutIntoBoundedSets --graph 0-1,1-2,2-3 --edge-weights 1,1,1 --source 0 --sink 2 --size-bound 2 --cut-bound 1"
Comment thread docs/paper/reductions.typ
Given an undirected graph $G = (V, E)$ with edge weights $w: E -> ZZ^+$, designated vertices $s, t in V$, a positive integer $B <= |V|$, and a positive integer $K$, determine whether there exists a partition of $V$ into disjoint sets $V_1$ and $V_2$ such that $s in V_1$, $t in V_2$, $|V_1| <= B$, $|V_2| <= B$, and
$ sum_({u,v} in E: u in V_1, v in V_2) w({u,v}) <= K. $
][
Minimum Cut Into Bounded Sets (Garey & Johnson ND17) combines the classical minimum $s$-$t$ cut problem with a balance constraint on partition sizes. Without the balance constraint ($B = |V|$), the problem reduces to standard minimum $s$-$t$ cut, solvable in polynomial time via network flow. Adding the requirement $|V_1| <= B$ and $|V_2| <= B$ makes the problem NP-complete; it remains NP-complete even for $B = |V| slash 2$ and unit edge weights (the minimum bisection problem) @garey1976. Applications include VLSI layout, load balancing, and graph bisection.
Comment thread docs/paper/reductions.typ
][
Minimum Cut Into Bounded Sets (Garey & Johnson ND17) combines the classical minimum $s$-$t$ cut problem with a balance constraint on partition sizes. Without the balance constraint ($B = |V|$), the problem reduces to standard minimum $s$-$t$ cut, solvable in polynomial time via network flow. Adding the requirement $|V_1| <= B$ and $|V_2| <= B$ makes the problem NP-complete; it remains NP-complete even for $B = |V| slash 2$ and unit edge weights (the minimum bisection problem) @garey1976. Applications include VLSI layout, load balancing, and graph bisection.

The best known exact algorithm is brute-force enumeration of all $2^n$ vertex partitions in $O(2^n)$ time. For the special case of minimum bisection, Cygan et al. @cygan2014 showed fixed-parameter tractability with respect to the cut size. No polynomial-time finite approximation factor exists for balanced graph partition unless $P = N P$ (Andreev and Racke, 2006). Arora, Rao, and Vazirani @arora2009 gave an $O(sqrt(log n))$-approximation for balanced separator.
Comment on lines +171 to +183
fn evaluate(&self, config: &[usize]) -> bool {
let n = self.graph.num_vertices();
if config.len() != n {
return false;
}

// Check source is in V1 (config=0) and sink is in V2 (config=1)
if config[self.source] != 0 {
return false;
}
if config[self.sink] != 1 {
return false;
}
Comment on lines +185 to +190
// Check size bounds
let count_v1 = config.iter().filter(|&&x| x == 0).count();
let count_v2 = config.iter().filter(|&&x| x == 1).count();
if count_v1 > self.size_bound || count_v2 > self.size_bound {
return false;
}
Comment on lines +14 to +28
inventory::submit! {
ProblemSchemaEntry {
name: "MinimumCutIntoBoundedSets",
module_path: module_path!(),
description: "Partition vertices into two bounded-size sets with cut weight at most K",
fields: &[
FieldInfo { name: "graph", type_name: "G", description: "The undirected graph G = (V, E)" },
FieldInfo { name: "edge_weights", type_name: "Vec<W>", description: "Edge weights w: E -> Z+" },
FieldInfo { name: "source", type_name: "usize", description: "Source vertex s (must be in V1)" },
FieldInfo { name: "sink", type_name: "usize", description: "Sink vertex t (must be in V2)" },
FieldInfo { name: "size_bound", type_name: "usize", description: "Maximum size B for each partition set" },
FieldInfo { name: "cut_bound", type_name: "W::Sum", description: "Maximum total cut weight K" },
],
}
}
Comment on lines +1046 to +1054
let graph = util::create_random_graph(num_vertices, edge_prob, args.seed);
let num_edges = graph.num_edges();
let edge_weights = vec![1i32; num_edges];
let source = 0;
let sink = if num_vertices > 1 {
num_vertices - 1
} else {
0
};
GiggleLiu and others added 3 commits March 19, 2026 17:37
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add missing ProblemSchemaEntry fields (display_name, aliases, dimensions)
- Add 'default sat' prefix to declare_variants! macro
- Remove duplicate source/sink CLI fields (already defined by main)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add canonical_model_example_specs() for MinimumCutIntoBoundedSets
  using the 8-vertex issue #228 instance, register in graph/mod.rs
- Add brute-force test verifying K=5 has no solution on the issue instance

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@GiggleLiu GiggleLiu closed this Mar 19, 2026
@GiggleLiu GiggleLiu reopened this Mar 19, 2026
GiggleLiu and others added 2 commits March 19, 2026 18:26
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@GiggleLiu GiggleLiu marked this pull request as draft March 19, 2026 10:39
@GiggleLiu GiggleLiu marked this pull request as ready for review March 19, 2026 10:39
@GiggleLiu GiggleLiu mentioned this pull request Mar 19, 2026
3 tasks
GiggleLiu and others added 2 commits March 19, 2026 18:44
…-into-bounded-sets

# Conflicts:
#	docs/paper/reductions.typ
#	problemreductions-cli/src/cli.rs
#	problemreductions-cli/src/commands/create.rs
#	src/models/mod.rs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@GiggleLiu GiggleLiu merged commit b373477 into main Mar 19, 2026
2 of 3 checks passed
@GiggleLiu GiggleLiu deleted the issue-228-minimum-cut-into-bounded-sets branch March 19, 2026 11:01
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] MinimumCutIntoBoundedSets

3 participants