InductiveGraph (InductiveGraph v0.1.0) View Source

Functions that work on graphs as an inductive data structure.

Link to this section Summary

Construction Functions

Builds a graph from contexts.

Creates an empty graph.

Inserts contexts into graph.

Inserts tagged_edge into graph.

Inserts tagged_edges into graph.

Inserts tagged_vertex into graph.

Inserts tagged_vertices into graph.

Creates a graph from lists tagged_vertices and tagged_edges.

Merges context into graph.

Destruction Functions

Decomposes graph into an arbitrary context and the remaining graph.

Decomposes graph into the context containing vertex and the remaining graph.

Deletes edge from graph.

Deletes edges from graph.

Deletes vertex from graph.

Deletes vertices from graph.

Update Functions

Filters edges based on edge values that fails predicate in graph.

Applies function to every edge value in graph.

Applies function to every context in graph.

Applies function to every vertex value in graph.

Applies vertex_function to every vertex value and edge_function to every edge value in graph.

Folds function over graph with starting value accumulator.

Inspection Functions

Counts number of edges in graph.

Counts number of vertices in graph.

Determines if graph is empty.

Checks if two graphs are equal.

Determines if edge is in graph.

Determines if vertex is in graph.

Lists all tagged edges in graph.

Lists all tagged vertices in graph.

Pretty prints inductive representation of graph.

Gets range of vertex values in graph.

Link to this section Types

Specs

adjacents() :: [{edge_value(), neighbor()}]

Specs

context() :: {predecessors(), vertex(), vertex_value(), successors()}

Specs

edge() :: {from_vertex :: vertex(), to_vertex :: vertex()}

Specs

edge_value() :: value()

Specs

neighbor() :: vertex()

Specs

predecessors() :: adjacents()

Specs

successors() :: adjacents()

Specs

t()

Specs

tagged_edge() :: {from_vertex :: vertex(), to_vertex :: vertex(), edge_value()}

Specs

tagged_vertex() :: {vertex(), vertex_value()}

Specs

value() :: term()

Specs

vertex() :: integer()

Specs

vertex_value() :: value()

Link to this section Construction Functions

Specs

build_graph([context()]) :: {:ok, t()} | :error

Builds a graph from contexts.

Examples

iex> contexts = [{[{"down", 2}], 3, "c", [{"up", 1}]}, {[{"right", 1}], 2, "b", [{"left", 1}]}, {[], 1, "a", []}]
iex> {:ok, graph1} = InductiveGraph.build_graph(contexts)
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> {:ok, graph2} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> InductiveGraph.equal?(graph1, graph2)
true

Specs

empty_graph() :: t()

Creates an empty graph.

Examples

iex> graph = InductiveGraph.empty_graph()
#InductiveGraph<>
iex> InductiveGraph.pretty_print(graph)
"| Empty"
Link to this function

insert_contexts(graph, contexts)

View Source

Specs

insert_contexts(t(), [context()]) :: {:ok, t()} | :error

Inserts contexts into graph.

Examples

iex> graph1 = InductiveGraph.empty_graph()
iex> contexts = [{[{"down", 2}], 3, "c", [{"up", 1}]}, {[{"right", 1}], 2, "b", [{"left", 1}]}, {[], 1, "a", []}]
iex> {:ok, graph2} = InductiveGraph.insert_contexts(graph1, contexts)
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> {:ok, graph3} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> InductiveGraph.equal?(graph2, graph3)
true
Link to this function

insert_tagged_edge(graph, tagged_edge)

View Source

Specs

insert_tagged_edge(t(), tagged_edge()) :: {:ok, t()} | :error

Inserts tagged_edge into graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}]
iex> new_tagged_edge = {3, 1, "up"}
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> {:ok, graph} = InductiveGraph.insert_tagged_edge(graph, new_tagged_edge)
iex> InductiveGraph.pretty_print(graph) <> "\n"
~s'''
| {[{"down", 2}], 3, "c", [{"up", 1}]}
& {[{"right", 1}], 2, "b", [{"left", 1}]}
& {[], 1, "a", []}
& Empty
'''
Link to this function

