Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 1 addition & 1 deletion docs/paper/reductions.typ
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ In all graph problems below, $G = (V, E)$ denotes an undirected graph with $|V|
#problem-def("MaximumIndependentSet")[
Given $G = (V, E)$ with vertex weights $w: V -> RR$, find $S subset.eq V$ maximizing $sum_(v in S) w(v)$ such that no two vertices in $S$ are adjacent: $forall u, v in S: (u, v) in.not E$.
][
One of Karp's 21 NP-complete problems @karp1972, MIS appears in wireless network scheduling, register allocation, and coding theory @shannon1956. Solvable in polynomial time on bipartite graphs (König's theorem), interval graphs, chordal graphs, and cographs. The best known algorithm runs in $O^*(1.1996^n)$ time via measure-and-conquer branching @xiao2017.
One of Karp's 21 NP-complete problems @karp1972, MIS appears in wireless network scheduling, register allocation, and coding theory @shannon1956. Solvable in polynomial time on bipartite graphs (König's theorem), interval graphs, chordal graphs, and cographs. The best known algorithm runs in $O^*(1.1996^n)$ time via measure-and-conquer branching @xiao2017. On geometric graphs (King's subgraph, triangular subgraph, unit disk graphs), MIS admits subexponential $O^*(c^sqrt(n))$ algorithms for some constant $c$, via geometric separation @alber2004.

*Example.* Consider the Petersen graph $G$ with $n = 10$ vertices, $|E| = 15$ edges, and unit weights $w(v) = 1$ for all $v in V$. The graph is 3-regular (every vertex has degree 3). A maximum independent set is $S = {v_1, v_3, v_5, v_9}$ with $w(S) = sum_(v in S) w(v) = 4 = alpha(G)$. No two vertices in $S$ share an edge, and no vertex can be added without violating independence.

Expand Down
11 changes: 11 additions & 0 deletions docs/paper/references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -355,3 +355,14 @@ @article{shannon1956
doi = {10.1109/TIT.1956.1056798}
}

@article{alber2004,
author = {Jochen Alber and Ji\v{r}\'{\i} Fiala},
title = {Geometric separation and exact solutions for the parameterized independent set problem on disk graphs},
journal = {Journal of Algorithms},
volume = {52},
number = {2},
pages = {134--151},
year = {2004},
doi = {10.1016/j.jalgor.2003.10.001}
Comment on lines +358 to +366

Copilot AI Feb 28, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new BibTeX entry uses LaTeX accent escapes in the author field (e.g., Ji\v{r}\'{\i}), while the rest of references.bib appears to use plain text. Typst/Bib parsers often don't fully expand LaTeX macros, which can lead to incorrect rendering in the compiled paper. Consider replacing the escapes with the actual Unicode characters (e.g., "Jiří Fiala") to ensure consistent bibliography output.

Copilot uses AI. Check for mistakes.
}

7 changes: 6 additions & 1 deletion problemreductions-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,12 @@ fn generate_reduction_entry(
let overhead = match &attrs.overhead {
Some(OverheadSpec::Legacy(tokens)) => tokens.clone(),
Some(OverheadSpec::Parsed(fields)) => generate_parsed_overhead(fields)?,
None => quote! { crate::rules::registry::ReductionOverhead::default() },
None => {
return Err(syn::Error::new(
proc_macro2::Span::call_site(),
"#[reduction] requires overhead = { ... }. Specify overhead expressions for all target problem size fields.",

Copilot AI Feb 28, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The compile error text for missing overhead is a bit ambiguous: it says "requires overhead = { ... }" but the actual syntax is #[reduction(overhead = { ... })]. It may be clearer to include the full attribute form (and/or a short example), so users immediately know what to paste when they hit this error.

Suggested change
"#[reduction] requires overhead = { ... }. Specify overhead expressions for all target problem size fields.",
"Missing overhead specification. Use #[reduction(overhead = { ... })] and specify overhead expressions for all target problem size fields.",

Copilot uses AI. Check for mistakes.
));
}
};

// Generate the combined output
Expand Down
2 changes: 1 addition & 1 deletion src/models/graph/max_cut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ where
}

crate::declare_variants! {
MaxCut<SimpleGraph, i32> => "2^num_vertices",
MaxCut<SimpleGraph, i32> => "2^(omega * num_vertices / 3)",
}

#[cfg(test)]
Expand Down
2 changes: 1 addition & 1 deletion src/models/graph/maximal_is.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ pub(crate) fn is_maximal_independent_set<G: Graph>(graph: &G, selected: &[bool])
}

crate::declare_variants! {
MaximalIS<SimpleGraph, i32> => "2^num_vertices",
MaximalIS<SimpleGraph, i32> => "3^(num_vertices / 3)",
}

#[cfg(test)]
Expand Down
2 changes: 1 addition & 1 deletion src/models/graph/maximum_clique.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ fn is_clique_config<G: Graph>(graph: &G, config: &[usize]) -> bool {
}

crate::declare_variants! {
MaximumClique<SimpleGraph, i32> => "2^num_vertices",
MaximumClique<SimpleGraph, i32> => "1.1996^num_vertices",
}

/// Check if a set of vertices forms a clique.
Expand Down
14 changes: 7 additions & 7 deletions src/models/graph/maximum_independent_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,13 +160,13 @@ fn is_independent_set_config<G: Graph>(graph: &G, config: &[usize]) -> bool {
}

crate::declare_variants! {
MaximumIndependentSet<SimpleGraph, i32> => "2^num_vertices",
MaximumIndependentSet<SimpleGraph, One> => "2^num_vertices",
MaximumIndependentSet<KingsSubgraph, i32> => "2^num_vertices",
MaximumIndependentSet<KingsSubgraph, One> => "2^num_vertices",
MaximumIndependentSet<TriangularSubgraph, i32> => "2^num_vertices",
MaximumIndependentSet<UnitDiskGraph, i32> => "2^num_vertices",
MaximumIndependentSet<UnitDiskGraph, One> => "2^num_vertices",
MaximumIndependentSet<SimpleGraph, i32> => "1.1996^num_vertices",
MaximumIndependentSet<SimpleGraph, One> => "1.1996^num_vertices",
MaximumIndependentSet<KingsSubgraph, i32> => "2^sqrt(num_vertices)",
MaximumIndependentSet<KingsSubgraph, One> => "2^sqrt(num_vertices)",
MaximumIndependentSet<TriangularSubgraph, i32> => "2^sqrt(num_vertices)",
MaximumIndependentSet<UnitDiskGraph, i32> => "2^sqrt(num_vertices)",
MaximumIndependentSet<UnitDiskGraph, One> => "2^sqrt(num_vertices)",
}

/// Check if a set of vertices forms an independent set.
Expand Down
2 changes: 1 addition & 1 deletion src/models/graph/minimum_dominating_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ where
}

crate::declare_variants! {
MinimumDominatingSet<SimpleGraph, i32> => "2^num_vertices",
MinimumDominatingSet<SimpleGraph, i32> => "1.4969^num_vertices",
}

/// Check if a set of vertices is a dominating set.
Expand Down
2 changes: 1 addition & 1 deletion src/models/graph/minimum_vertex_cover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ fn is_vertex_cover_config<G: Graph>(graph: &G, config: &[usize]) -> bool {
}

crate::declare_variants! {
MinimumVertexCover<SimpleGraph, i32> => "2^num_vertices",
MinimumVertexCover<SimpleGraph, i32> => "1.1996^num_vertices",
}

/// Check if a set of vertices forms a vertex cover.
Expand Down
2 changes: 1 addition & 1 deletion src/models/graph/traveling_salesman.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ pub(crate) fn is_hamiltonian_cycle<G: Graph>(graph: &G, selected: &[bool]) -> bo
}

