src/HOL/Tools/function_package/lexicographic_order.ML
author bulwahn
Tue, 13 Feb 2007 10:09:21 +0100
changeset 22309 87ec1ca65312
parent 22258 0967b03844b5
child 22325 be61bd159a99
permissions -rw-r--r--
improved lexicographic order termination tactic
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
     1
(*  Title:       HOL/Tools/function_package/lexicographic_order.ML
21201
803bc7672d17 method exported
krauss
parents: 21131
diff changeset
     2
    ID:          $Id$
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
     3
    Author:      Lukas Bulwahn, TU Muenchen
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
     4
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
     5
Method for termination proofs with lexicographic orderings.
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
     6
*)
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
     7
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
     8
signature LEXICOGRAPHIC_ORDER =
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
     9
sig
21319
cf814e36f788 replaced "auto_term" by the simpler method "relation", which does not try
krauss
parents: 21237
diff changeset
    10
  val lexicographic_order : Proof.context -> Method.method
21510
7e72185e4b24 exported mk_base_funs for use by size-change tools
krauss
parents: 21319
diff changeset
    11
7e72185e4b24 exported mk_base_funs for use by size-change tools
krauss
parents: 21319
diff changeset
    12
  (* exported for use by size-change termination prototype.
7e72185e4b24 exported mk_base_funs for use by size-change tools
krauss
parents: 21319
diff changeset
    13
     FIXME: provide a common interface later *)
7e72185e4b24 exported mk_base_funs for use by size-change tools
krauss
parents: 21319
diff changeset
    14
  val mk_base_funs : typ -> term list
22309
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
    15
  (* exported for debugging *)
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    16
  val setup: theory -> theory
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    17
end
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    18
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    19
structure LexicographicOrder : LEXICOGRAPHIC_ORDER =
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    20
struct
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    21
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    22
(* Theory dependencies *)
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    23
val measures = "List.measures"
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    24
val wf_measures = thm "wf_measures"
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    25
val measures_less = thm "measures_less"
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    26
val measures_lesseq = thm "measures_lesseq"
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    27
                      
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    28
fun del_index (n, []) = []
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    29
  | del_index (n, x :: xs) =
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    30
    if n>0 then x :: del_index (n - 1, xs) else xs 
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    31
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    32
fun transpose ([]::_) = []
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    33
  | transpose xss = map hd xss :: transpose (map tl xss)
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    34
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    35
fun mk_sum_case (f1, f2) =
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    36
    case (fastype_of f1, fastype_of f2) of
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    37
      (Type("fun", [A, B]), Type("fun", [C, D])) =>
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    38
      if (B = D) then
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    39
        Const("Datatype.sum.sum_case", (A --> B) --> (C --> D) --> Type("+", [A,C]) --> B) $ f1 $ f2
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    40
      else raise TERM ("mk_sum_case: range type mismatch", [f1, f2]) 
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    41
    | _ => raise TERM ("mk_sum_case", [f1, f2])
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    42
                 
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    43
fun dest_wf (Const ("Wellfounded_Recursion.wf", _) $ t) = t
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    44
  | dest_wf t = raise TERM ("dest_wf", [t])
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    45
                      
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    46
datatype cell = Less of thm | LessEq of thm | None of thm | False of thm;
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    47
         
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    48
fun is_Less cell = case cell of (Less _) => true | _ => false  
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    49
                                                        
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    50
fun is_LessEq cell = case cell of (LessEq _) => true | _ => false
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    51
                                                            
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    52
fun thm_of_cell cell =
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    53
    case cell of 
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    54
      Less thm => thm
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    55
    | LessEq thm => thm
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    56
    | False thm => thm
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    57
    | None thm => thm
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    58
                  
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    59
fun mk_base_fun_bodys (t : term) (tt : typ) =
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    60
    case tt of
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    61
      Type("*", [ft, st]) => (mk_base_fun_bodys (Const("fst", tt --> ft) $ t) ft) @ (mk_base_fun_bodys (Const("snd", tt --> st) $ t) st)      
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    62
    | _ => [(t, tt)]
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    63
           
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    64
fun mk_base_fun_header fulltyp (t, typ) =
21816
453fd9857b4c nat type now has a size functin => no longer needed as special case
krauss
parents: 21757
diff changeset
    65
    Abs ("x", fulltyp, Const("Nat.size", typ --> HOLogic.natT) $ t)
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    66
         
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    67
fun mk_base_funs (tt: typ) = 
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    68
    mk_base_fun_bodys (Bound 0) tt |>
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    69
                      map (mk_base_fun_header tt)
