Graph

Struct Graph 

Source
pub struct Graph<NodeT, Arena = <NodeT as NodeEnum>::GenArena>
where NodeT: NodeEnum, Arena: CateArena<V = NodeT, D = NodeT::Discriminant>,
{ /* private fields */ }
Expand description

A graph with typed nodes

The graph can only by modified by commiting a transaction, which avoids mutable borrow of the graph

§Example:

use ttgraph::*;

#[derive(TypedNode, Debug)]
struct NodeA{
  link: NodeIndex,
  data: usize,
}

#[derive(TypedNode, Debug)]
struct NodeB{
  links: BTreeSet<NodeIndex>,
  another_data: String,
}

node_enum!{
  #[derive(Debug)]
  enum Node{
    A(NodeA),
    B(NodeB)
  }
}

let ctx = Context::new();
let mut graph = Graph::<Node>::new(&ctx);
let mut trans = Transaction::new(&ctx);
// Does some operations on the transaction
graph.commit(trans).unwrap();

Implementations§

Source§

impl<NodeT, Arena> Graph<NodeT, Arena>
where NodeT: NodeEnum, Arena: CateArena<V = NodeT, D = NodeT::Discriminant>,

Source

pub fn new(context: &Context) -> Self

Create an empty graph

Source

pub fn get(&self, idx: NodeIndex) -> Option<&NodeT>

Get the reference of a node. For convinience, if the type of the node is previously known, use get_node!() instead.

§Example
use ttgraph::*;

#[derive(TypedNode, Debug)]
struct NodeA{
  data: usize,
}

node_enum!{
  #[derive(Debug)]
  enum Node{
    A(NodeA)
  }
}

let ctx = Context::new();
let mut graph = Graph::<Node>::new(&ctx);
let mut trans = Transaction::new(&ctx);
let idx = trans.insert(Node::A(NodeA{
  data: 1
}));
graph.commit(trans).unwrap();

// node: Option<&Node>
let node = graph.get(idx);
if let Some(Node::A(node)) = node {
  assert_eq!(node.data, 1);
} else {
  panic!();
}

assert!(graph.get(NodeIndex::empty()).is_none());
Source

pub fn iter(&self) -> Arena::Iter<'_>

Iterate all nodes in the graph following the order of NodeIndex.

If only a type of node is wanted, use iter_nodes! instead.

§Example
use ttgraph::*;

#[derive(TypedNode, Debug)]
struct NodeA{
  a: usize
}
#[derive(TypedNode, Debug)]
struct NodeB{
  b: usize
}

node_enum!{
  #[derive(Debug)]
  enum Node{
    A(NodeA),
    B(NodeB),
  }
}

let ctx = Context::new();
let mut graph = Graph::<Node>::new(&ctx);
let mut trans = Transaction::new(&ctx);

trans.insert(Node::A(NodeA{ a: 1 }));
trans.insert(Node::A(NodeA{ a: 2 }));
trans.insert(Node::B(NodeB{ b: 0 }));
graph.commit(trans).unwrap();

// iterator.next() returns Option<(NodeIndex, &Node)>
let iterator = graph.iter();
for (i, (_, node)) in (1..3).zip(iterator) {
  if let Node::A(a) = node {
    assert_eq!(i, a.a);
  } else {
    panic!();
  }
}
Source

pub fn iter_type<'a>( &'a self, d: NodeT::Discriminant, ) -> NodeIterator<'a, NodeT, Iter<'a, usize, NodeT>>

Iterate a certain type of nodes denote by the discriminant. Time complexity is only related to the number of nodes of that kind. It is backed by ordermap::OrderMap so it should be fast.

§Example
use ttgraph::*;

#[derive(TypedNode, Debug)]
struct NodeA{
  a: usize
}
#[derive(TypedNode, Debug)]
struct NodeB{
  b: usize
}

node_enum!{
  #[derive(Debug)]
  enum Node{
    A(NodeA),
    B(NodeB),
  }
}

