Fact sss_compute_inv P st1 st2 st3 :
out_code (fst st3) P
-> P // st1 ->> st2
-> P // st1 ->> st3
-> P // st2 ->> st3.
Fact sss_compute_step_out_inv P k st1 st2 st3 :
st1 <> st2
-> out_code (fst st3) P
-> P // st1 ->> st2
-> P // st1 -[k]-> st3
-> exists q, q < k /\ P // st2 -[q]-> st3.
Fact subcode_sss_subcode_compute_inv P Q k st1 st2 st3 :
in_code (fst st1) P
-> out_code (fst st2) P
-> out_code (fst st3) P
-> P <sc Q
-> P // st1 ->> st2
-> Q // st1 -[k]-> st3
-> exists q, q < k /\ Q // st2 -[q]-> st3.
Fact subcode_sss_steps_inv_1 P i k st1 st2 st3 :
st1 <> st3
-> i // st1 -1> st2
-> (fst st1,i::nil) <sc P
-> P // st1 -[k]-> st3
-> exists k', k = S k' /\ P // st2 -[k']-> st3.
Fact subcode_sss_steps_stop P i k st1 st2 :
(forall st, ~ i // st1 -1> st)
->  (fst st1,i::nil) <sc P
->  P // st1 -[k]-> st2 -> k = 0 /\ st1 = st2.
Fact sss_steps_stop P k st1 st2 :
out_code (fst st1) P
-> P // st1 -[k]-> st2
-> st1 = st2.
Fact sss_compute_stop P st1 st2 :
out_code (fst st1) P
-> P // st1 ->> st2
-> st1 = st2.
Fact sss_compute_fun P st1 st2 st3 :
out_code (fst st2) P
-> out_code (fst st3) P
-> P // st1 ->> st2
-> P // st1 ->> st3
-> st2 = st3.
Fact sss_output_fun P st st1 st2 : P // st ~~> st1 -> P // st ~~> st2 -> st1 = st2.
Fact subcode_sss_terminates P Q st : P <sc Q -> Q // st ↓ -> P // st ↓.
Section sss_loop.
(* P contains a loop that modifies the data (in a way computable by f) when condition C1 is satisfied and otherwise stops somewhere outside of P when condition C2 is satisfied.  Then P stops iff exists n, C2 (iter f x n) *)
Variable (P : code) (pre : data -> Prop) (spec : data -> data -> Prop)
(f : data -> data) (Hf : forall x, x <> f x)
(C1 C2 : data -> Prop) (HC : forall x, pre x -> { C1 x } + { C2 x })
(i : nat) (p : nat) (Hp : out_code p P)
(HP1 : forall x, pre x -> C1 x -> P // (i,x) ->> (i,f x) /\ pre (f x))
(HP2 : forall x, pre x -> C2 x -> exists y, P // (i,x) ->> (p,y) /\ spec x y).

(* Specifications: *)
Theorem sss_loop_sound x : pre x
-> (exists n, C2 (iter f x n))
-> exists n y, P // (i,x) ->> (p,y) /\ spec (iter f x n) y.
Theorem sss_loop_complete x y q : pre x
-> out_code q P
-> P // (i,x) ->> (q,y)
-> p = q /\ exists n, C2 (iter f x n) /\ spec (iter f x n) y.