use std::collections::BTreeMap;
#[derive(Debug)]
pub struct DirectedLabelGraph<D> {
nodes: BTreeMap<String, LabelGraphNode<D>>,
}
impl<D> DirectedLabelGraph<D> {
pub fn new() -> Self {
DirectedLabelGraph::default()
}
fn get_node(&self, node_label: &str) -> Option<&LabelGraphNode<D>> {
self.nodes.get(node_label)
}
fn get_mut_node(&mut self, node_label: &str) -> Option<&mut LabelGraphNode<D>> {
self.nodes.get_mut(node_label)
}
pub fn check_node_exists(&self, node_label: &str) -> bool {
self.nodes.contains_key(node_label)
}
pub fn create_node(&mut self, node_label: &str, node_data: D) {
if self.check_node_exists(node_label) {
self.nodes.get_mut(node_label).unwrap().data = node_data;
} else {
self.nodes
.insert(node_label.to_string(), LabelGraphNode::new(node_data));
}
}
pub fn get_node_data(&self, node_label: &str) -> Option<&D> {
self.get_node(node_label).map(|n| &n.data)
}
pub fn get_mut_node_data(&mut self, node_label: &str) -> Option<&mut D> {
self.get_mut_node(node_label).map(|n| &mut n.data)
}
pub fn link_nodes(&mut self, from_node_label: &str, to_node_label: &str, weight: i64) {
if !self.check_node_exists(from_node_label) {
panic!("node {} doesn't exist", from_node_label);
} else if !self.check_node_exists(to_node_label) {
panic!("node {} doesn't exist", to_node_label);
}
if let Some(node) = self.get_mut_node(from_node_label) {
match node.connections.iter_mut().find(|edge| {
edge.node_label == to_node_label && edge.direction == ConnectionDirection::To
}) {
Some(edge) => {
edge.weight = weight;
}
None => {
node.connections.push(LabelGraphEdge::new(
to_node_label.to_string(),
ConnectionDirection::To,
weight,
))
}
};
}
if let Some(node) = self.get_mut_node(to_node_label) {
match node.connections.iter_mut().find(|edge| {
edge.node_label == from_node_label && edge.direction == ConnectionDirection::From
}) {
Some(edge) => {
edge.weight = weight;
}
None => {
node.connections.push(LabelGraphEdge::new(
from_node_label.to_string(),
ConnectionDirection::From,
weight,
))
}
};
};
}
pub fn get_inputs_for_node(&self, node_label: &str) -> Option<Vec<&LabelGraphEdge>> {
if let Some(node) = self.get_node(node_label) {
Some(
node.connections
.iter()
.filter(|edge| edge.direction == ConnectionDirection::From)
.collect(),
)
} else {
None
}
}
pub fn get_outputs_for_node(&self, node_label: &str) -> Option<Vec<&LabelGraphEdge>> {
let node = self.get_node(node_label);
if node.is_some() {
Some(
node.unwrap()
.connections
.iter()
.filter(|edge| edge.direction == ConnectionDirection::To)
.collect(),
)
} else {
None
}
}
pub fn iter_node_data(&self) -> impl Iterator<Item = &D> {
IterGraphNodeData::new(self.nodes.values().map(|node| &node.data).collect())
}
pub fn iter_node_label_and_data(&self) -> impl Iterator<Item = (&String, &D)> {
IterGraphNodeLabelAndData::new(
self.nodes
.iter()
.map(|node| (node.0, &node.1.data))
.collect(),
)
}
}
impl<D> Default for DirectedLabelGraph<D> {
fn default() -> Self {
DirectedLabelGraph {
nodes: BTreeMap::new(),
}
}
}
pub struct IterGraphNodeData<'a, D> {
curr_idx: usize,
items: Vec<&'a D>,
}
impl<'a, D> IterGraphNodeData<'a, D> {
pub fn new(items: Vec<&'a D>) -> Self {
IterGraphNodeData { curr_idx: 0, items }
}
}
impl<'a, D> Iterator for IterGraphNodeData<'a, D> {
type Item = &'a D;
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
if self.curr_idx >= self.items.len() {
None
} else {
self.curr_idx += 1;
Some(self.items[self.curr_idx - 1])
}
}
}
pub struct IterGraphNodeLabelAndData<'a, D> {
curr_idx: usize,
items: Vec<(&'a String, &'a D)>,
}
impl<'a, D> IterGraphNodeLabelAndData<'a, D> {
pub fn new(items: Vec<(&'a String, &'a D)>) -> Self {
IterGraphNodeLabelAndData { curr_idx: 0, items }
}
}
impl<'a, D> Iterator for IterGraphNodeLabelAndData<'a, D> {
type Item = (&'a String, &'a D);
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
if self.curr_idx >= self.items.len() {
None
} else {
self.curr_idx += 1;
Some(self.items[self.curr_idx - 1])
}
}
}
#[derive(Debug, Clone)]
pub struct LabelGraphEdge {
direction: ConnectionDirection,
node_label: String,
weight: i64,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum ConnectionDirection {
From,
To,
}
impl LabelGraphEdge {
fn new(node_label: String, direction: ConnectionDirection, weight: i64) -> LabelGraphEdge {
LabelGraphEdge {
direction,
node_label,
weight,
}
}
pub fn get_connection_direction(&self) -> ConnectionDirection {
self.direction
}
pub fn get_connected_label(&self) -> String {
self.node_label.clone()
}
pub fn get_edge_weight(&self) -> i64 {
self.weight
}
}
#[derive(Debug, Clone)]
struct LabelGraphNode<D> {
connections: Vec<LabelGraphEdge>,
data: D,
}
impl<D> LabelGraphNode<D> {
pub fn new(data: D) -> Self {
LabelGraphNode {
connections: Vec::new(),
data,
}
}
}