Skip to content

Commit

Permalink
Merge pull request #37 from mimuw-jnp2-rust/scc
Browse files Browse the repository at this point in the history
Strongly connected components
  • Loading branch information
mikolaj-pirog authored Jun 26, 2022
2 parents 2ede3ea + 5231615 commit a3d22a1
Show file tree
Hide file tree
Showing 8 changed files with 308 additions and 75 deletions.
22 changes: 17 additions & 5 deletions src/graph/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub struct Edge {
to: Position,
color: Color,
enabled: bool,
reversed: bool,

arrow: Mesh,
line: Mesh,
Expand Down Expand Up @@ -50,6 +51,7 @@ impl Edge {
Edge {
from,
to,
reversed: false,
color: Color::BLACK,
arrow: Edge::create_arrow(ctx, from, to),
line: Mesh::polyline(ctx, BASE_STROKE_WIDTH, &[from, to]).unwrap(),
Expand All @@ -60,20 +62,30 @@ impl Edge {
pub fn update_position(&mut self, ctx: &mut Context, from: Position, to: Position) {
self.from = from;
self.to = to;
self.arrow = Edge::create_arrow(ctx, from, to);
if !self.reversed {
self.arrow = Edge::create_arrow(ctx, from, to);
} else {
self.arrow = Edge::create_arrow(ctx, to, from);
}
self.line = Mesh::polyline(ctx, BASE_STROKE_WIDTH, &[from, to]).unwrap();
}

pub fn disable_edge(&mut self) {
pub fn reverse(&mut self) {
self.reversed = !self.reversed;
}

pub fn disable(&mut self) {
self.enabled = false;
self.color.a = 0.5;
self.color.a = 0.3;
}

pub fn enable_edge(&mut self) {
self.reset_state();
pub fn enable(&mut self) {
self.enabled = true;
self.color.a = 1.0;
}

pub fn reset_state(&mut self) {
self.reversed = false;
self.enabled = true;
self.color.a = 1.0;
}
Expand Down
18 changes: 9 additions & 9 deletions src/step_algorithms/bfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ impl EdgeStep {
impl Step for EdgeStep {
fn apply_step(&self, graph: &mut crate::graph::Graph) {
if let Some(edge) = graph.edge_weight_mut(self.idx) {
edge.enable_edge();
edge.enable();
}
}
}
Expand All @@ -69,13 +69,12 @@ pub struct Bfs {
}

impl StepAlgorithm for Bfs {
fn result<N, E, D: EdgeType>(
mut self,
graph: &Graph<N, E, D>,
start_idx: NodeIndex,
) -> StepAlgorithmResult {
fn run<N, E, D: EdgeType>(&mut self, graph: &Graph<N, E, D>, start_idx: NodeIndex) {
self.bfs(graph, start_idx);
StepAlgorithmResult::from_steps(self.steps, start_idx)
}

fn result(self) -> StepAlgorithmResult {
StepAlgorithmResult::from_steps(self.steps)
}
}

Expand Down Expand Up @@ -135,8 +134,9 @@ mod tests {
let a = graph.add_node(1);
let b = graph.add_node(2);
let edge_idx = graph.add_edge(a, b, 0);

let res = Bfs::from_graph(&graph).result(&graph, a);
let mut bfs = Bfs::from_graph(&graph);
bfs.run(&graph, a);
let res = bfs.result();

let mut desired = VecDeque::<Box<dyn Step>>::new();
desired.push_back(Box::new(NodeStep::new(a, NodeState::Queued)));
Expand Down
73 changes: 58 additions & 15 deletions src/step_algorithms/dfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,28 +58,53 @@ impl EdgeStep {
impl Step for EdgeStep {
fn apply_step(&self, graph: &mut crate::graph::Graph) {
if let Some(edge) = graph.edge_weight_mut(self.idx) {
edge.enable_edge();
edge.enable();
}
}
}

pub struct Dfs {
steps: VecDeque<Box<dyn Step>>,
states: HashMap<NodeIndex, NodeState>,
preorder: Vec<NodeIndex>,
postorder: Vec<NodeIndex>,
}

impl StepAlgorithm for Dfs {
fn result<N, E, D: EdgeType>(
mut self,
graph: &Graph<N, E, D>,
start_idx: NodeIndex,
) -> StepAlgorithmResult {
fn run<N, E, D: EdgeType>(&mut self, graph: &Graph<N, E, D>, start_idx: NodeIndex) {
self.dfs(graph, start_idx);
StepAlgorithmResult::from_steps(self.steps, start_idx)
}

fn result(self) -> StepAlgorithmResult {
StepAlgorithmResult::from_steps(self.into_steps())
}
}

impl Dfs {
pub fn states(&self) -> &HashMap<NodeIndex, NodeState> {
&self.states
}

pub fn _preorder(&self) -> &Vec<NodeIndex> {
&self.preorder
}

pub fn postorder(&self) -> &Vec<NodeIndex> {
&self.postorder
}

pub fn postorder_mut(&mut self) -> &mut Vec<NodeIndex> {
&mut self.postorder
}

pub fn into_steps(self) -> VecDeque<Box<dyn Step>> {
self.steps
}

pub fn steps_mut(&mut self) -> &mut VecDeque<Box<dyn Step>> {
&mut self.steps
}

pub fn from_graph<N, E, D: EdgeType>(graph: &Graph<N, E, D>) -> Dfs {
let mut states = HashMap::new();
for index in graph.node_indices() {
Expand All @@ -88,28 +113,42 @@ impl Dfs {
Dfs {
steps: VecDeque::new(),
states,
preorder: Vec::new(),
postorder: Vec::new(),
}
}

fn dfs<N, E, D: EdgeType>(&mut self, graph: &Graph<N, E, D>, start_idx: NodeIndex) {
self.dfs_helper(graph, start_idx);
fn dfs<N, E, D: EdgeType>(&mut self, graph: &Graph<N, E, D>, node_index: NodeIndex) {
self.dfs_helper(graph, node_index, Direction::Outgoing);
}

fn dfs_helper<N, E, D: EdgeType>(&mut self, graph: &Graph<N, E, D>, node_index: NodeIndex) {
pub fn dfs_reversed<N, E, D: EdgeType>(
&mut self,
graph: &Graph<N, E, D>,
node_index: NodeIndex,
) {
self.dfs_helper(graph, node_index, Direction::Incoming);
}

fn dfs_helper<N, E, D: EdgeType>(
&mut self,
graph: &Graph<N, E, D>,
node_index: NodeIndex,
direction: Direction,
) {
self.steps
.push_back(Box::new(NodeStep::new(node_index, NodeState::Queued)));

self.states.insert(node_index, NodeState::Queued);
self.preorder.push(node_index);

let mut walker = graph
.neighbors_directed(node_index, Direction::Outgoing)
.detach();
let mut walker = graph.neighbors_directed(node_index, direction).detach();

while let Some((edge_idx, other_node_idx)) = walker.next(graph) {
if let Some(other_state) = self.states.get(&other_node_idx) {
if matches!(other_state, NodeState::NotVisited) {
self.steps.push_back(Box::new(EdgeStep::new(edge_idx)));
self.dfs_helper(graph, other_node_idx);
self.dfs_helper(graph, other_node_idx, direction);
}
}
}
Expand All @@ -118,6 +157,7 @@ impl Dfs {
.push_back(Box::new(NodeStep::new(node_index, NodeState::Visited)));

self.states.insert(node_index, NodeState::Visited);
self.postorder.push(node_index);
}
}

Expand All @@ -138,7 +178,10 @@ mod tests {
let b = graph.add_node(N::default());
let edge_idx = graph.add_edge(a, b, E::default());

let res = Dfs::from_graph(&graph).result(&graph, a);
let mut dfs = Dfs::from_graph(&graph);
dfs.run(&graph, a);

let res = dfs.result();

let mut desired = VecDeque::<Box<dyn Step>>::new();
desired.push_back(Box::new(NodeStep::new(a, NodeState::Queued)));
Expand Down
2 changes: 2 additions & 0 deletions src/step_algorithms/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
mod bfs;
mod dfs;
mod scc;
mod step_algorithm;
mod timer;

pub use bfs::Bfs;
pub use dfs::Dfs;
pub use scc::Scc;
pub use step_algorithm::{DirectedStepAlgorithm, UndirectedStepAlgorithm};
pub use step_algorithm::{StepAlgorithm, StepAlgorithmResult};
pub use timer::Timer;
Loading

0 comments on commit a3d22a1

Please sign in to comment.