Implement copy and composition of automata.
authorKim Nguyễn <kn@lri.fr>
Tue, 23 Jul 2013 06:50:13 +0000 (08:50 +0200)
committerKim Nguyễn <kn@lri.fr>
Tue, 23 Jul 2013 06:50:13 +0000 (08:50 +0200)
src/ata.ml
src/ata.mli
src/tatoo.ml

index 79d47a9..70213fd 100644 (file)
@@ -225,7 +225,7 @@ let complete_transitions a =
   StateSet.iter (fun q ->
     if StateSet.mem q a.starting_states then ()
     else
-      let qtrans = try Hashtbl.find a.transitions q with Not_found -> eprintf "Not found here 226\n%!"; raise Not_found in
+      let qtrans = Hashtbl.find a.transitions q in
       let rem =
         List.fold_left (fun rem (labels, _) ->
           QNameSet.diff rem labels) QNameSet.any qtrans
@@ -317,13 +317,16 @@ let normalize_negations auto =
           in
           Hashtbl.add memo_state key nq; nq
     in
-    let trans = try Hashtbl.find auto.transitions q with Not_found -> eprintf "Not_found here 318\n%!"; [] in
+    let trans = try Hashtbl.find auto.transitions q with Not_found -> [] in
     let trans' = List.map (fun (lab, f) -> lab, flip b f) trans in
     Hashtbl.replace auto.transitions q' trans';
   done;
   cleanup_states auto
 
 
+
+
+
 module Builder =
   struct
     type auto = t
@@ -394,3 +397,63 @@ module Builder =
       normalize_negations a;
       a
   end
+
+
+let map_set f s =
+  StateSet.fold (fun q a -> StateSet.add (f q) a) s StateSet.empty
+
+let map_hash fk fv h =
+  let h' = Hashtbl.create (Hashtbl.length h) in
+  let () = Hashtbl.iter (fun k v -> Hashtbl.add h' (fk k) (fv v)) h in
+  h'
+
+let rec map_form f phi =
+  match Formula.expr phi with
+  | Boolean.Or(phi1, phi2) -> Formula.or_ (map_form f phi1) (map_form f phi2)
+  | Boolean.And(phi1, phi2) -> Formula.and_ (map_form f phi1) (map_form f phi2)
+  | Boolean.Atom({ Atom.node = Move(m,q); _}, b) ->
+      let a = Formula.mk_atom (Move (m,f q)) in
+      if b then a else Formula.not_ a
+  | _ -> phi
+
+let rename_states mapper a =
+  let rename q = try Hashtbl.find mapper q with Not_found -> q in
+  { Builder.make () with
+    states = map_set rename a.states;
+    starting_states = map_set rename a.starting_states;
+    selecting_states = map_set rename a.selecting_states;
+    transitions =
+      map_hash
+        rename
+        (fun l ->
+          (List.map (fun (labels, form) -> (labels, map_form rename form)) l))
+        a.transitions;
+  }
+
+let copy a =
+  let mapper = Hashtbl.create MED_H_SIZE in
+  let () =
+    StateSet.iter (fun q -> Hashtbl.add mapper q (State.make())) a.states
+  in
+  rename_states mapper a
+
+
+let concat a1 a2 =
+  let a1 = copy a1 in
+  let a2 = copy a2 in
+  let link_phi =
+    StateSet.fold
+      (fun q phi -> Formula.(or_ (stay q) phi))
+      a1.selecting_states Formula.true_
+  in
+  StateSet.iter
+    (fun q ->
+      Hashtbl.add a1.transitions q [(QNameSet.any, link_phi)])
+    a2.starting_states;
+  Hashtbl.iter (fun q trs -> Hashtbl.add a1.transitions q trs)
+    a2.transitions;
+  { a1 with
+    states = StateSet.union a1.states a2.states;
+    selecting_states = a2.selecting_states;
+    transitions = a1.transitions;
+  }
index 2676923..6b4c02a 100644 (file)
@@ -100,6 +100,15 @@ val get_trans : t -> QNameSet.elt -> StateSet.t -> TransList.t
 val print : Format.formatter -> t -> unit
 (** Pretty printing of the automaton *)
 
+val copy : t -> t
+(** [copy a] creates a copy of automaton [a], that is a new automaton with
+    the same transitions but with fresh states, such that [get_states a] and
+    [get_states (copy a)] are distinct
+*)
+val concat : t -> t -> t
+(** [concat a a'] creates a new automaton [a''] such that, given a set of tree
+    nodes [N], [a'' N = a' (a N)].
+*)
 
 module Builder :
 sig
index 362c4fb..1dff2a4 100644 (file)
@@ -40,6 +40,7 @@ let main () =
   let auto =
     time Xpath.Compile.path query "compiling XPath query"
   in
+  let auto = time Ata.copy auto "copying Automaton" in
   let output =
     match !Options.output_file with
     | None | Some "-" | Some "/dev/stdout" -> stdout
@@ -67,7 +68,7 @@ let main () =
   output_string output "</xml_result>\n";
   flush output;
   if output != stdout then close_out output
+
 ) () "serializing results"