Qcert.NRAEnv.Optim.TNRAEnvRewrite




Section TOptimEnv.








  Context {m:basic_model}.

  Lemma tand_comm_arrow (q₁ q₂:cnraenv) :
    q₁ q₂ q₂ q₁.

  Lemma tand_commc τenv τin} (q₁ q₂ ql qr: m τin Bool τc;τenv) :
    (`ql = `q₂ `q₁)
    (`qr = `q₁ `q₂)
    ql ≡τ qr.


  Lemma tconcat_empty_record_r_arrow q:
    q ‵[||] q.

  Lemma tconcat_empty_record_l_arrow q:
    ‵[||] q q.

  Lemma tmerge_empty_record_r_arrow q:
    q ‵[||] ‵{| q |}.


  Lemma tmerge_empty_record_l_arrow q:
    ‵[||] q ‵{| q |}.


  Lemma tdot_over_rec_arrow a q :
    (‵[| (a, q)|]) · a q.

  Lemma tdot_over_concat_eq_r_arrow a (q₁ q₂:cnraenv) :
    (q₁ ‵[| (a, q₂) |]a q₂.

  Lemma tdot_over_concat_neq_r_arrow a₁ a₂ (q₁ q₂:cnraenv) :
    a₁ a₂
    (q₁ ‵[| (a₁, q₂) |]a₂ q₁·a₂.

  Lemma tdot_over_concat_neq_l_arrow a₁ a₂ (q₁ q₂:cnraenv) :
    a₁ a₂
    (‵[| (a₁, q₁) |] q₂ a₂ q₂·a₂.


  Lemma tenvdot_from_duplicate_r_arrow a₁ a₂ (q₁ q₂:cnraenv) :
    (‵[| (a₁, q₁) |] ‵[| (a₂, q₂) |]a₂ q₂.


  Lemma tenvdot_from_duplicate_l_arrow a₁ a₂ (q₁ q₂:cnraenv) :
    a₁ a₂ (‵[| (a₁, q₁) |] ‵[| (a₂, q₂) |]a₁ q₁.


  Lemma tproduct_singletons_arrow a₁ a₂ q₁ q₂:
    ‵{|‵[| (a₁, q₁) |] |} × ‵{| ‵[| (a₂, q₂) |] |}
     ‵{|‵[| (a₁, q₁) |] ‵[| (a₂, q₂) |] |}.


  Lemma tproduct_empty_right_arrow q:
    q × ‵{| ‵[||] |} q.

  Lemma tproduct_empty_left_arrow q:
    ‵{| ‵[||] |} × q q.


  Lemma tconcat_over_rec_eq s p₁ p₂ :
     ‵[| (s, p₁) |] ‵[| (s, p₂) |] ‵[| (s, p₂) |].


  Lemma tmerge_concat_to_concat_arrow a₁ a₂ q₁ q₂:
    a₁ a₂
    ‵[| (a₁, q₁)|] ‵[| (a₂, q₂) |] ‵{|‵[| (a₁, q₁)|] ‵[| (a₂, q₂)|]|}.


  Lemma tmerge_with_concat_to_concat_arrow a₁ a₂ q₁ q₂:
    a₁ a₂
    ‵[| (a₁, q₁)|] (‵[| (a₁, q₁) |] ‵[| (a₂, q₂) |]) ‵{|‵[| (a₁, q₁)|] ‵[| (a₂, q₂)|]|}.


  Lemma tselect_over_nil q : σ⟨ q ⟩(‵{||}) ‵{||}.


  Lemma tselect_and_comm_arrow (q q₁ q₂:cnraenv) :
    σ⟨ q₁ q₂ ⟩(q) σ⟨ q₂ q₁ ⟩(q).

  Lemma tselect_and_commc τenv τin τ} (q ql qr: m τin Coll τ τc;τenv)
        (q₁ q₂: m τ Bool τc;τenv) :
    (`ql = σ⟨ `q₂ `q₁ ⟩(`q))
    (`qr = σ⟨ `q₁ `q₂ ⟩(`q))
    ql ≡τ qr.


  Lemma tselect_and_arrow (q q₁ q₂:cnraenv) :
    σ⟨ q₁ ⟩(σ⟨ q₂ ⟩(q)) σ⟨ q₂ q₁ ⟩(q).


  Lemma selection_split_and (q q₁ q₂:cnraenv) :
    σ⟨ q₂ q₁ ⟩(q) σ⟨ q₁ ⟩(σ⟨ q₂ ⟩(q)).


  Lemma tselect_andc τenv τin τ} (q ql qr: m τin (Coll τ) τc;τenv) (q₁ q₂:m τ Bool τc;τenv) :
    (`ql = σ⟨ `q₁ ⟩(σ⟨ `q₂ ⟩(`q)))
    (`qr = σ⟨ `q₂ `q₁ ⟩(`q))
    (ql ≡τ qr).


  Lemma tselect_comm_arrow (q q₁ q₂:cnraenv) :
    σ⟨ q₁ ⟩(σ⟨ q₂ ⟩( q )) σ⟨ q₂ ⟩(σ⟨ q₁ ⟩( q )).

  Lemma tselect_commc τenv τin τ} (q₁ q₂:m τ Bool τc;τenv) (q ql qr: m τin (Coll τ) τc;τenv) :
    (`ql = σ⟨ `q₁ ⟩(σ⟨ `q₂ ⟩(`q)))
    (`qr = σ⟨ `q₂ ⟩(σ⟨ `q₁ ⟩(`q)))
    ql ≡τ qr.



  Lemma tenvflatten_collc τenv τin τout} (q:m τin Coll τout τc;τenv) (ql qr:m τin Coll τout τc;τenv):
    (`ql = flatten(‵{| `q |})) (`qr = `q) ql ≡τ qr.

  Lemma tenvflatten_coll_arrow (q:cnraenv):
    flatten(‵{| q |}) q.

  Lemma tenvflatten_nil_arrow :
    flatten(‵{||}) ‵{||}.


  Lemma tenvflatten_map_coll_arrow q₁ q₂ :
    flatten(χ⟨ ‵{| q₁ |} ⟩( q₂ )) χ⟨ q₁ ⟩( q₂ ).

  Lemma tflatten_flatten_map_either_nil p₁ p₂ p₃ :
    flatten( flatten(χ⟨ANEither p₁ ‵{||} p₂⟩(p₃)))
     flatten( χ⟨ANEither( flatten(p₁)) ‵{||} p₂⟩(p₃)).


  Lemma tflatten_mapenv_coll_arrow q₁:
    flatten(ANMapEnv (‵{| q₁ |})) ANMapEnv q₁.


  Lemma tdouble_flatten_map_coll_arrow q₁ q₂ q₃ :
    flatten(χ⟨ χ⟨ ‵{| q₃ |} ⟩( q₁ ) ⟩( q₂ )) χ⟨ ‵{| q₃ |} ⟩(flatten(χ⟨ q₁ ⟩( q₂ ))).


  Lemma tnested_map_over_singletons_arrow q₁ q₂ q₃:
    flatten(χ⟨ σ⟨ q₁ ⟩(‵{|q₂|}) ⟩(q₃)) σ⟨ q₁ ⟩(χ⟨ q₂ ⟩(q₃)).


  Lemma tflatten_over_double_map_with_either_arrow q₁ q₂ q₃ q₄ :
    flatten(χ⟨ χ⟨ q₁ ⟩( σ⟨ q₂ ⟩( (ANEither (‵{|ID|}) ‵{||}) q₃ ) ) ⟩( q₄ ))
             χ⟨ q₁ ⟩( σ⟨ q₂ ⟩( flatten( χ⟨ (ANEither (‵{|ID|}) ‵{||}) q₃ ⟩( q₄ ) ) ) ).


  Lemma tflatten_over_double_map_arrow q₁ q₂ q₃ :
    flatten(χ⟨χ⟨ q₁ ⟩( σ⟨ q₂ ⟩(‵{|ID|}) ) ⟩( q₃ )) χ⟨ q₁ ⟩( σ⟨ q₂ ⟩( q₃ ) ).

  Lemma tselect_over_flatten p₁ p₂ :
    σ⟨p₁⟩(flatten(p₂)) flatten(χ⟨σ⟨p₁⟩(ID)⟩(p₂)).

  Lemma tselect_over_flatten_b p₁ p₂ :
    flatten(χ⟨σ⟨p₁⟩(ID)⟩(p₂)) σ⟨p₁⟩(flatten(p₂)).

  Lemma tmap_over_flatten p₁ p₂ :
    χ⟨p₁⟩(flatten(p₂)) flatten(χ⟨χ⟨p₁⟩(ID)⟩(p₂)).

  Lemma tmap_over_flatten_b p₁ p₂ :
    flatten(χ⟨χ⟨p₁⟩(ID)⟩(p₂)) χ⟨p₁⟩(flatten(p₂)).

  Lemma tselect_over_either p₁ p₂ p₃ :
    σ⟨p₁⟩( ANEither p₂ p₃) ANEither (σ⟨p₁⟩(p₂)) (σ⟨p₁⟩(p₃)).


  Lemma tmap_over_nil q : χ⟨ q ⟩(‵{||}) ‵{||}.


  Lemma tenvmap_into_id_arrow q :
    χ⟨ ID ⟩( q ) q.


  Lemma tenvmap_map_compose_arrow q₁ q₂ q:
    χ⟨ q₁ ⟩( χ⟨ q₂ ⟩( q ) ) χ⟨ q₁ q₂ ⟩( q ).


  Lemma tenvmap_singleton_arrow q₁ q₂:
    χ⟨ q₁ ⟩( ‵{| q₂ |} ) ‵{| q₁ q₂ |}.


  Lemma tmap_full_over_select_arrow q q₁ q₂:
    χ⟨ q₂ ⟩(σ⟨ q₁ ⟩(‵{| q |})) χ⟨ q₂ q ⟩(σ⟨ q₁ q ⟩(‵{| ID |})).

  Lemma tmap_over_map_split p₁ p₂ p₃ :
    χ⟨χ⟨p₁ ⟩( p₂) ⟩( p₃) χ⟨χ⟨p₁ ⟩( ID) ⟩(χ⟨p₂⟩(p₃)).


  Lemma tflip_env6_arrow q₁ q₂:
    χ⟨ ENV ID ⟩(σ⟨ q₁ ⟩(ENV q₂)) χ⟨ ‵{|ID|} ⟩(σ⟨ q₁ ⟩(ENV q₂)).

  Lemma tmap_over_either p₁ p₂ p₃ :
    χ⟨p₁⟩( ANEither p₂ p₃) ANEither (χ⟨p₁⟩(p₂)) (χ⟨p₁⟩(p₃)).

  Lemma tmap_over_either_app p₁ p₂ p₃ p₄:
    χ⟨p₁⟩( ANEither p₂ p₃ p₄) ANEither (χ⟨p₁⟩(p₂)) (χ⟨p₁⟩(p₃)) p₄.



  Lemma tapp_over_const_arrow d q:
    (ANConst d) q (ANConst d).


  Lemma tapp_over_env_arrow q :
    ENV q ENV.


  Lemma tapp_over_id_r_arrow q:
    q ID q.


  Lemma tapp_over_id_l_arrow q:
    ID q q.


  Lemma tapp_over_unop_arrow u q₁ q₂:
    (ANUnop u q₁) q₂ (ANUnop u (q₁ q₂)).


  Lemma tapp_over_binop_arrow b q q₁ q₂:
    (ANBinop b q₂ q₁) q (ANBinop b (q₂ q) (q₁ q)).


  Lemma tapp_over_map_arrow q q₁ q₂:
    (χ⟨q₁⟩(q₂)) q χ⟨ q₁ ⟩(q₂ q).


  Lemma tapp_over_mapconcat_arrow q q₁ q₂:
    ⋈ᵈ⟨ q₁ ⟩( q₂ ) q ⋈ᵈ⟨ q₁ ⟩( q₂ q ).


  Lemma tapp_over_product_arrow q q₁ q₂:
    (q₁ × q₂) q (q₁ q) × (q₂ q).


  Lemma tapp_over_select_arrow q q₁ q₂:
    (σ⟨ q₁ ⟩( q₂ )) q (σ⟨ q₁ ⟩( q₂ q )).

  Lemma tapp_over_select_back_arrow q q₁ q₂:
    (σ⟨ q₁ ⟩( q₂ q )) (σ⟨ q₁ ⟩( q₂ )) q.


  Lemma tapp_over_app_arrow q₁ q₂ q₃:
    (q₁ q₂) q₃ q₁ (q₂ q₃).

  Lemma tselect_over_app_either p₁ p₂ p₃ p₄ :
    σ⟨p₁⟩( ANEither p₂ p₃ p₄ ) ANEither (σ⟨p₁⟩(p₂)) (σ⟨p₁⟩(p₃)) p₄.



  Lemma tappenv_over_const_arrow d q:
    (ANConst d) ◯ₑ q (ANConst d).


  Lemma tappenv_over_id_l_arrow q:
    ID ◯ₑ q ID.


  Lemma tapp_over_ignoreid_arrow q₁ q₂:
    cnraenv_ignores_id q₁ q₁ q₂ q₁.


  Lemma tappenv_over_env_l_arrow q:
    ENV ◯ₑ q q.


  Lemma tappenv_over_env_r_arrow q:
    q ◯ₑ ENV q.


  Lemma tappenv_over_unop_arrow u q₁ q₂:
    (ANUnop u q₁) ◯ₑ q₂ (ANUnop u (q₁ ◯ₑ q₂)).

  Lemma tunop_over_either u p₁ p₂ :
    ANUnop u (ANEither p₁ p₂) ANEither (ANUnop u p₁)(ANUnop u p₂).

  Lemma tunop_over_either_app u p₁ p₂ p₃:
    ANUnop u (ANEither p₁ p₂ p₃) ANEither (ANUnop u p₁)(ANUnop u p₂) p₃.


  Lemma tappenv_over_binop b q₁ q₂ q :
    (ANBinop b q₁ q₂) ◯ₑ q (ANBinop b (q₁ ◯ₑ q) (q₂ ◯ₑ q)).


  Lemma tappenv_over_map_arrow q q₁ q₂:
    cnraenv_ignores_id q
    χ⟨ q₁ ⟩( q₂ ) ◯ₑ q χ⟨ q₁ ◯ₑ q ⟩( q₂ ◯ₑ q ).


  Lemma tappenv_over_map_cnraenv_ignores_env_arrow q₁ q₂:
    cnraenv_ignores_env q₁
    χ⟨ q₁ ⟩( q₂ ) ◯ₑ ANID χ⟨ q₁ ◯ₑ ANID ⟩( q₂ ◯ₑ ANID ).


  Lemma tappenv_over_select_arrow q q₁ q₂:
    cnraenv_ignores_id q
    σ⟨ q₁ ⟩( q₂ ) ◯ₑ q σ⟨ q₁ ◯ₑ q ⟩( q₂ ◯ₑ q ).


  Lemma tappenv_over_appenv_arrow q q₁ q₂:
    (q₁ ◯ₑ q₂) ◯ₑ q q₁ ◯ₑ (q₂ ◯ₑ q).


  Lemma tappenv_over_app_arrow q q₁ q₂:
    cnraenv_ignores_id q (q₁ q₂) ◯ₑ q (q₁ ◯ₑ q) (q₂ ◯ₑ q).

  Lemma tappenv_over_app_ie_arrow p1 p2 p3:
    cnraenv_ignores_env p3
    ((p3 p2) ◯ₑ p1) p3 (p2 ◯ₑ p1).


  Lemma tapp_over_appenv_arrow q q₁ q₂:
    cnraenv_ignores_id q₁ (q₁ ◯ₑ q₂) q q₁ ◯ₑ (q₂ q).


  Lemma tappenv_over_ignoreenv_arrow q₁ q₂:
    cnraenv_ignores_env q₁ q₁ ◯ₑ q₂ q₁.


  Lemma tappenv_over_env_merge_l_arrow q₁ q:
    cnraenv_ignores_env q₁
    ANAppEnv (ENV q₁) q q q₁.


  Lemma tflip_env1_arrow q :
    (χ⟨ ENV ⟩(σ⟨ q ⟩(‵{|ID|}))) ◯ₑ ID σ⟨ q ⟩(‵{|ID|}) ◯ₑ ID.

  Lemma tflip_env4_arrow q₁ q₂:
    cnraenv_ignores_env q₁ (χ⟨ENV⟩( σ⟨ q₁ ⟩(‵{|ID|}))) ◯ₑ q₂ χ⟨q₂⟩( σ⟨ q₁ ⟩(‵{|ID|})).


  Lemma tflip_env2_arrow q :
    σ⟨ q ⟩(‵{|ID|}) ◯ₑ ID σ⟨ q ◯ₑ ID ⟩(‵{|ID|}).


  Lemma tflatten_through_appenv_arrow q₁ q₂ :
    flatten(q₁ ◯ₑ q₂) flatten(q₁) ◯ₑ q₂.

  Lemma tappenv_through_either q₁ q₂ q₃:
    cnraenv_ignores_id q₃
    ANEither q₁ q₂ ◯ₑ q₃ ANEither (q₁ ◯ₑ q₃) (q₂ ◯ₑ q₃).



  Lemma tmapenv_to_env_arrow q :
    (ANMapEnv (ENV)) q ENV.

  Lemma tmapenv_over_singleton_arrow q₁ q₂ :
    (ANMapEnv q₁) ◯ₑ (‵{|q₂|}) ‵{| q₁ ◯ₑ q₂ |}.


  Lemma tmapenv_to_map_arrow q₁ q₂:
    cnraenv_ignores_id q₁
    (ANMapEnv q₁) ◯ₑ q₂ χ⟨ q₁ ◯ₑ ID ⟩(q₂).



  Lemma tcompose_selects_in_mapenv_arrow q₁ q₂ :
    (flatten(ANMapEnv (χ⟨ENV⟩(σ⟨ q₁ ⟩( ‵{| ID |}))))) ◯ₑ (χ⟨ENV⟩(σ⟨ q₂ ⟩( ‵{| ID |})))
                                                           (χ⟨ENV⟩(σ⟨ q₁ ⟩(σ⟨ q₂ ⟩( ‵{| ID |})))).


  Lemma tappenv_mapenv_to_map_arrow q a:
    ANAppEnv (ANMapEnv q) (ENV ‵[| (a, ID)|])
             χ⟨(q (ANUnop (ADot a) ANEnv)) ◯ₑ ID⟩( (ENV ‵[| (a, ID)|]) ).


  Lemma tappenv_flatten_mapenv_to_map_arrow q a:
    ANAppEnv (flatten(ANMapEnv q)) (ENV ‵[| (a, ID)|])
           flatten(χ⟨(q (ANUnop (ADot a) ANEnv)) ◯ₑ ID⟩( (ENV ‵[| (a, ID)|]) )).



  Lemma ttostring_dstring_arrow s:
    (ANUnop AToString (ANConst (dstring s))) (ANConst (dstring s)).


  Lemma ttostring_tostring_arrow q:
    (ANUnop AToString (ANUnop AToString q)) (ANUnop AToString q).


  Lemma ttostring_sconcat_arrow q₁ q₂:
    (ANUnop AToString (ANBinop ASConcat q₁ q₂)) (ANBinop ASConcat q₁ q₂).


  Lemma trproject_nil p :
    π[nil](p) ‵[||].

  Lemma trproject_over_concat_rec_r_in sl s p₁ p₂ :
    In s sl
    π[sl](p₁ ‵[| (s, p₂) |]) π[remove string_dec s sl](p₁) ‵[| (s, p₂) |] .
   Lemma trproject_over_const sl l :
    π[sl](ANConst (drec l)) ANConst (drec (rproject l sl)).

  Lemma trproject_over_rec_in sl s p :
    In s sl
    π[sl](‵[| (s, p) |]) ‵[| (s, p) |].

  Lemma trproject_over_rec_nin sl s p :
    ¬ In s sl
    π[sl](‵[| (s, p) |]) ‵[||].

  Lemma trproject_over_concat_rec_r_nin sl s p₁ p₂ :
    ¬ In s sl
    π[sl](p₁ ‵[| (s, p₂) |]) π[sl](p₁).

  Lemma trproject_over_concat_rec_l_nin sl s p₁ p₂ :
    ¬ In s sl
    π[sl](‵[| (s, p₁) |] p₂) π[sl](p₂).

  Lemma trproject_over_concat_recs_in_in sl s₁ p₁ s₂ p₂ :
    In s₁ sl In s₂ sl
    π[sl](‵[| (s₁, p₁) |] ‵[| (s₂, p₂) |]) ‵[| (s₁, p₁) |] ‵[| (s₂, p₂) |].

  Lemma trproject_over_rproject sl1 sl2 p :
    π[sl1](π[sl2](p)) π[set_inter string_dec sl2 sl1](p).

  Lemma trproject_over_either sl p1 p2 :
    π[sl](ANEither p1 p2) ANEither (π[sl](p1)) (π[sl](p2)).



  Lemma tcount_over_map p₁ p₂ :
        count(χ⟨p₁⟩(p₂)) count(p₂).

  Lemma tcount_over_flat_map_map p₁ p₂ p₃ :
    count(flatten(χ⟨χ⟨p₁⟩(p₂)⟩(p₃)))
          count(flatten(χ⟨p₂⟩(p₃))).

  Lemma tmap_over_either_nil_b p₁ p₂ :
    ANEither (χ⟨p₁⟩(p₂)) ‵{||} χ⟨p₁⟩(ANEither p₂ ‵{||}).

  Lemma tcount_over_flat_map_either_nil_map p₁ p₂ p₃ :
    count(flatten(χ⟨ANEither (χ⟨p₁⟩(p₂)) ‵{||}⟩(p₃)))
          count(flatten(χ⟨ANEither p₂ ‵{||}⟩(p₃))).

  Lemma tcount_over_flat_map_either_nil_app_map p₁ p₂ p₃ p₄:
    count(flatten(χ⟨ANEither (χ⟨p₁⟩(p₂)) ‵{||} p₄⟩(p₃)))
          count(flatten(χ⟨ANEither p₂ ‵{||} p₄⟩(p₃))).

  Lemma tcount_over_flat_map_either_nil_app_singleton p₁ p₂ p₃:
    count(flatten(χ⟨ANEither (‵{| p₁ |}) ‵{||} p₃⟩(p₂)))
          count(flatten(χ⟨ANEither (‵{| ANConst dunit |}) ‵{||} p₃⟩(p₂))).



  Lemma tmapconcat_over_singleton p₁ :
    ⋈ᵈ⟨ p₁ ⟩(‵{| ‵[||] |}) p₁ (‵[||]).

composite lemmas: these are just composites of previous rewrites. They are here since the optimizer uses them.