diff options
| author | JSDurand <mmemmew@gmail.com> | 2026-10-16 14:01:01 +0800 |
|---|---|---|
| committer | JSDurand <mmemmew@gmail.com> | 2026-10-16 14:02:10 +0800 |
| commit | fba9a90cfc6aca2a26cce72f55fb261789139781 (patch) | |
| tree | b4b121791ad639e745df689c0d5a8ed7a9e5dcc4 /graph/src/labelled/binary.rs | |
| parent | 3ae0cf9898485a2ec35df7d23cd274e7dea5796d (diff) | |
Now I tested and discussed with claude, and had a working version of
this project. The rest is to port the claude version to my own
writings. So this serves as the starting point before that attempt.
In the new attempt the design is better, and a number of bugs were
found and supposedly fixed, so let us see how this goes at the end.
Diffstat (limited to 'graph/src/labelled/binary.rs')
| -rw-r--r-- | graph/src/labelled/binary.rs | 78 |
1 files changed, 76 insertions, 2 deletions
diff --git a/graph/src/labelled/binary.rs b/graph/src/labelled/binary.rs index 862f25b..fecc295 100644 --- a/graph/src/labelled/binary.rs +++ b/graph/src/labelled/binary.rs @@ -2,7 +2,7 @@ //! labels and each node knows about its parents. use super::*; -use crate::{Parent, ParentsGraph, RedirectGraph}; +use crate::{Parent, ParentsGraph, RedirectGraph, VLabelGraph}; use std::{ collections::{hash_map::Iter as MapIter, HashMap as Map}, @@ -223,7 +223,7 @@ impl<T: GraphLabel> Graph for PLGraph<T> { for node in self.nodes() { post.push_str(&format!( " {node} [label = \"{node}:{}\"]\n", - match self.vertex_label(node) { + match VLabelGraph::vertex_label(self, node) { Ok(Some(label)) => { format!("{label}") } @@ -249,6 +249,7 @@ impl<T: GraphLabel> Graph for PLGraph<T> { let mut file = std::fs::File::options() .write(true) .create(true) + .truncate(true) .open(&filename)?; use std::io::Write; @@ -405,6 +406,79 @@ impl<T: GraphLabel> RedirectGraph for PLGraph<T> { } } +/// A delegation of iterators. +/// +/// This is used to avoid a boxed pointer to an iterator. +#[derive(Debug, Clone)] +pub struct PLVIter<'a, T: GraphLabel> { + iter: Iter<'a, usize>, + graph: &'a PLGraph<T>, +} + +impl<'a, T: GraphLabel> PLVIter<'a, T> { + /// Return an iterator from a graph and a node. + pub fn try_new(graph: &'a PLGraph<T>, node: usize) -> Result<Self, Error> { + let iter = graph + .nodes + .get(node) + .ok_or(Error::IndexOutOfBounds(node, graph.nodes.len()))? + .children + .iter(); + + Ok(Self { iter, graph }) + } +} + +impl<'a, T: GraphLabel> Iterator for PLVIter<'a, T> { + type Item = (T, usize); + + #[inline] + fn next(&mut self) -> Option<Self::Item> { + self.iter.next().and_then(|child| { + VLabelGraph::vertex_label(self.graph, *child) + .ok() + .flatten() + .map(|label| (label, *child)) + }) + } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + let len = self.iter.len(); + + (len, Some(len)) + } +} + +impl<'a, T: GraphLabel> ExactSizeIterator for PLVIter<'a, T> { + #[inline] + fn len(&self) -> usize { + self.iter.len() + } +} + +impl<T: GraphLabel> VLabelGraph<T> for PLGraph<T> { + type TupleIter<'a> = PLVIter<'a,T> + where + Self: 'a, + T: 'a; + + fn vertex_label(&self, node_id: usize) -> Result<Option<T>, Error> { + self.nodes + .get(node_id) + .ok_or(Error::IndexOutOfBounds(node_id, self.nodes.len())) + .map(|node| Some(node.label)) + } + + fn query_label(&self, label: T) -> Option<usize> { + self.label_index_map.get(&label).copied() + } + + fn verlabren_of(&self, node_id: usize) -> Result<Self::TupleIter<'_>, Error> { + PLVIter::try_new(self, node_id) + } +} + impl<T: GraphLabel> LabelGraph<T> for PLGraph<T> { type Iter<'a> = std::iter::Empty<usize> where |
