#![forbid(unsafe_code)]
#![warn(missing_docs)]
pub extern crate petgraph;
use petgraph as pg;
use petgraph::graph::{DefIndex, GraphIndex, IndexType};
use std::marker::PhantomData;
use std::ops::{Index, IndexMut};
pub use petgraph::graph::{EdgeIndex, NodeIndex, EdgeWeightsMut, NodeWeightsMut};
pub use walker::Walker;
pub mod walker;
pub type PetGraph<N, E, Ix> = pg::Graph<N, E, pg::Directed, Ix>;
pub type RawNodes<'a, N, Ix> = &'a [pg::graph::Node<N, Ix>];
pub type RawEdges<'a, E, Ix> = &'a [pg::graph::Edge<E, Ix>];
#[derive(Clone, Debug)]
pub struct Dag<N, E, Ix: IndexType = DefIndex> {
graph: PetGraph<N, E, Ix>,
}
pub struct Children<N, E, Ix: IndexType> {
walk_edges: pg::graph::WalkEdges<Ix>,
_node: PhantomData<N>,
_edge: PhantomData<E>,
}
pub struct Parents<N, E, Ix: IndexType> {
walk_edges: pg::graph::WalkEdges<Ix>,
_node: PhantomData<N>,
_edge: PhantomData<E>,
}
pub struct EdgeIndices<Ix: IndexType> {
indices: ::std::ops::Range<usize>,
_phantom: PhantomData<Ix>,
}
pub type RecursiveWalk<N, E, Ix, F> = walker::Recursive<Dag<N, E, Ix>, Ix, F>;
#[derive(Copy, Clone, Debug)]
pub struct WouldCycle<E>(pub E);
impl<N, E, Ix> Dag<N, E, Ix> where Ix: IndexType {
pub fn new() -> Self {
Self::with_capacity(1, 1)
}
pub fn with_capacity(nodes: usize, edges: usize) -> Self {
Dag { graph: PetGraph::with_capacity(nodes, edges) }
}
pub fn clear(&mut self) {
self.graph.clear();
}
pub fn node_count(&self) -> usize {
self.graph.node_count()
}
pub fn edge_count(&self) -> usize {
self.graph.edge_count()
}
pub fn graph(&self) -> &PetGraph<N, E, Ix> {
&self.graph
}
pub fn into_graph(self) -> PetGraph<N, E, Ix> {
let Dag { graph } = self;
graph
}
pub fn add_node(&mut self, weight: N) -> NodeIndex<Ix> {
self.graph.add_node(weight)
}
pub fn add_edge(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>, weight: E)
-> Result<EdgeIndex<Ix>, WouldCycle<E>>
{
let should_check_for_cycle = must_check_for_cycle(self, a, b);
let idx = self.graph.add_edge(a, b, weight);
if should_check_for_cycle && pg::algo::is_cyclic_directed(&self.graph) {
let weight = self.graph.remove_edge(idx).expect("No edge for index");
Err(WouldCycle(weight))
} else {
Ok(idx)
}
}
pub fn add_edges<I>(&mut self, edges: I) -> Result<EdgeIndices<Ix>, WouldCycle<Vec<E>>> where
I: IntoIterator<Item=(NodeIndex<Ix>, NodeIndex<Ix>, E)>,
{
let mut num_edges = 0;
let mut should_check_for_cycle = false;
for (a, b, weight) in edges {
if !should_check_for_cycle {
if must_check_for_cycle(self, a, b) {
should_check_for_cycle = true;
}
}
self.graph.add_edge(a, b, weight);
num_edges += 1;
}
let total_edges = self.edge_count();
let new_edges_range = total_edges-num_edges..total_edges;
if should_check_for_cycle && pg::algo::is_cyclic_directed(&self.graph) {
let removed_edges = new_edges_range.rev().filter_map(|i| {
let idx = EdgeIndex::new(i);
self.graph.remove_edge(idx)
});
Err(WouldCycle(removed_edges.collect()))
} else {
Ok(EdgeIndices { indices: new_edges_range, _phantom: ::std::marker::PhantomData, })
}
}
pub fn update_edge(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>, weight: E)
-> Result<EdgeIndex<Ix>, WouldCycle<E>>
{
if let Some(edge_idx) = self.find_edge(a, b) {
if let Some(edge) = self.edge_weight_mut(edge_idx) {
*edge = weight;
return Ok(edge_idx);
}
}
self.add_edge(a, b, weight)
}
pub fn find_edge(&self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> Option<EdgeIndex<Ix>> {
self.graph.find_edge(a, b)
}
pub fn edge_endpoints(&self, e: EdgeIndex<Ix>) -> Option<(NodeIndex<Ix>, NodeIndex<Ix>)> {
self.graph.edge_endpoints(e)
}
pub fn clear_edges(&mut self) {
self.graph.clear_edges()
}
pub fn add_parent(&mut self, child: NodeIndex<Ix>, edge: E, node: N)
-> (EdgeIndex<Ix>, NodeIndex<Ix>)
{
let parent_node = self.graph.add_node(node);
let parent_edge = self.graph.add_edge(parent_node, child, edge);
(parent_edge, parent_node)
}
pub fn add_child(&mut self, parent: NodeIndex<Ix>, edge: E, node: N)
-> (EdgeIndex<Ix>, NodeIndex<Ix>)
{
let child_node = self.graph.add_node(node);
let child_edge = self.graph.add_edge(parent, child_node, edge);
(child_edge, child_node)
}
pub fn node_weight(&self, node: NodeIndex<Ix>) -> Option<&N> {
self.graph.node_weight(node)
}
pub fn node_weight_mut(&mut self, node: NodeIndex<Ix>) -> Option<&mut N> {
self.graph.node_weight_mut(node)
}
pub fn raw_nodes(&self) -> RawNodes<N, Ix> {
self.graph.raw_nodes()
}
pub fn node_weights_mut(&mut self) -> NodeWeightsMut<N, Ix> {
self.graph.node_weights_mut()
}
pub fn edge_weight(&self, edge: EdgeIndex<Ix>) -> Option<&E> {
self.graph.edge_weight(edge)
}
pub fn edge_weight_mut(&mut self, edge: EdgeIndex<Ix>) -> Option<&mut E> {
self.graph.edge_weight_mut(edge)
}
pub fn raw_edges(&self) -> RawEdges<E, Ix> {
self.graph.raw_edges()
}
pub fn edge_weights_mut(&mut self) -> EdgeWeightsMut<E, Ix> {
self.graph.edge_weights_mut()
}
pub fn index_twice_mut<A, B>(&mut self, a: A, b: B)
-> (&mut <PetGraph<N, E, Ix> as Index<A>>::Output,
&mut <PetGraph<N, E, Ix> as Index<B>>::Output) where
PetGraph<N, E, Ix>: IndexMut<A> + IndexMut<B>,
A: GraphIndex,
B: GraphIndex,
{
self.graph.index_twice_mut(a, b)
}
pub fn remove_node(&mut self, node: NodeIndex<Ix>) -> Option<N> {
self.graph.remove_node(node)
}
pub fn remove_edge(&mut self, e: EdgeIndex<Ix>) -> Option<E> {
self.graph.remove_edge(e)
}
pub fn parents(&self, child: NodeIndex<Ix>) -> Parents<N, E, Ix> {
let walk_edges = self.graph.walk_edges_directed(child, pg::Incoming);
Parents {
walk_edges: walk_edges,
_node: PhantomData,
_edge: PhantomData,
}
}
pub fn children(&self, parent: NodeIndex<Ix>) -> Children<N, E, Ix> {
let walk_edges = self.graph.walk_edges_directed(parent, pg::Outgoing);
Children {
walk_edges: walk_edges,
_node: PhantomData,
_edge: PhantomData,
}
}
pub fn recursive_walk<F>(&self, start: NodeIndex<Ix>, recursive_fn: F)
-> RecursiveWalk<N, E, Ix, F>
where F: FnMut(&Self, NodeIndex<Ix>) -> Option<(EdgeIndex<Ix>, NodeIndex<Ix>)>
{
walker::Recursive::new(start, recursive_fn)
}
}
fn must_check_for_cycle<N, E, Ix>(dag: &Dag<N, E, Ix>, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> bool
where Ix: IndexType,
{
dag.parents(a).next(dag).is_some() && dag.children(b).next(dag).is_some()
&& dag.find_edge(a, b).is_none()
}
impl<N, E, Ix> Index<NodeIndex<Ix>> for Dag<N, E, Ix> where Ix: IndexType {
type Output = N;
fn index(&self, index: NodeIndex<Ix>) -> &N {
&self.graph[index]
}
}
impl<N, E, Ix> IndexMut<NodeIndex<Ix>> for Dag<N, E, Ix> where Ix: IndexType {
fn index_mut(&mut self, index: NodeIndex<Ix>) -> &mut N {
&mut self.graph[index]
}
}
impl<N, E, Ix> Index<EdgeIndex<Ix>> for Dag<N, E, Ix> where Ix: IndexType {
type Output = E;
fn index(&self, index: EdgeIndex<Ix>) -> &E {
&self.graph[index]
}
}
impl<N, E, Ix> IndexMut<EdgeIndex<Ix>> for Dag<N, E, Ix> where Ix: IndexType {
fn index_mut(&mut self, index: EdgeIndex<Ix>) -> &mut E {
&mut self.graph[index]
}
}
impl<N, E, Ix> Walker<Dag<N, E, Ix>> for Children<N, E, Ix>
where Ix: IndexType,
{
type Index = Ix;
#[inline]
fn next(&mut self, dag: &Dag<N, E, Ix>) -> Option<(EdgeIndex<Ix>, NodeIndex<Ix>)> {
self.walk_edges.next_neighbor(&dag.graph)
}
}
impl<N, E, Ix> Walker<Dag<N, E, Ix>> for Parents<N, E, Ix>
where Ix: IndexType,
{
type Index = Ix;
#[inline]
fn next(&mut self, dag: &Dag<N, E, Ix>) -> Option<(EdgeIndex<Ix>, NodeIndex<Ix>)> {
self.walk_edges.next_neighbor(&dag.graph)
}
}
impl<Ix> Iterator for EdgeIndices<Ix> where Ix: IndexType {
type Item = EdgeIndex<Ix>;
fn next(&mut self) -> Option<EdgeIndex<Ix>> {
self.indices.next().map(|i| EdgeIndex::new(i))
}
}
impl<E> ::std::fmt::Display for WouldCycle<E> where E: ::std::fmt::Debug {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
writeln!(f, "{:?}", self)
}
}
impl<E> ::std::error::Error for WouldCycle<E> where E: ::std::fmt::Debug + ::std::any::Any {
fn description(&self) -> &str {
"Adding this input would have caused the graph to cycle!"
}
}