use std::collections::VecDeque;
use std::collections::HashSet;
use std::collections::BinaryHeap;
use std::cmp::Ordering;
pub struct Node<T> {
pub content: T,
pub adjecent: Vec<Vertex>,
}
#[derive(Eq, PartialEq, Debug)]
pub struct Vertex {
pub cost: i32,
pub node: usize
}
impl Ord for Vertex {
fn cmp(&self, other: &Vertex) -> Ordering {
other.cost.cmp(&self.cost)
}
}
impl PartialOrd for Vertex {
fn partial_cmp(&self, other: &Vertex) -> Option<Ordering> {
Some(self.cmp(other))
}
}
pub struct Graph<T> {
graph: Vec<Node<T>>
}
impl <T: PartialEq> Graph<T> {
pub fn new(input: Vec<Node<T>>) -> Graph<T> {
Graph { graph: input }
}
pub fn search(&self, start: usize, target: T) -> Option<VecDeque<usize>> {
return self.dijkstra(start, &target)
}
pub fn search_using_index(&self, start: usize, target: usize) -> Option<VecDeque<usize>> {
return self.dijkstra_using_index(start, target)
}
pub fn breadth_first_search(&self, start: usize, target: T) -> Option<VecDeque<usize>> {
return self.inner_search(start, &target, true)
}
pub fn breadth_first_search_using_index(&self, start: usize, target: usize) -> Option<VecDeque<usize>> {
return self.inner_search_using_index(start, target, true)
}
pub fn depth_first_search(&self, start: usize, target: T) -> Option<VecDeque<usize>> {
return self.inner_search(start, &target, false)
}
pub fn depth_first_search_using_index(&self, start: usize, target: usize) -> Option<VecDeque<usize>> {
return self.inner_search_using_index(start, target, false)
}
pub fn dijkstra(&self, start: usize, target: &T) -> Option<VecDeque<usize>> {
let mut q = BinaryHeap::new();
let mut costs: Vec<_> = (0..self.graph.len()).map(|_| std::i32::MAX).collect();
let mut prev: Vec<usize> = (0..self.graph.len()).map(|_| 0).collect();
let mut pathfound = false;
let mut target_index = start;
costs[start] = 0;
q.push(Vertex {cost: 0, node: start});
while !q.is_empty() {
let v = q.pop();
match v {
None => {},
Some(Vertex {cost, node}) => {
if &self.graph[node].content == target {
pathfound = true;
target_index = node
}
if cost > costs[node] { continue; } for vert in &self.graph[node].adjecent {
let next = Vertex { cost: cost+vert.cost, node: vert.node };
if next.cost < costs[vert.node] {
costs[vert.node] = next.cost;
prev[vert.node] = node;
q.push(next);
}
}
}
}
}
if pathfound { return Some(self.backtrack(prev, start, target_index)) }
return None
}
pub fn dijkstra_using_index(&self, start: usize, target: usize) -> Option<VecDeque<usize>> {
match self.index_to_node(target) {
None => { return None }, Some(node) => { return self.dijkstra(start, &node.content) }
}
}
pub fn cost_of_path(&self, path: &VecDeque<usize>) -> i32 {
let mut cost = 0;
for i in (0..path.len()-1) {
for vert in &self.graph[path[i]].adjecent {
if vert.node==path[i+1] { cost = cost + vert.cost; }
}
}
return cost
}
pub fn node_to_index(&self, node: Node<T>) -> Option<usize> {
for i in (0..self.graph.len()) {
if node.content==self.graph[i].content { return Some(i) }
}
return None
}
pub fn index_to_node(&self, index: usize) -> Option<&Node<T>> {
if index < self.graph.len() { return Some(&self.graph[index]); }
return None
}
fn inner_search(&self, start: usize, target: &T, bfs: bool) -> Option<VecDeque<usize>> {
let mut q = VecDeque::new();
let mut discovered: HashSet<usize> = HashSet::new();
let mut prev: Vec<usize> = (0..self.graph.len()).map(|_| 0).collect();
let mut pathfound = false;
let mut target_index = start;
q.push_back(start);
discovered.insert(start);
while !q.is_empty() {
let mut v: Option<usize>;
if bfs {
v = q.pop_front()
} else {
v = q.pop_back();
}
match v {
None => {}, Some(v) => { let node = &self.graph[v];
if !discovered.contains(&v) { discovered.insert(v); }
if &node.content == target {
pathfound = true;
target_index=v;
}
for vertex in &node.adjecent {
if !discovered.contains(&vertex.node) {
q.push_back(vertex.node);
prev[vertex.node]=v; }
}
}
}
}
if pathfound { return Some(self.backtrack(prev, start, target_index)) }
return None
}
fn inner_search_using_index(&self, start: usize, target: usize, bfs: bool) -> Option<VecDeque<usize>> {
match self.index_to_node(target) {
None => { return None }, Some(node) => { return self.inner_search(start, &node.content, bfs) }
}
}
fn backtrack(&self, prev: Vec<usize>, start: usize, target: usize) -> VecDeque<usize> {
let mut path: VecDeque<usize> = VecDeque::new();
let mut curr = target;
while curr != start {
path.push_front(curr);
curr = prev[curr];
}
path.push_front(start);
return path
}
}
#[test]
fn search_test() {
let testgraph = vec![Node{content: 0, adjecent: vec![Vertex{cost: 20, node: 1}, Vertex{cost: 50, node: 2}, Vertex{cost: 10, node: 3}]},
Node{content: 1, adjecent: Vec::new()},
Node{content: 2, adjecent: vec![Vertex{cost: 50, node: 6}]},
Node{content: 3, adjecent: vec![Vertex{cost: 20, node: 4}]},
Node{content: 4, adjecent: vec![Vertex{cost: 20, node: 3}, Vertex{cost: 50, node: 3}, Vertex{cost: 30, node: 6}]},
Node{content: 5, adjecent: Vec::new()},
Node{content: 6, adjecent: Vec::new()}];
let start: usize = 0;
let target: usize = 6;
let expected_path = vec![0, 3, 4, 6];
let expected_cost = 60;
let g = Graph::new(testgraph);
let res = g.search(start, target);
match res {
None => {
println!("Search returned None");
assert!(false);
}
Some(result) => {
println!("Search returned something: {:?}", result);
println!("The cost of path is: {}", g.cost_of_path(&result));
assert_eq!(result[result.len()-1], target);
assert_eq!(result[0], start);
for i in (0..expected_path.len()) { assert_eq!(result[i], expected_path[i]); }
assert_eq!(expected_cost, g.cost_of_path(&result));
}
}
}
#[test]
fn search_test_no_valid_path() {
let testgraph = vec![Node{content: 0, adjecent: vec![Vertex{cost: 20, node: 1}, Vertex{cost: 50, node: 2}, Vertex{cost: 10, node: 3}]},
Node{content: 1, adjecent: Vec::new()},
Node{content: 2, adjecent: vec![Vertex{cost: 50, node: 6}]},
Node{content: 3, adjecent: vec![Vertex{cost: 20, node: 4}]},
Node{content: 4, adjecent: vec![Vertex{cost: 20, node: 3}, Vertex{cost: 50, node: 3}, Vertex{cost: 30, node: 6}]},
Node{content: 5, adjecent: Vec::new()},
Node{content: 6, adjecent: Vec::new()}];
let start: usize = 0;
let target: usize = 5; let g = Graph::new(testgraph);
let res = g.search(start, target);
match res {
None => {
println!("Search returned None");
assert!(true);
}
Some(result) => {
println!("Search returned something: {:?}", result);
println!("The returned path cost: {}", g.cost_of_path(&result));
assert_eq!(result[result.len()-1], target);
assert_eq!(result[0], start);
assert!(false);
}
}
}
#[test]
fn search_using_index_test() {
let testgraph = vec![Node{content: 0, adjecent: vec![Vertex{cost: 20, node: 1}, Vertex{cost: 50, node: 2}, Vertex{cost: 10, node: 3}]},
Node{content: 1, adjecent: Vec::new()},
Node{content: 2, adjecent: vec![Vertex{cost: 50, node: 6}]},
Node{content: 3, adjecent: vec![Vertex{cost: 20, node: 4}]},
Node{content: 4, adjecent: vec![Vertex{cost: 20, node: 3}, Vertex{cost: 50, node: 3}, Vertex{cost: 30, node: 6}]},
Node{content: 5, adjecent: Vec::new()},
Node{content: 6, adjecent: Vec::new()}];
let start: usize = 0;
let target: usize = 6;
let expected_path = vec![0, 3, 4, 6];
let expected_cost = 60;
let g = Graph::new(testgraph);
let res = g.search_using_index(start, target);
match res {
None => {
println!("Search returned None");
assert!(false);
}
Some(result) => {
println!("Search returned something: {:?}", result);
println!("The cost of path is: {}", g.cost_of_path(&result));
assert_eq!(result[result.len()-1], target);
assert_eq!(result[0], start);
for i in (0..expected_path.len()) { assert_eq!(result[i], expected_path[i]); }
assert_eq!(expected_cost, g.cost_of_path(&result));
}
}
}
#[test]
fn search_using_index_test_no_valid_path() {
let testgraph = vec![Node{content: 0, adjecent: vec![Vertex{cost: 20, node: 1}, Vertex{cost: 50, node: 2}, Vertex{cost: 10, node: 3}]},
Node{content: 1, adjecent: Vec::new()},
Node{content: 2, adjecent: vec![Vertex{cost: 50, node: 6}]},
Node{content: 3, adjecent: vec![Vertex{cost: 20, node: 4}]},
Node{content: 4, adjecent: vec![Vertex{cost: 20, node: 3}, Vertex{cost: 50, node: 3}, Vertex{cost: 30, node: 6}]},
Node{content: 5, adjecent: Vec::new()},
Node{content: 6, adjecent: Vec::new()}];
let start: usize = 0;
let target: usize = 5; let g = Graph::new(testgraph);
let res = g.search_using_index(start, target);
match res {
None => {
println!("Search returned None");
assert!(true);
}
Some(result) => {
println!("Search returned something: {:?}", result);
println!("The returned path cost: {}", g.cost_of_path(&result));
assert_eq!(result[result.len()-1], target);
assert_eq!(result[0], start);
assert!(false);
}
}
}
#[test]
fn breadth_first_search_test() {
let testgraph = vec![Node{content: 0, adjecent: vec![Vertex{cost: 20, node: 1}, Vertex{cost: 50, node: 2}, Vertex{cost: 10, node: 3}]},
Node{content: 1, adjecent: Vec::new()},
Node{content: 2, adjecent: vec![Vertex{cost: 50, node: 6}]},
Node{content: 3, adjecent: vec![Vertex{cost: 20, node: 4}]},
Node{content: 4, adjecent: vec![Vertex{cost: 20, node: 3}, Vertex{cost: 50, node: 3}, Vertex{cost: 30, node: 6}]},
Node{content: 5, adjecent: Vec::new()},
Node{content: 6, adjecent: Vec::new()}];
let start: usize = 0;
let target: usize = 6;
let expected_path = vec![0, 2, 6];
let expected_cost = 100;
let g = Graph::new(testgraph);
let res = g.breadth_first_search(start, target);
match res {
None => {
println!("Breadth first search returned None");
assert!(false);
}
Some(result) => {
println!("Breadth first search returned something: {:?}", result);
println!("The cost of path is: {}", g.cost_of_path(&result));
assert_eq!(result[result.len()-1], target);
assert_eq!(result[0], start);
for i in (0..expected_path.len()) { assert_eq!(result[i], expected_path[i]); }
assert_eq!(expected_cost, g.cost_of_path(&result));
}
}
}
#[test]
fn breadth_first_search_test_no_valid_path() {
let testgraph = vec![Node{content: 0, adjecent: vec![Vertex{cost: 20, node: 1}, Vertex{cost: 50, node: 2}, Vertex{cost: 10, node: 3}]},
Node{content: 1, adjecent: Vec::new()},
Node{content: 2, adjecent: vec![Vertex{cost: 50, node: 6}]},
Node{content: 3, adjecent: vec![Vertex{cost: 20, node: 4}]},
Node{content: 4, adjecent: vec![Vertex{cost: 20, node: 3}, Vertex{cost: 50, node: 3}, Vertex{cost: 30, node: 6}]},
Node{content: 5, adjecent: Vec::new()},
Node{content: 6, adjecent: Vec::new()}];
let start: usize = 0;
let target: usize = 5; let g = Graph::new(testgraph);
let res = g.breadth_first_search(start, target);
match res {
None => {
println!("Breadth first search returned None");
assert!(true);
}
Some(result) => {
println!("Breadth first search returned something: {:?}", result);
assert_eq!(result[result.len()-1], target);
assert_eq!(result[0], start);
assert!(false);
}
}
}
#[test]
fn breadth_first_search_using_index_test() {
let testgraph = vec![Node{content: 0, adjecent: vec![Vertex{cost: 20, node: 1}, Vertex{cost: 50, node: 2}, Vertex{cost: 10, node: 3}]},
Node{content: 1, adjecent: Vec::new()},
Node{content: 2, adjecent: vec![Vertex{cost: 50, node: 6}]},
Node{content: 3, adjecent: vec![Vertex{cost: 20, node: 4}]},
Node{content: 4, adjecent: vec![Vertex{cost: 20, node: 3}, Vertex{cost: 50, node: 3}, Vertex{cost: 30, node: 6}]},
Node{content: 5, adjecent: Vec::new()},
Node{content: 6, adjecent: Vec::new()}];
let start: usize = 0;
let target: usize = 6;
let expected_path = vec![0, 2, 6];
let expected_cost = 100;
let g = Graph::new(testgraph);
let res = g.breadth_first_search_using_index(start, target);
match res {
None => {
println!("Breadth first search returned None");
assert!(false);
}
Some(result) => {
println!("Breadth first search returned something: {:?}", result);
println!("The cost of path is: {}", g.cost_of_path(&result));
assert_eq!(result[result.len()-1], target);
assert_eq!(result[0], start);
for i in (0..expected_path.len()) { assert_eq!(result[i], expected_path[i]); }
assert_eq!(expected_cost, g.cost_of_path(&result));
}
}
}
#[test]
fn breadth_first_search_using_index_test_no_valid_path() {
let testgraph = vec![Node{content: 0, adjecent: vec![Vertex{cost: 20, node: 1}, Vertex{cost: 50, node: 2}, Vertex{cost: 10, node: 3}]},
Node{content: 1, adjecent: Vec::new()},
Node{content: 2, adjecent: vec![Vertex{cost: 50, node: 6}]},
Node{content: 3, adjecent: vec![Vertex{cost: 20, node: 4}]},
Node{content: 4, adjecent: vec![Vertex{cost: 20, node: 3}, Vertex{cost: 50, node: 3}, Vertex{cost: 30, node: 6}]},
Node{content: 5, adjecent: Vec::new()},
Node{content: 6, adjecent: Vec::new()}];
let start: usize = 0;
let target: usize = 5; let g = Graph::new(testgraph);
let res = g.breadth_first_search_using_index(start, target);
match res {
None => {
println!("Breadth first search returned None");
assert!(true);
}
Some(result) => {
println!("Breadth first search returned something: {:?}", result);
assert_eq!(result[result.len()-1], target);
assert_eq!(result[0], start);
assert!(false);
}
}
}
#[test]
fn depth_first_search_test() {
let testgraph = vec![Node{content: 0, adjecent: vec![Vertex{cost: 20, node: 1}, Vertex{cost: 50, node: 2}, Vertex{cost: 10, node: 3}]},
Node{content: 1, adjecent: Vec::new()},
Node{content: 2, adjecent: vec![Vertex{cost: 50, node: 6}]},
Node{content: 3, adjecent: vec![Vertex{cost: 20, node: 4}]},
Node{content: 4, adjecent: vec![Vertex{cost: 20, node: 3}, Vertex{cost: 50, node: 3}, Vertex{cost: 30, node: 6}]},
Node{content: 5, adjecent: Vec::new()},
Node{content: 6, adjecent: Vec::new()}];
let start: usize = 0;
let target: usize = 6;
let expected_path = vec![0, 3, 4, 6];
let expected_cost = 60;
let g = Graph::new(testgraph);
let res = g.depth_first_search(start, target);
match res {
None => {
println!("Depth first search returned None");
assert!(false);
}
Some(result) => {
println!("Depth first search returned something: {:?}", result);
println!("The cost of path is: {}", g.cost_of_path(&result));
assert_eq!(result[result.len()-1], target);
assert_eq!(result[0], start);
for i in (0..expected_path.len()) { assert_eq!(result[i], expected_path[i]); }
assert_eq!(expected_cost, g.cost_of_path(&result));
}
}
}
#[test]
fn depth_first_search_test_no_valid_path() {
let testgraph = vec![Node{content: 0, adjecent: vec![Vertex{cost: 20, node: 1}, Vertex{cost: 50, node: 2}, Vertex{cost: 10, node: 3}]},
Node{content: 1, adjecent: Vec::new()},
Node{content: 2, adjecent: vec![Vertex{cost: 50, node: 6}]},
Node{content: 3, adjecent: vec![Vertex{cost: 20, node: 4}]},
Node{content: 4, adjecent: vec![Vertex{cost: 20, node: 3}, Vertex{cost: 50, node: 3}, Vertex{cost: 30, node: 6}]},
Node{content: 5, adjecent: Vec::new()},
Node{content: 6, adjecent: Vec::new()}];
let start: usize = 0;
let target: usize = 5; let g = Graph::new(testgraph);
let res = g.depth_first_search(start, target);
match res {
None => {
println!("Depth first search returned None");
assert!(true);
}
Some(result) => {
println!("Depth first search returned something: {:?}", result);
assert_eq!(result[result.len()-1], target);
assert_eq!(result[0], start);
assert!(false);
}
}
}
#[test]
fn depth_first_search_using_index_test() {
let testgraph = vec![Node{content: 0, adjecent: vec![Vertex{cost: 20, node: 1}, Vertex{cost: 50, node: 2}, Vertex{cost: 10, node: 3}]},
Node{content: 1, adjecent: Vec::new()},
Node{content: 2, adjecent: vec![Vertex{cost: 50, node: 6}]},
Node{content: 3, adjecent: vec![Vertex{cost: 20, node: 4}]},
Node{content: 4, adjecent: vec![Vertex{cost: 20, node: 3}, Vertex{cost: 50, node: 3}, Vertex{cost: 30, node: 6}]},
Node{content: 5, adjecent: Vec::new()},
Node{content: 6, adjecent: Vec::new()}];
let start: usize = 0;
let target: usize = 6;
let expected_path = vec![0, 3, 4, 6];
let expected_cost = 60;
let g = Graph::new(testgraph);
let res = g.depth_first_search_using_index(start, target);
match res {
None => {
println!("Depth first search returned None");
assert!(false);
}
Some(result) => {
println!("Depth first search returned something: {:?}", result);
println!("The cost of path is: {}", g.cost_of_path(&result));
assert_eq!(result[result.len()-1], target);
assert_eq!(result[0], start);
for i in (0..expected_path.len()) { assert_eq!(result[i], expected_path[i]); }
assert_eq!(expected_cost, g.cost_of_path(&result));
}
}
}
#[test]
fn depth_first_search_using_index_test_no_valid_path() {
let testgraph = vec![Node{content: 0, adjecent: vec![Vertex{cost: 20, node: 1}, Vertex{cost: 50, node: 2}, Vertex{cost: 10, node: 3}]},
Node{content: 1, adjecent: Vec::new()},
Node{content: 2, adjecent: vec![Vertex{cost: 50, node: 6}]},
Node{content: 3, adjecent: vec![Vertex{cost: 20, node: 4}]},
Node{content: 4, adjecent: vec![Vertex{cost: 20, node: 3}, Vertex{cost: 50, node: 3}, Vertex{cost: 30, node: 6}]},
Node{content: 5, adjecent: Vec::new()},
Node{content: 6, adjecent: Vec::new()}];
let start: usize = 0;
let target: usize = 5; let g = Graph::new(testgraph);
let res = g.depth_first_search_using_index(start, target);
match res {
None => {
println!("Depth first search returned None");
assert!(true);
}
Some(result) => {
println!("Depth first search returned something: {:?}", result);
assert_eq!(result[result.len()-1], target);
assert_eq!(result[0], start);
assert!(false);
}
}
}
#[test]
fn dijkstra_test_no_valid_path() {
let testgraph = vec![Node{content: 0, adjecent: vec![Vertex{cost: 20, node: 1}, Vertex{cost: 50, node: 2}, Vertex{cost: 10, node: 3}]},
Node{content: 1, adjecent: Vec::new()},
Node{content: 2, adjecent: vec![Vertex{cost: 50, node: 6}]},
Node{content: 3, adjecent: vec![Vertex{cost: 20, node: 4}]},
Node{content: 4, adjecent: vec![Vertex{cost: 20, node: 3}, Vertex{cost: 50, node: 3}, Vertex{cost: 30, node: 6}]},
Node{content: 5, adjecent: Vec::new()},
Node{content: 6, adjecent: Vec::new()}];
let start: usize = 0;
let target: usize = 5; let g = Graph::new(testgraph);
let res = g.dijkstra(start, &target);
match res {
None => {
println!("Dijkstra returned None");
assert!(true);
}
Some(result) => {
println!("Dijkstra returned something: {:?}", result);
assert_eq!(result[result.len()-1], target);
assert_eq!(result[0], start);
assert!(false);
}
}
}
#[test]
fn dijkstra_using_index_test() {
let testgraph = vec![Node{content: 0, adjecent: vec![Vertex{cost: 20, node: 1}, Vertex{cost: 50, node: 2}, Vertex{cost: 10, node: 3}]},
Node{content: 1, adjecent: Vec::new()},
Node{content: 2, adjecent: vec![Vertex{cost: 50, node: 6}]},
Node{content: 3, adjecent: vec![Vertex{cost: 20, node: 4}]},
Node{content: 4, adjecent: vec![Vertex{cost: 20, node: 3}, Vertex{cost: 50, node: 3}, Vertex{cost: 30, node: 6}]},
Node{content: 5, adjecent: Vec::new()},
Node{content: 6, adjecent: Vec::new()}];
let start: usize = 0;
let target: usize = 6;
let expected_path = vec![0, 3, 4, 6];
let expected_cost = 60;
let g = Graph::new(testgraph);
let res = g.dijkstra_using_index(start, target);
match res {
None => {
println!("Dijkstra search returned None");
assert!(false);
}
Some(result) => {
println!("Dijkstra returned something: {:?}", result);
println!("The cost of path is: {}", g.cost_of_path(&result));
assert_eq!(result[result.len()-1], target);
assert_eq!(result[0], start);
for i in (0..expected_path.len()) { assert_eq!(result[i], expected_path[i]); }
assert_eq!(expected_cost, g.cost_of_path(&result));
}
}
}
#[test]
fn dijkstra_using_index_test_no_valid_path() {
let testgraph = vec![Node{content: 0, adjecent: vec![Vertex{cost: 20, node: 1}, Vertex{cost: 50, node: 2}, Vertex{cost: 10, node: 3}]},
Node{content: 1, adjecent: Vec::new()},
Node{content: 2, adjecent: vec![Vertex{cost: 50, node: 6}]},
Node{content: 3, adjecent: vec![Vertex{cost: 20, node: 4}]},
Node{content: 4, adjecent: vec![Vertex{cost: 20, node: 3}, Vertex{cost: 50, node: 3}, Vertex{cost: 30, node: 6}]},
Node{content: 5, adjecent: Vec::new()},
Node{content: 6, adjecent: Vec::new()}];
let start: usize = 0;
let target: usize = 5; let g = Graph::new(testgraph);
let res = g.dijkstra_using_index(start, target);
match res {
None => {
println!("Dijkstra returned None");
assert!(true);
}
Some(result) => {
println!("Dijkstra returned something: {:?}", result);
assert_eq!(result[result.len()-1], target);
assert_eq!(result[0], start);
assert!(false);
}
}
}