]> matita.cs.unibo.it Git - fireball-separation.git/blobdiff - ocaml/lambda4.ml
Check for absence of bombs and pacmans
[fireball-separation.git] / ocaml / lambda4.ml
index 2e96fc3dc0ef658c05b87cd55bdca9e196baf73d..2f6a0a0fed506d5c82b4974aa87176268f91a298 100644 (file)
@@ -58,7 +58,7 @@ let first bound p var f =
    with Backtrack s ->
 prerr_endline (">>>>>> BACKTRACK (reason: " ^ s ^") measure=$ ");
      List.iter (fun (r,l) -> r := l) (List.combine p.deltas (List.hd p.trail)) ;
-prerr_endline("Now trying var="^string_of_var p.var_names var^" i="^string_of_int i);
+prerr_endline("Now trying var="^string_of_var p.var_names var^" i="^string_of_int (i+1));
      aux (i+1)
  in
   aux 1
@@ -284,10 +284,9 @@ List.iter (fun x -> prerr_endline ("IN2: " ^ print (fst x :> nf))) super_simplif
 
 exception Dangerous
 
-let arity_of arities k =
- let _,pos,y = List.find (fun (v,_,_) -> v=k) arities in
- let arity = match y with `Var _ -> 0 | `I(_,args) -> Listx.length args | `N _ -> assert false in
- arity + if pos = -1 then - 1 else 0
+let arity_of arities hd =
+ let pos,_,nargs = List.find (fun (_,hd',_) -> hd=hd') arities in
+ nargs + if pos = -1 then - 1 else 0
 ;;
 
 let rec dangerous arities showstoppers =
@@ -369,32 +368,40 @@ let rec edible ({div; conv; ps} as p) arities showstoppers =
            aux showstoppers xs
           with
            Dangerous ->
-            aux (sort_uniq (h::showstoppers)) ps
-  in
   let showstoppers = sort_uniq (aux showstoppers ps) in
   let dangerous_conv =
-     List.map (dangerous_conv p arities showstoppers) (conv :> nf_nob list) in
+            aux (sort_uniq (h::showstoppers)) ps in
+
+ let showstoppers = sort_uniq (aux showstoppers ps) in
+ let dangerous_conv =
+  List.map (dangerous_conv p arities showstoppers) (conv :> nf_nob list) in
 
 prerr_endline ("dangerous_conv lenght:" ^ string_of_int (List.length dangerous_conv));
 List.iter (fun l -> prerr_endline (String.concat " " (List.map (string_of_var p.var_names) l))) dangerous_conv;
 
   let showstoppers' = showstoppers @ List.concat dangerous_conv in
   let showstoppers' = sort_uniq (match div with
-     | None -> showstoppers'
-     | Some div ->
-       if List.exists ((=) (hd_of_i_var div)) showstoppers'
-       then showstoppers' @ free_vars (div :> nf) else showstoppers') in
   if showstoppers <> showstoppers' then edible p arities showstoppers' else showstoppers', dangerous_conv
+ let showstoppers' = showstoppers @ List.concat dangerous_conv in
+ let showstoppers' = sort_uniq (match div with
+  | None -> showstoppers'
+  | Some div ->
+    if List.exists ((=) (hd_of_i_var div)) showstoppers'
+    then showstoppers' @ free_vars (div :> nf) else showstoppers') in
+ if showstoppers <> showstoppers' then edible p arities showstoppers' else showstoppers', dangerous_conv
 ;;
 
 let precompute_edible_data {ps; div} xs =
- (match div with None -> [] | Some div -> [hd_of_i_var div, -1, (div :> i_n_var)]) @
-  List.map (fun hd ->
+ let aux t = match t with `Var _ -> 0 | `I(_, args) -> Listx.length args | `N _ -> assert false in
+ (fun l -> match div with
+  | None -> l
+  | Some div -> (-1, hd_of_i_var div, aux div) :: l)
+  (List.map (fun hd ->
    let i, tm = Util.findi (fun y -> hd_of y = Some hd) ps in
-    hd, i, tm
-   ) xs
+    i, hd, aux tm
+   ) xs)
 ;;
 
+(** Returns (p, showstoppers_step, showstoppers_eat) where:
+    - showstoppers_step are the heads occurring twice
+      in the same discriminating set
+    - showstoppers_eat are the heads in ps having different number
+      of arguments *)
 let critical_showstoppers p =
   let p = super_simplify p in
   let hd_of_div = match p.div with None -> [] | Some t -> [hd_of_i_var t] in