22258
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
    70
22309
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
    71
fun mk_funorder_funs (tt : typ) (one : bool) : Term.term list =
22258
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
    72
    case tt of
22309
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
    73
      Type("+", [ft, st]) => let
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
    74
                               val ft_funs = mk_funorder_funs ft
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
    75
                               val st_funs = mk_funorder_funs st 
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
    76
                             in
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
    77
                               (if one then 
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
    78
                                 (product (ft_funs true) (st_funs false)) @ (product (ft_funs false) (st_funs true))
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
    79
                               else
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
    80
                                 product (ft_funs false) (st_funs false)) 
22258
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
    81
                                    |> map mk_sum_case
22309
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
    82
                             end
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
    83
    | _ => if one then [Abs ("x", tt, HOLogic.Suc_zero)] else [Abs ("x", tt, HOLogic.zero)]
22258
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
    84
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    85
fun mk_ext_base_funs (tt : typ) =
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    86
    case tt of
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    87
      Type("+", [ft, st]) =>
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    88
      product (mk_ext_base_funs ft) (mk_ext_base_funs st)
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    89
              |> map mk_sum_case
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    90
    | _ => mk_base_funs tt
22258
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
    91
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
    92
fun mk_all_measure_funs (tt : typ) =
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
    93
    case tt of
22309
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
    94
      Type("+", _) => (mk_ext_base_funs tt) @ (mk_funorder_funs tt true)
22258
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
    95
    | _ => mk_base_funs tt
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    96
           
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    97
fun dest_term (t : term) =
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
    98
    let
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
    99
      val (vars, prop) = (FundefLib.dest_all_all t)
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   100
      val prems = Logic.strip_imp_prems prop
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   101
      val (tuple, rel) = Logic.strip_imp_concl prop
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   102
                         |> HOLogic.dest_Trueprop 
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   103
                         |> HOLogic.dest_mem
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   104
      val (lhs, rhs) = HOLogic.dest_prod tuple
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   105
    in
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   106
      (vars, prems, lhs, rhs, rel)
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   107
    end
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   108
    
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   109
fun mk_goal (vars, prems, lhs, rhs) rel =
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   110
    let 
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   111
      val concl = HOLogic.mk_binrel rel (lhs, rhs) |> HOLogic.mk_Trueprop
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   112
    in  
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   113
      Logic.list_implies (prems, concl) |>
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   114
                         fold_rev FundefLib.mk_forall vars
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   115
    end
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   116
    
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   117
fun prove (thy: theory) (t: term) =
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   118
    cterm_of thy t |> Goal.init 
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   119
    |> SINGLE (CLASIMPSET auto_tac) |> the
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   120
    
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   121
fun mk_cell (thy : theory) (vars, prems) (lhs, rhs) = 
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   122
    let 
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   123
      val goals = mk_goal (vars, prems, lhs, rhs) 
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   124
      val less_thm = goals "Orderings.less" |> prove thy
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   125
    in
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   126
      if Thm.no_prems less_thm then
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   127
        Less (Goal.finish less_thm)
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   128
      else
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   129
        let
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   130
          val lesseq_thm = goals "Orderings.less_eq" |> prove thy
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   131
        in
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   132
          if Thm.no_prems lesseq_thm then
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   133
            LessEq (Goal.finish lesseq_thm)
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   134
          else 
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   135
            if prems_of lesseq_thm = [HOLogic.Trueprop $ HOLogic.false_const] then False lesseq_thm
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   136
            else None lesseq_thm
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   137
        end
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   138
    end
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   139
    
22258
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
   140
fun mk_row (thy: theory) measure_funs (t : term) =
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   141
    let
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   142
      val (vars, prems, lhs, rhs, _) = dest_term t
22258
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
   143
      val lhs_list = map (fn x => x $ lhs) measure_funs
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
   144
      val rhs_list = map (fn x => x $ rhs) measure_funs
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   145
    in
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   146
      map (mk_cell thy (vars, prems)) (lhs_list ~~ rhs_list)
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   147
    end
