Initial commit

This commit is contained in:
hal8174 2024-11-09 20:33:25 +01:00
commit 68bfda7077
13 changed files with 4952 additions and 0 deletions

View file

@ -0,0 +1,71 @@
use crate::Graph;
use std::collections::HashSet;
pub fn binary_edge(graph: &Graph, k: u16, v: HashSet<u16>) -> Option<HashSet<u16>> {
let edge = match graph.get_edge_filtered(&v) {
Some(edge) => edge,
None => return Some(v),
};
if k == 0 {
return None;
}
let mut v1 = v.clone();
v1.insert(edge.0);
match binary_edge(graph, k - 1, v1) {
Some(s) => Some(s),
None => {
let mut v2 = v;
v2.insert(edge.1);
binary_edge(graph, k - 1, v2)
}
}
}
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) {
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) {
v3.insert(vertex);
c += 1;
}
if c <= k {
Some(v3)
} else {
None
}
}
}
};
if k == 0 {
return None;
}
let mut v1 = v.clone();
v1.insert(vertex);
match binary_vertex(graph, k - 1, v1) {
Some(s) => Some(s),
None => {
let mut v2 = v;
let mut c = 0;
for o in graph.get_edges(vertex) {
if !v2.contains(&o) {
c += 1;
v2.insert(o);
}
}
if c <= k {
binary_vertex(graph, k - c, v2)
} else {
None
}
}
}
}

162
vertex_cover/src/main.rs Normal file
View file

@ -0,0 +1,162 @@
use clap::{Parser, ValueEnum};
use std::{
collections::HashSet,
path::{Path, PathBuf},
};
mod filtered;
fn parse(filename: impl AsRef<Path>) -> Graph {
let content = std::fs::read_to_string(filename).unwrap();
let mut line_iter = content
.split('\n')
.map(|l| l.trim())
.filter(|l| !l.is_empty());
let first_line = line_iter.next().unwrap();
let (nodes_str, edges_str) = first_line.split_once(' ').unwrap();
let nodes = nodes_str.parse::<u16>().unwrap();
let edges = edges_str.parse::<u16>().unwrap();
let mut g = Graph::new(nodes);
let mut c = 0;
for l in line_iter {
let (from_str, to_str) = l.split_once(' ').unwrap();
let from = from_str.parse::<u16>().unwrap();
let to = to_str.parse::<u16>().unwrap();
g.add_edge(from - 1, to - 1);
c += 1;
}
assert_eq!(edges, c);
g
}
/// Datastructure is 0 indexed
#[derive(Debug)]
struct Graph {
edge_list: Vec<Vec<u16>>,
}
impl Graph {
fn new(num_vertices: u16) -> Self {
Self {
edge_list: vec![Vec::new(); num_vertices as usize],
}
}
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);
}
fn get_edges(&self, vertex: u16) -> impl Iterator<Item = u16> + '_ {
self.edge_list[vertex as usize].iter().copied()
}
fn iter_edges_filtered<'a>(
&'a self,
v: &'a HashSet<u16>,
) -> impl Iterator<Item = (u16, u16)> + 'a {
self.edge_list
.iter()
.enumerate()
.filter(|(i, _)| !v.contains(&(*i as u16)))
.flat_map(move |(i, s)| {
let from = i as u16;
s.iter().filter_map(move |&to| {
if !v.contains(&to) && from < to {
Some((from, to))
} else {
None
}
})
})
}
fn get_edge_filtered(&self, v: &HashSet<u16>) -> Option<(u16, u16)> {
self.iter_edges_filtered(v).next()
}
fn iter_vertices_filtered_with_degree_grater<'a>(
&'a self,
v: &'a HashSet<u16>,
min_degree: u16,
) -> impl Iterator<Item = u16> + 'a {
self.edge_list.iter().enumerate().filter_map(move |(i, s)| {
let i = i as u16;
if !v.contains(&i) && s.iter().filter(|&o| !v.contains(o)).count() as u16 >= min_degree
{
Some(i)
} else {
None
}
})
}
fn get_vertex_filtered_with_degree_grater(
&self,
v: &HashSet<u16>,
min_degree: u16,
) -> Option<u16> {
self.iter_vertices_filtered_with_degree_grater(v, min_degree)
.next()
}
}
fn vertex_cover(graph: &Graph, k: u16, method: Method) -> Option<HashSet<u16>> {
match method {
Method::Edge => filtered::binary_edge(graph, k, HashSet::new()),
Method::Vertex => filtered::binary_vertex(graph, k, HashSet::new()),
}
}
#[derive(Debug, Clone, Copy, ValueEnum)]
enum Method {
Edge,
Vertex,
}
#[derive(Debug, Parser)]
struct Args {
filename: PathBuf,
method: Method,
k: Option<u16>,
}
fn main() {
let args = Args::parse();
let graph = parse(args.filename);
let result = if let Some(k) = args.k {
let start = std::time::Instant::now();
let r = vertex_cover(&graph, k, args.method);
eprintln!("{}: {:?}", k, start.elapsed());
r
} else {
let mut k = 0;
loop {
let start = std::time::Instant::now();
let r = vertex_cover(&graph, k, args.method);
eprintln!("{}: {:?}", k, start.elapsed());
if let Some(r) = r {
break Some(r);
}
k += 1;
}
};
if let Some(solution) = result {
println!("{}", solution.len());
for n in solution {
println!("{}", n + 1);
}
}
}