diff --git a/Cargo.toml b/Cargo.toml index 8ec0452c3..d06e87f66 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,8 @@ members = [ [package] name = "problemreductions" version = "0.6.0" -edition = "2021" +edition = "2024" +rust-version = "1.88" description = "A library for reducing NP-hard problems" license = "MIT" repository = "https://github.com/CodingThrust/problem-reductions" diff --git a/benches/solver_benchmarks.rs b/benches/solver_benchmarks.rs index 72dffb2e4..1841eca21 100644 --- a/benches/solver_benchmarks.rs +++ b/benches/solver_benchmarks.rs @@ -1,6 +1,6 @@ //! Benchmarks for the BruteForce solver on various problem types. -use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; +use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main}; use problemreductions::models::formula::*; use problemreductions::models::graph::*; use problemreductions::models::misc::*; diff --git a/examples/detect_isolated_problems.rs b/examples/detect_isolated_problems.rs index c5445d62c..c4822eac6 100644 --- a/examples/detect_isolated_problems.rs +++ b/examples/detect_isolated_problems.rs @@ -2,8 +2,8 @@ //! //! Run with: `cargo run --example detect_isolated_problems` -use problemreductions::rules::analysis::check_connectivity; use problemreductions::rules::ReductionGraph; +use problemreductions::rules::analysis::check_connectivity; fn main() { let graph = ReductionGraph::new(); diff --git a/examples/detect_unreachable_from_3sat.rs b/examples/detect_unreachable_from_3sat.rs index f4e0baf87..9b6454db3 100644 --- a/examples/detect_unreachable_from_3sat.rs +++ b/examples/detect_unreachable_from_3sat.rs @@ -7,8 +7,8 @@ //! //! Run with: `cargo run --example detect_unreachable_from_3sat` -use problemreductions::rules::analysis::{check_reachability_from_3sat, UnreachableReason}; use problemreductions::rules::ReductionGraph; +use problemreductions::rules::analysis::{UnreachableReason, check_reachability_from_3sat}; fn main() { let graph = ReductionGraph::new(); diff --git a/examples/export_mapping_stages.rs b/examples/export_mapping_stages.rs index 884ac242c..3f5fe8391 100644 --- a/examples/export_mapping_stages.rs +++ b/examples/export_mapping_stages.rs @@ -9,8 +9,8 @@ use problemreductions::rules::unitdiskmapping::{ _internal::{ - create_copylines, mis_overhead_copyline, mis_overhead_copyline_triangular, CopyLine, - MappingGrid, + CopyLine, MappingGrid, create_copylines, mis_overhead_copyline, + mis_overhead_copyline_triangular, }, ksg, triangular, }; @@ -110,21 +110,21 @@ fn extract_grid_nodes(grid: &MappingGrid) -> Vec { let (rows, cols) = grid.size(); for r in 0..rows { for c in 0..cols { - if let Some(cell) = grid.get(r, c) { - if !cell.is_empty() { - let state = match cell { - CellState::Occupied { .. } => "O", - CellState::Doubled { .. } => "D", - CellState::Connected { .. } => "C", - CellState::Empty => ".", - }; - nodes.push(GridNodeExport { - row: r as i64, // 0-indexed - DO NOT change! - col: c as i64, // 0-indexed - DO NOT change! - weight: cell.weight(), - state: state.to_string(), - }); - } + if let Some(cell) = grid.get(r, c) + && !cell.is_empty() + { + let state = match cell { + CellState::Occupied { .. } => "O", + CellState::Doubled { .. } => "D", + CellState::Connected { .. } => "C", + CellState::Empty => ".", + }; + nodes.push(GridNodeExport { + row: r as i64, // 0-indexed - DO NOT change! + col: c as i64, // 0-indexed - DO NOT change! + weight: cell.weight(), + state: state.to_string(), + }); } } } @@ -159,21 +159,20 @@ fn crossat_triangular( fn get_vertex_order_from_julia(graph_name: &str) -> Option> { let path = format!("tests/data/{}_triangular_trace.json", graph_name); - if let Ok(content) = fs::read_to_string(&path) { - if let Ok(data) = serde_json::from_str::(&content) { - if let Some(copy_lines) = data["copy_lines"].as_array() { - let mut lines: Vec<_> = copy_lines - .iter() - .filter_map(|cl| { - let vertex = cl["vertex"].as_u64()? as usize; - let vslot = cl["vslot"].as_u64()? as usize; - Some((vertex - 1, vslot)) // Convert to 0-indexed - }) - .collect(); - lines.sort_by_key(|(_, vslot)| *vslot); - return Some(lines.into_iter().map(|(v, _)| v).collect()); - } - } + if let Ok(content) = fs::read_to_string(&path) + && let Ok(data) = serde_json::from_str::(&content) + && let Some(copy_lines) = data["copy_lines"].as_array() + { + let mut lines: Vec<_> = copy_lines + .iter() + .filter_map(|cl| { + let vertex = cl["vertex"].as_u64()? as usize; + let vslot = cl["vslot"].as_u64()? as usize; + Some((vertex - 1, vslot)) // Convert to 0-indexed + }) + .collect(); + lines.sort_by_key(|(_, vslot)| *vslot); + return Some(lines.into_iter().map(|(v, _)| v).collect()); } None } diff --git a/examples/export_petersen_mapping.rs b/examples/export_petersen_mapping.rs index 87753371e..170226eb4 100644 --- a/examples/export_petersen_mapping.rs +++ b/examples/export_petersen_mapping.rs @@ -28,7 +28,7 @@ //! - `docs/paper/static/petersen_square_unweighted.json` - Unweighted King's subgraph //! - `docs/paper/static/petersen_triangular.json` - Weighted triangular lattice -use problemreductions::rules::unitdiskmapping::{ksg, triangular, MappingResult}; +use problemreductions::rules::unitdiskmapping::{MappingResult, ksg, triangular}; use serde::Serialize; use std::fs; use std::path::Path; diff --git a/examples/export_schemas.rs b/examples/export_schemas.rs index 892f52bd6..70f7ffac6 100644 --- a/examples/export_schemas.rs +++ b/examples/export_schemas.rs @@ -2,7 +2,7 @@ //! //! Run with: `cargo run --example export_schemas [output_path]` -use problemreductions::registry::{collect_schemas, ProblemSchemaEntry}; +use problemreductions::registry::{ProblemSchemaEntry, collect_schemas}; use std::path::{Path, PathBuf}; pub fn run(output_path: &Path) { diff --git a/examples/polynomial_compare_audit.rs b/examples/polynomial_compare_audit.rs index 5a4c77e71..e8ee21992 100644 --- a/examples/polynomial_compare_audit.rs +++ b/examples/polynomial_compare_audit.rs @@ -5,7 +5,7 @@ //! Each endpoint group is one generic batch, including every nonzero field certificate. //! //! cargo run --release --example polynomial_compare_audit -use problemreductions::poly_compare::{compare_all, Direction, Profile, Reason, Verdict}; +use problemreductions::poly_compare::{Direction, Profile, Reason, Verdict, compare_all}; use problemreductions::rules::{ReductionGraph, ReductionPath, ReductionStep}; use std::collections::BTreeMap; use std::time::Instant; diff --git a/problemreductions-cli/Cargo.toml b/problemreductions-cli/Cargo.toml index 76cf6c772..9206a683a 100644 --- a/problemreductions-cli/Cargo.toml +++ b/problemreductions-cli/Cargo.toml @@ -1,7 +1,8 @@ [package] name = "problemreductions-cli" version = "0.6.0" -edition = "2021" +edition = "2024" +rust-version = "1.88" description = "CLI tool for exploring NP-hard problem reductions" license = "MIT" repository = "https://github.com/CodingThrust/problem-reductions" diff --git a/problemreductions-cli/src/bin/pred_sym.rs b/problemreductions-cli/src/bin/pred_sym.rs index 9a0731b7b..4105b56e5 100644 --- a/problemreductions-cli/src/bin/pred_sym.rs +++ b/problemreductions-cli/src/bin/pred_sym.rs @@ -1,5 +1,5 @@ use clap::{Parser, Subcommand}; -use problemreductions::{big_o_normal_form, evaluate_approximate, Expr, ProblemParameters}; +use problemreductions::{Expr, ProblemParameters, big_o_normal_form, evaluate_approximate}; #[derive(Parser)] #[command( diff --git a/problemreductions-cli/src/cli.rs b/problemreductions-cli/src/cli.rs index 13a3bd934..817075a09 100644 --- a/problemreductions-cli/src/cli.rs +++ b/problemreductions-cli/src/cli.rs @@ -398,10 +398,10 @@ pub fn print_subcommand_help_hint(error_msg: &str) { let cmd = Cli::command(); for (pattern, name) in subcmds { if first_line.contains(pattern) { - if let Some(sub) = cmd.find_subcommand(name) { - if let Some(help) = sub.get_after_help() { - eprintln!("\n{help}"); - } + if let Some(sub) = cmd.find_subcommand(name) + && let Some(help) = sub.get_after_help() + { + eprintln!("\n{help}"); } return; } @@ -477,16 +477,18 @@ mod tests { .kind(), ErrorKind::UnknownArgument ); - assert!(Cli::try_parse_from([ - "pred", - "create", - "ThreePartition", - "--sizes", - "1,1,1", - "--bound", - "9223372036854775808", - ]) - .is_err()); + assert!( + Cli::try_parse_from([ + "pred", + "create", + "ThreePartition", + "--sizes", + "1,1,1", + "--bound", + "9223372036854775808", + ]) + .is_err() + ); Cli::try_parse_from([ "pred", "create", @@ -573,25 +575,23 @@ mod tests { #[test] fn extract_requires_exactly_one_mapping_input() { - assert!(Cli::try_parse_from([ - "pred", - "extract", - "bundle.json", - "--config", - "[true,false]" - ]) - .is_ok()); + assert!( + Cli::try_parse_from(["pred", "extract", "bundle.json", "--config", "[true,false]"]) + .is_ok() + ); assert!(Cli::try_parse_from(["pred", "extract", "bundle.json"]).is_err()); assert!(Cli::try_parse_from(["pred", "extract", "bundle.json", "--value", "2"]).is_ok()); - assert!(Cli::try_parse_from([ - "pred", - "extract", - "bundle.json", - "--config", - "[true,false]", - "--value", - "2" - ]) - .is_err()); + assert!( + Cli::try_parse_from([ + "pred", + "extract", + "bundle.json", + "--config", + "[true,false]", + "--value", + "2" + ]) + .is_err() + ); } } diff --git a/problemreductions-cli/src/commands/create.rs b/problemreductions-cli/src/commands/create.rs index f8cee6354..b2a2c572c 100644 --- a/problemreductions-cli/src/commands/create.rs +++ b/problemreductions-cli/src/commands/create.rs @@ -3,7 +3,7 @@ use crate::dispatch::ProblemJsonOutput; use crate::output::OutputConfig; use crate::problem_name::{resolve_problem_ref, unknown_problem_error}; use crate::util; -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result, bail}; use num_bigint::BigUint; use problemreductions::export::{ModelExample, ProblemRef, ProblemSide, RuleExample}; use problemreductions::models::formula::Quantifier; @@ -19,7 +19,7 @@ use std::collections::{BTreeMap, BTreeSet}; mod schema_support; use self::schema_support::*; pub(crate) use self::schema_support::{ - create_inputs_for, resolve_schema_field_type, InputValueKind, + InputValueKind, create_inputs_for, resolve_schema_field_type, }; fn all_data_flags_empty(args: &CreateArgs) -> bool { diff --git a/problemreductions-cli/src/commands/create/tests.rs b/problemreductions-cli/src/commands/create/tests.rs index 595b39be5..bd1740a3e 100644 --- a/problemreductions-cli/src/commands/create/tests.rs +++ b/problemreductions-cli/src/commands/create/tests.rs @@ -1046,9 +1046,10 @@ fn test_create_generalized_hex_requires_sink() { }; let err = create(&args, &out).unwrap_err(); - assert!(err - .to_string() - .contains("missing required construction input(s): sink")); + assert!( + err.to_string() + .contains("missing required construction input(s): sink") + ); } #[test] @@ -1189,9 +1190,10 @@ fn test_create_production_planning_requires_all_period_vectors() { }; let err = create(&args, &out).unwrap_err(); - assert!(err - .to_string() - .contains("missing required construction input(s): production_costs")); + assert!( + err.to_string() + .contains("missing required construction input(s): production_costs") + ); } #[test] @@ -1228,9 +1230,10 @@ fn test_create_production_planning_rejects_mismatched_period_lengths() { }; let err = create(&args, &out).unwrap_err(); - assert!(err - .to_string() - .contains("all per-period vectors must have length num_periods")); + assert!( + err.to_string() + .contains("all per-period vectors must have length num_periods") + ); } #[test] @@ -1452,9 +1455,10 @@ fn test_create_longest_path_requires_edge_lengths() { }; let err = create(&args, &out).unwrap_err(); - assert!(err - .to_string() - .contains("missing required construction input(s): edge_lengths")); + assert!( + err.to_string() + .contains("missing required construction input(s): edge_lengths") + ); } #[test] @@ -1509,9 +1513,10 @@ fn test_create_undirected_flow_lower_bounds_requires_lower_bounds() { }; let err = create(&args, &out).unwrap_err(); - assert!(err - .to_string() - .contains("missing required construction input(s): lower_bounds")); + assert!( + err.to_string() + .contains("missing required construction input(s): lower_bounds") + ); } fn empty_args() -> CreateArgs { @@ -2130,9 +2135,11 @@ fn test_create_kclique() { let problem: KClique = serde_json::from_value(created.data).unwrap(); assert_eq!(problem.k(), 3); assert_eq!(problem.num_vertices(), 5); - assert!(problem - .evaluate(&vec![false, false, true, true, true]) - .unwrap()); + assert!( + problem + .evaluate(&vec![false, false, true, true, true]) + .unwrap() + ); let _ = std::fs::remove_file(output_path); } diff --git a/problemreductions-cli/src/commands/evaluate.rs b/problemreductions-cli/src/commands/evaluate.rs index 7ce07cadf..4594085f6 100644 --- a/problemreductions-cli/src/commands/evaluate.rs +++ b/problemreductions-cli/src/commands/evaluate.rs @@ -1,4 +1,4 @@ -use crate::dispatch::{load_problem, read_input, ProblemJson}; +use crate::dispatch::{ProblemJson, load_problem, read_input}; use crate::output::OutputConfig; use anyhow::{Context, Result}; use std::path::Path; diff --git a/problemreductions-cli/src/commands/extract.rs b/problemreductions-cli/src/commands/extract.rs index 55289543e..2a19dbf94 100644 --- a/problemreductions-cli/src/commands/extract.rs +++ b/problemreductions-cli/src/commands/extract.rs @@ -1,5 +1,5 @@ use crate::cli::ExtractArgs; -use crate::dispatch::{extract_bundle_value, read_input, BundleReplay, ReductionBundle}; +use crate::dispatch::{BundleReplay, ReductionBundle, extract_bundle_value, read_input}; use crate::output::OutputConfig; use anyhow::{Context, Result}; diff --git a/problemreductions-cli/src/commands/graph.rs b/problemreductions-cli/src/commands/graph.rs index aada66532..d537e97e2 100644 --- a/problemreductions-cli/src/commands/graph.rs +++ b/problemreductions-cli/src/commands/graph.rs @@ -1,10 +1,10 @@ -use crate::dispatch::{load_problem, read_input, ProblemJson}; +use crate::dispatch::{ProblemJson, load_problem, read_input}; use crate::output::OutputConfig; use crate::problem_name::{aliases_for, parse_problem_spec, resolve_problem_ref}; use anyhow::Result; use problemreductions::parameters::ParameterRelation; -use problemreductions::registry::collect_schemas; use problemreductions::registry::ProblemCategory; +use problemreductions::registry::collect_schemas; use problemreductions::rules::{ExecutedPath, ReductionGraph, ReductionPath, TraversalFlow}; use problemreductions::{Expr, Growth}; use std::any::Any; @@ -21,7 +21,7 @@ pub fn list( verbose: bool, out: &OutputConfig, ) -> Result<()> { - use crate::output::{format_table, Align}; + use crate::output::{Align, format_table}; let needs_variant_rows = verbose || out.json || out.output.is_some(); let catalog = problemreductions::registry::problem_types(); @@ -263,7 +263,7 @@ pub fn list( } pub fn list_rules(query: Option<&str>, all: bool, verbose: bool, out: &OutputConfig) -> Result<()> { - use crate::output::{format_table, Align}; + use crate::output::{Align, format_table}; let num_registered = problemreductions::rules::registry::reduction_entries().len(); let expanded = all || query.is_some() || verbose || out.json || out.output.is_some(); @@ -463,10 +463,10 @@ pub fn show(problem: &str, out: &OutputConfig) -> Result<()> { let slash = variant_to_full_slash(name, variant); let header = format!("{name}{slash}"); let mut text = format!("{}\n", crate::output::fmt_problem_name(&header)); - if let Some(schema) = schema { - if !schema.description.is_empty() { - text.push_str(&format!(" {}\n", schema.description)); - } + if let Some(schema) = schema + && !schema.description.is_empty() + { + text.push_str(&format!(" {}\n", schema.description)); } if !complexity.is_empty() { text.push_str(&format!( diff --git a/problemreductions-cli/src/commands/graph_compare.rs b/problemreductions-cli/src/commands/graph_compare.rs index a195e9d2b..3e6edbc3d 100644 --- a/problemreductions-cli/src/commands/graph_compare.rs +++ b/problemreductions-cli/src/commands/graph_compare.rs @@ -1,9 +1,9 @@ //! Presentation only: decisions and the front come from `poly_compare::compare_all`. -use super::{fmt_path_chain, ReductionGraph, ReductionPath}; +use super::{ReductionGraph, ReductionPath, fmt_path_chain}; use problemreductions::poly_compare::{ - compare_all, Direction, PathComparison, Profile, ProfileComparison, Side, Verdict, + Direction, PathComparison, Profile, ProfileComparison, Side, Verdict, compare_all, }; -use serde_json::{json, Value}; +use serde_json::{Value, json}; /// 1-based `(winner, loser)` of a dominated pair. fn winner_loser(i: usize, j: usize, verdict: Verdict) -> Option<(usize, usize)> { @@ -104,7 +104,9 @@ impl ComparisonView { paths: &[ReductionPath], proofs: bool, ) -> String { - let mut text = String::from("Polynomial comparison: generic order of chosen certificates, batch-relative regular valid growth families; smaller certificates are better. Ignores exact-cancellation families such as complete graphs; keeps bounded strata and exponent cells.\n"); + let mut text = String::from( + "Polynomial comparison: generic order of chosen certificates, batch-relative regular valid growth families; smaller certificates are better. Ignores exact-cancellation families such as complete graphs; keeps bounded strata and exponent cells.\n", + ); text.push_str(&format!( "\nPair verdicts ({} pairs):\n", self.result.pairs.len() @@ -199,7 +201,7 @@ impl ComparisonView { #[cfg(test)] mod tests { use super::*; - use problemreductions::{parameters::ParameterRelation, poly_compare::FieldCertificate, Expr}; + use problemreductions::{Expr, parameters::ParameterRelation, poly_compare::FieldCertificate}; use std::collections::BTreeMap; fn certificate(s: &str) -> FieldCertificate { diff --git a/problemreductions-cli/src/commands/inspect.rs b/problemreductions-cli/src/commands/inspect.rs index f71d9cc90..d430437fb 100644 --- a/problemreductions-cli/src/commands/inspect.rs +++ b/problemreductions-cli/src/commands/inspect.rs @@ -1,5 +1,5 @@ use crate::dispatch::{ - load_problem, read_input, solver_capabilities_view, ProblemJson, ReductionBundle, + ProblemJson, ReductionBundle, load_problem, read_input, solver_capabilities_view, }; use crate::output::OutputConfig; use anyhow::Result; diff --git a/problemreductions-cli/src/commands/reduce.rs b/problemreductions-cli/src/commands/reduce.rs index 6f9bb2c04..b42b372dc 100644 --- a/problemreductions-cli/src/commands/reduce.rs +++ b/problemreductions-cli/src/commands/reduce.rs @@ -1,6 +1,6 @@ use crate::dispatch::{ - load_problem, read_input, serialize_any_problem, PathStep, ProblemJson, ProblemJsonOutput, - ReductionBundle, + PathStep, ProblemJson, ProblemJsonOutput, ReductionBundle, load_problem, read_input, + serialize_any_problem, }; use crate::output::OutputConfig; use anyhow::{Context, Result}; diff --git a/problemreductions-cli/src/commands/solve.rs b/problemreductions-cli/src/commands/solve.rs index be960dfa3..44362790c 100644 --- a/problemreductions-cli/src/commands/solve.rs +++ b/problemreductions-cli/src/commands/solve.rs @@ -1,6 +1,6 @@ use crate::dispatch::{ - load_problem, read_input, solve_result_json, solver_request, BundleReplay, ProblemJson, - ReductionBundle, + BundleReplay, ProblemJson, ReductionBundle, load_problem, read_input, solve_result_json, + solver_request, }; use crate::output::OutputConfig; use anyhow::{Context, Result}; diff --git a/problemreductions-cli/src/create_args.rs b/problemreductions-cli/src/create_args.rs index 27c446fcd..6538942ac 100644 --- a/problemreductions-cli/src/create_args.rs +++ b/problemreductions-cli/src/create_args.rs @@ -1,6 +1,6 @@ use clap::parser::ValueSource; use clap::{Arg, ArgAction, ArgMatches, Args, Command, Error, FromArgMatches}; -use problemreductions::registry::{variant_entries, ProblemType}; +use problemreductions::registry::{ProblemType, variant_entries}; use std::collections::BTreeMap; use std::ffi::OsStr; use std::str::FromStr; diff --git a/problemreductions-cli/src/dispatch.rs b/problemreductions-cli/src/dispatch.rs index cebb9591b..91b559533 100644 --- a/problemreductions-cli/src/dispatch.rs +++ b/problemreductions-cli/src/dispatch.rs @@ -2,8 +2,8 @@ use anyhow::{Context, Result}; use problemreductions::registry::{DynProblem, LoadedDynProblem}; use problemreductions::rules::ReductionGraph; use problemreductions::solvers::{ - brute_force_dimensions, solve, solver_capabilities, ExactProblemKey, SolveOutcome, SolveResult, - SolverRequest, + ExactProblemKey, SolveOutcome, SolveResult, SolverRequest, brute_force_dimensions, solve, + solver_capabilities, }; use serde_json::Value; use std::any::Any; @@ -471,7 +471,7 @@ mod tests { } use super::*; - use crate::test_support::{AggregateValueSource, AGGREGATE_SOURCE_NAME}; + use crate::test_support::{AGGREGATE_SOURCE_NAME, AggregateValueSource}; use problemreductions::models::graph::MaximumIndependentSet; use problemreductions::models::misc::BinPacking; use problemreductions::topology::SimpleGraph; @@ -542,7 +542,7 @@ mod tests { #[test] fn completed_recovery_handles_infeasible_numeric_cast() { - use problemreductions::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; + use problemreductions::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; let source = ILP::::new( 1, vec![LinearConstraint::eq(vec![(0, 1)], 2)], @@ -603,22 +603,24 @@ mod tests { (json!([true, true, true]), "Max(None)"), (json!([true, false, false]), "Max(99)"), ] { - assert!(replay - .extract_result(&SolveOutcome::Optimal { - solution, - evaluation: evaluation.into() - }) - .is_err()); + assert!( + replay + .extract_result(&SolveOutcome::Optimal { + solution, + evaluation: evaluation.into() + }) + .is_err() + ); } } } #[test] fn completed_recovery_carries_negative_answers_through_value_mappings() { + use problemreductions::Problem; use problemreductions::models::formula::{CNFClause, NAESatisfiability, Satisfiability}; use problemreductions::models::graph::MaxCut; use problemreductions::solvers::BruteForce; - use problemreductions::Problem; for unsatisfiable in [false, true] { let clauses = if unsatisfiable { vec![vec![1], vec![-1]] @@ -655,8 +657,8 @@ mod tests { #[test] fn completed_recovery_checks_value_and_solution_agreement() { - use problemreductions::models::algebraic::{ObjectiveSense, ILP, QUBO}; use problemreductions::Problem; + use problemreductions::models::algebraic::{ILP, ObjectiveSense, QUBO}; let source = ILP::::new(1, vec![], vec![(0, 1)], ObjectiveSense::Maximize).unwrap(); let mut replay = replay(&source, vec![problem_step::>()]); let target_result = replay @@ -677,22 +679,26 @@ mod tests { serde_json::to_value(different).unwrap(), ) .unwrap(); - assert!(replay - .extract_result(&target_result) - .unwrap_err() - .to_string() - .contains("does not realize the mapped aggregate")); - assert!(replay - .source - .aggregate_witness_evaluation(&json!(true)) - .is_err()); + assert!( + replay + .extract_result(&target_result) + .unwrap_err() + .to_string() + .contains("does not realize the mapped aggregate") + ); + assert!( + replay + .source + .aggregate_witness_evaluation(&json!(true)) + .is_err() + ); } #[test] fn decision_chain_carries_no_through_identity_and_threshold_maps() { use problemreductions::models::{ - formula::{CNFClause, KSatisfiability, Satisfiability}, MinimumVertexCover, + formula::{CNFClause, KSatisfiability, Satisfiability}, }; use problemreductions::variant::K3; for second in [1, -1] { @@ -868,9 +874,11 @@ mod tests { let coefficient = restored.target.data["objective"][0][1].as_f64().unwrap(); restored.target.data["objective"][0][1] = json!(f64::from_bits(coefficient.to_bits() + 1)); let error = BundleReplay::prepare(&restored).err().unwrap(); - assert!(error - .to_string() - .contains("does not match the result of replaying")); + assert!( + error + .to_string() + .contains("does not match the result of replaying") + ); } #[test] @@ -1060,8 +1068,8 @@ mod tests { #[test] fn solver_capabilities_view_centralizes_default_and_available_order() { - use problemreductions::models::graph::RootedTreeArrangement; use problemreductions::Problem; + use problemreductions::models::graph::RootedTreeArrangement; let problem = RootedTreeArrangement::new(SimpleGraph::new(2, vec![(0, 1)]), 1); let loaded = load_problem( diff --git a/problemreductions-cli/src/mcp/prompts.rs b/problemreductions-cli/src/mcp/prompts.rs index 82fbd18b1..77789699e 100644 --- a/problemreductions-cli/src/mcp/prompts.rs +++ b/problemreductions-cli/src/mcp/prompts.rs @@ -9,9 +9,11 @@ pub fn list_prompts() -> Vec { "Explain a problem type: what it models, its variants, and how it connects to \ other problems", ), - Some(vec![PromptArgument::new("problem") - .with_description("Problem name or alias (e.g., MIS, QUBO, MaxCut)") - .with_required(true)]), + Some(vec![ + PromptArgument::new("problem") + .with_description("Problem name or alias (e.g., MIS, QUBO, MaxCut)") + .with_required(true), + ]), ), Prompt::new( "model_my_problem", @@ -19,9 +21,11 @@ pub fn list_prompts() -> Vec { "Map a real-world problem to the closest NP-hard problem type in the reduction \ graph", ), - Some(vec![PromptArgument::new("description") - .with_description("Free-text description of your real-world problem") - .with_required(true)]), + Some(vec![ + PromptArgument::new("description") + .with_description("Free-text description of your real-world problem") + .with_required(true), + ]), ), Prompt::new( "compare", diff --git a/problemreductions-cli/src/mcp/tests.rs b/problemreductions-cli/src/mcp/tests.rs index 1d3264bfd..25b5371a6 100644 --- a/problemreductions-cli/src/mcp/tests.rs +++ b/problemreductions-cli/src/mcp/tests.rs @@ -100,10 +100,12 @@ fn test_find_path_schema_accepts_complete_problem_json() { "problem_json": "{\"type\":\"MaximumIndependentSet\",\"variant\":{},\"data\":{}}" })) .unwrap(); - assert!(params - .problem_json - .unwrap() - .contains("MaximumIndependentSet")); + assert!( + params + .problem_json + .unwrap() + .contains("MaximumIndependentSet") + ); } #[test] @@ -245,11 +247,13 @@ fn test_create_problem_longest_circuit_random() { let json: serde_json::Value = serde_json::from_str(&result.unwrap()).unwrap(); assert_eq!(json["type"], "LongestCircuit"); assert_eq!(json["data"]["graph"]["num_vertices"], 5); - assert!(json["data"]["edge_lengths"] - .as_array() - .unwrap() - .iter() - .all(|length| length == 1)); + assert!( + json["data"]["edge_lengths"] + .as_array() + .unwrap() + .iter() + .all(|length| length == 1) + ); } #[test] diff --git a/problemreductions-cli/src/mcp/tools.rs b/problemreductions-cli/src/mcp/tools.rs index 110997db5..badf72f28 100644 --- a/problemreductions-cli/src/mcp/tools.rs +++ b/problemreductions-cli/src/mcp/tools.rs @@ -6,8 +6,8 @@ use rmcp::tool; use std::collections::BTreeMap; use crate::dispatch::{ - load_problem, solve_result_json, solver_capabilities_view, solver_request, BundleReplay, - ProblemJson, ProblemJsonOutput, ReductionBundle, + BundleReplay, ProblemJson, ProblemJsonOutput, ReductionBundle, load_problem, solve_result_json, + solver_capabilities_view, solver_request, }; use crate::problem_name::{aliases_for, resolve_catalog_problem_ref, resolve_problem_ref}; @@ -254,16 +254,16 @@ impl McpServer { load_problem(&problem.problem_type, &problem.variant, problem.data) }) .transpose()?; - if let Some(loaded) = &loaded { - if loaded.problem_name() != src_ref.name || loaded.variant_map() != src_ref.variant { - anyhow::bail!( - "Source argument resolves to {} with variant {:?} but problem_json contains {} with variant {:?}", - src_ref.name, - src_ref.variant, - loaded.problem_name(), - loaded.variant_map(), - ); - } + if let Some(loaded) = &loaded + && (loaded.problem_name() != src_ref.name || loaded.variant_map() != src_ref.variant) + { + anyhow::bail!( + "Source argument resolves to {} with variant {:?} but problem_json contains {} with variant {:?}", + src_ref.name, + src_ref.variant, + loaded.problem_name(), + loaded.variant_map(), + ); } let batch = crate::commands::graph::find_path_batch( @@ -712,9 +712,11 @@ mod tests { let shown: serde_json::Value = serde_json::from_str(&server.show_problem_inner(name).unwrap()).unwrap(); let inputs = shown["inputs"].as_array().unwrap(); - assert!(inputs - .iter() - .any(|input| input["name"] == "bound" && input["type_name"] == "i64")); + assert!( + inputs + .iter() + .any(|input| input["name"] == "bound" && input["type_name"] == "i64") + ); assert!(!inputs.iter().any(|input| input["name"] == "weights")); let output = server.create_problem_inner(name, &data).unwrap(); let created: ProblemJsonOutput = serde_json::from_str(&output).unwrap(); diff --git a/problemreductions-cli/src/test_support.rs b/problemreductions-cli/src/test_support.rs index 88c3c941d..d6870a02c 100644 --- a/problemreductions-cli/src/test_support.rs +++ b/problemreductions-cli/src/test_support.rs @@ -1,5 +1,5 @@ use crate::dispatch::{PathStep, ProblemJsonOutput, ReductionBundle}; -use problemreductions::models::algebraic::{ObjectiveSense, ILP}; +use problemreductions::models::algebraic::{ILP, ObjectiveSense}; use problemreductions::registry::{ CreateInputCodec, CreateInputInfo, FieldInfo, ProblemSchemaEntry, VariantEntry, }; diff --git a/problemreductions-cli/src/util.rs b/problemreductions-cli/src/util.rs index 04204bb8b..233697b49 100644 --- a/problemreductions-cli/src/util.rs +++ b/problemreductions-cli/src/util.rs @@ -1,6 +1,6 @@ //! Shared utilities for CLI and MCP: parsing helpers and random generation. -use anyhow::{bail, Result}; +use anyhow::{Result, bail}; use num_bigint::BigUint; // --------------------------------------------------------------------------- diff --git a/problemreductions-cli/tests/cli_tests.rs b/problemreductions-cli/tests/cli_tests.rs index ff872587a..43aa0d8ef 100644 --- a/problemreductions-cli/tests/cli_tests.rs +++ b/problemreductions-cli/tests/cli_tests.rs @@ -63,8 +63,10 @@ fn polynomial_comparison_default_layout_and_opt_in_proofs() { assert!(semantics < pairs && pairs < unresolved && unresolved < front); assert!(text.contains("Path 1") && text.contains("num_vars")); assert!(!text.contains("[upper bound]") && !text.contains("[exact]")); - assert!(text[pairs..unresolved] - .contains("2 dominated, 1 equivalent, 3 proven incomparable, 0 unresolved")); + assert!( + text[pairs..unresolved] + .contains("2 dominated, 1 equivalent, 3 proven incomparable, 0 unresolved") + ); assert!(!text.contains("worst case:") && !text.contains("Generic candidate front")); assert!(text.contains("Paths 1, 3: proven incomparable")); assert!(text.contains("Paths 1, 2: Path 1 ≡ Path 2")); @@ -108,17 +110,34 @@ fn polynomial_comparison_default_layout_and_opt_in_proofs() { let identity = &view["pairs"][0]["fields"]["num_vars"]["forward"]["certificate"]; assert_eq!(identity["kind"], "identity"); assert_eq!(identity.as_object().unwrap().len(), 1); - assert!(view["pairs"][0]["fields"]["num_vars"] - .get("generic") - .is_none()); + assert!( + view["pairs"][0]["fields"]["num_vars"] + .get("generic") + .is_none() + ); let output = pred() .args(["path", "MIS", "QUBO", "--proofs"]) .output() .unwrap(); assert!(!output.status.success()); - assert!(String::from_utf8(output.stderr) - .unwrap() - .contains("--compare")); + assert!( + String::from_utf8(output.stderr) + .unwrap() + .contains("--compare") + ); +} + +#[test] +fn test_parse_error_appends_subcommand_workflow_help() { + let output = pred().args(["solve", "--pred solve"]).output().unwrap(); + assert_eq!(output.status.code(), Some(2)); + let stderr = String::from_utf8(output.stderr).unwrap(); + assert!( + stderr.contains("unexpected argument '--pred solve'"), + "{stderr}" + ); + assert!(stderr.contains("pred create"), "{stderr}"); + assert!(stderr.contains("brute-force"), "{stderr}"); } fn extract_target_config( @@ -250,15 +269,21 @@ fn test_list_json_respects_category_filter() { let json: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap(); let variants = json["variants"].as_array().unwrap(); assert_eq!(json["num_types"], 10); - assert!(variants - .iter() - .all(|variant| variant["name"] != "MaximumIndependentSet")); - assert!(variants - .iter() - .all(|variant| variant["category"] == "formula")); - assert!(variants - .iter() - .any(|variant| variant["name"] == "KSatisfiability/K3")); + assert!( + variants + .iter() + .all(|variant| variant["name"] != "MaximumIndependentSet") + ); + assert!( + variants + .iter() + .all(|variant| variant["category"] == "formula") + ); + assert!( + variants + .iter() + .any(|variant| variant["name"] == "KSatisfiability/K3") + ); } #[test] @@ -484,11 +509,13 @@ fn test_solve_balanced_complete_bipartite_subgraph_default_solver_uses_ilp() { let json: serde_json::Value = serde_json::from_str(&stdout).unwrap(); assert_eq!(json["problem"], "BalancedCompleteBipartiteSubgraph"); assert_eq!(json["solver"]["kind"], "ilp"); - assert!(json["solver"]["reduction_path"] - .as_array() - .and_then(|path| path.last()) - .and_then(|step| step.as_str()) - .is_some_and(|step| step.starts_with("ILP<"))); + assert!( + json["solver"]["reduction_path"] + .as_array() + .and_then(|path| path.last()) + .and_then(|step| step.as_str()) + .is_some_and(|step| step.starts_with("ILP<")) + ); assert_eq!(json["evaluation"], "Or(true)"); assert!( json["solution"] @@ -641,9 +668,11 @@ fn test_path_save() { let content = std::fs::read_to_string(&tmp).unwrap(); let json: serde_json::Value = serde_json::from_str(&content).unwrap(); assert!(json.get("path").is_none()); - assert!(json["paths"] - .as_array() - .is_some_and(|paths| !paths.is_empty())); + assert!( + json["paths"] + .as_array() + .is_some_and(|paths| !paths.is_empty()) + ); std::fs::remove_file(&tmp).ok(); } @@ -668,8 +697,10 @@ fn test_path_rejects_limit_above_maximum() { .output() .unwrap(); assert!(!output.status.success()); - assert!(String::from_utf8_lossy(&output.stderr) - .contains("limit must be an integer from 1 to 999 or 'all'")); + assert!( + String::from_utf8_lossy(&output.stderr) + .contains("limit must be an integer from 1 to 999 or 'all'") + ); } #[test] @@ -697,8 +728,10 @@ fn test_path_rejects_zero_limit() { .output() .unwrap(); assert!(!output.status.success()); - assert!(String::from_utf8_lossy(&output.stderr) - .contains("limit must be an integer from 1 to 999 or 'all'")); + assert!( + String::from_utf8_lossy(&output.stderr) + .contains("limit must be an integer from 1 to 999 or 'all'") + ); } #[test] @@ -786,9 +819,11 @@ fn test_show_inputs_follow_the_selected_variant() { "{spec}" ); assert!(result["schema"].get("fields").is_none()); - assert!(inputs - .iter() - .all(|input| !input["type_name"].as_str().unwrap().contains(""))); + assert!( + inputs + .iter() + .all(|input| !input["type_name"].as_str().unwrap().contains("")) + ); } } @@ -1822,9 +1857,11 @@ fn test_path_set_envelope_has_only_per_item_paths() { let json: serde_json::Value = serde_json::from_str(&String::from_utf8(output.stdout).unwrap()).unwrap(); - assert!(json["paths"] - .as_array() - .is_some_and(|paths| !paths.is_empty())); + assert!( + json["paths"] + .as_array() + .is_some_and(|paths| !paths.is_empty()) + ); assert!(json.get("path").is_none()); let path = json["paths"][0]["path"] @@ -5734,9 +5771,11 @@ fn test_path_overall_preserves_unavailable_fields_alongside_exact_fields() { .find(|field| field["field"] == "schedule_horizon") .unwrap(); assert_eq!(horizon["relation"], "unavailable"); - assert!(horizon["reason"] - .as_str() - .is_some_and(|reason| !reason.is_empty())); + assert!( + horizon["reason"] + .as_str() + .is_some_and(|reason| !reason.is_empty()) + ); } #[test] @@ -5775,11 +5814,13 @@ fn test_vertex_cover_via_lcs_to_mis_solves_and_recovers_optimum() { ); let selected: serde_json::Value = serde_json::from_slice(&std::fs::read(&route).unwrap()).unwrap(); - assert!(selected["overall_parameters"]["fields"] - .as_array() - .unwrap() - .iter() - .all(|field| field["relation"] != "unavailable")); + assert!( + selected["overall_parameters"]["fields"] + .as_array() + .unwrap() + .iter() + .all(|field| field["relation"] != "unavailable") + ); let reduced = pred() .args([ "reduce", @@ -9861,7 +9902,7 @@ fn extract_test_solve_bundle(bundle_file: &std::path::Path) -> (String, String) #[test] fn test_decision_extract_checks_bound_while_solve_recovers_no() { - use problemreductions::models::{graph::MinimumVertexCover, Decision}; + use problemreductions::models::{Decision, graph::MinimumVertexCover}; use problemreductions::rules::{ReduceTo, ReductionResult}; use problemreductions::topology::SimpleGraph; use serde_json::json; @@ -9954,7 +9995,7 @@ fn test_decision_extract_checks_bound_while_solve_recovers_no() { #[test] fn test_extract_rejects_infeasible_target_even_when_decoded_source_is_feasible() { - use problemreductions::models::{OpenShopScheduling, ILP}; + use problemreductions::models::{ILP, OpenShopScheduling}; use problemreductions::rules::{ReduceTo, ReductionResult}; use serde_json::json; @@ -10121,7 +10162,9 @@ fn test_extract_rejects_structurally_invalid_one_hot_config() { let extract_out = extract_target_config( &bundle_file, - serde_json::json!([false, false, false, false, false, false, false, false, false]), + serde_json::json!([ + false, false, false, false, false, false, false, false, false + ]), ); assert!(!extract_out.status.success()); let stderr = String::from_utf8(extract_out.stderr).unwrap(); diff --git a/problemreductions-cli/tests/mcp_integration.rs b/problemreductions-cli/tests/mcp_integration.rs index 04874f2fc..c88d4e810 100644 --- a/problemreductions-cli/tests/mcp_integration.rs +++ b/problemreductions-cli/tests/mcp_integration.rs @@ -49,10 +49,10 @@ mod mcp_tests { if trimmed.is_empty() { continue; } - if let Ok(val) = serde_json::from_str::(trimmed) { - if val.get("jsonrpc").is_some() { - return val; - } + if let Ok(val) = serde_json::from_str::(trimmed) + && val.get("jsonrpc").is_some() + { + return val; } } } @@ -205,10 +205,12 @@ mod mcp_tests { assert_eq!(call_resp["id"], 3); assert!(call_resp.get("error").is_none(), "{call_resp}"); assert_ne!(call_resp["result"]["isError"], true); - assert!(call_resp["result"]["content"][0]["text"] - .as_str() - .unwrap() - .contains("MaximumIndependentSet")); + assert!( + call_resp["result"]["content"][0]["text"] + .as_str() + .unwrap() + .contains("MaximumIndependentSet") + ); assert!(call_resp["result"].get("resultType").is_none()); shutdown(stdin, child); @@ -359,10 +361,12 @@ mod mcp_tests { let message = &prompt_resp["result"]["messages"][0]; assert_eq!(message["role"], "user"); assert_eq!(message["content"]["type"], "text"); - assert!(message["content"]["text"] - .as_str() - .unwrap() - .contains("QUBO")); + assert!( + message["content"]["text"] + .as_str() + .unwrap() + .contains("QUBO") + ); send( &mut stdin, diff --git a/problemreductions-expr/Cargo.toml b/problemreductions-expr/Cargo.toml index 09304c30f..1f301b615 100644 --- a/problemreductions-expr/Cargo.toml +++ b/problemreductions-expr/Cargo.toml @@ -1,7 +1,8 @@ [package] name = "problemreductions-expr" version = "0.6.0" -edition = "2021" +edition = "2024" +rust-version = "1.88" description = "Lossless symbolic expressions for problemreductions" license = "MIT" repository = "https://github.com/CodingThrust/problem-reductions" diff --git a/problemreductions-macros/Cargo.toml b/problemreductions-macros/Cargo.toml index d20910c69..4c2981b73 100644 --- a/problemreductions-macros/Cargo.toml +++ b/problemreductions-macros/Cargo.toml @@ -1,7 +1,8 @@ [package] name = "problemreductions-macros" version = "0.6.0" -edition = "2021" +edition = "2024" +rust-version = "1.88" description = "Procedural macros for problemreductions" license = "MIT" repository = "https://github.com/CodingThrust/problem-reductions" diff --git a/problemreductions-macros/src/expr_codegen.rs b/problemreductions-macros/src/expr_codegen.rs index 03e58df74..f09197f92 100644 --- a/problemreductions-macros/src/expr_codegen.rs +++ b/problemreductions-macros/src/expr_codegen.rs @@ -49,16 +49,17 @@ pub(crate) fn complexity_estimate_tokens( ) -> syn::Result { Ok(match expression.node() { ExprNode::Const(value) => { - let value = - value - .to_f64() - .filter(|value| value.is_finite()) - .ok_or_else(|| { - syn::Error::new( - proc_macro2::Span::call_site(), - format!("exact expression constant {value} is outside complexity estimation"), - ) - })?; + let value = value + .to_f64() + .filter(|value| value.is_finite()) + .ok_or_else(|| { + syn::Error::new( + proc_macro2::Span::call_site(), + format!( + "exact expression constant {value} is outside complexity estimation" + ), + ) + })?; quote! { #value } } ExprNode::Var(name) => { @@ -141,6 +142,21 @@ fn unary_expr_tokens(value: &Expr, build: impl FnOnce(TokenStream) -> TokenStrea mod tests { use super::*; + #[test] + fn test_complexity_codegen_rejects_unrepresentable_constant() { + let decimal = "1".to_owned() + &"0".repeat(400); + let expression = Expr::parse(&decimal); + let parameters = syn::parse_quote!(parameters); + let error = complexity_estimate_tokens(&expression, ¶meters).unwrap_err(); + assert_eq!( + error.to_string(), + format!( + "exact expression constant {} is outside complexity estimation", + decimal + ) + ); + } + #[test] fn shared_parser_drives_codegen() { let expression = Expr::parse("n * (n - 1) / 2 - m"); diff --git a/problemreductions-macros/src/lib.rs b/problemreductions-macros/src/lib.rs index 4047f7bb1..3da9fa834 100644 --- a/problemreductions-macros/src/lib.rs +++ b/problemreductions-macros/src/lib.rs @@ -12,7 +12,7 @@ use proc_macro::TokenStream; use proc_macro2::TokenStream as TokenStream2; use quote::quote; use std::collections::{HashMap, HashSet}; -use syn::{parse_macro_input, DeriveInput, GenericArgument, ItemImpl, Path, PathArguments, Type}; +use syn::{DeriveInput, GenericArgument, ItemImpl, Path, PathArguments, Type, parse_macro_input}; /// Generate static construction-input metadata from a typed create spec. #[proc_macro_derive(CreateSpec, attributes(create))] @@ -167,7 +167,7 @@ fn create_codec_tokens(value: &syn::LitStr) -> syn::Result { return Err(syn::Error::new( value.span(), "unknown construction codec; expected one of: auto, scalar, json, comma-separated, semicolon-separated, edge-list, arc-list, bipartite-edge-list, equality-pair-list, functional-dependency-list, character-rows", - )) + )); } }; Ok(quote!(crate::registry::CreateInputCodec::#variant)) @@ -273,7 +273,7 @@ fn generate_common_aggregate_impl( return Err(syn::Error::new_spanned( mapping, "expected identity or ilp_feasibility", - )) + )); } }; let mut implementation = implementation.clone(); @@ -455,7 +455,7 @@ impl ReductionAttrs { return Err(syn::Error::new( relation.span(), "expected `exact`, `upper_bound`, or `unavailable`", - )) + )); } }; self.fields.extend( @@ -516,15 +516,15 @@ fn extract_type_name(ty: &Type) -> Option { let segment = type_path.path.segments.last()?; let ident = segment.ident.to_string(); - if ident == "Decision" { - if let PathArguments::AngleBracketed(args) = &segment.arguments { - let inner_ty = args.args.iter().find_map(|arg| match arg { - GenericArgument::Type(ty) => Some(ty), - _ => None, - })?; - let inner_name = extract_type_name(inner_ty)?; - return Some(format!("Decision{inner_name}")); - } + if ident == "Decision" + && let PathArguments::AngleBracketed(args) = &segment.arguments + { + let inner_ty = args.args.iter().find_map(|arg| match arg { + GenericArgument::Type(ty) => Some(ty), + _ => None, + })?; + let inner_name = extract_type_name(inner_ty)?; + return Some(format!("Decision{inner_name}")); } Some(ident) @@ -555,16 +555,15 @@ fn collect_type_generic_names(generics: &syn::Generics) -> HashSet { fn type_uses_type_generics(ty: &Type, type_generics: &HashSet) -> bool { match ty { Type::Path(type_path) => { - if let Some(segment) = type_path.path.segments.last() { - if let PathArguments::AngleBracketed(args) = &segment.arguments { - for arg in args.args.iter() { - if let GenericArgument::Type(Type::Path(inner)) = arg { - if let Some(ident) = inner.path.get_ident() { - if type_generics.contains(&ident.to_string()) { - return true; - } - } - } + if let Some(segment) = type_path.path.segments.last() + && let PathArguments::AngleBracketed(args) = &segment.arguments + { + for arg in args.args.iter() { + if let GenericArgument::Type(Type::Path(inner)) = arg + && let Some(ident) = inner.path.get_ident() + && type_generics.contains(&ident.to_string()) + { + return true; } } } @@ -696,10 +695,10 @@ fn extract_target_from_trait(path: &Path) -> syn::Result { return Err(syn::Error::new_spanned(segment, "Expected ReduceTo trait")); } - if let PathArguments::AngleBracketed(args) = &segment.arguments { - if let Some(GenericArgument::Type(ty)) = args.args.first() { - return Ok(ty.clone()); - } + if let PathArguments::AngleBracketed(args) = &segment.arguments + && let Some(GenericArgument::Type(ty)) = args.args.first() + { + return Ok(ty.clone()); } Err(syn::Error::new_spanned( @@ -1077,7 +1076,31 @@ fn generate_complexity_eval_fn( #[cfg(test)] mod tests { use super::*; - use syn::{parse_str, Type}; + use syn::{Type, parse_str}; + + #[test] + fn test_extract_type_name_skips_lifetime_and_const_arguments() { + let ty: Type = parse_str("Decision<'a, 3, MinimumVertexCover>").unwrap(); + assert_eq!( + extract_type_name(&ty).as_deref(), + Some("DecisionMinimumVertexCover") + ); + let ty: Type = parse_str("Decision<'a, 3>").unwrap(); + assert_eq!(extract_type_name(&ty), None); + } + + #[test] + fn test_reduction_rejects_type_generic_source() { + let attrs: ReductionAttrs = + syn::parse_quote! { transform = exact { num_vertices = "num_vertices" } }; + let implementation: ItemImpl = + syn::parse_quote! { impl ReduceTo for Source {} }; + let error = generate_reduction_entry(&attrs, &implementation).unwrap_err(); + assert_eq!( + error.to_string(), + "#[reduction] does not support type generics (found: G). Make the ReduceTo impl concrete by specifying explicit types." + ); + } #[test] fn parameters_report_expression_domain_errors() { @@ -1350,10 +1373,12 @@ mod tests { .to_string(); assert!(tokens.contains("reduce_aggregate_fn : None")); assert!(tokens.contains("aggregate_view_fn : None")); - assert!(syn::parse2::(quote! { - aggregate = identity, transform = exact { n = n } - }) - .is_err()); + assert!( + syn::parse2::(quote! { + aggregate = identity, transform = exact { n = n } + }) + .is_err() + ); } #[test] @@ -1446,26 +1471,34 @@ mod tests { #[test] fn reduction_rejects_legacy_exact_and_bound_attributes() { - assert!(syn::parse2::(quote! { - exact = { n = "n" } - }) - .is_err()); - assert!(syn::parse2::(quote! { - bound = { n = "n" } - }) - .is_err()); + assert!( + syn::parse2::(quote! { + exact = { n = "n" } + }) + .is_err() + ); + assert!( + syn::parse2::(quote! { + bound = { n = "n" } + }) + .is_err() + ); } #[test] fn reduction_requires_unavailable_to_be_the_primary_transform_declaration() { - assert!(syn::parse2::(quote! { - unavailable = { n = "not represented" } - }) - .is_err()); - assert!(syn::parse2::(quote! { - transform = unavailable { n = "not represented" } - }) - .is_ok()); + assert!( + syn::parse2::(quote! { + unavailable = { n = "not represented" } + }) + .is_err() + ); + assert!( + syn::parse2::(quote! { + transform = unavailable { n = "not represented" } + }) + .is_ok() + ); } #[test] diff --git a/problemreductions-web/Cargo.toml b/problemreductions-web/Cargo.toml index 7c6365e3e..994b70aee 100644 --- a/problemreductions-web/Cargo.toml +++ b/problemreductions-web/Cargo.toml @@ -1,7 +1,8 @@ [package] name = "problemreductions-web" version = "0.6.0" -edition = "2021" +edition = "2024" +rust-version = "1.88" publish = false [lib] diff --git a/problemreductions-web/src/lib.rs b/problemreductions-web/src/lib.rs index 69d7aadfa..3a1e2c679 100644 --- a/problemreductions-web/src/lib.rs +++ b/problemreductions-web/src/lib.rs @@ -14,7 +14,7 @@ pub mod types; use expr::{Expr, Symbol}; use parameters::{ParameterRelation, ParameterTransform}; -use poly_compare::{compare_summary, Profile, Reason}; +use poly_compare::{Profile, Reason, compare_summary}; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; use wasm_bindgen::prelude::*; diff --git a/problemreductions-web/tests/paths.rs b/problemreductions-web/tests/paths.rs index 7f63203fe..2de799546 100644 --- a/problemreductions-web/tests/paths.rs +++ b/problemreductions-web/tests/paths.rs @@ -1,5 +1,5 @@ use problemreductions_web::{edge_growth, find_paths, summarize_paths}; -use serde_json::{json, Value}; +use serde_json::{Value, json}; fn graph() -> Value { json!({ @@ -190,9 +190,11 @@ fn comparison_retains_explicit_null_certificates_and_typed_unavailable_reasons() assert_eq!(field.get("certificate"), Some(&Value::Null)); assert_eq!(field["accuracy"]["kind"], "unavailable"); assert_eq!(field["accuracy"]["reason"]["kind"], expected_reason); - assert!(field["accuracy"]["reason"]["detail"] - .as_str() - .is_some_and(|detail| !detail.is_empty())); + assert!( + field["accuracy"]["reason"]["detail"] + .as_str() + .is_some_and(|detail| !detail.is_empty()) + ); } } diff --git a/rustfmt.toml b/rustfmt.toml index 2feefadfe..754ecb1ff 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -2,7 +2,7 @@ # See: https://rust-lang.github.io/rustfmt/ # Stable options -edition = "2021" +edition = "2024" max_width = 100 tab_spaces = 4 newline_style = "Unix" diff --git a/scripts/pipeline_pr.py b/scripts/pipeline_pr.py index db9543b38..e9cd934ea 100644 --- a/scripts/pipeline_pr.py +++ b/scripts/pipeline_pr.py @@ -825,6 +825,7 @@ def parse_args(argv: list[str]) -> argparse.Namespace: if name == "wait-ci": command.add_argument("--timeout", type=float, default=900) command.add_argument("--interval", type=float, default=30) + command.add_argument("--format", choices=["json", "text"], default="json") elif name == "create": command.add_argument("--title", required=True) command.add_argument("--body-file", required=True) diff --git a/scripts/test_pipeline_pr.py b/scripts/test_pipeline_pr.py index 279c876f2..34d853bb9 100644 --- a/scripts/test_pipeline_pr.py +++ b/scripts/test_pipeline_pr.py @@ -640,10 +640,22 @@ def test_create_pr_uses_gh_pr_create_and_returns_current_context( "--head", "issue-117-graph-partitioning", ) - fetch_current_pr_data_for_repo.assert_called_once_with("CodingThrust/problem-reductions") + fetch_current_pr_data_for_repo.assert_called_once_with( + "CodingThrust/problem-reductions", head="issue-117-graph-partitioning" + ) self.assertEqual(result["pr_number"], 570) self.assertEqual(result["repo"], "CodingThrust/problem-reductions") + def test_parse_args_wait_ci_output_format(self) -> None: + for options, expected in [ + ([], "json"), + (["--format", "json"], "json"), + (["--format", "text"], "text"), + ]: + with self.subTest(options=options): + args = parse_args(["wait-ci", "--repo", "x/y", "--pr", "1", *options]) + self.assertEqual(args.format, expected) + def test_parse_args_accepts_comment_and_create_commands(self) -> None: comment_args = parse_args( [ diff --git a/src/example_db/specs.rs b/src/example_db/specs.rs index 39d9dd8e8..b1934d127 100644 --- a/src/example_db/specs.rs +++ b/src/example_db/specs.rs @@ -5,7 +5,7 @@ use crate::export::{ProblemSide, RuleExample, SolutionPair}; use crate::models::algebraic::{ - Bounded, BoundsPolicy, General, ILPCoefficient, VariableDomain, ILP, + Bounded, BoundsPolicy, General, ILP, ILPCoefficient, VariableDomain, }; use crate::prelude::{Problem, ReduceTo, ReductionResult}; use crate::registry::DynProblem; diff --git a/src/export.rs b/src/export.rs index 86f6ece00..0e7f58d39 100644 --- a/src/export.rs +++ b/src/export.rs @@ -1,7 +1,7 @@ //! JSON export schema for example payloads. -use crate::rules::registry::{ParameterContractError, ReductionParameterContract}; use crate::rules::ReductionGraph; +use crate::rules::registry::{ParameterContractError, ReductionParameterContract}; use crate::traits::Problem; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; diff --git a/src/growth.rs b/src/growth.rs index 1a2e05d30..10cb97aae 100644 --- a/src/growth.rs +++ b/src/growth.rs @@ -339,9 +339,7 @@ pub enum GrowthFailure { InvalidExponentialBase(String), #[error("represented exponent is outside the growth domain: {0}")] RepresentedExponentOutOfRange(String), - #[error( - "exponential factor {base}^({coefficient} * {variable}) decreases as {variable} grows" - )] + #[error("exponential factor {base}^({coefficient} * {variable}) decreases as {variable} grows")] DecayingExponential { base: String, variable: String, diff --git a/src/io.rs b/src/io.rs index 9e3eb8dc6..1371361f2 100644 --- a/src/io.rs +++ b/src/io.rs @@ -4,7 +4,7 @@ //! to various file formats using serde. use crate::error::{ProblemError, Result}; -use serde::{de::DeserializeOwned, Serialize}; +use serde::{Serialize, de::DeserializeOwned}; use std::fs::File; use std::io::{BufReader, BufWriter, Read, Write}; use std::path::Path; diff --git a/src/lib.rs b/src/lib.rs index 599fc3af0..2bb197104 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,9 +49,9 @@ pub mod variant; pub mod prelude { // Problem types pub use crate::models::algebraic::{ - AlgebraicEquationsOverGF2, ConsecutiveOnesMatrixAugmentation, - MinimumWeightSolutionToLinearEquations, QuadraticAssignment, QuadraticCongruences, - SimultaneousIncongruences, SparseMatrixCompression, BMF, QUBO, + AlgebraicEquationsOverGF2, BMF, ConsecutiveOnesMatrixAugmentation, + MinimumWeightSolutionToLinearEquations, QUBO, QuadraticAssignment, QuadraticCongruences, + SimultaneousIncongruences, SparseMatrixCompression, }; pub use crate::models::formula::{ CNFClause, CircuitSAT, KSatisfiability, Maximum2Satisfiability, NAESatisfiability, @@ -116,7 +116,7 @@ pub mod prelude { pub use big_o::big_o_normal_form; pub use error::{ProblemError, Result}; pub use expr::{ - evaluate_approximate, ApproximationError, AsymptoticAnalysisError, Expr, ParseError, + ApproximationError, AsymptoticAnalysisError, Expr, ParseError, evaluate_approximate, }; pub use growth::Growth; pub use registry::{ComplexityClass, ProblemInfo}; @@ -129,8 +129,8 @@ pub use types::{ // Re-export proc macros for reduction registration and variant declaration pub use problemreductions_macros::{ - aggregate_reduction, declare_variants, reduction, register_aggregate_reduction, - register_brute_force, CreateSpec, + CreateSpec, aggregate_reduction, declare_variants, reduction, register_aggregate_reduction, + register_brute_force, }; // Re-export inventory so `declare_variants!` can use `$crate::inventory::submit!` diff --git a/src/models/algebraic/closest_vector_problem.rs b/src/models/algebraic/closest_vector_problem.rs index 0f2658844..4a8e0065f 100644 --- a/src/models/algebraic/closest_vector_problem.rs +++ b/src/models/algebraic/closest_vector_problem.rs @@ -305,8 +305,8 @@ crate::declare_variants! { crate::register_decision_variant!(@edges ClosestVectorProblem, "DecisionClosestVectorProblem"); #[cfg(feature = "example-db")] -pub(crate) fn decision_canonical_rule_example_specs( -) -> Vec { +pub(crate) fn decision_canonical_rule_example_specs() +-> Vec { vec![crate::example_db::specs::RuleExampleSpec { id: "decision_closest_vector_problem_to_closest_vector_problem", build: || { diff --git a/src/models/algebraic/consecutive_ones_submatrix.rs b/src/models/algebraic/consecutive_ones_submatrix.rs index 1f9e64adb..6a3e88f98 100644 --- a/src/models/algebraic/consecutive_ones_submatrix.rs +++ b/src/models/algebraic/consecutive_ones_submatrix.rs @@ -218,7 +218,7 @@ impl Problem for ConsecutiveOnesSubmatrix { let selected: Vec = config .iter() .enumerate() - .filter(|(_, &v)| v) + .filter(|&(_, &v)| v) .map(|(i, _)| i) .collect(); if self.bound != selected.len() { diff --git a/src/models/algebraic/feasible_basis_extension.rs b/src/models/algebraic/feasible_basis_extension.rs index 09ebd5a2b..ac53cd52c 100644 --- a/src/models/algebraic/feasible_basis_extension.rs +++ b/src/models/algebraic/feasible_basis_extension.rs @@ -414,7 +414,7 @@ impl Problem for FeasibleBasisExtension { let selected_free: Vec = config .iter() .enumerate() - .filter(|(_, &v)| v) + .filter(|&(_, &v)| v) .map(|(i, _)| free_cols[i]) .collect(); diff --git a/src/models/algebraic/ilp.rs b/src/models/algebraic/ilp.rs index f1b39bad3..2b2906e1e 100644 --- a/src/models/algebraic/ilp.rs +++ b/src/models/algebraic/ilp.rs @@ -7,7 +7,7 @@ use crate::registry::{ConstructionError, FieldInfo, ProblemSchemaEntry, VariantDimension}; use crate::traits::{EvaluationError, Problem}; use crate::types::{ - i64_to_exact_f64, Extremum, NumericArithmeticError, NumericSize, WeightElement, + Extremum, NumericArithmeticError, NumericSize, WeightElement, i64_to_exact_f64, }; use serde::{Deserialize, Deserializer, Serialize}; use std::fmt::Debug; @@ -585,20 +585,20 @@ fn normalize_constraint( terms.sort_by_key(|&(variable, _)| variable); let mut normalized: Vec<(usize, C)> = Vec::with_capacity(terms.len()); for (variable, coefficient) in terms { - if let Some((previous_variable, previous_coefficient)) = normalized.last_mut() { - if *previous_variable == variable { - *previous_coefficient = previous_coefficient - .checked_add_value(coefficient) - .map_err(|error| { - construction_arithmetic_error( - error, - format!( - "merging duplicate variable {variable} in ILP constraint {constraint_index}" - ), - ) - })?; - continue; - } + if let Some((previous_variable, previous_coefficient)) = normalized.last_mut() + && *previous_variable == variable + { + *previous_coefficient = previous_coefficient + .checked_add_value(coefficient) + .map_err(|error| { + construction_arithmetic_error( + error, + format!( + "merging duplicate variable {variable} in ILP constraint {constraint_index}" + ), + ) + })?; + continue; } normalized.push((variable, coefficient)); } @@ -625,18 +625,18 @@ fn normalize_objective( objective.sort_by_key(|&(variable, _)| variable); let mut normalized: Vec<(usize, C)> = Vec::with_capacity(objective.len()); for (variable, coefficient) in objective { - if let Some((previous_variable, previous_coefficient)) = normalized.last_mut() { - if *previous_variable == variable { - *previous_coefficient = previous_coefficient - .checked_add_value(coefficient) - .map_err(|error| { - construction_arithmetic_error( - error, - format!("merged objective coefficient of variable {variable}"), - ) - })?; - continue; - } + if let Some((previous_variable, previous_coefficient)) = normalized.last_mut() + && *previous_variable == variable + { + *previous_coefficient = previous_coefficient + .checked_add_value(coefficient) + .map_err(|error| { + construction_arithmetic_error( + error, + format!("merged objective coefficient of variable {variable}"), + ) + })?; + continue; } normalized.push((variable, coefficient)); } diff --git a/src/models/algebraic/minimum_matrix_domination.rs b/src/models/algebraic/minimum_matrix_domination.rs index 98f1e2ec9..b581a72f0 100644 --- a/src/models/algebraic/minimum_matrix_domination.rs +++ b/src/models/algebraic/minimum_matrix_domination.rs @@ -96,7 +96,7 @@ impl MinimumMatrixDomination { .flat_map(|(i, row)| { row.iter() .enumerate() - .filter(|(_, &value)| value) + .filter(|&(_, &value)| value) .map(move |(j, _)| (i, j)) }) .collect(); @@ -157,7 +157,7 @@ impl Problem for MinimumMatrixDomination { let selected: Vec = config .iter() .enumerate() - .filter(|(_, &v)| v) + .filter(|&(_, &v)| v) .map(|(i, _)| i) .collect(); diff --git a/src/models/algebraic/minimum_weight_decoding.rs b/src/models/algebraic/minimum_weight_decoding.rs index 99ab2a3c1..30d9737c2 100644 --- a/src/models/algebraic/minimum_weight_decoding.rs +++ b/src/models/algebraic/minimum_weight_decoding.rs @@ -153,7 +153,7 @@ impl Problem for MinimumWeightDecoding { let dot: usize = row .iter() .zip(config.iter()) - .filter(|(&h, &x)| h && x) + .filter(|&(&h, &x)| h && x) .count(); let syndrome_bit = dot % 2 == 1; if syndrome_bit != self.target[i] { 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 b1f25afd8..bbfdb2413 100644 --- a/src/models/algebraic/minimum_weight_solution_to_linear_equations.rs +++ b/src/models/algebraic/minimum_weight_solution_to_linear_equations.rs @@ -224,7 +224,7 @@ impl Problem for MinimumWeightSolutionToLinearEquations { let columns: Vec = config .iter() .enumerate() - .filter(|(_, &v)| v) + .filter(|&(_, &v)| v) .map(|(j, _)| j) .collect(); diff --git a/src/models/algebraic/mod.rs b/src/models/algebraic/mod.rs index c4b7393c9..560270820 100644 --- a/src/models/algebraic/mod.rs +++ b/src/models/algebraic/mod.rs @@ -47,8 +47,8 @@ pub use consecutive_ones_submatrix::ConsecutiveOnesSubmatrix; pub use equilibrium_point::EquilibriumPoint; pub use feasible_basis_extension::FeasibleBasisExtension; pub use ilp::{ - Bounded, BoundsPolicy, Comparison, General, ILPCoefficient, IntegerVariable, LinearConstraint, - ObjectiveSense, VariableDomain, ILP, + Bounded, BoundsPolicy, Comparison, General, ILP, ILPCoefficient, IntegerVariable, + LinearConstraint, ObjectiveSense, VariableDomain, }; pub use minimum_matrix_cover::MinimumMatrixCover; pub use minimum_matrix_domination::MinimumMatrixDomination; diff --git a/src/models/algebraic/quadratic_assignment.rs b/src/models/algebraic/quadratic_assignment.rs index 50ef13fbd..c4a22b97f 100644 --- a/src/models/algebraic/quadratic_assignment.rs +++ b/src/models/algebraic/quadratic_assignment.rs @@ -261,8 +261,8 @@ crate::register_decision_variant!( ); #[cfg(feature = "example-db")] -pub(crate) fn decision_canonical_rule_example_specs( -) -> Vec { +pub(crate) fn decision_canonical_rule_example_specs() +-> Vec { vec![crate::example_db::specs::RuleExampleSpec { id: "decision_quadratic_assignment_to_quadratic_assignment", build: || { diff --git a/src/models/algebraic/qubo.rs b/src/models/algebraic/qubo.rs index fc6d178ed..7f9dead34 100644 --- a/src/models/algebraic/qubo.rs +++ b/src/models/algebraic/qubo.rs @@ -382,8 +382,8 @@ crate::register_decision_variant!( ); #[cfg(feature = "example-db")] -pub(crate) fn decision_canonical_rule_example_specs( -) -> Vec { +pub(crate) fn decision_canonical_rule_example_specs() +-> Vec { vec![crate::example_db::specs::RuleExampleSpec { id: "decision_qubo_to_qubo", build: || { diff --git a/src/models/formula/ksat.rs b/src/models/formula/ksat.rs index 6d2e9bb7c..001f7e804 100644 --- a/src/models/formula/ksat.rs +++ b/src/models/formula/ksat.rs @@ -7,10 +7,10 @@ use crate::registry::{FieldInfo, ProblemSchemaEntry, VariantDimension}; use crate::traits::Problem; -use crate::variant::{KValue, K2, K3}; -use serde::{de::Error as _, Deserialize, Deserializer, Serialize}; +use crate::variant::{K2, K3, KValue}; +use serde::{Deserialize, Deserializer, Serialize, de::Error as _}; -use super::{sat::validate_cnf_literals, CNFClause}; +use super::{CNFClause, sat::validate_cnf_literals}; pub(crate) fn first_n_odd_primes(count: usize) -> Vec { let mut primes = Vec::with_capacity(count); diff --git a/src/models/formula/maximum_2_satisfiability.rs b/src/models/formula/maximum_2_satisfiability.rs index 67954de0a..c5c330fda 100644 --- a/src/models/formula/maximum_2_satisfiability.rs +++ b/src/models/formula/maximum_2_satisfiability.rs @@ -9,7 +9,7 @@ use crate::traits::Problem; use crate::types::Max; use serde::{Deserialize, Serialize}; -use super::{sat::validate_cnf_literals, CNFClause}; +use super::{CNFClause, sat::validate_cnf_literals}; inventory::submit! { ProblemSchemaEntry { @@ -208,8 +208,8 @@ crate::register_decision_variant!( ); #[cfg(feature = "example-db")] -pub(crate) fn decision_canonical_rule_example_specs( -) -> Vec { +pub(crate) fn decision_canonical_rule_example_specs() +-> Vec { vec![crate::example_db::specs::RuleExampleSpec { id: "decision_maximum_2_satisfiability_to_maximum_2_satisfiability", build: || { diff --git a/src/models/formula/nae_satisfiability.rs b/src/models/formula/nae_satisfiability.rs index c3edbe42c..4a7064344 100644 --- a/src/models/formula/nae_satisfiability.rs +++ b/src/models/formula/nae_satisfiability.rs @@ -7,7 +7,7 @@ use crate::registry::{FieldInfo, ProblemSchemaEntry}; use crate::traits::Problem; use serde::{Deserialize, Serialize}; -use super::{sat::validate_cnf_literals, CNFClause}; +use super::{CNFClause, sat::validate_cnf_literals}; inventory::submit! { ProblemSchemaEntry { @@ -152,11 +152,7 @@ impl NAESatisfiability { fn literal_value(lit: i64, assignment: &[bool]) -> bool { let var = lit.unsigned_abs() as usize - 1; let value = assignment.get(var).copied().unwrap_or(false); - if lit > 0 { - value - } else { - !value - } + if lit > 0 { value } else { !value } } fn clause_is_nae_satisfied(clause: &CNFClause, assignment: &[bool]) -> bool { diff --git a/src/models/formula/non_tautology.rs b/src/models/formula/non_tautology.rs index a45f40aab..1f70c62a0 100644 --- a/src/models/formula/non_tautology.rs +++ b/src/models/formula/non_tautology.rs @@ -114,11 +114,7 @@ impl NonTautology { fn literal_is_true(lit: i64, assignment: &[bool]) -> bool { let var = lit.unsigned_abs() as usize - 1; let value = assignment.get(var).copied().unwrap_or(false); - if lit > 0 { - value - } else { - !value - } + if lit > 0 { value } else { !value } } /// Check if all disjuncts are false (the formula evaluates to false). diff --git a/src/models/formula/one_in_three_satisfiability.rs b/src/models/formula/one_in_three_satisfiability.rs index f78004e32..e0ebb93b8 100644 --- a/src/models/formula/one_in_three_satisfiability.rs +++ b/src/models/formula/one_in_three_satisfiability.rs @@ -8,7 +8,7 @@ use crate::registry::{FieldInfo, ProblemSchemaEntry}; use crate::traits::Problem; use serde::{Deserialize, Serialize}; -use super::{sat::validate_cnf_literals, CNFClause}; +use super::{CNFClause, sat::validate_cnf_literals}; inventory::submit! { ProblemSchemaEntry { @@ -117,11 +117,7 @@ impl OneInThreeSatisfiability { .filter(|&&lit| { let var = lit.unsigned_abs() as usize - 1; // Convert to 0-indexed let value = assignment.get(var).copied().unwrap_or(false); - if lit > 0 { - value - } else { - !value - } + if lit > 0 { value } else { !value } }) .count(); true_count == 1 diff --git a/src/models/formula/planar_3_satisfiability.rs b/src/models/formula/planar_3_satisfiability.rs index f32349663..ecb17f905 100644 --- a/src/models/formula/planar_3_satisfiability.rs +++ b/src/models/formula/planar_3_satisfiability.rs @@ -9,7 +9,7 @@ use crate::registry::{FieldInfo, ProblemSchemaEntry}; use crate::traits::Problem; use serde::{Deserialize, Serialize}; -use super::{sat::validate_cnf_literals, CNFClause}; +use super::{CNFClause, sat::validate_cnf_literals}; inventory::submit! { ProblemSchemaEntry { diff --git a/src/models/formula/qbf.rs b/src/models/formula/qbf.rs index 1dca5cc6c..f1f83f6b3 100644 --- a/src/models/formula/qbf.rs +++ b/src/models/formula/qbf.rs @@ -8,7 +8,7 @@ //! ∀ (ForAll) or ∃ (Exists) and E is a Boolean expression in CNF, //! determine whether F is true. -use crate::models::formula::{sat::validate_cnf_literals, CNFClause}; +use crate::models::formula::{CNFClause, sat::validate_cnf_literals}; use crate::registry::{FieldInfo, ProblemSchemaEntry}; use crate::traits::Problem; use serde::{Deserialize, Serialize}; diff --git a/src/models/formula/sat.rs b/src/models/formula/sat.rs index fb0b6ff5f..c4455eeb5 100644 --- a/src/models/formula/sat.rs +++ b/src/models/formula/sat.rs @@ -60,11 +60,7 @@ impl CNFClause { .checked_sub(1) .expect("CNF literal 0 is invalid"); let value = assignment.get(var).copied().unwrap_or(false); - if lit > 0 { - value - } else { - !value - } + if lit > 0 { value } else { !value } }) } @@ -309,11 +305,7 @@ pub(crate) fn is_satisfying_assignment( clause.iter().any(|&lit| { let var = lit.unsigned_abs() as usize - 1; let value = assignment.get(var).copied().unwrap_or(false); - if lit > 0 { - value - } else { - !value - } + if lit > 0 { value } else { !value } }) }) } diff --git a/src/models/graph/bounded_diameter_spanning_tree.rs b/src/models/graph/bounded_diameter_spanning_tree.rs index a415d801e..da6b7322e 100644 --- a/src/models/graph/bounded_diameter_spanning_tree.rs +++ b/src/models/graph/bounded_diameter_spanning_tree.rs @@ -294,7 +294,7 @@ where let selected_indices: Vec = config .iter() .enumerate() - .filter(|(_, &v)| v) + .filter(|&(_, &v)| v) .map(|(i, _)| i) .collect(); diff --git a/src/models/graph/degree_constrained_spanning_tree.rs b/src/models/graph/degree_constrained_spanning_tree.rs index f22fdf445..c8660ff2f 100644 --- a/src/models/graph/degree_constrained_spanning_tree.rs +++ b/src/models/graph/degree_constrained_spanning_tree.rs @@ -162,7 +162,7 @@ where let selected: Vec<(usize, usize)> = config .iter() .enumerate() - .filter(|(_, &v)| v) + .filter(|&(_, &v)| v) .map(|(i, _)| self.edge_list[i]) .collect(); diff --git a/src/models/graph/disjoint_connecting_paths.rs b/src/models/graph/disjoint_connecting_paths.rs index 47d893965..a8c94002f 100644 --- a/src/models/graph/disjoint_connecting_paths.rs +++ b/src/models/graph/disjoint_connecting_paths.rs @@ -224,11 +224,7 @@ fn canonical_edges(graph: &G) -> Vec<(usize, usize)> { } fn normalize_edge(u: usize, v: usize) -> (usize, usize) { - if u <= v { - (u, v) - } else { - (v, u) - } + if u <= v { (u, v) } else { (v, u) } } fn is_valid_disjoint_connecting_paths( diff --git a/src/models/graph/highly_connected_deletion.rs b/src/models/graph/highly_connected_deletion.rs index 11b6734ea..2379d1c7c 100644 --- a/src/models/graph/highly_connected_deletion.rs +++ b/src/models/graph/highly_connected_deletion.rs @@ -315,11 +315,7 @@ fn edge_connectivity(vertices: &[usize], adj: &[Vec]) -> usize { } } } - if best == usize::MAX { - 0 - } else { - best - } + if best == usize::MAX { 0 } else { best } } crate::declare_variants! { diff --git a/src/models/graph/kcoloring.rs b/src/models/graph/kcoloring.rs index e0d5227ce..e026143dc 100644 --- a/src/models/graph/kcoloring.rs +++ b/src/models/graph/kcoloring.rs @@ -7,7 +7,7 @@ use super::simple_graph_from_create; use crate::registry::{CreateSpec, ProblemSchemaEntry, VariantDimension}; use crate::topology::{Graph, SimpleGraph}; use crate::traits::Problem; -use crate::variant::{KValue, VariantParam, K2, K3, KN}; +use crate::variant::{K2, K3, KN, KValue, VariantParam}; use serde::{Deserialize, Serialize}; inventory::submit! { diff --git a/src/models/graph/length_bounded_disjoint_paths.rs b/src/models/graph/length_bounded_disjoint_paths.rs index a3cd829e7..a47621a35 100644 --- a/src/models/graph/length_bounded_disjoint_paths.rs +++ b/src/models/graph/length_bounded_disjoint_paths.rs @@ -4,7 +4,7 @@ //! each using at most `K` edges, over up to `max_paths` path slots. use crate::registry::{CreateSpec, ProblemSchemaEntry, VariantDimension}; -use crate::topology::{is_simple_st_path, Graph, SimpleGraph}; +use crate::topology::{Graph, SimpleGraph, is_simple_st_path}; use crate::traits::Problem; use crate::types::Max; use crate::variant::VariantParam; diff --git a/src/models/graph/longest_circuit.rs b/src/models/graph/longest_circuit.rs index a25c5f65a..0d4a4cf45 100644 --- a/src/models/graph/longest_circuit.rs +++ b/src/models/graph/longest_circuit.rs @@ -368,8 +368,8 @@ crate::register_decision_variant!( ); #[cfg(feature = "example-db")] -pub(crate) fn decision_canonical_rule_example_specs( -) -> Vec { +pub(crate) fn decision_canonical_rule_example_specs() +-> Vec { vec![crate::example_db::specs::RuleExampleSpec { id: "decision_longest_circuit_to_longest_circuit", build: || { diff --git a/src/models/graph/longest_path.rs b/src/models/graph/longest_path.rs index 2e86158e0..fd249f7ee 100644 --- a/src/models/graph/longest_path.rs +++ b/src/models/graph/longest_path.rs @@ -4,7 +4,7 @@ //! vertices that maximizes the total edge length. use crate::registry::{CreateSpec, ProblemSchemaEntry, VariantDimension}; -use crate::topology::{is_simple_st_path, Graph, SimpleGraph}; +use crate::topology::{Graph, SimpleGraph, is_simple_st_path}; use crate::traits::Problem; use crate::types::{Max, One, WeightElement}; use num_traits::Zero; @@ -349,8 +349,8 @@ crate::register_decision_variant!( ); #[cfg(feature = "example-db")] -pub(crate) fn decision_canonical_rule_example_specs( -) -> Vec { +pub(crate) fn decision_canonical_rule_example_specs() +-> Vec { vec![crate::example_db::specs::RuleExampleSpec { id: "decision_longest_path_to_longest_path", build: || { diff --git a/src/models/graph/max_cut.rs b/src/models/graph/max_cut.rs index 703f883d7..286f0efb6 100644 --- a/src/models/graph/max_cut.rs +++ b/src/models/graph/max_cut.rs @@ -347,8 +347,8 @@ crate::register_decision_variant!( ); #[cfg(feature = "example-db")] -pub(crate) fn decision_canonical_rule_example_specs( -) -> Vec { +pub(crate) fn decision_canonical_rule_example_specs() +-> Vec { vec![crate::example_db::specs::RuleExampleSpec { id: "decision_max_cut_to_max_cut", build: || { diff --git a/src/models/graph/maximum_clique.rs b/src/models/graph/maximum_clique.rs index 958be384b..bfef92675 100644 --- a/src/models/graph/maximum_clique.rs +++ b/src/models/graph/maximum_clique.rs @@ -210,7 +210,7 @@ fn is_clique_config(graph: &G, config: &[bool]) -> bool { let selected: Vec = config .iter() .enumerate() - .filter(|(_, &v)| v) + .filter(|&(_, &v)| v) .map(|(i, _)| i) .collect(); @@ -287,7 +287,7 @@ pub(crate) fn is_clique(graph: &G, selected: &[bool]) -> bool { let selected_vertices: Vec = selected .iter() .enumerate() - .filter(|(_, &s)| s) + .filter(|&(_, &s)| s) .map(|(i, _)| i) .collect(); diff --git a/src/models/graph/maximum_co_k_plex.rs b/src/models/graph/maximum_co_k_plex.rs index 9b482cd05..3544576eb 100644 --- a/src/models/graph/maximum_co_k_plex.rs +++ b/src/models/graph/maximum_co_k_plex.rs @@ -12,7 +12,7 @@ use crate::registry::{CreateSpec, ProblemSchemaEntry, VariantDimension}; use crate::topology::{Graph, SimpleGraph}; use crate::traits::Problem; use crate::types::{Max, One, WeightElement}; -use crate::variant::{KValue, VariantParam, KN}; +use crate::variant::{KN, KValue, VariantParam}; use num_traits::Zero; use serde::{Deserialize, Serialize}; @@ -150,10 +150,10 @@ impl MaximumCoKPlex { if bound_k == 0 { return Err("co-k-plex parameter k must be at least 1".into()); } - if let Some(fixed) = K::K { - if fixed != bound_k { - return Err("fixed K type disagrees with runtime bound_k".into()); - } + if let Some(fixed) = K::K + && fixed != bound_k + { + return Err("fixed K type disagrees with runtime bound_k".into()); } Ok(Self { graph, diff --git a/src/models/graph/maximum_contact_map_overlap.rs b/src/models/graph/maximum_contact_map_overlap.rs index 41e0be746..2254efc03 100644 --- a/src/models/graph/maximum_contact_map_overlap.rs +++ b/src/models/graph/maximum_contact_map_overlap.rs @@ -219,10 +219,10 @@ impl MaximumContactMapOverlap { if !used.insert(value) { return false; } - if let Some(prev) = previous_nonzero { - if value <= prev { - return false; - } + if let Some(prev) = previous_nonzero + && value <= prev + { + return false; } previous_nonzero = Some(value); } diff --git a/src/models/graph/maximum_edge_weighted_k_clique.rs b/src/models/graph/maximum_edge_weighted_k_clique.rs index 8bde51c2e..977597887 100644 --- a/src/models/graph/maximum_edge_weighted_k_clique.rs +++ b/src/models/graph/maximum_edge_weighted_k_clique.rs @@ -236,7 +236,7 @@ fn is_k_clique_config(graph: &SimpleGraph, config: &[bool], k: usize) -> bool { let selected: Vec = config .iter() .enumerate() - .filter(|(_, &selected)| selected) + .filter(|&(_, &selected)| selected) .map(|(i, _)| i) .collect(); if selected.len() != k { diff --git a/src/models/graph/maximum_independent_set.rs b/src/models/graph/maximum_independent_set.rs index c3e29b4d7..089fa9f5d 100644 --- a/src/models/graph/maximum_independent_set.rs +++ b/src/models/graph/maximum_independent_set.rs @@ -484,8 +484,8 @@ pub(crate) fn canonical_model_example_specs() -> Vec Vec { +pub(crate) fn decision_canonical_model_example_specs() +-> Vec { vec![ crate::example_db::specs::ModelExampleSpec { id: "decision_maximum_independent_set_simplegraph", @@ -509,9 +509,9 @@ pub(crate) fn decision_canonical_model_example_specs( } #[cfg(feature = "example-db")] -pub(crate) fn decision_canonical_rule_example_specs( -) -> Vec { - use crate::example_db::specs::{rule_example_with_witness, RuleExampleSpec}; +pub(crate) fn decision_canonical_rule_example_specs() +-> Vec { + use crate::example_db::specs::{RuleExampleSpec, rule_example_with_witness}; use crate::export::SolutionPair; use crate::models::decision::Decision; vec![ diff --git a/src/models/graph/maximum_matching.rs b/src/models/graph/maximum_matching.rs index 0c017a9a0..f0af1449d 100644 --- a/src/models/graph/maximum_matching.rs +++ b/src/models/graph/maximum_matching.rs @@ -176,14 +176,12 @@ impl MaximumMatching { let mut vertex_used = vec![false; self.graph.num_vertices()]; for (idx, &selected) in config.iter().enumerate() { - if selected { - if let Some((u, v)) = self.edge_endpoints(idx) { - if vertex_used[u] || vertex_used[v] { - return false; - } - vertex_used[u] = true; - vertex_used[v] = true; + if selected && let Some((u, v)) = self.edge_endpoints(idx) { + if vertex_used[u] || vertex_used[v] { + return false; } + vertex_used[u] = true; + vertex_used[v] = true; } } true @@ -265,14 +263,12 @@ where } let mut total = W::Sum::zero(); for (idx, &selected) in config.iter().enumerate() { - if selected { - if let Some(w) = self.edge_weights.get(idx) { - total = W::checked_add_to_sum( - total, - w.to_sum(), - "summing selected matching-edge weights", - )?; - } + if selected && let Some(w) = self.edge_weights.get(idx) { + total = W::checked_add_to_sum( + total, + w.to_sum(), + "summing selected matching-edge weights", + )?; } } Max(Some(total)) diff --git a/src/models/graph/min_max_multicenter.rs b/src/models/graph/min_max_multicenter.rs index 6dc371efc..3430b31b7 100644 --- a/src/models/graph/min_max_multicenter.rs +++ b/src/models/graph/min_max_multicenter.rs @@ -433,8 +433,8 @@ crate::register_decision_variant!( ); #[cfg(feature = "example-db")] -pub(crate) fn decision_canonical_rule_example_specs( -) -> Vec { +pub(crate) fn decision_canonical_rule_example_specs() +-> Vec { vec![crate::example_db::specs::RuleExampleSpec { id: "decision_min_max_multicenter_to_min_max_multicenter", build: || { diff --git a/src/models/graph/minimum_capacitated_spanning_tree.rs b/src/models/graph/minimum_capacitated_spanning_tree.rs index 13d7b5204..304f98f8d 100644 --- a/src/models/graph/minimum_capacitated_spanning_tree.rs +++ b/src/models/graph/minimum_capacitated_spanning_tree.rs @@ -419,14 +419,12 @@ where } let mut total = W::Sum::zero(); for (idx, &selected) in config.iter().enumerate() { - if selected { - if let Some(w) = self.weights.get(idx) { - total = W::checked_add_to_sum( - total, - w.to_sum(), - "summing capacitated spanning tree edge weights", - )?; - } + if selected && let Some(w) = self.weights.get(idx) { + total = W::checked_add_to_sum( + total, + w.to_sum(), + "summing capacitated spanning tree edge weights", + )?; } } Min(Some(total)) diff --git a/src/models/graph/minimum_covering_by_cliques.rs b/src/models/graph/minimum_covering_by_cliques.rs index 1f5f52048..6a259a01b 100644 --- a/src/models/graph/minimum_covering_by_cliques.rs +++ b/src/models/graph/minimum_covering_by_cliques.rs @@ -234,8 +234,8 @@ crate::registry::FieldInfo { name: "bound", type_name: "i64", description: "Acce ); #[cfg(feature = "example-db")] -pub(crate) fn decision_canonical_rule_example_specs( -) -> Vec { +pub(crate) fn decision_canonical_rule_example_specs() +-> Vec { vec![crate::example_db::specs::RuleExampleSpec { id: "decision_minimum_covering_by_cliques_to_minimum_covering_by_cliques", build: || { diff --git a/src/models/graph/minimum_dominating_set.rs b/src/models/graph/minimum_dominating_set.rs index 1c3f11d26..f0b181731 100644 --- a/src/models/graph/minimum_dominating_set.rs +++ b/src/models/graph/minimum_dominating_set.rs @@ -336,8 +336,8 @@ pub(crate) fn canonical_model_example_specs() -> Vec Vec { +pub(crate) fn decision_canonical_model_example_specs() +-> Vec { vec![ crate::example_db::specs::ModelExampleSpec { id: "decision_minimum_dominating_set_simplegraph", @@ -370,8 +370,8 @@ pub(crate) fn decision_canonical_model_example_specs( } #[cfg(feature = "example-db")] -pub(crate) fn decision_canonical_rule_example_specs( -) -> Vec { +pub(crate) fn decision_canonical_rule_example_specs() +-> Vec { vec![ crate::example_db::specs::RuleExampleSpec { id: "decision_minimum_dominating_set_to_minimum_dominating_set", diff --git a/src/models/graph/minimum_edge_cost_flow.rs b/src/models/graph/minimum_edge_cost_flow.rs index d58b93fca..a639b0c5c 100644 --- a/src/models/graph/minimum_edge_cost_flow.rs +++ b/src/models/graph/minimum_edge_cost_flow.rs @@ -301,7 +301,7 @@ impl MinimumEdgeCostFlow { config .iter() .enumerate() - .filter(|(_, &flow)| flow > 0) + .filter(|&(_, &flow)| flow > 0) .try_fold(0_i64, |total, (arc, _)| { total.checked_add(self.prices[arc]).ok_or_else(|| { crate::traits::EvaluationError::IntegerOverflow( diff --git a/src/models/graph/minimum_geometric_connected_dominating_set.rs b/src/models/graph/minimum_geometric_connected_dominating_set.rs index 393b20b6c..9b81f7a20 100644 --- a/src/models/graph/minimum_geometric_connected_dominating_set.rs +++ b/src/models/graph/minimum_geometric_connected_dominating_set.rs @@ -151,7 +151,7 @@ impl MinimumGeometricConnectedDominatingSet { let selected: Vec = config .iter() .enumerate() - .filter(|(_, &v)| v) + .filter(|&(_, &v)| v) .map(|(i, _)| i) .collect(); diff --git a/src/models/graph/minimum_sum_multicenter.rs b/src/models/graph/minimum_sum_multicenter.rs index b8a269e12..648b7bb0c 100644 --- a/src/models/graph/minimum_sum_multicenter.rs +++ b/src/models/graph/minimum_sum_multicenter.rs @@ -422,8 +422,8 @@ crate::register_decision_variant!( ); #[cfg(feature = "example-db")] -pub(crate) fn decision_canonical_rule_example_specs( -) -> Vec { +pub(crate) fn decision_canonical_rule_example_specs() +-> Vec { vec![crate::example_db::specs::RuleExampleSpec { id: "decision_minimum_sum_multicenter_to_minimum_sum_multicenter", build: || { diff --git a/src/models/graph/minimum_vertex_cover.rs b/src/models/graph/minimum_vertex_cover.rs index 7c9a40f21..f98e4a494 100644 --- a/src/models/graph/minimum_vertex_cover.rs +++ b/src/models/graph/minimum_vertex_cover.rs @@ -340,8 +340,8 @@ pub(crate) fn canonical_model_example_specs() -> Vec Vec { +pub(crate) fn decision_canonical_model_example_specs() +-> Vec { vec![crate::example_db::specs::ModelExampleSpec { id: "decision_minimum_vertex_cover_simplegraph", instance: Box::new(crate::models::decision::Decision::new( @@ -357,9 +357,9 @@ pub(crate) fn decision_canonical_model_example_specs( } #[cfg(feature = "example-db")] -pub(crate) fn decision_canonical_rule_example_specs( -) -> Vec { - use crate::example_db::specs::{rule_example_with_witness, RuleExampleSpec}; +pub(crate) fn decision_canonical_rule_example_specs() +-> Vec { + use crate::example_db::specs::{RuleExampleSpec, rule_example_with_witness}; use crate::export::SolutionPair; vec![ RuleExampleSpec { diff --git a/src/models/graph/optimal_linear_arrangement.rs b/src/models/graph/optimal_linear_arrangement.rs index 6fa590f25..60dfca2a7 100644 --- a/src/models/graph/optimal_linear_arrangement.rs +++ b/src/models/graph/optimal_linear_arrangement.rs @@ -260,8 +260,8 @@ pub(crate) fn canonical_model_example_specs() -> Vec Vec { +pub(crate) fn decision_canonical_model_example_specs() +-> Vec { use crate::topology::SimpleGraph; // Path P_4 (0-1-2-3): optimal arrangement has cost 3; bound 3 is YES. vec![crate::example_db::specs::ModelExampleSpec { @@ -276,8 +276,8 @@ pub(crate) fn decision_canonical_model_example_specs( } #[cfg(feature = "example-db")] -pub(crate) fn decision_canonical_rule_example_specs( -) -> Vec { +pub(crate) fn decision_canonical_rule_example_specs() +-> Vec { vec![crate::example_db::specs::RuleExampleSpec { id: "decision_optimal_linear_arrangement_to_optimal_linear_arrangement", build: || { diff --git a/src/models/graph/partial_feedback_edge_set.rs b/src/models/graph/partial_feedback_edge_set.rs index c62ad3c72..ae9d67af4 100644 --- a/src/models/graph/partial_feedback_edge_set.rs +++ b/src/models/graph/partial_feedback_edge_set.rs @@ -270,11 +270,7 @@ pub(crate) fn canonical_model_example_specs() -> Vec (usize, usize) { - if u <= v { - (u, v) - } else { - (v, u) - } + if u <= v { (u, v) } else { (v, u) } } crate::declare_variants! { diff --git a/src/models/graph/rural_postman.rs b/src/models/graph/rural_postman.rs index e968482ac..630e3e4a3 100644 --- a/src/models/graph/rural_postman.rs +++ b/src/models/graph/rural_postman.rs @@ -412,8 +412,8 @@ crate::register_decision_variant!( ); #[cfg(feature = "example-db")] -pub(crate) fn decision_canonical_rule_example_specs( -) -> Vec { +pub(crate) fn decision_canonical_rule_example_specs() +-> Vec { vec![crate::example_db::specs::RuleExampleSpec { id: "decision_rural_postman_to_rural_postman", build: || { diff --git a/src/models/graph/shortest_weight_constrained_path.rs b/src/models/graph/shortest_weight_constrained_path.rs index 7715caa35..c0e535134 100644 --- a/src/models/graph/shortest_weight_constrained_path.rs +++ b/src/models/graph/shortest_weight_constrained_path.rs @@ -5,7 +5,7 @@ //! the total weight within a prescribed bound. use crate::registry::{CreateSpec, ProblemSchemaEntry, VariantDimension}; -use crate::topology::{is_simple_st_path, Graph, SimpleGraph}; +use crate::topology::{Graph, SimpleGraph, is_simple_st_path}; use crate::traits::Problem; use crate::types::{Min, WeightElement}; use num_traits::Zero; diff --git a/src/models/graph/spin_glass.rs b/src/models/graph/spin_glass.rs index 476f1770e..ca525f454 100644 --- a/src/models/graph/spin_glass.rs +++ b/src/models/graph/spin_glass.rs @@ -462,8 +462,8 @@ crate::register_decision_variant!( ); #[cfg(feature = "example-db")] -pub(crate) fn decision_canonical_rule_example_specs( -) -> Vec { +pub(crate) fn decision_canonical_rule_example_specs() +-> Vec { vec![crate::example_db::specs::RuleExampleSpec { id: "decision_spin_glass_to_spin_glass", build: || { diff --git a/src/models/graph/steiner_tree.rs b/src/models/graph/steiner_tree.rs index 37a9992d3..abff88f3e 100644 --- a/src/models/graph/steiner_tree.rs +++ b/src/models/graph/steiner_tree.rs @@ -296,14 +296,12 @@ where } let mut total = W::Sum::zero(); for (idx, &selected) in config.iter().enumerate() { - if selected { - if let Some(w) = self.edge_weights.get(idx) { - total = W::checked_add_to_sum( - total, - w.to_sum(), - "summing Steiner tree edge weights", - )?; - } + if selected && let Some(w) = self.edge_weights.get(idx) { + total = W::checked_add_to_sum( + total, + w.to_sum(), + "summing Steiner tree edge weights", + )?; } } Min(Some(total)) diff --git a/src/models/misc/additional_key.rs b/src/models/misc/additional_key.rs index c0ae3ccd8..42285779d 100644 --- a/src/models/misc/additional_key.rs +++ b/src/models/misc/additional_key.rs @@ -260,7 +260,7 @@ impl Problem for AdditionalKey { let selected: Vec = config .iter() .enumerate() - .filter(|(_, &v)| v) + .filter(|&(_, &v)| v) .map(|(i, _)| self.relation_attrs[i]) .collect(); diff --git a/src/models/misc/boyce_codd_normal_form_violation.rs b/src/models/misc/boyce_codd_normal_form_violation.rs index 1b387d518..cbb02c8e6 100644 --- a/src/models/misc/boyce_codd_normal_form_violation.rs +++ b/src/models/misc/boyce_codd_normal_form_violation.rs @@ -238,7 +238,7 @@ impl Problem for BoyceCoddNormalFormViolation { let x: HashSet = config .iter() .enumerate() - .filter(|(_, &v)| v) + .filter(|&(_, &v)| v) .map(|(i, _)| self.target_subset[i]) .collect(); let closure = Self::compute_closure(&x, &self.functional_deps); diff --git a/src/models/misc/knapsack.rs b/src/models/misc/knapsack.rs index 1936686b5..47cb16e91 100644 --- a/src/models/misc/knapsack.rs +++ b/src/models/misc/knapsack.rs @@ -179,7 +179,7 @@ impl Problem for Knapsack { let total_weight = config .iter() .enumerate() - .filter(|(_, &x)| x) + .filter(|&(_, &x)| x) .map(|(i, _)| self.weights[i]) .try_fold(0_i64, |total, weight| { total.checked_add(weight).ok_or_else(|| { @@ -194,7 +194,7 @@ impl Problem for Knapsack { let total_value = config .iter() .enumerate() - .filter(|(_, &x)| x) + .filter(|&(_, &x)| x) .map(|(i, _)| self.values[i]) .try_fold(0_i64, |total, value| { total.checked_add(value).ok_or_else(|| { diff --git a/src/models/misc/minimum_code_generation_one_register.rs b/src/models/misc/minimum_code_generation_one_register.rs index 4f73aadc8..ac071034c 100644 --- a/src/models/misc/minimum_code_generation_one_register.rs +++ b/src/models/misc/minimum_code_generation_one_register.rs @@ -74,6 +74,14 @@ struct MinimumCodeGenerationOneRegisterData { num_leaves: usize, } +fn add_instructions(count: i64, additional: i64) -> Result { + count.checked_add(additional).ok_or_else(|| { + crate::traits::EvaluationError::IntegerOverflow( + "counting one-register instructions".to_string(), + ) + }) +} + impl TryFrom for MinimumCodeGenerationOneRegister { type Error = crate::registry::ConstructionError; fn try_from(data: MinimumCodeGenerationOneRegisterData) -> Result { @@ -276,15 +284,12 @@ impl MinimumCodeGenerationOneRegister { // 1. Register holds a value // 2. That value is still needed in the future // 3. That value is not already in memory - if let Some(r) = register { - if !in_memory[r] && future_uses[r] > 0 { - instructions = instructions.checked_add(1).ok_or_else(|| { - crate::traits::EvaluationError::IntegerOverflow( - "counting one-register instructions".to_string(), - ) - })?; // STORE - in_memory[r] = true; - } + if let Some(r) = register + && !in_memory[r] + && future_uses[r] > 0 + { + instructions = add_instructions(instructions, 1)?; // STORE + in_memory[r] = true; } // Now compute v @@ -294,33 +299,17 @@ impl MinimumCodeGenerationOneRegister { let one_in_register = (register == Some(c0) && in_memory[c1]) || (register == Some(c1) && in_memory[c0]); if one_in_register { - instructions = instructions.checked_add(1).ok_or_else(|| { - crate::traits::EvaluationError::IntegerOverflow( - "counting one-register instructions".to_string(), - ) - })?; // OP v + instructions = add_instructions(instructions, 1)?; // OP v } else { // Need to LOAD one operand, OP with the other from memory - instructions = instructions.checked_add(2).ok_or_else(|| { - crate::traits::EvaluationError::IntegerOverflow( - "counting one-register instructions".to_string(), - ) - })?; // LOAD + OP + instructions = add_instructions(instructions, 2)?; // LOAD + OP } } else if operands.len() == 1 { let c0 = operands[0]; if register == Some(c0) { - instructions = instructions.checked_add(1).ok_or_else(|| { - crate::traits::EvaluationError::IntegerOverflow( - "counting one-register instructions".to_string(), - ) - })?; // OP v + instructions = add_instructions(instructions, 1)?; // OP v } else { - instructions = instructions.checked_add(2).ok_or_else(|| { - crate::traits::EvaluationError::IntegerOverflow( - "counting one-register instructions".to_string(), - ) - })?; // LOAD + OP + instructions = add_instructions(instructions, 2)?; // LOAD + OP } } diff --git a/src/models/misc/minimum_code_generation_unlimited_registers.rs b/src/models/misc/minimum_code_generation_unlimited_registers.rs index b2bb74c78..abb5daf20 100644 --- a/src/models/misc/minimum_code_generation_unlimited_registers.rs +++ b/src/models/misc/minimum_code_generation_unlimited_registers.rs @@ -314,15 +314,15 @@ impl MinimumCodeGenerationUnlimitedRegisters { let lc = self.left_child(v); let rc = self.right_child(v); - if let Some(l) = lc { - if !computed[l] { - return Ok(None); - } + if let Some(l) = lc + && !computed[l] + { + return Ok(None); } - if let Some(r) = rc { - if !computed[r] { - return Ok(None); - } + if let Some(r) = rc + && !computed[r] + { + return Ok(None); } // Decrement future use counts diff --git a/src/models/misc/minimum_weight_and_or_graph.rs b/src/models/misc/minimum_weight_and_or_graph.rs index f8c06a458..fc38a8df4 100644 --- a/src/models/misc/minimum_weight_and_or_graph.rs +++ b/src/models/misc/minimum_weight_and_or_graph.rs @@ -318,7 +318,7 @@ impl Problem for MinimumWeightAndOrGraph { let total_weight = selected .iter() .enumerate() - .filter(|(_, &sel)| sel) + .filter(|&(_, &sel)| sel) .map(|(i, _)| self.arc_weights[i]) .try_fold(0_i64, |total, weight| { total.checked_add(weight).ok_or_else(|| { diff --git a/src/models/misc/mod.rs b/src/models/misc/mod.rs index 83dd2e2b3..aae9a2e5a 100644 --- a/src/models/misc/mod.rs +++ b/src/models/misc/mod.rs @@ -213,8 +213,8 @@ pub use integer_expression_membership::{IntExpr, IntegerExpressionMembership}; pub use job_shop_scheduling::JobShopScheduling; pub use knapsack::Knapsack; pub use kth_largest_m_tuple::KthLargestMTuple; -pub(crate) use longest_common_subsequence::is_subsequence; pub use longest_common_subsequence::LongestCommonSubsequence; +pub(crate) use longest_common_subsequence::is_subsequence; pub use maximum_likelihood_ranking::MaximumLikelihoodRanking; pub use minimum_axiom_set::MinimumAxiomSet; pub use minimum_code_generation_one_register::MinimumCodeGenerationOneRegister; diff --git a/src/models/misc/open_shop_scheduling.rs b/src/models/misc/open_shop_scheduling.rs index 86a32afd6..e6ef335df 100644 --- a/src/models/misc/open_shop_scheduling.rs +++ b/src/models/misc/open_shop_scheduling.rs @@ -340,8 +340,8 @@ crate::register_decision_variant!( ); #[cfg(feature = "example-db")] -pub(crate) fn decision_canonical_rule_example_specs( -) -> Vec { +pub(crate) fn decision_canonical_rule_example_specs() +-> Vec { vec![crate::example_db::specs::RuleExampleSpec { id: "decision_open_shop_scheduling_to_open_shop_scheduling", build: || { diff --git a/src/models/misc/partially_ordered_knapsack.rs b/src/models/misc/partially_ordered_knapsack.rs index dc9bb4605..5bb929609 100644 --- a/src/models/misc/partially_ordered_knapsack.rs +++ b/src/models/misc/partially_ordered_knapsack.rs @@ -292,7 +292,7 @@ impl Problem for PartiallyOrderedKnapsack { let total_weight = config .iter() .enumerate() - .filter(|(_, &x)| x) + .filter(|&(_, &x)| x) .map(|(i, _)| self.weights[i]) .try_fold(0_i64, |total, weight| { total.checked_add(weight).ok_or_else(|| { @@ -307,7 +307,7 @@ impl Problem for PartiallyOrderedKnapsack { let total_value = config .iter() .enumerate() - .filter(|(_, &x)| x) + .filter(|&(_, &x)| x) .map(|(i, _)| self.values[i]) .try_fold(0_i64, |total, value| { total.checked_add(value).ok_or_else(|| { diff --git a/src/models/misc/partition.rs b/src/models/misc/partition.rs index 7d329b028..dc7e1e0c6 100644 --- a/src/models/misc/partition.rs +++ b/src/models/misc/partition.rs @@ -136,7 +136,7 @@ impl Problem for Partition { let selected_sum: i64 = config .iter() .enumerate() - .filter(|(_, &x)| x) + .filter(|&(_, &x)| x) .map(|(i, _)| self.sizes[i]) .sum(); selected_sum == self.total_sum() - selected_sum diff --git a/src/models/misc/preemptive_scheduling.rs b/src/models/misc/preemptive_scheduling.rs index 6d0c2d47c..8b6a25d80 100644 --- a/src/models/misc/preemptive_scheduling.rs +++ b/src/models/misc/preemptive_scheduling.rs @@ -331,10 +331,10 @@ impl Problem for PreemptiveScheduling { for &(pred, succ) in &self.precedences { let last_pred = (0..d).rev().find(|&u| solution[pred][u]); let first_succ = (0..d).find(|&u| solution[succ][u]); - if let (Some(lp), Some(fs)) = (last_pred, first_succ) { - if lp >= fs { - return Ok(Min(None)); - } + if let (Some(lp), Some(fs)) = (last_pred, first_succ) + && lp >= fs + { + return Ok(Min(None)); } } 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 e5bfe0a9e..171d740d4 100644 --- a/src/models/misc/sequencing_to_minimize_tardy_task_weight.rs +++ b/src/models/misc/sequencing_to_minimize_tardy_task_weight.rs @@ -280,20 +280,29 @@ crate::registry::FieldInfo { name: "bound", type_name: "i64", description: "Acce ); #[cfg(feature = "example-db")] -pub(crate) fn decision_canonical_rule_example_specs( -) -> Vec { +pub(crate) fn decision_canonical_rule_example_specs() +-> Vec { vec![crate::example_db::specs::RuleExampleSpec { id: "decision_sequencing_to_minimize_tardy_task_weight_to_sequencing_to_minimize_tardy_task_weight", build: || { - let source = crate::models::decision::Decision::new(SequencingToMinimizeTardyTaskWeight::new( - vec![3, 2, 4, 1, 2], - vec![5, 3, 7, 2, 4], - vec![6, 4, 10, 2, 8], - ), 3); + let source = crate::models::decision::Decision::new( + SequencingToMinimizeTardyTaskWeight::new( + vec![3, 2, 4, 1, 2], + vec![5, 3, 7, 2, 4], + vec![6, 4, 10, 2, 8], + ), + 3, + ); let witness = serde_json::json!(vec![3, 0, 4, 2, 1]); - crate::example_db::specs::rule_example_with_witness::<_, SequencingToMinimizeTardyTaskWeight>( + crate::example_db::specs::rule_example_with_witness::< + _, + SequencingToMinimizeTardyTaskWeight, + >( source, - crate::export::SolutionPair { source_config: witness.clone(), target_config: witness }, + crate::export::SolutionPair { + source_config: witness.clone(), + target_config: witness, + }, ) }, }] 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 fccc06b66..eefab5eef 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 @@ -163,16 +163,16 @@ impl SequencingWithDeadlinesAndSetUpTimes { let mut prev_compiler: Option = None; for &task in schedule { // Add setup time if the compiler switches. - if let Some(prev) = prev_compiler { - if prev != self.compilers[task] { - elapsed = elapsed - .checked_add(self.setup_times[self.compilers[task]]) - .ok_or_else(|| { - crate::traits::EvaluationError::IntegerOverflow( - "adding sequencing setup time".to_string(), - ) - })?; - } + if let Some(prev) = prev_compiler + && prev != self.compilers[task] + { + elapsed = elapsed + .checked_add(self.setup_times[self.compilers[task]]) + .ok_or_else(|| { + crate::traits::EvaluationError::IntegerOverflow( + "adding sequencing setup time".to_string(), + ) + })?; } elapsed = elapsed.checked_add(self.lengths[task]).ok_or_else(|| { crate::traits::EvaluationError::IntegerOverflow( diff --git a/src/models/misc/stacker_crane.rs b/src/models/misc/stacker_crane.rs index 52915f21a..c76147d22 100644 --- a/src/models/misc/stacker_crane.rs +++ b/src/models/misc/stacker_crane.rs @@ -446,8 +446,8 @@ crate::register_decision_variant!( ); #[cfg(feature = "example-db")] -pub(crate) fn decision_canonical_rule_example_specs( -) -> Vec { +pub(crate) fn decision_canonical_rule_example_specs() +-> Vec { vec![crate::example_db::specs::RuleExampleSpec { id: "decision_stacker_crane_to_stacker_crane", build: || { diff --git a/src/models/mod.rs b/src/models/mod.rs index 6d5dcf591..fa5003f72 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -10,12 +10,12 @@ pub mod misc; pub mod set; pub use algebraic::{ - AlgebraicEquationsOverGF2, ClosestVectorProblem, ConsecutiveBlockMinimization, + AlgebraicEquationsOverGF2, BMF, ClosestVectorProblem, ConsecutiveBlockMinimization, ConsecutiveOnesMatrixAugmentation, ConsecutiveOnesSubmatrix, EquilibriumPoint, - FeasibleBasisExtension, MinimumMatrixCover, MinimumMatrixDomination, MinimumWeightDecoding, - MinimumWeightSolutionToLinearEquations, QuadraticAssignment, QuadraticCongruences, - QuadraticDiophantineEquations, SimultaneousIncongruences, SparseMatrixCompression, BMF, ILP, - QUBO, + FeasibleBasisExtension, ILP, MinimumMatrixCover, MinimumMatrixDomination, + MinimumWeightDecoding, MinimumWeightSolutionToLinearEquations, QUBO, QuadraticAssignment, + QuadraticCongruences, QuadraticDiophantineEquations, SimultaneousIncongruences, + SparseMatrixCompression, }; pub use decision::Decision; pub use formula::{ diff --git a/src/models/set/comparative_containment.rs b/src/models/set/comparative_containment.rs index f03046481..45a1b504d 100644 --- a/src/models/set/comparative_containment.rs +++ b/src/models/set/comparative_containment.rs @@ -87,7 +87,9 @@ fn validate_create_set_family( for (set_index, set) in sets.iter().enumerate() { for &element in set { if element >= universe_size { - return Err(ConstructionError::Conversion(format!("{label} set {set_index} contains element {element} outside universe of size {universe_size}"))); + return Err(ConstructionError::Conversion(format!( + "{label} set {set_index} contains element {element} outside universe of size {universe_size}" + ))); } } } diff --git a/src/models/set/exact_cover_by_3_sets.rs b/src/models/set/exact_cover_by_3_sets.rs index 1fc915b31..aac527cb3 100644 --- a/src/models/set/exact_cover_by_3_sets.rs +++ b/src/models/set/exact_cover_by_3_sets.rs @@ -186,10 +186,8 @@ impl ExactCoverBy3Sets { pub fn covered_elements(&self, config: &[bool]) -> HashSet { let mut covered = HashSet::new(); for (i, &selected) in config.iter().enumerate() { - if selected { - if let Some(subset) = self.subsets.get(i) { - covered.extend(subset.iter().copied()); - } + if selected && let Some(subset) = self.subsets.get(i) { + covered.extend(subset.iter().copied()); } } covered diff --git a/src/models/set/maximum_set_packing.rs b/src/models/set/maximum_set_packing.rs index 6f9e94b65..49ad6a33d 100644 --- a/src/models/set/maximum_set_packing.rs +++ b/src/models/set/maximum_set_packing.rs @@ -262,7 +262,7 @@ fn is_valid_packing(sets: &[Vec], config: &[bool]) -> bool { let selected_sets: Vec<_> = config .iter() .enumerate() - .filter(|(_, &selected)| selected) + .filter(|&(_, &selected)| selected) .map(|(i, _)| i) .collect(); diff --git a/src/models/set/minimum_set_covering.rs b/src/models/set/minimum_set_covering.rs index 0a7f0db09..293434781 100644 --- a/src/models/set/minimum_set_covering.rs +++ b/src/models/set/minimum_set_covering.rs @@ -179,10 +179,8 @@ impl MinimumSetCovering { pub fn covered_elements(&self, config: &[bool]) -> HashSet { let mut covered = HashSet::new(); for (i, &selected) in config.iter().enumerate() { - if selected { - if let Some(set) = self.sets.get(i) { - covered.extend(set.iter().copied()); - } + if selected && let Some(set) = self.sets.get(i) { + covered.extend(set.iter().copied()); } } covered diff --git a/src/parameters.rs b/src/parameters.rs index 8b3763982..fef97356b 100644 --- a/src/parameters.rs +++ b/src/parameters.rs @@ -1,7 +1,7 @@ //! Symbolic parameter transformations carried by reduction rules. use crate::expr::{AlgebraicAnalysis, Expr, ExprNode, ExprNodeId, Symbol}; -use crate::polynomial::{pow_rational, Poly}; +use crate::polynomial::{Poly, pow_rational}; use crate::types::ProblemParameters; use num_bigint::{BigInt, BigUint, Sign}; use num_rational::BigRational; @@ -258,7 +258,7 @@ impl ParameterTransform { edge: next.edge.clone(), field: field.name.clone(), expression: field.expression.to_string().into(), - }) + }); } }; let bounded_input = !bounded.is_empty(); @@ -464,21 +464,27 @@ pub enum ParameterTransformError { }, #[error("reduction `{edge}` declares target parameter field `{field}` more than once")] DuplicateTargetField { edge: Box, field: Box }, - #[error("reduction `{edge}` target field `{field}` has non-integral constant exponent `{exponent}` in `{expression}`")] + #[error( + "reduction `{edge}` target field `{field}` has non-integral constant exponent `{exponent}` in `{expression}`" + )] NonIntegralConstantExponent { edge: Box, field: Box, expression: Box, exponent: Box, }, - #[error("reduction `{edge}` target field `{field}` uses unsupported operator `{operator}` in `{expression}`")] + #[error( + "reduction `{edge}` target field `{field}` uses unsupported operator `{operator}` in `{expression}`" + )] UnsupportedOperator { edge: Box, field: Box, expression: Box, operator: &'static str, }, - #[error("reduction `{edge}` target field `{field}` cannot propagate an upper bound through `{expression}`")] + #[error( + "reduction `{edge}` target field `{field}` cannot propagate an upper bound through `{expression}`" + )] CannotPropagateUpperBound { edge: Box, field: Box, @@ -502,7 +508,9 @@ pub enum ParameterTransformError { }, #[error("reduction `{edge}` target field `{field}` divides by zero")] DivisionByZero { edge: Box, field: Box }, - #[error("reduction `{edge}` target field `{field}` evaluates to non-integral parameter value `{value}`")] + #[error( + "reduction `{edge}` target field `{field}` evaluates to non-integral parameter value `{value}`" + )] NonIntegralResult { edge: Box, field: Box, diff --git a/src/poly_compare/mod.rs b/src/poly_compare/mod.rs index 1b8090618..752170cdb 100644 --- a/src/poly_compare/mod.rs +++ b/src/poly_compare/mod.rs @@ -702,10 +702,10 @@ fn direction( } else { None }; - if let Some(proof) = immediate { - if proof.verify(f.poly, g.poly) { - return Direction::Yes(proof); - } + if let Some(proof) = immediate + && proof.verify(f.poly, g.poly) + { + return Direction::Yes(proof); } let lp = CoverageLp::new(&g.support, vars); let coverage: Result>, _> = diff --git a/src/poly_compare/render.rs b/src/poly_compare/render.rs index cdec90e6d..080957150 100644 --- a/src/poly_compare/render.rs +++ b/src/poly_compare/render.rs @@ -1,7 +1,7 @@ //! Human-readable certificates and the version-5 exact JSON proof schema. use super::*; use serde::{Serialize, Serializer}; -use serde_json::{json, Value}; +use serde_json::{Value, json}; use std::fmt; fn monomial(m: &Monomial) -> String { @@ -10,10 +10,11 @@ fn monomial(m: &Monomial) -> String { .to_string() } fn powers(m: &Monomial) -> Value { - json!(m - .iter() - .map(|(v, e)| (v.to_string(), e.to_string())) - .collect::>()) + json!( + m.iter() + .map(|(v, e)| (v.to_string(), e.to_string())) + .collect::>() + ) } fn domain(d: &BTreeSet) -> Vec { d.iter().map(ToString::to_string).collect() @@ -33,10 +34,11 @@ fn leading(p: &BTreeMap) -> String { .unwrap_or_else(|| "0".into()) } fn univariate(p: &BTreeMap) -> Value { - json!(p - .iter() - .map(|(e, c)| json!({"exponent":e.to_string(), "coefficient":c.to_string()})) - .collect::>()) + json!( + p.iter() + .map(|(e, c)| json!({"exponent":e.to_string(), "coefficient":c.to_string()})) + .collect::>() + ) } impl fmt::Display for Reason { @@ -45,7 +47,10 @@ impl fmt::Display for Reason { Self::NotPolynomial(s) => write!(f, "not polynomial: {s}"), Self::Unavailable(e) => write!(f, "unavailable: {e}"), Self::MissingField => write!(f, "field missing on one path"), - Self::Validity => write!(f, "Newton coverage fails; no regular witness found positive for every batch certificate"), + Self::Validity => write!( + f, + "Newton coverage fails; no regular witness found positive for every batch certificate" + ), Self::ResourceLimit(s) => write!(f, "resource limit: {s}"), } } diff --git a/src/polynomial.rs b/src/polynomial.rs index 067e783bf..8592aa0cf 100644 --- a/src/polynomial.rs +++ b/src/polynomial.rs @@ -286,11 +286,7 @@ pub(crate) fn pow_rational(mut base: BigRational, exponent: &BigInt) -> BigRatio base = &base * &base; } } - if negative { - result.recip() - } else { - result - } + if negative { result.recip() } else { result } } #[cfg(test)] diff --git a/src/registry/mod.rs b/src/registry/mod.rs index b76eb4199..cc7e07f96 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -51,19 +51,19 @@ pub mod problem_type; mod schema; pub mod variant; -pub use dyn_problem::{format_metric, DynProblem, LoadedDynProblem}; +pub use dyn_problem::{DynProblem, LoadedDynProblem, format_metric}; pub use info::{ComplexityClass, FieldInfo, ProblemInfo, ProblemMetadata}; -pub use problem_ref::{parse_catalog_problem_ref, require_graph_variant, ProblemRef}; -pub use problem_type::{find_problem_type, find_problem_type_by_alias, problem_types, ProblemType}; +pub use problem_ref::{ProblemRef, parse_catalog_problem_ref, require_graph_variant}; +pub use problem_type::{ProblemType, find_problem_type, find_problem_type_by_alias, problem_types}; pub use schema::{ - collect_schemas, FieldInfoJson, ParseProblemCategoryError, ProblemCategory, ProblemSchemaEntry, - ProblemSchemaJson, VariantDimension, + FieldInfoJson, ParseProblemCategoryError, ProblemCategory, ProblemSchemaEntry, + ProblemSchemaJson, VariantDimension, collect_schemas, }; pub use variant::{ - find_variant_by_alias, find_variant_entry, validate_create_inputs, - validate_direct_create_inputs, validate_variant_aliases, validate_variant_parameter_schemas, - variant_entries, ConstructProblemFn, ConstructionError, CreateInputCodec, CreateInputInfo, - CreateSpec, RandomGenerate, RandomRegistration, VariantEntry, + ConstructProblemFn, ConstructionError, CreateInputCodec, CreateInputInfo, CreateSpec, + RandomGenerate, RandomRegistration, VariantEntry, find_variant_by_alias, find_variant_entry, + validate_create_inputs, validate_direct_create_inputs, validate_variant_aliases, + validate_variant_parameter_schemas, variant_entries, }; /// Construct a problem from normalized construction inputs using the exact diff --git a/src/registry/problem_ref.rs b/src/registry/problem_ref.rs index 3f0b56ed8..1d5c3db67 100644 --- a/src/registry/problem_ref.rs +++ b/src/registry/problem_ref.rs @@ -1,7 +1,7 @@ //! Typed internal problem references with catalog-validated variants. -use super::problem_type::ProblemType; use super::ConstructionError; +use super::problem_type::ProblemType; use std::collections::BTreeMap; /// A typed internal reference to a specific problem variant. diff --git a/src/registry/problem_type.rs b/src/registry/problem_type.rs index 509ecff45..35ef07d06 100644 --- a/src/registry/problem_type.rs +++ b/src/registry/problem_type.rs @@ -1,7 +1,7 @@ //! Problem type catalog: runtime lookup by name, alias, and variant validation. -use super::schema::{ProblemCategory, ProblemSchemaEntry, VariantDimension}; use super::FieldInfo; +use super::schema::{ProblemCategory, ProblemSchemaEntry, VariantDimension}; use std::collections::BTreeMap; /// A runtime view of a registered problem type from the catalog. diff --git a/src/registry/variant.rs b/src/registry/variant.rs index 4f2dc0fb8..65db87761 100644 --- a/src/registry/variant.rs +++ b/src/registry/variant.rs @@ -3,8 +3,8 @@ use std::any::Any; use std::collections::BTreeMap; -use crate::registry::dyn_problem::DynProblem; use crate::registry::FieldInfo; +use crate::registry::dyn_problem::DynProblem; /// Reusable syntax used to transport one construction input. /// diff --git a/src/rules/acyclicpartition_ilp.rs b/src/rules/acyclicpartition_ilp.rs index 69a6e0574..4971324bb 100644 --- a/src/rules/acyclicpartition_ilp.rs +++ b/src/rules/acyclicpartition_ilp.rs @@ -1,6 +1,6 @@ //! Bounded partition labels with exact crossing flags and occupied-part budgets. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::AcyclicPartition; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/balancedcompletebipartitesubgraph_ilp.rs b/src/rules/balancedcompletebipartitesubgraph_ilp.rs index d97e2f193..8cc3ba6a0 100644 --- a/src/rules/balancedcompletebipartitesubgraph_ilp.rs +++ b/src/rules/balancedcompletebipartitesubgraph_ilp.rs @@ -4,7 +4,7 @@ //! Cardinality: Σ x_l = k, Σ y_r = k. //! Non-edge forbidding: x_l + y_r ≤ 1 for every non-edge (l, r). -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::BalancedCompleteBipartiteSubgraph; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/betweenness_ilp.rs b/src/rules/betweenness_ilp.rs index a2cff2767..f9988e1cd 100644 --- a/src/rules/betweenness_ilp.rs +++ b/src/rules/betweenness_ilp.rs @@ -1,6 +1,6 @@ //! One orientation selector per betweenness triple, with bounded element ranks. -use crate::models::algebraic::{Bounded, IntegerVariable, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, ObjectiveSense}; use crate::models::misc::Betweenness; use crate::rules::ilp_helpers::{bounded_order_comparison, ranks_to_positions}; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/biconnectivityaugmentation_ilp.rs b/src/rules/biconnectivityaugmentation_ilp.rs index 67b75fa71..11e8da1e2 100644 --- a/src/rules/biconnectivityaugmentation_ilp.rs +++ b/src/rules/biconnectivityaugmentation_ilp.rs @@ -4,7 +4,7 @@ //! certify that the remaining augmented graph stays connected via unit-flow //! commodities from a surviving root to every other surviving vertex. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::BiconnectivityAugmentation; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/binpacking_casts.rs b/src/rules/binpacking_casts.rs index bfeccb10b..bd65dc725 100644 --- a/src/rules/binpacking_casts.rs +++ b/src/rules/binpacking_casts.rs @@ -2,7 +2,7 @@ use crate::impl_variant_reduction; use crate::models::misc::BinPacking; -use crate::rules::{weight_casts::exact_float_weights, ReductionError}; +use crate::rules::{ReductionError, weight_casts::exact_float_weights}; use crate::types::i64_to_exact_f64; impl_variant_reduction!( diff --git a/src/rules/binpacking_ilp.rs b/src/rules/binpacking_ilp.rs index e5d8af17b..471f36419 100644 --- a/src/rules/binpacking_ilp.rs +++ b/src/rules/binpacking_ilp.rs @@ -6,7 +6,7 @@ //! - Constraints: assignment (each item in exactly one bin) + capacity/linking //! - Objective: minimize number of bins used -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::BinPacking; use crate::reduction; use crate::rules::ilp_helpers::one_hot_decode_rows; diff --git a/src/rules/bmf_ilp.rs b/src/rules/bmf_ilp.rs index 369fae11f..1fe8b7f7e 100644 --- a/src/rules/bmf_ilp.rs +++ b/src/rules/bmf_ilp.rs @@ -1,6 +1,6 @@ //! Exact Boolean factorization with coverage indicators only for true entries. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, BMF, ILP}; +use crate::models::algebraic::{BMF, ILP, LinearConstraint, ObjectiveSense}; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/bottlenecktravelingsalesman_ilp.rs b/src/rules/bottlenecktravelingsalesman_ilp.rs index dba6468f0..306fa29f4 100644 --- a/src/rules/bottlenecktravelingsalesman_ilp.rs +++ b/src/rules/bottlenecktravelingsalesman_ilp.rs @@ -1,6 +1,6 @@ //! Bottleneck TSP to ILP using cyclic positions and a selected maximum edge. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::BottleneckTravelingSalesman; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/boundedcomponentspanningforest_ilp.rs b/src/rules/boundedcomponentspanningforest_ilp.rs index 7710cca61..e7b0442d3 100644 --- a/src/rules/boundedcomponentspanningforest_ilp.rs +++ b/src/rules/boundedcomponentspanningforest_ilp.rs @@ -4,7 +4,7 @@ //! connectivity inside each used component via flow. //! See the paper entry for the full formulation. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::BoundedComponentSpanningForest; use crate::reduction; use crate::rules::ilp_helpers::one_hot_decode_rows; diff --git a/src/rules/boundeddiameterspanningtree_ilp.rs b/src/rules/boundeddiameterspanningtree_ilp.rs index 6d3cb0baf..baef03266 100644 --- a/src/rules/boundeddiameterspanningtree_ilp.rs +++ b/src/rules/boundeddiameterspanningtree_ilp.rs @@ -1,5 +1,5 @@ //! A bounded-depth tree rooted at a vertex or the two ends of a center edge. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::BoundedDiameterSpanningTree; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::SimpleGraph; diff --git a/src/rules/capacityassignment_ilp.rs b/src/rules/capacityassignment_ilp.rs index 30fcebb5b..9b147308a 100644 --- a/src/rules/capacityassignment_ilp.rs +++ b/src/rules/capacityassignment_ilp.rs @@ -7,7 +7,7 @@ //! - Objective: Minimize Σ_{l,c} cost[l][c]·x_{l,c} //! - Extraction: argmax_c x_{l,c} for each link l -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::CapacityAssignment; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/circuit_ilp.rs b/src/rules/circuit_ilp.rs index e00574185..8b78fb9e2 100644 --- a/src/rules/circuit_ilp.rs +++ b/src/rules/circuit_ilp.rs @@ -14,7 +14,7 @@ //! ## Objective //! Trivial (minimize 0): any feasible ILP solution is a satisfying assignment. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::formula::{BooleanExpr, BooleanOp, CircuitSAT}; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/circuit_sat.rs b/src/rules/circuit_sat.rs index 0bc5657ac..0b917e0cd 100644 --- a/src/rules/circuit_sat.rs +++ b/src/rules/circuit_sat.rs @@ -256,7 +256,7 @@ fn normalize_nary_gate( for arg in args { match normalize_expr(arg) { NormalizedExpr::Const(value) if value == absorbing_value => { - return NormalizedExpr::Const(absorbing_value) + return NormalizedExpr::Const(absorbing_value); } NormalizedExpr::Const(value) if value == identity_value => {} normalized => normalized_args.push(normalized), diff --git a/src/rules/closeststring_ilp.rs b/src/rules/closeststring_ilp.rs index 17299eb1b..ec64c1571 100644 --- a/src/rules/closeststring_ilp.rs +++ b/src/rules/closeststring_ilp.rs @@ -21,7 +21,7 @@ //! substring problems," Journal of the ACM 49(2):157-171, 2002. //! -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::misc::ClosestString; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/closestsubstring_ilp.rs b/src/rules/closestsubstring_ilp.rs index fdb96047f..b0f7a4c1f 100644 --- a/src/rules/closestsubstring_ilp.rs +++ b/src/rules/closestsubstring_ilp.rs @@ -29,7 +29,7 @@ //! substring problems," Journal of the ACM 49(2):157-171, 2002. //! -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::misc::ClosestSubstring; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/clustering_ilp.rs b/src/rules/clustering_ilp.rs index 69bbb04af..4eb272a09 100644 --- a/src/rules/clustering_ilp.rs +++ b/src/rules/clustering_ilp.rs @@ -5,7 +5,7 @@ //! cluster, and conflict constraints forbid any pair with distance above the //! diameter bound from sharing a cluster. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::Clustering; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/coloring_ilp.rs b/src/rules/coloring_ilp.rs index 7806d5dc6..78f35b0b8 100644 --- a/src/rules/coloring_ilp.rs +++ b/src/rules/coloring_ilp.rs @@ -7,13 +7,13 @@ //! 2. Adjacent vertices have different colors: x_{u,c} + x_{v,c} <= 1 for each edge (u,v) and color c //! - Objective: None (feasibility problem, minimize 0) -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::KColoring; use crate::reduction; use crate::rules::ilp_helpers::one_hot_decode_rows; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::{Graph, SimpleGraph}; -use crate::variant::{KValue, K2, K3, KN}; +use crate::variant::{K2, K3, KN, KValue}; /// Result of reducing KColoring to ILP. /// diff --git a/src/rules/coloring_qubo.rs b/src/rules/coloring_qubo.rs index e6b6fdc38..f21e343bc 100644 --- a/src/rules/coloring_qubo.rs +++ b/src/rules/coloring_qubo.rs @@ -14,7 +14,7 @@ use crate::models::graph::KColoring; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::{Graph, SimpleGraph}; -use crate::variant::{KValue, K2, K3, KN}; +use crate::variant::{K2, K3, KN, KValue}; /// Result of reducing KColoring to QUBO. #[derive(Debug, Clone)] diff --git a/src/rules/comparativecontainment_casts.rs b/src/rules/comparativecontainment_casts.rs index 3c3bcefa3..dc737a5ab 100644 --- a/src/rules/comparativecontainment_casts.rs +++ b/src/rules/comparativecontainment_casts.rs @@ -2,7 +2,7 @@ use crate::impl_variant_reduction; use crate::models::set::ComparativeContainment; -use crate::rules::{weight_casts::exact_float_weights, ReductionError}; +use crate::rules::{ReductionError, weight_casts::exact_float_weights}; use crate::types::One; impl_variant_reduction!( diff --git a/src/rules/consecutiveblockminimization_ilp.rs b/src/rules/consecutiveblockminimization_ilp.rs index ba5d6acdb..555323d3c 100644 --- a/src/rules/consecutiveblockminimization_ilp.rs +++ b/src/rules/consecutiveblockminimization_ilp.rs @@ -4,7 +4,7 @@ //! by detecting each 0-to-1 transition after permutation. use crate::models::algebraic::{ - ConsecutiveBlockMinimization, LinearConstraint, ObjectiveSense, ILP, + ConsecutiveBlockMinimization, ILP, LinearConstraint, ObjectiveSense, }; use crate::reduction; use crate::rules::ilp_helpers::{one_hot_assignment_constraints, one_hot_decode}; diff --git a/src/rules/consecutiveonesmatrixaugmentation_ilp.rs b/src/rules/consecutiveonesmatrixaugmentation_ilp.rs index 83eea00d1..7fc37a557 100644 --- a/src/rules/consecutiveonesmatrixaugmentation_ilp.rs +++ b/src/rules/consecutiveonesmatrixaugmentation_ilp.rs @@ -1,8 +1,8 @@ //! Bound each row’s span in a column permutation using two integer endpoints. use crate::models::algebraic::{ - Bounded, ConsecutiveOnesMatrixAugmentation, IntegerVariable, LinearConstraint, ObjectiveSense, - ILP, + Bounded, ConsecutiveOnesMatrixAugmentation, ILP, IntegerVariable, LinearConstraint, + ObjectiveSense, }; use crate::reduction; use crate::rules::ilp_helpers::{one_hot_assignment_constraints, one_hot_decode}; diff --git a/src/rules/consecutiveonessubmatrix_ilp.rs b/src/rules/consecutiveonessubmatrix_ilp.rs index f8d99fe36..b4f77cd1f 100644 --- a/src/rules/consecutiveonessubmatrix_ilp.rs +++ b/src/rules/consecutiveonessubmatrix_ilp.rs @@ -4,7 +4,7 @@ //! every row to have a single consecutive block within the chosen submatrix. //! The output is the column-selection bits s_c. -use crate::models::algebraic::{ConsecutiveOnesSubmatrix, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ConsecutiveOnesSubmatrix, ILP, LinearConstraint, ObjectiveSense}; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/consistencyofdatabasefrequencytables_ilp.rs b/src/rules/consistencyofdatabasefrequencytables_ilp.rs index f53094e6a..78ca92d83 100644 --- a/src/rules/consistencyofdatabasefrequencytables_ilp.rs +++ b/src/rules/consistencyofdatabasefrequencytables_ilp.rs @@ -6,7 +6,7 @@ //! //! The pair-count equalities are linearized with standard McCormick constraints. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::ConsistencyOfDatabaseFrequencyTables; use crate::reduction; use crate::rules::ilp_helpers::mccormick_product; @@ -116,12 +116,12 @@ impl ReductionResult for ReductionCDFTToILP { (None, _) => { return Err(crate::rules::ExtractionError::invalid(format!( "object {object}, attribute {attribute} has no selected value" - ))) + ))); } (Some(_), Some(_)) => { return Err(crate::rules::ExtractionError::invalid(format!( "object {object}, attribute {attribute} has multiple selected values" - ))) + ))); } }; source_solution.push(value); diff --git a/src/rules/cyclicordering_ilp.rs b/src/rules/cyclicordering_ilp.rs index c7747bf51..7d7ec546b 100644 --- a/src/rules/cyclicordering_ilp.rs +++ b/src/rules/cyclicordering_ilp.rs @@ -1,6 +1,6 @@ //! Sparse rank comparisons for cyclic ordering triples. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::misc::CyclicOrdering; use crate::rules::ilp_helpers::{bounded_order_comparison, ranks_to_positions}; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/decisionilp_sat.rs b/src/rules/decisionilp_sat.rs index 7830a03dc..118ab0211 100644 --- a/src/rules/decisionilp_sat.rs +++ b/src/rules/decisionilp_sat.rs @@ -1,6 +1,6 @@ //! Binary decision ILP to SAT using ripple adders and Tseitin gate clauses. -use crate::models::algebraic::{Comparison, ObjectiveSense, ILP}; +use crate::models::algebraic::{Comparison, ILP, ObjectiveSense}; use crate::models::{CNFClause, Decision, Satisfiability}; use crate::registry::ConstructionError; use crate::rules::sat_helpers::SatVariableAllocator; @@ -211,7 +211,7 @@ mod tests; #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { use crate::example_db::specs::{ - assemble_rule_example, rule_example_with_witness, RuleExampleSpec, + RuleExampleSpec, assemble_rule_example, rule_example_with_witness, }; use crate::export::SolutionPair; use crate::models::algebraic::ilp::canonical_decision_example; diff --git a/src/rules/decisionminimumvertexcover_hamiltoniancircuit.rs b/src/rules/decisionminimumvertexcover_hamiltoniancircuit.rs index c5bd03e23..0969be63d 100644 --- a/src/rules/decisionminimumvertexcover_hamiltoniancircuit.rs +++ b/src/rules/decisionminimumvertexcover_hamiltoniancircuit.rs @@ -269,7 +269,7 @@ impl ReductionResult for ReductionDecisionMinimumVertexCoverToHamiltonianCircuit ConstructionKind::FixedNo => { return Err(crate::rules::ExtractionError::invalid( "the fixed negative target instance has no extractable witness", - )) + )); } ConstructionKind::Theorem(construction) => { construction.decode_solution(target_solution)? diff --git a/src/rules/directedhamiltonianpath_ilp.rs b/src/rules/directedhamiltonianpath_ilp.rs index 133efcf35..362e11f58 100644 --- a/src/rules/directedhamiltonianpath_ilp.rs +++ b/src/rules/directedhamiltonianpath_ilp.rs @@ -6,7 +6,7 @@ //! - Arc existence: for each consecutive position pair (k, k+1), any pair (v, w) where //! (v, w) is NOT a directed arc is forbidden: x_{v,k} + x_{w,k+1} <= 1 -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::DirectedHamiltonianPath; use crate::reduction; use crate::rules::ilp_helpers::{one_hot_assignment_constraints, one_hot_decode}; diff --git a/src/rules/directedtwocommodityintegralflow_ilp.rs b/src/rules/directedtwocommodityintegralflow_ilp.rs index 42519071c..e1311a6e0 100644 --- a/src/rules/directedtwocommodityintegralflow_ilp.rs +++ b/src/rules/directedtwocommodityintegralflow_ilp.rs @@ -12,7 +12,7 @@ //! Objective: Minimize 0 (feasibility). //! Extraction: Direct 2*|A| variables. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::DirectedTwoCommodityIntegralFlow; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/disjointconnectingpaths_ilp.rs b/src/rules/disjointconnectingpaths_ilp.rs index 22f6975da..75eb131da 100644 --- a/src/rules/disjointconnectingpaths_ilp.rs +++ b/src/rules/disjointconnectingpaths_ilp.rs @@ -3,7 +3,7 @@ //! Binary flow variables `f^k_{e,dir}` per commodity per directed arc orientation. //! Flow conservation and unit vertex capacities enforce vertex-disjoint paths. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::DisjointConnectingPaths; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/dynamicstorageallocation_qubo.rs b/src/rules/dynamicstorageallocation_qubo.rs index 25b0c1920..a1890d8e8 100644 --- a/src/rules/dynamicstorageallocation_qubo.rs +++ b/src/rules/dynamicstorageallocation_qubo.rs @@ -2,8 +2,8 @@ use crate::models::algebraic::QUBO; use crate::models::decision::Decision; use crate::models::misc::DynamicStorageAllocation; -use crate::rules::qubo_helpers::decode_rows; use crate::rules::qubo_helpers::QuboBuilder; +use crate::rules::qubo_helpers::decode_rows; use crate::rules::traits::validate_target_witness; use crate::rules::{ExtractionResult, ReduceTo, ReductionError, ReductionResult}; #[derive(Debug, Clone)] diff --git a/src/rules/ensemblecomputation_ilp.rs b/src/rules/ensemblecomputation_ilp.rs index b94272171..fc043d244 100644 --- a/src/rules/ensemblecomputation_ilp.rs +++ b/src/rules/ensemblecomputation_ilp.rs @@ -1,6 +1,6 @@ //! Polynomial-size circuit-slot reduction from EnsembleComputation to `ILP`. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::EnsembleComputation; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/eulerianpath_ilp.rs b/src/rules/eulerianpath_ilp.rs index 761a13022..3be299191 100644 --- a/src/rules/eulerianpath_ilp.rs +++ b/src/rules/eulerianpath_ilp.rs @@ -23,7 +23,7 @@ //! Bang-Jensen and Gutin, *Digraphs: Theory, Algorithms and Applications*, //! 2nd ed., Springer (2009). -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::EulerianPath; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/exactcoverby3sets_ilp.rs b/src/rules/exactcoverby3sets_ilp.rs index 3072e4ea9..f6156d54a 100644 --- a/src/rules/exactcoverby3sets_ilp.rs +++ b/src/rules/exactcoverby3sets_ilp.rs @@ -3,7 +3,7 @@ //! Binary variable x_j per triple; for each element e, require Σ x_j = 1 //! (exact cover). Additional constraint Σ x_j = universe_size/3. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::set::ExactCoverBy3Sets; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/expectedretrievalcost_ilp.rs b/src/rules/expectedretrievalcost_ilp.rs index a25129278..57f21e52b 100644 --- a/src/rules/expectedretrievalcost_ilp.rs +++ b/src/rules/expectedretrievalcost_ilp.rs @@ -14,7 +14,7 @@ //! //! Objective: Minimize Σ_{r,s,r',s'} lat(s,s') * p_r * p_{r'} * z_{r,s,r',s'} -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::ExpectedRetrievalCost; use crate::reduction; use crate::rules::ilp_helpers::{mccormick_product, one_hot_decode_rows}; diff --git a/src/rules/factoring_ilp.rs b/src/rules/factoring_ilp.rs index f4010c09f..092209a7f 100644 --- a/src/rules/factoring_ilp.rs +++ b/src/rules/factoring_ilp.rs @@ -19,7 +19,7 @@ //! 4. Binary bounds: p_i ≤ 1, q_j ≤ 1 //! 5. Carry bounds: 0 ≤ c_k ≤ min(m, n) -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::misc::Factoring; use crate::reduction; use crate::rules::ilp_helpers::mccormick_product; @@ -99,11 +99,7 @@ impl ReductionResult for ReductionFactoringToILP { .fold(num_bigint::BigUint::from(0u8), |value, index| { value + (num_bigint::BigUint::from(1u8) << index) }); - if p <= q { - (p, q) - } else { - (q, p) - } + if p <= q { (p, q) } else { (q, p) } }) } } diff --git a/src/rules/feasibleregisterassignment_ilp.rs b/src/rules/feasibleregisterassignment_ilp.rs index 73cf309ed..67238867c 100644 --- a/src/rules/feasibleregisterassignment_ilp.rs +++ b/src/rules/feasibleregisterassignment_ilp.rs @@ -1,6 +1,6 @@ //! Bounded ranks with order selectors only for vertices sharing a register. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::misc::FeasibleRegisterAssignment; use crate::reduction; use crate::rules::ilp_helpers::{bounded_order_comparison, ranks_to_positions}; diff --git a/src/rules/flowshopscheduling_ilp.rs b/src/rules/flowshopscheduling_ilp.rs index 868450f83..d3b68a990 100644 --- a/src/rules/flowshopscheduling_ilp.rs +++ b/src/rules/flowshopscheduling_ilp.rs @@ -5,7 +5,7 @@ //! Machine-chain and big-M disjunctive constraints enforce a valid flow-shop //! schedule; the deadline becomes a makespan bound. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::misc::FlowShopScheduling; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/graph.rs b/src/rules/graph.rs index 922bc3f59..8ad9c7b07 100644 --- a/src/rules/graph.rs +++ b/src/rules/graph.rs @@ -154,13 +154,17 @@ pub enum ExecutePathsError { problem: String, variant: BTreeMap, }, - #[error("concrete path {path_index} has no registered edge from {source_problem} to {target_problem}")] + #[error( + "concrete path {path_index} has no registered edge from {source_problem} to {target_problem}" + )] MissingEdge { path_index: usize, source_problem: String, target_problem: String, }, - #[error("concrete path {path_index} edge {source_problem} -> {target_problem} is not witness-executable")] + #[error( + "concrete path {path_index} edge {source_problem} -> {target_problem} is not witness-executable" + )] NotWitnessExecutable { path_index: usize, source_problem: String, @@ -184,20 +188,22 @@ pub enum PathParameterError { problem: String, variant: BTreeMap, }, - #[error( - "reduction path contains no registered edge from {source_problem} to {target_problem}" - )] + #[error("reduction path contains no registered edge from {source_problem} to {target_problem}")] MissingEdge { source_problem: String, target_problem: String, }, - #[error("reduction step {step} ({source_problem} -> {target_problem}) is a multi-query reduction without a query-cost model")] + #[error( + "reduction step {step} ({source_problem} -> {target_problem}) is a multi-query reduction without a query-cost model" + )] TuringEdge { step: usize, source_problem: String, target_problem: String, }, - #[error("reduction step {step} ({source_problem} -> {target_problem}) has an invalid parameter contract: {error}")] + #[error( + "reduction step {step} ({source_problem} -> {target_problem}) has an invalid parameter contract: {error}" + )] InvalidContract { step: usize, source_problem: String, @@ -205,15 +211,15 @@ pub enum PathParameterError { #[source] error: Box, }, - #[error("reduction step {step} ({source_problem} -> {target_problem}) has no symbolic parameter transform")] + #[error( + "reduction step {step} ({source_problem} -> {target_problem}) has no symbolic parameter transform" + )] Unavailable { step: usize, source_problem: String, target_problem: String, }, - #[error( - "cannot compose reduction step {step} ({source_problem} -> {target_problem}): {error}" - )] + #[error("cannot compose reduction step {step} ({source_problem} -> {target_problem}): {error}")] Step { step: usize, source_problem: String, @@ -967,11 +973,11 @@ impl ReductionGraph { }) .unwrap_or_default(); variants.sort(); - if let Some(default) = self.default_variants.get(name) { - if let Some(index) = variants.iter().position(|variant| variant == default) { - let default = variants.remove(index); - variants.insert(0, default); - } + if let Some(default) = self.default_variants.get(name) + && let Some(index) = variants.iter().position(|variant| variant == default) + { + let default = variants.remove(index); + variants.insert(0, default); } variants } @@ -1541,14 +1547,13 @@ pub(crate) fn recover_completed_result( .aggregate_view .map(|view| view(step.result)?.extract_value_dyn(value.clone())) .transpose()?; - if let Some(mapped_value) = &mapped { - if step + if let Some(mapped_value) = &mapped + && step .source .aggregate_witness_evaluation(mapped_value)? .is_none() - { - return Ok(None); - } + { + return Ok(None); } witness = step.result.extract_solution_dyn(witness.as_ref())?; value = step diff --git a/src/rules/graphpartitioning_ilp.rs b/src/rules/graphpartitioning_ilp.rs index 4965ccedd..88e0107d0 100644 --- a/src/rules/graphpartitioning_ilp.rs +++ b/src/rules/graphpartitioning_ilp.rs @@ -5,7 +5,7 @@ //! - Constraints: one balance equality plus two linking inequalities per edge //! - Objective: minimize the number of crossing edges -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::GraphPartitioning; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/hamiltoniancircuit_hamiltonianpath.rs b/src/rules/hamiltoniancircuit_hamiltonianpath.rs index d697fef00..e37c531a1 100644 --- a/src/rules/hamiltoniancircuit_hamiltonianpath.rs +++ b/src/rules/hamiltoniancircuit_hamiltonianpath.rs @@ -68,7 +68,7 @@ impl ReductionResult for ReductionHamiltonianCircuitToHamiltonianPath { _ => { return Err(crate::rules::ExtractionError::invalid( "target path does not have the required pendant endpoints", - )) + )); } }; diff --git a/src/rules/hamiltoniancircuit_ilp.rs b/src/rules/hamiltoniancircuit_ilp.rs index 013e42d60..1a802c5d9 100644 --- a/src/rules/hamiltoniancircuit_ilp.rs +++ b/src/rules/hamiltoniancircuit_ilp.rs @@ -1,6 +1,6 @@ //! Degree two and a single bounded flow enforce a spanning cycle. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::HamiltonianCircuit; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::{Graph, SimpleGraph}; diff --git a/src/rules/hamiltonianpath_ilp.rs b/src/rules/hamiltonianpath_ilp.rs index c3cbbef12..568f4d98e 100644 --- a/src/rules/hamiltonianpath_ilp.rs +++ b/src/rules/hamiltonianpath_ilp.rs @@ -1,6 +1,6 @@ //! A permutation matrix with direct consecutive-position adjacency constraints. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::HamiltonianPath; use crate::reduction; use crate::rules::ilp_helpers::{one_hot_assignment_constraints, one_hot_decode}; diff --git a/src/rules/highlyconnecteddeletion_ilp.rs b/src/rules/highlyconnecteddeletion_ilp.rs index c10b92986..4a953e3da 100644 --- a/src/rules/highlyconnecteddeletion_ilp.rs +++ b/src/rules/highlyconnecteddeletion_ilp.rs @@ -14,7 +14,7 @@ //! deletion can restore all internal edges without losing connectivity, so an //! optimal source solution is represented. Self-loops are always kept. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::HighlyConnectedDeletion; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/ilp_casts.rs b/src/rules/ilp_casts.rs index 088ce6dca..1a1a06053 100644 --- a/src/rules/ilp_casts.rs +++ b/src/rules/ilp_casts.rs @@ -1,6 +1,6 @@ //! Numeric variant reductions for ILP. -use crate::models::algebraic::{Comparison, LinearConstraint, VariableDomain, ILP}; +use crate::models::algebraic::{Comparison, ILP, LinearConstraint, VariableDomain}; use crate::reduction; use crate::rules::{ReduceTo, ReductionError, ReductionResult}; use crate::types::i64_to_exact_f64; diff --git a/src/rules/ilp_i64_ilp_bool.rs b/src/rules/ilp_i64_ilp_bool.rs index b101ed675..fa970ac83 100644 --- a/src/rules/ilp_i64_ilp_bool.rs +++ b/src/rules/ilp_i64_ilp_bool.rs @@ -1,9 +1,9 @@ //! Encode finitely bounded integer ILP variables as binary variables. -use crate::models::algebraic::{Bounded, Comparison, LinearConstraint, ILP}; +use crate::models::algebraic::{Bounded, Comparison, ILP, LinearConstraint}; use crate::reduction; -use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::rules::ReductionError; +use crate::rules::traits::{ReduceTo, ReductionResult}; #[derive(Debug, Clone)] struct VarEncoding { diff --git a/src/rules/ilp_qubo.rs b/src/rules/ilp_qubo.rs index e7b042415..152418737 100644 --- a/src/rules/ilp_qubo.rs +++ b/src/rules/ilp_qubo.rs @@ -11,7 +11,7 @@ //! The custom aggregate restores the omitted constant and both objective senses; //! only zero-penalty configurations certify a feasible source assignment. -use crate::models::algebraic::{Comparison, ObjectiveSense, ILP, QUBO}; +use crate::models::algebraic::{Comparison, ILP, ObjectiveSense, QUBO}; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/integerknapsack_ilp.rs b/src/rules/integerknapsack_ilp.rs index 5c6918b9a..4ceccb469 100644 --- a/src/rules/integerknapsack_ilp.rs +++ b/src/rules/integerknapsack_ilp.rs @@ -4,7 +4,7 @@ //! capacity inequality omits oversized items (whose multiplicities are zero), and explicit upper bounds //! `c_i <= floor(B / s_i)` preserve the exact witness domain of the source. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::set::IntegerKnapsack; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/integralflowbundles_ilp.rs b/src/rules/integralflowbundles_ilp.rs index 63a663f7c..9a9e08399 100644 --- a/src/rules/integralflowbundles_ilp.rs +++ b/src/rules/integralflowbundles_ilp.rs @@ -4,7 +4,7 @@ //! the bundle-capacity inequalities, flow-conservation equalities at //! nonterminals, and the sink inflow lower bound from the source problem. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::IntegralFlowBundles; use crate::reduction; use crate::rules::ilp_helpers::bounded_flow_requirement; diff --git a/src/rules/integralflowhomologousarcs_ilp.rs b/src/rules/integralflowhomologousarcs_ilp.rs index 89e449f17..1c5097485 100644 --- a/src/rules/integralflowhomologousarcs_ilp.rs +++ b/src/rules/integralflowhomologousarcs_ilp.rs @@ -3,7 +3,7 @@ //! One integer flow variable per arc. Capacity bounds, conservation at //! non-terminals, homologous-pair equality, and sink inflow requirement. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::IntegralFlowHomologousArcs; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/integralflowwithmultipliers_ilp.rs b/src/rules/integralflowwithmultipliers_ilp.rs index 3ebc858cb..3a6440ab9 100644 --- a/src/rules/integralflowwithmultipliers_ilp.rs +++ b/src/rules/integralflowwithmultipliers_ilp.rs @@ -3,7 +3,7 @@ //! One integer flow variable per arc. Capacity bounds, multiplier-scaled //! conservation at non-terminals, and sink inflow requirement. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::IntegralFlowWithMultipliers; use crate::reduction; use crate::rules::ilp_helpers::bounded_flow_requirement; diff --git a/src/rules/isomorphicspanningtree_ilp.rs b/src/rules/isomorphicspanningtree_ilp.rs index 07efbbf05..ec8dd579d 100644 --- a/src/rules/isomorphicspanningtree_ilp.rs +++ b/src/rules/isomorphicspanningtree_ilp.rs @@ -3,7 +3,7 @@ //! Binary variable x_{u,v} with x_{u,v} = 1 iff tree vertex u maps to graph //! vertex v. Bijection constraints plus non-edge exclusion for every tree edge. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::IsomorphicSpanningTree; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/kclique_ilp.rs b/src/rules/kclique_ilp.rs index cd14be9c0..152d0f58f 100644 --- a/src/rules/kclique_ilp.rs +++ b/src/rules/kclique_ilp.rs @@ -9,7 +9,7 @@ //! //! The ILP is feasible if and only if the graph contains a clique of size at least k. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::KClique; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/kernel_ilp.rs b/src/rules/kernel_ilp.rs index 8363af39a..47390c335 100644 --- a/src/rules/kernel_ilp.rs +++ b/src/rules/kernel_ilp.rs @@ -1,6 +1,6 @@ //! Binary independence and absorption constraints for a directed graph kernel. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::Kernel; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/knapsack_ilp.rs b/src/rules/knapsack_ilp.rs index e26e2f8be..8c33cba17 100644 --- a/src/rules/knapsack_ilp.rs +++ b/src/rules/knapsack_ilp.rs @@ -7,7 +7,7 @@ //! //! Items exceeding capacity are fixed to zero and omitted from the capacity row. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::Knapsack; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/ksatisfiability_cyclicordering.rs b/src/rules/ksatisfiability_cyclicordering.rs index 0c2115133..ad016954c 100644 --- a/src/rules/ksatisfiability_cyclicordering.rs +++ b/src/rules/ksatisfiability_cyclicordering.rs @@ -129,11 +129,7 @@ fn normalize( + 1; let index = i64::try_from(compact) .expect("compaction cannot increase a valid source variable index"); - if *literal > 0 { - index - } else { - -index - } + if *literal > 0 { index } else { -index } }) .collect(); // Deduplication leaves one to three literals; fill the rest with fresh variables. diff --git a/src/rules/ksatisfiability_quadraticcongruences.rs b/src/rules/ksatisfiability_quadraticcongruences.rs index 585b7fdd4..7a4e43cfa 100644 --- a/src/rules/ksatisfiability_quadraticcongruences.rs +++ b/src/rules/ksatisfiability_quadraticcongruences.rs @@ -165,11 +165,7 @@ fn build_construction( .expect("native SAT indices fit usize"); let variable = i64::try_from(var_map[&original]).expect("compact SAT indices fit i64"); - if literal > 0 { - variable - } else { - -variable - } + if literal > 0 { variable } else { -variable } }) .collect() }) diff --git a/src/rules/ksatisfiability_simultaneousincongruences.rs b/src/rules/ksatisfiability_simultaneousincongruences.rs index 1ef37811e..cdfe3d410 100644 --- a/src/rules/ksatisfiability_simultaneousincongruences.rs +++ b/src/rules/ksatisfiability_simultaneousincongruences.rs @@ -7,7 +7,7 @@ use std::collections::BTreeMap; use crate::models::algebraic::SimultaneousIncongruences; -use crate::models::formula::{ksat::first_n_odd_primes, CNFClause, KSatisfiability}; +use crate::models::formula::{CNFClause, KSatisfiability, ksat::first_n_odd_primes}; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::variant::K3; @@ -52,11 +52,7 @@ impl ReductionResult for Reduction3SATToSimultaneousIncongruences { } fn falsifying_residue(literal: i64) -> u64 { - if literal > 0 { - 2 - } else { - 1 - } + if literal > 0 { 2 } else { 1 } } fn modular_inverse(value: u64, modulus: u64) -> Option { diff --git a/src/rules/ksatisfiability_timetabledesign.rs b/src/rules/ksatisfiability_timetabledesign.rs index a2b8e9def..aafe873be 100644 --- a/src/rules/ksatisfiability_timetabledesign.rs +++ b/src/rules/ksatisfiability_timetabledesign.rs @@ -130,11 +130,7 @@ fn literal_var_index(literal: i64) -> usize { fn evaluate_clause(clause: &CNFClause, assignment: &[bool]) -> bool { clause.literals.iter().any(|&literal| { let value = assignment[literal_var_index(literal)]; - if literal > 0 { - value - } else { - !value - } + if literal > 0 { value } else { !value } }) } diff --git a/src/rules/lengthboundeddisjointpaths_ilp.rs b/src/rules/lengthboundeddisjointpaths_ilp.rs index ed1ebcde0..98a3d9542 100644 --- a/src/rules/lengthboundeddisjointpaths_ilp.rs +++ b/src/rules/lengthboundeddisjointpaths_ilp.rs @@ -3,7 +3,7 @@ //! Binary flow variables per commodity per directed edge orientation. //! Conservation, edge/vertex disjointness, and length bound. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::LengthBoundedDisjointPaths; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/longestcircuit_ilp.rs b/src/rules/longestcircuit_ilp.rs index 9f940844e..07480ab4e 100644 --- a/src/rules/longestcircuit_ilp.rs +++ b/src/rules/longestcircuit_ilp.rs @@ -8,9 +8,9 @@ //! - Maximize: sum l_e y_e //! - Multi-commodity flow connectivity from a root chosen on the circuit -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; -use crate::models::graph::LongestCircuit; use crate::models::Decision; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; +use crate::models::graph::LongestCircuit; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::{Graph, SimpleGraph}; diff --git a/src/rules/longestcommonsubsequence_ilp.rs b/src/rules/longestcommonsubsequence_ilp.rs index 697e4ed23..108e01e45 100644 --- a/src/rules/longestcommonsubsequence_ilp.rs +++ b/src/rules/longestcommonsubsequence_ilp.rs @@ -10,7 +10,7 @@ //! positions, and character consistency. The objective maximizes the number of //! non-padding positions. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::LongestCommonSubsequence; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/longestcommonsubsequence_maximumindependentset.rs b/src/rules/longestcommonsubsequence_maximumindependentset.rs index 0705b3bcd..aa59d06a1 100644 --- a/src/rules/longestcommonsubsequence_maximumindependentset.rs +++ b/src/rules/longestcommonsubsequence_maximumindependentset.rs @@ -4,7 +4,7 @@ //! The target optimum is LCS for tuples, or h * m + LCS for h slots and m strings. use crate::models::graph::MaximumIndependentSet; -use crate::models::misc::{is_subsequence, LongestCommonSubsequence}; +use crate::models::misc::{LongestCommonSubsequence, is_subsequence}; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::{Graph, SimpleGraph}; diff --git a/src/rules/longestpath_ilp.rs b/src/rules/longestpath_ilp.rs index 9f440befb..1e9e6fbca 100644 --- a/src/rules/longestpath_ilp.rs +++ b/src/rules/longestpath_ilp.rs @@ -5,7 +5,7 @@ //! path positions. Flow-balance constraints force a single directed `s-t` path, //! while MTZ-style ordering constraints eliminate detached cycles. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::LongestPath; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/maximalis_ilp.rs b/src/rules/maximalis_ilp.rs index 0bf59f2c0..cccff9dce 100644 --- a/src/rules/maximalis_ilp.rs +++ b/src/rules/maximalis_ilp.rs @@ -3,7 +3,7 @@ //! Binary variable x_v per vertex. Independence: ∀ edge (u,v): x_u + x_v ≤ 1. //! Maximality: ∀ v: x_v + Σ_{u∈N(v)} x_u ≥ 1. Maximize Σ w_v·x_v. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::MaximalIS; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/maximum2satisfiability_ilp.rs b/src/rules/maximum2satisfiability_ilp.rs index a600e090e..d069573b2 100644 --- a/src/rules/maximum2satisfiability_ilp.rs +++ b/src/rules/maximum2satisfiability_ilp.rs @@ -7,7 +7,7 @@ //! literal expressions, ensuring z_j = 1 only if the clause is satisfied //! - Objective: maximize the sum of clause indicators -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::formula::Maximum2Satisfiability; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/maximum2satisfiability_maxcut.rs b/src/rules/maximum2satisfiability_maxcut.rs index e434ebbb5..94ec6cf6e 100644 --- a/src/rules/maximum2satisfiability_maxcut.rs +++ b/src/rules/maximum2satisfiability_maxcut.rs @@ -54,11 +54,7 @@ fn add_edge_weight(weights: &mut BTreeMap<(usize, usize), i64>, u: usize, v: usi } fn literal_polarity(lit: i64) -> i64 { - if lit > 0 { - 1 - } else { - -1 - } + if lit > 0 { 1 } else { -1 } } #[reduction( diff --git a/src/rules/maximumclique_ilp.rs b/src/rules/maximumclique_ilp.rs index e2871bf66..a27cf21d7 100644 --- a/src/rules/maximumclique_ilp.rs +++ b/src/rules/maximumclique_ilp.rs @@ -6,7 +6,7 @@ //! at most one can be in the clique //! - Objective: Maximize the sum of weights of selected vertices -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::MaximumClique; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/maximumcokplex_ilp.rs b/src/rules/maximumcokplex_ilp.rs index 1471c9014..96ca21d6e 100644 --- a/src/rules/maximumcokplex_ilp.rs +++ b/src/rules/maximumcokplex_ilp.rs @@ -5,13 +5,13 @@ //! For each vertex `v`, if `x_v = 1` then at most `k - 1` neighbours may also //! be selected, encoded by `sum_{u in N(v)} x_u + d(v) x_v <= d(v) + k - 1`. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::MaximumCoKPlex; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::{Graph, SimpleGraph}; use crate::types::{One, WeightElement}; -use crate::variant::{VariantParam, KN}; +use crate::variant::{KN, VariantParam}; use std::marker::PhantomData; #[derive(Debug, Clone)] diff --git a/src/rules/maximumcommonedgesubgraph_ilp.rs b/src/rules/maximumcommonedgesubgraph_ilp.rs index 0a11c46e8..ba8a89094 100644 --- a/src/rules/maximumcommonedgesubgraph_ilp.rs +++ b/src/rules/maximumcommonedgesubgraph_ilp.rs @@ -12,7 +12,7 @@ //! Bahiense, Manic, Piva, and de Souza (DAM 2012) adapted to the directed //! edge-labelled graph model used in the library. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::MaximumCommonEdgeSubgraph; use crate::reduction; use crate::rules::ilp_helpers::mccormick_product; diff --git a/src/rules/maximumcontactmapoverlap_ilp.rs b/src/rules/maximumcontactmapoverlap_ilp.rs index 8c5b3edb1..cbcd46917 100644 --- a/src/rules/maximumcontactmapoverlap_ilp.rs +++ b/src/rules/maximumcontactmapoverlap_ilp.rs @@ -14,7 +14,7 @@ //! Andonov, Malod-Dognin, and Yanev (J. Comput. Biol., 2011) and by //! Xie and Sahinidis (J. Comput. Biol., 2007). -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::MaximumContactMapOverlap; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/maximumdomaticnumber_ilp.rs b/src/rules/maximumdomaticnumber_ilp.rs index c978d5c02..811c4a1bb 100644 --- a/src/rules/maximumdomaticnumber_ilp.rs +++ b/src/rules/maximumdomaticnumber_ilp.rs @@ -8,7 +8,7 @@ //! - Linking constraints: x_{v,i} ≤ y_i for each v, i //! - Objective: maximize Σ y_i -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::MaximumDomaticNumber; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/maximumedgeweightedkclique_casts.rs b/src/rules/maximumedgeweightedkclique_casts.rs index 000960eae..5ca82b9f3 100644 --- a/src/rules/maximumedgeweightedkclique_casts.rs +++ b/src/rules/maximumedgeweightedkclique_casts.rs @@ -2,7 +2,7 @@ use crate::impl_variant_reduction; use crate::models::graph::MaximumEdgeWeightedKClique; -use crate::rules::{weight_casts::exact_float_weights, ReductionError}; +use crate::rules::{ReductionError, weight_casts::exact_float_weights}; impl_variant_reduction!( MaximumEdgeWeightedKClique, diff --git a/src/rules/maximumedgeweightedkclique_ilp.rs b/src/rules/maximumedgeweightedkclique_ilp.rs index 9cb107dd3..b2e40c453 100644 --- a/src/rules/maximumedgeweightedkclique_ilp.rs +++ b/src/rules/maximumedgeweightedkclique_ilp.rs @@ -22,7 +22,7 @@ //! sparse graphs with compact formulations," EURO J. Comput. Optim. 3(1) //! (2015). -use crate::models::algebraic::{ILPCoefficient, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ILPCoefficient, LinearConstraint, ObjectiveSense}; use crate::models::graph::MaximumEdgeWeightedKClique; use crate::reduction; use crate::rules::ilp_helpers::mccormick_product; diff --git a/src/rules/maximumindependentset_casts.rs b/src/rules/maximumindependentset_casts.rs index 886590e01..91427b466 100644 --- a/src/rules/maximumindependentset_casts.rs +++ b/src/rules/maximumindependentset_casts.rs @@ -3,9 +3,9 @@ //! Each rule converts one registered graph or weight representation. use crate::impl_variant_reduction; -use crate::models::graph::MaximumIndependentSet; use crate::models::Decision; -use crate::rules::{weight_casts::exact_float_weights, ReduceTo, ReductionResult}; +use crate::models::graph::MaximumIndependentSet; +use crate::rules::{ReduceTo, ReductionResult, weight_casts::exact_float_weights}; use crate::topology::{Graph, KingsSubgraph, SimpleGraph, TriangularSubgraph, UnitDiskGraph}; use crate::types::One; diff --git a/src/rules/maximumleafspanningtree_ilp.rs b/src/rules/maximumleafspanningtree_ilp.rs index 927a3959d..a5827d2ee 100644 --- a/src/rules/maximumleafspanningtree_ilp.rs +++ b/src/rules/maximumleafspanningtree_ilp.rs @@ -18,7 +18,7 @@ //! //! Objective: maximize sum(z_v) -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::MaximumLeafSpanningTree; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/maximumlikelihoodranking_ilp.rs b/src/rules/maximumlikelihoodranking_ilp.rs index cd0ef5a0f..5ff4475b0 100644 --- a/src/rules/maximumlikelihoodranking_ilp.rs +++ b/src/rules/maximumlikelihoodranking_ilp.rs @@ -10,7 +10,7 @@ //! Objective: minimize sum_{i { return Err(crate::rules::ExtractionError::invalid(format!( "dictionary slot {j} is active without a symbol" - ))) + ))); } _ => { return Err(crate::rules::ExtractionError::invalid(format!( "dictionary slot {j} selects multiple symbols" - ))) + ))); } } } else if !symbols.is_empty() { diff --git a/src/rules/minimumfaultdetectiontestset_ilp.rs b/src/rules/minimumfaultdetectiontestset_ilp.rs index ecf7fab3e..89bc04b3c 100644 --- a/src/rules/minimumfaultdetectiontestset_ilp.rs +++ b/src/rules/minimumfaultdetectiontestset_ilp.rs @@ -5,7 +5,7 @@ //! set contains that vertex. Minimizing the sum of the pair variables therefore //! recovers the minimum-size covering test set. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::MinimumFaultDetectionTestSet; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/minimumfeedbackarcset_ilp.rs b/src/rules/minimumfeedbackarcset_ilp.rs index 644a1be07..33bf52a6e 100644 --- a/src/rules/minimumfeedbackarcset_ilp.rs +++ b/src/rules/minimumfeedbackarcset_ilp.rs @@ -9,7 +9,7 @@ //! - Objective: Minimize Σ w_a * y_a //! - Variable layout: first |A| are y_a, next |V| are o_v -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::MinimumFeedbackArcSet; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/minimumfeedbackarcset_qubo.rs b/src/rules/minimumfeedbackarcset_qubo.rs index e310de3c3..336583fab 100644 --- a/src/rules/minimumfeedbackarcset_qubo.rs +++ b/src/rules/minimumfeedbackarcset_qubo.rs @@ -1,8 +1,8 @@ //! Direct exact quadratic encoding of MinimumFeedbackArcSet. use crate::models::algebraic::QUBO; use crate::models::graph::MinimumFeedbackArcSet; -use crate::rules::qubo_helpers::{pair_index, tournament_ranks}; use crate::rules::qubo_helpers::{ObjectiveEncoding, QuboBuilder}; +use crate::rules::qubo_helpers::{pair_index, tournament_ranks}; use crate::rules::{ExtractionResult, ReduceTo, ReductionError, ReductionResult}; use crate::types::Min; #[derive(Debug, Clone)] diff --git a/src/rules/minimumfeedbackvertexset_ilp.rs b/src/rules/minimumfeedbackvertexset_ilp.rs index fd1f9f809..33ab60a5b 100644 --- a/src/rules/minimumfeedbackvertexset_ilp.rs +++ b/src/rules/minimumfeedbackvertexset_ilp.rs @@ -6,7 +6,7 @@ //! Plus binary bounds (x_i <= 1) and order bounds (o_i <= n-1) //! - Objective: Minimize the weighted sum of removed vertices -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::MinimumFeedbackVertexSet; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/minimumgraphbandwidth_ilp.rs b/src/rules/minimumgraphbandwidth_ilp.rs index 5d1587aeb..a48a00c84 100644 --- a/src/rules/minimumgraphbandwidth_ilp.rs +++ b/src/rules/minimumgraphbandwidth_ilp.rs @@ -7,7 +7,7 @@ //! - For each edge (u,v): pos_u - pos_v <= B, pos_v - pos_u <= B //! - Objective: minimize B -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::MinimumGraphBandwidth; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/minimumhittingset_ilp.rs b/src/rules/minimumhittingset_ilp.rs index c6eeb8c77..551785f41 100644 --- a/src/rules/minimumhittingset_ilp.rs +++ b/src/rules/minimumhittingset_ilp.rs @@ -3,7 +3,7 @@ //! Binary variable x_e per universe element; for each set S, //! require Σ_{e∈S} x_e ≥ 1 (set is hit). Minimize Σ x_e. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::set::MinimumHittingSet; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/minimuminternalmacrodatacompression_ilp.rs b/src/rules/minimuminternalmacrodatacompression_ilp.rs index 2952b1014..6f487daec 100644 --- a/src/rules/minimuminternalmacrodatacompression_ilp.rs +++ b/src/rules/minimuminternalmacrodatacompression_ilp.rs @@ -15,7 +15,7 @@ //! = (sum lit[i]) + (sum ptr[i][l][r]) + (h−1) × (sum ptr[i][l][r]) //! = (sum lit[i]) + h × (sum ptr[i][l][r]) -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::MinimumInternalMacroDataCompression; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/minimummatrixcover_ilp.rs b/src/rules/minimummatrixcover_ilp.rs index fb10f3817..c6ae92e0f 100644 --- a/src/rules/minimummatrixcover_ilp.rs +++ b/src/rules/minimummatrixcover_ilp.rs @@ -8,7 +8,7 @@ //! y_{ij} ≤ x_i, y_{ij} ≤ x_j, y_{ij} ≥ x_i + x_j - 1 use crate::models::algebraic::MinimumMatrixCover; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::reduction; use crate::rules::ilp_helpers::mccormick_product; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/minimummaximalmatching_ilp.rs b/src/rules/minimummaximalmatching_ilp.rs index dc131a568..1870f135c 100644 --- a/src/rules/minimummaximalmatching_ilp.rs +++ b/src/rules/minimummaximalmatching_ilp.rs @@ -7,7 +7,7 @@ //! (if edge j is not selected, at least one edge adjacent to it must be) //! - Objective: Minimize sum e_i -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::MinimumMaximalMatching; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/minimummetricdimension_ilp.rs b/src/rules/minimummetricdimension_ilp.rs index adccd107e..3238cfdba 100644 --- a/src/rules/minimummetricdimension_ilp.rs +++ b/src/rules/minimummetricdimension_ilp.rs @@ -7,9 +7,9 @@ //! (at least one resolving vertex distinguishes u from v) //! - Objective: Minimize Σ z_v -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; -use crate::models::graph::minimum_metric_dimension::bfs_distances; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::MinimumMetricDimension; +use crate::models::graph::minimum_metric_dimension::bfs_distances; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::{Graph, SimpleGraph}; diff --git a/src/rules/minimummultiwaycut_ilp.rs b/src/rules/minimummultiwaycut_ilp.rs index 3d2c45700..c084bfaca 100644 --- a/src/rules/minimummultiwaycut_ilp.rs +++ b/src/rules/minimummultiwaycut_ilp.rs @@ -6,7 +6,7 @@ //! - Constraints: partition (each vertex in exactly one component) + edge-cut linking //! - Objective: minimize total weight of cut edges -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::MinimumMultiwayCut; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/minimumsetcovering_ilp.rs b/src/rules/minimumsetcovering_ilp.rs index 0934f2809..2057db8bc 100644 --- a/src/rules/minimumsetcovering_ilp.rs +++ b/src/rules/minimumsetcovering_ilp.rs @@ -5,7 +5,7 @@ //! - Constraints: For each element e: sum_{j: e in set_j} x_j >= 1 (element must be covered) //! - Objective: Minimize the sum of weights of selected sets -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::set::MinimumSetCovering; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/minimumsummulticenter_ilp.rs b/src/rules/minimumsummulticenter_ilp.rs index 92ff18be2..ffd5b3fdf 100644 --- a/src/rules/minimumsummulticenter_ilp.rs +++ b/src/rules/minimumsummulticenter_ilp.rs @@ -20,7 +20,7 @@ //! Note: All-pairs shortest-path distances are computed using weighted shortest //! paths over `edge_lengths`. Unreachable assignment variables are forced to 0. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::MinimumSumMulticenter; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/minimumtardinesssequencing_ilp.rs b/src/rules/minimumtardinesssequencing_ilp.rs index fadd74d53..a1176778d 100644 --- a/src/rules/minimumtardinesssequencing_ilp.rs +++ b/src/rules/minimumtardinesssequencing_ilp.rs @@ -4,7 +4,7 @@ //! with binary tardy indicator u_j. Precedence constraints and a //! length-aware tardy indicator with big-M linearization. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::MinimumTardinessSequencing; use crate::reduction; use crate::rules::ilp_helpers::one_hot_decode; diff --git a/src/rules/minimumtardinesssequencing_qubo.rs b/src/rules/minimumtardinesssequencing_qubo.rs index 3d58b15a4..ecbbe7889 100644 --- a/src/rules/minimumtardinesssequencing_qubo.rs +++ b/src/rules/minimumtardinesssequencing_qubo.rs @@ -1,7 +1,7 @@ //! Direct quadratic encoding of MinimumTardinessSequencing. use crate::models::algebraic::QUBO; use crate::models::misc::MinimumTardinessSequencing; -use crate::rules::qubo_helpers::{decode_rows, invert_permutation, ObjectiveEncoding, QuboBuilder}; +use crate::rules::qubo_helpers::{ObjectiveEncoding, QuboBuilder, decode_rows, invert_permutation}; use crate::rules::{ExtractionResult, ReduceTo, ReductionError, ReductionResult}; use crate::types::Min; use crate::types::One; diff --git a/src/rules/minimumvertexcover_casts.rs b/src/rules/minimumvertexcover_casts.rs index edfb7a254..9b7195ea6 100644 --- a/src/rules/minimumvertexcover_casts.rs +++ b/src/rules/minimumvertexcover_casts.rs @@ -1,8 +1,8 @@ //! Variant reductions for MinimumVertexCover. use crate::impl_variant_reduction; -use crate::models::graph::MinimumVertexCover; use crate::models::Decision; +use crate::models::graph::MinimumVertexCover; use crate::rules::{ReduceTo, ReductionResult}; use crate::topology::SimpleGraph; use crate::types::One; diff --git a/src/rules/minimumweightandorgraph_ilp.rs b/src/rules/minimumweightandorgraph_ilp.rs index ad633e089..11cddf556 100644 --- a/src/rules/minimumweightandorgraph_ilp.rs +++ b/src/rules/minimumweightandorgraph_ilp.rs @@ -1,5 +1,5 @@ //! Gate selection and source reachability, including shared or cyclic subgraphs. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::misc::MinimumWeightAndOrGraph; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/minimumweightdecoding_ilp.rs b/src/rules/minimumweightdecoding_ilp.rs index 3095d56ce..272294040 100644 --- a/src/rules/minimumweightdecoding_ilp.rs +++ b/src/rules/minimumweightdecoding_ilp.rs @@ -16,7 +16,7 @@ //! Objective: minimize Σ x_j (Hamming weight). use crate::models::algebraic::MinimumWeightDecoding; -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/minmaxmulticenter_ilp.rs b/src/rules/minmaxmulticenter_ilp.rs index 98084546a..9211e3518 100644 --- a/src/rules/minmaxmulticenter_ilp.rs +++ b/src/rules/minmaxmulticenter_ilp.rs @@ -24,7 +24,7 @@ //! Note: All-pairs shortest-path distances are computed using weighted shortest //! paths over `edge_lengths`. Unreachable assignment variables are forced to 0. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::MinMaxMulticenter; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/mixedchinesepostman_ilp.rs b/src/rules/mixedchinesepostman_ilp.rs index 3ccb23ed6..1cc573c3e 100644 --- a/src/rules/mixedchinesepostman_ilp.rs +++ b/src/rules/mixedchinesepostman_ilp.rs @@ -5,7 +5,7 @@ //! within the length bound. Uses connectivity flow constraints on both //! forward and reverse directions. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::MixedChinesePostman; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/mod.rs b/src/rules/mod.rs index 8493fdf52..7606f4923 100644 --- a/src/rules/mod.rs +++ b/src/rules/mod.rs @@ -42,7 +42,7 @@ mod graph; pub(crate) mod minimumweightandorgraph_ilp; pub(crate) mod partitionintoperfectmatchings_ilp; pub(crate) mod twodimensionalconsecutivesets_ilp; -pub(crate) use graph::{recover_completed_result, RecoveryStep}; +pub(crate) use graph::{RecoveryStep, recover_completed_result}; mod binpacking_casts; mod comparativecontainment_casts; pub(crate) mod graph_helpers; @@ -327,11 +327,11 @@ pub use graph::{ PathParameterError, ReductionChain, ReductionEdgeInfo, ReductionGraph, ReductionMode, ReductionPath, ReductionStep, TraversalFlow, }; -pub(crate) use traits::{validate_target_solution, DynReductionResult}; pub use traits::{ AggregateReductionResult, ExtractionError, ExtractionResult, ReduceTo, ReduceToAggregate, ReductionError, ReductionResult, VariantReductionResult, }; +pub(crate) use traits::{DynReductionResult, validate_target_solution}; #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { diff --git a/src/rules/monochromatictriangle_ilp.rs b/src/rules/monochromatictriangle_ilp.rs index 576f62c50..e79973b2d 100644 --- a/src/rules/monochromatictriangle_ilp.rs +++ b/src/rules/monochromatictriangle_ilp.rs @@ -4,7 +4,7 @@ //! encoded as the pair of inequalities `1 <= sum <= 2` over its three incident //! edge variables. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::MonochromaticTriangle; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/multiplechoicebranching_ilp.rs b/src/rules/multiplechoicebranching_ilp.rs index 8cf2df39b..401c00883 100644 --- a/src/rules/multiplechoicebranching_ilp.rs +++ b/src/rules/multiplechoicebranching_ilp.rs @@ -1,6 +1,6 @@ //! Reduction from MultipleChoiceBranching with integer weights to integer ILP. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::MultipleChoiceBranching; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/multiplecopyfileallocation_ilp.rs b/src/rules/multiplecopyfileallocation_ilp.rs index 04ee17e15..6689fce42 100644 --- a/src/rules/multiplecopyfileallocation_ilp.rs +++ b/src/rules/multiplecopyfileallocation_ilp.rs @@ -14,7 +14,7 @@ //! Objective: minimize Σ_v s(v)·x_v + Σ_{v,u} u(v)·d(v,u)·y_{v,u}. //! Extraction: first n variables (x_v). -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::MultipleCopyFileAllocation; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/multiprocessorscheduling_ilp.rs b/src/rules/multiprocessorscheduling_ilp.rs index 85b4a5135..a2c8afe8a 100644 --- a/src/rules/multiprocessorscheduling_ilp.rs +++ b/src/rules/multiprocessorscheduling_ilp.rs @@ -6,7 +6,7 @@ //! - Objective: Minimize 0 (feasibility) //! - Extraction: argmax_p x_{j,p} for each task j -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::MultiprocessorScheduling; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/naesatisfiability_ilp.rs b/src/rules/naesatisfiability_ilp.rs index df8495f5e..071e5ae2f 100644 --- a/src/rules/naesatisfiability_ilp.rs +++ b/src/rules/naesatisfiability_ilp.rs @@ -8,7 +8,7 @@ //! //! Objective: empty (feasibility problem). -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::formula::NAESatisfiability; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/numericalmatchingwithtargetsums_ilp.rs b/src/rules/numericalmatchingwithtargetsums_ilp.rs index 45cff4eb0..3b6b2cce2 100644 --- a/src/rules/numericalmatchingwithtargetsums_ilp.rs +++ b/src/rules/numericalmatchingwithtargetsums_ilp.rs @@ -11,7 +11,7 @@ //! //! Objective: minimize 0 (feasibility). -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::NumericalMatchingWithTargetSums; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/oneinthreesatisfiability_ilp.rs b/src/rules/oneinthreesatisfiability_ilp.rs index 31c530181..75c5a83a3 100644 --- a/src/rules/oneinthreesatisfiability_ilp.rs +++ b/src/rules/oneinthreesatisfiability_ilp.rs @@ -1,6 +1,6 @@ //! One binary variable per SAT variable and one equality per exact-one clause. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::formula::OneInThreeSatisfiability; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/openshopscheduling_ilp.rs b/src/rules/openshopscheduling_ilp.rs index c38aab5ef..5a423ff9d 100644 --- a/src/rules/openshopscheduling_ilp.rs +++ b/src/rules/openshopscheduling_ilp.rs @@ -1,7 +1,7 @@ //! Bounded disjunctive open-shop scheduling with identical-machine symmetry. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; -use crate::models::misc::OpenShopScheduling; use crate::models::Decision; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; +use crate::models::misc::OpenShopScheduling; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/optimallineararrangement_ilp.rs b/src/rules/optimallineararrangement_ilp.rs index a1e87a307..a44c5b0a0 100644 --- a/src/rules/optimallineararrangement_ilp.rs +++ b/src/rules/optimallineararrangement_ilp.rs @@ -7,7 +7,7 @@ //! - abs_diff_le constraints: z_{u,v} >= p_u - p_v, z_{u,v} >= p_v - p_u //! - Minimize: sum z_{u,v} -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::OptimalLinearArrangement; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/optimallineararrangement_qubo.rs b/src/rules/optimallineararrangement_qubo.rs index 15d2e93a3..473b3e23b 100644 --- a/src/rules/optimallineararrangement_qubo.rs +++ b/src/rules/optimallineararrangement_qubo.rs @@ -1,7 +1,7 @@ //! Tournament comparisons encode the vertices between each edge's endpoints. use crate::models::algebraic::QUBO; use crate::models::graph::OptimalLinearArrangement; -use crate::rules::qubo_helpers::{pair_index, tournament_ranks, ObjectiveEncoding, QuboBuilder}; +use crate::rules::qubo_helpers::{ObjectiveEncoding, QuboBuilder, pair_index, tournament_ranks}; use crate::rules::{ExtractionResult, ReduceTo, ReductionError, ReductionResult}; use crate::topology::{Graph, SimpleGraph}; use crate::types::Min; diff --git a/src/rules/optimumcommunicationspanningtree_ilp.rs b/src/rules/optimumcommunicationspanningtree_ilp.rs index 3a6c2b9c3..391593b03 100644 --- a/src/rules/optimumcommunicationspanningtree_ilp.rs +++ b/src/rules/optimumcommunicationspanningtree_ilp.rs @@ -7,7 +7,7 @@ //! - Tree constraints: sum x_e = n-1, and connectivity via flow conservation //! - Objective: minimize sum_{(u,v): r>0} r(u,v) * w(e) * (flow_uv(e->dir) + flow_uv(e<-dir)) -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::OptimumCommunicationSpanningTree; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/paintshop_ilp.rs b/src/rules/paintshop_ilp.rs index 0907a656e..c194f3845 100644 --- a/src/rules/paintshop_ilp.rs +++ b/src/rules/paintshop_ilp.rs @@ -4,7 +4,7 @@ //! sequence position (actual color), binary c_p per adjacent pair (switch //! indicator). Minimize Σ c_p. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::PaintShop; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/partiallyorderedknapsack_ilp.rs b/src/rules/partiallyorderedknapsack_ilp.rs index 1c82dd84a..0ddbefefd 100644 --- a/src/rules/partiallyorderedknapsack_ilp.rs +++ b/src/rules/partiallyorderedknapsack_ilp.rs @@ -3,7 +3,7 @@ //! Binary variable x_i per item. Capacity constraint Σ w_i·x_i ≤ C. //! Precedence constraints: ∀ (a,b): x_b ≤ x_a. Maximize Σ v_i·x_i. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::PartiallyOrderedKnapsack; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/partitionintocliques_ilp.rs b/src/rules/partitionintocliques_ilp.rs index 6b504241e..0da4d7f9c 100644 --- a/src/rules/partitionintocliques_ilp.rs +++ b/src/rules/partitionintocliques_ilp.rs @@ -1,6 +1,6 @@ //! Reduction from PartitionIntoCliques to binary ILP. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::PartitionIntoCliques; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/partitionintopathsoflength2_ilp.rs b/src/rules/partitionintopathsoflength2_ilp.rs index 16d7b7a1c..6a05c6a9b 100644 --- a/src/rules/partitionintopathsoflength2_ilp.rs +++ b/src/rules/partitionintopathsoflength2_ilp.rs @@ -16,7 +16,7 @@ //! //! Objective: Minimize 0 (feasibility) -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::PartitionIntoPathsOfLength2; use crate::reduction; use crate::rules::ilp_helpers::mccormick_product; diff --git a/src/rules/partitionintoperfectmatchings_ilp.rs b/src/rules/partitionintoperfectmatchings_ilp.rs index 80e09cb58..7ec3507b5 100644 --- a/src/rules/partitionintoperfectmatchings_ilp.rs +++ b/src/rules/partitionintoperfectmatchings_ilp.rs @@ -1,5 +1,5 @@ //! Group labels with exact same-group edge indicators and degree one. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::PartitionIntoPerfectMatchings; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::topology::{Graph, SimpleGraph}; diff --git a/src/rules/partitionintotriangles_ilp.rs b/src/rules/partitionintotriangles_ilp.rs index 379b21e33..9fea51395 100644 --- a/src/rules/partitionintotriangles_ilp.rs +++ b/src/rules/partitionintotriangles_ilp.rs @@ -9,7 +9,7 @@ //! - Objective: Minimize 0 (feasibility) //! - Extraction: argmax_g x_{v,g} for each vertex v -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::PartitionIntoTriangles; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/pathconstrainednetworkflow_ilp.rs b/src/rules/pathconstrainednetworkflow_ilp.rs index ac6687f4f..62b6967ec 100644 --- a/src/rules/pathconstrainednetworkflow_ilp.rs +++ b/src/rules/pathconstrainednetworkflow_ilp.rs @@ -3,7 +3,7 @@ //! One integer variable per prescribed path. Arc capacity aggregation //! across paths and total flow requirement. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::PathConstrainedNetworkFlow; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/precedenceconstrainedscheduling_ilp.rs b/src/rules/precedenceconstrainedscheduling_ilp.rs index 08c9a7729..f711944f4 100644 --- a/src/rules/precedenceconstrainedscheduling_ilp.rs +++ b/src/rules/precedenceconstrainedscheduling_ilp.rs @@ -10,7 +10,7 @@ //! - Objective: Minimize 0 (feasibility) //! - Extraction: For each task j, find argmax_t x_{j,t} -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::PrecedenceConstrainedScheduling; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/preemptivescheduling_ilp.rs b/src/rules/preemptivescheduling_ilp.rs index 4eca26882..992477de6 100644 --- a/src/rules/preemptivescheduling_ilp.rs +++ b/src/rules/preemptivescheduling_ilp.rs @@ -9,7 +9,7 @@ //! precedence edge: the matrix has 6*A + 2*p + 2*n nonzeros for A admissible //! activity slots, p precedence edges, and n tasks. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::misc::PreemptiveScheduling; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/prizecollectingsteinerforest_casts.rs b/src/rules/prizecollectingsteinerforest_casts.rs index d90c7d6ab..9a3162e14 100644 --- a/src/rules/prizecollectingsteinerforest_casts.rs +++ b/src/rules/prizecollectingsteinerforest_casts.rs @@ -2,7 +2,7 @@ use crate::impl_variant_reduction; use crate::models::graph::PrizeCollectingSteinerForest; -use crate::rules::{weight_casts::exact_float_weights, ReductionError}; +use crate::rules::{ReductionError, weight_casts::exact_float_weights}; use crate::topology::SimpleGraph; use crate::types::i64_to_exact_f64; diff --git a/src/rules/productionplanning_ilp.rs b/src/rules/productionplanning_ilp.rs index cd673c3d1..a131c3e92 100644 --- a/src/rules/productionplanning_ilp.rs +++ b/src/rules/productionplanning_ilp.rs @@ -1,5 +1,5 @@ //! Inventory conservation with exact production setup indicators. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::misc::ProductionPlanning; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/quadraticassignment_ilp.rs b/src/rules/quadraticassignment_ilp.rs index b0fcf4e74..1792f62fb 100644 --- a/src/rules/quadraticassignment_ilp.rs +++ b/src/rules/quadraticassignment_ilp.rs @@ -8,7 +8,7 @@ //! - Objective: minimize sum_{i!=j} C[i][j] * D[p][q] * z_{(i,p),(j,q)} use crate::models::algebraic::QuadraticAssignment; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::reduction; use crate::rules::ilp_helpers::{mccormick_product, one_hot_assignment_constraints}; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/quadraticassignment_qubo.rs b/src/rules/quadraticassignment_qubo.rs index b1487cb1e..beb12801a 100644 --- a/src/rules/quadraticassignment_qubo.rs +++ b/src/rules/quadraticassignment_qubo.rs @@ -1,7 +1,7 @@ //! Direct quadratic encoding of QuadraticAssignment. -use crate::models::algebraic::QuadraticAssignment; use crate::models::algebraic::QUBO; -use crate::rules::qubo_helpers::{decode_rows, ObjectiveEncoding, QuboBuilder}; +use crate::models::algebraic::QuadraticAssignment; +use crate::rules::qubo_helpers::{ObjectiveEncoding, QuboBuilder, decode_rows}; use crate::rules::{ExtractionResult, ReduceTo, ReductionError, ReductionResult}; use crate::types::Min; diff --git a/src/rules/qubo_ilp.rs b/src/rules/qubo_ilp.rs index fd67288ee..d7e4c6990 100644 --- a/src/rules/qubo_ilp.rs +++ b/src/rules/qubo_ilp.rs @@ -14,7 +14,7 @@ //! ## Objective //! minimize Σ_i Q_ii · x_i + Σ_{i> for RectilinearPictureCompression { let terms: Vec<(usize, i64)> = rects .iter() .enumerate() - .filter(|(_, &(r1, c1, r2, c2))| i >= r1 && i <= r2 && j >= c1 && j <= c2) + .filter(|&(_, &(r1, c1, r2, c2))| i >= r1 && i <= r2 && j >= c1 && j <= c2) .map(|(idx, _)| (idx, 1)) .collect(); constraints.push(LinearConstraint::ge(terms, 1)); diff --git a/src/rules/registersufficiency_ilp.rs b/src/rules/registersufficiency_ilp.rs index 4e6f6dee5..c16e11d39 100644 --- a/src/rules/registersufficiency_ilp.rs +++ b/src/rules/registersufficiency_ilp.rs @@ -1,6 +1,6 @@ //! Binary cumulative evaluation and live-value indicators for register sufficiency. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::RegisterSufficiency; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/resourceconstrainedscheduling_ilp.rs b/src/rules/resourceconstrainedscheduling_ilp.rs index 00ca83439..7475ec234 100644 --- a/src/rules/resourceconstrainedscheduling_ilp.rs +++ b/src/rules/resourceconstrainedscheduling_ilp.rs @@ -4,7 +4,7 @@ //! Each task in exactly one slot; processor capacity and resource bounds //! enforced per time slot. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::ResourceConstrainedScheduling; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/rootedtreestorageassignment_ilp.rs b/src/rules/rootedtreestorageassignment_ilp.rs index 36339e95e..19ed11f1f 100644 --- a/src/rules/rootedtreestorageassignment_ilp.rs +++ b/src/rules/rootedtreestorageassignment_ilp.rs @@ -4,7 +4,7 @@ //! a_{u,v}, transitive-closure helpers h_{u,v,w}, and per-subset gadgets //! (top/bottom selectors, pair selectors, endpoint depths, extension costs). -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::set::RootedTreeStorageAssignment; use crate::reduction; use crate::rules::ilp_helpers::{mccormick_product, one_hot_decode_rows}; diff --git a/src/rules/ruralpostman_ilp.rs b/src/rules/ruralpostman_ilp.rs index 7063b1dd7..c3da23a3c 100644 --- a/src/rules/ruralpostman_ilp.rs +++ b/src/rules/ruralpostman_ilp.rs @@ -4,7 +4,7 @@ //! connectivity flow constraints to encode an Eulerian connected subgraph //! covering all required edges within the length bound. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::RuralPostman; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/sat_ksat.rs b/src/rules/sat_ksat.rs index fc8411a5b..0f2d98ebe 100644 --- a/src/rules/sat_ksat.rs +++ b/src/rules/sat_ksat.rs @@ -10,7 +10,7 @@ use crate::models::formula::{CNFClause, KSatisfiability, Satisfiability}; use crate::reduction; use crate::rules::sat_helpers::SatVariableAllocator; use crate::rules::traits::{ReduceTo, ReductionResult}; -use crate::variant::{KValue, K2, K3}; +use crate::variant::{K2, K3, KValue}; /// Result of reducing general SAT to K-SAT. /// diff --git a/src/rules/schedulingtominimizeweightedcompletiontime_ilp.rs b/src/rules/schedulingtominimizeweightedcompletiontime_ilp.rs index acdb2f8f7..5af4a2170 100644 --- a/src/rules/schedulingtominimizeweightedcompletiontime_ilp.rs +++ b/src/rules/schedulingtominimizeweightedcompletiontime_ilp.rs @@ -5,7 +5,7 @@ //! ordering variables `y_{i,j}` for each task pair. Big-M constraints //! enforce that tasks sharing a processor do not overlap. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::misc::SchedulingToMinimizeWeightedCompletionTime; use crate::reduction; use crate::rules::ilp_helpers::one_hot_decode_rows; diff --git a/src/rules/schedulingwithindividualdeadlines_ilp.rs b/src/rules/schedulingwithindividualdeadlines_ilp.rs index 736076efa..39c4ef077 100644 --- a/src/rules/schedulingwithindividualdeadlines_ilp.rs +++ b/src/rules/schedulingwithindividualdeadlines_ilp.rs @@ -11,7 +11,7 @@ //! 4. Precedence: Σ_t t·x_{j,t} ≥ Σ_t t·x_{i,t} + 1 for each (i,j) //! - Objective: Minimize 0 (feasibility) -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::SchedulingWithIndividualDeadlines; use crate::reduction; use crate::rules::ilp_helpers::one_hot_decode_rows; diff --git a/src/rules/sequencingtominimizemaximumcumulativecost_ilp.rs b/src/rules/sequencingtominimizemaximumcumulativecost_ilp.rs index 3a3168180..af69d65ec 100644 --- a/src/rules/sequencingtominimizemaximumcumulativecost_ilp.rs +++ b/src/rules/sequencingtominimizemaximumcumulativecost_ilp.rs @@ -4,7 +4,7 @@ //! Permutation constraints, precedence constraints, and prefix cumulative-cost //! bounds at every position. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::misc::SequencingToMinimizeMaximumCumulativeCost; use crate::reduction; use crate::rules::ilp_helpers::one_hot_decode; diff --git a/src/rules/sequencingtominimizetardytaskweight_ilp.rs b/src/rules/sequencingtominimizetardytaskweight_ilp.rs index 235100e45..cc1049ec2 100644 --- a/src/rules/sequencingtominimizetardytaskweight_ilp.rs +++ b/src/rules/sequencingtominimizetardytaskweight_ilp.rs @@ -4,7 +4,7 @@ //! with exact binary tardy indicators. Position-specific prefix bounds give //! both implications of the deadline comparison, including signed model inputs. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::SequencingToMinimizeTardyTaskWeight; use crate::reduction; use crate::rules::ilp_helpers::one_hot_decode; diff --git a/src/rules/sequencingtominimizeweightedcompletiontime_ilp.rs b/src/rules/sequencingtominimizeweightedcompletiontime_ilp.rs index d847f6d3c..a1e8c8d30 100644 --- a/src/rules/sequencingtominimizeweightedcompletiontime_ilp.rs +++ b/src/rules/sequencingtominimizeweightedcompletiontime_ilp.rs @@ -1,7 +1,7 @@ //! Strict linear ordering with exact signed completion-time equations. //! Triangle inequalities rule out cyclic orders even for zero-duration jobs. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::misc::SequencingToMinimizeWeightedCompletionTime; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/sequencingtominimizeweightedcompletiontime_qubo.rs b/src/rules/sequencingtominimizeweightedcompletiontime_qubo.rs index 42bb858c3..ccad4ee28 100644 --- a/src/rules/sequencingtominimizeweightedcompletiontime_qubo.rs +++ b/src/rules/sequencingtominimizeweightedcompletiontime_qubo.rs @@ -2,7 +2,7 @@ use crate::models::algebraic::QUBO; use crate::models::misc::SequencingToMinimizeWeightedCompletionTime; use crate::rules::qubo_helpers::{ - invert_permutation, pair_index, tournament_ranks, ObjectiveEncoding, QuboBuilder, + ObjectiveEncoding, QuboBuilder, invert_permutation, pair_index, tournament_ranks, }; use crate::rules::{ExtractionResult, ReduceTo, ReductionError, ReductionResult}; use crate::types::Min; diff --git a/src/rules/sequencingtominimizeweightedtardiness_ilp.rs b/src/rules/sequencingtominimizeweightedtardiness_ilp.rs index 8ae908e7b..a4eac23b2 100644 --- a/src/rules/sequencingtominimizeweightedtardiness_ilp.rs +++ b/src/rules/sequencingtominimizeweightedtardiness_ilp.rs @@ -4,7 +4,7 @@ //! and nonnegative tardiness variables T_j. Big-M disjunctive constraints //! force a single-machine order; the weighted tardiness sum is bounded by K. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::misc::SequencingToMinimizeWeightedTardiness; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/sequencingwithdeadlinesandsetuptimes_ilp.rs b/src/rules/sequencingwithdeadlinesandsetuptimes_ilp.rs index e8ca8cbb0..6cc78c9b0 100644 --- a/src/rules/sequencingwithdeadlinesandsetuptimes_ilp.rs +++ b/src/rules/sequencingwithdeadlinesandsetuptimes_ilp.rs @@ -15,7 +15,7 @@ //! Deadline enforcement uses the standard big-M trick: for each (j, p), //! if `x_{j,p}=1` then the completion time at p must not exceed `d[j]`. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::SequencingWithDeadlinesAndSetUpTimes; use crate::reduction; use crate::rules::ilp_helpers::one_hot_decode; diff --git a/src/rules/sequencingwithinintervals_ilp.rs b/src/rules/sequencingwithinintervals_ilp.rs index 5e910e627..23fa089e5 100644 --- a/src/rules/sequencingwithinintervals_ilp.rs +++ b/src/rules/sequencingwithinintervals_ilp.rs @@ -15,7 +15,7 @@ //! - Objective: Minimize 0 (feasibility) //! - Extraction: For task j, find offset k where x_{j,k}=1; config[j] = k. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::SequencingWithinIntervals; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/sequencingwithinintervals_qubo.rs b/src/rules/sequencingwithinintervals_qubo.rs index 545950845..fceea6b6a 100644 --- a/src/rules/sequencingwithinintervals_qubo.rs +++ b/src/rules/sequencingwithinintervals_qubo.rs @@ -2,7 +2,7 @@ use crate::models::algebraic::QUBO; use crate::models::decision::Decision; use crate::models::misc::SequencingWithinIntervals; -use crate::rules::qubo_helpers::{decode_rows, QuboBuilder}; +use crate::rules::qubo_helpers::{QuboBuilder, decode_rows}; use crate::rules::traits::validate_target_witness; use crate::rules::{ExtractionResult, ReduceTo, ReductionError, ReductionResult}; diff --git a/src/rules/sequencingwithreleasetimesanddeadlines_ilp.rs b/src/rules/sequencingwithreleasetimesanddeadlines_ilp.rs index e9d9541db..1282d7390 100644 --- a/src/rules/sequencingwithreleasetimesanddeadlines_ilp.rs +++ b/src/rules/sequencingwithreleasetimesanddeadlines_ilp.rs @@ -2,7 +2,7 @@ //! The binary endpoint uniformly composes the same construction with the //! existing bounded-integer encoding; neither construction expands time slots. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::misc::SequencingWithReleaseTimesAndDeadlines; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; @@ -154,7 +154,7 @@ impl ReduceTo> for SequencingWithReleaseTimesAndDeadlines { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { use crate::example_db::specs::{ - rule_example_via_bounded_ilp, rule_example_via_ilp, RuleExampleSpec, + RuleExampleSpec, rule_example_via_bounded_ilp, rule_example_via_ilp, }; fn source() -> SequencingWithReleaseTimesAndDeadlines { SequencingWithReleaseTimesAndDeadlines::new(vec![1, 2, 1], vec![0, 0, 2], vec![3, 3, 4]) diff --git a/src/rules/setsplitting_ilp.rs b/src/rules/setsplitting_ilp.rs index e7fc89213..5cdfdc5ff 100644 --- a/src/rules/setsplitting_ilp.rs +++ b/src/rules/setsplitting_ilp.rs @@ -9,7 +9,7 @@ //! //! Objective: feasibility (minimize 0). -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::set::SetSplitting; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/shortestcommonsupersequence_ilp.rs b/src/rules/shortestcommonsupersequence_ilp.rs index 4f8e4fd27..61bce4a28 100644 --- a/src/rules/shortestcommonsupersequence_ilp.rs +++ b/src/rules/shortestcommonsupersequence_ilp.rs @@ -5,7 +5,7 @@ //! is matched to position p. Monotonicity forces strictly increasing match //! positions per string. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::ShortestCommonSupersequence; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/shortestcommonsuperstring_qubo.rs b/src/rules/shortestcommonsuperstring_qubo.rs index 2bcfab314..eabc57e23 100644 --- a/src/rules/shortestcommonsuperstring_qubo.rs +++ b/src/rules/shortestcommonsuperstring_qubo.rs @@ -1,8 +1,8 @@ //! Direct exact quadratic encoding of ShortestCommonSuperstring. use crate::models::algebraic::QUBO; use crate::models::misc::ShortestCommonSuperstring; -use crate::rules::qubo_helpers::{decode_rows, invert_permutation}; use crate::rules::qubo_helpers::{ObjectiveEncoding, QuboBuilder}; +use crate::rules::qubo_helpers::{decode_rows, invert_permutation}; use crate::rules::{ExtractionResult, ReduceTo, ReductionError, ReductionResult}; use crate::types::Min; #[derive(Debug, Clone)] diff --git a/src/rules/shortestweightconstrainedpath_ilp.rs b/src/rules/shortestweightconstrainedpath_ilp.rs index 5e17fb2d3..31312a920 100644 --- a/src/rules/shortestweightconstrainedpath_ilp.rs +++ b/src/rules/shortestweightconstrainedpath_ilp.rs @@ -6,7 +6,7 @@ //! bound constraint enforces the weight limit, and the objective minimizes //! total path length. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::ShortestWeightConstrainedPath; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/sparsematrixcompression_ilp.rs b/src/rules/sparsematrixcompression_ilp.rs index fcdc44d46..aa0d9044c 100644 --- a/src/rules/sparsematrixcompression_ilp.rs +++ b/src/rules/sparsematrixcompression_ilp.rs @@ -3,7 +3,7 @@ //! Assign each row one shift value and forbid any pair of shifted 1-entries //! from colliding in the storage vector. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, SparseMatrixCompression, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense, SparseMatrixCompression}; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/stackercrane_ilp.rs b/src/rules/stackercrane_ilp.rs index 0cb0a289b..dd9403076 100644 --- a/src/rules/stackercrane_ilp.rs +++ b/src/rules/stackercrane_ilp.rs @@ -4,7 +4,7 @@ //! for consecutive-pair costs. Uses precomputed shortest-path connector //! distances. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::StackerCrane; use crate::reduction; use crate::rules::ilp_helpers::{mccormick_product, one_hot_decode}; diff --git a/src/rules/stackercrane_qubo.rs b/src/rules/stackercrane_qubo.rs index 1bc3517c9..354024782 100644 --- a/src/rules/stackercrane_qubo.rs +++ b/src/rules/stackercrane_qubo.rs @@ -1,8 +1,8 @@ //! Direct exact quadratic encoding of StackerCrane. use crate::models::algebraic::QUBO; use crate::models::misc::StackerCrane; -use crate::rules::qubo_helpers::{decode_rows, invert_permutation}; use crate::rules::qubo_helpers::{ObjectiveEncoding, QuboBuilder}; +use crate::rules::qubo_helpers::{decode_rows, invert_permutation}; use crate::rules::{ExtractionResult, ReduceTo, ReductionError, ReductionResult}; use crate::types::Min; #[derive(Debug, Clone)] diff --git a/src/rules/staffscheduling_qubo.rs b/src/rules/staffscheduling_qubo.rs index a489eac4e..3d8932b88 100644 --- a/src/rules/staffscheduling_qubo.rs +++ b/src/rules/staffscheduling_qubo.rs @@ -1,5 +1,5 @@ //! Bounded worker multiplicities with exact budget and coverage residuals. -use crate::models::{algebraic::QUBO, misc::StaffScheduling, Decision}; +use crate::models::{Decision, algebraic::QUBO, misc::StaffScheduling}; use crate::rules::ilp_i64_ilp_bool::binary_weights; use crate::rules::qubo_helpers::QuboBuilder; use crate::rules::traits::validate_target_witness; diff --git a/src/rules/start_time_qubo.rs b/src/rules/start_time_qubo.rs index 15ead9edb..5b82c4120 100644 --- a/src/rules/start_time_qubo.rs +++ b/src/rules/start_time_qubo.rs @@ -1,7 +1,7 @@ //! Shared one-hot starts for nonnegative-duration schedules. -use super::qubo_helpers::{decode_rows, QuboBuilder}; -use crate::rules::{ExtractionResult, ReductionError}; +use super::qubo_helpers::{QuboBuilder, decode_rows}; use crate::Problem; +use crate::rules::{ExtractionResult, ReductionError}; #[derive(Debug, Clone)] pub(super) struct StartChoices { diff --git a/src/rules/steinertree_ilp.rs b/src/rules/steinertree_ilp.rs index 813a5b3fd..6e0a2c45e 100644 --- a/src/rules/steinertree_ilp.rs +++ b/src/rules/steinertree_ilp.rs @@ -4,7 +4,7 @@ //! Endpoint linking and |selected edges| = |selected vertices| - 1 then enforce //! a tree, independently of the objective's signs. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::SteinerTree; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/stringtostringcorrection_ilp.rs b/src/rules/stringtostringcorrection_ilp.rs index a3721dcad..9bc18ef20 100644 --- a/src/rules/stringtostringcorrection_ilp.rs +++ b/src/rules/stringtostringcorrection_ilp.rs @@ -4,7 +4,7 @@ //! emptiness bits e_{t,p}, and operation selectors (delete, swap, no-op) at //! each of K stages. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::StringToStringCorrection; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; @@ -98,12 +98,12 @@ impl ReductionResult for ReductionSTSCToILP { [] => { return Err(crate::rules::ExtractionError::invalid(format!( "edit step {t} has no selected operation" - ))) + ))); } _ => { return Err(crate::rules::ExtractionError::invalid(format!( "edit step {t} has multiple selected operations" - ))) + ))); } } } diff --git a/src/rules/strongconnectivityaugmentation_ilp.rs b/src/rules/strongconnectivityaugmentation_ilp.rs index 6167cc537..cd9a462ff 100644 --- a/src/rules/strongconnectivityaugmentation_ilp.rs +++ b/src/rules/strongconnectivityaugmentation_ilp.rs @@ -4,7 +4,7 @@ //! sending flow both from a root to every vertex and back again. //! See the paper entry for the full formulation. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::StrongConnectivityAugmentation; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/subgraphisomorphism_ilp.rs b/src/rules/subgraphisomorphism_ilp.rs index b8c2c647d..9b34eb04e 100644 --- a/src/rules/subgraphisomorphism_ilp.rs +++ b/src/rules/subgraphisomorphism_ilp.rs @@ -7,7 +7,7 @@ //! - Non-edge forbiddance: for each pattern edge {v,w} and each host non-edge {u,u'}, //! x_{v,u} + x_{w,u'} <= 1 AND x_{v,u'} + x_{w,u} <= 1 -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::SubgraphIsomorphism; use crate::reduction; use crate::rules::ilp_helpers::{one_hot_assignment_constraints, one_hot_decode_rows}; diff --git a/src/rules/sumofsquarespartition_ilp.rs b/src/rules/sumofsquarespartition_ilp.rs index b1dd7b7c5..c3542216b 100644 --- a/src/rules/sumofsquarespartition_ilp.rs +++ b/src/rules/sumofsquarespartition_ilp.rs @@ -16,7 +16,7 @@ //! //! Objective: Minimize Σ_g Σ_{i,j} s_i * s_j * z_{i,j,g} -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::SumOfSquaresPartition; use crate::reduction; use crate::rules::ilp_helpers::mccormick_product; diff --git a/src/rules/sumofsquarespartition_qubo.rs b/src/rules/sumofsquarespartition_qubo.rs index 4b6f258aa..00a9dc974 100644 --- a/src/rules/sumofsquarespartition_qubo.rs +++ b/src/rules/sumofsquarespartition_qubo.rs @@ -1,7 +1,7 @@ //! Direct quadratic encoding of SumOfSquaresPartition. use crate::models::algebraic::QUBO; use crate::models::misc::SumOfSquaresPartition; -use crate::rules::qubo_helpers::{decode_rows, ObjectiveEncoding, QuboBuilder}; +use crate::rules::qubo_helpers::{ObjectiveEncoding, QuboBuilder, decode_rows}; use crate::rules::{ExtractionResult, ReduceTo, ReductionError, ReductionResult}; use crate::types::Min; diff --git a/src/rules/threedimensionalmatching_ilp.rs b/src/rules/threedimensionalmatching_ilp.rs index 14f62f061..990a465b8 100644 --- a/src/rules/threedimensionalmatching_ilp.rs +++ b/src/rules/threedimensionalmatching_ilp.rs @@ -1,6 +1,6 @@ //! Reduction from ThreeDimensionalMatching to `ILP`. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::set::ThreeDimensionalMatching; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/threepartition_ilp.rs b/src/rules/threepartition_ilp.rs index 6f9c7e9fe..ff894a3c4 100644 --- a/src/rules/threepartition_ilp.rs +++ b/src/rules/threepartition_ilp.rs @@ -1,5 +1,5 @@ //! Exact cover of indexed items by triples whose sizes sum to the bound. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::ThreePartition; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/timetabledesign_ilp.rs b/src/rules/timetabledesign_ilp.rs index c444cb001..576d63394 100644 --- a/src/rules/timetabledesign_ilp.rs +++ b/src/rules/timetabledesign_ilp.rs @@ -4,7 +4,7 @@ //! and all feasibility conditions are already linear: availability forcing, //! per-period exclusivity, and exact pairwise work requirements. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::TimetableDesign; use crate::reduction; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/traits.rs b/src/rules/traits.rs index 2507bb4ed..2c72ee3a9 100644 --- a/src/rules/traits.rs +++ b/src/rules/traits.rs @@ -1,8 +1,8 @@ //! Core traits for problem reductions. use crate::traits::Problem; -use serde::de::DeserializeOwned; use serde::Serialize; +use serde::de::DeserializeOwned; use std::any::Any; use std::marker::PhantomData; diff --git a/src/rules/travelingsalesman_ilp.rs b/src/rules/travelingsalesman_ilp.rs index a51b5d233..36fff4ee3 100644 --- a/src/rules/travelingsalesman_ilp.rs +++ b/src/rules/travelingsalesman_ilp.rs @@ -5,7 +5,7 @@ //! - Constraints: assignment, non-edge consecutive, McCormick //! - Objective: minimize total edge weight of the tour -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::graph::TravelingSalesman; use crate::reduction; use crate::rules::ilp_helpers::{mccormick_product, one_hot_decode}; diff --git a/src/rules/twodimensionalconsecutivesets_ilp.rs b/src/rules/twodimensionalconsecutivesets_ilp.rs index e5a21f4d9..70fa2504a 100644 --- a/src/rules/twodimensionalconsecutivesets_ilp.rs +++ b/src/rules/twodimensionalconsecutivesets_ilp.rs @@ -1,6 +1,6 @@ //! Distinct labels within a subset occupy an interval of that subset's size. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::set::TwoDimensionalConsecutiveSets; use crate::rules::ilp_helpers::{bounded_order_comparison, decode_usize_values}; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/rules/undirectedflowlowerbounds_ilp.rs b/src/rules/undirectedflowlowerbounds_ilp.rs index 6c4c33046..6216635c4 100644 --- a/src/rules/undirectedflowlowerbounds_ilp.rs +++ b/src/rules/undirectedflowlowerbounds_ilp.rs @@ -23,7 +23,7 @@ //! //! Size upper bound: 3*|E| variables, 5*|E| + |V| + 1 constraints. -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::UndirectedFlowLowerBounds; use crate::reduction; use crate::rules::ilp_helpers::bounded_flow_requirement; diff --git a/src/rules/undirectedtwocommodityintegralflow_ilp.rs b/src/rules/undirectedtwocommodityintegralflow_ilp.rs index 1814b40f9..e8b236eb1 100644 --- a/src/rules/undirectedtwocommodityintegralflow_ilp.rs +++ b/src/rules/undirectedtwocommodityintegralflow_ilp.rs @@ -24,7 +24,7 @@ //! //! Constraints per edge (7 per edge) + flow conservation (2 per non-terminal vertex) + net flow (2) -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::models::graph::UndirectedTwoCommodityIntegralFlow; use crate::reduction; use crate::rules::ilp_helpers::bounded_flow_requirement; diff --git a/src/rules/unit_schedule_qubo.rs b/src/rules/unit_schedule_qubo.rs index d736963be..0f310c1da 100644 --- a/src/rules/unit_schedule_qubo.rs +++ b/src/rules/unit_schedule_qubo.rs @@ -1,7 +1,7 @@ //! Unit-task starts with exact capacities and pairwise precedence conflicts. -use crate::models::{algebraic::QUBO, decision::Decision}; -use crate::rules::{qubo_helpers::QuboBuilder, ReductionError}; use crate::Problem; +use crate::models::{algebraic::QUBO, decision::Decision}; +use crate::rules::{ReductionError, qubo_helpers::QuboBuilder}; pub(super) fn encode( deadlines: &[i64], diff --git a/src/rules/unitdiskmapping/copyline.rs b/src/rules/unitdiskmapping/copyline.rs index 059a86112..63618e99c 100644 --- a/src/rules/unitdiskmapping/copyline.rs +++ b/src/rules/unitdiskmapping/copyline.rs @@ -66,7 +66,7 @@ impl CopyLine { // Vertical segment: from vstart to vstop for v in self.vstart..=self.vstop { let row = spacing * (v - 1) + padding + 1; // 0-indexed - // Weight is 1 for regular positions + // Weight is 1 for regular positions locs.push((row, col, 1)); } @@ -74,7 +74,7 @@ impl CopyLine { let hrow = spacing * (self.hslot - 1) + padding + 1; // 0-indexed for h in (self.vslot + 1)..=self.hstop { let hcol = spacing * (h - 1) + padding; // 0-indexed - // Avoid duplicate at the corner (vslot, hslot) + // Avoid duplicate at the corner (vslot, hslot) if hcol != col || hrow != spacing * (self.hslot - 1) + padding + 1 { locs.push((hrow, hcol, 1)); } diff --git a/src/rules/unitdiskmapping/grid.rs b/src/rules/unitdiskmapping/grid.rs index d9031c880..3281a7995 100644 --- a/src/rules/unitdiskmapping/grid.rs +++ b/src/rules/unitdiskmapping/grid.rs @@ -146,11 +146,12 @@ impl MappingGrid { /// This matches that behavior - converts Occupied cells to Connected. /// Silently ignores out-of-bounds access. pub fn connect(&mut self, row: usize, col: usize) { - if row < self.rows && col < self.cols { - if let CellState::Occupied { weight } = self.content[row][col] { - // Julia: converts plain Occupied cell (MCell()) to Connected cell - self.content[row][col] = CellState::Connected { weight }; - } + if row < self.rows + && col < self.cols + && let CellState::Occupied { weight } = self.content[row][col] + { + // Julia: converts plain Occupied cell (MCell()) to Connected cell + self.content[row][col] = CellState::Connected { weight }; } } diff --git a/src/rules/unitdiskmapping/ksg/gadgets.rs b/src/rules/unitdiskmapping/ksg/gadgets.rs index 552fc8ba6..30b535a4a 100644 --- a/src/rules/unitdiskmapping/ksg/gadgets.rs +++ b/src/rules/unitdiskmapping/ksg/gadgets.rs @@ -5,9 +5,9 @@ //! KsgTrivialTurn, KsgEndTurn, KsgBranchFixB, KsgDanglingLeg, and their rotated/reflected variants. use super::super::grid::{CellState, MappingGrid}; -use super::super::traits::{apply_gadget, pattern_matches, Pattern, PatternCell}; -use crate::rules::unitdiskmapping::{mapping_integer_overflow, mapping_invalid}; +use super::super::traits::{Pattern, PatternCell, apply_gadget, pattern_matches}; use crate::rules::ReductionError; +use crate::rules::unitdiskmapping::{mapping_integer_overflow, mapping_invalid}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -1277,7 +1277,7 @@ pub fn tape_entry_mis_overhead(entry: &KsgTapeEntry) -> Result { return Err(mapping_invalid( "tape contains an unknown unweighted KSG gadget index", - )) + )); } }) } @@ -1567,10 +1567,10 @@ fn pattern_matches_weighted( for (_idx, (loc_r, loc_c)) in locs.iter().enumerate().skip(1) { let grid_r = i + loc_r - 1; let grid_c = j + loc_c - 1; - if let Some(cell) = grid.get(grid_r, grid_c) { - if cell.weight() != 2 { - return false; - } + if let Some(cell) = grid.get(grid_r, grid_c) + && cell.weight() != 2 + { + return false; } } diff --git a/src/rules/unitdiskmapping/ksg/gadgets_weighted.rs b/src/rules/unitdiskmapping/ksg/gadgets_weighted.rs index 756a81f02..8d818602c 100644 --- a/src/rules/unitdiskmapping/ksg/gadgets_weighted.rs +++ b/src/rules/unitdiskmapping/ksg/gadgets_weighted.rs @@ -5,10 +5,10 @@ //! actual weight methods, following Julia's formula: mis_overhead(weighted) = mis_overhead(unweighted) * 2. use super::super::grid::{CellState, MappingGrid}; -use super::super::traits::{apply_gadget, pattern_matches, Pattern, PatternCell}; +use super::super::traits::{Pattern, PatternCell, apply_gadget, pattern_matches}; use super::gadgets::{KsgReflectedGadget, KsgRotatedGadget, Mirror}; -use crate::rules::unitdiskmapping::{mapping_integer_overflow, mapping_invalid}; use crate::rules::ReductionError; +use crate::rules::unitdiskmapping::{mapping_integer_overflow, mapping_invalid}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -1006,7 +1006,7 @@ pub fn weighted_tape_entry_mis_overhead( _ => { return Err(mapping_invalid( "tape contains an unknown weighted KSG gadget index", - )) + )); } }) } diff --git a/src/rules/unitdiskmapping/ksg/mapping.rs b/src/rules/unitdiskmapping/ksg/mapping.rs index d8c9ebb18..f055c25cd 100644 --- a/src/rules/unitdiskmapping/ksg/mapping.rs +++ b/src/rules/unitdiskmapping/ksg/mapping.rs @@ -3,22 +3,22 @@ //! This module provides functions to map arbitrary graphs to King's SubGraph //! (8-connected grid graphs). It supports both unweighted and weighted mapping modes. -use super::super::copyline::{create_copylines, mis_overhead_copyline, CopyLine}; +use super::super::copyline::{CopyLine, create_copylines, mis_overhead_copyline}; use super::super::grid::MappingGrid; use super::super::pathdecomposition::{ - pathwidth, vertex_order_from_layout, PathDecompositionMethod, + PathDecompositionMethod, pathwidth, vertex_order_from_layout, }; use super::gadgets::{ - apply_crossing_gadgets, apply_simplifier_gadgets, tape_entry_mis_overhead, KsgPattern, - KsgTapeEntry, + KsgPattern, KsgTapeEntry, apply_crossing_gadgets, apply_simplifier_gadgets, + tape_entry_mis_overhead, }; use super::gadgets_weighted::{ - apply_weighted_crossing_gadgets, apply_weighted_simplifier_gadgets, - weighted_tape_entry_mis_overhead, WeightedKsgPattern, WeightedKsgTapeEntry, + WeightedKsgPattern, WeightedKsgTapeEntry, apply_weighted_crossing_gadgets, + apply_weighted_simplifier_gadgets, weighted_tape_entry_mis_overhead, }; use super::{PADDING, SPACING}; -use crate::rules::unitdiskmapping::{mapping_integer_overflow, mapping_invalid}; use crate::rules::ReductionError; +use crate::rules::unitdiskmapping::{mapping_integer_overflow, mapping_invalid}; use crate::topology::{Graph, KingsSubgraph, TriangularSubgraph}; use serde::{Deserialize, Serialize}; use std::collections::{HashMap, HashSet}; @@ -117,11 +117,7 @@ impl MappingResult { let has_node = pos_to_node.contains_key(&(row, column)); let s = if has_node { - if is_selected { - "*" - } else { - "o" - } + if is_selected { "*" } else { "o" } } else { "." }; @@ -192,11 +188,7 @@ impl MappingResult { } else { let w = self.node_weights[idx]; let ws = format!("{}", w); - if ws.len() == 1 { - ws - } else { - "●".to_string() - } + if ws.len() == 1 { ws } else { "●".to_string() } } } else { "⋅".to_string() diff --git a/src/rules/unitdiskmapping/ksg/mod.rs b/src/rules/unitdiskmapping/ksg/mod.rs index 309f4ee6a..70776a3d4 100644 --- a/src/rules/unitdiskmapping/ksg/mod.rs +++ b/src/rules/unitdiskmapping/ksg/mod.rs @@ -22,23 +22,23 @@ pub mod gadgets_weighted; pub mod mapping; pub use gadgets::{ - apply_crossing_gadgets, apply_simplifier_gadgets, crossing_ruleset_indices, - tape_entry_mis_overhead, KsgBranch, KsgBranchFix, KsgBranchFixB, KsgCross, KsgDanglingLeg, - KsgEndTurn, KsgPattern, KsgPatternBoxed, KsgReflectedGadget, KsgRotatedGadget, KsgTCon, - KsgTapeEntry, KsgTrivialTurn, KsgTurn, KsgWTurn, Mirror, + KsgBranch, KsgBranchFix, KsgBranchFixB, KsgCross, KsgDanglingLeg, KsgEndTurn, KsgPattern, + KsgPatternBoxed, KsgReflectedGadget, KsgRotatedGadget, KsgTCon, KsgTapeEntry, KsgTrivialTurn, + KsgTurn, KsgWTurn, Mirror, apply_crossing_gadgets, apply_simplifier_gadgets, + crossing_ruleset_indices, tape_entry_mis_overhead, }; pub use gadgets_weighted::{ + WeightedKsgBranch, WeightedKsgBranchFix, WeightedKsgBranchFixB, WeightedKsgCross, + WeightedKsgDanglingLeg, WeightedKsgEndTurn, WeightedKsgPattern, WeightedKsgTCon, + WeightedKsgTapeEntry, WeightedKsgTrivialTurn, WeightedKsgTurn, WeightedKsgWTurn, apply_weighted_crossing_gadgets, apply_weighted_simplifier_gadgets, - weighted_tape_entry_mis_overhead, WeightedKsgBranch, WeightedKsgBranchFix, - WeightedKsgBranchFixB, WeightedKsgCross, WeightedKsgDanglingLeg, WeightedKsgEndTurn, - WeightedKsgPattern, WeightedKsgTCon, WeightedKsgTapeEntry, WeightedKsgTrivialTurn, - WeightedKsgTurn, WeightedKsgWTurn, + weighted_tape_entry_mis_overhead, }; pub use mapping::{ - map_unweighted, map_unweighted_with_method, map_unweighted_with_order, map_weighted, - map_weighted_with_method, map_weighted_with_order, GridKind, MappingResult, + GridKind, MappingResult, map_unweighted, map_unweighted_with_method, map_unweighted_with_order, + map_weighted, map_weighted_with_method, map_weighted_with_order, }; /// Spacing between copy lines for KSG mapping. diff --git a/src/rules/unitdiskmapping/mod.rs b/src/rules/unitdiskmapping/mod.rs index 1b94e099c..2236ff603 100644 --- a/src/rules/unitdiskmapping/mod.rs +++ b/src/rules/unitdiskmapping/mod.rs @@ -64,12 +64,12 @@ fn mapping_non_finite(operation: impl Into) -> ReductionError { // Re-exports for unit tests (only needed in test builds) #[cfg(test)] pub(crate) use copyline::{ - copyline_weighted_locations_triangular, create_copylines, mis_overhead_copyline, CopyLine, + CopyLine, copyline_weighted_locations_triangular, create_copylines, mis_overhead_copyline, }; #[cfg(test)] pub(crate) use grid::{CellState, MappingGrid}; #[cfg(test)] -pub(crate) use traits::{apply_gadget, unapply_gadget, Pattern}; +pub(crate) use traits::{Pattern, apply_gadget, unapply_gadget}; #[cfg(test)] pub(crate) use weighted::{map_weights, trace_centers}; @@ -77,7 +77,7 @@ pub(crate) use weighted::{map_weights, trace_centers}; #[doc(hidden)] pub mod _internal { pub use super::copyline::{ - create_copylines, mis_overhead_copyline, mis_overhead_copyline_triangular, CopyLine, + CopyLine, create_copylines, mis_overhead_copyline, mis_overhead_copyline_triangular, }; pub use super::grid::{CellState, MappingGrid}; } diff --git a/src/rules/unitdiskmapping/pathdecomposition.rs b/src/rules/unitdiskmapping/pathdecomposition.rs index 37b6d06a3..7ff0a5675 100644 --- a/src/rules/unitdiskmapping/pathdecomposition.rs +++ b/src/rules/unitdiskmapping/pathdecomposition.rs @@ -14,9 +14,9 @@ //! Experimental evaluation of a branch and bound algorithm for computing pathwidth. //! +use rand::SeedableRng; use rand::rngs::SmallRng; use rand::seq::IndexedRandom; -use rand::SeedableRng; use std::collections::{BTreeSet, HashMap, HashSet}; /// Default seed used when no explicit seed is passed to [`pathwidth`]. @@ -289,7 +289,7 @@ fn greedy_step( let best_indices: Vec = costs .iter() .enumerate() - .filter(|(_, &c)| c == best_cost) + .filter(|&(_, &c)| c == best_cost) .map(|(i, _)| i) .collect(); diff --git a/src/rules/unitdiskmapping/triangular/gadgets.rs b/src/rules/unitdiskmapping/triangular/gadgets.rs index b6b6d25cd..ae3dde92a 100644 --- a/src/rules/unitdiskmapping/triangular/gadgets.rs +++ b/src/rules/unitdiskmapping/triangular/gadgets.rs @@ -4,8 +4,8 @@ //! All gadgets use weighted mode (weight 2 for standard nodes). use super::super::grid::{CellState, MappingGrid}; -use crate::rules::unitdiskmapping::mapping_invalid; use crate::rules::ReductionError; +use crate::rules::unitdiskmapping::mapping_invalid; use serde::{Deserialize, Serialize}; use std::collections::HashSet; @@ -1425,7 +1425,7 @@ pub fn tape_entry_mis_overhead(entry: &WeightedTriTapeEntry) -> Result { return Err(mapping_invalid( "tape contains an unknown weighted triangular gadget index", - )) + )); } }) } diff --git a/src/rules/unitdiskmapping/triangular/mapping.rs b/src/rules/unitdiskmapping/triangular/mapping.rs index 8173ddfad..739bbe386 100644 --- a/src/rules/unitdiskmapping/triangular/mapping.rs +++ b/src/rules/unitdiskmapping/triangular/mapping.rs @@ -3,17 +3,17 @@ //! This module provides functions to map arbitrary graphs to weighted triangular //! lattice grid graphs using the copy-line technique. -use super::super::copyline::{create_copylines, CopyLine}; +use super::super::copyline::{CopyLine, create_copylines}; use super::super::grid::MappingGrid; -use super::super::ksg::mapping::MappingResult; use super::super::ksg::KsgTapeEntry as TapeEntry; +use super::super::ksg::mapping::MappingResult; use super::super::pathdecomposition::{ - pathwidth, vertex_order_from_layout, PathDecompositionMethod, + PathDecompositionMethod, pathwidth, vertex_order_from_layout, }; use super::gadgets::{apply_crossing_gadgets, apply_simplifier_gadgets, tape_entry_mis_overhead}; +use crate::rules::ReductionError; use crate::rules::unitdiskmapping::ksg::mapping::GridKind; use crate::rules::unitdiskmapping::{mapping_integer_overflow, mapping_invalid}; -use crate::rules::ReductionError; use std::collections::HashMap; fn position_index( diff --git a/src/rules/unitdiskmapping/triangular/mod.rs b/src/rules/unitdiskmapping/triangular/mod.rs index 92b864ef0..d2ae65d6c 100644 --- a/src/rules/unitdiskmapping/triangular/mod.rs +++ b/src/rules/unitdiskmapping/triangular/mod.rs @@ -16,13 +16,13 @@ pub mod mapping; pub use super::weighted::{map_weights, trace_centers}; pub use gadgets::{ - apply_crossing_gadgets, apply_simplifier_gadgets, tape_entry_mis_overhead, SourceCell, - WeightedTriBranch, WeightedTriBranchFix, WeightedTriBranchFixB, WeightedTriCross, + SourceCell, WeightedTriBranch, WeightedTriBranchFix, WeightedTriBranchFixB, WeightedTriCross, WeightedTriEndTurn, WeightedTriTConDown, WeightedTriTConLeft, WeightedTriTConUp, WeightedTriTapeEntry, WeightedTriTrivialTurnLeft, WeightedTriTrivialTurnRight, WeightedTriTurn, - WeightedTriWTurn, WeightedTriangularGadget, + WeightedTriWTurn, WeightedTriangularGadget, apply_crossing_gadgets, apply_simplifier_gadgets, + tape_entry_mis_overhead, }; pub use mapping::{ - map_config_back, map_unit_weights, map_weighted, map_weighted_with_method, - map_weighted_with_order, PADDING, SPACING, + PADDING, SPACING, map_config_back, map_unit_weights, map_weighted, map_weighted_with_method, + map_weighted_with_order, }; diff --git a/src/solvers/customized/ensemble_computation.rs b/src/solvers/customized/ensemble_computation.rs index 0668decef..c482ad883 100644 --- a/src/solvers/customized/ensemble_computation.rs +++ b/src/solvers/customized/ensemble_computation.rs @@ -1,6 +1,6 @@ //! Direct union chains and bounded subset enumeration with a compact ILP fallback. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::models::misc::EnsembleComputation; use crate::solvers::{ILPSolveError, ILPSolver, SolveError}; use crate::traits::Problem; diff --git a/src/solvers/customized/fd_subset_search.rs b/src/solvers/customized/fd_subset_search.rs index 5f9d1695a..4754240dd 100644 --- a/src/solvers/customized/fd_subset_search.rs +++ b/src/solvers/customized/fd_subset_search.rs @@ -65,7 +65,7 @@ fn dfs( selected .iter() .enumerate() - .filter(|(_, &v)| v) + .filter(|&(_, &v)| v) .map(|(i, _)| i) .collect(), ); diff --git a/src/solvers/customized/solver.rs b/src/solvers/customized/solver.rs index 6b34ff0cb..312ba8d35 100644 --- a/src/solvers/customized/solver.rs +++ b/src/solvers/customized/solver.rs @@ -1,8 +1,8 @@ //! Exact customized solvers and their exact-variant registrations. use super::fd_subset_search::{ - self, compute_closure, find_essential_attributes, find_essential_attributes_restricted, - is_minimal_key, is_superkey, BranchDecision, + self, BranchDecision, compute_closure, find_essential_attributes, + find_essential_attributes_restricted, is_minimal_key, is_superkey, }; use crate::models::graph::{ MinimumCostCirculation, MinimumIntersectionGraphBasis, PartialFeedbackEdgeSet, diff --git a/src/solvers/decision_search.rs b/src/solvers/decision_search.rs index eb5cdbcc3..68648b73d 100644 --- a/src/solvers/decision_search.rs +++ b/src/solvers/decision_search.rs @@ -4,8 +4,8 @@ use crate::models::decision::{Decision, DecisionProblemMeta}; use crate::solvers::BruteForce; use crate::traits::Problem; use crate::types::{Max, Min, OptimizationValue, Or}; -use serde::de::DeserializeOwned; use serde::Serialize; +use serde::de::DeserializeOwned; use std::fmt; /// Whether a decision problem has at least one satisfying configuration. @@ -36,10 +36,10 @@ where } return Ok(None); } - if let Some(bound) = lower.checked_sub(1) { - if is_satisfiable(&Decision::new(problem.clone(), bound))? { - return Err(crate::solvers::SolveError::OptimumOutsideSearchInterval { lower, upper }); - } + if let Some(bound) = lower.checked_sub(1) + && is_satisfiable(&Decision::new(problem.clone(), bound))? + { + return Err(crate::solvers::SolveError::OptimumOutsideSearchInterval { lower, upper }); } let mut lo = lower; @@ -76,10 +76,10 @@ where } return Ok(None); } - if let Some(bound) = upper.checked_add(1) { - if is_satisfiable(&Decision::new(problem.clone(), bound))? { - return Err(crate::solvers::SolveError::OptimumOutsideSearchInterval { lower, upper }); - } + if let Some(bound) = upper.checked_add(1) + && is_satisfiable(&Decision::new(problem.clone(), bound))? + { + return Err(crate::solvers::SolveError::OptimumOutsideSearchInterval { lower, upper }); } let mut lo = lower; diff --git a/src/solvers/ilp/adapter.rs b/src/solvers/ilp/adapter.rs index b01123aa0..a34d65f64 100644 --- a/src/solvers/ilp/adapter.rs +++ b/src/solvers/ilp/adapter.rs @@ -5,9 +5,9 @@ //! Optimality and infeasibility follow HiGHS numerical tolerances, not exact proofs. use crate::models::algebraic::{ - BoundsPolicy, Comparison, ILPCoefficient, ObjectiveSense, VariableDomain, ILP, + BoundsPolicy, Comparison, ILP, ILPCoefficient, ObjectiveSense, VariableDomain, }; -use crate::types::{i64_to_exact_f64, MAX_EXACT_F64_INTEGER}; +use crate::types::{MAX_EXACT_F64_INTEGER, i64_to_exact_f64}; use highs::{HighsModelStatus, HighsSolutionStatus, RowProblem, Sense}; use super::solver::ILPSolveError; diff --git a/src/solvers/ilp/solver.rs b/src/solvers/ilp/solver.rs index 1e01e79fa..f26b79614 100644 --- a/src/solvers/ilp/solver.rs +++ b/src/solvers/ilp/solver.rs @@ -2,8 +2,8 @@ use super::adapter::HighsAdapter; use crate::models::algebraic::{Bounded, ILP}; -use crate::solvers::registry::solver_capability_registry; use crate::solvers::ExactProblemKey; +use crate::solvers::registry::solver_capability_registry; use crate::traits::Problem; /// A failure to produce an ILP solution optimal within backend numerical tolerances. diff --git a/src/solvers/mod.rs b/src/solvers/mod.rs index 9c409f756..ea056bb5b 100644 --- a/src/solvers/mod.rs +++ b/src/solvers/mod.rs @@ -15,10 +15,10 @@ pub use brute_force::BruteForceRegistration; pub(crate) use brute_force::CartesianIndices; pub use brute_force::{BruteForce, BruteForceProblem}; pub use registry::{ - brute_force_dimensions, solver_capabilities, CustomizedSolverCapability, ExactProblemKey, - IlpSolverCapability, RegistryBuildError, SolverCapabilities, + CustomizedSolverCapability, ExactProblemKey, IlpSolverCapability, RegistryBuildError, + SolverCapabilities, brute_force_dimensions, solver_capabilities, }; -pub use resolver::{solve, SolveOutcome, SolveResult, SolverExecution, SolverRequest}; +pub use resolver::{SolveOutcome, SolveResult, SolverExecution, SolverRequest, solve}; pub use ilp::{ILPSolveError, ILPSolver}; diff --git a/src/solvers/registry.rs b/src/solvers/registry.rs index 2fa82ac5f..5739cd001 100644 --- a/src/solvers/registry.rs +++ b/src/solvers/registry.rs @@ -1,8 +1,8 @@ //! Deterministic solver capabilities for exact problem variants. use crate::registry::VariantEntry; -use crate::rules::registry::{reduction_entries, AggregateViewFn, ReduceFn, ReductionEntry}; use crate::rules::DynReductionResult; +use crate::rules::registry::{AggregateViewFn, ReduceFn, ReductionEntry, reduction_entries}; use serde::Serialize; use std::any::Any; use std::collections::{BTreeMap, BTreeSet}; @@ -321,7 +321,9 @@ pub enum RegistryBuildError { UnsupportedTarget(String), #[error("ILP pipeline for {0} continues after reaching a supported ILP node")] ContinuesAfterIlp(String), - #[error("ILP pipeline edge {source_label} -> {target_label} resolves to {matches} witness reductions")] + #[error( + "ILP pipeline edge {source_label} -> {target_label} resolves to {matches} witness reductions" + )] InvalidEdge { source_label: String, target_label: String, @@ -472,8 +474,8 @@ fn build_registry( static REGISTRY: OnceLock> = OnceLock::new(); -pub(crate) fn solver_capability_registry( -) -> Result<&'static SolverCapabilityRegistry, &'static RegistryBuildError> { +pub(crate) fn solver_capability_registry() +-> Result<&'static SolverCapabilityRegistry, &'static RegistryBuildError> { REGISTRY .get_or_init(|| { build_registry( diff --git a/src/solvers/resolver.rs b/src/solvers/resolver.rs index 6444d1254..befd0582b 100644 --- a/src/solvers/resolver.rs +++ b/src/solvers/resolver.rs @@ -1,7 +1,7 @@ //! Shared deterministic solver dispatch. use super::registry::CompiledIlpPipeline; -use super::registry::{solver_capability_registry, CustomizedSolverRegistration, ExactProblemKey}; +use super::registry::{CustomizedSolverRegistration, ExactProblemKey, solver_capability_registry}; use crate::registry::LoadedDynProblem; use serde::Serialize; diff --git a/src/topology/bipartite_graph.rs b/src/topology/bipartite_graph.rs index b35c8e620..db2898352 100644 --- a/src/topology/bipartite_graph.rs +++ b/src/topology/bipartite_graph.rs @@ -128,11 +128,7 @@ impl Graph for BipartiteGraph { .map(|&(u, v)| { let a = u; let b = self.left_size + v; - if a < b { - (a, b) - } else { - (b, a) - } + if a < b { (a, b) } else { (b, a) } }) .collect() } diff --git a/src/unit_tests/example_db.rs b/src/unit_tests/example_db.rs index 62d007721..3c68ff842 100644 --- a/src/unit_tests/example_db.rs +++ b/src/unit_tests/example_db.rs @@ -3,7 +3,7 @@ use crate::example_db::{ }; use crate::export::ProblemRef; use crate::registry::load_dyn; -use crate::rules::{registry::reduction_entries, ReductionGraph}; +use crate::rules::{ReductionGraph, registry::reduction_entries}; use std::collections::{BTreeMap, BTreeSet, HashSet}; #[test] @@ -293,16 +293,20 @@ fn test_find_rule_example_integral_flow_bundles_to_ilp_contains_full_instances() assert_eq!(example.source.problem, "IntegralFlowBundles"); assert_eq!(example.target.problem, "ILP"); assert!(example.source.instance.get("graph").is_some()); - assert!(!example.solutions[0] - .source_config - .as_array() - .unwrap() - .is_empty()); - assert!(!example.solutions[0] - .target_config - .as_array() - .unwrap() - .is_empty()); + assert!( + !example.solutions[0] + .source_config + .as_array() + .unwrap() + .is_empty() + ); + assert!( + !example.solutions[0] + .target_config + .as_array() + .unwrap() + .is_empty() + ); } #[test] @@ -472,8 +476,12 @@ fn canonical_rule_examples_cover_exactly_authored_direct_reductions() { example_keys, direct_reduction_keys, "rule example coverage should match authored direct reductions exactly; missing examples: {:?}; unexpected examples: {:?}", - direct_reduction_keys.difference(&example_keys).collect::>(), - example_keys.difference(&direct_reduction_keys).collect::>() + direct_reduction_keys + .difference(&example_keys) + .collect::>(), + example_keys + .difference(&direct_reduction_keys) + .collect::>() ); } @@ -546,7 +554,7 @@ fn model_specs_are_self_consistent() { fn model_specs_are_optimal() { use crate::registry::load_dyn; use crate::solvers::{ - brute_force_dimensions, solve, solver_capabilities, SolveOutcome, SolverRequest, + SolveOutcome, SolverRequest, brute_force_dimensions, solve, solver_capabilities, }; let specs = crate::models::graph::canonical_model_example_specs() @@ -801,29 +809,30 @@ fn rule_specs_solution_pairs_are_consistent() { source_val, "Rule {label}: aggregate and witness mappings disagree" ); - if source_eval == "Or(true)" { - if let Some(config) = pair.target_config.as_array() { - for bit in [false, true] { - let candidate = serde_json::Value::Array( - config - .iter() - .map(|value| match value { - serde_json::Value::Bool(_) => serde_json::json!(bit), - serde_json::Value::Number(_) => { - serde_json::json!(i64::from(bit)) - } - _ => value.clone(), - }) - .collect(), + if source_eval == "Or(true)" + && let Some(config) = pair.target_config.as_array() + { + for bit in [false, true] { + let candidate = serde_json::Value::Array( + config + .iter() + .map(|value| match value { + serde_json::Value::Bool(_) => serde_json::json!(bit), + serde_json::Value::Number(_) => { + serde_json::json!(i64::from(bit)) + } + _ => value.clone(), + }) + .collect(), + ); + // Only test well-formed candidates whose mapped value is NO. + if let Ok(value) = target.evaluate_json(&candidate) + && chain.extract_value(value).unwrap() == serde_json::json!(false) + { + assert!( + chain.extract_solution_json(candidate).is_err(), + "Rule {label}: a negative certificate produced a witness" ); - // Only test well-formed candidates whose mapped value is NO. - if let Ok(value) = target.evaluate_json(&candidate) { - if chain.extract_value(value).unwrap() - == serde_json::json!(false) - { - assert!(chain.extract_solution_json(candidate).is_err(), "Rule {label}: a negative certificate produced a witness"); - } - } } } } diff --git a/src/unit_tests/graph_models.rs b/src/unit_tests/graph_models.rs index 7f046c2f9..25ce80086 100644 --- a/src/unit_tests/graph_models.rs +++ b/src/unit_tests/graph_models.rs @@ -228,14 +228,18 @@ mod maximum_independent_set { let problem = MaximumIndependentSet::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![1i64; 3]); - assert!(problem - .evaluate(&vec![true, false, true]) - .unwrap() - .is_valid()); - assert!(problem - .evaluate(&vec![false, true, false]) - .unwrap() - .is_valid()); + assert!( + problem + .evaluate(&vec![true, false, true]) + .unwrap() + .is_valid() + ); + assert!( + problem + .evaluate(&vec![false, true, false]) + .unwrap() + .is_valid() + ); assert_eq!( problem.evaluate(&vec![true, true, false]).unwrap(), Max(None) @@ -401,14 +405,18 @@ mod minimum_vertex_cover { let problem = MinimumVertexCover::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![1i64; 3]); - assert!(problem - .evaluate(&vec![false, true, false]) - .unwrap() - .is_valid()); - assert!(problem - .evaluate(&vec![true, false, true]) - .unwrap() - .is_valid()); + assert!( + problem + .evaluate(&vec![false, true, false]) + .unwrap() + .is_valid() + ); + assert!( + problem + .evaluate(&vec![true, false, true]) + .unwrap() + .is_valid() + ); assert_eq!( problem.evaluate(&vec![true, false, false]).unwrap(), Min(None) diff --git a/src/unit_tests/growth.rs b/src/unit_tests/growth.rs index 22dd1e897..d47f33d98 100644 --- a/src/unit_tests/growth.rs +++ b/src/unit_tests/growth.rs @@ -1,11 +1,11 @@ //! Unit tests for the symbolic growth domain (`src/growth.rs`). use super::{ - add, exact_growth, mul, ExpBase, Growth, GrowthFailure, GrowthState, GrowthTerm, - VariableGrowth, ANTICHAIN_CAP, + ANTICHAIN_CAP, ExpBase, Growth, GrowthFailure, GrowthState, GrowthTerm, VariableGrowth, add, + exact_growth, mul, }; use crate::expr::{ - evaluate_approximate, expression_from_approximation, AlgebraicAnalysis, Expr, ExprNode, + AlgebraicAnalysis, Expr, ExprNode, evaluate_approximate, expression_from_approximation, }; use crate::registry::variant_entries; use num_rational::BigRational; @@ -722,11 +722,7 @@ fn gen_linear(rng: &mut SplitMix64) -> Expr { fn gen_lin_term(rng: &mut SplitMix64) -> Expr { let v = gen_var(rng); let c = 1 + rng.below(3); - if c == 1 { - v - } else { - Expr::integer(c) * v - } + if c == 1 { v } else { Expr::integer(c) * v } } /// A deliberately nonlinear exponent, driving `2^(·)` to `Growth::Unknown`. diff --git a/src/unit_tests/ilp_overhead.rs b/src/unit_tests/ilp_overhead.rs index 9fd03eae2..a9044e7df 100644 --- a/src/unit_tests/ilp_overhead.rs +++ b/src/unit_tests/ilp_overhead.rs @@ -7,8 +7,8 @@ use crate::rules::{ReduceTo, ReductionGraph, ReductionPath, ReductionResult, Red use crate::solvers::{BruteForce, BruteForceProblem, ILPSolver}; use crate::topology::{MultiDigraph, SimpleDigraph, SimpleGraph}; use crate::{ - types::{Min, One}, Problem, ProblemParameters, + types::{Min, One}, }; type BoundedILP = ILP; @@ -685,7 +685,7 @@ fn hamiltonian_edge_bound_includes_normalization_and_fixed_outputs() { #[test] fn integer_knapsack_and_open_shop_bit_predictions_reach_qubo() { - use crate::models::{set::IntegerKnapsack, Decision}; + use crate::models::{Decision, set::IntegerKnapsack}; for capacity in [0, 2, 5] { check_qubo::<_, BoundedILP>( IntegerKnapsack::new(vec![2, 3], vec![3, 5], capacity).unwrap(), @@ -765,7 +765,7 @@ fn partition_knapsack_qubo_predictions_and_solution_recovery() { #[test] fn subset_sum_lattice_qubo_predictions_and_solution_recovery() { - use crate::models::{algebraic::ClosestVectorProblem, Decision}; + use crate::models::{Decision, algebraic::ClosestVectorProblem}; for (sizes, target) in [(vec![1], 1), (vec![2], 1)] { let source = SubsetSum::new(sizes.clone(), target); // The carry lattices have unit selected determinants. Squared column @@ -902,9 +902,11 @@ where let result = ILPSolver::new().solve(ilp); if matches!(result, Err(crate::solvers::ILPSolveError::Infeasible)) { assert!(expected.is_none()); - assert!(chain - .extract_solution::(&vec![false; target.num_vars()]) - .is_err()); + assert!( + chain + .extract_solution::(&vec![false; target.num_vars()]) + .is_err() + ); return; } let assignment = result.unwrap(); diff --git a/src/unit_tests/models/algebraic/bmf.rs b/src/unit_tests/models/algebraic/bmf.rs index d380dc062..c0bb917b0 100644 --- a/src/unit_tests/models/algebraic/bmf.rs +++ b/src/unit_tests/models/algebraic/bmf.rs @@ -201,12 +201,16 @@ fn test_rank_zero_exactness() { fn test_is_exact() { let matrix = vec![vec![true]]; let problem = BMF::new(matrix, 1); - assert!(problem - .is_exact(&(vec![vec![true]], vec![vec![true]])) - .unwrap()); - assert!(!problem - .is_exact(&(vec![vec![false]], vec![vec![false]])) - .unwrap()); + assert!( + problem + .is_exact(&(vec![vec![true]], vec![vec![true]])) + .unwrap() + ); + assert!( + !problem + .is_exact(&(vec![vec![false]], vec![vec![false]])) + .unwrap() + ); } #[test] @@ -293,10 +297,10 @@ fn test_bmf_paper_example() { #[test] fn json_rejects_invalid_instance() { - assert!(serde_json::from_value::( - serde_json::json!({"matrix":[[true],[]],"k":1,"m":2,"n":1}) - ) - .is_err()); + assert!( + serde_json::from_value::(serde_json::json!({"matrix":[[true],[]],"k":1,"m":2,"n":1})) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/algebraic/consecutive_ones_matrix_augmentation.rs b/src/unit_tests/models/algebraic/consecutive_ones_matrix_augmentation.rs index 5d631115d..55f0b45d7 100644 --- a/src/unit_tests/models/algebraic/consecutive_ones_matrix_augmentation.rs +++ b/src/unit_tests/models/algebraic/consecutive_ones_matrix_augmentation.rs @@ -7,13 +7,13 @@ fn create_spec_rejects_negative_bound() { ConsecutiveOnesMatrixAugmentationCreateSpec::FIELDS[1].name, "bound" ); - assert!(ConsecutiveOnesMatrixAugmentation::try_from( - ConsecutiveOnesMatrixAugmentationCreateSpec { + assert!( + ConsecutiveOnesMatrixAugmentation::try_from(ConsecutiveOnesMatrixAugmentationCreateSpec { matrix: vec![vec![true]], bound: -1 - } - ) - .is_err()); + }) + .is_err() + ); } use crate::solvers::BruteForce; use crate::traits::Problem; diff --git a/src/unit_tests/models/algebraic/consecutive_ones_submatrix.rs b/src/unit_tests/models/algebraic/consecutive_ones_submatrix.rs index 39874eba4..d56f1bc7d 100644 --- a/src/unit_tests/models/algebraic/consecutive_ones_submatrix.rs +++ b/src/unit_tests/models/algebraic/consecutive_ones_submatrix.rs @@ -69,11 +69,13 @@ fn test_consecutive_ones_submatrix_evaluate_wrong_config_length() { #[test] fn test_consecutive_ones_submatrix_evaluate_invalid_variable_value() { let problem = ConsecutiveOnesSubmatrix::new(tucker_matrix(), 3); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([2, false, false, true]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([2, false, false, true]) + ) + .is_err() + ); } #[test] @@ -236,17 +238,21 @@ fn test_consecutive_ones_submatrix_inconsistent_rows() { #[test] fn json_rejects_invalid_instance() { - assert!(serde_json::from_value::( - serde_json::json!({"matrix":[[true]],"bound":2}) - ) - .is_err()); + assert!( + serde_json::from_value::( + serde_json::json!({"matrix":[[true]],"bound":2}) + ) + .is_err() + ); } #[test] fn json_rejects_negative_bound() { // The bound counts columns, so its type rejects negative values. - assert!(serde_json::from_value::( - serde_json::json!({"matrix":[[true]],"bound":-1}) - ) - .is_err()); + assert!( + serde_json::from_value::( + serde_json::json!({"matrix":[[true]],"bound":-1}) + ) + .is_err() + ); } diff --git a/src/unit_tests/models/algebraic/feasible_basis_extension.rs b/src/unit_tests/models/algebraic/feasible_basis_extension.rs index 9a616dd2c..609ad8ad5 100644 --- a/src/unit_tests/models/algebraic/feasible_basis_extension.rs +++ b/src/unit_tests/models/algebraic/feasible_basis_extension.rs @@ -105,11 +105,13 @@ fn test_feasible_basis_extension_evaluate_wrong_config_length() { #[test] fn test_feasible_basis_extension_evaluate_invalid_variable_value() { let problem = issue_example(); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([2, false, false, false]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([2, false, false, false]) + ) + .is_err() + ); } #[test] @@ -250,8 +252,10 @@ fn test_feasible_basis_extension_duplicate_required() { #[test] fn json_rejects_invalid_instance() { - assert!(serde_json::from_value::( - serde_json::json!({"matrix":[[1]],"rhs":[1],"required_columns":[]}) - ) - .is_err()); + assert!( + serde_json::from_value::( + serde_json::json!({"matrix":[[1]],"rhs":[1],"required_columns":[]}) + ) + .is_err() + ); } diff --git a/src/unit_tests/models/algebraic/ilp.rs b/src/unit_tests/models/algebraic/ilp.rs index 886896488..37344b84f 100644 --- a/src/unit_tests/models/algebraic/ilp.rs +++ b/src/unit_tests/models/algebraic/ilp.rs @@ -1,4 +1,19 @@ use super::*; + +#[test] +fn test_ilp_rejects_objective_normalization_overflow() { + let error = ILP::::new( + 1, + vec![], + vec![(0, i64::MAX), (0, 1)], + ObjectiveSense::Minimize, + ) + .unwrap_err(); + assert!( + matches!(error, crate::registry::ConstructionError::IntegerOverflow(message) + if message == "merged objective coefficient of variable 0") + ); +} use crate::solvers::{ILPSolveError, ILPSolver}; use crate::traits::Problem; use crate::types::Extremum; @@ -122,13 +137,15 @@ fn bounded_integer_ilp_loading_requires_finite_domains() { let mut invalid = instance.clone(); invalid["variables"] = serde_json::json!([{"lower_bound": lower, "upper_bound": upper}]); assert!(crate::registry::load_dyn("ILP", &variant, invalid).is_err()); - assert!(ILP::::with_variables( - vec![IntegerVariable::new(lower, upper).unwrap()], - vec![], - vec![], - ObjectiveSense::Minimize, - ) - .is_err()); + assert!( + ILP::::with_variables( + vec![IntegerVariable::new(lower, upper).unwrap()], + vec![], + vec![], + ObjectiveSense::Minimize, + ) + .is_err() + ); } } @@ -293,13 +310,15 @@ fn test_linear_constraint_reports_exact_evaluation_overflow() { #[test] fn test_linear_constraint_out_of_bounds() { - assert!(ILP::::new( - 3, - vec![LinearConstraint::le(vec![(5, 1)], 10)], - vec![], - ObjectiveSense::Minimize, - ) - .is_err()); + assert!( + ILP::::new( + 3, + vec![LinearConstraint::le(vec![(5, 1)], 10)], + vec![], + ObjectiveSense::Minimize, + ) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/algebraic/minimum_matrix_domination.rs b/src/unit_tests/models/algebraic/minimum_matrix_domination.rs index b7cc50946..3ec47b5e6 100644 --- a/src/unit_tests/models/algebraic/minimum_matrix_domination.rs +++ b/src/unit_tests/models/algebraic/minimum_matrix_domination.rs @@ -95,11 +95,13 @@ fn test_minimum_matrix_domination_evaluate_wrong_length() { #[test] fn test_minimum_matrix_domination_evaluate_invalid_variable() { let problem = MinimumMatrixDomination::new(p6_adjacency_matrix()); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([2, 0, 0, 0, 0, 0, 0, 0, 0, 0]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([2, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + ) + .is_err() + ); } #[test] @@ -203,10 +205,12 @@ fn test_minimum_matrix_domination_inconsistent_rows() { #[test] fn json_rejects_invalid_instance() { - assert!(serde_json::from_value::( - serde_json::json!({"matrix":[[true],[]],"ones":[]}) - ) - .is_err()); + assert!( + serde_json::from_value::( + serde_json::json!({"matrix":[[true],[]],"ones":[]}) + ) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/algebraic/minimum_weight_decoding.rs b/src/unit_tests/models/algebraic/minimum_weight_decoding.rs index 20947b66a..dfe540ea6 100644 --- a/src/unit_tests/models/algebraic/minimum_weight_decoding.rs +++ b/src/unit_tests/models/algebraic/minimum_weight_decoding.rs @@ -179,8 +179,10 @@ fn test_minimum_weight_decoding_target_mismatch() { #[test] fn json_rejects_invalid_instance() { - assert!(serde_json::from_value::( - serde_json::json!({"matrix":[[true]],"target":[]}) - ) - .is_err()); + assert!( + serde_json::from_value::( + serde_json::json!({"matrix":[[true]],"target":[]}) + ) + .is_err() + ); } diff --git a/src/unit_tests/models/algebraic/quadratic_assignment.rs b/src/unit_tests/models/algebraic/quadratic_assignment.rs index d73e1a7a6..909d946fd 100644 --- a/src/unit_tests/models/algebraic/quadratic_assignment.rs +++ b/src/unit_tests/models/algebraic/quadratic_assignment.rs @@ -162,8 +162,10 @@ fn test_quadratic_assignment_solver() { #[test] fn json_rejects_invalid_instance() { - assert!(serde_json::from_value::( - serde_json::json!({"cost_matrix":[[1]],"distance_matrix":[[]]}) - ) - .is_err()); + assert!( + serde_json::from_value::( + serde_json::json!({"cost_matrix":[[1]],"distance_matrix":[[]]}) + ) + .is_err() + ); } diff --git a/src/unit_tests/models/algebraic/quadratic_congruences.rs b/src/unit_tests/models/algebraic/quadratic_congruences.rs index 41a805acc..52fb9ce93 100644 --- a/src/unit_tests/models/algebraic/quadratic_congruences.rs +++ b/src/unit_tests/models/algebraic/quadratic_congruences.rs @@ -104,9 +104,10 @@ fn test_quadratic_congruences_brute_force_finds_all_witnesses() { let solver = BruteForce::new(); let all = solver.find_all_witnesses(&yes_problem()).unwrap(); assert_eq!(all.len(), 3); - assert!(all - .iter() - .all(|sol| yes_problem().evaluate(sol).unwrap() == Or(true))); + assert!( + all.iter() + .all(|sol| yes_problem().evaluate(sol).unwrap() == Or(true)) + ); let decoded = all .iter() .cloned() diff --git a/src/unit_tests/models/algebraic/quadratic_diophantine_equations.rs b/src/unit_tests/models/algebraic/quadratic_diophantine_equations.rs index 09d0c968b..8df988fd2 100644 --- a/src/unit_tests/models/algebraic/quadratic_diophantine_equations.rs +++ b/src/unit_tests/models/algebraic/quadratic_diophantine_equations.rs @@ -114,9 +114,10 @@ fn test_quadratic_diophantine_equations_solver_finds_all_witnesses() { let solver = BruteForce::new(); let all = solver.find_all_witnesses(&problem).unwrap(); assert_eq!(all.len(), 2); - assert!(all - .iter() - .all(|sol| problem.evaluate(sol).unwrap() == Or(true))); + assert!( + all.iter() + .all(|sol| problem.evaluate(sol).unwrap() == Or(true)) + ); let decoded = all .iter() .cloned() diff --git a/src/unit_tests/models/algebraic/qubo.rs b/src/unit_tests/models/algebraic/qubo.rs index f76f651ff..cf2e69ebe 100644 --- a/src/unit_tests/models/algebraic/qubo.rs +++ b/src/unit_tests/models/algebraic/qubo.rs @@ -65,11 +65,13 @@ fn test_qubo_entries_reject_invalid_data() { let error = serde_json::from_value::>(data).unwrap_err(); assert!(error.to_string().contains(message), "{error}"); } - assert!(QUBO::try_from(QuboData { - num_vars: 1, - entries: vec![(0, 0, f64::NAN)] - }) - .is_err()); + assert!( + QUBO::try_from(QuboData { + num_vars: 1, + entries: vec![(0, 0, f64::NAN)] + }) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/algebraic/sparse_matrix_compression.rs b/src/unit_tests/models/algebraic/sparse_matrix_compression.rs index f8b7ef752..818113d82 100644 --- a/src/unit_tests/models/algebraic/sparse_matrix_compression.rs +++ b/src/unit_tests/models/algebraic/sparse_matrix_compression.rs @@ -147,8 +147,10 @@ fn test_sparse_matrix_compression_rejects_ragged_matrix() { #[test] fn json_rejects_invalid_instance() { - assert!(serde_json::from_value::( - serde_json::json!({"matrix":[[true]],"bound_k":0}) - ) - .is_err()); + assert!( + serde_json::from_value::( + serde_json::json!({"matrix":[[true]],"bound_k":0}) + ) + .is_err() + ); } diff --git a/src/unit_tests/models/decision.rs b/src/unit_tests/models/decision.rs index 20fda0ef7..0f38cc54e 100644 --- a/src/unit_tests/models/decision.rs +++ b/src/unit_tests/models/decision.rs @@ -149,9 +149,11 @@ fn construction_contract_decision_rejects_nested_persisted_shape() { .err() .expect("nested persisted shape must not be accepted for construction"); - assert!(error - .to_string() - .contains("unknown construction input(s): inner")); + assert!( + error + .to_string() + .contains("unknown construction input(s): inner") + ); } #[test] @@ -343,12 +345,16 @@ fn test_decision_mis_unit_registration_and_construction() { defaults[0].variant(), vec![("graph", "SimpleGraph"), ("weight", "i64")] ); - assert!(!DecisionCreateSpec::::inputs() - .iter() - .any(|input| input.name == "weights")); - assert!(DecisionCreateSpec::::inputs() - .iter() - .any(|input| input.name == "weights")); + assert!( + !DecisionCreateSpec::::inputs() + .iter() + .any(|input| input.name == "weights") + ); + assert!( + DecisionCreateSpec::::inputs() + .iter() + .any(|input| input.name == "weights") + ); let data = serde_json::json!({"graph":[[0,1],[1,2]],"bound":2}); let spec: DecisionCreateSpec = serde_json::from_value(data.clone()).unwrap(); let decision: Decision = spec.into(); diff --git a/src/unit_tests/models/formula/circuit.rs b/src/unit_tests/models/formula/circuit.rs index 8e692d141..6fe536bc5 100644 --- a/src/unit_tests/models/formula/circuit.rs +++ b/src/unit_tests/models/formula/circuit.rs @@ -291,13 +291,17 @@ fn test_circuit_sat_paper_example() { // Variables sorted: a, b, c, x1, x2 // Paper satisfying inputs (output c=1): (x1=0,x2=1) and (x1=1,x2=0) // (x1=0,x2=1): a=0, b=1, c=1 → config [0, 1, 1, 0, 1] - assert!(problem - .evaluate(&vec![false, true, true, false, true]) - .unwrap()); + assert!( + problem + .evaluate(&vec![false, true, true, false, true]) + .unwrap() + ); // (x1=1,x2=0): a=0, b=1, c=1 → config [0, 1, 1, 1, 0] - assert!(problem - .evaluate(&vec![false, true, true, true, false]) - .unwrap()); + assert!( + problem + .evaluate(&vec![false, true, true, true, false]) + .unwrap() + ); // All 4 consistent configs are satisfying (CircuitSAT checks consistency) let solver = BruteForce::new(); diff --git a/src/unit_tests/models/formula/nae_satisfiability.rs b/src/unit_tests/models/formula/nae_satisfiability.rs index 1e164b6ee..d87ff70eb 100644 --- a/src/unit_tests/models/formula/nae_satisfiability.rs +++ b/src/unit_tests/models/formula/nae_satisfiability.rs @@ -48,24 +48,32 @@ fn test_nae_clause_with_literal_and_negation_is_always_satisfied() { fn test_nae_satisfying_example_from_issue() { let problem = issue_problem(); - assert!(problem - .evaluate(&vec![false, false, false, true, true]) - .unwrap()); - assert!(problem - .is_valid_solution(&[false, false, false, true, true]) - .unwrap()); + assert!( + problem + .evaluate(&vec![false, false, false, true, true]) + .unwrap() + ); + assert!( + problem + .is_valid_solution(&[false, false, false, true, true]) + .unwrap() + ); } #[test] fn test_nae_complement_symmetry_for_issue_example() { let problem = issue_problem(); - assert!(problem - .evaluate(&vec![false, false, false, true, true]) - .unwrap()); - assert!(problem - .evaluate(&vec![true, true, true, false, false]) - .unwrap()); + assert!( + problem + .evaluate(&vec![false, false, false, true, true]) + .unwrap() + ); + assert!( + problem + .evaluate(&vec![true, true, true, false, false]) + .unwrap() + ); } #[test] @@ -132,9 +140,11 @@ fn test_nae_serialization_round_trip() { assert_eq!(round_trip.num_vars(), problem.num_vars()); assert_eq!(round_trip.num_clauses(), problem.num_clauses()); assert_eq!(round_trip.num_literals(), problem.num_literals()); - assert!(round_trip - .evaluate(&vec![false, false, false, true, true]) - .unwrap()); + assert!( + round_trip + .evaluate(&vec![false, false, false, true, true]) + .unwrap() + ); } #[test] @@ -150,11 +160,15 @@ fn test_nae_satisfiability_paper_example() { let problem = issue_problem(); let solver = BruteForce::new(); - assert!(problem - .evaluate(&vec![false, false, false, true, true]) - .unwrap()); - assert!(problem - .evaluate(&vec![true, true, true, false, false]) - .unwrap()); + assert!( + problem + .evaluate(&vec![false, false, false, true, true]) + .unwrap() + ); + assert!( + problem + .evaluate(&vec![true, true, true, false, false]) + .unwrap() + ); assert_eq!(solver.find_all_witnesses(&problem).unwrap().len(), 10); } diff --git a/src/unit_tests/models/graph/acyclic_partition.rs b/src/unit_tests/models/graph/acyclic_partition.rs index 94c380286..b1437a402 100644 --- a/src/unit_tests/models/graph/acyclic_partition.rs +++ b/src/unit_tests/models/graph/acyclic_partition.rs @@ -279,11 +279,13 @@ fn create_spec_maps_weight_inputs_to_canonical_fields() { #[test] fn simple_model_rejects_a_loop_in_construction_and_serde() { - assert!(std::panic::catch_unwind(|| { - let graph = crate::topology::SimpleDigraph::new(2, vec![(0, 0)]); - AcyclicPartition::new(graph, vec![1i64; 2], vec![1i64], 2, 2) - }) - .is_err()); + assert!( + std::panic::catch_unwind(|| { + let graph = crate::topology::SimpleDigraph::new(2, vec![(0, 0)]); + AcyclicPartition::new(graph, vec![1i64; 2], vec![1i64], 2, 2) + }) + .is_err() + ); let error = serde_json::from_value::>(serde_json::json!({ "graph": {"num_vertices": 2, "arcs": [[0,0]]}, "vertex_weights": [1,1], "arc_costs": [1], "weight_bound": 2, "cost_bound": 2 })).unwrap_err(); diff --git a/src/unit_tests/models/graph/balanced_complete_bipartite_subgraph.rs b/src/unit_tests/models/graph/balanced_complete_bipartite_subgraph.rs index af225e573..55b37f62b 100644 --- a/src/unit_tests/models/graph/balanced_complete_bipartite_subgraph.rs +++ b/src/unit_tests/models/graph/balanced_complete_bipartite_subgraph.rs @@ -13,15 +13,15 @@ fn create_spec_builds_bipartite_graph_and_rejects_invalid_edges() { .unwrap(); assert_eq!(problem.graph().left_edges(), &[(0, 1), (1, 0)]); assert_eq!(problem.k(), 1); - assert!(BalancedCompleteBipartiteSubgraph::try_from( - BalancedCompleteBipartiteSubgraphCreateSpec { + assert!( + BalancedCompleteBipartiteSubgraph::try_from(BalancedCompleteBipartiteSubgraphCreateSpec { left: 1, right: 1, biedges: vec![(1, 0)], k: 1, - } - ) - .is_err()); + }) + .is_err() + ); } use crate::solvers::BruteForce; use crate::topology::BipartiteGraph; @@ -87,27 +87,33 @@ fn test_balanced_complete_bipartite_subgraph_creation() { fn test_balanced_complete_bipartite_subgraph_evaluation_yes_instance() { let problem = BalancedCompleteBipartiteSubgraph::new(issue_instance_1_graph(), 2); - assert!(problem - .evaluate(&vec![true, true, false, false, true, true, false, false]) - .unwrap()); + assert!( + problem + .evaluate(&vec![true, true, false, false, true, true, false, false]) + .unwrap() + ); } #[test] fn test_balanced_complete_bipartite_subgraph_evaluation_no_instance() { let problem = BalancedCompleteBipartiteSubgraph::new(issue_instance_1_graph(), 3); - assert!(!problem - .evaluate(&vec![true, true, true, false, true, true, true, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, true, true, false, true, true, true, false]) + .unwrap() + ); } #[test] fn test_balanced_complete_bipartite_subgraph_invalid_pairing() { let problem = BalancedCompleteBipartiteSubgraph::new(issue_instance_1_graph(), 2); - assert!(!problem - .evaluate(&vec![true, true, false, false, true, false, true, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, true, false, false, true, false, true, false]) + .unwrap() + ); } #[test] @@ -127,11 +133,13 @@ fn test_balanced_complete_bipartite_subgraph_rejects_invalid_configs() { problem.evaluate(&vec![true, true, false, false, true, true, false]), Err(crate::traits::EvaluationError::InvalidConfiguration(_)) )); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([true, 2, false, false, true, true, false, false]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([true, 2, false, false, true, true, false, false]) + ) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/graph/biconnectivity_augmentation.rs b/src/unit_tests/models/graph/biconnectivity_augmentation.rs index c3c113b23..37ad05c9e 100644 --- a/src/unit_tests/models/graph/biconnectivity_augmentation.rs +++ b/src/unit_tests/models/graph/biconnectivity_augmentation.rs @@ -103,11 +103,10 @@ fn test_biconnectivity_augmentation_evaluation() { assert!(!problem.evaluate(&vec![false, true, false]).unwrap()); assert!(problem.evaluate(&vec![false, false, true]).unwrap()); assert!(!problem.evaluate(&vec![false, true, true]).unwrap()); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([2, false, false]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn(&problem, &serde_json::json!([2, false, false])) + .is_err() + ); assert!(matches!( problem.evaluate(&vec![true, false]), Err(crate::traits::EvaluationError::InvalidConfiguration(_)) diff --git a/src/unit_tests/models/graph/bounded_component_spanning_forest.rs b/src/unit_tests/models/graph/bounded_component_spanning_forest.rs index d54f8f248..9057559b4 100644 --- a/src/unit_tests/models/graph/bounded_component_spanning_forest.rs +++ b/src/unit_tests/models/graph/bounded_component_spanning_forest.rs @@ -139,9 +139,11 @@ fn test_bounded_component_spanning_forest_creation() { fn test_bounded_component_spanning_forest_yes_instance() { let problem = yes_instance(); assert!(problem.evaluate(&vec![0, 0, 1, 1, 1, 2, 2, 0]).unwrap()); - assert!(problem - .is_valid_solution(&[0, 0, 1, 1, 1, 2, 2, 0]) - .unwrap()); + assert!( + problem + .is_valid_solution(&[0, 0, 1, 1, 1, 2, 2, 0]) + .unwrap() + ); } #[test] 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 b5f7892e3..ec49edd36 100644 --- a/src/unit_tests/models/graph/bounded_diameter_spanning_tree.rs +++ b/src/unit_tests/models/graph/bounded_diameter_spanning_tree.rs @@ -25,6 +25,22 @@ fn test_json_enforces_construction_constraints() { use super::*; +#[test] +fn test_bounded_diameter_spanning_tree_create_rejects_undersized_graph() { + let error = BoundedDiameterSpanningTree::try_from(BoundedDiameterSpanningTreeCreateSpec { + graph: vec![(0, 2)], + num_vertices: Some(2), + edge_weights: None, + weight_bound: 1, + diameter_bound: 1, + }) + .unwrap_err(); + assert!( + matches!(error, crate::registry::ConstructionError::Conversion(message) + if message == "num_vertices 2 is too small for graph endpoints; need at least 3") + ); +} + #[test] fn test_json_rebuilds_edge_list() { let problem = BoundedDiameterSpanningTree::new( @@ -82,9 +98,11 @@ fn test_bounded_diameter_spanning_tree_evaluate_valid() { // Weight: 1+1+1+1 = 4 ≤ 5 // Tree adjacency: 0-{1,3}, 1-{0}, 2-{3}, 3-{0,2,4}, 4-{3} // Diameter: longest path is e.g. 1-0-3-2 or 1-0-3-4 = 3 edges ≤ 3 - assert!(problem - .evaluate(&vec![true, false, true, false, false, true, true]) - .unwrap()); + assert!( + problem + .evaluate(&vec![true, false, true, false, false, true, true]) + .unwrap() + ); } #[test] @@ -92,9 +110,11 @@ fn test_bounded_diameter_spanning_tree_evaluate_exceeds_weight() { let problem = example_instance(); // Select edges 1,2,4,6: (0,2),(0,3),(1,4),(3,4) // Weight: 2+1+2+1 = 6 > 5 - assert!(!problem - .evaluate(&vec![false, true, true, false, true, false, true]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![false, true, true, false, true, false, true]) + .unwrap() + ); } #[test] @@ -113,13 +133,17 @@ fn test_bounded_diameter_spanning_tree_evaluate_exceeds_diameter() { fn test_bounded_diameter_spanning_tree_evaluate_not_tree() { let problem = example_instance(); // Too few edges - assert!(!problem - .evaluate(&vec![true, true, false, false, false, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, true, false, false, false, false, false]) + .unwrap() + ); // Too many edges - assert!(!problem - .evaluate(&vec![true, true, true, true, true, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, true, true, true, true, false, false]) + .unwrap() + ); } #[test] diff --git a/src/unit_tests/models/graph/degree_constrained_spanning_tree.rs b/src/unit_tests/models/graph/degree_constrained_spanning_tree.rs index 9f0a708ee..f82996b0f 100644 --- a/src/unit_tests/models/graph/degree_constrained_spanning_tree.rs +++ b/src/unit_tests/models/graph/degree_constrained_spanning_tree.rs @@ -62,9 +62,11 @@ fn test_degree_constrained_spanning_tree_evaluate_valid() { // Select edges 1,2,3,4: (0,2),(0,3),(1,2),(1,4) // Degrees: 0→2, 1→2, 2→2, 3→1, 4→1 — all ≤ 2 // Connected and n-1=4 edges → valid spanning tree - assert!(problem - .evaluate(&vec![false, true, true, true, true, false, false]) - .unwrap()); + assert!( + problem + .evaluate(&vec![false, true, true, true, true, false, false]) + .unwrap() + ); } #[test] @@ -72,22 +74,28 @@ fn test_degree_constrained_spanning_tree_evaluate_invalid_degree() { let problem = example_instance(); // Select edges 0,1,2,4: (0,1),(0,2),(0,3),(1,4) // Degrees: 0→3 (exceeds K=2) - assert!(!problem - .evaluate(&vec![true, true, true, false, true, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, true, true, false, true, false, false]) + .unwrap() + ); } #[test] fn test_degree_constrained_spanning_tree_evaluate_not_tree() { let problem = example_instance(); // Select only 3 edges (not enough for n-1=4) - assert!(!problem - .evaluate(&vec![true, true, true, false, false, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, true, true, false, false, false, false]) + .unwrap() + ); // Select 5 edges (too many) - assert!(!problem - .evaluate(&vec![true, true, true, true, true, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, true, true, true, true, false, false]) + .unwrap() + ); } #[test] @@ -100,9 +108,11 @@ fn test_degree_constrained_spanning_tree_evaluate_disconnected() { // Need to pick 4 edges forming a tree where no vertex has degree > 2. // edges (0,2),(2,3),(3,4),(1,4) → indices 1,5,6,4 // Degrees: 0→1, 1→1, 2→2, 3→2, 4→2 → valid and connected! - assert!(problem - .evaluate(&vec![false, true, false, false, true, true, true]) - .unwrap()); + assert!( + problem + .evaluate(&vec![false, true, false, false, true, true, true]) + .unwrap() + ); } #[test] diff --git a/src/unit_tests/models/graph/directed_hamiltonian_path.rs b/src/unit_tests/models/graph/directed_hamiltonian_path.rs index 9c140cdf7..bd8be79a6 100644 --- a/src/unit_tests/models/graph/directed_hamiltonian_path.rs +++ b/src/unit_tests/models/graph/directed_hamiltonian_path.rs @@ -143,11 +143,13 @@ fn test_decode_lehmer_identity() { #[test] fn simple_model_rejects_a_loop_in_construction_and_serde() { - assert!(std::panic::catch_unwind(|| { - let graph = crate::topology::SimpleDigraph::new(2, vec![(0, 0)]); - DirectedHamiltonianPath::new(graph) - }) - .is_err()); + assert!( + std::panic::catch_unwind(|| { + let graph = crate::topology::SimpleDigraph::new(2, vec![(0, 0)]); + DirectedHamiltonianPath::new(graph) + }) + .is_err() + ); let error = serde_json::from_value::(serde_json::json!({ "graph": {"num_vertices": 2, "arcs": [[0,0]]}, })) 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 17e9204c8..717912cca 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 @@ -104,7 +104,7 @@ fn test_directed_two_commodity_integral_flow_conservation_violation() { // f1 sends flow into vertex 2 but not out let mut config = vec![0; 16]; config[0] = 1; // f1 on arc 0 (0->2): flow into vertex 2 - // No outgoing flow from vertex 2 for commodity 1 + // No outgoing flow from vertex 2 for commodity 1 assert!(!problem.evaluate(&config).unwrap()); } diff --git a/src/unit_tests/models/graph/disjoint_connecting_paths.rs b/src/unit_tests/models/graph/disjoint_connecting_paths.rs index 9b3a573fe..9e66e0cca 100644 --- a/src/unit_tests/models/graph/disjoint_connecting_paths.rs +++ b/src/unit_tests/models/graph/disjoint_connecting_paths.rs @@ -116,19 +116,23 @@ fn test_disjoint_connecting_paths_rejects_wrong_length_config() { #[test] fn test_disjoint_connecting_paths_rejects_non_binary_entries() { let problem = issue_yes_problem(); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([1, 0, 1, 2, 1, 0, 1]), - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([1, 0, 1, 2, 1, 0, 1]), + ) + .is_err() + ); } #[test] fn test_disjoint_connecting_paths_rejects_branching_subgraph() { let problem = issue_yes_problem(); - assert!(!problem - .evaluate(&vec![true, false, true, true, true, false, true]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, false, true, true, true, false, true]) + .unwrap() + ); } #[test] diff --git a/src/unit_tests/models/graph/graph_partitioning.rs b/src/unit_tests/models/graph/graph_partitioning.rs index cc4289b27..47eb520be 100644 --- a/src/unit_tests/models/graph/graph_partitioning.rs +++ b/src/unit_tests/models/graph/graph_partitioning.rs @@ -134,11 +134,13 @@ fn test_graphpartitioning_unbalanced_invalid() { fn test_graphpartitioning_rejects_non_binary_configs() { let problem = issue_example(); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([false, false, true, true, true, 2]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([false, false, true, true, true, 2]) + ) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/graph/integral_flow_homologous_arcs.rs b/src/unit_tests/models/graph/integral_flow_homologous_arcs.rs index f60de676b..989b2a620 100644 --- a/src/unit_tests/models/graph/integral_flow_homologous_arcs.rs +++ b/src/unit_tests/models/graph/integral_flow_homologous_arcs.rs @@ -161,9 +161,11 @@ fn test_integral_flow_homologous_arcs_paper_example() { let solutions = solver.find_all_witnesses(&problem).unwrap(); assert!(!solutions.is_empty()); - assert!(solutions - .iter() - .all(|solution| problem.evaluate(solution).unwrap().0)); + assert!( + solutions + .iter() + .all(|solution| problem.evaluate(solution).unwrap().0) + ); } #[test] diff --git a/src/unit_tests/models/graph/kclique.rs b/src/unit_tests/models/graph/kclique.rs index 5b0174a08..ddf4c7887 100644 --- a/src/unit_tests/models/graph/kclique.rs +++ b/src/unit_tests/models/graph/kclique.rs @@ -19,12 +19,14 @@ use super::*; use crate::solvers::BruteForceProblem as _; #[test] fn create_spec_rejects_k_above_vertex_count() { - assert!(KClique::try_from(KCliqueCreateSpec { - graph: vec![(0, 1)], - num_vertices: None, - k: 3 - }) - .is_err()); + assert!( + KClique::try_from(KCliqueCreateSpec { + graph: vec![(0, 1)], + num_vertices: None, + k: 3 + }) + .is_err() + ); } use crate::solvers::BruteForce; use crate::topology::SimpleGraph; @@ -62,9 +64,11 @@ fn test_kclique_evaluate_yes_instance() { fn test_kclique_evaluate_rejects_non_clique() { let problem = KClique::new(issue_graph(), 3); - assert!(!problem - .evaluate(&vec![true, false, true, true, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, false, true, true, false]) + .unwrap() + ); assert!(!problem.is_valid_solution(&[true, false, true, true, false])); } @@ -72,12 +76,16 @@ fn test_kclique_evaluate_rejects_non_clique() { fn test_kclique_evaluate_rejects_too_small_clique() { let problem = KClique::new(issue_graph(), 3); - assert!(!problem - .evaluate(&vec![true, false, true, false, false]) - .unwrap()); - assert!(!problem - .evaluate(&vec![false, false, true, true, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, false, true, false, false]) + .unwrap() + ); + assert!( + !problem + .evaluate(&vec![false, false, true, true, false]) + .unwrap() + ); } #[test] diff --git a/src/unit_tests/models/graph/kernel.rs b/src/unit_tests/models/graph/kernel.rs index 09715a3b3..2f9b6cabb 100644 --- a/src/unit_tests/models/graph/kernel.rs +++ b/src/unit_tests/models/graph/kernel.rs @@ -130,11 +130,13 @@ fn test_kernel_empty_graph() { #[test] fn simple_model_rejects_a_loop_in_construction_and_serde() { - assert!(std::panic::catch_unwind(|| { - let graph = crate::topology::SimpleDigraph::new(2, vec![(0, 0)]); - Kernel::new(graph) - }) - .is_err()); + assert!( + std::panic::catch_unwind(|| { + let graph = crate::topology::SimpleDigraph::new(2, vec![(0, 0)]); + Kernel::new(graph) + }) + .is_err() + ); let error = serde_json::from_value::(serde_json::json!({ "graph": {"num_vertices": 2, "arcs": [[0,0]]}, })) diff --git a/src/unit_tests/models/graph/kth_best_spanning_tree.rs b/src/unit_tests/models/graph/kth_best_spanning_tree.rs index 6672b8aee..6c4454eff 100644 --- a/src/unit_tests/models/graph/kth_best_spanning_tree.rs +++ b/src/unit_tests/models/graph/kth_best_spanning_tree.rs @@ -1,4 +1,20 @@ use super::*; + +#[test] +fn test_kth_best_spanning_tree_create_rejects_undersized_graph() { + let error = KthBestSpanningTree::try_from(KthBestSpanningTreeCreateSpec { + graph: vec![(0, 2)], + num_vertices: Some(2), + edge_weights: None, + k: 1, + bound: 1, + }) + .unwrap_err(); + assert!( + matches!(error, crate::registry::ConstructionError::Conversion(message) + if message == "num_vertices 2 is too small for graph endpoints; need at least 3") + ); +} use crate::solvers::BruteForce; use crate::solvers::BruteForceProblem as _; @@ -113,11 +129,13 @@ fn test_kthbestspanningtree_evaluation_rejects_wrong_length_config() { #[test] fn test_kthbestspanningtree_evaluation_rejects_nonbinary_value() { let problem = yes_instance(); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([[2, 1, 1, 0, 0, 0], [1, 1, 0, 0, 1, 0]]), - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([[2, 1, 1, 0, 0, 0], [1, 1, 0, 0, 1, 0]]), + ) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/graph/length_bounded_disjoint_paths.rs b/src/unit_tests/models/graph/length_bounded_disjoint_paths.rs index f34b5451e..3d87776f3 100644 --- a/src/unit_tests/models/graph/length_bounded_disjoint_paths.rs +++ b/src/unit_tests/models/graph/length_bounded_disjoint_paths.rs @@ -155,15 +155,17 @@ fn test_length_bounded_disjoint_paths_rejects_reused_direct_edge() { #[test] fn test_length_bounded_disjoint_paths_rejects_non_binary_entries() { let problem = sample_problem(); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([ - [true, true, false, 2, false, false], - vec![false; 6], - vec![false; 6] - ]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([ + [true, true, false, 2, false, false], + vec![false; 6], + vec![false; 6] + ]) + ) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/graph/longest_path.rs b/src/unit_tests/models/graph/longest_path.rs index 6df940f4c..be4c702df 100644 --- a/src/unit_tests/models/graph/longest_path.rs +++ b/src/unit_tests/models/graph/longest_path.rs @@ -24,14 +24,16 @@ use super::*; use crate::solvers::BruteForceProblem as _; #[test] fn create_spec_rejects_nonpositive_lengths() { - assert!(LongestPath::try_from(LongestPathI64CreateSpec { - graph: vec![(0, 1)], - num_vertices: None, - edge_lengths: vec![0], - source_vertex: 0, - target_vertex: 1 - }) - .is_err()); + assert!( + LongestPath::try_from(LongestPathI64CreateSpec { + graph: vec![(0, 1)], + num_vertices: None, + edge_lengths: vec![0], + source_vertex: 0, + target_vertex: 1 + }) + .is_err() + ); } use crate::solvers::BruteForce; use crate::topology::SimpleGraph; @@ -132,11 +134,13 @@ fn test_longest_path_evaluate_valid_and_invalid_configs() { ); assert_eq!(problem.evaluate(&vec![false; 10]).unwrap(), Max(None)); assert!(!problem.is_valid_solution(&[true, false, true])); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([1, 0, 1, 0, 1, 0, 1, 0, 1, 2]), - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([1, 0, 1, 0, 1, 0, 1, 0, 1, 2]), + ) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/graph/maximum_clique.rs b/src/unit_tests/models/graph/maximum_clique.rs index f88a92d5b..730ea759d 100644 --- a/src/unit_tests/models/graph/maximum_clique.rs +++ b/src/unit_tests/models/graph/maximum_clique.rs @@ -239,14 +239,18 @@ fn test_is_clique_method() { let problem = MaximumClique::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![1i64; 3]); - assert!(problem - .evaluate(&vec![true, true, false]) - .unwrap() - .is_valid()); - assert!(problem - .evaluate(&vec![false, true, true]) - .unwrap() - .is_valid()); + assert!( + problem + .evaluate(&vec![true, true, false]) + .unwrap() + .is_valid() + ); + assert!( + problem + .evaluate(&vec![false, true, true]) + .unwrap() + .is_valid() + ); assert_eq!( problem.evaluate(&vec![true, false, true]).unwrap(), Max(None) diff --git a/src/unit_tests/models/graph/maximum_matching.rs b/src/unit_tests/models/graph/maximum_matching.rs index 3cdab9f6a..550ebe53f 100644 --- a/src/unit_tests/models/graph/maximum_matching.rs +++ b/src/unit_tests/models/graph/maximum_matching.rs @@ -16,6 +16,15 @@ fn test_json_enforces_construction_constraints() { } use super::*; + +#[test] +fn test_maximum_matching_evaluate_weight_overflow() { + let problem = + MaximumMatching::new(SimpleGraph::new(4, vec![(0, 1), (2, 3)]), vec![i64::MAX, 1]); + assert!(matches!(problem.evaluate(&vec![true, true]), + Err(crate::traits::EvaluationError::IntegerOverflow(message)) + if message == "summing selected matching-edge weights")); +} use crate::solvers::BruteForce; use crate::solvers::BruteForceProblem as _; use crate::topology::SimpleGraph; diff --git a/src/unit_tests/models/graph/min_max_multicenter.rs b/src/unit_tests/models/graph/min_max_multicenter.rs index 8ec290c2b..58fcb86ef 100644 --- a/src/unit_tests/models/graph/min_max_multicenter.rs +++ b/src/unit_tests/models/graph/min_max_multicenter.rs @@ -25,6 +25,22 @@ fn test_json_enforces_construction_constraints() { } use super::*; + +#[test] +fn test_minmaxmulticenter_create_rejects_undersized_graph() { + let error = MinMaxMulticenter::try_from(MinMaxMulticenterI64CreateSpec { + graph: vec![(0, 2)], + num_vertices: Some(2), + weights: None, + edge_weights: None, + k: 1, + }) + .unwrap_err(); + assert!( + matches!(error, crate::registry::ConstructionError::Conversion(message) + if message == "num_vertices 2 is too small for graph endpoints; need at least 3") + ); +} use crate::solvers::BruteForce; use crate::solvers::BruteForceProblem as _; use crate::topology::SimpleGraph; 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 84cb65671..64227c0a1 100644 --- a/src/unit_tests/models/graph/minimum_capacitated_spanning_tree.rs +++ b/src/unit_tests/models/graph/minimum_capacitated_spanning_tree.rs @@ -25,6 +25,20 @@ fn test_json_enforces_construction_constraints() { } use super::*; + +#[test] +fn test_minimum_capacitated_spanning_tree_evaluate_weight_overflow() { + let problem = MinimumCapacitatedSpanningTree::new( + SimpleGraph::new(3, vec![(0, 1), (1, 2)]), + vec![i64::MAX, 1], + 0, + vec![0, 1, 1], + 2, + ); + assert!(matches!(problem.evaluate(&vec![true, true]), + Err(crate::traits::EvaluationError::IntegerOverflow(message)) + if message == "summing capacitated spanning tree edge weights")); +} use crate::solvers::BruteForceProblem as _; #[test] @@ -175,13 +189,17 @@ fn test_tight_capacity() { fn test_is_valid_solution() { let problem = example_instance(); // Valid - assert!(problem - .is_valid_solution(&[true, true, false, false, true, false, false, true]) - .unwrap()); + assert!( + problem + .is_valid_solution(&[true, true, false, false, true, false, false, true]) + .unwrap() + ); // Invalid: not enough edges - assert!(!problem - .is_valid_solution(&[true, true, false, false, false, false, false, false]) - .unwrap()); + assert!( + !problem + .is_valid_solution(&[true, true, false, false, false, false, false, false]) + .unwrap() + ); // Invalid: wrong length assert!(!problem.is_valid_solution(&[true, true, false]).unwrap()); } diff --git a/src/unit_tests/models/graph/minimum_dummy_activities_pert.rs b/src/unit_tests/models/graph/minimum_dummy_activities_pert.rs index bc606e09c..b0fd6453c 100644 --- a/src/unit_tests/models/graph/minimum_dummy_activities_pert.rs +++ b/src/unit_tests/models/graph/minimum_dummy_activities_pert.rs @@ -107,11 +107,13 @@ fn test_minimum_dummy_activities_pert_paper_example() { #[test] fn simple_model_rejects_a_loop_in_construction_and_serde() { - assert!(std::panic::catch_unwind(|| { - let graph = crate::topology::SimpleDigraph::new(2, vec![(0, 0)]); - MinimumDummyActivitiesPert::new(graph) - }) - .is_err()); + assert!( + std::panic::catch_unwind(|| { + let graph = crate::topology::SimpleDigraph::new(2, vec![(0, 0)]); + MinimumDummyActivitiesPert::new(graph) + }) + .is_err() + ); let error = serde_json::from_value::(serde_json::json!({ "graph": {"num_vertices": 2, "arcs": [[0,0]]}, })) diff --git a/src/unit_tests/models/graph/minimum_intersection_graph_basis.rs b/src/unit_tests/models/graph/minimum_intersection_graph_basis.rs index 17fd4e160..261bc6fca 100644 --- a/src/unit_tests/models/graph/minimum_intersection_graph_basis.rs +++ b/src/unit_tests/models/graph/minimum_intersection_graph_basis.rs @@ -97,9 +97,11 @@ fn test_minimum_intersection_graph_basis_empty_graph() { fn test_minimum_intersection_graph_basis_wrong_length() { let graph = SimpleGraph::new(3, vec![(0, 1), (1, 2)]); let problem = MinimumIntersectionGraphBasis::new(graph); - assert!(problem - .evaluate(&vec![vec![true, false], vec![true]]) - .is_err()); + assert!( + problem + .evaluate(&vec![vec![true, false], vec![true]]) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/graph/minimum_sum_multicenter.rs b/src/unit_tests/models/graph/minimum_sum_multicenter.rs index bbeee4061..fb7ea920e 100644 --- a/src/unit_tests/models/graph/minimum_sum_multicenter.rs +++ b/src/unit_tests/models/graph/minimum_sum_multicenter.rs @@ -24,6 +24,22 @@ fn test_json_enforces_construction_constraints() { } use super::*; + +#[test] +fn test_minimum_sum_multicenter_create_rejects_undersized_graph() { + let error = MinimumSumMulticenter::try_from(MinimumSumMulticenterCreateSpec { + graph: vec![(0, 2)], + num_vertices: Some(2), + weights: None, + edge_weights: None, + k: 1, + }) + .unwrap_err(); + assert!( + matches!(error, crate::registry::ConstructionError::Conversion(message) + if message == "num_vertices 2 is too small for graph endpoints; need at least 3") + ); +} use crate::solvers::BruteForce; use crate::solvers::BruteForceProblem as _; use crate::topology::SimpleGraph; diff --git a/src/unit_tests/models/graph/minimum_vertex_cover.rs b/src/unit_tests/models/graph/minimum_vertex_cover.rs index d5e22aac1..85499cab3 100644 --- a/src/unit_tests/models/graph/minimum_vertex_cover.rs +++ b/src/unit_tests/models/graph/minimum_vertex_cover.rs @@ -89,9 +89,11 @@ fn test_complement_relationship() { // Complement should be a valid vertex cover let vc_config: Vec = is_sol.iter().map(|&selected| !selected).collect(); // Valid cover should return Valid - assert!(Problem::evaluate(&vc_problem, &vc_config) - .unwrap() - .is_valid()); + assert!( + Problem::evaluate(&vc_problem, &vc_config) + .unwrap() + .is_valid() + ); } } diff --git a/src/unit_tests/models/graph/monochromatic_triangle.rs b/src/unit_tests/models/graph/monochromatic_triangle.rs index e694b632c..91a2b21ce 100644 --- a/src/unit_tests/models/graph/monochromatic_triangle.rs +++ b/src/unit_tests/models/graph/monochromatic_triangle.rs @@ -33,22 +33,28 @@ fn test_monochromatic_triangle_evaluate_valid() { // Triangle (0,1,3): edges 0,2,4 -> 0,1,0 -> mixed // Triangle (0,2,3): edges 1,2,5 -> 0,1,1 -> mixed // Triangle (1,2,3): edges 3,4,5 -> 1,0,1 -> mixed - assert!(problem - .evaluate(&vec![false, false, true, true, false, true]) - .unwrap()); + assert!( + problem + .evaluate(&vec![false, false, true, true, false, true]) + .unwrap() + ); } #[test] fn test_monochromatic_triangle_evaluate_invalid() { let problem = k4_instance(); // All edges color 0: every triangle is monochromatic - assert!(!problem - .evaluate(&vec![false, false, false, false, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![false, false, false, false, false, false]) + .unwrap() + ); // All edges color 1: every triangle is monochromatic - assert!(!problem - .evaluate(&vec![true, true, true, true, true, true]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, true, true, true, true, true]) + .unwrap() + ); } #[test] diff --git a/src/unit_tests/models/graph/multiple_choice_branching.rs b/src/unit_tests/models/graph/multiple_choice_branching.rs index c9fb076ee..e453e4efd 100644 --- a/src/unit_tests/models/graph/multiple_choice_branching.rs +++ b/src/unit_tests/models/graph/multiple_choice_branching.rs @@ -127,20 +127,26 @@ fn test_multiple_choice_branching_partition_validation_missing_arc() { #[test] fn test_multiple_choice_branching_evaluate_yes_instance() { let problem = yes_instance(); - assert!(problem - .evaluate(&vec![true, false, true, false, false, true, false, true]) - .unwrap()); - assert!(problem - .is_valid_solution(&[true, false, true, false, false, true, false, true]) - .unwrap()); + assert!( + problem + .evaluate(&vec![true, false, true, false, false, true, false, true]) + .unwrap() + ); + assert!( + problem + .is_valid_solution(&[true, false, true, false, false, true, false, true]) + .unwrap() + ); } #[test] fn test_multiple_choice_branching_rejects_partition_violation() { let problem = yes_instance(); - assert!(!problem - .evaluate(&vec![true, true, false, false, false, false, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, true, false, false, false, false, false, false]) + .unwrap() + ); } #[test] @@ -155,11 +161,13 @@ fn test_multiple_choice_branching_rejects_wrong_config_length() { #[test] fn test_multiple_choice_branching_rejects_non_binary_config_value() { let problem = yes_instance(); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([2, false, true, false, false, true, false, true]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([2, false, true, false, false, true, false, true]) + ) + .is_err() + ); } #[test] @@ -187,9 +195,11 @@ fn test_multiple_choice_branching_rejects_cycle_violation() { #[test] fn test_multiple_choice_branching_rejects_threshold_violation() { let problem = yes_instance(); - assert!(!problem - .evaluate(&vec![true, false, true, false, false, false, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, false, true, false, false, false, false, false]) + .unwrap() + ); } #[test] @@ -282,11 +292,13 @@ fn test_multiple_choice_branching_num_variables() { #[test] fn simple_model_rejects_a_loop_in_construction_and_serde() { - assert!(std::panic::catch_unwind(|| { - let graph = crate::topology::SimpleDigraph::new(2, vec![(0, 0)]); - MultipleChoiceBranching::new(graph, vec![1i64], vec![vec![0]], 1) - }) - .is_err()); + assert!( + std::panic::catch_unwind(|| { + let graph = crate::topology::SimpleDigraph::new(2, vec![(0, 0)]); + MultipleChoiceBranching::new(graph, vec![1i64], vec![vec![0]], 1) + }) + .is_err() + ); let error = serde_json::from_value::>(serde_json::json!({ "graph": {"num_vertices": 2, "arcs": [[0,0]]}, "weights": [1], "partition": [[0]], "threshold": 1 })).unwrap_err(); diff --git a/src/unit_tests/models/graph/multiple_copy_file_allocation.rs b/src/unit_tests/models/graph/multiple_copy_file_allocation.rs index 0260274be..df67631a3 100644 --- a/src/unit_tests/models/graph/multiple_copy_file_allocation.rs +++ b/src/unit_tests/models/graph/multiple_copy_file_allocation.rs @@ -103,11 +103,13 @@ fn test_multiple_copy_file_allocation_invalid_configs() { Err(crate::traits::EvaluationError::InvalidConfiguration(_)) )); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([false, true, 2, true, false, true]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([false, true, 2, true, false, true]) + ) + .is_err() + ); assert_eq!(problem.total_cost(&[false; 6]).unwrap(), None); assert_eq!( @@ -180,7 +182,8 @@ fn test_multiple_copy_file_allocation_paper_example() { let solver = BruteForce::new(); let all = solver.find_all_witnesses(&problem).unwrap(); // The optimal is placing all 6 copies (cost=6), check that witness exists - assert!(all - .iter() - .any(|config| problem.total_cost(config).unwrap() == Some(6))); + assert!( + all.iter() + .any(|config| problem.total_cost(config).unwrap() == Some(6)) + ); } diff --git a/src/unit_tests/models/graph/partial_feedback_edge_set.rs b/src/unit_tests/models/graph/partial_feedback_edge_set.rs index c39b3895a..480cc224a 100644 --- a/src/unit_tests/models/graph/partial_feedback_edge_set.rs +++ b/src/unit_tests/models/graph/partial_feedback_edge_set.rs @@ -104,11 +104,13 @@ fn test_partial_feedback_edge_set_rejects_wrong_length_config() { #[test] fn test_partial_feedback_edge_set_rejects_non_binary_entries() { let problem = yes_instance(); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([2, 0, 0, 0, 0, 0, 0, 0, 0]), - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([2, 0, 0, 0, 0, 0, 0, 0, 0]), + ) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/graph/path_constrained_network_flow.rs b/src/unit_tests/models/graph/path_constrained_network_flow.rs index 76b84fde4..45bedc652 100644 --- a/src/unit_tests/models/graph/path_constrained_network_flow.rs +++ b/src/unit_tests/models/graph/path_constrained_network_flow.rs @@ -105,9 +105,11 @@ fn test_path_constrained_network_flow_solver_yes_and_no() { let satisfying = solver.find_all_witnesses(&yes).unwrap(); assert_eq!(satisfying.len(), 2); - assert!(satisfying - .iter() - .all(|config| yes.evaluate(config).unwrap().0)); + assert!( + satisfying + .iter() + .all(|config| yes.evaluate(config).unwrap().0) + ); assert!(solver.solve(&no).unwrap().is_none()); } 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 a66c20d90..1e3852605 100644 --- a/src/unit_tests/models/graph/prize_collecting_steiner_forest.rs +++ b/src/unit_tests/models/graph/prize_collecting_steiner_forest.rs @@ -208,14 +208,16 @@ fn test_prize_collecting_steiner_forest_rejects_edge_costs_length_mismatch() { #[test] fn test_prize_collecting_steiner_forest_rejects_non_finite_weight() { - assert!(PrizeCollectingSteinerForest::::new( - SimpleGraph::new(1, vec![]), - vec![f64::NAN], - vec![], - 1.0, - 1.0, - ) - .is_err()); + assert!( + PrizeCollectingSteinerForest::::new( + SimpleGraph::new(1, vec![]), + vec![f64::NAN], + vec![], + 1.0, + 1.0, + ) + .is_err() + ); } #[test] fn create_specs_default_prizes_and_costs_to_one() { @@ -251,22 +253,26 @@ fn test_prize_collecting_steiner_forest_rejects_negative_inputs() { let graph = SimpleGraph::new(2, vec![(0, 1)]); for values in [[-1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, -1]] { let [prize, cost, beta, omega] = values; - assert!(PrizeCollectingSteinerForest::new( - graph.clone(), - vec![prize, 0], - vec![cost], - beta, - omega - ) - .is_err()); - assert!(PrizeCollectingSteinerForest::new( - graph.clone(), - vec![prize as f64, 0.0], - vec![cost as f64], - beta as f64, - omega as f64 - ) - .is_err()); + assert!( + PrizeCollectingSteinerForest::new( + graph.clone(), + vec![prize, 0], + vec![cost], + beta, + omega + ) + .is_err() + ); + assert!( + PrizeCollectingSteinerForest::new( + graph.clone(), + vec![prize as f64, 0.0], + vec![cost as f64], + beta as f64, + omega as f64 + ) + .is_err() + ); } let valid = serde_json::to_value(canonical_problem()).unwrap(); for (field, value) in [ diff --git a/src/unit_tests/models/graph/shortest_weight_constrained_path.rs b/src/unit_tests/models/graph/shortest_weight_constrained_path.rs index 2d213acf2..71aa01a7d 100644 --- a/src/unit_tests/models/graph/shortest_weight_constrained_path.rs +++ b/src/unit_tests/models/graph/shortest_weight_constrained_path.rs @@ -227,11 +227,13 @@ fn test_shortest_weight_constrained_path_rejects_invalid_configs() { let problem = issue_problem(); assert_eq!(problem.is_valid_solution(&[false, true]).unwrap(), None); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([false, true, false, true, false, true, false, 2]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([false, true, false, true, false, true, false, 2]) + ) + .is_err() + ); assert_eq!( problem .is_valid_solution(&[false, false, false, false, false, false, false, false]) diff --git a/src/unit_tests/models/graph/steiner_tree.rs b/src/unit_tests/models/graph/steiner_tree.rs index 450d1d4ba..02d61f24e 100644 --- a/src/unit_tests/models/graph/steiner_tree.rs +++ b/src/unit_tests/models/graph/steiner_tree.rs @@ -1,5 +1,17 @@ use super::*; +#[test] +fn test_steiner_tree_evaluate_weight_overflow() { + let problem = SteinerTree::new( + SimpleGraph::new(3, vec![(0, 1), (1, 2)]), + vec![i64::MAX, 1], + vec![0, 2], + ); + assert!(matches!(problem.evaluate(&vec![true, true]), + Err(crate::traits::EvaluationError::IntegerOverflow(message)) + if message == "summing Steiner tree edge weights")); +} + #[test] fn signed_complexity_counts_nonterminal_subsets() { let problem = SteinerTree::new(SimpleGraph::new(2, vec![(0, 1)]), vec![-2i64], vec![0]); diff --git a/src/unit_tests/models/graph/strong_connectivity_augmentation.rs b/src/unit_tests/models/graph/strong_connectivity_augmentation.rs index a6e738462..51f5c5ea1 100644 --- a/src/unit_tests/models/graph/strong_connectivity_augmentation.rs +++ b/src/unit_tests/models/graph/strong_connectivity_augmentation.rs @@ -169,11 +169,13 @@ fn test_strong_connectivity_augmentation_out_of_range_candidate_panics() { #[test] fn simple_model_rejects_a_loop_in_construction_and_serde() { - assert!(std::panic::catch_unwind(|| { - let graph = crate::topology::SimpleDigraph::new(2, vec![(0, 0)]); - StrongConnectivityAugmentation::::new(graph, vec![], 1i64) - }) - .is_err()); + assert!( + std::panic::catch_unwind(|| { + let graph = crate::topology::SimpleDigraph::new(2, vec![(0, 0)]); + StrongConnectivityAugmentation::::new(graph, vec![], 1i64) + }) + .is_err() + ); let error = serde_json::from_value::>(serde_json::json!({ "graph": {"num_vertices": 2, "arcs": [[0,0]]}, "candidate_arcs": [], "bound": 1 })) diff --git a/src/unit_tests/models/misc/additional_key.rs b/src/unit_tests/models/misc/additional_key.rs index 58c70a901..d5114eb41 100644 --- a/src/unit_tests/models/misc/additional_key.rs +++ b/src/unit_tests/models/misc/additional_key.rs @@ -78,18 +78,22 @@ fn test_additional_key_evaluate_satisfying() { // Minimality: remove 0 => {2}, closure of {2} = {2} => does not cover all. OK. // remove 2 => {0}, closure of {0} = {0} => does not cover all. OK. // {0,2} sorted is [0,2], not in known_keys [{0,1},{2,3},{4,5}]. - assert!(problem - .evaluate(&vec![true, false, true, false, false, false]) - .unwrap()); + assert!( + problem + .evaluate(&vec![true, false, true, false, false, false]) + .unwrap() + ); } #[test] fn test_additional_key_evaluate_known_key() { let problem = instance1(); // Config [1,1,0,0,0,0] selects attrs {0,1} which IS in known_keys. - assert!(!problem - .evaluate(&vec![true, true, false, false, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, true, false, false, false, false]) + .unwrap() + ); } #[test] @@ -97,9 +101,11 @@ fn test_additional_key_evaluate_not_a_key() { let problem = instance1(); // Config [0,0,0,0,0,1] selects {5}. Closure of {5} = {5}. // Does not cover all attrs. - assert!(!problem - .evaluate(&vec![false, false, false, false, false, true]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![false, false, false, false, false, true]) + .unwrap() + ); } #[test] @@ -107,9 +113,11 @@ fn test_additional_key_evaluate_non_minimal() { let problem = instance1(); // Config [1,1,1,0,0,0] selects {0,1,2}. // {0,1} alone determines all attrs (known key), so {0,1,2} is NOT minimal. - assert!(!problem - .evaluate(&vec![true, true, true, false, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, true, true, false, false, false]) + .unwrap() + ); } #[test] @@ -137,11 +145,13 @@ fn test_additional_key_wrong_config_length() { #[test] fn test_additional_key_invalid_variable_value() { let problem = instance1(); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([2, false, false, false, false, false]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([2, false, false, false, false, false]) + ) + .is_err() + ); } #[test] @@ -191,9 +201,11 @@ fn test_additional_key_serialization() { fn test_additional_key_empty_selection() { let problem = instance1(); // All zeros = no attributes selected = not a key - assert!(!problem - .evaluate(&vec![false, false, false, false, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![false, false, false, false, false, false]) + .unwrap() + ); } #[test] 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 846227618..b80aa6296 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 @@ -73,9 +73,11 @@ fn test_bcnf_creation() { fn test_bcnf_evaluate_violation() { let problem = canonical_problem(); // X = {2}: closure = {2, 3}. In A' \ X = {0,1,3,4,5}: 3 ∈ closure, 0 ∉ closure → violation. - assert!(problem - .evaluate(&vec![false, false, true, false, false, false]) - .unwrap()); + assert!( + problem + .evaluate(&vec![false, false, true, false, false, false]) + .unwrap() + ); } #[test] @@ -83,18 +85,22 @@ fn test_bcnf_evaluate_no_violation_empty_x() { let problem = canonical_problem(); // X = {} (all zeros): A' \ X = all attributes, closure of {} = {}. // Nothing in closure → no violation. - assert!(!problem - .evaluate(&vec![false, false, false, false, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![false, false, false, false, false, false]) + .unwrap() + ); } #[test] fn test_bcnf_evaluate_no_violation_x_covers_all() { let problem = canonical_problem(); // X = all attributes: A' \ X = {} → no attributes to test → no violation. - assert!(!problem - .evaluate(&vec![true, true, true, true, true, true]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, true, true, true, true, true]) + .unwrap() + ); } #[test] @@ -113,11 +119,13 @@ fn test_bcnf_evaluate_invalid_config_length() { #[test] fn test_bcnf_evaluate_invalid_config_values() { let problem = canonical_problem(); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([false, false, 2, false, false, false]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([false, false, 2, false, false, false]) + ) + .is_err() + ); } #[test] @@ -257,7 +265,9 @@ fn test_bcnf_multi_step_transitive_closure() { // X={0,1}: {0,1}→{2} then {2}→{3} (two-step chain). // A' \ X = {2,3,4,5}. closure = {0,1,2,3}. 2∈closure, 4∉closure → violation. let problem = canonical_problem(); - assert!(problem - .evaluate(&vec![true, true, false, false, false, false]) - .unwrap()); + assert!( + problem + .evaluate(&vec![true, true, false, false, false, false]) + .unwrap() + ); } diff --git a/src/unit_tests/models/misc/capacity_assignment.rs b/src/unit_tests/models/misc/capacity_assignment.rs index 4b7d86e9e..75cde0a2a 100644 --- a/src/unit_tests/models/misc/capacity_assignment.rs +++ b/src/unit_tests/models/misc/capacity_assignment.rs @@ -30,13 +30,15 @@ fn test_capacity_assignment_validates_persisted_input() { #[test] fn create_spec_validates_monotonicity() { - assert!(CapacityAssignment::try_from(CapacityAssignmentCreateSpec { - capacities: vec![1, 2], - cost: vec![vec![2, 1]], - delay: vec![vec![2, 1]], - delay_budget: 3 - }) - .is_err()); + assert!( + CapacityAssignment::try_from(CapacityAssignmentCreateSpec { + capacities: vec![1, 2], + cost: vec![vec![2, 1]], + delay: vec![vec![2, 1]], + delay_budget: 3 + }) + .is_err() + ); } use crate::solvers::BruteForce; use crate::traits::Problem; diff --git a/src/unit_tests/models/misc/cosine_product_integration.rs b/src/unit_tests/models/misc/cosine_product_integration.rs index 3e5413f8d..0c67e4235 100644 --- a/src/unit_tests/models/misc/cosine_product_integration.rs +++ b/src/unit_tests/models/misc/cosine_product_integration.rs @@ -5,10 +5,10 @@ use crate::traits::Problem; #[test] fn test_cosine_product_integration_deserialization_rejects_empty_coefficients() { - assert!(serde_json::from_value::( - serde_json::json!({"coefficients": []}) - ) - .is_err()); + assert!( + serde_json::from_value::(serde_json::json!({"coefficients": []})) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/misc/grouping_by_swapping.rs b/src/unit_tests/models/misc/grouping_by_swapping.rs index e8911fffc..1158791a8 100644 --- a/src/unit_tests/models/misc/grouping_by_swapping.rs +++ b/src/unit_tests/models/misc/grouping_by_swapping.rs @@ -71,11 +71,13 @@ fn test_grouping_by_swapping_bruteforce_yes_and_no() { .unwrap() .expect("expected a satisfying 3-swap sequence"); assert!(yes_problem.evaluate(&satisfying).unwrap()); - assert!(solver - .find_all_witnesses(&yes_problem) - .unwrap() - .iter() - .any(|config| config == &vec![2, 1, 3])); + assert!( + solver + .find_all_witnesses(&yes_problem) + .unwrap() + .iter() + .any(|config| config == &vec![2, 1, 3]) + ); assert!(solver.solve(&no_problem).unwrap().is_none()); assert!(solver.find_all_witnesses(&no_problem).unwrap().is_empty()); @@ -87,11 +89,13 @@ fn test_grouping_by_swapping_paper_example() { assert!(problem.evaluate(&vec![2, 1, 3, 5, 5]).unwrap()); let solver = BruteForce::new(); - assert!(solver - .find_all_witnesses(&problem) - .unwrap() - .iter() - .any(|config| config == &vec![2, 1, 3, 5, 5])); + assert!( + solver + .find_all_witnesses(&problem) + .unwrap() + .iter() + .any(|config| config == &vec![2, 1, 3, 5, 5]) + ); assert!(solver.solve(&issue_two_swap_instance()).unwrap().is_none()); } diff --git a/src/unit_tests/models/misc/integer_expression_membership.rs b/src/unit_tests/models/misc/integer_expression_membership.rs index 4d812a911..c3b39293c 100644 --- a/src/unit_tests/models/misc/integer_expression_membership.rs +++ b/src/unit_tests/models/misc/integer_expression_membership.rs @@ -99,11 +99,10 @@ fn test_integer_expression_membership_evaluate_wrong_config() { Err(crate::traits::EvaluationError::InvalidConfiguration(_)) )); // Invalid value - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([2, false, false]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn(&problem, &serde_json::json!([2, false, false])) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/misc/job_shop_scheduling.rs b/src/unit_tests/models/misc/job_shop_scheduling.rs index 80d775adb..e42aac9ba 100644 --- a/src/unit_tests/models/misc/job_shop_scheduling.rs +++ b/src/unit_tests/models/misc/job_shop_scheduling.rs @@ -142,11 +142,13 @@ fn test_job_shop_scheduling_create_spec_derives_processor_count() { #[test] fn test_job_shop_scheduling_create_spec_rejects_invalid_jobs() { - assert!(JobShopScheduling::try_from(JobShopSchedulingCreateSpec { - jobs: vec![vec![(0, -1)]], - num_processors: Some(1), - }) - .is_err()); + assert!( + JobShopScheduling::try_from(JobShopSchedulingCreateSpec { + jobs: vec![vec![(0, -1)]], + num_processors: Some(1), + }) + .is_err() + ); let empty = JobShopScheduling::try_from(JobShopSchedulingCreateSpec { jobs: vec![], diff --git a/src/unit_tests/models/misc/knapsack.rs b/src/unit_tests/models/misc/knapsack.rs index d3723684d..b99c63a16 100644 --- a/src/unit_tests/models/misc/knapsack.rs +++ b/src/unit_tests/models/misc/knapsack.rs @@ -3,10 +3,12 @@ use crate::solvers::BruteForceProblem as _; #[test] fn test_knapsack_deserialization_rejects_mismatched_lengths() { - assert!(serde_json::from_value::( - serde_json::json!({"weights": [1], "values": [2, 3], "capacity": 3}) - ) - .is_err()); + assert!( + serde_json::from_value::( + serde_json::json!({"weights": [1], "values": [2, 3], "capacity": 3}) + ) + .is_err() + ); } #[test] 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 77a59683c..55e8824c1 100644 --- a/src/unit_tests/models/misc/kth_largest_m_tuple.rs +++ b/src/unit_tests/models/misc/kth_largest_m_tuple.rs @@ -7,10 +7,12 @@ fn tuple_count_must_fit_usize() { KthLargestMTuple::try_new(sets.clone(), 1, 1), Err(crate::registry::ConstructionError::IntegerOverflow(_)) )); - assert!(serde_json::from_value::( - serde_json::json!({"sets": sets, "k": 1, "bound": 1}) - ) - .is_err()); + assert!( + serde_json::from_value::( + serde_json::json!({"sets": sets, "k": 1, "bound": 1}) + ) + .is_err() + ); let problem = KthLargestMTuple::try_new(vec![vec![1, 2]; usize::BITS as usize - 1], 1, 1).unwrap(); assert_eq!(problem.total_tuples(), 1usize << (usize::BITS - 1)); diff --git a/src/unit_tests/models/misc/longest_common_subsequence.rs b/src/unit_tests/models/misc/longest_common_subsequence.rs index 2c0cbc80d..c113cac7c 100644 --- a/src/unit_tests/models/misc/longest_common_subsequence.rs +++ b/src/unit_tests/models/misc/longest_common_subsequence.rs @@ -151,7 +151,7 @@ fn test_lcs_empty_string_max_length_zero() { let problem = LongestCommonSubsequence::new(2, vec![vec![], vec![0, 1]]); assert_eq!(problem.max_length(), 0); assert_eq!(problem.dimensions(), Vec::::new()); // empty config space - // Empty config is the only valid config; LCS length is 0 + // Empty config is the only valid config; LCS length is 0 assert_eq!(problem.evaluate(&vec![]).unwrap(), Max(Some(0))); } diff --git a/src/unit_tests/models/misc/maximum_likelihood_ranking.rs b/src/unit_tests/models/misc/maximum_likelihood_ranking.rs index 950ac5000..5b16d250d 100644 --- a/src/unit_tests/models/misc/maximum_likelihood_ranking.rs +++ b/src/unit_tests/models/misc/maximum_likelihood_ranking.rs @@ -204,10 +204,12 @@ fn test_maximum_likelihood_ranking_rejects_invalid_json() { vec![vec![0, 1, 2], vec![1, 0, 1], vec![2, 1, 0]], vec![vec![0, i64::MAX], vec![1, 0]], ] { - assert!(serde_json::from_value::( - serde_json::json!({ "matrix": matrix }) - ) - .is_err()); + assert!( + serde_json::from_value::( + serde_json::json!({ "matrix": matrix }) + ) + .is_err() + ); } let problem: MaximumLikelihoodRanking = serde_json::from_value(serde_json::json!({ "matrix": [[0, i64::MAX], [0, 0]] })).unwrap(); diff --git a/src/unit_tests/models/misc/minimum_axiom_set.rs b/src/unit_tests/models/misc/minimum_axiom_set.rs index 25f5db3f8..78c4249f3 100644 --- a/src/unit_tests/models/misc/minimum_axiom_set.rs +++ b/src/unit_tests/models/misc/minimum_axiom_set.rs @@ -105,11 +105,13 @@ fn test_minimum_axiom_set_evaluate_wrong_length() { #[test] fn test_minimum_axiom_set_evaluate_out_of_range() { let problem = canonical_instance(); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([2, false, false, false, false, false, false, false]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([2, false, false, false, false, false, false, false]) + ) + .is_err() + ); } #[test] 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 09c9cd871..adc04a706 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 @@ -25,6 +25,22 @@ fn test_minimum_code_generation_one_register_validates_persisted_input() { } use crate::types::Min; +#[test] +fn test_instruction_count_accepts_exact_limit_and_rejects_overflow() { + for additional in [1, 2] { + let last_valid_count = i64::MAX - additional; + assert_eq!( + add_instructions(last_valid_count, additional).unwrap(), + i64::MAX + ); + assert!(matches!( + add_instructions(last_valid_count + 1, additional), + Err(crate::traits::EvaluationError::IntegerOverflow(message)) + if message == "counting one-register instructions" + )); + } +} + #[test] fn test_minimum_code_generation_one_register_creation() { let problem = MinimumCodeGenerationOneRegister::new( @@ -251,23 +267,18 @@ fn test_minimum_code_generation_one_register_paper_example() { } #[test] -fn test_minimum_code_generation_one_register_lost_value() { - // Test that a value computed but not stored and overwritten becomes unavailable +fn test_minimum_code_generation_one_register_stores_live_value_before_overwrite() { // v0 = op(v1, v2), v1 = op(v3, v4), v2 = op(v3, v5) // Leaves: {3, 4, 5}, Internal: {0, 1, 2} - // If we evaluate v1, then v2 (overwriting v1 in register without storing), - // then v0 needs v1 which is lost. let problem = MinimumCodeGenerationOneRegister::new( 6, vec![(0, 1), (0, 2), (1, 3), (1, 4), (2, 3), (2, 5)], 3, ); - // Order: v1, v2, v0 => config: v0->2, v1->0, v2->1 - let config = vec![2, 0, 1]; - // v1 computed first, but v1 is needed by v0. - // When v2 is computed, we should check if v1 needs to be stored. - // future_uses[1] = 1 (used by v0), so STORE v1 before computing v2. - // So this should NOT be None — the simulation stores v1 automatically. - let result = problem.simulate(&config).unwrap(); - assert!(result.is_some()); + // Each child needs LOAD + OP. Preserve the first child with one STORE, + // then combine the stored child and the register with one OP: 2 + 1 + 2 + 1. + for config in [vec![2, 0, 1], vec![2, 1, 0]] { + assert_eq!(problem.simulate(&config).unwrap(), Some(6)); + assert_eq!(problem.evaluate(&config).unwrap(), Min(Some(6))); + } } diff --git a/src/unit_tests/models/misc/minimum_decision_tree.rs b/src/unit_tests/models/misc/minimum_decision_tree.rs index dd68182ef..6ad14e0d8 100644 --- a/src/unit_tests/models/misc/minimum_decision_tree.rs +++ b/src/unit_tests/models/misc/minimum_decision_tree.rs @@ -132,7 +132,7 @@ fn test_minimum_decision_tree_two_objects() { 1, ); assert_eq!(problem.dimensions().len(), 1); // 2^(2-1) - 1 = 1 slot - // Test at root, both objects go to leaves at depth 1 + // Test at root, both objects go to leaves at depth 1 assert_eq!(problem.evaluate(&vec![0]).unwrap(), Min(Some(2))); // depth 1 + depth 1 assert_eq!(problem.evaluate(&vec![1]).unwrap(), Min(None)); // sentinel=1 is leaf at root, both objects at same leaf } diff --git a/src/unit_tests/models/misc/minimum_discrete_planar_inverse_kinematics.rs b/src/unit_tests/models/misc/minimum_discrete_planar_inverse_kinematics.rs index 9eeeaa600..db544d25f 100644 --- a/src/unit_tests/models/misc/minimum_discrete_planar_inverse_kinematics.rs +++ b/src/unit_tests/models/misc/minimum_discrete_planar_inverse_kinematics.rs @@ -152,27 +152,33 @@ fn test_minimum_discrete_planar_inverse_kinematics_problem_name() { #[test] fn test_minimum_discrete_planar_inverse_kinematics_rejects_invalid_numeric_data() { - assert!(MinimumDiscretePlanarInverseKinematics::new( - vec![f64::NAN], - (0.0, 0.0), - vec![vec![0.0]], - vec![], - ) - .is_err()); - assert!(MinimumDiscretePlanarInverseKinematics::new( - vec![1.0], - (f64::INFINITY, 0.0), - vec![vec![0.0]], - vec![], - ) - .is_err()); - assert!(MinimumDiscretePlanarInverseKinematics::new( - vec![1.0], - (0.0, 0.0), - vec![vec![f64::NEG_INFINITY]], - vec![], - ) - .is_err()); + assert!( + MinimumDiscretePlanarInverseKinematics::new( + vec![f64::NAN], + (0.0, 0.0), + vec![vec![0.0]], + vec![], + ) + .is_err() + ); + assert!( + MinimumDiscretePlanarInverseKinematics::new( + vec![1.0], + (f64::INFINITY, 0.0), + vec![vec![0.0]], + vec![], + ) + .is_err() + ); + assert!( + MinimumDiscretePlanarInverseKinematics::new( + vec![1.0], + (0.0, 0.0), + vec![vec![f64::NEG_INFINITY]], + vec![], + ) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/misc/non_liveness_free_petri_net.rs b/src/unit_tests/models/misc/non_liveness_free_petri_net.rs index 987c583b8..5bee37756 100644 --- a/src/unit_tests/models/misc/non_liveness_free_petri_net.rs +++ b/src/unit_tests/models/misc/non_liveness_free_petri_net.rs @@ -191,12 +191,14 @@ fn test_non_liveness_rejects_marking_length_mismatch() { #[test] fn test_non_liveness_rejects_free_choice_violation() { // t0 has preset {s0}, t1 has preset {s0, s1} -- they share s0 but have different presets - assert!(NonLivenessFreePetriNet::new( - 2, - 2, - vec![(0, 0), (0, 1), (1, 1)], - vec![(0, 0), (1, 1)], - vec![1, 1], - ) - .is_err()); + assert!( + NonLivenessFreePetriNet::new( + 2, + 2, + vec![(0, 0), (0, 1), (1, 1)], + vec![(0, 0), (1, 1)], + vec![1, 1], + ) + .is_err() + ); } diff --git a/src/unit_tests/models/misc/open_shop_scheduling.rs b/src/unit_tests/models/misc/open_shop_scheduling.rs index 77e75989c..d7ad8778c 100644 --- a/src/unit_tests/models/misc/open_shop_scheduling.rs +++ b/src/unit_tests/models/misc/open_shop_scheduling.rs @@ -240,11 +240,13 @@ fn test_open_shop_scheduling_construction_paths_reject_invalid_matrices() { (2, vec![vec![i64::MAX, 1]]), ] { assert!(OpenShopScheduling::try_new(machines, times.clone()).is_err()); - assert!(OpenShopScheduling::try_from(OpenShopSchedulingCreateSpec { - num_processors: machines, - processing_times: times.clone(), - }) - .is_err()); + assert!( + OpenShopScheduling::try_from(OpenShopSchedulingCreateSpec { + num_processors: machines, + processing_times: times.clone(), + }) + .is_err() + ); assert!( serde_json::from_value::(serde_json::json!({ "num_machines": machines, "processing_times": times, diff --git a/src/unit_tests/models/misc/optimum_communication_spanning_tree.rs b/src/unit_tests/models/misc/optimum_communication_spanning_tree.rs index 8d7520a3b..b4e17b536 100644 --- a/src/unit_tests/models/misc/optimum_communication_spanning_tree.rs +++ b/src/unit_tests/models/misc/optimum_communication_spanning_tree.rs @@ -147,11 +147,13 @@ fn test_ocst_evaluate_invalid() { Min(None) ); // Value > 1 - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([2, false, true, false, false, false]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([2, false, true, false, false, false]) + ) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/misc/partially_ordered_knapsack.rs b/src/unit_tests/models/misc/partially_ordered_knapsack.rs index bd7167a58..682f80df7 100644 --- a/src/unit_tests/models/misc/partially_ordered_knapsack.rs +++ b/src/unit_tests/models/misc/partially_ordered_knapsack.rs @@ -167,11 +167,13 @@ fn test_partially_ordered_knapsack_evaluate_wrong_config_length() { #[test] fn test_partially_ordered_knapsack_evaluate_invalid_variable_value() { let problem = example_instance(); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([2, false, false, false, false, false]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([2, false, false, false, false, false]) + ) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/misc/partition.rs b/src/unit_tests/models/misc/partition.rs index 9177e1341..9f5102fe4 100644 --- a/src/unit_tests/models/misc/partition.rs +++ b/src/unit_tests/models/misc/partition.rs @@ -16,22 +16,28 @@ fn test_partition_basic() { fn test_partition_evaluate_satisfying() { let problem = Partition::new(vec![3, 1, 1, 2, 2, 1]).unwrap(); // A' = {3, 2} (indices 0, 3), sum = 5 = 10/2 - assert!(problem - .evaluate(&vec![true, false, false, true, false, false]) - .unwrap()); + assert!( + problem + .evaluate(&vec![true, false, false, true, false, false]) + .unwrap() + ); } #[test] fn test_partition_evaluate_unsatisfying() { let problem = Partition::new(vec![3, 1, 1, 2, 2, 1]).unwrap(); // All in first subset, selected sum = 0 != 5 - assert!(!problem - .evaluate(&vec![false, false, false, false, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![false, false, false, false, false, false]) + .unwrap() + ); // All in second subset, selected sum = 10 != 5 - assert!(!problem - .evaluate(&vec![true, true, true, true, true, true]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, true, true, true, true, true]) + .unwrap() + ); } #[test] @@ -50,11 +56,13 @@ fn test_partition_evaluate_wrong_length() { #[test] fn test_partition_evaluate_invalid_value() { let problem = Partition::new(vec![3, 1, 1, 2, 2, 1]).unwrap(); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([2, false, false, false, false, false]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([2, false, false, false, false, false]) + ) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/misc/preemptive_scheduling.rs b/src/unit_tests/models/misc/preemptive_scheduling.rs index b0ba235bb..4d42becb5 100644 --- a/src/unit_tests/models/misc/preemptive_scheduling.rs +++ b/src/unit_tests/models/misc/preemptive_scheduling.rs @@ -96,9 +96,10 @@ fn test_preemptive_scheduling_evaluate_wrong_length() { let p = small_instance(); assert!(p.evaluate(&vec![]).is_err()); assert!(p.evaluate(&vec![vec![true, true, false]]).is_err()); - assert!(p - .evaluate(&vec![vec![true, true, false], vec![true, false]]) - .is_err()); + assert!( + p.evaluate(&vec![vec![true, true, false], vec![true, false]]) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/misc/production_planning.rs b/src/unit_tests/models/misc/production_planning.rs index 49058f798..0528e2752 100644 --- a/src/unit_tests/models/misc/production_planning.rs +++ b/src/unit_tests/models/misc/production_planning.rs @@ -35,16 +35,18 @@ fn test_production_planning_validates_persisted_input() { #[test] fn create_spec_rejects_period_vector_mismatch() { assert_eq!(ProductionPlanningCreateSpec::FIELDS[0].name, "num_periods"); - assert!(ProductionPlanning::try_from(ProductionPlanningCreateSpec { - num_periods: 1, - demands: vec![], - capacities: vec![1], - setup_costs: vec![1], - production_costs: vec![1], - inventory_costs: vec![1], - cost_bound: 1 - }) - .is_err()); + assert!( + ProductionPlanning::try_from(ProductionPlanningCreateSpec { + num_periods: 1, + demands: vec![], + capacities: vec![1], + setup_costs: vec![1], + production_costs: vec![1], + inventory_costs: vec![1], + cost_bound: 1 + }) + .is_err() + ); } use crate::solvers::BruteForce; use crate::traits::Problem; diff --git a/src/unit_tests/models/misc/rectilinear_picture_compression.rs b/src/unit_tests/models/misc/rectilinear_picture_compression.rs index 854480243..69e2f7444 100644 --- a/src/unit_tests/models/misc/rectilinear_picture_compression.rs +++ b/src/unit_tests/models/misc/rectilinear_picture_compression.rs @@ -24,10 +24,12 @@ fn test_rectilinear_picture_compression_rejects_invalid_json_without_panicking() serde_json::json!([[]]), serde_json::json!([[true], []]), ] { - assert!(serde_json::from_value::( - serde_json::json!({"matrix": matrix, "bound": 1}) - ) - .is_err()); + assert!( + serde_json::from_value::( + serde_json::json!({"matrix": matrix, "bound": 1}) + ) + .is_err() + ); } } diff --git a/src/unit_tests/models/misc/scheduling_with_individual_deadlines.rs b/src/unit_tests/models/misc/scheduling_with_individual_deadlines.rs index c844d7db8..099078ad8 100644 --- a/src/unit_tests/models/misc/scheduling_with_individual_deadlines.rs +++ b/src/unit_tests/models/misc/scheduling_with_individual_deadlines.rs @@ -31,15 +31,15 @@ fn create_spec_rejects_deadline_count_mismatch() { SchedulingWithIndividualDeadlinesCreateSpec::FIELDS[2].name, "deadlines" ); - assert!(SchedulingWithIndividualDeadlines::try_from( - SchedulingWithIndividualDeadlinesCreateSpec { + assert!( + SchedulingWithIndividualDeadlines::try_from(SchedulingWithIndividualDeadlinesCreateSpec { num_tasks: 2, num_processors: 1, deadlines: vec![1], precedences: None - } - ) - .is_err()); + }) + .is_err() + ); } use crate::solvers::BruteForce; use crate::traits::Problem; diff --git a/src/unit_tests/models/misc/sequencing_to_minimize_weighted_tardiness.rs b/src/unit_tests/models/misc/sequencing_to_minimize_weighted_tardiness.rs index acfa4f316..26c1f1035 100644 --- a/src/unit_tests/models/misc/sequencing_to_minimize_weighted_tardiness.rs +++ b/src/unit_tests/models/misc/sequencing_to_minimize_weighted_tardiness.rs @@ -41,15 +41,17 @@ fn create_spec_rejects_vector_length_mismatch() { SequencingToMinimizeWeightedTardinessCreateSpec::FIELDS[1].name, "weights" ); - assert!(SequencingToMinimizeWeightedTardiness::try_from( - SequencingToMinimizeWeightedTardinessCreateSpec { - lengths: vec![1], - weights: vec![], - deadlines: vec![1], - bound: 0 - } - ) - .is_err()); + assert!( + SequencingToMinimizeWeightedTardiness::try_from( + SequencingToMinimizeWeightedTardinessCreateSpec { + lengths: vec![1], + weights: vec![], + deadlines: vec![1], + bound: 0 + } + ) + .is_err() + ); } use crate::solvers::BruteForce; use crate::traits::Problem; diff --git a/src/unit_tests/models/misc/sequencing_with_deadlines_and_set_up_times.rs b/src/unit_tests/models/misc/sequencing_with_deadlines_and_set_up_times.rs index 26f9f9f0a..8df65140a 100644 --- a/src/unit_tests/models/misc/sequencing_with_deadlines_and_set_up_times.rs +++ b/src/unit_tests/models/misc/sequencing_with_deadlines_and_set_up_times.rs @@ -1,4 +1,17 @@ use super::*; + +#[test] +fn test_sequencing_with_deadlines_and_set_up_times_evaluate_setup_overflow() { + let problem = SequencingWithDeadlinesAndSetUpTimes::new( + vec![i64::MAX, 1], + vec![i64::MAX; 2], + vec![0, 1], + vec![0, 1], + ); + assert!(matches!(problem.evaluate(&vec![0, 1]), + Err(crate::traits::EvaluationError::IntegerOverflow(message)) + if message == "adding sequencing setup time")); +} use crate::solvers::BruteForce; use crate::solvers::BruteForceProblem as _; use crate::traits::Problem; diff --git a/src/unit_tests/models/misc/subset_product.rs b/src/unit_tests/models/misc/subset_product.rs index 032a6b9b3..b581bfc77 100644 --- a/src/unit_tests/models/misc/subset_product.rs +++ b/src/unit_tests/models/misc/subset_product.rs @@ -40,30 +40,40 @@ fn test_subsetproduct_basic() { fn test_subsetproduct_evaluate_satisfying() { let problem = SubsetProduct::new(vec![2u32, 3, 5, 7, 6, 10], 210u32); // {2, 3, 5, 7} = 210 - assert!(problem - .evaluate(&vec![true, true, true, true, false, false]) - .unwrap()); + assert!( + problem + .evaluate(&vec![true, true, true, true, false, false]) + .unwrap() + ); // {3, 7, 10} = 210 - assert!(problem - .evaluate(&vec![false, true, false, true, false, true]) - .unwrap()); + assert!( + problem + .evaluate(&vec![false, true, false, true, false, true]) + .unwrap() + ); } #[test] fn test_subsetproduct_evaluate_unsatisfying() { let problem = SubsetProduct::new(vec![2u32, 3, 5, 7, 6, 10], 210u32); // {2, 3} = 6 != 210 - assert!(!problem - .evaluate(&vec![true, true, false, false, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, true, false, false, false, false]) + .unwrap() + ); // empty = 1 != 210 - assert!(!problem - .evaluate(&vec![false, false, false, false, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![false, false, false, false, false, false]) + .unwrap() + ); // all = 2*3*5*7*6*10 = 12600 != 210 - assert!(!problem - .evaluate(&vec![true, true, true, true, true, true]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, true, true, true, true, true]) + .unwrap() + ); } #[test] @@ -203,10 +213,14 @@ fn test_subsetproduct_zero_target_panic() { #[test] fn test_subsetproduct_large_integer_input() { let problem = SubsetProduct::new(vec![2i128, 3, 5, 7, 6, 10], 210i128); - assert!(problem - .evaluate(&vec![true, true, true, true, false, false]) - .unwrap()); // 2*3*5*7 = 210 - assert!(!problem - .evaluate(&vec![true, true, false, false, false, false]) - .unwrap()); // 2*3 = 6 + assert!( + problem + .evaluate(&vec![true, true, true, true, false, false]) + .unwrap() + ); // 2*3*5*7 = 210 + assert!( + !problem + .evaluate(&vec![true, true, false, false, false, false]) + .unwrap() + ); // 2*3 = 6 } diff --git a/src/unit_tests/models/misc/subset_sum.rs b/src/unit_tests/models/misc/subset_sum.rs index fffee4f93..b09db7c71 100644 --- a/src/unit_tests/models/misc/subset_sum.rs +++ b/src/unit_tests/models/misc/subset_sum.rs @@ -6,10 +6,10 @@ use num_bigint::BigUint; #[test] fn test_subsetsum_deserialization_validates_positive_sizes() { - assert!(serde_json::from_value::( - serde_json::json!({"sizes": ["0"], "target": "0"}) - ) - .is_err()); + assert!( + serde_json::from_value::(serde_json::json!({"sizes": ["0"], "target": "0"})) + .is_err() + ); let empty: SubsetSum = serde_json::from_value(serde_json::json!({"sizes": [], "target": "0"})).unwrap(); assert!(empty.evaluate(&vec![]).unwrap().0); @@ -38,30 +38,40 @@ fn test_subsetsum_basic() { fn test_subsetsum_evaluate_satisfying() { let problem = SubsetSum::new(vec![3u32, 7, 1, 8, 2, 4], 11u32); // {3, 8} = 11 - assert!(problem - .evaluate(&vec![true, false, false, true, false, false]) - .unwrap()); + assert!( + problem + .evaluate(&vec![true, false, false, true, false, false]) + .unwrap() + ); // {7, 4} = 11 - assert!(problem - .evaluate(&vec![false, true, false, false, false, true]) - .unwrap()); + assert!( + problem + .evaluate(&vec![false, true, false, false, false, true]) + .unwrap() + ); } #[test] fn test_subsetsum_evaluate_unsatisfying() { let problem = SubsetSum::new(vec![3u32, 7, 1, 8, 2, 4], 11u32); // {3, 7} = 10 ≠ 11 - assert!(!problem - .evaluate(&vec![true, true, false, false, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, true, false, false, false, false]) + .unwrap() + ); // empty = 0 ≠ 11 - assert!(!problem - .evaluate(&vec![false, false, false, false, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![false, false, false, false, false, false]) + .unwrap() + ); // all = 25 ≠ 11 - assert!(!problem - .evaluate(&vec![true, true, true, true, true, true]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, true, true, true, true, true]) + .unwrap() + ); } #[test] @@ -195,12 +205,16 @@ fn test_subsetsum_zero_size_panic() { #[test] fn test_subsetsum_large_integer_input() { let problem = SubsetSum::new(vec![3i128, 7, 1, 8, 2, 4], 11i128); - assert!(problem - .evaluate(&vec![true, false, false, true, false, false]) - .unwrap()); // 3 + 8 = 11 - assert!(!problem - .evaluate(&vec![true, true, false, false, false, false]) - .unwrap()); // 3 + 7 = 10 + assert!( + problem + .evaluate(&vec![true, false, false, true, false, false]) + .unwrap() + ); // 3 + 8 = 11 + assert!( + !problem + .evaluate(&vec![true, true, false, false, false, false]) + .unwrap() + ); // 3 + 7 = 10 } #[test] diff --git a/src/unit_tests/models/misc/three_partition.rs b/src/unit_tests/models/misc/three_partition.rs index 44c354c02..5048e1bdc 100644 --- a/src/unit_tests/models/misc/three_partition.rs +++ b/src/unit_tests/models/misc/three_partition.rs @@ -97,9 +97,10 @@ fn test_three_partition_paper_example() { let solver = BruteForce::new(); let all = solver.find_all_witnesses(&problem).unwrap(); assert_eq!(all.len(), 8); - assert!(all - .iter() - .all(|sol| problem.evaluate(sol).unwrap() == Or(true))); + assert!( + all.iter() + .all(|sol| problem.evaluate(sol).unwrap() == Or(true)) + ); } #[test] diff --git a/src/unit_tests/models/misc/timetable_design.rs b/src/unit_tests/models/misc/timetable_design.rs index 12f660eaf..ce8fc166e 100644 --- a/src/unit_tests/models/misc/timetable_design.rs +++ b/src/unit_tests/models/misc/timetable_design.rs @@ -32,15 +32,17 @@ fn test_timetable_design_validates_persisted_input() { #[test] fn create_spec_rejects_matrix_shape_mismatch() { assert_eq!(TimetableDesignCreateSpec::FIELDS[3].name, "craftsman_avail"); - assert!(TimetableDesign::try_from(TimetableDesignCreateSpec { - num_periods: 1, - num_craftsmen: 1, - num_tasks: 1, - craftsman_avail: vec![], - task_avail: vec![vec![true]], - requirements: vec![vec![1]] - }) - .is_err()); + assert!( + TimetableDesign::try_from(TimetableDesignCreateSpec { + num_periods: 1, + num_craftsmen: 1, + num_tasks: 1, + craftsman_avail: vec![], + task_avail: vec![vec![true]], + requirements: vec![vec![1]] + }) + .is_err() + ); } use crate::solvers::BruteForce; use crate::traits::Problem; diff --git a/src/unit_tests/models/set/comparative_containment.rs b/src/unit_tests/models/set/comparative_containment.rs index 8d0ecd984..39702120f 100644 --- a/src/unit_tests/models/set/comparative_containment.rs +++ b/src/unit_tests/models/set/comparative_containment.rs @@ -88,11 +88,13 @@ fn test_comparative_containment_rejects_invalid_configs() { problem.evaluate(&vec![true, false, false]), Err(crate::traits::EvaluationError::InvalidConfiguration(_)) )); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([true, false, false, 2]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([true, false, false, 2]) + ) + .is_err() + ); } #[test] @@ -158,74 +160,56 @@ fn test_comparative_containment_weight_sums() { #[test] fn test_comparative_containment_rejects_mismatched_r_weights() { - assert!(ComparativeContainment::with_weights( - 2, - vec![vec![0]], - vec![vec![0]], - vec![1, 2], - vec![1] - ) - .is_err()); + assert!( + ComparativeContainment::with_weights(2, vec![vec![0]], vec![vec![0]], vec![1, 2], vec![1]) + .is_err() + ); } #[test] fn test_comparative_containment_rejects_mismatched_s_weights() { - assert!(ComparativeContainment::with_weights( - 2, - vec![vec![0]], - vec![vec![0]], - vec![1], - vec![1, 2] - ) - .is_err()); + assert!( + ComparativeContainment::with_weights(2, vec![vec![0]], vec![vec![0]], vec![1], vec![1, 2]) + .is_err() + ); } #[test] fn test_comparative_containment_rejects_nonpositive_i64_weights() { - assert!(ComparativeContainment::with_weights( - 2, - vec![vec![0]], - vec![vec![0]], - vec![0], - vec![1] - ) - .is_err()); + assert!( + ComparativeContainment::with_weights(2, vec![vec![0]], vec![vec![0]], vec![0], vec![1]) + .is_err() + ); } #[test] fn test_comparative_containment_rejects_nonpositive_i64_s_weights() { - assert!(ComparativeContainment::with_weights( - 2, - vec![vec![0]], - vec![vec![0]], - vec![1], - vec![0] - ) - .is_err()); + assert!( + ComparativeContainment::with_weights(2, vec![vec![0]], vec![vec![0]], vec![1], vec![0]) + .is_err() + ); } #[test] fn test_comparative_containment_rejects_non_finite_f64_weights() { - assert!(ComparativeContainment::with_weights( - 2, - vec![vec![0]], - vec![vec![0]], - vec![f64::NAN], - vec![1.0], - ) - .is_err()); + assert!( + ComparativeContainment::with_weights( + 2, + vec![vec![0]], + vec![vec![0]], + vec![f64::NAN], + vec![1.0], + ) + .is_err() + ); } #[test] fn test_comparative_containment_rejects_nonpositive_f64_weights() { - assert!(ComparativeContainment::with_weights( - 2, - vec![vec![0]], - vec![vec![0]], - vec![1.0], - vec![0.0] - ) - .is_err()); + assert!( + ComparativeContainment::with_weights(2, vec![vec![0]], vec![vec![0]], vec![1.0], vec![0.0]) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/set/consecutive_sets.rs b/src/unit_tests/models/set/consecutive_sets.rs index 0bb7fdf3c..c079804df 100644 --- a/src/unit_tests/models/set/consecutive_sets.rs +++ b/src/unit_tests/models/set/consecutive_sets.rs @@ -25,13 +25,17 @@ fn test_consecutive_sets_evaluation() { 6, ); // YES: w = [0, 4, 2, 5, 1, 3] - assert!(problem - .evaluate(&vec![Some(0), Some(4), Some(2), Some(5), Some(1), Some(3)]) - .unwrap()); + assert!( + problem + .evaluate(&vec![Some(0), Some(4), Some(2), Some(5), Some(1), Some(3)]) + .unwrap() + ); // NO: identity string [0, 1, 2, 3, 4, 5] — {0,4} not adjacent - assert!(!problem - .evaluate(&vec![Some(0), Some(1), Some(2), Some(3), Some(4), Some(5)]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![Some(0), Some(1), Some(2), Some(3), Some(4), Some(5)]) + .unwrap() + ); // NO: all unused (empty string can't satisfy non-empty subsets) assert!(!problem.evaluate(&vec![None; 6]).unwrap()); } @@ -81,17 +85,21 @@ fn test_consecutive_sets_rejects_internal_unused() { // Internal "unused" symbol should be rejected let problem = ConsecutiveSets::new(3, vec![vec![0, 1]], 4); // [0, 3, 1, 3] has "unused" (3) at position 1, which is internal - assert!(!problem - .evaluate(&vec![Some(0), None, Some(1), None]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![Some(0), None, Some(1), None]) + .unwrap() + ); } #[test] fn test_consecutive_sets_accepts_shorter_string_with_trailing_unused() { let problem = ConsecutiveSets::new(3, vec![vec![0, 1]], 4); - assert!(problem - .evaluate(&vec![Some(0), Some(1), None, None]) - .unwrap()); + assert!( + problem + .evaluate(&vec![Some(0), Some(1), None, None]) + .unwrap() + ); } #[test] 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 9ba110205..d3bd91a19 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 @@ -56,11 +56,10 @@ fn test_exact_cover_by_3_sets_rejects_wrong_config_length() { #[test] fn test_exact_cover_by_3_sets_rejects_non_binary_config_values() { let problem = ExactCoverBy3Sets::new(6, vec![[0, 1, 2], [3, 4, 5], [0, 3, 4]]); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([true, true, 2]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn(&problem, &serde_json::json!([true, true, 2])) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/set/minimum_cardinality_key.rs b/src/unit_tests/models/set/minimum_cardinality_key.rs index 260af4620..95df8ae50 100644 --- a/src/unit_tests/models/set/minimum_cardinality_key.rs +++ b/src/unit_tests/models/set/minimum_cardinality_key.rs @@ -117,11 +117,13 @@ fn test_minimum_cardinality_key_invalid_config() { Err(crate::traits::EvaluationError::InvalidConfiguration(_)) )); // Value > 1. - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([2, true, false, false, false, false]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([2, true, false, false, false, false]) + ) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/set/minimum_hitting_set.rs b/src/unit_tests/models/set/minimum_hitting_set.rs index 566abf56b..c672cddb3 100644 --- a/src/unit_tests/models/set/minimum_hitting_set.rs +++ b/src/unit_tests/models/set/minimum_hitting_set.rs @@ -65,11 +65,13 @@ fn test_minimum_hitting_set_evaluate_valid_and_invalid() { problem.evaluate(&vec![true, false, false, false]).unwrap(), Min(None) ); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([false, 2, false, true]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([false, 2, false, true]) + ) + .is_err() + ); assert!(problem.is_valid_solution(&[false, true, false, true])); assert!(!problem.is_valid_solution(&[true, false, false, false])); } @@ -112,9 +114,11 @@ fn test_minimum_hitting_set_bruteforce_optimum_issue_example() { let best_solutions = solver.find_all_witnesses(&problem).unwrap(); let best_solution_set: HashSet> = best_solutions.iter().cloned().collect(); assert!(best_solution_set.contains(&issue_example_config())); - assert!(best_solutions - .iter() - .all(|config| problem.evaluate(config).unwrap() == Min(Some(3)))); + assert!( + best_solutions + .iter() + .all(|config| problem.evaluate(config).unwrap() == Min(Some(3))) + ); } #[test] diff --git a/src/unit_tests/models/set/prime_attribute_name.rs b/src/unit_tests/models/set/prime_attribute_name.rs index caea58daa..a9015f3a7 100644 --- a/src/unit_tests/models/set/prime_attribute_name.rs +++ b/src/unit_tests/models/set/prime_attribute_name.rs @@ -51,9 +51,11 @@ fn test_prime_attribute_name_creation() { fn test_prime_attribute_name_evaluate_yes() { let problem = example1(); // {2, 3} is a candidate key containing attribute 3 - assert!(problem - .evaluate(&vec![false, false, true, true, false, false]) - .unwrap()); + assert!( + problem + .evaluate(&vec![false, false, true, true, false, false]) + .unwrap() + ); } #[test] @@ -61,13 +63,17 @@ fn test_prime_attribute_name_evaluate_no() { let problem = example2(); // Only key is {0,1} which doesn't contain attribute 3 // Config selecting {0,1}: this is a candidate key but doesn't contain query=3 - assert!(!problem - .evaluate(&vec![true, true, false, false, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, true, false, false, false, false]) + .unwrap() + ); // Config selecting {2,3}: not a superkey since closure({2,3}) != A - assert!(!problem - .evaluate(&vec![false, false, true, true, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![false, false, true, true, false, false]) + .unwrap() + ); } #[test] @@ -75,36 +81,44 @@ fn test_prime_attribute_name_evaluate_superkey_not_minimal() { let problem = example1(); // {1,2,3} has closure = A (since {2,3}->rest), but it's not minimal // because {2,3} alone is also a superkey - assert!(!problem - .evaluate(&vec![false, true, true, true, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![false, true, true, true, false, false]) + .unwrap() + ); } #[test] fn test_prime_attribute_name_evaluate_not_superkey() { let problem = example1(); // {0} alone: closure({0}) = {0}, not all of A - assert!(!problem - .evaluate(&vec![true, false, false, false, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, false, false, false, false, false]) + .unwrap() + ); } #[test] fn test_prime_attribute_name_evaluate_query_not_in_k() { let problem = example1(); // {0,1} is a candidate key but doesn't contain attribute 3 - assert!(!problem - .evaluate(&vec![true, true, false, false, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, true, false, false, false, false]) + .unwrap() + ); } #[test] fn test_prime_attribute_name_evaluate_all_selected() { let problem = example1(); // All attributes selected: superkey but not minimal - assert!(!problem - .evaluate(&vec![true, true, true, true, true, true]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, true, true, true, true, true]) + .unwrap() + ); } #[test] @@ -116,11 +130,13 @@ fn test_prime_attribute_name_evaluate_invalid_config() { Err(crate::traits::EvaluationError::InvalidConfiguration(_)) )); // Non-binary value - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([false, false, true, 2, false, false]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([false, false, true, 2, false, false]) + ) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/set/set_basis.rs b/src/unit_tests/models/set/set_basis.rs index 40706c8c0..4349dcc24 100644 --- a/src/unit_tests/models/set/set_basis.rs +++ b/src/unit_tests/models/set/set_basis.rs @@ -49,25 +49,29 @@ fn test_set_basis_evaluation() { let problem = issue_example_problem(3); assert!(problem.evaluate(&canonical_solution()).unwrap()); - assert!(!problem - .evaluate(&vec![ - vec![true, true, false, false], - vec![false; 4], - vec![false, false, true, false], - ]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![ + vec![true, true, false, false], + vec![false; 4], + vec![false, false, true, false], + ]) + .unwrap() + ); } #[test] fn test_set_basis_no_solution_for_k_two() { let problem = issue_example_problem(2); - assert!(!problem - .evaluate(&vec![ - vec![true, true, false, false], - vec![false, false, true, false], - ]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![ + vec![true, true, false, false], + vec![false, false, true, false], + ]) + .unwrap() + ); let solver = BruteForce::new(); assert!(solver.find_all_witnesses(&problem).unwrap().is_empty()); @@ -83,9 +87,11 @@ fn test_set_basis_solver() { assert_eq!(solutions.len(), 12); assert_eq!(solution_set.len(), 12); assert!(solution_set.contains(&canonical_solution())); - assert!(solutions - .iter() - .all(|solution| problem.evaluate(solution).unwrap().0)); + assert!( + solutions + .iter() + .all(|solution| problem.evaluate(solution).unwrap().0) + ); } #[test] @@ -115,11 +121,13 @@ fn test_set_basis_paper_example() { #[test] fn test_set_basis_invalid_config_values() { let problem = issue_example_problem(3); - assert!(crate::registry::DynProblem::evaluate_dyn( - &problem, - &serde_json::json!([[2, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0]]) - ) - .is_err()); + assert!( + crate::registry::DynProblem::evaluate_dyn( + &problem, + &serde_json::json!([[2, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0]]) + ) + .is_err() + ); } #[test] diff --git a/src/unit_tests/models/set/set_splitting.rs b/src/unit_tests/models/set/set_splitting.rs index 0d8dcaf3d..88a3e1449 100644 --- a/src/unit_tests/models/set/set_splitting.rs +++ b/src/unit_tests/models/set/set_splitting.rs @@ -73,12 +73,16 @@ fn test_set_splitting_evaluate_multiple_subsets() { #[test] fn test_set_splitting_is_valid_solution() { let problem = SetSplitting::new(4, vec![vec![0, 1], vec![2, 3]]); - assert!(problem - .is_valid_solution(&[false, true, false, true]) - .unwrap()); - assert!(!problem - .is_valid_solution(&[false, false, false, false]) - .unwrap()); + assert!( + problem + .is_valid_solution(&[false, true, false, true]) + .unwrap() + ); + assert!( + !problem + .is_valid_solution(&[false, false, false, false]) + .unwrap() + ); } #[test] diff --git a/src/unit_tests/models/set/three_dimensional_matching.rs b/src/unit_tests/models/set/three_dimensional_matching.rs index d4f7f7f5a..022dff998 100644 --- a/src/unit_tests/models/set/three_dimensional_matching.rs +++ b/src/unit_tests/models/set/three_dimensional_matching.rs @@ -25,34 +25,46 @@ fn test_three_dimensional_matching_evaluation() { ); // T0, T1, T2: W={0,1,2} distinct, X={1,0,2} distinct, Y={2,1,0} distinct -> valid - assert!(problem - .evaluate(&vec![true, true, true, false, false]) - .unwrap()); + assert!( + problem + .evaluate(&vec![true, true, true, false, false]) + .unwrap() + ); // T0, T3: both have w=0 -> invalid (also only 2 selected, need 3) - assert!(!problem - .evaluate(&vec![true, false, false, true, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, false, false, true, false]) + .unwrap() + ); // T0, T1, T3: w-coordinates {0,1,0} not distinct -> invalid - assert!(!problem - .evaluate(&vec![true, true, false, true, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, true, false, true, false]) + .unwrap() + ); // Only T0 selected (need q=3 triples) - assert!(!problem - .evaluate(&vec![true, false, false, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, false, false, false, false]) + .unwrap() + ); // All selected (too many) - assert!(!problem - .evaluate(&vec![true, true, true, true, true]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![true, true, true, true, true]) + .unwrap() + ); // None selected - assert!(!problem - .evaluate(&vec![false, false, false, false, false]) - .unwrap()); + assert!( + !problem + .evaluate(&vec![false, false, false, false, false]) + .unwrap() + ); } #[test] diff --git a/src/unit_tests/parameter_formula_validation.rs b/src/unit_tests/parameter_formula_validation.rs index c884f4b49..cf42ac4b0 100644 --- a/src/unit_tests/parameter_formula_validation.rs +++ b/src/unit_tests/parameter_formula_validation.rs @@ -1,7 +1,7 @@ use crate::parameters::ParameterRelation; use crate::registry::DynProblem; -use crate::rules::{registry::ReductionEntry, ReductionGraph}; -use serde_json::{json, Value}; +use crate::rules::{ReductionGraph, registry::ReductionEntry}; +use serde_json::{Value, json}; use std::collections::BTreeMap; type SourceKey = (String, BTreeMap); @@ -106,10 +106,10 @@ fn source_for( .flat_map(|(_, examples)| examples), ); for example in examples { - if let Ok(source) = (registered.factory)(example.clone()) { - if let Ok(actual) = target_parameters(entry, source.as_ref()) { - return Ok((source, actual)); - } + if let Ok(source) = (registered.factory)(example.clone()) + && let Ok(actual) = target_parameters(entry, source.as_ref()) + { + return Ok((source, actual)); } } // Geometric variants without canonical instances use the existing seeded @@ -414,16 +414,16 @@ fn simple_graph_create_contracts_propagate_edge_validation() { #[test] fn direct_qubo_sparse_support_bounds_avoid_dense_cliques() { + use crate::Problem; + use crate::models::Decision; use crate::models::algebraic::QUBO; use crate::models::graph::OptimalLinearArrangement; use crate::models::misc::{ CyclicOrdering, SequencingWithReleaseTimesAndDeadlines, ShortestCommonSuperstring, StackerCrane, StaffScheduling, ThreePartition, }; - use crate::models::Decision; use crate::rules::{ReduceTo, ReductionResult}; use crate::topology::SimpleGraph; - use crate::Problem; fn check + 'static, T: Problem>(source: S, budget: u64) { let entry = crate::rules::registry::reduction_entries() diff --git a/src/unit_tests/poly_compare.rs b/src/unit_tests/poly_compare.rs index 374350c39..1e7eeb145 100644 --- a/src/unit_tests/poly_compare.rs +++ b/src/unit_tests/poly_compare.rs @@ -66,15 +66,19 @@ fn witnesses_reject_negative_and_cancelled_top_faces() { } let f = poly("m^2-n"); let g = poly("m-n"); - assert!(Witness::on(curve.clone(), &f, &g, &[]) - .unwrap() - .verify(&f, &g, &[])); + assert!( + Witness::on(curve.clone(), &f, &g, &[]) + .unwrap() + .verify(&f, &g, &[]) + ); let zero = poly("m-n^2/2"); assert!(Witness::on(curve.clone(), &f, &zero, &[]).is_none()); let zero = poly("0"); - assert!(Witness::on(curve, &f, &zero, &[]) - .unwrap() - .verify(&f, &zero, &[])); + assert!( + Witness::on(curve, &f, &zero, &[]) + .unwrap() + .verify(&f, &zero, &[]) + ); let c = pair("n^3-m", "n-m"); let Direction::No(w) = c.forward else { panic!("n grows while m stays bounded, with both leading coefficients positive") diff --git a/src/unit_tests/poly_compare_render.rs b/src/unit_tests/poly_compare_render.rs index 8d5a6b7af..ff4596b92 100644 --- a/src/unit_tests/poly_compare_render.rs +++ b/src/unit_tests/poly_compare_render.rs @@ -86,9 +86,11 @@ fn unknown_and_field_certificates_use_typed_reasons() { assert_eq!(upper.to_string(), "<= n"); assert_eq!(field("n").to_string(), "= n"); let missing = field("log(n)"); - assert!(missing - .to_string() - .starts_with("unavailable: not polynomial")); + assert!( + missing + .to_string() + .starts_with("unavailable: not polynomial") + ); let json = serde_json::to_value(&missing).unwrap(); assert_eq!(json["accuracy"]["reason"]["kind"], "not_polynomial"); assert_eq!( @@ -106,10 +108,11 @@ fn signed_coverage_and_regular_refutations_serialize_as_single_directions() { assert_eq!(json.as_object().unwrap().len(), 2); assert_eq!(json["forward"]["certificate"]["kind"], "newton"); let c = compare(&field("n"), &field("n^2"), &BTreeSet::new()); - assert!(c - .reverse - .to_string() - .contains("regular and positive across the batch")); + assert!( + c.reverse + .to_string() + .contains("regular and positive across the batch") + ); let json = serde_json::to_value(c).unwrap(); assert_eq!(json["forward"]["certificate"]["kind"], "newton"); assert_eq!(json["reverse"]["certificate"]["kind"], "witness"); diff --git a/src/unit_tests/reduction_graph.rs b/src/unit_tests/reduction_graph.rs index 34e503294..ac1e3f8d9 100644 --- a/src/unit_tests/reduction_graph.rs +++ b/src/unit_tests/reduction_graph.rs @@ -13,7 +13,7 @@ use std::collections::BTreeMap; #[test] fn real_graph_path_comparison_runs_from_registered_formulas() { - use crate::poly_compare::{compare_all, compare_profiles, Verdict}; + use crate::poly_compare::{Verdict, compare_all, compare_profiles}; let graph = crate::rules::ReductionGraph::new(); let paths = graph.find_paths_up_to( "MaximumIndependentSet", @@ -199,9 +199,11 @@ fn integer_ilp_graph_requires_bounded_domains_for_binary_encoding() { let graph = ReductionGraph::new(); let general = ReductionGraph::variant_to_map(&ILP::::variant()); let binary = ReductionGraph::variant_to_map(&ILP::::variant()); - assert!(graph - .find_all_paths("ILP", &general, "ILP", &binary) - .is_empty()); + assert!( + graph + .find_all_paths("ILP", &general, "ILP", &binary) + .is_empty() + ); let bounded = ReductionGraph::variant_to_map(&[ ("variable", "i64"), ("coefficient", "i64"), @@ -212,10 +214,12 @@ fn integer_ilp_graph_requires_bounded_domains_for_binary_encoding() { (&bounded, &general), (&binary, &bounded), ] { - assert!(graph - .find_all_paths("ILP", source, "ILP", target) - .iter() - .any(|path| path.len() == 1)); + assert!( + graph + .find_all_paths("ILP", source, "ILP", target) + .iter() + .any(|path| path.len() == 1) + ); } } @@ -336,10 +340,12 @@ fn compose_path_parameter_transform_is_absent_for_one_node() { }], }; - assert!(graph - .compose_path_parameter_transform(&path) - .unwrap() - .is_none()); + assert!( + graph + .compose_path_parameter_transform(&path) + .unwrap() + .is_none() + ); } #[test] @@ -422,24 +428,28 @@ fn aggregate_mode_rejects_witness_only_real_edge() { let src = ReductionGraph::variant_to_map(&MaximumIndependentSet::::variant()); let dst = ReductionGraph::variant_to_map(&MinimumVertexCover::::variant()); - assert!(!graph - .find_all_paths_mode( - "MaximumIndependentSet", - &src, - "MinimumVertexCover", - &dst, - ReductionMode::Witness - ) - .is_empty()); - assert!(graph - .find_all_paths_mode( - "MaximumIndependentSet", - &src, - "MinimumVertexCover", - &dst, - ReductionMode::Aggregate - ) - .is_empty()); + assert!( + !graph + .find_all_paths_mode( + "MaximumIndependentSet", + &src, + "MinimumVertexCover", + &dst, + ReductionMode::Witness + ) + .is_empty() + ); + assert!( + graph + .find_all_paths_mode( + "MaximumIndependentSet", + &src, + "MinimumVertexCover", + &dst, + ReductionMode::Aggregate + ) + .is_empty() + ); } #[test] @@ -450,24 +460,28 @@ fn variant_reduction_supports_both_modes_public_api() { let dst = ReductionGraph::variant_to_map(&MaximumIndependentSet::::variant()); - assert!(!graph - .find_all_paths_mode( - "MaximumIndependentSet", - &src, - "MaximumIndependentSet", - &dst, - ReductionMode::Witness - ) - .is_empty()); - assert!(!graph - .find_all_paths_mode( - "MaximumIndependentSet", - &src, - "MaximumIndependentSet", - &dst, - ReductionMode::Aggregate - ) - .is_empty()); + assert!( + !graph + .find_all_paths_mode( + "MaximumIndependentSet", + &src, + "MaximumIndependentSet", + &dst, + ReductionMode::Witness + ) + .is_empty() + ); + assert!( + !graph + .find_all_paths_mode( + "MaximumIndependentSet", + &src, + "MaximumIndependentSet", + &dst, + ReductionMode::Aggregate + ) + .is_empty() + ); } #[test] @@ -478,15 +492,17 @@ fn value_changing_variant_cast_is_not_aggregate_capable() { let src = ReductionGraph::variant_to_map(&MaximumSetPacking::::variant()); let dst = ReductionGraph::variant_to_map(&MaximumSetPacking::::variant()); - assert!(graph - .find_all_paths_mode( - "MaximumSetPacking", - &src, - "MaximumSetPacking", - &dst, - ReductionMode::Aggregate - ) - .is_empty()); + assert!( + graph + .find_all_paths_mode( + "MaximumSetPacking", + &src, + "MaximumSetPacking", + &dst, + ReductionMode::Aggregate + ) + .is_empty() + ); } #[test] @@ -496,16 +512,20 @@ fn test_problem_parameters_propagation() { let src = ReductionGraph::variant_to_map(&MaximumIndependentSet::::variant()); let dst = ReductionGraph::variant_to_map(&MinimumVertexCover::::variant()); - assert!(!graph - .find_all_paths("MaximumIndependentSet", &src, "MinimumVertexCover", &dst) - .is_empty()); + assert!( + !graph + .find_all_paths("MaximumIndependentSet", &src, "MinimumVertexCover", &dst) + .is_empty() + ); let src2 = ReductionGraph::variant_to_map(&MaximumIndependentSet::::variant()); let dst2 = ReductionGraph::variant_to_map(&MaximumSetPacking::::variant()); - assert!(!graph - .find_all_paths("MaximumIndependentSet", &src2, "MaximumSetPacking", &dst2) - .is_empty()); + assert!( + !graph + .find_all_paths("MaximumIndependentSet", &src2, "MaximumSetPacking", &dst2) + .is_empty() + ); } // ---- JSON export ---- @@ -1008,8 +1028,10 @@ fn vertex_cover_identity_does_not_define_a_matching_reduction() { let target_witness = solver.solve(&target).unwrap().unwrap(); assert_eq!(source.evaluate(&source_witness).unwrap(), Min(Some(3))); assert_eq!(target.evaluate(&target_witness).unwrap(), Min(Some(2))); - assert!(!ReductionGraph::new() - .has_direct_reduction_by_name("MinimumVertexCover", "MinimumMaximalMatching",)); + assert!( + !ReductionGraph::new() + .has_direct_reduction_by_name("MinimumVertexCover", "MinimumMaximalMatching",) + ); } #[test] @@ -1089,8 +1111,8 @@ fn test_decision_minimum_dominating_set_has_both_edges() { } #[test] -fn test_decision_minimum_dominating_set_to_minmax_multicenter_has_direct_witness_and_aggregate_edges( -) { +fn test_decision_minimum_dominating_set_to_minmax_multicenter_has_direct_witness_and_aggregate_edges() + { let graph = ReductionGraph::new(); assert!(graph.has_direct_reduction_mode::< @@ -1133,8 +1155,8 @@ fn test_decision_minimum_dominating_set_to_minmax_multicenter_has_direct_witness } #[test] -fn test_decision_minimum_dominating_set_to_minimum_sum_multicenter_has_direct_witness_and_aggregate_edges( -) { +fn test_decision_minimum_dominating_set_to_minimum_sum_multicenter_has_direct_witness_and_aggregate_edges() + { let graph = ReductionGraph::new(); assert!(graph.has_direct_reduction_mode::< @@ -1249,8 +1271,8 @@ fn test_find_paths_bounded_limits_depth() { #[test] fn test_find_paths_bounded_returns_shortest_when_truncated() { use crate::expr::Expr; - use crate::rules::registry::{ReductionParameterContract, ReductionParameterDeclarations}; use crate::rules::ReductionEdgeData; + use crate::rules::registry::{ReductionParameterContract, ReductionParameterDeclarations}; fn edge() -> ReductionEdgeData { fn reduce( diff --git a/src/unit_tests/registry/dispatch.rs b/src/unit_tests/registry/dispatch.rs index 2291f949d..ce2d85a3f 100644 --- a/src/unit_tests/registry/dispatch.rs +++ b/src/unit_tests/registry/dispatch.rs @@ -1,12 +1,12 @@ +use crate::Problem; use crate::models::graph::MaximumIndependentSet; use crate::models::graph::MinimumVertexCover; use crate::models::misc::SubsetSum; use crate::registry::variant::find_variant_entry; -use crate::registry::{load_dyn, serialize_any, DynProblem, LoadedDynProblem}; -use crate::solvers::{brute_force_dimensions, solve, SolveOutcome, SolverRequest}; +use crate::registry::{DynProblem, LoadedDynProblem, load_dyn, serialize_any}; +use crate::solvers::{SolveOutcome, SolverRequest, brute_force_dimensions, solve}; use crate::topology::SimpleGraph; use crate::types::{Max, Sum}; -use crate::Problem; use std::any::Any; use std::collections::BTreeMap; @@ -127,12 +127,16 @@ fn test_dyn_witness_evaluation_distinguishes_infeasibility_and_malformed_input() .unwrap(), None ); - assert!(dyn_problem - .evaluate_witness_dyn(&serde_json::json!([true])) - .is_err()); - assert!(dyn_problem - .evaluate_witness_dyn(&serde_json::json!([0, 0, 0])) - .is_err()); + assert!( + dyn_problem + .evaluate_witness_dyn(&serde_json::json!([true])) + .is_err() + ); + assert!( + dyn_problem + .evaluate_witness_dyn(&serde_json::json!([0, 0, 0])) + .is_err() + ); } #[test] diff --git a/src/unit_tests/registry/problem_type.rs b/src/unit_tests/registry/problem_type.rs index 15f1e3e5e..17487f3cd 100644 --- a/src/unit_tests/registry/problem_type.rs +++ b/src/unit_tests/registry/problem_type.rs @@ -1,6 +1,6 @@ use crate::registry::{ - find_problem_type, find_problem_type_by_alias, parse_catalog_problem_ref, problem_types, - ProblemCategory, ProblemRef, ProblemSchemaEntry, + ProblemCategory, ProblemRef, ProblemSchemaEntry, find_problem_type, find_problem_type_by_alias, + parse_catalog_problem_ref, problem_types, }; use std::collections::{BTreeSet, HashMap}; @@ -61,9 +61,11 @@ fn problem_types_returns_all_registered() { types.len() ); // Should include MIS - assert!(types - .iter() - .any(|t| t.canonical_name == "MaximumIndependentSet")); + assert!( + types + .iter() + .any(|t| t.canonical_name == "MaximumIndependentSet") + ); } #[test] diff --git a/src/unit_tests/rules/analysis.rs b/src/unit_tests/rules/analysis.rs index 81ee495cb..e3140c884 100644 --- a/src/unit_tests/rules/analysis.rs +++ b/src/unit_tests/rules/analysis.rs @@ -1,4 +1,4 @@ -use super::{check_connectivity, check_reachability_from_3sat, UnreachableReason}; +use super::{UnreachableReason, check_connectivity, check_reachability_from_3sat}; use crate::rules::ReductionGraph; // ---- Connectivity checks ---- diff --git a/src/unit_tests/rules/balancedcompletebipartitesubgraph_ilp.rs b/src/unit_tests/rules/balancedcompletebipartitesubgraph_ilp.rs index f044cf0f9..b2ac4224e 100644 --- a/src/unit_tests/rules/balancedcompletebipartitesubgraph_ilp.rs +++ b/src/unit_tests/rules/balancedcompletebipartitesubgraph_ilp.rs @@ -1,8 +1,8 @@ use super::*; use crate::models::algebraic::ILP; use crate::models::graph::BalancedCompleteBipartiteSubgraph; -use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::rules::ReduceTo; +use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::topology::BipartiteGraph; use crate::traits::Problem; diff --git a/src/unit_tests/rules/bmf_ilp.rs b/src/unit_tests/rules/bmf_ilp.rs index 5aa996351..2825385f4 100644 --- a/src/unit_tests/rules/bmf_ilp.rs +++ b/src/unit_tests/rules/bmf_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::rules::{ReduceTo, ReductionResult}; @@ -71,9 +71,11 @@ fn test_bmf_to_ilp_trivial() { fn bmf_extraction_requires_exact_reconstruction() { let source = BMF::new(vec![vec![true]], 1); let reduced = ReduceTo::>::reduce_to(&source).unwrap(); - assert!(reduced - .extract_solution(&vec![0; reduced.target_problem().num_vars()]) - .is_err()); + assert!( + reduced + .extract_solution(&vec![0; reduced.target_problem().num_vars()]) + .is_err() + ); } #[test] diff --git a/src/unit_tests/rules/bottlenecktravelingsalesman_ilp.rs b/src/unit_tests/rules/bottlenecktravelingsalesman_ilp.rs index c93582e95..922917356 100644 --- a/src/unit_tests/rules/bottlenecktravelingsalesman_ilp.rs +++ b/src/unit_tests/rules/bottlenecktravelingsalesman_ilp.rs @@ -181,9 +181,11 @@ fn test_bottleneck_ilp_signed_full_range_and_simple_cycles() { invalid[variable] = 2; assert!(result.extract_solution(&invalid).is_err()); } - assert!(result - .extract_solution(&witness[..witness.len() - 1].to_vec()) - .is_err()); + assert!( + result + .extract_solution(&witness[..witness.len() - 1].to_vec()) + .is_err() + ); } } diff --git a/src/unit_tests/rules/circuit_sat.rs b/src/unit_tests/rules/circuit_sat.rs index be07e6372..0921f9979 100644 --- a/src/unit_tests/rules/circuit_sat.rs +++ b/src/unit_tests/rules/circuit_sat.rs @@ -1,7 +1,7 @@ use super::*; use crate::models::formula::{Assignment, BooleanExpr, Circuit, CircuitSAT, Satisfiability}; -use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::rules::ReduceTo; +use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::solvers::BruteForce; use crate::traits::Problem; diff --git a/src/unit_tests/rules/closeststring_ilp.rs b/src/unit_tests/rules/closeststring_ilp.rs index 3442074fb..41adffbab 100644 --- a/src/unit_tests/rules/closeststring_ilp.rs +++ b/src/unit_tests/rules/closeststring_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{Bounded, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, ObjectiveSense}; use crate::models::misc::ClosestString; use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::solvers::{BruteForce, ILPSolver}; diff --git a/src/unit_tests/rules/closestsubstring_ilp.rs b/src/unit_tests/rules/closestsubstring_ilp.rs index 2953e4edd..f714c49ac 100644 --- a/src/unit_tests/rules/closestsubstring_ilp.rs +++ b/src/unit_tests/rules/closestsubstring_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{Bounded, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, ObjectiveSense}; use crate::models::misc::ClosestSubstring; use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::solvers::{BruteForce, ILPSolver}; diff --git a/src/unit_tests/rules/closestvectorproblem_qubo.rs b/src/unit_tests/rules/closestvectorproblem_qubo.rs index 5556ce205..a343fa41f 100644 --- a/src/unit_tests/rules/closestvectorproblem_qubo.rs +++ b/src/unit_tests/rules/closestvectorproblem_qubo.rs @@ -136,9 +136,11 @@ fn test_closestvectorproblem_to_qubo_preserves_squared_distance_up_to_constant() source.evaluate(&witness).unwrap(), source.evaluate(&direct).unwrap() ); - assert!(reduction - .extract_solution(&vec![false; qubo.num_vars() + 1]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![false; qubo.num_vars() + 1]) + .is_err() + ); } } diff --git a/src/unit_tests/rules/clustering_ilp.rs b/src/unit_tests/rules/clustering_ilp.rs index 2142986ba..6c9392570 100644 --- a/src/unit_tests/rules/clustering_ilp.rs +++ b/src/unit_tests/rules/clustering_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{Comparison, ObjectiveSense, ILP}; +use crate::models::algebraic::{Comparison, ILP, ObjectiveSense}; use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::solvers::ILPSolver; use crate::traits::Problem; diff --git a/src/unit_tests/rules/consecutiveblockminimization_ilp.rs b/src/unit_tests/rules/consecutiveblockminimization_ilp.rs index fe9267c0a..84ad0641a 100644 --- a/src/unit_tests/rules/consecutiveblockminimization_ilp.rs +++ b/src/unit_tests/rules/consecutiveblockminimization_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::rules::{ReduceTo, ReductionResult}; use crate::solvers::{BruteForce, ILPSolver}; diff --git a/src/unit_tests/rules/consecutiveonesmatrixaugmentation_ilp.rs b/src/unit_tests/rules/consecutiveonesmatrixaugmentation_ilp.rs index 180073d8e..429bf64ab 100644 --- a/src/unit_tests/rules/consecutiveonesmatrixaugmentation_ilp.rs +++ b/src/unit_tests/rules/consecutiveonesmatrixaugmentation_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::rules::{ReduceTo, ReductionResult}; use crate::solvers::{BruteForce, ILPSolver}; use crate::traits::Problem; diff --git a/src/unit_tests/rules/consecutiveonessubmatrix_ilp.rs b/src/unit_tests/rules/consecutiveonessubmatrix_ilp.rs index 8f67288ed..fb7602a38 100644 --- a/src/unit_tests/rules/consecutiveonessubmatrix_ilp.rs +++ b/src/unit_tests/rules/consecutiveonessubmatrix_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::rules::{ReduceTo, ReductionResult}; use crate::solvers::{BruteForce, ILPSolver}; use crate::traits::Problem; diff --git a/src/unit_tests/rules/consistencyofdatabasefrequencytables_ilp.rs b/src/unit_tests/rules/consistencyofdatabasefrequencytables_ilp.rs index 18146da9e..94c790f4f 100644 --- a/src/unit_tests/rules/consistencyofdatabasefrequencytables_ilp.rs +++ b/src/unit_tests/rules/consistencyofdatabasefrequencytables_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::models::misc::{ConsistencyOfDatabaseFrequencyTables, FrequencyTable, KnownValue}; use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::rules::{ReduceTo, ReductionResult}; @@ -14,12 +14,14 @@ fn binary_attributes_reduce_without_materializing_the_domain_product() { assert_eq!(reduction.target_problem().num_constraints(), 64); let witness = vec![0; 64]; let encoded = reduction.encode_source_solution(&witness); - assert!(reduction - .target_problem() - .evaluate(&encoded) - .unwrap() - .value - .is_some()); + assert!( + reduction + .target_problem() + .evaluate(&encoded) + .unwrap() + .value + .is_some() + ); assert_eq!(reduction.extract_solution(&encoded).unwrap(), witness); } diff --git a/src/unit_tests/rules/decisionilp_sat.rs b/src/unit_tests/rules/decisionilp_sat.rs index 6d46ba869..5458b0e06 100644 --- a/src/unit_tests/rules/decisionilp_sat.rs +++ b/src/unit_tests/rules/decisionilp_sat.rs @@ -1,5 +1,5 @@ use crate::models::algebraic::{Comparison, LinearConstraint, ObjectiveSense}; -use crate::models::{Decision, Satisfiability, ILP}; +use crate::models::{Decision, ILP, Satisfiability}; use crate::rules::{AggregateReductionResult, ReduceTo, ReductionResult}; use crate::solvers::{BruteForce, ILPSolver}; use crate::traits::Problem; @@ -33,9 +33,11 @@ fn test_decisionilp_to_sat_closed_loop() { reduction.extract_value(sat.evaluate(&witness).unwrap()), Or(true) ); - assert!(reduction - .extract_solution(&witness[..witness.len() - 1].to_vec()) - .is_err()); + assert!( + reduction + .extract_solution(&witness[..witness.len() - 1].to_vec()) + .is_err() + ); let invalid = vec![false; sat.num_vars()]; assert!(reduction.extract_solution(&invalid).is_err()); } else { diff --git a/src/unit_tests/rules/decisionminimumdominatingset_minimumsummulticenter.rs b/src/unit_tests/rules/decisionminimumdominatingset_minimumsummulticenter.rs index ffbe8d295..5ec4f6309 100644 --- a/src/unit_tests/rules/decisionminimumdominatingset_minimumsummulticenter.rs +++ b/src/unit_tests/rules/decisionminimumdominatingset_minimumsummulticenter.rs @@ -177,9 +177,11 @@ fn test_decisionminimumdominatingset_to_minimumsummulticenter_all_small_graphs() Or(source_yes), "n={n}, edges={edges:?}, K={bound}" ); - assert!(reduction - .extract_solution(&vec![false; target.num_vertices() + 1]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![false; target.num_vertices() + 1]) + .is_err() + ); } } } diff --git a/src/unit_tests/rules/decisionminimumvertexcover_hamiltoniancircuit.rs b/src/unit_tests/rules/decisionminimumvertexcover_hamiltoniancircuit.rs index 2dabcf767..64a4b69f3 100644 --- a/src/unit_tests/rules/decisionminimumvertexcover_hamiltoniancircuit.rs +++ b/src/unit_tests/rules/decisionminimumvertexcover_hamiltoniancircuit.rs @@ -76,8 +76,8 @@ fn test_decisionminimumvertexcover_to_hamiltoniancircuit_ignores_isolated_vertic } #[test] -fn test_decisionminimumvertexcover_to_hamiltoniancircuit_fixed_yes_when_k_covers_all_active_vertices( -) { +fn test_decisionminimumvertexcover_to_hamiltoniancircuit_fixed_yes_when_k_covers_all_active_vertices() + { let source = decision_mvc(3, &[(0, 1), (1, 2)], 3); let reduction = ReduceTo::>::reduce_to(&source) .expect("reduction should succeed"); diff --git a/src/unit_tests/rules/direct_qubo.rs b/src/unit_tests/rules/direct_qubo.rs index 172a1bde3..1d4002bc0 100644 --- a/src/unit_tests/rules/direct_qubo.rs +++ b/src/unit_tests/rules/direct_qubo.rs @@ -1,4 +1,4 @@ -use crate::models::algebraic::{QuadraticAssignment, QUBO}; +use crate::models::algebraic::{QUBO, QuadraticAssignment}; use crate::models::decision::Decision; use crate::models::graph::OptimalLinearArrangement; use crate::models::misc::{ @@ -85,9 +85,11 @@ where Min(Some(expected)) ); } - assert!(reduction - .extract_solution_dyn(&vec![false; bits + 1]) - .is_err()); + assert!( + reduction + .extract_solution_dyn(&vec![false; bits + 1]) + .is_err() + ); } pub(super) fn feasible + 'static>(source: S, expected: bool, bits: usize) @@ -122,9 +124,11 @@ where Or(true) ); } - assert!(reduction - .extract_solution_dyn(&vec![false; bits + 1]) - .is_err()); + assert!( + reduction + .extract_solution_dyn(&vec![false; bits + 1]) + .is_err() + ); } #[test] diff --git a/src/unit_tests/rules/direct_qubo_conditional.rs b/src/unit_tests/rules/direct_qubo_conditional.rs index 855a32b95..faaf5e636 100644 --- a/src/unit_tests/rules/direct_qubo_conditional.rs +++ b/src/unit_tests/rules/direct_qubo_conditional.rs @@ -1,6 +1,6 @@ use super::direct_qubo_tests::{direct, feasible, optimum}; -use crate::models::{algebraic::QUBO, misc::*}; use crate::BruteForce; +use crate::models::{algebraic::QUBO, misc::*}; #[test] fn test_deferred_qubo_rules_retain_ilp_routes() { @@ -11,9 +11,11 @@ fn test_deferred_qubo_rules_retain_ilp_routes() { "Betweenness", "ShortestCommonSupersequence", ] { - assert!(entries - .iter() - .any(|e| e.source_name == source && e.target_name == "ILP")); + assert!( + entries + .iter() + .any(|e| e.source_name == source && e.target_name == "ILP") + ); assert!( !entries.iter().any( |e| e.source_name == source && matches!(e.target_name, "QUBO" | "DecisionQUBO") @@ -133,9 +135,9 @@ fn test_start_encodings_check_source_arithmetic_and_extreme_windows() { #[test] fn test_conditional_encodings_preserve_completed_no_values() { + use crate::Problem; use crate::rules::{AggregateReductionResult, ReduceTo, ReductionResult}; use crate::types::Min; - use crate::Problem; let source = MinimumTardinessSequencing::with_lengths(vec![1], vec![1], vec![(0, 0)]); let r = ReduceTo::>::reduce_to(&source).unwrap(); let target = ReductionResult::target_problem(&r); diff --git a/src/unit_tests/rules/directedtwocommodityintegralflow_ilp.rs b/src/unit_tests/rules/directedtwocommodityintegralflow_ilp.rs index 3d59604c0..ba3e891f6 100644 --- a/src/unit_tests/rules/directedtwocommodityintegralflow_ilp.rs +++ b/src/unit_tests/rules/directedtwocommodityintegralflow_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{Bounded, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, ObjectiveSense}; use crate::solvers::{BruteForce, ILPSolver}; use crate::topology::MultiDigraph; use crate::traits::Problem; @@ -18,12 +18,14 @@ fn sink_self_loop_cannot_supply_commodity_flow() { ); let reduction = ReduceTo::>::reduce_to(&source).unwrap(); assert!(!source.evaluate(&vec![1, 0]).unwrap().0); - assert!(reduction - .target_problem() - .evaluate(&vec![1, 0]) - .unwrap() - .value - .is_none()); + assert!( + reduction + .target_problem() + .evaluate(&vec![1, 0]) + .unwrap() + .value + .is_none() + ); assert!(reduction.extract_solution(&vec![1, 0]).is_err()); } diff --git a/src/unit_tests/rules/disjointconnectingpaths_ilp.rs b/src/unit_tests/rules/disjointconnectingpaths_ilp.rs index 740f58586..f5282c144 100644 --- a/src/unit_tests/rules/disjointconnectingpaths_ilp.rs +++ b/src/unit_tests/rules/disjointconnectingpaths_ilp.rs @@ -1,7 +1,7 @@ use super::*; use crate::models::algebraic::ILP; -use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::rules::ReduceTo; +use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::solvers::ILPSolver; use crate::topology::SimpleGraph; use crate::traits::Problem; @@ -40,10 +40,12 @@ fn test_disjointconnectingpaths_to_ilp_forbids_using_another_pairs_terminal() { for index in [0, 13, 14] { colliding_flow[index] = 1; } - assert!(!reduction - .target_problem() - .is_feasible(&colliding_flow) - .unwrap()); + assert!( + !reduction + .target_problem() + .is_feasible(&colliding_flow) + .unwrap() + ); let target_solution = ILPSolver::new().solve(reduction.target_problem()).unwrap(); let extracted = reduction.extract_solution(&target_solution).unwrap(); assert!(source.evaluate(&extracted).unwrap().0); @@ -60,10 +62,12 @@ fn test_disjointconnectingpaths_to_ilp_discards_disconnected_circulation() { for index in [0, 4, 7, 8, 12] { target_solution[index] = 1; } - assert!(reduction - .target_problem() - .is_feasible(&target_solution) - .unwrap()); + assert!( + reduction + .target_problem() + .is_feasible(&target_solution) + .unwrap() + ); let extracted = reduction.extract_solution(&target_solution).unwrap(); assert_eq!(extracted, vec![true, true, false, false, false]); assert!(source.evaluate(&extracted).unwrap().0); diff --git a/src/unit_tests/rules/eulerianpath_ilp.rs b/src/unit_tests/rules/eulerianpath_ilp.rs index 887f46606..ea299f939 100644 --- a/src/unit_tests/rules/eulerianpath_ilp.rs +++ b/src/unit_tests/rules/eulerianpath_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{Bounded, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, ObjectiveSense}; use crate::models::graph::EulerianPath; use crate::solvers::ILPSolver; use crate::topology::MultiDigraph; diff --git a/src/unit_tests/rules/exactcoverby3sets_boundeddiameterspanningtree.rs b/src/unit_tests/rules/exactcoverby3sets_boundeddiameterspanningtree.rs index ba458bb61..2c5deca0a 100644 --- a/src/unit_tests/rules/exactcoverby3sets_boundeddiameterspanningtree.rs +++ b/src/unit_tests/rules/exactcoverby3sets_boundeddiameterspanningtree.rs @@ -84,9 +84,11 @@ fn test_exactcoverby3sets_to_boundeddiameterspanningtree_extract_solution() { invalid[3] = true; assert!(reduction.extract_solution(&invalid).is_err()); assert!(reduction.extract_solution(&vec![]).is_err()); - assert!(reduction - .extract_solution(&vec![true; target_config.len()]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![true; target_config.len()]) + .is_err() + ); } #[test] @@ -114,10 +116,12 @@ fn test_exactcoverby3sets_to_boundeddiameterspanningtree_universe_boundaries() { ReduceTo::>::reduce_to(&source).unwrap(); assert_eq!(reduction.target_problem().num_vertices(), 2); assert_eq!(reduction.target_problem().num_edges(), 0); - assert!(BruteForce::new() - .solve(reduction.target_problem()) - .unwrap() - .is_none()); + assert!( + BruteForce::new() + .solve(reduction.target_problem()) + .unwrap() + .is_none() + ); assert!(reduction.extract_solution(&vec![]).is_err()); } let source = ExactCoverBy3Sets::new(0, vec![]); diff --git a/src/unit_tests/rules/exactcoverby3sets_staffscheduling.rs b/src/unit_tests/rules/exactcoverby3sets_staffscheduling.rs index 1ac06e987..7d469ae4e 100644 --- a/src/unit_tests/rules/exactcoverby3sets_staffscheduling.rs +++ b/src/unit_tests/rules/exactcoverby3sets_staffscheduling.rs @@ -1,8 +1,8 @@ use super::*; use crate::models::misc::StaffScheduling; use crate::models::set::ExactCoverBy3Sets; -use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::rules::ReduceTo; +use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::solvers::BruteForce; use crate::traits::Problem; diff --git a/src/unit_tests/rules/expectedretrievalcost_ilp.rs b/src/unit_tests/rules/expectedretrievalcost_ilp.rs index ae9b2af03..a3e98fd8d 100644 --- a/src/unit_tests/rules/expectedretrievalcost_ilp.rs +++ b/src/unit_tests/rules/expectedretrievalcost_ilp.rs @@ -68,11 +68,11 @@ fn test_solution_extraction() { // record 0 -> sector 0, record 1 -> sector 1 // x_{0,0}=1, x_{0,1}=0, x_{1,0}=0, x_{1,1}=1 let mut ilp_solution = vec![0_i64; 4 + 16]; // n + n^2 - // x vars + // x vars ilp_solution[0] = 1; // x_{0,0} ilp_solution[3] = 1; // x_{1,1} - // z vars: z_{r,s,r',s'} at offset 4 + (r*2+s)*4 + (r'*2+s') - // z_{0,0,0,0} = x_{0,0}*x_{0,0} = 1: offset 4 + 0*4 + 0 = 4 + // z vars: z_{r,s,r',s'} at offset 4 + (r*2+s)*4 + (r'*2+s') + // z_{0,0,0,0} = x_{0,0}*x_{0,0} = 1: offset 4 + 0*4 + 0 = 4 ilp_solution[4] = 1; // z_{1,1,1,1} = x_{1,1}*x_{1,1} = 1: offset 4 + 3*4 + 3 = 4+15=19 ilp_solution[19] = 1; diff --git a/src/unit_tests/rules/factoring_circuit.rs b/src/unit_tests/rules/factoring_circuit.rs index 0cd10c8b9..2dc494eb0 100644 --- a/src/unit_tests/rules/factoring_circuit.rs +++ b/src/unit_tests/rules/factoring_circuit.rs @@ -393,9 +393,11 @@ fn test_factoring_to_circuit_rejects_invalid_certificates() { let source = Factoring::with_factor_bits(6, 2, 2); let reduction = ReduceTo::::reduce_to(&source).unwrap(); assert!(reduction.extract_solution(&vec![]).is_err()); - assert!(reduction - .extract_solution(&vec![false; reduction.target_problem().num_variables()]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![false; reduction.target_problem().num_variables()]) + .is_err() + ); let values = evaluate_multiplier_circuit(&reduction, 1, 1); let config = reduction .target_problem() diff --git a/src/unit_tests/rules/flowshopscheduling_ilp.rs b/src/unit_tests/rules/flowshopscheduling_ilp.rs index 580b2e6a8..a66041a89 100644 --- a/src/unit_tests/rules/flowshopscheduling_ilp.rs +++ b/src/unit_tests/rules/flowshopscheduling_ilp.rs @@ -11,12 +11,14 @@ fn zero_duration_jobs_preserve_the_common_machine_order() { let reduction = ReduceTo::>::reduce_to(&source).unwrap(); // Job 1 precedes job 0, but both finish on machine 1 at time 11. let assignment = vec![0, 4, 11, 1, 11]; - assert!(reduction - .target_problem() - .evaluate(&assignment) - .unwrap() - .value - .is_some()); + assert!( + reduction + .target_problem() + .evaluate(&assignment) + .unwrap() + .value + .is_some() + ); let decoded = reduction.extract_solution(&assignment).unwrap(); assert_eq!(decoded, vec![1, 0]); assert_eq!(source.evaluate(&decoded).unwrap(), Or(true)); diff --git a/src/unit_tests/rules/graph.rs b/src/unit_tests/rules/graph.rs index f89389a68..73417e621 100644 --- a/src/unit_tests/rules/graph.rs +++ b/src/unit_tests/rules/graph.rs @@ -623,10 +623,12 @@ fn path_parameter_contract_errors_are_typed_and_isolated() { let empty = ReductionPath { steps: vec![] }; let graph = ReductionGraph::from_test_edges(&["A", "B"], &[]); assert!(graph.path_parameter_transforms(&single).unwrap().is_empty()); - assert!(graph - .compose_path_parameter_transform(&single) - .unwrap() - .is_none()); + assert!( + graph + .compose_path_parameter_transform(&single) + .unwrap() + .is_none() + ); assert!(matches!( graph.compose_path_parameter_transform(&empty), Err(PathParameterError::EmptyPath) @@ -908,24 +910,28 @@ fn witness_path_search_rejects_aggregate_only_edge() { }, ); - assert!(graph - .find_all_paths_mode( - AggregateChainSource::NAME, - &source_variant, - AggregateChainMiddle::NAME, - &target_variant, - ReductionMode::Witness - ) - .is_empty()); - assert!(!graph - .find_all_paths_mode( - AggregateChainSource::NAME, - &source_variant, - AggregateChainMiddle::NAME, - &target_variant, - ReductionMode::Aggregate - ) - .is_empty()); + assert!( + graph + .find_all_paths_mode( + AggregateChainSource::NAME, + &source_variant, + AggregateChainMiddle::NAME, + &target_variant, + ReductionMode::Witness + ) + .is_empty() + ); + assert!( + !graph + .find_all_paths_mode( + AggregateChainSource::NAME, + &source_variant, + AggregateChainMiddle::NAME, + &target_variant, + ReductionMode::Aggregate + ) + .is_empty() + ); } #[test] @@ -946,24 +952,28 @@ fn aggregate_path_search_rejects_witness_only_edge() { }, ); - assert!(graph - .find_all_paths_mode( - AggregateChainSource::NAME, - &source_variant, - AggregateChainMiddle::NAME, - &target_variant, - ReductionMode::Aggregate - ) - .is_empty()); - assert!(!graph - .find_all_paths_mode( - AggregateChainSource::NAME, - &source_variant, - AggregateChainMiddle::NAME, - &target_variant, - ReductionMode::Witness - ) - .is_empty()); + assert!( + graph + .find_all_paths_mode( + AggregateChainSource::NAME, + &source_variant, + AggregateChainMiddle::NAME, + &target_variant, + ReductionMode::Aggregate + ) + .is_empty() + ); + assert!( + !graph + .find_all_paths_mode( + AggregateChainSource::NAME, + &source_variant, + AggregateChainMiddle::NAME, + &target_variant, + ReductionMode::Witness + ) + .is_empty() + ); } #[test] @@ -984,24 +994,28 @@ fn witness_executor_does_not_imply_aggregate_capability() { }, ); - assert!(!graph - .find_all_paths_mode( - NaturalVariantProblem::NAME, - &source_variant, - NaturalVariantProblem::NAME, - &target_variant, - ReductionMode::Witness - ) - .is_empty()); - assert!(graph - .find_all_paths_mode( - NaturalVariantProblem::NAME, - &source_variant, - NaturalVariantProblem::NAME, - &target_variant, - ReductionMode::Aggregate - ) - .is_empty()); + assert!( + !graph + .find_all_paths_mode( + NaturalVariantProblem::NAME, + &source_variant, + NaturalVariantProblem::NAME, + &target_variant, + ReductionMode::Witness + ) + .is_empty() + ); + assert!( + graph + .find_all_paths_mode( + NaturalVariantProblem::NAME, + &source_variant, + NaturalVariantProblem::NAME, + &target_variant, + ReductionMode::Aggregate + ) + .is_empty() + ); } #[test] @@ -1026,10 +1040,12 @@ fn reduce_aggregate_along_path_rejects_single_step_path() { variant: source_variant, }], }; - assert!(graph - .reduce_aggregate_along_path(&single_step_path, &AggregateChainSource as &dyn Any) - .expect("single-step path lookup should not fail") - .is_none()); + assert!( + graph + .reduce_aggregate_along_path(&single_step_path, &AggregateChainSource as &dyn Any) + .expect("single-step path lookup should not fail") + .is_none() + ); } #[test] @@ -1061,10 +1077,12 @@ fn reduce_aggregate_returns_none_for_witness_only_edge() { }, ], }; - assert!(graph - .reduce_aggregate_along_path(&path, &AggregateChainSource as &dyn Any) - .expect("witness-only edge lookup should not fail") - .is_none()); + assert!( + graph + .reduce_aggregate_along_path(&path, &AggregateChainSource as &dyn Any) + .expect("witness-only edge lookup should not fail") + .is_none() + ); } #[test] @@ -1212,20 +1230,24 @@ fn test_find_direct_path_variants() { let dst = ReductionGraph::variant_to_map( &crate::models::graph::SpinGlass::::variant(), ); - assert!(graph - .find_all_paths("MaxCut", &src, "SpinGlass", &dst) - .iter() - .any(|path| path.len() == 1)); + assert!( + graph + .find_all_paths("MaxCut", &src, "SpinGlass", &dst) + .iter() + .any(|path| path.len() == 1) + ); let src = ReductionGraph::variant_to_map(&crate::models::misc::Factoring::variant()); let dst = ReductionGraph::variant_to_map( &crate::models::graph::SpinGlass::::variant(), ); - assert!(graph - .find_all_paths("Factoring", &src, "SpinGlass", &dst) - .iter() - .any(|path| path.type_names() - == ["Factoring", "CircuitSAT", "DecisionSpinGlass", "SpinGlass"])); + assert!( + graph + .find_all_paths("Factoring", &src, "SpinGlass", &dst) + .iter() + .any(|path| path.type_names() + == ["Factoring", "CircuitSAT", "DecisionSpinGlass", "SpinGlass"]) + ); } #[test] @@ -1269,14 +1291,16 @@ fn test_to_json() { assert!(json.nodes.len() >= 10); assert!(json.nodes.iter().any(|n| n.name == "MaximumIndependentSet")); - assert!(json - .nodes - .iter() - .any(|n| n.category == ProblemCategory::Graph)); - assert!(json - .nodes - .iter() - .any(|n| n.category == ProblemCategory::Algebraic)); + assert!( + json.nodes + .iter() + .any(|n| n.category == ProblemCategory::Graph) + ); + assert!( + json.nodes + .iter() + .any(|n| n.category == ProblemCategory::Algebraic) + ); assert!(json.edges.len() >= 10); @@ -1314,16 +1338,20 @@ fn graph_export_identifies_declared_defaults_and_catalog_aliases() { .unwrap() ); for alias in problem.aliases { - assert!(export["aliases"][problem.canonical_name] - .as_array() - .unwrap() - .contains(&serde_json::json!(alias))); + assert!( + export["aliases"][problem.canonical_name] + .as_array() + .unwrap() + .contains(&serde_json::json!(alias)) + ); } } - assert!(export["aliases"]["KSatisfiability"] - .as_array() - .unwrap() - .contains(&serde_json::json!("3SAT"))); + assert!( + export["aliases"]["KSatisfiability"] + .as_array() + .unwrap() + .contains(&serde_json::json!("3SAT")) + ); } #[test] @@ -1405,10 +1433,10 @@ fn test_circuit_reductions() { let dst = ReductionGraph::variant_to_map(&SpinGlass::::variant()); let paths = graph.find_all_paths("Factoring", &src, "SpinGlass", &dst); assert!(!paths.is_empty()); - assert!(paths - .iter() - .any(|path| path.type_names() - == ["Factoring", "CircuitSAT", "DecisionSpinGlass", "SpinGlass"])); + assert!( + paths.iter().any(|path| path.type_names() + == ["Factoring", "CircuitSAT", "DecisionSpinGlass", "SpinGlass"]) + ); } #[test] @@ -1460,8 +1488,11 @@ fn test_nae_sat_to_partition_into_perfect_matchings_reduction_registered() { let graph = ReductionGraph::new(); - assert!(graph - .has_direct_reduction::>()); + assert!( + graph + .has_direct_reduction::>( + ) + ); } #[test] @@ -1552,12 +1583,16 @@ fn test_unknown_name_returns_empty() { assert!(!graph.has_direct_reduction_by_name("UnknownA", "UnknownB")); // find_all_paths with unknown name - assert!(graph - .find_all_paths("UnknownProblem", &unknown, "MaximumIndependentSet", &is_var) - .is_empty()); - assert!(graph - .find_all_paths("MaximumIndependentSet", &is_var, "UnknownProblem", &unknown) - .is_empty()); + assert!( + graph + .find_all_paths("UnknownProblem", &unknown, "MaximumIndependentSet", &is_var) + .is_empty() + ); + assert!( + graph + .find_all_paths("MaximumIndependentSet", &is_var, "UnknownProblem", &unknown) + .is_empty() + ); } #[test] @@ -1607,10 +1642,12 @@ fn test_circuitsat_to_satisfiability_direct_edge() { assert!(graph.has_direct_reduction_by_name("CircuitSAT", "Satisfiability")); - assert!(graph - .find_all_paths("CircuitSAT", &src, "Satisfiability", &dst) - .iter() - .any(|path| path.len() == 1)); + assert!( + graph + .find_all_paths("CircuitSAT", &src, "Satisfiability", &dst) + .iter() + .any(|path| path.len() == 1) + ); } #[test] @@ -2057,25 +2094,33 @@ fn test_outgoing_reductions_from_uses_exact_variant_and_mode() { let unit_targets = graph.outgoing_reductions_from("MaximumIndependentSet", &unit, ReductionMode::Witness); - assert!(unit_targets - .iter() - .all(|edge| edge.source_variant == unit && edge.capabilities.witness)); + assert!( + unit_targets + .iter() + .all(|edge| edge.source_variant == unit && edge.capabilities.witness) + ); assert!(unit_targets.iter().any(|edge| { edge.target_name == "MaximumSetPacking" && edge.target_variant.get("weight").map(String::as_str) == Some("One") })); - assert!(!unit_targets - .iter() - .any(|edge| edge.target_name == "IntegralFlowBundles")); + assert!( + !unit_targets + .iter() + .any(|edge| edge.target_name == "IntegralFlowBundles") + ); let weighted_targets = graph.outgoing_reductions_from("MaximumIndependentSet", &weighted, ReductionMode::Witness); - assert!(weighted_targets - .iter() - .all(|edge| edge.source_variant == weighted && edge.capabilities.witness)); - assert!(!weighted_targets - .iter() - .any(|edge| edge.target_name == "IntegralFlowBundles")); + assert!( + weighted_targets + .iter() + .all(|edge| edge.source_variant == weighted && edge.capabilities.witness) + ); + assert!( + !weighted_targets + .iter() + .any(|edge| edge.target_name == "IntegralFlowBundles") + ); for (variant, has_flow_rule) in [(&unit, true), (&weighted, false)] { let decision_targets = graph.outgoing_reductions_from( "DecisionMaximumIndependentSet", @@ -2090,10 +2135,12 @@ fn test_outgoing_reductions_from_uses_exact_variant_and_mode() { ); let optimization_queries = graph.outgoing_reductions_from("MaximumIndependentSet", variant, ReductionMode::Turing); - assert!(optimization_queries - .iter() - .any(|edge| edge.target_name == "DecisionMaximumIndependentSet" - && edge.target_variant == *variant)); + assert!( + optimization_queries + .iter() + .any(|edge| edge.target_name == "DecisionMaximumIndependentSet" + && edge.target_variant == *variant) + ); } assert!(!weighted_targets.iter().any(|edge| { edge.target_name == "MaximumIndependentSet" @@ -2224,12 +2271,14 @@ fn completed_cut() -> crate::solvers::SolveOutcome { #[test] fn completed_recovery_propagates_target_infeasibility() { - assert!(recover_fixture( - &recovery_fixture(Some(1), true), - &crate::solvers::SolveOutcome::Infeasible - ) - .unwrap() - .is_none()); + assert!( + recover_fixture( + &recovery_fixture(Some(1), true), + &crate::solvers::SolveOutcome::Infeasible + ) + .unwrap() + .is_none() + ); } #[test] @@ -2246,9 +2295,11 @@ fn completed_recovery_rejects_witness_not_realizing_mapped_value() { let error = recover_fixture(&recovery_fixture(Some(2), false), &completed_cut()) .err() .unwrap(); - assert!(error - .to_string() - .contains("does not realize the mapped aggregate")); + assert!( + error + .to_string() + .contains("does not realize the mapped aggregate") + ); } #[test] @@ -2272,9 +2323,11 @@ fn completed_recovery_checks_target_evaluation() { let error = recover_fixture(&recovery_fixture(Some(1), false), &outcome) .err() .unwrap(); - assert!(error - .to_string() - .contains("target evaluation does not match")); + assert!( + error + .to_string() + .contains("target evaluation does not match") + ); } #[test] diff --git a/src/unit_tests/rules/hamiltoniancircuit_biconnectivityaugmentation.rs b/src/unit_tests/rules/hamiltoniancircuit_biconnectivityaugmentation.rs index e31cd03f5..f6cfdcd8a 100644 --- a/src/unit_tests/rules/hamiltoniancircuit_biconnectivityaugmentation.rs +++ b/src/unit_tests/rules/hamiltoniancircuit_biconnectivityaugmentation.rs @@ -1,10 +1,10 @@ +use crate::Problem; use crate::models::graph::{BiconnectivityAugmentation, HamiltonianCircuit}; -use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::rules::ReduceTo; use crate::rules::ReductionResult; +use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::solvers::BruteForce; use crate::topology::SimpleGraph; -use crate::Problem; fn cycle4_hc() -> HamiltonianCircuit { HamiltonianCircuit::new(SimpleGraph::cycle(4)) diff --git a/src/unit_tests/rules/hamiltoniancircuit_bottlenecktravelingsalesman.rs b/src/unit_tests/rules/hamiltoniancircuit_bottlenecktravelingsalesman.rs index 5623656a4..e6d73ae90 100644 --- a/src/unit_tests/rules/hamiltoniancircuit_bottlenecktravelingsalesman.rs +++ b/src/unit_tests/rules/hamiltoniancircuit_bottlenecktravelingsalesman.rs @@ -1,11 +1,11 @@ +use crate::Problem; use crate::models::graph::{BottleneckTravelingSalesman, HamiltonianCircuit}; -use crate::rules::test_helpers::assert_satisfaction_round_trip_from_optimization_target; use crate::rules::ReduceTo; use crate::rules::ReductionResult; +use crate::rules::test_helpers::assert_satisfaction_round_trip_from_optimization_target; use crate::solvers::BruteForce; use crate::topology::{Graph, SimpleGraph}; use crate::types::Min; -use crate::Problem; fn cycle5_hc() -> HamiltonianCircuit { HamiltonianCircuit::new(SimpleGraph::cycle(5)) diff --git a/src/unit_tests/rules/hamiltoniancircuit_hamiltonianpath.rs b/src/unit_tests/rules/hamiltoniancircuit_hamiltonianpath.rs index 4f0482880..7546a953c 100644 --- a/src/unit_tests/rules/hamiltoniancircuit_hamiltonianpath.rs +++ b/src/unit_tests/rules/hamiltoniancircuit_hamiltonianpath.rs @@ -1,10 +1,10 @@ +use crate::Problem; use crate::models::graph::{HamiltonianCircuit, HamiltonianPath}; -use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::rules::ReduceTo; use crate::rules::ReductionResult; +use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::solvers::BruteForce; use crate::topology::{Graph, SimpleGraph}; -use crate::Problem; fn cycle4_hc() -> HamiltonianCircuit { HamiltonianCircuit::new(SimpleGraph::cycle(4)) diff --git a/src/unit_tests/rules/hamiltoniancircuit_ilp.rs b/src/unit_tests/rules/hamiltoniancircuit_ilp.rs index 29c7bce5a..6e7b2e65e 100644 --- a/src/unit_tests/rules/hamiltoniancircuit_ilp.rs +++ b/src/unit_tests/rules/hamiltoniancircuit_ilp.rs @@ -57,12 +57,16 @@ fn circuit_flow_requires_one_cycle_and_three_distinct_vertices() { .unwrap() .0 ); - assert!(reduction - .extract_solution(&vec![0; solution.len()]) - .is_err()); - assert!(reduction - .extract_solution(&vec![0; solution.len() + 1]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![0; solution.len()]) + .is_err() + ); + assert!( + reduction + .extract_solution(&vec![0; solution.len() + 1]) + .is_err() + ); } Err(ILPSolveError::Infeasible) => assert!(!expected), Err(error) => panic!("{error}"), diff --git a/src/unit_tests/rules/hamiltoniancircuit_longestcircuit.rs b/src/unit_tests/rules/hamiltoniancircuit_longestcircuit.rs index efca83cb3..7988c517d 100644 --- a/src/unit_tests/rules/hamiltoniancircuit_longestcircuit.rs +++ b/src/unit_tests/rules/hamiltoniancircuit_longestcircuit.rs @@ -1,11 +1,11 @@ +use crate::Problem; use crate::models::graph::{HamiltonianCircuit, LongestCircuit}; -use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::rules::ReduceTo; use crate::rules::ReductionResult; +use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::solvers::BruteForce; use crate::topology::{Graph, SimpleGraph}; use crate::types::Max; -use crate::Problem; fn cycle4_hc() -> HamiltonianCircuit { HamiltonianCircuit::new(SimpleGraph::cycle(4)) @@ -161,9 +161,11 @@ fn test_hamiltoniancircuit_extraction_matches_all_small_target_configurations() assert!(source.evaluate(&order).unwrap().0); } } - assert!(reduction - .extract_solution(&vec![false; target.num_edges() + 1]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![false; target.num_edges() + 1]) + .is_err() + ); } } } diff --git a/src/unit_tests/rules/hamiltoniancircuit_quadraticassignment.rs b/src/unit_tests/rules/hamiltoniancircuit_quadraticassignment.rs index 22461add5..583aab725 100644 --- a/src/unit_tests/rules/hamiltoniancircuit_quadraticassignment.rs +++ b/src/unit_tests/rules/hamiltoniancircuit_quadraticassignment.rs @@ -1,13 +1,13 @@ +use crate::Problem; use crate::models::algebraic::QuadraticAssignment; use crate::models::decision::Decision; use crate::models::graph::HamiltonianCircuit; -use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::rules::ReduceTo; use crate::rules::ReductionResult; +use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::solvers::BruteForce; use crate::topology::{Graph, SimpleGraph}; use crate::types::Min; -use crate::Problem; fn cycle4_hc() -> HamiltonianCircuit { HamiltonianCircuit::new(SimpleGraph::cycle(4)) diff --git a/src/unit_tests/rules/hamiltoniancircuit_ruralpostman.rs b/src/unit_tests/rules/hamiltoniancircuit_ruralpostman.rs index 4a91bb267..bc0570775 100644 --- a/src/unit_tests/rules/hamiltoniancircuit_ruralpostman.rs +++ b/src/unit_tests/rules/hamiltoniancircuit_ruralpostman.rs @@ -1,11 +1,11 @@ +use crate::Problem; use crate::models::graph::{HamiltonianCircuit, RuralPostman}; -use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::rules::ReduceTo; use crate::rules::ReductionResult; +use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::solvers::BruteForce; use crate::topology::SimpleGraph; use crate::types::Min; -use crate::Problem; fn triangle_hc() -> HamiltonianCircuit { HamiltonianCircuit::new(SimpleGraph::new(3, vec![(0, 1), (1, 2), (0, 2)])) diff --git a/src/unit_tests/rules/hamiltoniancircuit_stackercrane.rs b/src/unit_tests/rules/hamiltoniancircuit_stackercrane.rs index 9aa4c1038..88b31de75 100644 --- a/src/unit_tests/rules/hamiltoniancircuit_stackercrane.rs +++ b/src/unit_tests/rules/hamiltoniancircuit_stackercrane.rs @@ -1,13 +1,13 @@ +use crate::Problem; use crate::models::decision::Decision; use crate::models::graph::HamiltonianCircuit; use crate::models::misc::StackerCrane; -use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::rules::ReduceTo; use crate::rules::ReductionResult; +use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::solvers::BruteForce; use crate::topology::SimpleGraph; use crate::types::Min; -use crate::Problem; fn cycle4_hc() -> HamiltonianCircuit { HamiltonianCircuit::new(SimpleGraph::cycle(4)) diff --git a/src/unit_tests/rules/hamiltoniancircuit_strongconnectivityaugmentation.rs b/src/unit_tests/rules/hamiltoniancircuit_strongconnectivityaugmentation.rs index f81fd7003..287ed2c97 100644 --- a/src/unit_tests/rules/hamiltoniancircuit_strongconnectivityaugmentation.rs +++ b/src/unit_tests/rules/hamiltoniancircuit_strongconnectivityaugmentation.rs @@ -1,10 +1,10 @@ +use crate::Problem; use crate::models::graph::{HamiltonianCircuit, StrongConnectivityAugmentation}; -use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::rules::ReduceTo; use crate::rules::ReductionResult; +use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::solvers::BruteForce; use crate::topology::{Graph, SimpleGraph}; -use crate::Problem; fn cycle4_hc() -> HamiltonianCircuit { HamiltonianCircuit::new(SimpleGraph::cycle(4)) diff --git a/src/unit_tests/rules/hamiltoniancircuit_travelingsalesman.rs b/src/unit_tests/rules/hamiltoniancircuit_travelingsalesman.rs index 4eecf4f08..cad088b93 100644 --- a/src/unit_tests/rules/hamiltoniancircuit_travelingsalesman.rs +++ b/src/unit_tests/rules/hamiltoniancircuit_travelingsalesman.rs @@ -1,11 +1,11 @@ +use crate::Problem; use crate::models::graph::{HamiltonianCircuit, TravelingSalesman}; -use crate::rules::test_helpers::assert_satisfaction_round_trip_from_optimization_target; use crate::rules::ReduceTo; use crate::rules::ReductionResult; +use crate::rules::test_helpers::assert_satisfaction_round_trip_from_optimization_target; use crate::solvers::BruteForce; use crate::topology::{Graph, SimpleGraph}; use crate::types::Min; -use crate::Problem; fn cycle4_hc() -> HamiltonianCircuit { HamiltonianCircuit::new(SimpleGraph::cycle(4)) diff --git a/src/unit_tests/rules/hamiltonianpath_isomorphicspanningtree.rs b/src/unit_tests/rules/hamiltonianpath_isomorphicspanningtree.rs index 380451464..24ed1f591 100644 --- a/src/unit_tests/rules/hamiltonianpath_isomorphicspanningtree.rs +++ b/src/unit_tests/rules/hamiltonianpath_isomorphicspanningtree.rs @@ -1,7 +1,7 @@ use super::*; use crate::models::graph::{HamiltonianPath, IsomorphicSpanningTree}; -use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::rules::ReduceTo; +use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::solvers::BruteForce; use crate::topology::SimpleGraph; use crate::traits::Problem; diff --git a/src/unit_tests/rules/hamiltonianpathbetweentwovertices_longestpath.rs b/src/unit_tests/rules/hamiltonianpathbetweentwovertices_longestpath.rs index fbd7c8fbe..a5cd4c693 100644 --- a/src/unit_tests/rules/hamiltonianpathbetweentwovertices_longestpath.rs +++ b/src/unit_tests/rules/hamiltonianpathbetweentwovertices_longestpath.rs @@ -1,8 +1,8 @@ use super::*; use crate::models::decision::Decision; use crate::models::graph::{HamiltonianPathBetweenTwoVertices, LongestPath}; -use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::rules::ReduceTo; +use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::solvers::BruteForce; use crate::topology::SimpleGraph; use crate::types::One; @@ -168,9 +168,11 @@ fn test_hamiltonian_path_extraction_for_all_small_graphs_and_endpoints() { assert!(source.evaluate(&order).unwrap().0); } } - assert!(reduction - .extract_solution(&vec![false; edges.len() + 1]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![false; edges.len() + 1]) + .is_err() + ); } } } diff --git a/src/unit_tests/rules/ilp_bool_ilp_i64.rs b/src/unit_tests/rules/ilp_bool_ilp_i64.rs index 367f4d737..861b835f2 100644 --- a/src/unit_tests/rules/ilp_bool_ilp_i64.rs +++ b/src/unit_tests/rules/ilp_bool_ilp_i64.rs @@ -1,4 +1,4 @@ -use crate::models::algebraic::{Bounded, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, LinearConstraint, ObjectiveSense}; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::solvers::ILPSolver; use crate::traits::Problem; diff --git a/src/unit_tests/rules/ilp_casts.rs b/src/unit_tests/rules/ilp_casts.rs index 2784c1f0b..784e11f7c 100644 --- a/src/unit_tests/rules/ilp_casts.rs +++ b/src/unit_tests/rules/ilp_casts.rs @@ -59,10 +59,12 @@ fn test_ilp_cast_rechecks_source_feasibility() { let reduction = ReduceTo::>::reduce_to(&source).unwrap(); let target_solution = vec![rhs + 1]; - assert!(reduction - .target_problem() - .is_feasible(&target_solution) - .unwrap()); + assert!( + reduction + .target_problem() + .is_feasible(&target_solution) + .unwrap() + ); assert!(reduction.extract_solution(&target_solution).is_err()); } diff --git a/src/unit_tests/rules/ilp_helpers.rs b/src/unit_tests/rules/ilp_helpers.rs index 9ca18265d..01f6b8908 100644 --- a/src/unit_tests/rules/ilp_helpers.rs +++ b/src/unit_tests/rules/ilp_helpers.rs @@ -82,9 +82,11 @@ fn test_flow_conservation_simple_path() { // Solution: f_01 = 1, f_12 = 1 let values = vec![1i64, 1]; - assert!(constraints - .iter() - .all(|constraint| constraint.is_satisfied(&values).unwrap())); + assert!( + constraints + .iter() + .all(|constraint| constraint.is_satisfied(&values).unwrap()) + ); } #[test] @@ -113,17 +115,23 @@ fn test_abs_diff_le() { // |a - b| <= z // a=3, b=1, z=2: |3-1|=2 <= 2 ✓ - assert!(constraints - .iter() - .all(|constraint| constraint.is_satisfied(&[3, 1, 2]).unwrap())); + assert!( + constraints + .iter() + .all(|constraint| constraint.is_satisfied(&[3, 1, 2]).unwrap()) + ); // a=3, b=1, z=1: |3-1|=2 > 1 ✗ - assert!(!constraints - .iter() - .all(|constraint| constraint.is_satisfied(&[3, 1, 1]).unwrap())); + assert!( + !constraints + .iter() + .all(|constraint| constraint.is_satisfied(&[3, 1, 1]).unwrap()) + ); // a=1, b=3, z=2: |1-3|=2 <= 2 ✓ - assert!(constraints - .iter() - .all(|constraint| constraint.is_satisfied(&[1, 3, 2]).unwrap())); + assert!( + constraints + .iter() + .all(|constraint| constraint.is_satisfied(&[1, 3, 2]).unwrap()) + ); } #[test] @@ -136,13 +144,17 @@ fn test_minimax_constraints() { assert_eq!(constraints.len(), 2); // z=5, x_0=3, x_1=4: z >= max(3,4) ✓ - assert!(constraints - .iter() - .all(|constraint| constraint.is_satisfied(&[3, 4, 5]).unwrap())); + assert!( + constraints + .iter() + .all(|constraint| constraint.is_satisfied(&[3, 4, 5]).unwrap()) + ); // z=3, x_0=3, x_1=4: z < max(3,4) ✗ - assert!(!constraints - .iter() - .all(|constraint| constraint.is_satisfied(&[3, 4, 3]).unwrap())); + assert!( + !constraints + .iter() + .all(|constraint| constraint.is_satisfied(&[3, 4, 3]).unwrap()) + ); } #[test] @@ -217,7 +229,9 @@ fn test_one_hot_assignment_constraints() { solution[0] = 1; // item 0 -> slot 0 solution[4] = 1; // item 1 -> slot 1 solution[8] = 1; // item 2 -> slot 2 - assert!(constraints - .iter() - .all(|constraint| constraint.is_satisfied(&solution).unwrap())); + assert!( + constraints + .iter() + .all(|constraint| constraint.is_satisfied(&solution).unwrap()) + ); } diff --git a/src/unit_tests/rules/ilp_i64_ilp_bool.rs b/src/unit_tests/rules/ilp_i64_ilp_bool.rs index 94aec190b..47579f385 100644 --- a/src/unit_tests/rules/ilp_i64_ilp_bool.rs +++ b/src/unit_tests/rules/ilp_i64_ilp_bool.rs @@ -1,4 +1,4 @@ -use crate::models::algebraic::{Bounded, IntegerVariable, LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, IntegerVariable, LinearConstraint, ObjectiveSense}; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::solvers::ILPSolver; @@ -77,11 +77,13 @@ fn test_ilp_i64_to_ilp_bool_target_structure() { let reduction = ReduceTo::>::reduce_to(&source).unwrap(); assert_eq!(reduction.target_problem().num_vars(), 6); assert_eq!(reduction.target_problem().constraints().len(), 1); - assert!(reduction - .target_problem() - .variables() - .iter() - .all(|variable| variable.lower_bound() == Some(0) && variable.upper_bound() == Some(1))); + assert!( + reduction + .target_problem() + .variables() + .iter() + .all(|variable| variable.lower_bound() == Some(0) && variable.upper_bound() == Some(1)) + ); } #[test] diff --git a/src/unit_tests/rules/ilp_qubo.rs b/src/unit_tests/rules/ilp_qubo.rs index 1e056d92b..bfe936594 100644 --- a/src/unit_tests/rules/ilp_qubo.rs +++ b/src/unit_tests/rules/ilp_qubo.rs @@ -238,8 +238,8 @@ fn test_ilp_to_qubo_structure() { #[test] fn test_ilp_qubo_all_small_rows_and_target_assignments() { - use crate::rules::AggregateReductionResult; use crate::Problem; + use crate::rules::AggregateReductionResult; for n in 0usize..=3 { for mut code in 0..3usize.pow(n as u32) { let coefficients: Vec<_> = (0..n) @@ -313,9 +313,11 @@ fn test_ilp_qubo_all_small_rows_and_target_assignments() { .unwrap(); } assert_eq!(actual, expected); - assert!(reduction - .extract_solution(&vec![false; target.num_vars() + 1]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![false; target.num_vars() + 1]) + .is_err() + ); } } } @@ -325,8 +327,8 @@ fn test_ilp_qubo_all_small_rows_and_target_assignments() { #[test] fn test_ilp_qubo_inconsistent_rows_and_absent_aggregate() { - use crate::rules::AggregateReductionResult; use crate::Problem; + use crate::rules::AggregateReductionResult; for sense in [ObjectiveSense::Minimize, ObjectiveSense::Maximize] { let source = ILP::::new( 3, @@ -350,16 +352,14 @@ fn test_ilp_qubo_inconsistent_rows_and_absent_aggregate() { !AggregateReductionResult::extract_value(&reduction, crate::types::Min(None)) .is_valid() ); - assert!(!AggregateReductionResult::extract_value( - &reduction, - crate::types::Min(Some(i64::MIN)) - ) - .is_valid()); - assert!(!AggregateReductionResult::extract_value( - &reduction, - crate::types::Min(Some(i64::MAX)) - ) - .is_valid()); + assert!( + !AggregateReductionResult::extract_value(&reduction, crate::types::Min(Some(i64::MIN))) + .is_valid() + ); + assert!( + !AggregateReductionResult::extract_value(&reduction, crate::types::Min(Some(i64::MAX))) + .is_valid() + ); } } diff --git a/src/unit_tests/rules/integerknapsack_ilp.rs b/src/unit_tests/rules/integerknapsack_ilp.rs index 2c51e527f..980dd1a63 100644 --- a/src/unit_tests/rules/integerknapsack_ilp.rs +++ b/src/unit_tests/rules/integerknapsack_ilp.rs @@ -1,6 +1,6 @@ #[cfg(feature = "example-db")] use super::canonical_rule_example_specs; -use crate::models::algebraic::{Bounded, Comparison, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, Comparison, ILP, ObjectiveSense}; use crate::models::set::IntegerKnapsack; use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::rules::{ReduceTo, ReductionResult}; diff --git a/src/unit_tests/rules/integralflowbundles_ilp.rs b/src/unit_tests/rules/integralflowbundles_ilp.rs index a1e1637c3..b2a65198b 100644 --- a/src/unit_tests/rules/integralflowbundles_ilp.rs +++ b/src/unit_tests/rules/integralflowbundles_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{Bounded, Comparison, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, Comparison, ILP, ObjectiveSense}; use crate::solvers::{BruteForce, ILPSolver}; use crate::topology::MultiDigraph; use crate::traits::Problem; diff --git a/src/unit_tests/rules/isomorphicspanningtree_ilp.rs b/src/unit_tests/rules/isomorphicspanningtree_ilp.rs index 4f90f2ee2..515cd7eaf 100644 --- a/src/unit_tests/rules/isomorphicspanningtree_ilp.rs +++ b/src/unit_tests/rules/isomorphicspanningtree_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::solvers::{BruteForce, ILPSolver}; use crate::topology::SimpleGraph; diff --git a/src/unit_tests/rules/kcoloring_bicliquecover.rs b/src/unit_tests/rules/kcoloring_bicliquecover.rs index 9002cdc3c..ebd52a948 100644 --- a/src/unit_tests/rules/kcoloring_bicliquecover.rs +++ b/src/unit_tests/rules/kcoloring_bicliquecover.rs @@ -154,7 +154,7 @@ fn test_kcoloring_to_bicliquecover_rejects_adjacent_grouping() { set(&mut bad, 0, 0); // a_0 set(&mut bad, 1, 0); // g_0 set(&mut bad, left_size + n, 0); // h_0 - // Biclique 1: G_1 = ({a_1, g_1}, {h_1}); no nonadjacent w of 1. + // Biclique 1: G_1 = ({a_1, g_1}, {h_1}); no nonadjacent w of 1. set(&mut bad, 2, 1); // a_1 set(&mut bad, 3, 1); // g_1 set(&mut bad, left_size + n + 1, 1); // h_1 diff --git a/src/unit_tests/rules/knapsack_ilp.rs b/src/unit_tests/rules/knapsack_ilp.rs index 36c11a5c4..30def4ae0 100644 --- a/src/unit_tests/rules/knapsack_ilp.rs +++ b/src/unit_tests/rules/knapsack_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{Comparison, ObjectiveSense, ILP}; +use crate::models::algebraic::{Comparison, ILP, ObjectiveSense}; use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::solvers::{BruteForce, ILPSolver}; use crate::traits::Problem; diff --git a/src/unit_tests/rules/ksatisfiability_bicliquecover.rs b/src/unit_tests/rules/ksatisfiability_bicliquecover.rs index 7ecd3e734..2b9646a94 100644 --- a/src/unit_tests/rules/ksatisfiability_bicliquecover.rs +++ b/src/unit_tests/rules/ksatisfiability_bicliquecover.rs @@ -67,7 +67,7 @@ fn test_ksatisfiability_to_bicliquecover_structure_issue_example() { let n = 8; // next power of two of 2*4 = 8 let ell = 3; // log2 8 let m = 2 + 2 * (n / 2); // 2 source + 2 per normalized var = 2 + 8 = 10 - // k_f = 4*3 + 2*ceil(log2 10) + 6 = 12 + 8 + 6 = 26 + // k_f = 4*3 + 2*ceil(log2 10) + 6 = 12 + 8 + 6 = 26 let k_f = 4 * ell + 2 * 4 + 6; let rank = k_f + 2 * ell + 2; diff --git a/src/unit_tests/rules/ksatisfiability_cyclicordering.rs b/src/unit_tests/rules/ksatisfiability_cyclicordering.rs index 078a004ae..ec0dcf842 100644 --- a/src/unit_tests/rules/ksatisfiability_cyclicordering.rs +++ b/src/unit_tests/rules/ksatisfiability_cyclicordering.rs @@ -175,12 +175,14 @@ fn test_ksatisfiability_to_cyclicordering_unsatisfiable_repeated_literal_pair() assert_eq!(normalized.clauses.len(), 8); assert_eq!(reduction.target_problem().num_elements(), 55); for mask in 0..1usize << normalized.num_vars { - assert!(!normalized - .clauses - .iter() - .all(|clause| clause.iter().any(|&literal| { - (mask & (1 << (literal.unsigned_abs() as usize - 1)) != 0) == (literal > 0) - }))); + assert!( + !normalized + .clauses + .iter() + .all(|clause| clause.iter().any(|&literal| { + (mask & (1 << (literal.unsigned_abs() as usize - 1)) != 0) == (literal > 0) + })) + ); } } @@ -222,11 +224,13 @@ fn repeated_and_unsorted_clauses_preserve_all_source_assignments() { .unwrap(); let reduction = ReduceTo::::reduce_to(&source).unwrap(); let normalized = normalize(&source).unwrap(); - assert!(normalized - .clauses - .iter() - .all(|clause| clause[0].unsigned_abs() < clause[1].unsigned_abs() - && clause[1].unsigned_abs() < clause[2].unsigned_abs())); + assert!( + normalized + .clauses + .iter() + .all(|clause| clause[0].unsigned_abs() < clause[1].unsigned_abs() + && clause[1].unsigned_abs() < clause[2].unsigned_abs()) + ); for mask in 0..64 { let assignment: Vec<_> = (0..6).map(|bit| mask & (1 << bit) != 0).collect(); if source.evaluate(&assignment).unwrap().0 { diff --git a/src/unit_tests/rules/ksatisfiability_directedtwocommodityintegralflow.rs b/src/unit_tests/rules/ksatisfiability_directedtwocommodityintegralflow.rs index ef995f0ab..e99ff10f2 100644 --- a/src/unit_tests/rules/ksatisfiability_directedtwocommodityintegralflow.rs +++ b/src/unit_tests/rules/ksatisfiability_directedtwocommodityintegralflow.rs @@ -63,8 +63,8 @@ fn test_ksatisfiability_to_directedtwocommodityintegralflow_structure() { } #[test] -fn test_ksatisfiability_to_directedtwocommodityintegralflow_assignment_encoding_matches_truth_table( -) { +fn test_ksatisfiability_to_directedtwocommodityintegralflow_assignment_encoding_matches_truth_table() + { let source = issue_example(); let reduction = ReduceTo::::reduce_to(&source) diff --git a/src/unit_tests/rules/ksatisfiability_kclique.rs b/src/unit_tests/rules/ksatisfiability_kclique.rs index baa3dc457..14abcd480 100644 --- a/src/unit_tests/rules/ksatisfiability_kclique.rs +++ b/src/unit_tests/rules/ksatisfiability_kclique.rs @@ -41,10 +41,12 @@ fn test_ksatisfiability_to_kclique_closed_loop() { ); let reduction = ReduceTo::>::reduce_to(&no).unwrap(); assert_eq!(reduction.target_problem().num_edges(), 6); - assert!(BruteForce::new() - .solve(reduction.target_problem()) - .unwrap() - .is_none()); + assert!( + BruteForce::new() + .solve(reduction.target_problem()) + .unwrap() + .is_none() + ); } #[test] diff --git a/src/unit_tests/rules/ksatisfiability_kernel.rs b/src/unit_tests/rules/ksatisfiability_kernel.rs index 9805e42ac..2a6233266 100644 --- a/src/unit_tests/rules/ksatisfiability_kernel.rs +++ b/src/unit_tests/rules/ksatisfiability_kernel.rs @@ -59,10 +59,12 @@ fn test_ksatisfiability_to_kernel_unsatisfiable_instance_has_no_kernel() { ); let reduction = ReduceTo::::reduce_to(&source).expect("reduction should succeed"); - assert!(BruteForce::new() - .solve(reduction.target_problem()) - .unwrap() - .is_none()); + assert!( + BruteForce::new() + .solve(reduction.target_problem()) + .unwrap() + .is_none() + ); } #[test] diff --git a/src/unit_tests/rules/ksatisfiability_monochromatictriangle.rs b/src/unit_tests/rules/ksatisfiability_monochromatictriangle.rs index b70a1fc25..038b366f4 100644 --- a/src/unit_tests/rules/ksatisfiability_monochromatictriangle.rs +++ b/src/unit_tests/rules/ksatisfiability_monochromatictriangle.rs @@ -1,5 +1,5 @@ use super::add_equality_sender; -use crate::models::algebraic::{LinearConstraint, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint}; use crate::models::formula::{CNFClause, KSatisfiability}; use crate::models::graph::MonochromaticTriangle; use crate::rules::traits::{ReduceTo, ReductionResult}; diff --git a/src/unit_tests/rules/ksatisfiability_preemptivescheduling.rs b/src/unit_tests/rules/ksatisfiability_preemptivescheduling.rs index 25c7c3e93..3ebcd82c1 100644 --- a/src/unit_tests/rules/ksatisfiability_preemptivescheduling.rs +++ b/src/unit_tests/rules/ksatisfiability_preemptivescheduling.rs @@ -58,10 +58,12 @@ fn test_ksatisfiability_to_preemptivescheduling_structure() { assert_eq!(target.num_tasks(), 28); assert_eq!(target.d_max(), 28); let construction = build_ullman_construction(&source); - assert!(construction - .filler_jobs_by_slot - .iter() - .all(|layer| !layer.is_empty())); + assert!( + construction + .filler_jobs_by_slot + .iter() + .all(|layer| !layer.is_empty()) + ); assert!(target.lengths().iter().all(|&length| length == 1)); } @@ -181,12 +183,10 @@ fn test_threshold_value_mapping_and_repeated_literals() { ); assert_eq!(result.extract_value(Min(None)), Or(false)); if let Some(schedule) = schedule { - assert!(construct_schedule_from_assignment( - target, - &vec![true; source.num_vars()], - &source - ) - .is_some()); + assert!( + construct_schedule_from_assignment(target, &vec![true; source.num_vars()], &source) + .is_some() + ); let value = target.evaluate(&schedule).unwrap(); assert_eq!(result.extract_value(value), Or(true)); assert!( @@ -213,12 +213,14 @@ fn test_extract_rejects_invalid_and_late_schedules() { Min(Some(5)) ); assert!(result.extract_solution(&schedule).is_err()); - assert!(result - .extract_solution(&vec![ - vec![false; result.target_problem().d_max()]; - schedule.len() - ]) - .is_err()); + assert!( + result + .extract_solution(&vec![ + vec![false; result.target_problem().d_max()]; + schedule.len() + ]) + .is_err() + ); assert!(result.extract_solution(&vec![]).is_err()); } diff --git a/src/unit_tests/rules/ksatisfiability_qubo.rs b/src/unit_tests/rules/ksatisfiability_qubo.rs index acc349424..42fc75fe4 100644 --- a/src/unit_tests/rules/ksatisfiability_qubo.rs +++ b/src/unit_tests/rules/ksatisfiability_qubo.rs @@ -311,9 +311,11 @@ fn test_sat_qubo_all_one_variable_clause_pairs_and_raw_targets() { Or(false) ); assert!(reduction.extract_solution(&vec![]).is_err()); - assert!(reduction - .extract_solution(&vec![false; target.num_vars() + 1]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![false; target.num_vars() + 1]) + .is_err() + ); } } for n in [0, 3] { diff --git a/src/unit_tests/rules/ksatisfiability_registersufficiency.rs b/src/unit_tests/rules/ksatisfiability_registersufficiency.rs index e9a2fbced..bad74ebe2 100644 --- a/src/unit_tests/rules/ksatisfiability_registersufficiency.rs +++ b/src/unit_tests/rules/ksatisfiability_registersufficiency.rs @@ -190,11 +190,13 @@ fn test_repeated_and_tautological_clauses() { .map(|&i| original[i]) .collect(); let positions = layout.schedule_for_assignment(&compact); - assert!(reduction - .target_problem() - .simulate_registers(&positions) - .unwrap() - .is_some()); + assert!( + reduction + .target_problem() + .simulate_registers(&positions) + .unwrap() + .is_some() + ); let source_value = source.evaluate(&original).unwrap(); assert_eq!( reduction.target_problem().evaluate(&positions).unwrap(), diff --git a/src/unit_tests/rules/lengthboundeddisjointpaths_ilp.rs b/src/unit_tests/rules/lengthboundeddisjointpaths_ilp.rs index 595c3bc38..24fefa107 100644 --- a/src/unit_tests/rules/lengthboundeddisjointpaths_ilp.rs +++ b/src/unit_tests/rules/lengthboundeddisjointpaths_ilp.rs @@ -1,7 +1,7 @@ use super::*; use crate::models::algebraic::ILP; -use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::rules::ReduceTo; +use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::solvers::{BruteForce, ILPSolver}; use crate::topology::SimpleGraph; use crate::traits::Problem; @@ -71,10 +71,12 @@ fn test_lengthboundeddisjointpaths_to_ilp_preserves_edge_order() { for index in [1, 13, 15, 16, 17] { target_solution[index] = 1; } - assert!(reduction - .target_problem() - .is_feasible(&target_solution) - .unwrap()); + assert!( + reduction + .target_problem() + .is_feasible(&target_solution) + .unwrap() + ); let extracted = reduction.extract_solution(&target_solution).unwrap(); assert_eq!( extracted, @@ -98,10 +100,12 @@ fn test_lengthboundeddisjointpaths_to_ilp_extracts_path_from_circulation() { let source = LengthBoundedDisjointPaths::new(SimpleGraph::new(5, edges), 0, 1, 4); let reduction = ReduceTo::>::reduce_to(&source).unwrap(); let target_solution = vec![1, 0, 1, 0, 1, 0, 1, 0, 1]; - assert!(reduction - .target_problem() - .is_feasible(&target_solution) - .unwrap()); + assert!( + reduction + .target_problem() + .is_feasible(&target_solution) + .unwrap() + ); let extracted = reduction.extract_solution(&target_solution).unwrap(); assert_eq!(extracted, vec![vec![true, false, false, false]]); assert_eq!(source.evaluate(&extracted).unwrap(), Max(Some(1))); diff --git a/src/unit_tests/rules/longestcircuit_ilp.rs b/src/unit_tests/rules/longestcircuit_ilp.rs index 55a4222f4..6b987563f 100644 --- a/src/unit_tests/rules/longestcircuit_ilp.rs +++ b/src/unit_tests/rules/longestcircuit_ilp.rs @@ -33,9 +33,11 @@ fn test_decision_longestcircuit_to_ilp_bound_is_a_constraint() { source.evaluate(&actual.unwrap()).unwrap(), crate::types::Or(true) ); - assert!(reduction - .extract_solution(&vec![0; target.num_vars()]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![0; target.num_vars()]) + .is_err() + ); } } let acyclic = Decision::new(LongestCircuit::new(SimpleGraph::path(3), vec![1, 2]), -1); diff --git a/src/unit_tests/rules/longestpath_ilp.rs b/src/unit_tests/rules/longestpath_ilp.rs index 45d443943..aafd3f487 100644 --- a/src/unit_tests/rules/longestpath_ilp.rs +++ b/src/unit_tests/rules/longestpath_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{Bounded, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, ObjectiveSense}; use crate::solvers::{BruteForce, ILPSolver}; use crate::topology::SimpleGraph; use crate::traits::Problem; diff --git a/src/unit_tests/rules/maximum2satisfiability_ilp.rs b/src/unit_tests/rules/maximum2satisfiability_ilp.rs index 758a80d6a..5e6201a49 100644 --- a/src/unit_tests/rules/maximum2satisfiability_ilp.rs +++ b/src/unit_tests/rules/maximum2satisfiability_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{Comparison, ObjectiveSense, ILP}; +use crate::models::algebraic::{Comparison, ILP, ObjectiveSense}; use crate::models::formula::CNFClause; use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::solvers::{BruteForce, ILPSolver}; diff --git a/src/unit_tests/rules/maximumclique_ilp.rs b/src/unit_tests/rules/maximumclique_ilp.rs index 4774f6e14..12c959808 100644 --- a/src/unit_tests/rules/maximumclique_ilp.rs +++ b/src/unit_tests/rules/maximumclique_ilp.rs @@ -7,7 +7,7 @@ fn is_valid_clique(problem: &MaximumClique, config: &[bool]) - let selected: Vec = config .iter() .enumerate() - .filter(|(_, &selected)| selected) + .filter(|&(_, &selected)| selected) .map(|(i, _)| i) .collect(); @@ -26,7 +26,7 @@ fn clique_size(problem: &MaximumClique, config: &[bool]) -> i6 config .iter() .enumerate() - .filter(|(_, &selected)| selected) + .filter(|&(_, &selected)| selected) .map(|(i, _)| problem.weights()[i]) .sum() } diff --git a/src/unit_tests/rules/maximumclique_maximumindependentset.rs b/src/unit_tests/rules/maximumclique_maximumindependentset.rs index c2c81f989..be842a167 100644 --- a/src/unit_tests/rules/maximumclique_maximumindependentset.rs +++ b/src/unit_tests/rules/maximumclique_maximumindependentset.rs @@ -48,9 +48,11 @@ fn test_maximumclique_to_maximumindependentset_triangle() { let target_solutions = solver.find_all_witnesses(target).unwrap(); // MIS on empty graph is all vertices selected - assert!(target_solutions - .iter() - .any(|s| s.iter().filter(|&&selected| selected).count() == 3)); + assert!( + target_solutions + .iter() + .any(|s| s.iter().filter(|&&selected| selected).count() == 3) + ); // Extract solution: should be the full clique {0,1,2} let source_sol = reduction.extract_solution(&target_solutions[0]).unwrap(); @@ -83,9 +85,11 @@ fn test_maximumclique_to_maximumindependentset_empty_graph() { let target_solutions = solver.find_all_witnesses(target).unwrap(); // MIS on K3 is any single vertex - assert!(target_solutions - .iter() - .all(|s| s.iter().filter(|&&selected| selected).count() == 1)); + assert!( + target_solutions + .iter() + .all(|s| s.iter().filter(|&&selected| selected).count() == 1) + ); } #[test] diff --git a/src/unit_tests/rules/maximumcokplex_ilp.rs b/src/unit_tests/rules/maximumcokplex_ilp.rs index 8e479e61f..609b5b6de 100644 --- a/src/unit_tests/rules/maximumcokplex_ilp.rs +++ b/src/unit_tests/rules/maximumcokplex_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::models::graph::MaximumCoKPlex; use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::solvers::ILPSolver; diff --git a/src/unit_tests/rules/maximumcommonedgesubgraph_ilp.rs b/src/unit_tests/rules/maximumcommonedgesubgraph_ilp.rs index 7d63945d2..b1c8314a9 100644 --- a/src/unit_tests/rules/maximumcommonedgesubgraph_ilp.rs +++ b/src/unit_tests/rules/maximumcommonedgesubgraph_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::models::graph::{LabelledArc, LabelledDigraph, MaximumCommonEdgeSubgraph}; use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::solvers::ILPSolver; diff --git a/src/unit_tests/rules/maximumcontactmapoverlap_ilp.rs b/src/unit_tests/rules/maximumcontactmapoverlap_ilp.rs index 111385baa..a528058bc 100644 --- a/src/unit_tests/rules/maximumcontactmapoverlap_ilp.rs +++ b/src/unit_tests/rules/maximumcontactmapoverlap_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::models::graph::MaximumContactMapOverlap; use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::solvers::ILPSolver; diff --git a/src/unit_tests/rules/maximumedgeweightedkclique_ilp.rs b/src/unit_tests/rules/maximumedgeweightedkclique_ilp.rs index af6dc72df..e1b5dd10c 100644 --- a/src/unit_tests/rules/maximumedgeweightedkclique_ilp.rs +++ b/src/unit_tests/rules/maximumedgeweightedkclique_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::models::graph::MaximumEdgeWeightedKClique; use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::topology::SimpleGraph; diff --git a/src/unit_tests/rules/maximumindependentset_ilp.rs b/src/unit_tests/rules/maximumindependentset_ilp.rs index b20f2b265..78dd46f67 100644 --- a/src/unit_tests/rules/maximumindependentset_ilp.rs +++ b/src/unit_tests/rules/maximumindependentset_ilp.rs @@ -1,4 +1,4 @@ -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::models::graph::MaximumIndependentSet; use crate::rules::{ReductionChain, ReductionGraph, ReductionPath}; use crate::solvers::{BruteForce, ILPSolver}; diff --git a/src/unit_tests/rules/maximumindependentset_maximumclique.rs b/src/unit_tests/rules/maximumindependentset_maximumclique.rs index 6b265c794..91e42b5a8 100644 --- a/src/unit_tests/rules/maximumindependentset_maximumclique.rs +++ b/src/unit_tests/rules/maximumindependentset_maximumclique.rs @@ -61,9 +61,11 @@ fn test_maximumindependentset_to_maximumclique_empty_graph() { // All 4 vertices form a clique in complement = all 4 are independent set in source let solver = BruteForce::new(); let best_target = solver.find_all_witnesses(target).unwrap(); - assert!(best_target - .iter() - .all(|s| s.iter().filter(|&&selected| selected).count() == 4)); + assert!( + best_target + .iter() + .all(|s| s.iter().filter(|&&selected| selected).count() == 4) + ); } #[test] @@ -103,7 +105,8 @@ fn test_maximumindependentset_to_maximumclique_complete_graph() { // Max clique in empty graph is single vertex, max IS in K4 is also single vertex let solver = BruteForce::new(); let best = solver.find_all_witnesses(target).unwrap(); - assert!(best - .iter() - .all(|s| s.iter().filter(|&&selected| selected).count() == 1)); + assert!( + best.iter() + .all(|s| s.iter().filter(|&&selected| selected).count() == 1) + ); } diff --git a/src/unit_tests/rules/maximumleafspanningtree_ilp.rs b/src/unit_tests/rules/maximumleafspanningtree_ilp.rs index f76cb0b96..4e23efbf2 100644 --- a/src/unit_tests/rules/maximumleafspanningtree_ilp.rs +++ b/src/unit_tests/rules/maximumleafspanningtree_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{Bounded, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, ObjectiveSense}; use crate::models::graph::MaximumLeafSpanningTree; use crate::rules::ReduceTo; use crate::solvers::{BruteForce, ILPSolver}; diff --git a/src/unit_tests/rules/maximumlikelihoodranking_ilp.rs b/src/unit_tests/rules/maximumlikelihoodranking_ilp.rs index 5e215cb55..a94e337b6 100644 --- a/src/unit_tests/rules/maximumlikelihoodranking_ilp.rs +++ b/src/unit_tests/rules/maximumlikelihoodranking_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::solvers::{BruteForce, ILPSolver}; use crate::traits::Problem; diff --git a/src/unit_tests/rules/maximumsetpacking_casts.rs b/src/unit_tests/rules/maximumsetpacking_casts.rs index 5c37d5230..454a42a91 100644 --- a/src/unit_tests/rules/maximumsetpacking_casts.rs +++ b/src/unit_tests/rules/maximumsetpacking_casts.rs @@ -1,6 +1,6 @@ use super::*; -use crate::rules::traits::ReductionResult; use crate::rules::ReduceTo; +use crate::rules::traits::ReductionResult; use crate::solvers::BruteForce; use crate::traits::Problem; diff --git a/src/unit_tests/rules/minimumcapacitatedspanningtree_ilp.rs b/src/unit_tests/rules/minimumcapacitatedspanningtree_ilp.rs index 67f8205f4..f5d42d33d 100644 --- a/src/unit_tests/rules/minimumcapacitatedspanningtree_ilp.rs +++ b/src/unit_tests/rules/minimumcapacitatedspanningtree_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{Bounded, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, ObjectiveSense}; use crate::models::graph::MinimumCapacitatedSpanningTree; use crate::rules::ReduceTo; use crate::solvers::{BruteForce, ILPSolver}; diff --git a/src/unit_tests/rules/minimumcutintoboundedsets_ilp.rs b/src/unit_tests/rules/minimumcutintoboundedsets_ilp.rs index ae22e673d..27736f641 100644 --- a/src/unit_tests/rules/minimumcutintoboundedsets_ilp.rs +++ b/src/unit_tests/rules/minimumcutintoboundedsets_ilp.rs @@ -1,8 +1,8 @@ use super::*; use crate::models::algebraic::ILP; use crate::models::graph::MinimumCutIntoBoundedSets; -use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::rules::ReduceTo; +use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::topology::SimpleGraph; use crate::traits::Problem; diff --git a/src/unit_tests/rules/minimumdiscreteplanarinversekinematics_qubo.rs b/src/unit_tests/rules/minimumdiscreteplanarinversekinematics_qubo.rs index 0bc0c6efc..3d4c71f49 100644 --- a/src/unit_tests/rules/minimumdiscreteplanarinversekinematics_qubo.rs +++ b/src/unit_tests/rules/minimumdiscreteplanarinversekinematics_qubo.rs @@ -26,9 +26,11 @@ fn test_large_link_keeps_one_hot_penalty_strict() { #[test] fn test_extraction_rejects_forbidden_pair() { let reduction = ReduceTo::>::reduce_to(&worked_example()).unwrap(); - assert!(reduction - .extract_solution(&vec![false, true, true, false]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![false, true, true, false]) + .is_err() + ); } fn worked_example() -> MinimumDiscretePlanarInverseKinematics { diff --git a/src/unit_tests/rules/minimumedgecostflow_ilp.rs b/src/unit_tests/rules/minimumedgecostflow_ilp.rs index dff00bfbe..e9cd3809c 100644 --- a/src/unit_tests/rules/minimumedgecostflow_ilp.rs +++ b/src/unit_tests/rules/minimumedgecostflow_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{Bounded, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, ObjectiveSense}; use crate::solvers::{BruteForce, ILPSolver}; use crate::topology::MultiDigraph; use crate::traits::Problem; diff --git a/src/unit_tests/rules/minimumexternalmacrodatacompression_ilp.rs b/src/unit_tests/rules/minimumexternalmacrodatacompression_ilp.rs index b7a71629b..21a3a1371 100644 --- a/src/unit_tests/rules/minimumexternalmacrodatacompression_ilp.rs +++ b/src/unit_tests/rules/minimumexternalmacrodatacompression_ilp.rs @@ -1,5 +1,27 @@ use super::*; -use crate::models::algebraic::{ObjectiveSense, ILP}; + +#[test] +fn test_minimumexternalmacrodatacompression_to_ilp_rejects_malformed_dictionary_slots() { + let source = MinimumExternalMacroDataCompression::new(2, vec![0], 2); + let reduction = ReduceTo::>::reduce_to(&source).unwrap(); + for (symbols, expected) in [ + ([0, 0], "dictionary slot 0 is active without a symbol"), + ([1, 1], "dictionary slot 0 selects multiple symbols"), + ] { + let mut witness = vec![0; reduction.target_problem().num_vars()]; + witness[reduction.layout.d_used_var(0)] = 1; + for (symbol, selected) in symbols.into_iter().enumerate() { + witness[reduction.layout.d_var(0, symbol)] = selected; + } + assert_eq!( + reduction.target_problem().evaluate(&witness).unwrap().value, + None + ); + assert!(matches!(reduction.extract_solution(&witness), + Err(crate::rules::ExtractionError::InvalidTargetSolution(message)) if message == expected)); + } +} +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::solvers::ILPSolver; use crate::traits::Problem; use crate::types::Min; diff --git a/src/unit_tests/rules/minimumfeedbackarcset_ilp.rs b/src/unit_tests/rules/minimumfeedbackarcset_ilp.rs index 84aae55d9..31a2be61b 100644 --- a/src/unit_tests/rules/minimumfeedbackarcset_ilp.rs +++ b/src/unit_tests/rules/minimumfeedbackarcset_ilp.rs @@ -20,10 +20,12 @@ fn feedback_arc_set_solves_through_integer_binary_ilp_and_qubo() { .unwrap(); let binary_solution = qubo.extract_solution(&optimum).unwrap(); let integer_solution = binary.extract_solution(&binary_solution).unwrap(); - assert!(integer - .target_problem() - .is_feasible(&integer_solution) - .unwrap()); + assert!( + integer + .target_problem() + .is_feasible(&integer_solution) + .unwrap() + ); let solution = integer.extract_solution(&integer_solution).unwrap(); assert_eq!(source.evaluate(&solution).unwrap(), Min(Some(2))); } diff --git a/src/unit_tests/rules/minimumfeedbackvertexset_minimumcodegenerationunlimitedregisters.rs b/src/unit_tests/rules/minimumfeedbackvertexset_minimumcodegenerationunlimitedregisters.rs index 68605427a..26118d82a 100644 --- a/src/unit_tests/rules/minimumfeedbackvertexset_minimumcodegenerationunlimitedregisters.rs +++ b/src/unit_tests/rules/minimumfeedbackvertexset_minimumcodegenerationunlimitedregisters.rs @@ -1,7 +1,7 @@ -use super::{issue_example_source, ReductionFVSToCodeGen}; +use super::{ReductionFVSToCodeGen, issue_example_source}; use crate::models::misc::MinimumCodeGenerationUnlimitedRegisters; -use crate::rules::test_helpers::assert_optimization_round_trip_from_optimization_target; use crate::rules::ReduceTo; +use crate::rules::test_helpers::assert_optimization_round_trip_from_optimization_target; #[test] fn test_minimumfeedbackvertexset_to_minimumcodegenerationunlimitedregisters_closed_loop() { diff --git a/src/unit_tests/rules/minimummatrixcover_ilp.rs b/src/unit_tests/rules/minimummatrixcover_ilp.rs index da371feef..b9e43bd34 100644 --- a/src/unit_tests/rules/minimummatrixcover_ilp.rs +++ b/src/unit_tests/rules/minimummatrixcover_ilp.rs @@ -1,6 +1,6 @@ use super::*; use crate::models::algebraic::MinimumMatrixCover; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::solvers::{BruteForce, ILPSolver}; use crate::traits::Problem; diff --git a/src/unit_tests/rules/minimumsummulticenter_ilp.rs b/src/unit_tests/rules/minimumsummulticenter_ilp.rs index a6d254c93..5c9a16a00 100644 --- a/src/unit_tests/rules/minimumsummulticenter_ilp.rs +++ b/src/unit_tests/rules/minimumsummulticenter_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::models::graph::MinimumSumMulticenter; use crate::solvers::{BruteForce, ILPSolver}; use crate::topology::SimpleGraph; diff --git a/src/unit_tests/rules/minimumvertexcover_casts.rs b/src/unit_tests/rules/minimumvertexcover_casts.rs index d8a3bb02c..95b9bc2f3 100644 --- a/src/unit_tests/rules/minimumvertexcover_casts.rs +++ b/src/unit_tests/rules/minimumvertexcover_casts.rs @@ -55,8 +55,10 @@ fn test_minimumvertexcover_one_to_i64_closed_loop() { .unwrap(), serde_json::to_value(Min(Some(optimum))).unwrap(), ); - assert!(chain - .extract_solution::, _>(&vec![false; input.num_vertices() + 1]) - .is_err()); + assert!( + chain + .extract_solution::, _>(&vec![false; input.num_vertices() + 1]) + .is_err() + ); } } diff --git a/src/unit_tests/rules/minimumvertexcover_comparativecontainment.rs b/src/unit_tests/rules/minimumvertexcover_comparativecontainment.rs index 8beb764e7..35d9f2afd 100644 --- a/src/unit_tests/rules/minimumvertexcover_comparativecontainment.rs +++ b/src/unit_tests/rules/minimumvertexcover_comparativecontainment.rs @@ -35,10 +35,12 @@ fn test_minimumvertexcover_to_comparativecontainment_closed_loop() { 0, ); let reduction = ReduceTo::>::reduce_to(&source).unwrap(); - assert!(BruteForce::new() - .solve(reduction.target_problem()) - .unwrap() - .is_none()); + assert!( + BruteForce::new() + .solve(reduction.target_problem()) + .unwrap() + .is_none() + ); } #[test] @@ -77,11 +79,13 @@ fn test_signed_containment_all_small_graphs_and_witnesses() { assert_eq!(target.universe_size(), n); assert!(target.num_r_sets() <= n + 1); assert!(target.num_s_sets() <= n + edges.len() + 1); - assert!(target - .r_weights() - .iter() - .chain(target.s_weights()) - .all(|&w| w > 0)); + assert!( + target + .r_weights() + .iter() + .chain(target.s_weights()) + .all(|&w| w > 0) + ); for mask in 0..(1usize << n) { let witness: Vec<_> = (0..n).map(|v| mask & (1 << v) != 0).collect(); let valid = source.evaluate(&witness).unwrap().0; diff --git a/src/unit_tests/rules/minimumvertexcover_ensemblecomputation.rs b/src/unit_tests/rules/minimumvertexcover_ensemblecomputation.rs index cc13bdf98..1cb7d8674 100644 --- a/src/unit_tests/rules/minimumvertexcover_ensemblecomputation.rs +++ b/src/unit_tests/rules/minimumvertexcover_ensemblecomputation.rs @@ -1,7 +1,7 @@ use crate::models::graph::MinimumVertexCover; use crate::models::misc::EnsembleComputation; -use crate::rules::traits::ReduceTo; use crate::rules::ReductionResult; +use crate::rules::traits::ReduceTo; use crate::solvers::BruteForce; use crate::topology::{Graph, SimpleGraph}; use crate::traits::Problem; diff --git a/src/unit_tests/rules/minimumvertexcover_ilp.rs b/src/unit_tests/rules/minimumvertexcover_ilp.rs index 371655368..890284b1a 100644 --- a/src/unit_tests/rules/minimumvertexcover_ilp.rs +++ b/src/unit_tests/rules/minimumvertexcover_ilp.rs @@ -1,4 +1,4 @@ -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::models::graph::MinimumVertexCover; use crate::rules::{ReductionChain, ReductionGraph, ReductionPath}; use crate::solvers::{BruteForce, ILPSolver}; diff --git a/src/unit_tests/rules/minimumvertexcover_minimumfeedbackarcset.rs b/src/unit_tests/rules/minimumvertexcover_minimumfeedbackarcset.rs index 876c5e16c..41ac99d02 100644 --- a/src/unit_tests/rules/minimumvertexcover_minimumfeedbackarcset.rs +++ b/src/unit_tests/rules/minimumvertexcover_minimumfeedbackarcset.rs @@ -1,10 +1,10 @@ +use super::ReductionVCToFAS; #[cfg(feature = "example-db")] use super::canonical_rule_example_specs; -use super::ReductionVCToFAS; use crate::models::graph::{MinimumFeedbackArcSet, MinimumVertexCover}; +use crate::rules::ReduceTo; use crate::rules::test_helpers::assert_optimization_round_trip_from_optimization_target; use crate::rules::traits::ReductionResult; -use crate::rules::ReduceTo; use crate::solvers::BruteForce; use crate::topology::{Graph, SimpleGraph}; use crate::traits::Problem; @@ -39,14 +39,18 @@ fn test_signed_weights_preserve_all_target_optima() { fn test_extraction_rejects_uncovered_edges_and_penalty_overflow() { let source = MinimumVertexCover::new(SimpleGraph::new(2, vec![(0, 1)]), vec![1_i64; 2]); let reduction = ReduceTo::>::reduce_to(&source).unwrap(); - assert!(reduction - .target_problem() - .evaluate(&vec![false, false, true, true]) - .unwrap() - .is_valid()); - assert!(reduction - .extract_solution(&vec![false, false, true, true]) - .is_err()); + assert!( + reduction + .target_problem() + .evaluate(&vec![false, false, true, true]) + .unwrap() + .is_valid() + ); + assert!( + reduction + .extract_solution(&vec![false, false, true, true]) + .is_err() + ); for weights in [vec![i64::MAX, 0], vec![i64::MAX, 1]] { let source = MinimumVertexCover::new(SimpleGraph::new(2, vec![(0, 1)]), weights); assert!(ReduceTo::>::reduce_to(&source).is_err()); diff --git a/src/unit_tests/rules/minimumvertexcover_minimumfeedbackvertexset.rs b/src/unit_tests/rules/minimumvertexcover_minimumfeedbackvertexset.rs index 9230ebe1c..57f51e320 100644 --- a/src/unit_tests/rules/minimumvertexcover_minimumfeedbackvertexset.rs +++ b/src/unit_tests/rules/minimumvertexcover_minimumfeedbackvertexset.rs @@ -1,10 +1,10 @@ +use super::ReductionVCToFVS; #[cfg(feature = "example-db")] use super::canonical_rule_example_specs; -use super::ReductionVCToFVS; use crate::models::graph::{MinimumFeedbackVertexSet, MinimumVertexCover}; +use crate::rules::ReduceTo; use crate::rules::test_helpers::assert_optimization_round_trip_from_optimization_target; use crate::rules::traits::ReductionResult; -use crate::rules::ReduceTo; #[cfg(feature = "example-db")] use crate::solvers::BruteForce; use crate::topology::{Graph, SimpleGraph}; diff --git a/src/unit_tests/rules/minimumvertexcover_minimumweightandorgraph.rs b/src/unit_tests/rules/minimumvertexcover_minimumweightandorgraph.rs index 1bb809624..c3dd95c3a 100644 --- a/src/unit_tests/rules/minimumvertexcover_minimumweightandorgraph.rs +++ b/src/unit_tests/rules/minimumvertexcover_minimumweightandorgraph.rs @@ -1,11 +1,11 @@ #[cfg(feature = "example-db")] use super::canonical_rule_example_specs; -use super::{issue_example_source, ReductionVCToAndOrGraph}; +use super::{ReductionVCToAndOrGraph, issue_example_source}; use crate::models::graph::MinimumVertexCover; use crate::models::misc::MinimumWeightAndOrGraph; +use crate::rules::ReduceTo; use crate::rules::test_helpers::assert_optimization_round_trip_from_optimization_target; use crate::rules::traits::ReductionResult; -use crate::rules::ReduceTo; #[cfg(feature = "example-db")] use crate::solvers::BruteForce; use crate::topology::SimpleGraph; diff --git a/src/unit_tests/rules/minimumweightdecoding_ilp.rs b/src/unit_tests/rules/minimumweightdecoding_ilp.rs index c4d322a78..ab8d9a200 100644 --- a/src/unit_tests/rules/minimumweightdecoding_ilp.rs +++ b/src/unit_tests/rules/minimumweightdecoding_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{Bounded, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, ObjectiveSense}; use crate::solvers::{BruteForce, ILPSolver}; use crate::traits::Problem; use crate::types::Min; diff --git a/src/unit_tests/rules/minmaxmulticenter_ilp.rs b/src/unit_tests/rules/minmaxmulticenter_ilp.rs index 517661794..5b70499a2 100644 --- a/src/unit_tests/rules/minmaxmulticenter_ilp.rs +++ b/src/unit_tests/rules/minmaxmulticenter_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{Bounded, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, ObjectiveSense}; use crate::models::graph::MinMaxMulticenter; use crate::solvers::{BruteForce, ILPSolver}; use crate::topology::SimpleGraph; diff --git a/src/unit_tests/rules/monochromatictriangle_ilp.rs b/src/unit_tests/rules/monochromatictriangle_ilp.rs index 0dbd944fd..8023c4a51 100644 --- a/src/unit_tests/rules/monochromatictriangle_ilp.rs +++ b/src/unit_tests/rules/monochromatictriangle_ilp.rs @@ -1,4 +1,4 @@ -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::models::graph::MonochromaticTriangle; use crate::rules::traits::{ReduceTo, ReductionResult}; use crate::solvers::ILPSolver; diff --git a/src/unit_tests/rules/naesatisfiability_maxcut.rs b/src/unit_tests/rules/naesatisfiability_maxcut.rs index 78a6ac704..f45676fae 100644 --- a/src/unit_tests/rules/naesatisfiability_maxcut.rs +++ b/src/unit_tests/rules/naesatisfiability_maxcut.rs @@ -225,9 +225,11 @@ fn check_every_cut(source: &NAESatisfiability) { decoded.iter().any(|&valid| valid) ); assert!(!AggregateReductionResult::extract_value(&reduction, crate::types::Or(false)).0); - assert!(reduction - .extract_solution(&vec![false; target.num_vertices() + 1]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![false; target.num_vertices() + 1]) + .is_err() + ); } #[test] diff --git a/src/unit_tests/rules/naesatisfiability_partitionintoperfectmatchings.rs b/src/unit_tests/rules/naesatisfiability_partitionintoperfectmatchings.rs index effae7251..a0b5576f1 100644 --- a/src/unit_tests/rules/naesatisfiability_partitionintoperfectmatchings.rs +++ b/src/unit_tests/rules/naesatisfiability_partitionintoperfectmatchings.rs @@ -249,10 +249,12 @@ fn test_naesatisfiability_to_partitionintoperfectmatchings_constructed_witness_r let target_solution = reduction.construct_target_solution(&source_solution); assert!(source.evaluate(&source_solution).unwrap()); - assert!(reduction - .target_problem() - .evaluate(&target_solution) - .unwrap()); + assert!( + reduction + .target_problem() + .evaluate(&target_solution) + .unwrap() + ); assert_eq!( reduction.extract_solution(&target_solution).unwrap(), source_solution @@ -325,9 +327,11 @@ fn test_long_clauses_preserve_assignments() { assert_eq!(result.extract_solution(&witness).unwrap(), assignment); } } - assert!(result - .extract_solution(&vec![0; layout.num_vertices]) - .is_err()); + assert!( + result + .extract_solution(&vec![0; layout.num_vertices]) + .is_err() + ); assert!(result.extract_solution(&vec![]).is_err()); } } diff --git a/src/unit_tests/rules/naesatisfiability_satisfiability.rs b/src/unit_tests/rules/naesatisfiability_satisfiability.rs index da21b22e5..49c5b2cae 100644 --- a/src/unit_tests/rules/naesatisfiability_satisfiability.rs +++ b/src/unit_tests/rules/naesatisfiability_satisfiability.rs @@ -111,18 +111,22 @@ fn test_naesatisfiability_to_satisfiability_witness_and_near_witness() { let error = reduction .extract_solution(&vec![false, true, false]) .unwrap_err(); - assert!(error - .to_string() - .contains("target assignment does not satisfy CNF clauses")); + assert!( + error + .to_string() + .contains("target assignment does not satisfy CNF clauses") + ); } #[test] fn test_naesatisfiability_to_satisfiability_rejects_malformed_assignment() { let reduction = reduce(&canonical_source()); assert!(reduction.extract_solution(&vec![false, false]).is_err()); - assert!(reduction - .extract_solution(&vec![false, false, true, false]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![false, false, true, false]) + .is_err() + ); } #[test] diff --git a/src/unit_tests/rules/numerical3dimensionalmatching_numericalmatchingwithtargetsums.rs b/src/unit_tests/rules/numerical3dimensionalmatching_numericalmatchingwithtargetsums.rs index cf2136f51..f5e693397 100644 --- a/src/unit_tests/rules/numerical3dimensionalmatching_numericalmatchingwithtargetsums.rs +++ b/src/unit_tests/rules/numerical3dimensionalmatching_numericalmatchingwithtargetsums.rs @@ -90,10 +90,12 @@ fn test_n3dm_to_nmts_unsatisfiable_maps_to_unsatisfiable() { let reduction = ReduceTo::::reduce_to(&source) .expect("reduction should succeed"); assert!(BruteForce::new().solve(&source).unwrap().is_none()); - assert!(BruteForce::new() - .solve(reduction.target_problem()) - .unwrap() - .is_none()); + assert!( + BruteForce::new() + .solve(reduction.target_problem()) + .unwrap() + .is_none() + ); } } diff --git a/src/unit_tests/rules/numericalmatchingwithtargetsums_ilp.rs b/src/unit_tests/rules/numericalmatchingwithtargetsums_ilp.rs index 2c2061814..ac554e645 100644 --- a/src/unit_tests/rules/numericalmatchingwithtargetsums_ilp.rs +++ b/src/unit_tests/rules/numericalmatchingwithtargetsums_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{Comparison, ObjectiveSense, ILP}; +use crate::models::algebraic::{Comparison, ILP, ObjectiveSense}; use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::solvers::ILPSolver; use crate::traits::Problem; diff --git a/src/unit_tests/rules/openshopscheduling_ilp.rs b/src/unit_tests/rules/openshopscheduling_ilp.rs index b43b05a0c..365633889 100644 --- a/src/unit_tests/rules/openshopscheduling_ilp.rs +++ b/src/unit_tests/rules/openshopscheduling_ilp.rs @@ -37,9 +37,11 @@ fn test_decision_openshopscheduling_to_ilp_preserves_makespan_threshold() { source.evaluate(&result.unwrap()).unwrap(), crate::types::Or(true) ); - assert!(reduction - .extract_solution(&vec![0; target.num_vars()]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![0; target.num_vars()]) + .is_err() + ); } } assert_eq!( diff --git a/src/unit_tests/rules/optimallineararrangement_consecutiveonesmatrixaugmentation.rs b/src/unit_tests/rules/optimallineararrangement_consecutiveonesmatrixaugmentation.rs index bac2f366b..6978e5eb0 100644 --- a/src/unit_tests/rules/optimallineararrangement_consecutiveonesmatrixaugmentation.rs +++ b/src/unit_tests/rules/optimallineararrangement_consecutiveonesmatrixaugmentation.rs @@ -190,9 +190,11 @@ fn test_optimallineararrangement_to_consecutiveonesmatrixaugmentation_native_dom Or(true) ); } else { - assert!(reduction - .extract_solution(&(0..target.num_cols()).collect()) - .is_err()); + assert!( + reduction + .extract_solution(&(0..target.num_cols()).collect()) + .is_err() + ); } } } diff --git a/src/unit_tests/rules/optimallineararrangement_sequencingtominimizeweightedcompletiontime.rs b/src/unit_tests/rules/optimallineararrangement_sequencingtominimizeweightedcompletiontime.rs index 0347eda91..da96c2f7b 100644 --- a/src/unit_tests/rules/optimallineararrangement_sequencingtominimizeweightedcompletiontime.rs +++ b/src/unit_tests/rules/optimallineararrangement_sequencingtominimizeweightedcompletiontime.rs @@ -94,8 +94,8 @@ fn test_optimallineararrangement_to_sequencingtominimizeweightedcompletiontime_t } #[test] -fn test_optimallineararrangement_to_sequencingtominimizeweightedcompletiontime_extracts_vertex_order( -) { +fn test_optimallineararrangement_to_sequencingtominimizeweightedcompletiontime_extracts_vertex_order() + { let (source, reduction) = reduce_path(4); let schedule = vec![3, 2, 6, 1, 5, 0, 4]; let extracted = reduction.extract_solution(&schedule).unwrap(); diff --git a/src/unit_tests/rules/optimumcommunicationspanningtree_ilp.rs b/src/unit_tests/rules/optimumcommunicationspanningtree_ilp.rs index 4e0f1cf8c..acd720ffd 100644 --- a/src/unit_tests/rules/optimumcommunicationspanningtree_ilp.rs +++ b/src/unit_tests/rules/optimumcommunicationspanningtree_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::solvers::{BruteForce, ILPSolver}; use crate::traits::Problem; diff --git a/src/unit_tests/rules/paintshop_ilp.rs b/src/unit_tests/rules/paintshop_ilp.rs index aa721eda1..8d77e87ef 100644 --- a/src/unit_tests/rules/paintshop_ilp.rs +++ b/src/unit_tests/rules/paintshop_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::solvers::{BruteForce, ILPSolver}; use crate::traits::Problem; diff --git a/src/unit_tests/rules/partition_openshopscheduling.rs b/src/unit_tests/rules/partition_openshopscheduling.rs index 0ed35ce0f..1f080ff83 100644 --- a/src/unit_tests/rules/partition_openshopscheduling.rs +++ b/src/unit_tests/rules/partition_openshopscheduling.rs @@ -137,9 +137,11 @@ fn test_partition_to_open_shop_all_small_partitions_and_machine_orders() { } } assert!(reduction.extract_solution(&vec![0; (n + 1) * 3]).is_err()); - assert!(reduction - .extract_solution(&vec![0; (n + 1) * 3 + 1]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![0; (n + 1) * 3 + 1]) + .is_err() + ); } } } diff --git a/src/unit_tests/rules/partition_sequencingtominimizetardytaskweight.rs b/src/unit_tests/rules/partition_sequencingtominimizetardytaskweight.rs index 8743e1abb..d81a8ec96 100644 --- a/src/unit_tests/rules/partition_sequencingtominimizetardytaskweight.rs +++ b/src/unit_tests/rules/partition_sequencingtominimizetardytaskweight.rs @@ -2,9 +2,9 @@ use super::canonical_rule_example_specs; use crate::models::decision::Decision; use crate::models::misc::{Partition, SequencingToMinimizeTardyTaskWeight}; +use crate::rules::ReduceTo; use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::rules::traits::ReductionResult; -use crate::rules::ReduceTo; use crate::solvers::BruteForce; use crate::traits::Problem; use crate::types::Min; @@ -179,9 +179,11 @@ fn test_partition_to_tardy_weight_all_small_configurations() { source_feasible ); assert!(reduction.extract_solution(&vec![]).is_err()); - assert!(reduction - .extract_solution(&vec![n as usize; n as usize]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![n as usize; n as usize]) + .is_err() + ); assert!( !crate::rules::AggregateReductionResult::extract_value( &reduction, diff --git a/src/unit_tests/rules/partition_subsetsum.rs b/src/unit_tests/rules/partition_subsetsum.rs index 6cc6380eb..d6dcc1c93 100644 --- a/src/unit_tests/rules/partition_subsetsum.rs +++ b/src/unit_tests/rules/partition_subsetsum.rs @@ -68,7 +68,9 @@ fn test_partition_to_subsetsum_rejects_wrong_solution_length() { let source = Partition::new(vec![1, 1, 2, 2]).unwrap(); let reduction = ReduceTo::::reduce_to(&source).expect("reduction should succeed"); - assert!(reduction - .extract_solution(&vec![false, true, false]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![false, true, false]) + .is_err() + ); } diff --git a/src/unit_tests/rules/partitionintocliques_minimumcoveringbycliques.rs b/src/unit_tests/rules/partitionintocliques_minimumcoveringbycliques.rs index bcca36292..34ff0aa66 100644 --- a/src/unit_tests/rules/partitionintocliques_minimumcoveringbycliques.rs +++ b/src/unit_tests/rules/partitionintocliques_minimumcoveringbycliques.rs @@ -58,10 +58,12 @@ fn test_partitionintocliques_to_minimumcoveringbycliques_closed_loop() { assert!(reduction.target_problem().evaluate(&solution).unwrap().0); let decoded = reduction.extract_solution(&solution).unwrap(); assert!(source.evaluate(&decoded).unwrap().0); - assert!(crate::solvers::BruteForce::new() - .find_all_witnesses(&source) - .unwrap() - .contains(&decoded)); + assert!( + crate::solvers::BruteForce::new() + .find_all_witnesses(&source) + .unwrap() + .contains(&decoded) + ); } #[test] @@ -214,9 +216,11 @@ fn test_partitionintocliques_native_bounds_and_adjacency_semantics() { assert!(reduction.extract_solution(&witness).is_err()); } assert!(reduction.extract_solution(&vec![0; witness.len()]).is_err()); - assert!(reduction - .extract_solution(&vec![0; witness.len() + 1]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![0; witness.len() + 1]) + .is_err() + ); let q = layout.num_directed_pairs(); assert_eq!(target.num_vertices(), 2 * n + 2 * q + 4); assert_eq!(target.num_edges(), (n + q) * (n + q) + 4 * n + 7 * q + 2); diff --git a/src/unit_tests/rules/partitionintopathsoflength2_boundedcomponentspanningforest.rs b/src/unit_tests/rules/partitionintopathsoflength2_boundedcomponentspanningforest.rs index 9ed00d230..d813404ff 100644 --- a/src/unit_tests/rules/partitionintopathsoflength2_boundedcomponentspanningforest.rs +++ b/src/unit_tests/rules/partitionintopathsoflength2_boundedcomponentspanningforest.rs @@ -1,7 +1,7 @@ use super::*; use crate::models::graph::{BoundedComponentSpanningForest, PartitionIntoPathsOfLength2}; -use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::rules::ReduceTo; +use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::solvers::BruteForce; use crate::topology::SimpleGraph; use crate::traits::Problem; diff --git a/src/unit_tests/rules/precedenceconstrainedscheduling_ilp.rs b/src/unit_tests/rules/precedenceconstrainedscheduling_ilp.rs index e2b54f808..2f23ac44e 100644 --- a/src/unit_tests/rules/precedenceconstrainedscheduling_ilp.rs +++ b/src/unit_tests/rules/precedenceconstrainedscheduling_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::solvers::{BruteForce, ILPSolver}; use crate::traits::Problem; diff --git a/src/unit_tests/rules/prizecollectingsteinerforest_steinertree.rs b/src/unit_tests/rules/prizecollectingsteinerforest_steinertree.rs index eb1cf4e5a..45c54d27b 100644 --- a/src/unit_tests/rules/prizecollectingsteinerforest_steinertree.rs +++ b/src/unit_tests/rules/prizecollectingsteinerforest_steinertree.rs @@ -50,9 +50,11 @@ fn test_low_prizes_do_not_bypass_component_costs() { let forest = reduction.extract_solution(&tree).unwrap(); assert_eq!(source.evaluate(&forest).unwrap(), Min(Some(expected))); } - assert!(reduction - .extract_solution(&vec![false; reduction.target_problem().num_edges()]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![false; reduction.target_problem().num_edges()]) + .is_err() + ); } } diff --git a/src/unit_tests/rules/productionplanning_ilp.rs b/src/unit_tests/rules/productionplanning_ilp.rs index 1413e8d3e..e7469ca9f 100644 --- a/src/unit_tests/rules/productionplanning_ilp.rs +++ b/src/unit_tests/rules/productionplanning_ilp.rs @@ -1,7 +1,7 @@ use super::*; use crate::{ - solvers::{BruteForce, ILPSolveError, ILPSolver}, Problem, + solvers::{BruteForce, ILPSolveError, ILPSolver}, }; #[test] diff --git a/src/unit_tests/rules/reduction_path_parity.rs b/src/unit_tests/rules/reduction_path_parity.rs index 8def3533f..e69a6e428 100644 --- a/src/unit_tests/rules/reduction_path_parity.rs +++ b/src/unit_tests/rules/reduction_path_parity.rs @@ -6,8 +6,8 @@ use crate::models::algebraic::Bounded; use crate::models::algebraic::QUBO; use crate::models::graph::{MaxCut, SpinGlass}; use crate::models::misc::Factoring; -use crate::rules::test_helpers::assert_optimization_round_trip_chain; use crate::rules::ReductionGraph; +use crate::rules::test_helpers::assert_optimization_round_trip_chain; use crate::solvers::BruteForce; use crate::solvers::BruteForceProblem as _; use crate::topology::SimpleGraph; diff --git a/src/unit_tests/rules/registersufficiency_ilp.rs b/src/unit_tests/rules/registersufficiency_ilp.rs index 9b50c2864..81067ff2c 100644 --- a/src/unit_tests/rules/registersufficiency_ilp.rs +++ b/src/unit_tests/rules/registersufficiency_ilp.rs @@ -146,9 +146,11 @@ fn cumulative_schedule_preserves_live_values_and_rejects_invalid_targets() { Err(error) => panic!("unexpected solver failure: {error}"), } if source.num_vertices() > 0 { - assert!(reduction - .extract_solution(&vec![0; reduction.target_problem().num_vars()]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![0; reduction.target_problem().num_vars()]) + .is_err() + ); } } } diff --git a/src/unit_tests/rules/registry.rs b/src/unit_tests/rules/registry.rs index 9a3eeec91..98d703230 100644 --- a/src/unit_tests/rules/registry.rs +++ b/src/unit_tests/rules/registry.rs @@ -91,10 +91,12 @@ fn aggregate_registration_matches_exact_endpoints_and_rejects_conflicts() { vec![turing], vec![entries[1]], ] { - assert!(std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { - attach_aggregate_mapping(&mut invalid, &mapping); - })) - .is_err()); + assert!( + std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + attach_aggregate_mapping(&mut invalid, &mapping); + })) + .is_err() + ); } } @@ -174,21 +176,27 @@ fn parameter_contract_errors_and_entry_debug_are_transparent() { [("x", Expr::variable("n")), ("x", Expr::variable("m"))], ) .unwrap_err(); - assert!(ParameterContractError::from(transform_error) + assert!( + ParameterContractError::from(transform_error) + .to_string() + .starts_with("invalid parameter transform:") + ); + assert!( + ParameterContractError::DuplicateClassification { + edge: "A -> B".into(), + field: "x".into(), + } .to_string() - .starts_with("invalid parameter transform:")); - assert!(ParameterContractError::DuplicateClassification { - edge: "A -> B".into(), - field: "x".into(), - } - .to_string() - .contains("classifies target field `x` more than once")); - assert!(ParameterContractError::EmptyUnavailableReason { - edge: "A -> B".into(), - field: "x".into(), - } - .to_string() - .contains("unavailable without a reason")); + .contains("classifies target field `x` more than once") + ); + assert!( + ParameterContractError::EmptyUnavailableReason { + edge: "A -> B".into(), + field: "x".into(), + } + .to_string() + .contains("unavailable without a reason") + ); let entry = entry_with(ReductionParameterDeclarations::default); let debug = format!("{entry:?}"); diff --git a/src/unit_tests/rules/rootedtreestorageassignment_ilp.rs b/src/unit_tests/rules/rootedtreestorageassignment_ilp.rs index c276916c7..da2973e54 100644 --- a/src/unit_tests/rules/rootedtreestorageassignment_ilp.rs +++ b/src/unit_tests/rules/rootedtreestorageassignment_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{Bounded, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, ObjectiveSense}; use crate::solvers::{BruteForce, ILPSolver}; use crate::traits::Problem; use crate::types::Or; diff --git a/src/unit_tests/rules/sat_circuitsat.rs b/src/unit_tests/rules/sat_circuitsat.rs index 259064674..e7be52d0d 100644 --- a/src/unit_tests/rules/sat_circuitsat.rs +++ b/src/unit_tests/rules/sat_circuitsat.rs @@ -1,7 +1,7 @@ use super::*; use crate::models::formula::{CNFClause, CircuitSAT, Satisfiability}; -use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::rules::ReduceTo; +use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::solvers::BruteForce; #[test] diff --git a/src/unit_tests/rules/sat_maximumindependentset.rs b/src/unit_tests/rules/sat_maximumindependentset.rs index 23d6c717a..d6c702ee1 100644 --- a/src/unit_tests/rules/sat_maximumindependentset.rs +++ b/src/unit_tests/rules/sat_maximumindependentset.rs @@ -316,9 +316,11 @@ fn test_sat_to_independentset_all_certificates() { accepted, BruteForce::new().solve(&source).unwrap().is_some() ); - assert!(reduction - .extract_solution(&vec![false; target.num_vertices() + 1]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![false; target.num_vertices() + 1]) + .is_err() + ); } } for num_vars in [0, 3] { diff --git a/src/unit_tests/rules/sat_minimumdominatingset.rs b/src/unit_tests/rules/sat_minimumdominatingset.rs index 4f9e16ebb..1c91bfc37 100644 --- a/src/unit_tests/rules/sat_minimumdominatingset.rs +++ b/src/unit_tests/rules/sat_minimumdominatingset.rs @@ -318,9 +318,11 @@ fn test_sat_to_dominatingset_native_certificates() { accepted, BruteForce::new().solve(&source).unwrap().is_some() ); - assert!(result - .extract_solution(&vec![false; target.num_vertices() + 1]) - .is_err()); + assert!( + result + .extract_solution(&vec![false; target.num_vertices() + 1]) + .is_err() + ); } } diff --git a/src/unit_tests/rules/satisfiability_maximum2satisfiability.rs b/src/unit_tests/rules/satisfiability_maximum2satisfiability.rs index 7e6ffde0a..57458ed14 100644 --- a/src/unit_tests/rules/satisfiability_maximum2satisfiability.rs +++ b/src/unit_tests/rules/satisfiability_maximum2satisfiability.rs @@ -181,9 +181,11 @@ fn test_satisfiability_to_maximum2satisfiability_every_target_witness() { } let source_yes = BruteForce::new().solve(&source).unwrap().is_some(); assert_eq!(best == threshold, source_yes); - assert!(reduction - .extract_solution(&vec![false; target.num_vars() + 1]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![false; target.num_vars() + 1]) + .is_err() + ); assert_eq!( crate::rules::AggregateReductionResult::extract_value( &reduction, diff --git a/src/unit_tests/rules/satisfiability_naesatisfiability.rs b/src/unit_tests/rules/satisfiability_naesatisfiability.rs index e1ee71120..59c6f6b50 100644 --- a/src/unit_tests/rules/satisfiability_naesatisfiability.rs +++ b/src/unit_tests/rules/satisfiability_naesatisfiability.rs @@ -91,14 +91,18 @@ fn test_solution_extraction_distinguishes_zero_assignment_from_malformed_input() error.to_string(), "target evaluation failed during extraction: invalid configuration: assignment length does not match the formula variables" ); - assert!(reduction - .extract_solution(&vec![false, false, false, false]) - .is_err()); - assert!(crate::rules::DynReductionResult::target_solution_from_json( - &reduction, - serde_json::json!([false, 2, false]) - ) - .is_err()); + assert!( + reduction + .extract_solution(&vec![false, false, false, false]) + .is_err() + ); + assert!( + crate::rules::DynReductionResult::target_solution_from_json( + &reduction, + serde_json::json!([false, 2, false]) + ) + .is_err() + ); } #[test] diff --git a/src/unit_tests/rules/schedulingtominimizeweightedcompletiontime_ilp.rs b/src/unit_tests/rules/schedulingtominimizeweightedcompletiontime_ilp.rs index 500ee00c6..da1af7f8b 100644 --- a/src/unit_tests/rules/schedulingtominimizeweightedcompletiontime_ilp.rs +++ b/src/unit_tests/rules/schedulingtominimizeweightedcompletiontime_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{Bounded, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, ObjectiveSense}; use crate::models::misc::SchedulingToMinimizeWeightedCompletionTime; use crate::solvers::{BruteForce, ILPSolver}; use crate::traits::Problem; @@ -19,18 +19,21 @@ fn test_reduction_creates_valid_ilp_structure() { // Objective should reference C_t variables with weights // C vars are at indices 6, 7, 8 - assert!(ilp - .objective() - .iter() - .any(|&(idx, coeff)| idx == 6 && coeff == 4)); - assert!(ilp - .objective() - .iter() - .any(|&(idx, coeff)| idx == 7 && coeff == 2)); - assert!(ilp - .objective() - .iter() - .any(|&(idx, coeff)| idx == 8 && coeff == 1)); + assert!( + ilp.objective() + .iter() + .any(|&(idx, coeff)| idx == 6 && coeff == 4) + ); + assert!( + ilp.objective() + .iter() + .any(|&(idx, coeff)| idx == 7 && coeff == 2) + ); + assert!( + ilp.objective() + .iter() + .any(|&(idx, coeff)| idx == 8 && coeff == 1) + ); } #[test] @@ -49,10 +52,10 @@ fn test_solution_extraction() { sol[1] = 0; // x_{0,1} = 0 sol[2] = 0; // x_{1,0} = 0 sol[3] = 1; // x_{1,1} = 1 - // C vars: indices 4, 5 + // C vars: indices 4, 5 sol[4] = 1; // C_0 = 1 sol[5] = 2; // C_1 = 2 - // y vars: index 6 + // y vars: index 6 sol[6] = 1; // y_{0,1} = 1 let extracted = reduction.extract_solution(&sol).unwrap(); diff --git a/src/unit_tests/rules/schedulingwithindividualdeadlines_ilp.rs b/src/unit_tests/rules/schedulingwithindividualdeadlines_ilp.rs index 64c85c59f..0831dd917 100644 --- a/src/unit_tests/rules/schedulingwithindividualdeadlines_ilp.rs +++ b/src/unit_tests/rules/schedulingwithindividualdeadlines_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::solvers::{BruteForce, ILPSolver}; use crate::traits::Problem; @@ -33,11 +33,13 @@ fn test_schedulingwithindividualdeadlines_to_ilp_structure() { fn test_schedulingwithindividualdeadlines_to_ilp_fixes_unused_slots() { let problem = SchedulingWithIndividualDeadlines::new(2, 2, vec![1, 2], vec![]); let reduction = ReduceTo::>::reduce_to(&problem).unwrap(); - assert!(!reduction - .target_problem() - .evaluate(&vec![1, 1, 1, 0]) - .unwrap() - .is_valid()); + assert!( + !reduction + .target_problem() + .evaluate(&vec![1, 1, 1, 0]) + .unwrap() + .is_valid() + ); let witnesses: Vec> = (0..16) .map(|bits| (0..4).map(|bit| i64::from((bits >> bit) & 1)).collect()) .filter(|witness| { diff --git a/src/unit_tests/rules/sequencingtominimizetardytaskweight_ilp.rs b/src/unit_tests/rules/sequencingtominimizetardytaskweight_ilp.rs index baac86613..6e3c68322 100644 --- a/src/unit_tests/rules/sequencingtominimizetardytaskweight_ilp.rs +++ b/src/unit_tests/rules/sequencingtominimizetardytaskweight_ilp.rs @@ -142,16 +142,22 @@ fn test_tardy_ilp_signed_permutations_and_all_indicators() { } } } - assert!(reduction - .extract_solution(&vec![0; target.num_vars() + 1]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![0; target.num_vars() + 1]) + .is_err() + ); if count > 0 { - assert!(reduction - .extract_solution(&vec![0; target.num_vars()]) - .is_err()); - assert!(reduction - .extract_solution(&vec![2; target.num_vars()]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![0; target.num_vars()]) + .is_err() + ); + assert!( + reduction + .extract_solution(&vec![2; target.num_vars()]) + .is_err() + ); } } } diff --git a/src/unit_tests/rules/sequencingtominimizeweightedcompletiontime_ilp.rs b/src/unit_tests/rules/sequencingtominimizeweightedcompletiontime_ilp.rs index 4f49c9b50..251c32dad 100644 --- a/src/unit_tests/rules/sequencingtominimizeweightedcompletiontime_ilp.rs +++ b/src/unit_tests/rules/sequencingtominimizeweightedcompletiontime_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{Bounded, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, ObjectiveSense}; use crate::models::misc::SequencingToMinimizeWeightedCompletionTime; use crate::solvers::{BruteForce, ILPSolver}; use crate::traits::Problem; diff --git a/src/unit_tests/rules/sequencingwithinintervals_ilp.rs b/src/unit_tests/rules/sequencingwithinintervals_ilp.rs index db289afef..35fd1daaa 100644 --- a/src/unit_tests/rules/sequencingwithinintervals_ilp.rs +++ b/src/unit_tests/rules/sequencingwithinintervals_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::solvers::{BruteForce, ILPSolver}; use crate::traits::Problem; diff --git a/src/unit_tests/rules/sequencingwithreleasetimesanddeadlines_ilp.rs b/src/unit_tests/rules/sequencingwithreleasetimesanddeadlines_ilp.rs index d3b6b4b0e..f93b992fe 100644 --- a/src/unit_tests/rules/sequencingwithreleasetimesanddeadlines_ilp.rs +++ b/src/unit_tests/rules/sequencingwithreleasetimesanddeadlines_ilp.rs @@ -99,15 +99,19 @@ fn identical_tasks_share_a_canonical_temporal_order() { let source = SequencingWithReleaseTimesAndDeadlines::new(vec![1; 3], vec![0; 3], vec![3; 3]); assert_eq!(source.evaluate(&vec![2, 1, 0]).unwrap(), Or(true)); let reduction = ReduceTo::>::reduce_to(&source).unwrap(); - assert!(reduction - .target_problem() - .is_feasible(&[0, 1, 2, 1, 1, 1]) - .unwrap()); + assert!( + reduction + .target_problem() + .is_feasible(&[0, 1, 2, 1, 1, 1]) + .unwrap() + ); // Reversing indistinguishable task labels must not create another target order. - assert!(!reduction - .target_problem() - .is_feasible(&[2, 1, 0, 0, 0, 0]) - .unwrap()); + assert!( + !reduction + .target_problem() + .is_feasible(&[2, 1, 0, 0, 0, 0]) + .unwrap() + ); assert_eq!( source .evaluate(&ILPSolver::new().solve(&source).unwrap()) diff --git a/src/unit_tests/rules/setsplitting_betweenness.rs b/src/unit_tests/rules/setsplitting_betweenness.rs index 75a56fb01..e39393370 100644 --- a/src/unit_tests/rules/setsplitting_betweenness.rs +++ b/src/unit_tests/rules/setsplitting_betweenness.rs @@ -108,10 +108,12 @@ fn test_setsplitting_to_betweenness_issue_no_instance_is_unsat() { let source = issue_no_instance(); let reduction = ReduceTo::::reduce_to(&source).expect("reduction should succeed"); - assert!(BruteForce::new() - .solve(reduction.target_problem()) - .unwrap() - .is_none()); + assert!( + BruteForce::new() + .solve(reduction.target_problem()) + .unwrap() + .is_none() + ); } #[cfg(feature = "example-db")] diff --git a/src/unit_tests/rules/setsplitting_naesatisfiability.rs b/src/unit_tests/rules/setsplitting_naesatisfiability.rs index 1a3fbfd68..35d1590a7 100644 --- a/src/unit_tests/rules/setsplitting_naesatisfiability.rs +++ b/src/unit_tests/rules/setsplitting_naesatisfiability.rs @@ -48,10 +48,12 @@ fn test_setsplitting_to_naesatisfiability_repeated_members() { ReduceTo::::reduce_to(&source).expect("reduction should succeed"); assert_eq!(reduction.target_problem().clauses()[0].literals, [1, 1]); - assert!(BruteForce::new() - .solve(reduction.target_problem()) - .unwrap() - .is_none()); + assert!( + BruteForce::new() + .solve(reduction.target_problem()) + .unwrap() + .is_none() + ); } #[test] diff --git a/src/unit_tests/rules/shortestcommonsupersequence_ilp.rs b/src/unit_tests/rules/shortestcommonsupersequence_ilp.rs index 80ed3daef..28ac3e7e2 100644 --- a/src/unit_tests/rules/shortestcommonsupersequence_ilp.rs +++ b/src/unit_tests/rules/shortestcommonsupersequence_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::solvers::{BruteForce, ILPSolver}; use crate::traits::Problem; diff --git a/src/unit_tests/rules/shortestweightconstrainedpath_ilp.rs b/src/unit_tests/rules/shortestweightconstrainedpath_ilp.rs index 0de30cfae..22ff99407 100644 --- a/src/unit_tests/rules/shortestweightconstrainedpath_ilp.rs +++ b/src/unit_tests/rules/shortestweightconstrainedpath_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{Bounded, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, ObjectiveSense}; use crate::solvers::{BruteForce, ILPSolver}; use crate::topology::SimpleGraph; use crate::traits::Problem; diff --git a/src/unit_tests/rules/sparsematrixcompression_ilp.rs b/src/unit_tests/rules/sparsematrixcompression_ilp.rs index ebc2628b0..34a4a7fc2 100644 --- a/src/unit_tests/rules/sparsematrixcompression_ilp.rs +++ b/src/unit_tests/rules/sparsematrixcompression_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::rules::{ReduceTo, ReductionResult}; use crate::solvers::{BruteForce, ILPSolver}; diff --git a/src/unit_tests/rules/spinglass_qubo.rs b/src/unit_tests/rules/spinglass_qubo.rs index 7e1c7bb5d..c8ea233a0 100644 --- a/src/unit_tests/rules/spinglass_qubo.rs +++ b/src/unit_tests/rules/spinglass_qubo.rs @@ -178,19 +178,19 @@ fn test_jl_parity_rule_qubo_to_spinglass() { .unwrap(); let q_data: serde_json::Value = serde_json::from_str(include_str!("../../../tests/data/jl/qubo.json")).unwrap(); - let jl_matrix: Vec> = jl_find_instance_by_label(&q_data, "rule_3x3")["instance"] - ["matrix"] - .as_array() - .unwrap() - .iter() - .map(|row| { - row.as_array() - .unwrap() - .iter() - .map(|v| v.as_f64().unwrap()) - .collect() - }) - .collect(); + let jl_matrix: Vec> = + jl_find_instance_by_label(&q_data, "rule_3x3")["instance"]["matrix"] + .as_array() + .unwrap() + .iter() + .map(|row| { + row.as_array() + .unwrap() + .iter() + .map(|v| v.as_f64().unwrap()) + .collect() + }) + .collect(); let n = jl_matrix.len(); let mut rust_matrix = vec![vec![0.0f64; n]; n]; for i in 0..n { diff --git a/src/unit_tests/rules/stackercrane_ilp.rs b/src/unit_tests/rules/stackercrane_ilp.rs index 849e3339c..99edef1de 100644 --- a/src/unit_tests/rules/stackercrane_ilp.rs +++ b/src/unit_tests/rules/stackercrane_ilp.rs @@ -1,7 +1,7 @@ use super::*; use crate::models::algebraic::ILP; -use crate::rules::test_helpers::assert_bf_vs_ilp; use crate::rules::ReduceTo; +use crate::rules::test_helpers::assert_bf_vs_ilp; #[test] fn test_stackercrane_to_ilp_closed_loop() { diff --git a/src/unit_tests/rules/staffscheduling_qubo.rs b/src/unit_tests/rules/staffscheduling_qubo.rs index ce8a6e5f3..a78e77b17 100644 --- a/src/unit_tests/rules/staffscheduling_qubo.rs +++ b/src/unit_tests/rules/staffscheduling_qubo.rs @@ -1,8 +1,8 @@ -use crate::models::{algebraic::QUBO, misc::StaffScheduling, Decision}; +use crate::Problem; +use crate::models::{Decision, algebraic::QUBO, misc::StaffScheduling}; +use crate::rules::ReductionError; use crate::rules::direct_qubo_tests::{direct, feasible}; use crate::rules::registry::reduction_entries; -use crate::rules::ReductionError; -use crate::Problem; #[test] fn test_staffscheduling_to_qubo_closed_loop() { diff --git a/src/unit_tests/rules/stringtostringcorrection_ilp.rs b/src/unit_tests/rules/stringtostringcorrection_ilp.rs index 7f7b1597e..4c6c84935 100644 --- a/src/unit_tests/rules/stringtostringcorrection_ilp.rs +++ b/src/unit_tests/rules/stringtostringcorrection_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, ObjectiveSense}; use crate::solvers::{BruteForce, ILPSolver}; use crate::traits::Problem; use crate::types::Or; diff --git a/src/unit_tests/rules/subsetsum_closestvectorproblem.rs b/src/unit_tests/rules/subsetsum_closestvectorproblem.rs index 328cb6159..852353a3c 100644 --- a/src/unit_tests/rules/subsetsum_closestvectorproblem.rs +++ b/src/unit_tests/rules/subsetsum_closestvectorproblem.rs @@ -89,13 +89,15 @@ fn test_subsetsum_to_closestvectorproblem_large_integers_and_unit_pivots() { Min(Some(1)) ); assert_eq!(result.extract_solution(&witness).unwrap(), vec![true]); - assert!(result - .target_problem() - .inner() - .basis() - .iter() - .flatten() - .all(|&x| (-2..=1).contains(&x))); + assert!( + result + .target_problem() + .inner() + .basis() + .iter() + .flatten() + .all(|&x| (-2..=1).contains(&x)) + ); let source = SubsetSum::new(vec![1u32; 40], 20u32); let result = ReduceTo::>::reduce_to(&source).unwrap(); diff --git a/src/unit_tests/rules/subsetsum_integerexpressionmembership.rs b/src/unit_tests/rules/subsetsum_integerexpressionmembership.rs index 4016a402e..aec871d94 100644 --- a/src/unit_tests/rules/subsetsum_integerexpressionmembership.rs +++ b/src/unit_tests/rules/subsetsum_integerexpressionmembership.rs @@ -2,9 +2,9 @@ use super::canonical_rule_example_specs; use crate::models::misc::IntegerExpressionMembership; use crate::models::misc::SubsetSum; +use crate::rules::ReduceTo; use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::rules::traits::ReductionResult; -use crate::rules::ReduceTo; use crate::solvers::BruteForce; #[cfg(feature = "example-db")] use crate::traits::Problem; @@ -52,9 +52,11 @@ fn test_subsetsum_to_integerexpressionmembership_extract_solution_matches_choice .unwrap(), issue_example_source_config() ); - assert!(reduction - .extract_solution(&vec![true, false, false, true]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![true, false, false, true]) + .is_err() + ); } #[test] @@ -64,10 +66,12 @@ fn test_subsetsum_to_integerexpressionmembership_unsatisfiable_instance_stays_un .expect("reduction should succeed"); assert!(BruteForce::new().solve(&source).unwrap().is_none()); - assert!(BruteForce::new() - .solve(reduction.target_problem()) - .unwrap() - .is_none()); + assert!( + BruteForce::new() + .solve(reduction.target_problem()) + .unwrap() + .is_none() + ); } #[cfg(feature = "example-db")] diff --git a/src/unit_tests/rules/subsetsum_partition.rs b/src/unit_tests/rules/subsetsum_partition.rs index 663dbd54e..e412445c8 100644 --- a/src/unit_tests/rules/subsetsum_partition.rs +++ b/src/unit_tests/rules/subsetsum_partition.rs @@ -1,9 +1,9 @@ #[cfg(feature = "example-db")] use super::canonical_rule_example_specs; use crate::models::misc::{Partition, SubsetSum}; +use crate::rules::ReduceTo; use crate::rules::test_helpers::assert_satisfaction_round_trip_from_satisfaction_target; use crate::rules::traits::ReductionResult; -use crate::rules::ReduceTo; use crate::solvers::BruteForce; #[cfg(feature = "example-db")] use crate::traits::Problem; diff --git a/src/unit_tests/rules/threedimensionalmatching_ilp.rs b/src/unit_tests/rules/threedimensionalmatching_ilp.rs index 528d233bf..0ceaa1b58 100644 --- a/src/unit_tests/rules/threedimensionalmatching_ilp.rs +++ b/src/unit_tests/rules/threedimensionalmatching_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{Comparison, ObjectiveSense, ILP}; +use crate::models::algebraic::{Comparison, ILP, ObjectiveSense}; use crate::models::misc::{ResourceConstrainedScheduling, ThreePartition}; use crate::models::set::ThreeDimensionalMatching; use crate::rules::{ReduceTo, ReductionGraph, ReductionResult}; diff --git a/src/unit_tests/rules/threedimensionalmatching_minimumweightdecoding.rs b/src/unit_tests/rules/threedimensionalmatching_minimumweightdecoding.rs index 0be0f5096..20ae8c188 100644 --- a/src/unit_tests/rules/threedimensionalmatching_minimumweightdecoding.rs +++ b/src/unit_tests/rules/threedimensionalmatching_minimumweightdecoding.rs @@ -176,7 +176,9 @@ fn test_threedimensionalmatching_to_minimumweightdecoding_solution_extraction_id ); } - assert!(reduction - .extract_solution(&vec![false, true, false]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![false, true, false]) + .is_err() + ); } diff --git a/src/unit_tests/rules/threedimensionalmatching_threepartition.rs b/src/unit_tests/rules/threedimensionalmatching_threepartition.rs index ed7f8d383..8ddcceb61 100644 --- a/src/unit_tests/rules/threedimensionalmatching_threepartition.rs +++ b/src/unit_tests/rules/threedimensionalmatching_threepartition.rs @@ -30,10 +30,12 @@ fn test_threedimensionalmatching_to_threepartition_q1_overhead_and_bounds() { let bound = i128::from(target.bound()); let total_sum: i128 = target.sizes().iter().map(|&size| i128::from(size)).sum(); assert_eq!(total_sum, bound * target.num_groups() as i128); - assert!(target - .sizes() - .iter() - .all(|&size| 4 * i128::from(size) > bound && 2 * i128::from(size) < bound)); + assert!( + target + .sizes() + .iter() + .all(|&size| 4 * i128::from(size) > bound && 2 * i128::from(size) < bound) + ); } #[test] @@ -61,10 +63,12 @@ fn empty_triple_sets_preserve_empty_and_nonempty_universe_truth() { ); } else { assert!(BruteForce::new().solve(&source).unwrap().is_none()); - assert!(BruteForce::new() - .solve(reduction.target_problem()) - .unwrap() - .is_none()); + assert!( + BruteForce::new() + .solve(reduction.target_problem()) + .unwrap() + .is_none() + ); } } } diff --git a/src/unit_tests/rules/threepartition_ilp.rs b/src/unit_tests/rules/threepartition_ilp.rs index 14f0ea7ea..659c7067c 100644 --- a/src/unit_tests/rules/threepartition_ilp.rs +++ b/src/unit_tests/rules/threepartition_ilp.rs @@ -1,7 +1,7 @@ use super::*; use crate::{ - solvers::{BruteForce, ILPSolveError, ILPSolver}, Problem, + solvers::{BruteForce, ILPSolveError, ILPSolver}, }; #[test] @@ -27,8 +27,10 @@ fn indexed_triples_preserve_duplicate_items_and_impossibility() { } other => panic!("partition disagreement: {other:?}"), } - assert!(reduction - .extract_solution(&vec![0; reduction.target_problem().num_vars() + 1]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![0; reduction.target_problem().num_vars() + 1]) + .is_err() + ); } } diff --git a/src/unit_tests/rules/traits.rs b/src/unit_tests/rules/traits.rs index 1f792a394..badd0ace0 100644 --- a/src/unit_tests/rules/traits.rs +++ b/src/unit_tests/rules/traits.rs @@ -4,8 +4,8 @@ fn test_traits_compile() { } use crate::rules::traits::{ - validate_target_solution, AggregateReductionResult, DynAggregateReductionResult, ReduceTo, - ReduceToAggregate, ReductionResult, + AggregateReductionResult, DynAggregateReductionResult, ReduceTo, ReduceToAggregate, + ReductionResult, validate_target_solution, }; use crate::solvers::BruteForceProblem as _; use crate::traits::Problem; @@ -270,10 +270,12 @@ fn test_dyn_aggregate_reduction_result_extracts_value() { }; let dyn_result: &dyn DynAggregateReductionResult = &result; - assert!(dyn_result - .target_problem_any() - .downcast_ref::() - .is_some()); + assert!( + dyn_result + .target_problem_any() + .downcast_ref::() + .is_some() + ); assert_eq!(dyn_result.extract_value_dyn(json!(7)).unwrap(), json!(9)); assert!(matches!( dyn_result.extract_value_dyn(json!("not a count")), @@ -324,17 +326,21 @@ impl AggregateReductionResult for UnserializableReduction { #[test] fn dynamic_aggregate_serialization_failure_returns_an_error() { let reduction = UnserializableReduction(AggregateTargetProblem); - assert!(reduction - .extract_value_from_solution_dyn(&vec![0usize]) - .is_err()); + assert!( + reduction + .extract_value_from_solution_dyn(&vec![0usize]) + .is_err() + ); let error = reduction.extract_value_dyn(json!(0)).unwrap_err(); assert!(matches!( error, crate::rules::ExtractionError::InvalidTargetSolution(_) )); - assert!(error - .to_string() - .contains("source aggregate serialization failed")); + assert!( + error + .to_string() + .contains("source aggregate serialization failed") + ); } #[derive(Clone)] @@ -534,7 +540,7 @@ impl Problem for CountedTarget { #[test] fn target_witness_validation_evaluates_once_and_preserves_rejection() { - use crate::rules::{traits::validate_target_witness, ExtractionError}; + use crate::rules::{ExtractionError, traits::validate_target_witness}; let target = CountedTarget(std::cell::Cell::new(0)); validate_target_witness( &target, diff --git a/src/unit_tests/rules/travelingsalesman_ilp.rs b/src/unit_tests/rules/travelingsalesman_ilp.rs index 1062063d9..e6931af59 100644 --- a/src/unit_tests/rules/travelingsalesman_ilp.rs +++ b/src/unit_tests/rules/travelingsalesman_ilp.rs @@ -184,9 +184,11 @@ fn simple_graphs_with_fewer_than_three_vertices_produce_infeasible_ilps() { graph.num_vertices(), graph.num_edges() ); - assert!(reduction - .extract_solution(&vec![0; target.num_vars()]) - .is_err()); + assert!( + reduction + .extract_solution(&vec![0; target.num_vars()]) + .is_err() + ); } } } diff --git a/src/unit_tests/rules/undirectedflowlowerbounds_ilp.rs b/src/unit_tests/rules/undirectedflowlowerbounds_ilp.rs index 7cc7fd1b0..db7ad65dd 100644 --- a/src/unit_tests/rules/undirectedflowlowerbounds_ilp.rs +++ b/src/unit_tests/rules/undirectedflowlowerbounds_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{Bounded, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, ObjectiveSense}; use crate::solvers::{BruteForce, ILPSolver}; use crate::topology::SimpleGraph; use crate::traits::Problem; diff --git a/src/unit_tests/rules/undirectedtwocommodityintegralflow_ilp.rs b/src/unit_tests/rules/undirectedtwocommodityintegralflow_ilp.rs index 9c46c0854..ef4cfc0f4 100644 --- a/src/unit_tests/rules/undirectedtwocommodityintegralflow_ilp.rs +++ b/src/unit_tests/rules/undirectedtwocommodityintegralflow_ilp.rs @@ -1,5 +1,5 @@ use super::*; -use crate::models::algebraic::{Bounded, ObjectiveSense, ILP}; +use crate::models::algebraic::{Bounded, ILP, ObjectiveSense}; use crate::solvers::{BruteForce, ILPSolver}; use crate::topology::SimpleGraph; use crate::traits::Problem; diff --git a/src/unit_tests/rules/unitdiskmapping/ksg/gadgets_weighted.rs b/src/unit_tests/rules/unitdiskmapping/ksg/gadgets_weighted.rs index a9261ec62..4cacc7064 100644 --- a/src/unit_tests/rules/unitdiskmapping/ksg/gadgets_weighted.rs +++ b/src/unit_tests/rules/unitdiskmapping/ksg/gadgets_weighted.rs @@ -1,5 +1,17 @@ use super::*; +#[test] +fn test_weighted_ksg_tape_rejects_unknown_gadget() { + let entry = WeightedKsgTapeEntry { + pattern_idx: 106, + row: 0, + col: 0, + }; + assert!(matches!(weighted_tape_entry_mis_overhead(&entry), + Err(ReductionError::InvalidTarget { source_problem: "Graph", target_problem: "UnitDiskMapping", message }) + if message == "tape contains an unknown weighted KSG gadget index")); +} + #[test] fn test_weighted_ksg_cross_false_mis_overhead() { assert_eq!(WeightedKsgCross::.mis_overhead(), -2); diff --git a/src/unit_tests/rules/unitdiskmapping/weighted.rs b/src/unit_tests/rules/unitdiskmapping/weighted.rs index 7a2101080..9fd46c493 100644 --- a/src/unit_tests/rules/unitdiskmapping/weighted.rs +++ b/src/unit_tests/rules/unitdiskmapping/weighted.rs @@ -17,9 +17,11 @@ fn map_weights_adds_one_weight_per_source_vertex() { let mapped = map_weights(&result, &[0.5, 0.3, 0.7]).unwrap(); assert_eq!(mapped.len(), result.positions.len()); - assert!(mapped - .iter() - .all(|weight| weight.is_finite() && *weight > 0.0)); + assert!( + mapped + .iter() + .all(|weight| weight.is_finite() && *weight > 0.0) + ); } #[test] diff --git a/src/unit_tests/rules/weight_casts.rs b/src/unit_tests/rules/weight_casts.rs index 52516cef6..cadf7cc4a 100644 --- a/src/unit_tests/rules/weight_casts.rs +++ b/src/unit_tests/rules/weight_casts.rs @@ -1,12 +1,12 @@ +use crate::models::Decision; use crate::models::graph::*; use crate::models::misc::{BinPacking, MinimumTardinessSequencing}; use crate::models::set::ComparativeContainment; -use crate::models::Decision; use crate::rules::{ReductionError, ReductionGraph}; use crate::solvers::{BruteForce, BruteForceProblem}; use crate::topology::{MultiDigraph, MultiMixedGraph, SimpleGraph}; use crate::traits::Problem; -use crate::types::{One, MAX_EXACT_F64_INTEGER}; +use crate::types::{MAX_EXACT_F64_INTEGER, One}; use crate::variant::KN; use serde::Serialize; use std::collections::BTreeSet; diff --git a/src/unit_tests/solvers/brute_force.rs b/src/unit_tests/solvers/brute_force.rs index 66d4f23e2..6af407687 100644 --- a/src/unit_tests/solvers/brute_force.rs +++ b/src/unit_tests/solvers/brute_force.rs @@ -621,10 +621,12 @@ fn cartesian_indices_empty_dimensions_have_one_candidate() { #[test] fn cartesian_indices_zero_dimension_has_no_candidates() { - assert!(CartesianIndices::new(vec![2, 0, 3]) - .unwrap() - .next() - .is_none()); + assert!( + CartesianIndices::new(vec![2, 0, 3]) + .unwrap() + .next() + .is_none() + ); } #[test] diff --git a/src/unit_tests/solvers/customized/closest_vector_problem.rs b/src/unit_tests/solvers/customized/closest_vector_problem.rs index 25c4c4c5a..59c417b4a 100644 --- a/src/unit_tests/solvers/customized/closest_vector_problem.rs +++ b/src/unit_tests/solvers/customized/closest_vector_problem.rs @@ -1,6 +1,6 @@ use super::*; use crate::models::algebraic::ClosestVectorProblem; -use crate::solvers::{solver_capabilities, ExactProblemKey}; +use crate::solvers::{ExactProblemKey, solver_capabilities}; use crate::traits::Problem; use std::collections::BTreeMap; diff --git a/src/unit_tests/solvers/customized/solver.rs b/src/unit_tests/solvers/customized/solver.rs index c193fd8f6..bc56f1b56 100644 --- a/src/unit_tests/solvers/customized/solver.rs +++ b/src/unit_tests/solvers/customized/solver.rs @@ -1,8 +1,8 @@ use crate::models::graph::{PartialFeedbackEdgeSet, RootedTreeArrangement}; -use crate::solvers::registry::solver_capability_registry; use crate::solvers::BruteForceProblem as _; use crate::solvers::CartesianIndices; use crate::solvers::ExactProblemKey; +use crate::solvers::registry::solver_capability_registry; use crate::topology::{Graph, SimpleGraph}; use crate::traits::Problem; @@ -621,8 +621,8 @@ fn test_solve_two_coloring_direct_graph_cases() { #[test] fn customized_clique_cover_and_decision_preserve_optimum() { - use crate::models::graph::MinimumCoveringByCliques; use crate::models::Decision; + use crate::models::graph::MinimumCoveringByCliques; for graph in all_simple_graphs(4).chain([ SimpleGraph::new(0, vec![]), SimpleGraph::new(3, vec![(1, 2)]), diff --git a/src/unit_tests/solvers/ilp/solver.rs b/src/unit_tests/solvers/ilp/solver.rs index cecfd13f8..a42969d82 100644 --- a/src/unit_tests/solvers/ilp/solver.rs +++ b/src/unit_tests/solvers/ilp/solver.rs @@ -228,7 +228,7 @@ fn test_ilp_with_time_limit() { fn test_registered_ilp_pipeline_success() { use crate::models::graph::MaximumIndependentSet; use crate::registry::load_dyn; - use crate::solvers::{solve, SolveOutcome, SolverExecution, SolverRequest}; + use crate::solvers::{SolveOutcome, SolverExecution, SolverRequest, solve}; use crate::topology::SimpleGraph; use std::collections::BTreeMap; @@ -311,9 +311,11 @@ fn test_kernel_registered_ilp_feasibility() { #[test] fn test_ilp_solve_dyn_bool() { let ilp = ILP::::new(1, vec![], vec![(0, 1.0)], ObjectiveSense::Maximize).unwrap(); - assert!(ILPSolver::new() - .solve_dyn(&ilp as &dyn std::any::Any) - .is_ok()); + assert!( + ILPSolver::new() + .solve_dyn(&ilp as &dyn std::any::Any) + .is_ok() + ); } #[test] @@ -328,9 +330,11 @@ fn test_ilp_solve_dyn_i64() { ObjectiveSense::Minimize, ) .unwrap(); - assert!(ILPSolver::new() - .solve_dyn(&ilp as &dyn std::any::Any) - .is_ok()); + assert!( + ILPSolver::new() + .solve_dyn(&ilp as &dyn std::any::Any) + .is_ok() + ); } #[test] @@ -402,8 +406,8 @@ fn test_ilp_solver_rejects_source_objective_overflow() { #[test] fn production_planning_pipeline_accounts_for_inventory_and_setups() { - use crate::models::misc::ProductionPlanning; use crate::Problem; + use crate::models::misc::ProductionPlanning; for budget in [7, 8] { let source = ProductionPlanning::new( 3, diff --git a/src/unit_tests/solvers/resolver.rs b/src/unit_tests/solvers/resolver.rs index eea8cdbec..7acb6dde8 100644 --- a/src/unit_tests/solvers/resolver.rs +++ b/src/unit_tests/solvers/resolver.rs @@ -1,6 +1,6 @@ -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::registry::load_dyn; -use crate::solvers::{solve, SolveOutcome, SolverExecution, SolverRequest}; +use crate::solvers::{SolveOutcome, SolverExecution, SolverRequest, solve}; use crate::traits::Problem; use std::collections::BTreeMap; diff --git a/src/unit_tests/symbolic_parameter_contracts.rs b/src/unit_tests/symbolic_parameter_contracts.rs index c881b99c7..42d7678d9 100644 --- a/src/unit_tests/symbolic_parameter_contracts.rs +++ b/src/unit_tests/symbolic_parameter_contracts.rs @@ -1,3 +1,4 @@ +use crate::Problem; use crate::models::algebraic::AlgebraicEquationsOverGF2; use crate::models::algebraic::Bounded; use crate::models::graph::{MaximumClique, MaximumIndependentSet}; @@ -6,7 +7,6 @@ use crate::parameters::ParameterRelation; use crate::rules::{ReduceTo, ReductionGraph, ReductionResult}; use crate::topology::SimpleGraph; use crate::types::ProblemParameters; -use crate::Problem; #[test] fn parameter_schemas_keep_distinct_counts_without_synonymous_aliases() { @@ -31,10 +31,12 @@ fn parameter_schemas_keep_distinct_counts_without_synonymous_aliases() { assert!(fields.iter().any(|name| name == field), "{model}: {field}"); } } - assert!(!graph - .parameter_names("ExactCoverBy3Sets") - .iter() - .any(|field| field == "num_sets")); + assert!( + !graph + .parameter_names("ExactCoverBy3Sets") + .iter() + .any(|field| field == "num_sets") + ); for (model, expected) in [ ("HamiltonianPath", &["num_edges", "num_vertices"][..]), ( @@ -255,7 +257,7 @@ where fn parameter_relations_match_reduced_instances() { use crate::models::algebraic::MinimumMatrixCover; use crate::models::algebraic::{ - IntegerVariable, LinearConstraint, ObjectiveSense, QuadraticAssignment, BMF, ILP, + BMF, ILP, IntegerVariable, LinearConstraint, ObjectiveSense, QuadraticAssignment, }; use crate::models::graph::BicliqueCover; use crate::models::graph::{ @@ -396,7 +398,7 @@ fn parameter_relations_match_reduced_instances() { #[test] fn exact_parameter_formulas_cover_sparse_and_boundary_instances() { - use crate::models::algebraic::{QuadraticAssignment, ILP}; + use crate::models::algebraic::{ILP, QuadraticAssignment}; use crate::models::graph::{HamiltonianCircuit, HamiltonianPath, MinimumVertexCover}; use crate::models::misc::{ ConsistencyOfDatabaseFrequencyTables, FrequencyTable, KnownValue, LongestCommonSubsequence, @@ -720,8 +722,8 @@ fn set_splitting_bounds_cover_deduplication_and_large_subsets() { #[test] fn decision_cover_bounds_do_not_depend_on_threshold_magnitude() { use crate::models::{ - graph::{HamiltonianCircuit, MinimumVertexCover}, Decision, + graph::{HamiltonianCircuit, MinimumVertexCover}, }; use crate::types::One; for graph in [ @@ -747,7 +749,7 @@ fn decision_cover_bounds_do_not_depend_on_threshold_magnitude() { #[test] fn subset_lattice_dimensions_use_existing_numeric_magnitude() { - use crate::models::{algebraic::ClosestVectorProblem, misc::SubsetSum, Decision}; + use crate::models::{Decision, algebraic::ClosestVectorProblem, misc::SubsetSum}; for (sizes, target) in [ (vec![], 0u64), (vec![1], 0), @@ -815,7 +817,7 @@ fn integer_knapsack_capacity_bits_bound_ilp_magnitudes() { #[test] fn open_shop_horizon_bits_cover_totals_and_decision_bounds() { - use crate::models::{algebraic::ILP, misc::OpenShopScheduling, Decision}; + use crate::models::{Decision, algebraic::ILP, misc::OpenShopScheduling}; for (machines, times, bits) in [ (0, vec![vec![]], 1), (2, vec![], 1), @@ -844,8 +846,8 @@ fn open_shop_horizon_bits_cover_totals_and_decision_bounds() { #[test] fn partition_propagates_open_shop_horizon_bits() { use crate::models::{ - misc::{OpenShopScheduling, Partition}, Decision, + misc::{OpenShopScheduling, Partition}, }; for sizes in [vec![1], vec![1, 1], vec![1, 2], vec![1 << 20; 2]] { check_reduced_parameters::<_, Decision>( diff --git a/src/unit_tests/topology/bipartite_graph.rs b/src/unit_tests/topology/bipartite_graph.rs index a49a9401f..1e7cdff82 100644 --- a/src/unit_tests/topology/bipartite_graph.rs +++ b/src/unit_tests/topology/bipartite_graph.rs @@ -62,15 +62,19 @@ fn test_bipartite_graph_invalid_right_index() { #[test] fn deserialize_checks_partition_endpoints_and_total_size() { for edges in [vec![(1, 0)], vec![(0, 1)]] { - assert!(serde_json::from_value::(serde_json::json!({ - "left_size": 1, "right_size": 1, "edges": edges - })) - .is_err()); + assert!( + serde_json::from_value::(serde_json::json!({ + "left_size": 1, "right_size": 1, "edges": edges + })) + .is_err() + ); } - assert!(serde_json::from_value::(serde_json::json!({ - "left_size": usize::MAX, "right_size": 1, "edges": [] - })) - .is_err()); + assert!( + serde_json::from_value::(serde_json::json!({ + "left_size": usize::MAX, "right_size": 1, "edges": [] + })) + .is_err() + ); let graph: BipartiteGraph = serde_json::from_value(serde_json::json!({ "left_size": 1, "right_size": 1, "edges": [[0, 0]] })) @@ -82,10 +86,12 @@ fn deserialize_checks_partition_endpoints_and_total_size() { fn bipartite_graph_rejects_repeated_edges() { let edges = vec![(0, 0), (0, 0)]; assert!(BipartiteGraph::try_new(2, 2, edges.clone()).is_err()); - assert!(serde_json::from_value::(serde_json::json!({ - "left_size": 2, "right_size": 2, "edges": edges, - })) - .is_err()); + assert!( + serde_json::from_value::(serde_json::json!({ + "left_size": 2, "right_size": 2, "edges": edges, + })) + .is_err() + ); // These are different cross-partition pairs, not reversed copies of one edge. let graph = BipartiteGraph::new(2, 2, vec![(0, 1), (1, 0)]); assert_eq!(graph.num_edges(), 2); diff --git a/src/unit_tests/topology/graph.rs b/src/unit_tests/topology/graph.rs index 81c748ba7..a8d45b598 100644 --- a/src/unit_tests/topology/graph.rs +++ b/src/unit_tests/topology/graph.rs @@ -155,10 +155,12 @@ fn test_simplegraph_json_format() { #[test] fn deserialize_rejects_out_of_range_edges() { - assert!(serde_json::from_value::(serde_json::json!({ - "num_vertices": 2, "edges": [[0, 2]] - })) - .is_err()); + assert!( + serde_json::from_value::(serde_json::json!({ + "num_vertices": 2, "edges": [[0, 2]] + })) + .is_err() + ); } #[test] diff --git a/src/unit_tests/topology/multi_digraph.rs b/src/unit_tests/topology/multi_digraph.rs index 68120ca3a..58c59ea73 100644 --- a/src/unit_tests/topology/multi_digraph.rs +++ b/src/unit_tests/topology/multi_digraph.rs @@ -237,10 +237,12 @@ fn test_directed_graph_invalid_arc() { #[test] fn deserialize_rejects_out_of_range_arcs() { - assert!(serde_json::from_value::(serde_json::json!({ - "num_vertices": 2, "arcs": [[2, 0]] - })) - .is_err()); + assert!( + serde_json::from_value::(serde_json::json!({ + "num_vertices": 2, "arcs": [[2, 0]] + })) + .is_err() + ); } #[test] diff --git a/src/unit_tests/topology/planar_graph.rs b/src/unit_tests/topology/planar_graph.rs index eb2cbd510..0a97caaa4 100644 --- a/src/unit_tests/topology/planar_graph.rs +++ b/src/unit_tests/topology/planar_graph.rs @@ -50,10 +50,12 @@ fn deserialize_checks_the_edge_bound() { let edges: Vec<_> = (0..5) .flat_map(|u| ((u + 1)..5).map(move |v| (u, v))) .collect(); - assert!(serde_json::from_value::(serde_json::json!({ - "inner": {"num_vertices": 5, "edges": edges} - })) - .is_err()); + assert!( + serde_json::from_value::(serde_json::json!({ + "inner": {"num_vertices": 5, "edges": edges} + })) + .is_err() + ); let graph: PlanarGraph = serde_json::from_value(serde_json::json!({ "inner": {"num_vertices": 2, "edges": [[0, 1]]} })) diff --git a/src/unit_tests/types.rs b/src/unit_tests/types.rs index f3bf96ba1..e94aeee8e 100644 --- a/src/unit_tests/types.rs +++ b/src/unit_tests/types.rs @@ -227,9 +227,11 @@ fn test_problem_parameters_deserialization_rejects_duplicate_names() { "components": [["vertices", 10], ["vertices", 20]] })) .unwrap_err(); - assert!(error - .to_string() - .contains("duplicate problem parameter `vertices`")); + assert!( + error + .to_string() + .contains("duplicate problem parameter `vertices`") + ); } #[test] diff --git a/src/unit_tests/unitdiskmapping_algorithms/alpha_tensor.rs b/src/unit_tests/unitdiskmapping_algorithms/alpha_tensor.rs index 39bffd330..704460821 100644 --- a/src/unit_tests/unitdiskmapping_algorithms/alpha_tensor.rs +++ b/src/unit_tests/unitdiskmapping_algorithms/alpha_tensor.rs @@ -4,11 +4,11 @@ //! because an unweighted triangular gadget ruleset has not been implemented. use super::common::ksg_edges; +use crate::rules::unitdiskmapping::Pattern; use crate::rules::unitdiskmapping::ksg::{ KsgBranch, KsgBranchFix, KsgBranchFixB, KsgCross, KsgDanglingLeg, KsgEndTurn, KsgReflectedGadget, KsgRotatedGadget, KsgTCon, KsgTrivialTurn, KsgTurn, KsgWTurn, Mirror, }; -use crate::rules::unitdiskmapping::Pattern; use std::collections::HashSet; fn weighted_mis_with_fixed_pins( diff --git a/src/unit_tests/unitdiskmapping_algorithms/common.rs b/src/unit_tests/unitdiskmapping_algorithms/common.rs index 601d0cc46..49af1b999 100644 --- a/src/unit_tests/unitdiskmapping_algorithms/common.rs +++ b/src/unit_tests/unitdiskmapping_algorithms/common.rs @@ -1,6 +1,6 @@ //! Common test utilities for mapping tests. -use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::rules::unitdiskmapping::MappingResult; use crate::solvers::ILPSolver; diff --git a/src/unit_tests/unitdiskmapping_algorithms/copyline.rs b/src/unit_tests/unitdiskmapping_algorithms/copyline.rs index aa6b44a60..360149b33 100644 --- a/src/unit_tests/unitdiskmapping_algorithms/copyline.rs +++ b/src/unit_tests/unitdiskmapping_algorithms/copyline.rs @@ -2,7 +2,7 @@ use super::common::solve_weighted_mis; use crate::rules::unitdiskmapping::{ - create_copylines, ksg, mis_overhead_copyline, triangular, CopyLine, + CopyLine, create_copylines, ksg, mis_overhead_copyline, triangular, }; // === Edge Case Tests === diff --git a/src/unit_tests/unitdiskmapping_algorithms/gadgets.rs b/src/unit_tests/unitdiskmapping_algorithms/gadgets.rs index aaa006309..2e9401f26 100644 --- a/src/unit_tests/unitdiskmapping_algorithms/gadgets.rs +++ b/src/unit_tests/unitdiskmapping_algorithms/gadgets.rs @@ -1,6 +1,34 @@ //! Tests for gadget properties (src/rules/mapping/gadgets.rs and triangular gadgets). use super::common::{ksg_edges, solve_weighted_mis, triangular_edges}; + +#[test] +fn test_weighted_ksg_simplifier_rejects_noncenter_weight() { + use crate::rules::unitdiskmapping::ksg::gadgets::apply_weighted_simplifier_gadgets; + use crate::rules::unitdiskmapping::{CellState, MappingGrid}; + + for weights in [[1, 3, 2], [1, 2, 3]] { + let mut grid = MappingGrid::new(4, 3, 1); + for (row, weight) in (1..=3).zip(weights) { + grid.set(row, 1, CellState::Occupied { weight }); + } + assert!(apply_weighted_simplifier_gadgets(&mut grid, 1).is_empty()); + for (row, weight) in (1..=3).zip(weights) { + assert_eq!(grid.get(row, 1), Some(&CellState::Occupied { weight })); + } + } + let mut grid = MappingGrid::new(4, 3, 1); + for (row, weight) in (1..=3).zip([1, 2, 2]) { + grid.set(row, 1, CellState::Occupied { weight }); + } + let tape = apply_weighted_simplifier_gadgets(&mut grid, 1); + assert_eq!(tape.len(), 1); + assert_eq!((tape[0].pattern_idx, tape[0].row, tape[0].col), (100, 0, 0)); + assert_eq!(grid.get(1, 1), Some(&CellState::Empty)); + assert_eq!(grid.get(2, 1), Some(&CellState::Empty)); + assert_eq!(grid.get(3, 1), Some(&CellState::Occupied { weight: 1 })); +} +use crate::rules::unitdiskmapping::Pattern; use crate::rules::unitdiskmapping::ksg::{ KsgBranch, KsgBranchFix, KsgBranchFixB, KsgCross, KsgDanglingLeg, KsgEndTurn, KsgReflectedGadget, KsgRotatedGadget, KsgTCon, KsgTrivialTurn, KsgTurn, KsgWTurn, Mirror, @@ -13,7 +41,6 @@ use crate::rules::unitdiskmapping::triangular::{ WeightedTriEndTurn, WeightedTriTConDown, WeightedTriTConUp, WeightedTriTrivialTurnLeft, WeightedTriTrivialTurnRight, WeightedTriTurn, WeightedTriWTurn, WeightedTriangularGadget, }; -use crate::rules::unitdiskmapping::Pattern; // === Square Gadget Tests === diff --git a/src/unit_tests/unitdiskmapping_algorithms/gadgets_ground_truth.rs b/src/unit_tests/unitdiskmapping_algorithms/gadgets_ground_truth.rs index 15bb0c395..8b02346ee 100644 --- a/src/unit_tests/unitdiskmapping_algorithms/gadgets_ground_truth.rs +++ b/src/unit_tests/unitdiskmapping_algorithms/gadgets_ground_truth.rs @@ -3,6 +3,7 @@ //! The ground truth is generated by scripts/dump_gadgets.jl and stored in //! tests/data/gadgets_ground_truth.json +use crate::rules::unitdiskmapping::Pattern; use crate::rules::unitdiskmapping::ksg::{ KsgBranch, KsgBranchFix, KsgBranchFixB, KsgCross, KsgDanglingLeg, KsgEndTurn, KsgReflectedGadget, KsgRotatedGadget, KsgTCon, KsgTrivialTurn, KsgTurn, KsgWTurn, Mirror, @@ -13,7 +14,6 @@ use crate::rules::unitdiskmapping::triangular::{ WeightedTriTrivialTurnLeft, WeightedTriTrivialTurnRight, WeightedTriTurn, WeightedTriWTurn, WeightedTriangularGadget, }; -use crate::rules::unitdiskmapping::Pattern; use serde::Deserialize; use std::collections::HashMap; use std::fs; diff --git a/src/unit_tests/unitdiskmapping_algorithms/julia_comparison.rs b/src/unit_tests/unitdiskmapping_algorithms/julia_comparison.rs index 799f9ba4e..cf0b4485b 100644 --- a/src/unit_tests/unitdiskmapping_algorithms/julia_comparison.rs +++ b/src/unit_tests/unitdiskmapping_algorithms/julia_comparison.rs @@ -5,7 +5,7 @@ //! - Weighted (square lattice with weights) //! - Triangular (triangular lattice with weights) -use crate::rules::unitdiskmapping::{ksg, triangular, MappingResult}; +use crate::rules::unitdiskmapping::{MappingResult, ksg, triangular}; use serde::Deserialize; use std::collections::HashSet; use std::fs; diff --git a/src/unit_tests/unitdiskmapping_algorithms/map_graph.rs b/src/unit_tests/unitdiskmapping_algorithms/map_graph.rs index fc6daf52d..cb8a35049 100644 --- a/src/unit_tests/unitdiskmapping_algorithms/map_graph.rs +++ b/src/unit_tests/unitdiskmapping_algorithms/map_graph.rs @@ -3,7 +3,7 @@ //! Tests square lattice mapping, MappingResult, and config_back. use super::common::{is_independent_set, solve_mis, solve_mis_config}; -use crate::rules::unitdiskmapping::{ksg, GridKind, MappingResult}; +use crate::rules::unitdiskmapping::{GridKind, MappingResult, ksg}; use crate::topology::smallgraph; // === Square Lattice Basic Tests === @@ -392,7 +392,7 @@ fn test_grid_graph_nodes_have_weights() { // === Tape Entry and Ruleset Tests === -use crate::rules::unitdiskmapping::ksg::{tape_entry_mis_overhead, KsgTapeEntry}; +use crate::rules::unitdiskmapping::ksg::{KsgTapeEntry, tape_entry_mis_overhead}; #[test] fn test_tape_entry_mis_overhead_crossing_patterns() { diff --git a/src/unit_tests/unitdiskmapping_algorithms/mapping_result.rs b/src/unit_tests/unitdiskmapping_algorithms/mapping_result.rs index 066883221..34bacc726 100644 --- a/src/unit_tests/unitdiskmapping_algorithms/mapping_result.rs +++ b/src/unit_tests/unitdiskmapping_algorithms/mapping_result.rs @@ -138,8 +138,8 @@ fn test_unapply_weighted_gadgets_empty_tape() { #[test] fn test_unapply_gadgets_rejects_unknown_tape_entry() { - use crate::rules::unitdiskmapping::ksg::mapping::unapply_gadgets; use crate::rules::unitdiskmapping::ksg::KsgTapeEntry; + use crate::rules::unitdiskmapping::ksg::mapping::unapply_gadgets; let tape = vec![KsgTapeEntry { pattern_idx: 999, @@ -153,8 +153,8 @@ fn test_unapply_gadgets_rejects_unknown_tape_entry() { #[test] fn test_unapply_weighted_gadgets_rejects_unknown_tape_entry() { - use crate::rules::unitdiskmapping::ksg::mapping::unapply_weighted_gadgets; use crate::rules::unitdiskmapping::ksg::WeightedKsgTapeEntry; + use crate::rules::unitdiskmapping::ksg::mapping::unapply_weighted_gadgets; let tape = vec![WeightedKsgTapeEntry { pattern_idx: 999, @@ -429,7 +429,7 @@ fn test_full_pipeline_triangular_house() { fn test_apply_and_unapply_gadget() { use crate::rules::unitdiskmapping::ksg::KsgTurn; use crate::rules::unitdiskmapping::{ - apply_gadget, unapply_gadget, CellState, MappingGrid, Pattern, + CellState, MappingGrid, Pattern, apply_gadget, unapply_gadget, }; let mut grid = MappingGrid::new(10, 10, 4); @@ -460,7 +460,7 @@ fn test_apply_and_unapply_gadget() { #[test] fn test_apply_gadget_at_various_positions() { use crate::rules::unitdiskmapping::ksg::KsgTurn; - use crate::rules::unitdiskmapping::{apply_gadget, CellState, MappingGrid, Pattern}; + use crate::rules::unitdiskmapping::{CellState, MappingGrid, Pattern, apply_gadget}; let mut grid = MappingGrid::new(20, 20, 4); let turn = KsgTurn; diff --git a/src/unit_tests/unitdiskmapping_algorithms/triangular.rs b/src/unit_tests/unitdiskmapping_algorithms/triangular.rs index 567942791..8f8ec3d8d 100644 --- a/src/unit_tests/unitdiskmapping_algorithms/triangular.rs +++ b/src/unit_tests/unitdiskmapping_algorithms/triangular.rs @@ -1,9 +1,23 @@ //! Tests for triangular lattice mapping (src/rules/mapping/triangular.rs). use super::common::solve_weighted_grid_mis; -use crate::rules::unitdiskmapping::{trace_centers, triangular, MappingResult}; +use crate::rules::unitdiskmapping::{MappingResult, trace_centers, triangular}; use crate::topology::smallgraph; +#[test] +fn test_weighted_triangular_tape_rejects_unknown_gadget() { + let entry = triangular::gadgets::WeightedTriTapeEntry { + gadget_idx: 104, + row: 0, + col: 0, + }; + assert!( + matches!(triangular::gadgets::tape_entry_mis_overhead(&entry), + Err(crate::rules::ReductionError::InvalidTarget { source_problem: "Graph", target_problem: "UnitDiskMapping", message }) + if message == "tape contains an unknown weighted triangular gadget index") + ); +} + // === Basic Triangular Mapping Tests === #[test] diff --git a/src/unit_tests/unitdiskmapping_algorithms/weighted.rs b/src/unit_tests/unitdiskmapping_algorithms/weighted.rs index 943a4ce20..decb03f54 100644 --- a/src/unit_tests/unitdiskmapping_algorithms/weighted.rs +++ b/src/unit_tests/unitdiskmapping_algorithms/weighted.rs @@ -1,7 +1,7 @@ //! Tests for weighted mode functionality (src/rules/mapping/weighted.rs). use crate::rules::unitdiskmapping::{ - copyline_weighted_locations_triangular, ksg, map_weights, trace_centers, triangular, CopyLine, + CopyLine, copyline_weighted_locations_triangular, ksg, map_weights, trace_centers, triangular, }; // === Trace Centers Tests === @@ -590,7 +590,7 @@ fn test_square_danglinleg_weights() { #[test] fn test_weighted_map_config_back_standard_graphs() { use super::common::{is_independent_set, solve_mis}; - use crate::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; + use crate::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use crate::solvers::ILPSolver; // Keep every standard-graph case, bounded to an eight-vertex induced subgraph. diff --git a/src/unit_tests/unitdiskmapping_algorithms/weighted_gadget.rs b/src/unit_tests/unitdiskmapping_algorithms/weighted_gadget.rs index b5472f5b6..9b2a326b0 100644 --- a/src/unit_tests/unitdiskmapping_algorithms/weighted_gadget.rs +++ b/src/unit_tests/unitdiskmapping_algorithms/weighted_gadget.rs @@ -2,6 +2,7 @@ use super::alpha_tensor::alpha_tensor; use super::common::{ksg_edges, triangular_edges}; +use crate::rules::unitdiskmapping::Pattern; use crate::rules::unitdiskmapping::ksg::{ KsgReflectedGadget, KsgRotatedGadget, Mirror, WeightedKsgBranch, WeightedKsgBranchFix, WeightedKsgBranchFixB, WeightedKsgCross, WeightedKsgDanglingLeg, WeightedKsgEndTurn, @@ -13,7 +14,6 @@ use crate::rules::unitdiskmapping::triangular::{ WeightedTriTrivialTurnLeft, WeightedTriTrivialTurnRight, WeightedTriTurn, WeightedTriWTurn, WeightedTriangularGadget, }; -use crate::rules::unitdiskmapping::Pattern; fn assert_weighted_boundary_equivalent( source: (&[(usize, usize)], &mut [i64], &[usize]), diff --git a/tests/suites/consecutive_ones_matrix_augmentation.rs b/tests/suites/consecutive_ones_matrix_augmentation.rs index 276dc3662..01cd899e6 100644 --- a/tests/suites/consecutive_ones_matrix_augmentation.rs +++ b/tests/suites/consecutive_ones_matrix_augmentation.rs @@ -1,5 +1,5 @@ -use problemreductions::models::algebraic::ConsecutiveOnesMatrixAugmentation; use problemreductions::Problem; +use problemreductions::models::algebraic::ConsecutiveOnesMatrixAugmentation; #[test] fn test_consecutive_ones_matrix_augmentation_yes_instance() { diff --git a/tests/suites/examples.rs b/tests/suites/examples.rs index 24ad255f8..4014d7223 100644 --- a/tests/suites/examples.rs +++ b/tests/suites/examples.rs @@ -69,10 +69,12 @@ fn test_export_schemas() { .into_iter() .find(|schema| schema.name == "MaximumIndependentSet") .unwrap(); - assert!(serde_json::to_value(public_schema) - .unwrap() - .get("module_path") - .is_none()); + assert!( + serde_json::to_value(public_schema) + .unwrap() + .get("module_path") + .is_none() + ); std::fs::remove_dir_all(output_dir).unwrap(); } diff --git a/tests/suites/integration.rs b/tests/suites/integration.rs index db976e33f..159adc914 100644 --- a/tests/suites/integration.rs +++ b/tests/suites/integration.rs @@ -147,9 +147,11 @@ mod all_problems_solvable { let solver = BruteForce::new(); let satisfying = solver.find_all_witnesses(&problem).unwrap(); assert_eq!(satisfying, vec![vec![false, false, true]]); - assert!(satisfying - .iter() - .all(|config| problem.evaluate(config).unwrap().0)); + assert!( + satisfying + .iter() + .all(|config| problem.evaluate(config).unwrap().0) + ); } #[test] diff --git a/tests/suites/ksatisfiability_simultaneous_incongruences.rs b/tests/suites/ksatisfiability_simultaneous_incongruences.rs index 43812429b..c4a97c05e 100644 --- a/tests/suites/ksatisfiability_simultaneous_incongruences.rs +++ b/tests/suites/ksatisfiability_simultaneous_incongruences.rs @@ -1,9 +1,9 @@ +use problemreductions::Problem; use problemreductions::models::algebraic::SimultaneousIncongruences; use problemreductions::models::formula::{CNFClause, KSatisfiability}; use problemreductions::rules::{ReduceTo, ReductionGraph, ReductionResult}; use problemreductions::solvers::BruteForce; use problemreductions::variant::K3; -use problemreductions::Problem; #[test] fn test_ksatisfiability_to_simultaneous_incongruences_closed_loop() { diff --git a/tests/suites/numeric_boundaries.rs b/tests/suites/numeric_boundaries.rs index ae98948d3..09c1e17ba 100644 --- a/tests/suites/numeric_boundaries.rs +++ b/tests/suites/numeric_boundaries.rs @@ -1,3 +1,4 @@ +use problemreductions::Problem; use problemreductions::models::formula::{ CNFClause, KSatisfiability, Maximum2Satisfiability, NAESatisfiability, OneInThreeSatisfiability, Planar3Satisfiability, QuantifiedBooleanFormulas, Quantifier, @@ -8,7 +9,6 @@ use problemreductions::models::set::MinimumSetCovering; use problemreductions::rules::ReduceTo; use problemreductions::topology::SimpleGraph; use problemreductions::variant::K3; -use problemreductions::Problem; #[test] fn numeric_boundaries_weight_totals_use_i64() { diff --git a/tests/suites/reductions.rs b/tests/suites/reductions.rs index ffde6fc64..f7ff1077e 100644 --- a/tests/suites/reductions.rs +++ b/tests/suites/reductions.rs @@ -3,7 +3,7 @@ //! These tests verify that reduction chains work correctly and //! solutions can be properly extracted through the reduction pipeline. -use problemreductions::models::algebraic::{LinearConstraint, ObjectiveSense, ILP}; +use problemreductions::models::algebraic::{ILP, LinearConstraint, ObjectiveSense}; use problemreductions::models::graph::{MinimumCoveringByCliques, PartitionIntoCliques}; use problemreductions::prelude::*; use problemreductions::rules::ReductionGraph; @@ -683,11 +683,7 @@ mod qubo_reductions { .iter() .map(|l| { let var = (l.variable + 1) as i64; // 0-indexed to 1-indexed - if l.negated { - -var - } else { - var - } + if l.negated { -var } else { var } }) .collect(); CNFClause::new(signed) @@ -752,7 +748,7 @@ mod qubo_reductions { let terms: Vec<(usize, i64)> = row .iter() .enumerate() - .filter(|(_, &c)| c != 0) + .filter(|&(_, &c)| c != 0) .map(|(i, &c)| (i, c)) .collect(); match sign { @@ -769,7 +765,7 @@ mod qubo_reductions { .objective .iter() .enumerate() - .filter(|(_, &c)| c != 0) + .filter(|&(_, &c)| c != 0) .map(|(i, &c)| (i, c)) .collect();