22309
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   148
    
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   149
fun pr_cell cell = case cell of Less _ => " <  " 
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   150
                              | LessEq _ => " <= " 
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   151
                              | None _ => " N  "
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   152
                              | False _ => " F  "
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   153
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   154
fun pr_table table = writeln (cat_lines (map (fn r => concat (map pr_cell r)) table))
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   155
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   156
fun check_col ls = (forall (fn c => is_Less c orelse is_LessEq c) ls) andalso not (forall (fn c => is_LessEq c) ls)
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   157
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   158
fun transform_table table col = table |> filter_out (fn x => is_Less (nth x col)) |> map (curry del_index col)
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   159
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   160
fun transform_order col order = map (fn x => if x>=col then x+1 else x) order
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   161
      
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   162
(* simple depth-first search algorithm for the table *)
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   163
fun search_table table =
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   164
    case table of
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   165
      [] => SOME []
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   166
    | _ =>
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   167
      let
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   168
        val col = find_index (check_col) (transpose table)
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   169
      in case col of
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   170
           ~1 => NONE 
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   171
         | _ =>
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   172
           let
22309
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   173
             val order_opt = (table, col) |-> transform_table |> search_table
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   174
           in case order_opt of
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   175
                NONE => NONE
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   176
              | SOME order =>SOME (col::(transform_order col order))
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   177
           end
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   178
      end
22258
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
   179
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
   180
(* find all positions of elements in a list *) 
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
   181
fun find_index_list pred =
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
   182
  let fun find _ [] = []
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
   183
        | find n (x :: xs) = if pred x then n::(find (n + 1) xs) else find (n + 1) xs;
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
   184
  in find 0 end;
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
   185
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
   186
(* simple breadth-first search algorithm for the table *) 
22309
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   187
fun bfs_search_table nodes =
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   188
    case nodes of
22258
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
   189
      [] => sys_error "INTERNAL ERROR IN lexicographic order termination tactic - fun search_table (breadth search finished)" 
22309
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   190
    | (node::rnodes) => let
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   191
	val (order, table) = node
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   192
      in
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   193
        case table of
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   194
          [] => SOME (foldr (fn (c, order) => c::transform_order c order) [] (rev order))
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   195
        | _ => let
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   196
	    val cols = find_index_list (check_col) (transpose table)
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   197
          in
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   198
            case cols of
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   199
	      [] => NONE
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   200
            | _ => let 
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   201
              val newtables = map (transform_table table) cols 
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   202
              val neworders = map (fn c => c::order) cols
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   203
              val newnodes = neworders ~~ newtables
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   204
            in
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   205
              bfs_search_table (rnodes @ newnodes)
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   206
            end 
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   207
          end
22258
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
   208
      end
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
   209
22309
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   210
fun nsearch_table table = bfs_search_table [([], table)] 	       
22258
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
   211
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   212
fun prove_row row (st : thm) =
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   213
    case row of
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   214
      [] => sys_error "INTERNAL ERROR IN lexicographic order termination tactic - fun prove_row (row is empty)" 
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   215
    | cell::tail =>
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   216
      case cell of
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   217
        Less less_thm =>
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   218
        let
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   219
          val next_thm = st |> SINGLE (rtac measures_less 1) |> the
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   220
        in
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   221
          implies_elim next_thm less_thm
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   222
        end
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   223
      | LessEq lesseq_thm =>
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   224
        let
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   225
          val next_thm = st |> SINGLE (rtac measures_lesseq 1) |> the
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   226
        in
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   227
          implies_elim next_thm lesseq_thm 
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   228
          |> prove_row tail
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   229
        end
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   230
      | _ => sys_error "INTERNAL ERROR IN lexicographic order termination tactic - fun prove_row (Only expecting Less or LessEq)"
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   231
             
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   232
fun pr_unprovable_subgoals table =
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   233
    filter (fn x => not (is_Less x) andalso not (is_LessEq x)) (flat table)
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   234
    |> map ((fn th => Pretty.string_of (Pretty.chunks (Display.pretty_goals (Thm.nprems_of th) th))) o thm_of_cell)
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   235
    
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   236
fun pr_goal thy t i = 
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   237
    let
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   238
      val (_, prems, lhs, rhs, _) = dest_term t 
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   239
      val prterm = string_of_cterm o (cterm_of thy)
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   240
    in
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   241
      (* also show prems? *)
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   242
        i ^ ") " ^ (prterm lhs) ^ " '<' " ^ (prterm rhs) 
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   243
    end
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   244
    
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   245
fun pr_fun thy t i =
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   246
    (string_of_int i) ^ ") " ^ (string_of_cterm (cterm_of thy t))
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   247
                                             
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   248
(* fun pr_err: prints the table if tactic failed *)
22258
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
   249
fun pr_err table thy tl measure_funs =  
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   250
    let 
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   251
      val gc = map (fn i => chr (i + 96)) (1 upto (length table))
