Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions docs/paper/reductions.typ
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
"QUBO": [QUBO],
"ILP": [Integer Linear Programming],
"Knapsack": [Knapsack],
"PartiallyOrderedKnapsack": [Partially Ordered Knapsack],
"Satisfiability": [SAT],
"KSatisfiability": [$k$-SAT],
"CircuitSAT": [CircuitSAT],
Expand Down Expand Up @@ -2477,6 +2478,14 @@ NP-completeness was established by Garey, Johnson, and Stockmeyer @gareyJohnsonS
*Example.* Let $n = 4$ items with weights $(2, 3, 4, 5)$, values $(3, 4, 5, 7)$, and capacity $C = 7$. Selecting $S = {1, 2}$ (items with weights 3 and 4) gives total weight $3 + 4 = 7 lt.eq C$ and total value $4 + 5 = 9$. Selecting $S = {0, 3}$ (weights 2 and 5) gives weight $2 + 5 = 7 lt.eq C$ and value $3 + 7 = 10$, which is optimal.
]

#problem-def("PartiallyOrderedKnapsack")[
Given $n$ items with weights $w_0, dots, w_(n-1) in NN$ and values $v_0, dots, v_(n-1) in NN$, a partial order $prec$ on the items (given by its cover relations), and a capacity $C in NN$, find a downward-closed subset $S subset.eq {0, dots, n - 1}$ (i.e., if $i in S$ and $j prec i$ then $j in S$) maximizing $sum_(i in S) v_i$ subject to $sum_(i in S) w_i lt.eq C$.
][
Garey and Johnson's problem A6 MP12 @garey1979. Unlike standard Knapsack, the partial order constraint makes the problem _strongly_ NP-complete --- it remains NP-complete even when $w_i = v_i$ for all $i$, so no pseudo-polynomial algorithm exists unless $P = N P$. The problem arises in manufacturing scheduling, project selection, and mining operations. For tree partial orders, Johnson and Niemi @johnson1983 gave pseudo-polynomial $O(n dot C)$ tree DP and an FPTAS. Kolliopoulos and Steiner @kolliopoulos2007 extended the FPTAS to 2-dimensional partial orders with $O(n^4 slash epsilon)$ running time.

*Example.* Let $n = 6$ items with weights $(2, 3, 4, 1, 2, 3)$, values $(3, 2, 5, 4, 3, 8)$, and capacity $C = 11$. The partial order has cover relations $0 prec 2$, $0 prec 3$, $1 prec 4$, $3 prec 5$, $4 prec 5$. Selecting $S = {0, 1, 3, 4, 5}$ is downward-closed (all predecessors included), has total weight $2 + 3 + 1 + 2 + 3 = 11 lt.eq C$, and total value $3 + 2 + 4 + 3 + 8 = 20$. Adding item 2 would exceed capacity ($15 > 11$).
]

#{
let x = load-model-example("RectilinearPictureCompression")
let mat = x.instance.matrix
Expand Down
22 changes: 22 additions & 0 deletions docs/paper/references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,28 @@ @article{cygan2014
doi = {10.1137/140990255}
}

@article{johnson1983,
author = {David S. Johnson and Kenneth A. Niemi},
title = {On Knapsacks, Partitions, and a New Dynamic Programming Technique for Trees},
journal = {Mathematics of Operations Research},
volume = {8},
number = {1},
pages = {1--14},
year = {1983},
doi = {10.1287/moor.8.1.1}
}

@article{kolliopoulos2007,
author = {Stavros G. Kolliopoulos and George Steiner},
title = {Partially Ordered Knapsack and Applications to Scheduling},
journal = {Discrete Applied Mathematics},
volume = {155},
number = {8},
pages = {889--897},
year = {2007},
doi = {10.1016/j.dam.2006.09.003}
}

