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
41 changes: 41 additions & 0 deletions docs/paper/reductions.typ
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
"SubsetSum": [Subset Sum],
"MinimumFeedbackArcSet": [Minimum Feedback Arc Set],
"MinimumFeedbackVertexSet": [Minimum Feedback Vertex Set],
"MultipleChoiceBranching": [Multiple Choice Branching],
"ShortestCommonSupersequence": [Shortest Common Supersequence],
"MinimumSumMulticenter": [Minimum Sum Multicenter],
"SteinerTree": [Steiner Tree],
Expand Down Expand Up @@ -1945,6 +1946,46 @@ NP-completeness was established by Garey, Johnson, and Stockmeyer @gareyJohnsonS
*Example.* Consider $G$ with $V = {0, 1, 2, 3, 4, 5}$ and arcs $(0 arrow 1), (1 arrow 2), (2 arrow 0), (1 arrow 3), (3 arrow 4), (4 arrow 1), (2 arrow 5), (5 arrow 3), (3 arrow 0)$. This graph contains four directed cycles: $0 arrow 1 arrow 2 arrow 0$, $1 arrow 3 arrow 4 arrow 1$, $0 arrow 1 arrow 3 arrow 0$, and $2 arrow 5 arrow 3 arrow 0 arrow 1 arrow 2$. Removing $A' = {(0 arrow 1), (3 arrow 4)}$ breaks all four cycles (vertex 0 becomes a sink in the residual graph), giving a minimum FAS of size 2.
]

#{
let x = load-model-example("MultipleChoiceBranching")
let nv = graph-num-vertices(x.instance)
let arcs = x.instance.graph.inner.edges.map(e => (e.at(0), e.at(1)))
let sol = x.samples.at(0)
let chosen = sol.config.enumerate().filter(((i, v)) => v == 1).map(((i, _)) => i)
[
#problem-def("MultipleChoiceBranching")[
Given a directed graph $G = (V, A)$, arc weights $w: A -> ZZ^+$, a partition $A_1, A_2, dots, A_m$ of $A$, and a threshold $K in ZZ^+$, determine whether there exists a subset $A' subset.eq A$ with $sum_(a in A') w(a) >= K$ such that every vertex has in-degree at most one in $(V, A')$, the selected subgraph $(V, A')$ is acyclic, and $|A' inter A_i| <= 1$ for every partition group.
][
Multiple Choice Branching is the directed-graph problem ND11 in Garey & Johnson @garey1979. The partition constraint turns the polynomial-time maximum branching setting into an NP-complete decision problem: Garey and Johnson note that the problem remains NP-complete even when the digraph is strongly connected and all weights are equal, while the special case in which every partition group has size 1 reduces to ordinary maximum branching and becomes polynomial-time solvable @garey1979.

A conservative exact algorithm enumerates all $2^{|A|}$ arc subsets and checks the partition, in-degree, acyclicity, and threshold constraints in polynomial time. This is the brute-force search space used by the implementation.#footnote[We use the registry complexity bound $O^*(2^{|A|})$ for the full partitioned problem.]

*Example.* Consider the digraph on $n = #nv$ vertices with arcs $(0 arrow 1), (0 arrow 2), (1 arrow 3), (2 arrow 3), (1 arrow 4), (3 arrow 5), (4 arrow 5), (2 arrow 4)$, partition groups $A_1 = {(0 arrow 1), (0 arrow 2)}$, $A_2 = {(1 arrow 3), (2 arrow 3)}$, $A_3 = {(1 arrow 4), (2 arrow 4)}$, $A_4 = {(3 arrow 5), (4 arrow 5)}$, and threshold $K = 10$. The highlighted selection $A' = {(0 arrow 1), (1 arrow 3), (2 arrow 4), (3 arrow 5)}$ has total weight $3 + 4 + 3 + 3 = 13 >= 10$, uses exactly one arc from each partition group, and gives in-degrees 1 at vertices $1, 3, 4,$ and $5$. Because every selected arc points strictly left-to-right in the drawing, the selected subgraph is acyclic. The canonical fixture contains #x.optimal.len() satisfying selections for this instance; the figure highlights one of them.

#figure({
let verts = ((0, 1.6), (1.3, 2.3), (1.3, 0.9), (3.0, 2.3), (3.0, 0.9), (4.6, 1.6))
canvas(length: 1cm, {
for (idx, arc) in arcs.enumerate() {
let (u, v) = arc
let selected = chosen.contains(idx)
draw.line(
verts.at(u),
verts.at(v),
stroke: if selected { 2pt + graph-colors.at(0) } else { 0.9pt + luma(180) },
mark: (end: "straight", scale: if selected { 0.5 } else { 0.4 }),
)
}
for (k, pos) in verts.enumerate() {
g-node(pos, name: "v" + str(k), label: [$v_#k$])
}
})
},
caption: [Directed graph for Multiple Choice Branching. Blue arcs show the satisfying branching $(0 arrow 1), (1 arrow 3), (2 arrow 4), (3 arrow 5)$ of total weight 13; gray arcs are available but unselected.],
) <fig:mcb-example>
]
]
}

