problemreductions/models/graph/
minimum_metric_dimension.rs1use crate::registry::{FieldInfo, ProblemSchemaEntry, VariantDimension};
8use crate::topology::{Graph, SimpleGraph};
9use crate::traits::Problem;
10use crate::types::Min;
11use serde::{Deserialize, Serialize};
12use std::collections::VecDeque;
13
14inventory::submit! {
15 ProblemSchemaEntry {
16 name: "MinimumMetricDimension",
17 display_name: "Minimum Metric Dimension",
18 aliases: &[],
19 dimensions: &[
20 VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]),
21 ],
22 category: crate::registry::ProblemCategory::Graph,
23 module_path: module_path!(),
24 description: "Find minimum resolving set of a graph",
25 fields: &[
26 FieldInfo { name: "graph", type_name: "G", description: "The underlying graph G=(V,E)" },
27 ],
28 }
29}
30
31pub fn bfs_distances<G: Graph>(graph: &G, source: usize) -> Vec<usize> {
36 let n = graph.num_vertices();
37 let mut dist = vec![usize::MAX; n];
38 dist[source] = 0;
39 let mut queue = VecDeque::new();
40 queue.push_back(source);
41 while let Some(u) = queue.pop_front() {
42 for v in graph.neighbors(u) {
43 if dist[v] == usize::MAX {
44 dist[v] = dist[u] + 1;
45 queue.push_back(v);
46 }
47 }
48 }
49 dist
50}
51
52#[derive(Debug, Clone, Serialize)]
79pub struct MinimumMetricDimension<G> {
80 graph: G,
82 #[serde(skip)]
84 dist_matrix: Vec<Vec<usize>>,
85}
86
87impl<'de, G: Graph + Deserialize<'de>> Deserialize<'de> for MinimumMetricDimension<G> {
88 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
89 where
90 D: serde::Deserializer<'de>,
91 {
92 #[derive(Deserialize)]
93 struct Helper<G> {
94 graph: G,
95 }
96 let helper = Helper::<G>::deserialize(deserializer)?;
97 Ok(Self::new(helper.graph))
98 }
99}
100
101impl<G: Graph> MinimumMetricDimension<G> {
102 pub fn new(graph: G) -> Self {
104 let n = graph.num_vertices();
105 let dist_matrix = (0..n).map(|v| bfs_distances(&graph, v)).collect();
106 Self { graph, dist_matrix }
107 }
108
109 pub fn graph(&self) -> &G {
111 &self.graph
112 }
113
114 pub fn num_vertices(&self) -> usize {
116 self.graph.num_vertices()
117 }
118
119 pub fn num_edges(&self) -> usize {
121 self.graph.num_edges()
122 }
123
124 pub fn is_resolving(&self, config: &[bool]) -> bool {
129 let n = self.graph.num_vertices();
130 let selected: Vec<usize> = (0..n).filter(|&i| config[i]).collect();
131 if selected.is_empty() {
132 return false;
133 }
134
135 for u in 0..n {
138 for v in (u + 1)..n {
139 let all_same = selected
140 .iter()
141 .all(|&w| self.dist_matrix[w][u] == self.dist_matrix[w][v]);
142 if all_same {
143 return false;
144 }
145 }
146 }
147
148 true
149 }
150}
151
152impl<G> Problem for MinimumMetricDimension<G>
153where
154 G: Graph + crate::variant::VariantParam,
155{
156 const NAME: &'static str = "MinimumMetricDimension";
157 type Solution = Vec<bool>;
158 type Value = Min<i64>;
159
160 crate::problem_parameters![("num_vertices", num_vertices),];
161
162 fn variant() -> Vec<(&'static str, &'static str)> {
163 crate::variant_params![G]
164 }
165
166 fn evaluate(
167 &self,
168 config: &Self::Solution,
169 ) -> Result<Min<i64>, crate::traits::EvaluationError> {
170 if config.len() != self.graph.num_vertices() {
171 return Err(crate::traits::EvaluationError::InvalidConfiguration(
172 "vertex-selection length does not match the graph".into(),
173 ));
174 }
175 Ok({
176 if !self.is_resolving(config) {
177 return Ok(Min(None));
178 }
179 let count = config.iter().filter(|&&x| x).count();
180 Min(Some(i64::try_from(count).map_err(|_| {
181 crate::traits::EvaluationError::IntegerOverflow(
182 "converting metric-basis size to i64".into(),
183 )
184 })?))
185 })
186 }
187}
188
189impl<G> crate::solvers::BruteForceProblem for MinimumMetricDimension<G>
190where
191 G: Graph + crate::variant::VariantParam,
192{
193 fn dimensions(&self) -> Vec<usize> {
194 vec![2; self.graph.num_vertices()]
195 }
196}
197
198crate::declare_variants! {
199 default MinimumMetricDimension<SimpleGraph> => "2^num_vertices",
200}
201
202crate::register_brute_force! {
203 MinimumMetricDimension<SimpleGraph> decode |_, indices: Vec<usize>| crate::config::config_to_bits(&indices),
204}
205
206#[cfg(feature = "example-db")]
207pub(crate) fn canonical_model_example_specs() -> Vec<crate::example_db::specs::ModelExampleSpec> {
208 vec![crate::example_db::specs::ModelExampleSpec {
209 id: "minimum_metric_dimension_simplegraph",
210 instance: Box::new(MinimumMetricDimension::new(SimpleGraph::new(
211 5,
212 vec![(0, 1), (0, 2), (1, 3), (2, 3), (2, 4), (3, 4)],
213 ))),
214 optimal_config: serde_json::json!(vec![true, true, false, false, false]),
215 optimal_value: serde_json::json!(2),
216 }]
217}
218
219#[cfg(test)]
220#[path = "../../unit_tests/models/graph/minimum_metric_dimension.rs"]
221mod tests;