@article{raiha1981,
author = {Kari-Jouko R{\"a}ih{\"a} and Esko Ukkonen},
title = {The Shortest Common Supersequence Problem over Binary Alphabet is {NP}-Complete},
Expand Down
7 changes: 7 additions & 0 deletions problemreductions-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ Flags by problem type:
LCS --strings, --bound [--alphabet-size]
FAS --arcs [--weights] [--num-vertices]
FVS --arcs [--weights] [--num-vertices]
PartiallyOrderedKnapsack --sizes, --values, --capacity, --precedences
QAP --matrix (cost), --distance-matrix
StrongConnectivityAugmentation --arcs, --candidate-arcs, --bound [--num-vertices]
FlowShopScheduling --task-lengths, --deadline [--num-processors]
Expand Down Expand Up @@ -472,6 +473,12 @@ pub struct CreateArgs {
/// Directed arcs for directed graph problems (e.g., 0>1,1>2,2>0)
#[arg(long)]
pub arcs: Option<String>,
/// Item values (e.g., 3,4,5,7) for PartiallyOrderedKnapsack
#[arg(long)]
pub values: Option<String>,
/// Precedence pairs (e.g., "0>2,0>3,1>4") for PartiallyOrderedKnapsack
#[arg(long, alias = "item-precedences")]
pub precedences: Option<String>,
/// Distance matrix for QuadraticAssignment (semicolon-separated rows, e.g., "0,1,2;1,0,1;2,1,0")
#[arg(long)]
pub distance_matrix: Option<String>,
Expand Down
56 changes: 53 additions & 3 deletions problemreductions-cli/src/commands/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ use problemreductions::models::graph::{
};
use problemreductions::models::misc::{
BinPacking, FlowShopScheduling, LongestCommonSubsequence, MinimumTardinessSequencing,
MultiprocessorScheduling, PaintShop, RectilinearPictureCompression,
SequencingWithReleaseTimesAndDeadlines, SequencingWithinIntervals, ShortestCommonSupersequence,
StringToStringCorrection, SubsetSum, SumOfSquaresPartition,
MultiprocessorScheduling, PaintShop, PartiallyOrderedKnapsack, RectilinearPictureCompression,
SequencingWithReleaseTimesAndDeadlines, SequencingWithinIntervals,
ShortestCommonSupersequence, StringToStringCorrection, SubsetSum, SumOfSquaresPartition,
};
use problemreductions::models::BiconnectivityAugmentation;
use problemreductions::prelude::*;
Expand Down Expand Up @@ -84,6 +84,8 @@ fn all_data_flags_empty(args: &CreateArgs) -> bool {
&& args.pattern.is_none()
&& args.strings.is_none()
&& args.arcs.is_none()
&& args.values.is_none()
&& args.precedences.is_none()
&& args.distance_matrix.is_none()
&& args.candidate_arcs.is_none()
&& args.potential_edges.is_none()
Expand Down Expand Up @@ -2104,6 +2106,52 @@ pub fn create(args: &CreateArgs, out: &OutputConfig) -> Result<()> {
)
}

// PartiallyOrderedKnapsack
"PartiallyOrderedKnapsack" => {
let sizes_str = args.sizes.as_deref().ok_or_else(|| {
anyhow::anyhow!(
"PartiallyOrderedKnapsack requires --sizes, --values, and --capacity (--precedences is optional)\n\n\
Usage: pred create PartiallyOrderedKnapsack --sizes 2,3,4,1,2,3 --values 3,2,5,4,3,8 --precedences \"0>2,0>3,1>4,3>5,4>5\" --capacity 11"
)
})?;
let values_str = args.values.as_deref().ok_or_else(|| {
anyhow::anyhow!("PartiallyOrderedKnapsack requires --values (e.g., 3,2,5,4,3,8)")
})?;
let cap_str = args.capacity.as_deref().ok_or_else(|| {
anyhow::anyhow!("PartiallyOrderedKnapsack requires --capacity (e.g., 11)")
})?;
let weights: Vec<i64> = util::parse_comma_list(sizes_str)?;
let values: Vec<i64> = util::parse_comma_list(values_str)?;
let capacity: i64 = cap_str.parse()?;
let precedences = match args.precedences.as_deref() {
Some(s) if !s.trim().is_empty() => s
.split(',')
.map(|pair| {
let parts: Vec<&str> = pair.trim().split('>').collect();
anyhow::ensure!(
parts.len() == 2,
"Invalid precedence format '{}', expected 'a>b'",
pair.trim()
);
Ok((
parts[0].trim().parse::<usize>()?,
parts[1].trim().parse::<usize>()?,
))
})
.collect::<Result<Vec<_>>>()?,
_ => vec![],
};
(
ser(PartiallyOrderedKnapsack::new(
weights,
values,
precedences,
capacity,
))?,
resolved_variant.clone(),
)
}

// PrimeAttributeName
"PrimeAttributeName" => {
let universe = args.universe.ok_or_else(|| {
Expand Down Expand Up @@ -3788,6 +3836,8 @@ mod tests {
pattern: None,
strings: None,
arcs: None,
values: None,
precedences: None,
distance_matrix: None,
potential_edges: None,
budget: None,
Expand Down
4 changes: 4 additions & 0 deletions src/models/misc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
//! - [`LongestCommonSubsequence`]: Longest Common Subsequence
//! - [`MinimumTardinessSequencing`]: Minimize tardy tasks in single-machine scheduling
//! - [`PaintShop`]: Minimize color switches in paint shop scheduling
//! - [`PartiallyOrderedKnapsack`]: Knapsack with precedence constraints
//! - [`PrecedenceConstrainedScheduling`]: Schedule unit tasks on processors by deadline
//! - [`RectilinearPictureCompression`]: Cover 1-entries with bounded rectangles
//! - [`SequencingWithReleaseTimesAndDeadlines`]: Single-machine scheduling feasibility
Expand All @@ -26,6 +27,7 @@ mod longest_common_subsequence;
mod minimum_tardiness_sequencing;
mod multiprocessor_scheduling;
pub(crate) mod paintshop;
pub(crate) mod partially_ordered_knapsack;
mod precedence_constrained_scheduling;
mod rectilinear_picture_compression;
mod sequencing_with_release_times_and_deadlines;
Expand All @@ -44,6 +46,7 @@ pub use longest_common_subsequence::LongestCommonSubsequence;
pub use minimum_tardiness_sequencing::MinimumTardinessSequencing;
pub use multiprocessor_scheduling::MultiprocessorScheduling;
pub use paintshop::PaintShop;
pub use partially_ordered_knapsack::PartiallyOrderedKnapsack;
pub use precedence_constrained_scheduling::PrecedenceConstrainedScheduling;
pub use rectilinear_picture_compression::RectilinearPictureCompression;
pub use sequencing_with_release_times_and_deadlines::SequencingWithReleaseTimesAndDeadlines;
Expand All @@ -65,6 +68,7 @@ pub(crate) fn canonical_model_example_specs() -> Vec<crate::example_db::specs::M
specs.extend(sequencing_within_intervals::canonical_model_example_specs());
specs.extend(staff_scheduling::canonical_model_example_specs());
specs.extend(shortest_common_supersequence::canonical_model_example_specs());
specs.extend(partially_ordered_knapsack::canonical_model_example_specs());
specs.extend(string_to_string_correction::canonical_model_example_specs());
specs.extend(minimum_tardiness_sequencing::canonical_model_example_specs());
specs.extend(sum_of_squares_partition::canonical_model_example_specs());
Expand Down
Loading
Loading