problemreductions/rules/
rootedtreearrangement_rootedtreestorageassignment.rs1use crate::models::graph::RootedTreeArrangement;
13use crate::models::set::RootedTreeStorageAssignment;
14use crate::reduction;
15use crate::rules::traits::{ReduceTo, ReductionResult};
16use crate::topology::{Graph, SimpleGraph};
17
18#[derive(Debug, Clone)]
20pub struct ReductionRootedTreeArrangementToRootedTreeStorageAssignment {
21 target: RootedTreeStorageAssignment,
22 num_vertices: usize,
24}
25
26impl ReductionResult for ReductionRootedTreeArrangementToRootedTreeStorageAssignment {
27 type Source = RootedTreeArrangement<SimpleGraph>;
28 type Target = RootedTreeStorageAssignment;
29
30 fn target_problem(&self) -> &Self::Target {
31 &self.target
32 }
33
34 fn extract_solution(
40 &self,
41 target_solution: &<Self::Target as crate::traits::Problem>::Solution,
42 ) -> crate::rules::ExtractionResult<<Self::Source as crate::traits::Problem>::Solution> {
43 crate::rules::traits::validate_target_witness(
44 self.target_problem(),
45 target_solution,
46 |value| value.0,
47 "target witness does not satisfy the target problem",
48 )?;
49
50 Ok({
51 let n = self.num_vertices;
52 let mut source_config = target_solution.to_vec();
55 source_config.extend(0..n);
57 source_config
58 })
59 }
60}
61
62#[crate::aggregate_reduction(identity)]
63impl crate::rules::AggregateReductionResult
64 for ReductionRootedTreeArrangementToRootedTreeStorageAssignment
65{
66}
67
68#[reduction(
69 transform = upper_bound {
70 universe_size = "num_vertices",
71 num_subsets = "num_edges",
72 }
73)]
74impl ReduceTo<RootedTreeStorageAssignment> for RootedTreeArrangement<SimpleGraph> {
75 type Result = ReductionRootedTreeArrangementToRootedTreeStorageAssignment;
76
77 fn reduce_to(&self) -> Result<Self::Result, crate::rules::ReductionError> {
78 let n = self.num_vertices();
79 let edges: Vec<_> = self
81 .graph()
82 .edges()
83 .into_iter()
84 .filter(|&(u, v)| u != v)
85 .collect();
86 let num_edges = edges.len();
87
88 let subsets: Vec<Vec<usize>> = edges.iter().map(|&(u, v)| vec![u, v]).collect();
90
91 let num_edges = i64::try_from(num_edges).map_err(|_| {
93 crate::rules::ReductionError::integer_overflow::<
94 RootedTreeArrangement<SimpleGraph>,
95 RootedTreeStorageAssignment,
96 >("converting the number of edges to i64")
97 })?;
98 let bound = if self.bound() < num_edges {
99 -1
100 } else {
101 self.bound() - num_edges
102 };
103
104 let target = RootedTreeStorageAssignment::new(n, subsets, bound);
105
106 Ok(
107 ReductionRootedTreeArrangementToRootedTreeStorageAssignment {
108 target,
109 num_vertices: n,
110 },
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::export::SolutionPair;
118
119 vec![crate::example_db::specs::RuleExampleSpec {
120 id: "rootedtreearrangement_to_rootedtreestorageassignment",
121 build: || {
122 let source =
129 RootedTreeArrangement::new(SimpleGraph::new(4, vec![(0, 1), (1, 2), (2, 3)]), 5);
130 let source_config = vec![0, 0, 1, 2, 0, 1, 2, 3];
131 let target_config = vec![0, 0, 1, 2];
132 crate::example_db::specs::rule_example_with_witness::<_, RootedTreeStorageAssignment>(
133 source,
134 SolutionPair {
135 source_config: serde_json::to_value(source_config)
136 .expect("solution serialization must succeed"),
137 target_config: serde_json::to_value(target_config)
138 .expect("solution serialization must succeed"),
139 },
140 )
141 },
142 }]
143}
144
145#[cfg(test)]
146#[path = "../unit_tests/rules/rootedtreearrangement_rootedtreestorageassignment.rs"]
147mod tests;