Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Graphs

Each block is the whole file — copy it into x.manic and run manic x.manic (live) or --record out (video).

graph

Labelled nodes + edges, drawn on; reflowing links.

// Graph — the algo kit's `graph` builtin (Manim's Graph/DiGraph). Nodes are
// labelled circles; `a-b` is an undirected edge, `a>b` a directed arrow. Tag
// broadcast (`draw(g.edges)`, `flash(g.nodes, …)`) animates whole groups.
//
//   manic examples/graph.manic
//   manic examples/graph.manic --record out --fps 60

title("Graph");
canvas(1280, 720);

text(head, (640, 118), "a directed graph, traversed");
display(head);  color(head, cyan);  size(head, 34);  hidden(head);
text(cap, (640, 664), "");  color(cap, dim);  size(cap, 22);

// six vertices in a circle; directed edges (a>b)
graph(g, "a b c d e f",
         "a>b b>c c>d d>e e>f f>a a>d b>e",
         circular, (640, 384), 210);

// nodes fade in (hidden→show); edges trace on (untraced→draw)
hidden(g.nodes);
untraced(g.edges);

show(head, 0.5);
say(cap, "drop in the vertices");
show(g.nodes, 0.4);            // broadcasts over every node
say(cap, "connect the directed edges");
draw(g.edges, 0.6);           // broadcasts over every edge

section("Traversal");
say(cap, "walk a > b > c > d");
seq {
  flash(g.a, magenta);
  flash(g.b, magenta);
  flash(g.c, magenta);
  flash(g.d, magenta);
}
say(cap, "highlight the visited path");
par {
  recolor(g.a, lime, 0.4);
  recolor(g.b, lime, 0.4);
  recolor(g.c, lime, 0.4);
  recolor(g.d, lime, 0.4);
}
wait(1.2);

graph_moving

Drag a vertex and its incident edges follow.

// Moving Graph — vertices move and the edges reflow to follow them
// (Manim's MovingVertices / MovingDiGraph). Also exercises layout reveal,
// per-node moves, tag-broadcast recolour, and a highlight sweep.
//
//   manic examples/graph_moving.manic
//   manic examples/graph_moving.manic --record out --fps 60
//
// Node ids are g.1 … g.4 ; edge ids g.1-2 etc ; tags g.nodes / g.edges.

title("Moving Graph");
canvas(1280, 720);

text(head, (640, 118), "edges follow their vertices");
display(head);  color(head, cyan);  size(head, 34);  hidden(head);
text(cap, (640, 664), "");  color(cap, dim);  size(cap, 22);

// four vertices, five undirected edges, circular to start
graph(g, "1 2 3 4", "1-2 2-3 3-4 1-3 1-4", circular, (640, 384), 150);
hidden(g.nodes);
untraced(g.edges);

// --- reveal ---
show(head, 0.5);
say(cap, "a small graph");
show(g.nodes, 0.4);
draw(g.edges, 0.6);
wait(0.5);

// --- case 1: fling the vertices to the corners; edges reflow live ---
section("Moving vertices");
say(cap, "move each vertex — the edges stretch to follow");
par {
  move(g.1, (360, 250), 1.2, overshoot);
  move(g.2, (920, 250), 1.2, overshoot);
  move(g.3, (920, 520), 1.2, overshoot);
  move(g.4, (360, 520), 1.2, overshoot);
}
wait(0.8);

// --- case 2: orbit two vertices past each other ---
say(cap, "swap two vertices");
par {
  move(g.2, (360, 520), 1.0, smooth);
  move(g.4, (920, 250), 1.0, smooth);
}
wait(0.8);

// --- case 3: pull one vertex around; incident edges track it ---
say(cap, "drag one vertex around");
seq {
  move(g.1, (640, 150), 0.7, smooth);
  move(g.1, (1080, 384), 0.7, smooth);
  move(g.1, (640, 620), 0.7, smooth);
  move(g.1, (360, 250), 0.7, smooth);
}
wait(0.6);

// --- case 4: recolour the whole graph via tag broadcast, then highlight ---
section("Styling");
say(cap, "recolour every edge, then highlight a node");
recolor(g.edges, cyan, 0.5);
flash(g.1, magenta);
par {
  recolor(g.1, lime, 0.4);
  pulse(g.1);
}
wait(1.5);

bfs_dfs

The same graph, queue vs stack, with live frontier readouts.

// Graph Traversal — BFS vs DFS, the classic side-by-side. They're the SAME
// algorithm; only the frontier differs: BFS uses a QUEUE (explore level by
// level), DFS uses a STACK (dive deep first). `bfs(g, start)` / `dfs(g, start)`
// read the graph's adjacency, run the traversal, and animate the textbook
// states — discovered (cyan) -> current (magenta) -> done (lime) — with tree
// edges lighting up and live `queue:` / `stack:` + `visited:` readouts.
//
//   manic examples/bfs_dfs.manic

title("Graph Traversal");
canvas("16:9");

text(head, (cx, 56), "BFS vs DFS: same graph, queue vs stack");
display(head);  color(head, cyan);  size(head, 26);  hidden(head);
text(cap, (cx, 690), "");  color(cap, dim);  size(cap, 24);

graph(gr, "a b c d e f g", "a-b a-c b-d b-e c-f c-g", circular, (cx, 320), 200, 30);

show(head, 0.5);
wait(0.4);

section("BFS");
say(cap, "BFS explores level by level, using a QUEUE");
bfs(gr, a);
say(cap, "queue order: a, then b c, then d e f g");
wait(0.8);

section("DFS");
par { recolor(gr.nodes, panel, 0.4);  recolor(gr.edges, dim, 0.4); }
say(gr.frontier, "stack:");
say(gr.visited, "visited:");
say(cap, "DFS dives deep down one branch, using a STACK");
dfs(gr, a);
say(cap, "the stack drove it depth-first before backtracking");
wait(1.2);

dijkstra

Weighted edges, settling distances, a shortest-path tree.

// Dijkstra — single-source shortest paths on a WEIGHTED graph. Give edges a
// weight with `a-b:w` (drawn as a midpoint label). `dijkstra(g, start)` reads the
// weights, then runs the classic loop: repeatedly settle the nearest unsettled
// node (magenta -> lime), relaxing its edges and lowering neighbours' distances.
// Each node shows its best-known distance (inf -> the final shortest distance),
// and the shortest-path-tree edges stay lit at the end.
//
//   manic examples/dijkstra.manic

title("Dijkstra");
canvas("16:9");

text(head, (cx, 58), "shortest paths: settle the nearest node, relax its edges");
display(head);  color(head, cyan);  size(head, 25);  hidden(head);
text(cap, (cx, 690), "");  color(cap, dim);  size(cap, 24);

graph(g, "a b c d e f",
      "a-b:2 a-c:5 b-c:1 b-d:4 c-e:3 d-e:1 d-f:2 e-f:6",
      circular, (cx, 350), 210, 30);

show(head, 0.5);
say(cap, "each node shows its best distance: start 0, the rest inf");
wait(0.7);

section("Relax");
say(cap, "settle the nearest node, then relax every edge leaving it");
dijkstra(g, a);
say(cap, "settled distances are final; the lime edges form the shortest-path tree");
wait(1.4);