Skip to content

Commit 8bc7b03

Browse files
isPANNclaude
andcommitted
paper review session 6: entries 51-60 (MinimumHittingSet–MinimumCardinalityKey)
Add 5 figures (ConsecutiveSets, ExactCoverBy3Sets, ThreeDimensionalMatching, ThreeMatroidIntersection, MinimumCardinalityKey), fix SetSplitting citation (Lovász 1973 via NAE-3SAT), fix PrimeAttributeName citation (@lucchesi1978keys), add @lovasz1973 bib entry. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent c6f0345 commit 8bc7b03

2 files changed

Lines changed: 191 additions & 2 deletions

File tree

docs/paper/reductions.typ

Lines changed: 183 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3671,7 +3671,7 @@ In all graph problems below, $G = (V, E)$ denotes an undirected graph with $|V|
36713671
#problem-def("SetSplitting")[
36723672
Given a finite universe $U$ and a collection $cal(C) = {C_1, dots, C_m}$ of subsets of $U$ each of size $gt.eq 2$, does there exist a 2-coloring $chi: U -> {0, 1}$ such that every $C_i$ is non-monochromatic — i.e., contains at least one element of each color?
36733673
][
3674-
One of Garey and Johnson's NP-complete problems (SP4 in @garey1979), shown NP-complete by reduction from 3-SAT. It is equivalent to deciding whether a hypergraph is 2-colorable (also called Property B). The problem is trivially satisfiable when every subset has size exactly 2, reducing to 2-colorability of the corresponding graph; it becomes NP-complete for subsets of size $gt.eq 3$. The best known exact algorithm runs in $O^*(2^n)$ by brute-force enumeration over the $n = |U|$ elements.
3674+
One of Garey and Johnson's NP-complete problems (SP4 in @garey1979), shown NP-complete by #cite(<lovasz1973>, form: "prose") via reduction from Not-All-Equal 3-Satisfiability. It is equivalent to deciding whether a hypergraph is 2-colorable (also called Property B). The problem is trivially satisfiable when every subset has size exactly 2, reducing to 2-colorability of the corresponding graph; it becomes NP-complete for subsets of size $gt.eq 3$. The best known exact algorithm runs in $O^*(2^n)$ by brute-force enumeration over the $n = |U|$ elements.
36753675

36763676
*Example.* Let $U = {1, 2, dots, #n}$ and $cal(C) = {C_1, dots, C_#m}$ with #range(m).map(i => $C_#(i + 1) = #fmt-set(subsets.at(i))$).join(", "). Coloring $S_1 = #fmt-set(part0)$ and $S_2 = #fmt-set(part1)$ splits all subsets: each $C_i$ has at least one element in each part.
36773677

@@ -3736,6 +3736,39 @@ In all graph problems below, $G = (V, E)$ denotes an undirected graph with $|V|
37363736
"pred solve consecutive-sets.json",
37373737
"pred evaluate consecutive-sets.json --config " + x.optimal_config.map(str).join(","),
37383738
)
3739+
3740+
// Subset span data: (start_pos, end_pos) in the solution string
3741+
// Σ1={0,4} at 0–1, Σ2={2,4} at 1–2, Σ3={2,5} at 2–3, Σ4={1,5} at 3–4, Σ5={1,3} at 4–5
3742+
#let spans = ((0, 1), (1, 2), (2, 3), (3, 4), (4, 5))
3743+
#let span-colors = (rgb("#4e79a7"), rgb("#e15759"), rgb("#59a14f"), rgb("#f28e2b"), rgb("#b07aa1"))
3744+
3745+
#figure(
3746+
canvas(length: 1cm, {
3747+
import draw: *
3748+
let cell = 1.0
3749+
// String positions as boxes
3750+
for (pos, sym) in sol.enumerate() {
3751+
let x = pos * cell
3752+
rect((x - cell / 2, -0.3), (x + cell / 2, 0.3), stroke: 0.6pt + black)
3753+
content((x, 0), text(10pt, weight: "bold", str(sym)))
3754+
// Position label above
3755+
content((x, 0.55), text(7pt, fill: luma(120), str(pos)))
3756+
}
3757+
// Subset spans as colored brackets below
3758+
for (si, ((s, e), color)) in spans.zip(span-colors).enumerate() {
3759+
let y = -0.65 - si * 0.4
3760+
let x0 = s * cell
3761+
let x1 = e * cell
3762+
line((x0, y), (x1, y), stroke: 1.5pt + color)
3763+
// Tick marks at endpoints
3764+
line((x0, y - 0.08), (x0, y + 0.08), stroke: 1.2pt + color)
3765+
line((x1, y - 0.08), (x1, y + 0.08), stroke: 1.2pt + color)
3766+
// Label
3767+
content((x1 + 0.45, y), text(7pt, fill: color, $Sigma_#(si + 1)$))
3768+
}
3769+
}),
3770+
caption: [Consecutive Sets: the string $w = (#sol.map(str).join(", "))$ with each subset $Sigma_i$ occupying a contiguous block. Colored bars below indicate the span of each subset.]
3771+
) <fig:consecutive-sets>
37393772
]
37403773
]
37413774
}
@@ -3765,6 +3798,43 @@ In all graph problems below, $G = (V, E)$ denotes an undirected graph with $|V|
37653798
"pred solve exact-cover-by-3-sets.json",
37663799
"pred evaluate exact-cover-by-3-sets.json --config " + x3c.optimal_config.map(str).join(","),
37673800
)
3801+
3802+
#figure(
3803+
canvas(length: 1cm, {
3804+
import draw: *
3805+
// Element nodes (top row, 1-indexed labels)
3806+
let elem-pos = range(n).map(i => ((i - (n - 1) / 2) * 0.9, 1.2))
3807+
// Subset nodes (bottom row)
3808+
let sub-pos = range(m).map(j => ((j - (m - 1) / 2) * 1.3, -1.2))
3809+
// Edges: element ∈ subset
3810+
for (j, subset) in subs.enumerate() {
3811+
let is-sel = selected.contains(j)
3812+
for i in subset {
3813+
line(elem-pos.at(i), sub-pos.at(j),
3814+
stroke: if is-sel { 1pt + graph-colors.at(0) } else { 0.5pt + luma(190) })
3815+
}
3816+
}
3817+
// Element nodes
3818+
for (k, pos) in elem-pos.enumerate() {
3819+
// Find which selected subset covers this element
3820+
let covered-by = selected.filter(j => subs.at(j).contains(k))
3821+
let covered = covered-by.len() > 0
3822+
circle(pos, radius: 0.22,
3823+
fill: if covered { graph-colors.at(0) } else { white },
3824+
stroke: 0.8pt + black)
3825+
content(pos, text(7pt, fill: if covered { white } else { black }, [#(k + 1)]))
3826+
}
3827+
// Subset nodes
3828+
for (j, pos) in sub-pos.enumerate() {
3829+
let is-sel = selected.contains(j)
3830+
circle(pos, radius: 0.26,
3831+
fill: if is-sel { graph-colors.at(0).lighten(70%) } else { luma(240) },
3832+
stroke: if is-sel { 1pt + graph-colors.at(0) } else { 0.8pt + black })
3833+
content(pos, text(7pt, $S_#(j + 1)$))
3834+
}
3835+
}),
3836+
caption: [Exact Cover by 3-Sets: the selected cover $cal(C)' = {#selected.map(i => $S_#(i + 1)$).join(", ")}$ (blue) partitions the universe $X = {1, dots, #n}$ into $q = #q$ disjoint triples. Every element (top) is covered by exactly one selected subset (bottom).]
3837+
) <fig:exact-cover-by-3-sets>
37683838
]
37693839
]
37703840
}
@@ -3793,6 +3863,43 @@ In all graph problems below, $G = (V, E)$ denotes an undirected graph with $|V|
37933863
"pred solve three-dimensional-matching.json",
37943864
"pred evaluate three-dimensional-matching.json --config " + tdm.optimal_config.map(str).join(","),
37953865
)
3866+
3867+
// Tripartite layout: W (left), X (center), Y (right) with triples as hyperedges
3868+
#figure(
3869+
canvas(length: 1cm, {
3870+
import draw: *
3871+
let col-x = (-2.0, 0.0, 2.0) // W, X, Y column positions
3872+
let col-labels = ($W$, $X$, $Y$)
3873+
let spacing = 0.9
3874+
// Node positions for each dimension
3875+
let node-pos(dim, idx) = (col-x.at(dim), (q - 1) / 2 * spacing - idx * spacing)
3876+
// Draw triples as colored lines connecting W, X, Y nodes
3877+
let triple-colors = (graph-colors.at(0), rgb("#e15759"), rgb("#59a14f"), luma(180), luma(180))
3878+
for (ti, triple) in triples.enumerate() {
3879+
let is-sel = selected.contains(ti)
3880+
let color = if is-sel { triple-colors.at(ti) } else { luma(200) }
3881+
let sw = if is-sel { 1.2pt } else { 0.5pt }
3882+
// W→X, X→Y lines
3883+
line(node-pos(0, triple.at(0)), node-pos(1, triple.at(1)), stroke: sw + color)
3884+
line(node-pos(1, triple.at(1)), node-pos(2, triple.at(2)), stroke: sw + color)
3885+
}
3886+
// Nodes
3887+
for dim in range(3) {
3888+
for idx in range(q) {
3889+
let pos = node-pos(dim, idx)
3890+
// Check if this node is used by a selected triple in this dimension
3891+
let used = selected.any(ti => triples.at(ti).at(dim) == idx)
3892+
circle(pos, radius: 0.22,
3893+
fill: if used { graph-colors.at(0) } else { white },
3894+
stroke: 0.8pt + black)
3895+
content(pos, text(8pt, fill: if used { white } else { black }, [#(idx + 1)]))
3896+
}
3897+
// Column label
3898+
content((col-x.at(dim), (q - 1) / 2 * spacing + 0.65), text(9pt, col-labels.at(dim)))
3899+
}
3900+
}),
3901+
caption: [Three-Dimensional Matching: tripartite layout with $W$, $X$, $Y$ columns. The matching $M' = {#selected.map(i => $t_#(i + 1)$).join(", ")}$ (colored paths) covers every element exactly once.]
3902+
) <fig:three-dimensional-matching>
37963903
]
37973904
]
37983905
}
@@ -3825,6 +3932,39 @@ In all graph problems below, $G = (V, E)$ denotes an undirected graph with $|V|
38253932
"pred solve three-matroid-intersection.json",
38263933
"pred evaluate three-matroid-intersection.json --config " + tmi.optimal_config.map(str).join(","),
38273934
)
3935+
3936+
// Three rows of partition groups, elements shown in each
3937+
#figure(
3938+
canvas(length: 1cm, {
3939+
import draw: *
3940+
let matroid-labels = ($cal(F)_1$, $cal(F)_2$, $cal(F)_3$)
3941+
let row-y = (1.6, 0.0, -1.6)
3942+
let group-colors = (rgb("#4e79a7"), rgb("#e15759"), rgb("#59a14f"))
3943+
for (mi, partition) in parts.enumerate() {
3944+
let y = row-y.at(mi)
3945+
let total-groups = partition.len()
3946+
// Label
3947+
content((-3.2, y), text(9pt, matroid-labels.at(mi)), anchor: "east")
3948+
// Draw each group as a rounded rectangle with elements inside
3949+
for (gi, group) in partition.enumerate() {
3950+
let gx = (gi - (total-groups - 1) / 2) * 2.2
3951+
let w = group.len() * 0.55 + 0.3
3952+
rect((gx - w / 2, y - 0.35), (gx + w / 2, y + 0.35),
3953+
stroke: 0.8pt + group-colors.at(mi), radius: 4pt)
3954+
// Elements inside the group
3955+
for (ei, elem) in group.enumerate() {
3956+
let ex = gx + (ei - (group.len() - 1) / 2) * 0.5
3957+
let is-sel = selected.contains(elem)
3958+
circle((ex, y), radius: 0.18,
3959+
fill: if is-sel { graph-colors.at(0) } else { white },
3960+
stroke: 0.6pt + black)
3961+
content((ex, y), text(7pt, fill: if is-sel { white } else { black }, str(elem)))
3962+
}
3963+
}
3964+
}
3965+
}),
3966+
caption: [Three-Matroid Intersection: each row shows one partition matroid's groups (rounded boxes). The selected elements $E' = #fmt-set(selected)$ (blue) place at most one element per group in all three matroids.]
3967+
) <fig:three-matroid-intersection>
38283968
]
38293969
]
38303970
}
@@ -4000,7 +4140,7 @@ In all graph problems below, $G = (V, E)$ denotes an undirected graph with $|V|
40004140
][
40014141
A functional dependency $X arrow Y$ on attribute set $A$ means: whenever two database rows agree on every attribute in $X$, they must also agree on every attribute in $Y$. The _closure_ $X^+_F$ of a subset $X subset.eq A$ under a set $F$ of functional dependencies is the largest set of attributes determined by $X$: start with $X^+_F = X$, then repeatedly apply every rule $L arrow R in F$ for which $L subset.eq X^+_F$, adding $R$ to $X^+_F$, until no more attributes can be added. A _superkey_ is any $K subset.eq A$ with $K^+_F = A$ (knowing $K$ determines everything). A _candidate key_ is a minimal superkey — no proper subset of $K$ is itself a superkey. An attribute $x$ is _prime_ if it belongs to at least one candidate key.
40024142

4003-
Determining whether an attribute is prime is NP-complete (Lucchesi and Osborn, 1978; Garey & Johnson SR28). The brute-force approach enumerates all $2^n$ subsets of $A$ containing $x$ and checks each for the key property; no algorithm significantly improving on this is known for the general problem.
4143+
Determining whether an attribute is prime is NP-complete @lucchesi1978keys (Garey & Johnson SR28 @garey1979). The brute-force approach enumerates all $2^n$ subsets of $A$ containing $x$ and checks each for the key property; no algorithm significantly improving on this is known for the general problem.
40044144

40054145
*Example.* Let $A = {0, 1, ..., #(n - 1)}$ ($n = #n$), query attribute $x = #q$, and $F = {#deps.enumerate().map(((i, d)) => $#fmt-set-math(d.at(0)) arrow #fmt-set-math(d.at(1))$).join(", ")}$.
40064146

@@ -4087,6 +4227,47 @@ In all graph problems below, $G = (V, E)$ denotes an undirected graph with $|V|
40874227
"pred solve minimum-cardinality-key.json",
40884228
"pred evaluate minimum-cardinality-key.json --config " + x.optimal_config.map(str).join(","),
40894229
)
4230+
4231+
#figure(
4232+
canvas(length: 1cm, {
4233+
import draw: *
4234+
// Attribute nodes in a single row
4235+
let spacing = 1.0
4236+
let attr-pos = range(n).map(i => (i * spacing, 0))
4237+
// FD colors
4238+
let fd-colors = (rgb("#e15759"), rgb("#59a14f"), rgb("#b07aa1"), rgb("#f28e2b"), rgb("#76b7b2"))
4239+
// Junction y-levels for each FD
4240+
let fd-y = range(m).map(i => -1.0 - i * 0.9)
4241+
// Draw FDs: LHS → junction dot → arrows to RHS
4242+
for (fi, (lhs, rhs)) in deps.enumerate() {
4243+
let color = fd-colors.at(calc.rem(fi, fd-colors.len()))
4244+
let y = fd-y.at(fi)
4245+
let jx = lhs.map(a => attr-pos.at(a).at(0)).sum() / lhs.len()
4246+
let junc = (jx, y)
4247+
for a in lhs {
4248+
line(attr-pos.at(a), junc, stroke: 0.8pt + color)
4249+
}
4250+
for a in rhs {
4251+
line(junc, attr-pos.at(a), stroke: 0.8pt + color, mark: (end: "straight"))
4252+
}
4253+
circle(junc, radius: 0.08, fill: color, stroke: none)
4254+
on-layer(1, {
4255+
content((jx - 0.5, y),
4256+
text(6.5pt, fill: color)[FD#(fi + 1)],
4257+
anchor: "east")
4258+
})
4259+
}
4260+
// Attribute nodes (drawn on top layer)
4261+
for (k, pos) in attr-pos.enumerate() {
4262+
let is-key = key-attrs.contains(k)
4263+
circle(pos, radius: 0.22,
4264+
fill: if is-key { graph-colors.at(0) } else { white },
4265+
stroke: 0.8pt + black)
4266+
content(pos, text(8pt, fill: if is-key { white } else { black }, [$#k$]))
4267+
}
4268+
}),
4269+
caption: [Minimum Cardinality Key: optimal key $K = #fmt-set(key-attrs)$ shown in blue. Each FD is drawn as lines converging to a dot (LHS) with arrows fanning out to RHS attributes. Chaining all FDs from $K$ reaches every attribute in $A$.]
4270+
) <fig:minimum-cardinality-key>
40904271
]
40914272
]
40924273
}

docs/paper/references.bib

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1837,3 +1837,11 @@ @article{gramm2009
18371837
year = {2009},
18381838
doi = {10.1145/1412228.1412236}
18391839
}
1840+
1841+
@inproceedings{lovasz1973,
1842+
author = {László Lovász},
1843+
title = {Coverings and Colorings of Hypergraphs},
1844+
booktitle = {Proceedings of the 4th Southeastern Conference on Combinatorics, Graph Theory, and Computing (Congressus Numerantium 8)},
1845+
pages = {3--12},
1846+
year = {1973}
1847+
}

0 commit comments

Comments
 (0)