Compare commits
No commits in common. "2f600e01e39c3a85d8f88984b6bd449bbeb849e9" and "3338b255a11c34ac79ebc8bf9f79610c9e4db15b" have entirely different histories.
2f600e01e3
...
3338b255a1
@ -11,45 +11,15 @@ use self::regex::Regex;
|
|||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
|
|
||||||
/// Constructs RegEx and panics if error.
|
/// Constructs RegEx and panics if error.
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn construct_regex(pattern: &str) -> Regex {
|
pub fn construct_regex(pattern: &str) -> Regex {
|
||||||
return Regex::new(pattern)
|
return Regex::new(pattern)
|
||||||
.expect("Invalid regex construction!");
|
.expect("Invalid regex construction!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
// METHODS values
|
// METHOD hello world
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
|
|
||||||
pub fn min<T>(x: T, y: T) -> T
|
pub fn greet() {
|
||||||
where T: PartialOrd
|
println!("Hello world!");
|
||||||
{
|
|
||||||
return if y < x { y } else { x };
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------
|
|
||||||
// METHODS Vectors
|
|
||||||
// ----------------------------------------------------------------
|
|
||||||
|
|
||||||
pub fn restrict<T>(x: &mut Vec<T>, i: usize, j: usize) -> Vec<T>
|
|
||||||
where T: Clone
|
|
||||||
{
|
|
||||||
return x[i..j].iter()
|
|
||||||
.cloned()
|
|
||||||
.collect::<Vec<T>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remove_last<T>(x: &mut Vec<T>) -> Vec<T>
|
|
||||||
where T: Clone
|
|
||||||
{
|
|
||||||
let n = x.len();
|
|
||||||
return restrict::<T>(x, 0, n-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn remove_first<T>(x: &mut Vec<T>) -> Vec<T>
|
|
||||||
where T: Clone
|
|
||||||
{
|
|
||||||
let n = x.len();
|
|
||||||
return restrict::<T>(x, 0, n);
|
|
||||||
}
|
}
|
||||||
|
@ -1,72 +0,0 @@
|
|||||||
// ----------------------------------------------------------------
|
|
||||||
// IMPORTS
|
|
||||||
// ----------------------------------------------------------------
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// CLASS Graph
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
/**
|
|
||||||
A data structure for graphs
|
|
||||||
*/
|
|
||||||
pub struct Graph<T> {
|
|
||||||
pub nodes: Vec<T>,
|
|
||||||
pub edges: Vec<(T,T)>,
|
|
||||||
#[allow(dead_code)]
|
|
||||||
string: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Graph<T>
|
|
||||||
where T: PartialEq + Clone + ToString {
|
|
||||||
/// Creates new typed instance of stack.
|
|
||||||
pub fn new(nodes: Vec<T>, edges: Vec<(T,T)>) -> Graph<T> {
|
|
||||||
return Graph {
|
|
||||||
nodes: nodes,
|
|
||||||
edges: edges,
|
|
||||||
string: String::from(""),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @returns number of elements in stack.
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn len(self: &Self) -> usize {
|
|
||||||
return self.nodes.len();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @returns graph induced by subset of nodes
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn subgraph(self: Self, nodes: Vec<T>) -> Graph<T> {
|
|
||||||
let nodes_ = self.nodes
|
|
||||||
.iter()
|
|
||||||
.filter(|&u| (nodes.contains(u)))
|
|
||||||
.map(|u| u.clone())
|
|
||||||
.collect::<Vec<T>>();
|
|
||||||
let edges_ = self.edges
|
|
||||||
.iter()
|
|
||||||
.filter(|&(u, v)| (nodes.contains(u) && nodes.contains(v)))
|
|
||||||
.map(|(u, v)| (u.clone(), v.clone()))
|
|
||||||
.collect::<Vec<(T,T)>>();
|
|
||||||
return Graph::new(nodes_, edges_);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @returns all successor nodes of a particular node
|
|
||||||
pub fn successors(self: &Self, u: &T) -> Vec<T> {
|
|
||||||
return self.edges
|
|
||||||
.iter()
|
|
||||||
.filter(|&(u_, _)| (*u_ == *u))
|
|
||||||
.map(|(_, v)| (v.clone()))
|
|
||||||
.collect::<Vec<T>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @returns all predecessors nodes of a particular node
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn predecessors(self: &Self, v: &T) -> Vec<T> {
|
|
||||||
return self.edges
|
|
||||||
.iter()
|
|
||||||
.filter(|&(_, v_)| (*v_ == *v))
|
|
||||||
.map(|(u, _)| (u.clone()))
|
|
||||||
.collect::<Vec<T>>();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
pub mod graph;
|
|
||||||
pub mod tarjan;
|
|
@ -1,176 +0,0 @@
|
|||||||
// ----------------------------------------------------------------
|
|
||||||
// IMPORTS
|
|
||||||
// ----------------------------------------------------------------
|
|
||||||
|
|
||||||
use std::fmt::Display;
|
|
||||||
use std::hash::Hash;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use crate::core::utils;
|
|
||||||
use crate::stacks::stack::Stack;
|
|
||||||
use crate::graphs::graph::Graph;
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// CONSTANTS
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
|
||||||
enum State {
|
|
||||||
UNTOUCHED,
|
|
||||||
PENDING,
|
|
||||||
FINISHED,
|
|
||||||
}
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// METHOD Tarjan Algorithm
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
|
|
||||||
/// # Tarjan Algorithm #
|
|
||||||
/// Runs the Tarjan-Algorithm to compute the strongly connected components.
|
|
||||||
pub fn tarjan_algorithm<T>(gph: &Graph<T>) -> Vec<Vec<T>>
|
|
||||||
where T: Eq + Hash + Clone + Display
|
|
||||||
{
|
|
||||||
let mut ctx = Context::new(&gph);
|
|
||||||
|
|
||||||
for u in gph.nodes.iter() {
|
|
||||||
tarjan_visit(gph, u, &mut ctx);
|
|
||||||
}
|
|
||||||
return ctx.components;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// recursive depth-first search algorithm to compute components
|
|
||||||
fn tarjan_visit<T>(gph: &Graph<T>, v: &T, ctx: &mut Context<T>)
|
|
||||||
where T: Eq + Hash + Clone + Display
|
|
||||||
{
|
|
||||||
if !(ctx.get_state(v) == State::UNTOUCHED) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.max_index += 1;
|
|
||||||
ctx.push(v);
|
|
||||||
ctx.set_root(v, ctx.max_index);
|
|
||||||
ctx.set_index(v, ctx.max_index);
|
|
||||||
ctx.set_state(v, State::PENDING);
|
|
||||||
|
|
||||||
// depth first search:
|
|
||||||
for u in gph.successors(&v) {
|
|
||||||
tarjan_visit(gph, &u, ctx);
|
|
||||||
// remains relevant for v, provided u still in Stack:
|
|
||||||
if ctx.stack.elements.contains(&u) {
|
|
||||||
let root = utils::min(
|
|
||||||
ctx.get_root(&u),
|
|
||||||
ctx.get_root(v)
|
|
||||||
);
|
|
||||||
ctx.set_root(v, root);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ctx.set_state(v, State::FINISHED);
|
|
||||||
|
|
||||||
if ctx.get_index(v) == ctx.get_root(v) {
|
|
||||||
let mut component: Vec<T> = Vec::new();
|
|
||||||
loop {
|
|
||||||
let u = ctx.top();
|
|
||||||
ctx.pop();
|
|
||||||
component.push(u.clone());
|
|
||||||
if u == *v {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ctx.components.push(component);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// AUXILIARY context variables for algorithm
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
struct NodeInformation {
|
|
||||||
root: usize,
|
|
||||||
index: usize,
|
|
||||||
state: State,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Context<T> {
|
|
||||||
stack: Stack<T>,
|
|
||||||
max_index: usize,
|
|
||||||
infos: HashMap<T, NodeInformation>,
|
|
||||||
components: Vec<Vec<T>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Context<T>
|
|
||||||
where T: Eq + Hash + Clone + Display
|
|
||||||
{
|
|
||||||
fn new(gph: &Graph<T>) -> Context<T> {
|
|
||||||
let mut infos = HashMap::<T, NodeInformation>::new();
|
|
||||||
for u in gph.nodes.iter() {
|
|
||||||
infos.entry(u.clone()).or_insert(NodeInformation::new());
|
|
||||||
}
|
|
||||||
return Context {
|
|
||||||
stack: Stack::new(),
|
|
||||||
max_index: 0,
|
|
||||||
infos: infos,
|
|
||||||
components: vec![],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push(self: &mut Self, u: &T) {
|
|
||||||
self.stack.push(u.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn top(self: &mut Self) -> T {
|
|
||||||
return self.stack.top();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pop(self: &mut Self) -> T {
|
|
||||||
return self.stack.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_infos(self: &mut Self, u: &T, info: NodeInformation) {
|
|
||||||
self.infos.insert(u.clone(), info);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_state(self: &mut Self, u: &T, state: State) {
|
|
||||||
let mut info = *self.infos.get(u).unwrap();
|
|
||||||
info.state = state;
|
|
||||||
self.update_infos(u, info);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_root(self: &mut Self, u: &T, root: usize) {
|
|
||||||
let mut info = *self.infos.get(u).unwrap();
|
|
||||||
info.root = root;
|
|
||||||
self.update_infos(u, info);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_index(self: &mut Self, u: &T, index: usize) {
|
|
||||||
let mut info = *self.infos.get(u).unwrap();
|
|
||||||
info.index = index;
|
|
||||||
self.update_infos(u, info);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_state(self: &mut Self, u: &T) -> State {
|
|
||||||
let info = *self.infos.get(u).unwrap();
|
|
||||||
return info.state;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_root(self: &mut Self, u: &T) -> usize {
|
|
||||||
let info = *self.infos.get(u).unwrap();
|
|
||||||
return info.root;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_index(self: &mut Self, u: &T) -> usize {
|
|
||||||
let info = *self.infos.get(u).unwrap();
|
|
||||||
return info.index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NodeInformation {
|
|
||||||
fn new() -> NodeInformation {
|
|
||||||
return NodeInformation {
|
|
||||||
root: 0,
|
|
||||||
index: 0,
|
|
||||||
state: State::UNTOUCHED,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +1 @@
|
|||||||
pub mod core;
|
pub mod core;
|
||||||
pub mod stacks;
|
|
||||||
pub mod graphs;
|
|
||||||
|
@ -2,24 +2,14 @@
|
|||||||
// IMPORTS
|
// IMPORTS
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
|
|
||||||
mod stacks;
|
extern crate ads2;
|
||||||
mod core;
|
|
||||||
mod graphs;
|
|
||||||
|
|
||||||
use graphs::graph::Graph;
|
use ads2::core::utils;
|
||||||
use graphs::tarjan::tarjan_algorithm;
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
// MAIN METHOD
|
// MAIN METHOD
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let nodes: Vec<_> = vec![1,2,3,4,5,6,7];
|
utils::greet();
|
||||||
let edges: Vec<(_, _)> = vec![(1,2), (1,3), (2,3), (3,4), (4,5), (5,2), (5,6), (5,7), (6,7)];
|
|
||||||
let gph = Graph::new(nodes, edges);
|
|
||||||
let components = tarjan_algorithm(&gph);
|
|
||||||
println!("Components:");
|
|
||||||
for component in components {
|
|
||||||
println!("{:?}", component);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1 +0,0 @@
|
|||||||
pub mod stack;
|
|
@ -1,77 +0,0 @@
|
|||||||
// ----------------------------------------------------------------
|
|
||||||
// IMPORTS
|
|
||||||
// ----------------------------------------------------------------
|
|
||||||
|
|
||||||
use crate::core::utils;
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// CLASS Stack
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
/**
|
|
||||||
A data structure for stacks
|
|
||||||
*/
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Stack<T> {
|
|
||||||
pub elements: Vec<T>,
|
|
||||||
string: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Stack<T>
|
|
||||||
where T: Clone + ToString {
|
|
||||||
/// Creates new typed instance of stack.
|
|
||||||
pub fn new() -> Stack<T> {
|
|
||||||
return Stack {
|
|
||||||
elements: Vec::new(),
|
|
||||||
string: String::from(""),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @returns number of elements in stack.
|
|
||||||
pub fn len(self: &Self) -> usize {
|
|
||||||
return self.elements.len();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// adds element to stack
|
|
||||||
pub fn push(self: &mut Self, x: T) {
|
|
||||||
self.elements.push(x.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// obtains top element of stack without removing it
|
|
||||||
pub fn top(self: &mut Self) -> T {
|
|
||||||
let n = self.len();
|
|
||||||
match self.elements.get(n-1) {
|
|
||||||
Some(element) => { return element.clone(); },
|
|
||||||
None => { panic!("Stack is empty!"); }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// obtains top element of stack and removes it
|
|
||||||
pub fn pop(self: &mut Self) -> T {
|
|
||||||
let element: T = self.top();
|
|
||||||
self.elements = utils::remove_last::<T>(&mut self.elements);
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// convert entries to strings
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn repr(self: &Self) -> Vec<String> {
|
|
||||||
return self.elements.iter()
|
|
||||||
.map(|element| element.to_string())
|
|
||||||
.collect::<Vec<String>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// String representation
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn to_string(self: &mut Self) -> String {
|
|
||||||
self.string = format!("{} |", self.repr().join("; "));
|
|
||||||
return self.string.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// &str representation
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn as_string(self: &mut Self) -> &str {
|
|
||||||
self.to_string();
|
|
||||||
return self.string.as_str();
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user