insert_tagged_edges(graph, tagged_edges)

View Source

Specs

insert_tagged_edges(t(), [tagged_edge()]) :: {:ok, t()} | :error

Inserts tagged_edges into graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}] iex> tagged_edges = [] iex> new_tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}] iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, tagged_edges) iex> {:ok, graph} = InductiveGraph.insert_tagged_edges(graph, new_tagged_edges) iex> InductiveGraph.pretty_print(graph) <> "\n" ~s''' | {[{"down", 2}], 3, "c", [{"up", 1}]} & {[{"right", 1}], 2, "b", [{"left", 1}]} & {[], 1, "a", []} & Empty '''

Link to this function

insert_tagged_vertex(graph, tagged_vertex)

View Source

Specs

insert_tagged_vertex(t(), tagged_vertex()) :: {:ok, t()} | :error

Inserts tagged_vertex into graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> new_tagged_vertex = {4, "d"}
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> {:ok, graph} = InductiveGraph.insert_tagged_vertex(graph, new_tagged_vertex)
iex> {:ok, context, _graph} = InductiveGraph.decompose(graph, 4)
iex> context
{[], 4, "d", []}
Link to this function

insert_tagged_vertices(graph, tagged_vertices)

View Source

Specs

insert_tagged_vertices(t(), [tagged_vertex()]) :: {:ok, t()} | :error

Inserts tagged_vertices into graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> new_tagged_vertices = [{4, "d"}, {5, "e"}]
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> {:ok, graph} = InductiveGraph.insert_tagged_vertices(graph, new_tagged_vertices)
iex> InductiveGraph.pretty_print(graph, 2) <> "\n"
~s'''
| {[], 5, "e", []}
& {[], 4, "d", []}
& InductiveGraph
'''
Link to this function

make_graph(tagged_vertices, tagged_edges)

View Source

Specs

make_graph([tagged_vertex()], [tagged_edge()]) :: {:ok, t()} | :error

