Crate dynalgo

Source
Expand description

ยงdynalgo

dynalgo is a tiny RUST library designed to produce animated SVG images that can illustrate graph algorithms in action.

The library focuces on providing a convenient tiny API for making animations in SVG SMIL format when developping algorithms working with graph structures.

The crate offers a basic graph structure representation. Interesting point is that each graph structure modification results in an animation rendered in SVG SMIL format into a HTML page. Several graphs animations can be rendered together in the same HTML page (side to side).

Dynalgo automatically layout nodes according to imaginary springs forces applying to them. Custom animations can be made by playing with the nodes and links graphical representations.

The Algo module provides animated algorithms applying to graph.

ยงExample: traversing a maze

use dynalgo::graph::Graph;

let config = "๐Ÿ˜€ 0 0
	๐Ÿ˜ 45 0
	๐Ÿ˜‚ 90 0
	๐Ÿ˜ƒ 135 0
	๐Ÿ˜„ 180 0
	๐Ÿ˜… 225 0
	๐Ÿ˜† 270 0
	๐Ÿ˜‡ 315 0
	๐Ÿ˜ˆ 0 45
	๐Ÿ˜‰ 45 45
	๐Ÿ˜Š 90 45
	๐Ÿ˜‹ 135 45
	๐Ÿ˜Œ 180 45
	๐Ÿ˜ 225 45
	๐Ÿ˜Ž 270 45
	๐Ÿ˜ 315 45
	๐Ÿ˜ 0 90
	๐Ÿ˜‘ 45 90
	๐Ÿ˜’ 90 90
	๐Ÿ˜“ 135 90
	๐Ÿ˜” 180 90
	๐Ÿ˜• 225 90
	๐Ÿ˜– 270 90
	๐Ÿ˜— 315 90
	๐Ÿ˜˜ 0 135
	๐Ÿ˜™ 45 135
	๐Ÿ˜š 90 135
	๐Ÿ˜› 135 135
	๐Ÿ˜œ 180 135
	๐Ÿ˜ 225 135
	๐Ÿ˜ž 270 135
	๐Ÿ˜Ÿ 315 135
	๐Ÿ˜  0 180
	๐Ÿ˜ก 45 180
	๐Ÿ˜ข 90 180
	๐Ÿ˜ฃ 135 180
	๐Ÿ˜ค 180 180
	๐Ÿ˜ฅ 225 180
	๐Ÿ˜ฆ 270 180
	๐Ÿ˜ง 315 180
	๐Ÿ˜จ 0 225
	๐Ÿ˜ฉ 45 225
	๐Ÿ˜ช 90 225
	๐Ÿ˜ซ 135 225
	๐Ÿ˜ฌ 180 225
	๐Ÿ˜ญ 225 225
	๐Ÿ˜ฎ 270 225
	๐Ÿ˜ฏ 315 225
	๐Ÿ˜ฐ 0 270
	๐Ÿ˜ฑ 45 270
	๐Ÿ˜ฒ 90 270
	๐Ÿ˜ณ 135 270
	๐Ÿ˜ด 180 270
	๐Ÿ˜ต 225 270
	๐Ÿ˜ถ 270 270
	๐Ÿ˜ท 315 270
	๐Ÿ˜ธ 0 315
	๐Ÿ˜น 45 315
	๐Ÿ˜บ 90 315
	๐Ÿ˜ป 135 315
	๐Ÿ˜ผ 180 315
	๐Ÿ˜ฝ 225 315
	๐Ÿ˜พ 270 315
	๐Ÿ˜ฟ 315 315
	๐Ÿ˜€ - ๐Ÿ˜ 0
	๐Ÿ˜ - ๐Ÿ˜‰ 0
	๐Ÿ˜‚ - ๐Ÿ˜ƒ 0
	๐Ÿ˜‚ - ๐Ÿ˜Š 0
	๐Ÿ˜ƒ - ๐Ÿ˜„ 0
	๐Ÿ˜„ - ๐Ÿ˜… 0
	๐Ÿ˜… - ๐Ÿ˜ 0
	๐Ÿ˜† - ๐Ÿ˜Ž 0
	๐Ÿ˜‡ - ๐Ÿ˜ 0
	๐Ÿ˜ˆ - ๐Ÿ˜‰ 0
	๐Ÿ˜ˆ - ๐Ÿ˜ 0
	๐Ÿ˜Š - ๐Ÿ˜’ 0
	๐Ÿ˜‹ - ๐Ÿ˜“ 0
	๐Ÿ˜Œ - ๐Ÿ˜” 0
	๐Ÿ˜Ž - ๐Ÿ˜ 0
	๐Ÿ˜Ž - ๐Ÿ˜– 0
	๐Ÿ˜ - ๐Ÿ˜‘ 0
	๐Ÿ˜ - ๐Ÿ˜˜ 0
	๐Ÿ˜‘ - ๐Ÿ˜’ 0
	๐Ÿ˜’ - ๐Ÿ˜“ 0
	๐Ÿ˜“ - ๐Ÿ˜› 0
	๐Ÿ˜” - ๐Ÿ˜• 0
	๐Ÿ˜• - ๐Ÿ˜– 0
	๐Ÿ˜• - ๐Ÿ˜ 0
	๐Ÿ˜— - ๐Ÿ˜Ÿ 0
	๐Ÿ˜˜ - ๐Ÿ˜  0
	๐Ÿ˜™ - ๐Ÿ˜š 0
	๐Ÿ˜š - ๐Ÿ˜ข 0
	๐Ÿ˜œ - ๐Ÿ˜ 0
	๐Ÿ˜ - ๐Ÿ˜ฅ 0
	๐Ÿ˜ž - ๐Ÿ˜Ÿ 0
	๐Ÿ˜ž - ๐Ÿ˜ฆ 0
	๐Ÿ˜  - ๐Ÿ˜ก 0
	๐Ÿ˜ก - ๐Ÿ˜ข 0
	๐Ÿ˜ก - ๐Ÿ˜ฉ 0
	๐Ÿ˜ข - ๐Ÿ˜ช 0
	๐Ÿ˜ฃ - ๐Ÿ˜ค 0
	๐Ÿ˜ค - ๐Ÿ˜ฌ 0
	๐Ÿ˜ฅ - ๐Ÿ˜ฆ 0
	๐Ÿ˜ฅ - ๐Ÿ˜ญ 0
	๐Ÿ˜ฆ - ๐Ÿ˜ง 0
	๐Ÿ˜ฆ - ๐Ÿ˜ฎ 0
	๐Ÿ˜ง - ๐Ÿ˜ฏ 0
	๐Ÿ˜จ - ๐Ÿ˜ฉ 0
	๐Ÿ˜ฉ - ๐Ÿ˜ฑ 0
	๐Ÿ˜ช - ๐Ÿ˜ซ 0
	๐Ÿ˜ช - ๐Ÿ˜ฒ 0
	๐Ÿ˜ซ - ๐Ÿ˜ฌ 0
	๐Ÿ˜ฌ - ๐Ÿ˜ด 0
	๐Ÿ˜ฎ - ๐Ÿ˜ถ 0
	๐Ÿ˜ฏ - ๐Ÿ˜ท 0
	๐Ÿ˜ฐ - ๐Ÿ˜ฑ 0
	๐Ÿ˜ฑ - ๐Ÿ˜น 0
	๐Ÿ˜ณ - ๐Ÿ˜ป 0
	๐Ÿ˜ด - ๐Ÿ˜ผ 0
	๐Ÿ˜ต - ๐Ÿ˜ถ 0
	๐Ÿ˜ถ - ๐Ÿ˜พ 0
	๐Ÿ˜ท - ๐Ÿ˜ฟ 0
	๐Ÿ˜ธ - ๐Ÿ˜น 0
	๐Ÿ˜น - ๐Ÿ˜บ 0
	๐Ÿ˜ป - ๐Ÿ˜ผ 0
	๐Ÿ˜ผ - ๐Ÿ˜ฝ 0
	๐Ÿ˜ฝ - ๐Ÿ˜พ 0";

