diff options
Diffstat (limited to 'hol-light/TacticRecording/hiproofs.ml')
-rw-r--r-- | hol-light/TacticRecording/hiproofs.ml | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/hol-light/TacticRecording/hiproofs.ml b/hol-light/TacticRecording/hiproofs.ml new file mode 100644 index 00000000..b48dd2da --- /dev/null +++ b/hol-light/TacticRecording/hiproofs.ml @@ -0,0 +1,279 @@ +(* ========================================================================== *) +(* HIPROOFS (HOL LIGHT) *) +(* - Hiproofs and refactoring operations *) +(* *) +(* By Mark Adams *) +(* Copyright (c) Univeristy of Edinburgh, 2012 *) +(* ========================================================================== *) + + +(* This file defines a hiproof [1] datatype and various operations on it. *) +(* The datatype closely resembles that proposed in [2], with the notable *) +(* difference that atomic steps carry their arity. *) + +(* [1] "Hiproofs: A Hierarchical Notion of Proof Tree", Denney, Power & *) +(* Tourlas, 2006. *) +(* [2] "A Tactic Language for Hiproofs", Aspinall, Denney & Luth, 2008. *) + + + +(* ** DATATYPE ** *) + + +(* Hiproof datatype *) + +(* Note that atomic tactics are labelled with their arity, corresponding to *) +(* how many subgoals they result in. An arity of -1 indicates unknown, and 0 *) +(* indicates a tactic that completes its goal. *) + +type hiproof = + Hactive (* Active subgoal *) + | Hatomic of (finfo * int) (* Atomic tactic + arity *) + | Hidentity (* Null, for wiring *) + | Hlabelled of (finfo * hiproof) (* Box *) + | Hsequence of (hiproof * hiproof) (* Serial application *) + | Htensor of hiproof list (* Parallel application *) + | Hempty;; (* Completed goal *) + + +(* Constructors and destructors *) + +let hsequence (h1,h2) = Hsequence (h1,h2);; + +let dest_hsequence h = + match h with + Hsequence hh -> hh + | _ -> failwith "Not a sequence hiproof";; + +let is_hsequence h = can dest_hsequence h;; + +let dest_atomic_hiproof h = + match h with + Hatomic (info,n) -> (info,n) + | _ -> failwith "dest_atomic_hiproof: Not an atomic hiproof";; + + +(* Arity *) + +let rec hiproof_arity h = + match h with + Hactive -> 1 + | Hatomic (_,n) -> n + | Hidentity -> 1 + | Hlabelled (_,h0) -> hiproof_arity h0 + | Hsequence (h1,h2) -> hiproof_arity h2 + | Htensor hs -> sum (map hiproof_arity hs) + | Hempty -> 0;; + + +(* Hitrace *) + +type hitrace = + Hicomment of int list + | Hiproof of hiproof;; + + + +(* ** REFACTORING OPERATIONS ** *) + + +(* Generic refactoring operation *) + +(* Applies a refactoring function 'foo' at every level of hiproof 'h', from *) +(* bottom up. If the 'r' flag is set then refactoring is repeated bottom up *) +(* whenever 'foo' makes a change. Note that if 'foo' makes no change then it *) +(* should just return its input hiproof (rather than raise an exception). *) + +let rec refactor_hiproof r foo h = + let h' = + match h with + Hlabelled (info,h0) + -> let h0' = refactor_hiproof r foo h0 in + Hlabelled (info,h0') + | Hsequence (h1,h2) + -> let h1' = refactor_hiproof r foo h1 in + let h2' = refactor_hiproof r foo h2 in + Hsequence (h1',h2') + | Htensor hs + -> let hs' = map (refactor_hiproof r foo) hs in + Htensor hs' + | _ -> h in + let h'' = if (h' = h) then h else h' in + let h''' = foo h'' in + if r & not (h''' = h'') + then refactor_hiproof r foo h''' + else h''';; + + +(* Trivial simplification *) + +(* Removes basic algebraic identities/zeros. *) + +let collapse_tensor h hs = + match h with + Hempty -> hs + | Htensor hs0 -> hs0 @ hs + | _ -> h :: hs;; + +let trivsimp_hiproof h = + let trivsimp h = + match h with + Hatomic ((Some"ALL_TAC",[]), _) -> Hidentity + | Hsequence (h1, Hempty) -> h1 + | Hsequence (h1, Hidentity) -> h1 + | Hsequence (Hidentity, h2) -> h2 + | Htensor [] -> Hempty + | Htensor [h0] -> h0 + | Htensor hs0 -> if (forall (fun h0 -> h0 = Hidentity) hs0) + then Hidentity + else Htensor (foldr collapse_tensor hs0 []) + | _ -> h in + refactor_hiproof true trivsimp h;; + + +(* Matching up lists of hiproofs *) + +let rec matchup_hiproofs hs1 hs2 = + match hs1 with + [] -> [] + | h1::hs01 + -> let n1 = hiproof_arity h1 in + let (hs2a,hs2b) = try chop_list n1 hs2 + with Failure _ -> + if (n1 = -1) + then failwith "matchup_hiproofs: unknown arity" + else failwith "matchup_hiproofs: Internal error - \ + inconsistent arities" in + Hsequence (h1, Htensor hs2a) :: (matchup_hiproofs hs01 hs2b);; + + +(* Separating out lists of hiproofs *) + +let separate_hiproofs0 h (hs01,hs02) = + match h with + Hsequence (h1,h2) + -> (h1::hs01, h2::hs02) + | _ -> let n = hiproof_arity h in + let h2 = Htensor (copy n Hidentity) in + (h::hs01, h2::hs02);; + +let separate_hiproofs hs = foldr separate_hiproofs0 hs ([],[]);; + + +(* Delabelling *) + +(* Strips out any boxes from the proof. Note that some boxes, such as *) +(* 'SUBGOAL_THEN', cannot be stripped out without spoiling the proof, and so *) +(* are left alone. *) + +let delabel_hiproof h = + let delabel h = + match h with + Hlabelled ((Some "SUBGOAL_THEN",_),h0) + -> h + | Hlabelled (_,h0) + -> h0 + | _ -> h in + refactor_hiproof true delabel h;; + + +(* Right-grouping *) + +(* Expands the proof into a right-associative sequence, with tensor *) +(* compounding on the right. Leaves all boxes unchanged. *) + +let rightgroup_hiproof h = + let rightgroup h = + match h with + Hsequence (Hsequence (h1, Htensor hs2), Htensor hs3) + -> Hsequence (h1, Htensor (matchup_hiproofs hs2 hs3)) + | Hsequence (Hsequence (h1, Htensor hs2), h3) + -> Hsequence (h1, Htensor (matchup_hiproofs hs2 [h3])) + | _ -> h in + refactor_hiproof true rightgroup h;; + + +(* Left-grouping *) + +(* Expands the proof into a left-associative sequence. *) + +let leftgroup_hiproof h = + let leftgroup h = + match h with + Hsequence (h1, Hsequence (h2, h3)) + -> Hsequence (Hsequence (h1,h2), h3) +(* | Hsequence (h1, Htensor hs2) + -> if (exists is_hsequence hs2) + then let (hs2a,hs2b) = separate_hiproofs hs2 in + Hsequence (Hsequence (h1, Htensor hs2a), Htensor hs2b) + else h *) + | _ -> h in + refactor_hiproof true leftgroup h;; + + +(* THEN insertion *) + +(* Looks for opportunities to use 'THEN' tacticals. Note that this disrupts *) +(* arity consistency. *) + +let thenise_hiproof h = + let thenise h = + match h with + Hsequence (h1, Htensor (h2::h2s)) + -> if (forall (fun h0 -> h0 = h2) h2s) + then Hlabelled ((Some "THEN", []), h) + else h + | Hsequence (h1, Hsequence (Htensor (h2::h2s), h3)) + -> if (forall (fun h0 -> h0 = h2) h2s) + then Hsequence + (Hlabelled ((Some "THEN", []), + Hsequence (h1, Htensor (h2::h2s))), h3) + else h + | _ -> h in + refactor_hiproof false thenise h;; + + + +(* ** OTHER OPERATIONS ** *) + + +(* Tactic trace *) + +(* Gives a trace of the basic tactics used in the proof, ignoring how they *) +(* were combined by tacticals. *) + +let rec hiproof_tactic_trace0 h = + match h with + Hactive + -> [active_info] + | Hatomic (info, _) + -> [info] + | Hidentity + -> [] + | Hlabelled (info,h0) + -> hiproof_tactic_trace0 h0 + | Hsequence (h1,h2) + -> (hiproof_tactic_trace0 h1) @ (hiproof_tactic_trace0 h2) + | Htensor hs + -> flat (map hiproof_tactic_trace0 hs) + | Hempty + -> [];; + +let hiproof_tactic_trace h = (hiproof_tactic_trace0 o delabel_hiproof) h;; + + +(* Block trace *) + +(* Gives a trace of the hiproofs used in the proof, stopping at boxes. *) + +let rec hiproof_block_trace0 ns0 h = + match h with + | Hsequence (h1,h2) + -> (hiproof_block_trace0 ns0 h1) @ (hiproof_block_trace0 ns0 h2) + | Htensor hs + -> let nss = map (fun n -> ns0 @ [n]) (1 -- length hs) in + flat (map (fun (ns,h) -> (Hicomment ns) :: hiproof_block_trace0 ns h) + (zip nss hs)) + | _ -> [Hiproof h];; + +let hiproof_block_trace h = hiproof_block_trace0 [] h;; |