Skip to content
Open
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 @@ -96,6 +96,7 @@
"LongestCommonSubsequence": [Longest Common Subsequence],
"ExactCoverBy3Sets": [Exact Cover by 3-Sets],
"SubsetSum": [Subset Sum],
"Partition": [Partition],
"MinimumFeedbackArcSet": [Minimum Feedback Arc Set],
"MinimumFeedbackVertexSet": [Minimum Feedback Vertex Set],
"ShortestCommonSupersequence": [Shortest Common Supersequence],
Expand Down Expand Up @@ -1705,6 +1706,14 @@ NP-completeness was established by Garey, Johnson, and Stockmeyer @gareyJohnsonS
*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$.
]

#problem-def("Partition")[
Given a finite set $A = {a_0, dots, a_(n-1)}$ with sizes $s(a_i) in ZZ^+$, determine whether there exists a subset $A' subset.eq A$ such that $sum_(a in A') s(a) = sum_(a in A without A') s(a)$.
][
One of Karp's 21 NP-complete problems @karp1972, listed as SP12 in Garey & Johnson @garey1979. Partition is the special case of Subset Sum where the target equals half the total sum. Though NP-complete, it is only _weakly_ NP-hard: a dynamic-programming algorithm runs in $O(n dot B_"total")$ pseudo-polynomial time, where $B_"total" = sum_i s(a_i)$. The best known exact algorithm is the $O^*(2^(n slash 2))$ meet-in-the-middle approach of Schroeppel and Shamir (1981).

*Example.* Let $A = {3, 1, 1, 2, 2, 1}$ ($n = 6$, total sum $= 10$). Setting $A' = {3, 2}$ (indices 0, 3) gives sum $3 + 2 = 5 = 10 slash 2$, and $A without A' = {1, 1, 2, 1}$ also sums to 5. Hence a balanced partition exists.
]

