From a8c637c7b219ccce724ebb1f739bf7ff9d165e6a Mon Sep 17 00:00:00 2001 From: Xiwei Pan Date: Thu, 26 Mar 2026 11:06:27 +0800 Subject: [PATCH 1/3] Replace hardcoded canonical rule examples with ILPSolver calls Convert 46 ILP reduction rules from hardcoded SolutionPair to dynamic ILPSolver::new().solve() calls, ensuring canonical examples actually verify the ILP solver can solve the reduction. Also adds a z upper bound constraint in MinMaxMulticenter ILP formulation to prevent HiGHS from stalling on unbounded [0, 2^31) domain. Closes #772 Co-Authored-By: Claude Opus 4.6 (1M context) --- src/rules/bmf_ilp.rs | 22 ++------ src/rules/capacityassignment_ilp.rs | 11 ++-- src/rules/consecutiveblockminimization_ilp.rs | 56 ++----------------- ...onsistencyofdatabasefrequencytables_ilp.rs | 12 ++-- .../directedtwocommodityintegralflow_ilp.rs | 12 ++-- src/rules/factoring_ilp.rs | 14 +++-- src/rules/integralflowbundles_ilp.rs | 16 ++++-- src/rules/integralflowhomologousarcs_ilp.rs | 9 ++- src/rules/integralflowwithmultipliers_ilp.rs | 9 ++- src/rules/longestcommonsubsequence_ilp.rs | 36 +++--------- src/rules/longestpath_ilp.rs | 12 +++- src/rules/maximalis_ilp.rs | 9 ++- src/rules/maximumclique_ilp.rs | 9 ++- src/rules/maximummatching_ilp.rs | 9 ++- src/rules/maximumsetpacking_ilp.rs | 9 ++- src/rules/minimumcutintoboundedsets_ilp.rs | 9 ++- src/rules/minimumdominatingset_ilp.rs | 9 ++- src/rules/minimumfeedbackarcset_ilp.rs | 9 ++- src/rules/minimumfeedbackvertexset_ilp.rs | 9 ++- src/rules/minimumhittingset_ilp.rs | 9 ++- src/rules/minimummultiwaycut_ilp.rs | 11 ++-- src/rules/minimumsetcovering_ilp.rs | 9 ++- src/rules/minimumsummulticenter_ilp.rs | 16 +++--- src/rules/minmaxmulticenter_ilp.rs | 31 ++++++---- src/rules/multiplecopyfileallocation_ilp.rs | 20 +++---- src/rules/multiprocessorscheduling_ilp.rs | 11 ++-- src/rules/naesatisfiability_ilp.rs | 9 ++- src/rules/partiallyorderedknapsack_ilp.rs | 9 ++- src/rules/partitionintopathsoflength2_ilp.rs | 20 +++---- src/rules/partitionintotriangles_ilp.rs | 12 ++-- src/rules/pathconstrainednetworkflow_ilp.rs | 9 ++- .../precedenceconstrainedscheduling_ilp.rs | 11 ++-- src/rules/qubo_ilp.rs | 9 ++- .../rectilinearpicturecompression_ilp.rs | 9 ++- .../schedulingwithindividualdeadlines_ilp.rs | 12 ++-- ...ingtominimizeweightedcompletiontime_ilp.rs | 12 +++- .../shortestweightconstrainedpath_ilp.rs | 11 ++-- src/rules/steinertree_ilp.rs | 12 ++-- src/rules/sumofsquarespartition_ilp.rs | 53 +++--------------- src/rules/travelingsalesman_ilp.rs | 13 +++-- src/rules/undirectedflowlowerbounds_ilp.rs | 13 +++-- src/unit_tests/example_db.rs | 4 +- src/unit_tests/rules/minmaxmulticenter_ilp.rs | 8 +-- 43 files changed, 315 insertions(+), 299 deletions(-) diff --git a/src/rules/bmf_ilp.rs b/src/rules/bmf_ilp.rs index 3f36616d3..257f2f991 100644 --- a/src/rules/bmf_ilp.rs +++ b/src/rules/bmf_ilp.rs @@ -120,26 +120,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - // Build target config by encoding: - // p_{0,0,0}=1, p_{0,0,1}=0, p_{0,1,0}=0, p_{0,1,1}=0 - // p_{1,0,0}=0, p_{1,0,1}=0, p_{1,1,0}=0, p_{1,1,1}=1 - // w: [1,0,0,1], e: [0,0,0,0] - let target_config = vec![ - 1, 0, 0, 1, // B - 1, 0, 0, 1, // C - 1, 0, 0, 0, 0, 0, 0, 1, // P - 1, 0, 0, 1, // W - 0, 0, 0, 0, // E - ]; + let reduction = ReduceTo::>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { source_config, - target_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/capacityassignment_ilp.rs b/src/rules/capacityassignment_ilp.rs index 25fffa479..80b97f82a 100644 --- a/src/rules/capacityassignment_ilp.rs +++ b/src/rules/capacityassignment_ilp.rs @@ -121,13 +121,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - // link 0 → cap 1, link 1 → cap 0 - source_config: vec![1, 0], - // x_{0,0}=0, x_{0,1}=1, x_{1,0}=1, x_{1,1}=0 - target_config: vec![0, 1, 1, 0], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/consecutiveblockminimization_ilp.rs b/src/rules/consecutiveblockminimization_ilp.rs index dc7e3bcb2..83df33cbe 100644 --- a/src/rules/consecutiveblockminimization_ilp.rs +++ b/src/rules/consecutiveblockminimization_ilp.rs @@ -122,60 +122,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec columns reordered as [2,0,1] - // Row 0: A[0,2]=1, A[0,0]=1, A[0,1]=0 => [1,1,0] => 1 block - // Row 1: A[1,2]=1, A[1,0]=0, A[1,1]=1 => [1,0,1] => 2 blocks - // Total = 3 > 2, try [0,2,1]: - // Row 0: A[0,0]=1, A[0,2]=1, A[0,1]=0 => [1,1,0] => 1 block - // Row 1: A[1,0]=0, A[1,2]=1, A[1,1]=1 => [0,1,1] => 1 block - // Total = 2 <= 2. Good. - let source_config = vec![0, 2, 1]; - let reduction: ReductionCBMToILP = ReduceTo::>::reduce_to(&source); - // Encode x_{c,p}: column c at position p - // c=0 at p=0: x_{0*3+0}=1, c=2 at p=1: x_{2*3+1}=1, c=1 at p=2: x_{1*3+2}=1 - let n = 3; - let mut target_config = vec![0; reduction.target.num_vars]; - // x_{0,0} = 1 - target_config[0 * n + 0] = 1; - // x_{2,1} = 1 - target_config[2 * n + 1] = 1; - // x_{1,2} = 1 - target_config[1 * n + 2] = 1; - // a values - let a_offset = n * n; - let m = 2; - let matrix = vec![vec![true, false, true], vec![false, true, true]]; - let perm = [0, 2, 1]; - for r in 0..m { - for p in 0..n { - if matrix[r][perm[p]] { - target_config[a_offset + r * n + p] = 1; - } - } - } - // b values - let b_offset = n * n + m * n; - for r in 0..m { - for p in 0..n { - let a_cur = if matrix[r][perm[p]] { 1 } else { 0 }; - let a_prev = if p > 0 && matrix[r][perm[p - 1]] { - 1 - } else { - 0 - }; - if p == 0 { - target_config[b_offset + r * n + p] = a_cur; - } else if a_cur > a_prev { - target_config[b_offset + r * n + p] = 1; - } - } - } - + let reduction = ReduceTo::>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { source_config, - target_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/consistencyofdatabasefrequencytables_ilp.rs b/src/rules/consistencyofdatabasefrequencytables_ilp.rs index 9461ac9f5..db41420ad 100644 --- a/src/rules/consistencyofdatabasefrequencytables_ilp.rs +++ b/src/rules/consistencyofdatabasefrequencytables_ilp.rs @@ -55,7 +55,7 @@ impl ReductionCDFTToILP { } /// Encode a satisfying source assignment as a concrete ILP variable vector. - #[cfg_attr(not(any(test, feature = "example-db")), allow(dead_code))] + #[cfg_attr(not(test), allow(dead_code))] pub(crate) fn encode_source_solution(&self, source_solution: &[usize]) -> Vec { let mut target_solution = vec![0usize; self.target.num_vars]; let num_attributes = self.source.num_attributes(); @@ -223,14 +223,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { source_config, - target_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/directedtwocommodityintegralflow_ilp.rs b/src/rules/directedtwocommodityintegralflow_ilp.rs index 583e1cd5d..74840fbd1 100644 --- a/src/rules/directedtwocommodityintegralflow_ilp.rs +++ b/src/rules/directedtwocommodityintegralflow_ilp.rs @@ -178,14 +178,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1], - target_config: vec![1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/factoring_ilp.rs b/src/rules/factoring_ilp.rs index c66fc3f51..06e000db6 100644 --- a/src/rules/factoring_ilp.rs +++ b/src/rules/factoring_ilp.rs @@ -228,13 +228,17 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( - Factoring::new(3, 3, 35), + source, SolutionPair { - source_config: vec![1, 0, 1, 1, 1, 1], - target_config: vec![ - 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, - ], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/integralflowbundles_ilp.rs b/src/rules/integralflowbundles_ilp.rs index 1fd15c1fd..a0bf5c74f 100644 --- a/src/rules/integralflowbundles_ilp.rs +++ b/src/rules/integralflowbundles_ilp.rs @@ -93,18 +93,24 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>( - IntegralFlowBundles::new( + let source = IntegralFlowBundles::new( DirectedGraph::new(4, vec![(0, 1), (0, 2), (1, 3), (2, 3), (1, 2), (2, 1)]), 0, 3, vec![vec![0, 1], vec![2, 5], vec![3, 4]], vec![1, 1, 1], 1, - ), + ); + let reduction = ReduceTo::>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); + crate::example_db::specs::rule_example_with_witness::<_, ILP>( + source, SolutionPair { - source_config: vec![1, 0, 1, 0, 0, 0], - target_config: vec![1, 0, 1, 0, 0, 0], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/integralflowhomologousarcs_ilp.rs b/src/rules/integralflowhomologousarcs_ilp.rs index 3d8f41f07..2f98173f3 100644 --- a/src/rules/integralflowhomologousarcs_ilp.rs +++ b/src/rules/integralflowhomologousarcs_ilp.rs @@ -104,11 +104,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![1, 1, 1, 1], - target_config: vec![1, 1, 1, 1], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/integralflowwithmultipliers_ilp.rs b/src/rules/integralflowwithmultipliers_ilp.rs index 04f849cb1..c35c6f102 100644 --- a/src/rules/integralflowwithmultipliers_ilp.rs +++ b/src/rules/integralflowwithmultipliers_ilp.rs @@ -103,11 +103,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![1, 1, 1, 1], - target_config: vec![1, 1, 1, 1], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/longestcommonsubsequence_ilp.rs b/src/rules/longestcommonsubsequence_ilp.rs index 1d9b83a0f..e31e85dc7 100644 --- a/src/rules/longestcommonsubsequence_ilp.rs +++ b/src/rules/longestcommonsubsequence_ilp.rs @@ -171,38 +171,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![0, 2, 3], - target_config, + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/longestpath_ilp.rs b/src/rules/longestpath_ilp.rs index 5cdd3392a..bf0ec24ca 100644 --- a/src/rules/longestpath_ilp.rs +++ b/src/rules/longestpath_ilp.rs @@ -180,11 +180,17 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( - LongestPath::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![2, 3], 0, 2), + source, SolutionPair { - source_config: vec![1, 1], - target_config: vec![1, 0, 1, 0, 0, 1, 2], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/maximalis_ilp.rs b/src/rules/maximalis_ilp.rs index bd540a902..1c6e84319 100644 --- a/src/rules/maximalis_ilp.rs +++ b/src/rules/maximalis_ilp.rs @@ -79,11 +79,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![1, 0, 1], - target_config: vec![1, 0, 1], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/maximumclique_ilp.rs b/src/rules/maximumclique_ilp.rs index 4ca25dc18..3e934de10 100644 --- a/src/rules/maximumclique_ilp.rs +++ b/src/rules/maximumclique_ilp.rs @@ -87,11 +87,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![1, 1, 1, 0, 0, 0], - target_config: vec![1, 1, 1, 0, 0, 0], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/maximummatching_ilp.rs b/src/rules/maximummatching_ilp.rs index a491bd688..b3a8d7eaf 100644 --- a/src/rules/maximummatching_ilp.rs +++ b/src/rules/maximummatching_ilp.rs @@ -87,11 +87,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1], - target_config: vec![0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/maximumsetpacking_ilp.rs b/src/rules/maximumsetpacking_ilp.rs index 5a50afd45..43af37df2 100644 --- a/src/rules/maximumsetpacking_ilp.rs +++ b/src/rules/maximumsetpacking_ilp.rs @@ -92,11 +92,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![0, 0, 0, 1, 1, 0], - target_config: vec![0, 0, 0, 1, 1, 0], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/minimumcutintoboundedsets_ilp.rs b/src/rules/minimumcutintoboundedsets_ilp.rs index 871e809ff..239f6d28d 100644 --- a/src/rules/minimumcutintoboundedsets_ilp.rs +++ b/src/rules/minimumcutintoboundedsets_ilp.rs @@ -108,11 +108,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![0, 0, 1, 1], - target_config: vec![0, 0, 1, 1, 0, 1, 0], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/minimumdominatingset_ilp.rs b/src/rules/minimumdominatingset_ilp.rs index 7725779d2..c1b128576 100644 --- a/src/rules/minimumdominatingset_ilp.rs +++ b/src/rules/minimumdominatingset_ilp.rs @@ -89,11 +89,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![0, 0, 1, 0, 0, 1, 0, 0, 0, 1], - target_config: vec![0, 0, 1, 0, 0, 1, 0, 0, 0, 1], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/minimumfeedbackarcset_ilp.rs b/src/rules/minimumfeedbackarcset_ilp.rs index 959b76d6b..e0a380d24 100644 --- a/src/rules/minimumfeedbackarcset_ilp.rs +++ b/src/rules/minimumfeedbackarcset_ilp.rs @@ -121,11 +121,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![0, 0, 1], - target_config: vec![0, 0, 1, 0, 1, 2], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/minimumfeedbackvertexset_ilp.rs b/src/rules/minimumfeedbackvertexset_ilp.rs index 82f71f94f..cddf8dcf0 100644 --- a/src/rules/minimumfeedbackvertexset_ilp.rs +++ b/src/rules/minimumfeedbackvertexset_ilp.rs @@ -115,11 +115,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec 1 -> 2 -> 0 (FVS = 1 vertex) let graph = DirectedGraph::new(3, vec![(0, 1), (1, 2), (2, 0)]); let source = MinimumFeedbackVertexSet::new(graph, vec![1i32; 3]); + let reduction = ReduceTo::>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![0, 1, 0], - target_config: vec![0, 1, 0, 1, 0, 0], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/minimumhittingset_ilp.rs b/src/rules/minimumhittingset_ilp.rs index cbfdc781f..f11b70fb3 100644 --- a/src/rules/minimumhittingset_ilp.rs +++ b/src/rules/minimumhittingset_ilp.rs @@ -58,11 +58,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![0, 1, 0, 1], - target_config: vec![0, 1, 0, 1], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/minimummultiwaycut_ilp.rs b/src/rules/minimummultiwaycut_ilp.rs index 143f7035a..a54cdf1a4 100644 --- a/src/rules/minimummultiwaycut_ilp.rs +++ b/src/rules/minimummultiwaycut_ilp.rs @@ -136,13 +136,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&problem); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( problem, SolutionPair { - source_config: vec![1, 0, 0, 1, 1, 0], - target_config: vec![ - 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, - ], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/minimumsetcovering_ilp.rs b/src/rules/minimumsetcovering_ilp.rs index cd0760aec..9c2431cab 100644 --- a/src/rules/minimumsetcovering_ilp.rs +++ b/src/rules/minimumsetcovering_ilp.rs @@ -99,11 +99,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![0, 1, 0, 1, 1, 0], - target_config: vec![0, 1, 0, 1, 1, 0], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/minimumsummulticenter_ilp.rs b/src/rules/minimumsummulticenter_ilp.rs index ffbc40ae5..715038e34 100644 --- a/src/rules/minimumsummulticenter_ilp.rs +++ b/src/rules/minimumsummulticenter_ilp.rs @@ -199,18 +199,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![0, 1, 0], - target_config: vec![ - 0, 1, 0, // x_0, x_1, x_2 - 0, 1, 0, // y_{0,0}, y_{0,1}, y_{0,2} - 0, 1, 0, // y_{1,0}, y_{1,1}, y_{1,2} - 0, 1, 0, // y_{2,0}, y_{2,1}, y_{2,2} - ], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/minmaxmulticenter_ilp.rs b/src/rules/minmaxmulticenter_ilp.rs index c228bb96b..33664a9d8 100644 --- a/src/rules/minmaxmulticenter_ilp.rs +++ b/src/rules/minmaxmulticenter_ilp.rs @@ -116,7 +116,7 @@ fn weighted_distances_mmc( #[reduction( overhead = { num_vars = "num_vertices + num_vertices^2 + 1", - num_constraints = "2 * num_vertices^2 + 4 * num_vertices + 1", + num_constraints = "2 * num_vertices^2 + 4 * num_vertices + 2", } )] impl ReduceTo> for MinMaxMulticenter { @@ -176,6 +176,19 @@ impl ReduceTo> for MinMaxMulticenter { } } + // Upper bound on z: the worst-case weighted distance over all vertex + // pairs. Without this bound HiGHS sees z ∈ [0, 2^31) and can stall. + let z_upper: f64 = all_dist + .iter() + .enumerate() + .flat_map(|(i, row)| { + row.iter().filter_map(move |d| { + d.map(|d| (vertex_weights[i] as f64) * (d as f64)) + }) + }) + .fold(0.0_f64, f64::max); + constraints.push(LinearConstraint::le(vec![(z_var, 1.0)], z_upper)); + // Minimax constraints: ∀i: Σ_j w_i · d(i,j) · y_{i,j} ≤ z for (i, &w) in vertex_weights.iter().enumerate() { let w_i = w as f64; @@ -216,18 +229,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![0, 1, 0], - target_config: vec![ - 0, 1, 0, // x_0, x_1, x_2 - 0, 1, 0, // y_{0,0}, y_{0,1}, y_{0,2} - 0, 1, 0, // y_{1,0}, y_{1,1}, y_{1,2} - 0, 1, 0, // y_{2,0}, y_{2,1}, y_{2,2} - 1, // z - ], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/multiplecopyfileallocation_ilp.rs b/src/rules/multiplecopyfileallocation_ilp.rs index 810f76d33..91f772ebb 100644 --- a/src/rules/multiplecopyfileallocation_ilp.rs +++ b/src/rules/multiplecopyfileallocation_ilp.rs @@ -155,22 +155,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![0, 1, 0], - target_config: vec![ - 0, 1, 0, // x_0, x_1, x_2 - 0, 1, 0, // y_{0,0}, y_{0,1}, y_{0,2} - 0, 1, 0, // y_{1,0}, y_{1,1}, y_{1,2} - 0, 1, 0, // y_{2,0}, y_{2,1}, y_{2,2} - ], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/multiprocessorscheduling_ilp.rs b/src/rules/multiprocessorscheduling_ilp.rs index ffe97c21f..fce1c5031 100644 --- a/src/rules/multiprocessorscheduling_ilp.rs +++ b/src/rules/multiprocessorscheduling_ilp.rs @@ -101,13 +101,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - // task 0→p0, task 1→p1, task 2→p0 - source_config: vec![0, 1, 0], - // x_{0,0}=1, x_{0,1}=0, x_{1,0}=0, x_{1,1}=1, x_{2,0}=1, x_{2,1}=0 - target_config: vec![1, 0, 0, 1, 1, 0], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/naesatisfiability_ilp.rs b/src/rules/naesatisfiability_ilp.rs index d047bdc33..ecbdf19f8 100644 --- a/src/rules/naesatisfiability_ilp.rs +++ b/src/rules/naesatisfiability_ilp.rs @@ -94,11 +94,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![1, 0, 0], - target_config: vec![1, 0, 0], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/partiallyorderedknapsack_ilp.rs b/src/rules/partiallyorderedknapsack_ilp.rs index 45aec66b2..738931674 100644 --- a/src/rules/partiallyorderedknapsack_ilp.rs +++ b/src/rules/partiallyorderedknapsack_ilp.rs @@ -74,11 +74,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![1, 0, 1], - target_config: vec![1, 0, 1], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/partitionintopathsoflength2_ilp.rs b/src/rules/partitionintopathsoflength2_ilp.rs index 6ffb05aaf..c85a6ce4f 100644 --- a/src/rules/partitionintopathsoflength2_ilp.rs +++ b/src/rules/partitionintopathsoflength2_ilp.rs @@ -138,22 +138,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - // vertex 0,1,2 → group 0; vertex 3,4,5 → group 1 - source_config: vec![0, 0, 0, 1, 1, 1], - // x vars: x_{0,0}=1,x_{0,1}=0, x_{1,0}=1,x_{1,1}=0, x_{2,0}=1,x_{2,1}=0, - // x_{3,0}=0,x_{3,1}=1, x_{4,0}=0,x_{4,1}=1, x_{5,0}=0,x_{5,1}=1 - // y vars (4 edges * 2 groups): - // e0=(0,1): y_{0,0}=1,y_{0,1}=0 - // e1=(1,2): y_{1,0}=1,y_{1,1}=0 - // e2=(3,4): y_{2,0}=0,y_{2,1}=1 - // e3=(4,5): y_{3,0}=0,y_{3,1}=1 - target_config: vec![ - 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, // x vars - 1, 0, 1, 0, 0, 1, 0, 1, // y vars - ], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/partitionintotriangles_ilp.rs b/src/rules/partitionintotriangles_ilp.rs index d5c736130..2e582bf27 100644 --- a/src/rules/partitionintotriangles_ilp.rs +++ b/src/rules/partitionintotriangles_ilp.rs @@ -118,14 +118,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - // vertex 0,1,2 → group 0; vertex 3,4,5 → group 1 - source_config: vec![0, 0, 0, 1, 1, 1], - // x_{v,g}: v0g0=1,v0g1=0, v1g0=1,v1g1=0, v2g0=1,v2g1=0, - // v3g0=0,v3g1=1, v4g0=0,v4g1=1, v5g0=0,v5g1=1 - target_config: vec![1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/pathconstrainednetworkflow_ilp.rs b/src/rules/pathconstrainednetworkflow_ilp.rs index e0b1db438..1243f1012 100644 --- a/src/rules/pathconstrainednetworkflow_ilp.rs +++ b/src/rules/pathconstrainednetworkflow_ilp.rs @@ -86,11 +86,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![1, 1], - target_config: vec![1, 1], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/precedenceconstrainedscheduling_ilp.rs b/src/rules/precedenceconstrainedscheduling_ilp.rs index 9a0171900..3b6d321ae 100644 --- a/src/rules/precedenceconstrainedscheduling_ilp.rs +++ b/src/rules/precedenceconstrainedscheduling_ilp.rs @@ -109,14 +109,17 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![0, 0, 1], - target_config: vec![1, 0, 1, 0, 0, 1], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/qubo_ilp.rs b/src/rules/qubo_ilp.rs index 2410ad2ac..5746df269 100644 --- a/src/rules/qubo_ilp.rs +++ b/src/rules/qubo_ilp.rs @@ -115,11 +115,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![1, 1, 1, 1], - target_config: vec![1, 1, 1, 1, 1, 1, 1], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/rectilinearpicturecompression_ilp.rs b/src/rules/rectilinearpicturecompression_ilp.rs index 4673ff34c..595dffa71 100644 --- a/src/rules/rectilinearpicturecompression_ilp.rs +++ b/src/rules/rectilinearpicturecompression_ilp.rs @@ -72,11 +72,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![1], - target_config: vec![1], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/schedulingwithindividualdeadlines_ilp.rs b/src/rules/schedulingwithindividualdeadlines_ilp.rs index b3d930380..42719d9e0 100644 --- a/src/rules/schedulingwithindividualdeadlines_ilp.rs +++ b/src/rules/schedulingwithindividualdeadlines_ilp.rs @@ -112,15 +112,17 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![0, 0, 1], - target_config: vec![1, 0, 0, 1, 0, 0, 0, 1, 0], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/sequencingtominimizeweightedcompletiontime_ilp.rs b/src/rules/sequencingtominimizeweightedcompletiontime_ilp.rs index 7f92aee38..0b6d4f251 100644 --- a/src/rules/sequencingtominimizeweightedcompletiontime_ilp.rs +++ b/src/rules/sequencingtominimizeweightedcompletiontime_ilp.rs @@ -170,11 +170,17 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( - SequencingToMinimizeWeightedCompletionTime::new(vec![2, 1], vec![3, 5], vec![]), + source, SolutionPair { - source_config: vec![1, 0], - target_config: vec![3, 1, 0], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/shortestweightconstrainedpath_ilp.rs b/src/rules/shortestweightconstrainedpath_ilp.rs index 04303e7a2..8768f3286 100644 --- a/src/rules/shortestweightconstrainedpath_ilp.rs +++ b/src/rules/shortestweightconstrainedpath_ilp.rs @@ -231,13 +231,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec1->2: a_{0,fwd}=1, a_{1,fwd}=1, orders: 0, 1, 2 + let reduction = ReduceTo::>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![1, 1], - target_config: vec![1, 0, 1, 0, 0, 1, 2], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/steinertree_ilp.rs b/src/rules/steinertree_ilp.rs index fd403d33d..eefa62c66 100644 --- a/src/rules/steinertree_ilp.rs +++ b/src/rules/steinertree_ilp.rs @@ -137,14 +137,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![1, 1, 1, 1, 0, 0, 0], - target_config: vec![ - 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, - ], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/sumofsquarespartition_ilp.rs b/src/rules/sumofsquarespartition_ilp.rs index 89c0ffcd4..296aacf5c 100644 --- a/src/rules/sumofsquarespartition_ilp.rs +++ b/src/rules/sumofsquarespartition_ilp.rs @@ -154,55 +154,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - // element 0(1)→g0, element 1(2)→g1, element 2(3)→g1, element 3(4)→g0 - source_config: vec![0, 1, 1, 0], - // x vars: x_{0,0}=1,x_{0,1}=0, x_{1,0}=0,x_{1,1}=1, - // x_{2,0}=0,x_{2,1}=1, x_{3,0}=1,x_{3,1}=0 - // z vars (4*4*2 = 32): z_{i,j,g} = x_{i,g}*x_{j,g} - // g=0: elements 0,3 assigned → z_{0,0,0}=1,z_{0,3,0}=1,z_{3,0,0}=1,z_{3,3,0}=1, rest 0 - // g=1: elements 1,2 assigned → z_{1,1,1}=1,z_{1,2,1}=1,z_{2,1,1}=1,z_{2,2,1}=1, rest 0 - target_config: vec![ - 1, 0, // x_{0,*} - 0, 1, // x_{1,*} - 0, 1, // x_{2,*} - 1, 0, // x_{3,*} - // z_{i,j,g}: for each (i,j) pair and both groups - // z_{0,0,0}=1,z_{0,0,1}=0 - 1, 0, // z_{0,0,*} - // z_{0,1,0}=0,z_{0,1,1}=0 - 0, 0, // z_{0,1,*} - // z_{0,2,0}=0,z_{0,2,1}=0 - 0, 0, // z_{0,2,*} - // z_{0,3,0}=1,z_{0,3,1}=0 - 1, 0, // z_{0,3,*} - // z_{1,0,*} - 0, 0, // z_{1,0,*} - // z_{1,1,*}: g=1 has element 1 → z_{1,1,1}=1 - 0, 1, // z_{1,1,*} - // z_{1,2,*}: g=1 has elements 1,2 → z_{1,2,1}=1 - 0, 1, // z_{1,2,*} - // z_{1,3,*} - 0, 0, // z_{1,3,*} - // z_{2,0,*} - 0, 0, // z_{2,0,*} - // z_{2,1,*}: g=1 has elements 1,2 - 0, 1, // z_{2,1,*} - // z_{2,2,*}: g=1 has element 2 - 0, 1, // z_{2,2,*} - // z_{2,3,*} - 0, 0, // z_{2,3,*} - // z_{3,0,*}: g=0 has elements 0,3 - 1, 0, // z_{3,0,*} - // z_{3,1,*} - 0, 0, // z_{3,1,*} - // z_{3,2,*} - 0, 0, // z_{3,2,*} - // z_{3,3,*}: g=0 has element 3 - 1, 0, // z_{3,3,*} - ], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/travelingsalesman_ilp.rs b/src/rules/travelingsalesman_ilp.rs index 98a16fedb..69a399bb7 100644 --- a/src/rules/travelingsalesman_ilp.rs +++ b/src/rules/travelingsalesman_ilp.rs @@ -207,15 +207,16 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![1, 1, 0, 0, 1, 1], - target_config: vec![ - 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - ], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/rules/undirectedflowlowerbounds_ilp.rs b/src/rules/undirectedflowlowerbounds_ilp.rs index 5047b354f..57af077c1 100644 --- a/src/rules/undirectedflowlowerbounds_ilp.rs +++ b/src/rules/undirectedflowlowerbounds_ilp.rs @@ -175,7 +175,6 @@ pub(crate) fn canonical_rule_example_specs() -> Vec Vec>::reduce_to(&source); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be solvable"); + let source_config = reduction.extract_solution(&ilp_solution); crate::example_db::specs::rule_example_with_witness::<_, ILP>( source, SolutionPair { - source_config: vec![0, 0], - target_config: vec![1, 0, 1, 0, 1, 1], + source_config, + target_config: ilp_solution, }, ) }, diff --git a/src/unit_tests/example_db.rs b/src/unit_tests/example_db.rs index 1a861337d..e07d63cf9 100644 --- a/src/unit_tests/example_db.rs +++ b/src/unit_tests/example_db.rs @@ -243,8 +243,8 @@ 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_eq!(example.solutions[0].source_config, vec![1, 0, 1, 0, 0, 0]); - assert_eq!(example.solutions[0].target_config, vec![1, 0, 1, 0, 0, 0]); + assert!(!example.solutions[0].source_config.is_empty()); + assert!(!example.solutions[0].target_config.is_empty()); } #[test] diff --git a/src/unit_tests/rules/minmaxmulticenter_ilp.rs b/src/unit_tests/rules/minmaxmulticenter_ilp.rs index bc7745847..0bf3b8787 100644 --- a/src/unit_tests/rules/minmaxmulticenter_ilp.rs +++ b/src/unit_tests/rules/minmaxmulticenter_ilp.rs @@ -19,12 +19,12 @@ fn test_reduction_creates_valid_ilp() { let ilp = reduction.target_problem(); // num_vars = n + n^2 + 1 = 3 + 9 + 1 = 13 assert_eq!(ilp.num_vars, 13, "n + n^2 + 1 variables"); - // num_constraints = 1 (cardinality) + n (assignment) + n^2 (link) + n (x bounds) + n^2 (y bounds) + n (minimax) - // = 1 + 3 + 9 + 3 + 9 + 3 = 28 + // num_constraints = 1 (cardinality) + n (assignment) + n^2 (link) + n (x bounds) + n^2 (y bounds) + 1 (z bound) + n (minimax) + // = 1 + 3 + 9 + 3 + 9 + 1 + 3 = 29 assert_eq!( ilp.constraints.len(), - 28, - "cardinality + assignment + link + binary bounds + minimax constraints" + 29, + "cardinality + assignment + link + binary bounds + z bound + minimax constraints" ); assert_eq!(ilp.sense, ObjectiveSense::Minimize); // Objective should minimize z (last variable) From 392e8307db2fe6eca140f5df62529e22a84b9537 Mon Sep 17 00:00:00 2001 From: Xiwei Pan Date: Thu, 26 Mar 2026 11:14:52 +0800 Subject: [PATCH 2/3] refactor: extract rule_example_via_ilp helper, eliminating 60x boilerplate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add `rule_example_via_ilp()` to `example_db::specs` that performs reduce → ILP solve → extract → assemble in one call. This replaces the 8-line block that was copy-pasted across 60 ILP rule files, and also eliminates the double `reduce_to()` call (once explicit, once inside `rule_example_with_witness`). Also fixes stale docstring on `build_example_db()` which incorrectly claimed no solver is called. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/example_db/mod.rs | 4 +-- src/example_db/specs.rs | 29 +++++++++++++++++++ src/rules/bmf_ilp.rs | 14 +-------- src/rules/bottlenecktravelingsalesman_ilp.rs | 14 +-------- src/rules/capacityassignment_ilp.rs | 17 ++--------- src/rules/consecutiveblockminimization_ilp.rs | 14 +-------- ...onsistencyofdatabasefrequencytables_ilp.rs | 14 +-------- .../directedtwocommodityintegralflow_ilp.rs | 14 +-------- src/rules/disjointconnectingpaths_ilp.rs | 14 +-------- src/rules/factoring_ilp.rs | 17 ++--------- src/rules/flowshopscheduling_ilp.rs | 17 ++--------- src/rules/hamiltonianpath_ilp.rs | 14 +-------- src/rules/integralflowbundles_ilp.rs | 14 +-------- src/rules/integralflowhomologousarcs_ilp.rs | 14 +-------- src/rules/integralflowwithmultipliers_ilp.rs | 14 +-------- src/rules/lengthboundeddisjointpaths_ilp.rs | 14 +-------- src/rules/longestcircuit_ilp.rs | 14 +-------- src/rules/longestcommonsubsequence_ilp.rs | 17 ++--------- src/rules/longestpath_ilp.rs | 17 ++--------- src/rules/maximalis_ilp.rs | 14 +-------- src/rules/maximumclique_ilp.rs | 17 ++--------- src/rules/maximummatching_ilp.rs | 17 ++--------- src/rules/maximumsetpacking_ilp.rs | 17 ++--------- src/rules/minimumcutintoboundedsets_ilp.rs | 14 +-------- src/rules/minimumdominatingset_ilp.rs | 17 ++--------- src/rules/minimumfeedbackarcset_ilp.rs | 14 +-------- src/rules/minimumfeedbackvertexset_ilp.rs | 14 +-------- src/rules/minimumhittingset_ilp.rs | 14 +-------- src/rules/minimummultiwaycut_ilp.rs | 15 +--------- src/rules/minimumsetcovering_ilp.rs | 17 ++--------- src/rules/minimumsummulticenter_ilp.rs | 17 ++--------- src/rules/minimumtardinesssequencing_ilp.rs | 17 ++--------- src/rules/minmaxmulticenter_ilp.rs | 17 ++--------- src/rules/mixedchinesepostman_ilp.rs | 14 +-------- src/rules/multiplecopyfileallocation_ilp.rs | 17 ++--------- src/rules/multiprocessorscheduling_ilp.rs | 17 ++--------- src/rules/naesatisfiability_ilp.rs | 14 +-------- src/rules/optimallineararrangement_ilp.rs | 14 +-------- src/rules/partiallyorderedknapsack_ilp.rs | 14 +-------- src/rules/partitionintopathsoflength2_ilp.rs | 17 ++--------- src/rules/partitionintotriangles_ilp.rs | 17 ++--------- src/rules/pathconstrainednetworkflow_ilp.rs | 14 +-------- .../precedenceconstrainedscheduling_ilp.rs | 17 ++--------- src/rules/quadraticassignment_ilp.rs | 14 +-------- src/rules/qubo_ilp.rs | 17 ++--------- .../rectilinearpicturecompression_ilp.rs | 14 +-------- .../resourceconstrainedscheduling_ilp.rs | 17 ++--------- src/rules/ruralpostman_ilp.rs | 14 +-------- .../schedulingwithindividualdeadlines_ilp.rs | 17 ++--------- ...cingtominimizemaximumcumulativecost_ilp.rs | 17 ++--------- ...ingtominimizeweightedcompletiontime_ilp.rs | 17 ++--------- ...quencingtominimizeweightedtardiness_ilp.rs | 17 ++--------- ...uencingwithreleasetimesanddeadlines_ilp.rs | 17 ++--------- .../shortestweightconstrainedpath_ilp.rs | 17 ++--------- src/rules/stackercrane_ilp.rs | 14 +-------- src/rules/steinertree_ilp.rs | 17 ++--------- src/rules/steinertreeingraphs_ilp.rs | 14 +-------- src/rules/subgraphisomorphism_ilp.rs | 14 +-------- src/rules/sumofsquarespartition_ilp.rs | 17 ++--------- src/rules/timetabledesign_ilp.rs | 17 ++--------- src/rules/travelingsalesman_ilp.rs | 17 ++--------- src/rules/undirectedflowlowerbounds_ilp.rs | 14 +-------- 62 files changed, 121 insertions(+), 843 deletions(-) diff --git a/src/example_db/mod.rs b/src/example_db/mod.rs index adddc3df4..6ed577a95 100644 --- a/src/example_db/mod.rs +++ b/src/example_db/mod.rs @@ -53,8 +53,8 @@ fn validate_model_uniqueness(models: &[ModelExample]) -> Result<()> { /// Build the full example database from specs. /// -/// Fast — specs store concrete instances and pre-computed solutions, -/// no solver is called. +/// ILP rule examples call the ILP solver at build time to compute solutions +/// dynamically (feature-gated behind `ilp-solver`). pub fn build_example_db() -> Result { let model_db = build_model_db()?; let rule_db = build_rule_db()?; diff --git a/src/example_db/specs.rs b/src/example_db/specs.rs index d5cb82a85..d6facb3ca 100644 --- a/src/example_db/specs.rs +++ b/src/example_db/specs.rs @@ -62,3 +62,32 @@ where let target = reduction.target_problem(); assemble_rule_example(&source, target, vec![solution]) } + +/// Reduce the source to an ILP, solve it, and assemble the rule example. +/// +/// This is the standard pattern for canonical ILP rule examples: reduce once, +/// solve the ILP, extract the source config, and build the example — avoiding +/// the double `reduce_to()` that would occur with `rule_example_with_witness`. +#[cfg(feature = "ilp-solver")] +pub fn rule_example_via_ilp(source: S) -> RuleExample +where + S: Problem + Serialize + ReduceTo>, + V: crate::models::algebraic::VariableDomain, + >>::Result: + ReductionResult>, +{ + use crate::export::SolutionPair; + let reduction = source.reduce_to(); + let ilp_solution = crate::solvers::ILPSolver::new() + .solve(reduction.target_problem()) + .expect("canonical example must be ILP-solvable"); + let source_config = reduction.extract_solution(&ilp_solution); + assemble_rule_example( + &source, + reduction.target_problem(), + vec![SolutionPair { + source_config, + target_config: ilp_solution, + }], + ) +} diff --git a/src/rules/bmf_ilp.rs b/src/rules/bmf_ilp.rs index 257f2f991..aca0223d3 100644 --- a/src/rules/bmf_ilp.rs +++ b/src/rules/bmf_ilp.rs @@ -114,24 +114,12 @@ impl ReduceTo> for BMF { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; vec![crate::example_db::specs::RuleExampleSpec { id: "bmf_to_ilp", build: || { // 2x2 identity matrix, rank 2 let source = BMF::new(vec![vec![true, false], vec![false, true]], 2); - let reduction = ReduceTo::>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/bottlenecktravelingsalesman_ilp.rs b/src/rules/bottlenecktravelingsalesman_ilp.rs index c86bf15dc..a67dda8e2 100644 --- a/src/rules/bottlenecktravelingsalesman_ilp.rs +++ b/src/rules/bottlenecktravelingsalesman_ilp.rs @@ -174,7 +174,6 @@ impl ReduceTo> for BottleneckTravelingSalesman { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; vec![crate::example_db::specs::RuleExampleSpec { id: "bottlenecktravelingsalesman_to_ilp", build: || { @@ -183,18 +182,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, i32>(source) }, }] } diff --git a/src/rules/capacityassignment_ilp.rs b/src/rules/capacityassignment_ilp.rs index 80b97f82a..33946a7bc 100644 --- a/src/rules/capacityassignment_ilp.rs +++ b/src/rules/capacityassignment_ilp.rs @@ -101,9 +101,7 @@ impl ReduceTo> for CapacityAssignment { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "capacityassignment_to_ilp", build: || { // 2 links, 2 capacity levels @@ -121,18 +119,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/consecutiveblockminimization_ilp.rs b/src/rules/consecutiveblockminimization_ilp.rs index 83df33cbe..f63ff9770 100644 --- a/src/rules/consecutiveblockminimization_ilp.rs +++ b/src/rules/consecutiveblockminimization_ilp.rs @@ -113,7 +113,6 @@ impl ReduceTo> for ConsecutiveBlockMinimization { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; vec![crate::example_db::specs::RuleExampleSpec { id: "consecutiveblockminimization_to_ilp", build: || { @@ -122,18 +121,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/consistencyofdatabasefrequencytables_ilp.rs b/src/rules/consistencyofdatabasefrequencytables_ilp.rs index db41420ad..a900f93de 100644 --- a/src/rules/consistencyofdatabasefrequencytables_ilp.rs +++ b/src/rules/consistencyofdatabasefrequencytables_ilp.rs @@ -204,7 +204,6 @@ impl ReduceTo> for ConsistencyOfDatabaseFrequencyTables { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; use crate::models::misc::{FrequencyTable, KnownValue}; vec![crate::example_db::specs::RuleExampleSpec { @@ -223,18 +222,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/directedtwocommodityintegralflow_ilp.rs b/src/rules/directedtwocommodityintegralflow_ilp.rs index 74840fbd1..f16c304cd 100644 --- a/src/rules/directedtwocommodityintegralflow_ilp.rs +++ b/src/rules/directedtwocommodityintegralflow_ilp.rs @@ -147,7 +147,6 @@ impl ReduceTo> for DirectedTwoCommodityIntegralFlow { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; use crate::topology::DirectedGraph; vec![crate::example_db::specs::RuleExampleSpec { @@ -178,18 +177,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, i32>(source) }, }] } diff --git a/src/rules/disjointconnectingpaths_ilp.rs b/src/rules/disjointconnectingpaths_ilp.rs index 149856028..089c8079b 100644 --- a/src/rules/disjointconnectingpaths_ilp.rs +++ b/src/rules/disjointconnectingpaths_ilp.rs @@ -170,7 +170,6 @@ impl ReduceTo> for DisjointConnectingPaths { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; use crate::rules::ReduceTo as _; vec![crate::example_db::specs::RuleExampleSpec { @@ -181,18 +180,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/factoring_ilp.rs b/src/rules/factoring_ilp.rs index 06e000db6..a3cbb0ac7 100644 --- a/src/rules/factoring_ilp.rs +++ b/src/rules/factoring_ilp.rs @@ -223,24 +223,11 @@ impl ReduceTo> for Factoring { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "factoring_to_ilp", build: || { let source = Factoring::new(3, 3, 35); - let reduction = ReduceTo::>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, i32>(source) }, }] } diff --git a/src/rules/flowshopscheduling_ilp.rs b/src/rules/flowshopscheduling_ilp.rs index 32fb1a06d..86a6d19fd 100644 --- a/src/rules/flowshopscheduling_ilp.rs +++ b/src/rules/flowshopscheduling_ilp.rs @@ -207,25 +207,12 @@ impl ReduceTo> for FlowShopScheduling { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "flowshopscheduling_to_ilp", build: || { // 2 machines, 3 jobs, deadline 10 let source = FlowShopScheduling::new(2, vec![vec![2, 3], vec![3, 2], vec![1, 4]], 10); - let reduction = ReduceTo::>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, i32>(source) }, }] } diff --git a/src/rules/hamiltonianpath_ilp.rs b/src/rules/hamiltonianpath_ilp.rs index 422323d62..d60f1291a 100644 --- a/src/rules/hamiltonianpath_ilp.rs +++ b/src/rules/hamiltonianpath_ilp.rs @@ -109,24 +109,12 @@ impl ReduceTo> for HamiltonianPath { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; vec![crate::example_db::specs::RuleExampleSpec { id: "hamiltonianpath_to_ilp", build: || { // Path graph: 0-1-2-3 (has Hamiltonian path) let source = HamiltonianPath::new(SimpleGraph::new(4, vec![(0, 1), (1, 2), (2, 3)])); - let reduction = ReduceTo::>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/integralflowbundles_ilp.rs b/src/rules/integralflowbundles_ilp.rs index a0bf5c74f..be01dd299 100644 --- a/src/rules/integralflowbundles_ilp.rs +++ b/src/rules/integralflowbundles_ilp.rs @@ -87,7 +87,6 @@ impl ReduceTo> for IntegralFlowBundles { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; use crate::topology::DirectedGraph; vec![crate::example_db::specs::RuleExampleSpec { @@ -101,18 +100,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, i32>(source) }, }] } diff --git a/src/rules/integralflowhomologousarcs_ilp.rs b/src/rules/integralflowhomologousarcs_ilp.rs index 2f98173f3..05c6cfc1e 100644 --- a/src/rules/integralflowhomologousarcs_ilp.rs +++ b/src/rules/integralflowhomologousarcs_ilp.rs @@ -90,7 +90,6 @@ impl ReduceTo> for IntegralFlowHomologousArcs { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; use crate::topology::DirectedGraph; vec![crate::example_db::specs::RuleExampleSpec { @@ -104,18 +103,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, i32>(source) }, }] } diff --git a/src/rules/integralflowwithmultipliers_ilp.rs b/src/rules/integralflowwithmultipliers_ilp.rs index c35c6f102..c53b35bc4 100644 --- a/src/rules/integralflowwithmultipliers_ilp.rs +++ b/src/rules/integralflowwithmultipliers_ilp.rs @@ -88,7 +88,6 @@ impl ReduceTo> for IntegralFlowWithMultipliers { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; use crate::topology::DirectedGraph; vec![crate::example_db::specs::RuleExampleSpec { @@ -103,18 +102,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, i32>(source) }, }] } diff --git a/src/rules/lengthboundeddisjointpaths_ilp.rs b/src/rules/lengthboundeddisjointpaths_ilp.rs index 35ff884b3..d0298ceaa 100644 --- a/src/rules/lengthboundeddisjointpaths_ilp.rs +++ b/src/rules/lengthboundeddisjointpaths_ilp.rs @@ -199,7 +199,6 @@ impl ReduceTo> for LengthBoundedDisjointPaths { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; use crate::rules::ReduceTo as _; vec![crate::example_db::specs::RuleExampleSpec { @@ -212,18 +211,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/longestcircuit_ilp.rs b/src/rules/longestcircuit_ilp.rs index e3e9a4c70..e52911a30 100644 --- a/src/rules/longestcircuit_ilp.rs +++ b/src/rules/longestcircuit_ilp.rs @@ -149,7 +149,6 @@ impl ReduceTo> for LongestCircuit { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; vec![crate::example_db::specs::RuleExampleSpec { id: "longestcircuit_to_ilp", build: || { @@ -158,18 +157,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/longestcommonsubsequence_ilp.rs b/src/rules/longestcommonsubsequence_ilp.rs index e31e85dc7..4f4566fad 100644 --- a/src/rules/longestcommonsubsequence_ilp.rs +++ b/src/rules/longestcommonsubsequence_ilp.rs @@ -162,27 +162,14 @@ impl ReduceTo> for LongestCommonSubsequence { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "longestcommonsubsequence_to_ilp", build: || { // Source: alphabet {0,1,2}, strings [0,1,2] and [1,0,2], max_length = 3 // Optimal LCS: [0,2] (length 2) or [1,2] (length 2) // Config with padding: e.g. [0, 2, 3] (symbol 3 = padding) let source = LongestCommonSubsequence::new(3, vec![vec![0, 1, 2], vec![1, 0, 2]]); - let reduction = ReduceTo::>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/longestpath_ilp.rs b/src/rules/longestpath_ilp.rs index bf0ec24ca..3f7e81114 100644 --- a/src/rules/longestpath_ilp.rs +++ b/src/rules/longestpath_ilp.rs @@ -175,24 +175,11 @@ impl ReduceTo> for LongestPath { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "longestpath_to_ilp", build: || { let source = LongestPath::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![2, 3], 0, 2); - let reduction = ReduceTo::>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, i32>(source) }, }] } diff --git a/src/rules/maximalis_ilp.rs b/src/rules/maximalis_ilp.rs index 1c6e84319..8e0f45a00 100644 --- a/src/rules/maximalis_ilp.rs +++ b/src/rules/maximalis_ilp.rs @@ -73,24 +73,12 @@ impl ReduceTo> for MaximalIS { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; vec![crate::example_db::specs::RuleExampleSpec { id: "maximalis_to_ilp", build: || { // Path P3: 0-1-2 let source = MaximalIS::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![1, 1, 1]); - let reduction = ReduceTo::>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/maximumclique_ilp.rs b/src/rules/maximumclique_ilp.rs index 3e934de10..6c3064490 100644 --- a/src/rules/maximumclique_ilp.rs +++ b/src/rules/maximumclique_ilp.rs @@ -80,25 +80,12 @@ impl ReduceTo> for MaximumClique { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "maximumclique_to_ilp", build: || { let (n, edges) = crate::topology::small_graphs::octahedral(); let source = MaximumClique::new(SimpleGraph::new(n, edges), vec![1i32; 6]); - let reduction = ReduceTo::>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/maximummatching_ilp.rs b/src/rules/maximummatching_ilp.rs index b3a8d7eaf..9d0944ee8 100644 --- a/src/rules/maximummatching_ilp.rs +++ b/src/rules/maximummatching_ilp.rs @@ -80,25 +80,12 @@ impl ReduceTo> for MaximumMatching { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "maximummatching_to_ilp", build: || { let (n, edges) = crate::topology::small_graphs::petersen(); let source = MaximumMatching::unit_weights(SimpleGraph::new(n, edges)); - let reduction = ReduceTo::>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/maximumsetpacking_ilp.rs b/src/rules/maximumsetpacking_ilp.rs index 43af37df2..50791bc5c 100644 --- a/src/rules/maximumsetpacking_ilp.rs +++ b/src/rules/maximumsetpacking_ilp.rs @@ -79,9 +79,7 @@ impl ReduceTo> for MaximumSetPacking { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "maximumsetpacking_to_ilp", build: || { let source = MaximumSetPacking::new(vec![ @@ -92,18 +90,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/minimumcutintoboundedsets_ilp.rs b/src/rules/minimumcutintoboundedsets_ilp.rs index 239f6d28d..8edb3a65d 100644 --- a/src/rules/minimumcutintoboundedsets_ilp.rs +++ b/src/rules/minimumcutintoboundedsets_ilp.rs @@ -97,7 +97,6 @@ impl ReduceTo> for MinimumCutIntoBoundedSets { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; vec![crate::example_db::specs::RuleExampleSpec { id: "minimumcutintoboundedsets_to_ilp", build: || { @@ -108,18 +107,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/minimumdominatingset_ilp.rs b/src/rules/minimumdominatingset_ilp.rs index c1b128576..3febfae71 100644 --- a/src/rules/minimumdominatingset_ilp.rs +++ b/src/rules/minimumdominatingset_ilp.rs @@ -82,25 +82,12 @@ impl ReduceTo> for MinimumDominatingSet { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "minimumdominatingset_to_ilp", build: || { let (n, edges) = crate::topology::small_graphs::petersen(); let source = MinimumDominatingSet::new(SimpleGraph::new(n, edges), vec![1i32; 10]); - let reduction = ReduceTo::>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/minimumfeedbackarcset_ilp.rs b/src/rules/minimumfeedbackarcset_ilp.rs index e0a380d24..fcce6d4ec 100644 --- a/src/rules/minimumfeedbackarcset_ilp.rs +++ b/src/rules/minimumfeedbackarcset_ilp.rs @@ -109,7 +109,6 @@ impl ReduceTo> for MinimumFeedbackArcSet { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; use crate::topology::DirectedGraph; vec![crate::example_db::specs::RuleExampleSpec { @@ -121,18 +120,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, i32>(source) }, }] } diff --git a/src/rules/minimumfeedbackvertexset_ilp.rs b/src/rules/minimumfeedbackvertexset_ilp.rs index cddf8dcf0..1f3e45032 100644 --- a/src/rules/minimumfeedbackvertexset_ilp.rs +++ b/src/rules/minimumfeedbackvertexset_ilp.rs @@ -106,7 +106,6 @@ impl ReduceTo> for MinimumFeedbackVertexSet { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; use crate::topology::DirectedGraph; vec![crate::example_db::specs::RuleExampleSpec { @@ -115,18 +114,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec 1 -> 2 -> 0 (FVS = 1 vertex) let graph = DirectedGraph::new(3, vec![(0, 1), (1, 2), (2, 0)]); let source = MinimumFeedbackVertexSet::new(graph, vec![1i32; 3]); - let reduction = ReduceTo::>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, i32>(source) }, }] } diff --git a/src/rules/minimumhittingset_ilp.rs b/src/rules/minimumhittingset_ilp.rs index f11b70fb3..14018ffaf 100644 --- a/src/rules/minimumhittingset_ilp.rs +++ b/src/rules/minimumhittingset_ilp.rs @@ -53,23 +53,11 @@ impl ReduceTo> for MinimumHittingSet { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; vec![crate::example_db::specs::RuleExampleSpec { id: "minimumhittingset_to_ilp", build: || { let source = MinimumHittingSet::new(4, vec![vec![0, 1], vec![2, 3], vec![1, 2]]); - let reduction = ReduceTo::>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/minimummultiwaycut_ilp.rs b/src/rules/minimummultiwaycut_ilp.rs index a54cdf1a4..62f442eaf 100644 --- a/src/rules/minimummultiwaycut_ilp.rs +++ b/src/rules/minimummultiwaycut_ilp.rs @@ -129,25 +129,12 @@ impl ReduceTo> for MinimumMultiwayCut { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - vec![crate::example_db::specs::RuleExampleSpec { id: "minimummultiwaycut_to_ilp", build: || { let graph = SimpleGraph::new(5, vec![(0, 1), (1, 2), (2, 3), (3, 4), (0, 4), (1, 3)]); let problem = MinimumMultiwayCut::new(graph, vec![0, 2, 4], vec![2, 3, 1, 2, 4, 5]); - let reduction = ReduceTo::>::reduce_to(&problem); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - problem, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(problem) }, }] } diff --git a/src/rules/minimumsetcovering_ilp.rs b/src/rules/minimumsetcovering_ilp.rs index 9c2431cab..be662bfac 100644 --- a/src/rules/minimumsetcovering_ilp.rs +++ b/src/rules/minimumsetcovering_ilp.rs @@ -83,9 +83,7 @@ impl ReduceTo> for MinimumSetCovering { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "minimumsetcovering_to_ilp", build: || { let source = MinimumSetCovering::new( @@ -99,18 +97,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/minimumsummulticenter_ilp.rs b/src/rules/minimumsummulticenter_ilp.rs index 715038e34..ab3b58352 100644 --- a/src/rules/minimumsummulticenter_ilp.rs +++ b/src/rules/minimumsummulticenter_ilp.rs @@ -186,9 +186,7 @@ impl ReduceTo> for MinimumSumMulticenter { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "minimumsummulticenter_to_ilp", build: || { // 3-vertex path: 0 - 1 - 2, unit weights, K=1 @@ -199,18 +197,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/minimumtardinesssequencing_ilp.rs b/src/rules/minimumtardinesssequencing_ilp.rs index 8d55c2087..4c6a22b62 100644 --- a/src/rules/minimumtardinesssequencing_ilp.rs +++ b/src/rules/minimumtardinesssequencing_ilp.rs @@ -103,24 +103,11 @@ impl ReduceTo> for MinimumTardinessSequencing { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "minimumtardinesssequencing_to_ilp", build: || { let source = MinimumTardinessSequencing::new(3, vec![2, 3, 1], vec![(0, 2)]); - let reduction = ReduceTo::>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/minmaxmulticenter_ilp.rs b/src/rules/minmaxmulticenter_ilp.rs index 33664a9d8..7af565f84 100644 --- a/src/rules/minmaxmulticenter_ilp.rs +++ b/src/rules/minmaxmulticenter_ilp.rs @@ -216,9 +216,7 @@ impl ReduceTo> for MinMaxMulticenter { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "minmaxmulticenter_to_ilp", build: || { // 3-vertex path: 0 - 1 - 2, unit weights/lengths, K=1 @@ -229,18 +227,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, i32>(source) }, }] } diff --git a/src/rules/mixedchinesepostman_ilp.rs b/src/rules/mixedchinesepostman_ilp.rs index 4a2ab2faf..35f15d31f 100644 --- a/src/rules/mixedchinesepostman_ilp.rs +++ b/src/rules/mixedchinesepostman_ilp.rs @@ -364,7 +364,6 @@ impl ReduceTo> for MixedChinesePostman { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; use crate::rules::ReduceTo as _; use crate::topology::MixedGraph; @@ -377,18 +376,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, i32>(source) }, }] } diff --git a/src/rules/multiplecopyfileallocation_ilp.rs b/src/rules/multiplecopyfileallocation_ilp.rs index 91f772ebb..877f550ed 100644 --- a/src/rules/multiplecopyfileallocation_ilp.rs +++ b/src/rules/multiplecopyfileallocation_ilp.rs @@ -141,9 +141,7 @@ impl ReduceTo> for MultipleCopyFileAllocation { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "multiplecopyfileallocation_to_ilp", build: || { // 3-vertex path: 0 - 1 - 2 @@ -155,18 +153,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/multiprocessorscheduling_ilp.rs b/src/rules/multiprocessorscheduling_ilp.rs index fce1c5031..fb4403c13 100644 --- a/src/rules/multiprocessorscheduling_ilp.rs +++ b/src/rules/multiprocessorscheduling_ilp.rs @@ -90,9 +90,7 @@ impl ReduceTo> for MultiprocessorScheduling { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "multiprocessorscheduling_to_ilp", build: || { // 3 tasks with lengths [4, 5, 3], 2 processors, deadline 7 @@ -101,18 +99,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/naesatisfiability_ilp.rs b/src/rules/naesatisfiability_ilp.rs index ecbdf19f8..382fa58f5 100644 --- a/src/rules/naesatisfiability_ilp.rs +++ b/src/rules/naesatisfiability_ilp.rs @@ -80,7 +80,6 @@ impl ReduceTo> for NAESatisfiability { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; use crate::models::formula::CNFClause; vec![crate::example_db::specs::RuleExampleSpec { id: "naesatisfiability_to_ilp", @@ -94,18 +93,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/optimallineararrangement_ilp.rs b/src/rules/optimallineararrangement_ilp.rs index 2028e151e..b84b4f7d7 100644 --- a/src/rules/optimallineararrangement_ilp.rs +++ b/src/rules/optimallineararrangement_ilp.rs @@ -133,25 +133,13 @@ impl ReduceTo> for OptimalLinearArrangement { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; vec![crate::example_db::specs::RuleExampleSpec { id: "optimallineararrangement_to_ilp", build: || { // Path P4: 0-1-2-3 (identity permutation achieves cost 3) let source = OptimalLinearArrangement::new(SimpleGraph::new(4, vec![(0, 1), (1, 2), (2, 3)])); - let reduction = ReduceTo::>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, i32>(source) }, }] } diff --git a/src/rules/partiallyorderedknapsack_ilp.rs b/src/rules/partiallyorderedknapsack_ilp.rs index 738931674..a8a4d4161 100644 --- a/src/rules/partiallyorderedknapsack_ilp.rs +++ b/src/rules/partiallyorderedknapsack_ilp.rs @@ -68,24 +68,12 @@ impl ReduceTo> for PartiallyOrderedKnapsack { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; vec![crate::example_db::specs::RuleExampleSpec { id: "partiallyorderedknapsack_to_ilp", build: || { let source = PartiallyOrderedKnapsack::new(vec![2, 3, 1], vec![3, 4, 2], vec![(0, 1)], 4); - let reduction = ReduceTo::>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/partitionintopathsoflength2_ilp.rs b/src/rules/partitionintopathsoflength2_ilp.rs index c85a6ce4f..5ba64c05c 100644 --- a/src/rules/partitionintopathsoflength2_ilp.rs +++ b/src/rules/partitionintopathsoflength2_ilp.rs @@ -128,9 +128,7 @@ impl ReduceTo> for PartitionIntoPathsOfLength2 { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "partitionintopathsoflength2_to_ilp", build: || { // Two P3 paths: 0-1-2 and 3-4-5 @@ -138,18 +136,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/partitionintotriangles_ilp.rs b/src/rules/partitionintotriangles_ilp.rs index 2e582bf27..ecb6d2228 100644 --- a/src/rules/partitionintotriangles_ilp.rs +++ b/src/rules/partitionintotriangles_ilp.rs @@ -108,9 +108,7 @@ impl ReduceTo> for PartitionIntoTriangles { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "partitionintotriangles_to_ilp", build: || { // Two triangles: 0-1-2 and 3-4-5 @@ -118,18 +116,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/pathconstrainednetworkflow_ilp.rs b/src/rules/pathconstrainednetworkflow_ilp.rs index 1243f1012..ce761eb79 100644 --- a/src/rules/pathconstrainednetworkflow_ilp.rs +++ b/src/rules/pathconstrainednetworkflow_ilp.rs @@ -70,7 +70,6 @@ impl ReduceTo> for PathConstrainedNetworkFlow { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; use crate::topology::DirectedGraph; vec![crate::example_db::specs::RuleExampleSpec { @@ -86,18 +85,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, i32>(source) }, }] } diff --git a/src/rules/precedenceconstrainedscheduling_ilp.rs b/src/rules/precedenceconstrainedscheduling_ilp.rs index 3b6d321ae..df834409a 100644 --- a/src/rules/precedenceconstrainedscheduling_ilp.rs +++ b/src/rules/precedenceconstrainedscheduling_ilp.rs @@ -103,25 +103,12 @@ impl ReduceTo> for PrecedenceConstrainedScheduling { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "precedenceconstrainedscheduling_to_ilp", build: || { // 3 tasks, 2 processors, deadline 2, with task 0 < task 2 let source = PrecedenceConstrainedScheduling::new(3, 2, 2, vec![(0, 2)]); - let reduction = ReduceTo::>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/quadraticassignment_ilp.rs b/src/rules/quadraticassignment_ilp.rs index 9a2c907a4..62a3c9916 100644 --- a/src/rules/quadraticassignment_ilp.rs +++ b/src/rules/quadraticassignment_ilp.rs @@ -116,7 +116,6 @@ impl ReduceTo> for QuadraticAssignment { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; vec![crate::example_db::specs::RuleExampleSpec { id: "quadraticassignment_to_ilp", build: || { @@ -125,18 +124,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/qubo_ilp.rs b/src/rules/qubo_ilp.rs index 5746df269..a54b14e5e 100644 --- a/src/rules/qubo_ilp.rs +++ b/src/rules/qubo_ilp.rs @@ -101,9 +101,7 @@ impl ReduceTo> for QUBO { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "qubo_to_ilp", build: || { let mut matrix = vec![vec![0.0; 4]; 4]; @@ -115,18 +113,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/rectilinearpicturecompression_ilp.rs b/src/rules/rectilinearpicturecompression_ilp.rs index 595dffa71..063eb3264 100644 --- a/src/rules/rectilinearpicturecompression_ilp.rs +++ b/src/rules/rectilinearpicturecompression_ilp.rs @@ -66,24 +66,12 @@ impl ReduceTo> for RectilinearPictureCompression { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; vec![crate::example_db::specs::RuleExampleSpec { id: "rectilinearpicturecompression_to_ilp", build: || { let source = RectilinearPictureCompression::new(vec![vec![true, true], vec![true, true]], 1); - let reduction = ReduceTo::>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/resourceconstrainedscheduling_ilp.rs b/src/rules/resourceconstrainedscheduling_ilp.rs index 28f6ffb34..7ef80c1b5 100644 --- a/src/rules/resourceconstrainedscheduling_ilp.rs +++ b/src/rules/resourceconstrainedscheduling_ilp.rs @@ -94,9 +94,7 @@ impl ReduceTo> for ResourceConstrainedScheduling { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "resourceconstrainedscheduling_to_ilp", build: || { // 6 tasks, 3 processors, 1 resource with bound 20, deadline 2 @@ -106,18 +104,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/ruralpostman_ilp.rs b/src/rules/ruralpostman_ilp.rs index be40963e0..905a1b470 100644 --- a/src/rules/ruralpostman_ilp.rs +++ b/src/rules/ruralpostman_ilp.rs @@ -215,7 +215,6 @@ impl ReduceTo> for RuralPostman { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; use crate::rules::ReduceTo as _; vec![crate::example_db::specs::RuleExampleSpec { @@ -227,18 +226,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, i32>(source) }, }] } diff --git a/src/rules/schedulingwithindividualdeadlines_ilp.rs b/src/rules/schedulingwithindividualdeadlines_ilp.rs index 42719d9e0..c3b797805 100644 --- a/src/rules/schedulingwithindividualdeadlines_ilp.rs +++ b/src/rules/schedulingwithindividualdeadlines_ilp.rs @@ -106,25 +106,12 @@ impl ReduceTo> for SchedulingWithIndividualDeadlines { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "schedulingwithindividualdeadlines_to_ilp", build: || { // 3 tasks, 2 processors, deadlines [2, 2, 3], precedence (0, 2) let source = SchedulingWithIndividualDeadlines::new(3, 2, vec![2, 2, 3], vec![(0, 2)]); - let reduction = ReduceTo::>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/sequencingtominimizemaximumcumulativecost_ilp.rs b/src/rules/sequencingtominimizemaximumcumulativecost_ilp.rs index 7e6e59fff..42026dc63 100644 --- a/src/rules/sequencingtominimizemaximumcumulativecost_ilp.rs +++ b/src/rules/sequencingtominimizemaximumcumulativecost_ilp.rs @@ -114,25 +114,12 @@ impl ReduceTo> for SequencingToMinimizeMaximumCumulativeCost { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "sequencingtominimizemaximumcumulativecost_to_ilp", build: || { let source = SequencingToMinimizeMaximumCumulativeCost::new(vec![2, -1, 3, -2], vec![(0, 2)]); - let reduction = ReduceTo::>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, i32>(source) }, }] } diff --git a/src/rules/sequencingtominimizeweightedcompletiontime_ilp.rs b/src/rules/sequencingtominimizeweightedcompletiontime_ilp.rs index 0b6d4f251..0e82829f3 100644 --- a/src/rules/sequencingtominimizeweightedcompletiontime_ilp.rs +++ b/src/rules/sequencingtominimizeweightedcompletiontime_ilp.rs @@ -165,24 +165,11 @@ impl ReduceTo> for SequencingToMinimizeWeightedCompletionTime { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "sequencingtominimizeweightedcompletiontime_to_ilp", build: || { let source = SequencingToMinimizeWeightedCompletionTime::new(vec![2, 1], vec![3, 5], vec![]); - let reduction = ReduceTo::>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, i32>(source) }, }] } diff --git a/src/rules/sequencingtominimizeweightedtardiness_ilp.rs b/src/rules/sequencingtominimizeweightedtardiness_ilp.rs index 38b655ed8..09c380108 100644 --- a/src/rules/sequencingtominimizeweightedtardiness_ilp.rs +++ b/src/rules/sequencingtominimizeweightedtardiness_ilp.rs @@ -153,9 +153,7 @@ impl ReduceTo> for SequencingToMinimizeWeightedTardiness { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "sequencingtominimizeweightedtardiness_to_ilp", build: || { let source = SequencingToMinimizeWeightedTardiness::new( @@ -164,18 +162,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, i32>(source) }, }] } diff --git a/src/rules/sequencingwithreleasetimesanddeadlines_ilp.rs b/src/rules/sequencingwithreleasetimesanddeadlines_ilp.rs index 61f43d22e..98362166d 100644 --- a/src/rules/sequencingwithreleasetimesanddeadlines_ilp.rs +++ b/src/rules/sequencingwithreleasetimesanddeadlines_ilp.rs @@ -139,9 +139,7 @@ impl ReduceTo> for SequencingWithReleaseTimesAndDeadlines { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "sequencingwithreleasetimesanddeadlines_to_ilp", build: || { let source = SequencingWithReleaseTimesAndDeadlines::new( @@ -149,18 +147,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/shortestweightconstrainedpath_ilp.rs b/src/rules/shortestweightconstrainedpath_ilp.rs index 8768f3286..de61cae44 100644 --- a/src/rules/shortestweightconstrainedpath_ilp.rs +++ b/src/rules/shortestweightconstrainedpath_ilp.rs @@ -214,9 +214,7 @@ impl ReduceTo> for ShortestWeightConstrainedPath { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "shortestweightconstrainedpath_to_ilp", build: || { // 3-vertex path: 0 -- 1 -- 2, s=0, t=2 @@ -231,18 +229,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, i32>(source) }, }] } diff --git a/src/rules/stackercrane_ilp.rs b/src/rules/stackercrane_ilp.rs index 092c185db..830567f62 100644 --- a/src/rules/stackercrane_ilp.rs +++ b/src/rules/stackercrane_ilp.rs @@ -200,7 +200,6 @@ fn all_pairs_shortest_paths( #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; use crate::rules::ReduceTo as _; vec![crate::example_db::specs::RuleExampleSpec { @@ -209,18 +208,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/steinertree_ilp.rs b/src/rules/steinertree_ilp.rs index eefa62c66..79539cf21 100644 --- a/src/rules/steinertree_ilp.rs +++ b/src/rules/steinertree_ilp.rs @@ -124,9 +124,7 @@ impl ReduceTo> for SteinerTree { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "steinertree_to_ilp", build: || { let source = SteinerTree::new( @@ -137,18 +135,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/steinertreeingraphs_ilp.rs b/src/rules/steinertreeingraphs_ilp.rs index 467c8c0f3..55aab30f9 100644 --- a/src/rules/steinertreeingraphs_ilp.rs +++ b/src/rules/steinertreeingraphs_ilp.rs @@ -126,7 +126,6 @@ impl ReduceTo> for SteinerTreeInGraphs { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; use crate::rules::ReduceTo as _; vec![crate::example_db::specs::RuleExampleSpec { @@ -139,18 +138,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/subgraphisomorphism_ilp.rs b/src/rules/subgraphisomorphism_ilp.rs index 0dba403e2..6868197ea 100644 --- a/src/rules/subgraphisomorphism_ilp.rs +++ b/src/rules/subgraphisomorphism_ilp.rs @@ -101,7 +101,6 @@ impl ReduceTo> for SubgraphIsomorphism { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; use crate::topology::SimpleGraph; vec![crate::example_db::specs::RuleExampleSpec { id: "subgraphisomorphism_to_ilp", @@ -110,18 +109,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/sumofsquarespartition_ilp.rs b/src/rules/sumofsquarespartition_ilp.rs index 296aacf5c..f92825cc4 100644 --- a/src/rules/sumofsquarespartition_ilp.rs +++ b/src/rules/sumofsquarespartition_ilp.rs @@ -146,26 +146,13 @@ impl ReduceTo> for SumOfSquaresPartition { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "sumofsquarespartition_to_ilp", build: || { // 4 elements [1, 2, 3, 4], K=2 groups // Group {1,4}: sum=5, Group {2,3}: sum=5 → sos = 25+25 = 50 let source = SumOfSquaresPartition::new(vec![1, 2, 3, 4], 2); - let reduction = ReduceTo::>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/timetabledesign_ilp.rs b/src/rules/timetabledesign_ilp.rs index 4cbb3f385..3d46cdea5 100644 --- a/src/rules/timetabledesign_ilp.rs +++ b/src/rules/timetabledesign_ilp.rs @@ -96,9 +96,7 @@ impl ReduceTo> for TimetableDesign { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "timetabledesign_to_ilp", build: || { // Small 2-craftsman, 2-task, 2-period instance @@ -110,18 +108,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/travelingsalesman_ilp.rs b/src/rules/travelingsalesman_ilp.rs index 69a399bb7..95c03e629 100644 --- a/src/rules/travelingsalesman_ilp.rs +++ b/src/rules/travelingsalesman_ilp.rs @@ -198,27 +198,14 @@ impl ReduceTo> for TravelingSalesman { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; - - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "travelingsalesman_to_ilp", build: || { let source = TravelingSalesman::new( SimpleGraph::new(4, vec![(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]), vec![10, 15, 20, 35, 25, 30], ); - let reduction = ReduceTo::>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, bool>(source) }, }] } diff --git a/src/rules/undirectedflowlowerbounds_ilp.rs b/src/rules/undirectedflowlowerbounds_ilp.rs index 57af077c1..7c666abca 100644 --- a/src/rules/undirectedflowlowerbounds_ilp.rs +++ b/src/rules/undirectedflowlowerbounds_ilp.rs @@ -167,7 +167,6 @@ impl ReduceTo> for UndirectedFlowLowerBounds { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::export::SolutionPair; use crate::topology::SimpleGraph; vec![crate::example_db::specs::RuleExampleSpec { @@ -183,18 +182,7 @@ pub(crate) fn canonical_rule_example_specs() -> Vec>::reduce_to(&source); - let ilp_solution = crate::solvers::ILPSolver::new() - .solve(reduction.target_problem()) - .expect("canonical example must be solvable"); - let source_config = reduction.extract_solution(&ilp_solution); - crate::example_db::specs::rule_example_with_witness::<_, ILP>( - source, - SolutionPair { - source_config, - target_config: ilp_solution, - }, - ) + crate::example_db::specs::rule_example_via_ilp::<_, i32>(source) }, }] } From 49fc30f327c383d1db77da5d6e164e176542339f Mon Sep 17 00:00:00 2001 From: zazabap Date: Thu, 26 Mar 2026 09:41:06 +0000 Subject: [PATCH 3/3] fix: address PR #775 review comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix indentation in ~32 canonical_rule_example_specs functions (cargo fmt) - Fix incorrect overhead in minmaxmulticenter_ilp: num_constraints formula was 2n²+4n+2, correct is 2n²+3n+2 (matching actual constraint count: 1 cardinality + n assignment + n² link + n x-bounds + n² y-bounds + 1 z-bound + n minimax) - Fix Vec::with_capacity hint to match corrected formula - Remove 6 unused `use crate::rules::ReduceTo as _;` imports in files that switched to rule_example_via_ilp Co-Authored-By: Claude Opus 4.6 (1M context) --- src/rules/capacityassignment_ilp.rs | 2 +- src/rules/disjointconnectingpaths_ilp.rs | 2 -- src/rules/factoring_ilp.rs | 2 +- src/rules/flowshopscheduling_ilp.rs | 2 +- src/rules/integralflowbundles_ilp.rs | 14 +++++++------- src/rules/lengthboundeddisjointpaths_ilp.rs | 2 -- src/rules/longestcommonsubsequence_ilp.rs | 2 +- src/rules/longestpath_ilp.rs | 5 +++-- src/rules/maximumclique_ilp.rs | 2 +- src/rules/maximummatching_ilp.rs | 2 +- src/rules/maximumsetpacking_ilp.rs | 2 +- src/rules/minimumdominatingset_ilp.rs | 2 +- src/rules/minimumsetcovering_ilp.rs | 2 +- src/rules/minimumsummulticenter_ilp.rs | 2 +- src/rules/minimumtardinesssequencing_ilp.rs | 2 +- src/rules/minmaxmulticenter_ilp.rs | 11 +++++------ src/rules/mixedchinesepostman_ilp.rs | 1 - src/rules/multiplecopyfileallocation_ilp.rs | 2 +- src/rules/multiprocessorscheduling_ilp.rs | 2 +- src/rules/partitionintopathsoflength2_ilp.rs | 2 +- src/rules/partitionintotriangles_ilp.rs | 2 +- src/rules/precedenceconstrainedscheduling_ilp.rs | 2 +- src/rules/qubo_ilp.rs | 2 +- src/rules/resourceconstrainedscheduling_ilp.rs | 2 +- src/rules/ruralpostman_ilp.rs | 2 -- src/rules/schedulingwithindividualdeadlines_ilp.rs | 2 +- ...equencingtominimizemaximumcumulativecost_ilp.rs | 2 +- ...quencingtominimizeweightedcompletiontime_ilp.rs | 5 +++-- .../sequencingtominimizeweightedtardiness_ilp.rs | 2 +- .../sequencingwithreleasetimesanddeadlines_ilp.rs | 2 +- src/rules/shortestweightconstrainedpath_ilp.rs | 2 +- src/rules/stackercrane_ilp.rs | 2 -- src/rules/steinertree_ilp.rs | 2 +- src/rules/steinertreeingraphs_ilp.rs | 2 -- src/rules/sumofsquarespartition_ilp.rs | 2 +- src/rules/timetabledesign_ilp.rs | 2 +- src/rules/travelingsalesman_ilp.rs | 2 +- 37 files changed, 45 insertions(+), 55 deletions(-) diff --git a/src/rules/capacityassignment_ilp.rs b/src/rules/capacityassignment_ilp.rs index 33946a7bc..798646c85 100644 --- a/src/rules/capacityassignment_ilp.rs +++ b/src/rules/capacityassignment_ilp.rs @@ -101,7 +101,7 @@ impl ReduceTo> for CapacityAssignment { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "capacityassignment_to_ilp", build: || { // 2 links, 2 capacity levels diff --git a/src/rules/disjointconnectingpaths_ilp.rs b/src/rules/disjointconnectingpaths_ilp.rs index 089c8079b..1c4b7f5df 100644 --- a/src/rules/disjointconnectingpaths_ilp.rs +++ b/src/rules/disjointconnectingpaths_ilp.rs @@ -170,8 +170,6 @@ impl ReduceTo> for DisjointConnectingPaths { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::rules::ReduceTo as _; - vec![crate::example_db::specs::RuleExampleSpec { id: "disjointconnectingpaths_to_ilp", build: || { diff --git a/src/rules/factoring_ilp.rs b/src/rules/factoring_ilp.rs index a3cbb0ac7..a3bffb0e9 100644 --- a/src/rules/factoring_ilp.rs +++ b/src/rules/factoring_ilp.rs @@ -223,7 +223,7 @@ impl ReduceTo> for Factoring { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "factoring_to_ilp", build: || { let source = Factoring::new(3, 3, 35); diff --git a/src/rules/flowshopscheduling_ilp.rs b/src/rules/flowshopscheduling_ilp.rs index 86a6d19fd..7f15251e2 100644 --- a/src/rules/flowshopscheduling_ilp.rs +++ b/src/rules/flowshopscheduling_ilp.rs @@ -207,7 +207,7 @@ impl ReduceTo> for FlowShopScheduling { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "flowshopscheduling_to_ilp", build: || { // 2 machines, 3 jobs, deadline 10 diff --git a/src/rules/integralflowbundles_ilp.rs b/src/rules/integralflowbundles_ilp.rs index be01dd299..ad423ec32 100644 --- a/src/rules/integralflowbundles_ilp.rs +++ b/src/rules/integralflowbundles_ilp.rs @@ -93,13 +93,13 @@ pub(crate) fn canonical_rule_example_specs() -> Vec(source) }, }] diff --git a/src/rules/lengthboundeddisjointpaths_ilp.rs b/src/rules/lengthboundeddisjointpaths_ilp.rs index d0298ceaa..08eaadc37 100644 --- a/src/rules/lengthboundeddisjointpaths_ilp.rs +++ b/src/rules/lengthboundeddisjointpaths_ilp.rs @@ -199,8 +199,6 @@ impl ReduceTo> for LengthBoundedDisjointPaths { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::rules::ReduceTo as _; - vec![crate::example_db::specs::RuleExampleSpec { id: "lengthboundeddisjointpaths_to_ilp", build: || { diff --git a/src/rules/longestcommonsubsequence_ilp.rs b/src/rules/longestcommonsubsequence_ilp.rs index 4f4566fad..565305fc2 100644 --- a/src/rules/longestcommonsubsequence_ilp.rs +++ b/src/rules/longestcommonsubsequence_ilp.rs @@ -162,7 +162,7 @@ impl ReduceTo> for LongestCommonSubsequence { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "longestcommonsubsequence_to_ilp", build: || { // Source: alphabet {0,1,2}, strings [0,1,2] and [1,0,2], max_length = 3 diff --git a/src/rules/longestpath_ilp.rs b/src/rules/longestpath_ilp.rs index 3f7e81114..7c43a1a74 100644 --- a/src/rules/longestpath_ilp.rs +++ b/src/rules/longestpath_ilp.rs @@ -175,10 +175,11 @@ impl ReduceTo> for LongestPath { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "longestpath_to_ilp", build: || { - let source = LongestPath::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![2, 3], 0, 2); + let source = + LongestPath::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![2, 3], 0, 2); crate::example_db::specs::rule_example_via_ilp::<_, i32>(source) }, }] diff --git a/src/rules/maximumclique_ilp.rs b/src/rules/maximumclique_ilp.rs index 6c3064490..c0ac43130 100644 --- a/src/rules/maximumclique_ilp.rs +++ b/src/rules/maximumclique_ilp.rs @@ -80,7 +80,7 @@ impl ReduceTo> for MaximumClique { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "maximumclique_to_ilp", build: || { let (n, edges) = crate::topology::small_graphs::octahedral(); diff --git a/src/rules/maximummatching_ilp.rs b/src/rules/maximummatching_ilp.rs index 9d0944ee8..329a104d5 100644 --- a/src/rules/maximummatching_ilp.rs +++ b/src/rules/maximummatching_ilp.rs @@ -80,7 +80,7 @@ impl ReduceTo> for MaximumMatching { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "maximummatching_to_ilp", build: || { let (n, edges) = crate::topology::small_graphs::petersen(); diff --git a/src/rules/maximumsetpacking_ilp.rs b/src/rules/maximumsetpacking_ilp.rs index 50791bc5c..7ccd7de47 100644 --- a/src/rules/maximumsetpacking_ilp.rs +++ b/src/rules/maximumsetpacking_ilp.rs @@ -79,7 +79,7 @@ impl ReduceTo> for MaximumSetPacking { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "maximumsetpacking_to_ilp", build: || { let source = MaximumSetPacking::new(vec![ diff --git a/src/rules/minimumdominatingset_ilp.rs b/src/rules/minimumdominatingset_ilp.rs index 3febfae71..7aa9933c0 100644 --- a/src/rules/minimumdominatingset_ilp.rs +++ b/src/rules/minimumdominatingset_ilp.rs @@ -82,7 +82,7 @@ impl ReduceTo> for MinimumDominatingSet { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "minimumdominatingset_to_ilp", build: || { let (n, edges) = crate::topology::small_graphs::petersen(); diff --git a/src/rules/minimumsetcovering_ilp.rs b/src/rules/minimumsetcovering_ilp.rs index be662bfac..7befcbaca 100644 --- a/src/rules/minimumsetcovering_ilp.rs +++ b/src/rules/minimumsetcovering_ilp.rs @@ -83,7 +83,7 @@ impl ReduceTo> for MinimumSetCovering { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "minimumsetcovering_to_ilp", build: || { let source = MinimumSetCovering::new( diff --git a/src/rules/minimumsummulticenter_ilp.rs b/src/rules/minimumsummulticenter_ilp.rs index ab3b58352..976f1a387 100644 --- a/src/rules/minimumsummulticenter_ilp.rs +++ b/src/rules/minimumsummulticenter_ilp.rs @@ -186,7 +186,7 @@ impl ReduceTo> for MinimumSumMulticenter { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "minimumsummulticenter_to_ilp", build: || { // 3-vertex path: 0 - 1 - 2, unit weights, K=1 diff --git a/src/rules/minimumtardinesssequencing_ilp.rs b/src/rules/minimumtardinesssequencing_ilp.rs index 4c6a22b62..8d976e358 100644 --- a/src/rules/minimumtardinesssequencing_ilp.rs +++ b/src/rules/minimumtardinesssequencing_ilp.rs @@ -103,7 +103,7 @@ impl ReduceTo> for MinimumTardinessSequencing { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "minimumtardinesssequencing_to_ilp", build: || { let source = MinimumTardinessSequencing::new(3, vec![2, 3, 1], vec![(0, 2)]); diff --git a/src/rules/minmaxmulticenter_ilp.rs b/src/rules/minmaxmulticenter_ilp.rs index 7af565f84..0e475e6a3 100644 --- a/src/rules/minmaxmulticenter_ilp.rs +++ b/src/rules/minmaxmulticenter_ilp.rs @@ -116,7 +116,7 @@ fn weighted_distances_mmc( #[reduction( overhead = { num_vars = "num_vertices + num_vertices^2 + 1", - num_constraints = "2 * num_vertices^2 + 4 * num_vertices + 2", + num_constraints = "2 * num_vertices^2 + 3 * num_vertices + 2", } )] impl ReduceTo> for MinMaxMulticenter { @@ -139,7 +139,7 @@ impl ReduceTo> for MinMaxMulticenter { let z_var = n + n * n; let num_vars = n + n * n + 1; - let mut constraints = Vec::with_capacity(2 * n * n + 4 * n + 1); + let mut constraints = Vec::with_capacity(2 * n * n + 3 * n + 2); // Cardinality constraint: Σ_j x_j = k let center_terms: Vec<(usize, f64)> = (0..n).map(|j| (x_var(j), 1.0)).collect(); @@ -182,9 +182,8 @@ impl ReduceTo> for MinMaxMulticenter { .iter() .enumerate() .flat_map(|(i, row)| { - row.iter().filter_map(move |d| { - d.map(|d| (vertex_weights[i] as f64) * (d as f64)) - }) + row.iter() + .filter_map(move |d| d.map(|d| (vertex_weights[i] as f64) * (d as f64))) }) .fold(0.0_f64, f64::max); constraints.push(LinearConstraint::le(vec![(z_var, 1.0)], z_upper)); @@ -216,7 +215,7 @@ impl ReduceTo> for MinMaxMulticenter { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "minmaxmulticenter_to_ilp", build: || { // 3-vertex path: 0 - 1 - 2, unit weights/lengths, K=1 diff --git a/src/rules/mixedchinesepostman_ilp.rs b/src/rules/mixedchinesepostman_ilp.rs index 35f15d31f..ded42a6fb 100644 --- a/src/rules/mixedchinesepostman_ilp.rs +++ b/src/rules/mixedchinesepostman_ilp.rs @@ -364,7 +364,6 @@ impl ReduceTo> for MixedChinesePostman { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::rules::ReduceTo as _; use crate::topology::MixedGraph; vec![crate::example_db::specs::RuleExampleSpec { diff --git a/src/rules/multiplecopyfileallocation_ilp.rs b/src/rules/multiplecopyfileallocation_ilp.rs index 877f550ed..1852fb2a6 100644 --- a/src/rules/multiplecopyfileallocation_ilp.rs +++ b/src/rules/multiplecopyfileallocation_ilp.rs @@ -141,7 +141,7 @@ impl ReduceTo> for MultipleCopyFileAllocation { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "multiplecopyfileallocation_to_ilp", build: || { // 3-vertex path: 0 - 1 - 2 diff --git a/src/rules/multiprocessorscheduling_ilp.rs b/src/rules/multiprocessorscheduling_ilp.rs index fb4403c13..f96d7ff4d 100644 --- a/src/rules/multiprocessorscheduling_ilp.rs +++ b/src/rules/multiprocessorscheduling_ilp.rs @@ -90,7 +90,7 @@ impl ReduceTo> for MultiprocessorScheduling { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "multiprocessorscheduling_to_ilp", build: || { // 3 tasks with lengths [4, 5, 3], 2 processors, deadline 7 diff --git a/src/rules/partitionintopathsoflength2_ilp.rs b/src/rules/partitionintopathsoflength2_ilp.rs index 5ba64c05c..2e3c3ccc6 100644 --- a/src/rules/partitionintopathsoflength2_ilp.rs +++ b/src/rules/partitionintopathsoflength2_ilp.rs @@ -128,7 +128,7 @@ impl ReduceTo> for PartitionIntoPathsOfLength2 { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "partitionintopathsoflength2_to_ilp", build: || { // Two P3 paths: 0-1-2 and 3-4-5 diff --git a/src/rules/partitionintotriangles_ilp.rs b/src/rules/partitionintotriangles_ilp.rs index ecb6d2228..18d32c5ca 100644 --- a/src/rules/partitionintotriangles_ilp.rs +++ b/src/rules/partitionintotriangles_ilp.rs @@ -108,7 +108,7 @@ impl ReduceTo> for PartitionIntoTriangles { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "partitionintotriangles_to_ilp", build: || { // Two triangles: 0-1-2 and 3-4-5 diff --git a/src/rules/precedenceconstrainedscheduling_ilp.rs b/src/rules/precedenceconstrainedscheduling_ilp.rs index df834409a..d464cc2a6 100644 --- a/src/rules/precedenceconstrainedscheduling_ilp.rs +++ b/src/rules/precedenceconstrainedscheduling_ilp.rs @@ -103,7 +103,7 @@ impl ReduceTo> for PrecedenceConstrainedScheduling { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "precedenceconstrainedscheduling_to_ilp", build: || { // 3 tasks, 2 processors, deadline 2, with task 0 < task 2 diff --git a/src/rules/qubo_ilp.rs b/src/rules/qubo_ilp.rs index a54b14e5e..249df5886 100644 --- a/src/rules/qubo_ilp.rs +++ b/src/rules/qubo_ilp.rs @@ -101,7 +101,7 @@ impl ReduceTo> for QUBO { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "qubo_to_ilp", build: || { let mut matrix = vec![vec![0.0; 4]; 4]; diff --git a/src/rules/resourceconstrainedscheduling_ilp.rs b/src/rules/resourceconstrainedscheduling_ilp.rs index 7ef80c1b5..61e2037bb 100644 --- a/src/rules/resourceconstrainedscheduling_ilp.rs +++ b/src/rules/resourceconstrainedscheduling_ilp.rs @@ -94,7 +94,7 @@ impl ReduceTo> for ResourceConstrainedScheduling { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "resourceconstrainedscheduling_to_ilp", build: || { // 6 tasks, 3 processors, 1 resource with bound 20, deadline 2 diff --git a/src/rules/ruralpostman_ilp.rs b/src/rules/ruralpostman_ilp.rs index 905a1b470..cc5ba5758 100644 --- a/src/rules/ruralpostman_ilp.rs +++ b/src/rules/ruralpostman_ilp.rs @@ -215,8 +215,6 @@ impl ReduceTo> for RuralPostman { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::rules::ReduceTo as _; - vec![crate::example_db::specs::RuleExampleSpec { id: "ruralpostman_to_ilp", build: || { diff --git a/src/rules/schedulingwithindividualdeadlines_ilp.rs b/src/rules/schedulingwithindividualdeadlines_ilp.rs index c3b797805..80f0745cd 100644 --- a/src/rules/schedulingwithindividualdeadlines_ilp.rs +++ b/src/rules/schedulingwithindividualdeadlines_ilp.rs @@ -106,7 +106,7 @@ impl ReduceTo> for SchedulingWithIndividualDeadlines { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "schedulingwithindividualdeadlines_to_ilp", build: || { // 3 tasks, 2 processors, deadlines [2, 2, 3], precedence (0, 2) diff --git a/src/rules/sequencingtominimizemaximumcumulativecost_ilp.rs b/src/rules/sequencingtominimizemaximumcumulativecost_ilp.rs index 42026dc63..dd5f4ab7d 100644 --- a/src/rules/sequencingtominimizemaximumcumulativecost_ilp.rs +++ b/src/rules/sequencingtominimizemaximumcumulativecost_ilp.rs @@ -114,7 +114,7 @@ impl ReduceTo> for SequencingToMinimizeMaximumCumulativeCost { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "sequencingtominimizemaximumcumulativecost_to_ilp", build: || { let source = diff --git a/src/rules/sequencingtominimizeweightedcompletiontime_ilp.rs b/src/rules/sequencingtominimizeweightedcompletiontime_ilp.rs index 0e82829f3..ba157bffe 100644 --- a/src/rules/sequencingtominimizeweightedcompletiontime_ilp.rs +++ b/src/rules/sequencingtominimizeweightedcompletiontime_ilp.rs @@ -165,10 +165,11 @@ impl ReduceTo> for SequencingToMinimizeWeightedCompletionTime { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "sequencingtominimizeweightedcompletiontime_to_ilp", build: || { - let source = SequencingToMinimizeWeightedCompletionTime::new(vec![2, 1], vec![3, 5], vec![]); + let source = + SequencingToMinimizeWeightedCompletionTime::new(vec![2, 1], vec![3, 5], vec![]); crate::example_db::specs::rule_example_via_ilp::<_, i32>(source) }, }] diff --git a/src/rules/sequencingtominimizeweightedtardiness_ilp.rs b/src/rules/sequencingtominimizeweightedtardiness_ilp.rs index 09c380108..aab00740d 100644 --- a/src/rules/sequencingtominimizeweightedtardiness_ilp.rs +++ b/src/rules/sequencingtominimizeweightedtardiness_ilp.rs @@ -153,7 +153,7 @@ impl ReduceTo> for SequencingToMinimizeWeightedTardiness { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "sequencingtominimizeweightedtardiness_to_ilp", build: || { let source = SequencingToMinimizeWeightedTardiness::new( diff --git a/src/rules/sequencingwithreleasetimesanddeadlines_ilp.rs b/src/rules/sequencingwithreleasetimesanddeadlines_ilp.rs index 98362166d..cbcbadce0 100644 --- a/src/rules/sequencingwithreleasetimesanddeadlines_ilp.rs +++ b/src/rules/sequencingwithreleasetimesanddeadlines_ilp.rs @@ -139,7 +139,7 @@ impl ReduceTo> for SequencingWithReleaseTimesAndDeadlines { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "sequencingwithreleasetimesanddeadlines_to_ilp", build: || { let source = SequencingWithReleaseTimesAndDeadlines::new( diff --git a/src/rules/shortestweightconstrainedpath_ilp.rs b/src/rules/shortestweightconstrainedpath_ilp.rs index de61cae44..9a7b92c44 100644 --- a/src/rules/shortestweightconstrainedpath_ilp.rs +++ b/src/rules/shortestweightconstrainedpath_ilp.rs @@ -214,7 +214,7 @@ impl ReduceTo> for ShortestWeightConstrainedPath { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "shortestweightconstrainedpath_to_ilp", build: || { // 3-vertex path: 0 -- 1 -- 2, s=0, t=2 diff --git a/src/rules/stackercrane_ilp.rs b/src/rules/stackercrane_ilp.rs index 830567f62..5dbbd3ad0 100644 --- a/src/rules/stackercrane_ilp.rs +++ b/src/rules/stackercrane_ilp.rs @@ -200,8 +200,6 @@ fn all_pairs_shortest_paths( #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::rules::ReduceTo as _; - vec![crate::example_db::specs::RuleExampleSpec { id: "stackercrane_to_ilp", build: || { diff --git a/src/rules/steinertree_ilp.rs b/src/rules/steinertree_ilp.rs index 79539cf21..f9c77eb30 100644 --- a/src/rules/steinertree_ilp.rs +++ b/src/rules/steinertree_ilp.rs @@ -124,7 +124,7 @@ impl ReduceTo> for SteinerTree { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "steinertree_to_ilp", build: || { let source = SteinerTree::new( diff --git a/src/rules/steinertreeingraphs_ilp.rs b/src/rules/steinertreeingraphs_ilp.rs index 55aab30f9..def751b4b 100644 --- a/src/rules/steinertreeingraphs_ilp.rs +++ b/src/rules/steinertreeingraphs_ilp.rs @@ -126,8 +126,6 @@ impl ReduceTo> for SteinerTreeInGraphs { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - use crate::rules::ReduceTo as _; - vec![crate::example_db::specs::RuleExampleSpec { id: "steinertreeingraphs_to_ilp", build: || { diff --git a/src/rules/sumofsquarespartition_ilp.rs b/src/rules/sumofsquarespartition_ilp.rs index f92825cc4..de6b8e02a 100644 --- a/src/rules/sumofsquarespartition_ilp.rs +++ b/src/rules/sumofsquarespartition_ilp.rs @@ -146,7 +146,7 @@ impl ReduceTo> for SumOfSquaresPartition { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "sumofsquarespartition_to_ilp", build: || { // 4 elements [1, 2, 3, 4], K=2 groups diff --git a/src/rules/timetabledesign_ilp.rs b/src/rules/timetabledesign_ilp.rs index 3d46cdea5..f235918e5 100644 --- a/src/rules/timetabledesign_ilp.rs +++ b/src/rules/timetabledesign_ilp.rs @@ -96,7 +96,7 @@ impl ReduceTo> for TimetableDesign { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "timetabledesign_to_ilp", build: || { // Small 2-craftsman, 2-task, 2-period instance diff --git a/src/rules/travelingsalesman_ilp.rs b/src/rules/travelingsalesman_ilp.rs index 95c03e629..e84d9d1f9 100644 --- a/src/rules/travelingsalesman_ilp.rs +++ b/src/rules/travelingsalesman_ilp.rs @@ -198,7 +198,7 @@ impl ReduceTo> for TravelingSalesman { #[cfg(feature = "example-db")] pub(crate) fn canonical_rule_example_specs() -> Vec { - vec![crate::example_db::specs::RuleExampleSpec { + vec![crate::example_db::specs::RuleExampleSpec { id: "travelingsalesman_to_ilp", build: || { let source = TravelingSalesman::new(