Definition weight_typenv (e: typenv) : nat := length e.(te_equ).Definition typassign := positive -> T.t.

(* Specifications: *)
Lemma satisf_initial: forall te, satisf te initial.
Lemma set_incr: forall te x ty e e', set e x ty = OK e' -> satisf te e' -> satisf te e.
Lemma set_sound: forall te x ty e e', set e x ty = OK e' -> satisf te e' -> te x = ty.
Lemma set_list_incr: forall te xl tyl e e', set_list e xl tyl = OK e' -> satisf te e' -> satisf te e.
Lemma set_list_sound: forall te xl tyl e e', set_list e xl tyl = OK e' -> satisf te e' -> map te xl = tyl.
Lemma move_incr: forall te e r1 r2 e' changed, move e r1 r2 = OK(changed, e') -> satisf te e' -> satisf te e.
Lemma move_sound: forall te e r1 r2 e' changed, move e r1 r2 = OK(changed, e') -> satisf te e' -> te r1 = te r2.
Lemma solve_rec_incr: forall te q e changed e' changed', solve_rec e changed q = OK(e', changed') -> satisf te e' -> satisf te e.
Lemma solve_rec_sound: forall te r1 r2 q e changed e' changed', solve_rec e changed q = OK(e', changed') -> In (r1, r2) q -> satisf te e' -> te r1 = te r2.
Lemma move_false: forall e r1 r2 e', move e r1 r2 = OK(false, e') -> te_typ e' = te_typ e /\ makeassign e r1 = makeassign e r2.
Lemma solve_rec_false: forall r1 r2 q e changed e', solve_rec e changed q = OK(e', false) -> changed = false /\ (In (r1, r2) q -> makeassign e r1 = makeassign e r2).
Lemma solve_constraints_incr: forall te e e', solve_constraints e = OK e' -> satisf te e' -> satisf te e.
Lemma solve_constraints_sound: forall e e', solve_constraints e = OK e' -> satisf (makeassign e') e'.
Theorem solve_sound: forall e te, solve e = OK te -> satisf te e.
Lemma set_complete: forall te e x ty, satisf te e -> te x = ty -> exists e', set e x ty = OK e' /\ satisf te e'.
Lemma set_list_complete: forall te xl tyl e, satisf te e -> map te xl = tyl -> exists e', set_list e xl tyl = OK e' /\ satisf te e'.
Lemma move_complete: forall te e r1 r2, satisf te e -> te r1 = te r2 -> exists changed e', move e r1 r2 = OK(changed, e') /\ satisf te e'.
Lemma solve_rec_complete: forall te q e changed, satisf te e -> (forall r1 r2, In (r1, r2) q -> te r1 = te r2) -> exists e' changed', solve_rec e changed q = OK(e', changed') /\ satisf te e'.
Lemma solve_constraints_complete: forall te e, satisf te e -> exists e', solve_constraints e = OK e' /\ satisf te e'.
Lemma solve_complete: forall te e, satisf te e -> exists te', solve e = OK te'.
Lemma satisf_initial: forall te, satisf te initial.
Lemma set_incr: forall te x ty e e', set e x ty = OK e' -> satisf te e' -> satisf te e.
Lemma set_sound: forall te x ty e e', set e x ty = OK e' -> satisf te e' -> te x = ty.
Lemma set_list_incr: forall te xl tyl e e', set_list e xl tyl = OK e' -> satisf te e' -> satisf te e.
Lemma set_list_sound: forall te xl tyl e e', set_list e xl tyl = OK e' -> satisf te e' -> map te xl = tyl.
Lemma move_incr: forall te e r1 r2 e' changed, move e r1 r2 = OK(changed, e') -> satisf te e' -> satisf te e.
Lemma move_sound: forall te e r1 r2 e' changed, move e r1 r2 = OK(changed, e') -> satisf te e' -> te r1 = te r2.
Lemma solve_rec_incr: forall te q e changed e' changed', solve_rec e changed q = OK(e', changed') -> satisf te e' -> satisf te e.
Lemma solve_rec_sound: forall te r1 r2 q e changed e' changed', solve_rec e changed q = OK(e', changed') -> In (r1, r2) q -> satisf te e' -> te r1 = te r2.
Lemma move_false: forall e r1 r2 e', move e r1 r2 = OK(false, e') -> te_typ e' = te_typ e /\ makeassign e r1 = makeassign e r2.
Lemma solve_rec_false: forall r1 r2 q e changed e', solve_rec e changed q = OK(e', false) -> changed = false /\ (In (r1, r2) q -> makeassign e r1 = makeassign e r2).
Lemma solve_constraints_incr: forall te e e', solve_constraints e = OK e' -> satisf te e' -> satisf te e.
Lemma solve_constraints_sound: forall e e', solve_constraints e = OK e' -> satisf (makeassign e') e'.
Theorem solve_sound: forall e te, solve e = OK te -> satisf te e.
Lemma set_complete: forall te e x ty, satisf te e -> te x = ty -> exists e', set e x ty = OK e' /\ satisf te e'.
Lemma set_list_complete: forall te xl tyl e, satisf te e -> map te xl = tyl -> exists e', set_list e xl tyl = OK e' /\ satisf te e'.
Lemma move_complete: forall te e r1 r2, satisf te e -> te r1 = te r2 -> exists changed e', move e r1 r2 = OK(changed, e') /\ satisf te e'.
Lemma solve_rec_complete: forall te q e changed, satisf te e -> (forall r1 r2, In (r1, r2) q -> te r1 = te r2) -> exists e' changed', solve_rec e changed q = OK(e', changed') /\ satisf te e'.
Lemma solve_constraints_complete: forall te e, satisf te e -> exists e', solve_constraints e = OK e' /\ satisf te e'.
Lemma solve_complete: forall te e, satisf te e -> exists te', solve e = OK te'.