diff --git a/docs/paper/reductions.typ b/docs/paper/reductions.typ index 44256b45b..36bdaea5b 100644 --- a/docs/paper/reductions.typ +++ b/docs/paper/reductions.typ @@ -2228,7 +2228,7 @@ In all graph problems below, $G = (V, E)$ denotes an undirected graph with $|V| import draw: * let blue = graph-colors.at(0) let gray = luma(185) - // Layout for issue #813: path 0–1–3–2–4–5 with clear bends so $v_0,v_1,v_3$ are not collinear + // Bend the path so $v_0,v_1,v_3$ are not collinear. // (otherwise $(0,3)$ lies on the same geometric line as $0 arrow.r 1 arrow.r 3$). let verts = ( (0, 0), @@ -17146,7 +17146,7 @@ The following table shows concrete target-variable counts for example instances, _Solution extraction._ First $n$ variables (sign variables) give the source configuration. ] -// === Non-ILP reduction rules (issue #974) === +// === Non-ILP reduction rules === #reduction-rule("ILP", "ILP")[ ILP variants convert between binary and bounded integer variable domains and between exact-integer and floating-point coefficients. The independent bounds dimension defaults to general; the bounded integer variant requires finite lower and upper endpoints for every variable. Binary variables embed into bounded integer ILP, which embeds into general integer ILP while retaining all stored bounds. A bounded integer variable is encoded by binary variables with truncated positional weights. Integer coefficients are embedded only when every stored coefficient and right-hand side has an exact `f64` representation. diff --git a/problemreductions-cli/src/bin/pred_sym.rs b/problemreductions-cli/src/bin/pred_sym.rs index 28f7bdadb..9a0731b7b 100644 --- a/problemreductions-cli/src/bin/pred_sym.rs +++ b/problemreductions-cli/src/bin/pred_sym.rs @@ -122,7 +122,6 @@ fn main() { }) .collect(); - // Check for unbound variables let expr_vars = parsed.variables(); let bound_vars: std::collections::HashSet<&str> = bindings.iter().map(|(name, _)| name.as_str()).collect(); diff --git a/problemreductions-cli/src/commands/create.rs b/problemreductions-cli/src/commands/create.rs index 0f5cc3834..bbc666e24 100644 --- a/problemreductions-cli/src/commands/create.rs +++ b/problemreductions-cli/src/commands/create.rs @@ -353,9 +353,7 @@ pub fn create(args: &CreateArgs, out: &OutputConfig) -> Result<()> { return create_registered_random(args, canonical, &resolved_variant, out); } - // ILP and CircuitSAT have complex input structures - // not suited for CLI flags. Check before the empty-flags help so they get a - // clear message. + // ILP and CircuitSAT have complex input structures not suited for CLI flags. if canonical == "ILP" || canonical == "CircuitSAT" { bail!( "CLI creation is not yet supported for {canonical}.\n\n\ diff --git a/problemreductions-cli/src/commands/create/tests.rs b/problemreductions-cli/src/commands/create/tests.rs index c4794de1a..95e432789 100644 --- a/problemreductions-cli/src/commands/create/tests.rs +++ b/problemreductions-cli/src/commands/create/tests.rs @@ -778,7 +778,6 @@ fn test_create_staff_scheduling_reports_invalid_schedule_without_panic() { let result = std::panic::catch_unwind(|| create(&args, &out)); assert!(result.is_ok(), "create should return an error, not panic"); let err = result.unwrap().unwrap_err().to_string(); - // parse_bool_rows catches ragged rows before validate_staff_scheduling_args assert!( err.contains("All rows") || err.contains("schedule 1 has 6 periods, expected 7"), "expected row-length validation error, got: {err}" diff --git a/problemreductions-cli/src/commands/graph.rs b/problemreductions-cli/src/commands/graph.rs index 53d94812c..12c29715f 100644 --- a/problemreductions-cli/src/commands/graph.rs +++ b/problemreductions-cli/src/commands/graph.rs @@ -1259,7 +1259,6 @@ pub fn neighbors( TraversalFlow::Both => "both directions", }; - // Build tree structure via BFS with parent tracking let tree = graph.k_neighbor_tree(&spec_name, &variant, max_hops, direction); out.emit( diff --git a/problemreductions-cli/src/commands/inspect.rs b/problemreductions-cli/src/commands/inspect.rs index f5546052c..f71d9cc90 100644 --- a/problemreductions-cli/src/commands/inspect.rs +++ b/problemreductions-cli/src/commands/inspect.rs @@ -11,7 +11,6 @@ pub fn inspect(input: &Path, out: &OutputConfig) -> Result<()> { let content = read_input(input)?; let json: serde_json::Value = serde_json::from_str(&content)?; - // Detect if it's a bundle or a problem if json.get("source").is_some() && json.get("target").is_some() && json.get("path").is_some() { let bundle: ReductionBundle = serde_json::from_value(json)?; inspect_bundle(&bundle, out) diff --git a/problemreductions-cli/src/mcp/tests.rs b/problemreductions-cli/src/mcp/tests.rs index b2fa3993b..3affb00bc 100644 --- a/problemreductions-cli/src/mcp/tests.rs +++ b/problemreductions-cli/src/mcp/tests.rs @@ -473,7 +473,6 @@ fn deterministic_solver_dispatch_mcp_output_is_repeatable_for_each_solver_class( fn test_solve_bundle() { let server = McpServer::new(); let problem_json = create_test_mis(&server); - // Reduce first, then solve the bundle let bundle_json = server .reduce_inner( &problem_json, diff --git a/problemreductions-cli/src/mcp/tools.rs b/problemreductions-cli/src/mcp/tools.rs index 7a32f99e0..110997db5 100644 --- a/problemreductions-cli/src/mcp/tools.rs +++ b/problemreductions-cli/src/mcp/tools.rs @@ -314,7 +314,6 @@ impl McpServer { ) })?; - // Check for random generation let is_random = params .get("random") .and_then(|v| v.as_bool()) @@ -363,7 +362,6 @@ impl McpServer { pub fn inspect_problem_inner(&self, problem_json: &str) -> anyhow::Result { let json: serde_json::Value = serde_json::from_str(problem_json)?; - // Detect if it's a bundle or a problem if json.get("source").is_some() && json.get("target").is_some() && json.get("path").is_some() @@ -442,7 +440,6 @@ impl McpServer { let timeout_secs = u64::try_from(timeout.unwrap_or(0)) .map_err(|_| anyhow::anyhow!("timeout must be a nonnegative i64"))?; - // Detect if it's a bundle or a problem let is_bundle = json.get("source").is_some() && json.get("target").is_some() && json.get("path").is_some(); diff --git a/problemreductions-cli/src/output.rs b/problemreductions-cli/src/output.rs index 3318764ee..664601b62 100644 --- a/problemreductions-cli/src/output.rs +++ b/problemreductions-cli/src/output.rs @@ -115,7 +115,6 @@ pub fn format_table( rows: &[Vec], color_fns: &[Option], ) -> String { - // Compute actual column widths (max of header width, specified width, and data width) let widths: Vec = columns .iter() .enumerate() @@ -127,7 +126,6 @@ pub fn format_table( let mut text = String::new(); - // Header text.push_str(" "); for (i, (header, align, _)) in columns.iter().enumerate() { if i > 0 { @@ -140,7 +138,6 @@ pub fn format_table( } text.push('\n'); - // Separator text.push_str(" "); for (i, _) in columns.iter().enumerate() { if i > 0 { @@ -150,7 +147,6 @@ pub fn format_table( } text.push('\n'); - // Data rows for row in rows { text.push_str(" "); for (i, (_, align, _)) in columns.iter().enumerate() { diff --git a/problemreductions-macros/src/lib.rs b/problemreductions-macros/src/lib.rs index a0493ded6..4e887231c 100644 --- a/problemreductions-macros/src/lib.rs +++ b/problemreductions-macros/src/lib.rs @@ -206,15 +206,6 @@ fn option_inner_type(ty: &Type) -> Option<&Type> { /// - `transform = { exact { ... }, upper_bound { ... }, unavailable { ... } }` — per-field relations /// - `transform = unavailable { field = "reason", ... }` — no symbolic parameter transform /// - `unavailable = { field = "reason", ... }` — fields that cannot be propagated -/// -/// ## Syntax -/// ```ignore -/// #[reduction(transform = exact { -/// num_vars = "num_vertices^2", -/// num_constraints = num_edges, -/// })] -/// ``` -/// #[proc_macro_attribute] pub fn reduction(attr: TokenStream, item: TokenStream) -> TokenStream { let attrs = parse_macro_input!(attr as ReductionAttrs); @@ -598,28 +589,22 @@ fn generate_reduction_entry( attrs: &ReductionAttrs, impl_block: &ItemImpl, ) -> syn::Result { - // Extract the trait path (should be ReduceTo) let trait_path = impl_block .trait_ .as_ref() .map(|(path, _)| path) .ok_or_else(|| syn::Error::new_spanned(impl_block, "Expected impl ReduceTo for S"))?; - // Extract target type from ReduceTo let target_type = extract_target_from_trait(trait_path)?; - // Extract source type (Self type) let source_type = &impl_block.self_ty; - // Get type names let source_name = extract_type_name(source_type) .ok_or_else(|| syn::Error::new_spanned(source_type, "Cannot extract source type name"))?; let target_name = extract_type_name(&target_type) .ok_or_else(|| syn::Error::new_spanned(&target_type, "Cannot extract target type name"))?; - // Collect generic parameter info from the impl block let type_generics = collect_type_generic_names(&impl_block.generics); - // Generate variant fn bodies let source_variant_body = make_variant_fn_body(source_type, &type_generics)?; let target_variant_body = make_variant_fn_body(&target_type, &type_generics)?; @@ -652,7 +637,6 @@ fn generate_reduction_entry( .iter() .map(|(field, reason)| quote! { crate::rules::registry::UnavailableParameterField { field: #field, reason: #reason } }); - // Generate the combined output let output = quote! { #impl_block @@ -926,8 +910,6 @@ pub fn register_brute_force(input: TokenStream) -> TokenStream { /// Generate code for all `declare_variants!` entries. fn generate_declare_variants(input: &DeclareVariantsInput) -> syn::Result { - // Validate default markers per problem name. - // Group entries by their base type name (e.g., "MaximumIndependentSet"). let mut defaults_per_problem: HashMap> = HashMap::new(); let mut problem_names = HashSet::new(); for (i, entry) in input.entries.iter().enumerate() { @@ -938,7 +920,6 @@ fn generate_declare_variants(input: &DeclareVariantsInput) -> syn::Result 1 { return Err(syn::Error::new( @@ -973,7 +954,6 @@ fn generate_declare_variants(input: &DeclareVariantsInput) -> syn::Result = entry.aliases.iter().map(|s| s.value()).collect(); - // Parse the complexity expression to validate syntax let parsed = problemreductions_expr::Expr::try_parse(&complexity_str).map_err(|e| { syn::Error::new( entry.complexity.span(), @@ -981,7 +961,6 @@ fn generate_declare_variants(input: &DeclareVariantsInput) -> syn::Result { diff --git a/src/lib.rs b/src/lib.rs index 1c70132cb..7622e9a36 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -111,7 +111,6 @@ pub mod prelude { }; } -// Re-export commonly used items at crate root pub use big_o::big_o_normal_form; pub use error::{ProblemError, Result}; pub use expr::{ diff --git a/src/models/algebraic/algebraic_equations_over_gf2.rs b/src/models/algebraic/algebraic_equations_over_gf2.rs index 32649b5f2..466161dba 100644 --- a/src/models/algebraic/algebraic_equations_over_gf2.rs +++ b/src/models/algebraic/algebraic_equations_over_gf2.rs @@ -74,7 +74,6 @@ impl AlgebraicEquationsOverGF2 { ) -> Result<(), crate::registry::ConstructionError> { for (eq_idx, equation) in equations.iter().enumerate() { for (mono_idx, monomial) in equation.iter().enumerate() { - // Check variable indices are in range for &var in monomial { if var >= num_variables { return Err(format!( @@ -84,7 +83,6 @@ impl AlgebraicEquationsOverGF2 { .into()); } } - // Check monomial is sorted and has no duplicates for w in monomial.windows(2) { if w[0] >= w[1] { return Err(format!( @@ -225,17 +223,13 @@ pub(crate) fn canonical_model_example_specs() -> Vec Vec Vec { - // Adjacency matrix of path graph P_6, K=6 (one block per row). - // Issue #420 Instance 2. vec![crate::example_db::specs::ModelExampleSpec { id: "consecutive_block_minimization", instance: Box::new(ConsecutiveBlockMinimization::new( diff --git a/src/models/algebraic/consecutive_ones_submatrix.rs b/src/models/algebraic/consecutive_ones_submatrix.rs index bad2a8a4c..528a36495 100644 --- a/src/models/algebraic/consecutive_ones_submatrix.rs +++ b/src/models/algebraic/consecutive_ones_submatrix.rs @@ -215,7 +215,6 @@ impl Problem for ConsecutiveOnesSubmatrix { "column-selection length does not match the matrix".into(), )); } - // Collect selected column indices let selected: Vec = config .iter() .enumerate() @@ -249,8 +248,7 @@ crate::register_brute_force! { pub(crate) fn canonical_model_example_specs() -> Vec { vec![crate::example_db::specs::ModelExampleSpec { id: "consecutive_ones_submatrix", - // Tucker matrix (3×4): full matrix lacks C1P, but K=3 works - // Select columns {0,1,3} (config [1,1,0,1]) + // A Tucker obstruction forces the witness to omit a column. instance: Box::new(ConsecutiveOnesSubmatrix::new( vec![ vec![true, true, false, true], diff --git a/src/models/algebraic/equilibrium_point.rs b/src/models/algebraic/equilibrium_point.rs index 6d3392c40..2922b456c 100644 --- a/src/models/algebraic/equilibrium_point.rs +++ b/src/models/algebraic/equilibrium_point.rs @@ -228,7 +228,6 @@ impl Problem for EquilibriumPoint { if alt == solution[i] { continue; } - // Build alternative assignment with player i using alt. let mut alt_assignment = solution.clone(); alt_assignment[i] = alt; let alt_payoff = self.eval_payoff(i, &alt_assignment)?; @@ -262,16 +261,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // 3 players, M_i = {0, 1} for all i. - // F1 = x1*x2*x3: factors [[0,1,0,0],[0,0,1,0],[0,0,0,1]] - // F2 = (1-x1)*x2: factors [[1,-1,0,0],[0,0,1,0]] - // F3 = x1*(1-x3): factors [[0,1,0,0],[1,0,0,-1]] - // - // config [0,1,0] → assignment (0,1,0). - // F1(0,1,0) = 0*1*0 = 0. Deviations for player 1: y'=1 → F1(1,1,0)=0. No improvement. - // F2(0,1,0) = (1-0)*1 = 1. Deviations for player 2: y'=0 → F2(0,0,0)=0. No improvement. - // F3(0,1,0) = 0*(1-0) = 0. Deviations for player 3: y'=1 → F3(0,1,1)=0. No improvement. - // → (0,1,0) is a Nash equilibrium. let polynomials = vec![ vec![vec![0, 1, 0, 0], vec![0, 0, 1, 0], vec![0, 0, 0, 1]], vec![vec![1, -1, 0, 0], vec![0, 0, 1, 0]], diff --git a/src/models/algebraic/feasible_basis_extension.rs b/src/models/algebraic/feasible_basis_extension.rs index 5ae37a870..09ebd5a2b 100644 --- a/src/models/algebraic/feasible_basis_extension.rs +++ b/src/models/algebraic/feasible_basis_extension.rs @@ -411,7 +411,6 @@ impl Problem for FeasibleBasisExtension { let s = self.num_required(); let needed = m - s; - // Count selected free columns let selected_free: Vec = config .iter() .enumerate() @@ -450,7 +449,6 @@ crate::register_brute_force! { pub(crate) fn canonical_model_example_specs() -> Vec { vec![crate::example_db::specs::ModelExampleSpec { id: "feasible_basis_extension", - // 3x6 matrix, rhs=[7,5,3], required={0,1}, select col 2 -> B={0,1,2}, x=(4,5,3)>=0 instance: Box::new(FeasibleBasisExtension::new( vec![ vec![1, 0, 1, 2, -1, 0], @@ -460,7 +458,7 @@ pub(crate) fn canonical_model_example_specs() -> Vec Vec { - // 4×4 symmetric matrix with zero diagonal - // Config [0,1,1,0] → f=(-1,+1,+1,-1) → value = -20 vec![crate::example_db::specs::ModelExampleSpec { id: "minimum_matrix_cover", instance: Box::new(MinimumMatrixCover::new(vec![ diff --git a/src/models/algebraic/minimum_matrix_domination.rs b/src/models/algebraic/minimum_matrix_domination.rs index fcad70c0a..98f1e2ec9 100644 --- a/src/models/algebraic/minimum_matrix_domination.rs +++ b/src/models/algebraic/minimum_matrix_domination.rs @@ -154,7 +154,6 @@ impl Problem for MinimumMatrixDomination { "selected-entry vector length does not match the matrix".into(), )); } - // Collect the set of selected 1-entry indices let selected: Vec = config .iter() .enumerate() @@ -207,9 +206,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // P6 adjacency matrix (6×6, 10 ones) - // 1-entries: (0,1),(1,0),(1,2),(2,1),(2,3),(3,2),(3,4),(4,3),(4,5),(5,4) - // Optimal: select indices 0,1,7,6 -> C = {(0,1),(1,0),(4,3),(3,4)}, value = 4 let matrix = vec![ vec![false, true, false, false, false, false], vec![true, false, true, false, false, false], diff --git a/src/models/algebraic/minimum_weight_decoding.rs b/src/models/algebraic/minimum_weight_decoding.rs index 5c9c4b283..99ab2a3c1 100644 --- a/src/models/algebraic/minimum_weight_decoding.rs +++ b/src/models/algebraic/minimum_weight_decoding.rs @@ -188,8 +188,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // H (3×4): [[1,0,1,1],[0,1,1,0],[1,1,0,1]], s = [1,1,0] - // Config [0,0,1,0] → weight 1, Hx = [1,1,0] ≡ s → Min(1) let matrix = vec![ vec![true, false, true, true], vec![false, true, true, false], diff --git a/src/models/algebraic/minimum_weight_solution_to_linear_equations.rs b/src/models/algebraic/minimum_weight_solution_to_linear_equations.rs index ce17060ba..b1f25afd8 100644 --- a/src/models/algebraic/minimum_weight_solution_to_linear_equations.rs +++ b/src/models/algebraic/minimum_weight_solution_to_linear_equations.rs @@ -266,9 +266,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // A = [[1,2,3,1],[2,1,1,3]], b = [5,4], m=4, n=2 - // Config [1,1,0,0]: select columns 0,1. Submatrix [[1,2],[2,1]]. - // Solve [1,2;2,1]y=[5,4] → y=(1,2). Consistent. Min(2). let matrix = vec![vec![1, 2, 3, 1], vec![2, 1, 1, 3]]; let rhs = vec![5, 4]; vec![crate::example_db::specs::ModelExampleSpec { diff --git a/src/models/algebraic/quadratic_assignment.rs b/src/models/algebraic/quadratic_assignment.rs index 8afd85804..50ef13fbd 100644 --- a/src/models/algebraic/quadratic_assignment.rs +++ b/src/models/algebraic/quadratic_assignment.rs @@ -153,7 +153,6 @@ impl Problem for QuadraticAssignment { let n = self.num_facilities(); let m = self.num_locations(); - // Check config length matches number of facilities if config.len() != n { return Err(crate::traits::EvaluationError::InvalidConfiguration( "assignment length does not match the number of facilities".into(), diff --git a/src/models/algebraic/qubo.rs b/src/models/algebraic/qubo.rs index 91e23d51b..fc6d178ed 100644 --- a/src/models/algebraic/qubo.rs +++ b/src/models/algebraic/qubo.rs @@ -229,12 +229,10 @@ impl QUBO { let num_vars = linear.len(); let mut matrix = vec![vec![W::default(); num_vars]; num_vars]; - // Set diagonal (linear terms) for (i, val) in linear.into_iter().enumerate() { matrix[i][i] = val; } - // Set off-diagonal (quadratic terms) for ((i, j), val) in quadratic { if i >= num_vars || j >= num_vars { return Err(ConstructionError::Conversion(format!( diff --git a/src/models/algebraic/simultaneous_incongruences.rs b/src/models/algebraic/simultaneous_incongruences.rs index c2b3bb330..3c7b6f1f6 100644 --- a/src/models/algebraic/simultaneous_incongruences.rs +++ b/src/models/algebraic/simultaneous_incongruences.rs @@ -168,7 +168,6 @@ pub(crate) fn canonical_model_example_specs() -> Vec Vec Vec { use crate::topology::BipartiteGraph; - // Biclique 0: L_0={ℓ_1}, R_0={r_1, r_2} — covers edges (0,0), (0,1). - // Biclique 1: L_1={ℓ_2}, R_1={r_2, r_3} — covers edges (1,1), (1,2). - // Both are sub-bicliques of G; every edge covered; total size = 6. - // One incidence row per biclique over the five vertices. vec![crate::example_db::specs::ModelExampleSpec { id: "biclique_cover", instance: Box::new(BicliqueCover::new( diff --git a/src/models/graph/bounded_diameter_spanning_tree.rs b/src/models/graph/bounded_diameter_spanning_tree.rs index 0c931954e..338ef4b60 100644 --- a/src/models/graph/bounded_diameter_spanning_tree.rs +++ b/src/models/graph/bounded_diameter_spanning_tree.rs @@ -318,7 +318,6 @@ where )); } - // Collect selected edges let selected_indices: Vec = config .iter() .enumerate() @@ -334,7 +333,6 @@ where return Ok(crate::types::Or(false)); } - // Build adjacency list and compute total weight let mut adj: Vec> = vec![Vec::new(); n]; let mut total_weight = W::Sum::zero(); for &idx in &selected_indices { @@ -348,12 +346,10 @@ where )?; } - // Check weight bound if total_weight > self.weight_bound.clone() { return Ok(crate::types::Or(false)); } - // Check connectivity using BFS let mut visited = vec![false; n]; let mut queue = VecDeque::new(); visited[0] = true; @@ -373,7 +369,6 @@ where return Ok(crate::types::Or(false)); } - // Check diameter bound (BFS from each vertex) let diameter = Self::tree_diameter(&adj, n); diameter <= self.diameter_bound }) @@ -401,10 +396,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // 5 vertices, 7 edges with weights: (0,1,1),(0,2,2),(0,3,1),(1,2,1),(1,4,2),(2,3,1),(3,4,1) - // B=5, D=3 - // Tree: edges (0,1),(0,3),(2,3),(3,4) → edge indices 0,2,5,6 - // Config: [1,0,1,0,0,1,1] → weight = 1+1+1+1 = 4 ≤ 5, diameter = 3 ≤ 3 vec![crate::example_db::specs::ModelExampleSpec { id: "bounded_diameter_spanning_tree_simplegraph", instance: Box::new(BoundedDiameterSpanningTree::new( diff --git a/src/models/graph/degree_constrained_spanning_tree.rs b/src/models/graph/degree_constrained_spanning_tree.rs index 80a7d3cce..f22fdf445 100644 --- a/src/models/graph/degree_constrained_spanning_tree.rs +++ b/src/models/graph/degree_constrained_spanning_tree.rs @@ -159,7 +159,6 @@ where )); } - // Collect selected edges let selected: Vec<(usize, usize)> = config .iter() .enumerate() @@ -175,7 +174,6 @@ where return Ok(crate::types::Or(false)); } - // Check connectivity using BFS on selected edges let mut adj: Vec> = vec![Vec::new(); n]; let mut degree = vec![0usize; n]; for &(u, v) in &selected { @@ -185,7 +183,6 @@ where degree[v] += 1; } - // Check max degree constraint if degree.iter().any(|&d| d > self.max_degree) { return Ok(crate::types::Or(false)); } @@ -231,10 +228,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // 5 vertices, 7 edges: (0,1),(0,2),(0,3),(1,2),(1,4),(2,3),(3,4), K=2 - // Spanning tree with max degree 2: edges (0,2),(0,3),(1,2),(1,4) - // indices: 1,2,3,4 → config [0,1,1,1,1,0,0] - // Degrees: 0→{2,3}=2, 1→{2,4}=2, 2→{0,1}=2, 3→{0}=1, 4→{1}=1 vec![crate::example_db::specs::ModelExampleSpec { id: "degree_constrained_spanning_tree_simplegraph", instance: Box::new(DegreeConstrainedSpanningTree::new( diff --git a/src/models/graph/directed_hamiltonian_path.rs b/src/models/graph/directed_hamiltonian_path.rs index 261e04250..9e843478a 100644 --- a/src/models/graph/directed_hamiltonian_path.rs +++ b/src/models/graph/directed_hamiltonian_path.rs @@ -31,11 +31,8 @@ inventory::submit! { /// /// # Representation /// -/// A configuration encodes a permutation using the Lehmer code: -/// `dims() = [n, n-1, ..., 2, 1]`, yielding `n!` reachable configurations. -/// Each configuration is decoded to a permutation of `0..n`, and a solution is -/// valid when every consecutive pair `(path[i], path[i+1])` is an arc in the -/// directed graph. +/// A solution is a permutation of `0..n` whose consecutive vertices form directed +/// arcs. The reference solver enumerates Lehmer codes and decodes them to paths. /// /// # Example /// @@ -162,7 +159,6 @@ pub(crate) fn is_valid_directed_hamiltonian_path(graph: &DirectedGraph, perm: &[ seen[v] = true; } - // Check that consecutive pairs are directed arcs for i in 0..n.saturating_sub(1) { if !graph.has_arc(perm[i], perm[i + 1]) { return false; @@ -174,8 +170,6 @@ pub(crate) fn is_valid_directed_hamiltonian_path(graph: &DirectedGraph, perm: &[ #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // 6 vertices, arcs from issue #813 - // Hamiltonian path: [0, 1, 3, 2, 4, 5] let graph = DirectedGraph::new( 6, vec![ diff --git a/src/models/graph/eulerian_path.rs b/src/models/graph/eulerian_path.rs index 661ebd04a..3838078f1 100644 --- a/src/models/graph/eulerian_path.rs +++ b/src/models/graph/eulerian_path.rs @@ -44,7 +44,7 @@ inventory::submit! { /// A configuration is an arc-ordering `pi`: position `t` carries the index of /// the arc occurrence used as the `t`-th arc of the trail. /// -/// `dims() = vec![m; m]` where `m = num_arcs()`. A configuration is feasible +/// `dimensions() = vec![m; m]` where `m = num_arcs()`. A configuration is feasible /// when: /// 1. it is a permutation of `0..m` (all values distinct, each in range), and /// 2. for every consecutive pair `(pi[t], pi[t+1])`, the target vertex of arc @@ -180,9 +180,6 @@ fn is_valid_eulerian_trail(graph: &DirectedGraph, config: &[usize]) -> bool { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // Canonical YES instance from the issue: V = {0,1,2}, - // A = [(0,1), (0,1), (1,2), (2,0)] (parallel arcs a_0, a_1 between 0 and 1). - // Witness ordering (a_0, a_2, a_3, a_1) traces 0->1->2->0->1. let graph = DirectedGraph::new(3, vec![(0, 1), (0, 1), (1, 2), (2, 0)]); let optimal_config = vec![0usize, 2, 3, 1]; vec![crate::example_db::specs::ModelExampleSpec { diff --git a/src/models/graph/graph_partitioning.rs b/src/models/graph/graph_partitioning.rs index 6a59a6e48..c9d373b72 100644 --- a/src/models/graph/graph_partitioning.rs +++ b/src/models/graph/graph_partitioning.rs @@ -122,7 +122,6 @@ where if count_ones != n / 2 { return Ok(Min(None)); } - // Count crossing edges let mut cut = 0i64; for (u, v) in self.graph.edges() { if config[u] != config[v] { @@ -154,7 +153,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { use crate::topology::SimpleGraph; - // Two triangles connected by 3 edges; balanced cut = 3 vec![crate::example_db::specs::ModelExampleSpec { id: "graph_partitioning", instance: Box::new(GraphPartitioning::new(SimpleGraph::new( diff --git a/src/models/graph/hamiltonian_circuit.rs b/src/models/graph/hamiltonian_circuit.rs index 35ea2621c..bdccd48b5 100644 --- a/src/models/graph/hamiltonian_circuit.rs +++ b/src/models/graph/hamiltonian_circuit.rs @@ -170,7 +170,6 @@ pub(crate) fn is_valid_hamiltonian_circuit(graph: &G, config: &[usize] pub(crate) fn canonical_model_example_specs() -> Vec { vec![crate::example_db::specs::ModelExampleSpec { id: "hamiltonian_circuit_simplegraph", - // Prism graph (triangular prism): 6 vertices, 9 edges instance: Box::new(HamiltonianCircuit::new(SimpleGraph::new( 6, vec![ diff --git a/src/models/graph/hamiltonian_path.rs b/src/models/graph/hamiltonian_path.rs index b31d6d2ff..5ba9c643a 100644 --- a/src/models/graph/hamiltonian_path.rs +++ b/src/models/graph/hamiltonian_path.rs @@ -38,7 +38,7 @@ inventory::submit! { /// vertex visited at step `i`. A valid solution must be a permutation of /// `0..n` where consecutive entries are adjacent in the graph. /// -/// The search space has `dims() = [n; n]` (each position can hold any of `n` +/// The search space has `dimensions() = [n; n]` (each position can hold any of `n` /// vertices), so brute-force enumerates `n^n` configurations. Only `n!` /// permutations can satisfy the constraints, but the encoding avoids complex /// variable-domain schemes and matches the problem's natural formulation. @@ -160,7 +160,6 @@ pub(crate) fn is_valid_hamiltonian_path(graph: &G, config: &[usize]) - seen[v] = true; } - // Check consecutive vertices are adjacent for i in 0..n.saturating_sub(1) { if !graph.has_edge(config[i], config[i + 1]) { return false; diff --git a/src/models/graph/hamiltonian_path_between_two_vertices.rs b/src/models/graph/hamiltonian_path_between_two_vertices.rs index aff4b79cf..03a19ab89 100644 --- a/src/models/graph/hamiltonian_path_between_two_vertices.rs +++ b/src/models/graph/hamiltonian_path_between_two_vertices.rs @@ -46,7 +46,7 @@ inventory::submit! { /// - The last element equals `target_vertex` /// - Consecutive entries are adjacent in the graph /// -/// The search space has `dims() = [n; n]` (each position can hold any of `n` +/// The search space has `dimensions() = [n; n]` (each position can hold any of `n` /// vertices), so brute-force enumerates `n^n` configurations. /// /// # Type Parameters @@ -255,12 +255,10 @@ pub(crate) fn is_valid_hamiltonian_st_path( seen[v] = true; } - // Check endpoint constraints if config[0] != source || config[n - 1] != target { return false; } - // Check consecutive vertices are adjacent for i in 0..n.saturating_sub(1) { if !graph.has_edge(config[i], config[i + 1]) { return false; @@ -272,8 +270,6 @@ pub(crate) fn is_valid_hamiltonian_st_path( #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // Instance from issue #831: 6 vertices, s=0, t=5 - // Hamiltonian s-t path: [0, 3, 2, 1, 4, 5] vec![crate::example_db::specs::ModelExampleSpec { id: "hamiltonian_path_between_two_vertices_simplegraph", instance: Box::new(HamiltonianPathBetweenTwoVertices::new( diff --git a/src/models/graph/highly_connected_deletion.rs b/src/models/graph/highly_connected_deletion.rs index 436eb6f7c..11b6734ea 100644 --- a/src/models/graph/highly_connected_deletion.rs +++ b/src/models/graph/highly_connected_deletion.rs @@ -174,7 +174,6 @@ fn is_feasible_deletion(graph: &G, config: &[bool]) -> bool { } } - // Find connected components by BFS. let mut visited = vec![false; n]; for start in 0..n { if visited[start] { @@ -339,7 +338,6 @@ pub(crate) fn canonical_model_example_specs() -> Vec( graph.num_vertices(), "coloring length must match num_vertices" ); - // Check all colors are valid if coloring.iter().any(|&c| c >= num_colors) { return false; } - // Check no adjacent vertices have same color for (u, v) in graph.edges() { if coloring[u] == coloring[v] { return false; diff --git a/src/models/graph/kernel.rs b/src/models/graph/kernel.rs index 359c5ad42..a110f0ea5 100644 --- a/src/models/graph/kernel.rs +++ b/src/models/graph/kernel.rs @@ -103,7 +103,6 @@ impl Problem for Kernel { Ok({ let n = self.graph.num_vertices(); - // Collect selected vertices let selected = config; // Independence: no arc between any two selected vertices @@ -143,8 +142,6 @@ impl crate::solvers::BruteForceProblem for Kernel { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // 5 vertices, arcs: (0,1),(0,2),(1,3),(2,3),(3,4),(4,0),(4,1) - // Kernel: V' = {0, 3}. let graph = DirectedGraph::new( 5, vec![(0, 1), (0, 2), (1, 3), (2, 3), (3, 4), (4, 0), (4, 1)], diff --git a/src/models/graph/kth_best_spanning_tree.rs b/src/models/graph/kth_best_spanning_tree.rs index 1d20f3f3f..d794e3feb 100644 --- a/src/models/graph/kth_best_spanning_tree.rs +++ b/src/models/graph/kth_best_spanning_tree.rs @@ -333,11 +333,7 @@ where #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // K4 with weights [1,1,2,2,2,3], k=2, B=4. - // 16 spanning trees; exactly 2 have weight ≤ 4 (both weight 4): - // {01,02,03} (star at 0) and {01,02,13}. - // Satisfying configs = 2 (the two orderings of this pair). - // 12 variables → 2^12 = 4096 configs, fast to enumerate. + // Keep reference enumeration small enough for the example-db checks. let graph = SimpleGraph::new(4, vec![(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]); let problem = KthBestSpanningTree::new(graph, vec![1, 1, 2, 2, 2, 3], 2, 4); vec![crate::example_db::specs::ModelExampleSpec { diff --git a/src/models/graph/length_bounded_disjoint_paths.rs b/src/models/graph/length_bounded_disjoint_paths.rs index c13ecaa35..9609e0e9f 100644 --- a/src/models/graph/length_bounded_disjoint_paths.rs +++ b/src/models/graph/length_bounded_disjoint_paths.rs @@ -332,9 +332,6 @@ fn encode_paths(num_edges: usize, max_paths: usize, slots: &[&[usize]]) -> Vec Vec { let graph = SimpleGraph::new(5, vec![(0, 1), (1, 4), (0, 2), (2, 4), (0, 3), (3, 4)]); - // max_paths = min(deg(0), deg(4)) = min(3, 3) = 3 - // Three edge-selection rows over six edges. - // Optimal: 3 disjoint paths [0,1,4], [0,2,4], [0,3,4] vec![crate::example_db::specs::ModelExampleSpec { id: "length_bounded_disjoint_paths_simplegraph", instance: Box::new(LengthBoundedDisjointPaths::new(graph, 0, 4, 3)), diff --git a/src/models/graph/max_cut.rs b/src/models/graph/max_cut.rs index 607a40f65..f0ace732c 100644 --- a/src/models/graph/max_cut.rs +++ b/src/models/graph/max_cut.rs @@ -209,7 +209,6 @@ impl MaxCut { /// Get the weight of an edge between vertices u and v. pub fn edge_weight(&self, u: usize, v: usize) -> Option<&W> { - // Find the edge index for (idx, (eu, ev)) in self.graph.edges().iter().enumerate() { if (*eu == u && *ev == v) || (*eu == v && *ev == u) { return self.edge_weights.get(idx); diff --git a/src/models/graph/maximal_is.rs b/src/models/graph/maximal_is.rs index 3f73f7cfa..a60d7c39e 100644 --- a/src/models/graph/maximal_is.rs +++ b/src/models/graph/maximal_is.rs @@ -263,7 +263,6 @@ pub(crate) fn is_maximal_independent_set(graph: &G, selected: &[bool]) "selected length must match num_vertices" ); - // Check independence for (u, v) in graph.edges() { if selected[u] && selected[v] { return false; diff --git a/src/models/graph/maximum_achromatic_number.rs b/src/models/graph/maximum_achromatic_number.rs index 6046f97e1..4072a7109 100644 --- a/src/models/graph/maximum_achromatic_number.rs +++ b/src/models/graph/maximum_achromatic_number.rs @@ -193,8 +193,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // C6: 6-cycle, achromatic number = 3 - // Coloring [0, 1, 2, 0, 1, 2] uses 3 colors and is both proper and complete. vec![crate::example_db::specs::ModelExampleSpec { id: "maximum_achromatic_number_simplegraph", instance: Box::new(MaximumAchromaticNumber::new(SimpleGraph::new( diff --git a/src/models/graph/maximum_clique.rs b/src/models/graph/maximum_clique.rs index a39f3c40d..958be384b 100644 --- a/src/models/graph/maximum_clique.rs +++ b/src/models/graph/maximum_clique.rs @@ -207,7 +207,6 @@ where /// Check if a configuration forms a valid clique. fn is_clique_config(graph: &G, config: &[bool]) -> bool { - // Collect all selected vertices let selected: Vec = config .iter() .enumerate() @@ -215,7 +214,6 @@ fn is_clique_config(graph: &G, config: &[bool]) -> bool { .map(|(i, _)| i) .collect(); - // Check all pairs of selected vertices are adjacent for i in 0..selected.len() { for j in (i + 1)..selected.len() { if !graph.has_edge(selected[i], selected[j]) { @@ -286,7 +284,6 @@ pub(crate) fn is_clique(graph: &G, selected: &[bool]) -> bool { "selected length must match num_vertices" ); - // Collect selected vertices let selected_vertices: Vec = selected .iter() .enumerate() @@ -294,7 +291,6 @@ pub(crate) fn is_clique(graph: &G, selected: &[bool]) -> bool { .map(|(i, _)| i) .collect(); - // Check all pairs of selected vertices are adjacent for i in 0..selected_vertices.len() { for j in (i + 1)..selected_vertices.len() { if !graph.has_edge(selected_vertices[i], selected_vertices[j]) { diff --git a/src/models/graph/maximum_common_edge_subgraph.rs b/src/models/graph/maximum_common_edge_subgraph.rs index 39a70bafa..d00e1d3fe 100644 --- a/src/models/graph/maximum_common_edge_subgraph.rs +++ b/src/models/graph/maximum_common_edge_subgraph.rs @@ -159,7 +159,7 @@ impl LabelledDigraph { /// /// # Configuration encoding /// -/// `dims()` returns `vec![graph_2.num_vertices + 1; graph_1.num_vertices]`. +/// `BruteForceProblem::dimensions()` returns `vec![graph_2.num_vertices + 1; graph_1.num_vertices]`. /// For each source vertex `u in V1`, `config[u]` is either an index in /// `0..graph_2.num_vertices` (the matched target vertex) or the sentinel /// value `graph_2.num_vertices` denoting `bottom` (unmatched). Feasibility @@ -357,8 +357,6 @@ pub(crate) fn canonical_model_example_specs() -> Vec0, 1->1, 2->2, 3->3, - // 4->bottom preserves the first five source arcs. optimal_config: serde_json::json!(vec![0, 1, 2, 3, 4]), optimal_value: serde_json::json!(5), }] diff --git a/src/models/graph/maximum_contact_map_overlap.rs b/src/models/graph/maximum_contact_map_overlap.rs index ae22629b7..41e0be746 100644 --- a/src/models/graph/maximum_contact_map_overlap.rs +++ b/src/models/graph/maximum_contact_map_overlap.rs @@ -64,7 +64,7 @@ inventory::submit! { /// /// # Configuration encoding /// -/// `dims()` returns `vec![|V_2| + 1; |V_1|]`. For each source vertex `i`, +/// `BruteForceProblem::dimensions()` returns `vec![|V_2| + 1; |V_1|]`. For each source vertex `i`, /// `config[i] = 0` denotes `bot` (unmatched) and `config[i] = j + 1` denotes /// "matched to vertex `j in V_2`". Feasibility requires that the nonzero /// entries are pairwise distinct (injectivity) and strictly increasing along @@ -317,15 +317,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // Canonical example from the issue: - // G_1: n_1 = 4, E_1 = {{0,2}, {1,3}} - // G_2: n_2 = 5, E_2 = {{0,3}, {1,4}, {0,2}} - // Optimal alignment: 0->0, 1->1, 2->3, 3->4 (encoded as [1, 2, 4, 5]). - // - order-preserving: 1 < 2 < 4 < 5 - // - injectivity: all values distinct - // - contact {0,2}: mapped (0, 3); sorted (0, 3) in E_2 - // - contact {1,3}: mapped (1, 4); sorted (1, 4) in E_2 - // - value = 2 contacts preserved. vec![crate::example_db::specs::ModelExampleSpec { id: "maximum_contact_map_overlap", instance: Box::new(MaximumContactMapOverlap::new( diff --git a/src/models/graph/maximum_domatic_number.rs b/src/models/graph/maximum_domatic_number.rs index fce59b0e1..05ff4ff8c 100644 --- a/src/models/graph/maximum_domatic_number.rs +++ b/src/models/graph/maximum_domatic_number.rs @@ -92,7 +92,6 @@ impl MaximumDomaticNumber { return None; } - // Collect which vertices belong to each set let mut sets: Vec> = vec![vec![]; n]; for (v, &set_idx) in config.iter().enumerate() { // Each set index must be within bounds of the available sets. @@ -102,7 +101,6 @@ impl MaximumDomaticNumber { sets[set_idx].push(v); } - // Check each non-empty set is a dominating set let mut count = 0; for set in &sets { if set.is_empty() { @@ -110,7 +108,6 @@ impl MaximumDomaticNumber { } count += 1; - // Build membership lookup let mut in_set = vec![false; n]; for &v in set { in_set[v] = true; diff --git a/src/models/graph/maximum_edge_weighted_k_clique.rs b/src/models/graph/maximum_edge_weighted_k_clique.rs index 4794fcbbf..8bde51c2e 100644 --- a/src/models/graph/maximum_edge_weighted_k_clique.rs +++ b/src/models/graph/maximum_edge_weighted_k_clique.rs @@ -51,7 +51,7 @@ inventory::submit! { /// use problemreductions::types::Max; /// use problemreductions::{BruteForce, Problem}; /// -/// // Graph from issue #1020: 4 vertices, triangles {0,1,2} and {0,1,3}. +/// // Graph: 4 vertices, triangles {0,1,2} and {0,1,3}. /// let graph = SimpleGraph::new(4, vec![(0, 1), (0, 2), (1, 2), (0, 3), (1, 3)]); /// let weights = vec![5_i64, 4, -1, 1, 0]; /// let problem = MaximumEdgeWeightedKClique::new(graph, weights, 3).unwrap(); diff --git a/src/models/graph/maximum_leaf_spanning_tree.rs b/src/models/graph/maximum_leaf_spanning_tree.rs index c7fb0d973..0ca004794 100644 --- a/src/models/graph/maximum_leaf_spanning_tree.rs +++ b/src/models/graph/maximum_leaf_spanning_tree.rs @@ -114,7 +114,6 @@ fn is_valid_spanning_tree(graph: &G, config: &[bool]) -> bool { return false; } - // Count selected edges let selected_count = config.iter().filter(|&&selected| selected).count(); if selected_count != n - 1 { return false; @@ -247,9 +246,6 @@ pub(crate) fn canonical_model_example_specs() -> Vec MinMaxMulticenter { let mut dist: Vec> = vec![None; n]; let mut visited = vec![false; n]; - // Initialize centers for (v, &selected) in config.iter().enumerate() { if selected { dist[v] = Some(W::Sum::zero()); @@ -294,7 +293,6 @@ impl MinMaxMulticenter { } for _ in 0..n { - // Find unvisited vertex with smallest distance let mut u = None; for v in 0..n { if visited[v] { @@ -371,13 +369,11 @@ where )); } - // Check exactly K centers are selected let num_selected = config.iter().filter(|&&selected| selected).count(); if num_selected != self.k { return Ok(Min(None)); } - // Compute shortest distances to nearest center let distances = match self.shortest_distances(config)? { Some(d) => d, None => { diff --git a/src/models/graph/minimum_capacitated_spanning_tree.rs b/src/models/graph/minimum_capacitated_spanning_tree.rs index ad014ba6d..13d7b5204 100644 --- a/src/models/graph/minimum_capacitated_spanning_tree.rs +++ b/src/models/graph/minimum_capacitated_spanning_tree.rs @@ -277,7 +277,6 @@ fn is_spanning_tree(graph: &G, config: &[bool]) -> bool { return false; } - // Build adjacency and BFS from vertex 0 let mut adj: Vec> = vec![vec![]; n]; for (idx, &sel) in config.iter().enumerate() { if sel { @@ -315,7 +314,6 @@ fn check_capacity( let n = graph.num_vertices(); let edges = graph.edges(); - // Build adjacency list with edge indices let mut adj: Vec> = vec![vec![]; n]; // (neighbor, edge_idx) for (idx, &sel) in config.iter().enumerate() { if sel { @@ -344,7 +342,6 @@ fn check_capacity( } } - // Compute subtree sums bottom-up let mut subtree_sum: Vec = requirements.iter().map(|r| r.to_sum()).collect(); for &v in order.iter().rev() { if v != root { @@ -473,15 +470,11 @@ pub(crate) fn canonical_model_example_specs() -> Vecreq=2<=3, subtree(2)={2}->req=1<=3, - // subtree(4)={4}->req=1<=3, subtree(3)={3}->req=1<=3 optimal_config: serde_json::json!(vec![true, true, false, false, true, false, false, true]), optimal_value: serde_json::json!(5), }] diff --git a/src/models/graph/minimum_cost_circulation.rs b/src/models/graph/minimum_cost_circulation.rs index 5c732cd54..11b5005f7 100644 --- a/src/models/graph/minimum_cost_circulation.rs +++ b/src/models/graph/minimum_cost_circulation.rs @@ -20,11 +20,11 @@ //! //! # Integral-circulation restriction //! -//! The mathematical formulation in issue #1030 uses continuous flows +//! The continuous formulation allows flows //! `g: A -> R_{>= 0}`, but this model's registered reference solver uses a //! finite Cartesian space. Following the same precedent as //! [`MinimumEdgeCostFlow`](super::MinimumEdgeCostFlow) and -//! the recently added [`MinimumCostMaximumFlow`](super::MinimumCostMaximumFlow), +//! [`MinimumCostMaximumFlow`](super::MinimumCostMaximumFlow), //! we therefore restrict to **integer** circulations: each variable //! `g(a)` ranges over `{0, 1, ..., c(a)}`. When capacities and costs are //! integral, the standard minimum-cost flow theory (see e.g. the MIT @@ -293,12 +293,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // Two competing cycles on V = {0, 1, 2}: - // cycle A: 0->1->0 (cost per unit = 2 + (-3) = -1, capacity 2) - // cycle B: 0->2->0 (cost per unit = 1 + (-4) = -3, capacity 1) - // Optimal: push both to capacity. - // arc 0 (0->1) = 2, arc 1 (1->0) = 2, arc 2 (0->2) = 1, arc 3 (2->0) = 1 - // cost = 2*2 + 2*(-3) + 1*1 + 1*(-4) = 4 - 6 + 1 - 4 = -5 let problem = MinimumCostCirculation::new( crate::topology::DirectedGraph::new(3, vec![(0, 1), (1, 0), (0, 2), (2, 0)]), vec![2, 2, 1, 1], diff --git a/src/models/graph/minimum_cost_maximum_flow.rs b/src/models/graph/minimum_cost_maximum_flow.rs index 78cf0e271..9652db515 100644 --- a/src/models/graph/minimum_cost_maximum_flow.rs +++ b/src/models/graph/minimum_cost_maximum_flow.rs @@ -14,8 +14,8 @@ //! //! # Integral-flow restriction //! -//! The mathematical CellRouter formulation in issue #1029 uses -//! continuous flows `f: A -> R_{>= 0}`, but this model's registered reference +//! The continuous formulation allows flows +//! `f: A -> R_{>= 0}`, but this model's registered reference //! solver uses a finite Cartesian space. Following the same precedent as //! [`MinimumEdgeCostFlow`](super::MinimumEdgeCostFlow) (see //! `src/models/graph/minimum_edge_cost_flow.rs`), we therefore restrict @@ -458,12 +458,6 @@ pub(crate) fn canonical_model_example_specs() -> Vec1->3 via arcs 0,3 (cost 1 + 1 = 2) - // - 1 unit on 0->1->2->3 via arcs 0,2,4 (cost 1 + 0 + 2 = 3) - // - 1 unit on 0->2->3 via arcs 1,4 (cost 0 + 2 = 2) - // Arc flows sum to f = [2, 1, 1, 1, 2]: value = 3, - // cost = 2*1 + 1*0 + 1*0 + 1*1 + 2*2 = 7. let optimal_config = vec![2, 1, 1, 1, 2]; let optimal_value = problem .evaluate(&optimal_config) diff --git a/src/models/graph/minimum_covering_by_cliques.rs b/src/models/graph/minimum_covering_by_cliques.rs index f664ced7b..1f5f52048 100644 --- a/src/models/graph/minimum_covering_by_cliques.rs +++ b/src/models/graph/minimum_covering_by_cliques.rs @@ -108,7 +108,6 @@ impl MinimumCoveringByCliques { groups[group].insert(v); } - // Check that each group's vertices form a clique. for vertices in &groups { let verts: Vec = vertices.iter().copied().collect(); for i in 0..verts.len() { @@ -191,14 +190,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // 6 vertices, 9 edges: - // (0,1),(1,2),(2,3),(3,0),(0,2),(4,0),(4,1),(5,2),(5,3) - // Optimal: 4 cliques - // edges 0,1,4 -> group 0 (clique {0,1,2}) - // edges 2,3 -> group 1 (clique {0,2,3}... wait, (2,3) and (3,0) -> vertices {0,2,3}) - // edges 5,6 -> group 2 (clique {0,1,4}) - // edges 7,8 -> group 3 (clique {2,3,5}) - // Config: [0, 0, 1, 1, 0, 2, 2, 3, 3] vec![crate::example_db::specs::ModelExampleSpec { id: "minimum_covering_by_cliques_simplegraph", instance: Box::new(MinimumCoveringByCliques::new(SimpleGraph::new( diff --git a/src/models/graph/minimum_cut_into_bounded_sets.rs b/src/models/graph/minimum_cut_into_bounded_sets.rs index 8d03f2846..449f1402f 100644 --- a/src/models/graph/minimum_cut_into_bounded_sets.rs +++ b/src/models/graph/minimum_cut_into_bounded_sets.rs @@ -252,14 +252,12 @@ where return Ok(Min(None)); } - // Check size bounds let count_v1 = config.iter().filter(|&&x| !x).count(); let count_v2 = config.iter().filter(|&&x| x).count(); if count_v1 > self.size_bound || count_v2 > self.size_bound { return Ok(Min(None)); } - // Compute cut weight let mut cut_weight = W::Sum::zero(); for ((u, v), weight) in self.graph.edges().iter().zip(self.edge_weights.iter()) { if config[*u] != config[*v] { @@ -313,7 +311,6 @@ pub(crate) fn canonical_model_example_specs() -> Vec 6 optimal_config: serde_json::json!(vec![false, false, false, false, true, true, true, true]), optimal_value: serde_json::json!(6), }] diff --git a/src/models/graph/minimum_dominating_set.rs b/src/models/graph/minimum_dominating_set.rs index c21a23dc0..1c3f11d26 100644 --- a/src/models/graph/minimum_dominating_set.rs +++ b/src/models/graph/minimum_dominating_set.rs @@ -447,7 +447,6 @@ pub(crate) fn is_dominating_set(graph: &G, selected: &[bool]) -> bool "selected length must match num_vertices" ); - // Check each vertex is dominated for v in 0..graph.num_vertices() { if selected[v] { continue; // v dominates itself diff --git a/src/models/graph/minimum_edge_cost_flow.rs b/src/models/graph/minimum_edge_cost_flow.rs index a704282b2..1070bcb2e 100644 --- a/src/models/graph/minimum_edge_cost_flow.rs +++ b/src/models/graph/minimum_edge_cost_flow.rs @@ -369,14 +369,12 @@ pub(crate) fn canonical_model_example_specs() -> Vec Vec { use crate::topology::DirectedGraph; - // 3-node cycle, unit weights; remove one arc to break cycle, cost = 1 vec![crate::example_db::specs::ModelExampleSpec { id: "minimum_feedback_arc_set", instance: Box::new(MinimumFeedbackArcSet::new( diff --git a/src/models/graph/minimum_graph_bandwidth.rs b/src/models/graph/minimum_graph_bandwidth.rs index d214d03e8..4059693eb 100644 --- a/src/models/graph/minimum_graph_bandwidth.rs +++ b/src/models/graph/minimum_graph_bandwidth.rs @@ -187,11 +187,7 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { use crate::topology::SimpleGraph; - // Star graph S4: center 0 connected to 1, 2, 3 - // Config [1,0,2,3]: f(0)=1, f(1)=0, f(2)=2, f(3)=3 - // Bandwidth = max(|1-0|, |1-2|, |1-3|) = max(1, 1, 2) = 2 - // Optimal bandwidth for S4 is 2 (center must be adjacent to all leaves, - // placing center at position 1 achieves max stretch 2). + // The center has three neighbors, forcing bandwidth at least 2. vec![crate::example_db::specs::ModelExampleSpec { id: "minimum_graph_bandwidth", instance: Box::new(MinimumGraphBandwidth::new(SimpleGraph::new( diff --git a/src/models/graph/minimum_intersection_graph_basis.rs b/src/models/graph/minimum_intersection_graph_basis.rs index 2f26294c4..5d439b59d 100644 --- a/src/models/graph/minimum_intersection_graph_basis.rs +++ b/src/models/graph/minimum_intersection_graph_basis.rs @@ -147,7 +147,6 @@ where } } - // Count elements used (union of all subsets) let used: HashSet = subsets.iter().flat_map(|s| s.iter().copied()).collect(); Min(Some(i64::try_from(used.len()).map_err(|_| { crate::traits::EvaluationError::IntegerOverflow( @@ -189,10 +188,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // P3: 3 vertices, edges (0,1), (1,2), num_edges=2 - // Intersection number = 2: S[0]={0}, S[1]={0,1}, S[2]={1} - // Incidence rows: vertex 0: [true,false], vertex 1: [true,true], - // vertex 2: [false,true]. vec![crate::example_db::specs::ModelExampleSpec { id: "minimum_intersection_graph_basis_simplegraph", instance: Box::new(MinimumIntersectionGraphBasis::new(SimpleGraph::new( diff --git a/src/models/graph/minimum_maximal_matching.rs b/src/models/graph/minimum_maximal_matching.rs index d559fb9c1..d959f9e3d 100644 --- a/src/models/graph/minimum_maximal_matching.rs +++ b/src/models/graph/minimum_maximal_matching.rs @@ -183,8 +183,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // Path graph P6: 6 vertices, edges [(0,1),(1,2),(2,3),(3,4),(4,5)] - // config [0,1,0,1,0] = edges {(1,2),(3,4)} — a maximal matching of size 2. vec![crate::example_db::specs::ModelExampleSpec { id: "minimum_maximal_matching_simplegraph", instance: Box::new(MinimumMaximalMatching::new(SimpleGraph::new( diff --git a/src/models/graph/minimum_multiway_cut.rs b/src/models/graph/minimum_multiway_cut.rs index 8be80045e..fb143d22a 100644 --- a/src/models/graph/minimum_multiway_cut.rs +++ b/src/models/graph/minimum_multiway_cut.rs @@ -175,7 +175,6 @@ fn terminals_separated(graph: &G, terminals: &[usize], config: &[bool] let n = graph.num_vertices(); let edges = graph.edges(); - // Build adjacency list from non-cut edges let mut adj: Vec> = vec![vec![]; n]; for (idx, (u, v)) in edges.iter().enumerate() { if !config[idx] { diff --git a/src/models/graph/minimum_sum_multicenter.rs b/src/models/graph/minimum_sum_multicenter.rs index e202b2dd2..353a748d4 100644 --- a/src/models/graph/minimum_sum_multicenter.rs +++ b/src/models/graph/minimum_sum_multicenter.rs @@ -261,7 +261,6 @@ impl MinimumSumMulticenter { let mut dist: Vec> = vec![None; n]; let mut visited = vec![false; n]; - // Initialize centers for (v, &selected) in config.iter().enumerate() { if selected { dist[v] = Some(W::Sum::zero()); @@ -269,7 +268,6 @@ impl MinimumSumMulticenter { } for _ in 0..n { - // Find unvisited vertex with smallest distance let mut u = None; for v in 0..n { if visited[v] { @@ -337,13 +335,11 @@ where )); } Ok({ - // Check exactly K centers are selected let num_selected = config.iter().filter(|&&selected| selected).count(); if num_selected != self.k { return Ok(Min(None)); } - // Compute shortest distances to nearest center let distances = match self.shortest_distances(config) { Some(d) => d, None => return Ok(Min(None)), diff --git a/src/models/graph/monochromatic_triangle.rs b/src/models/graph/monochromatic_triangle.rs index b4ef79649..d96db2761 100644 --- a/src/models/graph/monochromatic_triangle.rs +++ b/src/models/graph/monochromatic_triangle.rs @@ -222,13 +222,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // K4: 4 vertices, 6 edges, has a valid 2-coloring avoiding monochromatic triangles. - // Edges in order: (0,1),(0,2),(0,3),(1,2),(1,3),(2,3) - // Config [0,0,1,1,0,1]: - // Triangle (0,1,2): edges 0,1,3 -> colors 0,0,1 -> not monochromatic - // Triangle (0,1,3): edges 0,2,4 -> colors 0,1,0 -> not monochromatic - // Triangle (0,2,3): edges 1,2,5 -> colors 0,1,1 -> not monochromatic - // Triangle (1,2,3): edges 3,4,5 -> colors 1,0,1 -> not monochromatic vec![crate::example_db::specs::ModelExampleSpec { id: "monochromatic_triangle_simplegraph", instance: Box::new(MonochromaticTriangle::new(SimpleGraph::new( diff --git a/src/models/graph/optimal_linear_arrangement.rs b/src/models/graph/optimal_linear_arrangement.rs index c50552603..6fa590f25 100644 --- a/src/models/graph/optimal_linear_arrangement.rs +++ b/src/models/graph/optimal_linear_arrangement.rs @@ -248,8 +248,6 @@ crate::register_decision_variant!( #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { use crate::topology::SimpleGraph; - // 6 vertices, 7 edges (path + two long chords) - // Optimal arrangement [0,1,2,3,4,5] gives cost 1+1+1+1+1+3+3 = 11 vec![crate::example_db::specs::ModelExampleSpec { id: "optimal_linear_arrangement", instance: Box::new(OptimalLinearArrangement::new(SimpleGraph::new( diff --git a/src/models/graph/partition_into_forests.rs b/src/models/graph/partition_into_forests.rs index 1d5c02893..20f637d3d 100644 --- a/src/models/graph/partition_into_forests.rs +++ b/src/models/graph/partition_into_forests.rs @@ -220,8 +220,6 @@ pub(crate) fn canonical_model_example_specs() -> Vec PartitionIntoPathsOfLength2 { return false; } - // Check all assignments are in range if config.iter().any(|&g| g >= q) { return false; } diff --git a/src/models/graph/partition_into_triangles.rs b/src/models/graph/partition_into_triangles.rs index 772f82471..64be075b5 100644 --- a/src/models/graph/partition_into_triangles.rs +++ b/src/models/graph/partition_into_triangles.rs @@ -134,21 +134,18 @@ where let n = self.graph.num_vertices(); let q = n / 3; - // Check config length if config.len() != n { return Err(crate::traits::EvaluationError::InvalidConfiguration( "partition assignment length does not match the graph vertices".into(), )); } - // Check all values are in range [0, q) if config.iter().any(|&c| c >= q) { return Err(crate::traits::EvaluationError::InvalidConfiguration( "partition assignment contains an out-of-range group".into(), )); } - // Count vertices per group let mut counts = vec![0usize; q]; for &c in config { counts[c] += 1; @@ -169,7 +166,6 @@ where group_pos[g] = pos + 1; } - // Check each group forms a triangle for verts in &group_verts { if !self.graph.has_edge(verts[0], verts[1]) { return Ok(crate::types::Or(false)); diff --git a/src/models/graph/prize_collecting_steiner_forest.rs b/src/models/graph/prize_collecting_steiner_forest.rs index a29bfae3d..2b5aa49ae 100644 --- a/src/models/graph/prize_collecting_steiner_forest.rs +++ b/src/models/graph/prize_collecting_steiner_forest.rs @@ -474,10 +474,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // Issue #1026 canonical instance: path 0 - 1 - 2 with edge costs - // c(0,1)=1, c(1,2)=6, vertex prizes p = (5, 2, 5), beta = 1, omega = 2. - // Optimum: V_F = {0,1,2}, E_F = {(0,1)} (two components {0,1} and {2}), - // objective = 0 + 1 + 2*2 = 5. vec![crate::example_db::specs::ModelExampleSpec { id: "prize_collecting_steiner_forest_simplegraph", instance: Box::new( diff --git a/src/models/graph/rural_postman.rs b/src/models/graph/rural_postman.rs index da7737b8a..26f60b6a7 100644 --- a/src/models/graph/rural_postman.rs +++ b/src/models/graph/rural_postman.rs @@ -243,7 +243,6 @@ impl RuralPostman { let edges = self.graph.edges(); let n = self.graph.num_vertices(); - // Check all required edges are traversed at least once for &req_idx in &self.required_edges { if config[req_idx] == 0 { return Ok(None); @@ -394,8 +393,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { use crate::topology::SimpleGraph; - // Issue #248 instance 1: hexagonal graph, 8 edges, E'={e0,e2,e4} - // Solution: hexagon cycle with all 6 unit-cost edges, config [1,1,1,1,1,1,0,0], cost=6 let graph = SimpleGraph::new( 6, vec![ diff --git a/src/models/graph/steiner_tree.rs b/src/models/graph/steiner_tree.rs index 585174952..55f754183 100644 --- a/src/models/graph/steiner_tree.rs +++ b/src/models/graph/steiner_tree.rs @@ -214,7 +214,6 @@ fn is_valid_steiner_tree(graph: &G, terminals: &[usize], config: &[boo return false; } - // Build adjacency list from selected edges let mut adj: Vec> = vec![vec![]; n]; let mut selected_count = 0usize; let mut involved = vec![false; n]; diff --git a/src/models/graph/strong_connectivity_augmentation.rs b/src/models/graph/strong_connectivity_augmentation.rs index 5fbe8e943..f49bb31ec 100644 --- a/src/models/graph/strong_connectivity_augmentation.rs +++ b/src/models/graph/strong_connectivity_augmentation.rs @@ -262,21 +262,19 @@ where pub(crate) fn canonical_model_example_specs() -> Vec { vec![crate::example_db::specs::ModelExampleSpec { id: "strong_connectivity_augmentation", - // Path digraph 0→1→2→3→4 (not strongly connected — no back-edges). - // Nine candidate arcs are all individually affordable, but only the - // pair (4→1, w=3) + (1→0, w=5) = 8 = B achieves strong connectivity. + // The budget forces a two-arc repair instead of the direct closing arc. instance: Box::new(StrongConnectivityAugmentation::new( DirectedGraph::new(5, vec![(0, 1), (1, 2), (2, 3), (3, 4)]), vec![ - (4, 0, 10), // direct fix, too expensive - (4, 3, 3), // 4-escape to dead end - (4, 2, 3), // 4-escape to dead end - (4, 1, 3), // correct 4-escape - (3, 0, 7), // too expensive to combine - (3, 1, 3), // dead-end intermediate - (2, 0, 7), // too expensive to combine - (2, 1, 3), // dead-end intermediate - (1, 0, 5), // the closing arc + (4, 0, 10), + (4, 3, 3), + (4, 2, 3), + (4, 1, 3), + (3, 0, 7), + (3, 1, 3), + (2, 0, 7), + (2, 1, 3), + (1, 0, 5), ], 8, )), diff --git a/src/models/graph/subgraph_isomorphism.rs b/src/models/graph/subgraph_isomorphism.rs index def3018fc..569ad0484 100644 --- a/src/models/graph/subgraph_isomorphism.rs +++ b/src/models/graph/subgraph_isomorphism.rs @@ -199,7 +199,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { use crate::topology::SimpleGraph; - // Host: K4, Pattern: K3 → map [0,1,2] preserves all edges vec![crate::example_db::specs::ModelExampleSpec { id: "subgraph_isomorphism", instance: Box::new(SubgraphIsomorphism::new( diff --git a/src/models/misc/additional_key.rs b/src/models/misc/additional_key.rs index 99739ab6c..c0ae3ccd8 100644 --- a/src/models/misc/additional_key.rs +++ b/src/models/misc/additional_key.rs @@ -250,7 +250,6 @@ impl Problem for AdditionalKey { ) -> Result { Ok({ crate::types::Or({ - // Check config length if config.len() != self.relation_attrs.len() { return Err(crate::traits::EvaluationError::InvalidConfiguration( "attribute-selection length does not match the relation".into(), @@ -270,14 +269,12 @@ impl Problem for AdditionalKey { return Ok(crate::types::Or(false)); } - // Compute closure of selected attributes let mut attr_set = vec![false; self.num_attributes]; for &a in &selected { attr_set[a] = true; } let closure = self.compute_closure(&attr_set); - // Check closure covers all relation_attrs if !self.relation_attrs.iter().all(|&a| closure[a]) { return Ok(crate::types::Or(false)); } diff --git a/src/models/misc/bin_packing.rs b/src/models/misc/bin_packing.rs index 994c064b8..70a489bfb 100644 --- a/src/models/misc/bin_packing.rs +++ b/src/models/misc/bin_packing.rs @@ -188,11 +188,9 @@ where return Ok(false); } let n = sizes.len(); - // Check all bin indices are in range if config.iter().any(|&b| b >= n) { return Ok(false); } - // Compute load per bin let cap_sum = capacity.to_sum(); let mut bin_load: Vec = vec![W::Sum::zero(); n]; for (i, &bin) in config.iter().enumerate() { @@ -202,7 +200,6 @@ where "summing bin loads", )?; } - // Check capacity constraints Ok(bin_load.iter().all(|load| *load <= cap_sum)) } @@ -231,7 +228,6 @@ crate::register_brute_force! { pub(crate) fn canonical_model_example_specs() -> Vec { vec![crate::example_db::specs::ModelExampleSpec { id: "bin_packing", - // 3 items of sizes [3,3,4], capacity 7 → optimal 2 bins instance: Box::new(BinPacking::::new(vec![3, 3, 4], 7).unwrap()), optimal_config: serde_json::json!(vec![0, 1, 0]), optimal_value: serde_json::json!(2), diff --git a/src/models/misc/boyce_codd_normal_form_violation.rs b/src/models/misc/boyce_codd_normal_form_violation.rs index ec40d58df..1b387d518 100644 --- a/src/models/misc/boyce_codd_normal_form_violation.rs +++ b/src/models/misc/boyce_codd_normal_form_violation.rs @@ -291,7 +291,6 @@ pub(crate) fn canonical_model_example_specs() -> Vec violation optimal_config: serde_json::json!(vec![false, false, true, false, false, false]), optimal_value: serde_json::json!(true), }] diff --git a/src/models/misc/closest_substring.rs b/src/models/misc/closest_substring.rs index ece27fc47..d0a0e405d 100644 --- a/src/models/misc/closest_substring.rs +++ b/src/models/misc/closest_substring.rs @@ -252,8 +252,6 @@ pub(crate) fn canonical_model_example_specs() -> Vec Vec { - // 6 elements in two tight groups {0,1,2} and {3,4,5} - // Intra-group distance = 1, inter-group distance = 3 - // K=2, B=1 let distances = vec![ vec![0, 1, 1, 3, 3, 3], vec![1, 0, 1, 3, 3, 3], diff --git a/src/models/misc/conjunctive_boolean_query.rs b/src/models/misc/conjunctive_boolean_query.rs index 5853e5285..b964d6329 100644 --- a/src/models/misc/conjunctive_boolean_query.rs +++ b/src/models/misc/conjunctive_boolean_query.rs @@ -324,8 +324,6 @@ crate::register_brute_force! { pub(crate) fn canonical_model_example_specs() -> Vec { vec![crate::example_db::specs::ModelExampleSpec { id: "conjunctive_boolean_query", - // D={0..5}, 2 relations (binary R0, ternary R1), 3 atoms, 2 variables. - // Satisfying assignment: y0=0, y1=1. instance: Box::new(ConjunctiveBooleanQuery::new( 6, vec![ diff --git a/src/models/misc/conjunctive_query_foldability.rs b/src/models/misc/conjunctive_query_foldability.rs index dc61d1e2b..2943657b5 100644 --- a/src/models/misc/conjunctive_query_foldability.rs +++ b/src/models/misc/conjunctive_query_foldability.rs @@ -365,7 +365,6 @@ impl Problem for ConjunctiveQueryFoldability { }) .collect(); - // Collect Q2 as a set. let q2_set: HashSet<(usize, Vec)> = self.query2_conjuncts.iter().cloned().collect(); @@ -393,30 +392,23 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // YES instance: triangle + self-loop folds to lollipop. - // - // Q1: R(x, u) ∧ R(u, v) ∧ R(v, x) ∧ R(u, u) - // Q2: R(x, a) ∧ R(a, a) ∧ R(a, x) - // - // The substitution σ: U(0) → U(2), U(1) → U(2), U(2) → U(2) - // maps Q1 → Q2 (as a set). Config = [3, 3, 3]. vec![crate::example_db::specs::ModelExampleSpec { id: "conjunctive_query_foldability", instance: Box::new(ConjunctiveQueryFoldability::new( - 0, // domain_size - 1, // num_distinguished (x) - 3, // num_undistinguished (u, v, a) - vec![2], // one binary relation R + 0, + 1, + 3, + vec![2], vec![ - (0, vec![Term::Distinguished(0), Term::Undistinguished(0)]), // R(x, u) - (0, vec![Term::Undistinguished(0), Term::Undistinguished(1)]), // R(u, v) - (0, vec![Term::Undistinguished(1), Term::Distinguished(0)]), // R(v, x) - (0, vec![Term::Undistinguished(0), Term::Undistinguished(0)]), // R(u, u) + (0, vec![Term::Distinguished(0), Term::Undistinguished(0)]), + (0, vec![Term::Undistinguished(0), Term::Undistinguished(1)]), + (0, vec![Term::Undistinguished(1), Term::Distinguished(0)]), + (0, vec![Term::Undistinguished(0), Term::Undistinguished(0)]), ], vec![ - (0, vec![Term::Distinguished(0), Term::Undistinguished(2)]), // R(x, a) - (0, vec![Term::Undistinguished(2), Term::Undistinguished(2)]), // R(a, a) - (0, vec![Term::Undistinguished(2), Term::Distinguished(0)]), // R(a, x) + (0, vec![Term::Distinguished(0), Term::Undistinguished(2)]), + (0, vec![Term::Undistinguished(2), Term::Undistinguished(2)]), + (0, vec![Term::Undistinguished(2), Term::Distinguished(0)]), ], )), optimal_config: serde_json::json!(vec![3, 3, 3]), diff --git a/src/models/misc/dynamic_storage_allocation.rs b/src/models/misc/dynamic_storage_allocation.rs index 37ccb3c60..959155285 100644 --- a/src/models/misc/dynamic_storage_allocation.rs +++ b/src/models/misc/dynamic_storage_allocation.rs @@ -141,7 +141,6 @@ impl Problem for DynamicStorageAllocation { )); } - // Check each item fits within memory for (i, &(_, _, size)) in self.items.iter().enumerate() { let start = config[i]; if start + size > self.memory_size { diff --git a/src/models/misc/ensemble_computation.rs b/src/models/misc/ensemble_computation.rs index abe93a81c..eb624b9bf 100644 --- a/src/models/misc/ensemble_computation.rs +++ b/src/models/misc/ensemble_computation.rs @@ -258,8 +258,7 @@ impl TryFrom for EnsembleComputation { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // Keep the canonical example small enough for the example-db optimality check to solve - // it via brute force, while still demonstrating reuse of a previously computed set. + // Keep reference enumeration small while exercising reuse of a computed set. vec![crate::example_db::specs::ModelExampleSpec { id: "ensemble_computation", instance: Box::new(EnsembleComputation::new( diff --git a/src/models/misc/feasible_register_assignment.rs b/src/models/misc/feasible_register_assignment.rs index ae7322efc..d6e61c3f7 100644 --- a/src/models/misc/feasible_register_assignment.rs +++ b/src/models/misc/feasible_register_assignment.rs @@ -242,7 +242,6 @@ impl FeasibleRegisterAssignment { order[position] = vertex; } - // Check topological ordering and register conflicts let mut computed = vec![false; n]; for step in 0..n { @@ -328,16 +327,12 @@ crate::register_brute_force! { pub(crate) fn canonical_model_example_specs() -> Vec { vec![crate::example_db::specs::ModelExampleSpec { id: "feasible_register_assignment", - // 4 vertices, arcs: (0,1),(0,2),(1,3), K=2, assignment [0,1,0,0] - // Valid order: v3, v1, v2, v0 -> config [3, 1, 2, 0] instance: Box::new(FeasibleRegisterAssignment::new( 4, vec![(0, 1), (0, 2), (1, 3)], 2, vec![0, 1, 0, 0], )), - // config[v] = position: v0 at pos 3, v1 at pos 1, v2 at pos 2, v3 at pos 0 - // Order: v3(pos0), v1(pos1), v2(pos2), v0(pos3) optimal_config: serde_json::json!(vec![3, 1, 2, 0]), optimal_value: serde_json::json!(true), }] diff --git a/src/models/misc/flow_shop_scheduling.rs b/src/models/misc/flow_shop_scheduling.rs index a33e1b30a..4fb5c9f5a 100644 --- a/src/models/misc/flow_shop_scheduling.rs +++ b/src/models/misc/flow_shop_scheduling.rs @@ -35,13 +35,8 @@ inventory::submit! { /// /// # Representation /// -/// Configurations use Lehmer code encoding with `dims() = [n, n-1, ..., 1]`. -/// A config `[c_0, c_1, ..., c_{n-1}]` where `c_i < n - i` is decoded by -/// maintaining a list of available jobs and picking the `c_i`-th element: -/// -/// For 3 jobs, config `[2, 0, 0]`: available=`[0,1,2]`, pick index 2 → job 2; -/// available=`[0,1]`, pick index 0 → job 0; available=`[1]`, pick index 0 → job 1. -/// Result: job order `[2, 0, 1]`. +/// A solution is a permutation of job indices. The reference solver enumerates +/// Lehmer codes and decodes them to job orders before evaluation. /// /// Given a job order, start times are determined greedily (as early as possible). /// @@ -284,7 +279,6 @@ pub(crate) fn canonical_model_example_specs() -> Vec Vec { - // e = (1 ∪ 4) + (3 ∪ 6) + (2 ∪ 5), K = 12 - // 3 union nodes → 8 configs. Set = {6, 9, 12, 15}. - // Witness: choose right(4), right(6), left(2) → 4+6+2=12, config=[1,1,0] let expr = IntExpr::Sum( Box::new(IntExpr::Sum( Box::new(IntExpr::Union( diff --git a/src/models/misc/job_shop_scheduling.rs b/src/models/misc/job_shop_scheduling.rs index b0125dace..0e2effe81 100644 --- a/src/models/misc/job_shop_scheduling.rs +++ b/src/models/misc/job_shop_scheduling.rs @@ -343,8 +343,6 @@ pub(crate) fn canonical_model_example_specs() -> Vec [0,0,0,0,0,0] - // Machine 1 order [2,7,1,6,10,4] => [1,3,0,1,1,0] optimal_config: serde_json::json!(vec![0, 0, 0, 0, 0, 0, 1, 3, 0, 1, 1, 0]), optimal_value: serde_json::json!(19), }] diff --git a/src/models/misc/knapsack.rs b/src/models/misc/knapsack.rs index 8b7d37150..1936686b5 100644 --- a/src/models/misc/knapsack.rs +++ b/src/models/misc/knapsack.rs @@ -224,8 +224,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // 4 items: weights [2,3,4,5], values [3,4,5,7], capacity 7 - // Optimal: items 0,3 → weight=7, value=10 vec![crate::example_db::specs::ModelExampleSpec { id: "knapsack", instance: Box::new(Knapsack::new(vec![2, 3, 4, 5], vec![3, 4, 5, 7], 7)), diff --git a/src/models/misc/kth_largest_m_tuple.rs b/src/models/misc/kth_largest_m_tuple.rs index 91d2150fb..adfeb8618 100644 --- a/src/models/misc/kth_largest_m_tuple.rs +++ b/src/models/misc/kth_largest_m_tuple.rs @@ -242,8 +242,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // m=3, X_1={2,5,8}, X_2={3,6}, X_3={1,4,7}, B=12, K=14. - // 14 of 18 tuples have sum >= 12, so the answer is YES at K=14. vec![crate::example_db::specs::ModelExampleSpec { id: "kth_largest_m_tuple", instance: Box::new(KthLargestMTuple::new( diff --git a/src/models/misc/longest_common_subsequence.rs b/src/models/misc/longest_common_subsequence.rs index 1f28fda78..09401a0e9 100644 --- a/src/models/misc/longest_common_subsequence.rs +++ b/src/models/misc/longest_common_subsequence.rs @@ -262,7 +262,6 @@ impl Problem for LongestCommonSubsequence { return Ok(Max(None)); } - // Extract the non-padding prefix as the candidate subsequence. let prefix = &config[..effective_length]; // Check the prefix is a subsequence of every input string. diff --git a/src/models/misc/maximum_likelihood_ranking.rs b/src/models/misc/maximum_likelihood_ranking.rs index 092922633..43bac7cd5 100644 --- a/src/models/misc/maximum_likelihood_ranking.rs +++ b/src/models/misc/maximum_likelihood_ranking.rs @@ -223,12 +223,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // 4 items with comparison matrix. - // Optimal ranking: [0, 1, 2, 3] (identity) gives cost 7. - // Let's verify: items ranked in order 0,1,2,3. - // Disagreement = sum over (a,b) where config[a] > config[b] of matrix[a][b] - // = matrix[1][0] + matrix[2][0] + matrix[2][1] + matrix[3][0] + matrix[3][1] + matrix[3][2] - // = 1 + 2 + 1 + 0 + 2 + 1 = 7 let matrix = vec![ vec![0, 4, 3, 5], vec![1, 0, 4, 3], diff --git a/src/models/misc/minimum_axiom_set.rs b/src/models/misc/minimum_axiom_set.rs index c7d7ac584..a4bf40c25 100644 --- a/src/models/misc/minimum_axiom_set.rs +++ b/src/models/misc/minimum_axiom_set.rs @@ -117,7 +117,6 @@ impl MinimumAxiomSet { ); } } - // Check no duplicates let mut seen = vec![false; num_sentences]; for &s in &true_sentences { if seen[s] { @@ -218,7 +217,6 @@ impl Problem for MinimumAxiomSet { "axiom-selection length does not match the true sentences".into(), )); } - // Build the initial set of selected axioms let mut current = vec![false; self.num_sentences]; let mut count = 0usize; for (i, &v) in config.iter().enumerate() { @@ -228,7 +226,6 @@ impl Problem for MinimumAxiomSet { } } - // Compute deductive closure deductive_closure(&mut current, &self.implications); // Check if closure equals T @@ -263,8 +260,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // 8 sentences, all true, with implications forming a cycle - // Optimal: select {a, b} (indices 0, 1) → closure = all 8 vec![crate::example_db::specs::ModelExampleSpec { id: "minimum_axiom_set", instance: Box::new(MinimumAxiomSet::new( diff --git a/src/models/misc/minimum_code_generation_one_register.rs b/src/models/misc/minimum_code_generation_one_register.rs index a9f16d0fc..4f73aadc8 100644 --- a/src/models/misc/minimum_code_generation_one_register.rs +++ b/src/models/misc/minimum_code_generation_one_register.rs @@ -385,14 +385,6 @@ crate::register_brute_force! { pub(crate) fn canonical_model_example_specs() -> Vec { vec![crate::example_db::specs::ModelExampleSpec { id: "minimum_code_generation_one_register", - // Issue #900 example: 7 vertices, leaves {4,5,6}, internal {0,1,2,3} - // Edges: (0,1),(0,2),(1,3),(1,4),(2,3),(2,5),(3,5),(3,6) - // Optimal order: v3, v2, v1, v0 with positions [3, 2, 1, 0] - // Wait — config[i] = position for internal vertex i. - // Internal vertices sorted: [0, 1, 2, 3] - // Optimal evaluation order: v3, v2, v1, v0 - // v3 at position 0, v2 at position 1, v1 at position 2, v0 at position 3 - // So config = [3, 2, 1, 0] (internal idx 0=v0 -> pos 3, idx 1=v1 -> pos 2, ...) instance: Box::new(MinimumCodeGenerationOneRegister::new( 7, vec![ diff --git a/src/models/misc/minimum_code_generation_parallel_assignments.rs b/src/models/misc/minimum_code_generation_parallel_assignments.rs index f19edbe99..3bd5a9f85 100644 --- a/src/models/misc/minimum_code_generation_parallel_assignments.rs +++ b/src/models/misc/minimum_code_generation_parallel_assignments.rs @@ -218,18 +218,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // 4 variables, 4 assignments: - // A_0: a <- op(b, c) -> (0, [1, 2]) - // A_1: b <- op(a) -> (1, [0]) - // A_2: c <- op(d) -> (2, [3]) - // A_3: d <- op(b, c) -> (3, [1, 2]) - // - // Optimal ordering: config [0, 3, 1, 2] means - // A_0 at position 0, A_1 at position 3, A_2 at position 1, A_3 at position 2 - // Order: (A_0, A_2, A_3, A_1) - // Backward deps: A_0 writes a, A_1 reads a (later) -> 1 - // A_2 writes c, A_3 reads c (later) -> 1 - // Total: 2 let assignments = vec![(0, vec![1, 2]), (1, vec![0]), (2, vec![3]), (3, vec![1, 2])]; vec![crate::example_db::specs::ModelExampleSpec { id: "minimum_code_generation_parallel_assignments", diff --git a/src/models/misc/minimum_code_generation_unlimited_registers.rs b/src/models/misc/minimum_code_generation_unlimited_registers.rs index 3090a3944..b2bb74c78 100644 --- a/src/models/misc/minimum_code_generation_unlimited_registers.rs +++ b/src/models/misc/minimum_code_generation_unlimited_registers.rs @@ -314,7 +314,6 @@ impl MinimumCodeGenerationUnlimitedRegisters { let lc = self.left_child(v); let rc = self.right_child(v); - // Check dependencies if let Some(l) = lc { if !computed[l] { return Ok(None); @@ -409,13 +408,6 @@ crate::register_brute_force! { pub(crate) fn canonical_model_example_specs() -> Vec { vec![crate::example_db::specs::ModelExampleSpec { id: "minimum_code_generation_unlimited_registers", - // Issue #902 example: 5 vertices, leaves {3,4}, internal {0,1,2} - // left_arcs: (1,3),(2,3),(0,1) - // right_arcs: (1,4),(2,4),(0,2) - // Optimal order: v1,v2,v0 with 1 copy of v3 = 4 instructions - // Internal vertices sorted: [0, 1, 2] - // Order v1(pos 0), v2(pos 1), v0(pos 2) - // config[0]=2 (v0 at pos 2), config[1]=0 (v1 at pos 0), config[2]=1 (v2 at pos 1) instance: Box::new(MinimumCodeGenerationUnlimitedRegisters::new( 5, vec![(1, 3), (2, 3), (0, 1)], diff --git a/src/models/misc/minimum_decision_tree.rs b/src/models/misc/minimum_decision_tree.rs index 3149a8b89..fd596092f 100644 --- a/src/models/misc/minimum_decision_tree.rs +++ b/src/models/misc/minimum_decision_tree.rs @@ -264,7 +264,6 @@ pub(crate) fn canonical_model_example_specs() -> Vec = config .iter() .enumerate() @@ -199,7 +198,6 @@ impl Problem for MinimumDisjunctiveNormalForm { return Ok(Min(None)); } - // Check that all minterms are covered for &mt in &self.minterms { let covered = selected .iter() @@ -331,9 +329,7 @@ pub(crate) fn canonical_model_example_specs() -> Vec = d_slots[..d_len].to_vec(); if d_str.iter().any(|&v| v >= self.alphabet_size) { return Ok(Min(None)); @@ -278,7 +277,6 @@ impl Problem for MinimumExternalMacroDataCompression { } } - // Check decoded string matches the source string if decoded != self.string { return Ok(Min(None)); } @@ -342,19 +340,12 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // Issue #441 example: alphabet {a,b,c,d,e,f} (6), s="abcdefabcdefabcdef" (18), h=2. - // Optimal: D="abcdef"(6), C = ptr(0,6) ptr(0,6) ptr(0,6), cost = 6+3+(2-1)*3 = 12. - // Solved via ILP reduction (brute force infeasible at this size). - // - // Config encoding (2*18 = 36 slots): - // D-slots: [0,1,2,3,4,5, 6,6,...,6] (6 symbols + 12 empty, empty=alphabet_size=6) - // C-slots: [ptr(0,6), ptr(0,6), ptr(0,6), 6,6,...,6] (3 pointers + 15 empty) - // ptr(0,6) index: start=0, len=6 → index 5 → encoded as 6+1+5 = 12 + // Use ILP for this example; its reference enumeration is impractical. let s: Vec = (0..6).cycle().take(18).collect(); let mut optimal_config = vec![0, 1, 2, 3, 4, 5]; - optimal_config.extend(vec![6; 12]); // empty D-slots - optimal_config.extend(vec![12, 12, 12]); // 3 pointers to D[0..6] - optimal_config.extend(vec![6; 15]); // empty C-slots + optimal_config.extend(vec![6; 12]); + optimal_config.extend(vec![12, 12, 12]); + optimal_config.extend(vec![6; 15]); vec![crate::example_db::specs::ModelExampleSpec { id: "minimum_external_macro_data_compression", instance: Box::new(MinimumExternalMacroDataCompression::new(6, s, 2)), diff --git a/src/models/misc/minimum_fault_detection_test_set.rs b/src/models/misc/minimum_fault_detection_test_set.rs index 01c01f57b..a5b6fd82a 100644 --- a/src/models/misc/minimum_fault_detection_test_set.rs +++ b/src/models/misc/minimum_fault_detection_test_set.rs @@ -206,7 +206,6 @@ impl MinimumFaultDetectionTestSet { inputs: &[usize], outputs: &[usize], ) -> Vec> { - // Build adjacency lists let mut adj = vec![vec![]; num_vertices]; let mut rev_adj = vec![vec![]; num_vertices]; for &(u, v) in arcs { @@ -327,7 +326,6 @@ impl Problem for MinimumFaultDetectionTestSet { } } - // Check all internal vertices are covered. if covered.len() == required_internal_vertices { Min(Some(i64::try_from(count).map_err(|_| { crate::traits::EvaluationError::IntegerOverflow( @@ -357,11 +355,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // 7 vertices, inputs={0,1}, outputs={5,6} - // Internal vertices are {2,3,4} - // Arcs: (0,2),(0,3),(1,3),(1,4),(2,5),(3,5),(3,6),(4,6) - // Pairs: (0,5)->{0,2,3,5}, (0,6)->{0,3,6}, (1,5)->{1,3,5}, (1,6)->{1,3,4,6} - // Config [1,0,0,1]: select pairs (0,5) and (1,6) -> covers all internal vertices -> Min(2) vec![crate::example_db::specs::ModelExampleSpec { id: "minimum_fault_detection_test_set", instance: Box::new(MinimumFaultDetectionTestSet::new( diff --git a/src/models/misc/minimum_internal_macro_data_compression.rs b/src/models/misc/minimum_internal_macro_data_compression.rs index 611981db0..c1e6c2731 100644 --- a/src/models/misc/minimum_internal_macro_data_compression.rs +++ b/src/models/misc/minimum_internal_macro_data_compression.rs @@ -302,23 +302,8 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // Issue #442 example: alphabet {a,b,c} (3), s="abcabcabc" (9), h=2 - // Optimal: C = [a, b, c, ptr(0), ptr(0), EOS, EOS, EOS, EOS] - // active_len = 5, pointers = 2 - // cost = 5 + (2-1)*2 = 7 - // - // Config encoding: - // alphabet_size = 3, string_len = 9, domain = 3+9+1 = 13 - // Literals: 0=a, 1=b, 2=c - // EOS: 3 - // Pointers: 4=ptr(C[0]), 5=ptr(C[1]), ... let s: Vec = vec![0, 1, 2, 0, 1, 2, 0, 1, 2]; - let optimal_config = vec![ - 0, 1, 2, // literals a, b, c - 4, // ptr(C[0]) -> greedy "abc" - 4, // ptr(C[0]) -> greedy "abc" - 3, 3, 3, 3, // EOS padding - ]; + let optimal_config = vec![0, 1, 2, 4, 4, 3, 3, 3, 3]; vec![crate::example_db::specs::ModelExampleSpec { id: "minimum_internal_macro_data_compression", instance: Box::new(MinimumInternalMacroDataCompression::new(3, s, 2)), diff --git a/src/models/misc/minimum_register_sufficiency_for_loops.rs b/src/models/misc/minimum_register_sufficiency_for_loops.rs index cbcf7a1e4..838b2890a 100644 --- a/src/models/misc/minimum_register_sufficiency_for_loops.rs +++ b/src/models/misc/minimum_register_sufficiency_for_loops.rs @@ -200,7 +200,6 @@ impl Problem for MinimumRegisterSufficiencyForLoops { "register assignment length does not match the variables".into(), )); } - // Check all register indices are in valid range if config.iter().any(|®ister| register >= n) { return Err(crate::traits::EvaluationError::InvalidConfiguration( "register assignment contains an out-of-range register".into(), @@ -219,7 +218,6 @@ impl Problem for MinimumRegisterSufficiencyForLoops { } } - // Count distinct registers used let mut used = vec![false; n]; for &r in config { used[r] = true; @@ -253,8 +251,6 @@ crate::register_brute_force! { pub(crate) fn canonical_model_example_specs() -> Vec { vec![crate::example_db::specs::ModelExampleSpec { id: "minimum_register_sufficiency_for_loops", - // 3 variables on a loop of length 6, all pairs conflict (K3) - // Optimal: 3 registers (chromatic number of K3) instance: Box::new(MinimumRegisterSufficiencyForLoops::new( 6, vec![(0, 3), (2, 3), (4, 3)], diff --git a/src/models/misc/minimum_tardiness_sequencing.rs b/src/models/misc/minimum_tardiness_sequencing.rs index 0b7b2784a..5d6762afc 100644 --- a/src/models/misc/minimum_tardiness_sequencing.rs +++ b/src/models/misc/minimum_tardiness_sequencing.rs @@ -359,7 +359,6 @@ impl Problem for MinimumTardinessSequencing { schedule[pos] = task; } - // Compute completion times using actual lengths let mut completion = vec![0_i64; n]; let mut cumulative = 0_i64; for &task in &schedule { @@ -406,7 +405,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { vec![ - // Unit-length variant crate::example_db::specs::ModelExampleSpec { id: "minimum_tardiness_sequencing", instance: Box::new(MinimumTardinessSequencing::::new( @@ -417,13 +415,8 @@ pub(crate) fn canonical_model_example_specs() -> Vec::with_lengths( vec![3, 2, 2, 1, 2], vec![4, 3, 8, 3, 6], diff --git a/src/models/misc/minimum_weight_and_or_graph.rs b/src/models/misc/minimum_weight_and_or_graph.rs index 703b8f614..f8c06a458 100644 --- a/src/models/misc/minimum_weight_and_or_graph.rs +++ b/src/models/misc/minimum_weight_and_or_graph.rs @@ -315,7 +315,6 @@ impl Problem for MinimumWeightAndOrGraph { } } - // Compute total weight of selected arcs let total_weight = selected .iter() .enumerate() @@ -350,27 +349,7 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // 7 vertices: source=0 (AND), v1 (OR), v2 (OR), v3-v6 (leaves) - // Arcs: (0,1,1), (0,2,2), (1,3,3), (1,4,1), (2,5,4), (2,6,2) - // Optimal: AND at 0 requires both arcs to 1 and 2 (cost 1+2=3). - // OR at 1: pick arc to 4 (cost 1). OR at 2: pick arc to 6 (cost 2). - // Total = 1+2+1+2 = 6... but actually we should check: is there a cheaper? - // arc0(0->1,w=1), arc1(0->2,w=2), arc3(1->4,w=1), arc5(2->6,w=2) => 1+2+1+2=6 - // arc0(0->1,w=1), arc1(0->2,w=2), arc2(1->3,w=3), arc5(2->6,w=2) => 1+2+3+2=8 - // arc0(0->1,w=1), arc1(0->2,w=2), arc3(1->4,w=1), arc4(2->5,w=4) => 1+2+1+4=8 - // So optimal is config [1,1,0,1,0,1] with value 6... but wait, let me also check - // if val=5 is achievable: 1+2+1+1=5 impossible because OR at 2 must pick at least one. - // Actually optimal = 1(arc0) + 2(arc1) + 1(arc3) + 2(arc5) = 6 - // Hmm, let me reconsider: is there a solution with value 5? - // Source is AND, so both arcs 0 and 1 must be selected (cost 1+2=3). - // Then OR at 1: cheapest outgoing arc is arc3 (w=1), OR at 2: cheapest is arc5 (w=2). - // Total = 3+1+2 = 6. Can't do better since source AND forces both. - // Wait — check: what if we change arc weights. The issue says value 5 might be optimal. - // Let me re-read: issue example says Config [1,1,0,1,0,1] -> weight 1+2+1+2 = 6 -> Min(6). - // So 6 is the correct optimal. But let me verify: is there any config with value < 6? - // No — source is AND so arcs 0,1 are forced (cost 3), then OR nodes each need at least one. - // Min at OR-1 is 1 (arc3), min at OR-2 is 2 (arc5). Total = 3+1+2 = 6. - // Optimal config: [1,1,0,1,0,1] + // The AND source forces both branches; each OR node's cheapest arc attains the lower bound. vec![crate::example_db::specs::ModelExampleSpec { id: "minimum_weight_and_or_graph", instance: Box::new(MinimumWeightAndOrGraph::new( diff --git a/src/models/misc/non_liveness_free_petri_net.rs b/src/models/misc/non_liveness_free_petri_net.rs index 66fca114a..c64147401 100644 --- a/src/models/misc/non_liveness_free_petri_net.rs +++ b/src/models/misc/non_liveness_free_petri_net.rs @@ -246,7 +246,6 @@ impl NonLivenessFreePetriNet { new_marking[p] -= 1; } } - // Add tokens to output places for &(t, p) in &self.transition_to_place { if t == transition { new_marking[p] = new_marking[p].checked_add(1).ok_or_else(|| { diff --git a/src/models/misc/numerical_3_dimensional_matching.rs b/src/models/misc/numerical_3_dimensional_matching.rs index 2a07faf11..fe027bb02 100644 --- a/src/models/misc/numerical_3_dimensional_matching.rs +++ b/src/models/misc/numerical_3_dimensional_matching.rs @@ -184,7 +184,6 @@ impl Problem for Numerical3DimensionalMatching { // Second m values: assignment of Y-elements to W-elements (must be a permutation) let y_perm = &config[m..]; - // Check that both are valid permutations of 0..m let mut x_used = vec![false; m]; let mut y_used = vec![false; m]; @@ -196,7 +195,6 @@ impl Problem for Numerical3DimensionalMatching { y_used[y_perm[i]] = true; } - // Check that each triple sums to B for i in 0..m { let sum = self.sizes_w[i] .checked_add(self.sizes_x[x_perm[i]]) diff --git a/src/models/misc/numerical_matching_with_target_sums.rs b/src/models/misc/numerical_matching_with_target_sums.rs index 8b0a2166c..6ca0be9ef 100644 --- a/src/models/misc/numerical_matching_with_target_sums.rs +++ b/src/models/misc/numerical_matching_with_target_sums.rs @@ -150,7 +150,6 @@ impl Problem for NumericalMatchingWithTargetSums { )); } - // Check config is valid permutation of 0..m let mut used = vec![false; m]; for &idx in config { if used[idx] { @@ -159,7 +158,6 @@ impl Problem for NumericalMatchingWithTargetSums { used[idx] = true; } - // Compute pair sums and compare multisets let mut pair_sums: Vec = (0..m) .map(|i| i128::from(self.sizes_x[i]) + i128::from(self.sizes_y[config[i]])) .collect(); diff --git a/src/models/misc/open_shop_scheduling.rs b/src/models/misc/open_shop_scheduling.rs index d3b5062c0..86a32afd6 100644 --- a/src/models/misc/open_shop_scheduling.rs +++ b/src/models/misc/open_shop_scheduling.rs @@ -309,18 +309,7 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // 4 jobs × 3 machines example from issue #506. - // processing_times[j][i]: - // J1: p[0] = [3, 1, 2] - // J2: p[1] = [2, 3, 1] - // J3: p[2] = [1, 2, 3] - // J4: p[3] = [2, 2, 1] - // - // Per-machine totals: M1=8, M2=8, M3=7. Per-job totals: J1=6, J2=6, J3=6, J4=5. - // Lower bound: max(8, 6) = 8. True optimal makespan = 8. - // - // Job-major start times: J1=[0,3,4], J2=[3,0,6], J3=[5,6,0], J4=[6,4,3]. - // Each job and machine has non-overlapping operations; the last finish is 8. + // Machine load supplies a matching lower bound for this schedule. vec![crate::example_db::specs::ModelExampleSpec { id: "open_shop_scheduling", instance: Box::new(OpenShopScheduling::new( diff --git a/src/models/misc/optimum_communication_spanning_tree.rs b/src/models/misc/optimum_communication_spanning_tree.rs index ceb50cf26..f161dbb1b 100644 --- a/src/models/misc/optimum_communication_spanning_tree.rs +++ b/src/models/misc/optimum_communication_spanning_tree.rs @@ -175,7 +175,6 @@ impl OptimumCommunicationSpanningTree { } } - // Check symmetry and non-negativity for i in 0..n { for j in (i + 1)..n { if edge_weights[i][j] != edge_weights[j][i] { @@ -267,7 +266,6 @@ fn is_valid_spanning_tree(n: usize, edges: &[(usize, usize)], config: &[bool]) - return false; } - // Build adjacency and check connectivity via BFS let mut adj: Vec> = vec![vec![]; n]; for (idx, &sel) in config.iter().enumerate() { if sel { @@ -304,7 +302,6 @@ fn communication_cost( edge_weights: &[Vec], requirements: &[Vec], ) -> Result { - // Build weighted adjacency list for the tree let mut adj: Vec> = vec![vec![]; n]; for (idx, &sel) in config.iter().enumerate() { if sel { @@ -406,13 +403,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // K4 example from issue #906 - // Edge weights: - // w(0,1)=1, w(0,2)=3, w(0,3)=2, w(1,2)=2, w(1,3)=4, w(2,3)=1 - // Requirements: - // r(0,1)=2, r(0,2)=1, r(0,3)=3, r(1,2)=1, r(1,3)=1, r(2,3)=2 - // Optimal tree: {(0,1), (0,3), (2,3)} = edges at indices 0, 2, 5 - // Optimal cost: 20 let edge_weights = vec![ vec![0, 1, 3, 2], vec![1, 0, 2, 4], @@ -425,8 +415,6 @@ pub(crate) fn canonical_model_example_specs() -> Vec config = [1, 0, 1, 0, 0, 1] vec![crate::example_db::specs::ModelExampleSpec { id: "optimum_communication_spanning_tree", instance: Box::new(OptimumCommunicationSpanningTree::new( diff --git a/src/models/misc/paintshop.rs b/src/models/misc/paintshop.rs index dd78006a5..cb0b3ee5f 100644 --- a/src/models/misc/paintshop.rs +++ b/src/models/misc/paintshop.rs @@ -98,7 +98,6 @@ impl PaintShop { fn try_new>( sequence: Vec, ) -> Result { - // Build car-to-index mapping and count occurrences let mut car_count: HashMap<&str, usize> = HashMap::new(); let mut car_to_index: HashMap<&str, usize> = HashMap::new(); let mut car_labels: Vec = Vec::new(); @@ -113,7 +112,6 @@ impl PaintShop { *count += 1; } - // Verify each car appears exactly twice for (car, count) in &car_count { if *count != 2 { return Err(format!( @@ -123,7 +121,6 @@ impl PaintShop { } } - // Convert sequence to indices let sequence_indices: Vec = sequence .iter() .map(|item| car_to_index[item.as_ref()]) diff --git a/src/models/misc/partially_ordered_knapsack.rs b/src/models/misc/partially_ordered_knapsack.rs index 3d0b24072..dc9bb4605 100644 --- a/src/models/misc/partially_ordered_knapsack.rs +++ b/src/models/misc/partially_ordered_knapsack.rs @@ -286,11 +286,9 @@ impl Problem for PartiallyOrderedKnapsack { "item-selection length does not match the instance".into(), )); } - // Check downward-closure (precedence constraints) if !self.is_downward_closed(config) { return Ok(Max(None)); } - // Check capacity constraint let total_weight = config .iter() .enumerate() @@ -306,7 +304,6 @@ impl Problem for PartiallyOrderedKnapsack { if total_weight > self.capacity { return Ok(Max(None)); } - // Compute total value let total_value = config .iter() .enumerate() diff --git a/src/models/misc/precedence_constrained_scheduling.rs b/src/models/misc/precedence_constrained_scheduling.rs index bf17309ae..1f24258b3 100644 --- a/src/models/misc/precedence_constrained_scheduling.rs +++ b/src/models/misc/precedence_constrained_scheduling.rs @@ -248,7 +248,6 @@ crate::register_brute_force! { pub(crate) fn canonical_model_example_specs() -> Vec { vec![crate::example_db::specs::ModelExampleSpec { id: "precedence_constrained_scheduling", - // Issue #501 example: 8 tasks, 3 processors, deadline 4 instance: Box::new(PrecedenceConstrainedScheduling::new( 8, 3, @@ -265,7 +264,6 @@ pub(crate) fn canonical_model_example_specs() -> Vec self.num_processors { @@ -371,20 +370,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // 5 tasks, lengths [2,1,3,2,1], 2 processors, precedences [(0,2),(1,3)] - // D_max = 2+1+3+2+1 = 9 - // Optimal schedule (makespan 5): - // t0: slots 0,1 → t0*9+0=1, t0*9+1=1 - // t1: slot 0 → t1*9+0=1 - // t2: slots 2,3,4 → t2*9+2=1, t2*9+3=1, t2*9+4=1 - // t3: slots 2,3 → t3*9+2=1, t3*9+3=1 - // t4: slot 1 → t4*9+1=1 - // config indices (length 45): - // t0 (0..9): [1,1,0,0,0,0,0,0,0] - // t1 (9..18): [1,0,0,0,0,0,0,0,0] - // t2 (18..27):[0,0,1,1,1,0,0,0,0] - // t3 (27..36):[0,0,1,1,0,0,0,0,0] - // t4 (36..45):[0,1,0,0,0,0,0,0,0] let mut config = vec![vec![false; 9]; 5]; config[0][0] = true; config[0][1] = true; diff --git a/src/models/misc/rectilinear_picture_compression.rs b/src/models/misc/rectilinear_picture_compression.rs index b23cadb37..8fa88909b 100644 --- a/src/models/misc/rectilinear_picture_compression.rs +++ b/src/models/misc/rectilinear_picture_compression.rs @@ -284,7 +284,6 @@ impl Problem for RectilinearPictureCompression { "rectangle-selection length does not match the maximal rectangles".into(), )); } - // Count selected rectangles. let selected_count = config.iter().filter(|&&selected| selected).count(); let selected_count = i64::try_from(selected_count).map_err(|_| { crate::traits::EvaluationError::IntegerOverflow( @@ -295,7 +294,6 @@ impl Problem for RectilinearPictureCompression { return Ok(crate::types::Or(false)); } - // Check that all 1-entries are covered. let m = self.num_rows(); let n = self.num_cols(); let mut covered = vec![vec![false; n]; m]; @@ -342,9 +340,6 @@ crate::register_brute_force! { pub(crate) fn canonical_model_example_specs() -> Vec { vec![crate::example_db::specs::ModelExampleSpec { id: "rectilinear_picture_compression", - // Config: select both maximal rectangles (the two 2x2 blocks). - // The maximal rectangles for this matrix are exactly: - // (0,0,1,1) and (2,2,3,3), so config [1,1] selects both. instance: Box::new(RectilinearPictureCompression::new( vec![ vec![true, true, false, false], diff --git a/src/models/misc/register_sufficiency.rs b/src/models/misc/register_sufficiency.rs index 554784d54..694479fd7 100644 --- a/src/models/misc/register_sufficiency.rs +++ b/src/models/misc/register_sufficiency.rs @@ -213,13 +213,6 @@ impl RegisterSufficiency { } } - // Count registers at this step: - // A vertex v is in registers if: - // - v has been evaluated (config[v] <= step) - // - v is still needed (last_use[v] > step, or v is the current vertex) - // Actually, more precisely: after evaluating vertex at position `step`, - // the register set contains all vertices evaluated so far whose last - // use is > step (they're still needed later), plus the current vertex. let reg_count = order[..=step] .iter() .filter(|&&v| last_use[v] > step) @@ -524,9 +517,6 @@ crate::register_brute_force! { pub(crate) fn canonical_model_example_specs() -> Vec { vec![crate::example_db::specs::ModelExampleSpec { id: "register_sufficiency", - // Issue #515 example: 7 vertices, 8 arcs, K=3 - // Arcs (0-indexed): (2,0), (2,1), (3,1), (4,2), (4,3), (5,0), (6,4), (6,5) - // Order: v0,v1,v2,v3,v5,v4,v6 -> positions [0,1,2,3,5,4,6] instance: Box::new(RegisterSufficiency::new( 7, vec![ @@ -541,8 +531,6 @@ pub(crate) fn canonical_model_example_specs() -> Vec0, v1->1, v2->2, v3->3, v4->5, v5->4, v6->6 optimal_config: serde_json::json!(vec![0, 1, 2, 3, 5, 4, 6]), optimal_value: serde_json::json!(true), }] diff --git a/src/models/misc/resource_constrained_scheduling.rs b/src/models/misc/resource_constrained_scheduling.rs index ba7b48ccd..cd0eb4ab5 100644 --- a/src/models/misc/resource_constrained_scheduling.rs +++ b/src/models/misc/resource_constrained_scheduling.rs @@ -210,7 +210,6 @@ impl Problem for ResourceConstrainedScheduling { let d = self.deadline as usize; let r = self.num_resources(); - // Check config length if config.len() != n { return Err(crate::traits::EvaluationError::InvalidConfiguration( "schedule length does not match the tasks".into(), @@ -242,12 +241,10 @@ impl Problem for ResourceConstrainedScheduling { } } - // Check processor capacity if slot_tasks.len() > self.num_processors { return Ok(crate::types::Or(false)); } - // Check resource bounds for (usage, bound) in resource_usage.iter().zip(self.resource_bounds.iter()) { if usage > bound { return Ok(crate::types::Or(false)); @@ -279,7 +276,6 @@ crate::register_brute_force! { pub(crate) fn canonical_model_example_specs() -> Vec { vec![crate::example_db::specs::ModelExampleSpec { id: "resource_constrained_scheduling", - // 6 tasks, 3 processors, 1 resource B_1=20, deadline 2 instance: Box::new( ResourceConstrainedScheduling::new( 3, diff --git a/src/models/misc/scheduling_to_minimize_weighted_completion_time.rs b/src/models/misc/scheduling_to_minimize_weighted_completion_time.rs index bd478f199..c9c8721b4 100644 --- a/src/models/misc/scheduling_to_minimize_weighted_completion_time.rs +++ b/src/models/misc/scheduling_to_minimize_weighted_completion_time.rs @@ -37,7 +37,7 @@ inventory::submit! { /// # Representation /// /// Each task has a variable in `{0, ..., m-1}` representing its processor -/// assignment, giving `dims() = [m; n]`. +/// assignment, giving `dimensions() = [m; n]`. /// /// # Example /// @@ -334,7 +334,6 @@ pub(crate) fn canonical_model_example_specs() -> Vec config [0, 1, 0, 1, 0] optimal_config: serde_json::json!(vec![0, 1, 0, 1, 0]), optimal_value: serde_json::json!(47), }] diff --git a/src/models/misc/sequencing_to_minimize_maximum_cumulative_cost.rs b/src/models/misc/sequencing_to_minimize_maximum_cumulative_cost.rs index b226e1914..1688bee12 100644 --- a/src/models/misc/sequencing_to_minimize_maximum_cumulative_cost.rs +++ b/src/models/misc/sequencing_to_minimize_maximum_cumulative_cost.rs @@ -30,8 +30,8 @@ inventory::submit! { /// /// # Representation /// -/// Configurations use Lehmer-code dimensions `[n, n-1, ..., 1]` to encode a -/// permutation of the task indices. +/// A solution is a permutation of task indices; the reference solver decodes +/// its Lehmer-code enumeration before evaluation. #[derive(Debug, Clone, Serialize)] pub struct SequencingToMinimizeMaximumCumulativeCost { costs: Vec, diff --git a/src/models/misc/sequencing_to_minimize_tardy_task_weight.rs b/src/models/misc/sequencing_to_minimize_tardy_task_weight.rs index edf3b7916..e5bfe0a9e 100644 --- a/src/models/misc/sequencing_to_minimize_tardy_task_weight.rs +++ b/src/models/misc/sequencing_to_minimize_tardy_task_weight.rs @@ -31,7 +31,7 @@ inventory::submit! { /// This is the weighted generalization of minimizing the number of tardy tasks /// (problem SS8 in Garey & Johnson, 1979, written $1 || sum w_j U_j$). /// -/// Configurations are direct permutation encodings with `dims() = [n; n]`: +/// Configurations are direct permutation encodings with `dimensions() = [n; n]`: /// each position holds the index of the task scheduled at that position. /// A configuration is valid iff it is a permutation of `0..n`. #[derive(Debug, Clone, Serialize)] @@ -247,14 +247,6 @@ crate::register_brute_force! { pub(crate) fn canonical_model_example_specs() -> Vec { vec![crate::example_db::specs::ModelExampleSpec { id: "sequencing_to_minimize_tardy_task_weight", - // 5 tasks, lengths [3,2,4,1,2], weights [5,3,7,2,4], deadlines [6,4,10,2,8] - // Optimal schedule: [t4,t1,t5,t3,t2] = config [3,0,4,2,1] - // Start times: t4 starts 0, completes 1 (tardy: C=1 <= d=2, ok) - // t1 starts 1, completes 4 (tardy: C=4 <= d=6, ok) - // t5 starts 4, completes 6 (tardy: C=6 <= d=8, ok) - // t3 starts 6, completes 10 (tardy: C=10 <= d=10, ok) - // t2 starts 10, completes 12 (tardy: C=12 > d=4, tardy weight 3) - // Total tardy weight = 3 instance: Box::new(SequencingToMinimizeTardyTaskWeight::new( vec![3, 2, 4, 1, 2], vec![5, 3, 7, 2, 4], diff --git a/src/models/misc/sequencing_to_minimize_weighted_completion_time.rs b/src/models/misc/sequencing_to_minimize_weighted_completion_time.rs index a0004949c..566aae9b6 100644 --- a/src/models/misc/sequencing_to_minimize_weighted_completion_time.rs +++ b/src/models/misc/sequencing_to_minimize_weighted_completion_time.rs @@ -35,7 +35,8 @@ inventory::submit! { /// and minimizes `sum_t w(t) * C(t)`, where `C(t)` is the completion time of /// task `t`. /// -/// Configurations use Lehmer code with `dims() = [n, n-1, ..., 1]`. +/// A solution is a permutation of task indices. Lehmer codes are used only by +/// the reference solver to enumerate task orders. #[derive(Debug, Clone, Serialize)] pub struct SequencingToMinimizeWeightedCompletionTime { lengths: Vec, diff --git a/src/models/misc/sequencing_to_minimize_weighted_tardiness.rs b/src/models/misc/sequencing_to_minimize_weighted_tardiness.rs index dc729a1e8..5d2079675 100644 --- a/src/models/misc/sequencing_to_minimize_weighted_tardiness.rs +++ b/src/models/misc/sequencing_to_minimize_weighted_tardiness.rs @@ -32,8 +32,7 @@ inventory::submit! { /// /// # Representation /// -/// Configurations use Lehmer code to encode permutations of the jobs. -/// Decoding yields the job order processed by the single machine. +/// A solution is a permutation of job indices in processing order. /// /// # Example /// @@ -201,9 +200,9 @@ impl SequencingToMinimizeWeightedTardiness { Ok(total) } - /// Compute the total weighted tardiness of a Lehmer-encoded schedule. + /// Compute the total weighted tardiness of a job permutation. /// - /// Returns `Ok(None)` if the configuration is not a valid Lehmer code. + /// Returns `Ok(None)` if the configuration is not a valid permutation. pub fn total_weighted_tardiness( &self, config: &[usize], diff --git a/src/models/misc/sequencing_with_deadlines_and_set_up_times.rs b/src/models/misc/sequencing_with_deadlines_and_set_up_times.rs index 0f5ddbebb..fccc06b66 100644 --- a/src/models/misc/sequencing_with_deadlines_and_set_up_times.rs +++ b/src/models/misc/sequencing_with_deadlines_and_set_up_times.rs @@ -39,7 +39,7 @@ inventory::submit! { /// This is problem SS14 in Garey & Johnson (1979), written /// $1 | s_{ij} | \text{feasibility}$. /// -/// Configurations are direct permutation encodings with `dims() = [n; n]`: +/// Configurations are direct permutation encodings with `dimensions() = [n; n]`: /// each position holds the index of the task scheduled at that position. /// A configuration is valid iff it is a permutation of `0..n`. #[derive(Debug, Clone, Serialize)] @@ -268,14 +268,6 @@ crate::register_brute_force! { pub(crate) fn canonical_model_example_specs() -> Vec { vec![crate::example_db::specs::ModelExampleSpec { id: "sequencing_with_deadlines_and_set_up_times", - // 5 tasks, lengths [2,3,1,2,2], deadlines [4,11,3,16,7], compilers [0,1,0,1,0], - // setup_times [1,2]. - // Optimal config: [2,0,4,1,3] (tasks t3,t1,t5,t2,t4 in 1-indexed) - // Position 0: task 2 (compiler 0), no prev → elapsed = 0+1 = 1 ≤ d[2]=3 ✓ - // Position 1: task 0 (compiler 0), same → elapsed = 1+2 = 3 ≤ d[0]=4 ✓ - // Position 2: task 4 (compiler 0), same → elapsed = 3+2 = 5 ≤ d[4]=7 ✓ - // Position 3: task 1 (compiler 1), switch+s[1]=2 → elapsed = 5+2+3 = 10 ≤ d[1]=11 ✓ - // Position 4: task 3 (compiler 1), same → elapsed = 10+2 = 12 ≤ d[3]=16 ✓ instance: Box::new(SequencingWithDeadlinesAndSetUpTimes::new( vec![2, 3, 1, 2, 2], vec![4, 11, 3, 16, 7], diff --git a/src/models/misc/sequencing_with_release_times_and_deadlines.rs b/src/models/misc/sequencing_with_release_times_and_deadlines.rs index eb49c9fb1..d6211ff70 100644 --- a/src/models/misc/sequencing_with_release_times_and_deadlines.rs +++ b/src/models/misc/sequencing_with_release_times_and_deadlines.rs @@ -35,9 +35,7 @@ inventory::submit! { /// /// # Representation /// -/// Uses a permutation encoding (Lehmer code), where `config[i]` selects which -/// remaining task to schedule next from the pool of unscheduled tasks. -/// `dims() = [n, n-1, ..., 2, 1]`. Tasks are scheduled left-to-right: each +/// A solution lists task indices in schedule order. Each /// task starts at `max(release_time, current_time)`. The schedule is feasible /// iff every task finishes by its deadline. /// @@ -219,9 +217,6 @@ crate::register_brute_force! { pub(crate) fn canonical_model_example_specs() -> Vec { vec![crate::example_db::specs::ModelExampleSpec { id: "sequencing_with_release_times_and_deadlines", - // 5 tasks from issue example. - // Feasible schedule order: t3, t0, t1, t2, t4 - // Lehmer code [3,0,0,0,0] = permutation [3,0,1,2,4] instance: Box::new(SequencingWithReleaseTimesAndDeadlines::new( vec![3, 2, 4, 1, 2], vec![0, 1, 5, 0, 8], diff --git a/src/models/misc/sequencing_within_intervals.rs b/src/models/misc/sequencing_within_intervals.rs index dd7d3deb3..69182325c 100644 --- a/src/models/misc/sequencing_within_intervals.rs +++ b/src/models/misc/sequencing_within_intervals.rs @@ -244,7 +244,6 @@ impl Problem for SequencingWithinIntervals { }) .collect::, _>>()?; - // Check no two tasks overlap for i in 0..n { for j in (i + 1)..n { // Tasks overlap if neither finishes before the other starts diff --git a/src/models/misc/shortest_common_supersequence.rs b/src/models/misc/shortest_common_supersequence.rs index 5ea1fdea0..3b95070a5 100644 --- a/src/models/misc/shortest_common_supersequence.rs +++ b/src/models/misc/shortest_common_supersequence.rs @@ -266,9 +266,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // Alphabet {0, 1}, strings [0,1] and [1,0] - // max_length = 2 + 2 = 4, search space = 3^4 = 81 - // Optimal SCS length = 3, e.g. [0,1,0] padded to [0,1,0,2] vec![crate::example_db::specs::ModelExampleSpec { id: "shortest_common_supersequence", instance: Box::new(ShortestCommonSupersequence::new( diff --git a/src/models/misc/shortest_common_superstring.rs b/src/models/misc/shortest_common_superstring.rs index ed634b785..8172e668c 100644 --- a/src/models/misc/shortest_common_superstring.rs +++ b/src/models/misc/shortest_common_superstring.rs @@ -244,10 +244,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // Alphabet {0, 1}, strings [0,1] and [1,0]. - // max_length = 2 + 2 = 4, search space = 3^4 = 81. - // Optimal SCSS length = 3, e.g. [0,1,0] padded to [0,1,0,2] ("010" contains - // both "01" and "10" as contiguous substrings). vec![crate::example_db::specs::ModelExampleSpec { id: "shortest_common_superstring", instance: Box::new(ShortestCommonSuperstring::new( diff --git a/src/models/misc/square_tiling.rs b/src/models/misc/square_tiling.rs index 4f8b4b951..792afe949 100644 --- a/src/models/misc/square_tiling.rs +++ b/src/models/misc/square_tiling.rs @@ -125,7 +125,6 @@ impl SquareTiling { return false; } - // Check all tile indices are valid for &tile_idx in config { if tile_idx >= self.tiles.len() { return false; diff --git a/src/models/misc/string_to_string_correction.rs b/src/models/misc/string_to_string_correction.rs index d5912afb0..2acec3c7d 100644 --- a/src/models/misc/string_to_string_correction.rs +++ b/src/models/misc/string_to_string_correction.rs @@ -277,9 +277,6 @@ crate::register_brute_force! { pub(crate) fn canonical_model_example_specs() -> Vec { vec![crate::example_db::specs::ModelExampleSpec { id: "string_to_string_correction", - // source has length 6. Domain = 2*6+1 = 13. No-op = 12. - // First operation: swap at positions 2,3 → value = 6 + 2 = 8 - // Second operation: delete at position 5 instance: Box::new(StringToStringCorrection::new( 4, vec![0, 1, 2, 3, 1, 0], diff --git a/src/models/misc/subset_product.rs b/src/models/misc/subset_product.rs index ea1b071b1..4b8a44086 100644 --- a/src/models/misc/subset_product.rs +++ b/src/models/misc/subset_product.rs @@ -187,7 +187,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // 6 elements [2,3,5,7,6,10], target 210 → select {2,3,5,7} vec![crate::example_db::specs::ModelExampleSpec { id: "subset_product", instance: Box::new(SubsetProduct::new(vec![2u32, 3, 5, 7, 6, 10], 210u32)), diff --git a/src/models/misc/subset_sum.rs b/src/models/misc/subset_sum.rs index c2f300359..48334c86a 100644 --- a/src/models/misc/subset_sum.rs +++ b/src/models/misc/subset_sum.rs @@ -194,7 +194,6 @@ crate::register_brute_force! { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // 6 elements [3,7,1,8,2,4], target 11 → select {3,8} vec![crate::example_db::specs::ModelExampleSpec { id: "subset_sum", instance: Box::new(SubsetSum::new(vec![3u32, 7, 1, 8, 2, 4], 11u32)), diff --git a/src/models/misc/sum_of_squares_partition.rs b/src/models/misc/sum_of_squares_partition.rs index 0edae8f31..077e5d7e5 100644 --- a/src/models/misc/sum_of_squares_partition.rs +++ b/src/models/misc/sum_of_squares_partition.rs @@ -214,8 +214,6 @@ crate::register_brute_force! { pub(crate) fn canonical_model_example_specs() -> Vec { vec![crate::example_db::specs::ModelExampleSpec { id: "sum_of_squares_partition", - // sizes=[5,3,8,2,7,1], K=3 - // Optimal: groups {8},{2,7},{5,3,1} -> sums 8,9,9 -> 64+81+81=226 instance: Box::new(SumOfSquaresPartition::new(vec![5, 3, 8, 2, 7, 1], 3)), optimal_config: serde_json::json!(vec![2, 2, 0, 1, 1, 0]), optimal_value: serde_json::json!(226), diff --git a/src/models/mod.rs b/src/models/mod.rs index b01593468..6d5dcf591 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -9,7 +9,6 @@ pub mod graph; pub mod misc; pub mod set; -// Re-export commonly used types pub use algebraic::{ AlgebraicEquationsOverGF2, ClosestVectorProblem, ConsecutiveBlockMinimization, ConsecutiveOnesMatrixAugmentation, ConsecutiveOnesSubmatrix, EquilibriumPoint, diff --git a/src/models/set/consecutive_sets.rs b/src/models/set/consecutive_sets.rs index 64218b4a6..59109bb9a 100644 --- a/src/models/set/consecutive_sets.rs +++ b/src/models/set/consecutive_sets.rs @@ -281,7 +281,6 @@ crate::register_brute_force! { pub(crate) fn canonical_model_example_specs() -> Vec { vec![crate::example_db::specs::ModelExampleSpec { id: "consecutive_sets", - // YES instance from issue: w = [0, 4, 2, 5, 1, 3] instance: Box::new(ConsecutiveSets::new( 6, vec![vec![0, 4], vec![2, 4], vec![2, 5], vec![1, 5], vec![1, 3]], diff --git a/src/models/set/integer_knapsack.rs b/src/models/set/integer_knapsack.rs index 04be21fc8..0b7818a1f 100644 --- a/src/models/set/integer_knapsack.rs +++ b/src/models/set/integer_knapsack.rs @@ -277,8 +277,6 @@ impl<'de> Deserialize<'de> for IntegerKnapsack { #[cfg(feature = "example-db")] pub(crate) fn canonical_model_example_specs() -> Vec { - // 5 items: sizes [3,4,5,2,7], values [4,5,7,3,9], capacity 15 - // Optimal: c=(0,0,1,5,0) → total_size=5+10=15, total_value=7+15=22 vec![crate::example_db::specs::ModelExampleSpec { id: "integer-knapsack", instance: Box::new( diff --git a/src/models/set/maximum_set_packing.rs b/src/models/set/maximum_set_packing.rs index 7f654db01..6f9e94b65 100644 --- a/src/models/set/maximum_set_packing.rs +++ b/src/models/set/maximum_set_packing.rs @@ -266,7 +266,6 @@ fn is_valid_packing(sets: &[Vec], config: &[bool]) -> bool { .map(|(i, _)| i) .collect(); - // Check all pairs of selected sets are disjoint for i in 0..selected_sets.len() { for j in (i + 1)..selected_sets.len() { let set_i: HashSet<_> = sets[selected_sets[i]].iter().collect(); diff --git a/src/models/set/prime_attribute_name.rs b/src/models/set/prime_attribute_name.rs index 59e620c13..3b88c5780 100644 --- a/src/models/set/prime_attribute_name.rs +++ b/src/models/set/prime_attribute_name.rs @@ -266,7 +266,6 @@ crate::register_brute_force! { pub(crate) fn canonical_model_example_specs() -> Vec { vec![crate::example_db::specs::ModelExampleSpec { id: "prime_attribute_name", - // Issue Example 1: 6 attributes, 3 FDs, query=3 -> YES instance: Box::new(PrimeAttributeName::new( 6, vec![ @@ -276,7 +275,6 @@ pub(crate) fn canonical_model_example_specs() -> Vec Vec, S: AsRef, { - // Start with all defaults let mut variant: BTreeMap = problem_type.default_variant(); let mut matched_dims: Vec = vec![false; problem_type.dimensions.len()]; for value in values { let val = value.as_ref(); - // Find which dimension this value belongs to let dim_idx = problem_type .dimensions .iter() @@ -80,7 +78,6 @@ impl ProblemRef { problem_type: &ProblemType, variant: BTreeMap, ) -> Result { - // Validate all keys and values for (key, value) in &variant { let dim = problem_type .dimensions @@ -101,7 +98,6 @@ impl ProblemRef { } } - // Fill in defaults for missing dimensions let mut full_variant = problem_type.default_variant(); full_variant.extend(variant); @@ -178,7 +174,6 @@ pub fn parse_catalog_problem_ref(input: &str) -> Result = parts[1..].to_vec(); - // Resolve name through catalog let problem_type = super::problem_type::find_problem_type_by_alias(raw_name) .ok_or_else(|| format!("Unknown problem type: \"{raw_name}\""))?; diff --git a/src/rules/analysis.rs b/src/rules/analysis.rs index c7cb50648..30310f74c 100644 --- a/src/rules/analysis.rs +++ b/src/rules/analysis.rs @@ -33,7 +33,6 @@ pub fn check_connectivity(graph: &ReductionGraph) -> ConnectivityReport { let mut types = graph.problem_types(); types.sort(); - // Build undirected adjacency at the problem-type level let mut adj: BTreeMap<&str, BTreeSet<&str>> = BTreeMap::new(); for &name in &types { adj.entry(name).or_default(); @@ -43,7 +42,6 @@ pub fn check_connectivity(graph: &ReductionGraph) -> ConnectivityReport { } } - // Find connected components via BFS let mut visited: BTreeSet<&str> = BTreeSet::new(); let mut components: Vec> = Vec::new(); @@ -153,7 +151,6 @@ pub fn check_reachability_from_3sat(graph: &ReductionGraph) -> ReachabilityRepor let mut types = graph.problem_types(); types.sort(); - // Build directed adjacency at the type level let mut adj: BTreeMap<&str, BTreeSet<&str>> = BTreeMap::new(); for &name in &types { adj.entry(name).or_default(); diff --git a/src/rules/bicliquecover_bmf.rs b/src/rules/bicliquecover_bmf.rs index bcd5bd822..62d888a3d 100644 --- a/src/rules/bicliquecover_bmf.rs +++ b/src/rules/bicliquecover_bmf.rs @@ -77,7 +77,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec Vec( source, diff --git a/src/rules/bmf_ilp.rs b/src/rules/bmf_ilp.rs index 28ca4bfc1..369fae11f 100644 --- a/src/rules/bmf_ilp.rs +++ b/src/rules/bmf_ilp.rs @@ -177,7 +177,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec(source) }, diff --git a/src/rules/bottlenecktravelingsalesman_ilp.rs b/src/rules/bottlenecktravelingsalesman_ilp.rs index ebccfb62f..17aeec2d7 100644 --- a/src/rules/bottlenecktravelingsalesman_ilp.rs +++ b/src/rules/bottlenecktravelingsalesman_ilp.rs @@ -193,7 +193,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec 12 — infeasible - // link 0 → cap 1, link 1 → cap 0: cost=5, delay=11 ≤ 12 — feasible - // link 0 → cap 0, link 1 → cap 1: cost=5, delay=11 ≤ 12 — feasible (tied) - // link 0 → cap 1, link 1 → cap 1: cost=7, delay=7 ≤ 12 — feasible - // Optimal: cost=5 at [1,0] or [0,1] let source = CapacityAssignment::new( vec![1, 2], vec![vec![1, 3], vec![2, 4]], diff --git a/src/rules/circuit_spinglass.rs b/src/rules/circuit_spinglass.rs index 3acda5b81..0bd1ec465 100644 --- a/src/rules/circuit_spinglass.rs +++ b/src/rules/circuit_spinglass.rs @@ -327,7 +327,6 @@ impl SpinGlassBuilder { .ok_or("circuit SpinGlass coupling overflow")?; } - // Add fields for (local_idx, field) in gadget.problem.fields().iter().enumerate() { let global_idx = spin_map[local_idx]; self.fields[global_idx] = self.fields[global_idx] diff --git a/src/rules/closeststring_ilp.rs b/src/rules/closeststring_ilp.rs index ad007d5c9..17299eb1b 100644 --- a/src/rules/closeststring_ilp.rs +++ b/src/rules/closeststring_ilp.rs @@ -153,9 +153,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec Vec Vec> for DirectedHamiltonianPath { let n = self.num_vertices(); let arcs = self.graph().arcs(); - // Build arc set for fast lookup let mut arc_set = std::collections::HashSet::new(); for (u, v) in &arcs { arc_set.insert((*u, *v)); @@ -121,7 +120,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec1->2->3 let source = DirectedHamiltonianPath::new(crate::topology::DirectedGraph::new( 4, vec![(0, 1), (1, 2), (2, 3)], diff --git a/src/rules/directedtwocommodityintegralflow_ilp.rs b/src/rules/directedtwocommodityintegralflow_ilp.rs index f281c8e22..0fb6fc923 100644 --- a/src/rules/directedtwocommodityintegralflow_ilp.rs +++ b/src/rules/directedtwocommodityintegralflow_ilp.rs @@ -191,9 +191,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec a, None => { @@ -261,9 +260,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec1->2->0->1. let source = EulerianPath::new(DirectedGraph::new(3, vec![(0, 1), (0, 1), (1, 2), (2, 0)])); crate::example_db::specs::rule_example_via_bounded_ilp::<_>(source) diff --git a/src/rules/exactcoverby3sets_boundeddiameterspanningtree.rs b/src/rules/exactcoverby3sets_boundeddiameterspanningtree.rs index b3459a9e4..6eb630d90 100644 --- a/src/rules/exactcoverby3sets_boundeddiameterspanningtree.rs +++ b/src/rules/exactcoverby3sets_boundeddiameterspanningtree.rs @@ -177,7 +177,6 @@ impl ReduceTo> for ExactCoverBy3Se } } - // Set clique edges. for i in 0..m { for j in (i + 1)..m { edges.push((s_index(i), s_index(j))); @@ -204,24 +203,11 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec Vec( source, SolutionPair { diff --git a/src/rules/expectedretrievalcost_ilp.rs b/src/rules/expectedretrievalcost_ilp.rs index 5f0d49bad..a25129278 100644 --- a/src/rules/expectedretrievalcost_ilp.rs +++ b/src/rules/expectedretrievalcost_ilp.rs @@ -167,10 +167,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source).expect("reduction should succeed"); let solver = crate::solvers::ILPSolver::new(); diff --git a/src/rules/factoring_circuit.rs b/src/rules/factoring_circuit.rs index c130d1fe3..4992d8b51 100644 --- a/src/rules/factoring_circuit.rs +++ b/src/rules/factoring_circuit.rs @@ -149,7 +149,6 @@ fn build_multiplier_cell( c_pre: &BooleanExpr, cell_id: &str, ) -> (Vec, Vec) { - // Create unique ancilla variable names let a_name = format!("a_{}", cell_id); let a_xor_s_name = format!("axs_{}", cell_id); let a_xor_s_and_c_name = format!("axsc_{}", cell_id); @@ -229,7 +228,6 @@ impl ReduceTo for Factoring { let target = self.target(); let (width, capacity) = ReductionFactoringToCircuit::dimensions(n1, n2)?; - // Create input variables for the two factors let p_vars: Vec = (1..=n1).map(|i| format!("p{}", i)).collect(); let q_vars: Vec = (1..=n2).map(|i| format!("q{}", i)).collect(); @@ -253,11 +251,9 @@ impl ReduceTo for Factoring { let mut c_pre = BooleanExpr::constant(false); for j in 1..=n2 { - // Create signal names for this cell let c_name = format!("c{}_{}", i, j); let s_name = format!("s{}_{}", i, j); - // Build the multiplier cell let cell_id = format!("{}_{}", i, j); let (cell_assignments, _ancillas) = build_multiplier_cell( &s_name, @@ -315,7 +311,6 @@ impl ReduceTo for Factoring { assignments.push(Assignment::new(vec![overflow], BooleanExpr::constant(true))); } - // Build the circuit let circuit = Circuit::new(assignments); let circuit_sat = CircuitSAT::new(circuit); diff --git a/src/rules/factoring_ilp.rs b/src/rules/factoring_ilp.rs index 3b86900ae..f4010c09f 100644 --- a/src/rules/factoring_ilp.rs +++ b/src/rules/factoring_ilp.rs @@ -88,14 +88,12 @@ impl ReductionResult for ReductionFactoringToILP { )?; Ok({ - // Extract p bits (first factor) let p = (0..self.m) .filter(|&i| target_solution[self.p_var(i)] == 1) .fold(num_bigint::BigUint::from(0u8), |value, index| { value + (num_bigint::BigUint::from(1u8) << index) }); - // Extract q bits (second factor) let q = (0..self.n) .filter(|&j| target_solution[self.q_var(j)] == 1) .fold(num_bigint::BigUint::from(0u8), |value, index| { @@ -184,7 +182,6 @@ impl ReduceTo> for Factoring { } } - // Add carry_in (from position k-1) if k > 0 { terms.push((carry_var(k - 1), 1)); } diff --git a/src/rules/flowshopscheduling_ilp.rs b/src/rules/flowshopscheduling_ilp.rs index 712610d30..4b42e9237 100644 --- a/src/rules/flowshopscheduling_ilp.rs +++ b/src/rules/flowshopscheduling_ilp.rs @@ -211,7 +211,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec(source) }, diff --git a/src/rules/graph.rs b/src/rules/graph.rs index 5f922aad6..76821b9dc 100644 --- a/src/rules/graph.rs +++ b/src/rules/graph.rs @@ -413,7 +413,6 @@ impl ReductionGraph { } }; - // Collect declared default variants from VariantEntry inventory let mut default_variants: HashMap> = HashMap::new(); // Phase 1: Build nodes from VariantEntry inventory @@ -1325,14 +1324,12 @@ impl ReductionGraph { pub(crate) fn to_json(&self) -> ReductionGraphJson { use crate::registry::ProblemSchemaEntry; - // Build the model-owned metadata lookup from ProblemSchemaEntry inventory. let schema_metadata: HashMap<&str, (&str, crate::registry::ProblemCategory)> = inventory::iter:: .into_iter() .map(|entry| (entry.name, (entry.module_path, entry.category))) .collect(); - // Build sorted node list from the internal nodes let mut json_nodes: Vec<(usize, NodeJson)> = self .nodes .iter() @@ -1367,7 +1364,6 @@ impl ReductionGraph { let nodes: Vec = json_nodes.into_iter().map(|(_, n)| n).collect(); - // Build edges from the graph let mut edges: Vec = Vec::new(); for edge_ref in self.graph.edge_references() { let src_node_id = self.graph[edge_ref.source()]; @@ -1401,7 +1397,6 @@ impl ReductionGraph { } let parameter_contract_error = contract.as_ref().err().map(ToString::to_string); - // Find the doc_path from the matching ReductionEntry let src_name = self.nodes[src_node_id].name; let dst_name = self.nodes[dst_node_id].name; let src_variant = &self.nodes[src_node_id].variant; @@ -1801,7 +1796,6 @@ impl ReductionGraph { if path.steps.len() < 2 { return Ok(None); } - // Collect edge reduce_fns let mut edge_fns = Vec::new(); let mut aggregate_views = Vec::new(); for window in path.steps.windows(2) { diff --git a/src/rules/hamiltoniancircuit_biconnectivityaugmentation.rs b/src/rules/hamiltoniancircuit_biconnectivityaugmentation.rs index 8a5b16a46..6b29df020 100644 --- a/src/rules/hamiltoniancircuit_biconnectivityaugmentation.rs +++ b/src/rules/hamiltoniancircuit_biconnectivityaugmentation.rs @@ -66,7 +66,6 @@ impl ReductionResult for ReductionHamiltonianCircuitToBiconnectivityAugmentation )); } - // Collect selected edges (those with config value 1) let mut adj: Vec> = vec![vec![]; n]; for (i, &(u, v)) in self.potential_edges.iter().enumerate() { if target_solution[i] { @@ -75,7 +74,6 @@ impl ReductionResult for ReductionHamiltonianCircuitToBiconnectivityAugmentation } } - // Check that every vertex has exactly degree 2 (Hamiltonian cycle) if adj.iter().any(|neighbors| neighbors.len() != 2) { return Err(crate::rules::ExtractionError::invalid( "selected edges do not give every source vertex degree two", @@ -147,7 +145,6 @@ impl ReduceTo> for HamiltonianCircu // Edgeless initial graph let initial_graph = SimpleGraph::empty(n); - // Create potential edges for all pairs (u, v) with u < v let mut potential_weights = Vec::new(); let mut potential_edges = Vec::new(); for u in 0..n { @@ -183,13 +180,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec indices 0,3,5,2 - // Config: [1, 0, 1, 1, 0, 1] crate::example_db::specs::rule_example_with_witness::< _, BiconnectivityAugmentation, diff --git a/src/rules/hamiltoniancircuit_hamiltonianpath.rs b/src/rules/hamiltoniancircuit_hamiltonianpath.rs index 8563fade6..d697fef00 100644 --- a/src/rules/hamiltoniancircuit_hamiltonianpath.rs +++ b/src/rules/hamiltoniancircuit_hamiltonianpath.rs @@ -158,14 +158,11 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>( source, SolutionPair { - // HC solution: visit vertices in order 0, 1, 2, 3 source_config: serde_json::json!(vec![0, 1, 2, 3]), - // HP solution on G' (7 vertices): s=5, 0, 1, 2, 3, v'=4, t=6 target_config: serde_json::json!(vec![5, 0, 1, 2, 3, 4, 6]), }, ) diff --git a/src/rules/hamiltoniancircuit_ruralpostman.rs b/src/rules/hamiltoniancircuit_ruralpostman.rs index 1ea99e400..000fd1d9f 100644 --- a/src/rules/hamiltoniancircuit_ruralpostman.rs +++ b/src/rules/hamiltoniancircuit_ruralpostman.rs @@ -127,7 +127,6 @@ impl ReduceTo>> for HamiltonianCircuit = self.graph().edges(); let m = source_edges.len(); - // Build target graph with 2n vertices let num_target_edges = n + 2 * m; let mut target_edges = Vec::with_capacity(num_target_edges); let mut edge_weights = Vec::with_capacity(num_target_edges); @@ -178,16 +177,8 @@ pub(crate) fn canonical_rule_example_specs() -> Vec1: fwd edge of source edge 0=(0,1), idx=3 - // 1->2: fwd edge of source edge 1=(1,2), idx=5 - // 2->0: bwd edge of source edge 2=(0,2), idx=8 - // Required edges all have multiplicity 1. - // target_config = [1, 1, 1, 1, 0, 1, 0, 0, 1] crate::example_db::specs::rule_example_with_witness::< _, Decision>, diff --git a/src/rules/hamiltoniancircuit_strongconnectivityaugmentation.rs b/src/rules/hamiltoniancircuit_strongconnectivityaugmentation.rs index cc621ea80..357136084 100644 --- a/src/rules/hamiltoniancircuit_strongconnectivityaugmentation.rs +++ b/src/rules/hamiltoniancircuit_strongconnectivityaugmentation.rs @@ -44,7 +44,6 @@ impl ReductionResult for ReductionHamiltonianCircuitToStrongConnectivityAugmenta return Ok(vec![]); } - // Build directed adjacency from selected arcs. let candidate_arcs = self.target.candidate_arcs(); let mut successors = vec![Vec::new(); n]; for (idx, &selected) in target_solution.iter().enumerate() { @@ -108,7 +107,6 @@ impl ReduceTo> for HamiltonianCircuit Vec>::reduce_to(&source) .expect("reduction should succeed"); let target = reduction.target_problem(); - // The HC permutation [0, 1, 2, 3] corresponds to the directed cycle - // 0->1->2->3->0. We need to find the indices of these arcs in the - // candidate list. Candidate arcs are ordered: for each u in 0..n, - // for each v in 0..n where u!=v, so arc (u,v) is at index - // u*(n-1) + (if v > u then v-1 else v). let n = 4; let mut target_config = vec![false; n * (n - 1)]; let cycle_arcs = [(0, 1), (1, 2), (2, 3), (3, 0)]; @@ -157,7 +149,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec(source) }, diff --git a/src/rules/hamiltonianpath_isomorphicspanningtree.rs b/src/rules/hamiltonianpath_isomorphicspanningtree.rs index f37750098..3d09da57d 100644 --- a/src/rules/hamiltonianpath_isomorphicspanningtree.rs +++ b/src/rules/hamiltonianpath_isomorphicspanningtree.rs @@ -76,7 +76,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec Vec> for ILP { } } - // Add slack variable columns let mut slack_col = n; for (k, &ns) in slack_sizes.iter().enumerate() { if ns > 0 { @@ -198,7 +197,6 @@ impl ReduceTo> for ILP { } } - // Build dense cost vector (nq elements) let mut c_vec = vec![0_i64; nq]; for &(var, coef) in self.objective() { c_vec[var] = coef; diff --git a/src/rules/integralflowwithmultipliers_ilp.rs b/src/rules/integralflowwithmultipliers_ilp.rs index 94619829a..96a422005 100644 --- a/src/rules/integralflowwithmultipliers_ilp.rs +++ b/src/rules/integralflowwithmultipliers_ilp.rs @@ -127,7 +127,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec>( source, SolutionPair { source_config: serde_json::json!(vec![0, 1, 2, 3]), - // x_{0,0}=1, x_{1,1}=1, x_{2,2}=1, x_{3,3}=1 target_config: serde_json::json!(vec![ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ]), diff --git a/src/rules/kclique_balancedcompletebipartitesubgraph.rs b/src/rules/kclique_balancedcompletebipartitesubgraph.rs index b3cb09b81..7a94c0e73 100644 --- a/src/rules/kclique_balancedcompletebipartitesubgraph.rs +++ b/src/rules/kclique_balancedcompletebipartitesubgraph.rs @@ -129,19 +129,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec select {3,4,5,6} - // target_config for left: [0,0,0,1,1,1,1] - // Right side: select edge elements for clique edges + padding - // e0={0,1}, e1={0,2}, e2={1,2} are clique edges -> select them - // e3={2,3} is not a clique edge -> don't select - // w0 is padding -> select - // target_config for right: [1,1,1,0,1] - // Full target config: [0,0,0,1,1,1,1, 1,1,1,0,1] crate::example_db::specs::rule_example_with_witness::< _, BalancedCompleteBipartiteSubgraph, diff --git a/src/rules/kclique_conjunctivebooleanquery.rs b/src/rules/kclique_conjunctivebooleanquery.rs index 8513daf61..60558b3c8 100644 --- a/src/rules/kclique_conjunctivebooleanquery.rs +++ b/src/rules/kclique_conjunctivebooleanquery.rs @@ -106,7 +106,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec Vec `v` //! - `g_v` -> `n + v` @@ -234,7 +234,7 @@ impl ReduceTo for KColoring { } } -/// Build the canonical forward witness described in the issue. +/// Build a forward witness from a source coloring. /// /// For each source vertex `v` (with `v in 0..n`), create one guard biclique /// @@ -322,9 +322,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec::with_k(SimpleGraph::new(2, vec![(0, 1)]), 2); let coloring = vec![0usize, 1usize]; let target_config = forward_witness(&source, &coloring); diff --git a/src/rules/kcoloring_twodimensionalconsecutivesets.rs b/src/rules/kcoloring_twodimensionalconsecutivesets.rs index 4f15cee3c..c6b84bf18 100644 --- a/src/rules/kcoloring_twodimensionalconsecutivesets.rs +++ b/src/rules/kcoloring_twodimensionalconsecutivesets.rs @@ -128,9 +128,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec0, 1->1, 2->2, 3->0 let source = KColoring::::new(SimpleGraph::new(4, vec![(0, 1), (1, 2), (0, 2), (2, 3)])); let reduction = as ReduceTo< @@ -139,17 +136,9 @@ pub(crate) fn canonical_rule_example_specs() -> Vec0, 1->1, 2->2, 3->0 - // Target config: vertex 0->group 0, vertex 1->group 1, vertex 2->group 2, vertex 3->group 0 - // Dummies: - // d_{0,1} (symbol 4): colors used {0,1}, dummy->group 2 - // d_{1,2} (symbol 5): colors used {1,2}, dummy->group 0 - // d_{0,2} (symbol 6): colors used {0,2}, dummy->group 1 - // d_{2,3} (symbol 7): colors used {2,0}, dummy->group 1 let source_config = vec![0, 1, 2, 0]; let target_config = vec![0, 1, 2, 0, 2, 0, 1, 1]; - // Verify the target config is valid assert!( target .evaluate(&target_config) diff --git a/src/rules/knapsack_qubo.rs b/src/rules/knapsack_qubo.rs index 8ecc8cdda..323f70c61 100644 --- a/src/rules/knapsack_qubo.rs +++ b/src/rules/knapsack_qubo.rs @@ -79,7 +79,6 @@ impl ReduceTo> for Knapsack { let penalty = penalty_i64; let values = self.values(); - // Build QUBO matrix // H = -sum(v_i * x_i) + P * (sum(w_i * x_i) + sum(2^j * s_j) - C)^2 // // Let a_k be the coefficient of variable k in the constraint: diff --git a/src/rules/ksatisfiability_bicliquecover.rs b/src/rules/ksatisfiability_bicliquecover.rs index dec116ab8..c2091a826 100644 --- a/src/rules/ksatisfiability_bicliquecover.rs +++ b/src/rules/ksatisfiability_bicliquecover.rs @@ -39,9 +39,6 @@ //! identifies the biclique `B_1` covering `s_11^u s_11^v` and reads off //! `x_i = true` iff `h_i^u ∈ B_1` (after mapping `t_i, f_i` back to the //! source variables). -//! -//! See issue #1057 for the full construction; this file mirrors the -//! issue body section-by-section. #[cfg(feature = "example-db")] use crate::models::formula::CNFClause; @@ -917,7 +914,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec( source, SolutionPair { - source_config: serde_json::json!([true]), // x_1 = true + source_config: serde_json::json!([true]), target_config: serde_json::to_value(target_config) .expect("solution serialization must succeed"), }, diff --git a/src/rules/ksatisfiability_decisionminimumvertexcover.rs b/src/rules/ksatisfiability_decisionminimumvertexcover.rs index 9e355797a..87bc0f179 100644 --- a/src/rules/ksatisfiability_decisionminimumvertexcover.rs +++ b/src/rules/ksatisfiability_decisionminimumvertexcover.rs @@ -156,15 +156,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec( source, SolutionPair { - // x1=0, x2=0, x3=1 satisfies both clauses source_config: serde_json::json!(vec![false, false, true]), - // Literal vertices: u1(0), ~u1(1), u2(2), ~u2(3), u3(4), ~u3(5) - // Clause 0 triangle: v6, v7, v8 (literals x1, x2, x3) - // Clause 1 triangle: v9, v10, v11 (literals ~x1, ~x2, x3) - // VC: from truth-setting, pick ~u1(1), ~u2(3), u3(4) - // Clause 0: u1,u2 not in cover -> pick v6,v7; u3 in cover -> v8 free - // Clause 1: ~u1,~u2,u3 all in cover -> pick any 2: v9,v10 - // Total cover size = 3 + 2 + 2 = 7 = n + 2m target_config: serde_json::json!(vec![ false, true, false, true, true, false, true, true, false, true, true, false ]), diff --git a/src/rules/ksatisfiability_kclique.rs b/src/rules/ksatisfiability_kclique.rs index 79dc24313..02e1a637a 100644 --- a/src/rules/ksatisfiability_kclique.rs +++ b/src/rules/ksatisfiability_kclique.rs @@ -128,7 +128,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec::new( 3, vec![ @@ -136,10 +135,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>( source, SolutionPair { diff --git a/src/rules/ksatisfiability_registersufficiency.rs b/src/rules/ksatisfiability_registersufficiency.rs index c4acc61c9..69a09d947 100644 --- a/src/rules/ksatisfiability_registersufficiency.rs +++ b/src/rules/ksatisfiability_registersufficiency.rs @@ -2,8 +2,7 @@ //! //! This is Sethi's Reduction I / Theorem 3.11 (STOC 1973), with native //! empty-formula/empty-clause boundary targets, compact variables, and literal -//! repetition for nonempty short clauses. The corrected extraction -//! rule from issue #872: +//! repetition for nonempty short clauses. The extraction rule is: //! - the snapshot is taken immediately after `w[n]` //! - `x_k = true` iff `x_pos[k]` has been computed by that snapshot //! - at most one of `x_pos[k]`, `x_neg[k]` can have been computed by then diff --git a/src/rules/ksatisfiability_timetabledesign.rs b/src/rules/ksatisfiability_timetabledesign.rs index 18f6ef72f..b99345b88 100644 --- a/src/rules/ksatisfiability_timetabledesign.rs +++ b/src/rules/ksatisfiability_timetabledesign.rs @@ -1,18 +1,14 @@ //! Reduction from KSatisfiability (3-SAT) to TimetableDesign. //! -//! The issue sketch for #486 is not directly implementable against this -//! repository's `TimetableDesign` model: the sketch relies on pair-specific -//! availability and per-clause optional work, while the model exposes only -//! craftsman/task availability sets and exact pairwise requirements. -//! -//! This implementation uses a fully specified chain instead: +//! `TimetableDesign` exposes craftsman/task availability sets and exact pairwise +//! requirements, so the reduction uses the following chain: //! 1. Eliminate pure literals from the source formula. //! 2. Apply Tovey's bounded-occurrence cloning so every remaining variable //! appears at most three times and every clause has length two or three. //! 3. Build the explicit bipartite list-edge-coloring instance from Marx's //! outerplanar reduction, padding missing literal-occurrence colors with //! dummy colors when a variable occurs only `1+1`, `2+1`, or `1+2` times. -//! 4. Compile the list instance to a core edge-coloring instance with blocked +//! 4. Compile the list instance to a core edge-coloring instance with blocked //! colors on auxiliary vertices, following Marx's precoloring gadgets. //! 5. Encode blocked colors as dedicated dummy assignments in `TimetableDesign`. //! diff --git a/src/rules/lengthboundeddisjointpaths_ilp.rs b/src/rules/lengthboundeddisjointpaths_ilp.rs index 4f3dc6432..ed1ebcde0 100644 --- a/src/rules/lengthboundeddisjointpaths_ilp.rs +++ b/src/rules/lengthboundeddisjointpaths_ilp.rs @@ -145,7 +145,6 @@ impl ReduceTo> for LengthBoundedDisjointPaths { let flow_var = |k: usize, e: usize, dir: usize| k * flow_vars_per_k + 2 * e + dir; - // Build vertex-to-edge adjacency let mut vertex_edges: Vec> = vec![Vec::new(); n]; for (e, &(u, v)) in edges.iter().enumerate() { vertex_edges[u].push(e); @@ -249,7 +248,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec Vec(source) }, diff --git a/src/rules/longestcommonsubsequence_maximumindependentset.rs b/src/rules/longestcommonsubsequence_maximumindependentset.rs index be5454a14..0f96e1bc6 100644 --- a/src/rules/longestcommonsubsequence_maximumindependentset.rs +++ b/src/rules/longestcommonsubsequence_maximumindependentset.rs @@ -53,14 +53,12 @@ impl ReductionResult for ReductionLCSToIS { crate::rules::traits::validate_target_solution(self.target_problem(), target_solution)?; Ok({ - // Collect selected match nodes with their characters let mut selected: Vec<(usize, usize)> = target_solution .iter() .enumerate() .filter(|(_, &v)| v) .map(|(i, _)| (self.match_nodes[i][0], self.match_chars[i])) .collect(); - // Sort by position in the first string selected.sort_by_key(|&(pos, _)| pos); // Build config: characters followed by padding @@ -109,7 +107,6 @@ impl ReduceTo> for LongestCommonSubseque }) .collect(); - // Generate all k-tuples (Cartesian product of position lists) let tuples = cartesian_product(&positions_per_string); for tuple in tuples { match_nodes.push(tuple); @@ -190,28 +187,13 @@ fn cartesian_product(lists: &[Vec]) -> Vec> { pub(crate) fn canonical_rule_example_specs() -> Vec { use crate::export::SolutionPair; - /// Build the example from the issue: k=2, s1="ABAC", s2="BACA", alphabet={A,B,C}. fn lcs_abac_baca() -> LongestCommonSubsequence { - // A=0, B=1, C=2 - LongestCommonSubsequence::new( - 3, - vec![ - vec![0, 1, 0, 2], // ABAC - vec![1, 0, 2, 0], // BACA - ], - ) + LongestCommonSubsequence::new(3, vec![vec![0, 1, 0, 2], vec![1, 0, 2, 0]]) } vec![crate::example_db::specs::RuleExampleSpec { id: "longestcommonsubsequence_to_maximumindependentset", build: || { - // Issue example: MIS solution {v2, v4, v5} gives LCS "BAC" (length 3). - // Match nodes (ordered by character): - // c=A(0): v0=(0,1), v1=(0,3), v2=(2,1), v3=(2,3) - // c=B(1): v4=(1,0) - // c=C(2): v5=(3,2) - // MIS {v2, v4, v5} => positions B@(1,0), A@(2,1), C@(3,2) - // source_config = [1, 0, 2, null] (B, A, C, padding) crate::example_db::specs::rule_example_with_witness::< _, MaximumIndependentSet, diff --git a/src/rules/maxcut_minimumcutintoboundedsets.rs b/src/rules/maxcut_minimumcutintoboundedsets.rs index 5c47b8b0f..17ad95f81 100644 --- a/src/rules/maxcut_minimumcutintoboundedsets.rs +++ b/src/rules/maxcut_minimumcutintoboundedsets.rs @@ -84,7 +84,6 @@ impl ReduceTo> for MaxCut("computing the inverted-weight ceiling") })?; - // Build an adjacency lookup for the original graph let orig_edges = self.graph().edges(); let mut edge_weight_map: std::collections::HashMap<(usize, usize), i64> = std::collections::HashMap::new(); @@ -145,7 +144,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec>::reduce_to(&source) .expect("reduction should succeed"); - // Find optimal source and target solutions let solver = BruteForce::new(); let source_witness = solver .solve(&source) diff --git a/src/rules/maxcut_minimummatrixcover.rs b/src/rules/maxcut_minimummatrixcover.rs index a1e8f50c7..995a7437b 100644 --- a/src/rules/maxcut_minimummatrixcover.rs +++ b/src/rules/maxcut_minimummatrixcover.rs @@ -97,9 +97,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec::new( SimpleGraph::new(4, vec![(0, 1), (1, 2), (2, 3), (0, 3)]), vec![1, 1, 1, 1], @@ -107,7 +104,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec( source, SolutionPair { - // S = {0, 2}: vertices 0 and 2 have f = +1. source_config: serde_json::json!(vec![true, false, true, false]), target_config: serde_json::json!(vec![true, false, true, false]), }, diff --git a/src/rules/maximalis_ilp.rs b/src/rules/maximalis_ilp.rs index 1f8ebb2fb..fde014825 100644 --- a/src/rules/maximalis_ilp.rs +++ b/src/rules/maximalis_ilp.rs @@ -88,7 +88,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec(source) }, diff --git a/src/rules/maximum2satisfiability_ilp.rs b/src/rules/maximum2satisfiability_ilp.rs index 8dd0d60df..77302023d 100644 --- a/src/rules/maximum2satisfiability_ilp.rs +++ b/src/rules/maximum2satisfiability_ilp.rs @@ -130,16 +130,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec z4=1 - // C1: (x1 OR ~x2) = T -> z5=1 - // C2: (~x1 OR x3) = F -> z6=0 - // C3: (~x1 OR ~x3) = T -> z7=1 - // C4: (x2 OR x4) = T -> z8=1 - // C5: (~x3 OR ~x4) = T -> z9=1 - // C6: (x3 OR x4) = T -> z10=1 crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { diff --git a/src/rules/maximum2satisfiability_maxcut.rs b/src/rules/maximum2satisfiability_maxcut.rs index e153b5d4f..b74ed6504 100644 --- a/src/rules/maximum2satisfiability_maxcut.rs +++ b/src/rules/maximum2satisfiability_maxcut.rs @@ -123,10 +123,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>( source, SolutionPair { - // x1=F, x2=T, x3=T satisfies all five clauses. source_config: serde_json::json!(vec![false, true, true]), - // Vertex 0 is the reference vertex s. Variables are true - // exactly when they share s's side of the cut. target_config: serde_json::json!(vec![false, true, false, false]), }, ) diff --git a/src/rules/maximumcommonedgesubgraph_ilp.rs b/src/rules/maximumcommonedgesubgraph_ilp.rs index 41918ab2a..0a11c46e8 100644 --- a/src/rules/maximumcommonedgesubgraph_ilp.rs +++ b/src/rules/maximumcommonedgesubgraph_ilp.rs @@ -146,7 +146,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec0, 1->1, 2->3, 3->4 preserves 2 contacts. let source = MaximumContactMapOverlap::new( 4, vec![(0, 2), (1, 3)], diff --git a/src/rules/maximumdomaticnumber_ilp.rs b/src/rules/maximumdomaticnumber_ilp.rs index 312c616ca..03a1c7510 100644 --- a/src/rules/maximumdomaticnumber_ilp.rs +++ b/src/rules/maximumdomaticnumber_ilp.rs @@ -125,7 +125,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec(source) }, diff --git a/src/rules/maximumedgeweightedkclique_ilp.rs b/src/rules/maximumedgeweightedkclique_ilp.rs index bc6e68832..9cb107dd3 100644 --- a/src/rules/maximumedgeweightedkclique_ilp.rs +++ b/src/rules/maximumedgeweightedkclique_ilp.rs @@ -184,8 +184,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec::new( SimpleGraph::new(4, vec![(0, 1), (0, 2), (1, 2), (0, 3), (1, 3)]), vec![5, 4, -1, 1, 0], diff --git a/src/rules/maximumindependentset_maximumsetpacking.rs b/src/rules/maximumindependentset_maximumsetpacking.rs index 6695e87f4..acf29f60b 100644 --- a/src/rules/maximumindependentset_maximumsetpacking.rs +++ b/src/rules/maximumindependentset_maximumsetpacking.rs @@ -111,12 +111,10 @@ macro_rules! impl_sp_to_is { let sets = self.sets(); let n = sets.len(); - // Create edges between sets that overlap let mut edges = Vec::new(); for (i, set_i_vec) in sets.iter().enumerate() { let set_i: HashSet<_> = set_i_vec.iter().collect(); for (j, set_j) in sets.iter().enumerate().skip(i + 1) { - // Check if sets[i] and sets[j] overlap if set_j.iter().any(|elem| set_i.contains(elem)) { edges.push((i, j)); } diff --git a/src/rules/maximumlikelihoodranking_ilp.rs b/src/rules/maximumlikelihoodranking_ilp.rs index 14d009bf7..036f07089 100644 --- a/src/rules/maximumlikelihoodranking_ilp.rs +++ b/src/rules/maximumlikelihoodranking_ilp.rs @@ -138,7 +138,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec(source) }, diff --git a/src/rules/minimumcostmaximumflow_minimumcostcirculation.rs b/src/rules/minimumcostmaximumflow_minimumcostcirculation.rs index 0d6df7ddb..85d8374b2 100644 --- a/src/rules/minimumcostmaximumflow_minimumcostcirculation.rs +++ b/src/rules/minimumcostmaximumflow_minimumcostcirculation.rs @@ -134,10 +134,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec 0) with - // flow value 3, giving config [2, 1, 1, 1, 2, 3]. let source = MinimumCostMaximumFlow::new( DirectedGraph::new(4, vec![(0, 1), (0, 2), (1, 2), (1, 3), (2, 3)]), 0, diff --git a/src/rules/minimumexternalmacrodatacompression_ilp.rs b/src/rules/minimumexternalmacrodatacompression_ilp.rs index 485ef766e..c7822f870 100644 --- a/src/rules/minimumexternalmacrodatacompression_ilp.rs +++ b/src/rules/minimumexternalmacrodatacompression_ilp.rs @@ -132,7 +132,6 @@ impl ReductionResult for ReductionEMDCToILP { let k = self.alphabet_size; let empty = k; // empty marker - // Build D-slots let mut d_slots = vec![empty; n]; for j in 0..n { let symbols: Vec<_> = (0..k) @@ -391,10 +390,6 @@ impl ReduceTo> for MinimumExternalMacroDataCompression { pub(crate) fn canonical_rule_example_specs() -> Vec { use crate::export::SolutionPair; - // s = "ab" (len 2), alphabet {a,b} (size 2), h=2 - // Optimal: uncompressed, D="" C="ab", cost = 0+2+0 = 2 - // Config: D-slots=[2,2], C-slots=[0,1] - // ILP target_config: all d and d_used = 0, lit[0]=1, lit[1]=1, all ptr = 0 vec![crate::example_db::specs::RuleExampleSpec { id: "minimumexternalmacrodatacompression_to_ilp", build: || { @@ -405,15 +400,13 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>( source, diff --git a/src/rules/minimumfeedbackarcset_ilp.rs b/src/rules/minimumfeedbackarcset_ilp.rs index 2cafd52ec..d4d98452f 100644 --- a/src/rules/minimumfeedbackarcset_ilp.rs +++ b/src/rules/minimumfeedbackarcset_ilp.rs @@ -134,10 +134,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec 1 -> 2 -> 0 (FAS = 1 arc) - // 3 arcs, 3 vertices: 6 total variables - // Remove arc 2 (2->0): source_config = [0, 0, 1] - // ILP solution: y_0=0, y_1=0, y_2=1, o_0=0, o_1=1, o_2=2 let graph = DirectedGraph::new(3, vec![(0, 1), (1, 2), (2, 0)]); let source = MinimumFeedbackArcSet::new(graph, vec![1i64; 3]); crate::example_db::specs::rule_example_via_bounded_ilp::<_>(source) diff --git a/src/rules/minimumfeedbackvertexset_ilp.rs b/src/rules/minimumfeedbackvertexset_ilp.rs index 554de5e28..e7515f247 100644 --- a/src/rules/minimumfeedbackvertexset_ilp.rs +++ b/src/rules/minimumfeedbackvertexset_ilp.rs @@ -134,7 +134,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec 1 -> 2 -> 0 (FVS = 1 vertex) let graph = DirectedGraph::new(3, vec![(0, 1), (1, 2), (2, 0)]); let source = MinimumFeedbackVertexSet::new(graph, vec![1i64; 3]); crate::example_db::specs::rule_example_via_bounded_ilp::<_>(source) diff --git a/src/rules/minimumgraphbandwidth_ilp.rs b/src/rules/minimumgraphbandwidth_ilp.rs index 7504bfa1a..f4e510c95 100644 --- a/src/rules/minimumgraphbandwidth_ilp.rs +++ b/src/rules/minimumgraphbandwidth_ilp.rs @@ -154,7 +154,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec(source) diff --git a/src/rules/minimuminternalmacrodatacompression_ilp.rs b/src/rules/minimuminternalmacrodatacompression_ilp.rs index bf821ac5c..2952b1014 100644 --- a/src/rules/minimuminternalmacrodatacompression_ilp.rs +++ b/src/rules/minimuminternalmacrodatacompression_ilp.rs @@ -288,9 +288,6 @@ impl ReduceTo> for MinimumInternalMacroDataCompression { pub(crate) fn canonical_rule_example_specs() -> Vec { use crate::export::SolutionPair; - // s = "ab" (len 2), alphabet {a,b} (size 2), h=2 - // Optimal: uncompressed C="ab", cost = 2 - // ILP: lit[0]=1, lit[1]=1, no pointers vec![crate::example_db::specs::RuleExampleSpec { id: "minimuminternalmacrodatacompression_to_ilp", build: || { diff --git a/src/rules/minimummatrixcover_ilp.rs b/src/rules/minimummatrixcover_ilp.rs index 84e7afe6f..fb10f3817 100644 --- a/src/rules/minimummatrixcover_ilp.rs +++ b/src/rules/minimummatrixcover_ilp.rs @@ -158,14 +158,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>( source, SolutionPair { diff --git a/src/rules/minimummaximalmatching_ilp.rs b/src/rules/minimummaximalmatching_ilp.rs index 771237219..dc131a568 100644 --- a/src/rules/minimummaximalmatching_ilp.rs +++ b/src/rules/minimummaximalmatching_ilp.rs @@ -113,7 +113,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec, /// Source edges in unified vertex coordinates, in the same order as - /// `source.graph().edges()` (which determines the source `dims()`). + /// `source.graph().edges()` (which determines the source solution's edge order). source_edges: Vec<(usize, usize)>, } @@ -70,7 +70,6 @@ impl ReduceTo> for MinimumMaximalMatching = source_edges .iter() .map(|&(u, v)| if u < v { (u, v) } else { (v, u) }) @@ -102,50 +101,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec v0, local 1 -> v2, local 2 -> v4 - // right local 0 -> v1, local 1 -> v3 - // edges (left_idx, right_idx): - // (v0, v1) -> (0, 0) - // (v1, v2) -> (1, 0) - // (v2, v3) -> (1, 1) - // (v1, v4) -> (2, 0) - // - // Unified vertex labels: - // 0 = v0 (left 0), 1 = v2 (left 1), 2 = v4 (left 2), - // 3 = v1 (right 0), 4 = v3 (right 1). - // - // Unified edges from Graph::edges() (in source order): - // (0, 3), (1, 3), (1, 4), (2, 3). - // - // Maximal matchings of G: - // - {(v1, v2)} size 1 <-- mm(G) = 1 - // - {(v0, v1), (v2, v3)} size 2 (suboptimal 1) - // - {(v1, v4), (v2, v3)} size 2 (suboptimal 2) - // So the canonical example exhibits >=2 suboptimal maximal - // matchings besides the optimum. - // - // Canonical optimum: pick the central edge (v1, v2), which is - // source edge index 1. source_config = [0, 1, 0, 0]. - // - // complement(G) on K_5: 10 - 4 = 6 edges, namely - // (0, 1), (0, 2), (0, 4), (1, 2), (2, 4), (3, 4). - // - // Canonical achromatic 4-coloring of complement(G): - // v0 (idx 0) -> color 1 - // v2 (idx 1) -> color 0 (paired with v1 = G-edge (v1, v2)) - // v4 (idx 2) -> color 3 - // v1 (idx 3) -> color 0 - // v3 (idx 4) -> color 2 - // target_config = [1, 0, 3, 0, 2]; psi(H) = |V| - mm(G) = 4. + // Include suboptimal maximal matchings so the example exercises optimization. let source = MinimumMaximalMatching::new(BipartiteGraph::new( 3, 2, diff --git a/src/rules/minimummaximalmatching_minimummatrixdomination.rs b/src/rules/minimummaximalmatching_minimummatrixdomination.rs index 03b0c98d7..cc37a511c 100644 --- a/src/rules/minimummaximalmatching_minimummatrixdomination.rs +++ b/src/rules/minimummaximalmatching_minimummatrixdomination.rs @@ -335,32 +335,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec - // source_config = [1, 0, 0, 1, 0]. - // - // Constructed N x N matrix with N = 5; 1-entries in row-major - // order (matching the source edge order above): - // idx 0: (0, 2) <- (l0, r0) - // idx 1: (0, 3) <- (l0, r1) - // idx 2: (0, 4) <- (l0, r2) - // idx 3: (1, 3) <- (l1, r1) - // idx 4: (1, 4) <- (l1, r2) - // - // Selecting target_config = [1, 0, 0, 1, 0] picks 1-entries - // {(0, 2), (1, 3)}, which together dominate every other 1-entry by - // shared row 0 or row 1. let source = MinimumMaximalMatching::new(BipartiteGraph::new( 2, 3, diff --git a/src/rules/minimummetricdimension_ilp.rs b/src/rules/minimummetricdimension_ilp.rs index 1a71ac3ce..adccd107e 100644 --- a/src/rules/minimummetricdimension_ilp.rs +++ b/src/rules/minimummetricdimension_ilp.rs @@ -95,7 +95,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec(source) }, diff --git a/src/rules/minimumsetcovering_ilp.rs b/src/rules/minimumsetcovering_ilp.rs index 2805a7407..0934f2809 100644 --- a/src/rules/minimumsetcovering_ilp.rs +++ b/src/rules/minimumsetcovering_ilp.rs @@ -63,7 +63,6 @@ impl ReduceTo> for MinimumSetCovering { // This ensures each element is covered by at least one selected set let constraints: Vec = (0..self.universe_size()) .map(|element| { - // Find all sets containing this element let terms: Vec<(usize, i64)> = self .sets() .iter() diff --git a/src/rules/minimumsummulticenter_ilp.rs b/src/rules/minimumsummulticenter_ilp.rs index d2e33f01b..c50a520c7 100644 --- a/src/rules/minimumsummulticenter_ilp.rs +++ b/src/rules/minimumsummulticenter_ilp.rs @@ -205,8 +205,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec Vec( diff --git a/src/rules/minimumvertexcover_minimumfeedbackarcset.rs b/src/rules/minimumvertexcover_minimumfeedbackarcset.rs index 0cb8265ec..4dea73c45 100644 --- a/src/rules/minimumvertexcover_minimumfeedbackarcset.rs +++ b/src/rules/minimumvertexcover_minimumfeedbackarcset.rs @@ -120,8 +120,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec Vec> for MixedChinesePostman { let l = m + 2 * q; // total available arcs - // Build available arc list with lengths let mut avail_arcs: Vec<(usize, usize)> = Vec::with_capacity(l); let mut avail_lengths: Vec = Vec::with_capacity(l); @@ -397,7 +396,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec Vec(source) }, diff --git a/src/rules/naesatisfiability_ilp.rs b/src/rules/naesatisfiability_ilp.rs index c748f0e97..df8495f5e 100644 --- a/src/rules/naesatisfiability_ilp.rs +++ b/src/rules/naesatisfiability_ilp.rs @@ -104,13 +104,11 @@ pub(crate) fn canonical_rule_example_specs() -> Vec(source) diff --git a/src/rules/naesatisfiability_maxcut.rs b/src/rules/naesatisfiability_maxcut.rs index b5fec3dc9..0ddde9771 100644 --- a/src/rules/naesatisfiability_maxcut.rs +++ b/src/rules/naesatisfiability_maxcut.rs @@ -206,10 +206,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec( source, SolutionPair { - // x1=T(1), x2=F(0), x3=T(1) source_config: serde_json::json!(vec![true, false, true]), - // Vertices: x1(0)=1, ~x1(1)=0, x2(2)=0, ~x2(3)=1, x3(4)=1, ~x3(5)=0 - // All variable edges cross (weight M=3 each) -> 3*3=9 - // C1=(x1,x2,~x3): vertices 0,2,5 -> sides {1},{0,0} -> edges (0,2) crosses, (0,5) crosses, (2,5) doesn't -> +2 - // C2=(~x1,x3,x2): vertices 1,4,2 -> sides {0},{1,0} -> edges (1,4) crosses, (1,2) doesn't, (4,2) crosses -> +2 - // Total = 9 + 2 + 2 = 13 target_config: serde_json::json!(vec![true, false, false, true, true, false]), }, ) diff --git a/src/rules/openshopscheduling_ilp.rs b/src/rules/openshopscheduling_ilp.rs index a36e46f61..c38aab5ef 100644 --- a/src/rules/openshopscheduling_ilp.rs +++ b/src/rules/openshopscheduling_ilp.rs @@ -233,7 +233,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec(source) }, diff --git a/src/rules/optimallineararrangement_consecutiveonesmatrixaugmentation.rs b/src/rules/optimallineararrangement_consecutiveonesmatrixaugmentation.rs index bc10fe770..7e3dbcead 100644 --- a/src/rules/optimallineararrangement_consecutiveonesmatrixaugmentation.rs +++ b/src/rules/optimallineararrangement_consecutiveonesmatrixaugmentation.rs @@ -113,9 +113,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec::reduce_to(&source) .expect("reduction should succeed"); - // Source arrangement f(v) = v <=> target column permutation = identity. let source_config = vec![0, 1, 2, 3, 4, 5]; let target_config = vec![0, 1, 2, 3, 4, 5]; assemble_rule_example( diff --git a/src/rules/optimallineararrangement_ilp.rs b/src/rules/optimallineararrangement_ilp.rs index de1ca2add..6a8369304 100644 --- a/src/rules/optimallineararrangement_ilp.rs +++ b/src/rules/optimallineararrangement_ilp.rs @@ -159,7 +159,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec(source) diff --git a/src/rules/optimumcommunicationspanningtree_ilp.rs b/src/rules/optimumcommunicationspanningtree_ilp.rs index 54fc448ec..531d22313 100644 --- a/src/rules/optimumcommunicationspanningtree_ilp.rs +++ b/src/rules/optimumcommunicationspanningtree_ilp.rs @@ -175,7 +175,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec 3 cars let source = PaintShop::new(vec!["A", "B", "A", "C", "B", "C"]); let reduction: ReductionPaintShopToILP = ReduceTo::>::reduce_to(&source).expect("reduction should succeed"); diff --git a/src/rules/paintshop_qubo.rs b/src/rules/paintshop_qubo.rs index fd6bbeced..730553d78 100644 --- a/src/rules/paintshop_qubo.rs +++ b/src/rules/paintshop_qubo.rs @@ -118,7 +118,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>( source, diff --git a/src/rules/partition_cosineproductintegration.rs b/src/rules/partition_cosineproductintegration.rs index 75a121051..8ee62732b 100644 --- a/src/rules/partition_cosineproductintegration.rs +++ b/src/rules/partition_cosineproductintegration.rs @@ -68,12 +68,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec( Partition::new(vec![3, 1, 1, 2, 2, 1]).unwrap(), SolutionPair { diff --git a/src/rules/partition_multiprocessorscheduling.rs b/src/rules/partition_multiprocessorscheduling.rs index 5ff8a17f1..3443a72ff 100644 --- a/src/rules/partition_multiprocessorscheduling.rs +++ b/src/rules/partition_multiprocessorscheduling.rs @@ -84,8 +84,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec( Partition::new(vec![1, 2, 3, 4]).unwrap(), SolutionPair { diff --git a/src/rules/partition_sumofsquarespartition.rs b/src/rules/partition_sumofsquarespartition.rs index 691f3cb28..7722e78e4 100644 --- a/src/rules/partition_sumofsquarespartition.rs +++ b/src/rules/partition_sumofsquarespartition.rs @@ -125,8 +125,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec 5^2 + 5^2 = 50 = S^2 / 2. crate::example_db::specs::rule_example_with_witness::<_, SumOfSquaresPartition>( Partition::new(vec![3, 1, 1, 2, 2, 1]).unwrap(), SolutionPair { diff --git a/src/rules/partitionintopathsoflength2_boundedcomponentspanningforest.rs b/src/rules/partitionintopathsoflength2_boundedcomponentspanningforest.rs index eb7778cf8..adf8d5bc0 100644 --- a/src/rules/partitionintopathsoflength2_boundedcomponentspanningforest.rs +++ b/src/rules/partitionintopathsoflength2_boundedcomponentspanningforest.rs @@ -91,7 +91,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec Vec Vec1->2 and 0->2 - // Two paths: [0,1] (0->1->2) and [2] (0->2) let source = PathConstrainedNetworkFlow::new( DirectedGraph::new(3, vec![(0, 1), (1, 2), (0, 2)]), vec![1, 1, 1], diff --git a/src/rules/precedenceconstrainedscheduling_ilp.rs b/src/rules/precedenceconstrainedscheduling_ilp.rs index 10cd0e7c3..8e8fde714 100644 --- a/src/rules/precedenceconstrainedscheduling_ilp.rs +++ b/src/rules/precedenceconstrainedscheduling_ilp.rs @@ -37,7 +37,6 @@ impl ReductionResult for ReductionPCSToILP { /// Extract schedule from ILP solution. /// /// For each task j, find the time slot t where x_{j,t} = 1. - /// Returns the time slot for each task (matching the `dims()` encoding of PCS). fn extract_solution( &self, target_solution: &::Solution, @@ -132,7 +131,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec(source) }, diff --git a/src/rules/preemptivescheduling_ilp.rs b/src/rules/preemptivescheduling_ilp.rs index 4878d45d7..4eca26882 100644 --- a/src/rules/preemptivescheduling_ilp.rs +++ b/src/rules/preemptivescheduling_ilp.rs @@ -169,7 +169,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec(source) }, diff --git a/src/rules/prizecollectingsteinerforest_steinertree.rs b/src/rules/prizecollectingsteinerforest_steinertree.rs index c79151290..15acd2f09 100644 --- a/src/rules/prizecollectingsteinerforest_steinertree.rs +++ b/src/rules/prizecollectingsteinerforest_steinertree.rs @@ -225,11 +225,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec::new( SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![5, 1, 5], diff --git a/src/rules/quadraticassignment_ilp.rs b/src/rules/quadraticassignment_ilp.rs index 157bf6937..1674757de 100644 --- a/src/rules/quadraticassignment_ilp.rs +++ b/src/rules/quadraticassignment_ilp.rs @@ -132,7 +132,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec Vec1->2->3 (root=0), identity mapping - // Total distance = 1+1+1 = 3 <= 5 - // Target: universe_size=4, subsets={{0,1},{1,2},{2,3}}, bound=5-3=2 - // Target tree: parent=[0,0,1,2], identity mapping - // Extension cost = 0+0+0 = 0 <= 2 let source = RootedTreeArrangement::new(SimpleGraph::new(4, vec![(0, 1), (1, 2), (2, 3)]), 5); let source_config = vec![0, 0, 1, 2, 0, 1, 2, 3]; diff --git a/src/rules/ruralpostman_ilp.rs b/src/rules/ruralpostman_ilp.rs index 74225b9c4..7063b1dd7 100644 --- a/src/rules/ruralpostman_ilp.rs +++ b/src/rules/ruralpostman_ilp.rs @@ -234,7 +234,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec usize { - // Add 5 new vertices let new_vertices = self.add_vertices(5); let ancilla1 = new_vertices[0]; let ancilla2 = new_vertices[1]; @@ -285,7 +282,6 @@ impl ReduceTo> for Satisfiability { fn reduce_to(&self) -> Result { let mut constructor = SATColoringConstructor::new(self.num_vars()); - // Add each clause to the graph for clause in self.clauses() { constructor.add_clause(&clause.literals); } diff --git a/src/rules/sat_ksat.rs b/src/rules/sat_ksat.rs index fd5607f92..3880830be 100644 --- a/src/rules/sat_ksat.rs +++ b/src/rules/sat_ksat.rs @@ -83,12 +83,10 @@ fn add_clause_to_ksat( // (a v b) with k=3 becomes (a v b v x) AND (a v b v -x) let ancilla = variables.allocate()?; - // Add clause with positive ancilla let mut lits_pos = clause.literals.clone(); lits_pos.push(ancilla); add_clause_to_ksat(k, &CNFClause::new(lits_pos), result_clauses, variables)?; - // Add clause with negative ancilla let mut lits_neg = clause.literals.clone(); lits_neg.push(-ancilla); add_clause_to_ksat(k, &CNFClause::new(lits_neg), result_clauses, variables)?; diff --git a/src/rules/sat_maximumindependentset.rs b/src/rules/sat_maximumindependentset.rs index 79642a363..1f3c6116b 100644 --- a/src/rules/sat_maximumindependentset.rs +++ b/src/rules/sat_maximumindependentset.rs @@ -136,13 +136,11 @@ impl ReduceTo>> for Satisfiabil for clause in self.clauses() { let clause_start = literals.len(); - // Add vertices for each literal in this clause for &lit in &clause.literals { literals.push(BoolVar::from_literal(lit)); } let vertex_count = literals.len(); - // Add clique edges within this clause for i in clause_start..vertex_count { for j in (i + 1)..vertex_count { edges.push((i, j)); diff --git a/src/rules/sat_minimumdominatingset.rs b/src/rules/sat_minimumdominatingset.rs index 9dea994c8..b191da783 100644 --- a/src/rules/sat_minimumdominatingset.rs +++ b/src/rules/sat_minimumdominatingset.rs @@ -156,7 +156,6 @@ impl ReduceTo>> for Satisfiabili // These form a complete triangle (clique of 3) for i in 0..num_variables { let base = 3 * i; - // Add all edges of the triangle edges.push((base, base + 1)); edges.push((base, base + 2)); edges.push((base + 1, base + 2)); diff --git a/src/rules/schedulingtominimizeweightedcompletiontime_ilp.rs b/src/rules/schedulingtominimizeweightedcompletiontime_ilp.rs index ab3a5e2b7..bf9dbb7ab 100644 --- a/src/rules/schedulingtominimizeweightedcompletiontime_ilp.rs +++ b/src/rules/schedulingtominimizeweightedcompletiontime_ilp.rs @@ -216,7 +216,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec(source) diff --git a/src/rules/schedulingwithindividualdeadlines_ilp.rs b/src/rules/schedulingwithindividualdeadlines_ilp.rs index 93df3a70c..fde7a813e 100644 --- a/src/rules/schedulingwithindividualdeadlines_ilp.rs +++ b/src/rules/schedulingwithindividualdeadlines_ilp.rs @@ -156,7 +156,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec(source) }, diff --git a/src/rules/sequencingtominimizemaximumcumulativecost_ilp.rs b/src/rules/sequencingtominimizemaximumcumulativecost_ilp.rs index ee560f5dc..b842972f4 100644 --- a/src/rules/sequencingtominimizemaximumcumulativecost_ilp.rs +++ b/src/rules/sequencingtominimizemaximumcumulativecost_ilp.rs @@ -30,7 +30,6 @@ impl ReductionResult for ReductionSTMMCCToILP { &self.target } - /// Extract: decode position assignment → permutation → Lehmer code. fn extract_solution( &self, target_solution: &::Solution, diff --git a/src/rules/sequencingwithinintervals_ilp.rs b/src/rules/sequencingwithinintervals_ilp.rs index 1ff775fd4..e67c18f5e 100644 --- a/src/rules/sequencingwithinintervals_ilp.rs +++ b/src/rules/sequencingwithinintervals_ilp.rs @@ -170,9 +170,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec>::reduce_to(&source).expect("reduction should succeed"); diff --git a/src/rules/shortestweightconstrainedpath_ilp.rs b/src/rules/shortestweightconstrainedpath_ilp.rs index ee645c67d..0cc4c8ee9 100644 --- a/src/rules/shortestweightconstrainedpath_ilp.rs +++ b/src/rules/shortestweightconstrainedpath_ilp.rs @@ -235,10 +235,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec feasible let source = ShortestWeightConstrainedPath::new( SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![2, 3], diff --git a/src/rules/spinglass_maxcut.rs b/src/rules/spinglass_maxcut.rs index 31e315acc..6f14f36cc 100644 --- a/src/rules/spinglass_maxcut.rs +++ b/src/rules/spinglass_maxcut.rs @@ -58,23 +58,8 @@ impl ReduceTo> for MaxCut { let n = self.graph().num_vertices(); let edges_with_weights = self.edges(); - // MaxCut: maximize sum of w_ij for edges (i,j) where s_i != s_j - // SpinGlass: minimize sum of J_ij * s_i * s_j - // - // For MaxCut, we want to maximize cut, which means: - // - When s_i != s_j (opposite spins), edge contributes to cut - // - s_i * s_j = -1 when opposite, +1 when same - // - // To convert: maximize sum(w_ij * [s_i != s_j]) - // = maximize sum(w_ij * (1 - s_i*s_j)/2) - // = constant - minimize sum(w_ij * s_i*s_j / 2) - // - // So J_ij = -w_ij / 2 would work, but since we need to relate - // the problems directly, we use J_ij = w_ij and negate. - // Actually, for a proper reduction, we set J_ij = w_ij. - // MaxCut wants to maximize edges cut, SpinGlass minimizes energy. - // When J > 0 (antiferromagnetic), opposite spins lower energy. - // So maximizing cut = minimizing Ising energy with J = w. + // With J_ij = w_ij, energy = sum(w_ij) - 2 * cut_weight, + // so minimizing energy maximizes the cut without fractional couplings. let interactions: Vec<((usize, usize), i64)> = edges_with_weights .into_iter() .map(|(u, v, w)| ((u, v), w)) @@ -165,7 +150,6 @@ impl ReduceTo> for SpinGlass { let interactions = self.interactions(); let fields = self.fields(); - // Check if we need an ancilla vertex for onsite terms let need_ancilla = fields.iter().any(|h| !h.is_zero()); let total_vertices = if need_ancilla { n + 1 } else { n }; let ancilla_idx = if need_ancilla { Some(n) } else { None }; @@ -173,13 +157,11 @@ impl ReduceTo> for SpinGlass { let mut edges = Vec::new(); let mut weights = Vec::new(); - // Add interaction edges for ((i, j), w) in interactions { edges.push((i, j)); weights.push(w); } - // Add onsite terms as edges to ancilla // h_i * s_i can be modeled as an edge to ancilla with weight h_i // When s_i and s_ancilla are opposite, the edge is cut if need_ancilla { diff --git a/src/rules/spinglass_qubo.rs b/src/rules/spinglass_qubo.rs index e7b0da2b5..26cc826e4 100644 --- a/src/rules/spinglass_qubo.rs +++ b/src/rules/spinglass_qubo.rs @@ -152,7 +152,6 @@ impl ReduceTo> for SpinGlass { matrix[j][j] -= 2.0 * j_val; } - // Convert h fields to diagonal for (i, &h) in self.fields().iter().enumerate() { // h_i * s_i -> 2*h_i*x_i matrix[i][i] += 2.0 * h; diff --git a/src/rules/stackercrane_ilp.rs b/src/rules/stackercrane_ilp.rs index c24517495..0f0b5fb29 100644 --- a/src/rules/stackercrane_ilp.rs +++ b/src/rules/stackercrane_ilp.rs @@ -201,7 +201,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec(source) diff --git a/src/rules/stringtostringcorrection_ilp.rs b/src/rules/stringtostringcorrection_ilp.rs index 5acadd719..a3721dcad 100644 --- a/src/rules/stringtostringcorrection_ilp.rs +++ b/src/rules/stringtostringcorrection_ilp.rs @@ -402,7 +402,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source).expect("reduction should succeed"); diff --git a/src/rules/strongconnectivityaugmentation_ilp.rs b/src/rules/strongconnectivityaugmentation_ilp.rs index debe00ffb..207d571da 100644 --- a/src/rules/strongconnectivityaugmentation_ilp.rs +++ b/src/rules/strongconnectivityaugmentation_ilp.rs @@ -202,7 +202,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec Vec(source) }, diff --git a/src/rules/threedimensionalmatching_minimumweightdecoding.rs b/src/rules/threedimensionalmatching_minimumweightdecoding.rs index 20d9c722e..d4414375d 100644 --- a/src/rules/threedimensionalmatching_minimumweightdecoding.rs +++ b/src/rules/threedimensionalmatching_minimumweightdecoding.rs @@ -141,9 +141,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec( ThreeDimensionalMatching::new(2, vec![(0, 0, 0), (1, 1, 1), (0, 1, 0), (1, 0, 1)]), SolutionPair { diff --git a/src/rules/threepartition_resourceconstrainedscheduling.rs b/src/rules/threepartition_resourceconstrainedscheduling.rs index 546554b23..372857300 100644 --- a/src/rules/threepartition_resourceconstrainedscheduling.rs +++ b/src/rules/threepartition_resourceconstrainedscheduling.rs @@ -104,9 +104,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec( ThreePartition::new(vec![4, 5, 6, 4, 6, 5], 15), SolutionPair { diff --git a/src/rules/threepartition_sequencingwithreleasetimesanddeadlines.rs b/src/rules/threepartition_sequencingwithreleasetimesanddeadlines.rs index d23088f09..28ba0bb3f 100644 --- a/src/rules/threepartition_sequencingwithreleasetimesanddeadlines.rs +++ b/src/rules/threepartition_sequencingwithreleasetimesanddeadlines.rs @@ -181,24 +181,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec times [0,4), [4,9), [9,15) - // Filler [15,16): task 6(len=1) - // Slot 1 [16,31): tasks 3(len=4), 4(len=6), 5(len=5) -> times [16,20), [20,26), [26,31) - // Permutation: [0,1,2,6,3,4,5] - // Lehmer code: [0,0,0,3,0,0,0] - // remaining=[0,1,2,3,4,5,6], pick 0 -> 0, remaining=[1,2,3,4,5,6] - // remaining=[1,2,3,4,5,6], pick 0 -> 1, remaining=[2,3,4,5,6] - // remaining=[2,3,4,5,6], pick 0 -> 2, remaining=[3,4,5,6] - // remaining=[3,4,5,6], pick 3 -> 6, remaining=[3,4,5] - // remaining=[3,4,5], pick 0 -> 3, remaining=[4,5] - // remaining=[4,5], pick 0 -> 4, remaining=[5] - // remaining=[5], pick 0 -> 5 crate::example_db::specs::rule_example_with_witness::< _, SequencingWithReleaseTimesAndDeadlines, diff --git a/src/rules/timetabledesign_ilp.rs b/src/rules/timetabledesign_ilp.rs index 82572acbe..73d9e8479 100644 --- a/src/rules/timetabledesign_ilp.rs +++ b/src/rules/timetabledesign_ilp.rs @@ -124,7 +124,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec> for TravelingSalesman { .map_err(|_| overflow("computing the tour penalty constant"))?; let feasible_energy_upper = i128::from(a) - omitted_constant; - // Build n^2 x n^2 upper-triangular QUBO matrix let mut matrix = vec![vec![0i64; dim]; dim]; // Helper: add value to upper-triangular position diff --git a/src/rules/undirectedflowlowerbounds_ilp.rs b/src/rules/undirectedflowlowerbounds_ilp.rs index 3edc5e228..08ae117ac 100644 --- a/src/rules/undirectedflowlowerbounds_ilp.rs +++ b/src/rules/undirectedflowlowerbounds_ilp.rs @@ -203,8 +203,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec line.hslot; let has_right = line.hstop > line.vslot; diff --git a/src/rules/unitdiskmapping/ksg/gadgets.rs b/src/rules/unitdiskmapping/ksg/gadgets.rs index 4e64e7574..047897aa7 100644 --- a/src/rules/unitdiskmapping/ksg/gadgets.rs +++ b/src/rules/unitdiskmapping/ksg/gadgets.rs @@ -1479,7 +1479,6 @@ pub fn apply_simplifier_gadgets(grid: &mut MappingGrid, nrepeat: usize) -> Vec(pattern: &P, grid: &mut MappingGrid, i: *count_map.entry((r, c)).or_insert(0) += 1; } - // Set cells with proper weights for (&(r, c), &total_weight) in &weight_map { let grid_r = i + r - 1; // Convert 1-indexed to 0-indexed let grid_c = j + c - 1; diff --git a/src/rules/unitdiskmapping/ksg/gadgets_weighted.rs b/src/rules/unitdiskmapping/ksg/gadgets_weighted.rs index 71ea5c91c..756a81f02 100644 --- a/src/rules/unitdiskmapping/ksg/gadgets_weighted.rs +++ b/src/rules/unitdiskmapping/ksg/gadgets_weighted.rs @@ -1092,7 +1092,6 @@ pub fn apply_weighted_gadget(pattern: &P, grid: &mut MappingGrid, i: *count_map.entry((r, c)).or_insert(0) += 1; } - // Set cells with proper weights for (&(r, c), &total_weight) in &weight_map { let grid_r = i + r - 1; // Convert 1-indexed to 0-indexed let grid_c = j + c - 1; @@ -1257,7 +1256,6 @@ fn pattern_matches_weighted( return false; } - // Check that source weights match the grid weights let (locs, _, _) = pattern.source_graph_boxed(); let source_weights = pattern.source_weights_boxed(); diff --git a/src/rules/unitdiskmapping/ksg/mapping.rs b/src/rules/unitdiskmapping/ksg/mapping.rs index 23e471a58..d8c9ebb18 100644 --- a/src/rules/unitdiskmapping/ksg/mapping.rs +++ b/src/rules/unitdiskmapping/ksg/mapping.rs @@ -95,7 +95,6 @@ impl MappingResult { pub fn format_config(&self, config: &[Vec]) -> String { let (rows, cols) = self.grid_dimensions; - // Build position to node index map let mut pos_to_node: HashMap<(i64, i64), usize> = HashMap::new(); for (idx, &(r, c)) in self.positions.iter().enumerate() { pos_to_node.insert((r, c), idx); @@ -594,7 +593,6 @@ pub fn map_unweighted_with_order( .ok_or(mapping_integer_overflow("summing copy-line MIS overhead")) })?; - // Add MIS overhead from gadgets let gadget_overhead = tape.iter().try_fold(0_i64, |total, entry| { total .checked_add(tape_entry_mis_overhead(entry)?) @@ -714,7 +712,6 @@ pub fn map_weighted_with_order( )) })?; - // Add MIS overhead from weighted gadgets let gadget_overhead = tape.iter().try_fold(0_i64, |total, entry| { total .checked_add(weighted_tape_entry_mis_overhead(entry)?) @@ -735,7 +732,6 @@ pub fn map_weighted_with_order( )); } - // Extract positions and weights from occupied cells let positions_and_weights = grid .occupied_coords() .into_iter() diff --git a/src/rules/unitdiskmapping/ksg/mod.rs b/src/rules/unitdiskmapping/ksg/mod.rs index c4f1a35d0..309f4ee6a 100644 --- a/src/rules/unitdiskmapping/ksg/mod.rs +++ b/src/rules/unitdiskmapping/ksg/mod.rs @@ -21,7 +21,6 @@ pub mod gadgets; pub mod gadgets_weighted; pub mod mapping; -// Re-export all public items for convenient access pub use gadgets::{ apply_crossing_gadgets, apply_simplifier_gadgets, crossing_ruleset_indices, tape_entry_mis_overhead, KsgBranch, KsgBranchFix, KsgBranchFixB, KsgCross, KsgDanglingLeg, diff --git a/src/rules/unitdiskmapping/mod.rs b/src/rules/unitdiskmapping/mod.rs index 913925797..1b94e099c 100644 --- a/src/rules/unitdiskmapping/mod.rs +++ b/src/rules/unitdiskmapping/mod.rs @@ -33,7 +33,6 @@ mod traits; pub mod triangular; mod weighted; -// Re-export commonly used items from submodules for convenience pub use ksg::{GridKind, MappingResult}; use crate::rules::ReductionError; diff --git a/src/rules/unitdiskmapping/pathdecomposition.rs b/src/rules/unitdiskmapping/pathdecomposition.rs index e84dece95..37b6d06a3 100644 --- a/src/rules/unitdiskmapping/pathdecomposition.rs +++ b/src/rules/unitdiskmapping/pathdecomposition.rs @@ -374,7 +374,6 @@ fn branch_and_bound_internal( let mut remaining: Vec = p2.neighbors.clone(); remaining.extend(p2.disconnected.iter()); - // Sort by increasing vsep_updated let mut vsep_order: Vec<(usize, usize)> = remaining .iter() .map(|&v| (vsep_updated(adj, &p2, v), v)) diff --git a/src/rules/unitdiskmapping/triangular/gadgets.rs b/src/rules/unitdiskmapping/triangular/gadgets.rs index f5af487f1..b6b6d25cd 100644 --- a/src/rules/unitdiskmapping/triangular/gadgets.rs +++ b/src/rules/unitdiskmapping/triangular/gadgets.rs @@ -1019,7 +1019,6 @@ fn apply_gadget( for (idx, (r, c)) in locs.iter().enumerate() { if *r > 0 && *c > 0 && *r <= m && *c <= n { let weight = weights[idx]; - // Convert 1-indexed pattern pos to 0-indexed grid pos grid.add_node(i + r - 1, j + c - 1, weight); } } diff --git a/src/rules/unitdiskmapping/triangular/mapping.rs b/src/rules/unitdiskmapping/triangular/mapping.rs index 7fa8ebe29..8173ddfad 100644 --- a/src/rules/unitdiskmapping/triangular/mapping.rs +++ b/src/rules/unitdiskmapping/triangular/mapping.rs @@ -233,7 +233,6 @@ pub fn map_weighted_with_order( )) })?; - // Add gadget overhead (crossing gadgets + simplifiers) let gadget_overhead = triangular_tape.iter().try_fold(0_i64, |total, entry| { total .checked_add(tape_entry_mis_overhead(entry)?) @@ -254,7 +253,6 @@ pub fn map_weighted_with_order( )); } - // Convert triangular tape entries to generic tape entries let tape: Vec = triangular_tape .into_iter() .map(|entry| TapeEntry { @@ -267,7 +265,6 @@ pub fn map_weighted_with_order( // Extract doubled cells before extracting positions let doubled_cells = grid.doubled_cells(); - // Extract positions and weights from occupied cells let positions_and_weights = grid .occupied_coords() .into_iter() diff --git a/src/solvers/customized/partial_feedback_edge_set.rs b/src/solvers/customized/partial_feedback_edge_set.rs index a38992b57..4981b358b 100644 --- a/src/solvers/customized/partial_feedback_edge_set.rs +++ b/src/solvers/customized/partial_feedback_edge_set.rs @@ -21,7 +21,6 @@ pub(crate) fn solve(problem: &PartialFeedbackEdgeSet) -> Option> = vec![Vec::new(); n]; for (idx, &(u, v)) in edges.iter().enumerate() { adj[u].push((v, idx)); @@ -146,7 +145,6 @@ fn hitting_set_search( return; } - // Find the first uncovered cycle let uncovered = cycles[start_cycle..] .iter() .enumerate() diff --git a/src/solvers/customized/rooted_tree_arrangement.rs b/src/solvers/customized/rooted_tree_arrangement.rs index 8c807e9b1..dcc6a77fa 100644 --- a/src/solvers/customized/rooted_tree_arrangement.rs +++ b/src/solvers/customized/rooted_tree_arrangement.rs @@ -19,7 +19,6 @@ pub(crate) fn solve(problem: &RootedTreeArrangement) -> Option> = vec![Vec::new(); n]; for &(u, v) in &edges { adj[u].push(v); @@ -99,7 +98,6 @@ fn compute_depths(parent: &[usize], root: usize) -> Option> { loop { let p = parent[current]; if computed[p] { - // Compute depths for the whole path let base_depth = depth[p] + 1; for (i, &node) in path.iter().rev().enumerate() { depth[node] = base_depth + i; diff --git a/src/solvers/customized/solver.rs b/src/solvers/customized/solver.rs index 58bfb5194..6b34ff0cb 100644 --- a/src/solvers/customized/solver.rs +++ b/src/solvers/customized/solver.rs @@ -238,7 +238,6 @@ pub(crate) fn solve_additional_key(problem: &AdditionalKey) -> Option> let essential = find_essential_attributes_restricted(n_attrs, &deps, relation_attrs); - // Build branch order over relation_attrs indices (excluding essential) let essential_set: HashSet = essential.iter().copied().collect(); let branch_indices: Vec = relation_attrs .iter() @@ -253,7 +252,6 @@ pub(crate) fn solve_additional_key(problem: &AdditionalKey) -> Option> &branch_indices, |_selected, _depth| BranchDecision::Continue, |selected| { - // Check that selected forms a superkey over relation_attrs let closure = compute_closure(selected, &deps); if !relation_attrs.iter().all(|&a| closure[a]) { return false; diff --git a/src/topology/directed_graph.rs b/src/topology/directed_graph.rs index 1b30bb469..19c14f3e6 100644 --- a/src/topology/directed_graph.rs +++ b/src/topology/directed_graph.rs @@ -171,7 +171,6 @@ impl DirectedGraph { let n = self.num_vertices(); let arcs = self.arcs(); - // Build adjacency list for the subgraph let mut adj = vec![vec![]; n]; let mut in_degree = vec![0usize; n]; for (i, &(u, v)) in arcs.iter().enumerate() { diff --git a/src/topology/graph.rs b/src/topology/graph.rs index b21d5d223..ceef0eff8 100644 --- a/src/topology/graph.rs +++ b/src/topology/graph.rs @@ -245,7 +245,6 @@ impl PartialEq for SimpleGraph { if self.num_edges() != other.num_edges() { return false; } - // Check all edges exist in both let mut self_edges: Vec<_> = self.edges(); let mut other_edges: Vec<_> = other.edges(); // Normalize edge order diff --git a/src/topology/unit_disk_graph.rs b/src/topology/unit_disk_graph.rs index cbd352c78..2e574d1fd 100644 --- a/src/topology/unit_disk_graph.rs +++ b/src/topology/unit_disk_graph.rs @@ -69,7 +69,6 @@ impl UnitDiskGraph { let n = positions.len(); let mut edges = Vec::new(); - // Compute all edges based on distance for i in 0..n { for j in (i + 1)..n { if Self::distance(&positions[i], &positions[j])? <= radius { diff --git a/src/unit_tests/example_db.rs b/src/unit_tests/example_db.rs index 3bc887a26..d58a984dd 100644 --- a/src/unit_tests/example_db.rs +++ b/src/unit_tests/example_db.rs @@ -698,7 +698,6 @@ fn rule_specs_solution_pairs_are_consistent() { }; for pair in &example.solutions { - // Verify configs produce feasible evaluations. let source_eval = source .evaluate_dyn(&pair.source_config) .unwrap_or_else(|error| { @@ -814,9 +813,7 @@ fn rule_specs_solution_pairs_are_consistent() { } } -// ---- Rule lookup tests for issue #974 ---- - -// PR #777 rules +// ---- Rule lookup tests ---- #[test] fn test_find_rule_example_hamiltoniancircuit_to_hamiltonianpath() { @@ -938,8 +935,6 @@ fn test_find_rule_example_satisfiability_to_naesatisfiability() { assert_eq!(example.target.problem, "NAESatisfiability"); } -// PR #779 rules - #[test] fn test_find_rule_example_ksatisfiability_to_decisionminimumvertexcover() { let source = ProblemRef { @@ -1090,8 +1085,6 @@ fn test_find_rule_example_hamiltoniancircuit_to_quadraticassignment() { assert_eq!(example.target.problem, "DecisionQuadraticAssignment"); } -// PR #804 rules - #[test] fn test_find_rule_example_minimumvertexcover_to_minimumhittingset() { let source = ProblemRef { @@ -1286,8 +1279,6 @@ fn test_find_rule_example_paintshop_to_qubo() { assert_eq!(example.target.problem, "QUBO"); } -// PR #972 rules - #[test] fn test_find_rule_example_partition_to_binpacking() { let source = ProblemRef { diff --git a/src/unit_tests/expr.rs b/src/unit_tests/expr.rs index 19d527a1e..aaa629710 100644 --- a/src/unit_tests/expr.rs +++ b/src/unit_tests/expr.rs @@ -698,9 +698,6 @@ fn test_parse_unclosed_function_error() { #[test] fn test_parse_expect_mismatch() { - // "exp(n]" — expects RParen, gets unexpected token ']' - // Actually ']' is an invalid char so tokenizer catches it first. - // Use "exp(n +" to trigger expect mismatch (expects RParen, gets Plus). let err = Expr::try_parse("exp(n +").unwrap_err(); assert!( err.to_string().contains("expected") || err.to_string().contains("end of input"), diff --git a/src/unit_tests/graph_models.rs b/src/unit_tests/graph_models.rs index 1467ca792..651c12f26 100644 --- a/src/unit_tests/graph_models.rs +++ b/src/unit_tests/graph_models.rs @@ -1,8 +1,5 @@ //! Unit tests for graph problems. //! -//! Tests extracted from source files for better compilation times -//! and clearer separation of concerns. - use crate::models::graph::kcoloring::is_valid_coloring; use crate::models::graph::maximum_independent_set::is_independent_set; use crate::models::graph::minimum_vertex_cover::is_vertex_cover; @@ -79,7 +76,7 @@ mod maximum_independent_set { let problem = MaximumIndependentSet::new(SimpleGraph::new(4, vec![(0, 1), (2, 3)]), vec![1i64; 4]); - // Invalid: 0 and 1 are adjacent - returns Invalid + // Vertices 0 and 1 are adjacent. assert_eq!( problem.evaluate(&vec![true, true, false, false]).unwrap(), Max(None) @@ -152,7 +149,6 @@ mod maximum_independent_set { for sol in &solutions { let size: usize = sol.iter().filter(|&&selected| selected).count(); assert_eq!(size, 2); - // Verify it's valid (evaluate returns Valid, not Invalid) assert_eq!(problem.evaluate(sol).unwrap(), Max(Some(2))); } } @@ -232,7 +228,6 @@ mod maximum_independent_set { let problem = MaximumIndependentSet::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![1i64; 3]); - // Valid IS configurations return is_valid() == true assert!(problem .evaluate(&vec![true, false, true]) .unwrap() @@ -241,7 +236,6 @@ mod maximum_independent_set { .evaluate(&vec![false, true, false]) .unwrap() .is_valid()); - // Invalid configurations return Invalid assert_eq!( problem.evaluate(&vec![true, true, false]).unwrap(), Max(None) @@ -301,7 +295,6 @@ mod minimum_vertex_cover { let problem = MinimumVertexCover::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![1i64; 3]); - // Invalid: no vertex selected - returns Invalid for minimization assert_eq!( problem.evaluate(&vec![false, false, false]).unwrap(), Min(None) @@ -340,7 +333,6 @@ mod minimum_vertex_cover { assert_eq!(solutions.len(), 3); for sol in &solutions { assert_eq!(sol.iter().filter(|&&selected| selected).count(), 2); - // Verify valid (not Invalid) assert!(problem.evaluate(sol).unwrap().is_valid()); } } @@ -409,7 +401,6 @@ mod minimum_vertex_cover { let problem = MinimumVertexCover::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![1i64; 3]); - // Valid cover configurations return is_valid() == true assert!(problem .evaluate(&vec![false, true, false]) .unwrap() @@ -418,7 +409,6 @@ mod minimum_vertex_cover { .evaluate(&vec![true, false, true]) .unwrap() .is_valid()); - // Invalid configurations return Invalid assert_eq!( problem.evaluate(&vec![true, false, false]).unwrap(), Min(None) @@ -443,7 +433,6 @@ mod minimum_vertex_cover { for is_sol in &is_solutions { // Complement should be a valid vertex cover let vc_config: Vec = is_sol.iter().map(|&selected| !selected).collect(); - // Valid cover returns is_valid() == true assert!(vc_problem.evaluate(&vc_config).unwrap().is_valid()); } } diff --git a/src/unit_tests/growth.rs b/src/unit_tests/growth.rs index 3291e0c0f..22dd1e897 100644 --- a/src/unit_tests/growth.rs +++ b/src/unit_tests/growth.rs @@ -420,8 +420,6 @@ fn test_growth_reports_nested_and_numeric_failures() { assert_eq!(exact_growth(Vec::new()).to_expr(), Some(Expr::integer(1))); } -// --- Additional coverage --- - /// Pure constants, constant factors, and constant division are all O(1) / dropped. #[test] fn test_growth_constants_are_o1() { @@ -622,8 +620,7 @@ fn test_growth_rejects_large_unproved_exponential_antichain() { // --- Randomized property tests --- // // These cross-validate the symbolic growth domain against the numeric ground -// truth (`Expr::eval`) over a large, seeded input space, in the spirit of the -// repo's `/verify-reduction` adversarial culture. Three contracts are exercised +// truth (`Expr::eval`) over a large, seeded input space. Three contracts are exercised // ≥ 5000 times each with a hand-rolled, deterministic RNG (no wall-clock, no // entropy — CI must be byte-reproducible across platforms): // diff --git a/src/unit_tests/ilp_overhead.rs b/src/unit_tests/ilp_overhead.rs index 21ab2b84a..9f2af50ca 100644 --- a/src/unit_tests/ilp_overhead.rs +++ b/src/unit_tests/ilp_overhead.rs @@ -433,8 +433,6 @@ fn changed_predictions_bound_real_intermediate_targets() { } } } - // Includes empty clauses, repeated literals and a fresh sentinel through - // the new incoming support contract and a real solve/extract workflow. for literals in [vec![], vec![1, 1], vec![1, -1]] { check_path( Satisfiability::new(1, vec![CNFClause::new(literals)]), diff --git a/src/unit_tests/models/algebraic/algebraic_equations_over_gf2.rs b/src/unit_tests/models/algebraic/algebraic_equations_over_gf2.rs index 87df06fc5..1d47acd05 100644 --- a/src/unit_tests/models/algebraic/algebraic_equations_over_gf2.rs +++ b/src/unit_tests/models/algebraic/algebraic_equations_over_gf2.rs @@ -140,7 +140,6 @@ fn test_algebraic_equations_over_gf2_serialization() { let restored: AlgebraicEquationsOverGF2 = serde_json::from_value(json).unwrap(); assert_eq!(restored.num_variables(), p.num_variables()); assert_eq!(restored.num_equations(), p.num_equations()); - // Check round-trip preserves evaluation assert_eq!( restored.evaluate(&vec![true, false, false]).unwrap(), Or(true) @@ -185,7 +184,6 @@ fn test_algebraic_equations_over_gf2_validation_errors() { #[test] fn test_algebraic_equations_over_gf2_paper_example() { - // Canonical example from the issue: n=3, 3 equations, config [1,0,0] let p = satisfiable_problem(); assert_eq!(p.evaluate(&vec![true, false, false]).unwrap(), Or(true)); diff --git a/src/unit_tests/models/algebraic/equilibrium_point.rs b/src/unit_tests/models/algebraic/equilibrium_point.rs index dd30d1d37..cbd357a2f 100644 --- a/src/unit_tests/models/algebraic/equilibrium_point.rs +++ b/src/unit_tests/models/algebraic/equilibrium_point.rs @@ -4,7 +4,7 @@ use crate::solvers::BruteForceProblem as _; use crate::traits::Problem; use crate::types::Or; -/// Canonical 3-player game from the issue. +/// Canonical 3-player game. /// F1 = x1*x2*x3, F2 = (1-x1)*x2, F3 = x1*(1-x3), M_i = {0, 1}. fn canonical_problem() -> EquilibriumPoint { let polynomials = vec![ @@ -17,12 +17,8 @@ fn canonical_problem() -> EquilibriumPoint { } /// Simple 2-player coordination game: F1 = F2 = x1*x2. -/// Both (0,0) and (1,1) are equilibria (payoff 0 each with M_i = {0,1}). -/// Actually F1(0,0)=0, dev to (1,0): F1(1,0)=0 — no strict improvement. -/// So (0,0) is an equilibrium trivially (no player can strictly improve). +/// Both (0,0) and (1,1) are equilibria: neither allows a strict payoff improvement. fn coordination_problem() -> EquilibriumPoint { - // F1 = x1*x2: factors [[0,1,0,0],[0,0,1,0]] (but only constant + 2 player coeffs). - // Wait: 2 players → factor len = 3. let polynomials = vec![ vec![vec![0, 1, 0], vec![0, 0, 1]], // F1 = x1 * x2 vec![vec![0, 1, 0], vec![0, 0, 1]], // F2 = x1 * x2 @@ -67,13 +63,7 @@ fn test_equilibrium_point_evaluate_canonical_equilibrium() { #[test] fn test_equilibrium_point_evaluate_non_equilibria() { let p = canonical_problem(); - // (1,1,1): F1=1. Dev player1 to 0: F1(0,1,1)=0 < 1 — no. Dev player2 to 0: F1(1,0,1)=0 <1 — no. Dev player3 to 0: F1(1,1,0)=0 <1 — no. - // F2=(1-1)*1=0. Dev player2 to 0: F2(1,0,1)=0 — no improvement. Player1 dev to 0: F2(0,1,1)=1*1=1 > 0 → NOT equilibrium for player 1 in F2? - // Wait F2 is player-2's payoff. Let me recheck: player 1 can deviate but that changes F2 too. - // Actually equilibrium condition: for player i, no y'_i in M_i gives F_i(y) < F_i(y with y_i=y'). - // At (1,1,1): F2(1,1,1)=(1-1)*1=0. Dev player2 to 0: F2(1,0,1)=(1-1)*0=0 — no improvement. - // But dev player1 (player 1) only affects F1! F1(1,1,1)=1*1*1=1, dev to 0: F1(0,1,1)=0*1*1=0 — no improvement for player1. - // F3(1,1,1)=1*(1-1)=0. Dev player3 to 0: F3(1,1,0)=1*(1-0)=1 > 0 → player 3 can improve! NOT equilibrium. + // At (1,1,1), player 3 can switch to 0 and increase F3 from 0 to 1. assert_eq!(p.evaluate(&vec![1, 1, 1]).unwrap(), Or(false)); // (0,0,0): F2(0,0,0)=(1-0)*0=0. Dev player2 to 1: F2(0,1,0)=(1-0)*1=1 > 0 → NOT equilibrium. diff --git a/src/unit_tests/models/algebraic/feasible_basis_extension.rs b/src/unit_tests/models/algebraic/feasible_basis_extension.rs index e73edf383..9a616dd2c 100644 --- a/src/unit_tests/models/algebraic/feasible_basis_extension.rs +++ b/src/unit_tests/models/algebraic/feasible_basis_extension.rs @@ -22,7 +22,7 @@ fn create_spec_validates_matrix_shape() { use crate::solvers::BruteForce; use crate::traits::Problem; -/// Issue #530 example: 3x6 matrix, rhs=[7,5,3], S={0,1}. +/// Example: 3x6 matrix, rhs=[7,5,3], S={0,1}. fn issue_example() -> FeasibleBasisExtension { FeasibleBasisExtension::new( vec![ @@ -53,7 +53,6 @@ fn test_feasible_basis_extension_creation() { fn test_feasible_basis_extension_evaluate_satisfying() { let problem = issue_example(); // Free columns are [2, 3, 4, 5]. Select col 2 (index 0 in free list). - // B = {0, 1, 2}. A_B = I_3. x = (7, 5, 3) but actually A_B = [[1,0,1],[0,1,0],[0,0,1]] // A_B^{-1} a_bar: solve [[1,0,1],[0,1,0],[0,0,1]] x = [7,5,3] => x = (4, 5, 3) >= 0 assert!(problem.evaluate(&vec![true, false, false, false]).unwrap()); } @@ -129,7 +128,7 @@ fn test_feasible_basis_extension_brute_force_all() { let problem = issue_example(); let solver = BruteForce::new(); let solutions = solver.find_all_witnesses(&problem).unwrap(); - // From the issue: B={0,1,2} and B={0,1,3} are feasible, so 2 solutions + // B={0,1,2} and B={0,1,3} are feasible, so 2 solutions assert_eq!(solutions.len(), 2); for sol in &solutions { assert!(problem.evaluate(sol).unwrap()); diff --git a/src/unit_tests/models/algebraic/minimum_matrix_cover.rs b/src/unit_tests/models/algebraic/minimum_matrix_cover.rs index 2e6dc7ec6..44acdf013 100644 --- a/src/unit_tests/models/algebraic/minimum_matrix_cover.rs +++ b/src/unit_tests/models/algebraic/minimum_matrix_cover.rs @@ -154,16 +154,13 @@ fn test_minimum_matrix_cover_paper_example() { let problem = MinimumMatrixCover::new(matrix); let solver = BruteForce::new(); - // Verify the claimed optimal from the issue let value = problem.evaluate(&vec![false, true, true, false]).unwrap(); assert_eq!(value, Min(Some(-20))); - // Verify it is truly optimal let optimal_value_solution = solver.solve(&problem).unwrap().unwrap(); let optimal_value = problem.evaluate(&optimal_value_solution).unwrap(); assert_eq!(optimal_value, Min(Some(-20))); - // Verify the witness is one of the optimal solutions let all_witnesses = solver.find_all_witnesses(&problem).unwrap(); assert!(all_witnesses.contains(&vec![false, true, true, false])); } diff --git a/src/unit_tests/models/algebraic/quadratic_assignment.rs b/src/unit_tests/models/algebraic/quadratic_assignment.rs index 06c68cf95..d73e1a7a6 100644 --- a/src/unit_tests/models/algebraic/quadratic_assignment.rs +++ b/src/unit_tests/models/algebraic/quadratic_assignment.rs @@ -4,7 +4,7 @@ use crate::solvers::BruteForceProblem as _; use crate::traits::Problem; use crate::types::Min; -/// Create a 4x4 test instance matching issue #300's example. +/// Create a 4x4 test instance. /// /// Cost matrix C (flows between 4 facilities): /// [[0, 5, 2, 0], @@ -106,7 +106,6 @@ fn test_quadratic_assignment_serialization() { let qap2: QuadraticAssignment = serde_json::from_str(&json).expect("deserialize"); assert_eq!(qap2.num_facilities(), 4); assert_eq!(qap2.num_locations(), 4); - // Verify functional equivalence after round-trip. assert_eq!( Problem::evaluate(&qap, &vec![0, 1, 2, 3]).unwrap(), Problem::evaluate(&qap2, &vec![0, 1, 2, 3]).unwrap() diff --git a/src/unit_tests/models/formula/non_tautology.rs b/src/unit_tests/models/formula/non_tautology.rs index f3c41161a..c38a4a480 100644 --- a/src/unit_tests/models/formula/non_tautology.rs +++ b/src/unit_tests/models/formula/non_tautology.rs @@ -41,11 +41,9 @@ fn test_non_tautology_solver() { let solution = solver.solve(&problem).unwrap(); assert!(solution.is_some()); - // Verify the found solution actually falsifies the formula let sol = solution.unwrap(); assert!(problem.evaluate(&sol).unwrap()); - // Check all witnesses are valid let all_solutions = solver.find_all_witnesses(&problem).unwrap(); assert!(!all_solutions.is_empty()); for sol in &all_solutions { diff --git a/src/unit_tests/models/formula/one_in_three_satisfiability.rs b/src/unit_tests/models/formula/one_in_three_satisfiability.rs index 601ee47bc..1c4a7b856 100644 --- a/src/unit_tests/models/formula/one_in_three_satisfiability.rs +++ b/src/unit_tests/models/formula/one_in_three_satisfiability.rs @@ -60,11 +60,9 @@ fn test_one_in_three_satisfiability_solver() { let solution = solver.solve(&problem).unwrap(); assert!(solution.is_some()); - // Verify the found solution actually satisfies 1-in-3 let sol = solution.unwrap(); assert!(problem.evaluate(&sol).unwrap()); - // Check all witnesses are valid let all_solutions = solver.find_all_witnesses(&problem).unwrap(); assert!(!all_solutions.is_empty()); for sol in &all_solutions { diff --git a/src/unit_tests/models/formula/planar_3_satisfiability.rs b/src/unit_tests/models/formula/planar_3_satisfiability.rs index 7ecbe2c52..bf7dd0bed 100644 --- a/src/unit_tests/models/formula/planar_3_satisfiability.rs +++ b/src/unit_tests/models/formula/planar_3_satisfiability.rs @@ -57,11 +57,9 @@ fn test_planar_3_satisfiability_solver() { let solution = solver.solve(&problem).unwrap(); assert!(solution.is_some()); - // Verify the found solution actually satisfies the formula let sol = solution.unwrap(); assert!(problem.evaluate(&sol).unwrap()); - // Check all witnesses are valid let all_solutions = solver.find_all_witnesses(&problem).unwrap(); assert!(!all_solutions.is_empty()); for sol in &all_solutions { diff --git a/src/unit_tests/models/formula/qbf.rs b/src/unit_tests/models/formula/qbf.rs index 32bee8687..27ca20a3f 100644 --- a/src/unit_tests/models/formula/qbf.rs +++ b/src/unit_tests/models/formula/qbf.rs @@ -46,7 +46,7 @@ fn test_qbf_evaluate_true() { vec![CNFClause::new(vec![1, 2]), CNFClause::new(vec![1, -2])], ); - // dims() is empty; evaluate([]) runs the game-tree search + // The unit witness delegates truth evaluation to the game-tree search. assert_eq!(problem.dimensions(), Vec::::new()); assert!(problem.evaluate(&()).unwrap()); assert!(problem.is_true()); @@ -152,7 +152,6 @@ fn test_qbf_solver() { ); let solver = BruteForce::new(); - // With dims()=[], there is exactly one config: []. evaluate([]) = is_true() = true let solution = solver.solve(&problem).unwrap(); assert!(solution.is_some()); solution.unwrap(); @@ -237,7 +236,6 @@ fn test_qbf_dims() { ], vec![CNFClause::new(vec![1, 2, 3, 4])], ); - // dims() is always empty — QBF has no external config variables assert_eq!(problem.dimensions(), Vec::::new()); } diff --git a/src/unit_tests/models/graph/biclique_cover.rs b/src/unit_tests/models/graph/biclique_cover.rs index ffcfb1f4a..15486d3da 100644 --- a/src/unit_tests/models/graph/biclique_cover.rs +++ b/src/unit_tests/models/graph/biclique_cover.rs @@ -153,7 +153,6 @@ fn test_evaluate() { Min(Some(2)) ); - // Invalid cover returns Invalid assert_eq!( problem .evaluate(&vec![vec![true, false, false, false]]) diff --git a/src/unit_tests/models/graph/bounded_diameter_spanning_tree.rs b/src/unit_tests/models/graph/bounded_diameter_spanning_tree.rs index 75663d77f..b5f7892e3 100644 --- a/src/unit_tests/models/graph/bounded_diameter_spanning_tree.rs +++ b/src/unit_tests/models/graph/bounded_diameter_spanning_tree.rs @@ -99,7 +99,6 @@ fn test_bounded_diameter_spanning_tree_evaluate_exceeds_weight() { #[test] fn test_bounded_diameter_spanning_tree_evaluate_exceeds_diameter() { - // Create instance with very tight diameter bound let problem = BoundedDiameterSpanningTree::new( SimpleGraph::new(4, vec![(0, 1), (1, 2), (2, 3)]), vec![1, 1, 1], diff --git a/src/unit_tests/models/graph/directed_hamiltonian_path.rs b/src/unit_tests/models/graph/directed_hamiltonian_path.rs index d00fa1c5f..2efc7e0e8 100644 --- a/src/unit_tests/models/graph/directed_hamiltonian_path.rs +++ b/src/unit_tests/models/graph/directed_hamiltonian_path.rs @@ -57,7 +57,6 @@ fn test_directed_hamiltonian_path_brute_force() { #[test] fn test_directed_hamiltonian_path_issue_example() { - // 6-vertex example from issue #813 // Arcs: [(0,1),(0,3),(1,3),(1,4),(2,0),(2,4),(3,2),(3,5),(4,5),(5,1)] // Hamiltonian path: [0, 1, 3, 2, 4, 5] let graph = DirectedGraph::new( diff --git a/src/unit_tests/models/graph/directed_two_commodity_integral_flow.rs b/src/unit_tests/models/graph/directed_two_commodity_integral_flow.rs index eaf0437a3..0f2cc68d1 100644 --- a/src/unit_tests/models/graph/directed_two_commodity_integral_flow.rs +++ b/src/unit_tests/models/graph/directed_two_commodity_integral_flow.rs @@ -183,11 +183,9 @@ fn test_directed_two_commodity_integral_flow_paper_example() { let problem = yes_instance(); let solver = BruteForce::new(); - // Verify the known solution evaluates to true let config = vec![1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1]; assert!(problem.evaluate(&config).unwrap()); - // Find all satisfying solutions and verify count let all_solutions = solver.find_all_witnesses(&problem).unwrap(); assert!(!all_solutions.is_empty()); diff --git a/src/unit_tests/models/graph/eulerian_path.rs b/src/unit_tests/models/graph/eulerian_path.rs index 2b6724a77..e207374df 100644 --- a/src/unit_tests/models/graph/eulerian_path.rs +++ b/src/unit_tests/models/graph/eulerian_path.rs @@ -5,7 +5,7 @@ use crate::topology::DirectedGraph; use crate::traits::Problem; use crate::types::Or; -/// Build the canonical YES instance from issue #1024. +/// Build the canonical YES instance. /// /// `V = {0, 1, 2}` and `A = [(0, 1), (0, 1), (1, 2), (2, 0)]`, with parallel /// arcs `a_0` and `a_1` between vertices `0` and `1`. The witness ordering diff --git a/src/unit_tests/models/graph/graph_partitioning.rs b/src/unit_tests/models/graph/graph_partitioning.rs index e29077c1a..cc4289b27 100644 --- a/src/unit_tests/models/graph/graph_partitioning.rs +++ b/src/unit_tests/models/graph/graph_partitioning.rs @@ -4,7 +4,7 @@ use crate::solvers::BruteForceProblem as _; use crate::topology::SimpleGraph; use crate::traits::Problem; -/// Issue example: 6 vertices, edges forming two triangles connected by 3 edges. +/// Example: 6 vertices, edges forming two triangles connected by 3 edges. /// Optimal partition A={0,1,2}, B={3,4,5}, cut=3. fn issue_example() -> GraphPartitioning { let graph = SimpleGraph::new( @@ -28,7 +28,6 @@ fn issue_example() -> GraphPartitioning { fn test_graphpartitioning_basic() { let problem = issue_example(); - // Check dims: 6 binary variables assert_eq!(problem.dimensions(), vec![2, 2, 2, 2, 2, 2]); // Evaluate a valid balanced partition: A={0,1,2}, B={3,4,5} @@ -47,7 +46,6 @@ fn test_graphpartitioning_serialization() { assert_eq!(deserialized.graph().num_vertices(), 6); assert_eq!(deserialized.graph().num_edges(), 9); - // Verify evaluation is consistent after round-trip let config = vec![false, false, false, true, true, true]; assert_eq!( problem.evaluate(&config).unwrap(), diff --git a/src/unit_tests/models/graph/hamiltonian_path.rs b/src/unit_tests/models/graph/hamiltonian_path.rs index c86819a08..ed8eba244 100644 --- a/src/unit_tests/models/graph/hamiltonian_path.rs +++ b/src/unit_tests/models/graph/hamiltonian_path.rs @@ -62,7 +62,6 @@ fn test_hamiltonian_path_brute_force() { fn test_hamiltonian_path_nontrivial() { use crate::traits::Problem; - // Instance 2 from issue: 6 vertices, 8 edges let problem = HamiltonianPath::new(SimpleGraph::new( 6, vec![ @@ -132,7 +131,7 @@ fn test_parameter_getters() { fn test_hamiltonianpath_paper_example() { use crate::traits::Problem; - // Paper/issue #217: 6 vertices, 8 edges + // Paper example: 6 vertices, 8 edges let problem = HamiltonianPath::new(SimpleGraph::new( 6, vec![ @@ -150,7 +149,6 @@ fn test_hamiltonianpath_paper_example() { // Hamiltonian path: 0→2→4→3→1→5 assert!(problem.evaluate(&vec![0, 2, 4, 3, 1, 5]).unwrap()); - // Verify with brute force let solver = BruteForce::new(); let all = solver.find_all_witnesses(&problem).unwrap(); assert!(!all.is_empty()); diff --git a/src/unit_tests/models/graph/hamiltonian_path_between_two_vertices.rs b/src/unit_tests/models/graph/hamiltonian_path_between_two_vertices.rs index 47b465f9e..788b2ff2b 100644 --- a/src/unit_tests/models/graph/hamiltonian_path_between_two_vertices.rs +++ b/src/unit_tests/models/graph/hamiltonian_path_between_two_vertices.rs @@ -57,7 +57,7 @@ fn test_hamiltonian_path_between_two_vertices_basic() { #[test] fn test_hamiltonian_path_between_two_vertices_no_solution() { - // C5 cycle: s=0, t=2 has no Hamiltonian s-t path (from issue #831) + // C5 cycle: s=0, t=2 has no Hamiltonian s-t path let problem = HamiltonianPathBetweenTwoVertices::new( SimpleGraph::new(5, vec![(0, 1), (1, 2), (2, 3), (3, 4), (4, 0)]), 0, @@ -75,7 +75,6 @@ fn test_hamiltonian_path_between_two_vertices_no_solution() { fn test_hamiltonian_path_between_two_vertices_brute_force() { use crate::traits::Problem; - // Issue #831 Example 1: 6 vertices, 8 edges, s=0, t=5 let problem = HamiltonianPathBetweenTwoVertices::new( SimpleGraph::new( 6, @@ -102,7 +101,6 @@ fn test_hamiltonian_path_between_two_vertices_brute_force() { assert_eq!(sol[0], 0, "Path must start at source vertex 0"); assert_eq!(sol[5], 5, "Path must end at target vertex 5"); - // Issue says there are exactly 4 distinct Hamiltonian s-t paths let all = solver.find_all_witnesses(&problem).unwrap(); assert_eq!(all.len(), 4); for path in &all { @@ -153,7 +151,6 @@ fn test_hamiltonian_path_between_two_vertices_serialization() { fn test_hamiltonian_path_between_two_vertices_paper_example() { use crate::traits::Problem; - // Instance from issue #831: 6 vertices, s=0, t=5 let problem = HamiltonianPathBetweenTwoVertices::new( SimpleGraph::new( 6, @@ -172,15 +169,12 @@ fn test_hamiltonian_path_between_two_vertices_paper_example() { 5, ); - // Issue-specified solution: 0 -> 3 -> 2 -> 1 -> 4 -> 5 assert!(problem.evaluate(&vec![0, 3, 2, 1, 4, 5]).unwrap()); - // Verify edge-by-edge let path = [0usize, 3, 2, 1, 4, 5]; assert_eq!(path[0], 0, "path starts at s=0"); assert_eq!(path[5], 5, "path ends at t=5"); - // Verify brute force confirms the problem let solver = BruteForce::new(); let all = solver.find_all_witnesses(&problem).unwrap(); assert_eq!(all.len(), 4, "issue says 4 Hamiltonian s-t paths exist"); diff --git a/src/unit_tests/models/graph/highly_connected_deletion.rs b/src/unit_tests/models/graph/highly_connected_deletion.rs index f0bffa6cb..9ba395311 100644 --- a/src/unit_tests/models/graph/highly_connected_deletion.rs +++ b/src/unit_tests/models/graph/highly_connected_deletion.rs @@ -5,7 +5,6 @@ use crate::topology::SimpleGraph; use crate::traits::Problem; use crate::types::Min; -// Canonical instance from the issue: // V = {0,1,2,3}, E = {(0,1),(0,2),(1,2),(2,3)} — triangle on {0,1,2} with leaf 3. fn canonical_problem() -> HighlyConnectedDeletion { HighlyConnectedDeletion::new(SimpleGraph::new(4, vec![(0, 1), (0, 2), (1, 2), (2, 3)])) @@ -129,7 +128,6 @@ fn test_highly_connected_deletion_brute_force_double_triangle() { Min(Some(1)) ); - // Verify the named optimal config evaluates to 1. let bridge_only = vec![false, false, false, true, false, false, false]; assert_eq!(problem.evaluate(&bridge_only).unwrap(), Min(Some(1))); diff --git a/src/unit_tests/models/graph/isomorphic_spanning_tree.rs b/src/unit_tests/models/graph/isomorphic_spanning_tree.rs index 3f7f244c5..b8948d1cd 100644 --- a/src/unit_tests/models/graph/isomorphic_spanning_tree.rs +++ b/src/unit_tests/models/graph/isomorphic_spanning_tree.rs @@ -43,12 +43,6 @@ fn test_isomorphicspanningtree_evaluation_yes() { #[test] fn test_isomorphicspanningtree_evaluation_no() { - // Host graph: path 0-1-2 (no edge 0-2) - // Tree: star with center 1: edges (0,1), (1,2) -- this is also a path, same structure - // Actually let's make a case where it fails: - // Host graph: 0-1, 2-3 (disconnected, 2 components) - // But wait, the tree must span, so let's use a connected graph where the tree doesn't fit. - // Host graph: path 0-1-2-3 (edges: 0-1, 1-2, 2-3) // Tree: star K_{1,3} center=0, leaves=1,2,3 (edges: 0-1, 0-2, 0-3) // No vertex in graph has degree 3, so no valid mapping exists @@ -135,7 +129,6 @@ fn test_isomorphicspanningtree_serialization() { #[test] fn test_isomorphicspanningtree_caterpillar_example() { - // Example from the issue: 7-vertex graph with caterpillar tree let graph = SimpleGraph::new( 7, vec![ @@ -158,7 +151,6 @@ fn test_isomorphicspanningtree_caterpillar_example() { let tree = SimpleGraph::new(7, vec![(0, 1), (1, 2), (2, 3), (3, 4), (1, 5), (2, 6)]); let problem = IsomorphicSpanningTree::new(graph, tree); - // The issue gives solution: a→0, b→1, c→2, d→3, e→6, f→4, g→5 // As config: π = [0, 1, 2, 3, 6, 4, 5] assert!(problem.evaluate(&vec![0, 1, 2, 3, 6, 4, 5]).unwrap()); } diff --git a/src/unit_tests/models/graph/kernel.rs b/src/unit_tests/models/graph/kernel.rs index 3e4ed36f7..f2f404150 100644 --- a/src/unit_tests/models/graph/kernel.rs +++ b/src/unit_tests/models/graph/kernel.rs @@ -54,7 +54,6 @@ fn test_kernel_evaluate_not_independent() { #[test] fn test_kernel_evaluate_not_absorbing() { // Select only vertex 0: vertex 1 has no arc to 0 (only 0->1 exists), so not absorbing - // Actually, let's check: successors of 1 = {3}, and 3 is not selected // successors of 2 = {3}, not selected // successors of 3 = {4}, not selected // successors of 4 = {0, 1}, 0 is selected → ok for 4 @@ -92,7 +91,6 @@ fn test_kernel_no_solution() { // A directed 3-cycle has no kernel: // 0->1, 1->2, 2->0 // Any single vertex is not absorbing (e.g., {0}: vertex 2 has successor 0, ok; vertex 1 has successor 2, not selected → fail) - // Wait, let's verify: {0}: successors of 1 = {2}, not selected. Not absorbing. // {0,1}: arc (0,1) exists. Not independent. // No kernel exists for odd cycles. let graph = DirectedGraph::new(3, vec![(0, 1), (1, 2), (2, 0)]); diff --git a/src/unit_tests/models/graph/maximal_is.rs b/src/unit_tests/models/graph/maximal_is.rs index b169294e8..0461b31e9 100644 --- a/src/unit_tests/models/graph/maximal_is.rs +++ b/src/unit_tests/models/graph/maximal_is.rs @@ -223,7 +223,6 @@ fn test_maximal_is_paper_example() { assert!(result2.is_valid()); assert_eq!(result2.unwrap(), 3); - // Verify optimal weight is 3 let solver = BruteForce::new(); let best = solver.solve(&problem).unwrap().unwrap(); assert_eq!(problem.evaluate(&best).unwrap().unwrap(), 3); diff --git a/src/unit_tests/models/graph/maximum_clique.rs b/src/unit_tests/models/graph/maximum_clique.rs index 7ccd21ffd..f88a92d5b 100644 --- a/src/unit_tests/models/graph/maximum_clique.rs +++ b/src/unit_tests/models/graph/maximum_clique.rs @@ -95,7 +95,7 @@ fn test_evaluate_invalid() { // Path graph: 0-1-2 (no edge between 0 and 2) let problem = MaximumClique::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![1i64; 3]); - // Invalid: 0 and 2 are not adjacent - returns Invalid + // Vertices 0 and 2 are not adjacent. assert_eq!( problem.evaluate(&vec![true, false, true]).unwrap(), Max(None) @@ -169,7 +169,6 @@ fn test_brute_force_path() { for sol in &solutions { let size: usize = sol.iter().filter(|&&selected| selected).count(); assert_eq!(size, 2); - // Verify it's valid assert!(problem.evaluate(sol).unwrap().is_valid()); } } @@ -240,7 +239,6 @@ fn test_is_clique_method() { let problem = MaximumClique::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![1i64; 3]); - // Valid clique - returns Valid assert!(problem .evaluate(&vec![true, true, false]) .unwrap() @@ -249,7 +247,6 @@ fn test_is_clique_method() { .evaluate(&vec![false, true, true]) .unwrap() .is_valid()); - // Invalid: 0-2 not adjacent - returns Invalid assert_eq!( problem.evaluate(&vec![true, false, true]).unwrap(), Max(None) diff --git a/src/unit_tests/models/graph/maximum_co_k_plex.rs b/src/unit_tests/models/graph/maximum_co_k_plex.rs index ac610314a..26adfefc4 100644 --- a/src/unit_tests/models/graph/maximum_co_k_plex.rs +++ b/src/unit_tests/models/graph/maximum_co_k_plex.rs @@ -84,7 +84,7 @@ fn test_maximum_co_k_plex_creation() { fn test_maximum_co_k_plex_evaluate_feasible() { let problem = issue_instance(); - // Optimum from the issue: x = (1,0,1,0,1), S = {0,2,4}. + // Optimum: x = (1,0,1,0,1), S = {0,2,4}. // Induced subgraph has only the edge (4,0); induced degrees (1,0,1) all <= 1. assert_eq!( problem diff --git a/src/unit_tests/models/graph/maximum_common_edge_subgraph.rs b/src/unit_tests/models/graph/maximum_common_edge_subgraph.rs index c3e7f7d7f..68e6b853a 100644 --- a/src/unit_tests/models/graph/maximum_common_edge_subgraph.rs +++ b/src/unit_tests/models/graph/maximum_common_edge_subgraph.rs @@ -66,7 +66,7 @@ fn test_maximum_common_edge_subgraph_creation() { fn test_maximum_common_edge_subgraph_evaluate_optimum() { let problem = issue_instance(); - // Issue optimum: x = (0, 1, 2, 3, 4) with 4 = bottom (|V2| = 4). + // Optimum: x = (0, 1, 2, 3, 4) with 4 = bottom (|V2| = 4). // Preserved arcs: (0,a,1), (1,b,2), (0,c,2), (2,a,3), (1,d,3); the last // source arc (3,b,4) is skipped because vertex 4 is unmatched. assert!(problem.is_valid_solution(&[0, 1, 2, 3, 4])); diff --git a/src/unit_tests/models/graph/maximum_contact_map_overlap.rs b/src/unit_tests/models/graph/maximum_contact_map_overlap.rs index bab3dc7be..b55bd9a12 100644 --- a/src/unit_tests/models/graph/maximum_contact_map_overlap.rs +++ b/src/unit_tests/models/graph/maximum_contact_map_overlap.rs @@ -31,7 +31,6 @@ use crate::traits::Problem; use crate::types::Max; fn issue_instance() -> MaximumContactMapOverlap { - // Canonical example from the issue: // G_1: n_1 = 4, E_1 = {{0,2}, {1,3}} // G_2: n_2 = 5, E_2 = {{0,3}, {1,4}, {0,2}} MaximumContactMapOverlap::new(4, vec![(0, 2), (1, 3)], 5, vec![(0, 3), (1, 4), (0, 2)]) diff --git a/src/unit_tests/models/graph/maximum_domatic_number.rs b/src/unit_tests/models/graph/maximum_domatic_number.rs index f922d8cea..c80918662 100644 --- a/src/unit_tests/models/graph/maximum_domatic_number.rs +++ b/src/unit_tests/models/graph/maximum_domatic_number.rs @@ -17,7 +17,6 @@ fn test_maximum_domatic_number_creation() { #[test] fn test_maximum_domatic_number_evaluate_optimal() { - // Graph from issue: 6 vertices // Edges: (0,1), (0,2), (0,3), (1,4), (2,5), (3,4), (3,5), (4,5) // Config: [0, 1, 2, 0, 2, 1] → 3 non-empty dominating sets → Max(3) let graph = SimpleGraph::new( diff --git a/src/unit_tests/models/graph/maximum_edge_weighted_k_clique.rs b/src/unit_tests/models/graph/maximum_edge_weighted_k_clique.rs index 1db45c2fa..c34cc69c8 100644 --- a/src/unit_tests/models/graph/maximum_edge_weighted_k_clique.rs +++ b/src/unit_tests/models/graph/maximum_edge_weighted_k_clique.rs @@ -16,7 +16,7 @@ use crate::topology::SimpleGraph; use crate::traits::Problem; use crate::types::Max; -/// Canonical instance from issue #1020: 4 vertices, edges +/// Canonical instance: 4 vertices, edges /// {(0,1), (0,2), (1,2), (0,3), (1,3)} with weights [5, 4, -1, 1, 0] /// and k = 3. Triangles are {0,1,2} (value 8) and {0,1,3} (value 6). fn issue_instance() -> MaximumEdgeWeightedKClique { @@ -45,7 +45,7 @@ fn test_maximum_edge_weighted_k_clique_creation() { fn test_maximum_edge_weighted_k_clique_evaluate_feasible() { let problem = issue_instance(); - // Optimum from the issue: S = {0,1,2}, value 5 + 4 + (-1) = 8. + // Optimum: S = {0,1,2}, value 5 + 4 + (-1) = 8. assert_eq!( problem.evaluate(&vec![true, true, true, false]).unwrap(), Max(Some(8)) diff --git a/src/unit_tests/models/graph/maximum_independent_set.rs b/src/unit_tests/models/graph/maximum_independent_set.rs index 201b413e3..be88f10c0 100644 --- a/src/unit_tests/models/graph/maximum_independent_set.rs +++ b/src/unit_tests/models/graph/maximum_independent_set.rs @@ -262,7 +262,6 @@ fn test_mis_paper_example() { assert!(result.is_valid()); assert_eq!(result.unwrap(), 4); - // Verify this is optimal let solver = BruteForce::new(); let best = solver.solve(&problem).unwrap().unwrap(); assert_eq!(problem.evaluate(&best).unwrap().unwrap(), 4); diff --git a/src/unit_tests/models/graph/maximum_leaf_spanning_tree.rs b/src/unit_tests/models/graph/maximum_leaf_spanning_tree.rs index 7915e434a..e814941bf 100644 --- a/src/unit_tests/models/graph/maximum_leaf_spanning_tree.rs +++ b/src/unit_tests/models/graph/maximum_leaf_spanning_tree.rs @@ -19,7 +19,7 @@ use super::*; use crate::solvers::BruteForceProblem as _; use crate::{solvers::BruteForce, topology::SimpleGraph, traits::Problem}; -/// Issue #897 example: 6 vertices, 9 edges. +/// Example: 6 vertices, 9 edges. /// Edges: (0,1),(0,2),(0,3),(1,4),(2,4),(2,5),(3,5),(4,5),(1,3) fn example_instance() -> MaximumLeafSpanningTree { let graph = SimpleGraph::new( @@ -70,7 +70,6 @@ fn test_maximum_leaf_spanning_tree_evaluate_optimal() { fn test_maximum_leaf_spanning_tree_evaluate_valid_suboptimal() { let problem = example_instance(); // A path tree: (0,1),(1,3),(0,2),(2,4),(4,5) = indices 0,8,1,4,7 - // Wait, edge 8 is (1,3). So: indices 0,1,4,7,8 = [1,1,0,0,1,0,0,1,1] // Degrees: 0->2, 1->2, 2->2, 3->1, 4->2, 5->1 => 2 leaves let config = vec![true, true, false, false, true, false, false, true, true]; assert_eq!(problem.evaluate(&config).unwrap(), Max(Some(2))); diff --git a/src/unit_tests/models/graph/minimum_capacitated_spanning_tree.rs b/src/unit_tests/models/graph/minimum_capacitated_spanning_tree.rs index 9dec7081b..84cb65671 100644 --- a/src/unit_tests/models/graph/minimum_capacitated_spanning_tree.rs +++ b/src/unit_tests/models/graph/minimum_capacitated_spanning_tree.rs @@ -41,7 +41,7 @@ fn create_spec_defaults_edge_weights() { } use crate::{solvers::BruteForce, topology::SimpleGraph, traits::Problem}; -/// 5-vertex instance from issue #901. +/// 5-vertex instance. /// Edges: (0,1,2), (0,2,1), (0,3,4), (1,2,3), (1,4,1), (2,3,2), (2,4,3), (3,4,1) /// Root=0, capacity=3, all requirements=1 fn example_instance() -> MinimumCapacitatedSpanningTree { diff --git a/src/unit_tests/models/graph/minimum_cost_circulation.rs b/src/unit_tests/models/graph/minimum_cost_circulation.rs index 7505080c6..2a79b627f 100644 --- a/src/unit_tests/models/graph/minimum_cost_circulation.rs +++ b/src/unit_tests/models/graph/minimum_cost_circulation.rs @@ -163,7 +163,6 @@ fn test_minimum_cost_circulation_negative_cycle_beats_zero() { #[test] fn test_minimum_cost_circulation_issue_example_1030() { - // Verbatim instance from issue #1030: vertices {0,1}, arcs // 0->1 cap=2 cost= 3 // 1->0 cap=1 cost=-5 // Bottleneck is the back-arc (cap=1), so the optimum sends one unit diff --git a/src/unit_tests/models/graph/minimum_cost_maximum_flow.rs b/src/unit_tests/models/graph/minimum_cost_maximum_flow.rs index 5c56ee644..f5c1c4fb2 100644 --- a/src/unit_tests/models/graph/minimum_cost_maximum_flow.rs +++ b/src/unit_tests/models/graph/minimum_cost_maximum_flow.rs @@ -5,7 +5,7 @@ use crate::topology::DirectedGraph; use crate::traits::Problem; use crate::types::Min; -/// Canonical 4-vertex diamond instance from issue #1029. +/// Canonical 4-vertex diamond instance. /// /// Arcs (capacity, cost): /// - (0,1): cap=2, cost=1 diff --git a/src/unit_tests/models/graph/minimum_cut_into_bounded_sets.rs b/src/unit_tests/models/graph/minimum_cut_into_bounded_sets.rs index d493c4774..b92f95f79 100644 --- a/src/unit_tests/models/graph/minimum_cut_into_bounded_sets.rs +++ b/src/unit_tests/models/graph/minimum_cut_into_bounded_sets.rs @@ -43,7 +43,7 @@ use crate::topology::SimpleGraph; use crate::traits::Problem; use crate::types::{Min, SolutionAggregate}; -/// Build the example instance from issue #228: +/// Build the example instance: /// 8 vertices, 12 edges, s=0, t=7, B=5 fn example_instance() -> MinimumCutIntoBoundedSets { let graph = SimpleGraph::new( diff --git a/src/unit_tests/models/graph/minimum_dominating_set.rs b/src/unit_tests/models/graph/minimum_dominating_set.rs index 49dccf178..2bef1ac74 100644 --- a/src/unit_tests/models/graph/minimum_dominating_set.rs +++ b/src/unit_tests/models/graph/minimum_dominating_set.rs @@ -101,7 +101,6 @@ fn test_isolated_vertex() { // Vertex 2 is isolated, must be selected for sol in &solutions { assert!(sol[2]); - // Verify it's a valid dominating set assert!(Problem::evaluate(&problem, sol).unwrap().is_valid()); } } diff --git a/src/unit_tests/models/graph/minimum_edge_cost_flow.rs b/src/unit_tests/models/graph/minimum_edge_cost_flow.rs index aafd189eb..f6626b35f 100644 --- a/src/unit_tests/models/graph/minimum_edge_cost_flow.rs +++ b/src/unit_tests/models/graph/minimum_edge_cost_flow.rs @@ -25,7 +25,7 @@ use crate::topology::DirectedGraph; use crate::traits::Problem; use crate::types::Min; -/// 5-vertex network from issue #810. +/// 5-vertex network. /// s=0, t=4, R=3. Prices: [3,1,2,0,0,0], capacities all 2. /// Arcs: (0,1),(0,2),(0,3),(1,4),(2,4),(3,4) /// Optimal: route via v2 (1 unit) and v3 (2 units) → cost = 1 + 2 = 3 diff --git a/src/unit_tests/models/graph/minimum_feedback_arc_set.rs b/src/unit_tests/models/graph/minimum_feedback_arc_set.rs index 06786be07..270fc5e56 100644 --- a/src/unit_tests/models/graph/minimum_feedback_arc_set.rs +++ b/src/unit_tests/models/graph/minimum_feedback_arc_set.rs @@ -32,7 +32,6 @@ use crate::traits::Problem; #[test] fn test_minimum_feedback_arc_set_creation() { - // 6 vertices, 9 arcs (example from issue) let graph = DirectedGraph::new( 6, vec![ @@ -121,7 +120,6 @@ fn test_minimum_feedback_arc_set_solver_simple_cycle() { #[test] fn test_minimum_feedback_arc_set_solver_issue_example() { - // Example from issue #213: 6 vertices, 9 arcs let graph = DirectedGraph::new( 6, vec![ @@ -143,7 +141,6 @@ fn test_minimum_feedback_arc_set_solver_issue_example() { let fas_size: usize = solution.iter().filter(|&&selected| selected).count(); assert_eq!(fas_size, 2); - // Verify the solution is valid assert!(problem.is_valid_solution(&solution)); } diff --git a/src/unit_tests/models/graph/minimum_feedback_vertex_set.rs b/src/unit_tests/models/graph/minimum_feedback_vertex_set.rs index fad4b0297..f3e07a247 100644 --- a/src/unit_tests/models/graph/minimum_feedback_vertex_set.rs +++ b/src/unit_tests/models/graph/minimum_feedback_vertex_set.rs @@ -31,7 +31,6 @@ use crate::solvers::BruteForce; use crate::topology::DirectedGraph; use crate::traits::Problem; -/// Build the 9-vertex, 15-arc example from the issue. /// /// Three triangles: 0→1→2→0, 3→4→5→3, 6→7→8→6 /// Cross arcs set 1: 1→3, 4→6, 7→0 @@ -173,7 +172,6 @@ fn test_minimum_feedback_vertex_set_evaluate_wrong_length() { let graph = DirectedGraph::new(3, vec![(0, 1), (1, 2), (2, 0)]); let problem = MinimumFeedbackVertexSet::new(graph, vec![1i64; 3]); - // Wrong length config returns Invalid assert!(matches!( problem.evaluate(&vec![true, false]), Err(crate::traits::EvaluationError::InvalidConfiguration(_)) @@ -228,7 +226,6 @@ fn test_minimum_feedback_vertex_set_paper_example() { let config_v1 = vec![false, true, false, false, false]; assert!(!problem.evaluate(&config_v1).unwrap().is_valid()); - // Verify optimal FVS weight is 1 let solver = BruteForce::new(); let best = solver.solve(&problem).unwrap().unwrap(); assert_eq!(problem.evaluate(&best).unwrap().unwrap(), 1); diff --git a/src/unit_tests/models/graph/minimum_geometric_connected_dominating_set.rs b/src/unit_tests/models/graph/minimum_geometric_connected_dominating_set.rs index a5a1c6535..2de17dbce 100644 --- a/src/unit_tests/models/graph/minimum_geometric_connected_dominating_set.rs +++ b/src/unit_tests/models/graph/minimum_geometric_connected_dominating_set.rs @@ -114,7 +114,6 @@ fn test_ladder_example() { assert!(result.is_valid()); assert_eq!(result.unwrap(), 4); - // Verify with brute force let solver = BruteForce::new(); let witness = solver.solve(&problem).unwrap().unwrap(); let best_value = problem.evaluate(&witness).unwrap().unwrap(); diff --git a/src/unit_tests/models/graph/minimum_graph_bandwidth.rs b/src/unit_tests/models/graph/minimum_graph_bandwidth.rs index bdfa58ec7..2fcab8248 100644 --- a/src/unit_tests/models/graph/minimum_graph_bandwidth.rs +++ b/src/unit_tests/models/graph/minimum_graph_bandwidth.rs @@ -94,7 +94,6 @@ fn test_minimumgraphbandwidth_serialization() { assert_eq!(deserialized.graph().num_vertices(), 4); assert_eq!(deserialized.graph().num_edges(), 3); - // Verify evaluation is consistent after round-trip let config = vec![1, 0, 2, 3]; assert_eq!( problem.evaluate(&config).unwrap(), @@ -131,8 +130,7 @@ fn test_minimumgraphbandwidth_empty_graph() { #[test] fn test_minimumgraphbandwidth_complete_graph_k4() { - // K4: bandwidth is always 3 (max position difference in any permutation) - // Actually for K4, bandwidth = n-1 = 3 for any arrangement since edge (first, last) exists. + // K4 connects the first and last vertices in every arrangement, forcing bandwidth 3. let graph = SimpleGraph::new(4, vec![(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]); let problem = MinimumGraphBandwidth::new(graph); diff --git a/src/unit_tests/models/graph/minimum_metric_dimension.rs b/src/unit_tests/models/graph/minimum_metric_dimension.rs index 6e4764d1f..7fd50184b 100644 --- a/src/unit_tests/models/graph/minimum_metric_dimension.rs +++ b/src/unit_tests/models/graph/minimum_metric_dimension.rs @@ -104,7 +104,6 @@ fn test_minimum_metric_dimension_serialization() { assert_eq!(deserialized.num_vertices(), 3); assert_eq!(deserialized.num_edges(), 2); - // Verify evaluation is preserved let config = vec![true, false, false]; assert_eq!( problem.evaluate(&config).unwrap(), diff --git a/src/unit_tests/models/graph/minimum_multiway_cut.rs b/src/unit_tests/models/graph/minimum_multiway_cut.rs index 110e70296..07b96f256 100644 --- a/src/unit_tests/models/graph/minimum_multiway_cut.rs +++ b/src/unit_tests/models/graph/minimum_multiway_cut.rs @@ -28,7 +28,6 @@ fn test_minimummultiwaycut_creation() { #[test] fn test_minimummultiwaycut_evaluate_valid() { - // Issue example: 5 vertices, terminals {0,2,4} // Edges: (0,1)w=2, (1,2)w=3, (2,3)w=1, (3,4)w=2, (0,4)w=4, (1,3)w=5 let graph = SimpleGraph::new(5, vec![(0, 1), (1, 2), (2, 3), (3, 4), (0, 4), (1, 3)]); let problem = MinimumMultiwayCut::new(graph, vec![0, 2, 4], vec![2, 3, 1, 2, 4, 5]); @@ -53,7 +52,6 @@ fn test_minimummultiwaycut_evaluate_invalid() { #[test] fn test_minimummultiwaycut_brute_force() { - // Issue example: optimal cut has weight 8 let graph = SimpleGraph::new(5, vec![(0, 1), (1, 2), (2, 3), (3, 4), (0, 4), (1, 3)]); let problem = MinimumMultiwayCut::new(graph, vec![0, 2, 4], vec![2, 3, 1, 2, 4, 5]); diff --git a/src/unit_tests/models/graph/minimum_sum_multicenter.rs b/src/unit_tests/models/graph/minimum_sum_multicenter.rs index 22e24a296..bbeee4061 100644 --- a/src/unit_tests/models/graph/minimum_sum_multicenter.rs +++ b/src/unit_tests/models/graph/minimum_sum_multicenter.rs @@ -170,7 +170,6 @@ fn test_min_sum_multicenter_two_centers() { #[test] fn test_min_sum_multicenter_solver() { - // Issue example: 7 vertices, 8 edges, unit weights, K=2 let graph = SimpleGraph::new( 7, vec![ @@ -261,7 +260,7 @@ fn test_min_sum_multicenter_k_too_large() { #[test] fn test_min_sum_multicenter_paper_example() { - // Paper/issue #399: 7 vertices, 8 edges, unit weights, K=2 + // Paper example: 7 vertices, 8 edges, unit weights, K=2 let graph = SimpleGraph::new( 7, vec![ @@ -286,7 +285,6 @@ fn test_min_sum_multicenter_paper_example() { assert!(result.is_valid()); assert_eq!(result.unwrap(), 6); - // Verify optimality with brute force let solver = BruteForce::new(); let best = solver.solve(&problem).unwrap().unwrap(); assert_eq!(problem.evaluate(&best).unwrap().unwrap(), 6); diff --git a/src/unit_tests/models/graph/optimal_linear_arrangement.rs b/src/unit_tests/models/graph/optimal_linear_arrangement.rs index cd433e63d..983280546 100644 --- a/src/unit_tests/models/graph/optimal_linear_arrangement.rs +++ b/src/unit_tests/models/graph/optimal_linear_arrangement.rs @@ -5,7 +5,6 @@ use crate::topology::SimpleGraph; use crate::traits::Problem; use crate::types::Min; -/// Issue example: 6 vertices, 7 edges fn issue_example() -> OptimalLinearArrangement { let graph = SimpleGraph::new( 6, @@ -84,7 +83,6 @@ fn test_optimallineararrangement_serialization() { assert_eq!(deserialized.graph().num_vertices(), 6); assert_eq!(deserialized.graph().num_edges(), 7); - // Verify evaluation is consistent after round-trip let config = vec![0, 1, 2, 3, 4, 5]; assert_eq!( problem.evaluate(&config).unwrap(), diff --git a/src/unit_tests/models/graph/partition_into_paths_of_length_2.rs b/src/unit_tests/models/graph/partition_into_paths_of_length_2.rs index ef6ea5573..2788231e5 100644 --- a/src/unit_tests/models/graph/partition_into_paths_of_length_2.rs +++ b/src/unit_tests/models/graph/partition_into_paths_of_length_2.rs @@ -135,7 +135,6 @@ fn test_partition_into_paths_serialization() { assert_eq!(deserialized.num_edges(), 4); assert_eq!(deserialized.num_groups(), 2); - // Verify evaluation is consistent let config = vec![0, 0, 0, 1, 1, 1]; assert_eq!( problem.evaluate(&config).unwrap(), diff --git a/src/unit_tests/models/graph/prize_collecting_steiner_forest.rs b/src/unit_tests/models/graph/prize_collecting_steiner_forest.rs index a141e5241..a66c20d90 100644 --- a/src/unit_tests/models/graph/prize_collecting_steiner_forest.rs +++ b/src/unit_tests/models/graph/prize_collecting_steiner_forest.rs @@ -5,7 +5,7 @@ use crate::topology::SimpleGraph; use crate::traits::Problem; use crate::types::Min; -/// Canonical instance from issue #1026: path 0 - 1 - 2 with +/// Canonical instance: path 0 - 1 - 2 with /// edge costs c(0,1)=1, c(1,2)=6, vertex prizes p = (5, 2, 5), /// beta = 1, omega = 2. fn canonical_problem() -> PrizeCollectingSteinerForest { diff --git a/src/unit_tests/models/graph/rural_postman.rs b/src/unit_tests/models/graph/rural_postman.rs index c657749be..4f7b0eb23 100644 --- a/src/unit_tests/models/graph/rural_postman.rs +++ b/src/unit_tests/models/graph/rural_postman.rs @@ -25,7 +25,7 @@ use crate::topology::SimpleGraph; use crate::traits::Problem; use crate::types::Min; -/// Instance 1 from issue: hexagonal graph with 3 required edges +/// Instance: hexagonal graph with 3 required edges fn hexagon_rpp() -> RuralPostman { // 6 vertices, 8 edges // Edges: {0,1}:1, {1,2}:1, {2,3}:1, {3,4}:1, {4,5}:1, {5,0}:1, {0,3}:2, {1,4}:2 @@ -48,7 +48,7 @@ fn hexagon_rpp() -> RuralPostman { RuralPostman::new(graph, edge_lengths, required_edges) } -/// Instance 3 from issue: C4 cycle, all edges required (Chinese Postman) +/// Instance: C4 cycle, all edges required (Chinese Postman) fn chinese_postman_rpp() -> RuralPostman { let graph = SimpleGraph::new(4, vec![(0, 1), (1, 2), (2, 3), (3, 0)]); let edge_lengths = vec![1, 1, 1, 1]; @@ -153,7 +153,6 @@ fn test_rural_postman_brute_force_hexagon() { #[test] fn test_rural_postman_find_all_witnesses() { - // Issue #248 instance 1: hexagonal graph, 6 vertices, 8 edges // Required edges E'={{0,1},{2,3},{4,5}} // Search space = 3^8 = 6561 let problem = hexagon_rpp(); @@ -162,7 +161,7 @@ fn test_rural_postman_find_all_witnesses() { for sol in &solutions { assert!(problem.evaluate(sol).unwrap().0.is_some()); } - // The issue witness (hexagon cycle, all multiplicity 1) must be among solutions + // The hexagon cycle with all multiplicities 1 must be among solutions assert!(solutions.contains(&vec![1, 1, 1, 1, 1, 1, 0, 0])); // Only the hexagon cycle (cost 6) is optimal; diagonals cost 2 each assert_eq!(solutions.len(), 1); diff --git a/src/unit_tests/models/graph/spin_glass.rs b/src/unit_tests/models/graph/spin_glass.rs index 27cc19d84..1adb5d778 100644 --- a/src/unit_tests/models/graph/spin_glass.rs +++ b/src/unit_tests/models/graph/spin_glass.rs @@ -194,7 +194,6 @@ fn test_spinglass_paper_example() { assert!(result.is_valid()); assert_eq!(result.unwrap(), -3); - // Verify this is optimal let all_best = BruteForce::new().find_all_witnesses(&problem).unwrap(); assert!(!all_best.is_empty()); assert_eq!(problem.evaluate(&all_best[0]).unwrap().unwrap(), -3); diff --git a/src/unit_tests/models/graph/steiner_tree.rs b/src/unit_tests/models/graph/steiner_tree.rs index f0f8e3d82..450d1d4ba 100644 --- a/src/unit_tests/models/graph/steiner_tree.rs +++ b/src/unit_tests/models/graph/steiner_tree.rs @@ -42,7 +42,7 @@ fn create_spec_rejects_duplicate_terminals() { } use crate::{solvers::BruteForce, topology::SimpleGraph, traits::Problem}; -/// Issue #122 example: 5 vertices, 7 edges, terminals {0, 2, 4}. +/// Example: 5 vertices, 7 edges, terminals {0, 2, 4}. /// Edges in order: (0,1)=2, (0,3)=5, (1,2)=2, (1,3)=1, (2,3)=5, (2,4)=6, (3,4)=1 fn example_instance() -> SteinerTree { let graph = SimpleGraph::new( diff --git a/src/unit_tests/models/graph/subgraph_isomorphism.rs b/src/unit_tests/models/graph/subgraph_isomorphism.rs index bde097812..7df7689c5 100644 --- a/src/unit_tests/models/graph/subgraph_isomorphism.rs +++ b/src/unit_tests/models/graph/subgraph_isomorphism.rs @@ -163,7 +163,6 @@ fn test_subgraph_isomorphism_empty_pattern() { #[test] fn test_subgraph_isomorphism_issue_example() { - // Example from issue #218 // Host: K4 on {0,1,2,3} plus triangle {4,5,6} connected via 3-4 let host = SimpleGraph::new( 7, @@ -184,10 +183,8 @@ fn test_subgraph_isomorphism_issue_example() { let pattern = SimpleGraph::new(4, vec![(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]); let problem = SubgraphIsomorphism::new(host, pattern); - // The mapping from the issue: a->0, b->1, c->2, d->3 assert!(problem.evaluate(&vec![0, 1, 2, 3]).unwrap()); - // Verify solver can find a solution let solver = BruteForce::new(); let solution = solver.solve(&problem).unwrap(); assert!(solution.is_some()); diff --git a/src/unit_tests/models/graph/traveling_salesman.rs b/src/unit_tests/models/graph/traveling_salesman.rs index 4613b9a0d..58a1289e2 100644 --- a/src/unit_tests/models/graph/traveling_salesman.rs +++ b/src/unit_tests/models/graph/traveling_salesman.rs @@ -116,7 +116,6 @@ fn test_evaluate_no_edges_selected() { #[test] fn test_brute_force_k4() { - // Instance 1 from issue: K4 with weights let problem = k4_tsp(); let solver = BruteForce::new(); let solutions = solver.find_all_witnesses(&problem).unwrap(); @@ -129,7 +128,6 @@ fn test_brute_force_k4() { #[test] fn test_brute_force_path_graph_no_solution() { - // Instance 2 from issue: path graph, no Hamiltonian cycle exists let problem = TravelingSalesman::<_, i64>::unit_weights(SimpleGraph::new( 4, vec![(0, 1), (1, 2), (2, 3)], @@ -141,7 +139,6 @@ fn test_brute_force_path_graph_no_solution() { #[test] fn test_brute_force_c5_unique_solution() { - // Instance 3 from issue: C5 cycle graph, unique Hamiltonian cycle let problem = TravelingSalesman::<_, i64>::unit_weights(SimpleGraph::new( 5, vec![(0, 1), (1, 2), (2, 3), (3, 4), (4, 0)], @@ -155,7 +152,6 @@ fn test_brute_force_c5_unique_solution() { #[test] fn test_brute_force_bipartite_no_solution() { - // Instance 4 from issue: K_{2,3} bipartite, no Hamiltonian cycle let problem = TravelingSalesman::<_, i64>::unit_weights(SimpleGraph::new( 5, vec![(0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4)], diff --git a/src/unit_tests/models/misc/boyce_codd_normal_form_violation.rs b/src/unit_tests/models/misc/boyce_codd_normal_form_violation.rs index 4b7c53120..846227618 100644 --- a/src/unit_tests/models/misc/boyce_codd_normal_form_violation.rs +++ b/src/unit_tests/models/misc/boyce_codd_normal_form_violation.rs @@ -231,7 +231,7 @@ fn test_bcnf_fds_outside_target_subset() { #[test] fn test_bcnf_cyclic_keys_no_violation() { - // Issue example: 4 attributes, cyclic keys — every non-trivial subset is a superkey. + // Cyclic keys make every subset containing a key pair a superkey. // FDs: {0,1}→{2,3}, {2,3}→{0,1}, {0,2}→{1,3}, {1,3}→{0,2}. // All 2-element subsets containing a key pair have full closure → no BCNF violation. let problem = BoyceCoddNormalFormViolation::new( diff --git a/src/unit_tests/models/misc/clustering.rs b/src/unit_tests/models/misc/clustering.rs index fa469457e..e4203484e 100644 --- a/src/unit_tests/models/misc/clustering.rs +++ b/src/unit_tests/models/misc/clustering.rs @@ -25,7 +25,6 @@ fn test_clustering_validates_persisted_input() { } } -/// Helper: build the 6-element two-group instance from the issue. fn two_group_instance() -> Clustering { let distances = vec![ vec![0, 1, 1, 3, 3, 3], @@ -183,7 +182,6 @@ fn test_clustering_paper_example() { let result = problem.evaluate(&config).unwrap(); assert!(result.0); - // Verify this is satisfiable let solver = BruteForce::new(); let witness = solver.solve(&problem).unwrap(); assert!(witness.is_some()); diff --git a/src/unit_tests/models/misc/conjunctive_boolean_query.rs b/src/unit_tests/models/misc/conjunctive_boolean_query.rs index 3645dda91..40c36f16a 100644 --- a/src/unit_tests/models/misc/conjunctive_boolean_query.rs +++ b/src/unit_tests/models/misc/conjunctive_boolean_query.rs @@ -34,7 +34,6 @@ use crate::solvers::BruteForce; use crate::solvers::BruteForceProblem as _; use crate::traits::Problem; -/// Helper to build the issue example instance. fn issue_example() -> ConjunctiveBooleanQuery { let relations = vec![ Relation { @@ -160,7 +159,6 @@ fn test_conjunctivebooleanquery_serialization() { #[test] fn test_conjunctivebooleanquery_paper_example() { - // Same instance as the issue example — count all satisfying assignments let problem = issue_example(); let solver = BruteForce::new(); let all = solver.find_all_witnesses(&problem).unwrap(); @@ -171,9 +169,6 @@ fn test_conjunctivebooleanquery_paper_example() { // R_0(y1, 3): y1 in {0,1} // R_1(y0, y1, 5): need (y0, y1, 5) in R_1 // (0,1,5) yes, (0,0,5) no, (1,0,5) no, (1,1,5) no - // Wait — R_1 = {(0,1,5),(1,2,5),(2,3,4),(0,4,3)} - // (0,1,5): yes. (1,2,5): y0=1,y1=2 but need R_0(2,3)=(2,3) not in R_0. - // So only (0,1) works given the R_0 constraint. assert_eq!(all.len(), 1); assert_eq!(all[0], vec![0, 1]); } diff --git a/src/unit_tests/models/misc/cyclic_ordering.rs b/src/unit_tests/models/misc/cyclic_ordering.rs index b93680dc3..1054fffe5 100644 --- a/src/unit_tests/models/misc/cyclic_ordering.rs +++ b/src/unit_tests/models/misc/cyclic_ordering.rs @@ -31,12 +31,6 @@ fn test_cyclic_ordering_evaluate_satisfying() { #[test] fn test_cyclic_ordering_evaluate_unsatisfying() { let problem = example_problem(); - // Identity permutation [0,1,2,3,4]: - // (0,1,2): 0<1<2 ✓ (2,3,0): f(2)=2, f(3)=3, f(0)=0 → need - // (2<3<0) or (3<0<2) or (0<2<3). 0<2<3 ✓ - // (1,3,4): f(1)=1, f(3)=3, f(4)=4 → 1<3<4 ✓ - // Actually identity works! Let me pick one that doesn't. - // [0,2,1,3,4]: // (0,1,2): f(0)=0, f(1)=2, f(2)=1 → (0<2<1)? no. (2<1<0)? no. (1<0<2)? no. → fails assert_eq!(problem.evaluate(&vec![0, 2, 1, 3, 4]).unwrap(), Or(false)); } diff --git a/src/unit_tests/models/misc/dynamic_storage_allocation.rs b/src/unit_tests/models/misc/dynamic_storage_allocation.rs index 42fd55c8c..12db18a72 100644 --- a/src/unit_tests/models/misc/dynamic_storage_allocation.rs +++ b/src/unit_tests/models/misc/dynamic_storage_allocation.rs @@ -32,7 +32,7 @@ fn test_dynamic_storage_allocation_basic() { #[test] fn test_dynamic_storage_allocation_evaluate_feasible() { let problem = example_problem(); - // Solution from the issue: σ = [0, 2, 5, 2, 0] (0-indexed) + // Solution: σ = [0, 2, 5, 2, 0] (0-indexed) assert_eq!(problem.evaluate(&vec![0, 2, 5, 2, 0]).unwrap(), Or(true)); } diff --git a/src/unit_tests/models/misc/flow_shop_scheduling.rs b/src/unit_tests/models/misc/flow_shop_scheduling.rs index d0ebd9267..984d6bf71 100644 --- a/src/unit_tests/models/misc/flow_shop_scheduling.rs +++ b/src/unit_tests/models/misc/flow_shop_scheduling.rs @@ -43,7 +43,6 @@ fn test_flow_shop_scheduling_creation() { #[test] fn test_flow_shop_scheduling_evaluate_feasible() { - // From issue example: 3 machines, 5 jobs // Job 0: [3, 4, 2], Job 1: [2, 3, 5], Job 2: [4, 1, 3], Job 3: [1, 5, 4], Job 4: [3, 2, 3] // Sequence j4, j1, j5, j3, j2 = jobs [3, 0, 4, 2, 1] (0-indexed) // This has makespan 23 <= 25 @@ -173,7 +172,6 @@ fn test_flow_shop_scheduling_empty() { #[test] fn test_flow_shop_scheduling_find_all_witnesses() { - // Issue #507 example: 3 machines, 5 jobs, D=25 // Search space = 5! = 120 permutations let problem = FlowShopScheduling::new( 3, @@ -191,7 +189,7 @@ fn test_flow_shop_scheduling_find_all_witnesses() { for sol in &solutions { assert!(problem.evaluate(sol).unwrap()); } - // The issue witness sequence [3,0,4,2,1] gives makespan 23 ≤ 25. + // The sequence [3,0,4,2,1] gives makespan 23 ≤ 25. assert!(solutions.contains(&vec![3, 0, 4, 2, 1])); // 99 out of 120 permutations have makespan ≤ 25 assert_eq!(solutions.len(), 99); diff --git a/src/unit_tests/models/misc/integer_expression_membership.rs b/src/unit_tests/models/misc/integer_expression_membership.rs index ea611ac09..4d812a911 100644 --- a/src/unit_tests/models/misc/integer_expression_membership.rs +++ b/src/unit_tests/models/misc/integer_expression_membership.rs @@ -200,7 +200,6 @@ fn test_integer_expression_membership_paper_example() { // Witness: config [1, 1, 0] → 4+6+2 = 12 let problem = IntegerExpressionMembership::new(example_expr(), 12); - // Verify the claimed witness assert_eq!(problem.evaluate_config(&[true, true, false]), Some(12)); assert!(problem.evaluate(&vec![true, true, false]).unwrap()); diff --git a/src/unit_tests/models/misc/kth_largest_m_tuple.rs b/src/unit_tests/models/misc/kth_largest_m_tuple.rs index 306be25c8..77a59683c 100644 --- a/src/unit_tests/models/misc/kth_largest_m_tuple.rs +++ b/src/unit_tests/models/misc/kth_largest_m_tuple.rs @@ -133,7 +133,6 @@ fn test_kth_largest_m_tuple_zero_size_panics() { #[test] fn test_kth_largest_m_tuple_paper_example() { - // Issue example: m=3, X_1={2,5,8}, X_2={3,6}, X_3={1,4,7}, B=12, K=14 // 14 of 18 tuples have sum >= 12 -> YES (boundary case: count == K) let p = example_problem(14); let solver = BruteForce::new(); diff --git a/src/unit_tests/models/misc/longest_common_subsequence.rs b/src/unit_tests/models/misc/longest_common_subsequence.rs index ac7665979..2c0cbc80d 100644 --- a/src/unit_tests/models/misc/longest_common_subsequence.rs +++ b/src/unit_tests/models/misc/longest_common_subsequence.rs @@ -103,12 +103,6 @@ fn test_lcs_evaluate_interleaved_padding() { #[test] fn test_lcs_out_of_range_symbol() { let problem = LongestCommonSubsequence::new(2, vec![vec![0, 1, 0], vec![1, 0, 1]]); - // Symbol 3 > alphabet_size (2), but 2 is padding. Symbol 3 is truly out of range. - // Actually with alphabet_size=2, valid symbols are 0,1 and padding is 2. Symbol 3 is invalid. - // But dims allows 0..2, so symbol 3 wouldn't normally appear. Let's test with a symbol - // that is neither valid nor padding: but the config space is [0..3), so max valid index is 2. - // The evaluate function should reject symbols >= alphabet_size that aren't padding. - // Actually let me just test wrong length: assert!(matches!( problem.evaluate(&vec![Some(0), Some(1)]), Err(crate::traits::EvaluationError::InvalidConfiguration(_)) diff --git a/src/unit_tests/models/misc/minimum_axiom_set.rs b/src/unit_tests/models/misc/minimum_axiom_set.rs index 80b2ba3f0..25f5db3f8 100644 --- a/src/unit_tests/models/misc/minimum_axiom_set.rs +++ b/src/unit_tests/models/misc/minimum_axiom_set.rs @@ -21,7 +21,6 @@ fn test_minimum_axiom_set_validates_persisted_input() { } use crate::traits::Problem; -/// Helper: build the canonical 8-sentence example from the issue. fn canonical_instance() -> MinimumAxiomSet { MinimumAxiomSet::new( 8, @@ -174,7 +173,6 @@ fn test_minimum_axiom_set_paper_example() { // The canonical 8-sentence example let problem = canonical_instance(); - // Verify the issue's expected outcome: config [1,1,0,0,0,0,0,0] → Min(2) let result = problem .evaluate(&vec![true, true, false, false, false, false, false, false]) .unwrap(); diff --git a/src/unit_tests/models/misc/minimum_code_generation_one_register.rs b/src/unit_tests/models/misc/minimum_code_generation_one_register.rs index 303aff68b..09c9cd871 100644 --- a/src/unit_tests/models/misc/minimum_code_generation_one_register.rs +++ b/src/unit_tests/models/misc/minimum_code_generation_one_register.rs @@ -58,7 +58,7 @@ fn test_minimum_code_generation_one_register_creation() { #[test] fn test_minimum_code_generation_one_register_evaluate_optimal() { - // Issue #900 example: optimal is 8 instructions + // Example: optimal is 8 instructions // Evaluation order: v3, v2, v1, v0 // config[i] = position for internal vertex i // internal = [0,1,2,3], so config = [3, 2, 1, 0] @@ -160,13 +160,6 @@ fn test_minimum_code_generation_one_register_invalid_permutation() { #[test] fn test_minimum_code_generation_one_register_solver() { - // Small instance: 4 vertices, 2 leaves, 2 internal - // v0 = op(v1, v2), v1 = op(v2, v3) - // Leaves: {2, 3}, Internal: {0, 1} - // Edges: (0,1), (0,2), (1,2), (1,3) - // Wait — v2 appears as both child and parent? - // No: v0 has children v1,v2. v1 has children v2,v3. - // Leaves: v2 and v3 have out-degree 0. So num_leaves=2. let problem = MinimumCodeGenerationOneRegister::new(4, vec![(0, 1), (0, 2), (1, 2), (1, 3)], 2); let solver = BruteForce::new(); let result_solution = solver.solve(&problem).unwrap().unwrap(); @@ -229,7 +222,6 @@ fn test_minimum_code_generation_one_register_unary_ops() { #[test] fn test_minimum_code_generation_one_register_paper_example() { - // Issue #900 example let problem = MinimumCodeGenerationOneRegister::new( 7, vec![ @@ -249,13 +241,11 @@ fn test_minimum_code_generation_one_register_paper_example() { let config = vec![3, 2, 1, 0]; assert_eq!(problem.evaluate(&config).unwrap(), Min(Some(8))); - // Verify with brute force let solver = BruteForce::new(); let result_solution = solver.solve(&problem).unwrap().unwrap(); let result = problem.evaluate(&result_solution).unwrap(); assert_eq!(result, Min(Some(8))); - // Verify witness let witness = solver.solve(&problem).unwrap().unwrap(); assert_eq!(problem.simulate(&witness).unwrap(), Some(8)); } diff --git a/src/unit_tests/models/misc/minimum_code_generation_unlimited_registers.rs b/src/unit_tests/models/misc/minimum_code_generation_unlimited_registers.rs index f1ca88395..475d9222d 100644 --- a/src/unit_tests/models/misc/minimum_code_generation_unlimited_registers.rs +++ b/src/unit_tests/models/misc/minimum_code_generation_unlimited_registers.rs @@ -53,7 +53,7 @@ fn test_minimum_code_generation_unlimited_registers_creation() { #[test] fn test_minimum_code_generation_unlimited_registers_evaluate_optimal() { - // Issue #902 example: optimal is 4 instructions (3 OPs + 1 LOAD) + // Example: optimal is 4 instructions (3 OPs + 1 LOAD) // Evaluation order: v1, v2, v0 // config[i] = position for internal vertex i // internal = [0,1,2], so v0->pos 2, v1->pos 0, v2->pos 1 @@ -69,39 +69,14 @@ fn test_minimum_code_generation_unlimited_registers_evaluate_optimal() { #[test] fn test_minimum_code_generation_unlimited_registers_evaluate_suboptimal() { - // Order: v2, v1, v0 — v2 destroys v3 first, then v1 also needs v3 as left - // So v1 needs a copy of v3 too, but v3 was already destroyed by v2. - // Wait — with unlimited registers, v3 stays in its register. When v2 executes, - // OP v2 overwrites v3's register. But if v1 hasn't run yet and also needs v3, - // then before v2 we must copy v3. - // Then when v1 runs, v3 is gone (overwritten by v2), but we copied it. - // Actually: the copy goes to a new register. So v1 can use the copy. - // But in our simulation, we track: before OP v2, left_child=v3 still needed - // by v1 (as left operand). So we LOAD (copy) v3. Cost so far: 1 LOAD + 1 OP = 2. - // Then OP v1: left_child=v3. But v3's register was overwritten by v2. - // Hmm, our simulation tracks "computed" but not register aliasing. - // - // Actually, with unlimited registers, the LOAD creates a copy in a new register. - // The key insight: when we count future uses, we check if the left child - // value is still needed. If so, we add a LOAD before the OP. - // After the OP, the left child's "register slot" now holds the new value. - // But the copy made by LOAD is in a separate register. - // - // Our simulation correctly handles this: it counts LOADs needed. - // Order v2(pos 0), v1(pos 1), v0(pos 2): - // config: v0->2, v1->1, v2->0 + // Order v2, v1, v0 needs one LOAD to preserve v3 before v2 overwrites it, + // since v1 still needs v3. Together with three OPs, the cost is 4. let problem = MinimumCodeGenerationUnlimitedRegisters::new( 5, vec![(1, 3), (2, 3), (0, 1)], vec![(1, 4), (2, 4), (0, 2)], ); let config = vec![2, 1, 0]; - // Step 0: OP v2, left=v3. future uses of v3 after decrement: left_uses=1 (from v1), right_uses=0. - // Still needed -> LOAD v3. instructions = 2 (1 LOAD + 1 OP). - // Step 1: OP v1, left=v3_copy. future uses of v3 after decrement: 0. - // Not needed -> no LOAD. instructions = 3 (+ 1 OP). - // Step 2: OP v0, left=v1. future uses of v1: 0. No LOAD. instructions = 4 (+ 1 OP). - // Total: 4 (same as optimal for this instance) assert_eq!(problem.simulate(&config).unwrap(), Some(4)); } @@ -141,7 +116,6 @@ fn test_minimum_code_generation_unlimited_registers_invalid_permutation() { #[test] fn test_minimum_code_generation_unlimited_registers_solver() { - // Issue #902 example let problem = MinimumCodeGenerationUnlimitedRegisters::new( 5, vec![(1, 3), (2, 3), (0, 1)], @@ -211,7 +185,6 @@ fn test_minimum_code_generation_unlimited_registers_no_copy_needed() { #[test] fn test_minimum_code_generation_unlimited_registers_paper_example() { - // Issue #902 example let problem = MinimumCodeGenerationUnlimitedRegisters::new( 5, vec![(1, 3), (2, 3), (0, 1)], @@ -222,13 +195,11 @@ fn test_minimum_code_generation_unlimited_registers_paper_example() { let config = vec![2, 0, 1]; assert_eq!(problem.evaluate(&config).unwrap(), Min(Some(4))); - // Verify with brute force let solver = BruteForce::new(); let result_solution = solver.solve(&problem).unwrap().unwrap(); let result = problem.evaluate(&result_solution).unwrap(); assert_eq!(result, Min(Some(4))); - // Verify witness let witness = solver.solve(&problem).unwrap().unwrap(); assert_eq!(problem.simulate(&witness).unwrap(), Some(4)); } diff --git a/src/unit_tests/models/misc/minimum_disjunctive_normal_form.rs b/src/unit_tests/models/misc/minimum_disjunctive_normal_form.rs index 95dce96ec..01f7911d2 100644 --- a/src/unit_tests/models/misc/minimum_disjunctive_normal_form.rs +++ b/src/unit_tests/models/misc/minimum_disjunctive_normal_form.rs @@ -149,7 +149,7 @@ fn test_minimum_dnf_single_minterm() { #[test] fn test_minimum_dnf_tautology_minus_one() { - // f = all true except 000 and 111 (same as issue example) + // f is true except at 000 and 111. let problem = issue_instance(); let solver = BruteForce::new(); assert_eq!( diff --git a/src/unit_tests/models/misc/minimum_external_macro_data_compression.rs b/src/unit_tests/models/misc/minimum_external_macro_data_compression.rs index 13b50275b..b34b02bfc 100644 --- a/src/unit_tests/models/misc/minimum_external_macro_data_compression.rs +++ b/src/unit_tests/models/misc/minimum_external_macro_data_compression.rs @@ -140,16 +140,6 @@ fn test_minimum_external_macro_data_compression_paper_example() { // Paper example: Sigma = {a,b,c,d,e,f} (size 6), s = "abcdefabcdefabcdef" (len 18), h = 2 // Optimal: D = "abcdef" (6), C = "ptr(0,6) ptr(0,6) ptr(0,6)" (3, 3 ptrs) // Cost = 6 + 3 + 1*3 = 12 - // - // However, this has 2*18 = 36 variables with large domains, way too big for brute force. - // Instead, verify the optimal config evaluates correctly on a smaller instance. - // - // Use s = "abab" (len 4), alphabet {a,b} (size 2), h = 1 - // D = "ab" (2), C = "ptr(0,2) ptr(0,2)" (2, 2 ptrs) - // Cost = 2 + 2 + 0*2 = 4. Uncompressed = 4. Equal! - // - // Better: verify the issue example manually on the actual type. - // Construct s = [0,1,2,3,4,5, 0,1,2,3,4,5, 0,1,2,3,4,5], alphabet_size = 6, h = 2 let problem = MinimumExternalMacroDataCompression::new( 6, vec![0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5], diff --git a/src/unit_tests/models/misc/minimum_fault_detection_test_set.rs b/src/unit_tests/models/misc/minimum_fault_detection_test_set.rs index 4fb816e5e..bc9254b81 100644 --- a/src/unit_tests/models/misc/minimum_fault_detection_test_set.rs +++ b/src/unit_tests/models/misc/minimum_fault_detection_test_set.rs @@ -206,7 +206,6 @@ fn test_minimum_fault_detection_test_set_paper_example() { let optimal = problem.evaluate(&optimal_solution).unwrap(); assert_eq!(optimal, Min(Some(2))); - // Verify there is exactly one optimal witness let all = solver.find_all_witnesses(&problem).unwrap(); let optimal_witnesses: Vec<_> = all .into_iter() diff --git a/src/unit_tests/models/misc/minimum_internal_macro_data_compression.rs b/src/unit_tests/models/misc/minimum_internal_macro_data_compression.rs index 82be1e6e6..485c4573b 100644 --- a/src/unit_tests/models/misc/minimum_internal_macro_data_compression.rs +++ b/src/unit_tests/models/misc/minimum_internal_macro_data_compression.rs @@ -144,7 +144,6 @@ fn test_minimum_internal_macro_data_compression_serialization() { #[test] fn test_minimum_internal_macro_data_compression_paper_example() { - // Issue example: alphabet {a,b,c} (3), s="abcabcabc" (9), h=2 // Optimal: C = [a, b, c, ptr(0), ptr(0), EOS, EOS, EOS, EOS] // active_len=5, pointers=2, cost = 5 + 1*2 = 7 let problem = MinimumInternalMacroDataCompression::new(3, vec![0, 1, 2, 0, 1, 2, 0, 1, 2], 2); diff --git a/src/unit_tests/models/misc/minimum_register_sufficiency_for_loops.rs b/src/unit_tests/models/misc/minimum_register_sufficiency_for_loops.rs index 05a56ec18..f43127598 100644 --- a/src/unit_tests/models/misc/minimum_register_sufficiency_for_loops.rs +++ b/src/unit_tests/models/misc/minimum_register_sufficiency_for_loops.rs @@ -156,7 +156,6 @@ fn test_paper_example() { let result = problem.evaluate(&config).unwrap(); assert_eq!(result, Min(Some(3))); - // Verify optimality with brute force let solver = BruteForce::new(); let best = solver.solve(&problem).unwrap().unwrap(); assert_eq!(problem.evaluate(&best).unwrap(), Min(Some(3))); diff --git a/src/unit_tests/models/misc/minimum_tardiness_sequencing.rs b/src/unit_tests/models/misc/minimum_tardiness_sequencing.rs index 8304875e4..b363131d9 100644 --- a/src/unit_tests/models/misc/minimum_tardiness_sequencing.rs +++ b/src/unit_tests/models/misc/minimum_tardiness_sequencing.rs @@ -214,7 +214,6 @@ fn test_minimum_tardiness_sequencing_weighted_basic() { #[test] fn test_minimum_tardiness_sequencing_weighted_evaluate() { - // Issue example: 5 tasks, lengths [3,2,2,1,2], deadlines [4,3,8,3,6], prec (0→2, 1→3) // Schedule: t0,t4,t2,t1,t3 let problem = MinimumTardinessSequencing::::with_lengths( vec![3, 2, 2, 1, 2], @@ -283,7 +282,7 @@ fn test_minimum_tardiness_sequencing_weighted_zero_length() { #[test] fn test_minimum_tardiness_sequencing_paper_example() { - // Issue example (unit-length): 4 tasks, deadlines [2,3,1,4], prec (0→2) + // Unit-length example: 4 tasks, deadlines [2,3,1,4], prec (0→2) // t0: finish=1≤2✓, t1: finish=2≤3✓, t2: finish=3>1✗, t3: finish=4≤4✓ → 1 tardy let problem = MinimumTardinessSequencing::::new(4, vec![2, 3, 1, 4], vec![(0, 2)]); assert_eq!(problem.evaluate(&vec![0, 1, 2, 3]).unwrap(), Min(Some(1))); diff --git a/src/unit_tests/models/misc/minimum_weight_and_or_graph.rs b/src/unit_tests/models/misc/minimum_weight_and_or_graph.rs index 89b5ec61b..2b8ea064a 100644 --- a/src/unit_tests/models/misc/minimum_weight_and_or_graph.rs +++ b/src/unit_tests/models/misc/minimum_weight_and_or_graph.rs @@ -218,7 +218,6 @@ fn test_minimum_weight_and_or_graph_paper_example() { let optimal = problem.evaluate(&optimal_solution).unwrap(); assert_eq!(optimal, Min(Some(6))); - // Verify there is exactly one optimal witness let all = solver.find_all_witnesses(&problem).unwrap(); let optimal_witnesses: Vec<_> = all .into_iter() diff --git a/src/unit_tests/models/misc/multiprocessor_scheduling.rs b/src/unit_tests/models/misc/multiprocessor_scheduling.rs index de3b8277c..f9885c371 100644 --- a/src/unit_tests/models/misc/multiprocessor_scheduling.rs +++ b/src/unit_tests/models/misc/multiprocessor_scheduling.rs @@ -153,7 +153,6 @@ fn test_multiprocessor_scheduling_brute_force_infeasible() { #[test] fn test_multiprocessor_scheduling_find_all_witnesses() { - // Issue #212 example: 5 tasks [4,5,3,2,6], m=2, D=10 // Search space = 2^5 = 32 let problem = MultiprocessorScheduling::new(vec![4, 5, 3, 2, 6], 2, 10); let solver = BruteForce::new(); @@ -161,7 +160,7 @@ fn test_multiprocessor_scheduling_find_all_witnesses() { for sol in &solutions { assert!(problem.evaluate(sol).unwrap()); } - // The issue witness {t1,t5} on P0 and {t2,t3,t4} on P1 must be among solutions + // The assignment {t1,t5} on P0 and {t2,t3,t4} on P1 must be among solutions assert!(solutions.contains(&vec![0, 1, 1, 1, 0])); // Only 2 feasible partitions: {t1,t5}/{t2,t3,t4} and its mirror assert_eq!(solutions.len(), 2); diff --git a/src/unit_tests/models/misc/open_shop_scheduling.rs b/src/unit_tests/models/misc/open_shop_scheduling.rs index a80a35455..77e75989c 100644 --- a/src/unit_tests/models/misc/open_shop_scheduling.rs +++ b/src/unit_tests/models/misc/open_shop_scheduling.rs @@ -30,8 +30,7 @@ fn small_asymmetric() -> OpenShopScheduling { OpenShopScheduling::new(1, vec![vec![2], vec![3]]) } -/// Issue #506 example: 4 jobs × 3 machines, true optimal makespan = 8. -/// (The issue body incorrectly claimed 11 was optimal; brute-force confirms 8.) +/// Example: 4 jobs × 3 machines, true optimal makespan = 8. fn issue_example() -> OpenShopScheduling { OpenShopScheduling::new( 3, diff --git a/src/unit_tests/models/misc/paintshop.rs b/src/unit_tests/models/misc/paintshop.rs index f0d1c8824..be04329b7 100644 --- a/src/unit_tests/models/misc/paintshop.rs +++ b/src/unit_tests/models/misc/paintshop.rs @@ -100,9 +100,6 @@ fn test_adjacent_same_car() { let solver = BruteForce::new(); let solutions = solver.find_all_witnesses(&problem).unwrap(); - // Best case: [0,0] -> [0,1,0,1] = 3 switches, or [0,1] -> [0,1,1,0] = 2 switches - // Actually: [0,0] -> a=0,a=1,b=0,b=1 = [0,1,0,1] = 3 switches - // [0,1] -> a=0,a=1,b=1,b=0 = [0,1,1,0] = 2 switches let min_switches = problem.count_switches(&solutions[0]).unwrap(); assert!(min_switches <= 3); } diff --git a/src/unit_tests/models/misc/partially_ordered_knapsack.rs b/src/unit_tests/models/misc/partially_ordered_knapsack.rs index 038ca2902..bd7167a58 100644 --- a/src/unit_tests/models/misc/partially_ordered_knapsack.rs +++ b/src/unit_tests/models/misc/partially_ordered_knapsack.rs @@ -27,7 +27,6 @@ fn test_partially_ordered_knapsack_validates_persisted_input() { } use crate::traits::Problem; -/// Helper: create the example instance from the issue. /// Items: a=0, b=1, c=2, d=3, e=4, f=5 /// Precedences: a= 0 → violation + // The predecessor's last slot (1) is after the successor's first slot (0). let config = vec![vec![false, true], vec![true, false]]; assert_eq!(p.evaluate(&config).unwrap(), Min(None)); } diff --git a/src/unit_tests/models/misc/rectilinear_picture_compression.rs b/src/unit_tests/models/misc/rectilinear_picture_compression.rs index 4093d8d85..854480243 100644 --- a/src/unit_tests/models/misc/rectilinear_picture_compression.rs +++ b/src/unit_tests/models/misc/rectilinear_picture_compression.rs @@ -41,7 +41,6 @@ fn two_block_matrix() -> Vec> { } fn issue_matrix() -> Vec> { - // 6x6 matrix from the issue description vec![ vec![true, true, true, false, false, false], vec![true, true, true, false, false, false], diff --git a/src/unit_tests/models/misc/register_sufficiency.rs b/src/unit_tests/models/misc/register_sufficiency.rs index 31cc59563..b2dbbe6ff 100644 --- a/src/unit_tests/models/misc/register_sufficiency.rs +++ b/src/unit_tests/models/misc/register_sufficiency.rs @@ -63,7 +63,6 @@ fn test_register_sufficiency_basic() { #[test] fn test_register_sufficiency_evaluate_valid() { - // Issue #515 example: 7 vertices, 8 arcs, K=3 let problem = RegisterSufficiency::new( 7, vec![ @@ -83,7 +82,6 @@ fn test_register_sufficiency_evaluate_valid() { let config = vec![0, 1, 2, 3, 5, 4, 6]; assert!(problem.evaluate(&config).unwrap()); - // Verify register count let max_reg = problem.simulate_registers(&config).unwrap().unwrap(); assert_eq!(max_reg, 3); } @@ -119,7 +117,7 @@ fn test_register_sufficiency_evaluate_invalid_dependency() { #[test] fn test_register_sufficiency_evaluate_exceeds_bound() { - // Issue example with K=2 (should fail - minimum is 3) + // K=2 is infeasible because the minimum register count is 3. let problem = RegisterSufficiency::new( 7, vec![ @@ -216,7 +214,6 @@ fn test_register_sufficiency_single_vertex() { #[test] fn test_register_sufficiency_paper_example() { - // The issue example: 7 vertices, 8 arcs, K=3 let problem = RegisterSufficiency::new( 7, vec![ @@ -232,7 +229,7 @@ fn test_register_sufficiency_paper_example() { 3, ); - // The order from the issue: v1,v2,v3,v4,v6,v5,v7 (1-indexed) + // Order: v1,v2,v3,v4,v6,v5,v7 (1-indexed) // = v0,v1,v2,v3,v5,v4,v6 (0-indexed) // Positions: v0->0, v1->1, v2->2, v3->3, v4->5, v5->4, v6->6 let config = vec![0, 1, 2, 3, 5, 4, 6]; diff --git a/src/unit_tests/models/misc/scheduling_to_minimize_weighted_completion_time.rs b/src/unit_tests/models/misc/scheduling_to_minimize_weighted_completion_time.rs index 54fd389aa..7e11dee8b 100644 --- a/src/unit_tests/models/misc/scheduling_to_minimize_weighted_completion_time.rs +++ b/src/unit_tests/models/misc/scheduling_to_minimize_weighted_completion_time.rs @@ -41,7 +41,6 @@ fn test_scheduling_min_wct_creation() { #[test] fn test_scheduling_min_wct_evaluate_issue_example() { - // Issue example: 5 tasks, 2 processors // Optimal: P0={t0,t2,t4}, P1={t1,t3} => cost = 47 let problem = SchedulingToMinimizeWeightedCompletionTime::new( vec![1, 2, 3, 4, 5], @@ -112,7 +111,6 @@ fn test_scheduling_min_wct_find_all_witnesses() { ); let solver = BruteForce::new(); let witnesses = solver.find_all_witnesses(&problem).unwrap(); - // Issue says 2 optimal assignments (mirror pair) assert_eq!(witnesses.len(), 2); for w in &witnesses { assert_eq!(problem.evaluate(w).unwrap(), Min(Some(47))); @@ -204,7 +202,6 @@ fn test_scheduling_min_wct_three_processors() { #[test] fn test_scheduling_min_wct_paper_example() { - // Same as issue example - verifying the worked example let problem = SchedulingToMinimizeWeightedCompletionTime::new( vec![1, 2, 3, 4, 5], vec![6, 4, 3, 2, 1], diff --git a/src/unit_tests/models/misc/sequencing_to_minimize_tardy_task_weight.rs b/src/unit_tests/models/misc/sequencing_to_minimize_tardy_task_weight.rs index feae2b123..f7383bc4e 100644 --- a/src/unit_tests/models/misc/sequencing_to_minimize_tardy_task_weight.rs +++ b/src/unit_tests/models/misc/sequencing_to_minimize_tardy_task_weight.rs @@ -115,7 +115,6 @@ fn test_sequencing_to_minimize_tardy_task_weight_brute_force_small() { let value = problem.evaluate(&solution).unwrap(); assert!(value.is_valid()); - // Check it's truly optimal by brute-forcing all permutations let permutations: Vec> = vec![ vec![0, 1, 2], vec![0, 2, 1], diff --git a/src/unit_tests/models/misc/sequencing_with_release_times_and_deadlines.rs b/src/unit_tests/models/misc/sequencing_with_release_times_and_deadlines.rs index 91b02b864..97290cc83 100644 --- a/src/unit_tests/models/misc/sequencing_with_release_times_and_deadlines.rs +++ b/src/unit_tests/models/misc/sequencing_with_release_times_and_deadlines.rs @@ -53,7 +53,7 @@ fn test_sequencing_rtd_basic() { #[test] fn test_sequencing_rtd_evaluate_feasible() { - // Canonical 5-task instance from issue #494, verified by brute-force enumeration. + // Canonical 5-task instance, verified by brute-force enumeration. let problem = SequencingWithReleaseTimesAndDeadlines::new( vec![3, 2, 4, 1, 2], vec![0, 1, 5, 0, 8], diff --git a/src/unit_tests/models/misc/shortest_common_supersequence.rs b/src/unit_tests/models/misc/shortest_common_supersequence.rs index c4a233371..0c92a89db 100644 --- a/src/unit_tests/models/misc/shortest_common_supersequence.rs +++ b/src/unit_tests/models/misc/shortest_common_supersequence.rs @@ -116,13 +116,6 @@ fn test_shortestcommonsupersequence_evaluate_infeasible() { #[test] fn test_shortestcommonsupersequence_out_of_range() { let problem = ShortestCommonSupersequence::new(2, vec![vec![0, 1]]); - // max_length = 2, config must have 2 entries - // value 3 is out of range (alphabet_size=2, padding=2, so valid symbols are 0,1,2) - // Actually 3 > alphabet_size so treated as invalid (not padding) - // Config [0, 3]: position 1 has value 3, which is > alphabet_size (2) - // This means position 1 is neither a valid symbol nor padding - // After finding padding at... wait, 3 != 2 (padding), so effective_length = 2 - // Then prefix [0, 3] has 3 >= alphabet_size, so returns None assert_eq!(problem.evaluate(&vec![Some(0), None]).unwrap(), Min(None)); } @@ -238,7 +231,6 @@ fn test_shortestcommonsupersequence_paper_example() { Min(Some(4)) ); - // Verify a solution exists with brute force let solver = BruteForce::new(); let witness = solver .solve(&problem) diff --git a/src/unit_tests/models/misc/shortest_common_superstring.rs b/src/unit_tests/models/misc/shortest_common_superstring.rs index 71386218f..cc832292b 100644 --- a/src/unit_tests/models/misc/shortest_common_superstring.rs +++ b/src/unit_tests/models/misc/shortest_common_superstring.rs @@ -36,7 +36,7 @@ fn test_shortestcommonsuperstring_basic() { #[test] fn test_shortestcommonsuperstring_evaluate_valid_substring() { - // Issue Example 1 (Sigma = {a, b, c}, mapped a=0,b=1,c=2) + // Alphabet {a,b,c} is mapped to {0,1,2}. // R = {"abc", "bca", "cab", "bcc", "cca", "aab"}, max_length = 18 // Optimal superstring w = "aabcabcca" (length 9). let problem = ShortestCommonSuperstring::new( @@ -162,7 +162,6 @@ fn test_shortestcommonsuperstring_serialization() { #[test] fn test_shortestcommonsuperstring_example1_ternary() { - // Issue Example 1: Sigma = {a, b, c}, R = {"abc","bca","cab","bcc","cca","aab"}. // Optimal superstring w = "aabcabcca" (length 9). // Search space 4^18 is too large for brute force; verify the claimed witness // evaluates to Min(Some(9)) and that any shorter prefix is infeasible. @@ -196,7 +195,6 @@ fn test_shortestcommonsuperstring_example1_ternary() { #[test] fn test_shortestcommonsuperstring_example2_binary() { - // Issue Example 2: Sigma = {0, 1}, R = {"001","011","110","100","010","101"}. // Optimal superstring w = "00110100" (length 8). // Search space 3^18 is too large for brute force. let problem = ShortestCommonSuperstring::new( @@ -220,7 +218,6 @@ fn test_shortestcommonsuperstring_example2_binary() { #[test] fn test_shortestcommonsuperstring_example3() { - // Issue Example 3: Sigma = {a, b, c}, R = {"abc","cab","ba","bb"}. // The witness "abcabba" (length 7) is a valid superstring of all four // strings. Brute-force optimality is covered by the smaller instances in // `test_shortestcommonsuperstring_brute_force_small` / `_solve_aggregate` diff --git a/src/unit_tests/models/misc/square_tiling.rs b/src/unit_tests/models/misc/square_tiling.rs index 720a2128a..fe32fce60 100644 --- a/src/unit_tests/models/misc/square_tiling.rs +++ b/src/unit_tests/models/misc/square_tiling.rs @@ -4,7 +4,7 @@ use crate::solvers::BruteForceProblem as _; use crate::traits::Problem; use crate::types::Or; -/// Positive example from the issue: 3 colors, 4 tiles, 2x2 grid. +/// Positive example: 3 colors, 4 tiles, 2x2 grid. /// Tiles: t0=(0,1,2,0), t1=(0,0,2,1), t2=(2,1,0,0), t3=(2,0,0,1) fn example_problem() -> SquareTiling { SquareTiling::new( @@ -89,7 +89,6 @@ fn test_square_tiling_solver_finds_witness() { #[test] fn test_square_tiling_unsatisfiable_instance() { - // Negative example from issue: only t0=(0,1,2,0) and t2=(2,1,0,0) // Both have right=1, left=0, so no horizontal match possible. let problem = SquareTiling::new(3, vec![(0, 1, 2, 0), (2, 1, 0, 0)], 2); let solver = BruteForce::new(); @@ -186,7 +185,6 @@ fn test_square_tiling_color_out_of_range_panics() { #[test] fn test_square_tiling_count_valid_tilings() { - // Issue states 16 valid tilings out of 256 for the positive example let problem = example_problem(); let solver = BruteForce::new(); let witnesses = solver.find_all_witnesses(&problem).unwrap(); diff --git a/src/unit_tests/models/misc/string_to_string_correction.rs b/src/unit_tests/models/misc/string_to_string_correction.rs index e5c099713..b6cf14ad4 100644 --- a/src/unit_tests/models/misc/string_to_string_correction.rs +++ b/src/unit_tests/models/misc/string_to_string_correction.rs @@ -93,10 +93,8 @@ fn test_string_to_string_correction_solver() { fn test_string_to_string_correction_paper_example() { // Paper example: source [0,1,2,3,1,0], target [0,1,3,2,1], bound 2 let problem = StringToStringCorrection::new(4, vec![0, 1, 2, 3, 1, 0], vec![0, 1, 3, 2, 1], 2); - // Verify the known solution assert!(problem.evaluate(&vec![8, 5]).unwrap()); - // Verify all solutions with brute force let solver = BruteForce::new(); let all_solutions = solver.find_all_witnesses(&problem).unwrap(); assert!(!all_solutions.is_empty()); diff --git a/src/unit_tests/models/misc/sum_of_squares_partition.rs b/src/unit_tests/models/misc/sum_of_squares_partition.rs index 5afb1a20e..84c58f2e8 100644 --- a/src/unit_tests/models/misc/sum_of_squares_partition.rs +++ b/src/unit_tests/models/misc/sum_of_squares_partition.rs @@ -197,7 +197,6 @@ fn test_sum_of_squares_partition_square_overflow_is_an_error() { #[test] fn test_sum_of_squares_partition_paper_example() { - // Instance from the issue: sizes=[5,3,8,2,7,1], K=3 let problem = SumOfSquaresPartition::new(vec![5, 3, 8, 2, 7, 1], 3); // Verify a partition: diff --git a/src/unit_tests/models/set/exact_cover_by_3_sets.rs b/src/unit_tests/models/set/exact_cover_by_3_sets.rs index a4d877b66..9ba110205 100644 --- a/src/unit_tests/models/set/exact_cover_by_3_sets.rs +++ b/src/unit_tests/models/set/exact_cover_by_3_sets.rs @@ -66,7 +66,6 @@ fn test_exact_cover_by_3_sets_rejects_non_binary_config_values() { #[test] fn test_exact_cover_by_3_sets_solver() { // Universe: {0..8}, q=3 - // From issue example: // S0={0,1,2}, S1={0,2,4}, S2={3,4,5}, S3={3,5,7}, S4={6,7,8}, S5={1,4,6}, S6={2,5,8} let problem = ExactCoverBy3Sets::new( 9, @@ -89,7 +88,6 @@ fn test_exact_cover_by_3_sets_solver() { for sol in &solutions { assert!(problem.evaluate(sol).unwrap()); } - // Verify the known solution is in there assert!(solutions.contains(&vec![true, false, true, false, true, false, false])); } diff --git a/src/unit_tests/models/set/integer_knapsack.rs b/src/unit_tests/models/set/integer_knapsack.rs index b03fc1744..3ae2c6122 100644 --- a/src/unit_tests/models/set/integer_knapsack.rs +++ b/src/unit_tests/models/set/integer_knapsack.rs @@ -231,11 +231,9 @@ fn test_integer_knapsack_deserialization_rejects_invalid_fields() { #[test] fn test_integer_knapsack_paper_example() { - // From issue #532: 5 items, sizes=[3,4,5,2,7], values=[4,5,7,3,9], B=15 // Optimal=22 with c=(0,0,1,5,0) or c=(1,0,0,6,0) let problem = IntegerKnapsack::new(vec![3, 4, 5, 2, 7], vec![4, 5, 7, 3, 9], 15).unwrap(); - // Verify both optimal solutions assert_eq!( problem.evaluate(&vec![0, 0, 1, 5, 0]).unwrap(), Max(Some(22)) diff --git a/src/unit_tests/models/set/maximum_set_packing.rs b/src/unit_tests/models/set/maximum_set_packing.rs index fdf1b3308..013a145eb 100644 --- a/src/unit_tests/models/set/maximum_set_packing.rs +++ b/src/unit_tests/models/set/maximum_set_packing.rs @@ -87,7 +87,6 @@ fn test_relationship_to_independent_set() { let sets = vec![vec![0, 1], vec![1, 2], vec![2, 3], vec![3, 4]]; let sp_problem = MaximumSetPacking::::new(sets.clone()); - // Build intersection graph let edges = sp_problem.overlapping_pairs(); let n = sets.len(); let is_problem = MaximumIndependentSet::new(SimpleGraph::new(n, edges), vec![1i64; n]); diff --git a/src/unit_tests/models/set/minimum_cardinality_key.rs b/src/unit_tests/models/set/minimum_cardinality_key.rs index 3a941556d..260af4620 100644 --- a/src/unit_tests/models/set/minimum_cardinality_key.rs +++ b/src/unit_tests/models/set/minimum_cardinality_key.rs @@ -4,7 +4,7 @@ use crate::solvers::BruteForceProblem as _; use crate::traits::Problem; use crate::types::Min; -/// Instance 1 from the issue: 6 attributes, FDs {0,1}->{2}, {0,2}->{3}, +/// Instance: 6 attributes, FDs {0,1}->{2}, {0,2}->{3}, /// {1,3}->{4}, {2,4}->{5}. K={0,1} is a key of size 2. fn instance1() -> MinimumCardinalityKey { MinimumCardinalityKey::new( @@ -18,7 +18,7 @@ fn instance1() -> MinimumCardinalityKey { ) } -/// Instance 2 from the issue: 6 attributes, FDs {0,1,2}->{3}, {3,4}->{5}. +/// Instance: 6 attributes, FDs {0,1,2}->{3}, {3,4}->{5}. /// No 2-element subset determines all attributes. fn instance2() -> MinimumCardinalityKey { MinimumCardinalityKey::new(6, vec![(vec![0, 1, 2], vec![3]), (vec![3, 4], vec![5])]) diff --git a/src/unit_tests/models/set/prime_attribute_name.rs b/src/unit_tests/models/set/prime_attribute_name.rs index 11abd0bd4..caea58daa 100644 --- a/src/unit_tests/models/set/prime_attribute_name.rs +++ b/src/unit_tests/models/set/prime_attribute_name.rs @@ -18,7 +18,6 @@ fn test_prime_attribute_create_spec_uses_universe_size_input() { assert_eq!(problem.num_attributes(), 2); } -/// Helper: Issue Example 1 — 6 attributes, 3 FDs, query=3 /// Candidate keys: {0,1}, {2,3}, {0,3} — attribute 3 is prime fn example1() -> PrimeAttributeName { PrimeAttributeName::new( @@ -32,7 +31,6 @@ fn example1() -> PrimeAttributeName { ) } -/// Helper: Issue Example 2 — 6 attributes, 1 FD, query=3 /// Only candidate key: {0,1} — attribute 3 is NOT prime fn example2() -> PrimeAttributeName { PrimeAttributeName::new(6, vec![(vec![0, 1], vec![2, 3, 4, 5])], 3) diff --git a/src/unit_tests/models/set/set_splitting.rs b/src/unit_tests/models/set/set_splitting.rs index 476e97af4..0d8dcaf3d 100644 --- a/src/unit_tests/models/set/set_splitting.rs +++ b/src/unit_tests/models/set/set_splitting.rs @@ -96,14 +96,7 @@ fn test_set_splitting_brute_force_feasible() { #[test] fn test_set_splitting_brute_force_infeasible() { - // Single subset {0,1} with only 2 elements — either 0 or 1 must differ - // Actually {0,1} is always splittable: just color 0→0, 1→1. - // Infeasible instance: single element subset is rejected by constructor (< 2 elems). - // An instance with contradictory constraints: - // U={0}, subset {0,0} is rejected (too few distinct, but actually passes len check) - // Really simplest infeasible: universe_size=1, subset {0,0} has length 2 but only 1 unique. - // Both elements map to index 0 → sum is either 0 (all S1) or 2 (all S2), never split. - // config [0]: elem 0 → S1. subset needs both colors but only has elem 0 twice → impossible. + // Repeating element 0 satisfies the length requirement but cannot supply both colors. let problem = SetSplitting::new(1, vec![vec![0, 0]]); let solver = BruteForce::new(); let witness = solver.solve(&problem).unwrap(); diff --git a/src/unit_tests/models/set/three_dimensional_matching.rs b/src/unit_tests/models/set/three_dimensional_matching.rs index 1a1c9a022..d4f7f7f5a 100644 --- a/src/unit_tests/models/set/three_dimensional_matching.rs +++ b/src/unit_tests/models/set/three_dimensional_matching.rs @@ -69,7 +69,6 @@ fn test_three_dimensional_matching_solver() { for sol in &solutions { assert!(problem.evaluate(sol).unwrap()); } - // Verify the known solution is in there assert!(solutions.contains(&vec![true, true, true, false, false])); } @@ -143,9 +142,6 @@ fn test_three_dimensional_matching_is_valid_solution() { #[test] fn test_three_dimensional_matching_duplicate_coordinates() { - // q = 2, T0=(0,0,0), T1=(1,1,1), T2=(0,1,0) - // T0+T1 is valid matching; T0+T2 shares w=0; T1+T2 shares y (not y, T1 y=1, T2 y=0, ok) - // Actually T1+T2: w={1,0} ok, x={1,1} NOT distinct -> invalid let problem = ThreeDimensionalMatching::new(2, vec![(0, 0, 0), (1, 1, 1), (0, 1, 0)]); assert!(problem.evaluate(&vec![true, true, false]).unwrap()); // T0+T1: w={0,1}, x={0,1}, y={0,1} all distinct diff --git a/src/unit_tests/models/set/two_dimensional_consecutive_sets.rs b/src/unit_tests/models/set/two_dimensional_consecutive_sets.rs index b67594e2a..2af76940a 100644 --- a/src/unit_tests/models/set/two_dimensional_consecutive_sets.rs +++ b/src/unit_tests/models/set/two_dimensional_consecutive_sets.rs @@ -23,7 +23,6 @@ fn test_two_dimensional_consecutive_sets_creation() { #[test] fn test_two_dimensional_consecutive_sets_evaluation() { - // YES instance from issue: // Alphabet: {0,1,2,3,4,5} // Subsets: {0,1,2}, {3,4,5}, {1,3}, {2,4}, {0,5} let problem = TwoDimensionalConsecutiveSets::new( @@ -70,7 +69,6 @@ fn test_two_dimensional_consecutive_sets_evaluation_ignores_empty_group_labels() #[test] fn test_two_dimensional_consecutive_sets_no_instance() { - // NO instance from issue: // Alphabet: {0,1,2,3,4,5} // Subsets: {0,1,2}, {0,3,4}, {0,5,1}, {2,3,5} let problem = TwoDimensionalConsecutiveSets::new( @@ -143,7 +141,6 @@ fn test_two_dimensional_consecutive_sets_paper_example() { ], ); - // Verify the known valid solution let valid_config = vec![0, 1, 2, 2, 3, 1]; assert!(problem.evaluate(&valid_config).unwrap()); diff --git a/src/unit_tests/property.rs b/src/unit_tests/property.rs index 981f5e1de..34b08c45e 100644 --- a/src/unit_tests/property.rs +++ b/src/unit_tests/property.rs @@ -151,14 +151,12 @@ fn test_graph_strategy_sanity() { for _ in 0..10 { let (n, edges) = strategy.new_tree(&mut runner).unwrap().current(); - // Check all edges are valid for (u, v) in &edges { assert!(*u < n, "Edge source out of bounds"); assert!(*v < n, "Edge target out of bounds"); assert!(u != v, "Self-loop detected"); } - // Check no duplicate edges let unique: HashSet<_> = edges.iter().collect(); assert_eq!(unique.len(), edges.len(), "Duplicate edges detected"); } diff --git a/src/unit_tests/reduction_graph.rs b/src/unit_tests/reduction_graph.rs index 1e212c22f..173b1cf72 100644 --- a/src/unit_tests/reduction_graph.rs +++ b/src/unit_tests/reduction_graph.rs @@ -786,7 +786,6 @@ fn find_paths_up_to_stops_after_limit() { let src = ReductionGraph::variant_to_map(&MaximumIndependentSet::::variant()); let dst = ReductionGraph::variant_to_map(&QUBO::::variant()); - // Get all paths to know the total count let all = graph.find_all_paths("MaximumIndependentSet", &src, "QUBO", &dst); assert!(all.len() > 3, "need multiple paths for this test"); diff --git a/src/unit_tests/registry/problem_type.rs b/src/unit_tests/registry/problem_type.rs index 99384ee4b..15f1e3e5e 100644 --- a/src/unit_tests/registry/problem_type.rs +++ b/src/unit_tests/registry/problem_type.rs @@ -251,7 +251,6 @@ fn catalog_dimensions_cover_all_declared_variants() { use crate::registry::variant::VariantEntry; for entry in inventory::iter:: { - // Collect all variant entries for this problem let variants: Vec<_> = inventory::iter:: .into_iter() .filter(|v| v.name == entry.name) diff --git a/src/unit_tests/registry/schema.rs b/src/unit_tests/registry/schema.rs index 45fbb80bb..4136ef668 100644 --- a/src/unit_tests/registry/schema.rs +++ b/src/unit_tests/registry/schema.rs @@ -19,7 +19,6 @@ fn problem_category_parses_only_declared_values() { #[test] fn test_collect_schemas_returns_all_problems() { let schemas = collect_schemas(); - // We have 17 registered problems assert!( schemas.len() >= 17, "Expected at least 17 schemas, got {}", diff --git a/src/unit_tests/rules/acyclicpartition_ilp.rs b/src/unit_tests/rules/acyclicpartition_ilp.rs index 235cc0c33..6281c5b00 100644 --- a/src/unit_tests/rules/acyclicpartition_ilp.rs +++ b/src/unit_tests/rules/acyclicpartition_ilp.rs @@ -108,12 +108,10 @@ fn test_acyclicpartition_to_ilp_closed_loop() { ReduceTo::>::reduce_to(&source).expect("reduction should succeed"); let ilp = reduction.target_problem(); - // Solve source with brute force let bf = BruteForce::new(); let bf_solutions = bf.find_all_witnesses(&source).unwrap(); assert!(!bf_solutions.is_empty(), "source should be satisfiable"); - // Solve ILP let ilp_solver = ILPSolver::new(); let ilp_sol = ilp_solver.solve(ilp).expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_sol).unwrap(); diff --git a/src/unit_tests/rules/analysis.rs b/src/unit_tests/rules/analysis.rs index a6dfb15d0..81ee495cb 100644 --- a/src/unit_tests/rules/analysis.rs +++ b/src/unit_tests/rules/analysis.rs @@ -121,7 +121,6 @@ fn test_reachability_missing_proof_chains_filter() { for p in &missing { assert_eq!(p.reason, UnreachableReason::MissingProofChain); } - // Count should match manual filter let manual_count = report .unreachable .iter() diff --git a/src/unit_tests/rules/biconnectivityaugmentation_ilp.rs b/src/unit_tests/rules/biconnectivityaugmentation_ilp.rs index 4f39a3578..b0eafe5e7 100644 --- a/src/unit_tests/rules/biconnectivityaugmentation_ilp.rs +++ b/src/unit_tests/rules/biconnectivityaugmentation_ilp.rs @@ -22,12 +22,10 @@ fn test_biconnectivityaugmentation_to_ilp_closed_loop() { ReduceTo::>::reduce_to(&source).expect("reduction should succeed"); let ilp = reduction.target_problem(); - // Solve source with brute force let bf = BruteForce::new(); let bf_solutions = bf.find_all_witnesses(&source).unwrap(); assert!(!bf_solutions.is_empty(), "source should be satisfiable"); - // Solve ILP let ilp_solver = ILPSolver::new(); let ilp_sol = ilp_solver.solve(ilp).expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_sol).unwrap(); diff --git a/src/unit_tests/rules/binpacking_ilp.rs b/src/unit_tests/rules/binpacking_ilp.rs index b254153d5..24045ff1c 100644 --- a/src/unit_tests/rules/binpacking_ilp.rs +++ b/src/unit_tests/rules/binpacking_ilp.rs @@ -30,11 +30,9 @@ fn test_binpacking_to_ilp_closed_loop() { let bf = BruteForce::new(); let ilp_solver = ILPSolver::new(); - // Solve original with brute force let bf_solutions = bf.find_all_witnesses(&problem).unwrap(); let bf_obj = problem.evaluate(&bf_solutions[0]).unwrap(); - // Solve via ILP let ilp_solution = ilp_solver.solve(ilp).expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_solution).unwrap(); let ilp_obj = problem.evaluate(&extracted).unwrap(); diff --git a/src/unit_tests/rules/boundedcomponentspanningforest_ilp.rs b/src/unit_tests/rules/boundedcomponentspanningforest_ilp.rs index c2cbea23c..9b99c75dc 100644 --- a/src/unit_tests/rules/boundedcomponentspanningforest_ilp.rs +++ b/src/unit_tests/rules/boundedcomponentspanningforest_ilp.rs @@ -24,12 +24,10 @@ fn test_boundedcomponentspanningforest_to_ilp_closed_loop() { ReduceTo::>::reduce_to(&source).expect("reduction should succeed"); let ilp = reduction.target_problem(); - // Solve source with brute force let bf = BruteForce::new(); let bf_solutions = bf.find_all_witnesses(&source).unwrap(); assert!(!bf_solutions.is_empty(), "source should be satisfiable"); - // Solve ILP let ilp_solver = ILPSolver::new(); let ilp_sol = ilp_solver.solve(ilp).expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_sol).unwrap(); diff --git a/src/unit_tests/rules/circuit_spinglass.rs b/src/unit_tests/rules/circuit_spinglass.rs index 26f961931..f03dc6a52 100644 --- a/src/unit_tests/rules/circuit_spinglass.rs +++ b/src/unit_tests/rules/circuit_spinglass.rs @@ -245,7 +245,6 @@ fn test_reduction_result_methods() { let reduction = ReduceTo::>>::reduce_to(&problem) .expect("reduction should succeed"); - // Test target_problem and extract_solution work let sg = reduction.target_problem().inner(); assert!(sg.num_spins() >= 2); // At least c and x } diff --git a/src/unit_tests/rules/closeststring_ilp.rs b/src/unit_tests/rules/closeststring_ilp.rs index 487b7f68e..3442074fb 100644 --- a/src/unit_tests/rules/closeststring_ilp.rs +++ b/src/unit_tests/rules/closeststring_ilp.rs @@ -6,7 +6,7 @@ use crate::solvers::{BruteForce, ILPSolver}; use crate::traits::Problem; use crate::types::Min; -/// Canonical issue #1032 instance: binary alphabet, four length-3 strings +/// Canonical instance: binary alphabet, four length-3 strings /// 000, 011, 101, 110. Every binary length-3 center attains radius exactly 2; /// no center attains radius 1. fn issue_instance() -> ClosestString { diff --git a/src/unit_tests/rules/closestsubstring_ilp.rs b/src/unit_tests/rules/closestsubstring_ilp.rs index ed20f8b40..2953e4edd 100644 --- a/src/unit_tests/rules/closestsubstring_ilp.rs +++ b/src/unit_tests/rules/closestsubstring_ilp.rs @@ -6,7 +6,7 @@ use crate::solvers::{BruteForce, ILPSolver}; use crate::traits::Problem; use crate::types::Min; -/// Canonical issue #1033 instance: binary alphabet, length-3 windows on three +/// Canonical instance: binary alphabet, length-3 windows on three /// length-5 strings. Optimum radius is 1. fn issue_instance() -> ClosestSubstring { ClosestSubstring::new( @@ -164,7 +164,7 @@ fn test_closestsubstring_to_ilp_ternary_alphabet() { #[test] fn test_closestsubstring_to_ilp_extract_known_solution() { // Build the ILP encoding of center 010 with chosen windows (0, 1, 0) on - // the canonical issue instance, by hand: x_{0,0}=x_{1,1}=x_{2,0}=1, + // the canonical instance, by hand: x_{0,0}=x_{1,1}=x_{2,0}=1, // y_{1,0}=y_{2,1}=y_{3,0}=1, R = 1. Then verify the extracted source // config matches and gives radius 1. let source = issue_instance(); diff --git a/src/unit_tests/rules/coloring_ilp.rs b/src/unit_tests/rules/coloring_ilp.rs index 43d642468..5e7f83e84 100644 --- a/src/unit_tests/rules/coloring_ilp.rs +++ b/src/unit_tests/rules/coloring_ilp.rs @@ -78,7 +78,6 @@ fn test_coloring_to_ilp_closed_loop() { "Brute force should find solutions" ); - // Solve via ILP reduction let ilp_solution = ilp_solver.solve(ilp).expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_solution).unwrap(); @@ -103,17 +102,14 @@ fn test_ilp_solution_equals_brute_force_path() { let ilp_solver = ILPSolver::new(); - // Solve via ILP let ilp_solution = ilp_solver.solve(ilp).expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_solution).unwrap(); - // Verify validity assert!( problem.evaluate(&extracted).unwrap(), "Extracted solution should be valid" ); - // Check adjacent vertices have different colors assert_ne!(extracted[0], extracted[1]); assert_ne!(extracted[1], extracted[2]); assert_ne!(extracted[2], extracted[3]); diff --git a/src/unit_tests/rules/consecutiveonessubmatrix_ilp.rs b/src/unit_tests/rules/consecutiveonessubmatrix_ilp.rs index b6a7ecf2f..8f67288ed 100644 --- a/src/unit_tests/rules/consecutiveonessubmatrix_ilp.rs +++ b/src/unit_tests/rules/consecutiveonessubmatrix_ilp.rs @@ -46,7 +46,6 @@ fn test_cos_to_ilp_closed_loop() { let extracted = reduction.extract_solution(&ilp_solution).unwrap(); assert_eq!(problem.evaluate(&extracted).unwrap(), Or(true)); - // Verify brute-force on source agrees let bf = BruteForce::new(); let bf_witness = bf.solve(&problem).unwrap().expect("should be feasible"); assert_eq!(problem.evaluate(&bf_witness).unwrap(), Or(true)); diff --git a/src/unit_tests/rules/directedhamiltonianpath_ilp.rs b/src/unit_tests/rules/directedhamiltonianpath_ilp.rs index ad9c9f1bc..954d4ed28 100644 --- a/src/unit_tests/rules/directedhamiltonianpath_ilp.rs +++ b/src/unit_tests/rules/directedhamiltonianpath_ilp.rs @@ -32,7 +32,6 @@ fn test_directedhamiltonianpath_to_ilp_closed_loop() { .expect("brute-force should find a solution"); assert_eq!(problem.evaluate(&bf_solution).unwrap(), Or(true)); - // Solve via ILP let reduction: ReductionDirectedHamiltonianPathToILP = ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp_solver = ILPSolver::new(); @@ -49,7 +48,6 @@ fn test_directedhamiltonianpath_to_ilp_closed_loop() { #[test] fn test_directedhamiltonianpath_to_ilp_issue_example() { - // 6-vertex example from issue #813 let graph = DirectedGraph::new( 6, vec![ diff --git a/src/unit_tests/rules/eulerianpath_ilp.rs b/src/unit_tests/rules/eulerianpath_ilp.rs index 1a3abc688..ec43015b8 100644 --- a/src/unit_tests/rules/eulerianpath_ilp.rs +++ b/src/unit_tests/rules/eulerianpath_ilp.rs @@ -6,7 +6,7 @@ use crate::topology::DirectedGraph; use crate::traits::Problem; use crate::types::Or; -/// Canonical issue #1025 instance: V = {0,1,2}, A = [(0,1),(0,1),(1,2),(2,0)]. +/// Canonical instance: V = {0,1,2}, A = [(0,1),(0,1),(1,2),(2,0)]. /// A witness exists: ordering (a_0, a_2, a_3, a_1) traces 0->1->2->0->1. fn issue_instance() -> EulerianPath { EulerianPath::new(DirectedGraph::new(3, vec![(0, 1), (0, 1), (1, 2), (2, 0)])) diff --git a/src/unit_tests/rules/exactcoverby3sets_maximumsetpacking.rs b/src/unit_tests/rules/exactcoverby3sets_maximumsetpacking.rs index ec36b02dd..78cf697a8 100644 --- a/src/unit_tests/rules/exactcoverby3sets_maximumsetpacking.rs +++ b/src/unit_tests/rules/exactcoverby3sets_maximumsetpacking.rs @@ -40,7 +40,6 @@ fn test_exactcoverby3sets_to_maximumsetpacking_structure() { assert_eq!(target.get_set(i).unwrap().len(), 3); } - // Verify specific set contents assert_eq!(target.sets()[0], vec![0, 1, 2]); assert_eq!(target.sets()[1], vec![0, 1, 3]); assert_eq!(target.sets()[2], vec![3, 4, 5]); diff --git a/src/unit_tests/rules/exactcoverby3sets_staffscheduling.rs b/src/unit_tests/rules/exactcoverby3sets_staffscheduling.rs index 1d674cc43..1ac06e987 100644 --- a/src/unit_tests/rules/exactcoverby3sets_staffscheduling.rs +++ b/src/unit_tests/rules/exactcoverby3sets_staffscheduling.rs @@ -14,7 +14,6 @@ fn test_exactcoverby3sets_to_staffscheduling_closed_loop() { let result = ReduceTo::::reduce_to(&source).expect("reduction should succeed"); let target = result.target_problem(); - // Check target dimensions assert_eq!(target.num_periods(), 6); assert_eq!(target.shifts_per_schedule(), 3); assert_eq!(target.num_schedules(), 4); @@ -77,7 +76,6 @@ fn test_exactcoverby3sets_to_staffscheduling_unique_cover() { #[test] fn test_exactcoverby3sets_to_staffscheduling_extract_solution() { - // Verify extract_solution maps correctly let source = ExactCoverBy3Sets::new(6, vec![[0, 1, 2], [3, 4, 5], [0, 3, 4], [1, 2, 5]]); let result = ReduceTo::::reduce_to(&source).expect("reduction should succeed"); @@ -94,7 +92,6 @@ fn test_exactcoverby3sets_to_staffscheduling_extract_solution() { #[test] fn test_exactcoverby3sets_to_staffscheduling_schedule_structure() { - // Verify the schedule patterns are correctly constructed let source = ExactCoverBy3Sets::new(6, vec![[0, 1, 2], [3, 4, 5]]); let result = ReduceTo::::reduce_to(&source).expect("reduction should succeed"); let target = result.target_problem(); diff --git a/src/unit_tests/rules/factoring_circuit.rs b/src/unit_tests/rules/factoring_circuit.rs index 5b16f2702..0cd10c8b9 100644 --- a/src/unit_tests/rules/factoring_circuit.rs +++ b/src/unit_tests/rules/factoring_circuit.rs @@ -63,13 +63,11 @@ fn evaluate_multiplier_circuit( let circuit = reduction.target_problem().circuit(); let mut assignments: HashMap = HashMap::new(); - // Set input variables for p for (i, var_name) in reduction.p_vars().iter().enumerate() { let bit = ((p_val >> i) & 1) == 1; assignments.insert(var_name.clone(), bit); } - // Set input variables for q for (i, var_name) in reduction.q_vars().iter().enumerate() { let bit = ((q_val >> i) & 1) == 1; assignments.insert(var_name.clone(), bit); @@ -201,7 +199,6 @@ fn test_target_problem_structure() { ReduceTo::::reduce_to(&factoring).expect("reduction should succeed"); let circuit = reduction.target_problem(); - // Verify the circuit has variables and assignments assert!(circuit.num_variables() > 0); assert!(!circuit.circuit().assignments.is_empty()); } @@ -258,7 +255,6 @@ fn test_prime_7_only_trivial_factorizations() { if is_valid_factorization { assert!(satisfies, "{}*{}=7 should satisfy the circuit", p, q); - // Check it's a trivial factorization (1*7 or 7*1) assert!( (p == 1 && q == 7) || (p == 7 && q == 1), "7 is prime, so only 1*7 or 7*1 should work" diff --git a/src/unit_tests/rules/factoring_ilp.rs b/src/unit_tests/rules/factoring_ilp.rs index 1a1eb5c55..d1afae82b 100644 --- a/src/unit_tests/rules/factoring_ilp.rs +++ b/src/unit_tests/rules/factoring_ilp.rs @@ -57,7 +57,6 @@ fn test_factor_6() { let ilp_solution = ilp_solver.solve(ilp).expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_solution).unwrap(); - // Verify it's a valid factorization assert!(problem.is_valid_factorization(&extracted)); let (a, b) = extracted.clone(); @@ -182,12 +181,10 @@ fn test_factoring_to_ilp_closed_loop() { ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp = reduction.target_problem(); - // Get ILP solution let ilp_solver = ILPSolver::new(); let ilp_solution = ilp_solver.solve(ilp).expect("ILP should be solvable"); let ilp_factors = reduction.extract_solution(&ilp_solution).unwrap(); - // Get brute force solutions let bf = BruteForce::new(); let bf_solutions = bf.find_all_witnesses(&problem).unwrap(); diff --git a/src/unit_tests/rules/graph.rs b/src/unit_tests/rules/graph.rs index a2a8912d6..2ab267c09 100644 --- a/src/unit_tests/rules/graph.rs +++ b/src/unit_tests/rules/graph.rs @@ -1267,7 +1267,6 @@ fn test_to_json() { let graph = ReductionGraph::new(); let json = graph.to_json(); - // Check nodes assert!(json.nodes.len() >= 10); assert!(json.nodes.iter().any(|n| n.name == "MaximumIndependentSet")); assert!(json @@ -1279,7 +1278,6 @@ fn test_to_json() { .iter() .any(|n| n.category == ProblemCategory::Algebraic)); - // Check edges assert!(json.edges.len() >= 10); // Check that IS -> VC and VC -> IS both exist as separate directed edges @@ -1498,7 +1496,6 @@ fn test_to_json_file() { assert!(content.contains("\"edges\"")); assert!(content.contains("MaximumIndependentSet")); - // Parse as generic JSON to verify validity let parsed: serde_json::Value = serde_json::from_str(&content).unwrap(); assert!(!parsed["nodes"].as_array().unwrap().is_empty()); assert!(!parsed["edges"].as_array().unwrap().is_empty()); @@ -1604,9 +1601,7 @@ fn test_to_json_nodes_have_variants() { let graph = ReductionGraph::new(); let json = graph.to_json(); - // Check that nodes have variant information for node in &json.nodes { - // Verify node has a name assert!(!node.name.is_empty()); } } @@ -1870,7 +1865,6 @@ fn test_reduction_chain_with_variant_reductions() { }) .expect("explicit SAT route"); - // Create a 3-SAT formula let ksat = KSatisfiability::::new( 3, vec![ diff --git a/src/unit_tests/rules/hamiltoniancircuit_ruralpostman.rs b/src/unit_tests/rules/hamiltoniancircuit_ruralpostman.rs index 0fb4a1a55..4a91bb267 100644 --- a/src/unit_tests/rules/hamiltoniancircuit_ruralpostman.rs +++ b/src/unit_tests/rules/hamiltoniancircuit_ruralpostman.rs @@ -121,7 +121,6 @@ fn test_hamiltoniancircuit_to_ruralpostman_nonhamiltonian_cost_gap() { .expect("reduction should succeed"); let target = reduction.target_problem().inner(); - // Verify source has no Hamiltonian circuit let source_witness = BruteForce::new().solve(&source).unwrap(); assert!(source_witness.is_none(), "star graph should have no HC"); diff --git a/src/unit_tests/rules/hamiltonianpath_ilp.rs b/src/unit_tests/rules/hamiltonianpath_ilp.rs index 5a516dae6..9ef8e07d4 100644 --- a/src/unit_tests/rules/hamiltonianpath_ilp.rs +++ b/src/unit_tests/rules/hamiltonianpath_ilp.rs @@ -29,7 +29,6 @@ fn test_hamiltonianpath_to_ilp_closed_loop() { .expect("brute-force should find a solution"); assert_eq!(problem.evaluate(&bf_solution).unwrap(), Or(true)); - // Solve via ILP let reduction: ReductionHamiltonianPathToILP = ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp_solver = ILPSolver::new(); @@ -56,7 +55,6 @@ fn test_hamiltonianpath_to_ilp_cycle_graph() { .expect("brute-force should find a solution"); assert_eq!(problem.evaluate(&bf_solution).unwrap(), Or(true)); - // Solve via ILP let reduction: ReductionHamiltonianPathToILP = ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp_solver = ILPSolver::new(); diff --git a/src/unit_tests/rules/hamiltonianpath_isomorphicspanningtree.rs b/src/unit_tests/rules/hamiltonianpath_isomorphicspanningtree.rs index f0503e307..380451464 100644 --- a/src/unit_tests/rules/hamiltonianpath_isomorphicspanningtree.rs +++ b/src/unit_tests/rules/hamiltonianpath_isomorphicspanningtree.rs @@ -46,15 +46,7 @@ fn test_hamiltonianpath_to_isomorphicspanningtree_path_graph() { #[test] fn test_hamiltonianpath_to_isomorphicspanningtree_no_hamiltonian_path() { - // Star graph K_{1,4}: vertex 0 connected to 1,2,3,4 with no other edges. - // This has no Hamiltonian path because vertex 0 must appear in the middle - // but has only degree 4 neighbors that are pairwise non-adjacent. - // Actually for n=5 star, vertex 0 has degree 4, so it can be internal, - // but the leaves have degree 1, so at most 2 can be endpoints. - // A path visits 5 vertices needing 4 edges, but all edges go through 0. - // So the path must be leaf-0-leaf-..., but after visiting 0 we can only - // go to unvisited leaves, and from a leaf we can only go back to 0 (already visited). - // Path: leaf-0-leaf is length 2, can't extend. No HP exists. + // K_{1,4} has four degree-one leaves, but a Hamiltonian path has only two endpoints. let source = HamiltonianPath::new(SimpleGraph::new(5, vec![(0, 1), (0, 2), (0, 3), (0, 4)])); let result = ReduceTo::>::reduce_to(&source) .expect("reduction should succeed"); @@ -88,7 +80,6 @@ fn test_hamiltonianpath_to_isomorphicspanningtree_complete_graph() { .unwrap() .expect("K4 should have an IST solution"); let extracted = result.extract_solution(&target_solution).unwrap(); - // Extracted solution should be a valid Hamiltonian path assert!( source.evaluate(&extracted).unwrap().0, "Extracted solution should be a valid Hamiltonian path" diff --git a/src/unit_tests/rules/ilp_bool_ilp_i64.rs b/src/unit_tests/rules/ilp_bool_ilp_i64.rs index 6394c2e30..367f4d737 100644 --- a/src/unit_tests/rules/ilp_bool_ilp_i64.rs +++ b/src/unit_tests/rules/ilp_bool_ilp_i64.rs @@ -29,7 +29,6 @@ fn test_ilp_bool_to_ilp_i64_closed_loop() { assert_eq!(target.constraints(), source.constraints()); assert_eq!(target.variables(), source.variables()); - // Extract solution back to source and verify optimality let target_solution = ILPSolver::new().solve(target).unwrap(); let source_solution = result.extract_solution(&target_solution).unwrap(); assert_eq!(source.evaluate(&source_solution).unwrap(), source_obj); diff --git a/src/unit_tests/rules/ilp_qubo.rs b/src/unit_tests/rules/ilp_qubo.rs index 3ba2dada1..1e056d92b 100644 --- a/src/unit_tests/rules/ilp_qubo.rs +++ b/src/unit_tests/rules/ilp_qubo.rs @@ -233,7 +233,6 @@ fn test_ilp_to_qubo_structure() { let reduction = ReduceTo::>::reduce_to(&ilp).expect("reduction should succeed"); let qubo = reduction.target_problem(); - // Verify QUBO has appropriate structure assert!(qubo.num_variables() >= ilp.num_vars()); } diff --git a/src/unit_tests/rules/integralflowhomologousarcs_ilp.rs b/src/unit_tests/rules/integralflowhomologousarcs_ilp.rs index 60bc0a9b7..5980fa420 100644 --- a/src/unit_tests/rules/integralflowhomologousarcs_ilp.rs +++ b/src/unit_tests/rules/integralflowhomologousarcs_ilp.rs @@ -17,7 +17,6 @@ fn test_integralflowhomologousarcs_to_ilp_closed_loop() { 2, vec![(0, 1)], ); - // Verify source is satisfiable via brute force let direct = BruteForce::new() .solve(&source) .unwrap() diff --git a/src/unit_tests/rules/kclique_balancedcompletebipartitesubgraph.rs b/src/unit_tests/rules/kclique_balancedcompletebipartitesubgraph.rs index fb22fc12f..06d6e58c9 100644 --- a/src/unit_tests/rules/kclique_balancedcompletebipartitesubgraph.rs +++ b/src/unit_tests/rules/kclique_balancedcompletebipartitesubgraph.rs @@ -13,7 +13,6 @@ fn test_kclique_to_balancedcompletebipartitesubgraph_closed_loop() { .expect("reduction should succeed"); let target = reduction.target_problem(); - // Verify target parameterss // left_size = n + C(k,2) = 4 + 3 = 7 assert_eq!(target.left_size(), 7); // right_size = m + (n - k) = 4 + 1 = 5 diff --git a/src/unit_tests/rules/kclique_subgraphisomorphism.rs b/src/unit_tests/rules/kclique_subgraphisomorphism.rs index 7ba1863be..b78b37022 100644 --- a/src/unit_tests/rules/kclique_subgraphisomorphism.rs +++ b/src/unit_tests/rules/kclique_subgraphisomorphism.rs @@ -46,7 +46,6 @@ fn test_kclique_to_subgraphisomorphism_complete_graph() { assert_eq!(target.num_pattern_vertices(), 3); assert_eq!(target.num_pattern_edges(), 3); - // Solve the target and extract back to source let bf = BruteForce::new(); let witness = bf.solve(target).unwrap().expect("K4 should contain K3"); let extracted = reduction.extract_solution(&witness).unwrap(); diff --git a/src/unit_tests/rules/kcoloring_bicliquecover.rs b/src/unit_tests/rules/kcoloring_bicliquecover.rs index 9d86c589b..0eddd9fe4 100644 --- a/src/unit_tests/rules/kcoloring_bicliquecover.rs +++ b/src/unit_tests/rules/kcoloring_bicliquecover.rs @@ -34,9 +34,6 @@ fn test_kcoloring_to_bicliquecover_closed_loop_trivial() { assert_eq!(source.evaluate(&coloring).unwrap(), Or(true)); } -/// Structural assertions against the exact target parameterss derived in the -/// issue. Picks a small but non-trivial instance: P_3 (path on 3 vertices) -/// with q = 2. #[test] fn test_kcoloring_to_bicliquecover_structure_path() { // n = 3, m = 2 (path 0-1-2), q = 2. diff --git a/src/unit_tests/rules/kcoloring_twodimensionalconsecutivesets.rs b/src/unit_tests/rules/kcoloring_twodimensionalconsecutivesets.rs index 46338d9c3..7c236497f 100644 --- a/src/unit_tests/rules/kcoloring_twodimensionalconsecutivesets.rs +++ b/src/unit_tests/rules/kcoloring_twodimensionalconsecutivesets.rs @@ -55,7 +55,6 @@ fn test_kcoloring_to_tdcs_non_3colorable() { let source_solutions = solver.find_all_witnesses(&source).unwrap(); assert!(source_solutions.is_empty(), "K4 is not 3-colorable"); - // Verify the reduction produces the correct structure let reduction = ReduceTo::::reduce_to(&source) .expect("reduction should succeed"); let target = reduction.target_problem(); @@ -110,7 +109,6 @@ fn test_kcoloring_to_tdcs_extract_solution_valid() { for target_sol in &target_solutions { let source_sol = reduction.extract_solution(target_sol).unwrap(); assert_eq!(source_sol.len(), 3); - // Verify it is a valid coloring assert!( source.evaluate(&source_sol).unwrap().0, "Extracted coloring must be valid: {:?}", diff --git a/src/unit_tests/rules/ksatisfiability_bicliquecover.rs b/src/unit_tests/rules/ksatisfiability_bicliquecover.rs index 9c6b4b2c9..a4926db1b 100644 --- a/src/unit_tests/rules/ksatisfiability_bicliquecover.rs +++ b/src/unit_tests/rules/ksatisfiability_bicliquecover.rs @@ -4,9 +4,9 @@ //! hundreds of binary variables, so closed-loop brute-force solving is //! infeasible. The tests below verify: //! -//! - Structural sizes (vertex counts, rank, k_f) on the example from -//! the issue body (1 source variable; smallest power-of-two padding). -//! - Structural sizes on the four-variable example from the issue body +//! - Structural sizes (vertex counts, rank, k_f) on the one-variable example +//! (smallest power-of-two padding). +//! - Structural sizes on the four-variable example //! (n = 4, m = 2 source clauses; reduction adds 8 exactly-one //! clauses for m = 10 normalized clauses). //! - The construction terminates and produces a valid `BipartiteGraph` @@ -22,7 +22,7 @@ use crate::models::graph::BicliqueCover; use crate::traits::Problem; use crate::variant::K3; -/// Issue body Section 1 example: one source variable, one source clause. +/// One source variable and one source clause. /// Normalized counts: `n = 2` (t_1, f_1), `ell = 1`, `m = 3` clauses /// (1 translated + 2 exactly-one), `k_f = 4 + 4 + 6 = 14`, rank `= 18`. #[test] @@ -48,14 +48,9 @@ fn test_ksatisfiability_to_bicliquecover_structure_single_variable() { assert_eq!(target.k(), rank); } -/// Issue body Example section: `n = 4`, `m_source = 2`, `ell = 2`, +/// Four-variable example: `n = 4`, `m_source = 2`, `ell = 2`, /// `m_normalized = 2 + 4 = 6`, `k_f = 4*2 + 2*ceil(log2 6) + 6 = 18`, /// `rank = 18 + 4 + 2 = 24`. -/// -/// (The issue example computes `m = 2`, `k_f = 16`, `rank = 22` *if* -/// you skip the exactly-one normalization clauses. Our implementation -/// faithfully emits them so the rank rises from 22 to 24 — both are -/// admissible polynomial upper bounds for the same reduction.) #[test] fn test_ksatisfiability_to_bicliquecover_structure_issue_example() { let source = KSatisfiability::::new( diff --git a/src/unit_tests/rules/ksatisfiability_qubo.rs b/src/unit_tests/rules/ksatisfiability_qubo.rs index 2d9aae200..5b44562e6 100644 --- a/src/unit_tests/rules/ksatisfiability_qubo.rs +++ b/src/unit_tests/rules/ksatisfiability_qubo.rs @@ -71,7 +71,6 @@ fn test_ksatisfiability_to_qubo_closed_loop() { let solver = BruteForce::new(); let qubo_solutions = solver.find_all_witnesses(qubo).unwrap(); - // Verify all solutions satisfy all clauses for sol in &qubo_solutions { let extracted = reduction.extract_solution(sol).unwrap(); assert!(ksat.evaluate(&extracted).unwrap()); @@ -98,7 +97,6 @@ fn test_ksatisfiability_to_qubo_simple() { #[test] fn test_ksatisfiability_to_qubo_contradiction() { // 1 var, 2 clauses: (x1 ∨ x1) and (¬x1 ∨ ¬x1) — can't satisfy both - // Actually, this is (x1) and (¬x1), which is a contradiction // Max-2-SAT will satisfy 1 of 2 clauses let ksat = KSatisfiability::::new( 1, @@ -181,7 +179,6 @@ fn test_k3satisfiability_to_qubo_closed_loop() { let solver = BruteForce::new(); let qubo_solutions = solver.find_all_witnesses(qubo).unwrap(); - // Verify all extracted solutions maximize satisfied clauses for sol in &qubo_solutions { let extracted = reduction.extract_solution(sol).unwrap(); assert_eq!(extracted.len(), 5); diff --git a/src/unit_tests/rules/ksatisfiability_subsetsum.rs b/src/unit_tests/rules/ksatisfiability_subsetsum.rs index 5cacbc628..016f30f04 100644 --- a/src/unit_tests/rules/ksatisfiability_subsetsum.rs +++ b/src/unit_tests/rules/ksatisfiability_subsetsum.rs @@ -7,7 +7,6 @@ use num_bigint::BigUint; #[test] fn test_ksatisfiability_to_subsetsum_closed_loop() { - // Issue example: (x1 ∨ x2 ∨ x3) ∧ (¬x1 ∨ ¬x2 ∨ x3), n=3, m=2 let ksat = KSatisfiability::::new( 3, vec![ @@ -83,7 +82,6 @@ fn test_ksatisfiability_to_subsetsum_single_clause() { #[test] fn test_ksatisfiability_to_subsetsum_structure() { - // Verify sizes match the issue's example table let ksat = KSatisfiability::::new( 3, vec![ @@ -95,7 +93,6 @@ fn test_ksatisfiability_to_subsetsum_structure() { let target = reduction.target_problem(); let sizes = target.sizes(); - // From the issue: // y1=10010, z1=10001, y2=01010, z2=01001, y3=00111, z3=00100 // g1=00010, h1=00020, g2=00001, h2=00002 assert_eq!(sizes[0], BigUint::from(10010u32)); // y1 @@ -131,7 +128,6 @@ fn test_ksatisfiability_to_subsetsum_all_negated() { #[test] fn test_ksatisfiability_to_subsetsum_extract_solution_example() { - // Verify the specific example from the issue: // x1=T, x2=T, x3=T → select y1, y2, y3 + slack to reach target 11144 let ksat = KSatisfiability::::new( 3, diff --git a/src/unit_tests/rules/longestcircuit_ilp.rs b/src/unit_tests/rules/longestcircuit_ilp.rs index 1ff88d8f1..55a4222f4 100644 --- a/src/unit_tests/rules/longestcircuit_ilp.rs +++ b/src/unit_tests/rules/longestcircuit_ilp.rs @@ -94,7 +94,6 @@ fn test_longestcircuit_to_ilp_closed_loop() { .expect("brute-force should find a solution"); assert!(problem.evaluate(&bf_solution).unwrap().0.is_some()); - // Solve via ILP let reduction: ReductionLongestCircuitToILP = ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp_solver = ILPSolver::new(); diff --git a/src/unit_tests/rules/longestcommonsubsequence_ilp.rs b/src/unit_tests/rules/longestcommonsubsequence_ilp.rs index f920fa554..5f29c8bc3 100644 --- a/src/unit_tests/rules/longestcommonsubsequence_ilp.rs +++ b/src/unit_tests/rules/longestcommonsubsequence_ilp.rs @@ -66,7 +66,6 @@ fn test_lcs_to_ilp_extracts_valid_witness() { #[test] fn test_lcs_to_ilp_matches_brute_force() { - // Verify ILP optimal value matches brute force let problem = LongestCommonSubsequence::new(2, vec![vec![0, 1, 0], vec![1, 0, 1]]); let reduction: ReductionLCSToILP = ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); diff --git a/src/unit_tests/rules/longestcommonsubsequence_maximumindependentset.rs b/src/unit_tests/rules/longestcommonsubsequence_maximumindependentset.rs index 7daf6a1e0..77b9d19ee 100644 --- a/src/unit_tests/rules/longestcommonsubsequence_maximumindependentset.rs +++ b/src/unit_tests/rules/longestcommonsubsequence_maximumindependentset.rs @@ -6,7 +6,6 @@ use crate::traits::Problem; #[test] fn test_longestcommonsubsequence_to_maximumindependentset_closed_loop() { - // Issue example: k=2, s1="ABAC", s2="BACA", alphabet={A=0, B=1, C=2} let lcs = LongestCommonSubsequence::new( 3, vec![ @@ -25,7 +24,6 @@ fn test_longestcommonsubsequence_to_maximumindependentset_closed_loop() { #[test] fn test_lcs_to_mis_graph_structure() { - // Issue example: should produce 6 vertices, 9 edges let lcs = LongestCommonSubsequence::new( 3, vec![ @@ -119,9 +117,6 @@ fn test_lcs_to_mis_extract_solution() { let reduction = ReduceTo::>::reduce_to(&lcs) .expect("reduction should succeed"); - // Vertices: A nodes at indices 0-3, B node at index 4, C node at index 5 - // Actually the ordering depends on implementation: char 0 (A) first, then 1 (B), then 2 (C) - // Let's verify by solving let solver = BruteForce::new(); let witness = solver .solve(reduction.target_problem()) diff --git a/src/unit_tests/rules/maximum2satisfiability_maxcut.rs b/src/unit_tests/rules/maximum2satisfiability_maxcut.rs index 17bf8c50f..7431da2cb 100644 --- a/src/unit_tests/rules/maximum2satisfiability_maxcut.rs +++ b/src/unit_tests/rules/maximum2satisfiability_maxcut.rs @@ -61,7 +61,7 @@ fn test_maximum2satisfiability_to_maxcut_issue_affine_relation_on_all_partitions ReduceTo::>::reduce_to(&source).expect("reduction should succeed"); let target = reduction.target_problem(); - // For this issue instance, every partition satisfies + // For this instance, every partition satisfies // 2 * satisfied_clauses = 8 + cut_weight. for mask in 0..(1usize << target.num_vertices()) { let target_solution: Vec = (0..target.num_vertices()) diff --git a/src/unit_tests/rules/maximumclique_ilp.rs b/src/unit_tests/rules/maximumclique_ilp.rs index 4cc94c341..4774f6e14 100644 --- a/src/unit_tests/rules/maximumclique_ilp.rs +++ b/src/unit_tests/rules/maximumclique_ilp.rs @@ -11,7 +11,6 @@ fn is_valid_clique(problem: &MaximumClique, config: &[bool]) - .map(|(i, _)| i) .collect(); - // Check all pairs of selected vertices are adjacent for i in 0..selected.len() { for j in (i + 1)..selected.len() { if !problem.graph().has_edge(selected[i], selected[j]) { @@ -60,7 +59,6 @@ fn test_reduction_creates_valid_ilp() { ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp = reduction.target_problem(); - // Check ILP structure assert_eq!(ilp.num_vars(), 3, "Should have one variable per vertex"); assert_eq!( ilp.constraints().len(), @@ -96,7 +94,6 @@ fn test_reduction_weighted() { ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp = reduction.target_problem(); - // Check that weights are correctly transferred to objective let mut coeffs: Vec = vec![0; 3]; for &(var, coef) in ilp.objective() { coeffs[var] = coef; @@ -117,10 +114,8 @@ fn test_maximumclique_to_ilp_closed_loop() { let ilp_solver = ILPSolver::new(); - // Solve with brute force for clique let bf_size = brute_force_max_clique(&problem); - // Solve via ILP reduction let ilp_solution = ilp_solver.solve(ilp).expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_solution).unwrap(); @@ -129,7 +124,6 @@ fn test_maximumclique_to_ilp_closed_loop() { assert_eq!(bf_size, 3); assert_eq!(ilp_size, 3); - // Verify the ILP solution is a valid clique assert!( is_valid_clique(&problem, &extracted), "Extracted solution should be a valid clique" @@ -149,10 +143,8 @@ fn test_ilp_solution_equals_brute_force_path() { let ilp_solver = ILPSolver::new(); - // Solve with brute force for clique let bf_size = brute_force_max_clique(&problem); - // Solve via ILP let ilp_solution = ilp_solver.solve(ilp).expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_solution).unwrap(); let ilp_size = clique_size(&problem, &extracted); @@ -160,7 +152,6 @@ fn test_ilp_solution_equals_brute_force_path() { assert_eq!(bf_size, 2); assert_eq!(ilp_size, 2); - // Verify validity assert!(is_valid_clique(&problem, &extracted)); } @@ -187,7 +178,6 @@ fn test_ilp_solution_equals_brute_force_weighted() { assert_eq!(bf_obj, 101); assert_eq!(ilp_obj, 101); - // Verify the solution is a valid clique assert!(is_valid_clique(&problem, &extracted)); } diff --git a/src/unit_tests/rules/maximumclique_maximumindependentset.rs b/src/unit_tests/rules/maximumclique_maximumindependentset.rs index 2097108cf..c2c81f989 100644 --- a/src/unit_tests/rules/maximumclique_maximumindependentset.rs +++ b/src/unit_tests/rules/maximumclique_maximumindependentset.rs @@ -18,7 +18,6 @@ fn test_maximumclique_to_maximumindependentset_closed_loop() { .expect("reduction should succeed"); let target = reduction.target_problem(); - // Verify complement graph structure assert_eq!(target.graph().num_vertices(), 4); assert_eq!(target.graph().num_edges(), 3); // 4*3/2 - 3 = 3 diff --git a/src/unit_tests/rules/maximumcontactmapoverlap_ilp.rs b/src/unit_tests/rules/maximumcontactmapoverlap_ilp.rs index 75b2378ce..111385baa 100644 --- a/src/unit_tests/rules/maximumcontactmapoverlap_ilp.rs +++ b/src/unit_tests/rules/maximumcontactmapoverlap_ilp.rs @@ -6,7 +6,7 @@ use crate::solvers::ILPSolver; use crate::traits::Problem; use crate::types::Max; -/// Canonical instance from issue #1043 / #1044: +/// Canonical instance: /// G_1 has 4 vertices with contacts {{0,2},{1,3}}; /// G_2 has 5 vertices with contacts {{0,3},{1,4},{0,2}}. /// Optimal alignment 0->0, 1->1, 2->3, 3->4 preserves 2 contacts. diff --git a/src/unit_tests/rules/maximumdomaticnumber_ilp.rs b/src/unit_tests/rules/maximumdomaticnumber_ilp.rs index 47a49f21c..ad93b6f9b 100644 --- a/src/unit_tests/rules/maximumdomaticnumber_ilp.rs +++ b/src/unit_tests/rules/maximumdomaticnumber_ilp.rs @@ -15,11 +15,9 @@ fn test_maximumdomaticnumber_to_ilp_closed_loop() { let bf = BruteForce::new(); let ilp_solver = ILPSolver::new(); - // Solve with brute force on original problem let bf_witness = bf.solve(&problem).unwrap().unwrap(); let bf_value = problem.evaluate(&bf_witness).unwrap(); - // Solve via ILP reduction let ilp_solution = ilp_solver.solve(ilp).expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_solution).unwrap(); let ilp_value = problem.evaluate(&extracted).unwrap(); @@ -28,7 +26,6 @@ fn test_maximumdomaticnumber_to_ilp_closed_loop() { assert_eq!(bf_value, Max(Some(2))); assert_eq!(ilp_value, Max(Some(2))); - // Verify the ILP solution is valid for the original problem assert!(problem.evaluate(&extracted).unwrap().is_valid()); } @@ -114,7 +111,6 @@ fn test_maximumdomaticnumber_to_ilp_solution_extraction() { let extracted = reduction.extract_solution(&ilp_solution).unwrap(); assert_eq!(extracted, vec![0, 1, 0]); - // Verify this is a valid partition with 2 dominating sets let value = problem.evaluate(&extracted).unwrap(); assert_eq!(value, Max(Some(2))); } diff --git a/src/unit_tests/rules/maximumindependentset_maximumsetpacking.rs b/src/unit_tests/rules/maximumindependentset_maximumsetpacking.rs index 202b4819b..83323c4e3 100644 --- a/src/unit_tests/rules/maximumindependentset_maximumsetpacking.rs +++ b/src/unit_tests/rules/maximumindependentset_maximumsetpacking.rs @@ -50,7 +50,6 @@ fn test_disjoint_sets() { #[test] fn test_reduction_structure() { - // Test IS to SP structure let is_problem = MaximumIndependentSet::new(SimpleGraph::new(4, vec![(0, 1), (1, 2)]), vec![1i64; 4]); let reduction = ReduceTo::>::reduce_to(&is_problem) @@ -60,7 +59,6 @@ fn test_reduction_structure() { // SP should have same number of sets as vertices in IS assert_eq!(sp.num_sets(), 4); - // Test SP to IS structure let sets = vec![vec![0, 1], vec![2, 3]]; let sp_problem = MaximumSetPacking::new(sets); let reduction2: ReductionSPToIS = diff --git a/src/unit_tests/rules/maximumindependentset_triangular.rs b/src/unit_tests/rules/maximumindependentset_triangular.rs index 7205ac3f5..73c9433fa 100644 --- a/src/unit_tests/rules/maximumindependentset_triangular.rs +++ b/src/unit_tests/rules/maximumindependentset_triangular.rs @@ -147,13 +147,11 @@ fn test_mis_simple_one_to_triangular_graph_methods() { let edges = graph.edges(); assert_eq!(edges.len(), m); - // Check edges are consistent with has_edge for &(u, v) in &edges { assert!(graph.has_edge(u, v)); assert!(graph.has_edge(v, u)); // symmetric } - // Check neighbors are consistent with edges for v in 0..n { let nbrs = graph.neighbors(v); for &u in &nbrs { diff --git a/src/unit_tests/rules/maximumleafspanningtree_ilp.rs b/src/unit_tests/rules/maximumleafspanningtree_ilp.rs index 1c5034599..f76cb0b96 100644 --- a/src/unit_tests/rules/maximumleafspanningtree_ilp.rs +++ b/src/unit_tests/rules/maximumleafspanningtree_ilp.rs @@ -13,7 +13,7 @@ fn small_instance() -> MaximumLeafSpanningTree { MaximumLeafSpanningTree::new(SimpleGraph::new(4, vec![(0, 1), (1, 2), (2, 3), (0, 2)])) } -/// Issue #897 canonical instance: 6 vertices, 9 edges. +/// Canonical instance: 6 vertices, 9 edges. fn canonical_instance() -> MaximumLeafSpanningTree { MaximumLeafSpanningTree::new(SimpleGraph::new( 6, diff --git a/src/unit_tests/rules/maximumlikelihoodranking_ilp.rs b/src/unit_tests/rules/maximumlikelihoodranking_ilp.rs index e706c0c43..5e215cb55 100644 --- a/src/unit_tests/rules/maximumlikelihoodranking_ilp.rs +++ b/src/unit_tests/rules/maximumlikelihoodranking_ilp.rs @@ -64,14 +64,12 @@ fn test_maximumlikelihoodranking_to_ilp_extraction() { .expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_solution).unwrap(); - // Verify the extracted config is a valid permutation let n = problem.num_items(); assert_eq!(extracted.len(), n); let mut sorted = extracted.clone(); sorted.sort(); assert_eq!(sorted, (0..n).collect::>()); - // Verify evaluation is valid let value = problem.evaluate(&extracted).unwrap(); assert!(value.is_valid()); } @@ -116,7 +114,6 @@ fn test_maximumlikelihoodranking_to_ilp_single_item() { #[test] fn test_maximumlikelihoodranking_to_ilp_larger_instance() { - // 4-item instance from the issue let matrix = vec![ vec![0, 4, 3, 5], vec![1, 0, 4, 3], diff --git a/src/unit_tests/rules/maximummatching_ilp.rs b/src/unit_tests/rules/maximummatching_ilp.rs index 913253576..79a54cd45 100644 --- a/src/unit_tests/rules/maximummatching_ilp.rs +++ b/src/unit_tests/rules/maximummatching_ilp.rs @@ -42,7 +42,6 @@ fn test_reduction_creates_valid_ilp() { ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp = reduction.target_problem(); - // Check ILP structure assert_eq!(ilp.num_vars(), 3, "Should have one variable per edge"); // Each vertex has degree 2, so 3 constraints (one per vertex) assert_eq!( @@ -65,7 +64,6 @@ fn test_reduction_weighted() { ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp = reduction.target_problem(); - // Check that weights are correctly transferred to objective let mut coeffs: Vec = vec![0; 2]; for &(var, coef) in ilp.objective() { coeffs[var] = coef; @@ -85,10 +83,8 @@ fn test_maximummatching_to_ilp_closed_loop() { let bf = BruteForce::new(); let ilp_solver = ILPSolver::new(); - // Solve with brute force on original problem let bf_solutions = bf.find_all_witnesses(&problem).unwrap(); - // Solve via ILP reduction let ilp_solution = ilp_solver.solve(ilp).expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_solution).unwrap(); @@ -98,7 +94,6 @@ fn test_maximummatching_to_ilp_closed_loop() { assert_eq!(bf_size, Max(Some(1))); assert_eq!(ilp_size, Max(Some(1))); - // Verify the ILP solution is valid for the original problem assert!( problem.evaluate(&extracted).unwrap().is_valid(), "Extracted solution should be valid" @@ -117,11 +112,9 @@ fn test_ilp_solution_equals_brute_force_path() { let bf = BruteForce::new(); let ilp_solver = ILPSolver::new(); - // Solve with brute force let bf_solutions = bf.find_all_witnesses(&problem).unwrap(); let bf_size = problem.evaluate(&bf_solutions[0]).unwrap(); - // Solve via ILP let ilp_solution = ilp_solver.solve(ilp).expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_solution).unwrap(); let ilp_size = problem.evaluate(&extracted).unwrap(); @@ -129,7 +122,6 @@ fn test_ilp_solution_equals_brute_force_path() { assert_eq!(bf_size, Max(Some(2))); assert_eq!(ilp_size, Max(Some(2))); - // Verify validity assert!(problem.evaluate(&extracted).unwrap().is_valid()); } @@ -157,7 +149,6 @@ fn test_ilp_solution_equals_brute_force_weighted() { assert_eq!(bf_obj, Max(Some(100))); assert_eq!(ilp_obj, Max(Some(100))); - // Verify the solution selects edge 0 (0-1) assert_eq!(extracted, vec![true, false]); } @@ -230,7 +221,6 @@ fn test_k4_perfect_matching() { assert!(problem.evaluate(&extracted).unwrap().is_valid()); assert_eq!(problem.evaluate(&extracted).unwrap(), Max(Some(2))); // Perfect matching has 2 edges - // Verify all vertices are matched let sum: usize = extracted.iter().filter(|&&selected| selected).count(); assert_eq!(sum, 2); } diff --git a/src/unit_tests/rules/maximummatching_maximumsetpacking.rs b/src/unit_tests/rules/maximummatching_maximumsetpacking.rs index f839f0387..43d0e5606 100644 --- a/src/unit_tests/rules/maximummatching_maximumsetpacking.rs +++ b/src/unit_tests/rules/maximummatching_maximumsetpacking.rs @@ -46,7 +46,6 @@ fn test_matching_to_setpacking_weighted() { // Edge 0-1 (weight 100) alone beats edges 0-2 + 1-3 (weight 2) assert!(sp_solutions.contains(&vec![true, false, false])); - // Verify through direct MaximumMatching solution let direct_solutions = solver.find_all_witnesses(&matching).unwrap(); assert_eq!(matching.evaluate(&sp_solutions[0]).unwrap(), Max(Some(100))); assert_eq!( diff --git a/src/unit_tests/rules/minimumcapacitatedspanningtree_ilp.rs b/src/unit_tests/rules/minimumcapacitatedspanningtree_ilp.rs index 18af512bd..67f8205f4 100644 --- a/src/unit_tests/rules/minimumcapacitatedspanningtree_ilp.rs +++ b/src/unit_tests/rules/minimumcapacitatedspanningtree_ilp.rs @@ -18,7 +18,7 @@ fn small_instance() -> MinimumCapacitatedSpanningTree { ) } -/// Canonical instance from issue #901: 5 vertices, 8 edges. +/// Canonical instance: 5 vertices, 8 edges. fn canonical_instance() -> MinimumCapacitatedSpanningTree { MinimumCapacitatedSpanningTree::new( SimpleGraph::new( diff --git a/src/unit_tests/rules/minimumcostmaximumflow_minimumcostcirculation.rs b/src/unit_tests/rules/minimumcostmaximumflow_minimumcostcirculation.rs index 8bdc090ed..eec97c515 100644 --- a/src/unit_tests/rules/minimumcostmaximumflow_minimumcostcirculation.rs +++ b/src/unit_tests/rules/minimumcostmaximumflow_minimumcostcirculation.rs @@ -5,7 +5,7 @@ use crate::topology::DirectedGraph; use crate::traits::Problem; use crate::types::Min; -/// Canonical 4-vertex diamond instance from issue #1031. +/// Canonical 4-vertex diamond instance. /// /// Max-flow value = 3, min cost among value-3 flows = 7. fn canonical_source() -> MinimumCostMaximumFlow { diff --git a/src/unit_tests/rules/minimumdominatingset_ilp.rs b/src/unit_tests/rules/minimumdominatingset_ilp.rs index deddfa504..f63fc66b6 100644 --- a/src/unit_tests/rules/minimumdominatingset_ilp.rs +++ b/src/unit_tests/rules/minimumdominatingset_ilp.rs @@ -14,7 +14,6 @@ fn test_reduction_creates_valid_ilp() { ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp = reduction.target_problem(); - // Check ILP structure assert_eq!(ilp.num_vars(), 3, "Should have one variable per vertex"); assert_eq!( ilp.constraints().len(), @@ -37,7 +36,6 @@ fn test_reduction_weighted() { ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp = reduction.target_problem(); - // Check that weights are correctly transferred to objective let mut coeffs: Vec = vec![0; 3]; for &(var, coef) in ilp.objective() { coeffs[var] = coef; @@ -60,11 +58,9 @@ fn test_minimumdominatingset_to_ilp_closed_loop() { let bf = BruteForce::new(); let ilp_solver = ILPSolver::new(); - // Solve with brute force on original problem let bf_solutions = bf.find_all_witnesses(&problem).unwrap(); let bf_size = problem.evaluate(&bf_solutions[0]).unwrap(); - // Solve via ILP reduction let ilp_solution = ilp_solver.solve(ilp).expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_solution).unwrap(); let ilp_size = problem.evaluate(&extracted).unwrap(); @@ -73,7 +69,6 @@ fn test_minimumdominatingset_to_ilp_closed_loop() { assert_eq!(bf_size, Min(Some(1))); assert_eq!(ilp_size, Min(Some(1))); - // Verify the ILP solution is valid for the original problem assert!( problem.evaluate(&extracted).unwrap().is_valid(), "Extracted solution should be valid" @@ -94,11 +89,9 @@ fn test_ilp_solution_equals_brute_force_path() { let bf = BruteForce::new(); let ilp_solver = ILPSolver::new(); - // Solve with brute force let bf_solutions = bf.find_all_witnesses(&problem).unwrap(); let bf_size = problem.evaluate(&bf_solutions[0]).unwrap(); - // Solve via ILP let ilp_solution = ilp_solver.solve(ilp).expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_solution).unwrap(); let ilp_size = problem.evaluate(&extracted).unwrap(); @@ -106,7 +99,6 @@ fn test_ilp_solution_equals_brute_force_path() { assert_eq!(bf_size, Min(Some(2))); assert_eq!(ilp_size, Min(Some(2))); - // Verify validity assert!(problem.evaluate(&extracted).unwrap().is_valid()); } @@ -135,7 +127,6 @@ fn test_ilp_solution_equals_brute_force_weighted() { assert_eq!(bf_obj, Min(Some(3))); assert_eq!(ilp_obj, Min(Some(3))); - // Verify the solution selects all leaves assert_eq!(extracted, vec![false, true, true, true]); } diff --git a/src/unit_tests/rules/minimumfeedbackarcset_ilp.rs b/src/unit_tests/rules/minimumfeedbackarcset_ilp.rs index 59dd53eaf..8b4237905 100644 --- a/src/unit_tests/rules/minimumfeedbackarcset_ilp.rs +++ b/src/unit_tests/rules/minimumfeedbackarcset_ilp.rs @@ -62,11 +62,9 @@ fn test_minimumfeedbackarcset_to_ilp_bf_vs_ilp() { let bf = BruteForce::new(); let ilp_solver = ILPSolver::new(); - // Solve with brute force on original problem let bf_solutions = bf.find_all_witnesses(&problem).unwrap(); let bf_value = problem.evaluate(&bf_solutions[0]).unwrap(); - // Solve via ILP reduction let ilp_solution = ilp_solver.solve(ilp).expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_solution).unwrap(); let ilp_value = problem.evaluate(&extracted).unwrap(); diff --git a/src/unit_tests/rules/minimumfeedbackvertexset_ilp.rs b/src/unit_tests/rules/minimumfeedbackvertexset_ilp.rs index e37eb44cb..5c7f9aec5 100644 --- a/src/unit_tests/rules/minimumfeedbackvertexset_ilp.rs +++ b/src/unit_tests/rules/minimumfeedbackvertexset_ilp.rs @@ -34,11 +34,9 @@ fn test_minimumfeedbackvertexset_to_ilp_closed_loop() { let bf = BruteForce::new(); let ilp_solver = ILPSolver::new(); - // Solve with brute force on original problem let bf_solutions = bf.find_all_witnesses(&problem).unwrap(); let bf_size = problem.evaluate(&bf_solutions[0]).unwrap(); - // Solve via ILP reduction let ilp_solution = ilp_solver.solve(ilp).expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_solution).unwrap(); let ilp_size = problem.evaluate(&extracted).unwrap(); @@ -47,7 +45,6 @@ fn test_minimumfeedbackvertexset_to_ilp_closed_loop() { assert_eq!(bf_size, Min(Some(1))); assert_eq!(ilp_size, Min(Some(1))); - // Verify the ILP solution is valid for the original problem assert!( problem.evaluate(&extracted).unwrap().is_valid(), "Extracted solution should be valid" @@ -56,7 +53,6 @@ fn test_minimumfeedbackvertexset_to_ilp_closed_loop() { #[test] fn test_cycle_of_triangles() { - // The example from issue #141: n=9, m=15, FVS=3 let arcs = vec![ (0, 1), (1, 2), @@ -80,7 +76,6 @@ fn test_cycle_of_triangles() { ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp = reduction.target_problem(); - // Verify ILP structure assert_eq!(ilp.num_vars(), 18, "Should have 2*9 = 18 variables"); assert_eq!( ilp.constraints().len(), @@ -145,7 +140,6 @@ fn test_weighted() { ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp = reduction.target_problem(); - // Check that weights are correctly transferred to objective let mut coeffs: Vec = vec![0; ilp.num_vars()]; for &(var, coef) in ilp.objective() { coeffs[var] = coef; @@ -186,7 +180,6 @@ fn test_two_disjoint_cycles() { #[test] fn test_solution_extraction() { - // Verify that extraction correctly takes first n values let graph = DirectedGraph::new(3, vec![(0, 1), (1, 2), (2, 0)]); let problem = MinimumFeedbackVertexSet::new(graph, vec![1i64; 3]); let reduction: ReductionMFVSToILP = diff --git a/src/unit_tests/rules/minimumgraphbandwidth_ilp.rs b/src/unit_tests/rules/minimumgraphbandwidth_ilp.rs index af0d5374d..e30082701 100644 --- a/src/unit_tests/rules/minimumgraphbandwidth_ilp.rs +++ b/src/unit_tests/rules/minimumgraphbandwidth_ilp.rs @@ -29,7 +29,6 @@ fn test_minimumgraphbandwidth_to_ilp_closed_loop() { .expect("brute-force should find a solution"); assert!(problem.evaluate(&bf_solution).unwrap().0.is_some()); - // Solve via ILP let reduction: ReductionMGBToILP = ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp_solver = ILPSolver::new(); diff --git a/src/unit_tests/rules/minimuminternalmacrodatacompression_ilp.rs b/src/unit_tests/rules/minimuminternalmacrodatacompression_ilp.rs index 09908a2b9..dfe147af8 100644 --- a/src/unit_tests/rules/minimuminternalmacrodatacompression_ilp.rs +++ b/src/unit_tests/rules/minimuminternalmacrodatacompression_ilp.rs @@ -51,7 +51,6 @@ fn test_imdc_to_ilp_closed_loop_low_pointer_cost() { let source_config = reduction.extract_solution(&target_witness).unwrap(); let val = source.evaluate(&source_config).unwrap(); assert!(val.0.is_some()); - // Verify against brute force let bf_val_solution = BruteForce::new().solve(&source).unwrap().unwrap(); let bf_val = source.evaluate(&bf_val_solution).unwrap(); assert_eq!(val, bf_val); diff --git a/src/unit_tests/rules/minimummaximalmatching_minimummatrixdomination.rs b/src/unit_tests/rules/minimummaximalmatching_minimummatrixdomination.rs index 9d0a6ab52..394ba38d9 100644 --- a/src/unit_tests/rules/minimummaximalmatching_minimummatrixdomination.rs +++ b/src/unit_tests/rules/minimummaximalmatching_minimummatrixdomination.rs @@ -6,7 +6,7 @@ use crate::topology::{BipartiteGraph, Graph}; use crate::traits::Problem; use crate::types::Min; -/// Build the canonical YES bipartite instance from the issue: L = {l0, l1}, +/// Build the canonical YES bipartite instance: L = {l0, l1}, /// R = {r0, r1, r2}, F = {(l0, r0), (l0, r1), (l0, r2), (l1, r1), (l1, r2)}. /// /// In BipartiteGraph local coordinates this is: @@ -16,7 +16,7 @@ fn yes_bipartite() -> BipartiteGraph { BipartiteGraph::new(2, 3, vec![(0, 0), (0, 1), (0, 2), (1, 1), (1, 2)]) } -/// Build the canonical NO bipartite instance from the issue (a perfect +/// Build the canonical NO bipartite instance (a perfect /// matching on 3+3 vertices: L = {l0, l1, l2}, R = {r0, r1, r2}, F = /// {(l0, r0), (l1, r1), (l2, r2)}). fn no_bipartite() -> BipartiteGraph { @@ -224,7 +224,6 @@ fn test_identity_on_random_bipartite_instances() { BipartiteGraph::new(2, 2, vec![(0, 0), (0, 1), (1, 0), (1, 1)]), // 3+3 perfect matching. no_bipartite(), - // Issue's YES instance. yes_bipartite(), ]; diff --git a/src/unit_tests/rules/minimummetricdimension_ilp.rs b/src/unit_tests/rules/minimummetricdimension_ilp.rs index 431e64235..05a842170 100644 --- a/src/unit_tests/rules/minimummetricdimension_ilp.rs +++ b/src/unit_tests/rules/minimummetricdimension_ilp.rs @@ -17,11 +17,9 @@ fn test_minimummetricdimension_to_ilp_closed_loop() { let bf = BruteForce::new(); let ilp_solver = ILPSolver::new(); - // Solve with brute force on original problem let bf_solutions = bf.find_all_witnesses(&problem).unwrap(); let bf_size = problem.evaluate(&bf_solutions[0]).unwrap(); - // Solve via ILP reduction let ilp_solution = ilp_solver.solve(ilp).expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_solution).unwrap(); let ilp_size = problem.evaluate(&extracted).unwrap(); @@ -30,7 +28,6 @@ fn test_minimummetricdimension_to_ilp_closed_loop() { assert_eq!(bf_size, Min(Some(2))); assert_eq!(ilp_size, Min(Some(2))); - // Verify the ILP solution is valid for the original problem assert!( problem.evaluate(&extracted).unwrap().is_valid(), "Extracted solution should be valid" @@ -45,7 +42,6 @@ fn test_minimummetricdimension_to_ilp_structure() { ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp = reduction.target_problem(); - // Check ILP structure assert_eq!(ilp.num_vars(), 3, "Should have one variable per vertex"); // C(3,2) = 3 pairs assert_eq!( @@ -126,7 +122,6 @@ fn test_minimummetricdimension_to_ilp_solution_extraction() { let extracted = reduction.extract_solution(&ilp_solution).unwrap(); assert_eq!(extracted, vec![true, false, false]); - // Verify this is a valid resolving set assert!(problem.evaluate(&extracted).unwrap().is_valid()); } diff --git a/src/unit_tests/rules/minimummultiwaycut_ilp.rs b/src/unit_tests/rules/minimummultiwaycut_ilp.rs index 95d63b69d..8b8fc34a3 100644 --- a/src/unit_tests/rules/minimummultiwaycut_ilp.rs +++ b/src/unit_tests/rules/minimummultiwaycut_ilp.rs @@ -5,7 +5,7 @@ use crate::topology::SimpleGraph; use crate::traits::Problem; use crate::types::Min; -/// Build the canonical 5-vertex, 3-terminal example from issue #185. +/// Build the canonical 5-vertex, 3-terminal example. fn canonical_instance() -> MinimumMultiwayCut { let graph = SimpleGraph::new(5, vec![(0, 1), (1, 2), (2, 3), (3, 4), (0, 4), (1, 3)]); MinimumMultiwayCut::new(graph, vec![0, 2, 4], vec![2, 3, 1, 2, 4, 5]) @@ -38,11 +38,9 @@ fn test_minimummultiwaycut_to_ilp_closed_loop() { let bf = BruteForce::new(); let ilp_solver = ILPSolver::new(); - // Solve original with brute force let bf_solutions = bf.find_all_witnesses(&problem).unwrap(); let bf_obj = problem.evaluate(&bf_solutions[0]).unwrap(); - // Solve via ILP let ilp_solution = ilp_solver.solve(ilp).expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_solution).unwrap(); let ilp_obj = problem.evaluate(&extracted).unwrap(); diff --git a/src/unit_tests/rules/minimumsetcovering_ilp.rs b/src/unit_tests/rules/minimumsetcovering_ilp.rs index ab5a48864..90fa2ce67 100644 --- a/src/unit_tests/rules/minimumsetcovering_ilp.rs +++ b/src/unit_tests/rules/minimumsetcovering_ilp.rs @@ -11,7 +11,6 @@ fn test_reduction_creates_valid_ilp() { ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp = reduction.target_problem(); - // Check ILP structure assert_eq!(ilp.num_vars(), 2, "Should have one variable per set"); assert_eq!( ilp.constraints().len(), @@ -33,7 +32,6 @@ fn test_reduction_weighted() { ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp = reduction.target_problem(); - // Check that weights are correctly transferred to objective let mut coeffs: Vec = vec![0; 2]; for &(var, coef) in ilp.objective() { coeffs[var] = coef; @@ -53,10 +51,8 @@ fn test_minimumsetcovering_to_ilp_closed_loop() { let bf = BruteForce::new(); let ilp_solver = ILPSolver::new(); - // Solve with brute force on original problem let bf_solutions = bf.find_all_witnesses(&problem).unwrap(); - // Solve via ILP reduction let ilp_solution = ilp_solver.solve(ilp).expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_solution).unwrap(); @@ -66,7 +62,6 @@ fn test_minimumsetcovering_to_ilp_closed_loop() { assert_eq!(bf_size, 2); assert_eq!(ilp_size, 2); - // Verify the ILP solution is valid for the original problem assert!( problem.evaluate(&extracted).unwrap().is_valid(), "Extracted solution should be valid" @@ -101,7 +96,6 @@ fn test_ilp_solution_equals_brute_force_weighted() { assert_eq!(bf_obj, Min(Some(6))); assert_eq!(ilp_obj, Min(Some(6))); - // Verify the solution selects S1 and S2 assert_eq!(extracted, vec![false, true, true]); } @@ -116,7 +110,6 @@ fn test_solution_extraction() { let extracted = reduction.extract_solution(&ilp_solution).unwrap(); assert_eq!(extracted, vec![true, true]); - // Verify this is a valid set cover assert!(problem.evaluate(&extracted).unwrap().is_valid()); } diff --git a/src/unit_tests/rules/minimumvertexcover_ensemblecomputation.rs b/src/unit_tests/rules/minimumvertexcover_ensemblecomputation.rs index b44823425..c3fd583fb 100644 --- a/src/unit_tests/rules/minimumvertexcover_ensemblecomputation.rs +++ b/src/unit_tests/rules/minimumvertexcover_ensemblecomputation.rs @@ -27,7 +27,6 @@ fn test_minimumvertexcover_to_ensemblecomputation_closed_loop() { ReduceTo::::reduce_to(&source).expect("reduction should succeed"); let target = reduction.target_problem(); - // Verify target structure assert_eq!(target.universe_size(), 3); // |V| + 1 assert_eq!(target.num_subsets(), 1); // |E| assert_eq!(target.budget(), 3); // |V| + |E| @@ -62,7 +61,6 @@ fn test_reduction_structure_triangle() { ReduceTo::::reduce_to(&source).expect("reduction should succeed"); let target = reduction.target_problem(); - // Verify sizes assert_eq!(target.universe_size(), 4); // 3 + 1 assert_eq!(target.num_subsets(), 3); // 3 edges assert_eq!(target.budget(), 6); // 3 + 3 diff --git a/src/unit_tests/rules/minimumvertexcover_maximumindependentset.rs b/src/unit_tests/rules/minimumvertexcover_maximumindependentset.rs index 53fd77c03..717dd55be 100644 --- a/src/unit_tests/rules/minimumvertexcover_maximumindependentset.rs +++ b/src/unit_tests/rules/minimumvertexcover_maximumindependentset.rs @@ -5,7 +5,6 @@ include!("../jl_helpers.rs"); #[test] fn test_minimumvertexcover_to_maximumindependentset_closed_loop() { - // Test with weighted problems let is_problem = MaximumIndependentSet::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![10, 20, 30]); let reduction = ReduceTo::>::reduce_to(&is_problem) diff --git a/src/unit_tests/rules/minimumvertexcover_minimumhittingset.rs b/src/unit_tests/rules/minimumvertexcover_minimumhittingset.rs index e80a1fcd3..1fe5d3766 100644 --- a/src/unit_tests/rules/minimumvertexcover_minimumhittingset.rs +++ b/src/unit_tests/rules/minimumvertexcover_minimumhittingset.rs @@ -4,7 +4,6 @@ use crate::solvers::BruteForce; #[test] fn test_minimumvertexcover_to_minimumhittingset_closed_loop() { - // 6-vertex graph from the issue example // Edges: {0,1}, {0,2}, {1,3}, {2,3}, {2,4}, {3,5}, {4,5}, {1,4} // Minimum vertex cover size = 3 (e.g., {0, 3, 4}) let vc_problem = MinimumVertexCover::new( @@ -71,7 +70,6 @@ fn test_vc_to_hs_triangle() { assert_eq!(hs_problem.get_set(i).unwrap().len(), 2); } - // Solve both and verify they match let solver = BruteForce::new(); let vc_solutions = solver.find_all_witnesses(&vc_problem).unwrap(); let hs_solutions = solver.find_all_witnesses(hs_problem).unwrap(); diff --git a/src/unit_tests/rules/minimumvertexcover_minimumsetcovering.rs b/src/unit_tests/rules/minimumvertexcover_minimumsetcovering.rs index 11accfa1f..c193b98ad 100644 --- a/src/unit_tests/rules/minimumvertexcover_minimumsetcovering.rs +++ b/src/unit_tests/rules/minimumvertexcover_minimumsetcovering.rs @@ -15,7 +15,6 @@ fn test_minimumvertexcover_to_minimumsetcovering_closed_loop() { .expect("reduction should succeed"); let sc_problem = reduction.target_problem(); - // Check the sets are constructed correctly assert_eq!(sc_problem.universe_size(), 2); // 2 edges assert_eq!(sc_problem.num_sets(), 3); // 3 vertices @@ -42,7 +41,6 @@ fn test_vc_to_sc_triangle() { assert_eq!(sc_problem.universe_size(), 3); assert_eq!(sc_problem.num_sets(), 3); - // Verify each vertex covers exactly 2 edges for i in 0..3 { let set = sc_problem.get_set(i).unwrap(); assert_eq!(set.len(), 2); @@ -61,7 +59,6 @@ fn test_vc_to_sc_weighted() { // Weights should be preserved - access via weights_ref method on the problem assert_eq!(*sc_problem.weights_ref(), vec![10, 1, 10]); - // Solve both ways let solver = BruteForce::new(); let vc_solutions = solver.find_all_witnesses(&vc_problem).unwrap(); let sc_solutions = solver.find_all_witnesses(sc_problem).unwrap(); diff --git a/src/unit_tests/rules/naesatisfiability_ilp.rs b/src/unit_tests/rules/naesatisfiability_ilp.rs index 287d57652..0f462d3eb 100644 --- a/src/unit_tests/rules/naesatisfiability_ilp.rs +++ b/src/unit_tests/rules/naesatisfiability_ilp.rs @@ -56,22 +56,7 @@ fn test_naesatisfiability_to_ilp_bf_vs_ilp() { #[test] fn test_naesatisfiability_to_ilp_infeasible() { - // Single clause with one literal: (x1) — cannot be NAE (only one literal, never both T and F) - // NAESatisfiability requires ≥2 literals per clause, so use: (x1 ∨ x1) - // Actually we need a proper infeasible NAE instance. - // Simplest: (x1 ∨ x1) — both literals same variable: NAE requires T and F but both are x1. - // Wait, we can use a 1-variable, 1-clause with both polarities excluded: - // Use (x1 ∨ ¬x1): if x1=T → T,F ✓ NAE; if x1=F → F,T ✓ NAE. This is always satisfiable. - // True infeasible: ((x1 ∨ x2) ∧ (x1 ∨ ¬x2) ∧ (¬x1 ∨ x2) ∧ (¬x1 ∨ ¬x2)) - // x1=T,x2=T: clause4 (F,F) — not NAE. x1=T,x2=F: clause3 (F,F) — not NAE. - // x1=F,x2=T: clause2 (F,T) — NAE ✓; clause4: (T,F) — NAE ✓; - // clause1 (F,T) — NAE ✓; clause3 (T,T) — NOT NAE. So not infeasible. - // Use all-same-sign clause: (x1 ∨ x2) ∧ (¬x1 ∨ ¬x2) ∧ (x1 ∨ ¬x1) makes it tricky. - // Simplest provably infeasible NAE instance: 1 variable, clause (x1 ∨ x1) - // but NAESatisfiability requires ≥2 literals. Let's verify with ILP that it's infeasible. - // Known infeasible NAE: only one variable, clause (x1 ∨ x1) — requires x1=T (for one true) - // but then both are T so no false literal. Requires x1=F too — contradiction. - // But NAESat requires ≥2 literals per clause, so use (x1, x1): + // Repeated x1 literals always agree, so the clause cannot contain both truth values. use crate::models::formula::CNFClause; let problem = NAESatisfiability::new(1, vec![CNFClause::new(vec![1, 1])]); let reduction: ReductionNAESATToILP = diff --git a/src/unit_tests/rules/naesatisfiability_maxcut.rs b/src/unit_tests/rules/naesatisfiability_maxcut.rs index b492d2436..78a6ac704 100644 --- a/src/unit_tests/rules/naesatisfiability_maxcut.rs +++ b/src/unit_tests/rules/naesatisfiability_maxcut.rs @@ -57,7 +57,6 @@ fn test_naesatisfiability_to_maxcut_single_clause() { #[test] fn test_naesatisfiability_to_maxcut_two_literal_clause() { - // Clause with 2 literals: (x1, ~x2) — always NAE-satisfying unless x1=T, x2=F or x1=F, x2=T... actually (x1, ~x2) is NAE-unsatisfied when both literals are same: x1=T,~x2=T (x2=F) or x1=F,~x2=F (x2=T). // NAE-satisfied when x1 != ~x2, i.e., x1 == x2. let naesat = NAESatisfiability::new(2, vec![CNFClause::new(vec![1, -2])]); let reduction = ReduceTo::>>::reduce_to(&naesat) @@ -115,7 +114,6 @@ fn test_naesatisfiability_to_maxcut_extract_solution() { let extracted = reduction.extract_solution(&target_config).unwrap(); assert_eq!(extracted, vec![true, false, true]); // x1=T, x2=F, x3=T - // Verify this is a valid NAE-SAT solution assert!(naesat.evaluate(&extracted).unwrap().0); } diff --git a/src/unit_tests/rules/numericalmatchingwithtargetsums_ilp.rs b/src/unit_tests/rules/numericalmatchingwithtargetsums_ilp.rs index 697129347..2c2061814 100644 --- a/src/unit_tests/rules/numericalmatchingwithtargetsums_ilp.rs +++ b/src/unit_tests/rules/numericalmatchingwithtargetsums_ilp.rs @@ -81,12 +81,7 @@ fn test_numericalmatchingwithtargetsums_to_ilp_single_pair() { #[test] fn test_numericalmatchingwithtargetsums_to_ilp_compatible_triples_only() { - // Verify that only compatible triples generate variables - // m=2, sizes_x=[1,2], sizes_y=[3,4], targets=[4,6] // Compatible: (0,0,0): 1+3=4, (1,1,1): 2+4=6 - // Also (0,1,1): 1+4=5≠6, (1,0,0): 2+3=5≠4 — NOT compatible - // Wait: (0,1,0): 1+4=5≠4, (1,0,1): 2+3=5≠6 — also not - // So only 2 variables let problem = NumericalMatchingWithTargetSums::new(vec![1, 2], vec![3, 4], vec![4, 6]); let reduction = ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp = reduction.target_problem(); diff --git a/src/unit_tests/rules/optimallineararrangement_consecutiveonesmatrixaugmentation.rs b/src/unit_tests/rules/optimallineararrangement_consecutiveonesmatrixaugmentation.rs index a081c4de7..86a41485d 100644 --- a/src/unit_tests/rules/optimallineararrangement_consecutiveonesmatrixaugmentation.rs +++ b/src/unit_tests/rules/optimallineararrangement_consecutiveonesmatrixaugmentation.rs @@ -7,7 +7,7 @@ use crate::topology::SimpleGraph; use crate::traits::Problem; use crate::types::Or; -/// The 6-vertex / 7-edge worked example from the issue (path + two chords). +/// The 6-vertex / 7-edge worked example (path + two chords). fn example_graph() -> SimpleGraph { SimpleGraph::new( 6, @@ -31,7 +31,6 @@ fn test_optimallineararrangement_to_consecutiveonesmatrixaugmentation_structure( assert_eq!(target.num_cols(), 6); // num_vertices assert_eq!(target.bound(), 4); // k - m = 11 - 7 - // Verify the incidence matrix encodes edge endpoints. let expected = vec![ vec![true, true, false, false, false, false], // {0,1} vec![false, true, true, false, false, false], // {1,2} diff --git a/src/unit_tests/rules/optimallineararrangement_ilp.rs b/src/unit_tests/rules/optimallineararrangement_ilp.rs index ca28a7d1c..bbece0bd3 100644 --- a/src/unit_tests/rules/optimallineararrangement_ilp.rs +++ b/src/unit_tests/rules/optimallineararrangement_ilp.rs @@ -28,7 +28,6 @@ fn test_optimallineararrangement_to_ilp_closed_loop() { .expect("brute-force should find a solution"); assert!(problem.evaluate(&bf_solution).unwrap().0.is_some()); - // Solve via ILP let reduction: ReductionOLAToILP = ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp_solver = ILPSolver::new(); @@ -58,7 +57,6 @@ fn test_optimallineararrangement_to_ilp_with_chords() { .expect("brute-force should find a solution"); assert!(problem.evaluate(&bf_solution).unwrap().0.is_some()); - // Solve via ILP let reduction: ReductionOLAToILP = ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp_solver = ILPSolver::new(); diff --git a/src/unit_tests/rules/paintshop_qubo.rs b/src/unit_tests/rules/paintshop_qubo.rs index e5b6343f2..6517f4ed3 100644 --- a/src/unit_tests/rules/paintshop_qubo.rs +++ b/src/unit_tests/rules/paintshop_qubo.rs @@ -4,7 +4,6 @@ use crate::solvers::BruteForce; #[test] fn test_paintshop_to_qubo_closed_loop() { - // Issue example: Sequence [A, B, C, A, D, B, D, C], 4 cars let source = PaintShop::new(vec!["A", "B", "C", "A", "D", "B", "D", "C"]); let reduction = ReduceTo::>::reduce_to(&source).expect("reduction should succeed"); let qubo = reduction.target_problem(); @@ -37,7 +36,7 @@ fn test_paintshop_to_qubo_simple() { #[test] fn test_paintshop_to_qubo_optimal_value() { - // Issue example verifies optimal QUBO = -1, total switches = -1 + 3 = 2 + // Optimal QUBO = -1, total switches = -1 + 3 = 2 let source = PaintShop::new(vec!["A", "B", "C", "A", "D", "B", "D", "C"]); let reduction = ReduceTo::>::reduce_to(&source).expect("reduction should succeed"); let qubo = reduction.target_problem(); @@ -56,13 +55,11 @@ fn test_paintshop_to_qubo_optimal_value() { #[test] fn test_paintshop_to_qubo_matrix_structure() { - // Issue example: verify the Q matrix matches expected values let source = PaintShop::new(vec!["A", "B", "C", "A", "D", "B", "D", "C"]); let reduction = ReduceTo::>::reduce_to(&source).expect("reduction should succeed"); let qubo = reduction.target_problem(); let m = qubo.matrix(); - // From the issue: // Q = [ -1, -2, 2, 2 ] // [ 0, 2, -2, 0 ] // [ 0, 0, 1, -2 ] diff --git a/src/unit_tests/rules/partitionintocliques_minimumcoveringbycliques.rs b/src/unit_tests/rules/partitionintocliques_minimumcoveringbycliques.rs index 064b7bacc..503e1abbf 100644 --- a/src/unit_tests/rules/partitionintocliques_minimumcoveringbycliques.rs +++ b/src/unit_tests/rules/partitionintocliques_minimumcoveringbycliques.rs @@ -79,7 +79,6 @@ fn test_partitionintocliques_to_minimumcoveringbycliques_orlin_example_structure assert!(target.graph().has_edge(3, 8)); assert!(target.graph().has_edge(4, 9)); - // Matching and gadget cross edges from the issue body assert!(target.graph().has_edge(0, 3)); assert!(target.graph().has_edge(1, 4)); assert!(target.graph().has_edge(0, 4)); diff --git a/src/unit_tests/rules/partitionintopathsoflength2_boundedcomponentspanningforest.rs b/src/unit_tests/rules/partitionintopathsoflength2_boundedcomponentspanningforest.rs index 81b97ac33..9ed00d230 100644 --- a/src/unit_tests/rules/partitionintopathsoflength2_boundedcomponentspanningforest.rs +++ b/src/unit_tests/rules/partitionintopathsoflength2_boundedcomponentspanningforest.rs @@ -15,7 +15,6 @@ fn test_partitionintopathsoflength2_to_boundedcomponentspanningforest_closed_loo .expect("reduction should succeed"); let target = result.target_problem(); - // Check target structure assert_eq!(target.num_vertices(), 6); assert_eq!(target.num_edges(), 4); assert_eq!(target.max_components(), 2); // K = 6/3 = 2 @@ -51,7 +50,6 @@ fn test_partitionintopathsoflength2_to_boundedcomponentspanningforest_no_solutio #[test] fn test_partitionintopathsoflength2_to_boundedcomponentspanningforest_triangle_partition() { - // 9-vertex graph from the issue example let source = PartitionIntoPathsOfLength2::new(SimpleGraph::new( 9, vec![ @@ -85,7 +83,6 @@ fn test_partitionintopathsoflength2_to_boundedcomponentspanningforest_triangle_p #[test] fn test_partitionintopathsoflength2_to_boundedcomponentspanningforest_extract_solution() { - // Verify extract_solution is identity let source = PartitionIntoPathsOfLength2::new(SimpleGraph::new(6, vec![(0, 1), (1, 2), (3, 4), (4, 5)])); let result = ReduceTo::>::reduce_to(&source) diff --git a/src/unit_tests/rules/quadraticassignment_ilp.rs b/src/unit_tests/rules/quadraticassignment_ilp.rs index c68fd73e1..9e2950022 100644 --- a/src/unit_tests/rules/quadraticassignment_ilp.rs +++ b/src/unit_tests/rules/quadraticassignment_ilp.rs @@ -28,7 +28,6 @@ fn test_quadraticassignment_to_ilp_closed_loop() { let bf_solution = bf.solve(&problem).unwrap().expect("brute-force optimum"); let bf_value = problem.evaluate(&bf_solution).unwrap(); - // Solve via ILP let reduction: ReductionQAPToILP = ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp_solver = ILPSolver::new(); @@ -57,7 +56,6 @@ fn test_quadraticassignment_to_ilp_2x2() { let bf_solution = bf.solve(&problem).unwrap().expect("brute-force optimum"); let bf_value = problem.evaluate(&bf_solution).unwrap(); - // Solve via ILP let reduction: ReductionQAPToILP = ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp_solver = ILPSolver::new(); @@ -97,7 +95,6 @@ fn test_quadraticassignment_to_ilp_rectangular() { let bf_solution = bf.solve(&problem).unwrap().expect("brute-force optimum"); let bf_value = problem.evaluate(&bf_solution).unwrap(); - // Solve via ILP let reduction: ReductionQAPToILP = ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp_solver = ILPSolver::new(); diff --git a/src/unit_tests/rules/reduction_path_parity.rs b/src/unit_tests/rules/reduction_path_parity.rs index cb1490a2a..8def3533f 100644 --- a/src/unit_tests/rules/reduction_path_parity.rs +++ b/src/unit_tests/rules/reduction_path_parity.rs @@ -51,7 +51,6 @@ fn test_jl_parity_maxcut_to_spinglass_path() { .expect("Should reduce along path"); let target: &SpinGlass = chain.target_problem(); - // Verify target is SpinGlass assert_eq!(SpinGlass::::NAME, "SpinGlass"); let solver = BruteForce::new(); @@ -132,7 +131,6 @@ fn test_jl_parity_factoring_to_spinglass_path() { .expect("Should reduce along path"); let target: &SpinGlass = chain.target_problem(); - // Verify reduction produces a valid SpinGlass problem assert!( target.num_variables() > 0, "SpinGlass should have variables" diff --git a/src/unit_tests/rules/rootedtreearrangement_rootedtreestorageassignment.rs b/src/unit_tests/rules/rootedtreearrangement_rootedtreestorageassignment.rs index da6346190..dadd89f41 100644 --- a/src/unit_tests/rules/rootedtreearrangement_rootedtreestorageassignment.rs +++ b/src/unit_tests/rules/rootedtreearrangement_rootedtreestorageassignment.rs @@ -92,7 +92,6 @@ fn test_rootedtreearrangement_to_rootedtreestorageassignment_solution_extraction // Source config should be [parent_array | identity_mapping] = [0, 0, 0, 1] assert_eq!(source_config, vec![0, 0, 0, 1]); - // Verify it's valid for the source assert!(source.is_valid_solution(&source_config).unwrap()); } diff --git a/src/unit_tests/rules/sat_coloring.rs b/src/unit_tests/rules/sat_coloring.rs index 42fc5e598..08a093d1d 100644 --- a/src/unit_tests/rules/sat_coloring.rs +++ b/src/unit_tests/rules/sat_coloring.rs @@ -13,11 +13,9 @@ fn test_constructor_basic_structure() { // Should have 2*2 + 3 = 7 vertices assert_eq!(constructor.num_vertices, 7); - // Check pos_vertices and neg_vertices assert_eq!(constructor.pos_vertices, vec![3, 4]); assert_eq!(constructor.neg_vertices, vec![5, 6]); - // Check vmap assert_eq!(constructor.vmap[&(0, false)], 3); assert_eq!(constructor.vmap[&(0, true)], 5); assert_eq!(constructor.vmap[&(1, false)], 4); @@ -80,8 +78,6 @@ fn test_unsatisfiable_formula() { let solver = BruteForce::new(); let solutions = solver.find_all_witnesses(coloring).unwrap(); - // For an unsatisfiable formula, the coloring should have no valid solutions - // OR no valid coloring exists that extracts to a satisfying SAT assignment let mut found_satisfying = false; for sol in &solutions { let sat_sol = reduction.extract_solution(sol).unwrap(); @@ -91,13 +87,6 @@ fn test_unsatisfiable_formula() { } } - // The coloring should not yield a satisfying SAT assignment - // because the formula is unsatisfiable - // Note: The coloring graph itself may still be colorable, - // but the constraints should make it impossible for both - // x1 and NOT x1 to be TRUE color simultaneously - // Actually, let's check if ANY coloring solution produces a valid SAT solution - // If the formula is unsat, no valid coloring should extract to a satisfying assignment assert!( !found_satisfying, "Unsatisfiable formula should not produce satisfying assignment" @@ -133,7 +122,6 @@ fn test_coloring_structure() { ReduceTo::>::reduce_to(&sat).expect("reduction should succeed"); let coloring = reduction.target_problem(); - // Verify coloring has expected structure assert!(coloring.graph().num_vertices() > 0); assert_eq!(coloring.num_colors(), 3); } @@ -146,19 +134,6 @@ fn test_extract_solution_basic() { ReduceTo::>::reduce_to(&sat).expect("reduction should succeed"); // Manually construct a valid coloring where x1 has TRUE color - // Vertices: 0=TRUE, 1=FALSE, 2=AUX, 3=x1, 4=NOT_x1 - // Colors: TRUE=0, FALSE=1, AUX=2 - // For x1 to be true, pos_vertex[0]=3 should have color 0 (TRUE) - - // A valid coloring that satisfies x1=TRUE: - // - Vertex 0 (TRUE): color 0 - // - Vertex 1 (FALSE): color 1 - // - Vertex 2 (AUX): color 2 - // - Vertex 3 (x1): color 0 (TRUE) - connected to AUX(2), NOT_x1(4) - // - Vertex 4 (NOT_x1): color 1 (FALSE) - connected to AUX(2), x1(3) - - // However, the actual coloring depends on the full graph structure - // Let's just verify the extraction logic works by checking type signatures assert_eq!(reduction.pos_vertices().len(), 1); assert_eq!(reduction.neg_vertices().len(), 1); } @@ -243,11 +218,9 @@ fn test_num_clauses_accessor() { #[test] fn test_or_gadget_construction() { - // Test that OR gadget is correctly added let mut constructor = SATColoringConstructor::new(2); let initial_vertices = constructor.num_vertices; - // Add an OR gadget let input1 = constructor.pos_vertices[0]; // x1 let input2 = constructor.pos_vertices[1]; // x2 let output = constructor.add_or_gadget(input1, input2); diff --git a/src/unit_tests/rules/sat_ksat.rs b/src/unit_tests/rules/sat_ksat.rs index 4e4cfa7c5..c62ec5549 100644 --- a/src/unit_tests/rules/sat_ksat.rs +++ b/src/unit_tests/rules/sat_ksat.rs @@ -109,7 +109,6 @@ fn test_sat_to_3sat_single_literal() { #[test] fn test_sat_to_ksat_closed_loop() { - // Create a SAT formula and verify the 3-SAT version is equisatisfiable let sat = Satisfiability::new( 3, vec![ @@ -123,7 +122,6 @@ fn test_sat_to_ksat_closed_loop() { ReduceTo::>::reduce_to(&sat).expect("reduction should succeed"); let ksat = reduction.target_problem(); - // Solve both problems - use find_all_witnesses for satisfaction problems let solver = BruteForce::new(); let sat_solutions = solver.find_all_witnesses(&sat).unwrap(); @@ -135,7 +133,6 @@ fn test_sat_to_ksat_closed_loop() { assert_eq!(sat_satisfiable, ksat_satisfiable); - // Extract solutions should map back correctly if ksat_satisfiable { assert_satisfaction_round_trip_from_satisfaction_target( &sat, @@ -153,11 +150,9 @@ fn test_sat_to_3sat_solution_extraction() { ReduceTo::>::reduce_to(&sat).expect("reduction should succeed"); let ksat = reduction.target_problem(); - // Solve K-SAT - use find_all_witnesses for satisfaction problems let solver = BruteForce::new(); let ksat_solutions = solver.find_all_witnesses(ksat).unwrap(); - // Extract and verify solutions for ksat_sol in &ksat_solutions { let sat_sol = reduction.extract_solution(ksat_sol).unwrap(); // Should only have original 2 variables @@ -183,7 +178,6 @@ fn test_3sat_to_sat() { assert_eq!(sat.num_vars(), 3); assert_eq!(sat.num_clauses(), 2); - // Verify clauses are preserved assert_eq!(sat.clauses()[0].literals, vec![1, 2, 3]); assert_eq!(sat.clauses()[1].literals, vec![-1, -2, 3]); } @@ -216,7 +210,6 @@ fn test_roundtrip_sat_3sat_sat() { let to_sat = ReduceTo::::reduce_to(ksat).expect("reduction should succeed"); let final_sat = to_sat.target_problem(); - // Solve all three - use find_all_witnesses for satisfaction problems let solver = BruteForce::new(); let orig_solutions = solver.find_all_witnesses(&original_sat).unwrap(); @@ -298,7 +291,6 @@ fn test_mixed_clause_sizes() { assert_eq!(clause.len(), 3); } - // Verify satisfiability is preserved - use find_all_witnesses for satisfaction problems assert_satisfaction_round_trip_from_satisfaction_target( &sat, &reduction, diff --git a/src/unit_tests/rules/schedulingtominimizeweightedcompletiontime_ilp.rs b/src/unit_tests/rules/schedulingtominimizeweightedcompletiontime_ilp.rs index 52f8d9957..500ee00c6 100644 --- a/src/unit_tests/rules/schedulingtominimizeweightedcompletiontime_ilp.rs +++ b/src/unit_tests/rules/schedulingtominimizeweightedcompletiontime_ilp.rs @@ -85,7 +85,7 @@ fn test_ilp_matches_bruteforce_small() { #[test] fn test_issue_example_closed_loop() { - // Issue #505 example: 5 tasks, 2 processors, optimal = 47 + // Example: 5 tasks, 2 processors, optimal = 47 let problem = SchedulingToMinimizeWeightedCompletionTime::new( vec![1, 2, 3, 4, 5], vec![6, 4, 3, 2, 1], diff --git a/src/unit_tests/rules/sequencingtominimizemaximumcumulativecost_ilp.rs b/src/unit_tests/rules/sequencingtominimizemaximumcumulativecost_ilp.rs index b3ce0d01f..e570bd703 100644 --- a/src/unit_tests/rules/sequencingtominimizemaximumcumulativecost_ilp.rs +++ b/src/unit_tests/rules/sequencingtominimizemaximumcumulativecost_ilp.rs @@ -16,7 +16,6 @@ fn test_sequencingtominimizemaximumcumulativecost_to_ilp_closed_loop() { let bf_solution = bf.solve(&problem).unwrap().expect("brute-force optimum"); let bf_value = problem.evaluate(&bf_solution).unwrap(); - // Solve the ILP target with the ILP solver let ilp_solution = ILPSolver::new() .solve(reduction.target_problem()) .expect("ILP should be solvable"); diff --git a/src/unit_tests/rules/sequencingwithinintervals_ilp.rs b/src/unit_tests/rules/sequencingwithinintervals_ilp.rs index 4f4a6c7e6..db289afef 100644 --- a/src/unit_tests/rules/sequencingwithinintervals_ilp.rs +++ b/src/unit_tests/rules/sequencingwithinintervals_ilp.rs @@ -24,7 +24,6 @@ fn test_sequencingwithinintervals_to_ilp_structure() { ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp = reduction.target_problem(); - // task 0 has 1 start slot (d-r-l+1=3-0-2+1=2, so 2 offsets: 0 or 1... wait) // dim for task 0: d[0]-r[0]-l[0]+1 = 3-0-2+1 = 2 offsets // dim for task 1: d[1]-r[1]-l[1]+1 = 5-2-2+1 = 2 offsets // total vars = 2 + 2 = 4 diff --git a/src/unit_tests/rules/spinglass_maxcut.rs b/src/unit_tests/rules/spinglass_maxcut.rs index 75faf6fd8..f47e49a35 100644 --- a/src/unit_tests/rules/spinglass_maxcut.rs +++ b/src/unit_tests/rules/spinglass_maxcut.rs @@ -63,14 +63,12 @@ fn test_weighted_maxcut() { ReduceTo::>::reduce_to(&mc).expect("reduction should succeed"); let sg = reduction.target_problem(); - // Verify interactions have correct weights let interactions = sg.interactions(); assert_eq!(interactions.len(), 2); } #[test] fn test_reduction_structure() { - // Test MaxCut to SpinGlass structure let mc = MaxCut::<_, i64>::unweighted(SimpleGraph::new(3, vec![(0, 1), (1, 2)])); let reduction = ReduceTo::>::reduce_to(&mc).expect("reduction should succeed"); @@ -79,7 +77,6 @@ fn test_reduction_structure() { // SpinGlass should have same number of spins as vertices assert_eq!(sg.num_spins(), 3); - // Test SpinGlass to MaxCut structure let sg2 = SpinGlass::::new(3, vec![((0, 1), 1)], vec![0, 0, 0]).unwrap(); let reduction2 = ReduceTo::>::reduce_to(&sg2).expect("reduction should succeed"); diff --git a/src/unit_tests/rules/spinglass_qubo.rs b/src/unit_tests/rules/spinglass_qubo.rs index 97de04644..7e1c7bb5d 100644 --- a/src/unit_tests/rules/spinglass_qubo.rs +++ b/src/unit_tests/rules/spinglass_qubo.rs @@ -53,7 +53,6 @@ fn test_with_onsite_fields() { #[test] fn test_reduction_structure() { - // Test QUBO to SpinGlass structure let qubo = QUBO::from_matrix(vec![vec![1.0, -2.0], vec![0.0, 1.0]]).unwrap(); let reduction = ReduceTo::>::reduce_to(&qubo) .expect("reduction should succeed"); @@ -62,7 +61,6 @@ fn test_reduction_structure() { // SpinGlass should have same number of spins as QUBO variables assert_eq!(sg.num_spins(), 2); - // Test SpinGlass to QUBO structure let sg2 = SpinGlass::::new(3, vec![((0, 1), -1.0)], vec![0.0, 0.0, 0.0]).unwrap(); let reduction2 = ReduceTo::>::reduce_to(&sg2).expect("reduction should succeed"); diff --git a/src/unit_tests/rules/stringtostringcorrection_ilp.rs b/src/unit_tests/rules/stringtostringcorrection_ilp.rs index 83354d82f..7f7b1597e 100644 --- a/src/unit_tests/rules/stringtostringcorrection_ilp.rs +++ b/src/unit_tests/rules/stringtostringcorrection_ilp.rs @@ -57,7 +57,6 @@ fn test_stringtostringcorrection_to_ilp_infeasible() { // The ILP is trivially infeasible (0 vars, unsatisfiable constraint) let problem = StringToStringCorrection::new(2, vec![0], vec![0, 1], 1); - // Verify the source problem is actually infeasible let bf = BruteForce::new(); let bf_witness = bf.solve(&problem).unwrap(); assert!(bf_witness.is_none(), "source should be infeasible"); diff --git a/src/unit_tests/rules/strongconnectivityaugmentation_ilp.rs b/src/unit_tests/rules/strongconnectivityaugmentation_ilp.rs index a9062a5f4..3e6b5fc48 100644 --- a/src/unit_tests/rules/strongconnectivityaugmentation_ilp.rs +++ b/src/unit_tests/rules/strongconnectivityaugmentation_ilp.rs @@ -22,12 +22,10 @@ fn test_strongconnectivityaugmentation_to_ilp_closed_loop() { ReduceTo::>::reduce_to(&source).expect("reduction should succeed"); let ilp = reduction.target_problem(); - // Solve source with brute force let bf = BruteForce::new(); let bf_solutions = bf.find_all_witnesses(&source).unwrap(); assert!(!bf_solutions.is_empty(), "source should be satisfiable"); - // Solve ILP let ilp_solver = ILPSolver::new(); let ilp_sol = ilp_solver.solve(ilp).expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_sol).unwrap(); diff --git a/src/unit_tests/rules/subgraphisomorphism_ilp.rs b/src/unit_tests/rules/subgraphisomorphism_ilp.rs index cd7fe8f07..fc4f1ff87 100644 --- a/src/unit_tests/rules/subgraphisomorphism_ilp.rs +++ b/src/unit_tests/rules/subgraphisomorphism_ilp.rs @@ -33,7 +33,6 @@ fn test_subgraphisomorphism_to_ilp_closed_loop() { .expect("brute-force should find a solution"); assert_eq!(problem.evaluate(&bf_solution).unwrap(), Or(true)); - // Solve via ILP let reduction: ReductionSubIsoToILP = ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp_solver = ILPSolver::new(); @@ -63,7 +62,6 @@ fn test_subgraphisomorphism_to_ilp_path_in_cycle() { .expect("brute-force should find a solution"); assert_eq!(problem.evaluate(&bf_solution).unwrap(), Or(true)); - // Solve via ILP let reduction: ReductionSubIsoToILP = ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp_solver = ILPSolver::new(); diff --git a/src/unit_tests/rules/threepartition_resourceconstrainedscheduling.rs b/src/unit_tests/rules/threepartition_resourceconstrainedscheduling.rs index 33bac8549..ec670b095 100644 --- a/src/unit_tests/rules/threepartition_resourceconstrainedscheduling.rs +++ b/src/unit_tests/rules/threepartition_resourceconstrainedscheduling.rs @@ -49,7 +49,6 @@ fn test_threepartition_to_resourceconstrainedscheduling_structure() { assert_eq!(target.resource_bounds(), &[15]); assert_eq!(target.deadline(), 2); // m = 6/3 = 2 - // Check resource requirements match sizes for (i, req) in target.resource_requirements().iter().enumerate() { assert_eq!(req.len(), 1); assert_eq!(req[0], source.sizes()[i]); @@ -99,21 +98,7 @@ fn test_threepartition_to_resourceconstrainedscheduling_single_triple() { #[test] fn test_threepartition_to_resourceconstrainedscheduling_two_triples() { - // sizes [4, 4, 7, 4, 4, 7], B=15, m=2 - // Only valid grouping of triples summing to 15: {4, 4, 7} and {4, 4, 7} - // This is actually feasible. Let's pick something infeasible. - // sizes [5, 5, 5, 5, 5, 5], B=15, m=2 — all equal, any triple sums to 15. Feasible. - // - // For infeasibility within the 3-Partition constraints (B/4 < a_i < B/2), - // we need sum = m*B but no valid partition. With m=1, B=15: - // sizes [4, 4, 7] sums to 15 — feasible. - // Actually constructing an infeasible instance that satisfies B/4 < a_i < B/2 - // and sum = m*B is non-trivial for small instances. We test feasible cases - // and rely on the closed-loop test for correctness. - // - // Test with m=2, B=21, sizes [6,7,8,6,7,8] sum=42=2*21 - // B/4=5.25, B/2=10.5, all sizes in (5.25, 10.5) ✓ - // Partition: {6,7,8}=21 and {6,7,8}=21 ✓ + // Two {6,7,8} triples meet B=21, with each size strictly between B/4 and B/2. let (source, reduction) = reduce_three_partition(&[6, 7, 8, 6, 7, 8], 21); let target = reduction.target_problem(); diff --git a/src/unit_tests/rules/travelingsalesman_ilp.rs b/src/unit_tests/rules/travelingsalesman_ilp.rs index 04916fa25..db769d063 100644 --- a/src/unit_tests/rules/travelingsalesman_ilp.rs +++ b/src/unit_tests/rules/travelingsalesman_ilp.rs @@ -43,7 +43,6 @@ fn test_reduction_c4_closed_loop() { let ilp_solution = ilp_solver.solve(ilp).expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_solution).unwrap(); - // Verify extracted solution is valid on source problem let metric = problem.evaluate(&extracted).unwrap(); assert!(metric.is_valid(), "Extracted solution must be valid"); assert_eq!(metric, Min(Some(4))); @@ -54,7 +53,6 @@ fn test_reduction_k4_weighted_closed_loop() { // K4 weighted: find minimum weight Hamiltonian cycle let problem = k4_tsp(); - // Solve via ILP reduction let reduction: ReductionTSPToILP = ReduceTo::>::reduce_to(&problem).expect("reduction should succeed"); let ilp = reduction.target_problem(); @@ -62,7 +60,6 @@ fn test_reduction_k4_weighted_closed_loop() { let ilp_solution = ilp_solver.solve(ilp).expect("ILP should be solvable"); let extracted = reduction.extract_solution(&ilp_solution).unwrap(); - // Solve via brute force for cross-check let bf = BruteForce::new(); let bf_solutions = bf.find_all_witnesses(&problem).unwrap(); let bf_metric = problem.evaluate(&bf_solutions[0]).unwrap(); diff --git a/src/unit_tests/rules/unitdiskmapping/copyline.rs b/src/unit_tests/rules/unitdiskmapping/copyline.rs index a5a3259b5..e9ef79150 100644 --- a/src/unit_tests/rules/unitdiskmapping/copyline.rs +++ b/src/unit_tests/rules/unitdiskmapping/copyline.rs @@ -272,10 +272,8 @@ fn test_create_copylines_petersen() { let lines = create_copylines(10, &edges, &order).unwrap(); - // Verify all lines are created assert_eq!(lines.len(), 10); - // Verify basic invariants for (i, &v) in order.iter().enumerate() { let line = &lines[v]; assert_eq!(line.vertex, v, "Vertex mismatch"); @@ -292,7 +290,6 @@ fn test_create_copylines_petersen() { ); } - // Verify that neighboring vertices have overlapping L-shapes for &(u, v) in &edges { let line_u = &lines[u]; let line_v = &lines[v]; diff --git a/src/unit_tests/rules/unitdiskmapping/ksg/mapping.rs b/src/unit_tests/rules/unitdiskmapping/ksg/mapping.rs index e97765904..b168ebf08 100644 --- a/src/unit_tests/rules/unitdiskmapping/ksg/mapping.rs +++ b/src/unit_tests/rules/unitdiskmapping/ksg/mapping.rs @@ -29,7 +29,6 @@ fn test_map_weighted_triangle() { fn test_mapping_result_config_back_unweighted() { let edges = vec![(0, 1)]; let result = map_unweighted(2, &edges).unwrap(); - // Create a dummy config let config: Vec = vec![0; result.positions.len()]; let original = result.map_config_back(&config).unwrap(); assert_eq!(original.len(), 2); @@ -39,7 +38,6 @@ fn test_mapping_result_config_back_unweighted() { fn test_mapping_result_config_back_weighted() { let edges = vec![(0, 1)]; let result = map_weighted(2, &edges).unwrap(); - // Create a dummy config let config: Vec = vec![0; result.positions.len()]; let original = result.map_config_back(&config).unwrap(); assert_eq!(original.len(), 2); @@ -57,11 +55,9 @@ fn test_mapping_result_config_back_rejects_wrong_length() { #[test] fn test_map_config_copyback_simple() { - // Create a simple copyline let line = CopyLine::new(0, 1, 1, 1, 1, 3); let lines = vec![line]; - // Create config with some nodes selected let locs = lines[0].copyline_locations(PADDING, SPACING); let (rows, cols) = (20, 20); let mut config = vec![vec![0; cols]; rows]; diff --git a/src/unit_tests/rules/unitdiskmapping/pathdecomposition.rs b/src/unit_tests/rules/unitdiskmapping/pathdecomposition.rs index 015f6979a..abff2ea55 100644 --- a/src/unit_tests/rules/unitdiskmapping/pathdecomposition.rs +++ b/src/unit_tests/rules/unitdiskmapping/pathdecomposition.rs @@ -221,7 +221,7 @@ fn test_pathwidth_auto_large() { #[test] fn test_pathwidth_greedy_is_deterministic() { - // Reproduces issue #1061: pathwidth greedy must be deterministic across calls. + // pathwidth greedy must be deterministic across calls. // Graph is large enough that Auto picks Greedy and tie-breaking in greedy_step // is exercised (grid with many symmetric choices). let n = 64; diff --git a/src/unit_tests/solvers/customized/solver.rs b/src/unit_tests/solvers/customized/solver.rs index 80aa6c967..252c498ff 100644 --- a/src/unit_tests/solvers/customized/solver.rs +++ b/src/unit_tests/solvers/customized/solver.rs @@ -344,7 +344,6 @@ fn test_customized_solver_minimum_cardinality_key_finds_minimum() { let custom = CustomizedTestSolver::new().solve_dyn(&problem); assert!(brute.is_some()); assert!(custom.is_some()); - // Verify optimality: customized solver returns same value as brute force let brute_val = problem.evaluate(brute.as_ref().unwrap()).unwrap(); let custom_val = problem.evaluate(custom.as_ref().unwrap()).unwrap(); assert_eq!( diff --git a/src/unit_tests/topology/graph.rs b/src/unit_tests/topology/graph.rs index f98e2e4d2..42efd2cbb 100644 --- a/src/unit_tests/topology/graph.rs +++ b/src/unit_tests/topology/graph.rs @@ -128,7 +128,6 @@ fn test_simple_graph_cycle_small() { #[test] fn test_simple_graph_eq_different_sizes() { - // Test PartialEq when graphs have different sizes let g1 = SimpleGraph::new(3, vec![(0, 1)]); let g2 = SimpleGraph::new(4, vec![(0, 1)]); // Different vertex count assert_ne!(g1, g2); diff --git a/src/unit_tests/topology/unit_disk_graph.rs b/src/unit_tests/topology/unit_disk_graph.rs index 8eda99d22..4693ffbfc 100644 --- a/src/unit_tests/topology/unit_disk_graph.rs +++ b/src/unit_tests/topology/unit_disk_graph.rs @@ -92,8 +92,6 @@ fn test_udg_grid_diagonal() { // With radius > sqrt(2), diagonals are also connected let udg = UnitDiskGraph::grid(2, 2, 1.0, 1.5).unwrap(); assert_eq!(udg.num_vertices(), 4); - // All pairs are connected (4 edges: 0-1, 0-2, 0-3, 1-2, 1-3, 2-3) - // Actually: 0-1 (1.0), 0-2 (1.0), 1-3 (1.0), 2-3 (1.0), 0-3 (sqrt(2)≈1.41), 1-2 (sqrt(2)≈1.41) assert_eq!(udg.num_edges(), 6); } @@ -124,7 +122,6 @@ fn test_udg_vertex_distance_invalid() { #[test] fn test_udg_graph_trait() { - // Test the Graph trait implementation let udg = UnitDiskGraph::new(vec![(0.0, 0.0), (1.0, 0.0), (0.5, 0.5)], 1.0).unwrap(); // Use Graph trait methods assert_eq!(Graph::num_vertices(&udg), 3); diff --git a/src/unit_tests/types.rs b/src/unit_tests/types.rs index ac53023b0..f3bf96ba1 100644 --- a/src/unit_tests/types.rs +++ b/src/unit_tests/types.rs @@ -187,15 +187,12 @@ fn test_extremum_reports_invalid_combinations() { fn test_one() { let one = One; - // Test Display assert_eq!(format!("{}", one), "One"); - // Test Clone, Copy, Default let one2 = one; let _one3 = one2; // Copy works (no clone needed) let _one4: One = Default::default(); - // Test PartialEq assert_eq!(One, One); assert_eq!(One::unit(), One); @@ -263,7 +260,6 @@ fn test_weight_element_one() { let one = One; assert_eq!(one.to_sum(), 1); - // Verify associated type fn assert_weight_element() {} assert_weight_element::(); } diff --git a/src/unit_tests/unitdiskmapping_algorithms/copyline.rs b/src/unit_tests/unitdiskmapping_algorithms/copyline.rs index 179ca77ea..aa6b44a60 100644 --- a/src/unit_tests/unitdiskmapping_algorithms/copyline.rs +++ b/src/unit_tests/unitdiskmapping_algorithms/copyline.rs @@ -9,7 +9,6 @@ use crate::rules::unitdiskmapping::{ #[test] fn test_create_copylines_empty_graph() { - // Test with no edges let edges: Vec<(usize, usize)> = vec![]; let order = vec![0, 1, 2]; let copylines = create_copylines(3, &edges, &order).unwrap(); @@ -36,7 +35,6 @@ fn test_mis_overhead_copyline_basic() { #[test] fn test_mis_overhead_copyline_zero_hstop() { - // Test edge case with minimal hstop let line = CopyLine::new(0, 1, 1, 1, 1, 1); let _overhead = mis_overhead_copyline(&line, 4, 2); @@ -85,7 +83,6 @@ fn test_copyline_center_location() { #[test] fn test_copyline_center_location_offset() { - // Test with different padding and spacing let line = CopyLine::new(0, 1, 1, 1, 1, 2); let (row, col) = line.center_location(2, 4); // Rust 0-indexed: row = 4 * (1-1) + 2 + 2 - 1 = 3 @@ -313,7 +310,6 @@ fn test_copyline_weighted_mis_equals_overhead() { // Create copyline with vslot=5, hslot=5 (matching Julia's test) let line = CopyLine::new(0, 5, 5, vstart as usize, vstop as usize, hstop as usize); - // Get copyline locations with weights let locs = line.copyline_locations(padding, spacing as usize); let n = locs.len(); @@ -352,7 +348,6 @@ fn test_copyline_weighted_mis_equals_overhead() { let weights: Vec = locs.iter().map(|&(_, _, w)| w as i64).collect(); - // Solve weighted MIS let weighted_mis = solve_weighted_mis(n, &edges, &weights); // Calculate expected value using Julia's weighted formula: diff --git a/src/unit_tests/unitdiskmapping_algorithms/gadgets.rs b/src/unit_tests/unitdiskmapping_algorithms/gadgets.rs index d0bfa0434..aaa006309 100644 --- a/src/unit_tests/unitdiskmapping_algorithms/gadgets.rs +++ b/src/unit_tests/unitdiskmapping_algorithms/gadgets.rs @@ -117,49 +117,42 @@ fn test_all_gadgets_have_valid_pins() { assert!(mapped_pins.iter().all(|&p| p < mapped_locs.len())); assert_eq!(source_pins.len(), mapped_pins.len()); - // Test Turn let (source_locs, _, source_pins) = KsgTurn.source_graph(); let (mapped_locs, mapped_pins) = KsgTurn.mapped_graph(); assert!(source_pins.iter().all(|&p| p < source_locs.len())); assert!(mapped_pins.iter().all(|&p| p < mapped_locs.len())); assert_eq!(source_pins.len(), mapped_pins.len()); - // Test WTurn let (source_locs, _, source_pins) = KsgWTurn.source_graph(); let (mapped_locs, mapped_pins) = KsgWTurn.mapped_graph(); assert!(source_pins.iter().all(|&p| p < source_locs.len())); assert!(mapped_pins.iter().all(|&p| p < mapped_locs.len())); assert_eq!(source_pins.len(), mapped_pins.len()); - // Test Branch let (source_locs, _, source_pins) = KsgBranch.source_graph(); let (mapped_locs, mapped_pins) = KsgBranch.mapped_graph(); assert!(source_pins.iter().all(|&p| p < source_locs.len())); assert!(mapped_pins.iter().all(|&p| p < mapped_locs.len())); assert_eq!(source_pins.len(), mapped_pins.len()); - // Test BranchFix let (source_locs, _, source_pins) = KsgBranchFix.source_graph(); let (mapped_locs, mapped_pins) = KsgBranchFix.mapped_graph(); assert!(source_pins.iter().all(|&p| p < source_locs.len())); assert!(mapped_pins.iter().all(|&p| p < mapped_locs.len())); assert_eq!(source_pins.len(), mapped_pins.len()); - // Test TCon let (source_locs, _, source_pins) = KsgTCon.source_graph(); let (mapped_locs, mapped_pins) = KsgTCon.mapped_graph(); assert!(source_pins.iter().all(|&p| p < source_locs.len())); assert!(mapped_pins.iter().all(|&p| p < mapped_locs.len())); assert_eq!(source_pins.len(), mapped_pins.len()); - // Test TrivialTurn let (source_locs, _, source_pins) = KsgTrivialTurn.source_graph(); let (mapped_locs, mapped_pins) = KsgTrivialTurn.mapped_graph(); assert!(source_pins.iter().all(|&p| p < source_locs.len())); assert!(mapped_pins.iter().all(|&p| p < mapped_locs.len())); assert_eq!(source_pins.len(), mapped_pins.len()); - // Test EndTurn let (source_locs, _, source_pins) = KsgEndTurn.source_graph(); let (mapped_locs, mapped_pins) = KsgEndTurn.mapped_graph(); assert!(source_pins.iter().all(|&p| p < source_locs.len())); @@ -816,7 +809,6 @@ fn test_all_ksg_weighted_gadgets_mis_equivalence() { #[test] fn test_pattern_source_matrix() { - // Test source_matrix generation for all gadgets let cross_matrix = KsgCross::.source_matrix(); assert!(!cross_matrix.is_empty()); @@ -852,7 +844,6 @@ fn test_pattern_mapped_matrix() { #[test] fn test_weighted_pattern_weights_length() { - // Verify weights match location counts let (src_locs, _, _) = WeightedKsgCross::.source_graph(); let src_weights = WeightedKsgCross::.source_weights(); assert_eq!(src_locs.len(), src_weights.len()); @@ -895,7 +886,6 @@ fn test_all_weighted_gadgets_weights_positive() { #[test] fn test_gadget_is_connected_variants() { - // Test is_connected() method assert!(KsgCross::.is_connected()); assert!(!KsgCross::.is_connected()); @@ -953,7 +943,6 @@ fn test_triangular_gadget_mapped_matrix() { #[test] fn test_triangular_gadget_weights() { - // Test that weights are returned correctly let src_weights = WeightedTriTurn.source_weights(); let map_weights = WeightedTriTurn.mapped_weights(); assert!(!src_weights.is_empty()); @@ -966,7 +955,6 @@ fn test_triangular_gadget_weights() { #[test] fn test_triangular_gadget_connected_nodes() { - // Test connected gadgets let nodes = WeightedTriCross::.connected_nodes(); // TriCross should have connected nodes assert!(!nodes.is_empty() || WeightedTriCross::.is_connected()); diff --git a/src/unit_tests/unitdiskmapping_algorithms/gadgets_ground_truth.rs b/src/unit_tests/unitdiskmapping_algorithms/gadgets_ground_truth.rs index e1567c5e5..15bb0c395 100644 --- a/src/unit_tests/unitdiskmapping_algorithms/gadgets_ground_truth.rs +++ b/src/unit_tests/unitdiskmapping_algorithms/gadgets_ground_truth.rs @@ -68,10 +68,8 @@ macro_rules! check_gadget { let g = $gadget; let e = $expected; - // Check size assert_eq!(g.size(), (e.size[0], e.size[1]), "{}: size mismatch", $name); - // Check cross_location assert_eq!( g.cross_location(), (e.cross_location[0], e.cross_location[1]), @@ -79,7 +77,6 @@ macro_rules! check_gadget { $name ); - // Check mis_overhead assert_eq!( g.mis_overhead(), e.mis_overhead, @@ -87,7 +84,6 @@ macro_rules! check_gadget { $name ); - // Check source graph node count let (slocs, _, _) = g.source_graph(); assert_eq!( slocs.len(), @@ -96,7 +92,6 @@ macro_rules! check_gadget { $name ); - // Check mapped graph node count let (mlocs, _) = g.mapped_graph(); assert_eq!( mlocs.len(), @@ -132,10 +127,8 @@ macro_rules! check_weighted_gadget { let g = $gadget; let e = $expected; - // Check size assert_eq!(g.size(), (e.size[0], e.size[1]), "{}: size mismatch", $name); - // Check cross_location assert_eq!( g.cross_location(), (e.cross_location[0], e.cross_location[1]), @@ -147,7 +140,6 @@ macro_rules! check_weighted_gadget { // Julia's WeightedGadget has different mis_overhead than the base gadget, // but Rust doesn't have a separate WeightedGadget type. - // Check source graph node count let (slocs, _, _) = g.source_graph(); assert_eq!( slocs.len(), @@ -156,7 +148,6 @@ macro_rules! check_weighted_gadget { $name ); - // Check mapped graph node count let (mlocs, _) = g.mapped_graph(); assert_eq!( mlocs.len(), @@ -185,7 +176,6 @@ macro_rules! check_weighted_gadget { $name, rust_mlocs, julia_mlocs ); - // Check source weights let sw = g.source_weights(); assert_eq!( sw, e.source_weights, @@ -193,7 +183,6 @@ macro_rules! check_weighted_gadget { $name, sw, e.source_weights ); - // Check mapped weights let mw = g.mapped_weights(); assert_eq!( mw, e.mapped_weights, diff --git a/src/unit_tests/unitdiskmapping_algorithms/julia_comparison.rs b/src/unit_tests/unitdiskmapping_algorithms/julia_comparison.rs index 973e9ba77..799f9ba4e 100644 --- a/src/unit_tests/unitdiskmapping_algorithms/julia_comparison.rs +++ b/src/unit_tests/unitdiskmapping_algorithms/julia_comparison.rs @@ -325,7 +325,6 @@ fn compare_triangular(name: &str) { let edges = get_graph_edges(&julia); let num_vertices = julia.num_vertices; - // Extract Julia's vertex order from copy_lines let vertex_order = get_vertex_order(&julia); let rust_result = triangular::map_weighted_with_order(num_vertices, &edges, &vertex_order).unwrap(); @@ -662,7 +661,6 @@ fn compare_connected_cells(name: &str) { rust_result.padding, ); - // Add copyline nodes for line in &rust_result.lines { for (row, col, weight) in line.copyline_locations(rust_result.padding, rust_result.spacing) { @@ -690,7 +688,6 @@ fn compare_connected_cells(name: &str) { } } - // Collect Rust's Connected cell positions let rust_connected: HashSet<(i64, i64)> = { let (rows, cols) = grid.size(); let mut connected = HashSet::new(); @@ -708,7 +705,6 @@ fn compare_connected_cells(name: &str) { println!("Julia Connected: {} cells", julia_connected.len()); println!("Rust Connected: {} cells", rust_connected.len()); - // Find differences let julia_only: Vec<_> = julia_connected.difference(&rust_connected).collect(); let rust_only: Vec<_> = rust_connected.difference(&julia_connected).collect(); diff --git a/src/unit_tests/unitdiskmapping_algorithms/map_graph.rs b/src/unit_tests/unitdiskmapping_algorithms/map_graph.rs index 97751872d..ff6bf5d61 100644 --- a/src/unit_tests/unitdiskmapping_algorithms/map_graph.rs +++ b/src/unit_tests/unitdiskmapping_algorithms/map_graph.rs @@ -326,11 +326,9 @@ fn test_map_config_back_standard_graphs() { for name in graph_names { let (n, edges) = smallgraph(name).unwrap(); let result = ksg::map_unweighted(n, &edges).unwrap(); - // Solve MIS on mapped graph let grid_edges = result.edges(); let grid_config = solve_mis_config(result.positions.len(), &grid_edges); - // Extract original config using gadget traceback let original_config = result.map_config_back(&grid_config).unwrap(); // Verify it's a valid independent set assert!( diff --git a/src/unit_tests/unitdiskmapping_algorithms/mapping_result.rs b/src/unit_tests/unitdiskmapping_algorithms/mapping_result.rs index 037db5bbe..066883221 100644 --- a/src/unit_tests/unitdiskmapping_algorithms/mapping_result.rs +++ b/src/unit_tests/unitdiskmapping_algorithms/mapping_result.rs @@ -46,7 +46,6 @@ fn test_mapping_result_format_config_with_selected() { let (rows, cols) = result.grid_dimensions; let mut config: Vec> = vec![vec![0; cols]; rows]; - // Set some cells as selected if rows > 0 && cols > 0 { config[0][0] = 1; } @@ -200,7 +199,6 @@ fn test_full_pipeline_diamond_unweighted() { let (n, edges) = smallgraph("diamond").unwrap(); let result = ksg::map_unweighted(n, &edges).unwrap(); - // Solve MIS on the grid graph let grid_edges = result.edges(); let num_grid = result.positions.len(); let grid_config = solve_mis_config(num_grid, &grid_edges); @@ -274,7 +272,6 @@ fn test_full_pipeline_weighted_diamond() { let grid_edges = result.edges(); let num_grid = result.positions.len(); - // Get weights from the mapping result let weights: Vec = (0..num_grid) .map(|i| result.node_weights.get(i).copied().unwrap_or(1)) .collect(); @@ -316,10 +313,8 @@ fn test_mis_size_preserved_diamond() { let (n, edges) = smallgraph("diamond").unwrap(); let result = ksg::map_unweighted(n, &edges).unwrap(); - // Get original MIS size let original_mis = solve_mis(n, &edges); - // Get grid MIS size let grid_edges = result.edges(); let grid_mis = solve_mis(result.positions.len(), &grid_edges); @@ -437,7 +432,6 @@ fn test_apply_and_unapply_gadget() { apply_gadget, unapply_gadget, CellState, MappingGrid, Pattern, }; - // Create a small grid with spacing 4 let mut grid = MappingGrid::new(10, 10, 4); // Set up some occupied cells for a Turn gadget @@ -501,14 +495,12 @@ fn test_extracted_mis_equals_original() { let (n, edges) = smallgraph("diamond").unwrap(); let result = ksg::map_unweighted(n, &edges).unwrap(); - // Solve MIS on grid let grid_edges = result.edges(); let num_grid = result.positions.len(); let grid_config = solve_mis_config(num_grid, &grid_edges); // Map back let original_config = result.map_config_back(&grid_config).unwrap(); - // Count selected vertices let extracted_count = original_config.iter().filter(|&&x| x > 0).count(); let original_mis = solve_mis(n, &edges); @@ -653,7 +645,6 @@ fn test_interface_k23_unweighted() { "K23: MIS overhead formula should hold" ); - // Check map_config_back produces valid IS let mapped_back = result.map_config_back(&grid_config).unwrap(); assert!( is_independent_set(&edges, &mapped_back), @@ -687,7 +678,6 @@ fn test_interface_empty_graph_unweighted() { "Empty graph: MIS overhead formula should hold" ); - // Check map_config_back let mapped_back = result.map_config_back(&grid_config).unwrap(); assert!( is_independent_set(&edges, &mapped_back), @@ -706,7 +696,6 @@ fn test_interface_path_graph_unweighted() { let (n, edges) = path_graph(); let result = ksg::map_unweighted(n, &edges).unwrap(); - // Check MIS size preservation let grid_edges = result.edges(); let num_grid = result.positions.len(); let grid_config = solve_mis_config(num_grid, &grid_edges); @@ -723,7 +712,6 @@ fn test_interface_path_graph_unweighted() { "Path graph: MIS overhead formula should hold" ); - // Check map_config_back let mapped_back = result.map_config_back(&grid_config).unwrap(); assert!( is_independent_set(&edges, &mapped_back), @@ -737,12 +725,10 @@ fn test_interface_k23_weighted() { let (n, edges) = k23_graph(); let result = ksg::map_weighted(n, &edges).unwrap(); - // Check MIS size preservation let grid_edges = result.edges(); let num_grid = result.positions.len(); let grid_config = solve_mis_config(num_grid, &grid_edges); - // Check map_config_back produces valid IS let mapped_back = result.map_config_back(&grid_config).unwrap(); assert!( is_independent_set(&edges, &mapped_back), @@ -774,7 +760,6 @@ fn test_interface_path_graph_weighted() { let (n, edges) = path_graph(); let result = ksg::map_weighted(n, &edges).unwrap(); - // Check map_config_back let grid_edges = result.edges(); let num_grid = result.positions.len(); let grid_config = solve_mis_config(num_grid, &grid_edges); diff --git a/src/unit_tests/unitdiskmapping_algorithms/triangular.rs b/src/unit_tests/unitdiskmapping_algorithms/triangular.rs index 9fa9b7499..4eb6da0c8 100644 --- a/src/unit_tests/unitdiskmapping_algorithms/triangular.rs +++ b/src/unit_tests/unitdiskmapping_algorithms/triangular.rs @@ -195,7 +195,6 @@ fn verify_mapping_matches_julia(name: &str) -> bool { } } - // Compute and compare weighted MIS let mapped_mis = solve_weighted_grid_mis(&result) as i64; let julia_mis = julia_data["mapped_mis_size"] .as_f64() @@ -374,7 +373,6 @@ fn test_triangular_map_config_back_standard_graphs() { let grid_edges = result.edges(); let num_grid = result.positions.len(); - // Solve weighted MIS on grid let grid_config = solve_weighted_mis_config(num_grid, &grid_edges, &weights); let center_config = triangular::map_config_back(&result, &grid_config).unwrap(); diff --git a/src/unit_tests/unitdiskmapping_algorithms/weighted.rs b/src/unit_tests/unitdiskmapping_algorithms/weighted.rs index 45c9a617a..fb9c5482f 100644 --- a/src/unit_tests/unitdiskmapping_algorithms/weighted.rs +++ b/src/unit_tests/unitdiskmapping_algorithms/weighted.rs @@ -123,7 +123,6 @@ fn test_triangular_weighted_interface() { let (n, edges) = smallgraph("bull").unwrap(); let result = triangular::map_weighted(n, &edges).unwrap(); - // Test with uniform weights let ws = vec![0.5; n]; let grid_weights = map_weights(&result, &ws).unwrap(); @@ -145,12 +144,10 @@ fn test_triangular_interface_full() { assert_eq!(grid_weights.len(), result.positions.len()); assert!(grid_weights.iter().all(|&w| w >= 0.0)); - // Test map_config_back let config = vec![0; result.positions.len()]; let original_config = result.map_config_back(&config).unwrap(); assert_eq!(original_config.len(), n); - // Verify trace_centers let centers = trace_centers(&result).unwrap(); assert_eq!(centers.len(), n); } @@ -161,7 +158,6 @@ fn test_triangular_interface_full() { fn test_triangular_copyline_weight_invariant() { let spacing = 6usize; - // Test various copyline configurations let configs = [ (1, 1, 1, 2), // Simple case (1, 2, 1, 3), // With vertical segment @@ -204,7 +200,6 @@ fn test_map_config_back_extracts_valid_is_triangular() { let (n, edges) = smallgraph("bull").unwrap(); let result = triangular::map_weighted(n, &edges).unwrap(); - // Get all zeros config let config = vec![0; result.positions.len()]; let extracted = triangular::map_config_back(&result, &config).unwrap(); // All zeros should extract to all zeros @@ -242,7 +237,6 @@ fn test_trace_centers_consistency_with_config_back() { let (n, edges) = smallgraph("diamond").unwrap(); let result = triangular::map_weighted(n, &edges).unwrap(); - // Get centers let centers = trace_centers(&result).unwrap(); assert_eq!(centers.len(), n); @@ -633,7 +627,6 @@ fn test_weighted_map_config_back_standard_graphs() { // map_weights adds source weights at center locations (like Julia) let mapped_weights = map_weights(&result, &source_weights).unwrap(); - // Solve weighted MIS with ILP let grid_edges = result.edges(); let num_grid = result.positions.len(); @@ -666,10 +659,8 @@ fn test_weighted_map_config_back_standard_graphs() { } } - // Get traced center locations using triangular-specific trace_centers let centers = trace_centers(&result).unwrap(); - // Extract config at centers let center_config: Vec = centers .iter() .map(|&(row, col)| { diff --git a/src/unit_tests/variant.rs b/src/unit_tests/variant.rs index ed65d4770..6c5f7287a 100644 --- a/src/unit_tests/variant.rs +++ b/src/unit_tests/variant.rs @@ -1,6 +1,5 @@ use crate::variant::{KValue, VariantParam}; -// Test types for the new system #[derive(Clone, Debug)] struct TestRoot; #[derive(Clone, Debug)] @@ -81,7 +80,6 @@ fn test_variant_for_problems() { use crate::topology::SimpleGraph; use crate::traits::Problem; - // Test MaximumIndependentSet variants let v = MaximumIndependentSet::::variant(); assert_eq!(v.len(), 2); assert_eq!(v[0].0, "graph"); @@ -89,63 +87,51 @@ fn test_variant_for_problems() { assert_eq!(v[1].0, "weight"); assert_eq!(v[1].1, "i64"); - // Test MinimumVertexCover let v = MinimumVertexCover::::variant(); assert_eq!(v.len(), 2); assert_eq!(v[0].1, "SimpleGraph"); assert_eq!(v[1].1, "i64"); - // Test MinimumDominatingSet let v = MinimumDominatingSet::::variant(); assert_eq!(v.len(), 2); assert_eq!(v[0].1, "SimpleGraph"); - // Test MaximumMatching let v = MaximumMatching::::variant(); assert_eq!(v.len(), 2); assert_eq!(v[0].1, "SimpleGraph"); - // Test MaxCut let v = MaxCut::::variant(); assert_eq!(v.len(), 2); assert_eq!(v[0].1, "SimpleGraph"); - // Test KColoring (has K and graph parameters) let v = KColoring::::variant(); assert_eq!(v.len(), 2); assert_eq!(v[0], ("k", "K3")); assert_eq!(v[1], ("graph", "SimpleGraph")); - // Test MaximalIS let v = MaximalIS::::variant(); assert_eq!(v.len(), 2); assert_eq!(v[0].1, "SimpleGraph"); - // Test MaximumClique let v = MaximumClique::::variant(); assert_eq!(v.len(), 2); assert_eq!(v[0].1, "SimpleGraph"); - // Test Satisfiability (no type parameters) let v = Satisfiability::variant(); assert_eq!(v.len(), 0); - // Test KSatisfiability (K type parameter only) let v = KSatisfiability::::variant(); assert_eq!(v.len(), 1); assert_eq!(v[0], ("k", "K3")); - // Test MaximumSetPacking (weight parameter only) let v = MaximumSetPacking::::variant(); assert_eq!(v.len(), 1); assert_eq!(v[0], ("weight", "i64")); - // Test MinimumSetCovering (weight parameter only) let v = MinimumSetCovering::::variant(); assert_eq!(v.len(), 1); assert_eq!(v[0], ("weight", "i64")); - // Test SpinGlass (graph + weight parameters) let v = SpinGlass::::variant(); assert_eq!(v.len(), 2); assert_eq!(v[1].1, "f64"); @@ -153,28 +139,22 @@ fn test_variant_for_problems() { let v = SpinGlass::::variant(); assert_eq!(v[1].1, "i64"); - // Test QUBO (weight parameter only) let v = QUBO::::variant(); assert_eq!(v.len(), 1); assert_eq!(v[0], ("weight", "f64")); - // Test CircuitSAT (no type parameters) let v = CircuitSAT::variant(); assert_eq!(v.len(), 0); - // Test Factoring (no type parameters) let v = Factoring::variant(); assert_eq!(v.len(), 0); - // Test BicliqueCover (no type parameters) let v = BicliqueCover::variant(); assert_eq!(v.len(), 0); - // Test BMF (no type parameters) let v = BMF::variant(); assert_eq!(v.len(), 0); - // Test PaintShop (no type parameters) let v = PaintShop::variant(); assert_eq!(v.len(), 0); } diff --git a/tests/suites/examples.rs b/tests/suites/examples.rs index 5ad719351..24ad255f8 100644 --- a/tests/suites/examples.rs +++ b/tests/suites/examples.rs @@ -91,8 +91,4 @@ fn test_export_petersen_mapping() { std::fs::remove_dir_all(output_dir).unwrap(); } -// Note: detect_isolated_problems and detect_unreachable_from_3sat are diagnostic -// tools that exit(1) when they find issues. They are run via `make` targets -// (topology-sanity-check), not as part of `cargo test`. - // Note: export_examples is exercised by `make paper` with the example-db feature. diff --git a/tests/suites/reductions.rs b/tests/suites/reductions.rs index 4ec221377..ffde6fc64 100644 --- a/tests/suites/reductions.rs +++ b/tests/suites/reductions.rs @@ -25,7 +25,6 @@ mod is_vc_reductions { vec![1i64; 3], ); - // Reduce IS to VC let result = ReduceTo::>::reduce_to(&is_problem) .expect("reduction should succeed"); let vc_problem = result.target_problem(); @@ -34,11 +33,9 @@ mod is_vc_reductions { assert_eq!(vc_problem.graph().num_vertices(), 3); assert_eq!(vc_problem.graph().num_edges(), 3); - // Solve the target VC problem let solver = BruteForce::new(); let vc_solutions = solver.find_all_witnesses(vc_problem).unwrap(); - // Extract back to IS solution let is_solution = result.extract_solution(&vc_solutions[0]).unwrap(); // Solution should be valid for original problem @@ -53,7 +50,6 @@ mod is_vc_reductions { vec![1i64; 4], ); - // Reduce VC to IS let result = ReduceTo::>::reduce_to(&vc_problem) .expect("reduction should succeed"); let is_problem = result.target_problem(); @@ -62,11 +58,9 @@ mod is_vc_reductions { assert_eq!(is_problem.graph().num_vertices(), 4); assert_eq!(is_problem.graph().num_edges(), 3); - // Solve the target IS problem let solver = BruteForce::new(); let is_solutions = solver.find_all_witnesses(is_problem).unwrap(); - // Extract back to VC solution let vc_solution = result.extract_solution(&is_solutions[0]).unwrap(); // Solution should be valid for original problem @@ -97,11 +91,9 @@ mod is_vc_reductions { ); assert_eq!(final_is.graph().num_edges(), original.graph().num_edges()); - // Solve the final problem let solver = BruteForce::new(); let solutions = solver.find_all_witnesses(final_is).unwrap(); - // Extract through the chain let intermediate_sol = back_to_is.extract_solution(&solutions[0]).unwrap(); let original_sol = to_vc.extract_solution(&intermediate_sol).unwrap(); @@ -134,7 +126,6 @@ mod is_vc_reductions { let solver = BruteForce::new(); - // Solve IS, reduce to VC solution let is_solutions = solver.find_all_witnesses(&is_problem).unwrap(); let max_is = is_solutions[0].iter().filter(|&&selected| selected).count(); @@ -164,11 +155,9 @@ mod is_sp_reductions { // 3 sets (one per vertex) assert_eq!(sp_problem.num_sets(), 3); - // Solve let solver = BruteForce::new(); let sp_solutions = solver.find_all_witnesses(sp_problem).unwrap(); - // Extract to IS solution let is_solution = result.extract_solution(&sp_solutions[0]).unwrap(); assert!(is_problem.evaluate(&is_solution).unwrap().is_valid()); @@ -187,11 +176,9 @@ mod is_sp_reductions { // Should have an edge for each pair of overlapping sets (none here) assert_eq!(is_problem.graph().num_edges(), 0); - // Solve let solver = BruteForce::new(); let is_solutions = solver.find_all_witnesses(is_problem).unwrap(); - // Extract to SP solution let sp_solution = result.extract_solution(&is_solutions[0]).unwrap(); // All sets can be packed (disjoint) @@ -211,11 +198,9 @@ mod is_sp_reductions { .expect("reduction should succeed"); let sp_problem = to_sp.target_problem(); - // Solve SP let solver = BruteForce::new(); let sp_solutions = solver.find_all_witnesses(sp_problem).unwrap(); - // Extract to IS solution let is_solution = to_sp.extract_solution(&sp_solutions[0]).unwrap(); // Valid for original @@ -248,11 +233,9 @@ mod sg_qubo_reductions { assert_eq!(qubo.num_variables(), 2); - // Solve QUBO let solver = BruteForce::new(); let qubo_solutions = solver.find_all_witnesses(qubo).unwrap(); - // Extract to SG solution let sg_solution = result.extract_solution(&qubo_solutions[0]).unwrap(); assert_eq!(sg_solution.len(), 2); } @@ -268,11 +251,9 @@ mod sg_qubo_reductions { assert_eq!(sg.num_spins(), 2); - // Solve SG let solver = BruteForce::new(); let sg_solutions = solver.find_all_witnesses(sg).unwrap(); - // Extract to QUBO solution let qubo_solution = result.extract_solution(&sg_solutions[0]).unwrap(); assert_eq!(qubo_solution.len(), 2); } @@ -290,13 +271,11 @@ mod sg_qubo_reductions { let result = ReduceTo::>::reduce_to(&sg).expect("reduction should succeed"); let qubo = result.target_problem(); - // Check that ground states correspond let solver = BruteForce::new(); let sg_solutions = solver.find_all_witnesses(&sg).unwrap(); let qubo_solutions = solver.find_all_witnesses(qubo).unwrap(); - // Extract QUBO solution back to SG let extracted = result.extract_solution(&qubo_solutions[0]).unwrap(); // Should be among optimal SG solutions (or equivalent) @@ -420,11 +399,9 @@ mod sg_maxcut_reductions { // Same number of vertices assert_eq!(maxcut.graph().num_vertices(), 3); - // Solve MaxCut let solver = BruteForce::new(); let maxcut_solutions = solver.find_all_witnesses(maxcut).unwrap(); - // Extract to SG solution let sg_solution = result.extract_solution(&maxcut_solutions[0]).unwrap(); assert_eq!(sg_solution.len(), 3); } @@ -443,11 +420,9 @@ mod sg_maxcut_reductions { // Same number of spins assert_eq!(sg.num_spins(), 3); - // Solve SG let solver = BruteForce::new(); let sg_solutions = solver.find_all_witnesses(sg).unwrap(); - // Extract to MaxCut solution let maxcut_solution = result.extract_solution(&sg_solutions[0]).unwrap(); assert_eq!(maxcut_solution.len(), 3); } @@ -468,11 +443,9 @@ mod sg_maxcut_reductions { let solver = BruteForce::new(); - // Solve both let sg_solutions = solver.find_all_witnesses(&sg).unwrap(); let maxcut_solutions = solver.find_all_witnesses(maxcut).unwrap(); - // Extract MaxCut solution back to SG let extracted = result.extract_solution(&maxcut_solutions[0]).unwrap(); // Should have same energy as directly solved SG @@ -509,7 +482,6 @@ mod topology_tests { ]; let udg = UnitDiskGraph::new(positions, 1.0).unwrap(); - // Extract edges let edges = udg.edges().to_vec(); let is_problem = MaximumIndependentSet::new(SimpleGraph::new(4, edges), vec![1i64; 4]); @@ -522,9 +494,6 @@ mod topology_tests { } } -// TruthTable integration tests removed (module is now pub(crate)); -// equivalent coverage exists in src/unit_tests/truth_table.rs - /// Tests for QUBO reductions against ground truth JSON. mod qubo_reductions { use super::*; @@ -705,7 +674,6 @@ mod qubo_reductions { let json = std::fs::read_to_string("tests/data/qubo/ksatisfiability_to_qubo.json").unwrap(); let data: KSatToQuboData = serde_json::from_str(&json).unwrap(); - // Convert JSON clauses to CNFClause (1-indexed signed literals) let clauses: Vec = data .source .clauses @@ -742,7 +710,6 @@ mod qubo_reductions { assert!(ksat.evaluate(&extracted).unwrap()); } - // Verify extracted solution matches ground truth assignment let gt_config = &data.qubo_optimal.configs[0]; let our_config = reduction.extract_solution(&solutions[0]).unwrap(); assert_eq!( @@ -775,7 +742,6 @@ mod qubo_reductions { let json = std::fs::read_to_string("tests/data/qubo/ilp_to_qubo.json").unwrap(); let data: ILPToQuboData = serde_json::from_str(&json).unwrap(); - // Build constraints from dense matrix let constraints: Vec = data .source .constraints_lhs @@ -798,7 +764,6 @@ mod qubo_reductions { }) .collect(); - // Build objective (dense to sparse) let objective: Vec<(usize, i64)> = data .source .objective @@ -863,7 +828,6 @@ mod qubo_reductions { let n = data.source.num_vertices; let vc = MinimumVertexCover::new(SimpleGraph::new(n, data.source.edges), vec![1i64; n]); - // Find path MVC → ... → QUBO through the reduction graph let graph = ReductionGraph::new(); let src = ReductionGraph::variant_to_map(&MinimumVertexCover::::variant()); @@ -900,7 +864,6 @@ mod qubo_reductions { let solver = BruteForce::new(); let solutions = solver.find_all_witnesses(qubo).unwrap(); - // Extract back through the full chain to get VC solution for sol in &solutions { let vc_sol = chain.extract_solution(sol).unwrap(); assert!(vc.evaluate(&vc_sol).unwrap().is_valid()); @@ -939,7 +902,6 @@ mod io_tests { ); assert_eq!(restored.graph().num_edges(), original.graph().num_edges()); - // Reduce the restored problem let result = ReduceTo::>::reduce_to(&restored) .expect("reduction should succeed"); let vc = result.target_problem(); @@ -959,7 +921,6 @@ mod io_tests { // Deserialize let restored: QUBO = from_json(&json).unwrap(); - // Reduce to SG let result = ReduceTo::>::reduce_to(&restored) .expect("reduction should succeed"); let sg = result.target_problem(); @@ -986,12 +947,10 @@ mod end_to_end { vec![1i64; 5], ); - // Solve directly let solver = BruteForce::new(); let is_solutions = solver.find_all_witnesses(&is).unwrap(); let direct_size = is_solutions[0].iter().filter(|&&selected| selected).count(); - // Reduce to VC and solve let to_vc = ReduceTo::>::reduce_to(&is) .expect("reduction should succeed"); let vc = to_vc.target_problem(); @@ -999,7 +958,6 @@ mod end_to_end { let vc_extracted = to_vc.extract_solution(&vc_solutions[0]).unwrap(); let via_vc_size = vc_extracted.iter().filter(|&&selected| selected).count(); - // Reduce to MaximumSetPacking and solve let to_sp = ReduceTo::>::reduce_to(&is).expect("reduction should succeed"); let sp = to_sp.target_problem(); @@ -1022,13 +980,11 @@ mod end_to_end { ) .unwrap(); - // Solve directly let solver = BruteForce::new(); let sg_solutions = solver.find_all_witnesses(&sg).unwrap(); let direct_energy = sg.compute_energy(&sg_solutions[0]).unwrap(); - // Reduce to MaxCut and solve let to_maxcut = ReduceTo::>::reduce_to(&sg).expect("reduction should succeed"); let maxcut = to_maxcut.target_problem(); @@ -1057,11 +1013,9 @@ mod end_to_end { .expect("reduction should succeed"); let vc = is_to_vc.target_problem(); - // Solve VC let solver = BruteForce::new(); let vc_solutions = solver.find_all_witnesses(vc).unwrap(); - // Extract back through chain let is_sol = is_to_vc.extract_solution(&vc_solutions[0]).unwrap(); let sp_sol = sp_to_is.extract_solution(&is_sol).unwrap();