defmodule CPSolver.Examples.GraphColoring do alias CPSolver.Constraint.NotEqual alias CPSolver.IntVariable alias CPSolver.Model def solve(instance, solver_opts \\ []) def solve(instance, solver_opts) when is_binary(instance) do instance |> model() |> solve(solver_opts) end def solve(data, solver_opts) do {:ok, _solver} = CPSolver.solve_async(model(data), solver_opts) |> tap(fn _ -> Process.sleep(100) end) end def model(data) when is_binary(data) do parse_instance(data) |> model() end def model(data) when is_map(data) do color_vars = Enum.map(1..data.vertices, fn _idx -> IntVariable.new(1..data.max_color) end) edge_color_constraints = Enum.map(data.edges, fn [v1, v2] -> NotEqual.new(Enum.at(color_vars, v1), Enum.at(color_vars, v2)) end) Model.new(color_vars, edge_color_constraints) end defp parse_instance(instance) do [header | edge_lines] = File.read!(instance) |> String.split("\n", trim: true) [v, _e, max_color] = header |> String.split(" ", trim: true) |> Enum.map(&String.to_integer/1) edges = Enum.map(edge_lines, fn e -> String.split(e, " ") |> Enum.map(&String.to_integer/1) end) %{vertices: v, edges: edges, max_color: max_color} end def check_solution(colors, instance) when is_list(colors) do graph = parse_instance(instance) Enum.all?(graph.edges, fn [v1, v2] -> Enum.at(colors, v1) != Enum.at(colors, v2) end) end end