Current section
Files
Jump to
Current section
Files
test/neighbor_finder_test.exs
defmodule BitGraphTest.NeighborFinder do
use ExUnit.Case
alias BitGraph.Algorithms.Matching.Kuhn
test "neighbor finder function" do
## Complete bipartite graph with left -> right edges
graph =
for left <- 1..3, right <- 1..3, reduce: BitGraph.new() do
acc ->
BitGraph.add_edge(acc, {:L, left}, {:R, right})
end
## All edges are oriented from left partition to right partition - the graph
## is not strongly connected
refute BitGraph.strongly_connected?(graph)
## The same graph with matching edges oriented from right to left partition
## will form the cycle
## We now buld the neighbor finder that intperprets
## edges in bipartite matching as oriented from right to left partition
neighbor_finder_fun = build_neighbor_finder(graph)
assert BitGraph.strongly_connected?(graph, neighbor_finder: neighbor_finder_fun)
end
defp build_neighbor_finder(graph) do
%{matching: left_to_right_matching} = Kuhn.run(graph, Enum.map(1..3, fn idx -> {:L, idx} end))
right_to_left_matching = Map.new(left_to_right_matching, fn {l, r} -> {r, l} end)
fn graph, vertex_index, direction ->
vertex = BitGraph.V.get_vertex(graph, vertex_index)
BitGraph.E.default_neighbor_finder().(graph, vertex_index, direction)
|> reverse_matching_edges(
graph,
vertex,
left_to_right_matching,
right_to_left_matching,
direction
)
end
end
defp reverse_matching_edges(
_neighbors,
graph,
{:L, _vertex_index} = left_vertex,
left_to_right_matching,
_right_to_left_matching,
:in
) do
case get_matching_index(graph, left_to_right_matching, left_vertex) do
nil ->
MapSet.new()
right_vertex ->
MapSet.new([right_vertex])
end
end
defp reverse_matching_edges(
neighbors,
graph,
{:L, _vertex_index} = left_vertex,
left_to_right_matching,
_right_to_left_matching,
:out
) do
MapSet.delete(neighbors, get_matching_index(graph, left_to_right_matching, left_vertex))
end
defp reverse_matching_edges(
neighbors,
graph,
{:R, _vertex_index} = right_vertex,
_left_to_right_matching,
right_to_left_matching,
:in
) do
MapSet.delete(neighbors, get_matching_index(graph, right_to_left_matching, right_vertex))
end
defp reverse_matching_edges(
_neighbors,
graph,
{:R, _vertex_index} = right_vertex,
_left_to_right_matching,
right_to_left_matching,
:out
) do
case get_matching_index(graph, right_to_left_matching, right_vertex) do
nil ->
MapSet.new()
left_vertex ->
MapSet.new([left_vertex])
end
end
defp get_matching_index(graph, matching, vertex) do
case Map.get(matching, vertex) do
nil ->
nil
matching_vertex ->
BitGraph.V.get_vertex_index(graph, matching_vertex)
end
end
end