src/HOL/Tools/function_package/lexicographic_order.ML
changeset 21237 b803f9870e97
parent 21201 803bc7672d17
child 21319 cf814e36f788
equal deleted inserted replaced
21236:890fafbcf8b0 21237:b803f9870e97
     5 Method for termination proofs with lexicographic orderings.
     5 Method for termination proofs with lexicographic orderings.
     6 *)
     6 *)
     7 
     7 
     8 signature LEXICOGRAPHIC_ORDER =
     8 signature LEXICOGRAPHIC_ORDER =
     9 sig
     9 sig
    10     val lexicographic_order : Method.method
    10   val lexicographic_order : Method.method
    11     val setup: theory -> theory
    11   val setup: theory -> theory
    12 end
    12 end
    13 
    13 
    14 structure LexicographicOrder : LEXICOGRAPHIC_ORDER =
    14 structure LexicographicOrder : LEXICOGRAPHIC_ORDER =
    15 struct
    15 struct
    16 
    16 
    17 (* Theory dependencies *)
    17 (* Theory dependencies *)
    18 val measures = "List.measures"
    18 val measures = "List.measures"
    19 val wf_measures = thm "wf_measures"
    19 val wf_measures = thm "wf_measures"
    20 val measures_less = thm "measures_less"
    20 val measures_less = thm "measures_less"
    21 val measures_lesseq = thm "measures_lesseq"
    21 val measures_lesseq = thm "measures_lesseq"
    22 
    22                       
    23 fun del_index (n, []) = []
    23 fun del_index (n, []) = []
    24   | del_index (n, x :: xs) =
    24   | del_index (n, x :: xs) =
    25       if n>0 then x :: del_index (n - 1, xs) else xs 
    25     if n>0 then x :: del_index (n - 1, xs) else xs 
    26 
    26 
    27 fun transpose ([]::_) = []
    27 fun transpose ([]::_) = []
    28   | transpose xss = map hd xss :: transpose (map tl xss)
    28   | transpose xss = map hd xss :: transpose (map tl xss)
    29 
    29 
    30 fun mk_sum_case (f1, f2) =
    30 fun mk_sum_case (f1, f2) =
    31     case (fastype_of f1, fastype_of f2) of
    31     case (fastype_of f1, fastype_of f2) of
    32 	(Type("fun", [A, B]), Type("fun", [C, D])) =>
    32       (Type("fun", [A, B]), Type("fun", [C, D])) =>
    33 	if (B = D) then
    33       if (B = D) then
    34             Const("Datatype.sum.sum_case", (A --> B) --> (C --> D) --> Type("+", [A,C]) --> B) $ f1 $ f2
    34         Const("Datatype.sum.sum_case", (A --> B) --> (C --> D) --> Type("+", [A,C]) --> B) $ f1 $ f2
    35 	else raise TERM ("mk_sum_case: range type mismatch", [f1, f2]) 
    35       else raise TERM ("mk_sum_case: range type mismatch", [f1, f2]) 
    36       | _ => raise TERM ("mk_sum_case", [f1, f2])
    36     | _ => raise TERM ("mk_sum_case", [f1, f2])
    37 
    37                  
    38 fun dest_wf (Const ("Wellfounded_Recursion.wf", _) $ t) = t
    38 fun dest_wf (Const ("Wellfounded_Recursion.wf", _) $ t) = t
    39   | dest_wf t = raise TERM ("dest_wf", [t])
    39   | dest_wf t = raise TERM ("dest_wf", [t])
    40 
    40                       
    41 datatype cell = Less of thm | LessEq of thm | None of thm | False of thm;
    41 datatype cell = Less of thm | LessEq of thm | None of thm | False of thm;
    42 
    42          
    43 fun is_Less cell = case cell of (Less _) => true | _ => false  
    43 fun is_Less cell = case cell of (Less _) => true | _ => false  
    44 
    44                                                         
    45 fun is_LessEq cell = case cell of (LessEq _) => true | _ => false
    45 fun is_LessEq cell = case cell of (LessEq _) => true | _ => false
    46 
    46                                                             
    47 fun thm_of_cell cell =
    47 fun thm_of_cell cell =
    48     case cell of 
    48     case cell of 
    49 	Less thm => thm
    49       Less thm => thm
    50       | LessEq thm => thm
    50     | LessEq thm => thm
    51       | False thm => thm
    51     | False thm => thm
    52       | None thm => thm
    52     | None thm => thm
    53 			   
    53                   
    54 fun mk_base_fun_bodys (t : term) (tt : typ) =
    54 fun mk_base_fun_bodys (t : term) (tt : typ) =
    55     case tt of
    55     case tt of
    56 	Type("*", [ft, st]) => (mk_base_fun_bodys (Const("fst", tt --> ft) $ t) ft) @ (mk_base_fun_bodys (Const("snd", tt --> st) $ t) st)      
    56       Type("*", [ft, st]) => (mk_base_fun_bodys (Const("fst", tt --> ft) $ t) ft) @ (mk_base_fun_bodys (Const("snd", tt --> st) $ t) st)      
    57       | _ => [(t, tt)]
    57     | _ => [(t, tt)]
    58 	     
    58            
    59 fun mk_base_fun_header fulltyp (t, typ) =
    59 fun mk_base_fun_header fulltyp (t, typ) =
    60     if typ = HOLogic.natT then
    60     if typ = HOLogic.natT then
    61 	Abs ("x", fulltyp, t)
    61       Abs ("x", fulltyp, t)
    62     else Abs ("x", fulltyp, Const("Nat.size", typ --> HOLogic.natT) $ t)
    62     else Abs ("x", fulltyp, Const("Nat.size", typ --> HOLogic.natT) $ t)
    63 	 	 
    63          
    64 fun mk_base_funs (tt: typ) = 
    64 fun mk_base_funs (tt: typ) = 
    65     mk_base_fun_bodys (Bound 0) tt |>
    65     mk_base_fun_bodys (Bound 0) tt |>
    66 		      map (mk_base_fun_header tt)
    66                       map (mk_base_fun_header tt)
    67 		   
    67     
    68 fun mk_ext_base_funs (tt : typ) =
    68 fun mk_ext_base_funs (tt : typ) =
    69     case tt of
    69     case tt of
    70 	Type("+", [ft, st]) =>
    70       Type("+", [ft, st]) =>
    71 	product (mk_ext_base_funs ft) (mk_ext_base_funs st)
    71       product (mk_ext_base_funs ft) (mk_ext_base_funs st)
    72         |> map mk_sum_case
    72               |> map mk_sum_case
    73       | _ => mk_base_funs tt
    73     | _ => mk_base_funs tt
    74 
    74            
    75 fun dest_term (t : term) =
    75 fun dest_term (t : term) =
    76     let
    76     let
    77 	val (vars, prop) = (FundefLib.dest_all_all t)
    77       val (vars, prop) = (FundefLib.dest_all_all t)
    78 	val prems = Logic.strip_imp_prems prop
    78       val prems = Logic.strip_imp_prems prop
    79 	val (tuple, rel) = Logic.strip_imp_concl prop
    79       val (tuple, rel) = Logic.strip_imp_concl prop
    80                            |> HOLogic.dest_Trueprop 
    80                          |> HOLogic.dest_Trueprop 
    81                            |> HOLogic.dest_mem
    81                          |> HOLogic.dest_mem
    82 	val (lhs, rhs) = HOLogic.dest_prod tuple
    82       val (lhs, rhs) = HOLogic.dest_prod tuple
    83     in
    83     in
    84 	(vars, prems, lhs, rhs, rel)
    84       (vars, prems, lhs, rhs, rel)
    85     end
    85     end
    86 
    86     
    87 fun mk_goal (vars, prems, lhs, rhs) rel =
    87 fun mk_goal (vars, prems, lhs, rhs) rel =
    88     let 
    88     let 
    89 	val concl = HOLogic.mk_binrel rel (lhs, rhs) |> HOLogic.mk_Trueprop
    89       val concl = HOLogic.mk_binrel rel (lhs, rhs) |> HOLogic.mk_Trueprop
    90     in	
    90     in  
    91 	Logic.list_implies (prems, concl) |>
    91       Logic.list_implies (prems, concl) |>
    92 	fold_rev FundefLib.mk_forall vars
    92                          fold_rev FundefLib.mk_forall vars
    93     end
    93     end
    94 
    94     
    95 fun prove (thy: theory) (t: term) =
    95 fun prove (thy: theory) (t: term) =
    96     cterm_of thy t |> Goal.init 
    96     cterm_of thy t |> Goal.init 
    97     |> SINGLE (CLASIMPSET auto_tac) |> the
    97     |> SINGLE (CLASIMPSET auto_tac) |> the
    98 
    98     
    99 fun mk_cell (thy : theory) (vars, prems) (lhs, rhs) = 
    99 fun mk_cell (thy : theory) (vars, prems) (lhs, rhs) = 
   100     let	
   100     let 
   101 	val goals = mk_goal (vars, prems, lhs, rhs) 
   101       val goals = mk_goal (vars, prems, lhs, rhs) 
   102 	val less_thm = goals "Orderings.less" |> prove thy
   102       val less_thm = goals "Orderings.less" |> prove thy
   103     in
   103     in
   104 	if Thm.no_prems less_thm then
   104       if Thm.no_prems less_thm then
   105 	    Less (Goal.finish less_thm)
   105         Less (Goal.finish less_thm)
   106 	else
   106       else
   107 	    let
   107         let
   108 		val lesseq_thm = goals "Orderings.less_eq" |> prove thy
   108           val lesseq_thm = goals "Orderings.less_eq" |> prove thy
   109 	    in
   109         in
   110 		if Thm.no_prems lesseq_thm then
   110           if Thm.no_prems lesseq_thm then
   111 		    LessEq (Goal.finish lesseq_thm)
   111             LessEq (Goal.finish lesseq_thm)
   112 		else 
   112           else 
   113 		    if prems_of lesseq_thm = [HOLogic.Trueprop $ HOLogic.false_const] then False lesseq_thm
   113             if prems_of lesseq_thm = [HOLogic.Trueprop $ HOLogic.false_const] then False lesseq_thm
   114 		    else None lesseq_thm
   114             else None lesseq_thm
   115 	    end
   115         end
   116     end
   116     end
   117 
   117     
   118 fun mk_row (thy: theory) base_funs (t : term) =
   118 fun mk_row (thy: theory) base_funs (t : term) =
   119     let
   119     let
   120 	val (vars, prems, lhs, rhs, _) = dest_term t
   120       val (vars, prems, lhs, rhs, _) = dest_term t
   121 	val lhs_list = map (fn x => x $ lhs) base_funs
   121       val lhs_list = map (fn x => x $ lhs) base_funs
   122 	val rhs_list = map (fn x => x $ rhs) base_funs
   122       val rhs_list = map (fn x => x $ rhs) base_funs
   123     in
   123     in
   124 	map (mk_cell thy (vars, prems)) (lhs_list ~~ rhs_list)
   124       map (mk_cell thy (vars, prems)) (lhs_list ~~ rhs_list)
   125     end
   125     end
   126 
   126       
   127 (* simple depth-first search algorithm for the table *)
   127 (* simple depth-first search algorithm for the table *)
   128 fun search_table table =
   128 fun search_table table =
   129     case table of
   129     case table of
   130 	[] => SOME []
   130       [] => SOME []
   131       | _ =>
   131     | _ =>
   132 	let
   132       let
   133 	    val check_col = forall (fn c => is_Less c orelse is_LessEq c)
   133         val check_col = forall (fn c => is_Less c orelse is_LessEq c)
   134             val col = find_index (check_col) (transpose table)
   134         val col = find_index (check_col) (transpose table)
   135 	in case col of
   135       in case col of
   136 	       ~1 => NONE 
   136            ~1 => NONE 
   137              | _ =>
   137          | _ =>
   138                let
   138            let
   139 		   val order_opt = table |> filter_out (fn x => is_Less (nth x col)) |> map (curry del_index col) |> search_table
   139              val order_opt = table |> filter_out (fn x => is_Less (nth x col)) |> map (curry del_index col) |> search_table
   140 		   val transform_order = (fn col => map (fn x => if x>=col then x+1 else x))
   140              val transform_order = (fn col => map (fn x => if x>=col then x+1 else x))
   141                in case order_opt of
   141            in case order_opt of
   142 		      NONE => NONE
   142                 NONE => NONE
   143 		    | SOME order =>SOME (col::(transform_order col order))
   143               | SOME order =>SOME (col::(transform_order col order))
   144 	       end
   144            end
   145 	end
   145       end
   146 
   146       
   147 fun prove_row row (st : thm) =
   147 fun prove_row row (st : thm) =
   148     case row of
   148     case row of
   149         [] => sys_error "INTERNAL ERROR IN lexicographic order termination tactic - fun prove_row (row is empty)" 
   149       [] => sys_error "INTERNAL ERROR IN lexicographic order termination tactic - fun prove_row (row is empty)" 
   150       | cell::tail =>
   150     | cell::tail =>
   151 	case cell of
   151       case cell of
   152 	    Less less_thm =>
   152         Less less_thm =>
   153 	    let
   153         let
   154 		val next_thm = st |> SINGLE (rtac measures_less 1) |> the
   154           val next_thm = st |> SINGLE (rtac measures_less 1) |> the
   155 	    in
   155         in
   156 		implies_elim next_thm less_thm
   156           implies_elim next_thm less_thm
   157 	    end
   157         end
   158 	  | LessEq lesseq_thm =>
   158       | LessEq lesseq_thm =>
   159 	    let
   159         let
   160 		val next_thm = st |> SINGLE (rtac measures_lesseq 1) |> the
   160           val next_thm = st |> SINGLE (rtac measures_lesseq 1) |> the
   161 	    in
   161         in
   162 		implies_elim next_thm lesseq_thm |>
   162           implies_elim next_thm lesseq_thm 
   163                 prove_row tail
   163           |> prove_row tail
   164 	    end
   164         end
   165           | _ => sys_error "INTERNAL ERROR IN lexicographic order termination tactic - fun prove_row (Only expecting Less or LessEq)"
   165       | _ => sys_error "INTERNAL ERROR IN lexicographic order termination tactic - fun prove_row (Only expecting Less or LessEq)"
   166 
   166              
   167 fun pr_unprovable_subgoals table =
   167 fun pr_unprovable_subgoals table =
   168     filter (fn x => not (is_Less x) andalso not (is_LessEq x)) (flat table)
   168     filter (fn x => not (is_Less x) andalso not (is_LessEq x)) (flat table)
   169 	   |> map ((fn th => Pretty.string_of (Pretty.chunks (Display.pretty_goals (Thm.nprems_of th) th))) o thm_of_cell)
   169     |> map ((fn th => Pretty.string_of (Pretty.chunks (Display.pretty_goals (Thm.nprems_of th) th))) o thm_of_cell)
   170 
   170     
   171 fun pr_goal thy t i = 
   171 fun pr_goal thy t i = 
   172     let
   172     let
   173 	val (_, prems, lhs, rhs, _) = dest_term t 
   173       val (_, prems, lhs, rhs, _) = dest_term t 
   174 	val prterm = string_of_cterm o (cterm_of thy)
   174       val prterm = string_of_cterm o (cterm_of thy)
   175     in
   175     in
   176 	(* also show prems? *)
   176       (* also show prems? *)
   177         i ^ ") " ^ (prterm lhs) ^ " '<' " ^ (prterm rhs) 
   177         i ^ ") " ^ (prterm lhs) ^ " '<' " ^ (prterm rhs) 
   178     end
   178     end
   179 
   179     
   180 fun pr_fun thy t i =
   180 fun pr_fun thy t i =
   181     (string_of_int i) ^ ") " ^ (string_of_cterm (cterm_of thy t))
   181     (string_of_int i) ^ ") " ^ (string_of_cterm (cterm_of thy t))
   182 
   182     
   183 fun pr_cell cell = case cell of Less _ => " <  " 
   183 fun pr_cell cell = case cell of Less _ => " <  " 
   184 				| LessEq _ => " <= " 
   184                               | LessEq _ => " <= " 
   185 				| None _ => " N  "
   185                               | None _ => " N  "
   186 				| False _ => " F  "
   186                               | False _ => " F  "
   187        
   187                                              
   188 (* fun pr_err: prints the table if tactic failed *)
   188 (* fun pr_err: prints the table if tactic failed *)
   189 fun pr_err table thy tl base_funs =  
   189 fun pr_err table thy tl base_funs =  
   190     let 
   190     let 
   191 	val gc = map (fn i => chr (i + 96)) (1 upto (length table))
   191       val gc = map (fn i => chr (i + 96)) (1 upto (length table))
   192 	val mc = 1 upto (length base_funs)
   192       val mc = 1 upto (length base_funs)
   193 	val tstr = ("   " ^ (concat (map (fn i => " " ^ (string_of_int i) ^ "  ") mc))) ::
   193       val tstr = ("   " ^ (concat (map (fn i => " " ^ (string_of_int i) ^ "  ") mc))) ::
   194 		   (map2 (fn r => fn i => i ^ ": " ^ (concat (map pr_cell r))) table gc)
   194                  (map2 (fn r => fn i => i ^ ": " ^ (concat (map pr_cell r))) table gc)
   195 	val gstr = ("Goals:"::(map2 (pr_goal thy) tl gc))
   195       val gstr = ("Goals:"::(map2 (pr_goal thy) tl gc))
   196 	val mstr = ("Measures:"::(map2 (pr_fun thy) base_funs mc))   
   196       val mstr = ("Measures:"::(map2 (pr_fun thy) base_funs mc))   
   197 	val ustr = ("Unfinished subgoals:"::(pr_unprovable_subgoals table))
   197       val ustr = ("Unfinished subgoals:"::(pr_unprovable_subgoals table))
   198     in
   198     in
   199 	tstr @ gstr @ mstr @ ustr
   199       tstr @ gstr @ mstr @ ustr
   200     end
   200     end
   201 
   201       
   202 (* the main function: create table, search table, create relation,
   202 (* the main function: create table, search table, create relation,
   203    and prove the subgoals *)
   203    and prove the subgoals *)
   204 fun lexicographic_order_tac (st: thm) = 
   204 fun lexicographic_order_tac (st: thm) = 
   205     let
   205     let
   206 	val thy = theory_of_thm st
   206       val thy = theory_of_thm st
   207         val termination_thm = ProofContext.get_thm (Variable.thm_context st) (Name "termination")
   207       val termination_thm = ProofContext.get_thm (Variable.thm_context st) (Name "termination")
   208 	val next_st = SINGLE (rtac termination_thm 1) st |> the
   208       val next_st = SINGLE (rtac termination_thm 1) st |> the
   209         val premlist = prems_of next_st
   209       val premlist = prems_of next_st
   210     in
   210     in
   211         case premlist of 
   211       case premlist of 
   212             [] => error "invalid number of subgoals for this tactic - expecting at least 1 subgoal" 
   212             [] => error "invalid number of subgoals for this tactic - expecting at least 1 subgoal" 
   213           | (wf::tl) => let
   213           | (wf::tl) => let
   214 		val (var, prop) = FundefLib.dest_all wf
   214     val (var, prop) = FundefLib.dest_all wf
   215 		val rel = HOLogic.dest_Trueprop prop |> dest_wf |> head_of
   215     val rel = HOLogic.dest_Trueprop prop |> dest_wf |> head_of
   216 		val crel = cterm_of thy rel
   216     val crel = cterm_of thy rel
   217 		val base_funs = mk_ext_base_funs (fastype_of var)
   217     val base_funs = mk_ext_base_funs (fastype_of var)
   218 		val _ = writeln "Creating table"
   218     val _ = writeln "Creating table"
   219 		val table = map (mk_row thy base_funs) tl
   219     val table = map (mk_row thy base_funs) tl
   220 		val _ = writeln "Searching for lexicographic order"
   220     val _ = writeln "Searching for lexicographic order"
   221 		val possible_order = search_table table
   221     val possible_order = search_table table
   222 	    in
   222       in
   223 		case possible_order of 
   223     case possible_order of 
   224 		    NONE => error (cat_lines ("Could not prove it by lexicographic order:"::(pr_err table thy tl base_funs)))
   224         NONE => error (cat_lines ("Could not prove it by lexicographic order:"::(pr_err table thy tl base_funs)))
   225 		  | SOME order  => let
   225       | SOME order  => let
   226 			val clean_table = map (fn x => map (nth x) order) table
   226       val clean_table = map (fn x => map (nth x) order) table
   227 			val funs = map (nth base_funs) order
   227       val funs = map (nth base_funs) order
   228 			val list = HOLogic.mk_list (fn x => x) (fastype_of var --> HOLogic.natT) funs
   228       val list = HOLogic.mk_list (fn x => x) (fastype_of var --> HOLogic.natT) funs
   229 			val relterm = Abs ("x", fastype_of var, Const(measures, (fastype_of list) --> (range_type (fastype_of rel))) $ list)
   229       val relterm = Abs ("x", fastype_of var, Const(measures, (fastype_of list) --> (range_type (fastype_of rel))) $ list)
   230 			val crelterm = cterm_of thy relterm
   230       val crelterm = cterm_of thy relterm
   231 			val _ = writeln ("Instantiating R with " ^ (string_of_cterm crelterm))
   231       val _ = writeln ("Instantiating R with " ^ (string_of_cterm crelterm))
   232 			val _ = writeln "Proving subgoals"
   232       val _ = writeln "Proving subgoals"
   233 		    in
   233         in
   234 			next_st |> cterm_instantiate [(crel, crelterm)]
   234       next_st |> cterm_instantiate [(crel, crelterm)]
   235 				|> SINGLE (rtac wf_measures 1) |> the
   235         |> SINGLE (rtac wf_measures 1) |> the
   236 				|> fold prove_row clean_table
   236         |> fold prove_row clean_table
   237 				|> Seq.single
   237         |> Seq.single
   238                     end
   238                     end
   239             end
   239             end
   240     end
   240     end
   241 
   241 
   242 val lexicographic_order = Method.SIMPLE_METHOD lexicographic_order_tac
   242 val lexicographic_order = Method.SIMPLE_METHOD lexicographic_order_tac