crate::declare_variants! {
TravelingSalesman<SimpleGraph, i32> => "num_vertices!",
TravelingSalesman<SimpleGraph, i32> => "2^num_vertices",
}

#[cfg(test)]
Expand Down
4 changes: 2 additions & 2 deletions src/models/optimization/closest_vector_problem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ where
}

crate::declare_variants! {
ClosestVectorProblem<i32> => "exp(num_basis_vectors)",
ClosestVectorProblem<f64> => "exp(num_basis_vectors)",
ClosestVectorProblem<i32> => "2^num_basis_vectors",
ClosestVectorProblem<f64> => "2^num_basis_vectors",
}

#[cfg(test)]
Expand Down
2 changes: 1 addition & 1 deletion src/models/optimization/ilp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ impl OptimizationProblem for ILP {
}

crate::declare_variants! {
ILP => "exp(num_variables)",
ILP => "num_variables^num_variables",
}

#[cfg(test)]
Expand Down
2 changes: 1 addition & 1 deletion src/models/satisfiability/ksat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ impl<K: KValue> SatisfactionProblem for KSatisfiability<K> {}
crate::declare_variants! {
KSatisfiability<KN> => "2^num_variables",
KSatisfiability<K2> => "num_variables + num_clauses",
KSatisfiability<K3> => "2^num_variables",
KSatisfiability<K3> => "1.307^num_variables",
}

