1use crate::graph_types::SimpleGraph;
7use crate::traits::{ConstraintSatisfactionProblem, Problem};
8use crate::types::{EnergyMode, LocalConstraint, LocalSolutionSize, ProblemSize, SolutionSize};
9use petgraph::graph::{NodeIndex, UnGraph};
10use petgraph::visit::EdgeRef;
11use serde::{Deserialize, Serialize};
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct MaximalIS {
40 graph: UnGraph<(), ()>,
42}
43
44impl MaximalIS {
45 pub fn new(num_vertices: usize, edges: Vec<(usize, usize)>) -> Self {
47 let mut graph = UnGraph::new_undirected();
48 for _ in 0..num_vertices {
49 graph.add_node(());
50 }
51 for (u, v) in edges {
52 graph.add_edge(NodeIndex::new(u), NodeIndex::new(v), ());
53 }
54 Self { graph }
55 }
56
57 pub fn num_vertices(&self) -> usize {
59 self.graph.node_count()
60 }
61
62 pub fn num_edges(&self) -> usize {
64 self.graph.edge_count()
65 }
66
67 fn neighbors(&self, v: usize) -> Vec<usize> {
69 self.graph
70 .neighbors(NodeIndex::new(v))
71 .map(|n| n.index())
72 .collect()
73 }
74
75 fn is_independent(&self, config: &[usize]) -> bool {
77 for edge in self.graph.edge_references() {
78 let u = edge.source().index();
79 let v = edge.target().index();
80 if config.get(u).copied().unwrap_or(0) == 1
81 && config.get(v).copied().unwrap_or(0) == 1
82 {
83 return false;
84 }
85 }
86 true
87 }
88
89 fn is_maximal(&self, config: &[usize]) -> bool {
91 if !self.is_independent(config) {
92 return false;
93 }
94
95 let n = self.graph.node_count();
96 for v in 0..n {
97 if config.get(v).copied().unwrap_or(0) == 1 {
98 continue; }
100
101 let can_add = self.neighbors(v).iter().all(|&u| {
103 config.get(u).copied().unwrap_or(0) == 0
104 });
105
106 if can_add {
107 return false; }
109 }
110
111 true
112 }
113}
114
115impl Problem for MaximalIS {
116 const NAME: &'static str = "MaximalIS";
117 type GraphType = SimpleGraph;
118 type Weight = i32;
119 type Size = i32;
120
121 fn num_variables(&self) -> usize {
122 self.graph.node_count()
123 }
124
125 fn num_flavors(&self) -> usize {
126 2
127 }
128
129 fn problem_size(&self) -> ProblemSize {
130 ProblemSize::new(vec![
131 ("num_vertices", self.graph.node_count()),
132 ("num_edges", self.graph.edge_count()),
133 ])
134 }
135
136 fn energy_mode(&self) -> EnergyMode {
137 EnergyMode::LargerSizeIsBetter
140 }
141
142 fn solution_size(&self, config: &[usize]) -> SolutionSize<Self::Size> {
143 let is_valid = self.is_maximal(config);
144 let size: i32 = config.iter().sum::<usize>() as i32;
145 SolutionSize::new(size, is_valid)
146 }
147}
148
149impl ConstraintSatisfactionProblem for MaximalIS {
150 fn constraints(&self) -> Vec<LocalConstraint> {
151 let mut constraints = Vec::new();
152
153 for edge in self.graph.edge_references() {
155 let u = edge.source().index();
156 let v = edge.target().index();
157 constraints.push(LocalConstraint::new(
158 2,
159 vec![u, v],
160 vec![true, true, true, false],
161 ));
162 }
163
164 let n = self.graph.node_count();
167 for v in 0..n {
168 let mut vars = vec![v];
169 vars.extend(self.neighbors(v));
170
171 let num_vars = vars.len();
172 let num_configs = 2usize.pow(num_vars as u32);
173
174 let spec: Vec<bool> = (0..num_configs)
177 .map(|config_idx| {
178 let v_selected = (config_idx & 1) == 1;
179 let any_neighbor_selected = (config_idx >> 1) > 0;
180 v_selected || any_neighbor_selected
181 })
182 .collect();
183
184 constraints.push(LocalConstraint::new(2, vars, spec));
185 }
186
187 constraints
188 }
189
190 fn objectives(&self) -> Vec<LocalSolutionSize<Self::Size>> {
191 (0..self.graph.node_count())
193 .map(|i| LocalSolutionSize::new(2, vec![i], vec![0, 1]))
194 .collect()
195 }
196
197 fn weights(&self) -> Vec<Self::Size> {
198 vec![1; self.graph.node_count()]
199 }
200
201 fn set_weights(&mut self, _weights: Vec<Self::Size>) {}
202
203 fn is_weighted(&self) -> bool {
204 false
205 }
206}
207
208pub fn is_maximal_independent_set(
210 num_vertices: usize,
211 edges: &[(usize, usize)],
212 selected: &[bool],
213) -> bool {
214 if selected.len() != num_vertices {
215 return false;
216 }
217
218 let mut adj: Vec<Vec<usize>> = vec![vec![]; num_vertices];
220 for &(u, v) in edges {
221 if u < num_vertices && v < num_vertices {
222 adj[u].push(v);
223 adj[v].push(u);
224 }
225 }
226
227 for &(u, v) in edges {
229 if u < selected.len() && v < selected.len() && selected[u] && selected[v] {
230 return false;
231 }
232 }
233
234 for v in 0..num_vertices {
236 if selected[v] {
237 continue;
238 }
239 let can_add = adj[v].iter().all(|&u| !selected[u]);
240 if can_add {
241 return false;
242 }
243 }
244
245 true
246}
247
248#[cfg(test)]
249mod tests {
250 use super::*;
251 use crate::solvers::{BruteForce, Solver};
252
253 #[test]
254 fn test_maximal_is_creation() {
255 let problem = MaximalIS::new(4, vec![(0, 1), (1, 2), (2, 3)]);
256 assert_eq!(problem.num_vertices(), 4);
257 assert_eq!(problem.num_edges(), 3);
258 }
259
260 #[test]
261 fn test_is_independent() {
262 let problem = MaximalIS::new(3, vec![(0, 1), (1, 2)]);
263
264 assert!(problem.is_independent(&[1, 0, 1]));
265 assert!(problem.is_independent(&[0, 1, 0]));
266 assert!(!problem.is_independent(&[1, 1, 0]));
267 }
268
269 #[test]
270 fn test_is_maximal() {
271 let problem = MaximalIS::new(3, vec![(0, 1), (1, 2)]);
272
273 assert!(problem.is_maximal(&[1, 0, 1]));
275
276 assert!(problem.is_maximal(&[0, 1, 0]));
278
279 assert!(!problem.is_maximal(&[1, 0, 0]));
281
282 assert!(!problem.is_maximal(&[0, 0, 0]));
284 }
285
286 #[test]
287 fn test_solution_size() {
288 let problem = MaximalIS::new(3, vec![(0, 1), (1, 2)]);
289
290 let sol = problem.solution_size(&[1, 0, 1]);
292 assert!(sol.is_valid);
293 assert_eq!(sol.size, 2);
294
295 let sol = problem.solution_size(&[0, 1, 0]);
297 assert!(sol.is_valid);
298 assert_eq!(sol.size, 1);
299
300 let sol = problem.solution_size(&[1, 0, 0]);
302 assert!(!sol.is_valid);
303 }
304
305 #[test]
306 fn test_brute_force_path() {
307 let problem = MaximalIS::new(3, vec![(0, 1), (1, 2)]);
308 let solver = BruteForce::new();
309
310 let solutions = solver.find_best(&problem);
311 assert_eq!(solutions.len(), 1);
313 assert_eq!(solutions[0], vec![1, 0, 1]);
314 }
315
316 #[test]
317 fn test_brute_force_triangle() {
318 let problem = MaximalIS::new(3, vec![(0, 1), (1, 2), (0, 2)]);
319 let solver = BruteForce::new();
320
321 let solutions = solver.find_best(&problem);
322 assert_eq!(solutions.len(), 3);
324 for sol in &solutions {
325 assert_eq!(sol.iter().sum::<usize>(), 1);
326 assert!(problem.solution_size(sol).is_valid);
327 }
328 }
329
330 #[test]
331 fn test_is_maximal_independent_set_function() {
332 let edges = vec![(0, 1), (1, 2)];
333
334 assert!(is_maximal_independent_set(3, &edges, &[true, false, true]));
335 assert!(is_maximal_independent_set(3, &edges, &[false, true, false]));
336 assert!(!is_maximal_independent_set(3, &edges, &[true, false, false])); assert!(!is_maximal_independent_set(3, &edges, &[true, true, false])); }
339
340 #[test]
341 fn test_energy_mode() {
342 let problem = MaximalIS::new(2, vec![(0, 1)]);
343 assert!(problem.energy_mode().is_maximization());
344 }
345
346 #[test]
347 fn test_empty_graph() {
348 let problem = MaximalIS::new(3, vec![]);
349 let solver = BruteForce::new();
350
351 let solutions = solver.find_best(&problem);
352 assert_eq!(solutions.len(), 1);
354 assert_eq!(solutions[0], vec![1, 1, 1]);
355 }
356
357 #[test]
358 fn test_constraints() {
359 let problem = MaximalIS::new(3, vec![(0, 1)]);
360 let constraints = problem.constraints();
361 assert_eq!(constraints.len(), 4);
363 }
364
365 #[test]
366 fn test_is_satisfied() {
367 let problem = MaximalIS::new(3, vec![(0, 1), (1, 2)]);
368
369 assert!(problem.is_satisfied(&[1, 0, 1])); assert!(problem.is_satisfied(&[0, 1, 0])); }
373
374 #[test]
375 fn test_objectives() {
376 let problem = MaximalIS::new(3, vec![(0, 1)]);
377 let objectives = problem.objectives();
378 assert_eq!(objectives.len(), 3); }
380
381 #[test]
382 fn test_weights() {
383 let problem = MaximalIS::new(3, vec![(0, 1)]);
384 let weights = problem.weights();
385 assert_eq!(weights, vec![1, 1, 1]); }
387
388 #[test]
389 fn test_set_weights() {
390 let mut problem = MaximalIS::new(3, vec![(0, 1)]);
391 problem.set_weights(vec![1, 2, 3]);
393 assert_eq!(problem.weights(), vec![1, 1, 1]);
395 }
396
397 #[test]
398 fn test_is_weighted() {
399 let problem = MaximalIS::new(3, vec![(0, 1)]);
400 assert!(!problem.is_weighted()); }
402
403 #[test]
404 fn test_is_weighted_empty() {
405 let problem = MaximalIS::new(0, vec![]);
406 assert!(!problem.is_weighted());
407 }
408
409 #[test]
410 fn test_is_maximal_independent_set_wrong_len() {
411 assert!(!is_maximal_independent_set(3, &[(0, 1)], &[true, false]));
412 }
413
414 #[test]
415 fn test_problem_size() {
416 let problem = MaximalIS::new(5, vec![(0, 1), (1, 2), (2, 3)]);
417 let size = problem.problem_size();
418 assert_eq!(size.get("num_vertices"), Some(5));
419 assert_eq!(size.get("num_edges"), Some(3));
420 }
421}