1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
use super::*;
/// A single step in the graph
///
/// Steps are the way we compute and represent the graph traversal with the
/// various algorithms.
///
/// Steps can store a type `S` which can be used to hold any information like
/// total weight or any other primitive or structure.
///
/// The `Step` type is a singly linked list, where each step has a reference to its parent.
/// It is a singly linked list because we only need to go backwards to the root node to get the path.
#[derive(Debug, Default)]
pub struct Step<S = f32, Ix = DefaultIx> {
/// The parent State that invoked this instance.
/// If the option is None then it means we arrived to the root state.
pub caller: Option<Rc<Step<S, Ix>>>,
/// The current node index the step is at within the graph.
pub idx: NodeIndex<Ix>,
/// The index of the edge that binds caller -> self
pub rel: Option<EdgeIndex<Ix>>,
/// State of the walking progress
pub state: S,
}
impl<S, Ix: IndexType> Step<S, Ix> {
/// Returns the nodes that were traversed to reach this step.
///
/// It starts from the target node and goes backwards to the root node.
/// To get the nodes in the correct order, you need to reverse the result with `rev()`.
///
/// This is an O(n) operation.
pub fn collect_nodes(&self) -> Vec<NodeIndex<Ix>> {
self.iter().map(|step| step.idx).collect()
}
/// Returns the edges that were traversed to reach this step.
///
/// It starts from the target node and goes backwards to the root node.
/// To get the edges in the correct order, you need to reverse the result with `rev()`.
///
/// This is an O(n) operation.
pub fn collect_edges(&self) -> Vec<EdgeIndex<Ix>> {
self.iter().filter_map(|step| step.rel).collect()
}
/// Returns the size of the chain.
///
/// This is an O(n) operation.
pub fn chain_size(&self) -> usize {
let mut size = 0;
self.iter().for_each(|_| size += 1);
size
}
/// Creates a step chain from a slice of node indexes.
///
/// The cost of each step is computed with the state function `F`.
/// The state function receives data regarding the current node and its parent,
/// like current index, state of the parent step, binding edge between the parent
/// step and the current index, etc.
///
/// With this data the user should be able to compute any desired state for each
/// step in the chain.
///
/// The arguments of the state function are, in order:
/// - parent index
/// - edge between parent and current
/// - current index
/// - parent state
pub fn from_slice<I, N, E, Ty: EdgeType, F>(
indices: &[NodeIndex<Ix>],
graph: &Graph<I, N, E, Ty, Ix>,
state: F,
) -> Step<S, Ix>
where
F: Fn(NodeIndex<Ix>, EdgeIndex<Ix>, NodeIndex<Ix>, &S) -> S,
S: Default,
{
let mut step: Step<S, Ix> = Step {
caller: None,
idx: indices[0],
rel: None,
state: Default::default(),
};
for idx in indices.iter().skip(1).copied() {
let old_step = Rc::new(step);
step = Step {
caller: Some(old_step.clone()),
idx,
rel: graph.edge_between(old_step.idx, idx),
state: state(
old_step.idx,
graph.edge_between_unchecked(old_step.idx, idx),
idx,
&old_step.state,
),
};
}
step
}
/// Returns an iterator visiting all the steps in the chain
pub fn iter(&self) -> Iter<S, Ix> {
Iter::new(self)
}
}
impl<S: Clone, Ix: Clone> Clone for Step<S, Ix> {
/// Clone the step chain.
///
/// The new chain is a deep copy of the original chain.
fn clone(&self) -> Self {
Self {
caller: self.caller.as_ref().map(|step| Rc::new(Self::clone(step))),
idx: self.idx.clone(),
rel: self.rel.clone(),
state: self.state.clone(),
}
}
}
/// An iterator over the borrowed steps of a step chain
#[derive(Debug)]
pub struct Iter<'a, S, Ix> {
current: Option<&'a Step<S, Ix>>,
}
impl<'a, S, Ix> Iter<'a, S, Ix> {
pub fn new(step: &'a Step<S, Ix>) -> Self {
Self {
current: Some(step),
}
}
}
impl<'a, S, Ix> Iterator for Iter<'a, S, Ix> {
type Item = &'a Step<S, Ix>;
fn next(&mut self) -> Option<Self::Item> {
let head = self.current;
self.current = head.and_then(|head| head.caller.as_ref().map(|step| step.as_ref()));
head
}
}