#[cfg(test)]
Expand Down
4 changes: 4 additions & 0 deletions src/models/specialized/biclique_cover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,10 @@ impl OptimizationProblem for BicliqueCover {
}
}

crate::declare_variants! {
BicliqueCover => "2^num_vertices",
}

#[cfg(test)]
#[path = "../../unit_tests/models/specialized/biclique_cover.rs"]
mod tests;
4 changes: 4 additions & 0 deletions src/models/specialized/bmf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,10 @@ impl OptimizationProblem for BMF {
}
}

crate::declare_variants! {
BMF => "2^(rows * rank + rank * cols)",
}

#[cfg(test)]
#[path = "../../unit_tests/models/specialized/bmf.rs"]
mod tests;
2 changes: 1 addition & 1 deletion src/models/specialized/factoring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ impl OptimizationProblem for Factoring {
}

crate::declare_variants! {
Factoring => "exp(sqrt(num_bits))",
Factoring => "exp(num_bits^(1/3) * log(num_bits)^(2/3))",

Copilot AI Feb 28, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new Factoring complexity string references num_bits, but this model doesn’t define a num_bits() getter (it has m()/n() and num_bits_first()/num_bits_second()). This makes the complexity metadata inconsistent with the model’s size parameters and can be confusing/misleading in the exported docs. Consider expressing the bit-length in terms of existing fields (e.g., m + n, or num_bits_first + num_bits_second) or adding a num_bits() helper that matches the complexity expression.

Suggested change
Factoring => "exp(num_bits^(1/3) * log(num_bits)^(2/3))",
Factoring => "exp((m + n)^(1/3) * log(m + n)^(2/3))",

Copilot uses AI. Check for mistakes.
}

#[cfg(test)]
Expand Down
4 changes: 4 additions & 0 deletions src/models/specialized/paintshop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,10 @@ impl OptimizationProblem for PaintShop {
}
}

crate::declare_variants! {
PaintShop => "2^num_cars",
}

#[cfg(test)]
#[path = "../../unit_tests/models/specialized/paintshop.rs"]
mod tests;
2 changes: 1 addition & 1 deletion src/unit_tests/rules/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1082,7 +1082,7 @@ fn test_variant_complexity() {
let graph = ReductionGraph::new();
let variant = ReductionGraph::variant_to_map(&[("graph", "SimpleGraph"), ("weight", "i32")]);
let complexity = graph.variant_complexity("MaximumIndependentSet", &variant);
assert_eq!(complexity, Some("2^num_vertices"));
assert_eq!(complexity, Some("1.1996^num_vertices"));

// Unknown problem returns None
let unknown = BTreeMap::new();
Expand Down