let ctx = Context::new();
let mut graph = Graph::<Node>::new(&ctx);
let mut trans = Transaction::new(&ctx);

trans.insert(Node::A(NodeA{ a: 1 }));
trans.insert(Node::A(NodeA{ a: 2 }));
trans.insert(Node::B(NodeB{ b: 0 }));
graph.commit(trans).unwrap();

for (_, node) in graph.iter_type(discriminant!(Node::A)){
  if let Node::A(a) = node {
    // Ok
  } else {
    panic!();
  }
}
Source

pub fn iter_group( &self, name: &'static str, ) -> impl Iterator<Item = (NodeIndex, &NodeT)>

Iterate all nodes within the named group

§Example
use ttgraph::*;
#[derive(TypedNode, Debug)]
struct NodeA {
  a: usize,
}
#[derive(TypedNode, Debug)]
struct NodeB {
  b: usize,
}
#[derive(TypedNode, Debug)]
struct NodeC {
  c: usize,
}
#[derive(TypedNode, Debug)]
struct NodeD {
  d: usize,
}

node_enum! {
  #[derive(Debug)]
  enum MultiNodes{
    A(NodeA),
    B(NodeB),
    C(NodeC),
    D(NodeD),
  }
  group!{
    first{A, B},
    second{C, D},
    third{A, D},
    one{B},
    all{A, B, C, D},
  }
}

 let ctx = Context::new();
 let mut graph = Graph::<MultiNodes>::new(&ctx);
 let mut trans = Transaction::new(&ctx);
 let a = trans.insert(MultiNodes::A(NodeA { a: 1 }));
 let b = trans.insert(MultiNodes::B(NodeB { b: 2 }));
 let c = trans.insert(MultiNodes::C(NodeC { c: 3 }));
 let d = trans.insert(MultiNodes::D(NodeD { d: 4 }));
 graph.commit(trans).unwrap();

 assert_eq!(Vec::from_iter(graph.iter_group("first").map(|(x, _)| x)), vec![a, b]);
 assert_eq!(Vec::from_iter(graph.iter_group("second").map(|(x, _)| x)), vec![c, d]);
 assert_eq!(Vec::from_iter(graph.iter_group("third").map(|(x, _)| x)), vec![a, d]);
 assert_eq!(Vec::from_iter(graph.iter_group("one").map(|(x, _)| x)), vec![b]);
 assert_eq!(Vec::from_iter(graph.iter_group("all").map(|(x, _)| x)), vec![a, b, c, d]);
Source

pub fn len(&self) -> usize

Get the number of nodes in a graph

§Example
use ttgraph::*;
#[derive(TypedNode, Debug)]
struct NodeA{
  data: usize,
}
node_enum!{
  #[derive(Debug)]
  enum Node{
    A(NodeA)
  }
}

let ctx = Context::new();
let mut graph = Graph::<Node>::new(&ctx);
assert_eq!(graph.len(), 0);
let mut trans = Transaction::new(&ctx);
trans.insert(Node::A(NodeA{data: 1}));
trans.insert(Node::A(NodeA{data: 1}));
trans.insert(Node::A(NodeA{data: 1}));
graph.commit(trans).unwrap();
assert_eq!(graph.len(), 3);
Source

pub fn is_empty(&self) -> bool

Check if the graph has no node

Source

pub fn commit( &mut self, t: Transaction<'_, NodeT, Arena>, ) -> Result<(), CommitError<NodeT>>

Commit an Transaction to modify the graph

Operation order:

  • Redirect nodes
  • Insert new nodes
  • Modify nodes
  • Update nodes
  • Redirect all nodes
  • Remove nodes
  • Add/Remove links due to bidirectional declaration
  • Check link types
§Panics

Panics if:

  • the transaction and the graph have different context
§Errors
  • there are multiple choices to make a bidirectional link (i.e. a.x <-> {b.y, b.z}, found a.x, don’t know if b.y=x or b.z=x)
  • type check failed

** Note that in current version, the contents in the graph is always changed after commit, even with an error occurs. In this case, the graph will be in an unstable state. **

§Example
use ttgraph::*;
#[derive(TypedNode, Debug)]
struct NodeA{
  data: usize,
}
node_enum!{
  #[derive(Debug)]
  enum Node{
    A(NodeA)
  }
}

let ctx = Context::new();
let mut graph = Graph::<Node>::new(&ctx);
let mut trans = Transaction::new(&ctx);
trans.insert(Node::A(NodeA{data: 1}));
graph.commit(trans).unwrap();
Source

pub fn commit_checked( &mut self, t: Transaction<'_, NodeT, Arena>, checks: &GraphCheck<NodeT>, ) -> Result<(), CommitError<NodeT>>

Similar to commit(), but with additional checks on the changed nodes and links.

See GraphCheck for more information.

Source

pub fn switch_context( self, new_ctx: &Context, ) -> Result<Self, CommitError<NodeT>>

Switch the context and relabel the node ids.

§Usecase:
  • Useful when there are a lot of removed NodeIndex, and after context switching the indexes will be more concise.
  • Merge two graphs with different context. See merge for example.
§Warning:
  • Please ensure there is no uncommitted transactions!
  • NodeIndex pointing to this graph is useless after context switching!
Source

pub fn check_integrity(&self)

Check if all links are internal, just for debug

Trait Implementations§

Source§

impl<T: NodeEnum + Debug> Debug for Graph<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: NodeEnum + Display> Display for Graph<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<NodeT, Arena> From<Graph<NodeT, Arena>> for GraphSerializer<NodeT>
where NodeT: NodeEnum, Arena: CateArena<V = NodeT, D = NodeT::Discriminant>,

Source§

fn from(value: Graph<NodeT, Arena>) -> GraphSerializer<NodeT>

Converts to this type from the input type.
Source§

impl<'a, T: NodeEnum + 'static, A: CateArena<V = T, D = T::Discriminant>> IntoIterator for &'a Graph<T, A>

Source§

type IntoIter = <A as CateArena>::Iter<'a>

Which kind of iterator are we turning this into?
Source§

type Item = (NodeIndex, &'a T)

The type of the elements being iterated over.
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

impl<T: NodeEnum, A: CateArena<V = T, D = T::Discriminant>> IntoIterator for Graph<T, A>

Source§

type IntoIter = <A as CateArena>::IntoIter

Which kind of iterator are we turning this into?
Source§

type Item = (NodeIndex, T)

The type of the elements being iterated over.
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

impl<NodeT, Arena> Serialize for Graph<NodeT, Arena>
where NodeT: NodeEnum + Serialize + 'static, Arena: CateArena<V = NodeT, D = NodeT::Discriminant>,

Source§

fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

§

impl<NodeT, Arena> Freeze for Graph<NodeT, Arena>
where Arena: Freeze,

§

impl<NodeT, Arena> RefUnwindSafe for Graph<NodeT, Arena>
where Arena: RefUnwindSafe, <NodeT as NodeEnum>::SourceEnum: RefUnwindSafe,

§

impl<NodeT, Arena> Send for Graph<NodeT, Arena>
where Arena: Send, <NodeT as NodeEnum>::SourceEnum: Send,

§

impl<NodeT, Arena> Sync for Graph<NodeT, Arena>
where Arena: Sync, <NodeT as NodeEnum>::SourceEnum: Sync,

§

impl<NodeT, Arena> Unpin for Graph<NodeT, Arena>
where Arena: Unpin, <NodeT as NodeEnum>::SourceEnum: Unpin,

§

impl<NodeT, Arena> UnwindSafe for Graph<NodeT, Arena>
where Arena: UnwindSafe, <NodeT as NodeEnum>::SourceEnum: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V