Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

314
vendor/petgraph/src/visit/dfsvisit.rs vendored Normal file
View File

@@ -0,0 +1,314 @@
use crate::visit::IntoNeighbors;
use crate::visit::{VisitMap, Visitable};
/// Strictly monotonically increasing event time for a depth first search.
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Default, Hash)]
pub struct Time(pub usize);
/// A depth first search (DFS) visitor event.
#[derive(Copy, Clone, Debug)]
pub enum DfsEvent<N> {
Discover(N, Time),
/// An edge of the tree formed by the traversal.
TreeEdge(N, N),
/// An edge to an already visited node.
BackEdge(N, N),
/// A cross or forward edge.
///
/// For an edge *(u, v)*, if the discover time of *v* is greater than *u*,
/// then it is a forward edge, else a cross edge.
CrossForwardEdge(N, N),
/// All edges from a node have been reported.
Finish(N, Time),
}
/// Return if the expression is a break value, execute the provided statement
/// if it is a prune value.
macro_rules! try_control {
($e:expr, $p:stmt) => {
try_control!($e, $p, ());
};
($e:expr, $p:stmt, $q:stmt) => {
match $e {
x => {
if x.should_break() {
return x;
} else if x.should_prune() {
$p
} else {
$q
}
}
}
};
}
/// Control flow for `depth_first_search` callbacks.
#[derive(Copy, Clone, Debug)]
pub enum Control<B> {
/// Continue the DFS traversal as normal.
Continue,
/// Prune the current node from the DFS traversal. No more edges from this
/// node will be reported to the callback. A `DfsEvent::Finish` for this
/// node will still be reported. This can be returned in response to any
/// `DfsEvent`, except `Finish`, which will panic.
Prune,
/// Stop the DFS traversal and return the provided value.
Break(B),
}
impl<B> Control<B> {
pub fn breaking() -> Control<()> {
Control::Break(())
}
/// Get the value in `Control::Break(_)`, if present.
pub fn break_value(self) -> Option<B> {
match self {
Control::Continue | Control::Prune => None,
Control::Break(b) => Some(b),
}
}
}
/// Control flow for callbacks.
///
/// The empty return value `()` is equivalent to continue.
pub trait ControlFlow {
fn continuing() -> Self;
fn should_break(&self) -> bool;
fn should_prune(&self) -> bool;
}
impl ControlFlow for () {
fn continuing() {}
#[inline]
fn should_break(&self) -> bool {
false
}
#[inline]
fn should_prune(&self) -> bool {
false
}
}
impl<B> ControlFlow for Control<B> {
fn continuing() -> Self {
Control::Continue
}
fn should_break(&self) -> bool {
if let Control::Break(_) = *self {
true
} else {
false
}
}
fn should_prune(&self) -> bool {
match *self {
Control::Prune => true,
Control::Continue | Control::Break(_) => false,
}
}
}
impl<C: ControlFlow, E> ControlFlow for Result<C, E> {
fn continuing() -> Self {
Ok(C::continuing())
}
fn should_break(&self) -> bool {
if let Ok(ref c) = *self {
c.should_break()
} else {
true
}
}
fn should_prune(&self) -> bool {
if let Ok(ref c) = *self {
c.should_prune()
} else {
false
}
}
}
/// The default is `Continue`.
impl<B> Default for Control<B> {
fn default() -> Self {
Control::Continue
}
}
/// A recursive depth first search.
///
/// Starting points are the nodes in the iterator `starts` (specify just one
/// start vertex *x* by using `Some(x)`).
///
/// The traversal emits discovery and finish events for each reachable vertex,
/// and edge classification of each reachable edge. `visitor` is called for each
/// event, see [`DfsEvent`][de] for possible values.
///
/// The return value should implement the trait `ControlFlow`, and can be used to change
/// the control flow of the search.
///
/// `Control` Implements `ControlFlow` such that `Control::Continue` resumes the search.
/// `Control::Break` will stop the visit early, returning the contained value.
/// `Control::Prune` will stop traversing any additional edges from the current
/// node and proceed immediately to the `Finish` event.
///
/// There are implementations of `ControlFlow` for `()`, and `Result<C, E>` where
/// `C: ControlFlow`. The implementation for `()` will continue until finished.
/// For `Result`, upon encountering an `E` it will break, otherwise acting the same as `C`.
///
/// ***Panics** if you attempt to prune a node from its `Finish` event.
///
/// [de]: enum.DfsEvent.html
///
/// # Example returning `Control`.
///
/// Find a path from vertex 0 to 5, and exit the visit as soon as we reach
/// the goal vertex.
///
/// ```
/// use petgraph::prelude::*;
/// use petgraph::graph::node_index as n;
/// use petgraph::visit::depth_first_search;
/// use petgraph::visit::{DfsEvent, Control};
///
/// let gr: Graph<(), ()> = Graph::from_edges(&[
/// (0, 1), (0, 2), (0, 3),
/// (1, 3),
/// (2, 3), (2, 4),
/// (4, 0), (4, 5),
/// ]);
///
/// // record each predecessor, mapping node → node
/// let mut predecessor = vec![NodeIndex::end(); gr.node_count()];
/// let start = n(0);
/// let goal = n(5);
/// depth_first_search(&gr, Some(start), |event| {
/// if let DfsEvent::TreeEdge(u, v) = event {
/// predecessor[v.index()] = u;
/// if v == goal {
/// return Control::Break(v);
/// }
/// }
/// Control::Continue
/// });
///
/// let mut next = goal;
/// let mut path = vec![next];
/// while next != start {
/// let pred = predecessor[next.index()];
/// path.push(pred);
/// next = pred;
/// }
/// path.reverse();
/// assert_eq!(&path, &[n(0), n(2), n(4), n(5)]);
/// ```
///
/// # Example returning a `Result`.
/// ```
/// use petgraph::graph::node_index as n;
/// use petgraph::prelude::*;
/// use petgraph::visit::depth_first_search;
/// use petgraph::visit::{DfsEvent, Time};
///
/// let gr: Graph<(), ()> = Graph::from_edges(&[(0, 1), (1, 2), (1, 1), (2, 1)]);
/// let start = n(0);
/// let mut back_edges = 0;
/// let mut discover_time = 0;
/// // Stop the search, the first time a BackEdge is encountered.
/// let result = depth_first_search(&gr, Some(start), |event| {
/// match event {
/// // In the cases where Ok(()) is returned,
/// // Result falls back to the implementation of Control on the value ().
/// // In the case of (), this is to always return Control::Continue.
/// // continuing the search.
/// DfsEvent::Discover(_, Time(t)) => {
/// discover_time = t;
/// Ok(())
/// }
/// DfsEvent::BackEdge(_, _) => {
/// back_edges += 1;
/// // the implementation of ControlFlow for Result,
/// // treats this Err value as Continue::Break
/// Err(event)
/// }
/// _ => Ok(()),
/// }
/// });
///
/// // Even though the graph has more than one cycle,
/// // The number of back_edges visited by the search should always be 1.
/// assert_eq!(back_edges, 1);
/// println!("discover time:{:?}", discover_time);
/// println!("number of backedges encountered: {}", back_edges);
/// println!("back edge: {:?}", result);
/// ```
pub fn depth_first_search<G, I, F, C>(graph: G, starts: I, mut visitor: F) -> C
where
G: IntoNeighbors + Visitable,
I: IntoIterator<Item = G::NodeId>,
F: FnMut(DfsEvent<G::NodeId>) -> C,
C: ControlFlow,
{
let time = &mut Time(0);
let discovered = &mut graph.visit_map();
let finished = &mut graph.visit_map();
for start in starts {
try_control!(
dfs_visitor(graph, start, &mut visitor, discovered, finished, time),
unreachable!()
);
}
C::continuing()
}
pub(crate) fn dfs_visitor<G, F, C>(
graph: G,
u: G::NodeId,
visitor: &mut F,
discovered: &mut impl VisitMap<G::NodeId>,
finished: &mut impl VisitMap<G::NodeId>,
time: &mut Time,
) -> C
where
G: IntoNeighbors + Visitable,
F: FnMut(DfsEvent<G::NodeId>) -> C,
C: ControlFlow,
{
if !discovered.visit(u) {
return C::continuing();
}
try_control!(
visitor(DfsEvent::Discover(u, time_post_inc(time))),
{},
for v in graph.neighbors(u) {
if !discovered.is_visited(&v) {
try_control!(visitor(DfsEvent::TreeEdge(u, v)), continue);
try_control!(
dfs_visitor(graph, v, visitor, discovered, finished, time),
unreachable!()
);
} else if !finished.is_visited(&v) {
try_control!(visitor(DfsEvent::BackEdge(u, v)), continue);
} else {
try_control!(visitor(DfsEvent::CrossForwardEdge(u, v)), continue);
}
}
);
let first_finish = finished.visit(u);
debug_assert!(first_finish);
try_control!(
visitor(DfsEvent::Finish(u, time_post_inc(time))),
panic!("Pruning on the `DfsEvent::Finish` is not supported!")
);
C::continuing()
}
fn time_post_inc(x: &mut Time) -> Time {
let v = *x;
x.0 += 1;
v
}

