Skip to content

Commit 6bb3e9c

Browse files
zazabapclaudeisPANN
authored
Fix #494: Add SequencingWithReleaseTimesAndDeadlines model (#633)
* Fix #494: Add SequencingWithReleaseTimesAndDeadlines model Add the single-machine scheduling feasibility problem (Garey & Johnson A5 SS1): given tasks with processing times, release times, and deadlines, determine if a non-preemptive schedule exists. Strongly NP-complete. - Model implementation with Problem/SatisfactionProblem traits - CLI dispatch (load/serialize) and creation support - 13 unit tests covering feasibility, infeasibility, brute-force solver - Paper documentation in reductions.typ - Schema registration Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * merge: resolve conflicts with main Resolve merge conflicts from origin/main: - Accept main's deletion of per-reduction example binaries - Merge registry-based dispatch (main) with PR's model registration - Combine both sides' additive entries in paper, schemas, CLI, and module files - Fix declare_variants! syntax and ProblemSchemaEntry fields to match current API Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: use permutation encoding (Lehmer code) for SequencingWithReleaseTimesAndDeadlines Switch from start-time encoding to permutation encoding consistent with MinimumTardinessSequencing, as recommended in issue #494 review. This: - Uses dims = [n, n-1, ..., 2, 1] instead of [max_deadline; n] - Eliminates overflow concerns (no u64 arithmetic on config values) - Dramatically reduces brute-force search space - Schedules tasks left-to-right with greedy start times Addresses Copilot review comments about overflow protection and inflated search space. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add canonical example and trait_consistency entry for SequencingWithReleaseTimesAndDeadlines Add missing structural completeness items: - Canonical model example in example-db (Lehmer code [3,0,0,0,0] for 5-task instance) - trait_consistency test entry Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Replace hand-written feasibility test with brute-force enumeration The canonical 5-task instance now verified by BruteForce::find_all_satisfying, confirming exactly one feasible schedule exists (Lehmer code [3,0,0,0,0]). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Remove duplicate lengths/release_times CLI fields These fields already exist on main (lines 442-445); the PR's copies at lines 467-472 cause E0124 after merge. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Remove duplicate lengths/release_times checks in all_data_flags_empty Lines 86-87 duplicated the checks already at lines 76-78 after merge. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Xiwei Pan <xiwei.pan@connect.hkust-gz.edu.cn> Co-authored-by: Xiwei Pan <90967972+isPANN@users.noreply.github.com>
1 parent 514d5ff commit 6bb3e9c

10 files changed

Lines changed: 430 additions & 19 deletions

File tree

docs/paper/reductions.typ

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@
108108
"SubsetSum": [Subset Sum],
109109
"MinimumFeedbackArcSet": [Minimum Feedback Arc Set],
110110
"MinimumFeedbackVertexSet": [Minimum Feedback Vertex Set],
111+
"SequencingWithReleaseTimesAndDeadlines": [Sequencing with Release Times and Deadlines],
111112
"MultipleChoiceBranching": [Multiple Choice Branching],
112113
"ShortestCommonSupersequence": [Shortest Common Supersequence],
113114
"MinimumSumMulticenter": [Minimum Sum Multicenter],
@@ -2273,6 +2274,48 @@ NP-completeness was established by Garey, Johnson, and Stockmeyer @gareyJohnsonS
22732274
*Example.* Let $A = {3, 7, 1, 8, 2, 4}$ ($n = 6$) and target $B = 11$. Selecting $A' = {3, 8}$ gives sum $3 + 8 = 11 = B$. Another solution: $A' = {7, 4}$ with sum $7 + 4 = 11 = B$.
22742275
]
22752276

