problemreductions/rules/
kcoloring_twodimensionalconsecutivesets.rs1use crate::models::graph::KColoring;
16use crate::models::set::TwoDimensionalConsecutiveSets;
17use crate::reduction;
18use crate::rules::traits::{ReduceTo, ReductionResult};
19use crate::topology::{Graph, SimpleGraph};
20use crate::variant::K3;
21
22#[derive(Debug, Clone)]
24pub struct ReductionKColoringToTDCS {
25 target: TwoDimensionalConsecutiveSets,
26 num_vertices: usize,
28}
29
30impl ReductionResult for ReductionKColoringToTDCS {
31 type Source = KColoring<K3, SimpleGraph>;
32 type Target = TwoDimensionalConsecutiveSets;
33
34 fn target_problem(&self) -> &Self::Target {
35 &self.target
36 }
37
38 fn extract_solution(
45 &self,
46 target_solution: &<Self::Target as crate::traits::Problem>::Solution,
47 ) -> crate::rules::ExtractionResult<<Self::Source as crate::traits::Problem>::Solution> {
48 crate::rules::traits::validate_target_witness(
49 self.target_problem(),
50 target_solution,
51 |value| value.0,
52 "target grouping is not a consecutive-set partition",
53 )?;
54
55 Ok({
56 let vertex_groups = &target_solution[..self.num_vertices];
63
64 let mut used: Vec<usize> = vertex_groups.to_vec();
66 used.sort();
67 used.dedup();
68
69 let group_to_color: std::collections::HashMap<usize, usize> = used
70 .into_iter()
71 .enumerate()
72 .map(|(color, group)| (group, color % 3))
73 .collect();
74
75 vertex_groups.iter().map(|&g| group_to_color[&g]).collect()
76 })
77 }
78}
79
80#[crate::aggregate_reduction(identity)]
81impl crate::rules::AggregateReductionResult for ReductionKColoringToTDCS {}
82
83#[reduction(
84 transform = upper_bound {
85 alphabet_size = "num_vertices + num_edges + 3",
86 num_subsets = "num_edges + 3",
87 }
88)]
89impl ReduceTo<TwoDimensionalConsecutiveSets> for KColoring<K3, SimpleGraph> {
90 type Result = ReductionKColoringToTDCS;
91
92 fn reduce_to(&self) -> Result<Self::Result, crate::rules::ReductionError> {
93 let n = self.graph().num_vertices();
94 let edges: Vec<(usize, usize)> = self.graph().edges();
95 let m = edges.len();
96 let (alphabet_size, subsets) = if edges.iter().any(|&(u, v)| u == v) {
97 (3, vec![vec![0, 1], vec![1, 2], vec![0, 2]])
100 } else {
101 let alphabet_size = n + m;
103 let subsets = edges
104 .iter()
105 .enumerate()
106 .map(|(i, &(u, v))| vec![u, v, n + i])
107 .collect();
108 (alphabet_size.max(1), subsets)
111 };
112 let target = TwoDimensionalConsecutiveSets::try_new(alphabet_size, subsets).map_err(
113 crate::rules::ReductionError::construction::<Self, TwoDimensionalConsecutiveSets>,
114 )?;
115
116 Ok(ReductionKColoringToTDCS {
117 target,
118 num_vertices: n,
119 })
120 }
121}
122
123#[cfg(feature = "example-db")]
124pub(crate) fn canonical_rule_example_specs() -> Vec<crate::example_db::specs::RuleExampleSpec> {
125 use crate::export::SolutionPair;
126 use crate::traits::Problem;
127
128 vec![crate::example_db::specs::RuleExampleSpec {
129 id: "kcoloring_to_twodimensionalconsecutivesets",
130 build: || {
131 let source =
135 KColoring::<K3, _>::new(SimpleGraph::new(4, vec![(0, 1), (1, 2), (0, 2), (2, 3)]));
136 let reduction = <KColoring<K3, SimpleGraph> as ReduceTo<
137 TwoDimensionalConsecutiveSets,
138 >>::reduce_to(&source)
139 .expect("reduction should succeed");
140 let target = reduction.target_problem();
141
142 let source_config = vec![0, 1, 2, 0];
150 let target_config = vec![0, 1, 2, 0, 2, 0, 1, 1];
151
152 assert!(
154 target
155 .evaluate(&target_config)
156 .expect("canonical target evaluation must succeed")
157 .0,
158 "canonical example target config must be valid"
159 );
160
161 crate::example_db::specs::assemble_rule_example(
162 &source,
163 target,
164 vec![SolutionPair {
165 source_config: serde_json::to_value(source_config)
166 .expect("solution serialization must succeed"),
167 target_config: serde_json::to_value(target_config)
168 .expect("solution serialization must succeed"),
169 }],
170 )
171 },
172 }]
173}
174
175#[cfg(test)]
176#[path = "../unit_tests/rules/kcoloring_twodimensionalconsecutivesets.rs"]
177mod tests;