@@ -424,8 +431,8 @@ let critical_showstoppers p =
   let showstoppers_eat = List.filter
     (fun x -> not (List.mem x showstoppers_step))
     showstoppers_eat in
-  List.iter (fun v -> prerr_endline ("DANGEROUS STEP: " ^ (string_of_var p.var_names) v)) showstoppers_step;
-  List.iter (fun v -> prerr_endline ("DANGEROUS EAT: " ^ (string_of_var p.var_names) v)) showstoppers_eat;
+List.iter (fun v -> prerr_endline ("DANGEROUS STEP: " ^ (string_of_var p.var_names) v)) showstoppers_step;
+List.iter (fun v -> prerr_endline ("DANGEROUS EAT: " ^ (string_of_var p.var_names) v)) showstoppers_eat;
   p, showstoppers_step, showstoppers_eat
   ;;
 
@@ -434,30 +441,28 @@ let eat p =
   let showstoppers = showstoppers_step @ showstoppers_eat in
   let heads = List.sort compare (filter_map hd_of ps) in
   let arities = precompute_edible_data p (uniq heads) in
-  let showstoppers, showstoppers_conv =
-   edible p arities showstoppers in
-  let l = List.filter (fun (x,_,_) -> not (List.mem x showstoppers)) arities in
+  let inedible, showstoppers_conv = edible p arities showstoppers in
+  let l = List.filter (fun (_,hd,_) -> not (List.mem hd inedible)) arities in
   let p =
-  List.fold_left (fun p (x,pos,(xx : i_n_var)) -> if pos = -1 then p else
-   let n = match xx with `I(_,args) -> Listx.length args | _ -> 0 in
-   let v = `N(pos) in
-   let inst = make_lams v n in
-prerr_endline ("# INST_IN_EAT: " ^ string_of_var p.var_names x ^ " := " ^ string_of_term p inst);
-   { p with sigma = p.sigma @ [x,inst] }
+  List.fold_left (fun p (pos,hd,nargs) -> if pos = -1 then p else
+   let v = `N pos in
+   let inst = make_lams v nargs in
+prerr_endline ("# [INST_IN_EAT] eating: " ^ string_of_var p.var_names hd ^ " := " ^ string_of_term p inst);
+   { p with sigma = p.sigma @ [hd,inst] }
    ) p l in
   (* to avoid applied numbers in safe positions that
      trigger assert failures subst_in_problem x inst p*)
  let ps =
   List.map (fun t ->
    try
-    let _,j,_ = List.find (fun (h,_,_) -> hd_of t = Some h) l in
+    let j,_,_ = List.find (fun (_,hd,_) -> hd_of t = Some hd) l in
     `N j
    with Not_found -> t
   ) ps in
  let p = match p.div with
   | None -> p
   | Some div ->
-   if List.mem (hd_of_i_var div) showstoppers
+   if List.mem (hd_of_i_var div) inedible
    then p
    else
     let n = match div with `I(_,args) -> Listx.length args | `Var _ -> 0 in
@@ -465,14 +470,14 @@ prerr_endline ("# INST_IN_EAT: " ^ string_of_var p.var_names x ^ " := " ^ string
     let inst = make_lams `Bottom n in
     subst_in_problem x inst p in
  let dangerous_conv = showstoppers_conv in
-let _ = prerr_endline ("dangerous_conv lenght:" ^ string_of_int (List.length dangerous_conv));
-List.iter (fun l -> prerr_endline (String.concat " " (List.map (string_of_var p.var_names) l))) dangerous_conv; in
+prerr_endline ("dangerous_conv lenght:" ^ string_of_int (List.length dangerous_conv));
+List.iter (fun l -> prerr_endline (String.concat " " (List.map (string_of_var p.var_names) l))) dangerous_conv;
  let conv =
    List.map (function s,t ->
     try
      if s <> [] then t else (
      (match t with | `Var _ -> raise Not_found | _ -> ());
-     let _ = List.find (fun h -> hd_of t = Some h) showstoppers in
+     let _ = List.find (fun h -> hd_of t = Some h) inedible in
       t)
     with Not_found -> match hd_of t with
      | None -> assert (t = convergent_dummy); t
@@ -511,8 +516,8 @@ let safe_arity_of_var p x =
  List.fold_left (fun acc t -> Pervasives.min acc (aux t)) max_int tms
 ;;
 
