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(
36 &self,
37 target_solution: &<Self::Target as crate::traits::Problem>::Solution,
38 ) -> crate::rules::ExtractionResult<<Self::Source as crate::traits::Problem>::Solution> {
39 crate::rules::traits::validate_target_solution(self.target_problem(), target_solution)?;
40
41 Ok({
42 let mut arrangement = vec![0usize; self.num_vertices];
43 let mut next_position = 0usize;
44
45 for &task in target_solution {
46 if task < self.num_vertices {
47 arrangement[task] = next_position;
48 next_position += 1;
49 }
50 }
51
52 arrangement
53 })
54 }
55}
56
57#[reduction(
58 transform = exact {
59 num_tasks = "num_vertices + num_edges",
60 },
61 unavailable = {
62 num_precedences = "the exact target parameter is not represented by this reduction's symbolic transform",
63 }
64)]
65impl ReduceTo<SequencingToMinimizeWeightedCompletionTime>
66 for OptimalLinearArrangement<SimpleGraph>
67{
68 type Result = ReductionOLAToSequencingToMinimizeWeightedCompletionTime;
69
70 fn reduce_to(&self) -> Result<Self::Result, crate::rules::ReductionError> {
71 let graph = self.graph();
72 let num_vertices = graph.num_vertices();
73 let edges = graph.edges();
74 let max_degree = (0..num_vertices)
75 .map(|v| graph.degree(v))
76 .max()
77 .unwrap_or(0);
78 let max_degree = i64::try_from(max_degree).map_err(|_| {
79 crate::rules::ReductionError::integer_overflow::<
80 OptimalLinearArrangement<SimpleGraph>,
81 SequencingToMinimizeWeightedCompletionTime,
82 >("converting the maximum degree to i64")
83 })?;
84
85 let mut lengths = Vec::with_capacity(num_vertices + edges.len());
86 let mut weights = Vec::with_capacity(num_vertices + edges.len());
87 let mut precedences = Vec::with_capacity(2 * edges.len());
88
89 for vertex in 0..num_vertices {
90 let degree = i64::try_from(graph.degree(vertex)).map_err(|_| {
91 crate::rules::ReductionError::integer_overflow::<
92 OptimalLinearArrangement<SimpleGraph>,
93 SequencingToMinimizeWeightedCompletionTime,
94 >("converting a vertex degree to i64")
95 })?;
96 lengths.push(1);
97 weights.push(max_degree - degree);
98 }
99
100 for (edge_index, &(u, v)) in edges.iter().enumerate() {
101 let edge_task = num_vertices + edge_index;
102 lengths.push(0);
103 weights.push(2);
104 precedences.push((u, edge_task));
105 precedences.push((v, edge_task));
106 }
107
108 Ok(ReductionOLAToSequencingToMinimizeWeightedCompletionTime {
109 target: SequencingToMinimizeWeightedCompletionTime::new(lengths, weights, precedences),
110 num_vertices,
111 })
112 }
113}
114
115#[cfg(feature = "example-db")]
116pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
117 use crate::example_db::specs::assemble_rule_example;
118 use crate::export::SolutionPair;
119 use crate::solvers::BruteForce;
120
121 vec![crate::example_db::specs::RuleExampleSpec {
122 id: "optimallineararrangement_to_sequencingtominimizeweightedcompletiontime",
123 build: || {
124 let source =
125 OptimalLinearArrangement::new(SimpleGraph::new(4, vec![(0, 1), (1, 2), (2, 3)]));
126 let reduction =
127 ReduceTo::<SequencingToMinimizeWeightedCompletionTime>::reduce_to(&source)
128 .expect("reduction should succeed");
129 let target_config = BruteForce::new()
130 .solve(reduction.target_problem())
131 .expect("canonical target evaluation must succeed")
132 .expect("canonical example must be solvable");
133 let source_config = reduction.extract_solution(&target_config).unwrap();
134 assemble_rule_example(
135 &source,
136 reduction.target_problem(),
137 vec![SolutionPair {
138 source_config: serde_json::to_value(source_config)
139 .expect("solution serialization must succeed"),
140 target_config: serde_json::to_value(target_config)
141 .expect("solution serialization must succeed"),
142 }],
143 )
144 },
145 }]
146}
147
148#[cfg(test)]
149#[path = "../unit_tests/rules/optimallineararrangement_sequencingtominimizeweightedcompletiontime.rs"]
150mod tests;