2277+
#{
2278+
let x = load-model-example("SequencingWithReleaseTimesAndDeadlines")
2279+
let n = x.instance.lengths.len()
2280+
let lengths = x.instance.lengths
2281+
let release = x.instance.release_times
2282+
let deadline = x.instance.deadlines
2283+
let sol = x.optimal.at(0)
2284+
// Decode Lehmer code to permutation
2285+
let available = range(n)
2286+
let perm = ()
2287+
for c in sol.config {
2288+
perm = perm + (available.at(c),)
2289+
available = available.slice(0, c) + available.slice(c + 1)
2290+
}
2291+
// Compute start times by simulating the schedule (build (task_idx, start) pairs)
2292+
let current = 0
2293+
let schedule = ()
2294+
for idx in perm {
2295+
let s = calc.max(current, release.at(idx))
2296+
schedule = schedule + ((idx, s),)
2297+
current = s + lengths.at(idx)
2298+
}
2299+
[
2300+
#problem-def("SequencingWithReleaseTimesAndDeadlines")[
2301+
Given a set $T$ of $n$ tasks and, for each task $t in T$, a processing time $ell(t) in ZZ^+$, a release time $r(t) in ZZ^(>=0)$, and a deadline $d(t) in ZZ^+$, determine whether there exists a one-processor schedule $sigma: T -> ZZ^(>=0)$ such that for all $t in T$: $sigma(t) >= r(t)$, $sigma(t) + ell(t) <= d(t)$, and no two tasks overlap (i.e., $sigma(t) > sigma(t')$ implies $sigma(t) >= sigma(t') + ell(t')$).
2302+
][
2303+
Problem SS1 in Garey and Johnson's appendix @garey1979, and a fundamental single-machine scheduling feasibility problem. It is strongly NP-complete by reduction from 3-Partition, so no pseudo-polynomial time algorithm exists unless P = NP. The problem becomes polynomial-time solvable when: (1) all task lengths equal 1, (2) preemption is allowed, or (3) all release times are zero. The best known exact algorithm for the general case runs in $O^*(2^n dot n)$ time via dynamic programming on task subsets.
2304+
2305+
*Example.* Consider #n tasks:
2306+
#align(center, table(
2307+
columns: n + 1,
2308+
align: center,
2309+
table.header([], ..range(n).map(i => [$t_#(i + 1)$])),
2310+
[$ell(t)$], ..lengths.map(l => [#l]),
2311+
[$r(t)$], ..release.map(r => [#r]),
2312+
[$d(t)$], ..deadline.map(d => [#d]),
2313+
))
2314+
A feasible schedule: #schedule.map(((idx, s)) => [$sigma(t_#(idx + 1)) = #s$ (runs $[#s, #(s + lengths.at(idx)))$)]).join([, ]). All release and deadline constraints are satisfied with no overlap.
2315+
]
2316+
]
2317+
}
2318+
22762319
#{
22772320
let x = load-model-example("ShortestCommonSupersequence")
22782321
let alpha-size = x.instance.alphabet_size

problemreductions-cli/src/cli.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ pub struct CreateArgs {
473473
/// Candidate weighted arcs for StrongConnectivityAugmentation (e.g., 2>0:1,2>1:3)
474474
#[arg(long)]
475475
pub candidate_arcs: Option<String>,
476-
/// Deadlines for MinimumTardinessSequencing (comma-separated, e.g., "5,5,5,3,3")
476+
/// Deadlines for scheduling problems (comma-separated, e.g., "5,5,5,3,3")
477477
#[arg(long)]
478478
pub deadlines: Option<String>,
479479
/// Precedence pairs for MinimumTardinessSequencing (e.g., "0>3,1>3,1>4,2>4")

problemreductions-cli/src/commands/create.rs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ use problemreductions::models::graph::{
1414
};
1515
use problemreductions::models::misc::{
1616
BinPacking, FlowShopScheduling, LongestCommonSubsequence, MinimumTardinessSequencing,
17-
MultiprocessorScheduling, PaintShop, SequencingWithinIntervals, ShortestCommonSupersequence,
18-
StringToStringCorrection, SubsetSum,
17+
MultiprocessorScheduling, PaintShop, SequencingWithReleaseTimesAndDeadlines,
18+
SequencingWithinIntervals, ShortestCommonSupersequence, StringToStringCorrection, SubsetSum,
1919
};
2020
use problemreductions::models::BiconnectivityAugmentation;
2121
use problemreductions::prelude::*;
@@ -1900,6 +1900,47 @@ pub fn create(args: &CreateArgs, out: &OutputConfig) -> Result<()> {
19001900
)
19011901
}
19021902

1903+
// SequencingWithReleaseTimesAndDeadlines
1904+
"SequencingWithReleaseTimesAndDeadlines" => {
1905+
let lengths_str = args.lengths.as_deref().ok_or_else(|| {
1906+
anyhow::anyhow!(
1907+
"SequencingWithReleaseTimesAndDeadlines requires --lengths, --release-times, and --deadlines\n\n\
1908+
Usage: pred create SequencingWithReleaseTimesAndDeadlines --lengths 3,2,4 --release-times 0,1,5 --deadlines 5,6,10"
1909+
)
1910+
})?;
1911+
let release_str = args.release_times.as_deref().ok_or_else(|| {
1912+
anyhow::anyhow!(
1913+
"SequencingWithReleaseTimesAndDeadlines requires --release-times\n\n\
1914+
Usage: pred create SequencingWithReleaseTimesAndDeadlines --lengths 3,2,4 --release-times 0,1,5 --deadlines 5,6,10"
1915+
)
1916+
})?;
1917+
let deadlines_str = args.deadlines.as_deref().ok_or_else(|| {
1918+
anyhow::anyhow!(
1919+
"SequencingWithReleaseTimesAndDeadlines requires --deadlines\n\n\
1920+
Usage: pred create SequencingWithReleaseTimesAndDeadlines --lengths 3,2,4 --release-times 0,1,5 --deadlines 5,6,10"
1921+
)
1922+
})?;
1923+
let lengths: Vec<u64> = util::parse_comma_list(lengths_str)?;
1924+
let release_times: Vec<u64> = util::parse_comma_list(release_str)?;
1925+
let deadlines: Vec<u64> = util::parse_comma_list(deadlines_str)?;
1926+
if lengths.len() != release_times.len() || lengths.len() != deadlines.len() {
1927+
bail!(
1928+
"All three lists must have the same length: lengths={}, release_times={}, deadlines={}",
1929+
lengths.len(),
1930+
release_times.len(),
1931+
deadlines.len()
1932+
);
1933+
}
1934+
(
1935+
ser(SequencingWithReleaseTimesAndDeadlines::new(
1936+
lengths,
1937+
release_times,
1938+
deadlines,
1939+
))?,
1940+
resolved_variant.clone(),
1941+
)
1942+
}
1943+
19031944
// StringToStringCorrection
19041945
"StringToStringCorrection" => {
19051946
let usage = "Usage: pred create StringToStringCorrection --source-string \"0,1,2,3,1,0\" --target-string \"0,1,3,2,1\" --bound 2";

0 commit comments

Comments
 (0)