### Create a New Priority Queue Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-priority-queue.md Initializes an empty priority queue. Use this to start. ```elixir pq = PriorityQueue.new() ``` -------------------------------- ### Example: Retrieving All Vertices Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Demonstrates retrieving all vertices from a graph after adding them using `add_vertices/2`. ```elixir g = Graph.new() |> Graph.add_vertices([:a, :b]) Graph.vertices(g) # => [:a, :b] ``` -------------------------------- ### Example: Adding Multiple Vertices Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Shows how to initialize a graph and add a list of vertices using the `add_vertices/2` function. ```elixir g = Graph.new() |> Graph.add_vertices([:a, :b, :c]) ``` -------------------------------- ### Pathfinding Example with Priority Queue Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-priority-queue.md Demonstrates using PriorityQueue for pathfinding algorithms like A*, prioritizing exploration of lower-cost paths. ```elixir # A* pathfinding uses priority queue to explore lower-cost paths first pq = PriorityQueue.new() pq = PriorityQueue.push(pq, {:vertex_b, :vertex_a}, 5.0) # cost 5 pq = PriorityQueue.push(pq, {:vertex_c, :vertex_a}, 3.0) # cost 3 pq = PriorityQueue.push(pq, {:vertex_d, :vertex_a}, 7.0) # cost 7 # Pop returns lowest cost first {{:value, {:vertex_c, :vertex_a}}, pq} = PriorityQueue.pop(pq) {{:value, {:vertex_b, :vertex_a}}, pq} = PriorityQueue.pop(pq) {{:value, {:vertex_d, :vertex_a}}, pq} = PriorityQueue.pop(pq) ``` -------------------------------- ### Find Reachable Vertices Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/quick-reference.md Determine all vertices that can be reached from a given starting vertex or set of vertices. The starting point should be a list. ```elixir reachable = Graph.reachable(g, [:start]) ``` -------------------------------- ### Example: Adding and Labeling Vertices Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Demonstrates adding vertices to a new graph and subsequently applying single and multiple labels to a vertex. ```elixir g = Graph.new() |> Graph.add_vertex(:a) |> Graph.add_vertex(:b, :my_label) |> Graph.add_vertex(:c, [:label1, :label2]) ``` -------------------------------- ### Example: Retrieving Vertex Labels Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Demonstrates adding a vertex with a label and then retrieving that label. Also shows retrieving labels for a non-existent vertex. ```elixir g = Graph.new() |> Graph.add_vertex(:a, :label1) Graph.vertex_labels(g, :a) # => [:label1] Graph.vertex_labels(g, :b) # => [] ``` -------------------------------- ### Example: Removing All Vertex Labels Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Illustrates adding a vertex with labels, then removing all labels, and finally verifying that the vertex has no labels. ```elixir g = Graph.new() |> Graph.add_vertex(:a, [:foo, :bar]) g = Graph.remove_vertex_labels(g, :a) Graph.vertex_labels(g, :a) # => [] ``` -------------------------------- ### Example: Checking Vertex Existence Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Illustrates checking for the presence of vertices in a graph that has been populated with a list of vertices. ```elixir g = Graph.new() |> Graph.add_vertices([:a, :b]) Graph.has_vertex?(g, :a) # => true Graph.has_vertex?(g, :c) # => false ``` -------------------------------- ### Graph.Reducers.Bfs.reduce/3 Example: Skip branches Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-reducers.md Traverses the graph in breadth-first order, applying a reducing function. This example shows how to use the `{:skip, acc}` return value to prevent traversal of a vertex's neighbors. ```elixir g = Graph.new() |> Graph.add_vertices([1, 2, 3, 4, 5]) |> Graph.add_edges([{1, 3}, {1, 4}, {3, 2}, {2, 3}, {4, 5}]) # Skip branches result = Graph.Reducers.Bfs.reduce(g, [], fn 5, acc -> {:skip, acc} # don't explore neighbors of 5 v, acc -> {:next, [v | acc]} end) # => [2, 4, 3, 1] ``` -------------------------------- ### Example: Labeling a Vertex Multiple Times Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Shows adding a vertex and then applying multiple labels to it sequentially, followed by retrieving all its labels. ```elixir g = Graph.new() |> Graph.add_vertex(:a) |> Graph.label_vertex(:a, :start) |> Graph.label_vertex(:a, :important) Graph.vertex_labels(g, :a) # => [:start, :important] ``` -------------------------------- ### PriorityQueue.new/0 Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-priority-queue.md Creates a new, empty priority queue. This is the starting point for using the PriorityQueue module. ```APIDOC ## PriorityQueue.new/0 ### Description Creates a new empty priority queue. ### Method `new/0` ### Returns - `PriorityQueue.t()` — an empty priority queue ### Example ```elixir pq = PriorityQueue.new() ``` ``` -------------------------------- ### Graph.Reducers.Bfs.reduce/3 Example: Collect vertices with control flow Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-reducers.md Traverses the graph in breadth-first order, applying a reducing function. This example demonstrates collecting vertices into a list and halting the traversal when a specific vertex (4) is reached. ```elixir g = Graph.new() |> Graph.add_vertices([1, 2, 3, 4, 5]) |> Graph.add_edges([{1, 3}, {1, 4}, {3, 2}, {2, 3}, {4, 5}]) # Collect vertices with control flow result = Graph.Reducers.Bfs.reduce(g, [], fn v, acc -> if v == 4 do {:halt, acc} # stop when reaching 4 else {:next, [v | acc]} end end) # => [3, 1] ``` -------------------------------- ### Serialize Graph Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/quick-reference.md Provides examples for serializing a graph into different formats: Graphviz DOT, edge list, and flowchart. ```elixir # Graphviz DOT format {:ok, dot} = Graph.to_dot(g) File.write!("graph.dot", dot) ``` ```elixir # Edge list {:ok, edgelist} = Graph.to_edgelist(g) ``` ```elixir # Flowchart {:ok, flowchart} = Graph.to_flowchart(g) ``` -------------------------------- ### Example: Deleting a Vertex and its Edges Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Shows the process of adding vertices and edges, then deleting a specific vertex and observing the resulting vertices and edges. ```elixir g = Graph.new() |> Graph.add_vertices([:a, :b, :c]) |> Graph.add_edges([{:a, :b}, {:b, :c}]) g = Graph.delete_vertex(g, :b) Graph.vertices(g) # => [:a, :c] Graph.edges(g) # => [] ``` -------------------------------- ### Example: Replacing a Vertex Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Demonstrates replacing an existing vertex with a new one, including preserving associated edges and verifying the updated vertex list and edges. ```elixir g = Graph.new() |> Graph.add_vertices([:a, :b, :c]) |> Graph.add_edges([{:a, :b}, {:b, :c}]) g = Graph.replace_vertex(g, :a, :x) Graph.vertices(g) # => [:x, :b, :c] Graph.edges(g) # => [%Graph.Edge{v1: :x, v2: :b}, %Graph.Edge{v1: :b, v2: :c}] ``` -------------------------------- ### Graph.reachable/2 Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Retrieves all vertices that are reachable from a given set of starting vertices, including the starting vertices themselves. ```APIDOC ## Graph.reachable/2 ### Description Returns all vertices reachable from any of the given vertices, including the starting vertices. ### Function Signature ```elixir def reachable(g :: Graph.t(), vertices :: [vertex()]) :: [vertex()] ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```elixir g = Graph.new() |> Graph.add_edges([{:a, :b}, {:b, :c}, {:c, :d}]) Graph.reachable(g, [:a]) # => [:a, :b, :c, :d] ``` ### Response #### Success Response - Returns a list of vertices reachable from the specified starting vertices. #### Response Example ```json ["a", "b", "c", "d"] ``` ``` -------------------------------- ### Example: Deleting Multiple Vertices Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Illustrates deleting multiple vertices from a graph that was initially populated with several vertices. ```elixir g = Graph.new() |> Graph.add_vertices([:a, :b, :c]) |> Graph.delete_vertices([:a, :b]) Graph.vertices(g) # => [:c] ``` -------------------------------- ### Get Graph Information Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/types.md Illustrates how to create an undirected graph, add vertices and edges, and then retrieve information about the graph's type, vertex count, edge count, and approximate size. ```elixir g = Graph.new(type: :undirected) |> Graph.add_vertices([:a, :b, :c, :d]) |> Graph.add_edges([{:a, :b}, {:b, :c}, {:c, :d}]) info = Graph.info(g) %{ type: :undirected, num_vertices: 4, num_edges: 3, size_in_bytes: 2048 # approximate } ``` -------------------------------- ### Graph Neighborhood Analysis in Libgraph Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/quick-reference.md Provides examples for calculating vertex degrees (in, out, and total) and finding neighbors (all, incoming, and outgoing). Also shows how to retrieve incoming and outgoing edges for a vertex. ```elixir # Degree Graph.degree(g, :a) # in + out edges Graph.in_degree(g, :a) # incoming Graph.out_degree(g, :a) # outgoing # Neighbors Graph.neighbors(g, :a) # all connected Graph.in_neighbors(g, :a) # sources Graph.out_neighbors(g, :a) # targets # Edges Graph.in_edges(g, :a) # incoming edges Graph.out_edges(g, :a) # outgoing edges ``` -------------------------------- ### Ensuring Consistent Vertex IDs Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/configuration.md Highlights the importance of a custom identifier function returning the same value for equivalent vertices. The 'GOOD' example uses a deterministic function, while the 'BAD' example uses a non-deterministic one. ```elixir # ❌ BAD - returns different IDs for same vertex g = Graph.new(vertex_identifier: fn _ -> :erlang.make_ref() end) # ✓ GOOD - returns consistent IDs g = Graph.new(vertex_identifier: &String.to_atom/1) ``` -------------------------------- ### Get Graph Memory Info Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/configuration.md Creates a large graph and inspects its memory usage and statistics. The size_in_bytes is an approximation. ```elixir g = Graph.new() |> Graph.add_vertices(Enum.range(1, 1000)) |> Graph.add_edges(Enum.map(Enum.range(1, 999), fn i -> {i, i+1} end)) info = Graph.info(g) IO.inspect(info) # %{ # type: :directed, # num_vertices: 1000, # num_edges: 999, # size_in_bytes: ~8000 # approximate # } ``` -------------------------------- ### Graph.Reducers.Bfs.map/2 Example Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-reducers.md Applies a mapping function to each vertex in breadth-first order and collects the results in a list. Use this to transform each vertex's value. ```elixir g = Graph.new() |> Graph.add_vertices([1, 2, 3, 4]) |> Graph.add_edges([{1, 3}, {1, 4}, {3, 2}, {2, 3}]) Graph.Reducers.Bfs.map(g, fn v -> v * 10 end) # => [10, 30, 40, 20] ``` -------------------------------- ### Handle Graph Errors with False Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/quick-reference.md Shows how to handle functions that return false on invalid input, like attempting a topological sort on a cyclic graph. The example demonstrates checking the return value to determine if the operation was successful. ```elixir # Functions returning false on invalid input case Graph.topsort(g) do false -> IO.puts("Graph is cyclic") vertices -> IO.inspect(vertices) end ``` -------------------------------- ### Add Libgraph to Mix Dependencies Source: https://github.com/bitwalker/libgraph/blob/main/README.md Add the libgraph dependency to your project's mix.exs file to install the package. ```elixir def deps do [{:libgraph, "~> 0.16.0"}] end ``` -------------------------------- ### Handle Graph Errors with Tuples Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/quick-reference.md Illustrates how to handle functions that return error tuples, such as invalid vertex or edge operations. The example shows how to pattern match on the result and decide whether to keep the original graph or apply changes. ```elixir # Functions returning error tuples case Graph.label_vertex(g, :a, :label) do %Graph{} = g -> g {:error, {:invalid_vertex, _}} -> g # keep original end ``` ```elixir case Graph.replace_vertex(g, :a, :b) do %Graph{} = g -> g {:error, :no_such_vertex} -> g # keep original end ``` ```elixir case Graph.split_edge(g, :a, :b, :c) do %Graph{} = g -> g {:error, :no_such_edge} -> g # keep original end ``` -------------------------------- ### Get K-Core Subgraph Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/quick-reference.md Extracts the k-core subgraph where all vertices have a minimum degree. Also shows how to group components by coreness, find individual vertex coreness, and determine graph degeneracy. ```elixir # Get k-core subgraph core = Graph.k_core(g, 2) # subgraph where all vertices have degree >= 2 ``` ```elixir # Group by coreness Graph.k_core_components(g) # => %{1 => [vs...], 2 => [vs...], ...} ``` ```elixir # Individual vertex coreness Graph.coreness(g, :a) # => 2 ``` ```elixir # Graph degeneracy Graph.degeneracy(g) # => 3 ``` ```elixir # Degeneracy core Graph.degeneracy_core(g) # => Graph with highest k-core ``` -------------------------------- ### Get Vertices Reachable from Given Vertices Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns all vertices reachable from any of the given vertices, including the starting vertices. Useful for graph traversal analysis. ```elixir def reachable(g :: Graph.t(), vertices :: [vertex()]) :: [vertex()] Returns all vertices reachable from any of the given vertices, including the starting vertices. Example: g = Graph.new() |> Graph.add_edges([{:a, :b}, {:b, :c}, {:c, :d}]) Graph.reachable(g, [:a]) # => [:a, :b, :c, :d] ``` -------------------------------- ### Get Reachable Neighbors from Given Vertices Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns vertices reachable from any of the given vertices, excluding the starting vertices themselves. This is useful for finding direct or indirect successors without including the source nodes. ```elixir def reachable_neighbors(g :: Graph.t(), vertices :: [vertex()]) :: [vertex()] Returns vertices reachable from any of the given vertices, excluding the starting vertices themselves. ``` -------------------------------- ### Graph.reachable_neighbors/2 Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Finds all vertices reachable from a given set of starting vertices, excluding the starting vertices themselves. ```APIDOC ## Graph.reachable_neighbors/2 ### Description Returns vertices reachable from any of the given vertices, excluding the starting vertices themselves. ### Function Signature ```elixir def reachable_neighbors(g :: Graph.t(), vertices :: [vertex()]) :: [vertex()] ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Response #### Success Response - Returns a list of vertices reachable from the specified starting vertices, excluding the starting vertices. #### Response Example ```json ["b", "c", "d"] ``` ``` -------------------------------- ### Configure Graph with Pipeline Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/configuration.md Shows how to set up an undirected graph, add vertices, label them, and add edges using a pipeline. ```elixir # Configuration and setup in one pipeline g = Graph.new(type: :undirected) |> Graph.add_vertices([1, 2, 3, 4, 5]) |> Graph.label_vertex(1, :start) |> Graph.label_vertex(5, :end) |> Graph.add_edges([{1, 2}, {2, 3}, {2, 4}, {3, 5}, {4, 5}]) ``` -------------------------------- ### Get Strongly Connected Components of a Graph Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns strongly connected components using directed edges only. The output lists components, where each component is a list of vertices. ```elixir def strong_components(g :: Graph.t()) :: [[vertex()]] Returns strongly connected components using directed edges only. Example: g = Graph.new() |> Graph.add_edges([{:a, :b}, {:b, :c}, {:c, :a}, {:c, :d}]) Graph.strong_components(g) # => [[:d], [:a, :b, :c]] ``` -------------------------------- ### Use Different Layout Engines with PNG Output Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-serializers.md Demonstrates using alternative layout engines like `neato`, `circo`, `fdp`, and `twopi` to generate PNG output. Each engine offers a different approach to graph arrangement. ```bash neato -Tpng graph.dot > graph.png ``` ```bash circo -Tpng graph.dot > graph.png ``` ```bash fdp -Tpng graph.dot > graph.png ``` ```bash twopi -Tpng graph.dot > graph.png ``` -------------------------------- ### Elixir Edge Value Type Definition and Example Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/types.md Defines the edge value as a map from labels to edge weights. Shows examples of edges with no label or multiple labeled edges. ```elixir @type edge_value :: %{label() => edge_weight()} ``` ```elixir # Edge with no label (nil => weight) %{nil => 1} # Multiple labeled edges %{nil => 1, :uses => 2, :contains => 3} ``` -------------------------------- ### Get All Edges Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Retrieves a list of all edges present in the graph. ```Elixir def edges(g :: Graph.t()) :: [Graph.Edge.t()] ``` ```Elixir g = Graph.new() |> Graph.add_vertices([:a, :b, :c]) |> Graph.add_edges([{:a, :b}, {:b, :c}]) Graph.edges(g) # => [%Graph.Edge{v1: :a, v2: :b}, %Graph.Edge{v1: :b, v2: :c}] ``` -------------------------------- ### Get Out-Edges of a Vertex Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns a list of all edges that originate from the specified vertex. ```elixir def out_edges(g :: Graph.t(), v :: vertex()) :: [Graph.Edge.t()] ``` -------------------------------- ### Get In-Edges of a Vertex Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns a list of all edges that point to the specified vertex. ```elixir def in_edges(g :: Graph.t(), v :: vertex()) :: [Graph.Edge.t()] ``` -------------------------------- ### Visualize DOT Graph Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-serializers.md Demonstrates how to save DOT string to a file and convert it to various formats like PNG, SVG, or ASCII using the `dot` command-line tool. ```bash # Save to file dot_string |> File.write!("graph.dot") # Convert to PNG # $ dot -Tpng graph.dot > graph.png # Convert to SVG # $ dot -Tsvg graph.dot > graph.svg # View as ASCII # $ dot -Tascii graph.dot ``` -------------------------------- ### Get Out-Neighbors of a Vertex Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns a list of vertices that the specified vertex points to. ```elixir def out_neighbors(g :: Graph.t(), v :: vertex()) :: [vertex()] ``` ```elixir g = Graph.new() |> Graph.add_edges([{:a, :b}, {:a, :c}]) Graph.out_neighbors(g, :a) # => [:b, :c] ``` -------------------------------- ### Get Vertex Out-Degree Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns the out-degree of a vertex, which is the count of edges originating from it. ```elixir def out_degree(g :: Graph.t(), v :: vertex()) :: non_neg_integer() ``` -------------------------------- ### Get Number of Vertices Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns the total count of vertices present in the graph. ```elixir def num_vertices(g :: Graph.t()) :: non_neg_integer() ``` ```elixir g = Graph.new() |> Graph.add_vertices([:a, :b, :c]) Graph.num_vertices(g) # => 3 ``` -------------------------------- ### Create and Add Edges Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/types.md Demonstrates creating a new edge with attributes like weight and label, and adding it to a graph. Also shows adding multiple edges between the same vertices with different labels. ```elixir # Create edge with weight edge = Graph.Edge.new(:a, :b, weight: 5, label: :route) %Graph.Edge{v1: :a, v2: :b, weight: 5, label: :route} # Add edge to graph g = Graph.new() |> Graph.add_edge(edge) # Multiple edges between same vertices (different labels) g = Graph.new() |> Graph.add_edge(:a, :b, label: :uses) |> Graph.add_edge(:a, :b, label: :contains, weight: 2) # Internal representation: %{nil => 1, uses: 1, contains: 2} ``` -------------------------------- ### Get Graph Degeneracy Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns the degeneracy of the graph, which is the maximum k for which a k-core exists. ```elixir def degeneracy(g :: Graph.t()) :: non_neg_integer() ``` -------------------------------- ### Create a new directed graph Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/configuration.md Use `Graph.new/1` with no options to create a default directed graph. ```elixir g = Graph.new() # or g = Graph.new(type: :directed) ``` -------------------------------- ### Get In-Neighbors of a Vertex Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns a list of vertices that have edges pointing to the specified vertex. ```elixir def in_neighbors(g :: Graph.t(), v :: vertex()) :: [vertex()] ``` ```elixir g = Graph.new() |> Graph.add_edges([{:a, :b}, {:c, :b}]) Graph.in_neighbors(g, :b) # => [:a, :c] ``` -------------------------------- ### Create Different Graph Types Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/configuration.md Demonstrates how to create standard directed, undirected, and graphs with custom vertex identifiers. ```elixir # Standard directed graph (most common) directed = Graph.new() # Undirected graph for bidirectional relationships undirected = Graph.new(type: :undirected) # Directed graph with string vertex IDs string_keyed = Graph.new(vertex_identifier: &String.to_atom/1) # Directed graph with custom struct vertex IDs struct_keyed = Graph.new(vertex_identifier: fn %User{id: id} -> id end) ``` -------------------------------- ### Get Vertex In-Degree Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns the in-degree of a vertex, which is the count of edges pointing towards it. ```elixir def in_degree(g :: Graph.t(), v :: vertex()) :: non_neg_integer() ``` ```elixir g = Graph.new() |> Graph.add_edges([{:a, :b}, {:c, :b}, {:d, :b}]) Graph.in_degree(g, :b) # => 3 ``` -------------------------------- ### Get Edges for a Vertex Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns all edges, both inbound and outbound, connected to a specified vertex. ```Elixir def edges(g :: Graph.t(), v :: vertex()) :: [Graph.Edge.t()] ``` ```Elixir g = Graph.new() |> Graph.add_edges([{:a, :b}, {:b, :c}]) Graph.edges(g, :b) # => [%Graph.Edge{v1: :a, v2: :b}, %Graph.Edge{v1: :b, v2: :c}] ``` -------------------------------- ### Dependency Analysis Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/quick-reference.md Check if all dependencies for a given package are satisfied by verifying reachability. Requires a `can_install?/1` function to be defined. ```elixir # Check if all dependencies are satisfied dependencies_satisfied? = Graph.reachable(g, [:package_a]) |> Enum.all?(&can_install?/1) ``` -------------------------------- ### All Paths from Source to Target Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns all possible paths from a source vertex to a target vertex using a depth-first search approach. ```elixir def get_paths(g :: Graph.t(), source :: vertex(), target :: vertex()) :: [[vertex()]] ``` ```elixir g = Graph.new() |> Graph.add_edges([{:a, :b}, {:b, :c}, {:c, :d}, {:b, :d}, {:c, :a}]) Graph.get_paths(g, :a, :d) # => [[:a, :b, :c, :d], [:a, :b, :d]] ``` -------------------------------- ### Demonstrate Immutability Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/configuration.md Illustrates that graph functions return new structs instead of modifying in place, preserving the original graph. ```elixir original = Graph.new() |> Graph.add_vertex(:a) modified = Graph.add_vertex(original, :b) # original is unchanged Graph.vertices(original) # => [:a] Graph.vertices(modified) # => [:a, :b] ``` -------------------------------- ### Get Vertex Coreness Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns the k-coreness of a specific vertex, which is the highest k-value for which the vertex is part of the k-core. ```elixir g = Graph.new() |> Graph.add_edges([{:a, :b}, {:b, :c}, {:c, :a}]) Graph.coreness(g, :a) # => 2 ``` -------------------------------- ### DOT Directed Edge Syntax Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-serializers.md Demonstrates the syntax for creating directed edges between vertices in DOT, with options for weight and labels. ```dot v1 -> v2 [weight=1] # simple edge v1 -> v2 [weight=2; label="optional"] # with label ``` -------------------------------- ### Get Edges Between Two Vertices Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Retrieves a list of all edges that exist specifically between two given vertices. ```Elixir def edges(g :: Graph.t(), v1 :: vertex(), v2 :: vertex()) :: [Graph.Edge.t()] ``` ```Elixir g = Graph.new() |> Graph.add_edge(:a, :b) |> Graph.add_edge(:a, :b, label: :foo) Graph.edges(g, :a, :b) # => [%Graph.Edge{v1: :a, v2: :b}, %Graph.Edge{v1: :a, v2: :b, label: :foo}] ``` -------------------------------- ### Pathfinding Algorithms in Elixir Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/quick-reference.md Find shortest paths using Dijkstra or A* algorithms, or retrieve all possible paths. Bellman-Ford is available for graphs with negative weights. ```elixir # Shortest path Graph.dijkstra(g, :a, :d) # => [:a, :b, :d] or nil Graph.get_shortest_path(g, :a, :d) # same as dijkstra # A* with heuristic Graph.a_star(g, :a, :d, fn v -> estimate_cost(v, :d) end) # All paths Graph.get_paths(g, :a, :d) # => [[:a, :b, :d], [:a, :c, :d], ...] # Bellman-Ford (handles negative weights) Graph.bellman_ford(g, :a) # => %{a: 0, b: 1, c: 2, ...} or nil ``` -------------------------------- ### Graph Properties in Libgraph Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/quick-reference.md Shows how to retrieve graph information such as type, vertex count, edge count, and size. Also demonstrates checks for acyclicity, cyclicity, tree structure, and subgraph relationships. ```elixir # Structure Graph.info(g) # => %{type: :directed, num_vertices: N, num_edges: M, size_in_bytes: ...} # Cycles Graph.is_acyclic?(g) # => true/false Graph.is_cyclic?(g) # => true/false # Trees Graph.is_tree?(g) # => true/false Graph.is_arborescence?(g) # => true/false # Structure comparison Graph.is_subgraph?(g1, g2) # => true if g1 ⊆ g2 ``` -------------------------------- ### Get All Neighbors of a Vertex Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns a list of all vertices connected to the specified vertex, including both inbound and outbound connections. ```elixir def neighbors(g :: Graph.t(), v :: vertex()) :: [vertex()] ``` -------------------------------- ### Get Arborescence Root Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Use `Graph.arborescence_root/1` to find the root vertex of an arborescence. Returns nil if the graph is not an arborescence. ```elixir def arborescence_root(g :: Graph.t()) :: vertex() | nil ``` -------------------------------- ### DOT Vertex Syntax Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-serializers.md Shows the syntax for defining a vertex in DOT format, including how to assign a human-readable label. ```dot id[label="Human Readable Label"] ``` -------------------------------- ### Querying Edges in Libgraph Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/quick-reference.md Demonstrates how to retrieve all edges, edges connected to a specific vertex, edges between two vertices, and individual edges (both labelled and unlabelled). Also shows how to count the total number of edges. ```elixir # All edges edges = Graph.edges(g) # Edges from/to vertex edges = Graph.edges(g, :a) # Edges between two vertices edges = Graph.edges(g, :a, :b) # Single edge edge = Graph.edge(g, :a, :b) # unlabelled edge = Graph.edge(g, :a, :b, :label) # labelled # Count Graph.num_edges(g) ``` -------------------------------- ### Get Degeneracy Core Subgraph Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns the degeneracy core as a subgraph. This is the k-core where k is equal to the graph's degeneracy. ```elixir def degeneracy_core(g :: Graph.t()) :: Graph.t() ``` -------------------------------- ### Build Graph from Edges Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/quick-reference.md Construct a new graph and add multiple edges at once. Ensure edges are provided as a list of tuples. ```elixir edges = [{:a, :b}, {:b, :c}, {:c, :a}] g = Graph.new() |> Graph.add_edges(edges) ``` -------------------------------- ### Get Vertex Degree Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns the degree of a vertex, which is the count of its inbound and outbound edges. For undirected graphs, each edge is counted once. ```elixir def degree(g :: Graph.t(), v :: vertex()) :: non_neg_integer() ``` ```elixir g = Graph.new() |> Graph.add_edges([{:a, :b}, {:c, :a}, {:a, :d}]) Graph.degree(g, :a) # => 3 ``` -------------------------------- ### Export Graph to DOT and Save as PNG Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-serializers.md Exports a graph to DOT format, saves it to a file, and then uses the `dot` command to generate a PNG image. This is useful for visualizing graph structures. ```elixir # Export to DOT and save g = Graph.new() |> Graph.add_edges([{:a, :b}, {:b, :c}]) case Graph.to_dot(g) do {:ok, dot} -> File.write!("graph.dot", dot) System.cmd("dot", ["-Tpng", "graph.dot", "-o", "graph.png"]) IO.puts("Saved graph.png") {:error, reason} -> IO.inspect(reason) end ``` -------------------------------- ### DOT Graph Declaration Syntax Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-serializers.md Illustrates the basic syntax for declaring directed and undirected graphs in the DOT language. ```dot strict digraph { # For directed graphs // vertices and edges } strict graph { # For undirected graphs // vertices and edges } ``` -------------------------------- ### Get Connected Components of a Graph Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns a list of connected components, treating all edges as undirected. Each component is a list of vertices. ```elixir def components(g :: Graph.t()) :: [[vertex()]] Returns a list of connected components, where each component is a list of vertices. Treats all edges as undirected. Example: g = Graph.new() |> Graph.add_edges([{:a, :b}, {:c, :d}]) Graph.components(g) # => [[:a, :b], [:c, :d]] ``` -------------------------------- ### Create Graphs Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/quick-reference.md Use `Graph.new/1` to create new graphs. Specify `:undirected` for undirected graphs or provide a `vertex_identifier` function for custom vertex types. ```elixir # Directed graph (default) g = Graph.new() # Undirected graph g = Graph.new(type: :undirected) # Custom vertex identifiers g = Graph.new(vertex_identifier: &String.to_atom/1) ``` -------------------------------- ### Create a New Graph Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Initializes a new graph. Supports specifying the graph type (directed or undirected) and a custom function for vertex identification. ```elixir def new(opts \ []) :: Graph.t() ``` ```elixir # Directed graph (default) g = Graph.new() # Undirected graph g = Graph.new(type: :undirected) # Custom vertex identifier function g = Graph.new(vertex_identifier: fn v -> :erlang.phash2(v) end) ``` -------------------------------- ### Get Single Edge Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns a single edge between two vertices, or nil if no such edge exists. Supports retrieving labelled edges. ```Elixir def edge(g :: Graph.t(), v1 :: vertex(), v2 :: vertex()) :: Graph.Edge.t() | nil def edge(g :: Graph.t(), v1 :: vertex(), v2 :: vertex(), label :: term()) :: Graph.Edge.t() | nil ``` ```Elixir g = Graph.new() |> Graph.add_edges([{:a, :b}, {:a, :b, label: :foo}]) Graph.edge(g, :a, :b) # => %Graph.Edge{v1: :a, v2: :b} Graph.edge(g, :a, :b, :foo) # => %Graph.Edge{v1: :a, v2: :b, label: :foo} Graph.edge(g, :b, :a) # => nil (directed graph) ``` -------------------------------- ### Convert DOT to PNG Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-serializers.md Use the `dot` command with the `-Tpng` flag to convert a DOT file to a PNG image. This is useful for web display and general-purpose graphics. ```bash dot -Tpng graph.dot > graph.png ``` -------------------------------- ### Graph.get_paths/3 Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns all paths from source to target using depth-first search. ```APIDOC ## Graph.get_paths/3 ### Description Returns all paths from source to target using depth-first search. ### Method Signature ```elixir def get_paths(g :: Graph.t(), source :: vertex(), target :: vertex()) :: [[vertex()]] ``` ### Parameters - **g** (`Graph.t()`): The graph. - **source** (`vertex()`): The starting vertex. - **target** (`vertex()`): The target vertex. ### Returns - `[[vertex()]]`: A list of all paths from source to target. ### Example ```elixir g = Graph.new() |> Graph.add_edges([{:a, :b}, {:b, :c}, {:c, :d}, {:b, :d}, {:c, :a}]) Graph.get_paths(g, :a, :d) # => [[:a, :b, :c, :d], [:a, :b, :d]] ``` ``` -------------------------------- ### Create a new undirected graph Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/configuration.md Use `Graph.new/1` with `type: :undirected` to create an undirected graph. ```elixir g = Graph.new(type: :undirected) ``` -------------------------------- ### Remove and Get Lowest Priority Element Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-priority-queue.md Extracts the element with the smallest priority value from the queue. Returns {:empty, pq} if the queue is empty. ```elixir pq = PriorityQueue.new() |> PriorityQueue.push(:foo, 1) |> PriorityQueue.push(:bar, 2) {{:value, :foo}, pq} = PriorityQueue.pop(pq) {{:value, :bar}, pq} = PriorityQueue.pop(pq) {:empty, pq} = PriorityQueue.pop(pq) ``` -------------------------------- ### Get Number of Edges Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns the total count of distinct edges in the graph. Edges between the same pair of vertices are counted as one, regardless of labels or weights. ```elixir def num_edges(g :: Graph.t()) :: non_neg_integer() ``` ```elixir g = Graph.new() |> Graph.add_edges([{:a, :b}, {:b, :c}, {:a, :a}]) Graph.num_edges(g) # => 3 ``` -------------------------------- ### Pathfinding Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/README.md Functions for performing pathfinding algorithms on the graph, including Dijkstra's, A*, Bellman-Ford, and finding shortest paths. ```APIDOC ## Pathfinding ### Description Functions for performing pathfinding algorithms on the graph, including Dijkstra's, A*, Bellman-Ford, and finding shortest paths. ### Functions - `dijkstra/3`: Computes shortest paths using Dijkstra's algorithm. - `get_shortest_path/3`: Retrieves the shortest path between two vertices. - `a_star/4`: Computes shortest paths using the A* algorithm. - `bellman_ford/2`: Computes shortest paths using the Bellman-Ford algorithm. - `get_paths/3`: Retrieves all paths between two vertices. ``` -------------------------------- ### Get Graph Information Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Retrieves a map containing summary statistics of the graph, such as its type, number of vertices, number of edges, and estimated memory usage. ```elixir def info(g :: Graph.t()) :: Graph.graph_info() ``` ```elixir g = Graph.new() |> Graph.add_vertices([:a, :b, :c, :d]) |> Graph.add_edges([{:a, :b}, {:b, :c}]) Graph.info(g) # => %{type: :directed, num_vertices: 4, num_edges: 2, size_in_bytes: ...} ``` -------------------------------- ### Edge Operations in Libgraph Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/quick-reference.md Illustrates how to delete unlabelled, labelled, and multiple edges. Also shows how to update edge weights or labels, and how to split an edge by inserting a new vertex. ```elixir # Delete unlabelled edge g = Graph.delete_edge(g, :a, :b) # Delete labelled edge g = Graph.delete_edge(g, :a, :b, :label) # Delete multiple g = Graph.delete_edges(g, [{:a, :b}, {:b, :c}]) g = Graph.delete_edges(g, :a, :b) # all between two vertices # Update weight/label g = Graph.update_edge(g, :a, :b, weight: 5) g = Graph.update_labelled_edge(g, :a, :b, :old_label, weight: 5, label: :new) # Split edge (insert vertex) g = Graph.split_edge(g, :a, :c, :b) # turns :a->:c into :a->:b->:c ``` -------------------------------- ### Graph.topsort/1 Cyclic Graph Handling Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/errors.md Use Graph.topsort/1 to get a topological sort of a directed acyclic graph. It returns false if the graph contains a cycle. ```elixir g = Graph.new() |> Graph.add_edges([{:a, :b}, {:b, :c}]) [:a, :b, :c] = Graph.topsort(g) g = Graph.new() |> Graph.add_edges([{:a, :b}, {:b, :a}]) false = Graph.topsort(g) ``` -------------------------------- ### Graph.batch_topsort/1 Cyclic Graph Handling Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/errors.md Graph.batch_topsort/1 is similar to Graph.topsort/1 and returns false when the graph contains a cycle. ```elixir # This function is not shown with an example in the source. ``` -------------------------------- ### Convert DOT to PDF Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-serializers.md Generate a PDF file from a DOT source using `dot -Tpdf`. This is ideal for print or high-resolution documents. ```bash dot -Tpdf graph.dot > graph.pdf ``` -------------------------------- ### Get K-Core Subgraph Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns a subgraph containing all vertices with a coreness greater than or equal to k. A k-core is a maximal subgraph where each vertex has at least k neighbors. ```elixir g = Graph.new() |> Graph.add_edges([{:a, :b}, {:b, :c}, {:c, :a}, {:d, :a}]) Graph.k_core(g, 2) # vertices with degree >= 2 ``` -------------------------------- ### Handle Negative Cycles with Bellman-Ford Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/quick-reference.md Demonstrates how to detect negative cycles using the Bellman-Ford algorithm. The function returns nil if a negative cycle is detected, allowing for specific error handling. ```elixir # Bellman-Ford returns nil on negative cycle case Graph.bellman_ford(g, :a) do nil -> IO.puts("Negative cycle detected") distances -> IO.inspect(distances) end ``` -------------------------------- ### DOT Undirected Edge Syntax Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-serializers.md Illustrates the syntax for creating undirected edges between vertices in DOT, including options for weight and labels. ```dot v1 -- v2 [weight=1] # simple edge v1 -- v2 [weight=2; label="optional"] # with label ``` -------------------------------- ### Get Vertices Reaching Given Vertices Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns all vertices that can reach any of the given vertices, including the target vertices. This is useful for reverse graph traversal or dependency analysis. ```elixir def reaching(g :: Graph.t(), vertices :: [vertex()]) :: [vertex()] Returns all vertices that can reach any of the given vertices, including the target vertices. Example: g = Graph.new() |> Graph.add_edges([{:a, :b}, {:b, :c}, {:c, :d}]) Graph.reaching(g, [:d]) # => [:a, :b, :c, :d] ``` -------------------------------- ### libgraph Module Structure Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/README.md This snippet outlines the module structure of the libgraph library, showing the main modules and their sub-modules for graph operations, pathfinding, traversal, and serialization, as well as the PriorityQueue structure. ```elixir Graph # Main module - graph creation and operations ├── Graph.Edge # Edge struct and creation ├── Graph.Directed # Internal - directed graph algorithms ├── Graph.Pathfinding # Pathfinding algorithms │ └── Graph.Pathfindings.BellmanFord ├── Graph.Reducer # Behavior for graph traversal │ ├── Graph.Reducers.Bfs # Breadth-first search │ └── Graph.Reducers.Dfs # Depth-first search └── Graph.Serializer # Behavior for serialization ├── Graph.Serializers.DOT # Graphviz format ├── Graph.Serializers.Edgelist # Edge list format └── Graph.Serializers.Flowchart # Flowchart format PriorityQueue # Priority queue data structure ├── PriorityQueue.new/0 ├── PriorityQueue.push/3 ├── PriorityQueue.pop/1 └── PriorityQueue.peek/1 ``` -------------------------------- ### Graph Creation & Configuration Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/README.md Functions for creating new graphs and configuring their properties. Supports directed and undirected graph types, and custom vertex identifiers. ```APIDOC ## Graph Creation & Configuration ### Description Functions for creating new graphs and configuring their properties. Supports directed and undirected graph types, and custom vertex identifiers. ### Functions - `Graph.new/1`: Creates a new graph. - `Graph.new/2`: Creates a new graph with specified options. ### Options - `type`: `:directed` or `:undirected`. - `vertex_identifier`: Specifies the type of identifier for vertices. ``` -------------------------------- ### Graph.preorder/1 Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns all vertices ordered by depth-first preorder traversal. ```APIDOC ## Graph.preorder/1 ### Description Returns all vertices ordered by depth-first preorder traversal. ### Signature ```elixir def preorder(g :: Graph.t()) :: [vertex()] ``` ### Example ```elixir g = Graph.new() |> Graph.add_edges([{:a, :b}, {:b, :c}, {:b, :d}, {:c, :e}]) Graph.preorder(g) # => [:a, :b, :c, :e, :d] ``` ``` -------------------------------- ### Get Reaching Neighbors of Given Vertices Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-graph.md Returns vertices that can reach any of the given vertices, excluding the target vertices themselves. This function is useful for finding predecessors without including the target nodes. ```elixir def reaching_neighbors(g :: Graph.t(), vertices :: [vertex()]) :: [vertex()] Returns vertices that can reach any of the given vertices, excluding the target vertices themselves. ``` -------------------------------- ### Convert DOT to PostScript Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/api-serializers.md Generate a PostScript file from a DOT source using `dot -Tps`. This format is often used in publishing workflows. ```bash dot -Tps graph.dot > graph.ps ``` -------------------------------- ### Querying Edges Source: https://github.com/bitwalker/libgraph/blob/main/_autodocs/quick-reference.md Functions for retrieving edges from the graph. You can fetch all edges, edges connected to a specific vertex, or edges between two vertices. It also includes functions to get a single edge or the total number of edges. ```APIDOC ## Querying Edges ### Description Functions for retrieving edges from the graph. You can fetch all edges, edges connected to a specific vertex, or edges between two vertices. It also includes functions to get a single edge or the total number of edges. ### Functions - `Graph.edges(g)`: Returns all edges in the graph. - `Graph.edges(g, vertex)`: Returns all edges connected to the specified vertex. - `Graph.edges(g, vertex1, vertex2)`: Returns all edges between `vertex1` and `vertex2`. - `Graph.edge(g, vertex1, vertex2)`: Returns the unlabelled edge between `vertex1` and `vertex2`. - `Graph.edge(g, vertex1, vertex2, label)`: Returns the labelled edge between `vertex1` and `vertex2`. - `Graph.num_edges(g)`: Returns the total number of edges in the graph. ```