-let instantiate p x perm =
- let n = (prerr_endline "WARNING: using constant initialSpecialK"); p.initialSpecialK in
+let instantiate p x perm =
+ let n = (prerr_endline ("WARNING: using constant initialSpecialK=" ^ string_of_int p.initialSpecialK)); p.initialSpecialK in
  let arities = Array.to_list (Array.make (n+1) min_int) in
  let p,vars = make_fresh_vars p arities in
  (* manual lifting of vars by perm in next line *)
@@ -540,15 +545,28 @@ let compute_special_k tms =
  | `Bottom
  | `Pacman
  | `Var _ -> 0
- ) in Listx.max (Listx.map (aux 0) tms)
+ ) in
+ let rec aux' top t = match t with
+ | `Lam(_,t) -> aux' false t
+ | `I((_,ar), tms) -> max ar
+     (Listx.max (Listx.map (aux' false) (tms :> nf Listx.listx)))
+ | `Match(t, _, liftno, bs, args) ->
+     List.fold_left max 0 (List.map (aux' false) ((t :> nf)::(args :> nf list)@List.map snd !bs))
+ | `N _
+ | `Bottom
+ | `Pacman
+ | `Var _ -> 0 in
+ Listx.max (Listx.map (fun t -> max (aux 0 t) (aux' true t)) tms)
 ;;
 
-let choose_step (n,p) =
+let choose_step p =
  let p, showstoppers_step, showstoppers_eat = critical_showstoppers p in
  let x =
   match showstoppers_step, showstoppers_eat with
   | [], y::_ ->
-     prerr_endline ("INSTANTIATING CRITICAL TO EAT " ^ string_of_var p.var_names y); y
+     prerr_endline ("INSTANTIATING (critical eat) : " ^ string_of_var p.var_names y); y
+  | x::_, _ ->
+     prerr_endline ("INSTANTIATING (critical step): " ^ string_of_var p.var_names x); x
   | [], [] ->
      let heads =
       (* Choose only variables still alive (with arity > 0) *)
@@ -563,10 +581,7 @@ let choose_step (n,p) =
            Not_found -> assert false)
       | x::_ ->
          prerr_endline ("INSTANTIATING TO EAT " ^ string_of_var p.var_names x);
-         x)
-  | x::_, _ ->
-      prerr_endline ("INSTANTIATING " ^ string_of_var p.var_names x);
-      x in
+         x) in
 (* Strategy that  decreases the special_k to 0 first (round robin)
 1:11m42 2:14m5 3:11m16s 4:14m46s 5:12m7s 6:6m31s *)
  let x =
@@ -597,81 +612,39 @@ let x =
  with
   Not_found -> x
 in*)
- let special_k =
-     compute_special_k (Listx.from_list (all_terms p :> nf list) )in
- if special_k < n then
-  prerr_endline ("@@@@ NEW INSTANTIATE PHASE (" ^ string_of_int special_k ^ ") @@@@");
  let arity_of_x = Util.option_get (max_arity_tms x (all_terms p)) in
  let safe_arity_of_x = safe_arity_of_var p x in
- x, min arity_of_x safe_arity_of_x, special_k
+ x, min arity_of_x safe_arity_of_x
+;;
 
-let rec auto_eat (n,p) =
+let rec auto_eat p =
  prerr_endline "{{{{{{{{ Computing measure before auto_instantiate }}}}}}";
  let m = problem_measure p in
- let x, arity_of, n = choose_step (n,p) in
+ let x, arity_of = choose_step p in
  first arity_of p x (fun p j ->
-  let p' = instantiate p x j in
+  let p' = instantiate p x j in
   match eat p' with
   | `Finished p -> p
   | `Continue p ->
       prerr_endline "{{{{{{{{ Computing measure inafter auto_instantiate }}}}}}";
       let delta = problem_measure p - m in
-      (* let delta = m - problem_measure p' in *)
       if delta >= 0
        then
         (failwith
         ("Measure did not decrease (+=" ^ string_of_int delta ^ ")"))
-       else prerr_endline ("$ Measure decreased of " ^ string_of_int delta);
-      auto_eat (n,p))
+       else prerr_endline ("$ Measure decreased: " ^ string_of_int delta);
+      auto_eat p)
 ;;
 
 let auto p n =
- prerr_endline ("@@@@ FIRST INSTANTIATE PHASE (" ^ string_of_int n ^ ") @@@@");
+prerr_endline ("@@@@ FIRST INSTANTIATE PHASE (" ^ string_of_int n ^ ") @@@@");
  match eat p with
  | `Finished p -> p
- | `Continue p -> auto_eat (n,p)
+ | `Continue p -> auto_eat p
 ;;
 
-(*
-0 = snd
-
-      x y = y 0    a y = k  k z = z 0  c y = k   y u = u h1 h2 0          h2 a = h3
-1 x a c    1 a 0 c  1 k c    1 c 0      1 k        1 k                     1 k
-2 x a y    2 a 0 y  2 k y    2 y 0      2 y 0      2 h2 0                  2 h3
-3 x b y    3 b 0 y  3 b 0 y  3 b 0 y    3 b 0 y    3 b 0 (\u. u h1 h2 0)   3 b 0 (\u. u h1 (\w.h3) 0)
-4 x b c    4 b 0 c  4 b 0 c  4 b 0 c    4 b 0 c    4 b 0 c                 4 b 0 c
-5 x (b e)  5 b e 0  5 b e 0  5 b e 0    5 b e 0    5 b e 0                 5 b e 0
-6 y y      6 y y    6 y y    6 y y      6 y y      6 h1 h1 h2 0 h2 0       6 h1 h1 (\w. h3) 0 (\w. h3) 0
-
-                                l2 _ = l3
-b u = u l1 l2 0                 e _ _ _ _ = f                         l3 n = n j 0
-1 k                             1 k                                  1 k
-2 h3                            2 h3                                 2 h3
-3 l2 0 (\u. u h1 (\w. h3) 0)    3 l3 (\u. u h1 (\w. h3) 0)           3 j h1 (\w. h3) 0 0
-4 l2 0 c                        4 l3 c                               4 c j 0
-5 e l1 l2 0 0                   5 f                                  5 f
-6 h1 h1 (\w. h3) 0 (\w. h3) 0   6 h1 h1 (\w. h3) 0 (\w. h3) 0        6 h1 h1 (\w. h3) 0 (\w. h3) 0
-*)
 
-(*
-                x n = n 0 ?
-x a (b (a c))   a 0 = 1 ? (b (a c))   8
-x a (b d')      a 0 = 1 ? (b d')      7
-x b (a c)       b 0 = 1 ? (a c)       4
-x b (a c')      b 0 = 1 ? (a c')      5
-
-c = 2
-c' = 3
-a 2 = 4  (* a c *)
-a 3 = 5  (* a c' *)
-d' = 6
-b 6 = 7  (* b d' *)
-b 4 = 8  (* b (a c) *)
-b 0 = 1
-a 0 = 1
-*)
-
-(************** Tests ************************)
+(******************************************************************************)
 
 let optimize_numerals p =
   let replace_in_sigma perm =
@@ -784,23 +757,27 @@ let solve (p, todo) =
        Backtrack _ -> `Unseparable "backtrack"
 ;;
 
+let no_bombs_pacmans p =
+    not (List.exists (eta_subterm `Bottom) (p.ps@p.conv))
+ && not (List.exists (eta_subterm `Pacman) p.ps)
+ && Util.option_map (eta_subterm `Pacman) p.div <> Some true
+;;
+
 let check p =
- (* TODO check if there are duplicates in p.ps
-     before it was: ps = sort_uniq ~compare:eta_compare (ps :> nf list) *)
- (* FIXME what about initial fragments? *)
  if (let rec f = function
      | [] -> false
      | hd::tl -> List.exists (eta_eq hd) tl || f tl in
-   f p.ps)
+   f p.ps) (* FIXME what about initial fragments of numbers? *)
   then `CompleteUnseparable "ps contains duplicates"
  (* check if div occurs somewhere in ps@conv *)
  else if (match p.div with
   | None -> true
   | Some div -> not (List.exists (eta_subterm div) (p.ps@p.conv))
-  ) && false (* TODO no bombs && pacmans *)
+  ) && no_bombs_pacmans p
   then `CompleteSeparable "no bombs, pacmans and div"
- else if false (* TODO bombs or div fuori da lambda in ps@conv *)
-  then `CompleteUnseparable "bombs or div fuori da lambda in ps@conv"
+  (* il check seguente e' spostato nel parser e lancia un ParsingError *)
+ (* else if false (* TODO bombs or div fuori da lambda in ps@conv *)
+  then `CompleteUnseparable "bombs or div fuori da lambda in ps@conv" *)
  else if p.div = None
   then `CompleteSeparable "no div"
  else `Uncomplete