problemreductions/rules/
minimumfeedbackvertexset_minimumcodegenerationunlimitedregisters.rs1use crate::models::graph::MinimumFeedbackVertexSet;
9use crate::models::misc::MinimumCodeGenerationUnlimitedRegisters;
10use crate::reduction;
11use crate::rules::traits::{ReduceTo, ReductionResult};
12
13#[derive(Debug, Clone)]
15pub struct ReductionFVSToCodeGen {
16 target: MinimumCodeGenerationUnlimitedRegisters,
17 num_source_vertices: usize,
19 chain_start: Vec<Option<usize>>,
22 right_child_users: Vec<Vec<usize>>,
25}
26
27impl ReductionResult for ReductionFVSToCodeGen {
28 type Source = MinimumFeedbackVertexSet<i32>;
29 type Target = MinimumCodeGenerationUnlimitedRegisters;
30
31 fn target_problem(&self) -> &Self::Target {
32 &self.target
33 }
34
35 fn extract_solution(&self, target_solution: &[usize]) -> Vec<usize> {
41 let n = self.num_source_vertices;
42 let mut source_config = vec![0usize; n];
43
44 let eval_pos = target_solution;
50
51 for (x, cfg) in source_config.iter_mut().enumerate() {
52 if let Some(chain_start_idx) = self.chain_start[x] {
53 let start_j = chain_start_idx - n;
54 let start_pos = eval_pos[start_j];
55
56 for &user_idx in &self.right_child_users[x] {
57 let user_j = user_idx - n;
58 if eval_pos[user_j] > start_pos {
59 *cfg = 1;
60 break;
61 }
62 }
63 }
64 }
65
66 source_config
67 }
68}
69
70#[reduction(
71 overhead = {
72 num_vertices = "num_vertices + num_arcs",
73 }
74)]
75impl ReduceTo<MinimumCodeGenerationUnlimitedRegisters> for MinimumFeedbackVertexSet<i32> {
76 type Result = ReductionFVSToCodeGen;
77
78 fn reduce_to(&self) -> Self::Result {
79 let n = self.graph().num_vertices();
80 let m = self.graph().num_arcs();
81
82 let mut out_neighbors: Vec<Vec<usize>> = vec![vec![]; n];
84 for (u, v) in self.graph().arcs() {
85 out_neighbors[u].push(v);
86 }
87
88 let mut left_arcs = Vec::with_capacity(m);
90 let mut right_arcs = Vec::with_capacity(m);
91 let mut chain_start = vec![None; n];
92 let mut right_child_users: Vec<Vec<usize>> = vec![vec![]; n];
93
94 let mut next_internal = n; for x in 0..n {
96 let neighbors = &out_neighbors[x];
97 let d = neighbors.len();
98 if d == 0 {
99 continue;
100 }
101
102 chain_start[x] = Some(next_internal);
103
104 for (i, &neighbor) in neighbors.iter().enumerate() {
105 let node_idx = next_internal + i;
106 let left_child = if i == 0 {
108 x } else {
110 next_internal + i - 1 };
112 let right_child = neighbor; left_arcs.push((node_idx, left_child));
116 right_arcs.push((node_idx, right_child));
117 right_child_users[right_child].push(node_idx);
118 }
119
120 next_internal += d;
121 }
122
123 debug_assert_eq!(next_internal, n + m);
124
125 let target = MinimumCodeGenerationUnlimitedRegisters::new(n + m, left_arcs, right_arcs);
126
127 ReductionFVSToCodeGen {
128 target,
129 num_source_vertices: n,
130 chain_start,
131 right_child_users,
132 }
133 }
134}
135
136#[cfg(any(test, feature = "example-db"))]
137fn issue_example_source() -> MinimumFeedbackVertexSet<i32> {
138 use crate::topology::DirectedGraph;
139 MinimumFeedbackVertexSet::new(
141 DirectedGraph::new(3, vec![(0, 1), (1, 2), (2, 0)]),
142 vec![1i32; 3],
143 )
144}
145
146#[cfg(feature = "example-db")]
147pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
148 use crate::export::SolutionPair;
149 use crate::solvers::BruteForce;
150
151 vec![crate::example_db::specs::RuleExampleSpec {
152 id: "minimumfeedbackvertexset_to_minimumcodegenerationunlimitedregisters",
153 build: || {
154 let source = issue_example_source();
155 let reduction = ReduceTo::<MinimumCodeGenerationUnlimitedRegisters>::reduce_to(&source);
156
157 let solver = BruteForce::new();
159 let source_witnesses = solver.find_all_witnesses(&source);
160 let target_witnesses = solver.find_all_witnesses(reduction.target_problem());
161
162 let (source_config, target_config) = target_witnesses
163 .iter()
164 .find_map(|tw| {
165 let extracted = reduction.extract_solution(tw);
166 if source_witnesses.contains(&extracted) {
167 Some((extracted, tw.clone()))
168 } else {
169 None
170 }
171 })
172 .expect("canonical FVS -> CodeGen example must have matching witness");
173
174 crate::example_db::specs::assemble_rule_example(
175 &source,
176 reduction.target_problem(),
177 vec![SolutionPair {
178 source_config,
179 target_config,
180 }],
181 )
182 },
183 }]
184}
185
186#[cfg(test)]
187#[path = "../unit_tests/rules/minimumfeedbackvertexset_minimumcodegenerationunlimitedregisters.rs"]
188mod tests;