#{
let x = load-model-example("ShortestCommonSupersequence")
let alpha-size = x.instance.alphabet_size
Expand Down
11 changes: 11 additions & 0 deletions docs/src/reductions/problem_schemas.json
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,17 @@
}
]
},
{
"name": "Partition",
"description": "Determine whether a multiset of positive integers can be partitioned into two subsets of equal sum",
"fields": [
{
"name": "sizes",
"type_name": "Vec<u64>",
"description": "Positive integer size for each element"
}
]
},
{
"name": "PartitionIntoTriangles",
"description": "Partition vertices into triangles (K3 subgraphs)",
Expand Down
59 changes: 33 additions & 26 deletions docs/src/reductions/reduction_graph.json
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,13 @@
"doc_path": "models/misc/struct.PaintShop.html",
"complexity": "2^num_cars"
},
{
"name": "Partition",
"variant": {},
"category": "misc",
"doc_path": "models/misc/struct.Partition.html",
"complexity": "2^(num_elements / 2)"
},
{
"name": "PartitionIntoTriangles",
"variant": {
Expand Down Expand Up @@ -569,7 +576,7 @@
},
{
"source": 4,
"target": 54,
"target": 55,
"overhead": [
{
"field": "num_spins",
Expand Down Expand Up @@ -629,7 +636,7 @@
},
{
"source": 12,
"target": 49,
"target": 50,
"overhead": [
{
"field": "num_vars",
Expand Down Expand Up @@ -670,7 +677,7 @@
},
{
"source": 19,
"target": 49,
"target": 50,
"overhead": [
{
"field": "num_vars",
Expand All @@ -696,7 +703,7 @@
},
{
"source": 20,
"target": 49,
"target": 50,
"overhead": [
{
"field": "num_vars",
Expand All @@ -722,7 +729,7 @@
},
{
"source": 21,
"target": 49,
"target": 50,
"overhead": [
{
"field": "num_vars",
Expand All @@ -733,7 +740,7 @@
},
{
"source": 21,
"target": 58,
"target": 59,
"overhead": [
{
"field": "num_elements",
Expand All @@ -744,7 +751,7 @@
},
{
"source": 22,
"target": 51,
"target": 52,
"overhead": [
{
"field": "num_clauses",
Expand All @@ -763,7 +770,7 @@
},
{
"source": 23,
"target": 49,
"target": 50,
"overhead": [
{
"field": "num_vars",
Expand All @@ -789,7 +796,7 @@
},
{
"source": 25,
"target": 54,
"target": 55,
"overhead": [
{
"field": "num_spins",
Expand Down Expand Up @@ -1104,7 +1111,7 @@
},
{
"source": 37,
"target": 49,
"target": 50,
"overhead": [
{
"field": "num_vars",
Expand Down Expand Up @@ -1219,7 +1226,7 @@
"doc_path": "rules/minimumvertexcover_minimumsetcovering/index.html"
},
{
"source": 49,
"source": 50,
"target": 12,
"overhead": [
{
Expand All @@ -1234,8 +1241,8 @@
"doc_path": "rules/qubo_ilp/index.html"
},
{
"source": 49,
"target": 53,
"source": 50,
"target": 54,
"overhead": [
{
"field": "num_spins",
Expand All @@ -1245,7 +1252,7 @@
"doc_path": "rules/spinglass_qubo/index.html"
},
{
"source": 51,
"source": 52,
"target": 4,
"overhead": [
{
Expand All @@ -1260,7 +1267,7 @@
"doc_path": "rules/sat_circuitsat/index.html"
},
{
"source": 51,
"source": 52,
"target": 16,
"overhead": [
{
Expand All @@ -1275,7 +1282,7 @@
"doc_path": "rules/sat_coloring/index.html"
},
{
"source": 51,
"source": 52,
"target": 21,
"overhead": [
{
Expand All @@ -1290,7 +1297,7 @@
"doc_path": "rules/sat_ksat/index.html"
},
{
"source": 51,
"source": 52,
"target": 30,
"overhead": [
{
Expand All @@ -1305,7 +1312,7 @@
"doc_path": "rules/sat_maximumindependentset/index.html"
},
{
"source": 51,
"source": 52,
"target": 39,
"overhead": [
{
Expand All @@ -1320,8 +1327,8 @@
"doc_path": "rules/sat_minimumdominatingset/index.html"
},
{
"source": 53,
"target": 49,
"source": 54,
"target": 50,
"overhead": [
{
"field": "num_vars",
Expand All @@ -1331,7 +1338,7 @@
"doc_path": "rules/spinglass_qubo/index.html"
},
{
"source": 54,
"source": 55,
"target": 25,
"overhead": [
{
Expand All @@ -1346,8 +1353,8 @@
"doc_path": "rules/spinglass_maxcut/index.html"
},
{
"source": 54,
"target": 53,
"source": 55,
"target": 54,
"overhead": [
{
"field": "num_spins",
Expand All @@ -1361,7 +1368,7 @@
"doc_path": "rules/spinglass_casts/index.html"
},
{
"source": 59,
"source": 60,
"target": 12,
"overhead": [
{
Expand All @@ -1376,8 +1383,8 @@
"doc_path": "rules/travelingsalesman_ilp/index.html"
},
{
"source": 59,
"target": 49,
"source": 60,
"target": 50,
"overhead": [
{
"field": "num_vars",
Expand Down
1 change: 1 addition & 0 deletions src/example_db/fixtures/examples.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
{"problem":"MinimumTardinessSequencing","variant":{},"instance":{"deadlines":[2,3,1,4],"num_tasks":4,"precedences":[[0,2]]},"samples":[{"config":[0,0,0,0],"metric":{"Valid":1}}],"optimal":[{"config":[0,0,0,0],"metric":{"Valid":1}},{"config":[0,0,1,0],"metric":{"Valid":1}},{"config":[0,1,0,0],"metric":{"Valid":1}},{"config":[0,2,0,0],"metric":{"Valid":1}},{"config":[1,0,0,0],"metric":{"Valid":1}},{"config":[1,0,1,0],"metric":{"Valid":1}},{"config":[3,0,0,0],"metric":{"Valid":1}}]},
{"problem":"MinimumVertexCover","variant":{"graph":"SimpleGraph","weight":"i32"},"instance":{"graph":{"inner":{"edge_property":"undirected","edges":[[0,1,null],[0,2,null],[1,3,null],[2,3,null],[2,4,null],[3,4,null]],"node_holes":[],"nodes":[null,null,null,null,null]}},"weights":[1,1,1,1,1]},"samples":[{"config":[1,0,0,1,1],"metric":{"Valid":3}}],"optimal":[{"config":[0,1,1,0,1],"metric":{"Valid":3}},{"config":[0,1,1,1,0],"metric":{"Valid":3}},{"config":[1,0,0,1,1],"metric":{"Valid":3}},{"config":[1,0,1,1,0],"metric":{"Valid":3}}]},
{"problem":"PaintShop","variant":{},"instance":{"car_labels":["A","B","C"],"is_first":[true,true,false,true,false,false],"num_cars":3,"sequence_indices":[0,1,0,2,1,2]},"samples":[{"config":[0,0,1],"metric":{"Valid":2}}],"optimal":[{"config":[0,0,1],"metric":{"Valid":2}},{"config":[0,1,1],"metric":{"Valid":2}},{"config":[1,0,0],"metric":{"Valid":2}},{"config":[1,1,0],"metric":{"Valid":2}}]},
{"problem":"Partition","variant":{},"instance":{"sizes":[3,1,1,2,2,1]},"samples":[{"config":[1,0,0,1,0,0],"metric":true},{"config":[0,0,0,0,0,0],"metric":false}],"optimal":[{"config":[0,0,0,1,1,1],"metric":true},{"config":[0,0,1,1,1,0],"metric":true},{"config":[0,1,0,1,1,0],"metric":true},{"config":[0,1,1,0,1,1],"metric":true},{"config":[0,1,1,1,0,1],"metric":true},{"config":[1,0,0,0,1,0],"metric":true},{"config":[1,0,0,1,0,0],"metric":true},{"config":[1,0,1,0,0,1],"metric":true},{"config":[1,1,0,0,0,1],"metric":true},{"config":[1,1,1,0,0,0],"metric":true}]},
{"problem":"PartitionIntoTriangles","variant":{"graph":"SimpleGraph"},"instance":{"graph":{"inner":{"edge_property":"undirected","edges":[[0,1,null],[0,2,null],[1,2,null],[3,4,null],[3,5,null],[4,5,null],[0,3,null]],"node_holes":[],"nodes":[null,null,null,null,null,null]}}},"samples":[{"config":[0,0,0,1,1,1],"metric":true}],"optimal":[{"config":[0,0,0,1,1,1],"metric":true},{"config":[1,1,1,0,0,0],"metric":true}]},
{"problem":"QUBO","variant":{"weight":"f64"},"instance":{"matrix":[[-1.0,2.0,0.0],[0.0,-1.0,2.0],[0.0,0.0,-1.0]],"num_vars":3},"samples":[{"config":[1,0,1],"metric":{"Valid":-2.0}}],"optimal":[{"config":[1,0,1],"metric":{"Valid":-2.0}}]},
{"problem":"Satisfiability","variant":{},"instance":{"clauses":[{"literals":[1,2]},{"literals":[-1,3]},{"literals":[-2,-3]}],"num_vars":3},"samples":[{"config":[1,0,1],"metric":true}],"optimal":[{"config":[0,1,0],"metric":true},{"config":[1,0,1],"metric":true}]},
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ pub mod prelude {
};
pub use crate::models::misc::{
BinPacking, Factoring, FlowShopScheduling, Knapsack, LongestCommonSubsequence,
MinimumTardinessSequencing, PaintShop, ShortestCommonSupersequence, SubsetSum,
MinimumTardinessSequencing, PaintShop, Partition, ShortestCommonSupersequence, SubsetSum,
};
pub use crate::models::set::{ExactCoverBy3Sets, MaximumSetPacking, MinimumSetCovering};

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 @@ -8,6 +8,7 @@
//! - [`LongestCommonSubsequence`]: Longest Common Subsequence
//! - [`MinimumTardinessSequencing`]: Minimize tardy tasks in single-machine scheduling
//! - [`PaintShop`]: Minimize color switches in paint shop scheduling
//! - [`Partition`]: Partition a multiset into two equal-sum subsets
//! - [`ShortestCommonSupersequence`]: Find a common supersequence of bounded length
//! - [`SubsetSum`]: Find a subset summing to exactly a target value

Expand All @@ -18,6 +19,7 @@ mod knapsack;
mod longest_common_subsequence;
mod minimum_tardiness_sequencing;
pub(crate) mod paintshop;
pub(crate) mod partition;
pub(crate) mod shortest_common_supersequence;
mod subset_sum;

Expand All @@ -28,6 +30,7 @@ pub use knapsack::Knapsack;
pub use longest_common_subsequence::LongestCommonSubsequence;
pub use minimum_tardiness_sequencing::MinimumTardinessSequencing;
pub use paintshop::PaintShop;
pub use partition::Partition;
pub use shortest_common_supersequence::ShortestCommonSupersequence;
pub use subset_sum::SubsetSum;

Expand All @@ -36,6 +39,7 @@ pub(crate) fn canonical_model_example_specs() -> Vec<crate::example_db::specs::M
let mut specs = Vec::new();
specs.extend(factoring::canonical_model_example_specs());
specs.extend(paintshop::canonical_model_example_specs());
specs.extend(partition::canonical_model_example_specs());
specs.extend(shortest_common_supersequence::canonical_model_example_specs());
specs.extend(minimum_tardiness_sequencing::canonical_model_example_specs());
specs
Expand Down
Loading
Loading