Zog.Transform (Zog v0.3.0)

View Source

High-performance graph transformations for Zog.

Summary

Functions

Contracts two nodes in a graph into a single node.

Extracts the ego graph around center from a Zog.SoA builder.

Extracts an induced subgraph from a Zog.SoA builder containing only the specified node labels and all edges that exist between them in the original graph.

Computes the transitive closure of a directed graph.

Computes the transitive reduction of a directed acyclic graph (DAG).

Functions

contract(builder, label1, label2, opts \\ [])

@spec contract(Zog.SoA.t(), Zog.SoA.label(), Zog.SoA.label(), keyword()) ::
  Zog.SoA.t()

Contracts two nodes in a graph into a single node.

All edges incident to either node become incident to the merged node. Any resulting self-loops are removed. For undirected graphs, duplicate edges between the merged node and another node are deduplicated.

By default the merged node keeps label1. Pass as: label2 to keep the other label instead.

Raises ArgumentError if either node does not exist or if as is not one of the two labels.

Examples

iex> builder = Zog.undirected()
...> |> Zog.add_edge("A", "B", 1.0)
...> |> Zog.add_edge("B", "C", 2.0)
iex> contracted = Zog.Transform.contract(builder, "A", "B")
iex> Zog.node_count(contracted)
2

ego_graph(builder, center, radius \\ 1)

@spec ego_graph(Zog.SoA.t(), Zog.SoA.label(), non_neg_integer()) :: Zog.SoA.t()

Extracts the ego graph around center from a Zog.SoA builder.

The ego graph contains the center node, all nodes within radius hops, and all edges that exist between those nodes in the original graph. Edges are treated as undirected when expanding the neighbourhood, so both incoming and outgoing neighbours are included for directed graphs.

center must be a label present in the original graph.

Examples

iex> builder = Zog.directed()
...> |> Zog.add_edge("A", "B", 1.0)
...> |> Zog.add_edge("B", "C", 2.0)
iex> ego = Zog.Transform.ego_graph(builder, "B")
iex> Zog.node_count(ego)
3
iex> Zog.all_labels(ego) |> Enum.sort()
["A", "B", "C"]

subgraph(builder, node_labels)

@spec subgraph(Zog.SoA.t(), [Zog.SoA.label()] | MapSet.t(Zog.SoA.label())) ::
  Zog.SoA.t()

Extracts an induced subgraph from a Zog.SoA builder containing only the specified node labels and all edges that exist between them in the original graph.

node_labels may be a list or a MapSet. Labels not present in the original graph are silently ignored.

Examples

iex> builder = Zog.directed()
...> |> Zog.add_edge("A", "B", 1.5)
...> |> Zog.add_edge("B", "C", 2.5)
...> |> Zog.add_edge("C", "A", 3.5)
iex> sub = Zog.Transform.subgraph(builder, ["A", "B"])
iex> Zog.node_count(sub)
2
iex> Zog.edge_count(sub)
1
iex> Zog.all_labels(sub)
["A", "B"]

transitive_closure(builder)

@spec transitive_closure(Zog.SoA.t()) :: Zog.SoA.t()

Computes the transitive closure of a directed graph.

Returns a new directed SoA builder that contains an edge (u, v) with weight 1.0 for every node v reachable from node u in the original graph, including u itself (reflexive closure).

Raises ArgumentError if the input graph is undirected.

Examples

iex> builder = Zog.directed()
...> |> Zog.add_edge("A", "B", 1.0)
...> |> Zog.add_edge("B", "C", 1.0)
iex> closure = Zog.Transform.transitive_closure(builder)
iex> Zog.edge_count(closure)
6

transitive_reduction(builder)

@spec transitive_reduction(Zog.SoA.t()) :: Zog.SoA.t()

Computes the transitive reduction of a directed acyclic graph (DAG).

Returns a new directed SoA builder containing the minimal set of edges that preserves the same reachability as the original graph. Raises ArgumentError if the graph is undirected or contains cycles.

Examples

iex> builder = Zog.directed()
...> |> Zog.add_edge("A", "B", 1.0)
...> |> Zog.add_edge("B", "C", 1.0)
...> |> Zog.add_edge("A", "C", 1.0)
iex> reduction = Zog.Transform.transitive_reduction(builder)
iex> Zog.edge_count(reduction)
2