Local Open Scope positive_scope.
(** * Properties of coloring maps *)
(** ** Definition of a set of colors *)
Definition colors := S.t.
(** ** A coloring is complete if every vertex is colored *)
Definition coloring_complete (palette: colors) (g: graph) (f: coloring) :=
(forall i, M.In i g -> M.In i f) /\ coloring_ok palette g f.
Example ex_graph :=
mk_graph [ (6,4); (4,5); (4,3); (3,2); (5,2); (1,2); (1,5) ]%positive.
Definition two_colors: colors := SP.of_list [1; 2]%positive.
Definition three_colors: colors := SP.of_list [1; 2; 3]%positive.
Local Open Scope positive_scope.
(* Example of 3-coloring the example graph and proof with ok_coloring *)
Example ex_coloring :=
fold_right (fun p m => M.add (fst p) (snd p) m) (@M.empty _) [(6,1);(3,1);(5,1);(4,2);(2,2);(1,3)].
(* Proving that an explicit graph coloring is a valid coloring *)
Example ex_coloring_good : coloring_ok three_colors ex_graph ex_coloring.
(** ** Definition of $n$-coloring *)
Definition n_coloring (f : coloring) (p : colors) (n : nat) :=
S.cardinal p = n /\ forall v c, M.find v f = Some c -> S.In c p.
(** ** Definition of 3-coloring *)
Definition three_coloring (f : coloring) p := n_coloring f p 3.
(** ** Definition of 2-coloring *)
Definition two_coloring (f : coloring) p := n_coloring f p 2.
(** ** $(n+1)$-coloring not using a color is $n$-coloring *)
(** Let: - [f] be a coloring - [p] be palette of colors of size [n] - [c] be a color in [p]  Assume that [f] is a $(n+1)$-coloring wrt. [p], [c] is in [p], and [c] is unused by [f]. Then [f] is a $n$-coloring wrt. [c\{p}]. *)
(** ** Restriction to 3-coloring to 2-coloring *)
(** ** Restricting a coloring on the neighborhood of a node *)
Definition restrict_on_nbd (f : coloring) (g : graph) (v : node) :=
restrict f (nodes (neighborhood g v)).
(** * Constant coloring of a vertex set [s] with [c] *)
Definition constant_color {A} (s : nodeset) c := S.fold (fun v => M.add v c) s (@M.empty A).
(** * 2-color step *)
(** Let [g] be a graph, [v] be a vertex, $c_1$ and $c_2$ the colors we have that this function colors [v] with $c_1$ and colors its neighbors with $c_2$. *)
Definition two_color_step (g : graph) (v : node) c1 c2 (f : coloring) : coloring :=
M.add v c1 (constant_color (adj g v) c2).
(** ** Constant coloring on max degree vertices is complete *)
(** ** Union of two valid disjoint colorings is valid *)
(** Proof that the union of two disjoint and OK colorings is an OK coloring.  The palettes have to be disjoint *)
(** * Phase 2 of Wigderson *)
Function phase2 (g : graph) {measure M.cardinal g} : coloring * graph :=
match (max_deg g)%nat with
| 0%nat => (constant_color (nodes g) 1, (@M.empty _))
| S n => let (ns, g') := extract_vertices_degs g (S n) in
let (f', g'') := phase2 g' in
(Munion (constant_color ns (Pos.of_nat (S (S n)))) f', g'')
end.
(* Next steps: - how can we know a-priori what colors are used in phase2? - prove that the coloring returned by phase2 is ok - actually we're trying to prove that phase2 uses _at most_ max_deg + 1 colors - the coloring_ok predicate can overapproximate *)
Definition siota p := SP.of_list (map Pos.of_nat (seq 1 (p + 1))).
Definition phase2_colors g := siota (max_deg g).

(* if we have an independent set, we can augment any valid coloring with it to obtain another valid coloring *)
Lemma indep_set_union : forall (g : graph) (f : coloring) (s : nodeset) (p : colors) c,
undirected g ->
independent_set g s ->
~ S.In c p ->
coloring_ok p g f ->
coloring_ok (S.add c p) g (Munion (constant_color s c) f).