(***********************************************************************) (* *) (* 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_form phi tree node fcs nss ps ss = let rec loop phi = match Ata.SFormula.expr phi with Formula.True -> true | Formula.False -> false | Formula.Atom a -> let p, b, q = Ata.Atom.node a in let pos = let open Ata in match p with | First_child -> StateSet.mem q fcs | Next_sibling -> StateSet.mem q nss | Parent | Previous_sibling -> StateSet.mem q ps | Stay -> StateSet.mem q ss | Is_first_child -> node == (T.first_child tree (T.parent tree node)) | Is_next_sibling -> node == (T.next_sibling tree (T.parent tree node)) | Is k -> k == (T.kind tree node) | Has_first_child -> T.nil != T.first_child tree node | Has_next_sibling -> T.nil != T.next_sibling tree node in if Ata.is_move p && (not b) then eprintf "Warning: Invalid negative atom %a" Ata.Atom.print a; b == pos | Formula.And(phi1, phi2) -> loop phi1 && loop phi2 | Formula.Or (phi1, phi2) -> loop phi1 || loop phi2 in loop phi let eval_trans l tree node fcs nss ps ss acc = List.fold_left (fun (acct, accs) ((q, phi) as trs) -> if StateSet.mem q accs then (acct, accs) else if eval_form phi tree node fcs nss ps ss 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 = 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 ps = get cache tree parent in let fcs = get cache tree fc in let nss = get cache tree ns in eprintf "-- [Iteration % 4d] --\n node: %a\n%!" i T.print_node node; 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 tree node fcs nss ps states0 states0 in if states1 != states0 then set cache tree node states1; let () = loop fc in let fcs1 = get cache tree fc in let trans2, states2 = eval_trans trans1 tree node fcs1 nss ps states1 states1 in if states2 != states1 then set cache tree node states2; let () = loop ns in let _, states3 = eval_trans trans2 tree node fcs1 (get cache tree ns) ps states2 states2 in if states3 != states2 then set cache tree node states3; if states0 != states3 && (not !redo) then redo := true end in loop node; !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