problemreductions/models/graph/
maximum_domatic_number.rs1use crate::registry::{FieldInfo, ProblemSchemaEntry, VariantDimension};
7use crate::topology::{Graph, SimpleGraph};
8use crate::traits::Problem;
9use crate::types::Max;
10use serde::{Deserialize, Serialize};
11
12inventory::submit! {
13 ProblemSchemaEntry {
14 name: "MaximumDomaticNumber",
15 display_name: "Maximum Domatic Number",
16 aliases: &[],
17 dimensions: &[
18 VariantDimension::new("graph", "SimpleGraph", &["SimpleGraph"]),
19 ],
20 module_path: module_path!(),
21 description: "Find maximum number of disjoint dominating sets partitioning V",
22 fields: &[
23 FieldInfo { name: "graph", type_name: "G", description: "The underlying graph G=(V,E)" },
24 ],
25 }
26}
27
28#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct MaximumDomaticNumber<G> {
57 graph: G,
59}
60
61impl<G: Graph> MaximumDomaticNumber<G> {
62 pub fn new(graph: G) -> Self {
64 Self { graph }
65 }
66
67 pub fn graph(&self) -> &G {
69 &self.graph
70 }
71
72 pub fn num_vertices(&self) -> usize {
74 self.graph.num_vertices()
75 }
76
77 pub fn num_edges(&self) -> usize {
79 self.graph.num_edges()
80 }
81
82 fn evaluate_partition(&self, config: &[usize]) -> Option<usize> {
87 let n = self.graph.num_vertices();
88
89 if config.len() != n {
91 return None;
92 }
93
94 let mut sets: Vec<Vec<usize>> = vec![vec![]; n];
96 for (v, &set_idx) in config.iter().enumerate() {
97 if set_idx >= n {
99 return None;
100 }
101 sets[set_idx].push(v);
102 }
103
104 let mut count = 0;
106 for set in &sets {
107 if set.is_empty() {
108 continue;
109 }
110 count += 1;
111
112 let mut in_set = vec![false; n];
114 for &v in set {
115 in_set[v] = true;
116 }
117
118 for v in 0..n {
120 if in_set[v] {
121 continue;
122 }
123 if !self.graph.neighbors(v).iter().any(|&u| in_set[u]) {
124 return None;
125 }
126 }
127 }
128
129 Some(count)
130 }
131}
132
133impl<G> Problem for MaximumDomaticNumber<G>
134where
135 G: Graph + crate::variant::VariantParam,
136{
137 const NAME: &'static str = "MaximumDomaticNumber";
138 type Value = Max<usize>;
139
140 fn variant() -> Vec<(&'static str, &'static str)> {
141 crate::variant_params![G]
142 }
143
144 fn dims(&self) -> Vec<usize> {
145 let n = self.graph.num_vertices();
146 vec![n; n]
147 }
148
149 fn evaluate(&self, config: &[usize]) -> Max<usize> {
150 match self.evaluate_partition(config) {
151 Some(k) => Max(Some(k)),
152 None => Max(None),
153 }
154 }
155}
156
157crate::declare_variants! {
158 default MaximumDomaticNumber<SimpleGraph> => "2.695^num_vertices",
159}
160
161#[cfg(feature = "example-db")]
162pub(crate) fn canonical_model_example_specs() -> Vec<crate::example_db::specs::ModelExampleSpec> {
163 vec![crate::example_db::specs::ModelExampleSpec {
164 id: "maximum_domatic_number_simplegraph",
165 instance: Box::new(MaximumDomaticNumber::new(SimpleGraph::new(
166 6,
167 vec![
168 (0, 1),
169 (0, 2),
170 (0, 3),
171 (1, 4),
172 (2, 5),
173 (3, 4),
174 (3, 5),
175 (4, 5),
176 ],
177 ))),
178 optimal_config: vec![0, 1, 2, 0, 2, 1],
179 optimal_value: serde_json::json!(3),
180 }]
181}
182
183#[cfg(test)]
184#[path = "../../unit_tests/models/graph/maximum_domatic_number.rs"]
185mod tests;