#problem-def("FlowShopScheduling")[
Given $m$ processors and a set $J$ of $n$ jobs, where each job $j in J$ consists of $m$ tasks $t_1 [j], t_2 [j], dots, t_m [j]$ with lengths $ell(t_i [j]) in ZZ^+_0$, and a deadline $D in ZZ^+$, determine whether there exists a permutation schedule $pi$ of the jobs such that all jobs complete by time $D$. Each job must be processed on machines $1, 2, dots, m$ in order, and job $j$ cannot start on machine $i+1$ until its task on machine $i$ is completed.
][
Expand Down
26 changes: 26 additions & 0 deletions docs/src/reductions/problem_schemas.json
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,32 @@
}
]
},
{
"name": "MultipleChoiceBranching",
"description": "Find a branching with partition constraints and weight at least K",
"fields": [
{
"name": "graph",
"type_name": "DirectedGraph",
"description": "The directed graph G=(V,A)"
},
{
"name": "weights",
"type_name": "Vec<W>",
"description": "Arc weights w(a) for each arc a in A"
},
{
"name": "partition",
"type_name": "Vec<Vec<usize>>",
"description": "Partition of arc indices; each arc index must appear in exactly one group"
},
{
"name": "threshold",
"type_name": "W::Sum",
"description": "Weight threshold K"
}
]
},
{
"name": "OptimalLinearArrangement",
"description": "Find a vertex ordering on a line with total edge length at most K",
Expand Down
61 changes: 35 additions & 26 deletions docs/src/reductions/reduction_graph.json
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,15 @@
"doc_path": "models/graph/struct.MinimumVertexCover.html",
"complexity": "1.1996^num_vertices"
},
{
"name": "MultipleChoiceBranching",
"variant": {
"weight": "i32"
},
"category": "graph",
"doc_path": "models/graph/struct.MultipleChoiceBranching.html",
"complexity": "2^num_arcs"
},
{
"name": "OptimalLinearArrangement",
"variant": {
Expand Down Expand Up @@ -599,7 +608,7 @@
},
{
"source": 4,
"target": 57,
"target": 58,
"overhead": [
{
"field": "num_spins",
Expand Down Expand Up @@ -659,7 +668,7 @@
},
{
"source": 13,
"target": 51,
"target": 52,
"overhead": [
{
"field": "num_vars",
Expand Down Expand Up @@ -700,7 +709,7 @@
},
{
"source": 20,
"target": 51,
"target": 52,
"overhead": [
{
"field": "num_vars",
Expand All @@ -726,7 +735,7 @@
},
{
"source": 21,
"target": 51,
"target": 52,
"overhead": [
{
"field": "num_vars",
Expand All @@ -752,7 +761,7 @@
},
{
"source": 22,
"target": 51,
"target": 52,
"overhead": [
{
"field": "num_vars",
Expand All @@ -763,7 +772,7 @@
},
{
"source": 22,
"target": 61,
"target": 62,
"overhead": [
{
"field": "num_elements",
Expand All @@ -774,7 +783,7 @@
},
{
"source": 23,
"target": 53,
"target": 54,
"overhead": [
{
"field": "num_clauses",
Expand All @@ -793,7 +802,7 @@
},
{
"source": 24,
"target": 51,
"target": 52,
"overhead": [
{
"field": "num_vars",
Expand All @@ -819,7 +828,7 @@
},
{
"source": 27,
"target": 57,
"target": 58,
"overhead": [
{
"field": "num_spins",
Expand Down Expand Up @@ -1134,7 +1143,7 @@
},
{
"source": 39,
"target": 51,
"target": 52,
"overhead": [
{
"field": "num_vars",
Expand Down Expand Up @@ -1249,7 +1258,7 @@
"doc_path": "rules/minimumvertexcover_minimumsetcovering/index.html"
},
{
"source": 51,
"source": 52,
"target": 13,
"overhead": [
{
Expand All @@ -1264,8 +1273,8 @@
"doc_path": "rules/qubo_ilp/index.html"
},
{
"source": 51,
"target": 56,
"source": 52,
"target": 57,
"overhead": [
{
"field": "num_spins",
Expand All @@ -1275,7 +1284,7 @@
"doc_path": "rules/spinglass_qubo/index.html"
},
{
"source": 53,
"source": 54,
"target": 4,
"overhead": [
{
Expand All @@ -1290,7 +1299,7 @@
"doc_path": "rules/sat_circuitsat/index.html"
},
{
"source": 53,
"source": 54,
"target": 17,
"overhead": [
{
Expand All @@ -1305,7 +1314,7 @@
"doc_path": "rules/sat_coloring/index.html"
},
{
"source": 53,
"source": 54,
"target": 22,
"overhead": [
{
Expand All @@ -1320,7 +1329,7 @@
"doc_path": "rules/sat_ksat/index.html"
},
{
"source": 53,
"source": 54,
"target": 32,
"overhead": [
{
Expand All @@ -1335,7 +1344,7 @@
"doc_path": "rules/sat_maximumindependentset/index.html"
},
{
"source": 53,
"source": 54,
"target": 41,
"overhead": [
{
Expand All @@ -1350,8 +1359,8 @@
"doc_path": "rules/sat_minimumdominatingset/index.html"
},
{
"source": 56,
"target": 51,
"source": 57,
"target": 52,
"overhead": [
{
"field": "num_vars",
Expand All @@ -1361,7 +1370,7 @@
"doc_path": "rules/spinglass_qubo/index.html"
},
{
"source": 57,
"source": 58,
"target": 27,
"overhead": [
{
Expand All @@ -1376,8 +1385,8 @@
"doc_path": "rules/spinglass_maxcut/index.html"
},
{
"source": 57,
"target": 56,
"source": 58,
"target": 57,
"overhead": [
{
"field": "num_spins",
Expand All @@ -1391,7 +1400,7 @@
"doc_path": "rules/spinglass_casts/index.html"
},
{
"source": 62,
"source": 63,
"target": 13,
"overhead": [
{
Expand All @@ -1406,8 +1415,8 @@
"doc_path": "rules/travelingsalesman_ilp/index.html"
},
{
"source": 62,
"target": 51,
"source": 63,
"target": 52,
"overhead": [
{
"field": "num_vars",
Expand Down
7 changes: 6 additions & 1 deletion problemreductions-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ Flags by problem type:
CVP --basis, --target-vec [--bounds]
OptimalLinearArrangement --graph, --bound
RuralPostman (RPP) --graph, --edge-weights, --required-edges, --bound
MultipleChoiceBranching --arcs [--weights] --partition --bound [--num-vertices]
SubgraphIsomorphism --graph (host), --pattern (pattern)
LCS --strings
FAS --arcs [--weights] [--num-vertices]
Expand All @@ -264,6 +265,7 @@ Examples:
pred create MIS --graph 0-1,1-2,2-3 --weights 1,1,1
pred create SAT --num-vars 3 --clauses \"1,2;-1,3\"
pred create QUBO --matrix \"1,0.5;0.5,2\"
pred create MultipleChoiceBranching/i32 --arcs \"0>1,0>2,1>3,2>3,1>4,3>5,4>5,2>4\" --weights 3,2,4,1,2,3,1,3 --partition \"0,1;2,3;4,7;5,6\" --bound 10
pred create MIS/KingsSubgraph --positions \"0,0;1,0;1,1;0,1\"
pred create MIS/UnitDiskGraph --positions \"0,0;1,0;0.5,0.8\" --radius 1.5
pred create MIS --random --num-vertices 10 --edge-prob 0.3
Expand Down Expand Up @@ -380,6 +382,9 @@ pub struct CreateArgs {
/// Sets for SetPacking/SetCovering (semicolon-separated, e.g., "0,1;1,2;0,2")
#[arg(long)]
pub sets: Option<String>,
/// Partition groups for arc-index partitions (semicolon-separated, e.g., "0,1;2,3")
#[arg(long)]
pub partition: Option<String>,
/// Universe size for MinimumSetCovering
#[arg(long)]
pub universe: Option<usize>,
Expand Down Expand Up @@ -413,7 +418,7 @@ pub struct CreateArgs {
/// Required edge indices for RuralPostman (comma-separated, e.g., "0,2,4")
#[arg(long)]
pub required_edges: Option<String>,
/// Upper bound or length bound (for LengthBoundedDisjointPaths, OptimalLinearArrangement, RuralPostman, or SCS)
/// Upper bound or length bound (for LengthBoundedDisjointPaths, MultipleChoiceBranching, OptimalLinearArrangement, RuralPostman, or SCS)
#[arg(long, allow_hyphen_values = true)]
pub bound: Option<i64>,
/// Pattern graph edge list for SubgraphIsomorphism (e.g., 0-1,1-2,2-0)
Expand Down
Loading
Loading