Creates a graph from lists tagged_vertices and tagged_edges.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> graph |> InductiveGraph.list_tagged_vertices() |> Enum.sort()
[{1, "a"}, {2, "b"}, {3, "c"}]
iex> graph |> InductiveGraph.list_tagged_edges() |> Enum.sort()
[{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]

Specs

merge(t(), context()) :: {:ok, t()} | :error

Merges context into graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> {:ok, graph1} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> {:ok, context, graph2} = InductiveGraph.decompose(graph1, 3)
iex> {:ok, graph3} = InductiveGraph.merge(graph2, context)
iex> InductiveGraph.equal?(graph1, graph3)
true

Link to this section Destruction Functions

Specs

decompose(t()) :: {:ok, context(), t()} | :error

Decomposes graph into an arbitrary context and the remaining graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> InductiveGraph.count_vertices(graph)
3
iex> {:ok, _context, graph} = InductiveGraph.decompose(graph)
iex> InductiveGraph.count_vertices(graph)
2
Link to this function

decompose(graph, vertex)

View Source

Specs

decompose(t(), vertex()) :: {:ok, context(), t()} | :error

Decomposes graph into the context containing vertex and the remaining graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> {:ok, context1, graph} = InductiveGraph.decompose(graph, 3)
iex> context1
{[{"down", 2}], 3, "c", [{"up", 1}]}
iex> {:ok, context2, graph} = InductiveGraph.decompose(graph, 2)
iex> context2
{[{"right", 1}], 2, "b", [{"left", 1}]}
iex> {:ok, context3, graph} = InductiveGraph.decompose(graph, 1)
iex> context3
{[], 1, "a", []}
iex> InductiveGraph.empty?(graph)
true
Link to this function

delete_edge(graph, edge)

View Source

Specs

delete_edge(t(), edge()) :: {:ok, t()} | :error

Deletes edge from graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> edge = {1, 2}
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> {:ok, graph} = InductiveGraph.delete_edge(graph, edge)
iex> InductiveGraph.pretty_print(graph) <> "\n"
~s'''
| {[{"down", 2}], 3, "c", [{"up", 1}]}
& {[], 2, "b", [{"left", 1}]}
& {[], 1, "a", []}
& Empty
'''
Link to this function

delete_edges(graph, edges)

View Source

Specs

delete_edges(t(), [edge()]) :: {:ok, t()} | :error

Deletes edges from graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> edges = [{1, 2}, {2, 1}]
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> {:ok, graph} = InductiveGraph.delete_edges(graph, edges)
iex> InductiveGraph.pretty_print(graph) <> "\n"
~s'''
| {[{"down", 2}], 3, "c", [{"up", 1}]}
& {[], 2, "b", []}
& {[], 1, "a", []}
& Empty
'''
Link to this function

delete_vertex(graph, vertex)

View Source

Specs

delete_vertex(t(), vertex()) :: {:ok, t()} | :error

Deletes vertex from graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> {:ok, graph} = InductiveGraph.delete_vertex(graph, 3)
iex> InductiveGraph.has_vertex?(graph, 3)
false
Link to this function

delete_vertices(graph, vertices)

View Source

Specs

delete_vertices(t(), [vertex()]) :: {:ok, t()} | :error

Deletes vertices from graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> {:ok, graph} = InductiveGraph.delete_vertices(graph, [2, 3])
iex> InductiveGraph.has_vertex?(graph, 3)
false

Link to this section Update Functions

Link to this function

filter_edges(graph, predicate)

View Source

Specs

filter_edges(t(), (edge_value() -> boolean())) :: t()

Filters edges based on edge values that fails predicate in graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> predicate = fn edge_value -> String.length(edge_value) == 4 end
iex> graph = InductiveGraph.filter_edges(graph, predicate)
iex> InductiveGraph.pretty_print(graph) <> "\n"
~s'''
| {[{"down", 2}], 3, "c", []}
& {[], 2, "b", [{"left", 1}]}
& {[], 1, "a", []}
& Empty
'''
Link to this function

map_edges(graph, function)

View Source

Specs

map_edges(t(), (edge_value() -> edge_value())) :: t()

Applies function to every edge value in graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> function = &String.reverse(&1)
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> graph = InductiveGraph.map_edges(graph, function)
iex> {:ok, context, _graph} = InductiveGraph.decompose(graph, 3)
iex> context
{[{"nwod", 2}], 3, "c", [{"pu", 1}]}
Link to this function

map_graph(graph, function)

View Source

Specs

map_graph(t(), (context() -> context())) :: t()

Applies function to every context in graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> function = fn context = {_p, _v, value, _s} -> put_elem(context, 2, String.duplicate(value, 5)) end
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> graph = InductiveGraph.map_graph(graph, function)
iex> {:ok, context, _graph} = InductiveGraph.decompose(graph, 3)
iex> context
{[{"down", 2}], 3, "ccccc", [{"up", 1}]}
Link to this function

map_vertices(graph, function)

View Source

Specs

map_vertices(t(), (vertex_value() -> vertex_value())) :: t()

Applies function to every vertex value in graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> function = &String.duplicate(&1, 5)
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> graph = InductiveGraph.map_vertices(graph, function)
iex> {:ok, context, _graph} = InductiveGraph.decompose(graph, 3)
iex> context
{[{"down", 2}], 3, "ccccc", [{"up", 1}]}
Link to this function

map_vertices_and_edges(graph, vertex_function, edge_function)

View Source

Specs

map_vertices_and_edges(
  t(),
  (vertex_value() -> vertex_value()),
  (edge_value() -> edge_value())
) :: t()

Applies vertex_function to every vertex value and edge_function to every edge value in graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> vertex_function = &String.duplicate(&1, 5)
iex> edge_function = &String.reverse(&1)
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> graph = InductiveGraph.map_vertices_and_edges(graph, vertex_function, edge_function)
iex> {:ok, context, _graph} = InductiveGraph.decompose(graph, 3)
iex> context
{[{"nwod", 2}], 3, "ccccc", [{"pu", 1}]}
Link to this function

unordered_fold(graph, accumulator, function)

View Source

Specs

unordered_fold(t(), term(), (context(), term() -> term())) :: term()

Folds function over graph with starting value accumulator.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> function = fn {_p, vertex, _v, _s}, result -> vertex + result end
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> InductiveGraph.unordered_fold(graph, 0, function)
6

Link to this section Inspection Functions

Specs

count_edges(t()) :: non_neg_integer()

Counts number of edges in graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> graph |> InductiveGraph.count_edges()
4

Specs

count_vertices(t()) :: non_neg_integer()

Counts number of vertices in graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, [])
iex> InductiveGraph.count_vertices(graph)
3

