use std::cmp;
use traits::BasicGraphMethods;
#[derive(PartialEq, Clone, Debug)]
pub struct SimpleGraph {
size: usize,
weights: Vec<Option<f64>>,
}
impl SimpleGraph {
pub fn new(size: usize) -> SimpleGraph {
let weights: Vec<Option<f64>> = match size {
0 => vec![],
_ => vec![None; size * (size - 1) / 2]
};
SimpleGraph {
size: size,
weights: weights
}
}
pub fn from_vec(weights: &Vec<Option<f64>>) -> SimpleGraph {
let size: usize
= (((1.0f64 + 8.0f64 * (weights.len() as f64)).powf(0.5f64)
+ 1.0f64) / 2.0f64)
.ceil() as usize;
assert!(weights.len() == size * (size - 1) / 2,
"The weights vector does not fit the size of the upper \
right triangle of a matrix.");
SimpleGraph {
size: size,
weights: weights.clone()
}
}
pub fn to_vec(&self) -> Vec<Option<f64>> {
self.weights.clone()
}
pub fn to_digraph_vec(&self) -> Vec<Option<f64>> {
let mut matrix = self.weights.clone();
let size = self.size();
for i in 0..size {
for j in 0..i {
let value = matrix[j * size + i];
matrix.insert(i * size + j, value);
}
matrix.insert(i * (size + 1), None);
}
matrix
}
}
impl BasicGraphMethods for SimpleGraph {
fn size(&self) -> usize {
self.size
}
fn get_edge(&self, edge: (usize, usize)) -> Option<f64> {
let size: usize = self.size();
assert!(edge.0 < size, "The first node index is out of range.");
assert!(edge.1 < size, "The second node index is out of range.");
let (node1, node2): (usize, usize)
= (cmp::min(edge.0, edge.1), cmp::max(edge.0, edge.1));
if node1 == node2 {
return None;
};
self.weights[size * node1 + node2 - (node1 + 2) * (node1 + 1) / 2]
}
fn set_edge(&mut self, edge: (usize, usize), value: Option<f64>) {
let size: usize = self.size();
assert!(edge.0 < size, "The first node index is out of range.");
assert!(edge.1 < size, "The second node index is out of range.");
assert!(edge.0 != edge.1, "A SimpleGraph object cannot have loops.");
let (node1, node2): (usize, usize)
= (cmp::min(edge.0, edge.1), cmp::max(edge.0, edge.1));
self.weights[size * node1 + node2 - (node1 + 2) * (node1 + 1) / 2]
= value;
}
}
#[cfg(test)]
mod test {
use traits::BasicGraphMethods;
#[test]
fn test_graph_construction_1() {
let u1 = vec![
Some(4.0f64), None, Some(-1.0f64),
Some(2.5f64), Some(-3.0f64),
None
];
let w1 = vec![
None, Some(4.0f64), None, Some(-1.0f64),
Some(4.0f64), None, Some(2.5f64), Some(-3.0f64),
None, Some(2.5f64), None, None,
Some(-1.0f64), Some(-3.0f64), None, None
];
let mut g = super::SimpleGraph::from_vec(&u1);
let edges1 = vec![
g.get_edge((0, 0)), g.get_edge((0, 1)),
g.get_edge((0, 2)), g.get_edge((0, 3)),
g.get_edge((1, 0)), g.get_edge((1, 1)),
g.get_edge((1, 2)), g.get_edge((1, 3)),
g.get_edge((2, 0)), g.get_edge((2, 1)),
g.get_edge((2, 2)), g.get_edge((2, 3)),
g.get_edge((3, 0)), g.get_edge((3, 1)),
g.get_edge((3, 2)), g.get_edge((3, 3)),
];
assert_eq!(edges1, w1);
assert_eq!(g.to_digraph_vec(), w1);
assert_eq!(g.size(), 4);
g.set_edge((0, 2), Some(1.0f64));
g.set_edge((3, 2), Some(3.0f64));
let e03: f64 = g.get_edge((3, 0)).unwrap();
g.set_edge((0, 3), Some(-e03));
let e13: f64 = g.get_edge((3, 1)).unwrap();
g.set_edge((1, 3), Some(0.0f64 * e13));
let w2 = vec![
None, Some(4.0f64), Some(1.0f64), Some(1.0f64),
Some(4.0f64), None, Some(2.5f64), Some(-0.0f64),
Some(1.0f64), Some(2.5f64), None, Some(3.0f64),
Some(1.0f64), Some(-0.0f64), Some(3.0f64), None
];
let edges2 = vec![
g.get_edge((0, 0)), g.get_edge((0, 1)),
g.get_edge((0, 2)), g.get_edge((0, 3)),
g.get_edge((1, 0)), g.get_edge((1, 1)),
g.get_edge((1, 2)), g.get_edge((1, 3)),
g.get_edge((2, 0)), g.get_edge((2, 1)),
g.get_edge((2, 2)), g.get_edge((2, 3)),
g.get_edge((3, 0)), g.get_edge((3, 1)),
g.get_edge((3, 2)), g.get_edge((3, 3)),
];
assert_eq!(edges2, w2);
assert_eq!(g.to_digraph_vec(), w2);
assert_eq!(g.size(), 4);
}
#[test]
#[should_panic]
fn test_graph_construction_2() {
let w: Vec<Option<f64>> = vec![None, Some(1.0f64)];
super::SimpleGraph::from_vec(&w);
}
#[test]
fn test_graph_construction_3() {
let g = super::SimpleGraph::new(0);
let w: Vec<Option<f64>> = vec![];
assert_eq!(g.size(), 0);
assert_eq!(g.to_vec(), w);
}
#[test]
#[should_panic]
fn test_graph_construction_4() {
let g = super::SimpleGraph::new(0);
g.get_edge((0, 0));
}
#[test]
fn test_graph_construction_5() {
let g = super::SimpleGraph::new(1);
let w: Vec<Option<f64>> = vec![];
assert_eq!(g.size(), 1);
assert_eq!(g.to_vec(), w);
assert_eq!(g.get_edge((0, 0)), None);
}
#[test]
fn test_graph_construction_6() {
let w: Vec<Option<f64>> = vec![];
let g = super::SimpleGraph::from_vec(&w);
assert_eq!(g.size(), 1);
assert_eq!(g.to_vec(), w);
assert_eq!(g.get_edge((0, 0)), None);
}
#[test]
#[should_panic]
fn test_graph_construction_7() {
let mut g = super::SimpleGraph::new(2);
g.set_edge((1, 1), Some((1.0f64)));
}
}