diff --git a/src/grew_command.ml b/src/grew_command.ml index 591820f1d92f70633665ce0db121e4cd3f08cb95..3e3aabd189a20815915580fdce061143ad2c5b15 100644 --- a/src/grew_command.ml +++ b/src/grew_command.ml @@ -21,12 +21,12 @@ module Command = struct (* the command in pattern *) type p = | DEL_NODE of cnode - | DEL_EDGE_EXPL of (cnode * cnode *Edge.t) + | DEL_EDGE_EXPL of (cnode * cnode * G_edge.t) | DEL_EDGE_NAME of string - | ADD_EDGE of (cnode * cnode * Edge.t) + | ADD_EDGE of (cnode * cnode * G_edge.t) | DEL_FEAT of (cnode * string) | UPDATE_FEAT of (cnode * string * item list) - | NEW_NEIGHBOUR of (string * Edge.t * pid) + | NEW_NEIGHBOUR of (string * G_edge.t * pid) | SHIFT_EDGE of (cnode * cnode) | SHIFT_IN of (cnode * cnode) | SHIFT_OUT of (cnode * cnode) @@ -37,12 +37,12 @@ module Command = struct (* a item in the command history: command applied to a graph *) type h = | H_DEL_NODE of gid - | H_DEL_EDGE_EXPL of (gid * gid *Edge.t) + | H_DEL_EDGE_EXPL of (gid * gid *G_edge.t) | H_DEL_EDGE_NAME of string - | H_ADD_EDGE of (gid * gid * Edge.t) + | H_ADD_EDGE of (gid * gid * G_edge.t) | H_DEL_FEAT of (gid *string) | H_UPDATE_FEAT of (gid * string * string) - | H_NEW_NEIGHBOUR of (string * Edge.t * gid) + | H_NEW_NEIGHBOUR of (string * G_edge.t * gid) | H_SHIFT_EDGE of (gid * gid) | H_SHIFT_IN of (gid * gid) | H_SHIFT_OUT of (gid * gid) @@ -65,7 +65,7 @@ module Command = struct match ast_command with | (Ast.Del_edge_expl (i, j, lab), loc) -> check_node loc i kni; check_node loc j kni; - let edge = Edge.make ~locals [lab] in + let edge = G_edge.make ~locals lab in ((DEL_EDGE_EXPL (get_pid i, get_pid j, edge), loc), (kni, kei)) | (Ast.Del_edge_name id, loc) -> @@ -74,7 +74,7 @@ module Command = struct | (Ast.Add_edge (i, j, lab), loc) -> check_node loc i kni; check_node loc j kni; - let edge = Edge.make ~locals [lab] in + let edge = G_edge.make ~locals lab in ((ADD_EDGE (get_pid i, get_pid j, edge), loc), (kni, kei)) | (Ast.Shift_edge (i, j), loc) -> @@ -97,12 +97,12 @@ module Command = struct check_node loc ancestor kni; if List.mem name_created kni then Error.build ~loc "Node identifier \"%s\" is already used" name_created; - let edge = Edge.make ~locals [label] in + let edge = G_edge.make ~locals label in begin try ((NEW_NEIGHBOUR (name_created, edge, Id.build ~loc ancestor table), loc), (name_created::kni, kei)) with Not_found -> Log.fcritical "[GRS] tries to build a command New_neighbour (%s) on node %s which is not in the pattern %s" - (Edge.to_string edge) + (G_edge.to_string edge) ancestor (Loc.to_string loc) end diff --git a/src/grew_command.mli b/src/grew_command.mli index 958bdb4b14350ee8f83723ed3559c107a17ce075..4e1e07a53508d1c4a7d1e4c28f3f61d285c5c472 100644 --- a/src/grew_command.mli +++ b/src/grew_command.mli @@ -16,12 +16,12 @@ module Command : sig type p = | DEL_NODE of cnode - | DEL_EDGE_EXPL of (cnode * cnode *Edge.t) + | DEL_EDGE_EXPL of (cnode * cnode *G_edge.t) | DEL_EDGE_NAME of string - | ADD_EDGE of (cnode * cnode * Edge.t) + | ADD_EDGE of (cnode * cnode * G_edge.t) | DEL_FEAT of (cnode * string) | UPDATE_FEAT of (cnode * string * item list) - | NEW_NEIGHBOUR of (string * Edge.t * pid) + | NEW_NEIGHBOUR of (string * G_edge.t * pid) | SHIFT_EDGE of (cnode * cnode) | SHIFT_IN of (cnode * cnode) | SHIFT_OUT of (cnode * cnode) @@ -31,12 +31,12 @@ module Command : sig type t = (p * Loc.t) type h = | H_DEL_NODE of gid - | H_DEL_EDGE_EXPL of (gid * gid *Edge.t) + | H_DEL_EDGE_EXPL of (gid * gid *G_edge.t) | H_DEL_EDGE_NAME of string - | H_ADD_EDGE of (gid * gid * Edge.t) + | H_ADD_EDGE of (gid * gid * G_edge.t) | H_DEL_FEAT of (gid *string) | H_UPDATE_FEAT of (gid * string * string) - | H_NEW_NEIGHBOUR of (string * Edge.t * gid) + | H_NEW_NEIGHBOUR of (string * G_edge.t * gid) | H_SHIFT_EDGE of (gid * gid) | H_SHIFT_IN of (gid * gid) | H_SHIFT_OUT of (gid * gid) diff --git a/src/grew_edge.ml b/src/grew_edge.ml index 70939c88cbcdc12bf2c66594aeb0330b1f32e3d0..4163bb111a75cf31df6ee1ef65f7edeafdefea23 100644 --- a/src/grew_edge.ml +++ b/src/grew_edge.ml @@ -1,8 +1,10 @@ open Log +open Printf open Grew_utils open Grew_ast +(* ================================================================================ *) module Label = struct type decl = string * string option @@ -28,90 +30,78 @@ module Label = struct let get_color l = !colors.(l) end +(* ================================================================================ *) -module Edge = struct - (* the type of underspecified labels: a positive or negative constraint on a disjunction *) - type under_label = - | Pos of int list - | Neg of int list - +(* ================================================================================ *) +module G_edge = struct + type t = Label.t + + let to_string = Label.to_string + + let make ?(locals=[||]) string = Label.from_string ~locals string + + let build ?locals (ast_edge, loc) = + match ast_edge.Ast.negative, ast_edge.Ast.edge_labels with + | (false, [one]) -> Label.from_string ~loc ?locals one + | (true, _) -> Error.build "Negative edge spec are forbidden in graphs%s" (Loc.to_string loc) + | (false, _) -> Error.build "Only atomic edge valus are allowed in graphs%s" (Loc.to_string loc) + + let to_dot ?(deco=false) l = + match Label.get_color l with + | None -> Printf.sprintf "[label=\"%s\", color=%s]" (Label.to_string l) (if deco then "red" else "black") + | Some c -> Printf.sprintf "[label=\"%s\", fontcolor=%s, color=%s]" (Label.to_string l) c (if deco then "red" else "black") + + let to_dep ?(deco=false) l = + match (deco,Label.get_color l) with + | (false,None) -> Printf.sprintf "{ label = \"%s\"; }" (Label.to_string l) + | (false,Some c) -> Printf.sprintf "{ label = \"%s\"; forecolor=%s; color=%s; bottom; }" (Label.to_string l) c c + | (true,None) -> Printf.sprintf "{ label = \"%s\"; color=red}" (Label.to_string l) + | (true,Some c) -> Printf.sprintf "{ label = \"%s\"; forecolor=%s; color=red; bottom; }" (Label.to_string l) c + +end +(* ================================================================================ *) + +(* ================================================================================ *) +module P_edge = struct + type u_label = + | Pos of Label.t list + | Neg of Label.t list + type t = { id: string option; (* an identifier for naming under_label in patterns *) - under_label: under_label; + u_label: u_label; } - let get_id t = t.id - - let all = {id=None; under_label=Neg []} + let all = {id=None; u_label=Neg []} - let compare = Pervasives.compare + let get_id t = t.id let make ?(id=None) ?(neg=false) ?(locals=[||]) = function - | l when neg -> {id=id; under_label=Neg (List.sort compare (List.map (Label.from_string ~locals) l))} - | l -> {id=id; under_label=Pos (List.sort compare (List.map (Label.from_string ~locals) l))} + | l when neg -> {id=id; u_label=Neg (List.sort compare (List.map (Label.from_string ~locals) l))} + | l -> {id=id; u_label=Pos (List.sort compare (List.map (Label.from_string ~locals) l))} let build ?locals (ast_edge, loc) = { id = ast_edge.Ast.edge_id; - under_label = + u_label = if ast_edge.Ast.negative then Neg (List.sort compare (List.map (Label.from_string ~loc ?locals) ast_edge.Ast.edge_labels)) else Pos (List.sort compare (List.map (Label.from_string ~loc ?locals) ast_edge.Ast.edge_labels)) } - - let from_string string_label = - match string_label with - | s when s.[0] = '^' -> - let s' = String.sub s 1 ((String.length s) - 1) in - {id=None; under_label=Neg (List.map Label.from_string (Str.split (Str.regexp "|") s'))} - | _ -> {id=None; under_label=Pos (List.map Label.from_string (Str.split (Str.regexp "|") string_label))} - - let build_edge line = - try - let _ = Str.search_forward(Str.regexp("N\\(.*\\)->")) line 0 in - let i = int_of_string (Str.matched_group 1 line) in - let _ = Str.search_forward(Str.regexp("->N\\(.*\\)\\[")) line 0 in - let j = int_of_string (Str.matched_group 1 line) in - let _ = Str.search_forward(Str.regexp("label=\"\\([\\^|a-zA-Z0-9_\\-]*\\)\"")) line 0 in - let string_label = Str.matched_group 1 line in - (i,j,from_string string_label) - with Not_found | Invalid_argument _ -> failwith (Printf.sprintf "%s is not an edge declaration" line) - - let to_string t = - let pref = match t.id with None -> "" | Some i -> "i:" in - match t.under_label with + let to_string t = + let pref = match t.id with None -> "" | Some i -> sprintf "%s:" i in + match t.u_label with | Pos l -> pref^(List_.to_string Label.to_string "|" l) | Neg l -> pref^"^"^(List_.to_string Label.to_string "|" l) - let as_label t = match t.under_label with - | Pos [one] -> one - | _ -> failwith (Printf.sprintf "[Edge.as_label] edge '%s\' is not a label" (to_string t)) - - let of_label l = {id=None; under_label=Pos [l]} - - let to_dot ?(deco=false) x = - let l = as_label x in - match Label.get_color l with - | None -> Printf.sprintf "[label=\"%s\", color=%s]" (Label.to_string l) (if deco then "red" else "black") - | Some c -> Printf.sprintf "[label=\"%s\", fontcolor=%s, color=%s]" (Label.to_string l) c (if deco then "red" else "black") - let to_dep ?(deco=false) x = - let l = as_label x in - match (deco,Label.get_color l) with - | (false,None) -> Printf.sprintf "{ label = \"%s\"; }" (Label.to_string l) - | (false,Some c) -> Printf.sprintf "{ label = \"%s\"; forecolor=%s; color=%s; bottom; }" (Label.to_string l) c c - | (true,None) -> Printf.sprintf "{ label = \"%s\"; color=red}" (Label.to_string l) - | (true,Some c) -> Printf.sprintf "{ label = \"%s\"; forecolor=%s; color=red; bottom; }" (Label.to_string l) c + let compatible t g_edge = match t.u_label with + | Pos p -> List_.sort_mem g_edge p + | Neg n -> not (List_.sort_mem g_edge n) - let compatible edge1 edge2 = match (edge1.under_label,edge2.under_label) with - | Pos l1, Pos l2 -> not (List_.sort_is_empty_inter l1 l2) - | Pos p, Neg n | Neg n, Pos p -> not (List_.sort_include p n) - | Neg l1, Neg l2 -> failwith "Cannot compare two negative sets" - let is_in graph_edge list = - List.mem (as_label graph_edge) list type edge_matcher = @@ -119,30 +109,30 @@ module Edge = struct | Ok of Label.t | Binds of string * Label.t list - let match_ pattern_edge graph_edge = - let graph_label = as_label graph_edge in + let match_ pattern_edge graph_label = match pattern_edge with - | {id = Some i; under_label = Pos l} when List.mem graph_label l -> Binds (i, [graph_label]) - | {id = None; under_label = Pos l} when List.mem graph_label l -> Ok graph_label - | {id = Some i; under_label = Neg l} when not (List.mem graph_label l) -> Binds (i, [graph_label]) - | {id = None; under_label = Neg l} when not (List.mem graph_label l) -> Ok graph_label + | {id = Some i; u_label = Pos l} when List.mem graph_label l -> Binds (i, [graph_label]) + | {id = None; u_label = Pos l} when List.mem graph_label l -> Ok graph_label + | {id = Some i; u_label = Neg l} when not (List.mem graph_label l) -> Binds (i, [graph_label]) + | {id = None; u_label = Neg l} when not (List.mem graph_label l) -> Ok graph_label | _ -> Fail let match_list pattern_edge graph_edge_list = - let graph_labels = List.map as_label graph_edge_list in match pattern_edge with - | {id = None; under_label = Pos l} when List.exists (fun label -> List.mem label l) graph_labels -> Ok (List.hd graph_labels) - | {id = None; under_label = Neg l} when List.exists (fun label -> not (List.mem label l)) graph_labels -> Ok (List.hd graph_labels) - | {id = Some i; under_label = Pos l} -> - (match List.filter (fun label -> List.mem label l) graph_labels with + | {id = None; u_label = Pos l} when List.exists (fun label -> List.mem label l) graph_edge_list -> + Ok (List.hd graph_edge_list) + | {id = None; u_label = Neg l} when List.exists (fun label -> not (List.mem label l)) graph_edge_list -> + Ok (List.hd graph_edge_list) + | {id = Some i; u_label = Pos l} -> + (match List.filter (fun label -> List.mem label l) graph_edge_list with | [] -> Fail | list -> Binds (i, list)) - | {id = Some i; under_label = Neg l} -> - (match List.filter (fun label -> not (List.mem label l)) graph_labels with + | {id = Some i; u_label = Neg l} -> + (match List.filter (fun label -> not (List.mem label l)) graph_edge_list with | [] -> Fail | list -> Binds (i, list)) | _ -> Fail - end +(* ================================================================================ *) diff --git a/src/grew_edge.mli b/src/grew_edge.mli index 2aff9345ed6c08e77f63aef6e04f38f7cc5c7293..4d05a812becb2eec338edf9143a1f9c0e828f92c 100644 --- a/src/grew_edge.mli +++ b/src/grew_edge.mli @@ -16,16 +16,39 @@ module Label : sig end -module Edge : sig - type t - val as_label: t -> Label.t - val of_label: Label.t -> t - val get_id: t -> string option + +(* ================================================================================ *) +(** The module [G_edge] defines the type of Graph label edges: atomic edges *) +module G_edge: sig + type t = Label.t + + val to_string:t -> string + + val make: ?locals:Label.decl array -> string -> t + + val build: ?locals:Label.decl array -> Ast.edge -> t + + val to_dot: ?deco:bool -> t -> string + val to_dep: ?deco:bool -> t -> string + +end +(* ================================================================================ *) + + +(* ================================================================================ *) +(** The module [G_edge] defines the type of Graph label edges: atomic edges *) +module P_edge: sig + type t (* [all] is the joker pattern edge *) val all: t + val get_id: t -> string option + val to_string: t -> string + + val build: ?locals:Label.decl array -> Ast.edge -> t + val make: ?id: string option -> ?neg:bool -> @@ -33,27 +56,17 @@ module Edge : sig string list -> t - val build: ?locals:Label.decl array -> Ast.edge -> t - - val compare: 'a -> 'a -> int - val build_edge: string -> int * int * t - val to_string: t -> string - val to_dot: ?deco:bool -> t -> string - val to_dep: ?deco:bool -> t -> string - - val compatible : t -> t -> bool - - val is_in : t -> Label.t list -> bool - + val compatible: t -> G_edge.t -> bool type edge_matcher = | Fail | Ok of Label.t | Binds of string * Label.t list + val match_: t -> G_edge.t -> edge_matcher - val match_: t -> t -> edge_matcher + val match_list: t -> G_edge.t list -> edge_matcher - val match_list: t -> t list -> edge_matcher end +(* ================================================================================ *) diff --git a/src/grew_graph.ml b/src/grew_graph.ml index 65f0af0b341f4749f90371b9ab003abb793573bf..e3f18e6488ce3a0bf5947f9222a925a357395677 100644 --- a/src/grew_graph.ml +++ b/src/grew_graph.ml @@ -9,54 +9,38 @@ open Grew_node open Grew_command +(* ================================================================================ *) module Deco = struct type t = { nodes: int list; - edges: (int * Label.t * int) list; + edges: (int * G_edge.t * int) list; } let empty = {nodes=[]; edges=[]} end +(* ================================================================================ *) -module Graph = struct - type t = { - map: Node.t IntMap.t; (* node description *) - lub: int; (* least upper bound *) - } - let empty = {map = IntMap.empty; lub = 0} +(* ================================================================================ *) +module P_graph = struct + type t = P_node.t Pid_map.t - type gid = int - - type concat_item = - | Feat of (gid * string) - | String of string - - let find node_id graph = IntMap.find node_id graph.map + let empty = Pid_map.empty + let find = Pid_map.find let map_add_edge map id_src label id_tar = let node_src = (* Not found can be raised when adding an edge from pos to neg *) - try IntMap.find id_src map with Not_found -> Node.empty in - match Massoc.add id_tar label node_src.Node.next with - | Some l -> Some (IntMap.add id_src {node_src with Node.next = l} map) - | None -> None - - (* [add_edge graph id_src label id_tar] tries to add an edge grom [id_src] to [id_tar] with [label] to [graph]. - if it succeeds, [Some new_graph] is returned - if it fails (the edge already exists), [None] is returned - *) - let add_edge graph id_src label id_tar = - match map_add_edge graph.map id_src label id_tar with - | Some new_map -> Some {graph with map = new_map} + try Pid_map.find id_src map with Not_found -> P_node.empty in + match P_node.add_edge label id_tar node_src with | None -> None + | Some new_node -> Some (Pid_map.add id_src new_node map) let build_filter ?domain table (ast_node, loc) = let pid = Id.build ~loc ast_node.Ast.node_id table in let fs = Feature_structure.build ?domain ast_node.Ast.fs in (pid, fs) - let build ?domain ?(locals=[||]) full_node_list full_edge_list = let (named_nodes, constraints) = @@ -66,7 +50,7 @@ module Graph = struct let (tail_nodes, tail_const) = loop (ast_node.Ast.node_id :: already_bound) tail in if List.mem ast_node.Ast.node_id already_bound then (tail_nodes, (ast_node, loc)::tail_const) - else (Node.build ?domain (ast_node, loc) :: tail_nodes, tail_const) in + else (P_node.build ?domain (ast_node, loc) :: tail_nodes, tail_const) in loop [] full_node_list in (* let named_nodes = List.map (Node.build ?domain) full_node_list in *) @@ -78,34 +62,33 @@ module Graph = struct let table = Array.of_list sorted_ids in (* the nodes, in the same order *) - let map_without_edges = List_.foldi_left (fun i acc elt -> IntMap.add i elt acc) IntMap.empty node_list in + let map_without_edges = List_.foldi_left (fun i acc elt -> Pid_map.add i elt acc) Pid_map.empty node_list in let map = List.fold_left (fun acc (ast_edge, loc) -> let i1 = Id.build ~loc ast_edge.Ast.src table in let i2 = Id.build ~loc ast_edge.Ast.tar table in - let edge = Edge.build ~locals (ast_edge, loc) in + let edge = P_edge.build ~locals (ast_edge, loc) in (match map_add_edge acc i1 edge i2 with | Some g -> g | None -> Log.fcritical "[GRS] [Graph.build] try to build a graph with twice the same edge %s %s" - (Edge.to_string edge) + (P_edge.to_string edge) (Loc.to_string loc) ) ) map_without_edges full_edge_list in - - ({map=map;lub=Array.length table}, table, List.map (build_filter ?domain table) constraints) - + (map, table, List.map (build_filter ?domain table) constraints) + (* a type for extension of graph: a former graph exists: in grew the former is a positive pattern and an extension is a "without" *) - type extention = { - ext_map: Node.t IntMap.t; (* node description for new nodes and for edge "Old -> New" *) - old_map: Node.t IntMap.t; (* a partial map for new constraints on old nodes "Old [...]" *) + type extension = { + ext_map: P_node.t Pid_map.t; (* node description for new nodes and for edge "Old -> New" *) + old_map: P_node.t Pid_map.t; (* a partial map for new constraints on old nodes "Old [...]" *) } - let build_extention ?domain ?(locals=[||]) old_table full_node_list full_edge_list = + let build_extension ?domain ?(locals=[||]) old_table full_node_list full_edge_list = - let built_nodes = List.map (Node.build ?domain) full_node_list in + let built_nodes = List.map (P_node.build ?domain) full_node_list in let (old_nodes, new_nodes) = List.partition @@ -122,14 +105,14 @@ module Graph = struct (* the nodes, in the same order stored with index -1, -2, ... -N *) let ext_map_without_edges = List_.foldi_left - (fun i acc elt -> IntMap.add (-i-1) elt acc) - IntMap.empty + (fun i acc elt -> Pid_map.add (-i-1) elt acc) + Pid_map.empty new_node_list in let old_map_without_edges = List.fold_left - (fun acc (id,node) -> IntMap.add (Array_.dicho_find id old_table) node acc) - IntMap.empty + (fun acc (id,node) -> Pid_map.add (Array_.dicho_find id old_table) node acc) + Pid_map.empty old_nodes in let ext_map_with_all_edges = @@ -141,99 +124,13 @@ module Graph = struct let i2 = match Id.build_opt ast_edge.Ast.tar old_table with Some i -> i | None -> -1-(Id.build ~loc ast_edge.Ast.tar new_table) in - let edge = Edge.build ~locals (ast_edge, loc) in + let edge = P_edge.build ~locals (ast_edge, loc) in match map_add_edge acc i1 edge i2 with | Some map -> map - | None -> Log.fbug "[GRS] [Graph.build_extention] add_edge cannot fail in pattern extention (1)"; exit 2 + | None -> Log.fbug "[GRS] [Graph.build_extension] add_edge cannot fail in pattern extension (1)"; exit 2 ) ext_map_without_edges full_edge_list in ({ext_map = ext_map_with_all_edges; old_map = old_map_without_edges}, new_table) - - (* ---------------------------------------------------------------------------------------------------- *) - (* Output functions *) - (* ---------------------------------------------------------------------------------------------------- *) - let to_gr graph = - let buff = Buffer.create 32 in - - bprintf buff "graph {\n"; - - (* list of the nodes *) - IntMap.iter - (fun id node -> - bprintf buff "N%d %s [%s];\n" - id - (match node.Node.pos with Some i -> sprintf "(%d)" i | None -> "") - (Feature_structure.to_gr node.Node.fs) - ) graph.map; - (* list of the edges *) - IntMap.iter - (fun id node -> - Massoc.iter - (fun tar edge -> - bprintf buff "N%d -[%s]-> N%d;\n" id (Edge.to_string edge) tar - ) node.Node.next - ) graph.map; - - bprintf buff "}\n"; - Buffer.contents buff - - - let to_dot ?main_feat ?(deco=Deco.empty) graph = - let buff = Buffer.create 32 in - - bprintf buff "digraph G {\n"; - bprintf buff " rankdir=LR;\n"; - bprintf buff " node [shape=Mrecord];\n"; - - (* list of the nodes *) - IntMap.iter - (fun id node -> - bprintf buff " N%d [label=\"%s\", color=%s]\n" - id - (Feature_structure.to_dot ?main_feat node.Node.fs) - (if List.mem id deco.Deco.nodes then "red" else "black") - ) graph.map; - (* list of the edges *) - IntMap.iter - (fun id node -> - Massoc.iter - (fun tar edge -> - let deco = List.mem (id,Edge.as_label edge,tar) deco.Deco.edges in - bprintf buff " N%d -> N%d%s\n" id tar (Edge.to_dot ~deco edge) - ) node.Node.next - ) graph.map; - - bprintf buff "}\n"; - Buffer.contents buff - - let to_dep ?main_feat ?(deco=Deco.empty) graph = - let buff = Buffer.create 32 in - bprintf buff "[GRAPH] { opacity=0; scale = 200; fontname=\"Arial\"; }\n"; - - bprintf buff "[WORDS] { \n"; - - let nodes = IntMap.fold (fun id elt acc -> (id,elt)::acc) graph.map [] in - let snodes = List.sort (fun (_,n1) (_,n2) -> Pervasives.compare n1.Node.pos n2.Node.pos) nodes in - - List.iter - (fun (id, node) -> - if List.mem id deco.Deco.nodes - then bprintf buff "N%d { %sforecolor=red; subcolor=red; }\n" id (Feature_structure.to_dep ?main_feat node.Node.fs) - else bprintf buff "N%d { %s }\n" id (Feature_structure.to_dep ?main_feat node.Node.fs) - ) snodes; - bprintf buff "} \n"; - - bprintf buff "[EDGES] { \n"; - IntMap.iter - (fun id elt -> - Massoc.iter - (fun tar edge -> - let deco = List.mem (id,Edge.as_label edge,tar) deco.Deco.edges in - bprintf buff "N%d -> N%d %s\n" id tar (Edge.to_dep ~deco edge) - ) elt.Node.next - ) graph.map; - bprintf buff "} \n"; - Buffer.contents buff (* ---------------------------------------------------------------------------------------------------- *) (* Topology functions *) @@ -245,7 +142,7 @@ module Graph = struct let tree_and_roots graph = let tree_prop = ref true in let not_root = - IntMap.fold + Pid_map.fold (fun _ node acc -> Massoc.fold_left (fun acc2 tar _ -> @@ -255,67 +152,157 @@ module Graph = struct then (tree_prop := false; acc2) else IntSet.add tar acc2 else IntSet.add tar acc2 - ) acc node.Node.next - ) graph.map IntSet.empty in + ) acc (P_node.get_next node) + ) graph IntSet.empty in let roots = - IntMap.fold + Pid_map.fold (fun id _ acc -> if IntSet.mem id not_root then acc else id::acc - ) graph.map [] in + ) graph [] in (!tree_prop, roots) let roots graph = snd (tree_and_roots graph) +end (* module P_graph *) +(* ================================================================================ *) - (* ---------------------------------------------------------------------------------------------------- *) + + +(* ================================================================================ *) +module Gid = struct + type t = int + let compare = Pervasives.compare +end + +module Gid_map = Map.Make (Gid) +(* ================================================================================ *) + +(* ================================================================================ *) +module G_graph = struct + type t = { + map: G_node.t Gid_map.t; (* node description *) + lub: int; (* least upper bound *) + } + + let empty = {map = Gid_map.empty; lub = 0} + + let find node_id graph = Gid_map.find node_id graph.map + + type concat_item = + | Feat of (Gid.t * string) + | String of string + + + let map_add_edge map id_src label id_tar = + let node_src = + (* Not found can be raised when adding an edge from pos to neg *) + try Gid_map.find id_src map with Not_found -> G_node.empty in + match G_node.add_edge label id_tar node_src with + | None -> None + | Some new_node -> Some (Gid_map.add id_src new_node map) + + + let build ?domain ?(locals=[||]) full_node_list full_edge_list = + + let (named_nodes, constraints) = + let rec loop already_bound = function + | [] -> ([],[]) + | (ast_node, loc) :: tail -> + let (tail_nodes, tail_const) = loop (ast_node.Ast.node_id :: already_bound) tail in + if List.mem ast_node.Ast.node_id already_bound + then (tail_nodes, (ast_node, loc)::tail_const) + else (G_node.build ?domain (ast_node, loc) :: tail_nodes, tail_const) in + loop [] full_node_list in + + (* let named_nodes = List.map (Node.build ?domain) full_node_list in *) + + let sorted_nodes = List.sort (fun (id1,_) (id2,_) -> Pervasives.compare id1 id2) named_nodes in + let (sorted_ids, node_list) = List.split sorted_nodes in + + (* table contains the sorted list of node ids *) + let table = Array.of_list sorted_ids in + + (* the nodes, in the same order *) + let map_without_edges = List_.foldi_left (fun i acc elt -> Gid_map.add i elt acc) Gid_map.empty node_list in + + let map = + List.fold_left + (fun acc (ast_edge, loc) -> + let i1 = Id.build ~loc ast_edge.Ast.src table in + let i2 = Id.build ~loc ast_edge.Ast.tar table in + let edge = G_edge.build ~locals (ast_edge, loc) in + (match map_add_edge acc i1 edge i2 with + | Some g -> g + | None -> Log.fcritical "[GRS] [Graph.build] try to build a graph with twice the same edge %s %s" + (G_edge.to_string edge) + (Loc.to_string loc) + ) + ) map_without_edges full_edge_list in + + {map=map;lub=Array.length table} + + + (* ---------------------------------------------------- *) (* Update functions *) - (* ---------------------------------------------------------------------------------------------------- *) + (* ---------------------------------------------------- *) + + + + (* [add_edge graph id_src label id_tar] tries to add an edge grom [id_src] to [id_tar] with [label] to [graph]. + if it succeeds, [Some new_graph] is returned + if it fails (the edge already exists), [None] is returned + *) + let add_edge graph id_src label id_tar = + match map_add_edge graph.map id_src label id_tar with + | Some new_map -> Some {graph with map = new_map} + | None -> None + (* remove (id_src -[label]-> id_tar) from graph. Log.critical if the edge is not in graph *) let del_edge ?edge_ident loc graph id_src label id_tar = let node_src = - try IntMap.find id_src graph.map + try Gid_map.find id_src graph.map with Not_found -> match edge_ident with | None -> Log.fcritical "[RUN] Some edge refers to a dead node, please report" | Some id -> Error.run ~loc "[Graph.del_edge] cannot find source node of edge \"%s\"" id in try {graph with map = - IntMap.add id_src {node_src with Node.next = Massoc.remove id_tar label node_src.Node.next} graph.map + (* Gid_map.add id_src {node_src with Node.next = Massoc.remove id_tar label node_src.Node.next} graph.map *) + Gid_map.add id_src (G_node.remove id_tar label node_src) graph.map } - with Not_found -> Error.run ~loc "[Graph.del_edge] cannot find edge '%s'" (Edge.to_string label) + with Not_found -> Error.run ~loc "[Graph.del_edge] cannot find edge '%s'" (G_edge.to_string label) (* remove node i from graph, with all its incoming and outcoming edges *) (* [graph] is unchanged if the node is not in it *) let del_node graph node_id = let new_map = - IntMap.fold + Gid_map.fold (fun id value acc -> if id = node_id then acc - else IntMap.add id {value with Node.next = try Massoc.remove_key node_id value.Node.next with Not_found -> value.Node.next} acc - ) graph.map IntMap.empty in + (* else Gid_map.add id {value with Node.next = try Massoc.remove_key node_id value.Node.next with Not_found -> value.Node.next} acc *) + else Gid_map.add id (G_node.remove_key node_id value) acc + ) graph.map Gid_map.empty in {graph with map = new_map} - let add_neighbour loc graph node_id edge = - let label = Edge.as_label edge in + let add_neighbour loc graph node_id label = (* index is a new number (higher then lub and uniquely defined by (node_id,label) *) - let index = graph.lub + ((Grew_edge.Label.to_int label) * graph.lub) + node_id in + let index = graph.lub + ((Label.to_int label) * graph.lub) + node_id in - if IntMap.mem index graph.map + if Gid_map.mem index graph.map then Error.run ~loc "[Graph.add_neighbour] try to build twice the \"same\" neighbour node (with label '%s')" (Label.to_string label); - let node = IntMap.find node_id graph.map in + let node = Gid_map.find node_id graph.map in (* put the new node on the right of its "parent" *) - let new_node = {Node.empty with Node.pos = match node.Node.pos with Some x -> Some (x+1) | None -> None} in - let new_graph = {graph with map = IntMap.add index new_node graph.map} in - match add_edge new_graph node_id (Edge.of_label label) index with + let new_graph = {graph with map = Gid_map.add index (G_node.build_neighbour node) graph.map} in + match add_edge new_graph node_id label index with | Some g -> (index, g) | None -> Log.bug "[Graph.add_neighbour] add_edge must not fail"; exit 1 @@ -323,134 +310,205 @@ module Graph = struct (* move all in arcs to id_src are moved to in arcs on node id_tar from graph, with all its incoming edges *) let shift_in loc graph src_gid tar_gid = - let tar_node = IntMap.find tar_gid graph.map in + let tar_node = Gid_map.find tar_gid graph.map in - if Massoc.mem_key src_gid tar_node.Node.next + if Massoc.mem_key src_gid (G_node.get_next tar_node) then Error.run ~loc "[Graph.shift_in] dependency from tar to src"; let new_map = - IntMap.mapi + Gid_map.mapi (fun node_id node -> - try {node with Node.next = Massoc.merge_key src_gid tar_gid node.Node.next} - with Massoc.Duplicate -> Error.run ~loc "[Graph.shift_edges] create duplicate edge" + match G_node.merge_key src_gid tar_gid node with + | Some n -> n + | None -> Error.run ~loc "[Graph.shift_edges] create duplicate edge" ) graph.map in {graph with map = new_map} (* move all out-edges from id_src are moved to out-edges out off node id_tar *) let shift_out loc graph src_gid tar_gid = - let src_node = IntMap.find src_gid graph.map in - let tar_node = IntMap.find tar_gid graph.map in + let src_node = Gid_map.find src_gid graph.map in + let tar_node = Gid_map.find tar_gid graph.map in - if Massoc.mem_key tar_gid src_node.Node.next + if Massoc.mem_key tar_gid (G_node.get_next src_node) then Error.run ~loc "[Graph.shift_edges] dependency from src to tar"; let new_map = - IntMap.mapi + Gid_map.mapi (fun node_id node -> if node_id = src_gid then (* [src_id] becomes without out-edges *) - {node with Node.next = Massoc.empty} + G_node.rm_out_edges node else if node_id = tar_gid then - try {node with Node.next = Massoc.disjoint_union src_node.Node.next tar_node.Node.next} - with Massoc.Not_disjoint -> Error.run ~loc "[Graph.shift_edges] common successor" + match G_node.shift_out src_node tar_node with + | Some n -> n + | None -> Error.run ~loc "[Graph.shift_edges] common successor" else node (* other nodes don't change *) ) graph.map in {graph with map = new_map} (* move all incident arcs from/to id_src are moved to incident arcs on node id_tar from graph, with all its incoming and outcoming edges *) let shift_edges loc graph src_gid tar_gid = - let src_node = IntMap.find src_gid graph.map in - let tar_node = IntMap.find tar_gid graph.map in + let src_node = Gid_map.find src_gid graph.map in + let tar_node = Gid_map.find tar_gid graph.map in - if Massoc.mem_key tar_gid src_node.Node.next + if Massoc.mem_key tar_gid (G_node.get_next src_node) then Error.run ~loc "[Graph.shift_edges] dependency from src to tar"; - if Massoc.mem_key src_gid tar_node.Node.next + if Massoc.mem_key src_gid (G_node.get_next tar_node) then Error.run ~loc "[Graph.shift_edges] dependency from tar to src"; let new_map = - IntMap.mapi + Gid_map.mapi (fun node_id node -> if node_id = src_gid then (* [src_id] becomes an isolated node *) - {node with Node.next = Massoc.empty} + G_node.rm_out_edges node else if node_id = tar_gid then - try {node with Node.next = Massoc.disjoint_union src_node.Node.next tar_node.Node.next} - with Massoc.Not_disjoint -> Error.run ~loc "[Graph.shift_edges] common successor" - else - try {node with Node.next = Massoc.merge_key src_gid tar_gid node.Node.next} - with Massoc.Duplicate -> Error.run ~loc "[Graph.shift_edges] create duplicate edge" + match G_node.shift_out src_node tar_node with + | Some n -> n + | None -> Error.run ~loc "[Graph.shift_edges] common successor" + else + match G_node.merge_key src_gid tar_gid node with + | Some n -> n + | None -> Error.run ~loc "[Graph.shift_edges] create duplicate edge" ) graph.map in {graph with map = new_map} - - - - - - - - - - - - - - let merge_node loc graph src_gid tar_gid = let se_graph = shift_edges loc graph src_gid tar_gid in - let src_node = IntMap.find src_gid se_graph.map in - let tar_node = IntMap.find tar_gid se_graph.map in + let src_node = Gid_map.find src_gid se_graph.map in + let tar_node = Gid_map.find tar_gid se_graph.map in - match Feature_structure.unif src_node.Node.fs tar_node.Node.fs with + match Feature_structure.unif (G_node.get_fs src_node) (G_node.get_fs tar_node) with | Some new_fs -> let new_map = - IntMap.add + Gid_map.add tar_gid - {tar_node with Node.fs = new_fs} - (IntMap.remove src_gid se_graph.map) in + (G_node.set_fs tar_node new_fs) + (Gid_map.remove src_gid se_graph.map) in Some {se_graph with map = new_map} | None -> None (* FIXME: check consistency wrt the domain *) let update_feat graph tar_id tar_feat_name item_list = - let tar = IntMap.find tar_id graph.map in + let tar = Gid_map.find tar_id graph.map in let strings_to_concat = List.map (function | Feat (node_gid, feat_name) -> - let node = IntMap.find node_gid graph.map in + let node = Gid_map.find node_gid graph.map in (try - match Feature_structure.get_atom feat_name node.Node.fs with + match Feature_structure.get_atom feat_name (G_node.get_fs node) with | Some atom -> atom | None -> Log.fcritical "[BUG] [Graph.update_feat] Feature not atomic" with Not_found -> Log.fcritical "[RUN] [Graph.update_feat] no feature \"%s\" in node \"%s\"" - feat_name (Node.to_string node)) + feat_name (G_node.to_string node)) | String s -> s ) item_list in let new_feature_value = List_.to_string (fun s->s) "" strings_to_concat in - let new_f = Feature_structure.set_feat tar_feat_name [new_feature_value] tar.Node.fs in - ({graph with map = IntMap.add tar_id {tar with Node.fs = new_f} graph.map}, new_feature_value) + let new_fs = Feature_structure.set_feat tar_feat_name [new_feature_value] (G_node.get_fs tar) in + ({graph with map = Gid_map.add tar_id (G_node.set_fs tar new_fs) graph.map}, new_feature_value) (** [del_feat graph node_id feat_name] returns [graph] where the feat [feat_name] of [node_id] is deleted If the feature is not present, [graph] is returned. *) let del_feat graph node_id feat_name = - let node = IntMap.find node_id graph.map in - let new_fs = Feature_structure.del_feat feat_name node.Node.fs in - {graph with map = IntMap.add node_id {node with Node.fs = new_fs} graph.map} + let node = Gid_map.find node_id graph.map in + let new_fs = Feature_structure.del_feat feat_name (G_node.get_fs node) in + {graph with map = Gid_map.add node_id (* {node with Node.fs = new_fs} *) (G_node.set_fs node new_fs) graph.map} + + let to_gr graph = + let buff = Buffer.create 32 in + + bprintf buff "graph {\n"; + + (* list of the nodes *) + Gid_map.iter + (fun id node -> + bprintf buff "N%d %s;\n" id (G_node.to_gr node) + ) graph.map; + (* list of the edges *) + Gid_map.iter + (fun id node -> + Massoc.iter + (fun tar edge -> + bprintf buff "N%d -[%s]-> N%d;\n" id (G_edge.to_string edge) tar + ) (G_node.get_next node) + ) graph.map; + + bprintf buff "}\n"; + Buffer.contents buff + + let to_dep ?main_feat ?(deco=Deco.empty) graph = + let buff = Buffer.create 32 in + bprintf buff "[GRAPH] { opacity=0; scale = 200; fontname=\"Arial\"; }\n"; + + bprintf buff "[WORDS] { \n"; + + let nodes = Gid_map.fold (fun id elt acc -> (id,elt)::acc) graph.map [] in + let snodes = List.sort (fun (_,n1) (_,n2) -> G_node.pos_comp n1 n2) nodes in + + List.iter + (fun (id, node) -> + if List.mem id deco.Deco.nodes + then bprintf buff + "N%d { %sforecolor=red; subcolor=red; }\n" id (Feature_structure.to_dep ?main_feat (G_node.get_fs node)) + else bprintf buff + "N%d { %s }\n" id (Feature_structure.to_dep ?main_feat (G_node.get_fs node)) + ) snodes; + bprintf buff "} \n"; + + bprintf buff "[EDGES] { \n"; + Gid_map.iter + (fun gid elt -> + Massoc.iter + (fun tar g_edge -> + let deco = List.mem (gid,g_edge,tar) deco.Deco.edges in + bprintf buff "N%d -> N%d %s\n" gid tar (G_edge.to_dep ~deco g_edge) + ) (G_node.get_next elt) + ) graph.map; + bprintf buff "} \n"; + Buffer.contents buff + + let to_dot ?main_feat ?(deco=Deco.empty) graph = + let buff = Buffer.create 32 in + + bprintf buff "digraph G {\n"; + bprintf buff " rankdir=LR;\n"; + bprintf buff " node [shape=Mrecord];\n"; + + (* list of the nodes *) + Gid_map.iter + (fun id node -> + bprintf buff " N%d [label=\"%s\", color=%s]\n" + id + (Feature_structure.to_dot ?main_feat (G_node.get_fs node)) + (if List.mem id deco.Deco.nodes then "red" else "black") + ) graph.map; + (* list of the edges *) + Gid_map.iter + (fun id node -> + Massoc.iter + (fun tar g_edge -> + let deco = List.mem (id,g_edge,tar) deco.Deco.edges in + bprintf buff " N%d -> N%d%s\n" id tar (G_edge.to_dot ~deco g_edge) + ) (G_node.get_next node) + ) graph.map; + + bprintf buff "}\n"; + Buffer.contents buff - let equals t t' = IntMap.equal (fun node1 node2 -> node1 = node2) t.map t'.map + let equals t t' = Gid_map.equal (fun node1 node2 -> node1 = node2) t.map t'.map (* is there an edge e out of node i ? *) - let edge_out graph node_id edge = - let node = IntMap.find node_id graph.map in - Massoc.exists (fun _ e -> Edge.compatible e edge) node.Node.next - -end (* module Graph *) + let edge_out graph node_id p_edge = + let node = Gid_map.find node_id graph.map in + Massoc.exists (fun _ e -> P_edge.compatible p_edge e) (G_node.get_next node) +end (* module G_graph *) +(* ================================================================================ *) diff --git a/src/grew_graph.mli b/src/grew_graph.mli index a7fd944ff24ba604942088c8d186026ab6fe554d..a8107c3f787433007f69fabba8c5f9d3768377df 100644 --- a/src/grew_graph.mli +++ b/src/grew_graph.mli @@ -3,7 +3,6 @@ open Grew_fs open Grew_edge open Grew_node open Grew_utils -open Edge open Grew_command module Deco: sig @@ -14,19 +13,16 @@ module Deco: sig val empty:t end -module Graph : sig - type t = { - map: Node.t IntMap.t; (* node description *) - lub: int; (* least upper bound *) - } - - type gid = int - - type concat_item = - | Feat of (gid * string) - | String of string +module P_graph: sig + type t = P_node.t Pid_map.t val empty: t + val find: Pid.t -> t -> P_node.t + + type extension = { + ext_map: P_node.t Pid_map.t; (* node description for new nodes and for edge "Old -> New" *) + old_map: P_node.t Pid_map.t; (* a partial map for new constraints on old nodes "Old [...]" *) + } val build: ?domain: Ast.domain -> @@ -35,30 +31,54 @@ module Graph : sig Ast.edge list -> (t * Id.table * (Id.t * Feature_structure.t) list ) - (* a type for extension of graph: a former graph exists: in grew the former is a positive pattern and an extension is a "without" *) - type extention = { - ext_map: Node.t IntMap.t; (* node description *) - old_map: Node.t IntMap.t; (* a partial map on old nodes for edge "Old -> New" and/or for new constraints on old nodes "Old [...]" *) - } - - val build_extention: + val build_extension: ?domain: Ast.domain -> ?locals: Label.decl array -> Id.table -> Ast.node list -> Ast.edge list -> - (extention * Id.table) + (extension * Id.table) + + val roots: t -> Pid.t list + +end + +module Gid : sig type t = int end + +module Gid_map : Map.S with type key = Gid.t + + +module G_graph: sig + type t = { + map: G_node.t Gid_map.t; (* node description *) + lub: int; (* least upper bound *) + } + + + val empty: t - val find: int -> t -> Node.t + val find: Gid.t -> t -> G_node.t + + val build: + ?domain: Ast.domain -> + ?locals: Label.decl array -> + Ast.node list -> + Ast.edge list -> + t val to_gr: t -> string val to_dot: ?main_feat:string -> ?deco:Deco.t -> t -> string val to_dep: ?main_feat:string -> ?deco:Deco.t -> t -> string - val add_edge : t -> int -> Edge.t -> int -> t option - val del_edge : ?edge_ident: string -> Loc.t -> t -> int -> Edge.t -> int -> t + + type concat_item = + | Feat of (Gid.t * string) + | String of string + + val add_edge: t -> int -> G_edge.t -> int -> t option + val del_edge : ?edge_ident: string -> Loc.t -> t -> int -> G_edge.t -> int -> t val del_node : t -> int -> t - val add_neighbour : Loc.t -> t -> int -> Edge.t -> (int * t) + val add_neighbour : Loc.t -> t -> int -> G_edge.t -> (int * t) val merge_node : Loc.t -> t -> int -> int -> t option val shift_in : Loc.t -> t -> int -> int -> t @@ -72,11 +92,10 @@ module Graph : sig val del_feat : t -> int -> string -> t - val equals : t -> t -> bool - (** [edge_out t id edge] returns true iff there is an out-edge from the node [id] with a label compatible with [edge] *) - val edge_out: t -> int -> Edge.t -> bool + val edge_out: t -> int -> P_edge.t -> bool + + val equals: t -> t -> bool - val roots: t -> int list end diff --git a/src/grew_node.ml b/src/grew_node.ml index 75eac229e13cabbc5dd7f3c17907ae2dbbed4ac4..93408d11be7b84759c087cabc1e2bbd7e6811d89 100644 --- a/src/grew_node.ml +++ b/src/grew_node.ml @@ -1,18 +1,39 @@ +open Printf + open Grew_utils open Grew_ast open Grew_edge open Grew_fs - -module Node = struct +(* ================================================================================ *) +module G_node = struct type t = { - fs : Feature_structure.t; - pos : int option; - next : Edge.t Massoc.t; (* the massoc gives for each node [n], the (sorted) list of edge from the current node to [n] *) + fs: Feature_structure.t; + pos: int option; + next: G_edge.t Massoc.t; } - let empty = {fs = Feature_structure.empty; pos=None; next = Massoc.empty} - + let get_fs t = t.fs + let get_next t = t.next + + let set_fs t fs = {t with fs = fs} + + let empty = { fs = Feature_structure.empty; pos = None; next = Massoc.empty } + + let to_string t = + Printf.sprintf "[fs=%s ; next=%s]" + (Feature_structure.to_string t.fs) + (Massoc.to_string G_edge.to_string t.next) + + let to_gr t = + sprintf "%s [%s] " + (match t.pos with Some i -> sprintf "(%d)" i | None -> "") + (Feature_structure.to_gr t.fs) + + let add_edge g_edge gid_tar t = + match Massoc.add gid_tar g_edge t.next with + | Some l -> Some {t with next = l} + | None -> None let build ?domain (ast_node, loc) = (ast_node.Ast.node_id, @@ -20,13 +41,57 @@ module Node = struct pos = ast_node.Ast.position; next = Massoc.empty; } ) - + + let remove id_tar label t = {t with next = Massoc.remove id_tar label t.next} + + let remove_key node_id t = + try {t with next = Massoc.remove_key node_id t.next} with Not_found -> t + + let merge_key src_id tar_id t = + try Some {t with next = Massoc.merge_key src_id tar_id t.next} + with Massoc.Duplicate -> None + + let shift_out src_t tar_t = + try Some {tar_t with next = Massoc.disjoint_union src_t.next tar_t.next} + with Massoc.Not_disjoint -> None + + let rm_out_edges t = {t with next = Massoc.empty} + + + let build_neighbour t = {empty with pos = match t.pos with Some x -> Some (x+1) | None -> None} + + let pos_comp n1 n2 = Pervasives.compare n1.pos n2.pos +end +(* ================================================================================ *) + +(* ================================================================================ *) +module P_node = struct + type t = { + fs: Feature_structure.t; + next: P_edge.t Massoc.t; + } + + let get_fs t = t.fs + let get_next t = t.next + + let empty = { fs = Feature_structure.empty; next = Massoc.empty } + + let build ?domain (ast_node, loc) = + (ast_node.Ast.node_id, + { fs = Feature_structure.build ?domain ast_node.Ast.fs; + next = Massoc.empty; + } ) + + let add_edge p_edge pid_tar t = + match Massoc.add pid_tar p_edge t.next with + | Some l -> Some {t with next = l} + | None -> None (* Says that "pattern" t1 is a t2*) - let is_a pattern graph = Feature_structure.compatible pattern.fs graph.fs + let is_a p_node g_node = Feature_structure.compatible p_node.fs (G_node.get_fs g_node) - let to_string t = - Printf.sprintf "[fs=%s ; next=%s]" - (Feature_structure.to_string t.fs) - (Massoc.to_string Edge.to_string t.next) end +(* ================================================================================ *) + + + diff --git a/src/grew_node.mli b/src/grew_node.mli index bf7535e6b3940b6d90facbadc95285513f9931c7..82d15f5aa8dd80a0267dc206ebabc2edcd77115e 100644 --- a/src/grew_node.mli +++ b/src/grew_node.mli @@ -3,17 +3,52 @@ open Grew_fs open Grew_edge open Grew_ast -module Node : sig - type t = { - fs : Feature_structure.t; - pos : int option; - next : Edge.t Massoc.t; - } - +(* ================================================================================ *) +module G_node: sig + type t + + val empty: t + + val to_string: t -> string + val to_gr: t -> string + + val get_fs: t -> Feature_structure.t + val get_next: t -> G_edge.t Massoc.t + + val set_fs: t -> Feature_structure.t -> t + +(* FIXME move Gid up and replace int by Gid.t *) + val remove: int -> G_edge.t -> t -> t + + val remove_key: int -> t -> t + + val merge_key: int -> int -> t -> t option + val shift_out: t -> t -> t option + + val rm_out_edges: t -> t + + val add_edge: G_edge.t -> int -> t -> t option val build: ?domain:Ast.domain -> Ast.node -> (Id.name * t) + val pos_comp: t -> t -> int + + val build_neighbour: t -> t +end +(* ================================================================================ *) + +(* ================================================================================ *) +module P_node: sig + type t + + val empty: t + + val get_fs: t -> Feature_structure.t + val get_next: t -> P_edge.t Massoc.t + + val build: ?domain:Ast.domain -> Ast.node -> (Id.name * t) + + val add_edge: P_edge.t -> int -> t -> t option + + val is_a: t -> G_node.t -> bool - val is_a : t -> t -> bool - val empty : t - val to_string : t -> string end - +(* ================================================================================ *) diff --git a/src/grew_rule.ml b/src/grew_rule.ml index b6d5df691774b7480a8c1d2bc60b06eb29739602..ca7723e4f0b40b296380050840680729a07a229d 100644 --- a/src/grew_rule.ml +++ b/src/grew_rule.ml @@ -14,20 +14,21 @@ open Dep2pict ENDIF +(* ================================================================================ *) module Instance = struct type t = { - graph: Graph.t; + graph: G_graph.t; commands: Command.h list; rules: string list; big_step: Grew_types.big_step option; } - let empty = {graph = Graph.empty; rules=[]; commands=[]; big_step=None;} + let empty = {graph = G_graph.empty; rules=[]; commands=[]; big_step=None;} let from_graph g = {empty with graph = g} let build gr_ast = - let (graph,_,_) = Graph.build gr_ast.Ast.nodes gr_ast.Ast.edges in + let graph = G_graph.build gr_ast.Ast.nodes gr_ast.Ast.edges in { empty with graph = graph } let rev_steps t = @@ -39,51 +40,50 @@ module Instance = struct let clear t = {empty with graph = t.graph } (* FIXME: normalization of node ids ??? *) let get_graph t = t.graph - (* comparition is done on the list of commands *) + (* comparison is done on the list of commands *) (* only graph rewrited from the same init graph can be "compared" *) let compare t1 t2 = Pervasives.compare t1.commands t2.commands IFDEF DEP2PICT THEN let save_dep_png ?main_feat base t = - ignore (Dep2pict.fromDepStringToPng (Graph.to_dep ?main_feat t.graph) (base^".png")) + ignore (Dep2pict.fromDepStringToPng (G_graph.to_dep ?main_feat t.graph) (base^".png")) ENDIF - -end +end (* module Instance *) module Instance_set = Set.Make (Instance) - +(* ================================================================================ *) module Rule = struct - type pid = int + type pid = Pid.t type gid = int let max_depth = ref 500 exception Bound_reached type const = - | No_out of pid * Edge.t - | No_in of pid * Edge.t + | No_out of pid * P_edge.t + | No_in of pid * P_edge.t | Feature_eq of pid * string * pid * string | Filter of pid * Feature_structure.t (* used when a without impose a fs on a node defined by the match pattern *) let build_constraint ?locals table = function - | (Ast.Start (node_name, labels), loc) -> No_out (Id.build ~loc node_name table, Edge.make ?locals labels) - | (Ast.No_out node_name, loc) -> No_out (Id.build ~loc node_name table, Edge.all) - | (Ast.End (node_name, labels),loc) -> No_in (Id.build ~loc node_name table, Edge.make ?locals labels) - | (Ast.No_in node_name, loc) -> No_in (Id.build ~loc node_name table, Edge.all) + | (Ast.Start (node_name, labels), loc) -> No_out (Id.build ~loc node_name table, P_edge.make ?locals labels) + | (Ast.No_out node_name, loc) -> No_out (Id.build ~loc node_name table, P_edge.all) + | (Ast.End (node_name, labels),loc) -> No_in (Id.build ~loc node_name table, P_edge.make ?locals labels) + | (Ast.No_in node_name, loc) -> No_in (Id.build ~loc node_name table, P_edge.all) | (Ast.Feature_eq ((node_name1, feat_name1), (node_name2, feat_name2)), loc) -> Feature_eq (Id.build ~loc node_name1 table, feat_name1, Id.build ~loc node_name2 table, feat_name2) type pattern = - { graph: Graph.t; + { graph: P_graph.t; constraints: const list; } let build_pos_pattern ?domain ?(locals=[||]) pattern_ast = - let (graph,table,filter_nodes) = Graph.build ?domain ~locals pattern_ast.Ast.pat_nodes pattern_ast.Ast.pat_edges in + let (graph,table,filter_nodes) = P_graph.build ?domain ~locals pattern_ast.Ast.pat_nodes pattern_ast.Ast.pat_edges in ( { graph = graph; @@ -99,32 +99,32 @@ module Rule = struct let id_build loc string_id = match Id.build_opt string_id pos_table with Some i -> i | None -> -1-(Id.build ~loc string_id neg_table) in match const with - | (Ast.Start (node_name, labels),loc) -> No_out (id_build loc node_name, Edge.make ?locals labels) - | (Ast.No_out node_name, loc) -> No_out (id_build loc node_name, Edge.all) - | (Ast.End (node_name, labels),loc) -> No_in (id_build loc node_name, Edge.make ?locals labels) - | (Ast.No_in node_name, loc) -> No_in (id_build loc node_name, Edge.all) + | (Ast.Start (node_name, labels),loc) -> No_out (id_build loc node_name, P_edge.make ?locals labels) + | (Ast.No_out node_name, loc) -> No_out (id_build loc node_name, P_edge.all) + | (Ast.End (node_name, labels),loc) -> No_in (id_build loc node_name, P_edge.make ?locals labels) + | (Ast.No_in node_name, loc) -> No_in (id_build loc node_name, P_edge.all) | (Ast.Feature_eq ((node_name1, feat_name1), (node_name2, feat_name2)), loc) -> Feature_eq (id_build loc node_name1, feat_name1, id_build loc node_name2, feat_name2) let build_neg_pattern ?domain ?(locals=[||]) pos_table pattern_ast = let (extension, neg_table) = - Graph.build_extention ?domain ~locals pos_table pattern_ast.Ast.pat_nodes pattern_ast.Ast.pat_edges in + P_graph.build_extension ?domain ~locals pos_table pattern_ast.Ast.pat_nodes pattern_ast.Ast.pat_edges in - let filters = IntMap.fold (fun id node acc -> Filter (id, node.Node.fs) :: acc) extension.Graph.old_map [] in + let filters = Pid_map.fold (fun id node acc -> Filter (id, P_node.get_fs node) :: acc) extension.P_graph.old_map [] in (* (\* DEBUG *\) Printf.printf "-----> |filters| = %d\n%!" (List.length filters); *) { - graph = {Graph.map = extension.Graph.ext_map; lub=0 }; + graph = extension.P_graph.ext_map; constraints = filters @ List.map (build_neg_constraint ~locals pos_table neg_table) pattern_ast.Ast.pat_const ; } let get_edge_ids pattern = - IntMap.fold + Pid_map.fold (fun _ node acc -> Massoc.fold_left - (fun acc2 _ edge -> match Edge.get_id edge with None -> acc2 | Some id -> id::acc2) - acc node.Node.next - ) pattern.graph.Graph.map [] + (fun acc2 _ edge -> match P_edge.get_id edge with None -> acc2 | Some id -> id::acc2) + acc (P_node.get_next node) + ) pattern.graph [] type t = { name: string; @@ -161,19 +161,19 @@ module Rule = struct } type matching = { - n_match: gid IntMap.t; (* partial fct: pattern nodes |--> graph nodes *) + n_match: gid Pid_map.t; (* partial fct: pattern nodes |--> graph nodes *) e_match: (string*(gid*Label.t*gid)) list; (* edge matching: edge ident |--> (src,label,tar) *) a_match: (gid*Label.t*gid) list; (* anonymous edge mached *) } - let empty_matching = { n_match = IntMap.empty; e_match = []; a_match = [];} + let empty_matching = { n_match = Pid_map.empty; e_match = []; a_match = [];} - let singleton_matching i j = { empty_matching with n_match = IntMap.add i j IntMap.empty } + let singleton_matching i j = { empty_matching with n_match = Pid_map.add i j Pid_map.empty } let e_comp (e1,_) (e2,_) = compare e1 e2 let union match1 match2 = { - n_match = IntMap.union_if match1.n_match match2.n_match; + n_match = Pid_map.union_if match1.n_match match2.n_match; e_match = List_.sort_disjoint_union ~compare:e_comp match1.e_match match2.e_match; a_match = match1.a_match @ match2.a_match; } @@ -186,14 +186,14 @@ module Rule = struct let a_match_add edge matching = {matching with a_match = edge::matching.a_match } let up_deco matching = - { Deco.nodes = IntMap.fold (fun _ gid acc -> gid::acc) matching.n_match []; + { Deco.nodes = Pid_map.fold (fun _ gid acc -> gid::acc) matching.n_match []; Deco.edges = List.fold_left (fun acc (_,edge) -> edge::acc) matching.a_match matching.e_match; } let find cnode ?loc (matching, created_nodes) = match cnode with | Command.Pid pid -> - (try IntMap.find pid matching.n_match + (try Pid_map.find pid matching.n_match with Not_found -> Error.bug ?loc "Inconsistent matching pid '%d' not found" pid) | Command.New name -> try List.assoc name created_nodes @@ -212,7 +212,7 @@ module Rule = struct Deco.edges = List.fold_left (fun acc -> function | (Command.ADD_EDGE (src_cn,tar_cn,edge),loc) -> - (find src_cn (matching, created_nodes), Edge.as_label edge, find tar_cn (matching, created_nodes)) :: acc + (find src_cn (matching, created_nodes), edge, find tar_cn (matching, created_nodes)) :: acc | _ -> acc ) [] commands } @@ -222,7 +222,7 @@ module Rule = struct type partial = { sub: matching; unmatched_nodes: pid list; - unmatched_edges: (pid * Edge.t * pid) list; + unmatched_edges: (pid * P_edge.t * pid) list; already_matched_gids: gid list; (* to ensure injectivity *) check: const list (* constraints to verify at the end of the matching *) } @@ -233,9 +233,9 @@ module Rule = struct *) let init pattern = - let roots = Graph.roots pattern.graph in + let roots = P_graph.roots pattern.graph in - let node_list = IntMap.fold (fun pid _ acc -> pid::acc) pattern.graph.Graph.map [] in + let node_list = Pid_map.fold (fun pid _ acc -> pid::acc) pattern.graph [] in (* put all roots in the front of the list to speed up the algo *) let sorted_node_list = @@ -254,28 +254,29 @@ module Rule = struct let fullfill graph matching = function | No_out (pid,edge) -> - let gid = IntMap.find pid matching.n_match in - Graph.edge_out graph gid edge + let gid = Pid_map.find pid matching.n_match in + G_graph.edge_out graph gid edge | No_in (pid,edge) -> - let gid = IntMap.find pid matching.n_match in - IntMap.exists + let gid = Pid_map.find pid matching.n_match in + Gid_map.exists (fun _ node -> - List.exists (fun e -> Edge.compatible edge e) (Massoc.assoc gid node.Node.next) - ) graph.Graph.map + List.exists (fun e -> P_edge.compatible edge e) (Massoc.assoc gid (G_node.get_next node)) + ) graph.G_graph.map | Feature_eq (pid1, feat_name1, pid2, feat_name2) -> - let gnode1 = IntMap.find (IntMap.find pid1 matching.n_match) graph.Graph.map in - let gnode2 = IntMap.find (IntMap.find pid2 matching.n_match) graph.Graph.map in - (match (Feature_structure.get feat_name1 gnode1.Node.fs, - Feature_structure.get feat_name2 gnode2.Node.fs) with + let gnode1 = Gid_map.find (Pid_map.find pid1 matching.n_match) graph.G_graph.map in + let gnode2 = Gid_map.find (Pid_map.find pid2 matching.n_match) graph.G_graph.map in + (match (Feature_structure.get feat_name1 (G_node.get_fs gnode1), + Feature_structure.get feat_name2 (G_node.get_fs gnode2) + ) with | Some fv1, Some fv2 when fv1 = fv2 -> true | _ -> false) | Filter (pid, fs) -> - let gid = IntMap.find pid matching.n_match in - let gnode = IntMap.find gid graph.Graph.map in - Feature_structure.filter fs gnode.Node.fs + let gid = Pid_map.find pid matching.n_match in + let gnode = Gid_map.find gid graph.G_graph.map in + Feature_structure.filter fs (G_node.get_fs gnode) (* returns all extension of the partial input matching *) - let rec extend_matching (positive,neg) (graph:Graph.t) (partial:partial) = + let rec extend_matching (positive,neg) (graph:G_graph.t) (partial:partial) = match (partial.unmatched_edges, partial.unmatched_nodes) with | [], [] -> (* (\* DEBUG *\) Printf.printf "==<1>==\n%!"; *) @@ -286,17 +287,17 @@ module Rule = struct begin try (* is the tar already found in the matching ? *) let new_partials = - let src_gid = IntMap.find src_pid partial.sub.n_match in - let tar_gid = IntMap.find tar_pid partial.sub.n_match in - let src_gnode = Graph.find src_gid graph in - let g_edges = Massoc.assoc tar_gid src_gnode.Node.next in + let src_gid = Pid_map.find src_pid partial.sub.n_match in + let tar_gid = Pid_map.find tar_pid partial.sub.n_match in + let src_gnode = G_graph.find src_gid graph in + let g_edges = Massoc.assoc tar_gid (G_node.get_next src_gnode) in - match Edge.match_list p_edge g_edges with - | Edge.Fail -> (* no good edge in graph for this pattern edge -> stop here *) + match P_edge.match_list p_edge g_edges with + | P_edge.Fail -> (* no good edge in graph for this pattern edge -> stop here *) [] - | Edge.Ok label -> (* at least an edge in the graph fits the p_edge "constraint" -> go on *) + | P_edge.Ok label -> (* at least an edge in the graph fits the p_edge "constraint" -> go on *) [ {partial with unmatched_edges = tail_ue; sub = a_match_add (src_gid,label,tar_gid) partial.sub} ] - | Edge.Binds (id,labels) -> (* n edges in the graph match the identified p_edge -> make copies of the [k] matchings (and returns n*k matchings) *) + | P_edge.Binds (id,labels) -> (* n edges in the graph match the identified p_edge -> make copies of the [k] matchings (and returns n*k matchings) *) List.map (fun label -> {partial with sub = e_match_add (id,(src_gid,label,tar_gid)) partial.sub; unmatched_edges = tail_ue } @@ -304,19 +305,19 @@ module Rule = struct in List_.flat_map (extend_matching (positive,neg) graph) new_partials with Not_found -> (* p_edge goes to an unmatched node *) let candidates = (* candidates (of type (gid, matching)) for m(tar_pid) = gid) with new partial matching m *) - let src_gid = IntMap.find src_pid partial.sub.n_match in - let src_gnode = Graph.find src_gid graph in + let src_gid = Pid_map.find src_pid partial.sub.n_match in + let src_gnode = G_graph.find src_gid graph in Massoc.fold_left (fun acc gid_next g_edge -> - match Edge.match_ p_edge g_edge with - | Edge.Fail -> (* g_edge does not fit, no new candidate *) + match P_edge.match_ p_edge g_edge with + | P_edge.Fail -> (* g_edge does not fit, no new candidate *) acc - | Edge.Ok label -> (* g_edge fits with the same matching *) + | P_edge.Ok label -> (* g_edge fits with the same matching *) (gid_next, a_match_add (src_gid, label, gid_next) partial.sub) :: acc - | Edge.Binds (id,[label]) -> (* g_edge fits with an extended matching *) + | P_edge.Binds (id,[label]) -> (* g_edge fits with an extended matching *) (gid_next, e_match_add (id, (src_gid, label, gid_next)) partial.sub) :: acc - | _ -> Error.bug "Edge.match_ must return exactly one label" - ) [] src_gnode.Node.next in + | _ -> Error.bug "P_edge.match_ must return exactly one label" + ) [] (G_node.get_next src_gnode) in List_.flat_map (fun (gid_next, matching) -> extend_matching_from (positive,neg) graph tar_pid gid_next @@ -324,34 +325,34 @@ module Rule = struct ) candidates end | [], pid :: _ -> - IntMap.fold + Gid_map.fold (fun gid _ acc -> (extend_matching_from (positive,neg) graph pid gid partial) @ acc - ) graph.Graph.map [] + ) graph.G_graph.map [] - and extend_matching_from (positive,neg) (graph:Graph.t) pid gid partial = + and extend_matching_from (positive,neg) (graph:G_graph.t) pid gid partial = if List.mem gid partial.already_matched_gids then [] (* the required association pid -> gid is not injective *) else let p_node = if pid >= 0 - then try Graph.find pid positive with Not_found -> failwith "POS" - else try Graph.find pid neg with Not_found -> failwith "NEG" in - let g_node = try Graph.find gid graph with Not_found -> failwith "INS" in - if not (Node.is_a p_node g_node) + then try P_graph.find pid positive with Not_found -> failwith "POS" + else try P_graph.find pid neg with Not_found -> failwith "NEG" in + let g_node = try G_graph.find gid graph with Not_found -> failwith "INS" in + if not (P_node.is_a p_node g_node) then [] (* the nodes don't match *) else (* add all out-edges from pid in pattern *) let new_unmatched_edges = Massoc.fold_left (fun acc pid_next p_edge -> (pid, p_edge, pid_next) :: acc - ) partial.unmatched_edges p_node.Node.next in + ) partial.unmatched_edges (P_node.get_next p_node) in let new_partial = { partial with unmatched_nodes = (try List_.rm pid partial.unmatched_nodes with Not_found -> failwith "List_.rm"); unmatched_edges = new_unmatched_edges; already_matched_gids = gid :: partial.already_matched_gids; - sub = {partial.sub with n_match = IntMap.add pid gid partial.sub.n_match}; + sub = {partial.sub with n_match = Pid_map.add pid gid partial.sub.n_match}; } in extend_matching (positive,neg) graph new_partial @@ -369,7 +370,7 @@ module Rule = struct let src_gid = node_find src_cn in let tar_gid = node_find tar_cn in begin - match Graph.add_edge instance.Instance.graph src_gid edge tar_gid with + match G_graph.add_edge instance.Instance.graph src_gid edge tar_gid with | Some new_graph -> ( {instance with @@ -379,7 +380,7 @@ module Rule = struct created_nodes ) | None -> - Error.run "ADD_EDGE: the edge '%s' already exists %s" (Edge.to_string edge) (Loc.to_string loc) + Error.run "ADD_EDGE: the edge '%s' already exists %s" (G_edge.to_string edge) (Loc.to_string loc) end | Command.DEL_EDGE_EXPL (src_cn,tar_cn,edge) -> @@ -387,20 +388,19 @@ module Rule = struct let tar_gid = node_find tar_cn in ( {instance with - Instance.graph = Graph.del_edge loc instance.Instance.graph src_gid edge tar_gid; + Instance.graph = G_graph.del_edge loc instance.Instance.graph src_gid edge tar_gid; commands = List_.sort_insert (Command.H_DEL_EDGE_EXPL (src_gid,tar_gid,edge)) instance.Instance.commands }, created_nodes ) | Command.DEL_EDGE_NAME edge_ident -> - let (src_gid,label,tar_gid) = + let (src_gid,edge,tar_gid) = try List.assoc edge_ident matching.e_match with Not_found -> Error.bug "The edge identifier '%s' is undefined %s" edge_ident (Loc.to_string loc) in - let edge = Edge.of_label label in ( {instance with - Instance.graph = Graph.del_edge ~edge_ident loc instance.Instance.graph src_gid edge tar_gid; + Instance.graph = G_graph.del_edge ~edge_ident loc instance.Instance.graph src_gid edge tar_gid; commands = List_.sort_insert (Command.H_DEL_EDGE_EXPL (src_gid,tar_gid,edge)) instance.Instance.commands }, created_nodes @@ -410,7 +410,7 @@ module Rule = struct let node_gid = node_find node_cn in ( {instance with - Instance.graph = Graph.del_node instance.Instance.graph node_gid; + Instance.graph = G_graph.del_node instance.Instance.graph node_gid; commands = List_.sort_insert (Command.H_DEL_NODE node_gid) instance.Instance.commands }, created_nodes @@ -419,7 +419,7 @@ module Rule = struct | Command.MERGE_NODE (src_cn, tar_cn) -> let src_gid = node_find src_cn in let tar_gid = node_find tar_cn in - (match Graph.merge_node loc instance.Instance.graph src_gid tar_gid with + (match G_graph.merge_node loc instance.Instance.graph src_gid tar_gid with | Some new_graph -> ( {instance with @@ -435,11 +435,11 @@ module Rule = struct let tar_gid = node_find tar_cn in let rule_items = List.map (function - | Command.Feat (cnode, feat_name) -> Graph.Feat (node_find cnode, feat_name) - | Command.String s -> Graph.String s + | Command.Feat (cnode, feat_name) -> G_graph.Feat (node_find cnode, feat_name) + | Command.String s -> G_graph.String s ) item_list in let (new_graph, new_feature_value) = - Graph.update_feat instance.Instance.graph tar_gid tar_feat_name rule_items in + G_graph.update_feat instance.Instance.graph tar_gid tar_feat_name rule_items in ( {instance with Instance.graph = new_graph; @@ -454,15 +454,15 @@ module Rule = struct let tar_gid = node_find tar_cn in ( {instance with - Instance.graph = Graph.del_feat instance.Instance.graph tar_gid feat_name; + Instance.graph = G_graph.del_feat instance.Instance.graph tar_gid feat_name; commands = List_.sort_insert (Command.H_DEL_FEAT (tar_gid,feat_name)) instance.Instance.commands }, created_nodes ) | Command.NEW_NEIGHBOUR (created_name,edge,base_pid) -> - let base_gid = IntMap.find base_pid matching.n_match in - let (new_gid,new_graph) = Graph.add_neighbour loc instance.Instance.graph base_gid edge in + let base_gid = Pid_map.find base_pid matching.n_match in + let (new_gid,new_graph) = G_graph.add_neighbour loc instance.Instance.graph base_gid edge in ( {instance with Instance.graph = new_graph; @@ -476,7 +476,7 @@ module Rule = struct let tar_gid = node_find tar_cn in ( {instance with - Instance.graph = Graph.shift_in loc instance.Instance.graph src_gid tar_gid; + Instance.graph = G_graph.shift_in loc instance.Instance.graph src_gid tar_gid; commands = List_.sort_insert (Command.H_SHIFT_IN (src_gid,tar_gid)) instance.Instance.commands }, created_nodes @@ -487,7 +487,7 @@ module Rule = struct let tar_gid = node_find tar_cn in ( {instance with - Instance.graph = Graph.shift_out loc instance.Instance.graph src_gid tar_gid; + Instance.graph = G_graph.shift_out loc instance.Instance.graph src_gid tar_gid; commands = List_.sort_insert (Command.H_SHIFT_OUT (src_gid,tar_gid)) instance.Instance.commands }, created_nodes @@ -498,15 +498,12 @@ module Rule = struct let tar_gid = node_find tar_cn in ( {instance with - Instance.graph = Graph.shift_edges loc instance.Instance.graph src_gid tar_gid; + Instance.graph = G_graph.shift_edges loc instance.Instance.graph src_gid tar_gid; commands = List_.sort_insert (Command.H_SHIFT_EDGE (src_gid,tar_gid)) instance.Instance.commands }, created_nodes ) - -(* (\* DEBUG *\)let cpt = ref 0 *) - (** [apply_rule instance matching rule] returns a new instance after the application of the rule [Command_execution_fail] is raised if some merge unification fails *) @@ -528,24 +525,6 @@ module Rule = struct let rule_app = {Grew_types.rule_name = rule.name; up = up_deco matching; down = down_deco (matching,created_nodes) rule.commands } in - (* (\* DEBUG *\) let up_dot = Graph.to_dot ~deco:rule_app.Grew_types.up instance.Instance.graph in *) - (* (\* DEBUG *\) let _ = File.write up_dot (Printf.sprintf "dot_%d_a.dot" !cpt) in *) - (* (\* DEBUG *\) let _ = Sys.command (Printf.sprintf "dot -Tpng -o dot_%d_a.png dot_%d_a.dot" !cpt !cpt) in *) - - (* (\* DEBUG *\) let up_dep = Graph.to_dep ~deco:rule_app.Grew_types.up instance.Instance.graph in *) - (* (\* DEBUG *\) let _ = File.write up_dep (Printf.sprintf "dep_%d_a.dep" !cpt) in *) - (* (\* DEBUG *\) let _ = Sys.command (Printf.sprintf "dep2pict -png -o dep_%d_a.png -dep dep_%d_a.dep" !cpt !cpt) in *) - - (* (\* DEBUG *\) let down_dot = Graph.to_dot ~deco:rule_app.Grew_types.down new_instance.Instance.graph in *) - (* (\* DEBUG *\) let _ = File.write down_dot (Printf.sprintf "dot_%d_b.dot" !cpt) in *) - (* (\* DEBUG *\) let _ = Sys.command (Printf.sprintf "dot -Tpng -o dot_%d_b.png dot_%d_b.dot" !cpt !cpt) in *) - - (* (\* DEBUG *\) let down_dep = Graph.to_dep ~deco:rule_app.Grew_types.down new_instance.Instance.graph in *) - (* (\* DEBUG *\) let _ = File.write down_dep (Printf.sprintf "dep_%d_b.dep" !cpt) in *) - (* (\* DEBUG *\) let _ = Sys.command (Printf.sprintf "dep2pict -png -o dep_%d_b.png -dep dep_%d_b.dep" !cpt !cpt) in *) - - (* (\* DEBUG *\) incr cpt; *) - {new_instance with Instance.rules = rule.name :: new_instance.Instance.rules; big_step = match new_instance.Instance.big_step with @@ -557,21 +536,17 @@ module Rule = struct let update_partial pos_graph without (sub, already_matched_gids) = let neg_graph = without.graph in - let unmatched_nodes = IntMap.fold (fun pid _ acc -> if pid < 0 then pid::acc else acc) neg_graph.Graph.map [] in + let unmatched_nodes = Pid_map.fold (fun pid _ acc -> if pid < 0 then pid::acc else acc) neg_graph [] in let unmatched_edges = - IntMap.fold + Pid_map.fold (fun pid node acc -> if pid < 0 then acc else Massoc.fold_left (fun acc2 pid_next p_edge -> (pid, p_edge, pid_next) :: acc2) - acc node.Node.next - ) neg_graph.Graph.map [] in - -(* Printf.printf "XXX -> unmatched_nodes: %d\n" (List.length unmatched_nodes); *) -(* Printf.printf "XXX -> unmatched_edges: %d\n" (List.length unmatched_edges); *) - + acc (P_node.get_next node) + ) neg_graph [] in { sub = sub; unmatched_nodes = unmatched_nodes; @@ -596,7 +571,7 @@ module Rule = struct (* get the list of partial matching for positive part of the pattern *) let matching_list = extend_matching - (pos_graph,Graph.empty) + (pos_graph,P_graph.empty) instance.Instance.graph (init rule.pos) in @@ -627,7 +602,7 @@ module Rule = struct (* get the list of partial matching for positive part of the pattern *) let matching_list = extend_matching - (pos_graph,Graph.empty) + (pos_graph,P_graph.empty) instance.Instance.graph (init rule.pos) in @@ -649,7 +624,7 @@ module Rule = struct (** filter nfs being equal *) let rec filter_equal_nfs nfs = Instance_set.fold (fun nf acc -> - if Instance_set.exists (fun e -> Graph.equals e.Instance.graph nf.Instance.graph) acc + if Instance_set.exists (fun e -> G_graph.equals e.Instance.graph nf.Instance.graph) acc then (printf "two normal equal normal forms"; acc) else Instance_set.add nf acc) nfs Instance_set.empty diff --git a/src/grew_rule.mli b/src/grew_rule.mli index 0a2d962dad4df9a9d01e791ddaa03e606b2c9120..1b45af2593867637ccb5586e7190493f6fac0a61 100644 --- a/src/grew_rule.mli +++ b/src/grew_rule.mli @@ -7,7 +7,7 @@ open Grew_ast module Instance : sig type t = { - graph: Graph.t; + graph: G_graph.t; commands: Command.h list; rules: string list; big_step: Grew_types.big_step option; @@ -21,8 +21,8 @@ module Instance : sig val rev_steps: t -> t val clear: t -> t - val from_graph: Graph.t -> t - val get_graph: t -> Graph.t + val from_graph: G_graph.t -> t + val get_graph: t -> G_graph.t IFDEF DEP2PICT THEN (* [save_dep_png base t] writes a file "base.png" with the dep representation of [t] *) diff --git a/src/grew_types.ml b/src/grew_types.ml index fdc5f7a71a2d7ea41c13f322c05c11983896c5d5..e125689ef9455d15db041160660e349994e27ed6 100644 --- a/src/grew_types.ml +++ b/src/grew_types.ml @@ -1,6 +1,6 @@ open Grew_graph -type graph = Graph.t +type graph = G_graph.t type deco = Deco.t type module_name = string @@ -14,16 +14,16 @@ type rule_app = { (* the main type for display the result of a rewriting *) type rew_display = | Empty (* pour les besoin du dev *) - | Leaf of Graph.t - | Local_normal_form of Graph.t * module_name * rew_display - | Node of Graph.t * module_name * (big_step * rew_display) list + | Leaf of G_graph.t + | Local_normal_form of G_graph.t * module_name * rew_display + | Node of G_graph.t * module_name * (big_step * rew_display) list (* the type for big edges which correspond to a module *) and big_step = { first: rule_app; - small_step: (Graph.t * rule_app) list; + small_step: (G_graph.t * rule_app) list; } -let to_dot_graph ?main_feat ?(deco=Deco.empty) graph = Graph.to_dot ?main_feat graph ~deco -let to_dep_graph ?main_feat ?(deco=Deco.empty) graph = Graph.to_dep ?main_feat ~deco graph -let to_gr_graph graph = Graph.to_gr graph +let to_dot_graph ?main_feat ?(deco=Deco.empty) graph = G_graph.to_dot ?main_feat graph ~deco +let to_dep_graph ?main_feat ?(deco=Deco.empty) graph = G_graph.to_dep ?main_feat ~deco graph +let to_gr_graph graph = G_graph.to_gr graph diff --git a/src/grew_types.mli b/src/grew_types.mli index bc901ad229653b3fcd4e0f649296824d9873342e..d985b259e23fbc04b8107386295f02f956ddb3a7 100644 --- a/src/grew_types.mli +++ b/src/grew_types.mli @@ -3,7 +3,7 @@ open Grew_graph (**/**) -type graph = Graph.t +type graph = G_graph.t type deco = Deco.t (**/**) diff --git a/src/grew_utils.ml b/src/grew_utils.ml index b5718e393b4ed801b9b3907e452e1f143b35f6ef..74cb00570e1ee4603ccee9eb4282f3fcaf2c2f27 100644 --- a/src/grew_utils.ml +++ b/src/grew_utils.ml @@ -6,9 +6,16 @@ module StringMap = Map.Make (String) module IntSet = Set.Make (struct type t = int let compare = Pervasives.compare end) -module IntMap = +module IntMap = Map.Make (struct type t = int let compare = Pervasives.compare end) + +module Pid = struct + type t = int + let compare = Pervasives.compare +end + +module Pid_map = struct - include Map.Make (struct type t = int let compare = Pervasives.compare end) + include Map.Make (Pid) (** returns the image of a map [m]*) exception True @@ -172,6 +179,12 @@ module List_ = struct | [] -> "" | h::t -> List.fold_left (fun acc elt -> acc ^ sep ^ (string_of_item elt)) (string_of_item h) t + let rec sort_mem elt = function + | [] -> false + | h::t when elt<h -> false + | h::t when elt>h -> sort_mem elt t + | _ -> (* elt=h *) true + let rec sort_insert elt = function | [] -> [elt] | h::t when elt<h -> elt::h::t diff --git a/src/grew_utils.mli b/src/grew_utils.mli index 6030b3e2c7b32c8841efd4f2f1ed6638f03293e8..5b24918a750a0ddb20c8a2dd3249f82866e57f9c 100644 --- a/src/grew_utils.mli +++ b/src/grew_utils.mli @@ -1,7 +1,10 @@ module IntSet : Set.S with type elt = int +module IntMap : Map.S with type key = int -module IntMap : sig +module Pid : sig type t = int end + +module Pid_map : sig include Map.S with type key = int exception MatchNotInjective val exists: (key -> 'a -> bool) -> 'a t -> bool @@ -55,6 +58,8 @@ module List_: sig val mapi: (int -> 'a -> 'b) -> 'a list -> 'b list + val sort_mem: 'a -> 'a list -> bool + (* Insert an element in a sorted list. *) val sort_insert: 'a -> 'a list -> 'a list