Definition weight_typenv (e: typenv) : nat :=
  weight_constraints e.(te_typ) e.(te_sub).Definition typassign := positive -> T.t.

(* Specifications: *)
Lemma satisf_initial: forall te, satisf te initial.
Lemma type_def_incr: forall te x ty e e', type_def e x ty = OK e' -> satisf te e' -> satisf te e.
Lemma type_def_sound: forall te x ty e e', type_def e x ty = OK e' -> satisf te e' -> T.sub ty (te x).
Lemma type_defs_incr: forall te xl tyl e e', type_defs e xl tyl = OK e' -> satisf te e' -> satisf te e.
Lemma type_defs_sound: forall te xl tyl e e', type_defs e xl tyl = OK e' -> satisf te e' -> list_forall2 T.sub tyl (map te xl).
Lemma type_use_incr: forall te x ty e e', type_use e x ty = OK e' -> satisf te e' -> satisf te e.
Lemma type_use_sound: forall te x ty e e', type_use e x ty = OK e' -> satisf te e' -> T.sub (te x) ty.
Lemma type_uses_incr: forall te xl tyl e e', type_uses e xl tyl = OK e' -> satisf te e' -> satisf te e.
Lemma type_uses_sound: forall te xl tyl e e', type_uses e xl tyl = OK e' -> satisf te e' -> list_forall2 T.sub (map te xl) tyl.
Lemma type_move_incr: forall te e r1 r2 e' changed, type_move e r1 r2 = OK(changed, e') -> satisf te e' -> satisf te e.
Lemma type_move_sound: forall te e r1 r2 e' changed, type_move e r1 r2 = OK(changed, e') -> satisf te e' -> T.sub (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' -> T.sub (te r1) (te r2).
Lemma type_move_false: forall e r1 r2 e', type_move e r1 r2 = OK(false, e') -> te_typ e' = te_typ e /\ T.sub (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 -> T.sub (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 type_def_complete: forall te e x ty, satisf te e -> T.sub ty (te x) -> exists e', type_def e x ty = OK e' /\ satisf te e'.
Lemma type_defs_complete: forall te xl tyl e, satisf te e -> list_forall2 T.sub tyl (map te xl) -> exists e', type_defs e xl tyl = OK e' /\ satisf te e'.
Lemma type_use_complete: forall te e x ty, satisf te e -> T.sub (te x) ty -> exists e', type_use e x ty = OK e' /\ satisf te e'.
Lemma type_uses_complete: forall te xl tyl e, satisf te e -> list_forall2 T.sub (map te xl) tyl -> exists e', type_uses e xl tyl = OK e' /\ satisf te e'.
Lemma type_move_complete: forall te e r1 r2, satisf te e -> T.sub (te r1) (te r2) -> exists changed e', type_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 -> T.sub (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 type_def_incr: forall te x ty e e', type_def e x ty = OK e' -> satisf te e' -> satisf te e.
Lemma type_def_sound: forall te x ty e e', type_def e x ty = OK e' -> satisf te e' -> T.sub ty (te x).
Lemma type_defs_incr: forall te xl tyl e e', type_defs e xl tyl = OK e' -> satisf te e' -> satisf te e.
Lemma type_defs_sound: forall te xl tyl e e', type_defs e xl tyl = OK e' -> satisf te e' -> list_forall2 T.sub tyl (map te xl).
Lemma type_use_incr: forall te x ty e e', type_use e x ty = OK e' -> satisf te e' -> satisf te e.
Lemma type_use_sound: forall te x ty e e', type_use e x ty = OK e' -> satisf te e' -> T.sub (te x) ty.
Lemma type_uses_incr: forall te xl tyl e e', type_uses e xl tyl = OK e' -> satisf te e' -> satisf te e.
Lemma type_uses_sound: forall te xl tyl e e', type_uses e xl tyl = OK e' -> satisf te e' -> list_forall2 T.sub (map te xl) tyl.
Lemma type_move_incr: forall te e r1 r2 e' changed, type_move e r1 r2 = OK(changed, e') -> satisf te e' -> satisf te e.
Lemma type_move_sound: forall te e r1 r2 e' changed, type_move e r1 r2 = OK(changed, e') -> satisf te e' -> T.sub (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' -> T.sub (te r1) (te r2).
Lemma type_move_false: forall e r1 r2 e', type_move e r1 r2 = OK(false, e') -> te_typ e' = te_typ e /\ T.sub (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 -> T.sub (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 type_def_complete: forall te e x ty, satisf te e -> T.sub ty (te x) -> exists e', type_def e x ty = OK e' /\ satisf te e'.
Lemma type_defs_complete: forall te xl tyl e, satisf te e -> list_forall2 T.sub tyl (map te xl) -> exists e', type_defs e xl tyl = OK e' /\ satisf te e'.
Lemma type_use_complete: forall te e x ty, satisf te e -> T.sub (te x) ty -> exists e', type_use e x ty = OK e' /\ satisf te e'.
Lemma type_uses_complete: forall te xl tyl e, satisf te e -> list_forall2 T.sub (map te xl) tyl -> exists e', type_uses e xl tyl = OK e' /\ satisf te e'.
Lemma type_move_complete: forall te e r1 r2, satisf te e -> T.sub (te r1) (te r2) -> exists changed e', type_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 -> T.sub (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'.