let node_start = '๐Ÿ˜€';
let node_searched = '๐Ÿ˜ฟ';

let mut freezed_maze = Graph::new();
let mut unfreezed_maze = Graph::new();

for graph in [&mut freezed_maze, &mut unfreezed_maze].iter_mut() {
    graph.from_str(config);
    graph.fill_node(node_start, (0, 0, 196));
    graph.fill_node(node_searched, (0, 0, 196));
}

deep_first_search(
    &mut freezed_maze,
    node_start,
    node_searched,
    &mut Vec::new(),
);

unfreezed_maze.pause();
for node in unfreezed_maze.nodes() {
    unfreezed_maze.unfreeze_node(node);
}
unfreezed_maze.resume();

deep_first_search(
    &mut unfreezed_maze,
    node_start,
    node_searched,
    &mut Vec::new(),
);

Graph::to_html( vec![("Dynalgo maze example", vec![&freezed_maze, &unfreezed_maze])] ).unwrap();


fn deep_first_search(
    graph: &mut Graph,
    node_from: char,
    node_searched: char,
    visited: &mut Vec<char>,
) -> bool {
    visited.push(node_from);
    graph.color_node(node_from, (0, 255, 0));

   if node_from == node_searched {
        return true;
    }

    let adja = &graph.adjacency_list();
    let mut found = false;
    for (node_to, _link) in adja.get(&node_from).unwrap() {
        if visited.contains(node_to) {
            continue;
        }
        graph.color_link(node_from, *node_to, (0, 255, 0));

        found = deep_first_search(graph, *node_to, node_searched, visited);
        if found {
            break;
        }
    }

    if !found {
        graph.color_node(node_from, (255, 0, 0));
    }
    found
}

