Current section

Files

Jump to
bitgraph test algorithms algorithms_test.exs
Raw

test/algorithms/algorithms_test.exs

defmodule BitGraphTest.Algorithms do
use ExUnit.Case
alias BitGraph.Common
alias BitGraph.Algorithms
alias BitGraph.V
test "Topsort for DAG" do
edges = [
{"2", "1"},
{"2", "0"},
{"2", "3"},
{"3", "0"},
{"3", "4"},
{"1", "5"},
{"4", "5"},
{"0", "5"}
]
graph =
BitGraph.new() |> BitGraph.add_edges(
edges
)
topsort_result =
graph
|> Algorithms.topsort()
|> then(fn indices -> Common.vertex_indices_to_ids(graph, indices) end)
assert Enum.all?(edges,
fn {from, to} ->
Enum.find_index(topsort_result, fn val -> val == from end)
< Enum.find_index(topsort_result, fn val -> val == to end)
end)
end
test "Topsort and acyclicity for graphs with/without cycles" do
cycle = BitGraph.new() |> BitGraph.add_edges([{:a, :b}, {:c, :a}, {:b, :c}])
refute Algorithms.acyclic?(cycle)
refute Algorithms.topsort(cycle)
bull = BitGraph.add_edges(cycle, [{:a, :e}, {:f, :b}])
refute Algorithms.acyclic?(bull)
refute Algorithms.topsort(bull)
star = BitGraph.delete_edge(bull, :b, :c)
assert Algorithms.acyclic?(star)
assert Algorithms.topsort(star)
end
test "acyclic?" do
graph1 = BitGraph.new() |> BitGraph.add_edges([{:a, :b}, {:a, :c}, {:b, :c}])
assert Algorithms.acyclic?(graph1)
graph2 = BitGraph.new() |> BitGraph.add_edges([{:a, :b}, {:c, :a}, {:b, :c}])
refute Algorithms.acyclic?(graph2)
graph3 = BitGraph.new() |> BitGraph.add_edges(
[
{"2", "1"},
{"2", "0"},
{"2", "3"},
{"3", "0"},
{"3", "4"},
{"1", "5"},
{"4", "5"},
{"0", "5"}
]
)
assert Algorithms.acyclic?(graph3)
end
test "get_cycle" do
## Acyclic graph
graph1 = BitGraph.new() |> BitGraph.add_edges([{:a, :b}, {:a, :c}, {:b, :c}])
refute Enum.any?(BitGraph.vertex_indices(graph1),
fn v_idx -> Algorithms.get_cycle(graph1, v_idx) end)
## Cyclic triangle
graph2 = BitGraph.new() |> BitGraph.add_edges([{:a, :b}, {:c, :a}, {:b, :c}])
## For every starting vertex, there is a cycle of length 3
assert Enum.all?(BitGraph.vertex_indices(graph2),
fn v_idx ->
Algorithms.get_cycle(graph2, v_idx)
|> MapSet.new() |> MapSet.size() == 3
end)
## Bigger graph
edges = [
{:a, :b},
{:b, :c}, {:b, :e}, {:b, :f},
{:c, :d}, {:c, :g},
{:d, :c}, {:d, :h},
{:e, :a}, {:e, :f},
{:f, :g},
{:g, :f}, {:i, :f},
{:h, :d}, {:h, :g}
]
wiki_graph = BitGraph.new() |> BitGraph.add_edges(edges)
## No cycle for edge with a single neighbor
refute Algorithms.get_cycle(wiki_graph, V.get_vertex_index(wiki_graph, :i))
assert Enum.all?([:a, :b, :c, :d, :e, :f, :g],
fn v ->
v_idx = V.get_vertex_index(wiki_graph, v)
Common.cycle?(
wiki_graph,
Algorithms.get_cycle(wiki_graph, v_idx)
)
end)
end
test "components" do
edges = [
{:a, :b}, {:a, :c}, {:b, :c}, # component 1
{:d, :e}, {:d, :f}, {:e, :f}, # component 2
]
graph = BitGraph.new() |> BitGraph.add_edges(edges)
components = Algorithms.components(graph)
assert length(components) == 2
assert Enum.sort([MapSet.new([1, 2, 3]), MapSet.new([4, 5, 6])]) ==
Enum.sort(components)
single_component = BitGraph.add_edge(graph, :c, :f)
assert length(Algorithms.components(single_component)) == 1
end
end