583
vendor/petgraph/src/visit/filter.rs vendored Normal file
View File

@@ -0,0 +1,583 @@
use crate::prelude::*;
use fixedbitset::FixedBitSet;
use std::collections::HashSet;
use std::marker::PhantomData;
use crate::data::DataMap;
use crate::visit::{Data, NodeCompactIndexable, NodeCount};
use crate::visit::{
EdgeIndexable, GraphBase, GraphProp, IntoEdgeReferences, IntoEdges, IntoEdgesDirected,
IntoNeighbors, IntoNeighborsDirected, IntoNodeIdentifiers, IntoNodeReferences, NodeIndexable,
NodeRef, VisitMap, Visitable,
};
/// A graph filter for nodes.
pub trait FilterNode<N> {
/// Return true to have the node be part of the graph
fn include_node(&self, node: N) -> bool;
}
impl<F, N> FilterNode<N> for F
where
F: Fn(N) -> bool,
{
fn include_node(&self, n: N) -> bool {
(*self)(n)
}
}
/// This filter includes the nodes that are contained in the set.
impl<N> FilterNode<N> for FixedBitSet
where
FixedBitSet: VisitMap<N>,
{
fn include_node(&self, n: N) -> bool {
self.is_visited(&n)
}
}
/// This filter includes the nodes that are contained in the set.
impl<N, S> FilterNode<N> for HashSet<N, S>
where
HashSet<N, S>: VisitMap<N>,
{
fn include_node(&self, n: N) -> bool {
self.is_visited(&n)
}
}
// Can't express these as a generic impl over all references since that would conflict with the
// impl for Fn.
impl<N> FilterNode<N> for &FixedBitSet
where
FixedBitSet: VisitMap<N>,
{
fn include_node(&self, n: N) -> bool {
self.is_visited(&n)
}
}
impl<N, S> FilterNode<N> for &HashSet<N, S>
where
HashSet<N, S>: VisitMap<N>,
{
fn include_node(&self, n: N) -> bool {
self.is_visited(&n)
}
}
/// A node-filtering graph adaptor.
#[derive(Copy, Clone, Debug)]
pub struct NodeFiltered<G, F>(pub G, pub F);
impl<F, G> NodeFiltered<G, F>
where
G: GraphBase,
F: Fn(G::NodeId) -> bool,
{
/// Create an `NodeFiltered` adaptor from the closure `filter`.
pub fn from_fn(graph: G, filter: F) -> Self {
NodeFiltered(graph, filter)
}
}
impl<G, F> GraphBase for NodeFiltered<G, F>
where
G: GraphBase,
{
type NodeId = G::NodeId;
type EdgeId = G::EdgeId;
}
impl<'a, G, F> IntoNeighbors for &'a NodeFiltered<G, F>
where
G: IntoNeighbors,
F: FilterNode<G::NodeId>,
{
type Neighbors = NodeFilteredNeighbors<'a, G::Neighbors, F>;
fn neighbors(self, n: G::NodeId) -> Self::Neighbors {
NodeFilteredNeighbors {
include_source: self.1.include_node(n),
iter: self.0.neighbors(n),
f: &self.1,
}
}
}
/// A filtered neighbors iterator.
#[derive(Debug, Clone)]
pub struct NodeFilteredNeighbors<'a, I, F: 'a> {
include_source: bool,
iter: I,
f: &'a F,
}
impl<I, F> Iterator for NodeFilteredNeighbors<'_, I, F>
where
I: Iterator,
I::Item: Copy,
F: FilterNode<I::Item>,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
let f = self.f;
if !self.include_source {
None
} else {
self.iter.find(move |&target| f.include_node(target))
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (_, upper) = self.iter.size_hint();
(0, upper)
}
}
impl<'a, G, F> IntoNeighborsDirected for &'a NodeFiltered<G, F>
where
G: IntoNeighborsDirected,
F: FilterNode<G::NodeId>,
{
type NeighborsDirected = NodeFilteredNeighbors<'a, G::NeighborsDirected, F>;
fn neighbors_directed(self, n: G::NodeId, dir: Direction) -> Self::NeighborsDirected {
NodeFilteredNeighbors {
include_source: self.1.include_node(n),
iter: self.0.neighbors_directed(n, dir),
f: &self.1,
}
}
}
impl<'a, G, F> IntoNodeIdentifiers for &'a NodeFiltered<G, F>
where
G: IntoNodeIdentifiers,
F: FilterNode<G::NodeId>,
{
type NodeIdentifiers = NodeFilteredNeighbors<'a, G::NodeIdentifiers, F>;
fn node_identifiers(self) -> Self::NodeIdentifiers {
NodeFilteredNeighbors {
include_source: true,
iter: self.0.node_identifiers(),
f: &self.1,
}
}
}
impl<'a, G, F> IntoNodeReferences for &'a NodeFiltered<G, F>
where
G: IntoNodeReferences,
F: FilterNode<G::NodeId>,
{
type NodeRef = G::NodeRef;
type NodeReferences = NodeFilteredNodes<'a, G::NodeReferences, F>;
fn node_references(self) -> Self::NodeReferences {
NodeFilteredNodes {
include_source: true,
iter: self.0.node_references(),
f: &self.1,
}
}
}
/// A filtered node references iterator.
#[derive(Debug, Clone)]
pub struct NodeFilteredNodes<'a, I, F: 'a> {
include_source: bool,
iter: I,
f: &'a F,
}
impl<I, F> Iterator for NodeFilteredNodes<'_, I, F>
where
I: Iterator,
I::Item: Copy + NodeRef,
F: FilterNode<<I::Item as NodeRef>::NodeId>,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
let f = self.f;
if !self.include_source {
None
} else {
self.iter.find(move |&target| f.include_node(target.id()))
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (_, upper) = self.iter.size_hint();
(0, upper)
}
}
impl<'a, G, F> IntoEdgeReferences for &'a NodeFiltered<G, F>
where
G: IntoEdgeReferences,
F: FilterNode<G::NodeId>,
{
type EdgeRef = G::EdgeRef;
type EdgeReferences = NodeFilteredEdgeReferences<'a, G, G::EdgeReferences, F>;
fn edge_references(self) -> Self::EdgeReferences {
NodeFilteredEdgeReferences {
graph: PhantomData,
iter: self.0.edge_references(),
f: &self.1,
}
}
}
/// A filtered edges iterator.
#[derive(Debug, Clone)]
pub struct NodeFilteredEdgeReferences<'a, G, I, F: 'a> {
graph: PhantomData<G>,
iter: I,
f: &'a F,
}
impl<G, I, F> Iterator for NodeFilteredEdgeReferences<'_, G, I, F>
where
F: FilterNode<G::NodeId>,
G: IntoEdgeReferences,
I: Iterator<Item = G::EdgeRef>,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
let f = self.f;
self.iter
.find(move |&edge| f.include_node(edge.source()) && f.include_node(edge.target()))
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (_, upper) = self.iter.size_hint();
(0, upper)
}
}
impl<'a, G, F> IntoEdges for &'a NodeFiltered<G, F>
where
G: IntoEdges,
F: FilterNode<G::NodeId>,
{
type Edges = NodeFilteredEdges<'a, G, G::Edges, F>;
fn edges(self, a: G::NodeId) -> Self::Edges {
NodeFilteredEdges {
graph: PhantomData,
include_source: self.1.include_node(a),
iter: self.0.edges(a),
f: &self.1,
dir: Direction::Outgoing,
}
}
}
impl<'a, G, F> IntoEdgesDirected for &'a NodeFiltered<G, F>
where
G: IntoEdgesDirected,
F: FilterNode<G::NodeId>,
{
type EdgesDirected = NodeFilteredEdges<'a, G, G::EdgesDirected, F>;
fn edges_directed(self, a: G::NodeId, dir: Direction) -> Self::EdgesDirected {
NodeFilteredEdges {
graph: PhantomData,
include_source: self.1.include_node(a),
iter: self.0.edges_directed(a, dir),
f: &self.1,
dir,
}
}
}
/// A filtered edges iterator.
#[derive(Debug, Clone)]
pub struct NodeFilteredEdges<'a, G, I, F: 'a> {
graph: PhantomData<G>,
include_source: bool,
iter: I,
f: &'a F,
dir: Direction,
}
impl<G, I, F> Iterator for NodeFilteredEdges<'_, G, I, F>
where
F: FilterNode<G::NodeId>,
G: IntoEdges,
I: Iterator<Item = G::EdgeRef>,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
if !self.include_source {
None
} else {
let dir = self.dir;
let f = self.f;
self.iter.find(move |&edge| {
f.include_node(match dir {
Direction::Outgoing => edge.target(),
Direction::Incoming => edge.source(),
})
})
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (_, upper) = self.iter.size_hint();
(0, upper)
}
}
impl<G, F> DataMap for NodeFiltered<G, F>
where
G: DataMap,
F: FilterNode<G::NodeId>,
{
fn node_weight(&self, id: Self::NodeId) -> Option<&Self::NodeWeight> {
if self.1.include_node(id) {
self.0.node_weight(id)
} else {
None
}
}
fn edge_weight(&self, id: Self::EdgeId) -> Option<&Self::EdgeWeight> {
self.0.edge_weight(id)
}
}
macro_rules! access0 {
($e:expr) => {
$e.0
};
}
Data! {delegate_impl [[G, F], G, NodeFiltered<G, F>, access0]}
NodeIndexable! {delegate_impl [[G, F], G, NodeFiltered<G, F>, access0]}
EdgeIndexable! {delegate_impl [[G, F], G, NodeFiltered<G, F>, access0]}
GraphProp! {delegate_impl [[G, F], G, NodeFiltered<G, F>, access0]}
Visitable! {delegate_impl [[G, F], G, NodeFiltered<G, F>, access0]}
/// A graph filter for edges
pub trait FilterEdge<Edge> {
/// Return true to have the edge be part of the graph
fn include_edge(&self, edge: Edge) -> bool;
}
impl<F, N> FilterEdge<N> for F
where
F: Fn(N) -> bool,
{
fn include_edge(&self, n: N) -> bool {
(*self)(n)
}
}
/// An edge-filtering graph adaptor.
///
/// The adaptor may filter out edges. The filter implements the trait
/// `FilterEdge`. Closures of type `Fn(G::EdgeRef) -> bool` already
/// implement this trait.
///
/// The filter may use edge source, target, id, and weight to select whether to
/// include the edge or not.
#[derive(Copy, Clone, Debug)]
pub struct EdgeFiltered<G, F>(pub G, pub F);
impl<F, G> EdgeFiltered<G, F>
where
G: IntoEdgeReferences,
F: Fn(G::EdgeRef) -> bool,
{
/// Create an `EdgeFiltered` adaptor from the closure `filter`.
pub fn from_fn(graph: G, filter: F) -> Self {
EdgeFiltered(graph, filter)
}
}
impl<G, F> GraphBase for EdgeFiltered<G, F>
where
G: GraphBase,
{
type NodeId = G::NodeId;
type EdgeId = G::EdgeId;
}
impl<'a, G, F> IntoNeighbors for &'a EdgeFiltered<G, F>
where
G: IntoEdges,
F: FilterEdge<G::EdgeRef>,
{
type Neighbors = EdgeFilteredNeighbors<'a, G, F>;
fn neighbors(self, n: G::NodeId) -> Self::Neighbors {
EdgeFilteredNeighbors {
iter: self.0.edges(n),
f: &self.1,
}
}
}
impl<'a, G, F> IntoNeighborsDirected for &'a EdgeFiltered<G, F>
where
G: IntoEdgesDirected,
F: FilterEdge<G::EdgeRef>,
{
type NeighborsDirected = EdgeFilteredNeighborsDirected<'a, G, F>;
fn neighbors_directed(self, n: G::NodeId, dir: Direction) -> Self::NeighborsDirected {
EdgeFilteredNeighborsDirected {
iter: self.0.edges_directed(n, dir),
f: &self.1,
from: n,
}
}
}
/// A filtered neighbors iterator.
#[derive(Debug, Clone)]
pub struct EdgeFilteredNeighbors<'a, G, F: 'a>
where
G: IntoEdges,
{
iter: G::Edges,
f: &'a F,
}
impl<G, F> Iterator for EdgeFilteredNeighbors<'_, G, F>
where
F: FilterEdge<G::EdgeRef>,
G: IntoEdges,
{
type Item = G::NodeId;
fn next(&mut self) -> Option<Self::Item> {
let f = self.f;
(&mut self.iter)
.filter_map(move |edge| {
if f.include_edge(edge) {
Some(edge.target())
} else {
None
}
})
.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (_, upper) = self.iter.size_hint();
(0, upper)
}
}
impl<'a, G, F> IntoEdgeReferences for &'a EdgeFiltered<G, F>
where
G: IntoEdgeReferences,
F: FilterEdge<G::EdgeRef>,
{
type EdgeRef = G::EdgeRef;
type EdgeReferences = EdgeFilteredEdges<'a, G, G::EdgeReferences, F>;
fn edge_references(self) -> Self::EdgeReferences {
EdgeFilteredEdges {
graph: PhantomData,
iter: self.0.edge_references(),
f: &self.1,
}
}
}
impl<'a, G, F> IntoEdges for &'a EdgeFiltered<G, F>
where
G: IntoEdges,
F: FilterEdge<G::EdgeRef>,
{
type Edges = EdgeFilteredEdges<'a, G, G::Edges, F>;
fn edges(self, n: G::NodeId) -> Self::Edges {
EdgeFilteredEdges {
graph: PhantomData,
iter: self.0.edges(n),
f: &self.1,
}
}
}
impl<'a, G, F> IntoEdgesDirected for &'a EdgeFiltered<G, F>
where
G: IntoEdgesDirected,
F: FilterEdge<G::EdgeRef>,
{
type EdgesDirected = EdgeFilteredEdges<'a, G, G::EdgesDirected, F>;
fn edges_directed(self, n: G::NodeId, dir: Direction) -> Self::EdgesDirected {
EdgeFilteredEdges {
graph: PhantomData,
iter: self.0.edges_directed(n, dir),
f: &self.1,
}
}
}
/// A filtered edges iterator.
#[derive(Debug, Clone)]
pub struct EdgeFilteredEdges<'a, G, I, F: 'a> {
graph: PhantomData<G>,
iter: I,
f: &'a F,
}
impl<G, I, F> Iterator for EdgeFilteredEdges<'_, G, I, F>
where
F: FilterEdge<G::EdgeRef>,
G: IntoEdgeReferences,
I: Iterator<Item = G::EdgeRef>,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
let f = self.f;
self.iter.find(move |&edge| f.include_edge(edge))
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (_, upper) = self.iter.size_hint();
(0, upper)
}
}
/// A filtered neighbors-directed iterator.
#[derive(Debug, Clone)]
pub struct EdgeFilteredNeighborsDirected<'a, G, F: 'a>
where
G: IntoEdgesDirected,
{
iter: G::EdgesDirected,
f: &'a F,
from: G::NodeId,
}
impl<G, F> Iterator for EdgeFilteredNeighborsDirected<'_, G, F>
where
F: FilterEdge<G::EdgeRef>,
G: IntoEdgesDirected,
{
type Item = G::NodeId;
fn next(&mut self) -> Option<Self::Item> {
let f = self.f;
let from = self.from;
(&mut self.iter)
.filter_map(move |edge| {
if f.include_edge(edge) {
if edge.source() != from {
Some(edge.source())
} else {
Some(edge.target()) // includes case where from == source == target
}
} else {
None
}
})
.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (_, upper) = self.iter.size_hint();
(0, upper)
}
}
Data! {delegate_impl [[G, F], G, EdgeFiltered<G, F>, access0]}
GraphProp! {delegate_impl [[G, F], G, EdgeFiltered<G, F>, access0]}
IntoNodeIdentifiers! {delegate_impl [['a, G, F], G, &'a EdgeFiltered<G, F>, access0]}
IntoNodeReferences! {delegate_impl [['a, G, F], G, &'a EdgeFiltered<G, F>, access0]}
NodeCompactIndexable! {delegate_impl [[G, F], G, EdgeFiltered<G, F>, access0]}
NodeCount! {delegate_impl [[G, F], G, EdgeFiltered<G, F>, access0]}
NodeIndexable! {delegate_impl [[G, F], G, EdgeFiltered<G, F>, access0]}
EdgeIndexable! {delegate_impl [[G, F], G, EdgeFiltered<G, F>, access0]}
Visitable! {delegate_impl [[G, F], G, EdgeFiltered<G, F>, access0]}

135
vendor/petgraph/src/visit/macros.rs vendored Normal file
View File

@@ -0,0 +1,135 @@
/// Define a trait as usual, and a macro that can be used to instantiate
/// implementations of it.
///
/// There *must* be section markers in the trait definition:
/// @section type for associated types
/// @section self for methods
/// @section nodelegate for arbitrary tail that is not forwarded.
macro_rules! trait_template {
($(#[$doc:meta])* pub trait $name:ident $($methods:tt)*) => {
macro_rules! $name {
($m:ident $extra:tt) => {
$m! {
$extra
pub trait $name $($methods)*
}
}
}
remove_sections! { []
$(#[$doc])*
pub trait $name $($methods)*
// This is where the trait definition is reproduced by the macro.
// It makes the source links point to this place!
//
// I'm sorry, you'll have to find the source by looking at the
// source of the module the trait is defined in.
//
// We use this nifty macro so that we can automatically generate
// delegation trait impls and implement the graph traits for more
// types and combinators.
}
}
}
macro_rules! remove_sections_inner {
([$($stack:tt)*]) => {
$($stack)*
};
// escape the following tt
([$($stack:tt)*] @escape $_x:tt $($t:tt)*) => {
remove_sections_inner!([$($stack)*] $($t)*);
};
([$($stack:tt)*] @section $x:ident $($t:tt)*) => {
remove_sections_inner!([$($stack)*] $($t)*);
};
([$($stack:tt)*] $t:tt $($tail:tt)*) => {
remove_sections_inner!([$($stack)* $t] $($tail)*);
};
}
// This is the outer layer, just find the { } of the actual trait definition
// recurse once into { }, but not more.
macro_rules! remove_sections {
([$($stack:tt)*]) => {
$($stack)*
};
([$($stack:tt)*] { $($tail:tt)* }) => {
$($stack)* {
remove_sections_inner!([] $($tail)*);
}
};
([$($stack:tt)*] $t:tt $($tail:tt)*) => {
remove_sections!([$($stack)* $t] $($tail)*);
};
}
macro_rules! deref {
($e:expr) => {
*$e
};
}
macro_rules! deref_twice {
($e:expr) => {
**$e
};
}
/// Implement a trait by delegation. By default as if we are delegating
/// from &G to G.
macro_rules! delegate_impl {
([] $($rest:tt)*) => {
delegate_impl! { [['a, G], G, &'a G, deref] $($rest)* }
};
([[$($param:tt)*], $self_type:ident, $self_wrap:ty, $self_map:ident]
pub trait $name:ident $(: $sup:ident)* $(+ $more_sup:ident)* {
// "Escaped" associated types. Stripped before making the `trait`
// itself, but forwarded when delegating impls.
$(
@escape [type $assoc_name_ext:ident]
// Associated types. Forwarded.
)*
$(
@section type
$(
$(#[$_assoc_attr:meta])*
type $assoc_name:ident $(: $assoc_bound:ty)*;
)+
)*
// Methods. Forwarded. Using $self_map!(self) around the self argument.
// Methods must use receiver `self` or explicit type like `self: &Self`
// &self and &mut self are _not_ supported.
$(
@section self
$(
$(#[$_method_attr:meta])*
fn $method_name:ident(self $(: $self_selftype:ty)* $(,$marg:ident : $marg_ty:ty)*) $(-> $mret:ty)?;
)+
)*
// Arbitrary tail that is ignored when forwarding.
$(
@section nodelegate
$($tail:tt)*
)*
}) => {
impl<$($param)*> $name for $self_wrap where $self_type: $name {
$(
$(
type $assoc_name = $self_type::$assoc_name;
)*
)*
$(
type $assoc_name_ext = $self_type::$assoc_name_ext;
)*
$(
$(
fn $method_name(self $(: $self_selftype)* $(,$marg: $marg_ty)*) $(-> $mret)? {
$self_map!(self).$method_name($($marg),*)
}
)*
)*
}
}
}

481
vendor/petgraph/src/visit/mod.rs vendored Normal file
View File

@@ -0,0 +1,481 @@
//! Graph traits and graph traversals.
//!
//! ### The `Into-` Traits
//!
//! Graph traits like [`IntoNeighbors`][in] create iterators and use the same
//! pattern that `IntoIterator` does: the trait takes a reference to a graph,
//! and produces an iterator. These traits are quite composable, but with the
//! limitation that they only use shared references to graphs.
//!
//! ### Graph Traversal
//!
//! [`Dfs`](struct.Dfs.html), [`Bfs`][bfs], [`DfsPostOrder`][dfspo] and
//! [`Topo`][topo] are basic visitors and they use “walker” methods: the
//! visitors don't hold the graph as borrowed during traversal, only for the
//! `.next()` call on the walker. They can be converted to iterators
//! through the [`Walker`][w] trait.
//!
//! There is also the callback based traversal [`depth_first_search`][dfs].
//!
//! [bfs]: struct.Bfs.html
//! [dfspo]: struct.DfsPostOrder.html
//! [topo]: struct.Topo.html
//! [dfs]: fn.depth_first_search.html
//! [w]: trait.Walker.html
//!
//! ### Other Graph Traits
//!
//! The traits are rather loosely coupled at the moment (which is intentional,
//! but will develop a bit), and there are traits missing that could be added.
//!
//! Not much is needed to be able to use the visitors on a graph. A graph
//! needs to define [`GraphBase`][gb], [`IntoNeighbors`][in] and
//! [`Visitable`][vis] as a minimum.
//!
//! [gb]: trait.GraphBase.html
//! [in]: trait.IntoNeighbors.html
//! [vis]: trait.Visitable.html
//!
//! ### Graph Trait Implementations
//!
//! The following table lists the traits that are implemented for each graph type:
//!
//! | | Graph | StableGraph | GraphMap | MatrixGraph | Csr | List |
//! | --------------------- | :---: | :---------: | :------: | :---------: | :---: | :---: |
//! | GraphBase | x | x | x | x | x | x |
//! | GraphProp | x | x | x | x | x | x |
//! | NodeCount | x | x | x | x | x | x |
//! | NodeIndexable | x | x | x | x | x | x |
//! | NodeCompactIndexable | x | | x | | x | x |
//! | EdgeCount | x | x | x | x | x | x |
//! | EdgeIndexable | x | x | x | | | |
//! | Data | x | x | x | x | x | x |
//! | IntoNodeIdentifiers | x | x | x | x | x | x |
//! | IntoNodeReferences | x | x | x | x | x | x |
//! | IntoEdgeReferences | x | x | x | x | x | x |
//! | IntoNeighbors | x | x | x | x | x | x |
//! | IntoNeighborsDirected | x | x | x | x | | |
//! | IntoEdges | x | x | x | x | x | x |
//! | IntoEdgesDirected | x | x | x | x | | |
//! | Visitable | x | x | x | x | x | x |
//! | GetAdjacencyMatrix | x | x | x | x | x | x |
// filter, reversed have their `mod` lines at the end,
// so that they can use the trait template macros
pub use self::filter::*;
pub use self::reversed::*;
pub use self::undirected_adaptor::*;
#[macro_use]
mod macros;
mod dfsvisit;
mod traversal;
pub use self::dfsvisit::*;
pub use self::traversal::*;
use fixedbitset::FixedBitSet;
use std::collections::HashSet;
use std::hash::{BuildHasher, Hash};
use super::EdgeType;
use crate::prelude::Direction;
use crate::graph::IndexType;
trait_template! {
/// Base graph trait: defines the associated node identifier and
/// edge identifier types.
pub trait GraphBase {
// FIXME: We can drop this escape/nodelegate stuff in Rust 1.18
@escape [type NodeId]
@escape [type EdgeId]
@section nodelegate
/// edge identifier
type EdgeId: Copy + PartialEq;
/// node identifier
type NodeId: Copy + PartialEq;
}
}
GraphBase! {delegate_impl []}
GraphBase! {delegate_impl [['a, G], G, &'a mut G, deref]}
/// A copyable reference to a graph.
pub trait GraphRef: Copy + GraphBase {}
impl<G> GraphRef for &G where G: GraphBase {}
trait_template! {
/// Access to the neighbors of each node
///
/// The neighbors are, depending on the graphs edge type:
///
/// - `Directed`: All targets of edges from `a`.
/// - `Undirected`: All other endpoints of edges connected to `a`.
pub trait IntoNeighbors : GraphRef {
@section type
type Neighbors: Iterator<Item=Self::NodeId>;
@section self
/// Return an iterator of the neighbors of node `a`.
fn neighbors(self, a: Self::NodeId) -> Self::Neighbors;
}
}
IntoNeighbors! {delegate_impl []}
trait_template! {
/// Access to the neighbors of each node, through incoming or outgoing edges.
///
/// Depending on the graphs edge type, the neighbors of a given directionality
/// are:
///
/// - `Directed`, `Outgoing`: All targets of edges from `a`.
/// - `Directed`, `Incoming`: All sources of edges to `a`.
/// - `Undirected`: All other endpoints of edges connected to `a`.
pub trait IntoNeighborsDirected : IntoNeighbors {
@section type
type NeighborsDirected: Iterator<Item=Self::NodeId>;
@section self
fn neighbors_directed(self, n: Self::NodeId, d: Direction)
-> Self::NeighborsDirected;
}
}
trait_template! {
/// Access to the edges of each node.
///
/// The edges are, depending on the graphs edge type:
///
/// - `Directed`: All edges from `a`.
/// - `Undirected`: All edges connected to `a`, with `a` being the source of each edge.
///
/// This is an extended version of the trait `IntoNeighbors`; the former
/// only iterates over the target node identifiers, while this trait
/// yields edge references (trait [`EdgeRef`][er]).
///
/// [er]: trait.EdgeRef.html
pub trait IntoEdges : IntoEdgeReferences + IntoNeighbors {
@section type
type Edges: Iterator<Item=Self::EdgeRef>;
@section self
fn edges(self, a: Self::NodeId) -> Self::Edges;
}
}
IntoEdges! {delegate_impl []}
trait_template! {
/// Access to all edges of each node, in the specified direction.
///
/// The edges are, depending on the direction and the graphs edge type:
///
///
/// - `Directed`, `Outgoing`: All edges from `a`.
/// - `Directed`, `Incoming`: All edges to `a`.
/// - `Undirected`, `Outgoing`: All edges connected to `a`, with `a` being the source of each edge.
/// - `Undirected`, `Incoming`: All edges connected to `a`, with `a` being the target of each edge.
///
/// This is an extended version of the trait `IntoNeighborsDirected`; the former
/// only iterates over the target node identifiers, while this trait
/// yields edge references (trait [`EdgeRef`][er]).
///
/// [er]: trait.EdgeRef.html
pub trait IntoEdgesDirected : IntoEdges + IntoNeighborsDirected {
@section type
type EdgesDirected: Iterator<Item=Self::EdgeRef>;
@section self
fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::EdgesDirected;
}
}
IntoEdgesDirected! {delegate_impl []}
trait_template! {
/// Access to the sequence of the graphs `NodeId`s.
pub trait IntoNodeIdentifiers : GraphRef {
@section type
type NodeIdentifiers: Iterator<Item=Self::NodeId>;
@section self
fn node_identifiers(self) -> Self::NodeIdentifiers;
}
}
IntoNodeIdentifiers! {delegate_impl []}
IntoNeighborsDirected! {delegate_impl []}
trait_template! {
/// Define associated data for nodes and edges
pub trait Data : GraphBase {
@section type
type NodeWeight;
type EdgeWeight;
}
}
Data! {delegate_impl []}
Data! {delegate_impl [['a, G], G, &'a mut G, deref]}
/// An edge reference.
///
/// Edge references are used by traits `IntoEdges` and `IntoEdgeReferences`.
pub trait EdgeRef: Copy {
type NodeId;
type EdgeId;
type Weight;
/// The source node of the edge.
fn source(&self) -> Self::NodeId;
/// The target node of the edge.
fn target(&self) -> Self::NodeId;
/// A reference to the weight of the edge.
fn weight(&self) -> &Self::Weight;
/// The edges identifier.
fn id(&self) -> Self::EdgeId;
}
impl<N, E> EdgeRef for (N, N, &E)
where
N: Copy,
{
type NodeId = N;
type EdgeId = (N, N);
type Weight = E;
fn source(&self) -> N {
self.0
}
fn target(&self) -> N {
self.1
}
fn weight(&self) -> &E {
self.2
}
fn id(&self) -> (N, N) {
(self.0, self.1)
}
}
/// A node reference.
pub trait NodeRef: Copy {
type NodeId;
type Weight;
fn id(&self) -> Self::NodeId;
fn weight(&self) -> &Self::Weight;
}
trait_template! {
/// Access to the sequence of the graphs nodes
pub trait IntoNodeReferences : Data + IntoNodeIdentifiers {
@section type
type NodeRef: NodeRef<NodeId=Self::NodeId, Weight=Self::NodeWeight>;
type NodeReferences: Iterator<Item=Self::NodeRef>;
@section self
fn node_references(self) -> Self::NodeReferences;
}
}
IntoNodeReferences! {delegate_impl []}
impl<Id> NodeRef for (Id, ())
where
Id: Copy,
{
type NodeId = Id;
type Weight = ();
fn id(&self) -> Self::NodeId {
self.0
}
fn weight(&self) -> &Self::Weight {
static DUMMY: () = ();
&DUMMY
}
}
impl<Id, W> NodeRef for (Id, &W)
where
Id: Copy,
{
type NodeId = Id;
type Weight = W;
fn id(&self) -> Self::NodeId {
self.0
}
fn weight(&self) -> &Self::Weight {
self.1
}
}
trait_template! {
/// Access to the sequence of the graphs edges
pub trait IntoEdgeReferences : Data + GraphRef {
@section type
type EdgeRef: EdgeRef<NodeId=Self::NodeId, EdgeId=Self::EdgeId,
Weight=Self::EdgeWeight>;
type EdgeReferences: Iterator<Item=Self::EdgeRef>;
@section self
fn edge_references(self) -> Self::EdgeReferences;
}
}
IntoEdgeReferences! {delegate_impl [] }
trait_template! {
/// Edge kind property (directed or undirected edges)
pub trait GraphProp : GraphBase {
@section type
/// The kind of edges in the graph.
type EdgeType: EdgeType;
@section nodelegate
fn is_directed(&self) -> bool {
<Self::EdgeType>::is_directed()
}
}
}
GraphProp! {delegate_impl []}
trait_template! {
/// The graphs `NodeId`s map to indices
#[allow(clippy::needless_arbitrary_self_type)]
pub trait NodeIndexable : GraphBase {
@section self
/// Return an upper bound of the node indices in the graph
/// (suitable for the size of a bitmap).
fn node_bound(self: &Self) -> usize;
/// Convert `a` to an integer index.
fn to_index(self: &Self, a: Self::NodeId) -> usize;
/// Convert `i` to a node index. `i` must be a valid value in the graph.
fn from_index(self: &Self, i: usize) -> Self::NodeId;
}
}
NodeIndexable! {delegate_impl []}
trait_template! {
/// The graphs `NodeId`s map to indices
#[allow(clippy::needless_arbitrary_self_type)]
pub trait EdgeIndexable : GraphBase {
@section self
/// Return an upper bound of the edge indices in the graph
/// (suitable for the size of a bitmap).
fn edge_bound(self: &Self) -> usize;
/// Convert `a` to an integer index.
fn to_index(self: &Self, a: Self::EdgeId) -> usize;
/// Convert `i` to an edge index. `i` must be a valid value in the graph.
fn from_index(self: &Self, i: usize) -> Self::EdgeId;
}
}
EdgeIndexable! {delegate_impl []}
trait_template! {
/// A graph with a known node count.
#[allow(clippy::needless_arbitrary_self_type)]
pub trait NodeCount : GraphBase {
@section self
fn node_count(self: &Self) -> usize;
}
}
NodeCount! {delegate_impl []}
trait_template! {
/// The graphs `NodeId`s map to indices, in a range without holes.
///
/// The graph's node identifiers correspond to exactly the indices
/// `0..self.node_bound()`.
pub trait NodeCompactIndexable : NodeIndexable + NodeCount { }
}
NodeCompactIndexable! {delegate_impl []}
/// A mapping for storing the visited status for NodeId `N`.
pub trait VisitMap<N> {
/// Mark `a` as visited.
///
/// Return **true** if this is the first visit, false otherwise.
fn visit(&mut self, a: N) -> bool;
/// Return whether `a` has been visited before.
fn is_visited(&self, a: &N) -> bool;
}
impl<Ix> VisitMap<Ix> for FixedBitSet
where
Ix: IndexType,
{
fn visit(&mut self, x: Ix) -> bool {
!self.put(x.index())
}
fn is_visited(&self, x: &Ix) -> bool {
self.contains(x.index())
}
}
impl<N, S> VisitMap<N> for HashSet<N, S>
where
N: Hash + Eq,
S: BuildHasher,
{
fn visit(&mut self, x: N) -> bool {
self.insert(x)
}
fn is_visited(&self, x: &N) -> bool {
self.contains(x)
}
}
trait_template! {
/// A graph that can create a map that tracks the visited status of its nodes.
#[allow(clippy::needless_arbitrary_self_type)]
pub trait Visitable : GraphBase {
@section type
/// The associated map type
type Map: VisitMap<Self::NodeId>;
@section self
/// Create a new visitor map
fn visit_map(self: &Self) -> Self::Map;
/// Reset the visitor map (and resize to new size of graph if needed)
fn reset_map(self: &Self, map: &mut Self::Map);
}
}
Visitable! {delegate_impl []}
trait_template! {
/// Create or access the adjacency matrix of a graph.
///
/// The implementor can either create an adjacency matrix, or it can return
/// a placeholder if it has the needed representation internally.
#[allow(clippy::needless_arbitrary_self_type)]
pub trait GetAdjacencyMatrix : GraphBase {
@section type
/// The associated adjacency matrix type
type AdjMatrix;
@section self
/// Create the adjacency matrix
fn adjacency_matrix(self: &Self) -> Self::AdjMatrix;
/// Return true if there is an edge from `a` to `b`, false otherwise.
///
/// Computes in O(1) time.
fn is_adjacent(self: &Self, matrix: &Self::AdjMatrix, a: Self::NodeId, b: Self::NodeId) -> bool;
}
}
GetAdjacencyMatrix! {delegate_impl []}
trait_template! {
/// A graph with a known edge count.
#[allow(clippy::needless_arbitrary_self_type)]
pub trait EdgeCount : GraphBase {
@section self
/// Return the number of edges in the graph.
fn edge_count(self: &Self) -> usize;
}
}
EdgeCount! {delegate_impl []}
mod filter;
mod reversed;
mod undirected_adaptor;

184
vendor/petgraph/src/visit/reversed.rs vendored Normal file
View File

@@ -0,0 +1,184 @@
use crate::{Direction, Incoming};
use crate::visit::{
Data, EdgeCount, EdgeIndexable, EdgeRef, GetAdjacencyMatrix, GraphBase, GraphProp, GraphRef,
IntoEdgeReferences, IntoEdges, IntoEdgesDirected, IntoNeighbors, IntoNeighborsDirected,
IntoNodeIdentifiers, IntoNodeReferences, NodeCompactIndexable, NodeCount, NodeIndexable,
Visitable,
};
/// An edge-reversing graph adaptor.
///
/// All edges have the opposite direction with `Reversed`.
#[derive(Copy, Clone, Debug)]
pub struct Reversed<G>(pub G);
impl<G: GraphBase> GraphBase for Reversed<G> {
type NodeId = G::NodeId;
type EdgeId = G::EdgeId;
}
impl<G: GraphRef> GraphRef for Reversed<G> {}
Data! {delegate_impl [[G], G, Reversed<G>, access0]}
impl<G> IntoNeighbors for Reversed<G>
where
G: IntoNeighborsDirected,
{
type Neighbors = G::NeighborsDirected;
fn neighbors(self, n: G::NodeId) -> G::NeighborsDirected {
self.0.neighbors_directed(n, Incoming)
}
}
impl<G> IntoNeighborsDirected for Reversed<G>
where
G: IntoNeighborsDirected,
{
type NeighborsDirected = G::NeighborsDirected;
fn neighbors_directed(self, n: G::NodeId, d: Direction) -> G::NeighborsDirected {
self.0.neighbors_directed(n, d.opposite())
}
}
impl<G> IntoEdges for Reversed<G>
where
G: IntoEdgesDirected,
{
type Edges = ReversedEdges<G::EdgesDirected>;
fn edges(self, a: Self::NodeId) -> Self::Edges {
ReversedEdges {
iter: self.0.edges_directed(a, Incoming),
}
}
}
impl<G> IntoEdgesDirected for Reversed<G>
where
G: IntoEdgesDirected,
{
type EdgesDirected = ReversedEdges<G::EdgesDirected>;
fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::Edges {
ReversedEdges {
iter: self.0.edges_directed(a, dir.opposite()),
}
}
}
impl<G: Visitable> Visitable for Reversed<G> {
type Map = G::Map;
fn visit_map(&self) -> G::Map {
self.0.visit_map()
}
fn reset_map(&self, map: &mut Self::Map) {
self.0.reset_map(map);
}
}
/// A reversed edges iterator.
#[derive(Debug, Clone)]
pub struct ReversedEdges<I> {
iter: I,
}
impl<I> Iterator for ReversedEdges<I>
where
I: Iterator,
I::Item: EdgeRef,
{
type Item = ReversedEdgeReference<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(ReversedEdgeReference)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
/// A reversed edge reference
#[derive(Copy, Clone, Debug)]
pub struct ReversedEdgeReference<R>(R);
impl<R> ReversedEdgeReference<R> {
/// Return the original, unreversed edge reference.
pub fn as_unreversed(&self) -> &R {
&self.0
}
/// Consume `self` and return the original, unreversed edge reference.
pub fn into_unreversed(self) -> R {
self.0
}
}
/// An edge reference
impl<R> EdgeRef for ReversedEdgeReference<R>
where
R: EdgeRef,
{
type NodeId = R::NodeId;
type EdgeId = R::EdgeId;
type Weight = R::Weight;
fn source(&self) -> Self::NodeId {
self.0.target()
}
fn target(&self) -> Self::NodeId {
self.0.source()
}
fn weight(&self) -> &Self::Weight {
self.0.weight()
}
fn id(&self) -> Self::EdgeId {
self.0.id()
}
}
impl<G> IntoEdgeReferences for Reversed<G>
where
G: IntoEdgeReferences,
{
type EdgeRef = ReversedEdgeReference<G::EdgeRef>;
type EdgeReferences = ReversedEdgeReferences<G::EdgeReferences>;
fn edge_references(self) -> Self::EdgeReferences {
ReversedEdgeReferences {
iter: self.0.edge_references(),
}
}
}
/// A reversed edge references iterator.
#[derive(Debug, Clone)]
pub struct ReversedEdgeReferences<I> {
iter: I,
}
impl<I> Iterator for ReversedEdgeReferences<I>
where
I: Iterator,
I::Item: EdgeRef,
{
type Item = ReversedEdgeReference<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(ReversedEdgeReference)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
macro_rules! access0 {
($e:expr) => {
$e.0
};
}
NodeIndexable! {delegate_impl [[G], G, Reversed<G>, access0]}
NodeCompactIndexable! {delegate_impl [[G], G, Reversed<G>, access0]}
IntoNodeIdentifiers! {delegate_impl [[G], G, Reversed<G>, access0]}
IntoNodeReferences! {delegate_impl [[G], G, Reversed<G>, access0]}
GraphProp! {delegate_impl [[G], G, Reversed<G>, access0]}
NodeCount! {delegate_impl [[G], G, Reversed<G>, access0]}
EdgeCount! {delegate_impl [[G], G, Reversed<G>, access0]}
EdgeIndexable! {delegate_impl [[G], G, Reversed<G>, access0]}
GetAdjacencyMatrix! {delegate_impl [[G], G, Reversed<G>, access0]}

536
vendor/petgraph/src/visit/traversal.rs vendored Normal file
View File

@@ -0,0 +1,536 @@
use super::{GraphRef, IntoNodeIdentifiers, Reversed};
use super::{IntoNeighbors, IntoNeighborsDirected, VisitMap, Visitable};
use crate::Incoming;
use std::collections::VecDeque;
/// Visit nodes of a graph in a depth-first-search (DFS) emitting nodes in
/// preorder (when they are first discovered).
///
/// The traversal starts at a given node and only traverses nodes reachable
/// from it.
///
/// `Dfs` is not recursive.
///
/// `Dfs` does not itself borrow the graph, and because of this you can run
/// a traversal over a graph while still retaining mutable access to it, if you
/// use it like the following example:
///
/// ```
/// use petgraph::Graph;
/// use petgraph::visit::Dfs;
///
/// let mut graph = Graph::<_,()>::new();
/// let a = graph.add_node(0);
///
/// let mut dfs = Dfs::new(&graph, a);
/// while let Some(nx) = dfs.next(&graph) {
/// // we can access `graph` mutably here still
/// graph[nx] += 1;
/// }
///
/// assert_eq!(graph[a], 1);
/// ```
///
/// **Note:** The algorithm may not behave correctly if nodes are removed
/// during iteration. It may not necessarily visit added nodes or edges.
#[derive(Clone, Debug)]
pub struct Dfs<N, VM> {
/// The stack of nodes to visit
pub stack: Vec<N>,
/// The map of discovered nodes
pub discovered: VM,
}
impl<N, VM> Default for Dfs<N, VM>
where
VM: Default,
{
fn default() -> Self {
Dfs {
stack: Vec::new(),
discovered: VM::default(),
}
}
}
impl<N, VM> Dfs<N, VM>
where
N: Copy + PartialEq,
VM: VisitMap<N>,
{
/// Create a new **Dfs**, using the graph's visitor map, and put **start**
/// in the stack of nodes to visit.
pub fn new<G>(graph: G, start: N) -> Self
where
G: GraphRef + Visitable<NodeId = N, Map = VM>,
{
let mut dfs = Dfs::empty(graph);
dfs.move_to(start);
dfs
}
/// Create a `Dfs` from a vector and a visit map
pub fn from_parts(stack: Vec<N>, discovered: VM) -> Self {
Dfs { stack, discovered }
}
/// Clear the visit state
pub fn reset<G>(&mut self, graph: G)
where
G: GraphRef + Visitable<NodeId = N, Map = VM>,
{
graph.reset_map(&mut self.discovered);
self.stack.clear();
}
/// Create a new **Dfs** using the graph's visitor map, and no stack.
pub fn empty<G>(graph: G) -> Self
where
G: GraphRef + Visitable<NodeId = N, Map = VM>,
{
Dfs {
stack: Vec::new(),
discovered: graph.visit_map(),
}
}
/// Keep the discovered map, but clear the visit stack and restart
/// the dfs from a particular node.
pub fn move_to(&mut self, start: N) {
self.stack.clear();
self.stack.push(start);
}
/// Return the next node in the dfs, or **None** if the traversal is done.
pub fn next<G>(&mut self, graph: G) -> Option<N>
where
G: IntoNeighbors<NodeId = N>,
{
while let Some(node) = self.stack.pop() {
if self.discovered.visit(node) {
for succ in graph.neighbors(node) {
if !self.discovered.is_visited(&succ) {
self.stack.push(succ);
}
}
return Some(node);
}
}
None
}
}
/// Visit nodes in a depth-first-search (DFS) emitting nodes in postorder
/// (each node after all its descendants have been emitted).
///
/// `DfsPostOrder` is not recursive.
///
/// The traversal starts at a given node and only traverses nodes reachable
/// from it.
#[derive(Clone, Debug)]
pub struct DfsPostOrder<N, VM> {
/// The stack of nodes to visit
pub stack: Vec<N>,
/// The map of discovered nodes
pub discovered: VM,
/// The map of finished nodes
pub finished: VM,
}
impl<N, VM> Default for DfsPostOrder<N, VM>
where
VM: Default,
{
fn default() -> Self {
DfsPostOrder {
stack: Vec::new(),
discovered: VM::default(),
finished: VM::default(),
}
}
}
impl<N, VM> DfsPostOrder<N, VM>
where
N: Copy + PartialEq,
VM: VisitMap<N>,
{
/// Create a new `DfsPostOrder` using the graph's visitor map, and put
/// `start` in the stack of nodes to visit.
pub fn new<G>(graph: G, start: N) -> Self
where
G: GraphRef + Visitable<NodeId = N, Map = VM>,
{
let mut dfs = Self::empty(graph);
dfs.move_to(start);
dfs
}
/// Create a new `DfsPostOrder` using the graph's visitor map, and no stack.
pub fn empty<G>(graph: G) -> Self
where
G: GraphRef + Visitable<NodeId = N, Map = VM>,
{
DfsPostOrder {
stack: Vec::new(),
discovered: graph.visit_map(),
finished: graph.visit_map(),
}
}
/// Clear the visit state
pub fn reset<G>(&mut self, graph: G)
where
G: GraphRef + Visitable<NodeId = N, Map = VM>,
{
graph.reset_map(&mut self.discovered);
graph.reset_map(&mut self.finished);
self.stack.clear();
}
/// Keep the discovered and finished map, but clear the visit stack and restart
/// the dfs from a particular node.
pub fn move_to(&mut self, start: N) {
self.stack.clear();
self.stack.push(start);
}
/// Return the next node in the traversal, or `None` if the traversal is done.
pub fn next<G>(&mut self, graph: G) -> Option<N>
where
G: IntoNeighbors<NodeId = N>,
{
while let Some(&nx) = self.stack.last() {
if self.discovered.visit(nx) {
// First time visiting `nx`: Push neighbors, don't pop `nx`
for succ in graph.neighbors(nx) {
if !self.discovered.is_visited(&succ) {
self.stack.push(succ);
}
}
} else {
self.stack.pop();
if self.finished.visit(nx) {
// Second time: All reachable nodes must have been finished
return Some(nx);
}
}
}
None
}
}
/// A breadth first search (BFS) of a graph.
///
/// The traversal starts at a given node and only traverses nodes reachable
/// from it.
///
/// `Bfs` is not recursive.
///
/// `Bfs` does not itself borrow the graph, and because of this you can run
/// a traversal over a graph while still retaining mutable access to it, if you
/// use it like the following example:
///
/// ```
/// use petgraph::Graph;
/// use petgraph::visit::Bfs;
///
/// let mut graph = Graph::<_,()>::new();
/// let a = graph.add_node(0);
///
/// let mut bfs = Bfs::new(&graph, a);
/// while let Some(nx) = bfs.next(&graph) {
/// // we can access `graph` mutably here still
/// graph[nx] += 1;
/// }
///
/// assert_eq!(graph[a], 1);
/// ```
///
/// **Note:** The algorithm may not behave correctly if nodes are removed
/// during iteration. It may not necessarily visit added nodes or edges.
#[derive(Clone)]
pub struct Bfs<N, VM> {
/// The queue of nodes to visit
pub stack: VecDeque<N>,
/// The map of discovered nodes
pub discovered: VM,
}
impl<N, VM> Default for Bfs<N, VM>
where
VM: Default,
{
fn default() -> Self {
Bfs {
stack: VecDeque::new(),
discovered: VM::default(),
}
}
}
impl<N, VM> Bfs<N, VM>
where
N: Copy + PartialEq,
VM: VisitMap<N>,
{
/// Create a new **Bfs**, using the graph's visitor map, and put **start**
/// in the stack of nodes to visit.
pub fn new<G>(graph: G, start: N) -> Self
where
G: GraphRef + Visitable<NodeId = N, Map = VM>,
{
let mut discovered = graph.visit_map();
discovered.visit(start);
let mut stack = VecDeque::new();
stack.push_front(start);
Bfs { stack, discovered }
}
/// Return the next node in the bfs, or **None** if the traversal is done.
pub fn next<G>(&mut self, graph: G) -> Option<N>
where
G: IntoNeighbors<NodeId = N>,
{
if let Some(node) = self.stack.pop_front() {
for succ in graph.neighbors(node) {
if self.discovered.visit(succ) {
self.stack.push_back(succ);
}
}
return Some(node);
}
None
}
}
/// A topological order traversal for a graph.
///
/// **Note** that `Topo` only visits nodes that are not part of cycles,
/// i.e. nodes in a true DAG. Use other visitors like `DfsPostOrder` or
/// algorithms like kosaraju_scc to handle graphs with possible cycles.
#[derive(Clone)]
pub struct Topo<N, VM> {
tovisit: Vec<N>,
ordered: VM,
}
impl<N, VM> Default for Topo<N, VM>
where
VM: Default,
{
fn default() -> Self {
Topo {
tovisit: Vec::new(),
ordered: VM::default(),
}
}
}
impl<N, VM> Topo<N, VM>
where
N: Copy + PartialEq,
VM: VisitMap<N>,
{
/// Create a new `Topo`, using the graph's visitor map, and put all
/// initial nodes in the to visit list.
pub fn new<G>(graph: G) -> Self
where
G: IntoNodeIdentifiers + IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
{
let mut topo = Self::empty(graph);
topo.extend_with_initials(graph);
topo
}
/// Create a new `Topo` with initial nodes.
///
/// Nodes with incoming edges are ignored.
pub fn with_initials<G, I>(graph: G, initials: I) -> Self
where
G: IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
I: IntoIterator<Item = N>,
{
Topo {
tovisit: initials
.into_iter()
.filter(|&n| graph.neighbors_directed(n, Incoming).next().is_none())
.collect(),
ordered: graph.visit_map(),
}
}
fn extend_with_initials<G>(&mut self, g: G)
where
G: IntoNodeIdentifiers + IntoNeighborsDirected<NodeId = N>,
{
// find all initial nodes (nodes without incoming edges)
self.tovisit.extend(
g.node_identifiers()
.filter(move |&a| g.neighbors_directed(a, Incoming).next().is_none()),
);
}
/* Private until it has a use */
/// Create a new `Topo`, using the graph's visitor map with *no* starting
/// index specified.
fn empty<G>(graph: G) -> Self
where
G: GraphRef + Visitable<NodeId = N, Map = VM>,
{
Topo {
ordered: graph.visit_map(),
tovisit: Vec::new(),
}
}
/// Clear visited state, and put all initial nodes in the to visit list.
pub fn reset<G>(&mut self, graph: G)
where
G: IntoNodeIdentifiers + IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
{
graph.reset_map(&mut self.ordered);
self.tovisit.clear();
self.extend_with_initials(graph);
}
/// Return the next node in the current topological order traversal, or
/// `None` if the traversal is at the end.
///
/// *Note:* The graph may not have a complete topological order, and the only
/// way to know is to run the whole traversal and make sure it visits every node.
pub fn next<G>(&mut self, g: G) -> Option<N>
where
G: IntoNeighborsDirected + Visitable<NodeId = N, Map = VM>,
{
// Take an unvisited element and find which of its neighbors are next
while let Some(nix) = self.tovisit.pop() {
if self.ordered.is_visited(&nix) {
continue;
}
self.ordered.visit(nix);
for neigh in g.neighbors(nix) {
// Look at each neighbor, and those that only have incoming edges
// from the already ordered list, they are the next to visit.
if Reversed(g)
.neighbors(neigh)
.all(|b| self.ordered.is_visited(&b))
{
self.tovisit.push(neigh);
}
}
return Some(nix);
}
None
}
}
/// A walker is a traversal state, but where part of the traversal
/// information is supplied manually to each next call.
///
/// This for example allows graph traversals that don't hold a borrow of the
/// graph they are traversing.
pub trait Walker<Context> {
type Item;
/// Advance to the next item
fn walk_next(&mut self, context: Context) -> Option<Self::Item>;
/// Create an iterator out of the walker and given `context`.
fn iter(self, context: Context) -> WalkerIter<Self, Context>
where
Self: Sized,
Context: Clone,
{
WalkerIter {
walker: self,
context,
}
}
}
/// A walker and its context wrapped into an iterator.
#[derive(Clone, Debug)]
pub struct WalkerIter<W, C> {
walker: W,
context: C,
}
impl<W, C> WalkerIter<W, C>
where
W: Walker<C>,
C: Clone,
{
pub fn context(&self) -> C {
self.context.clone()
}
pub fn inner_ref(&self) -> &W {
&self.walker
}
pub fn inner_mut(&mut self) -> &mut W {
&mut self.walker
}
}
impl<W, C> Iterator for WalkerIter<W, C>
where
W: Walker<C>,
C: Clone,
{
type Item = W::Item;
fn next(&mut self) -> Option<Self::Item> {
self.walker.walk_next(self.context.clone())
}
}
impl<C, W: ?Sized> Walker<C> for &mut W
where
W: Walker<C>,
{
type Item = W::Item;
fn walk_next(&mut self, context: C) -> Option<Self::Item> {
(**self).walk_next(context)
}
}
impl<G> Walker<G> for Dfs<G::NodeId, G::Map>
where
G: IntoNeighbors + Visitable,
{
type Item = G::NodeId;
fn walk_next(&mut self, context: G) -> Option<Self::Item> {
self.next(context)
}
}
impl<G> Walker<G> for DfsPostOrder<G::NodeId, G::Map>
where
G: IntoNeighbors + Visitable,
{
type Item = G::NodeId;
fn walk_next(&mut self, context: G) -> Option<Self::Item> {
self.next(context)
}
}
impl<G> Walker<G> for Bfs<G::NodeId, G::Map>
where
G: IntoNeighbors + Visitable,
{
type Item = G::NodeId;
fn walk_next(&mut self, context: G) -> Option<Self::Item> {
self.next(context)
}
}
impl<G> Walker<G> for Topo<G::NodeId, G::Map>
where
G: IntoNeighborsDirected + Visitable,
{
type Item = G::NodeId;
fn walk_next(&mut self, context: G) -> Option<Self::Item> {
self.next(context)
}
}

View File

@@ -0,0 +1,111 @@
use crate::visit::{
Data, GraphBase, GraphProp, GraphRef, IntoEdgeReferences, IntoEdges, IntoEdgesDirected,
IntoNeighbors, IntoNeighborsDirected, IntoNodeIdentifiers, IntoNodeReferences,
NodeCompactIndexable, NodeCount, NodeIndexable, Visitable,
};
use crate::Direction;
/// An edge direction removing graph adaptor.
#[derive(Copy, Clone, Debug)]
pub struct UndirectedAdaptor<G>(pub G);
impl<G: GraphRef> GraphRef for UndirectedAdaptor<G> {}
impl<G> IntoNeighbors for UndirectedAdaptor<G>
where
G: IntoNeighborsDirected,
{
type Neighbors = std::iter::Chain<G::NeighborsDirected, G::NeighborsDirected>;
fn neighbors(self, n: G::NodeId) -> Self::Neighbors {
self.0
.neighbors_directed(n, Direction::Incoming)
.chain(self.0.neighbors_directed(n, Direction::Outgoing))
}
}
impl<G> IntoEdges for UndirectedAdaptor<G>
where
G: IntoEdgesDirected,
{
type Edges = std::iter::Chain<G::EdgesDirected, G::EdgesDirected>;
fn edges(self, a: Self::NodeId) -> Self::Edges {
self.0
.edges_directed(a, Direction::Incoming)
.chain(self.0.edges_directed(a, Direction::Outgoing))
}
}
impl<G> GraphProp for UndirectedAdaptor<G>
where
G: GraphBase,
{
type EdgeType = crate::Undirected;
fn is_directed(&self) -> bool {
false
}
}
macro_rules! access0 {
($e:expr) => {
$e.0
};
}
GraphBase! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
Data! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
IntoEdgeReferences! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
Visitable! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
NodeIndexable! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
NodeCompactIndexable! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
IntoNodeIdentifiers! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
IntoNodeReferences! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
NodeCount! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
#[cfg(test)]
mod tests {
use super::*;
use crate::graph::{DiGraph, Graph};
use crate::visit::Dfs;
static LINEAR_EDGES: [(u32, u32); 5] = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)];
#[test]
pub fn test_is_reachable() {
// create a linear digraph, choose a node in the centre and check all nodes are visited
// by a dfs
let graph = DiGraph::<(), ()>::from_edges(&LINEAR_EDGES);
let mut nodes = graph.node_identifiers().collect::<Vec<_>>();
nodes.sort();
let graph = UndirectedAdaptor(&graph);
use crate::visit::Walker;
let mut visited_nodes: Vec<_> = Dfs::new(&graph, nodes[2]).iter(&graph).collect();
visited_nodes.sort();
assert_eq!(visited_nodes, nodes);
}
#[test]
pub fn test_neighbors_count() {
{
let graph = Graph::<(), ()>::from_edges(&LINEAR_EDGES);
let graph = UndirectedAdaptor(&graph);
let mut nodes = graph.node_identifiers().collect::<Vec<_>>();
nodes.sort();
assert_eq!(graph.neighbors(nodes[1]).count(), 2);
}
{
let graph = Graph::<(), ()>::from_edges(&LINEAR_EDGES);
let graph = UndirectedAdaptor(&graph);
let mut nodes = graph.node_identifiers().collect::<Vec<_>>();
nodes.sort();
assert_eq!(graph.neighbors(nodes[1]).count(), 2);
}
}
}