defmodule CPSolver.Utils.Digraph do def new(opts \\ []) do :digraph.new(opts) end def add_edge(dg, v1, v2) do :digraph.add_edge(dg, v1, v2) dg end def add_edge(dg, v1, v2, label) do :digraph.add_edge(dg, v1, v2, label) dg end def add_edge(dg, e, v1, v2, label) do :digraph.add_edge(dg, e, v1, v2, label) dg end def add_vertex(dg, v) do :digraph.add_vertex(dg, v) dg end def add_vertex(dg, v, label) do :digraph.add_vertex(dg, v, label) dg end def delete_edge(dg, e) do :digraph.del_edge(dg, e) dg end def delete_edges(dg, edges) do :digraph.del_edges(dg, edges) dg end def delete_path(dg, v1, v2) do :digraph.del_path(dg, v1, v2) dg end def delete_vertex(dg, v) do :digraph.del_vertex(dg, v) dg end def delete_vertices(dg, vertices) do :digraph.del_vertices(dg, vertices) dg end def delete(dg) do :digraph.delete(dg) end def edge(dg, e) do :digraph.edge(dg, e) end def edges(dg) do :digraph.edges(dg) |> expand_edges(dg) end def edges(dg, v) do :digraph.edges(dg, v) |> expand_edges(dg) end def get_cycle(dg, v) do :digraph.get_cycle(dg, v) end def get_path(dg, v1, v2) do :digraph.get_path(dg, v1, v2) end def get_short_cycle(dg, v) do :digraph.get_short_cycle(dg, v) end def get_short_path(dg, v1, v2) do :digraph.get_short_path(dg, v1, v2) end def in_degree(dg, v) do :digraph.in_degree(dg, v) end def in_edges(dg, v) do :digraph.in_edges(dg, v) |> expand_edges(dg) end def in_neighbours(dg, v) do :digraph.in_neighbours(dg, v) end def no_edges(dg) do :digraph.no_edges(dg) end def no_vertices(dg) do :digraph.no_vertices(dg) end def out_degree(dg, v) do :digraph.out_degree(dg, v) end def out_edges(dg, v) do :digraph.out_edges(dg, v) |> expand_edges(dg) end def out_neighbours(dg, v) do :digraph.out_neighbours(dg, v) end def vertex(dg, v) do :digraph.vertex(dg, v) end def vertices(dg) do :digraph.vertices(dg) end def copy(graph) do dg = :digraph.new() Enum.each(:digraph.vertices(graph), fn vertex_id -> {_vertex_id, label} = vertex(graph, vertex_id) :digraph.add_vertex(dg, vertex_id, label) end) Enum.each(:digraph.edges(graph), fn edge -> {_e, v1, v2, label} = :digraph.edge(graph, edge) :digraph.add_edge(dg, v1, v2, label) end) dg end def from_libgraph(%Graph{} = graph) do dg = new() Enum.each(Graph.vertices(graph), fn vertex -> add_vertex(dg, vertex, Graph.vertex_labels(graph, vertex)) end) edges = Graph.edges(graph) Enum.each(edges, fn %Graph.Edge{v1: v1, v2: v2, label: label} -> add_edge(dg, v1, v2, label) end) dg end def to_libgraph(digraph) do g_vertices = Enum.reduce(vertices(digraph), Graph.new(), fn vertex, graph_acc -> {vertex_id, label} = vertex(digraph, vertex) Graph.add_vertex(graph_acc, vertex_id, label) end) Enum.reduce(edges(digraph), g_vertices, fn digraph_edge, graph_acc -> %Graph.Edge{v1: v1, v2: v2, label: label} = digraph_edge Graph.add_edge(graph_acc, v1, v2, label: label) end) end defp expand_edges(edges, digraph) do Enum.map(edges, fn e -> {_edge_id, v1, v2, labels} = edge(digraph, e) %Graph.Edge{v1: v1, v2: v2, label: labels, weight: 1} end) end end