[−][src]Type Definition net_ensembles::graph::Graph
type Graph<T> = GenericGraph<T, NodeContainer<T>>;
Contains the topology and implements functions for analyzing topology
used for graph ensembles
Example:
A graph, where each node stores a phase
use net_ensembles::{traits::*,Graph}; use std::fs::File; use std::io::prelude::*; // define your own vertices, if you need to store extra information at each vertex #[derive(Debug, Clone)] pub struct PhaseNode {phase: f64,} // implement whatever you need impl PhaseNode { pub fn set_phase(&mut self, phase: f64) { self.phase = phase; } pub fn get_phase(&self) -> f64 { self.phase } } // implement the trait `Node` impl Node for PhaseNode { fn new_from_index(index: u32) -> Self { PhaseNode { phase: index as f64 * 10.0} } // if you do not wish to print/load etc. you can do the following. // I do not recommend this though fn make_string(&self) -> Option<String> { unimplemented!() } fn parse_str(_: &str) -> Option<(&str, Self)> { unimplemented!() } } // now you can create an empty graph let mut graph: Graph<PhaseNode> = Graph::new(4); for i in 0..4 { assert_eq!( graph.at(i).get_phase(), i as f64 * 10.0 ); } // and fill it with edges for i in 0..4 { graph.add_edge(i, (i + 1) % 4).unwrap(); } // you can manipulate the extra information stored at each Vertex for i in 0..4 { graph.at_mut(i).set_phase(i as f64 * 0.5); } // you can, of course, also access the information for i in 0..4 { assert_eq!( graph.at(i).get_phase(), i as f64 * 0.5 ); } // if you want to visualize your graph, you can generate a string with graphviz representation let dot = graph.to_dot_with_labels_from_contained( "", |contained, index| format!( "Phase: {} at index {}", contained.get_phase(), index ) ); // which you can store in a dot file let mut f = File::create("phase_example.dot").expect("Unable to create file"); f.write_all(dot.as_bytes()).expect("Unable to write data"); // or just print it out println!("{}", dot);
phase_example.dot
will then contain
graph G{
0 1 2 3 ;
"0" [label="Phase: 0 at index 0"];
"1" [label="Phase: 0.5 at index 1"];
"2" [label="Phase: 1 at index 2"];
"3" [label="Phase: 1.5 at index 3"];
0 -- 1
0 -- 3
1 -- 2
2 -- 3
}
Now you can use circo
or similar programs to create a pdf from that.
Search for graphviz for more info.
Example 2
- if you also want to be able to store your graph, you have to override two functions of the Node trait, as shown below
use net_ensembles::{Node,Graph,traits::*}; use std::fs::File; use std::io::prelude::*; // define your own vertices, if you need to store extra information at each vertex #[derive(Debug, Clone)] pub struct PhaseNode {phase: f64,} impl PhaseNode { pub fn set_phase(&mut self, phase: f64) { self.phase = phase; } pub fn get_phase(&self) -> f64 { self.phase } } impl Node for PhaseNode { fn new_from_index(index: u32) -> Self { PhaseNode { phase: 10.0 * index as f64 } } // Override this, to save the graph fn make_string(&self) -> Option<String> { Some(format!("phase: {},", self.phase)) } // Override this, since you want to load the stored graph fn parse_str(to_parse: &str) -> Option<(&str, Self)> where Self: Sized { let identifier = "phase: "; // searching for identifier let mut split_index = to_parse.find(identifier)?; // add length of identifier to index split_index += identifier.len(); // new string slice to skip to our identifier let remaining_to_parse = &to_parse[split_index..]; // find out, where our data ends split_index = remaining_to_parse.find(",")?; // create new string slice, beginning after what Node::make_string() created let (phase_str, mut remaining_to_parse) = remaining_to_parse.split_at(split_index); remaining_to_parse = &remaining_to_parse[1..]; // parse our data let phase = phase_str.parse::<f64>().ok()?; let node = PhaseNode{ phase }; // return our struct as option Some((remaining_to_parse, node)) } } // now you can create an empty graph let mut graph: Graph<PhaseNode> = Graph::new(4); for i in 0..4 { assert_eq!( graph.at(i).get_phase(), i as f64 * 10.0 ); } // and fill it with edges for i in 0..4 { graph.add_edge(i, (i + 1) % 4).unwrap(); } // you can manipulate the extra information stored at each Vertex for i in 0..4 { graph.at_mut(i).set_phase(i as f64 * 0.5); } // you can, of course, also access the information for i in 0..4 { assert_eq!( graph.at(i).get_phase(), i as f64 * 0.5 ); } // if you want to visualize your graph, you can generate a string with graphviz representation let dot = graph.to_dot_with_labels_from_contained( "", |contained, index| format!( "Phase: {} at index {}", contained.get_phase(), index ) ); // which you can store in a dot file let mut f = File::create("phase_example_still_works.dot").expect("Unable to create file"); f.write_all(dot.as_bytes()).expect("Unable to write data"); // or just print it out println!("{}", dot); // if you want to store your graph, you can do the following: // first get string representation let s = graph.to_string(); // open file let mut graph_file = File::create("store_graph_example.dat").expect("Unable to create file"); // write to file graph_file.write_all(s.as_bytes()).expect("Unable to write data"); // close file drop(graph_file); // now, if you want to load your network: let mut read_in = File::open("store_graph_example.dat").expect("unable to open file"); let mut test_data = String::new(); read_in.read_to_string(&mut test_data).expect("unable to read file"); // now we read the string. We still have to parse it: let (_, graph2) = Graph::<PhaseNode>::parse_str(&test_data).unwrap(); // now, to show, that the graphs are equal, here is one of my test functions: // modified for this example, which is a doc-test, so this example also serves as unit test fn assert_equal_graphs(g1: &Graph<PhaseNode>, g2: &Graph<PhaseNode>) { assert_eq!(g1.edge_count(), g2.edge_count()); assert_eq!(g1.vertex_count(), g2.vertex_count()); for (n0, n1) in g2.container_iter().zip(g1.container_iter()) { assert_eq!(n1.id(), n0.id()); assert_eq!(n0.degree(), n1.degree()); for (i, j) in n1.neighbors().zip(n0.neighbors()) { assert_eq!(i, j); } } for i in 0..g2.vertex_count() as usize { assert_eq!( g1.at(i).get_phase(), g2.at(i).get_phase() ); } } // lets use it assert_equal_graphs(&graph, &graph2); // you can also clone the graph, if you need: let clone = graph.clone(); assert_equal_graphs(&graph, &clone); let clone2 = graph2.clone(); assert_equal_graphs(&clone, &clone2);