(***********************************************************************) (* *) (* TAToo *) (* *) (* Kim Nguyen, LRI UMR8623 *) (* Université Paris-Sud & CNRS *) (* *) (* Copyright 2010-2013 Université Paris-Sud and Centre National de la *) (* Recherche Scientifique. All rights reserved. This file is *) (* distributed under the terms of the GNU Lesser General Public *) (* License, with the special exception on linking described in file *) (* ../LICENSE. *) (* *) (***********************************************************************) (* Time-stamp: *) INCLUDE "utils.ml" open Format open Utils module Make (T : Tree.Sig.S) = struct type cache = (int, StateSet.t) Hashtbl.t let get c t n = try Hashtbl.find c (T.preorder t n) with Not_found -> StateSet.empty let set c t n v = Hashtbl.replace c (T.preorder t n) v let eval_trans l ctx acc = List.fold_left (fun (acct, accs) ((q, phi) as trs) -> if StateSet.mem q accs then (acct, accs) else if Ata.SFormula.eval ctx phi then (acct, StateSet.add q accs) else (trs::acct, accs) ) ([], acc) l let top_down_run auto tree node cache i = let redo = ref false in let rec loop node is_left = if node != T.nil then begin let parent = T.parent tree node in let fc = T.first_child tree node in let ns = T.next_sibling tree node in let states0 = get cache tree node in let tag = T.tag tree node in let trans0 = Ata.get_trans auto auto.Ata.states tag in let parent_states = if parent == T.nil then auto.Ata.top_states else get cache tree parent in let fc_states = if fc == T.nil then auto.Ata.bottom_states else get cache tree fc in let ns_states = if ns == T.nil then auto.Ata.bottom_states else get cache tree ns in let is_root = parent == T.nil in let ctx0 = if is_left then Ata.make_ctx fc_states ns_states parent_states StateSet.empty states0 is_left is_root else Ata.make_ctx fc_states ns_states StateSet.empty parent_states states0 is_left is_root in eprintf "-- [Iteration % 4d] --\n node: %a\n context: %a\n%!" i T.print_node node Ata.print_ctx ctx0; List.iter (fun (q, phi) -> eprintf " %a -> %a\n" State.print q Ata.SFormula.print phi) trans0; eprintf "----------------------\n%!"; let trans1, states1 = eval_trans trans0 ctx0 StateSet.empty in if states1 != states0 then set cache tree node states1; let () = loop fc true in let ctx1 = {ctx0 with Ata.left = (get cache tree fc) ; Ata.epsilon = states1 } in let trans2, states2 = eval_trans trans1 ctx1 states1 in if states2 != states1 then set cache tree node states2; let () = loop ns false in let ctx2 = { ctx1 with Ata.right = (get cache tree ns); Ata.epsilon = states2 } in let _, states3 = eval_trans trans2 ctx2 states2 in if states3 != states2 then set cache tree node states3; if states0 != states3 && (not !redo) then redo := true end in loop node true; !redo let get_results auto tree node cache = let rec loop node acc = if node == T.nil then acc else let acc0 = loop (T.next_sibling tree node) acc in let acc1 = loop (T.first_child tree node) acc0 in if StateSet.intersect (get cache tree node) auto.Ata.selection_states then node::acc1 else acc1 in loop node [] let eval auto tree node = let cache = Hashtbl.create 511 in let redo = ref true in let iter = ref 0 in while !redo do redo := top_down_run auto tree node cache !iter; incr iter; done; get_results auto tree node cache end