(*
File: status.ML
Author: Bohua Zhan
Definition of updates and proof status.
*)
datatype raw_update
= AddItems of {id: box_id, sc: int option, raw_items: raw_item list}
| AddBoxes of {id: box_id, sc: int option, init_assum: term}
| ResolveBox of {id: box_id, th: thm}
| ShadowItem of {id: box_id, item: box_item}
type update = {sc: int, prfstep_name: string, source: box_item list,
raw_updt: raw_update}
signature UPDATE =
sig
val target_of_update: raw_update -> box_id
val replace_id_of_update: raw_update -> raw_update
val string_of_raw_update: Proof.context -> raw_update -> string
val thm_to_ritem: thm -> raw_item
val thm_update: box_id * thm -> raw_update
val thm_update_sc: int -> box_id * thm -> raw_update
val apply_exists_ritems: Proof.context -> thm -> raw_item list * thm
val update_info: Proof.context -> box_id -> raw_item list -> string
val source_info: update -> string
end;
functor Update(
structure BoxItem: BOXITEM;
structure ItemIO: ITEM_IO;
structure UtilLogic: UTIL_LOGIC;
): UPDATE =
struct
fun target_of_update raw_updt =
case raw_updt of
AddItems {id, ...} => id
| AddBoxes {id, ...} => id
| ResolveBox {id, ...} => id
| ShadowItem {id, ...} => id
fun replace_id_of_update raw_updt =
let
val id = target_of_update raw_updt
val _ = assert (BoxID.has_incr_id id) "replace_id_of_update"
val id' = BoxID.replace_incr_id id
in
case raw_updt of
AddItems {sc, raw_items, ...} =>
AddItems {id = id', sc = sc, raw_items = raw_items}
| AddBoxes {sc, init_assum, ...} =>
AddBoxes {id = id', sc = sc, init_assum = init_assum}
| ResolveBox {th, ...} => ResolveBox {id = id', th = th}
| ShadowItem {item, ...} => ShadowItem {id = id', item = item}
end
(* Debugging output for raw update. *)
fun string_of_raw_update ctxt raw_updt =
case raw_updt of
AddItems {id, raw_items, ...} =>
"Add items " ^ (Util.string_of_list (
ItemIO.string_of_raw_item ctxt) raw_items) ^
" to box " ^ (BoxID.string_of_box_id id)
| AddBoxes {id, init_assum, ...} =>
"Add box " ^ (Syntax.string_of_term ctxt init_assum) ^
" under box " ^ (BoxID.string_of_box_id id)
| ResolveBox {id, ...} =>
"Resolve box " ^ (BoxID.string_of_box_id id)
| ShadowItem {id, item} =>
"Shadow item " ^ (ItemIO.string_of_item ctxt item) ^
" in box " ^ (BoxID.string_of_box_id id)
(* Create raw_item from theorem. *)
fun thm_to_ritem th =
let
val prop = Thm.prop_of th
val _ = assert (UtilLogic.is_Trueprop prop) "thm_update: prop is not Trueprop."
val _ = assert (not (Util.has_vars prop))
"thm_to_ritem: prop contains schematic variables."
in
Fact (TY_PROP, [UtilLogic.dest_Trueprop prop], th)
end
(* Create raw_update from id and theorem. *)
fun thm_update (id, th) =
if Thm.prop_of th aconv UtilLogic.pFalse then
ResolveBox {id = id, th = th}
else
AddItems {id = id, sc = NONE, raw_items = [thm_to_ritem th]}
fun thm_update_sc sc (id, th) =
if Thm.prop_of th aconv UtilLogic.pFalse then
ResolveBox {id = id, th = th}
else
AddItems {id = id, sc = SOME sc, raw_items = [thm_to_ritem th]}
(* Apply the given existence theorem. Return a pair (ritems, th),
ritems contain the new variables and the new handler, and th is the
instantiated property of the new variables, which can either be
processed further, or made into an ritem using thm_update.
*)
fun apply_exists_ritems ctxt ex_th =
let
val (vars, body) = (UtilLogic.strip_exists (UtilLogic.prop_of' ex_th))
|> Util.to_internal_vars ctxt
|> apsnd UtilLogic.mk_Trueprop
in
if null vars then ([], ex_th)
else (map (BoxItem.var_to_fact) vars @ [Handler (vars, body, ex_th)],
Thm.assume (Thm.cterm_of ctxt body))
end
(* Print a list of raw items. *)
fun update_info ctxt id ritems =
(Util.string_of_list' (ItemIO.string_of_raw_item ctxt)
(filter (not o BoxItem.is_handler_raw) ritems)) ^
" at box " ^ (BoxID.string_of_box_id id)
(* Print the source of the update. *)
fun source_info {prfstep_name, source, ...} =
prfstep_name ^ " on " ^
(Util.string_of_list'
(fn {uid, ...} => "(" ^ string_of_int uid ^ ")") source)
end (* structure Update. *)
structure Updates_Heap =
Heap (
type elem = update
fun ord ({sc = sc1, ...}, {sc = sc2, ...}) = int_ord (sc1, sc2)
)
type status = {
assums: term list,
handlers: (box_id * (term list * term * thm)) list,
items: (box_item * box_id list) Inttab.table,
queue: Updates_Heap.T,
resolve_th: thm option,
ctxt: Proof.context
}
signature STATUS =
sig
val empty_status: Proof.context -> status
val map_context: (Proof.context -> Proof.context) -> status -> status
val add_handler: box_id * (term list * term * thm) -> status -> status
val get_handlers: status -> (box_id * (term list * term * thm)) list
val add_item: box_item -> status -> status
val get_items: status -> box_item list
val get_all_items_at_id: status -> box_id -> box_item list
val get_num_items: status -> int
val set_resolve_th: thm -> status -> status
val get_resolve_th: status -> thm
val add_prim_box: box_id -> term -> status -> int * status
val add_resolved: box_id -> status -> status
val get_init_assums: status -> box_id -> term list
val get_init_assum: status -> int -> term
val lookup_item: status -> int -> (box_item * box_id list) option
val clear_incr: status -> status
val add_shadowed: box_id * box_item -> status -> status
val query_shadowed: status -> box_id -> box_item -> bool
val query_removed: status -> box_item -> bool
val find_fact: status -> box_id -> term -> thm option
val find_ritem_exact: status -> box_id -> raw_item -> bool
val invoke_handler: Proof.context -> term list * term * thm -> thm -> thm
val get_on_resolve: status -> box_id -> int -> thm -> thm
val find_prim_box: status -> box_id -> term -> int option
val map_queue: (Updates_Heap.T -> Updates_Heap.T) -> status -> status
val add_to_queue: update -> status -> status
val delmin_from_queue: status -> status
end;
functor Status(
structure BoxItem: BOXITEM;
structure ItemIO: ITEM_IO;
structure UtilLogic: UTIL_LOGIC
structure PropertyData: PROPERTY_DATA;
structure RewriteTable: REWRITE_TABLE;
structure WellformData: WELLFORM_DATA;
): STATUS =
struct
fun empty_status ctxt =
{assums = [UtilLogic.term_of_bool true],
handlers = [],
items = Inttab.empty,
queue = Updates_Heap.empty,
ctxt = ctxt,
resolve_th = NONE}
fun map_context f {assums, handlers, items, queue, ctxt, resolve_th} =
{assums = assums, handlers = handlers, items = items, queue = queue,
ctxt = f ctxt, resolve_th = resolve_th}
fun add_handler (id, handler) {assums, handlers, items, queue, ctxt,
resolve_th} =
{assums = assums, handlers = (id, handler) :: handlers, items = items,
queue = queue, ctxt = ctxt, resolve_th = resolve_th}
fun get_handlers {handlers, ...} = handlers
fun map_items f {assums, handlers, items, queue, ctxt, resolve_th} =
{assums = assums, handlers = handlers, items = f items, queue = queue,
ctxt = ctxt, resolve_th = resolve_th}
fun add_item (item as {uid, ...}) st =
st |> map_items (Inttab.update_new (uid, (item, [])))
fun get_items {items, ...} =
items |> Inttab.dest |> map snd
|> filter_out (fn ({id, ...}, shadow_ids) =>
member (op =) shadow_ids id)
|> map fst
fun get_items_at_id (st as {ctxt, ...}) id =
st |> get_items
|> filter (fn {id = id', ...} => BoxID.is_eq_ancestor ctxt id' id)
fun get_all_items_at_id {items, ctxt, ...} id =
items |> Inttab.dest |> map snd |> map fst
|> filter (fn {id = id', ...} => BoxID.is_eq_ancestor ctxt id' id)
fun get_num_items {items, ...} = length (Inttab.dest items)
fun set_resolve_th th {assums, handlers, items, queue, ctxt, ...} =
{assums = assums, handlers = handlers, items = items, queue = queue,
ctxt = ctxt, resolve_th = SOME th}
fun get_resolve_th {resolve_th, ...} =
case resolve_th of
NONE => raise Fail "get_resolve_th: not resolved."
| SOME th => th
fun add_prim_box parent_id assum
{assums, handlers, items, queue, ctxt, resolve_th} =
let
val (id, ctxt') = BoxID.add_prim_id parent_id ctxt
in
(id, {assums = assums @ [assum],
handlers = handlers, items = items, queue = queue,
ctxt = ctxt', resolve_th = resolve_th})
end
fun add_resolved id {assums, handlers, items, queue, ctxt, resolve_th} =
let
val ctxt' = BoxID.add_resolved id ctxt
in
{assums = assums, handlers = handlers, items = items, queue = queue,
ctxt = ctxt' |> RewriteTable.clean_resolved id
|> PropertyData.clean_resolved id
|> WellformData.clean_resolved id,
resolve_th = resolve_th}
end
fun get_init_assums {assums, ctxt, ...} id =
let
val parents = BoxID.get_ancestors_prim ctxt id
in
map (nth assums) parents
end
fun get_init_assum {assums, ...} prim_id =
nth assums prim_id
fun lookup_item {items, ...} uid =
Inttab.lookup items uid
fun clear_incr st =
st |> map_items (
Inttab.map (fn _ => fn (item, ids) => (BoxItem.item_replace_incr item, ids)))
fun add_shadowed (shadow_id, {uid, ...}) (st as {ctxt, ...}) =
case lookup_item st uid of
NONE => raise Fail "add_shadowed: item not found."
| SOME (item, shadow_ids) =>
let
val shadow_ids' = (shadow_id :: shadow_ids)
|> Util.max_partial (BoxID.is_eq_ancestor ctxt)
in
st |> map_items (Inttab.update (uid, (item, shadow_ids')))
end
fun query_shadowed (st as {ctxt, ...}) shadow_id {uid, ...} =
case lookup_item st uid of
NONE => raise Fail "query_shadowed: item not found."
| SOME (_, shadow_ids) =>
exists (BoxID.is_eq_descendent ctxt shadow_id) shadow_ids
fun query_removed st (item as {id, ...}) = query_shadowed st id item
(* Try to find fact at id or above with the proposition t. Return SOME
th if found.
*)
fun find_fact (st as {ctxt, ...}) id t =
let
val ct = Thm.cterm_of ctxt t
val items = get_items_at_id st id
val res = (WellformData.find_fact ctxt items (id, ct))
|> filter (fn (id', _) => id' = id)
in
case res of
[] => NONE
| (_, th) :: _ => SOME th
end
(* Find item with the exact ty_str and tname, whose id is an
eq-ancestor of the given id.
There are two special cases: if the ritem in question is of type EQ
and PROPERTY, in which case we try to find it in the rewrite table.
*)
fun find_ritem_exact (st as {ctxt, ...}) id ritem =
case ritem of
Handler _ => false
| Fact (ty_str, tname, _) =>
if ty_str = TY_EQ then
let
val (lhs, rhs) = the_pair (BoxItem.get_tname_raw ritem)
in
RewriteTable.is_equiv_t id ctxt (lhs, rhs)
end
else if ty_str = TY_PROPERTY then
let
val prop = the_single tname
val infos =
(PropertyData.get_property_t ctxt (id, prop))
|> filter (fn (id', _) => BoxID.is_eq_ancestor ctxt id' id)
in
not (null infos)
end
else
let
val thy = Proof_Context.theory_of ctxt
val {shadow_fn, ...} = ItemIO.get_io_info thy ty_str
fun eq_item {ty_str = ty_str2, tname = tname2, ...} =
if ty_str <> ty_str2 then false else
case shadow_fn of
NONE => eq_list (op aconv) (tname, map Thm.term_of tname2)
| SOME (f, _) => f ctxt id (tname, tname2)
in
exists eq_item (get_all_items_at_id st id)
end
(* Invoke a single handler (vars, t, ex_th) on the theorem th. *)
fun invoke_handler ctxt (vars, t, ex_th) th =
if member (op aconv) (Thm.hyps_of th) t then
th |> Thm.implies_intr (Thm.cterm_of ctxt t)
|> fold (UtilLogic.ex_elim ctxt) (rev vars)
|> Thm.elim_implies ex_th
else th
(* Derive the consequence if box id is resolved, to the parent id
formed by getting parent at index i.
*)
fun get_on_resolve (st as {ctxt, ...}) id i th =
let
(* First get list of handlers to invoke. *)
val prim_id = nth id i
val handlers =
st |> get_handlers
|> filter (fn (id', _) =>
BoxID.is_eq_ancestor ctxt [prim_id] id' andalso
BoxID.is_eq_descendent ctxt id id')
|> map snd
val init_assum = get_init_assum st prim_id
val th' = th |> fold (invoke_handler ctxt) handlers
|> Thm.implies_intr (Thm.cterm_of ctxt init_assum)
|> apply_to_thm UtilLogic.rewrite_from_contra_form
val _ = assert (prim_id <> BoxID.home_id orelse null (Thm.hyps_of th'))
"get_on_resolve: did not remove all hypothesis at box 0."
in
th'
end
(* Find a primitive box (if there is any) whose initial facts agree
exactly with the given initial facts. Note we cannot yet handle new
variables.
*)
fun find_prim_box {assums, ctxt, ...} id init_assum =
let
fun agree_at_id prim_id' =
let
val parent = BoxID.get_parent_prim ctxt prim_id'
val is_equiv_t = RewriteTable.is_equiv_t parent ctxt
in
is_equiv_t (init_assum, nth assums prim_id')
end
fun can_test_id prim_id' =
BoxID.is_eq_ancestor ctxt (BoxID.get_parent_prim ctxt prim_id') id
val ids_to_test = filter can_test_id (0 upto (length assums - 1))
in
find_first agree_at_id ids_to_test
end
fun map_queue f {assums, handlers, items, queue, ctxt, resolve_th} =
{assums = assums, handlers = handlers, items = items, queue = f queue,
ctxt = ctxt, resolve_th = resolve_th}
fun add_to_queue updt = map_queue (Updates_Heap.insert updt)
val delmin_from_queue = map_queue Updates_Heap.delete_min
end (* structure Status *)
¤ Dauer der Verarbeitung: 0.3 Sekunden
(vorverarbeitet am 2026-11-04)
¤
*© Formatika GbR, Deutschland
|
|