Specs

empty?(t()) :: boolean()

Determines if graph is empty.

Examples

iex> graph = InductiveGraph.empty_graph()
iex> InductiveGraph.empty?(graph)
true
iex> {:ok, graph} = InductiveGraph.make_graph([{1, 1}], [])
iex> InductiveGraph.empty?(graph)
false

Specs

equal?(t(), t()) :: boolean()

Checks if two graphs are equal.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> {:ok, graph1} = InductiveGraph.make_graph(tagged_vertices, [])
iex> {:ok, graph2} = InductiveGraph.insert_tagged_edges(graph1, tagged_edges)
iex> {:ok, graph3} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> InductiveGraph.equal?(graph1, graph2)
false
iex> InductiveGraph.equal?(graph2, graph3)
true

Specs

has_edge?(t(), edge()) :: boolean()

Determines if edge is in graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> InductiveGraph.has_edge?(graph, {1, 2})
true
iex> InductiveGraph.has_edge?(graph, {1, 3})
false
Link to this function

has_vertex?(graph, vertex)

View Source

Specs

has_vertex?(t(), vertex()) :: boolean()

Determines if vertex is in graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> edges = []
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, edges)
iex> InductiveGraph.has_vertex?(graph, 3)
true
iex> InductiveGraph.has_vertex?(graph, 4)
false
Link to this function

list_tagged_edges(graph)

View Source

Specs

list_tagged_edges(t()) :: [tagged_edge()]

Lists all tagged edges in graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> graph |> InductiveGraph.list_tagged_edges() |> Enum.sort()
[{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
Link to this function

list_tagged_vertices(graph)

View Source

Specs

list_tagged_vertices(t()) :: [tagged_vertex()]

Lists all tagged vertices in graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, [])
iex> graph |> InductiveGraph.list_tagged_vertices() |> Enum.sort()
[{1, "a"}, {2, "b"}, {3, "c"}]
Link to this function

pretty_print(graph, count \\ -1)

View Source

Specs

pretty_print(t(), integer()) :: String.t()

Pretty prints inductive representation of graph.

If count is provided, then up to count number of contexts will be shown.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> tagged_edges = [{1, 2, "right"}, {2, 1, "left"}, {2, 3, "down"}, {3, 1, "up"}]
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, tagged_edges)
iex> InductiveGraph.pretty_print(graph) <> "\n"
~s'''
| {[{"down", 2}], 3, "c", [{"up", 1}]}
& {[{"right", 1}], 2, "b", [{"left", 1}]}
& {[], 1, "a", []}
& Empty
'''

Specs

vertex_range(t()) :: {:ok, mininum :: integer(), maximum :: integer()} | :error

Gets range of vertex values in graph.

Examples

iex> tagged_vertices = [{1, "a"}, {2, "b"}, {3, "c"}]
iex> {:ok, graph} = InductiveGraph.make_graph(tagged_vertices, [])
iex> InductiveGraph.vertex_range(graph)
{:ok, 1, 3}