ยงExample: viewing algorithms in action

use dynalgo::graph::Graph;
use dynalgo::algo::coloration::Coloration;
use dynalgo::algo::connectivity::Connectivity;
use dynalgo::algo::eulerian::Eulerian;
use dynalgo::algo::tree::Tree;

let mut g = Graph::new();
g.from_str(
    "A 0 0, B 100 -100, C 200 -100, D 300 -100, E 300 100, F 200 150,
    G 200 50, H 100 100, I 100 0, A > I, I > B, B > C, C > D, D > E, E < F, E > G, F > G, F > H,
    G < H, H < I",
);
let (_c_g, _components) = Connectivity::components(&g);
assert!(_components.len() == 1);

let mut g = Graph::new();
g.from_str(
    "F 0 0, E 100 0, A 250 50, H 300 80, C 0 100, J 100 100, K 0 150, B 200 150,
    D 100 250, I 200 250, G 300 250, F > J, C > F, J > C, C > E, E > J, C - K, K > D, J > B,
    E > A, A - H,
    H > G, G > I, I > D, I > B, B > D, B > G",
);
let (scc_g, sc_components) = Connectivity::strongly_connected_components(&g);
assert!(sc_components.len() == 4);

let mut g = Graph::new();
g.from_str(
    "A 0 0, B 200 0, C 0 200, D 160 160, E 250 200, F 100 300,
    G 100 100, A - B 2, A - G 5,
    B - G 15, B - D 10, B - E 3, C - G 5, C - D 7, C - E 10, C - F 12,
    D - G 3, D - E 1, E - F 11",
);
let mst_tree = Tree::minimal_spanning_tree(&g);

let mut g = Graph::new();
g.from_str(
    "A 0 0, B 100 -100, C 200 -100, D 300 -100, E 300 100, F 200 150,
    G 200 50, H 100 100, I 100 0, J 100 -200, A > I, I > B, B > C, C > D, D > E, E < F,
    E > G, F > G, F > H,
    G < H, H < I, J - B",
);
let bfs_tree = Tree::bfs_tree(&g, 'A');

let mut g = Graph::new();
g.from_str(
    "A 0 0, B 200 0, C 0 200, D 160 160, E 250 200, F 100 300,
    G 100 100, A - B, A - G, B - G, B - D, B - E, C - G, C - E, C - F,
    D - G, D - E, E - F",
);
let (e_g, _cycle) = Eulerian::hierholzer(&g);

let mut g = Graph::new();
g.from_str(
    "A 0 0, B -80 200, C 100 100, D -100 100, E 80 200
    F 0 60, G -40 160, H 40 100, I 40 160, J -40 100,
    L 0 -60, M 160 100, N 120 240, O -120 240, P -160 100,
    Q -160 40, R -190 20, S -130 20,
    T 160 180, U 160 20, V 160 -60, W 240 180, X 240 20, Y 240 -60, Z 240 100
    A - F, A - D, A - C, C - H, C - E, E - I, E - B, B - G, B - D, D - J,
    J - H, J - I, F - I, F - G, H - G,
    A  - L, C - M, E - N, B - O, D - P,
    P - Q, Q - R, Q - S,
    V - X, V - Z, V - W, U - Y, U - Z, U - W, M - X, M - Y, M - W, T - X, T - Y, T - Z",
);
let (p_g, partitions) = Coloration::quick_partition(&g);
assert!(partitions.len() == 3);

Graph::to_html(vec![
    ("Strongly connected components (Kosaraju)", vec![&scc_g]),
    ("Minimal spanning tree (Prim)", vec![&mst_tree]),
    ("BFS tree", vec![&bfs_tree]),
    ("Eulerian path (Hierholzer)", vec![&e_g]),
    ("Color - Quick partition", vec![&p_g]),
])
.unwrap();

Modulesยง

algo
Algorithms using the Graph structure
graph
Basic graph structure representation with animation properties.