22258
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
   252
      val mc = 1 upto (length measure_funs)
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   253
      val tstr = ("   " ^ (concat (map (fn i => " " ^ (string_of_int i) ^ "  ") mc))) ::
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   254
                 (map2 (fn r => fn i => i ^ ": " ^ (concat (map pr_cell r))) table gc)
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   255
      val gstr = ("Goals:"::(map2 (pr_goal thy) tl gc))
22258
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
   256
      val mstr = ("Measures:"::(map2 (pr_fun thy) measure_funs mc))   
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   257
      val ustr = ("Unfinished subgoals:"::(pr_unprovable_subgoals table))
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   258
    in
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   259
      tstr @ gstr @ mstr @ ustr
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   260
    end
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   261
      
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   262
(* the main function: create table, search table, create relation,
21590
ef7278f553eb tuned spaces/comments;
wenzelm
parents: 21510
diff changeset
   263
   and prove the subgoals *)  (* FIXME proper goal addressing -- do not hardwire 1 *)
21319
cf814e36f788 replaced "auto_term" by the simpler method "relation", which does not try
krauss
parents: 21237
diff changeset
   264
fun lexicographic_order_tac ctxt (st: thm) = 
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   265
    let
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   266
      val thy = theory_of_thm st
21319
cf814e36f788 replaced "auto_term" by the simpler method "relation", which does not try
krauss
parents: 21237
diff changeset
   267
      val termination_thm = the (FundefCommon.get_termination_rule ctxt)
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   268
      val next_st = SINGLE (rtac termination_thm 1) st |> the
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   269
      val premlist = prems_of next_st
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   270
    in
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   271
      case premlist of 
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   272
            [] => error "invalid number of subgoals for this tactic - expecting at least 1 subgoal" 
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   273
          | (wf::tl) => let
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   274
    val (var, prop) = FundefLib.dest_all wf
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   275
    val rel = HOLogic.dest_Trueprop prop |> dest_wf |> head_of
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   276
    val crel = cterm_of thy rel
22258
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
   277
    val measure_funs = mk_all_measure_funs (fastype_of var)
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   278
    val _ = writeln "Creating table"
22258
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
   279
    val table = map (mk_row thy measure_funs) tl
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   280
    val _ = writeln "Searching for lexicographic order"
22309
87ec1ca65312 improved lexicographic order termination tactic
bulwahn
parents: 22258
diff changeset
   281
    (* val _ = pr_table table *)
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   282
    val possible_order = search_table table
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   283
      in
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   284
    case possible_order of 
22258
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
   285
        NONE => error (cat_lines ("Could not find lexicographic termination order:"::(pr_err table thy tl measure_funs)))
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   286
      | SOME order  => let
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   287
      val clean_table = map (fn x => map (nth x) order) table
22258
0967b03844b5 changes in lexicographic_order termination tactic
bulwahn
parents: 21817
diff changeset
   288
      val funs = map (nth measure_funs) order
21757
093ca3efb132 HOLogic cleanup;
wenzelm
parents: 21590
diff changeset
   289
      val list = HOLogic.mk_list (fastype_of var --> HOLogic.natT) funs
21237
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   290
      val relterm = Abs ("x", fastype_of var, Const(measures, (fastype_of list) --> (range_type (fastype_of rel))) $ list)
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   291
      val crelterm = cterm_of thy relterm
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   292
      val _ = writeln ("Instantiating R with " ^ (string_of_cterm crelterm))
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   293
      val _ = writeln "Proving subgoals"
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   294
        in
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   295
      next_st |> cterm_instantiate [(crel, crelterm)]
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   296
        |> SINGLE (rtac wf_measures 1) |> the
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   297
        |> fold prove_row clean_table
b803f9870e97 untabified
krauss
parents: 21201
diff changeset
   298
        |> Seq.single
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   299
                    end
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   300
            end
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   301
    end
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   302
21319
cf814e36f788 replaced "auto_term" by the simpler method "relation", which does not try
krauss
parents: 21237
diff changeset
   303
val lexicographic_order = Method.SIMPLE_METHOD o lexicographic_order_tac
21201
803bc7672d17 method exported
krauss
parents: 21131
diff changeset
   304
21319
cf814e36f788 replaced "auto_term" by the simpler method "relation", which does not try
krauss
parents: 21237
diff changeset
   305
val setup = Method.add_methods [("lexicographic_order", Method.ctxt_args lexicographic_order, "termination prover for lexicographic orderings")]
21131
a447addc14af added lexicographic_order tactic
bulwahn
parents:
diff changeset
   306
21590
ef7278f553eb tuned spaces/comments;
wenzelm
parents: 21510
diff changeset
   307
end