problemreductions/rules/
optimallineararrangement_sequencingtominimizeweightedcompletiontime.rs1use crate::models::graph::OptimalLinearArrangement;
15use crate::models::misc::SequencingToMinimizeWeightedCompletionTime;
16use crate::reduction;
17use crate::rules::traits::{ReduceTo, ReductionResult};
18use crate::topology::{Graph, SimpleGraph};
19
20#[derive(Debug, Clone)]
22pub struct ReductionOLAToSequencingToMinimizeWeightedCompletionTime {
23 target: SequencingToMinimizeWeightedCompletionTime,
24 num_vertices: usize,
25}
26
27impl ReductionResult for ReductionOLAToSequencingToMinimizeWeightedCompletionTime {
28 type Source = OptimalLinearArrangement<SimpleGraph>;
29 type Target = SequencingToMinimizeWeightedCompletionTime;
30
31 fn target_problem(&self) -> &Self::Target {
32 &self.target
33 }
34
35 fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> {
36 let schedule = crate::models::misc::decode_lehmer(target_solution, self.target.num_tasks())
37 .expect("target solution must be a valid Lehmer code");
38 let mut arrangement = vec![0usize; self.num_vertices];
39 let mut next_position = 0usize;
40
41 for task in schedule {
42 if task < self.num_vertices {
43 arrangement[task] = next_position;
44 next_position += 1;
45 }
46 }
47
48 arrangement
49 }
50}
51
52#[reduction(overhead = {
53 num_tasks = "num_vertices + num_edges",
54})]
55impl ReduceTo<SequencingToMinimizeWeightedCompletionTime>
56 for OptimalLinearArrangement<SimpleGraph>
57{
58 type Result = ReductionOLAToSequencingToMinimizeWeightedCompletionTime;
59
60 fn reduce_to(&self) -> Self::Result {
61 let graph = self.graph();
62 let num_vertices = graph.num_vertices();
63 let edges = graph.edges();
64 let max_degree = (0..num_vertices)
65 .map(|v| graph.degree(v))
66 .max()
67 .unwrap_or(0) as u64;
68
69 let mut lengths = Vec::with_capacity(num_vertices + edges.len());
70 let mut weights = Vec::with_capacity(num_vertices + edges.len());
71 let mut precedences = Vec::with_capacity(2 * edges.len());
72
73 for vertex in 0..num_vertices {
74 lengths.push(1);
75 weights.push(max_degree - graph.degree(vertex) as u64);
76 }
77
78 for (edge_index, &(u, v)) in edges.iter().enumerate() {
79 let edge_task = num_vertices + edge_index;
80 lengths.push(0);
81 weights.push(2);
82 precedences.push((u, edge_task));
83 precedences.push((v, edge_task));
84 }
85
86 ReductionOLAToSequencingToMinimizeWeightedCompletionTime {
87 target: SequencingToMinimizeWeightedCompletionTime::new(lengths, weights, precedences),
88 num_vertices,
89 }
90 }
91}
92
93#[cfg(feature = "example-db")]
94pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
95 use crate::example_db::specs::assemble_rule_example;
96 use crate::export::SolutionPair;
97 use crate::solvers::BruteForce;
98
99 vec![crate::example_db::specs::RuleExampleSpec {
100 id: "optimallineararrangement_to_sequencingtominimizeweightedcompletiontime",
101 build: || {
102 let source =
103 OptimalLinearArrangement::new(SimpleGraph::new(4, vec![(0, 1), (1, 2), (2, 3)]));
104 let reduction =
105 ReduceTo::<SequencingToMinimizeWeightedCompletionTime>::reduce_to(&source);
106 let target_config = BruteForce::new()
107 .find_witness(reduction.target_problem())
108 .expect("canonical example must be solvable");
109 let source_config = reduction.extract_solution(&target_config);
110 assemble_rule_example(
111 &source,
112 reduction.target_problem(),
113 vec![SolutionPair {
114 source_config,
115 target_config,
116 }],
117 )
118 },
119 }]
120}
121
122#[cfg(test)]
123#[path = "../unit_tests/rules/optimallineararrangement_sequencingtominimizeweightedcompletiontime.rs"]
124mod tests;