use ordered_hashmap::OrderedHashMap; use std::collections::HashSet; use std::error::Error; use std::fmt::Debug; use std::hash::Hash; pub const DEFAULT_EDGE_NAME: &str = "\x00"; pub const GRAPH_NODE: &str = "\x00"; pub const EDGE_KEY_DELIM: &str = "\x01"; #[derive(Debug, Clone)] pub struct Edge { pub v: String, pub w: String, pub name: Option, } #[derive(Default)] pub struct GraphOption { pub directed: Option, pub multigraph: Option, pub compound: Option, } pub enum DefaultNodeLabel { Val(Option), Func(Box Option>), } pub enum DefaultEdgeLabel { Val(Option), Func(Box Option>), } pub enum EdgeOrString { Edge(E), String(String), } pub enum EdgeLabelOrString { EdgeLabel(E), String(String), } pub struct Graph where GL: Default, { // GraphLabel Type, Node Type, Node Index Type, Edge Type, Edge Index Type _is_directed: bool, _is_multigraph: bool, _is_compound: bool, // Label for the graph itself _label: GL, // Defaults to be set when creating a new node _default_node_label_fn: DefaultNodeLabel, // Defaults to be set when creating a new edge _default_edge_label_fn: DefaultEdgeLabel, // v -> label _nodes: OrderedHashMap, // v -> e -> edgeObj _in: OrderedHashMap>, // u -> v -> Number _preds: OrderedHashMap>, // v -> e -> edgeObj _out: OrderedHashMap>, // v -> w -> Number _sucs: OrderedHashMap>, // e -> edgeObj _edge_objs: OrderedHashMap, // e -> label _edge_labels: OrderedHashMap, /* Number of nodes in the graph. Should only be changed by the implementation. */ _node_count: usize, /* Number of edges in the graph. Should only be changed by the implementation. */ _edge_count: usize, // v -> w _parent: OrderedHashMap, // v -> w -> boolean _children: OrderedHashMap>, } impl Default for Graph { fn default() -> Self { Self { _is_directed: true, _is_multigraph: false, _is_compound: false, _label: GL::default(), _default_node_label_fn: DefaultNodeLabel::Val(None), _default_edge_label_fn: DefaultEdgeLabel::Val(None), _nodes: OrderedHashMap::new(), _in: OrderedHashMap::new(), _preds: OrderedHashMap::new(), _out: OrderedHashMap::new(), _sucs: OrderedHashMap::new(), _edge_objs: OrderedHashMap::new(), _edge_labels: OrderedHashMap::new(), _node_count: 0, _edge_count: 0, _parent: OrderedHashMap::new(), _children: OrderedHashMap::new(), } } } impl Graph { pub fn new(opts: Option) -> Self { let mut graph = Self::default(); if let Some(_opts) = opts { if _opts.directed.is_some() { graph._is_directed = _opts.directed.unwrap(); } else { graph._is_directed = true; } if _opts.multigraph.is_some() { graph._is_multigraph = _opts.multigraph.unwrap(); } else { graph._is_multigraph = false; } if _opts.multigraph.is_some() { graph._is_multigraph = _opts.multigraph.unwrap(); } else { graph._is_multigraph = false; } if _opts.compound.is_some() { graph._is_compound = _opts.compound.unwrap(); } else { graph._is_compound = false; } } if graph._is_compound { // v -> parent graph._parent = OrderedHashMap::new(); graph._children = OrderedHashMap::new(); graph ._children .insert(GRAPH_NODE.clone().to_string(), OrderedHashMap::new()); } graph } /* === Graph functions ========= */ /** * Whether graph was created with 'directed' flag set to true or not. */ pub fn is_directed(&self) -> bool { return self._is_directed; } /** * Whether graph was created with 'multigraph' flag set to true or not. */ pub fn is_multigraph(&self) -> bool { return self._is_multigraph; } /** * Whether graph was created with 'compound' flag set to true or not. */ pub fn is_compound(&self) -> bool { return self._is_compound; } /** * Sets the label of the graph. */ pub fn set_graph(&mut self, label: GL) -> &mut Self { self._label = label; return self; } /** * Gets the graph label. */ pub fn graph(&self) -> &GL { return &self._label; } /** * Gets the graph label. */ pub fn graph_mut(&mut self) -> &mut GL { return &mut self._label; } /* === Node functions ========== */ /** * Sets the default node label. If newDefault is a function, it will be * invoked ach time when setting a label for a node. Otherwise, this label * will be assigned as default label in case if no label was specified while * setting a node. * Complexity: O(1). */ pub fn set_default_node_label(&mut self, new_default: DefaultNodeLabel) -> &mut Self { self._default_node_label_fn = new_default; return self; } pub fn default_node_label(&self, node_id: String) -> N { let mut _node_label: Option = None; match &self._default_node_label_fn { DefaultNodeLabel::Func(node_label_fn) => { _node_label = node_label_fn(node_id.clone()); } DefaultNodeLabel::Val(node_label_) => { if node_label_.is_some() { _node_label = Some(node_label_.clone().unwrap()); } else { _node_label = Some(N::default()); } } } return _node_label.unwrap(); } /** * Gets the number of nodes in the graph. * Complexity: O(1). */ pub fn node_count(&self) -> usize { return self._node_count; } /** * Gets all nodes of the graph. Note, the in case of compound graph subnodes are * not included in list. * Complexity: O(1). */ pub fn nodes(&self) -> Vec { return self._nodes.keys().cloned().collect(); } /** * Gets list of nodes without in-edges. * Complexity: O(|V|). */ pub fn sources(&self) -> Vec { return self .nodes() .iter() .filter(|n| { if let Some(in_edges) = self._in.get(&n.to_owned().clone()) { return in_edges.len() == 0; } return true; }) .map(|node_id| node_id.clone()) .collect(); } /** * Gets list of nodes without out-edges. * Complexity: O(|V|). */ pub fn sinks(&self) -> Vec { return self .nodes() .iter() .filter(|n| { if let Some(out_edges) = self._out.get(&n.to_owned().clone()) { return out_edges.len() == 0; } return true; }) .map(|node_id| node_id.clone()) .collect(); } /** * Invokes setNode method for each node in names list. * Complexity: O(|names|). */ pub fn set_nodes(&mut self, node_ids: Vec, value: Option) -> &mut Self { node_ids.iter().for_each(|node_id| { self.set_node(node_id.to_owned(), value.clone()); }); return self; } /** * Creates or updates the value for the node v in the graph. If label is supplied * it is set as the value for the node. If label is not supplied and the node was * created by this call then the default node label will be assigned. * Complexity: O(1). */ pub fn set_node(&mut self, v: String, value: Option) -> &mut Self { if self._nodes.get(&v).is_some() { if value.is_some() { self._nodes.insert(v, value.unwrap()); } return self; } if value.is_some() { self._nodes.insert(v.clone(), value.unwrap()); } else { self._nodes .insert(v.clone(), self.default_node_label(v.clone())); } if self._is_compound { let _graph_node = GRAPH_NODE.clone().to_string(); self._parent.insert(v.clone(), _graph_node.clone()); self._children.insert(v.clone(), OrderedHashMap::new()); self._children .entry(_graph_node.clone()) .or_insert(OrderedHashMap::new()) .entry(v.clone()) .or_insert(true); } self._in.insert(v.clone(), OrderedHashMap::new()); self._preds.insert(v.clone(), OrderedHashMap::new()); self._out.insert(v.clone(), OrderedHashMap::new()); self._sucs.insert(v.clone(), OrderedHashMap::new()); self._node_count += 1; return self; } /** * Gets the label of node with specified name. * Complexity: O(|V|). */ pub fn node(&self, v: &String) -> Option<&N> { return self._nodes.get(v); } /** * Gets the label of node with specified name. * Complexity: O(|V|). */ pub fn node_mut(&mut self, v: &String) -> Option<&mut N> { return self._nodes.get_mut(v); } /** * Detects whether graph has a node with specified name or not. */ pub fn has_node(&self, v: &String) -> bool { return self._nodes.contains_key(v); } /** * Remove the node with the name from the graph or do nothing if the node is not in * the graph. If the node was removed this function also removes any incident * edges. * Complexity: O(1). */ pub fn remove_node(&mut self, v: &String) -> &mut Self { if self._nodes.contains_key(v) { self._nodes.remove(v); if self._is_compound { self._remove_from_parents_child_list(v); if self._parent.contains_key(v) { self._parent.remove(v); } self.children(v).iter().for_each(|child_id| { // TODO: exception handling let _ = self.set_parent(child_id, None); }); self._children.remove(v); } // removing in edges if let Some(in_edges) = self._in.get(v) { let edge_ids: Vec = in_edges.keys().cloned().collect(); edge_ids.iter().for_each(|edge_id| { if let Some(edge) = self._edge_objs.get(edge_id) { self.remove_edge_with_obj(&edge.to_owned()); } }); self._in.remove(v); } self._preds.remove(v); // removing out edges if let Some(out_edges) = self._out.get(v) { let edge_ids: Vec = out_edges.keys().cloned().collect(); edge_ids.iter().for_each(|edge_id| { if let Some(edge) = self._edge_objs.get(edge_id) { self.remove_edge_with_obj(&edge.to_owned()); } }); self._out.remove(v); } self._sucs.remove(v); self._node_count -= 1; } return self; } /** * Sets node p as a parent for node v if it is defined, or removes the * parent for v if p is undefined. Method throws an exception in case of * invoking it in context of noncompound graph. * Average-case complexity: O(1). */ pub fn set_parent( &mut self, v: &String, parent: Option, ) -> Result<&mut Self, Box> { if !self._is_compound { return Err("Cannot set parent in a non-compound graph".into()); } let mut _parent: String = "".to_string(); if parent.is_none() { _parent = GRAPH_NODE.to_string(); } else { _parent = parent.unwrap().clone(); let mut ancestor = _parent.clone(); while let Some(new_ancestor) = self.parent(&ancestor) { if &new_ancestor == &v { return Err(format!( "Setting {} as parent of {} would create a cycle", _parent.clone(), v ) .into()); } ancestor = new_ancestor.clone(); } self.set_node(_parent.clone(), None); } self.set_node(v.clone(), None); self._remove_from_parents_child_list(v); self._parent.insert(v.clone(), _parent.clone()); self._children .entry(_parent.clone()) .or_insert_with(OrderedHashMap::new) .insert(v.clone(), true); Ok(self) } pub fn _remove_from_parents_child_list(&mut self, v: &String) { if let Some(parent) = self._parent.get(v) { if let Some(children) = self._children.get_mut(parent) { children.remove(v); } } } /** * Gets parent node for node v. * Complexity: O(1). */ pub fn parent(&self, v: &String) -> Option<&String> { if self._is_compound { if let Some(parent) = self._parent.get(v) { if parent != GRAPH_NODE { return Some(parent); } } } None } /** * Gets list of direct children of node v. * Complexity: O(1). */ pub fn children(&self, v: &String) -> Vec { if self._is_compound { if let Some(children) = self._children.get(v) { return children.keys().cloned().collect(); } } else if v == GRAPH_NODE { return self._nodes.keys().cloned().collect(); } else if self.has_node(&v) { return vec![]; } vec![] } /** * Return all nodes that are predecessors of the specified node or undefined if node v is not in * the graph. Behavior is undefined for undirected graphs - use neighbors instead. * Complexity: O(|V|). */ pub fn predecessors(&self, v: &String) -> Option> { if let Some(preds) = self._preds.get(v) { return Some(preds.keys().cloned().collect()); } None } /** * Return all nodes that are successors of the specified node or undefined if node v is not in * the graph. Behavior is undefined for undirected graphs - use neighbors instead. * Complexity: O(|V|). */ pub fn successors(&self, v: &String) -> Option> { if let Some(sucs) = self._sucs.get(v) { return Some(sucs.keys().cloned().collect()); } None } /** * Return all nodes that are predecessors or successors of the specified node or undefined if * node v is not in the graph. * Complexity: O(|V|). */ pub fn neighbors(&self, v: &String) -> Option> { if let Some(preds) = self.predecessors(v) { let mut union: HashSet = HashSet::new(); preds.into_iter().for_each(|pred| { union.insert(pred); }); if let Some(sucs) = self.successors(v) { sucs.into_iter().for_each(|successor| { union.insert(successor); }); } return Some(union.into_iter().collect()); } None } pub fn is_leaf(&self, v: &String) -> bool { let mut _neighbors: Option> = None; if self.is_directed() { _neighbors = self.successors(v); } else { _neighbors = self.neighbors(v); } if _neighbors.is_none() || _neighbors.unwrap().len() == 0 { return true; } false } /** * Creates new graph with nodes filtered via filter. Edges incident to rejected node * are also removed. In case of compound graph, if parent is rejected by filter, * than all its children are rejected too. * Average-case complexity: O(|E|+|V|). */ pub fn filter_nodes(&self, filter: F) -> Self where F: Fn(&String) -> bool, { let mut copy: Graph = Graph::new(Some(GraphOption { directed: Some(self._is_directed.clone()), multigraph: Some(self._is_multigraph.clone()), compound: Some(self._is_compound.clone()), })); for (v, value) in self._nodes.iter() { if filter(v) { copy.set_node(v.clone(), Some(value.clone())); } } for e_v in self._edge_objs.values() { if copy._nodes.contains_key(&e_v.v) && copy._nodes.contains_key(&e_v.w) { if let Some(edge_label) = self.edge_with_obj(e_v) { let _ = copy.set_edge_with_obj(e_v, Some(edge_label.to_owned())); } } } let mut parents: OrderedHashMap = OrderedHashMap::new(); if self._is_compound { let node_ids: Vec = copy._nodes.keys().cloned().into_iter().collect(); for v in node_ids { let parent = find_parent(&v, &mut parents, &mut copy, self); let _ = copy.set_parent(&v, parent); } } copy } /* === Edge functions ========== */ /** * Sets the default edge label or factory function. This label will be * assigned as default label in case if no label was specified while setting * an edge or this function will be invoked each time when setting an edge * with no label specified and returned value * will be used as a label for edge. * Complexity: O(1). */ pub fn set_default_edge_label(&mut self, new_default: DefaultEdgeLabel) -> &mut Self { self._default_edge_label_fn = new_default; return self; } pub fn default_edge_label(&self, edge_id: String) -> E { let mut _edge_label: Option = None; match &self._default_edge_label_fn { DefaultEdgeLabel::Func(edge_label_fn) => { _edge_label = edge_label_fn(edge_id.clone()); } DefaultEdgeLabel::Val(edge_label_) => { if edge_label_.is_some() { _edge_label = Some(edge_label_.clone().unwrap()); } else { _edge_label = Some(E::default()); } } } return _edge_label.unwrap(); } /** * Gets the number of edges in the graph. * Complexity: O(1). */ pub fn edge_count(&self) -> usize { return self._edge_count.clone(); } /** * Gets edges of the graph. In case of compound graph subgraphs are not considered. * Complexity: O(|E|). */ pub fn edges(&self) -> Vec { return self._edge_objs.values().cloned().collect(); } /** * Establish an edges path over the nodes in nodes list. If some edge is already * exists, it will update its label, otherwise it will create an edge between pair * of nodes with label provided or default label if no label provided. * Complexity: O(|nodes|). */ pub fn set_path(&mut self, vs: &Vec, value: Option) { vs.iter().reduce(|v1, v2| { let _ = self.set_edge(v1, v2, value.clone(), None); v2 }); } /** * Creates or updates the label for the edge (v, w) with the optionally supplied * name. If label is supplied it is set as the value for the edge. If label is not * supplied and the edge was created by this call then the default edge label will * be assigned. The name parameter is only useful with multigraphs. */ pub fn set_edge( &mut self, v: &String, w: &String, edge_label: Option, name: Option, ) -> Result<&mut Self, Box> { let e = edge_args_to_id(&self._is_directed, v, w, &name); if self._edge_labels.contains_key(&e) { if edge_label.is_some() { self._edge_labels.insert(e.clone(), edge_label.unwrap()); } return Ok(self); } if name.is_some() && !self._is_multigraph { return Err("Cannot set a named edge when isMultigraph = false".into()); } // It didn't exist, so we need to create it. // First ensure the nodes exist. self.set_node(v.clone(), None); self.set_node(w.clone(), None); if edge_label.is_some() { self._edge_labels .insert(e.clone(), edge_label.clone().unwrap()); } else { self._edge_labels .insert(e.clone(), self.default_edge_label(e.clone())); } let edge_obj = edge_args_to_obj(&self.is_directed(), v, w, &name); // Ensure we add undirected edges in a consistent way. self._edge_objs.insert(e.clone(), edge_obj.clone()); if let Some(preds) = self._preds.get_mut(w) { increment_or_init_entry(preds, v); } if let Some(sucs) = self._sucs.get_mut(v) { increment_or_init_entry(sucs, w); } let in_edges = self ._in .entry(w.clone()) .or_insert_with(OrderedHashMap::new); in_edges.insert(e.clone(), edge_obj.clone()); let out_edges = self ._out .entry(v.clone()) .or_insert_with(OrderedHashMap::new); out_edges.insert(e.clone(), edge_obj.clone()); self._edge_count += 1; return Ok(self); } pub fn set_edge_with_obj( &mut self, e: &Edge, edge_label: Option, ) -> Result<&mut Self, Box> { self.set_edge(&e.v, &e.w, edge_label, None) } /** * Gets the label for the specified edge. * Complexity: O(1). */ pub fn edge(&self, v: &String, w: &String, name: Option) -> Option<&E> { let e = edge_args_to_id(&self._is_directed, v, w, &name); return self._edge_labels.get(&e); } /** * Gets the label for the specified edge. * Complexity: O(1). */ pub fn edge_with_obj(&self, edge: &Edge) -> Option<&E> { let e = edge_obj_to_id(&self._is_directed, edge); return self._edge_labels.get(&e); } /** * Gets the label for the specified edge. * Complexity: O(1). */ pub fn edge_mut(&mut self, v: &String, w: &String, name: Option) -> Option<&mut E> { let e = edge_args_to_id(&self._is_directed, v, w, &name); return self._edge_labels.get_mut(&e); } /** * Gets the label for the specified edge. * Complexity: O(1). */ pub fn edge_mut_with_obj(&mut self, edge: &Edge) -> Option<&mut E> { let e = edge_obj_to_id(&self._is_directed, edge); return self._edge_labels.get_mut(&e); } /** * Detects whether the graph contains specified edge or not. No subgraphs are considered. * Complexity: O(1). */ pub fn has_edge(&self, v: &String, w: &String, name: Option) -> bool { let e = edge_args_to_id(&self._is_directed, v, w, &name); self._edge_labels.contains_key(&e) } pub fn has_edge_with_obj(&self, edge: &Edge) -> bool { let e = edge_obj_to_id(&self._is_directed, edge); self._edge_labels.contains_key(&e) } /** * Removes the specified edge from the graph. No subgraphs are considered. * Complexity: O(1). */ pub fn remove_edge(&mut self, v: &String, w: &String, name: Option) -> &mut Self { let e: String = edge_args_to_id(&self._is_directed, v, w, &name); if let Some(edge) = self._edge_objs.get_mut(&e) { let v = edge.v.clone(); let w = edge.w.clone(); self._edge_labels.remove(&e); self._edge_objs.remove(&e); if self._preds.contains_key(&w) { decrement_or_remove_entry(self._preds.get_mut(&w).unwrap(), &v); } if self._sucs.contains_key(&v) { decrement_or_remove_entry(self._sucs.get_mut(&v).unwrap(), &w); } if self._in.contains_key(&w) { self._in.get_mut(&w).unwrap().remove(&e); } if self._out.contains_key(&v) { self._out.get_mut(&v).unwrap().remove(&e); } self._edge_count -= 1; } return self; } /** * Removes the specified edge from the graph. No subgraphs are considered. * Complexity: O(1). */ pub fn remove_edge_with_obj(&mut self, e: &Edge) -> &mut Self { self.remove_edge(&e.v, &e.w, None); return self; } /** * Return all edges that point to the node v. Optionally filters those edges down to just those * coming from node u. Behavior is undefined for undirected graphs - use nodeEdges instead. * Complexity: O(|E|). */ pub fn in_edges(&self, v: &String, u: Option) -> Option> { if let Some(in_edges) = self._in.get(v) { let mut _in_edges: Vec = in_edges.values().cloned().collect(); if u.is_none() { return Some(_in_edges.clone()); } let _u = u.unwrap(); return Some(_in_edges.into_iter().filter(|edge| edge.v == _u).collect()); } None } /** * Return all edges that are pointed at by node v. Optionally filters those edges down to just * those point to w. Behavior is undefined for undirected graphs - use nodeEdges instead. * Complexity: O(|E|). */ pub fn out_edges(&self, v: &String, w: Option) -> Option> { if let Some(out_edges) = self._out.get(v) { let mut _out_edges: Vec = out_edges.values().cloned().collect(); if w.is_none() { return Some(_out_edges.clone()); } let _w = w.unwrap(); return Some(_out_edges.into_iter().filter(|edge| edge.w == _w).collect()); } None } /** * Returns all edges to or from node v regardless of direction. Optionally filters those edges * down to just those between nodes v and w regardless of direction. * Complexity: O(|E|). */ pub fn node_edges(&self, v: &String, w: Option) -> Option> { let _in_edges = self.in_edges(v, w.clone()); if let Some(mut in_edges) = _in_edges { let _out_edges = self.out_edges(v, w.clone()); if let Some(out_edges) = _out_edges { in_edges.append(out_edges.clone().as_mut()); } return Some(in_edges); } None } } fn increment_or_init_entry(map: &mut OrderedHashMap, k: &K) { if let Some(e) = map.get_mut(&k) { *e += 1; } else { map.insert(k.clone(), 1); } } fn decrement_or_remove_entry(map: &mut OrderedHashMap, k: &K) { if let Some(value) = map.get_mut(k) { *value -= 1; if *value <= 0 { map.remove(k); } } } fn edge_args_to_id(is_directed: &bool, v_: &String, w_: &String, name: &Option) -> String { let mut v: &str = &*v_; let mut w: &str = &*w_; if !is_directed.to_owned() && v > w { let tmp = v; v = w; w = tmp; } if name.is_some() { return v.to_owned() + EDGE_KEY_DELIM + w + EDGE_KEY_DELIM + &*name.clone().unwrap(); } return v.to_owned() + EDGE_KEY_DELIM + w + EDGE_KEY_DELIM + DEFAULT_EDGE_NAME; } fn edge_args_to_obj(is_directed: &bool, v_: &String, w_: &String, name: &Option) -> Edge { let mut v: &str = &*v_; let mut w: &str = &*w_; if !is_directed.to_owned() && v > w { let tmp = v; v = w; w = tmp; } return Edge { v: v.to_string(), w: w.to_string(), name: name.clone(), }; } fn edge_obj_to_id(is_directed: &bool, edge: &Edge) -> String { return edge_args_to_id(is_directed, &edge.v, &edge.w, &edge.name); } fn find_parent( v: &String, parents: &mut OrderedHashMap, copy: &mut Graph, graph: &Graph, ) -> Option { let parent = graph.parent(v); if parent.is_none() || copy._nodes.contains_key(&parent.unwrap().clone()) { if !parent.is_none() { parents.insert(v.clone(), parent.unwrap().clone()); return parent.cloned(); } None } else if let Some(parent_value) = parents.get(&parent.unwrap().clone()) { Some(parent_value.clone()) } else { if parent.is_some() { find_parent(parent.as_ref().unwrap(), parents, copy, graph) } else { None } } }