### Example for peek/1 Source: https://hexdocs.pm/multigraph/Multigraph.PriorityQueue.html Shows creating a queue, pushing :foo with priority 1, peeking to get {:value, :foo}, popping to get the value, and confirming the popped value is :foo. ```elixir iex> pq = Multigraph.PriorityQueue.new |> Multigraph.PriorityQueue.push(:foo, 1) ...> {:value, :foo} = Multigraph.PriorityQueue.peek(pq) ...> {{:value, val}, _} = Multigraph.PriorityQueue.pop(pq) ...> val :foo ``` -------------------------------- ### a_star/4 examples Source: https://hexdocs.pm/multigraph/Multigraph.html Examples showing successful path finding and a case where no path exists. ```elixir iex> g = Multigraph.new |> Multigraph.add_edges([{:a, :b}, {:b, :c}, {:c, :d}, {:b, :d}]) ...> Multigraph.a_star(g, :a, :d, fn _ -> 0 end) [:a, :b, :d] iex> g = Multigraph.new |> Multigraph.add_vertices([:a, :b, :c, :d]) ...> g = Multigraph.add_edges(g, [{:a, :c}, {:b, :c}, {:b, :d}]) ...> Multigraph.a_star(g, :a, :d, fn _ -> 0 end) nil ``` -------------------------------- ### new/1 examples with options Source: https://hexdocs.pm/multigraph/Multigraph.html Shows examples of creating graphs with the new/1 function and its options. The examples demonstrate default directed graph, undirected type, custom vertex_identifier, and multigraph with partition_by. The output shows the resulting edges for each configuration. ```elixir iex> Multigraph.new() #Multigraph iex> g = Multigraph.new(type: :undirected) |> Multigraph.add_edges([{:a, :b}, {:b, :a}]) ...> Multigraph.edges(g) [%Multigraph.Edge{v1: :a, v2: :b}] iex> g = Multigraph.new(type: :directed) |> Multigraph.add_edges([{:a, :b}, {:b, :a}]) ...> Multigraph.edges(g) [%Multigraph.Edge{v1: :a, v2: :b}, %Multigraph.Edge{v1: :b, v2: :a}] iex> g = Multigraph.new(vertex_identifier: fn v -> :erlang.phash2(v) end) |> Multigraph.add_edges([{:a, :b}, {:b, :a}]) ...> Multigraph.edges(g) [%Multigraph.Edge{v1: :a, v2: :b}, %Multigraph.Edge{v1: :b, v2: :a}] iex> g = Multigraph.new(multigraph: true, partition_by: fn edge -> [edge.weight] end) |> Multigraph.add_edges([{:a, :b, weight: 1}, {:b, :a, weight: 2}]) ...> Multigraph.edges(g, by: 1) [%Multigraph.Edge{v1: :a, v2: :b, weight: 1}] ``` -------------------------------- ### edges/2 examples with vertex and options Source: https://hexdocs.pm/multigraph/Multigraph.html Examples of using edges/2 to filter edges by vertex, by partition, or by a custom where function. The examples show results for existing and non-existing vertices, and for multigraph options. ```elixir iex> g = Multigraph.new |> Multigraph.add_edges([{:a, :b}, {:b, :c}]) ...> Multigraph.edges(g, :b) |> Enum.sort_by(& {&1.v1, &1.v2, &1.label}) [%Multigraph.Edge{v1: :a, v2: :b}, %Multigraph.Edge{v1: :b, v2: :c}] iex> g = Multigraph.new |> Multigraph.add_edges([{:a, :b}, {:b, :c}]) ...> Multigraph.edges(g, :d) [] iex> g = Multigraph.new(multigraph: true) |> Multigraph.add_edges([{:a, :b}, {:b, :c}]) ...> g = Multigraph.add_edge(g, :a, :b, label: :contains) ...> Multigraph.edges(g, :a, by: [:contains]) [%Multigraph.Edge{v1: :a, v2: :b, label: :contains}] iex> g = Multigraph.new(multigraph: true) |> Multigraph.add_edges([{:a, :b}, {:b, :c}]) ...> g = Multigraph.add_edge(g, :a, :b, label: :contains, weight: 2) ...> Multigraph.edges(g, :a, where: fn edge -> edge.weight == 2 end) [%Multigraph.Edge{v1: :a, v2: :b, label: :contains, weight: 2}] ``` -------------------------------- ### add_edge/2 example with Edge struct Source: https://hexdocs.pm/multigraph/Multigraph.html IEx example creating a graph and adding an edge using Multigraph.Edge.new/2. ```elixir iex> g = Multigraph.new |> Multigraph.add_edge(Multigraph.Edge.new(:a, :b)) ...> [:a, :b] = Multigraph.vertices(g) ...> Multigraph.edges(g) [%Multigraph.Edge{v1: :a, v2: :b}] ``` -------------------------------- ### a_star/5 example with partition filtering Source: https://hexdocs.pm/multigraph/Multigraph.html IEx example showing A* search restricted to edges with label :fast using the :by option. ```elixir iex> g = Multigraph.new(multigraph: true) |> Multigraph.add_edges([ ...> {:a, :b, label: :fast, weight: 1}, ...> {:a, :c, label: :slow, weight: 10}, ...> {:b, :d, label: :fast, weight: 1}, ...> {:c, :d, label: :slow, weight: 1} ...> ]) ...> Multigraph.a_star(g, :a, :d, fn _ -> 0 end, by: :fast) [:a, :b, :d] ``` -------------------------------- ### add_edge/4 examples with default and custom options Source: https://hexdocs.pm/multigraph/Multigraph.html Two IEx examples showing edge creation with default options and with label and weight options. ```elixir iex> g = Multigraph.new |> Multigraph.add_edge(:a, :b) ...> [:a, :b] = Multigraph.vertices(g) ...> Multigraph.edges(g) [%Multigraph.Edge{v1: :a, v2: :b, label: nil, weight: 1}] ``` ```elixir iex> g = Multigraph.new |> Multigraph.add_edge(:a, :b, label: :foo, weight: 2) ...> [:a, :b] = Multigraph.vertices(g) ...> Multigraph.edges(g) [%Multigraph.Edge{v1: :a, v2: :b, label: :foo, weight: 2}] ``` -------------------------------- ### edges/3 default example Source: https://hexdocs.pm/multigraph/Multigraph.html Example of edges/3 with default options, returning all edges between :a and :b sorted by label. ```elixir iex> g = Multigraph.new |> Multigraph.add_edge(:a, :b, label: :uses) ...> g = Multigraph.add_edge(g, :a, :b, label: :contains) ...> Multigraph.edges(g, :a, :b) |> Enum.sort_by(& &1.label) [%Multigraph.Edge{v1: :a, v2: :b, label: :contains}, %Multigraph.Edge{v1: :a, v2: :b, label: :uses}] ``` -------------------------------- ### postorder/1 example with graph diagram Source: https://hexdocs.pm/multigraph/Multigraph.html Example of postorder/1. The first block shows the graph structure, the second builds it and returns the postorder traversal result. ```text :a :b / :c :d / :e ``` ```elixir iex> g = Multigraph.new |> Multigraph.add_vertices([:a, :b, :c, :d, :e]) ...> g = Multigraph.add_edges(g, [{:a, :b}, {:b, :c}, {:b, :d}, {:c, :e}]) ...> Multigraph.postorder(g) [:e, :c, :d, :b, :a] ``` -------------------------------- ### preorder/1 example Source: https://hexdocs.pm/multigraph/Multigraph.html Example of using Multigraph.preorder/1 on a graph with vertices :a, :b, :c, :d, :e and edges :a-:b, :b-:c, :b-:d, :c-:e. The result is [:a, :b, :c, :e, :d]. ```elixir iex> g = Multigraph.new |> Multigraph.add_vertices([:a, :b, :c, :d, :e]) ...> g = Multigraph.add_edges(g, [{:a, :b}, {:b, :c}, {:b, :d}, {:c, :e}]) ...> Multigraph.preorder(g) [:a, :b, :c, :e, :d] ``` -------------------------------- ### info/1 example Source: https://hexdocs.pm/multigraph/Multigraph.html Example for info/1. Creates a directed graph with four vertices and two edges, then checks that info/1 returns a map with type :directed, num_vertices 4, and num_edges 2. The match returns true. ```elixir iex> g = Multigraph.new |> Multigraph.add_vertices([:a, :b, :c, :d]) ...> g = g |> Multigraph.add_edges([{:a, :b}, {:b, :c}]) ...> match?(%{type: :directed, num_vertices: 4, num_edges: 2}, Multigraph.info(g)) true ``` -------------------------------- ### num_vertices/1 spec and example Source: https://hexdocs.pm/multigraph/Multigraph.html Specifies the num_vertices/1 function and shows an example that adds three vertices and returns the vertex count. ```elixir @spec num_vertices(t()) :: non_neg_integer() ``` ```elixir iex> g = Multigraph.add_vertices(Multigraph.new, [:a, :b, :c]) ...> Multigraph.num_vertices(g) 3 ``` -------------------------------- ### components/1 example Source: https://hexdocs.pm/multigraph/Multigraph.html Example of components/1. The graph has vertices :a, :b, :c, and :d, and the function returns a single connected component containing all vertices. ```elixir iex> g = Multigraph.new |> Multigraph.add_vertices([:a, :b, :c, :d]) ...> g = Multigraph.add_edges(g, [{:a, :b}, {:a, :c}, {:b, :c}, {:c, :d}, {:c, :a}]) ...> Multigraph.components(g) [[:d, :b, :c, :a]] ``` -------------------------------- ### neighbors/2 spec and examples Source: https://hexdocs.pm/multigraph/Multigraph.html Specifies the neighbors/2 function signature and shows examples. It returns all neighboring vertices of the given vertex. The examples show returning neighbors for an existing vertex and an empty list for a non-existent vertex. ```elixir @spec neighbors(t(), vertex()) :: [vertex()] ``` ```elixir iex> g = Multigraph.new |> Multigraph.add_edges([{:a, :b}, {:b, :a}, {:b, :c}, {:c, :a}]) ...> Multigraph.neighbors(g, :a) [:b, :c] iex> g = Multigraph.new |> Multigraph.add_edges([{:a, :b}, {:b, :a}, {:b, :c}, {:c, :a}]) ...> Multigraph.neighbors(g, :d) [] ``` -------------------------------- ### loop_vertices/1 spec and example Source: https://hexdocs.pm/multigraph/Multigraph.html Specifies the loop_vertices/1 function signature and shows an example. It returns a list of vertices that are part of a loop (a cycle of length 1). The example creates a graph with a self-loop on :a and returns [:a]. ```elixir @spec loop_vertices(t()) :: [vertex()] ``` ```elixir iex> g = Multigraph.new |> Multigraph.add_vertices([:a, :b, :c]) |> Multigraph.add_edge(:a, :a) ...> Multigraph.loop_vertices(g) [:a] ``` -------------------------------- ### edges/1 example Source: https://hexdocs.pm/multigraph/Multigraph.html Example of using edges/1 to list all edges in a graph. The output is sorted by vertex and label, showing edges from :a to :c and :b to :c. ```elixir iex> g = Multigraph.new |> Multigraph.add_vertex(:a) |> Multigraph.add_vertex(:b) |> Multigraph.add_vertex(:c) ...> g = g |> Multigraph.add_edge(:a, :c) |> Multigraph.add_edge(:b, :c) ...> Multigraph.edges(g) |> Enum.sort_by(& {&1.v1, &1.v2, &1.label}) [%Multigraph.Edge{v1: :a, v2: :c}, %Multigraph.Edge{v1: :b, v2: :c}] ``` -------------------------------- ### delete_edge/3 directed example Source: https://hexdocs.pm/multigraph/Multigraph.html Example for delete_edge/3 on a directed graph, showing that all edges between :a and :b are removed. ```elixir iex> g = Multigraph.new |> Multigraph.add_edges([{:a, :b}, {:a, :b, label: :foo}]) ...> g = Multigraph.delete_edge(g, :a, :b) ...> [:a, :b] = Multigraph.vertices(g) ...> Multigraph.edges(g) [] ``` -------------------------------- ### edges/3 undirected example Source: https://hexdocs.pm/multigraph/Multigraph.html Example of edges/3 with an undirected graph, returning all edges between :a and :b sorted by label. ```elixir iex> g = Multigraph.new(type: :undirected) |> Multigraph.add_edge(:a, :b, label: :uses) ...> g = Multigraph.add_edge(g, :a, :b, label: :contains) ...> Multigraph.edges(g, :a, :b) |> Enum.sort_by(& &1.label) [%Multigraph.Edge{v1: :a, v2: :b, label: :contains}, %Multigraph.Edge{v1: :a, v2: :b, label: :uses}] ``` -------------------------------- ### reachable/2 example Source: https://hexdocs.pm/multigraph/Multigraph.html Example of using Multigraph.reachable/2 on a graph with vertices :a, :b, :c, :d and edges :a-:b, :a-:c, :b-:c, :c-:d. The result is [:d, :c, :b, :a]. ```elixir iex> g = Multigraph.new |> Multigraph.add_vertices([:a, :b, :c, :d]) ...> g = Multigraph.add_edges(g, [{:a, :b}, {:a, :c}, {:b, :c}, {:c, :d}]) ...> Multigraph.reachable(g, [:a]) [:d, :c, :b, :a] ``` -------------------------------- ### bellman_ford/3 with :by option example Source: https://hexdocs.pm/multigraph/Multigraph.html Example of bellman_ford/3 with the :by option set to :fast. The result is the distance to vertex :c, which is 3, ignoring the slow edge. ```elixir iex> g = Multigraph.new(multigraph: true) |> Multigraph.add_edges([ ...> {:a, :b, label: :fast, weight: 1}, ...> {:b, :c, label: :fast, weight: 2}, ...> {:a, :c, label: :slow, weight: 100} ...> ]) ...> distances = Multigraph.bellman_ford(g, :a, by: :fast) ...> distances[:c] 3 ``` -------------------------------- ### Construct a k-core with k_core_components/1 Source: https://hexdocs.pm/multigraph/Multigraph.html Example of constructing a k-core for a given graph using k_core_components/1. Filters vertices by a desired k value and then builds a subgraph with Multigraph.subgraph/2. ```elixir k_core_vertices = g |> Multigraph.k_core_components() |> Stream.filter(fn {k, _} -> k >= desired_k end) |> Enum.flat_map(fn {_, vs} -> vs end) Multigraph.subgraph(g, k_core_vertices) ``` -------------------------------- ### BFS reduce example Source: https://hexdocs.pm/multigraph/Multigraph.Reducers.Bfs.html Performs a breadth-first traversal of the graph, applying the reducer function to each vertex and the accumulator. The algorithm follows lower-weighted edges first. The result is the final accumulator state. The example shows a basic reduction that prepends vertices to the accumulator. ```elixir iex> g = Multigraph.new |> Multigraph.add_vertices([1, 2, 3, 4]) ...> g = Multigraph.add_edges(g, [{1, 3}, {1, 4}, {3, 2}, {2, 3}]) ...> Elixir.Multigraph.Reducers.Bfs.reduce(g, [], fn v, acc -> {:next, [v|acc]} end) [2, 4, 3, 1] ``` -------------------------------- ### dijkstra/4 with :by option example Source: https://hexdocs.pm/multigraph/Multigraph.html Example of using Multigraph.dijkstra/4 with the :by option to filter edges by partition key. The graph is created with multigraph: true and edges with labels and weights. The result is the shortest path [:a, :b, :d] when restricting traversal to edges with label :fast. ```elixir iex> g = Multigraph.new(multigraph: true) |> Multigraph.add_edges([ ...> {:a, :b, label: :fast, weight: 1}, ...> {:a, :c, label: :slow, weight: 10}, ...> {:b, :d, label: :fast, weight: 1}, ...> {:c, :d, label: :slow, weight: 1} ...> ]) ...> Multigraph.dijkstra(g, :a, :d, by: :fast) [:a, :b, :d] ``` -------------------------------- ### Example for pop/1 Source: https://hexdocs.pm/multigraph/Multigraph.PriorityQueue.html Shows popping elements in priority order from a shuffled queue, ending with :empty when the queue is exhausted. ```elixir iex> pq = Multigraph.PriorityQueue.new ...> pq = Enum.reduce(Enum.shuffle(0..4), pq, fn i, pq -> Multigraph.PriorityQueue.push(pq, ?a+i, i) end) ...> {{:value, ?a}, pq} = Multigraph.PriorityQueue.pop(pq) ...> {{:value, ?b}, pq} = Multigraph.PriorityQueue.pop(pq) ...> {{:value, ?c}, pq} = Multigraph.PriorityQueue.pop(pq) ...> {{:value, ?d}, pq} = Multigraph.PriorityQueue.pop(pq) ...> {{:value, ?e}, pq} = Multigraph.PriorityQueue.pop(pq) ...> {result, _} = Multigraph.PriorityQueue.pop(pq) ...> result :empty ``` -------------------------------- ### Example for push/3 Source: https://hexdocs.pm/multigraph/Multigraph.PriorityQueue.html Shows pushing elements with priorities and popping them, including two separate scenarios: one with a single element and one with two elements of the same priority. ```elixir iex> pq = Multigraph.PriorityQueue.new ...> pq = Multigraph.PriorityQueue.push(pq, :foo, 1) ...> {result, _} = Multigraph.PriorityQueue.pop(pq) ...> result {:value, :foo} iex> pq = Multigraph.PriorityQueue.new ...> pq = Multigraph.PriorityQueue.push(pq, :foo, 1) ...> {{:value, :foo}, pq} = Multigraph.PriorityQueue.pop(pq) ...> pq = Multigraph.PriorityQueue.push(pq, :bar, 1) ...> {result, _} = Multigraph.PriorityQueue.pop(pq) ...> result {:value, :bar} ``` -------------------------------- ### delete_edge/3 undirected example Source: https://hexdocs.pm/multigraph/Multigraph.html Example for delete_edge/3 on an undirected graph, showing that all edges between :a and :b are removed. ```elixir iex> g = Multigraph.new(type: :undirected) |> Multigraph.add_edges([{:a, :b}, {:a, :b, label: :foo}]) ...> g = Multigraph.delete_edge(g, :a, :b) ...> [:a, :b] = Multigraph.vertices(g) ...> Multigraph.edges(g) [] ``` -------------------------------- ### in_edges/3 example Source: https://hexdocs.pm/multigraph/Multigraph.html Example for in_edges/3. Creates a multigraph with two labeled edges from :a to :b, then filters the in edges to :b by the partition :foo. The result contains only the edge with label :foo. ```elixir iex> g = Multigraph.new(multigraph: true) |> Multigraph.add_edges([{:a, :b, label: :foo}, {:a, :b, label: :bar}]) ...> Multigraph.in_edges(g, :b, by: :foo) [%Multigraph.Edge{v1: :a, v2: :b, label: :foo}] ``` -------------------------------- ### label_vertex/3 spec and examples Source: https://hexdocs.pm/multigraph/Multigraph.html Specifies the label_vertex/3 function signature and shows usage examples. The function updates labels for a vertex; if the vertex does not exist, it returns {:error, {:invalid_vertex, v}}. The examples demonstrate adding a label and replacing labels with a list. ```elixir @spec label_vertex(t(), vertex(), term()) :: t() | {:error, {:invalid_vertex, vertex()}} ``` ```elixir iex> g = Multigraph.new |> Multigraph.add_vertex(:a, :foo) ...> [:foo] = Multigraph.vertex_labels(g, :a) ...> g = Multigraph.label_vertex(g, :a, :bar) ...> Multigraph.vertex_labels(g, :a) [:foo, :bar] iex> g = Multigraph.new |> Multigraph.add_vertex(:a) ...> g = Multigraph.label_vertex(g, :a, [:foo, :bar]) ...> Multigraph.vertex_labels(g, :a) [:foo, :bar] ``` -------------------------------- ### out_neighbors/2 example Source: https://hexdocs.pm/multigraph/Multigraph.html Example of using out_neighbors/2. It returns the unique vertices reachable from :a, which is [:b] even though there are two edges to :b. ```elixir iex> g = Multigraph.new |> Multigraph.add_edges([{:a, :b}, {:a, :b, label: :foo}, {:b, :c}]) ...> Multigraph.out_neighbors(g, :a) [:b] ``` -------------------------------- ### Add edges from tuples Source: https://hexdocs.pm/multigraph/Multigraph.html Example showing add_edges/2 with tuples of {vertex, vertex} and {vertex, vertex, edge_opts} including label and weight options. The result is sorted by vertices and label. ```elixir iex> g = Multigraph.new |> Multigraph.add_edges([{:a, :b}, {:a, :b, label: :foo}, {:a, :b, label: :foo, weight: 2}]) ...> Multigraph.edges(g) |> Enum.sort_by(& {&1.v1, &1.v2, &1.label}) [%Multigraph.Edge{v1: :a, v2: :b, label: :foo, weight: 2}, %Multigraph.Edge{v1: :a, v2: :b}] ``` -------------------------------- ### in_neighbors/2 example Source: https://hexdocs.pm/multigraph/Multigraph.html Example for in_neighbors/2. Creates a directed multigraph with edges from :a to :b (including a labeled edge) and from :b to :c, then returns the in neighbors of :b. The result is [:a]. ```elixir iex> g = Multigraph.new |> Multigraph.add_edges([{:a, :b}, {:a, :b, label: :foo}, {:b, :c}]) ...> Multigraph.in_neighbors(g, :b) [:a] ``` -------------------------------- ### out_degree/2 spec and example Source: https://hexdocs.pm/multigraph/Multigraph.html Specifies the out_degree/2 function and shows an example that builds a graph with vertices and one edge, then returns the out-degree of vertex :a. For undirected graphs, in-degree and out-degree are always the same. ```elixir @spec out_degree(t(), vertex()) :: non_neg_integer() ``` ```elixir iex> g = Multigraph.new |> Multigraph.add_vertices([:a, :b, :c]) |> Multigraph.add_edge(:a, :b) ...> Multigraph.out_degree(g, :a) 1 ``` -------------------------------- ### edges/3 with :by option Source: https://hexdocs.pm/multigraph/Multigraph.html Example of edges/3 with multigraph: true and the :by option to filter edges by partition label. ```elixir iex> g = Multigraph.new(multigraph: true) |> Multigraph.add_edges([{:a, :b}, {:b, :c}]) ...> g = Multigraph.add_edge(g, :a, :b, label: :contains) ...> Multigraph.edges(g, :a, by: :contains) [%Multigraph.Edge{v1: :a, v2: :b, label: :contains}] ``` -------------------------------- ### edges/3 with :by and :where options Source: https://hexdocs.pm/multigraph/Multigraph.html Example of edges/3 with multigraph: true, the :by option, and a :where function filtering edges by weight. ```elixir iex> g = Multigraph.new(multigraph: true) |> Multigraph.add_edges([{:a, :b}, {:b, :c}]) ...> g = Multigraph.add_edge(g, :a, :b, label: :contains, weight: 2) ...> Multigraph.edges(g, :a, by: :contains, where: fn edge -> edge.weight == 2 end) [%Multigraph.Edge{v1: :a, v2: :b, label: :contains, weight: 2}] ``` -------------------------------- ### reachable_neighbors/2 example Source: https://hexdocs.pm/multigraph/Multigraph.html Example of using Multigraph.reachable_neighbors/2 on a graph with vertices :a, :b, :c, :d and edges :a-:b, :a-:c, :b-:c, :c-:d. The result is [:d, :c, :b]. ```elixir iex> g = Multigraph.new |> Multigraph.add_vertices([:a, :b, :c, :d]) ...> g = Multigraph.add_edges(g, [{:a, :b}, {:a, :c}, {:b, :c}, {:c, :d}]) ...> Multigraph.reachable_neighbors(g, [:a]) [:d, :c, :b] ``` -------------------------------- ### out_edges/3 with :by and :where options Source: https://hexdocs.pm/multigraph/Multigraph.html Examples of using out_edges/3 with the :by and :where options. The first filters by partition key :foo, the second adds a predicate on edge weight. Both require multigraph: true. ```elixir iex> g = Multigraph.new(multigraph: true) |> Multigraph.add_edges([{:a, :b, label: :foo}, {:a, :b, label: :bar}, {:a, :c}]) ...> Multigraph.out_edges(g, :a, by: :foo) [%Multigraph.Edge{v1: :a, v2: :b, label: :foo}] ``` ```elixir iex> g = Multigraph.new(multigraph: true) |> Multigraph.add_edges([{:a, :b, label: :foo, weight: 5}, {:a, :b, label: :bar}]) ...> Multigraph.out_edges(g, :a, by: :foo, where: fn e -> e.weight > 1 end) [%Multigraph.Edge{v1: :a, v2: :b, label: :foo, weight: 5}] ``` -------------------------------- ### delete_edge/4 examples Source: https://hexdocs.pm/multigraph/Multigraph.html Examples for delete_edge/4: passing nil removes the unlabelled edge, passing :foo removes the labelled edge, and the undirected case removes the labelled edge. ```elixir iex> g = Multigraph.new |> Multigraph.add_edges([{:a, :b}, {:a, :b, label: :foo}]) ...> g = Multigraph.delete_edge(g, :a, :b, nil) ...> [:a, :b] = Multigraph.vertices(g) ...> Multigraph.edges(g) [%Multigraph.Edge{v1: :a, v2: :b, label: :foo}] iex> g = Multigraph.new |> Multigraph.add_edges([{:a, :b}, {:a, :b, label: :foo}]) ...> g = Multigraph.delete_edge(g, :a, :b, :foo) ...> [:a, :b] = Multigraph.vertices(g) ...> Multigraph.edges(g) [%Multigraph.Edge{v1: :a, v2: :b, label: nil}] iex> g = Multigraph.new(type: :undirected) |> Multigraph.add_edges([{:a, :b}, {:a, :b, label: :foo}]) ...> g = Multigraph.delete_edge(g, :a, :b, :foo) ...> [:a, :b] = Multigraph.vertices(g) ...> Multigraph.edges(g) [%Multigraph.Edge{v1: :a, v2: :b, label: nil}] ``` -------------------------------- ### edge/3 and edge/4 examples Source: https://hexdocs.pm/multigraph/Multigraph.html Examples of using Multigraph.edge/3 and edge/4. The first call with reversed vertices returns nil. The second returns an Edge struct without a label. The third returns an Edge with the specified label. The fourth shows that for an undirected graph, the edge is found regardless of vertex order. ```elixir iex> g = Multigraph.new |> Multigraph.add_edges([{:a, :b}, {:a, :b, label: :contains}, {:a, :b, label: :uses}]) ...> Multigraph.edge(g, :b, :a) nil iex> g = Multigraph.new |> Multigraph.add_edges([{:a, :b}, {:a, :b, label: :contains}, {:a, :b, label: :uses}]) ...> Multigraph.edge(g, :a, :b) %Multigraph.Edge{v1: :a, v2: :b} iex> g = Multigraph.new |> Multigraph.add_edges([{:a, :b}, {:a, :b, label: :contains}, {:a, :b, label: :uses}]) ...> Multigraph.edge(g, :a, :b, :contains) %Multigraph.Edge{v1: :a, v2: :b, label: :contains} iex> g = Multigraph.new(type: :undirected) |> Multigraph.add_edges([{:a, :b}, {:a, :b, label: :contains}, {:a, :b, label: :uses}]) ...> Multigraph.edge(g, :a, :b, :contains) %Multigraph.Edge{v1: :a, v2: :b, label: :contains} ``` -------------------------------- ### bellman_ford/2 example Source: https://hexdocs.pm/multigraph/Multigraph.html Example of bellman_ford/2. The first graph returns a map of distances from vertex :a, while the second graph contains a negative cycle and returns nil. ```elixir iex> g = Multigraph.new |> Multigraph.add_edges([ ...> {:b, :c, weight: -2}, {:a, :b, weight: 1}, ...> {:c, :d, weight: 3}, {:b, :d, weight: 4}]) ...> Multigraph.bellman_ford(g, :a) %{a: 0, b: 1, c: -1, d: 2} iex> g = Multigraph.new |> Multigraph.add_edges([ ...> {:b, :c, weight: -2}, {:a, :b, weight: -1}, ...> {:c, :d, weight: -3}, {:d, :a, weight: -5}]) ...> Multigraph.bellman_ford(g, :a) nil ``` -------------------------------- ### add_vertex/3 example Source: https://hexdocs.pm/multigraph/Multigraph.html Shows adding a vertex with a single label and with a list of labels. The second add_vertex call is a no-op because the vertex already exists. ```elixir iex> g = Multigraph.new |> Multigraph.add_vertex(:a, :mylabel) |> Multigraph.add_vertex(:a) ...> [:a] = Multigraph.vertices(g) ...> Multigraph.vertex_labels(g, :a) [:mylabel] iex> g = Multigraph.new |> Multigraph.add_vertex(:a, [:mylabel, :other]) ...> Multigraph.vertex_labels(g, :a) [:mylabel, :other] ``` -------------------------------- ### get_paths/3 IEx example Source: https://hexdocs.pm/multigraph/Multigraph.html IEx session showing get_paths/3 usage. The first graph returns two paths between :a and :d; the second graph has no path and returns an empty list. ```elixir iex> g = Multigraph.new |> Multigraph.add_edges([{:a, :b}, {:b, :c}, {:c, :d}, {:b, :d}, {:c, :a}]) ...> Multigraph.get_paths(g, :a, :d) [[:a, :b, :c, :d], [:a, :b, :d]] iex> g = Multigraph.new |> Multigraph.add_vertices([:a, :b, :c, :d]) ...> g = Multigraph.add_edges(g, [{:a, :c}, {:b, :c}, {:b, :d}]) ...> Multigraph.get_paths(g, :a, :d) [] ``` -------------------------------- ### num_edges/1 spec and example Source: https://hexdocs.pm/multigraph/Multigraph.html Specifies the num_edges/1 function and shows an example that adds edges (including a self-loop) and returns the edge count. Pseudo-edges (label/weight pairs) are not counted; only distinct vertex pairs with an edge are counted. ```elixir @spec num_edges(t()) :: non_neg_integer() ``` ```elixir iex> g = Multigraph.add_edges(Multigraph.new, [{:a, :b}, {:b, :c}, {:a, :a}]) ...> Multigraph.num_edges(g) 3 ``` -------------------------------- ### reduce/3 examples: DFS traversal with reducer function Source: https://hexdocs.pm/multigraph/Multigraph.Reducers.Dfs.html Performs a depth-first traversal of the graph, applying the reducer function to each new vertex and the accumulator. The algorithm follows lower-weighted edges first. The result is the accumulator state after the last reduction. The examples show basic reduction, skipping a vertex, and halting early. ```elixir iex> g = Multigraph.new |> Multigraph.add_vertices([1, 2, 3, 4]) ...> g = Multigraph.add_edges(g, [{1, 3}, {1, 4}, {3, 2}, {2, 4}]) ...> Elixir.Multigraph.Reducers.Dfs.reduce(g, [], fn v, acc -> {:next, [v|acc]} end) [4, 2, 3, 1] ``` ```elixir iex> g = Multigraph.new |> Multigraph.add_vertices([1, 2, 3, 4, 5]) ...> g = Multigraph.add_edges(g, [{1, 3}, {1, 4}, {3, 2}, {2, 4}, {4, 5}]) ...> Elixir.Multigraph.Reducers.Dfs.reduce(g, [], fn 5, acc -> {:skip, acc}; v, acc -> {:next, [v|acc]} end) [4, 2, 3, 1] ``` ```elixir iex> g = Multigraph.new |> Multigraph.add_vertices([1, 2, 3, 4, 5]) ...> g = Multigraph.add_edges(g, [{1, 3}, {1, 4}, {3, 2}, {2, 4}, {4, 5}]) ...> Elixir.Multigraph.Reducers.Dfs.reduce(g, [], fn 4, acc -> {:halt, acc}; v, acc -> {:next, [v|acc]} end) [2, 3, 1] ``` -------------------------------- ### in_edges/2 example Source: https://hexdocs.pm/multigraph/Multigraph.html Example for in_edges/2. Creates a directed multigraph with edges including a labeled edge, then returns the in edges to vertex :b sorted by label. The result includes both the labeled and unlabeled edges. ```elixir iex> g = Multigraph.new |> Multigraph.add_edges([{:a, :b}, {:a, :b, label: :foo}, {:b, :c}]) ...> Multigraph.in_edges(g, :b) |> Enum.sort_by(& &1.label) [%Multigraph.Edge{v1: :a, v2: :b, label: :foo}, %Multigraph.Edge{v1: :a, v2: :b}] ``` -------------------------------- ### add_vertices/2 example Source: https://hexdocs.pm/multigraph/Multigraph.html Adds a list of vertices, including a duplicate, and returns the unique vertices. ```elixir iex> g = Multigraph.new |> Multigraph.add_vertices([:a, :b, :a]) ...> Multigraph.vertices(g) [:a, :b] ``` -------------------------------- ### out_edges/2 spec and example Source: https://hexdocs.pm/multigraph/Multigraph.html Specifies the out_edges/2 function and shows an example that adds edges (including one with a label) and returns the out edges from vertex :a, sorted by label. For undirected graphs, it delegates to edges/2. ```elixir @spec out_edges(t(), vertex()) :: Multigraph.Edge.t() ``` ```elixir iex> g = Multigraph.new |> Multigraph.add_edges([{:a, :b}, {:a, :b, label: :foo}, {:b, :c}]) ...> Multigraph.out_edges(g, :a) |> Enum.sort_by(& &1.label) [%Multigraph.Edge{v1: :a, v2: :b, label: :foo}, %Multigraph.Edge{v1: :a, v2: :b}] ``` -------------------------------- ### batch_topsort/1 examples Source: https://hexdocs.pm/multigraph/Multigraph.html Shows batch topological sorting on various graphs, including a cyclic graph that returns false. Multiple edges are treated as a single edge. ```elixir iex> g = Multigraph.new |> Multigraph.add_vertices([:a, :b, :c]) ...> g = Multigraph.add_edges(g, [{:a, :b}, {:a, :c}]) ...> Multigraph.batch_topsort(g) [[:a], [:b, :c]] iex> g = Multigraph.new |> Multigraph.add_vertices([:a, :b, :c, :d]) ...> g = Multigraph.add_edges(g, [{:a, :b}, {:a, :c}, {:b, :c}, {:c, :d}]) ...> Multigraph.batch_topsort(g) [[:a], [:b], [:c], [:d]] iex> g = Multigraph.new |> Multigraph.add_vertices([:a, :b, :c, :d, :x, :y, :z]) ...> g = Multigraph.add_edges(g, [{:a, :b}, {:a, :c}, {:c, :d}, {:x, :y}, {:x, :z}]) ...> Multigraph.batch_topsort(g) [[:a, :x], [:b, :c, :y, :z], [:d]] iex> g = Multigraph.new |> Multigraph.add_vertices([:a, :b, :c, :d, :x, :y, :z]) ...> g = Multigraph.add_edges(g, [{:a, :b}, {:a, :c}, {:b, :c}, {:c, :d}, {:c, :a}]) ...> Multigraph.batch_topsort(g) false ``` -------------------------------- ### degree/2 IEx examples Source: https://hexdocs.pm/multigraph/Multigraph.html IEx examples for degree/2. Shows that for an undirected graph and a directed graph (default), the degree of vertex :b is 1 after adding a single edge. ```elixir iex> g = Multigraph.new(type: :undirected) |> Multigraph.add_vertices([:a, :b, :c]) |> Multigraph.add_edge(:a, :b) ...> Multigraph.degree(g, :b) 1 iex> g = Multigraph.new() |> Multigraph.add_vertices([:a, :b, :c]) |> Multigraph.add_edge(:a, :b) ...> Multigraph.degree(g, :b) 1 ``` -------------------------------- ### Add edges from Edge structs Source: https://hexdocs.pm/multigraph/Multigraph.html Example showing add_edges/2 with a list of Edge structs created via Edge.new/2 and Edge.new/3, including a weight option. The result is sorted by vertices and label. ```elixir iex> alias Multigraph.Edge ...> edges = [Edge.new(:a, :b), Edge.new(:b, :c, weight: 2)] ...> g = Multigraph.new |> Multigraph.add_vertices([:a, :b, :c]) |> Multigraph.add_edges(edges) ...> Multigraph.edges(g) |> Enum.sort_by(& {&1.v1, &1.v2, &1.label}) [%Multigraph.Edge{v1: :a, v2: :b}, %Multigraph.Edge{v1: :b, v2: :c, weight: 2}] ``` -------------------------------- ### has_vertex?/2 IEx example Source: https://hexdocs.pm/multigraph/Multigraph.html IEx session showing has_vertex?/2 usage. Returns true for an existing vertex and false for a missing vertex. ```elixir iex> g = Multigraph.new |> Multigraph.add_vertices([:a, :b]) ...> Multigraph.has_vertex?(g, :a) true iex> g = Multigraph.new |> Multigraph.add_vertices([:a, :b]) ...> Multigraph.has_vertex?(g, :c) false ``` -------------------------------- ### BFS map example Source: https://hexdocs.pm/multigraph/Multigraph.Reducers.Bfs.html Performs a breadth-first traversal of the graph, applying the mapping function to each vertex. The algorithm follows lower-weighted edges first. Returns a list of values from the mapper in encounter order. ```elixir iex> g = Multigraph.new |> Multigraph.add_vertices([1, 2, 3, 4]) ...> g = Multigraph.add_edges(g, [{1, 3}, {1, 4}, {3, 2}, {2, 3}]) ...> Elixir.Multigraph.Reducers.Bfs.map(g, fn v -> v end) [1, 3, 4, 2] ``` -------------------------------- ### BFS reduce with skip example Source: https://hexdocs.pm/multigraph/Multigraph.Reducers.Bfs.html Performs a breadth-first traversal of the graph, applying the reducer function to each vertex and the accumulator. The algorithm follows lower-weighted edges first. The reducer can return {:skip, acc} to skip a vertex, as shown for vertex 5. ```elixir iex> g = Multigraph.new |> Multigraph.add_vertices([1, 2, 3, 4]) ...> g = Multigraph.add_edges(g, [{1, 3}, {1, 4}, {3, 2}, {2, 3}, {4, 5}]) ...> Elixir.Multigraph.Reducers.Bfs.reduce(g, [], fn 5, acc -> {:skip, acc}; v, acc -> {:next, [v|acc]} end) [2, 4, 3, 1] ``` -------------------------------- ### BFS reduce with halt example Source: https://hexdocs.pm/multigraph/Multigraph.Reducers.Bfs.html Performs a breadth-first traversal of the graph, applying the reducer function to each vertex and the accumulator. The algorithm follows lower-weighted edges first. The reducer can return {:halt, acc} to stop traversal early, as shown for vertex 4. ```elixir iex> g = Multigraph.new |> Multigraph.add_vertices([1, 2, 3, 4]) ...> g = Multigraph.add_edges(g, [{1, 3}, {1, 4}, {3, 2}, {2, 3}, {4, 5}]) ...> Elixir.Multigraph.Reducers.Bfs.reduce(g, [], fn 4, acc -> {:halt, acc}; v, acc -> {:next, [v|acc]} end) [3, 1] ```