Add owned and reduction implementation for vertex cover
This commit is contained in:
parent
68bfda7077
commit
f0a1257b25
3 changed files with 256 additions and 7 deletions
|
|
@ -24,13 +24,13 @@ pub fn binary_edge(graph: &Graph, k: u16, v: HashSet<u16>) -> Option<HashSet<u16
|
|||
}
|
||||
|
||||
pub fn binary_vertex(graph: &Graph, k: u16, v: HashSet<u16>) -> Option<HashSet<u16>> {
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use std::{
|
|||
};
|
||||
|
||||
mod filtered;
|
||||
mod owned;
|
||||
|
||||
fn parse(filename: impl AsRef<Path>) -> 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<u16>,
|
||||
min_degree: u16,
|
||||
|
|
@ -109,10 +114,27 @@ impl Graph {
|
|||
}
|
||||
}
|
||||
|
||||
fn vertex_cover(graph: &Graph, k: u16, method: Method) -> Option<HashSet<u16>> {
|
||||
fn vertex_cover(graph: &Graph, k: u16, method: Method) -> Option<Vec<u16>> {
|
||||
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<HashSet<u16>> {
|
|||
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 {
|
||||
|
|
|
|||
224
vertex_cover/src/owned.rs
Normal file
224
vertex_cover/src/owned.rs
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
use std::collections::HashSet;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Vertex {
|
||||
name: u16,
|
||||
edges: Vec<u16>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Graph {
|
||||
index: Vec<u16>,
|
||||
vertices: Vec<Vertex>,
|
||||
stack: Vec<Vertex>,
|
||||
}
|
||||
|
||||
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<Item = &Vertex> {
|
||||
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<u16> {
|
||||
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<u16> {
|
||||
self.vertices
|
||||
.iter()
|
||||
.find(|&v| v.edges.len() == degree as usize)
|
||||
.map(|v| v.name)
|
||||
}
|
||||
|
||||
fn get_edges(&self, v: u16) -> impl Iterator<Item = u16> + '_ {
|
||||
let i = self.index[v as usize];
|
||||
self.vertices[i as usize].edges.iter().copied()
|
||||
}
|
||||
|
||||
fn get_edge(&self, v: u16) -> Option<u16> {
|
||||
self.get_edges(v).next()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn binary_vertex(graph: &mut Graph, k: u16) -> Option<Vec<u16>> {
|
||||
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<Vec<u16>> {
|
||||
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!()
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue