Theory SquareRoot_concept

(******************************************************************************
 * Clean
 *
 * Copyright (c) 2018-2019 Université Paris-Saclay, Univ. Paris-Sud, France
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *     * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 *
 *     * Neither the name of the copyright holders nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ******************************************************************************)

(*
 * SquareRoot_concept --- Example of monadic symbolic execution for a WHILE program.
 * Burkhart Wolff and Chantal Keller, LRI, Univ. Paris-Sud, France
 *)

section ‹ The Squareroot Example for Symbolic Execution › 

theory SquareRoot_concept
  imports Clean.Test_Clean
begin


subsection‹ The Conceptual Algorithm in Clean Notation›

text‹ In high-level notation, the algorithm we are investigating looks like this:

@{cartouche [display=true]
‹‹
function_spec sqrt (a::int) returns int
pre          "‹0 ≤ a›"    
post         "‹λres::int.  (res + 1)2 > a ∧ a ≥ (res)2›" 
defines      " (‹tm := 1› ;-
               ‹sqsum := 1› ;-
               ‹i := 0› ;-
               (whileSE ‹sqsum <= a› do 
                  ‹i := i+1› ;-
                  ‹tm := tm + 2› ;-
                  ‹sqsum := tm + sqsum›
               od) ;-
               returnC result_value_update ‹i›   
               )" 
››}


subsection‹ Definition of the Global State ›

text‹The state is just a record; and the global variables correspond to fields in this
     record. This corresponds to typed, structured, non-aliasing states.
     Note that the types in the state can be arbitrary HOL-types - want to have
     sets of functions in a ghost-field ? No problem !
    ›

text‹ The state of the square-root program looks like this : ›

typ "Clean.control_state"

MLval Type(s,t) = StateMgt_core.get_state_type_global @{theory}
val Type(u,v) = @{typ unit}

(* could also be local variable, we flipped a coin and it became this way *)
global_vars (state)
   tm    :: int
   i     :: int
   sqsum :: int


MLval Type(s,t) = StateMgt_core.get_state_type_global @{theory}
val Type(u,v) = @{typ unit}


(* should be automatic *)
lemma tm_independent [simp]: " tm_update"
  unfolding control_independence_def  by auto

lemma i_independent [simp]: " i_update"
  unfolding control_independence_def  by auto

lemma sqsum_independent [simp]: " sqsum_update"
  unfolding control_independence_def  by auto





subsection‹ Setting for Symbolic Execution ›

text‹ Some lemmas to reason about memory›

lemma tm_simp : "tm (σtm := t) = t"
  using [[simp_trace]]  by simp
(* from trace:
   [1]Procedure "record" produced rewrite rule:
   tm (?r⦇tm := ?k⦈) ≡ ?k 

   Unfortunately, this lemma is not exported ... It looks as if it is computed on the fly ...
   This could explain why this is slow for our purposes ...
*)
lemma tm_simp1 : "tm (σsqsum := s) = tm σ" by simp
lemma tm_simp2 : "tm (σi := s) = tm σ" by simp
lemma sqsum_simp : "sqsum (σsqsum := s) = s" by simp
lemma sqsum_simp1 : "sqsum (σtm := t) = sqsum σ" by simp
lemma sqsum_simp2 : "sqsum (σi := t) = sqsum σ" by simp
lemma i_simp : "i (σi := i') = i'" by simp
lemma i_simp1 : "i (σtm := i') = i σ" by simp
lemma i_simp2 : "i (σsqsum := i') = i σ" by simp

lemmas memory_theory =
  tm_simp tm_simp1 tm_simp2 
  sqsum_simp sqsum_simp1 sqsum_simp2 
  i_simp i_simp1 i_simp2 
     

declare memory_theory [memory_theory]


