Skip to content

Commit 81d92e5

Browse files
isPANNclaude
andauthored
Fix #515: [Model] RegisterSufficiency (#816)
* Fix #515: [Model] RegisterSufficiency Add the Register Sufficiency decision problem (Garey & Johnson A11 PO1): given a DAG and bound K, determine whether the computation can be performed using at most K registers. Value type Or, category misc. Includes model, unit tests (12), CLI create handler, canonical example, and paper entry with bibliography references (Sethi 1975, Sethi-Ullman 1970, Kessler 1998). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix pred solve command in paper to use --solver brute-force RegisterSufficiency has no ILP reduction path yet, so the default solver fails. Use --solver brute-force consistent with other models lacking an ILP path (e.g., PathConstrainedNetworkFlow, RootedTreeArrangement). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Add CLI regression test for RegisterSufficiency create Covers the documented create flow with --arcs, --bound, --num-vertices flags and verifies the output JSON structure. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent b4a2c62 commit 81d92e5

9 files changed

Lines changed: 607 additions & 2 deletions

File tree

docs/paper/reductions.typ

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@
182182
"QuadraticDiophantineEquations": [Quadratic Diophantine Equations],
183183
"QuantifiedBooleanFormulas": [Quantified Boolean Formulas (QBF)],
184184
"RectilinearPictureCompression": [Rectilinear Picture Compression],
185+
"RegisterSufficiency": [Register Sufficiency],
185186
"ResourceConstrainedScheduling": [Resource Constrained Scheduling],
186187
"RootedTreeStorageAssignment": [Rooted Tree Storage Assignment],
187188
"SchedulingToMinimizeWeightedCompletionTime": [Scheduling to Minimize Weighted Completion Time],
@@ -4170,6 +4171,33 @@ A classical NP-complete problem from Garey and Johnson @garey1979[Ch.~3, p.~76],
41704171
]
41714172
}
41724173

4174+
#{
4175+
let x = load-model-example("RegisterSufficiency")
4176+
let n = x.instance.num_vertices
4177+
let arcs = x.instance.arcs
4178+
let K = x.instance.bound
4179+
let sigma = x.optimal_config
4180+
// Build evaluation order (position -> vertex)
4181+
let order = range(n).map(pos =>
4182+
range(n).find(v => sigma.at(v) == pos)
4183+
)
4184+
[
4185+
#problem-def("RegisterSufficiency")[
4186+
Given a directed acyclic graph $G = (V, A)$ with $n = |V|$ vertices, where each arc $(v, u) in A$ means vertex $v$ depends on vertex $u$, and a positive integer $K$, determine whether there exists an evaluation ordering $v_(pi(0)), v_(pi(1)), dots, v_(pi(n-1))$ of all vertices such that the computation can be performed using at most $K$ registers. A value must reside in a register from the moment it is computed until all vertices that depend on it have been evaluated.
4187+
][
4188+
Register Sufficiency is problem SS19 (also A11 PO1) in Garey & Johnson @garey1979. NP-complete via reduction from 3-SAT @sethi1975. Remains NP-complete even when all vertices have out-degree at most 2. For expression trees (DAGs with tree structure), the Sethi--Ullman algorithm solves the problem in $O(n)$ time @sethiUllman1970. For general DAGs, Kessler's dynamic programming over register states runs in $O(n^2 dot 2^n)$ time @kessler1998.
4189+
4190+
*Example.* Let $n = #n$ vertices with arcs (dependencies): #{arcs.map(a => $v_#(a.at(0)) arrow.r v_#(a.at(1))$).join(", ")}. Bound $K = #K$. The evaluation order $pi = (#order.map(v => $v_#v$).join(", "))$ achieves a maximum of $#K$ registers.
4191+
4192+
#pred-commands(
4193+
"pred create --example RegisterSufficiency -o register-sufficiency.json",
4194+
"pred solve register-sufficiency.json --solver brute-force",
4195+
"pred evaluate register-sufficiency.json --config " + x.optimal_config.map(str).join(","),
4196+
)
4197+
]
4198+
]
4199+
}
4200+
41734201
#{
41744202
let x = load-model-example("RuralPostman")
41754203
let nv = x.instance.graph.num_vertices

