diff --git a/vertex_cover/src/filtered.rs b/vertex_cover/src/filtered.rs index 55ca7c1..cab88f4 100644 --- a/vertex_cover/src/filtered.rs +++ b/vertex_cover/src/filtered.rs @@ -24,13 +24,13 @@ pub fn binary_edge(graph: &Graph, k: u16, v: HashSet) -> Option) -> Option> { - let vertex = match graph.get_vertex_filtered_with_degree_grater(&v, 2) { + let vertex = match graph.get_vertex_filtered_with_degree_greater(&v, 2) { Some(vertex) => vertex, None => { return { let mut v3 = v; let mut c = 0; - while let Some(vertex) = graph.get_vertex_filtered_with_degree_grater(&v3, 1) { + while let Some(vertex) = graph.get_vertex_filtered_with_degree_greater(&v3, 1) { v3.insert(vertex); c += 1; } diff --git a/vertex_cover/src/main.rs b/vertex_cover/src/main.rs index c6a6fb9..aec5c03 100644 --- a/vertex_cover/src/main.rs +++ b/vertex_cover/src/main.rs @@ -5,6 +5,7 @@ use std::{ }; mod filtered; +mod owned; fn parse(filename: impl AsRef) -> Graph { let content = std::fs::read_to_string(filename).unwrap(); @@ -50,6 +51,10 @@ impl Graph { } } + fn num_vertices(&self) -> u16 { + self.edge_list.len() as u16 + } + fn add_edge(&mut self, from: u16, to: u16) { self.edge_list[(from) as usize].push(to); self.edge_list[(to) as usize].push(from); @@ -99,7 +104,7 @@ impl Graph { }) } - fn get_vertex_filtered_with_degree_grater( + fn get_vertex_filtered_with_degree_greater( &self, v: &HashSet, min_degree: u16, @@ -109,10 +114,27 @@ impl Graph { } } -fn vertex_cover(graph: &Graph, k: u16, method: Method) -> Option> { +fn vertex_cover(graph: &Graph, k: u16, method: Method) -> Option> { match method { - Method::Edge => filtered::binary_edge(graph, k, HashSet::new()), - Method::Vertex => filtered::binary_vertex(graph, k, HashSet::new()), + Method::Edge => { + let r = filtered::binary_edge(graph, k, HashSet::new()); + + r.map(|mut r| r.drain().collect()) + } + Method::Vertex => { + let r = filtered::binary_vertex(graph, k, HashSet::new()); + r.map(|mut r| r.drain().collect()) + } + Method::OwnedVertex => { + let mut g = owned::Graph::new(graph); + + owned::binary_vertex(&mut g, k) + } + Method::Reduction => { + let mut g = owned::Graph::new(graph); + + owned::reduction(&mut g, k) + } } } @@ -120,6 +142,8 @@ fn vertex_cover(graph: &Graph, k: u16, method: Method) -> Option> { enum Method { Edge, Vertex, + OwnedVertex, + Reduction, } #[derive(Debug, Parser)] @@ -152,7 +176,8 @@ fn main() { } }; - if let Some(solution) = result { + if let Some(mut solution) = result { + solution.sort(); println!("{}", solution.len()); for n in solution { diff --git a/vertex_cover/src/owned.rs b/vertex_cover/src/owned.rs new file mode 100644 index 0000000..5661b8f --- /dev/null +++ b/vertex_cover/src/owned.rs @@ -0,0 +1,224 @@ +use std::collections::HashSet; + +#[derive(Debug)] +struct Vertex { + name: u16, + edges: Vec, +} + +#[derive(Debug)] +pub struct Graph { + index: Vec, + vertices: Vec, + stack: Vec, +} + +impl Graph { + pub fn new(g: &crate::Graph) -> Self { + let mut vertices: Vec<_> = (0..g.num_vertices()) + .map(|i| Vertex { + name: i, + edges: Vec::new(), + }) + .collect(); + + for (start, s) in g.edge_list.iter().enumerate() { + vertices[start].edges.extend_from_slice(s); + } + + Self { + index: (0..g.num_vertices()).collect(), + vertices, + stack: Vec::new(), + } + } + + fn is_empty(&self) -> bool { + self.vertices.is_empty() + } + + fn remove_vertex(&mut self, v: u16) -> &Vertex { + let i = self.index[v as usize]; + // dbg!(&self.index, v, i); + let vertex = self.vertices.swap_remove(i as usize); + + assert_eq!(vertex.name, v); + + if (i as usize) < self.vertices.len() { + self.index[self.vertices[i as usize].name as usize] = i; + } + + for &e in &vertex.edges { + let i = self.index[e as usize]; + self.vertices[i as usize].edges.retain(|&o| o != v); + } + // dbg!(&self.index); + + self.stack.push(vertex); + + self.stack.last().unwrap() + } + + fn reinsert_vertices(&mut self, n: usize) -> impl Iterator { + for _ in 0..n { + let v = self.stack.pop().unwrap(); + for &e in &v.edges { + let i = self.index[e as usize]; + self.vertices[i as usize].edges.push(v.name); + } + + self.index[v.name as usize] = self.vertices.len() as u16; + self.vertices.push(v); + } + + self.vertices[(self.vertices.len() - n)..].iter() + } + + fn get_vertex_with_degree_greater(&self, min_degree: u16) -> Option { + self.vertices + .iter() + .find(|&v| v.edges.len() >= min_degree as usize) + .map(|v| v.name) + } + + fn get_vertex_with_degree(&self, degree: u16) -> Option { + self.vertices + .iter() + .find(|&v| v.edges.len() == degree as usize) + .map(|v| v.name) + } + + fn get_edges(&self, v: u16) -> impl Iterator + '_ { + let i = self.index[v as usize]; + self.vertices[i as usize].edges.iter().copied() + } + + fn get_edge(&self, v: u16) -> Option { + self.get_edges(v).next() + } +} + +pub fn binary_vertex(graph: &mut Graph, k: u16) -> Option> { + let vertex = match graph.get_vertex_with_degree_greater(2) { + Some(vertex) => vertex, + None => { + return { + let mut c = 0; + while let Some(vertex) = graph.get_vertex_with_degree_greater(1) { + graph.remove_vertex(vertex); + c += 1; + } + + if c <= k { + Some( + graph + .reinsert_vertices(c as usize) + .map(|v| v.name) + .collect(), + ) + } else { + let _ = graph.reinsert_vertices(c as usize); + None + } + } + } + }; + + if k == 0 { + return None; + } + + graph.remove_vertex(vertex); + + match binary_vertex(graph, k - 1) { + Some(mut s) => { + s.push(vertex); + Some(s) + } + None => { + let _ = graph.reinsert_vertices(1); + let num_neighbors = graph.get_edges(vertex).count(); + + if num_neighbors <= k as usize { + let mut c = 0; + while let Some(e) = graph.get_edge(vertex) { + graph.remove_vertex(e); + c += 1; + } + let mut r = binary_vertex(graph, k - c); + if let Some(r) = &mut r { + r.extend(graph.reinsert_vertices(c as usize).map(|v| v.name)); + } else { + let _ = graph.reinsert_vertices(c as usize); + } + r + } else { + None + } + } + } +} + +pub fn reduction(graph: &mut Graph, k: u16) -> Option> { + if let Some(vertex) = graph.get_vertex_with_degree(0) { + graph.remove_vertex(vertex); + + let r = reduction(graph, k); + + let _ = graph.reinsert_vertices(1); + + r + } else if k == 0 { + if graph.is_empty() { + Some(Vec::new()) + } else { + None + } + } else if let Some(vertex) = graph.get_vertex_with_degree(1) { + let neighbor = graph.get_edge(vertex).unwrap(); + + graph.remove_vertex(neighbor); + let mut r = reduction(graph, k - 1); + + let i = graph.reinsert_vertices(1); + + if let Some(r) = &mut r { + r.extend(i.map(|v| v.name)); + } + + r + } else if let Some(vertex) = graph.get_vertex_with_degree_greater(2) { + graph.remove_vertex(vertex); + + match reduction(graph, k - 1) { + Some(mut s) => { + let i = graph.reinsert_vertices(1); + s.extend(i.map(|v| v.name)); + Some(s) + } + None => { + let _ = graph.reinsert_vertices(1); + let num_neighbors = graph.get_edges(vertex).count(); + + if num_neighbors <= k as usize { + let mut c = 0; + while let Some(e) = graph.get_edge(vertex) { + graph.remove_vertex(e); + c += 1; + } + let mut r = reduction(graph, k - c); + + let i = graph.reinsert_vertices(c as usize); + if let Some(r) = &mut r { + r.extend(i.map(|v| v.name)); + } + r + } else { + None + } + } + } + } else { + unreachable!() + } +}