lemma non_exec_assign_globalD':
  assumes " upd"
  shows   "σ  upd :==G rhs ;- M   σ   upd (λ_. rhs σ) σ  M"
  apply(drule non_exec_assign_global'[THEN iffD1])
  using assms exec_stop_vs_control_independence apply blast
  by auto

lemmas non_exec_assign_globalD'_tm = non_exec_assign_globalD'[OF tm_independent]
lemmas non_exec_assign_globalD'_i = non_exec_assign_globalD'[OF i_independent]
lemmas non_exec_assign_globalD'_sqsum = non_exec_assign_globalD'[OF sqsum_independent]

text‹ Now we run a symbolic execution. We run match-tactics (rather than the Isabelle simplifier 
  which would do the trick as well) in order to demonstrate a symbolic execution in Isabelle. ›


subsection‹ A Symbolic Execution Simulation ›


lemma 
  assumes non_exec_stop[simp]: "¬ exec_stop σ0" 
   and    pos : "0  (a::int)"
   and    annotated_program: 
          "σ0  ‹tm := 1› ;-
                ‹sqsum := 1› ;-
                ‹i := 0› ;-
                (whileSE ‹sqsum <= a› do 
                   ‹i := i+1› ;-
                   ‹tm := tm + 2› ;-
                   ‹sqsum := tm + sqsum›
                od) ;-
                assertSE(λσ. σ=σR)"

       shows "σR assertSE ‹i2  ≤ a ∧ a < (i + 1)2 "
  

  apply(insert annotated_program)

  apply(tactic "dmatch_tac @{context} [@{thm \"non_exec_assign_globalD'_tm\"}] 1",simp)
  apply(tactic "dmatch_tac @{context} [@{thm \"non_exec_assign_globalD'_sqsum\"}] 1",simp)
  apply(tactic "dmatch_tac @{context} [@{thm \"non_exec_assign_globalD'_i\"}] 1",simp)

  apply(tactic "dmatch_tac @{context} [@{thm \"exec_whileD\"}] 1")
  apply(tactic "ematch_tac @{context} [@{thm \"if_SE_execE''\"}] 1")
   apply(simp_all only: memory_theory MonadSE.bind_assoc')

   apply(tactic "dmatch_tac @{context} [@{thm \"non_exec_assign_globalD'_i\"}] 1",simp)
   apply(tactic "dmatch_tac @{context} [@{thm \"non_exec_assign_globalD'_tm\"}] 1",simp)
   apply(tactic "dmatch_tac @{context} [@{thm \"non_exec_assign_globalD'_sqsum\"}] 1",simp)

   apply(tactic "dmatch_tac @{context} [@{thm \"exec_whileD\"}] 1")
    apply(tactic "ematch_tac @{context} [@{thm \"if_SE_execE''\"}] 1")
    apply(simp_all only: memory_theory MonadSE.bind_assoc')

    apply(tactic "dmatch_tac @{context} [@{thm \"non_exec_assign_globalD'_i\"}] 1",simp)
    apply(tactic "dmatch_tac @{context} [@{thm \"non_exec_assign_globalD'_tm\"}] 1",simp)
    apply(tactic "dmatch_tac @{context} [@{thm \"non_exec_assign_globalD'_sqsum\"}] 1",simp)

    apply(tactic "dmatch_tac @{context} [@{thm \"exec_whileD\"}] 1")
    apply(tactic "ematch_tac @{context} [@{thm \"if_SE_execE''\"}] 1")
    apply(simp_all only: memory_theory MonadSE.bind_assoc')

     
    apply(tactic "dmatch_tac @{context} [@{thm \"non_exec_assign_globalD'_i\"}] 1",simp)
    apply(tactic "dmatch_tac @{context} [@{thm \"non_exec_assign_globalD'_tm\"}] 1",simp)
    apply(tactic "dmatch_tac @{context} [@{thm \"non_exec_assign_globalD'_sqsum\"}] 1",simp)
     apply(simp_all)

  text‹Here are all abstract test-cases explicit. Each subgoal correstponds to 
       a path taken through the loop.›


  txt‹push away the test-hyp: postcond is true for programs with more than
    three loop traversals (criterion: all-paths(k). This reveals explicitly
    the three test-cases for  @{term "k<3"}. ›   
   defer 1 


(*
txt‹Instead of testing, we @{emph ‹prove›} that the test cases satisfy the
    post-condition for all @{term "k<3"} loop traversals and @{emph ‹all›} 
    positive inputs @{term "a "}.›     
   apply(auto  simp: assert_simp)
 *) 
oops

text‹TODO: re-establish  automatic test-coverage tactics of cite"DBLP:conf/tap/Keller18".›

end