docs/paper/references.bib

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,32 @@
1+
@article{sethi1975,
2+
author = {Ravi Sethi},
3+
title = {Complete Register Allocation Problems},
4+
journal = {SIAM Journal on Computing},
5+
volume = {4},
6+
number = {3},
7+
pages = {226--248},
8+
year = {1975},
9+
doi = {10.1137/0204020}
10+
}
11+
12+
@article{sethiUllman1970,
13+
author = {Ravi Sethi and Jeffrey D. Ullman},
14+
title = {The Generation of Optimal Code for Arithmetic Expressions},
15+
journal = {Journal of the ACM},
16+
volume = {17},
17+
number = {4},
18+
pages = {715--728},
19+
year = {1970},
20+
doi = {10.1145/321607.321620}
21+
}
22+
23+
@phdthesis{kessler1998,
24+
author = {Christoph W. Kessler},
25+
title = {Scheduling Expression {DAG}s for Minimal Register Need},
26+
school = {Universit{\"a}t des Saarlandes},
27+
year = {1998}
28+
}
29+
130
@inproceedings{wagner1975,
231
author = {Robert A. Wagner},
332
title = {On the Complexity of the Extended String-to-String Correction Problem},

problemreductions-cli/src/cli.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ Flags by problem type:
318318
StringToStringCorrection --source-string, --target-string, --bound [--alphabet-size]
319319
D2CIF --arcs, --capacities, --source-1, --sink-1, --source-2, --sink-2, --requirement-1, --requirement-2
320320
MinimumDummyActivitiesPert --arcs [--num-vertices]
321+
RegisterSufficiency --arcs, --bound [--num-vertices]
321322
CBQ --domain-size, --relations, --conjuncts-spec
322323
IntegerExpressionMembership --expression (JSON), --target
323324
ILP, CircuitSAT (via reduction only)

problemreductions-cli/src/commands/create.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use problemreductions::models::misc::{
2727
IntegerExpressionMembership, JobShopScheduling, KnownValue, KthLargestMTuple,
2828
LongestCommonSubsequence, MinimumTardinessSequencing, MultiprocessorScheduling, PaintShop,
2929
PartiallyOrderedKnapsack, ProductionPlanning, QueryArg, RectilinearPictureCompression,
30-
ResourceConstrainedScheduling, SchedulingToMinimizeWeightedCompletionTime,
30+
RegisterSufficiency, ResourceConstrainedScheduling, SchedulingToMinimizeWeightedCompletionTime,
3131
SchedulingWithIndividualDeadlines, SequencingToMinimizeMaximumCumulativeCost,
3232
SequencingToMinimizeWeightedCompletionTime, SequencingToMinimizeWeightedTardiness,
3333
SequencingWithReleaseTimesAndDeadlines, SequencingWithinIntervals, ShortestCommonSupersequence,
@@ -708,6 +708,9 @@ fn example_for(canonical: &str, graph_type: Option<&str>) -> &'static str {
708708
}
709709
"MinimumFeedbackArcSet" => "--arcs \"0>1,1>2,2>0\"",
710710
"MinimumDummyActivitiesPert" => "--arcs \"0>2,0>3,1>3,1>4,2>5\" --num-vertices 6",
711+
"RegisterSufficiency" => {
712+
"--arcs \"2>0,2>1,3>1,4>2,4>3,5>0,6>4,6>5\" --bound 3 --num-vertices 7"
713+
}
711714
"StrongConnectivityAugmentation" => {
712715
"--arcs \"0>1,1>2\" --candidate-arcs \"2>0:1\" --bound 1"
713716
}
@@ -4220,6 +4223,34 @@ pub fn create(args: &CreateArgs, out: &OutputConfig) -> Result<()> {
42204223
)
42214224
}
42224225

4226+
// RegisterSufficiency
4227+
"RegisterSufficiency" => {
4228+
let usage = "Usage: pred create RegisterSufficiency --arcs \"2>0,2>1,3>1,4>2,4>3,5>0,6>4,6>5\" --bound 3 [--num-vertices N]";
4229+
let arcs_str = args.arcs.as_deref().ok_or_else(|| {
4230+
anyhow::anyhow!(
4231+
"RegisterSufficiency requires --arcs and --bound\n\n\
4232+
{usage}"
4233+
)
4234+
})?;
4235+
let bound = args.bound.ok_or_else(|| {
4236+
anyhow::anyhow!(
4237+
"RegisterSufficiency requires --bound\n\n\
4238+
{usage}"
4239+
)
4240+
})?;
4241+
if bound < 0 {
4242+
bail!("RegisterSufficiency --bound must be non-negative\n\n{usage}");
4243+
}
4244+
let bound = bound as usize;
4245+
let (graph, _) = parse_directed_graph(arcs_str, args.num_vertices)?;
4246+
let n = graph.num_vertices();
4247+
let arcs = graph.arcs();
4248+
(
4249+
ser(RegisterSufficiency::new(n, arcs, bound))?,
4250+
resolved_variant.clone(),
4251+
)
4252+
}
4253+
42234254
// MixedChinesePostman
42244255
"MixedChinesePostman" => {
42254256
let usage = "Usage: pred create MixedChinesePostman --graph 0-2,1-3,0-4,4-2 --arcs \"0>1,1>2,2>3,3>0\" --edge-weights 2,3,1,2 --arc-costs 2,3,1,4 [--num-vertices N]";

problemreductions-cli/tests/cli_tests.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4088,6 +4088,38 @@ fn test_create_rectilinear_picture_compression_rejects_ragged_matrix() {
40884088
);
40894089
}
40904090

4091+
#[test]
4092+
fn test_create_register_sufficiency() {
4093+
let output_file = std::env::temp_dir().join("pred_test_create_register_sufficiency.json");
4094+
let output = pred()
4095+
.args([
4096+
"-o",
4097+
output_file.to_str().unwrap(),
4098+
"create",
4099+
"RegisterSufficiency",
4100+
"--arcs",
4101+
"2>0,2>1,3>1,4>2,4>3,5>0,6>4,6>5",
4102+
"--bound",
4103+
"3",
4104+
"--num-vertices",
4105+
"7",
4106+
])
4107+
.output()
4108+
.unwrap();
4109+
assert!(
4110+
output.status.success(),
4111+
"stderr: {}",
4112+
String::from_utf8_lossy(&output.stderr)
4113+
);
4114+
let content = std::fs::read_to_string(&output_file).unwrap();
4115+
let json: serde_json::Value = serde_json::from_str(&content).unwrap();
4116+
assert_eq!(json["type"], "RegisterSufficiency");
4117+
assert_eq!(json["data"]["num_vertices"], 7);
4118+
assert_eq!(json["data"]["bound"], 3);
4119+
assert_eq!(json["data"]["arcs"].as_array().unwrap().len(), 8);
4120+
std::fs::remove_file(&output_file).ok();
4121+
}
4122+
40914123
#[test]
40924124
fn test_create_help_uses_generic_matrix_and_k_descriptions() {
40934125
let output = pred().args(["create", "--help"]).output().unwrap();

src/models/misc/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
//! - [`PrecedenceConstrainedScheduling`]: Schedule unit tasks on processors by deadline
2525
//! - [`ProductionPlanning`]: Meet all period demands within capacity and total-cost bounds
2626
//! - [`RectilinearPictureCompression`]: Cover 1-entries with bounded rectangles
27+
//! - [`RegisterSufficiency`]: Evaluate DAG computation with bounded registers
2728
//! - [`ResourceConstrainedScheduling`]: Schedule unit-length tasks on processors with resource constraints
2829
//! - [`SchedulingWithIndividualDeadlines`]: Meet per-task deadlines on parallel processors
2930
//! - [`StackerCrane`]: Minimize the total length of a closed walk through required arcs
@@ -89,6 +90,7 @@ pub(crate) mod partition;
8990
mod precedence_constrained_scheduling;
9091
mod production_planning;
9192
mod rectilinear_picture_compression;
93+
mod register_sufficiency;
9294
pub(crate) mod resource_constrained_scheduling;
9395
mod scheduling_to_minimize_weighted_completion_time;
9496
mod scheduling_with_individual_deadlines;
@@ -134,6 +136,7 @@ pub use partition::Partition;
134136
pub use precedence_constrained_scheduling::PrecedenceConstrainedScheduling;
135137
pub use production_planning::ProductionPlanning;
136138
pub use rectilinear_picture_compression::RectilinearPictureCompression;
139+
pub use register_sufficiency::RegisterSufficiency;
137140
pub use resource_constrained_scheduling::ResourceConstrainedScheduling;
138141
pub use scheduling_to_minimize_weighted_completion_time::SchedulingToMinimizeWeightedCompletionTime;
139142
pub use scheduling_with_individual_deadlines::SchedulingWithIndividualDeadlines;
@@ -195,6 +198,7 @@ pub(crate) fn canonical_model_example_specs() -> Vec<crate::example_db::specs::M
195198
specs.extend(subset_sum::canonical_model_example_specs());
196199
specs.extend(three_partition::canonical_model_example_specs());
197200
specs.extend(cosine_product_integration::canonical_model_example_specs());
201+
specs.extend(register_sufficiency::canonical_model_example_specs());
198202
specs.extend(kth_largest_m_tuple::canonical_model_example_specs());
199203
specs
200204
}

0 commit comments

Comments
 (0)