src/HOL/Library/size_change_termination.ML
changeset 22370 44679bbcf43b
parent 22359 94a794672c8b
child 22371 c9f5895972b0
equal deleted inserted replaced
22369:a7263f330494 22370:44679bbcf43b
   180       measures
   180       measures
   181     end
   181     end
   182 
   182 
   183 
   183 
   184 
   184 
   185 val mk_number = HOLogic.mk_nat
   185 val mk_number = HOLogic.mk_nat o IntInf.fromInt
   186 val dest_number = HOLogic.dest_nat
   186 val dest_number = IntInf.toInt o HOLogic.dest_nat
   187 
   187 
   188 fun nums_to i = map mk_number (0 upto (i - 1))
   188 fun nums_to i = map mk_number (0 upto (i - 1))
   189 
   189 
   190 
   190 
   191 fun unfold_then_auto thm = 
   191 fun unfold_then_auto thm = 
   341       |> cterm_of thy 
   341       |> cterm_of thy 
   342       |> try_to_prove (unfold_then_auto decreq_def)
   342       |> try_to_prove (unfold_then_auto decreq_def)
   343       |> simple_result
   343       |> simple_result
   344 
   344 
   345 
   345 
   346 fun pr_tac (st : thm) = Seq.single (Output.warning (PolyML.makestring st); st)
       
   347 fun pr_thm (st : thm) = (Output.warning (PolyML.makestring st); st)
       
   348 
       
   349 
       
   350 fun build_approximating_graph thy Dtab Mtab Mss mlens mint nint =
   346 fun build_approximating_graph thy Dtab Mtab Mss mlens mint nint =
   351     let 
   347     let 
   352       val D1 = Dtab mint and D2 = Dtab nint
   348       val D1 = Dtab mint and D2 = Dtab nint
   353       val Mst1 = Mtab mint and Mst2 = Mtab nint
   349       val Mst1 = Mtab mint and Mst2 = Mtab nint
   354 
   350 
   478     in
   474     in
   479       tac (instantiate' [] [SOME (cterm_of thy ACG), SOME (cterm_of thy mfuns)] st)
   475       tac (instantiate' [] [SOME (cterm_of thy ACG), SOME (cterm_of thy mfuns)] st)
   480     end
   476     end
   481                   
   477                   
   482 
   478 
   483 
       
   484 
       
   485 
       
   486 
       
   487 
       
   488 
       
   489 
       
   490 
       
   491 
       
   492 
       
   493 (* Faster implementation of transitive closures *)
       
   494 
       
   495 (* sedge: Only relevant edges. Qtrees have separate value for 0 *)
       
   496 datatype sedge = LESS | LEQ | BOTH
       
   497 
       
   498 
       
   499 
       
   500 datatype key = KHere | K0 of key | K1 of key
       
   501 
       
   502 datatype 'a stree = 
       
   503   sLeaf of 'a
       
   504   | sBranch of ('a * 'a stree * 'a stree)
       
   505 
       
   506 (*
       
   507 fun lookup (sLeaf x) KHere = x
       
   508   | lookup (sBranch x s t) KHere = x
       
   509   | lookup (sBranch x s t) (K0 k) = lookup s k
       
   510   | lookup (sBranch x s t) (K1 k) = lookup t k
       
   511   | lookup _ _ = raise Match
       
   512 *)
       
   513 
       
   514 datatype 'a qtree =
       
   515   QEmpty
       
   516   | QNode of 'a
       
   517   | QQuad of ('a qtree * 'a qtree * 'a qtree * 'a qtree)
       
   518 
       
   519 fun qlookup z QEmpty k l = z
       
   520   | qlookup z (QNode S) k l = S
       
   521   | qlookup z (QQuad (a, b, c, d)) (K0 k) (K0 l) = qlookup z a k l
       
   522   | qlookup z (QQuad (a, b, c, d)) (K0 k) (K1 l) = qlookup z b k l
       
   523   | qlookup z (QQuad (a, b, c, d)) (K1 k) (K0 l) = qlookup z c k l
       
   524   | qlookup z (QQuad (a, b, c, d)) (K1 k) (K1 l) = qlookup z d k l
       
   525   | qlookup _ _ _ _ = raise Match
       
   526 
       
   527 
       
   528 
       
   529 (* Size-change graphs *)
       
   530 
       
   531 type
       
   532   scg = sedge qtree
       
   533 
       
   534 
       
   535 (* addition of single edges *)
       
   536 fun add_sedge BOTH _ = BOTH
       
   537   | add_sedge LESS LESS = LESS
       
   538   | add_sedge LESS _ = BOTH
       
   539   | add_sedge LEQ LEQ = LEQ
       
   540   | add_sedge LEQ _ = BOTH
       
   541 
       
   542 fun mult_sedge LESS _ = LESS
       
   543   | mult_sedge _ LESS = LESS
       
   544   | mult_sedge LEQ x = x
       
   545   | mult_sedge BOTH _ = BOTH
       
   546 
       
   547 fun subsumes_edge LESS LESS = true
       
   548   | subsumes_edge LEQ _ = true
       
   549   | subsumes_edge _ _ = false
       
   550 
       
   551 
       
   552 
       
   553 
       
   554 (* subsumes_SCG G H := G contains strictly less estimations than H *)
       
   555 fun subsumes_SCG (QEmpty : scg) (H : scg) = true
       
   556   | subsumes_SCG (QQuad (a, b, c, d)) (QQuad (e,f,g,h)) =
       
   557     (subsumes_SCG a e) andalso (subsumes_SCG b f)
       
   558     andalso (subsumes_SCG c g) andalso (subsumes_SCG d h)
       
   559   | subsumes_SCG (QNode e) (QNode e') = subsumes_edge e e'
       
   560   | subsumes_SCG _ QEmpty = false
       
   561   | subsumes_SCG _ _ = raise Match
       
   562 
       
   563 
       
   564 (* managing lists of SCGs. *)
       
   565 
       
   566 (* 
       
   567  Graphs are partially ordered. A list of graphs has the invariant that no G,H with G <= H.
       
   568  To maintain this when adding a new graph G, check 
       
   569    (1) G <= H for some H in l => Do nothing
       
   570    (2) has to be added. Then, all H <= G can be removed. 
       
   571 
       
   572  We can check (2) first, removing all smaller graphs. 
       
   573  If we could remove at least one, just add G in the end (Invariant!).
       
   574  Otherwise, check again, if G needs to be added at all. 
       
   575 
       
   576  OTOH, doing (1) first is probably better, because it does not produce garbage unless needed.
       
   577 
       
   578  The definition is tail-recursive. Order is not preserved (unneccessary).
       
   579 *)
       
   580 
       
   581 
       
   582 
       
   583 fun add_scg' G Hs = (* returns a flag indicating if the graph was really added *)
       
   584     if exists (fn H => subsumes_SCG H G) Hs then (false, Hs)  (* redundant addition *)
       
   585     else (true, G :: remove (uncurry subsumes_SCG) G Hs) (* remove all new redundancy and add G *)
       
   586          (* NB: This does the second checks twice :-( *)
       
   587 
       
   588 (* Simpler version *)
       
   589 fun add_scg' G Hs = (not (member (op =) Hs G), insert (op =) G Hs)
       
   590 
       
   591 
       
   592 val add_scg = snd oo add_scg' (* without flag *)
       
   593 
       
   594 
       
   595 
       
   596 
       
   597 
       
   598 (* quadtrees *)
       
   599 
       
   600 fun keylen 0 = 0 
       
   601   | keylen n = (keylen (n div 2)) + 1
       
   602 
       
   603 fun mk_key 0 _  = KHere
       
   604   | mk_key l m = if m mod 2 = 0 
       
   605                  then K0 (mk_key (l - 1) (m div 2)) 
       
   606                  else K1 (mk_key (l - 1) (m div 2)) 
       
   607 
       
   608 
       
   609 fun qupdate f KHere KHere n = f n
       
   610   | qupdate f (K0 k) (K0 k') (QQuad (a, b, c, d)) = QQuad (qupdate f k k' a, b, c, d)
       
   611   | qupdate f (K0 k) (K1 k') (QQuad (a, b, c, d)) = QQuad (a, qupdate f k k' b, c, d)
       
   612   | qupdate f (K1 k) (K0 k') (QQuad (a, b, c, d)) = QQuad (a, b, qupdate f k k' c, d)
       
   613   | qupdate f (K1 k) (K1 k') (QQuad (a, b, c, d)) = QQuad (a, b, c, qupdate f k k' d)
       
   614 
       
   615 
       
   616 
       
   617 
       
   618 
       
   619 
       
   620 
       
   621 
       
   622 (* quadtree composition *)
       
   623 
       
   624 fun qadd A QEmpty q = q
       
   625   | qadd A q QEmpty = q
       
   626   | qadd A (QNode s) (QNode t) = QNode (A s t)
       
   627   | qadd A (QQuad (a, b, c, d)) (QQuad (e, f, g, h)) =
       
   628     QQuad (qadd A a e, qadd A b f, qadd A c g, qadd A d h)
       
   629   | qadd _ _ _ = raise Match
       
   630 
       
   631 
       
   632 fun qmult A m QEmpty H = QEmpty
       
   633   | qmult A m G QEmpty = QEmpty
       
   634   | qmult A m (QNode x) (QNode y) = QNode (m x y)
       
   635   | qmult A m (QQuad (a, b, c, d)) (QQuad (e, f, g, h)) = 
       
   636     QQuad ((qadd A (qmult A m a e) (qmult A m b g)),
       
   637            (qadd A (qmult A m a f) (qmult A m b h)),
       
   638            (qadd A (qmult A m c e) (qmult A m d g)),
       
   639            (qadd A (qmult A m c f) (qmult A m d h)))
       
   640   | qmult _ _ _ _ = raise Match
       
   641 
       
   642 
       
   643 val (mult_scg : scg -> scg -> scg) = qmult add_sedge mult_sedge
       
   644 
       
   645 (* Misc notes:
       
   646 
       
   647 - When building the tcl: Check on addition and raise FAIL if the property is not true... (pract)
       
   648 
       
   649 - Can we reduce subsumption checking by some integer fingerprints?
       
   650 
       
   651  Number of edges: LESS(G) LEQ(G)
       
   652   G <= H ==> E(G) <= E(H)
       
   653   
       
   654 
       
   655 
       
   656 How to check:
       
   657 
       
   658 For each pair of adjacent edges: n -> m -> q
       
   659  compute all product SCGS and check if they are subsumed by something in the tcl.
       
   660 
       
   661  all midnode m: all fromnode n: all tonode q: alledges (n,m) e: alledges (m,q) e': subsumes (e*e') (edgs m,q)
       
   662 
       
   663  This is still quite a lot of checking... But: no garbage, just inspection. Can probably be done in logic. 
       
   664 
       
   665 *)
       
   666 
       
   667 
       
   668 
       
   669 (* Operations on lists: These preserve the invariants *)
       
   670 fun SCGs_mult Gs Hs = fold (fn (G,H) => add_scg (mult_scg G H)) (product Gs Hs) []
       
   671 val SCGs_plus = fold add_scg
       
   672 
       
   673 
       
   674 fun add_scgs Gs Hs = fold_rev (fn G => fn (Xs,As) => 
       
   675                                       let val (b, Xs') = add_scg' G Xs
       
   676                                       in (Xs', if b then G::As else As) end)
       
   677                           Gs (Hs,[])
       
   678 
       
   679 (* Transitive Closure for lists of SCGs *)
       
   680 fun SCGs_tcl Gs =
       
   681     let
       
   682       fun aux S [] = S
       
   683         | aux S (H::HS) =
       
   684           let val (S', Ns) = add_scgs (map (mult_scg H) Gs) S
       
   685           in aux S' (SCGs_plus Ns HS) end
       
   686     in
       
   687       aux Gs Gs
       
   688     end
       
   689 
       
   690 
       
   691 
       
   692 (* Kleene algorithm: DP version, with imperative array... *)
       
   693 
       
   694 
       
   695 
       
   696 
       
   697 (* Terrible imperative stuff: *)
       
   698 type matrix = scg list array array
       
   699 
       
   700 fun mupdate i j f M = 
       
   701     let 
       
   702       val row = Array.sub (M, i)
       
   703       val x = Array.sub (row, j)
       
   704     in 
       
   705       Array.update (row, j, f x)
       
   706     end
       
   707 
       
   708 fun mget i j M = Array.sub(Array.sub(M,i),j)
       
   709 
       
   710 fun print_scg (x : scg) = Output.warning (PolyML.makestring x);
       
   711 
       
   712 
       
   713 fun kleene add mult tcl M =
       
   714     let
       
   715       val n = Array.length M
       
   716 
       
   717       fun update Mkk i j k = 
       
   718           let
       
   719             val Mik = mget i k M
       
   720             val Mkj = mget k j M
       
   721           in
       
   722             mupdate i j (fn X => X |> add (mult Mik (mult Mkk Mkj))
       
   723                                    |> add (mult Mik Mkj))
       
   724                     M
       
   725           end
       
   726 
       
   727       fun step k () =
       
   728           let
       
   729             val _ = mupdate k k tcl M
       
   730             val Mkk = mget k k M
       
   731 
       
   732             val no_k = filter_out (fn i => i = k) (0 upto (n - 1)) 
       
   733             val _ = fold (fn i => fold (fn j => K (update Mkk i j k)) no_k) no_k ()
       
   734 
       
   735             val _ = fold (fn i => K (update Mkk i k k)) no_k ()
       
   736 
       
   737             val _ = fold (fn j => K (update Mkk k j k)) no_k ()
       
   738           in
       
   739             ()
       
   740           end
       
   741     in
       
   742       fold step (0 upto (n - 1)) ()
       
   743     end
       
   744 
       
   745 val (SCGs_kleene : matrix -> unit) = kleene SCGs_plus SCGs_mult SCGs_tcl
       
   746 
       
   747 
       
   748 fun andop x y = x andalso y
       
   749 fun orop x y = x orelse y
       
   750 
       
   751 fun array2 n x = Array.tabulate (n, (fn i => Array.array (n, x)))
       
   752 
       
   753 (*val bool_kleene = kleene orop andop I
       
   754 
       
   755 
       
   756 fun test_bool () =
       
   757     let
       
   758       val M = array2 2 false
       
   759       val _ = mupdate 0 1 (K true) M
       
   760       val _ = mupdate 1 0 (K true) M
       
   761       val _ = bool_kleene M
       
   762     in
       
   763       M
       
   764     end
       
   765 *)
       
   766 
       
   767 (* Standard 2-2-Size-change graphs *)
       
   768 
       
   769 val swap = QQuad(QEmpty, QNode LEQ,
       
   770                  QNode LEQ, QEmpty)
       
   771 
       
   772 val swapRTop = QQuad(QNode LESS, QNode LEQ,
       
   773                      QNode LEQ, QEmpty)
       
   774 
       
   775 val BTopRBot = QQuad(QNode LEQ, QEmpty,
       
   776                      QEmpty, QNode LESS)
       
   777 
       
   778 val RTopBBot = QQuad(QNode LESS, QEmpty,
       
   779                      QEmpty, QNode LEQ)
       
   780 
       
   781 val R2Straight = QQuad(QNode LESS, QEmpty,
       
   782                        QEmpty, QNode LESS)
       
   783 
       
   784 val R3StraightUp = QQuad(QNode LESS, QEmpty,
       
   785                          QNode LESS, QNode LESS)
       
   786 
       
   787 val R3StraightDn = QQuad(QNode LESS, QNode LESS,
       
   788                          QEmpty, QNode LESS)
       
   789 
       
   790 
       
   791 
       
   792 
       
   793 val diag = QQuad(QEmpty, QNode LEQ,
       
   794                  QEmpty, QEmpty)
       
   795 
       
   796 val straight = QQuad(QNode LEQ, QEmpty,
       
   797                      QEmpty, QEmpty)
       
   798 
       
   799 
       
   800 
       
   801 val R467913 = ([R2Straight, R3StraightDn, R3StraightDn] @ replicate 11 R2Straight @ [R3StraightUp, R3StraightUp])
       
   802                 |> map single
       
   803 
       
   804 val swapPos = [(0,8),(0,9),(0,10),(3,4),(3,5),(11,12)]
       
   805 
       
   806 val BRPos = (map (pair 5) (0 :: (3 upto 7)))
       
   807             @ (map (pair 8) [8,9,11,12,13])
       
   808             @ (map (pair 12) [8,9,11,12,13])
       
   809 
       
   810 val RBPos = map (pair 10) (3 upto 10)
       
   811 
       
   812 fun afold f arr x = Array.foldl (uncurry f) x arr
       
   813 
       
   814 fun msize M = afold (afold (curry op + o length)) M 0
       
   815 
       
   816 fun TestM () =
       
   817     let
       
   818       val M = array2 16 ([] : scg list)
       
   819       val _ = Array.update (M, 4, Array.fromList R467913)
       
   820       val _ = Array.update (M, 6, Array.fromList R467913)
       
   821       val _ = Array.update (M, 7, Array.fromList R467913)
       
   822       val _ = Array.update (M, 9, Array.fromList R467913)
       
   823       val _ = Array.update (M, 13, Array.fromList R467913)
       
   824 
       
   825       val _ = map (fn (i,j) => mupdate i j (K [swap]) M) swapPos
       
   826       val _ = map (fn (i,j) => mupdate i j (K [BTopRBot]) M) BRPos
       
   827       val _ = map (fn (i,j) => mupdate i j (K [RTopBBot]) M) RBPos
       
   828 
       
   829       val _ = mupdate 1 14 (K [swapRTop]) M
       
   830       val _ = mupdate 2 15 (K [swapRTop]) M
       
   831 
       
   832       val G = [QQuad (QNode LEQ, QNode LESS, QEmpty, QNode LESS)]
       
   833       val _ = mupdate 5 1 (K G) M
       
   834       val _ = mupdate 8 2 (K G) M
       
   835       val _ = mupdate 12 2 (K G) M
       
   836 
       
   837       val G = [QQuad (QNode LESS, QEmpty, QNode LESS, QNode LEQ)]
       
   838       val _ = mupdate 10 14 (K G) M
       
   839 
       
   840       val G = [QQuad (QEmpty, QNode LEQ, QNode LESS, QNode LESS)]
       
   841       val _ = mupdate 14 1 (K G) M
       
   842       val _ = mupdate 14 2 (K G) M
       
   843       val _ = mupdate 15 1 (K G) M
       
   844       val _ = mupdate 15 2 (K G) M
       
   845     in
       
   846       M
       
   847     end
       
   848 
       
   849 
       
   850 
       
   851 
       
   852 
       
   853 fun add_edge x QEmpty = QNode x
       
   854   | add_edge x (QNode y) = QNode (add_sedge x y)
       
   855 
       
   856 
       
   857 fun sedge2ML (Const ("SCT_Definition.sedge.LESS", _)) = LESS
       
   858   | sedge2ML (Const ("SCT_Definition.sedge.LEQ", _)) = LEQ
       
   859 
       
   860 
       
   861 
       
   862 
       
   863 
       
   864 
       
   865 
       
   866 
       
   867 
       
   868 
       
   869 
       
   870 
       
   871 
       
   872 
       
   873 
       
   874 
       
   875 end                   
   479 end                   
   876 
   480 
   877 
   481 
   878 
   482 
   879 
   483