Skip to content
67 changes: 67 additions & 0 deletions docs/paper/reductions.typ
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
"BMF": [Boolean Matrix Factorization],
"PaintShop": [Paint Shop],
"BicliqueCover": [Biclique Cover],
"BalancedCompleteBipartiteSubgraph": [Balanced Complete Bipartite Subgraph],
"BoundedComponentSpanningForest": [Bounded Component Spanning Forest],
"BinPacking": [Bin Packing],
"ClosestVectorProblem": [Closest Vector Problem],
Expand Down Expand Up @@ -1926,6 +1927,72 @@ NP-completeness was established by Garey, Johnson, and Stockmeyer @gareyJohnsonS
]
}

#{
let x = load-model-example("BalancedCompleteBipartiteSubgraph")
let left-size = x.instance.graph.left_size
let right-size = x.instance.graph.right_size
let k = x.instance.k
let bip-edges = x.instance.graph.edges
let sol = x.optimal.at(0)
let left-selected = range(left-size).filter(i => sol.config.at(i) == 1)
let right-selected = range(right-size).filter(i => sol.config.at(left-size + i) == 1)
let selected-edges = bip-edges.filter(e =>
left-selected.contains(e.at(0)) and right-selected.contains(e.at(1))
)
[
#problem-def("BalancedCompleteBipartiteSubgraph")[
Given a bipartite graph $G = (A, B, E)$ and an integer $k$, determine whether there exist subsets $A' subset.eq A$ and $B' subset.eq B$ such that $|A'| = |B'| = k$ and every cross pair is present:
$A' times B' subset.eq E.$
][
Balanced Complete Bipartite Subgraph is a classical NP-complete bipartite containment problem from Garey and Johnson @garey1979. Unlike Biclique Cover, which asks for a collection of bicliques covering all edges, this problem asks for a _single_ balanced biclique of prescribed size. It arises naturally in biclustering, dense submatrix discovery, and pattern mining on bipartite data. Chen et al. give an exact $O^*(1.3803^n)$ algorithm for dense bipartite graphs, and the registry records that best-known bound in the catalog metadata. A straightforward baseline still enumerates all $k$-subsets of $A$ and $B$ and checks whether they induce a complete bipartite graph, taking $O(binom(|A|, k) dot binom(|B|, k) dot k^2) = O^*(2^(|A| + |B|))$ time.

*Example.* Consider the bipartite graph with $A = {ell_1, ell_2, ell_3, ell_4}$, $B = {r_1, r_2, r_3, r_4}$, and edges $E = {#bip-edges.map(e => $(ell_#(e.at(0) + 1), r_#(e.at(1) + 1))$).join(", ")}$. For $k = #k$, the selected sets $A' = {#left-selected.map(i => $ell_#(i + 1)$).join(", ")}$ and $B' = {#right-selected.map(i => $r_#(i + 1)$).join(", ")}$ form a balanced complete bipartite subgraph: all #selected-edges.len() required cross edges are present. Vertex $ell_4$ is excluded because $(ell_4, r_3) in.not E$, so any witness using $ell_4$ cannot realize $K_(#k,#k)$.

#figure(
canvas(length: 1cm, {
let lpos = range(left-size).map(i => (0, left-size - 1 - i))
let rpos = range(right-size).map(i => (2.6, right-size - 1 - i))
for (li, rj) in bip-edges {
let selected = selected-edges.any(e => e.at(0) == li and e.at(1) == rj)
g-edge(
lpos.at(li),
rpos.at(rj),
stroke: if selected { 2pt + graph-colors.at(0) } else { 1pt + luma(180) },
)
}
for (idx, pos) in lpos.enumerate() {
let selected = left-selected.contains(idx)
g-node(
pos,
name: "bcbs-l" + str(idx),
fill: if selected { graph-colors.at(0) } else { luma(240) },
label: if selected {
text(fill: white)[$ell_#(idx + 1)$]
} else {
[$ell_#(idx + 1)$]
},
)
}
for (idx, pos) in rpos.enumerate() {
let selected = right-selected.contains(idx)
g-node(
pos,
name: "bcbs-r" + str(idx),
fill: if selected { graph-colors.at(0) } else { luma(240) },
label: if selected {
text(fill: white)[$r_#(idx + 1)$]
} else {
[$r_#(idx + 1)$]
},
)
}
}),
caption: [Balanced complete bipartite subgraph with $k = #k$: the selected vertices $A' = {#left-selected.map(i => $ell_#(i + 1)$).join(", ")}$ and $B' = {#right-selected.map(i => $r_#(i + 1)$).join(", ")}$ are blue, and the 9 edges of the induced $K_(#k,#k)$ are highlighted. The missing edge $(ell_4, r_3)$ prevents including $ell_4$.],
) <fig:balanced-complete-bipartite-subgraph>
]
]
}

#{
let x = load-model-example("PartitionIntoTriangles")
let nv = graph-num-vertices(x.instance)
Expand Down
Loading
Loading