-
Notifications
You must be signed in to change notification settings - Fork 7
/
graph_coloring.ex
68 lines (50 loc) · 1.73 KB
/
graph_coloring.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
defmodule GraphColoring do
@moduledoc false
require Logger
import MinizincUtils
## Example: Graph Coloring
@gc_model resource_file("mzn/graph_coloring.mzn")
def optimal_coloring(data, opts \\ [])
def optimal_coloring(dzn_file, opts) when is_binary(dzn_file) do
solve_sync(dzn_file, opts)
end
def optimal_coloring({vertices, edges}, opts) when is_integer(vertices) and is_list(edges) do
solve_sync(
%{edges: edges, n: vertices, n_edges: length(edges)},
opts
)
end
defp solve_sync(data, opts) do
{:ok, res} = MinizincSolver.solve_sync(@gc_model, data, Keyword.put_new(opts, :solution_handler, GraphColoring.Handler))
res
end
def show_results(gc_results) do
last_solution = MinizincResults.get_last_solution(gc_results)
color_classes = MinizincResults.get_solution_value(last_solution, "vertex_sets")
Logger.info "Best coloring found: #{MinizincResults.get_solution_objective(last_solution)} colors"
solution_status = gc_results[:summary][:status]
Logger.info "Optimal? #{if solution_status == :optimal, do: "Yes", else: "No"}"
Enum.each(
Enum.with_index(
## Model-specific: there are empty color classes, which will be dropped
Enum.filter(color_classes, fn c -> MapSet.size(c) > 0 end)
),
fn {class, idx} ->
Logger.info "Color #{idx + 1} -> vertices: #{Enum.join(class, ", ")}"
end
)
end
def do_coloring(data, opts \\ []) do
optimal_coloring(data, opts)
|> show_results
end
end
defmodule GraphColoring.Handler do
@moduledoc false
require Logger
use MinizincHandler
def handle_solution(solution) do
Logger.info "Found #{MinizincResults.get_solution_objective(solution)}-coloring"
:skip
end
end