From: acondolu Date: Wed, 12 Jul 2017 09:18:36 +0000 (+0200) Subject: andrea7 -> new andrea9 X-Git-Url: http://matita.cs.unibo.it/gitweb/?a=commitdiff_plain;h=a8a1711bd83c1d405a9fac806bc6baec8a8f165f;p=fireball-separation.git andrea7 -> new andrea9 - Removed Stuck and Pointer - Added again bool flag to match entries to recall if coming from div or conv - branches coming from div may diverge - branches whose continuation is still a variable are completed Fixed bug where entries in matches were not counted in all_terms Still crashing --- diff --git a/ocaml/Makefile b/ocaml/Makefile index b97d5af..de63c63 100644 --- a/ocaml/Makefile +++ b/ocaml/Makefile @@ -2,22 +2,10 @@ OCAMLC = ocamlopt -g -rectypes LIB = unix.cmxa str.cmxa UTILS = parser.cmx console.cmx listx.cmx util.cmx pure.cmx num.cmx -all: a.out test.out test34.out +all: andrea.out -a.out: $(UTILS) lambda3.cmx lambda4.cmx problems.cmx - $(OCAMLC) -o a.out $(LIB) $^ - -test.out: $(UTILS) lambda3.cmx test1.ml - $(OCAMLC) -o test.out $(LIB) $^ - -test34.out: $(UTILS) lambda3.cmx lambda4.cmx test.ml - $(OCAMLC) -o test34.out $(LIB) $^ - -andrea.out: $(UTILS) a.out andrea7.ml - $(OCAMLC) -o andrea.out $(LIB) $(UTILS) andrea7.ml - -#test2.out: $(UTILS) lambda3.ml test2.ml andrea -# ocamlc -o test2.out $(LIB) $(UTILS) lambda3.ml andrea4.ml test2.ml +andrea.out: $(UTILS) andrea8.ml + $(OCAMLC) -o andrea.out $(LIB) $(UTILS) andrea8.ml %.cmi: %.mli $(OCAMLC) -c $< @@ -26,7 +14,7 @@ andrea.out: $(UTILS) a.out andrea7.ml $(OCAMLC) -c $< clean: - rm -f *.cm* *.out .depend log + rm -f *.cm* *.out *.o .depend log .depend: *.ml *.mli ocamldep *.ml *.mli > .depend diff --git a/ocaml/andrea8.ml b/ocaml/andrea8.ml new file mode 100644 index 0000000..7fd82eb --- /dev/null +++ b/ocaml/andrea8.ml @@ -0,0 +1,736 @@ +let (++) f g x = f (g x);; + +let print_hline = Console.print_hline;; + +type var = int;; +type t = + | V of var + | A of t * t + | L of t + | B (* bottom *) + | P (* pacman *) + (* | Stuck of var * int *) + (* | Ptr of int *) +;; + +let rec consts = (* const_apps, const_lambda *) + let rec aux1 = function + | A(t, _) -> 1 + aux1 t + | _ -> 0 in + let rec aux2 = function + | L t -> 1 + aux2 t + | _ -> 0 in + function + | A(t1, t2) as t -> + let a1, b1 = consts t1 in + let a2, b2 = consts t2 in + max (aux1 t) (max a1 a2), max b1 b2 + | L t' as t -> + let a, b = consts t' in + a, max (aux2 t) b + | _ -> 0, 0 +;; + + +type problem = { + orig_freshno: int + ; freshno : int + ; div : t + ; conv : t list + ; matches : (var (* variable originating this match *) * ((bool (* coming from div *) * t (* term to discriminate *) * var (* continuation *))) list) list + ; sigma : (var * t) list (* substitutions *) + ; stepped : var list + ; arities : (var * int) list + ; k_app : int + ; k_lam : int +} + +let dummy_p = {orig_freshno=0; freshno=0; div=B; conv=[]; matches=[]; sigma=[]; stepped=[]; arities=[]; k_app=0;k_lam=0};; + +let append_conv p t = let len = List.length p.conv in let p = {p with conv=t::p.conv} in p, len;; +let get_conv p n = List.nth p.conv (List.length p.conv - 1 - n);; +let index_of_conv t conv = List.length conv - 1 - (Util.index_of t conv);; + +let eq_conv = (=);; +let eq_conv_indices p i j = eq_conv (get_conv p i) (get_conv p j);; +let all_terms p = (p.div :: p.conv) @ Util.concat_map (fun (_, lst) -> List.map (fun (_,x,_) -> x) lst) p.matches;; + +exception Done of (var * t) list (* substitution *);; +exception Fail of int * string;; + +let string_of_t p = + let bound_vars = ["x"; "y"; "z"; "w"; "q"; "x1"; "x2"; "x3"; "x4"; "x5"] in + let rec string_of_term_w_pars level = function + | V v -> if v >= level then "`" ^ string_of_int (v-level) else List.nth bound_vars (level - v-1) + | A _ + | L _ as t -> "(" ^ string_of_term_no_pars_lam level t ^ ")" + | B -> "BOT" + | P -> "PAC" + (* | Stuck _ as t -> "(" ^ string_of_term_no_pars_app level t ^ ")" *) + (* | Ptr _ as t-> "(" ^ string_of_term_no_pars_app level t ^ ")" *) + (* "&" ^ string_of_int n *) + and string_of_term_no_pars_app level = function + | A(t1,t2) -> (string_of_term_no_pars_app level t1) ^ " " ^ (string_of_term_w_pars level t2) + (* | Stuck(v,n) -> ":" ^ string_of_term_no_pars_app level (V v) ^ " " ^ (string_of_term_w_pars level (get_conv p n)) *) + (* | Ptr n -> string_of_term_no_pars_app level (get_conv p n) *) + (* | Ptr n -> "&" ^ string_of_int n *) + | _ as t -> string_of_term_w_pars level t + and string_of_term_no_pars_lam level = function + | L t -> "λ" ^ string_of_term_w_pars (level+1) (V 0) ^ ". " ^ (string_of_term_no_pars_lam (level+1) t) + | _ as t -> string_of_term_no_pars level t + and string_of_term_no_pars level = function + | L _ as t -> string_of_term_no_pars_lam level t + | _ as t -> string_of_term_no_pars_app level t + in string_of_term_no_pars 0 +;; + +let string_of_problem p = + let lines = [ + "[arities] " ^ String.concat " " (List.map (fun (v,n) -> "`" ^ string_of_int v ^ "=" ^ string_of_int n) p.arities); + "[stepped] " ^ String.concat " " (List.map string_of_int p.stepped); + "[DV] " ^ (string_of_t p p.div); + "[CV] " ^ String.concat "\n " (List.map (string_of_t p) p.conv); + (* "" ; *) + ] @ Util.concat_map (fun (v, lst) -> ("[<>] of "^(string_of_t p (V v))) :: List.map (fun (b,t,c) -> (if b then " * " else " ") ^ string_of_t p t + ^ " -> " ^ string_of_t p (V c) + ) lst) p.matches @ [""] in + String.concat "\n" lines +;; + +let problem_fail p reason = + print_endline "!!!!!!!!!!!!!!! FAIL !!!!!!!!!!!!!!!"; + print_endline (string_of_problem p); + raise (Fail (-1, reason)) +;; + +let freshvar ({freshno} as p) = + {p with freshno=freshno+1}, freshno+1 +;; + +let add_to_match p id fromdiv t = + let p, v = freshvar p in + let arity = (List.assoc id p.arities) - 1 in + let entry = fromdiv, t, v in + let matches = + List.map (fun (id',lst as x) -> if id <> id' then x else (id, entry::lst)) p.matches + in + let arities = (v,arity) :: p.arities in + {p with matches; arities}, V v +;; + +let var_occurs_in p v = + let rec aux level = function + | V v' -> v + level = v' + (* | Stuck(v',n) -> assert (v <> v'); aux level (get_conv p n) *) + | A(t1,t2) -> (aux level t1) || (aux level t2) + | L t -> aux (level+1) t + | B -> false + | P -> false + (* | Ptr n -> aux level (get_conv p n) *) + + in aux 0 +;; + +let rec is_inert p = + function + | A(t,_) -> is_inert p t + (* | Ptr n -> is_inert p (get_conv p n) *) + | V _ -> true + | L _ | B | P -> false +;; + +let is_var = function V _ -> true | _ -> false;; +let is_lambda = function L _ -> true | _ -> false;; +let is_pacman = function P -> true | _ -> false;; + +let rec subst level delift fromdiv sub p = + function + | V v -> p, if v = level + fst sub then lift level (snd sub) else V (if delift && v > level then v-1 else v) + | L t -> let p, t = subst (level + 1) delift fromdiv sub p t in p, L t + | A (t1,t2) -> + let p, t1 = subst level delift fromdiv sub p t1 in + let p, t2 = subst level delift fromdiv sub p t2 in + if t1 = B || t2 = B then p, B else + if level = 0 then mk_app fromdiv p t1 t2 else p, A (t1, t2) + | B -> p, B + | P -> p, P +and mk_app fromdiv p t1 t2 = let t1 = if t1 = P then L P else t1 in match t1 with + | B | _ when t2 = B -> p, B + | L t1 -> subst 0 true fromdiv (0, t2) p t1 + | V v when List.mem v p.stepped -> + let p, x = add_to_match p v fromdiv t2 in + p, x + | t1 -> p, A (t1, t2) +and mk_apps fromdiv p t = + function + | [] -> p, t + | t'::ts -> let p, t = mk_app fromdiv p t t' in mk_apps fromdiv p t ts +and lift n = + let rec aux n' = + function + | V m -> V (if m >= n' then m + n else m) + | L t -> L (aux (n'+1) t) + | A (t1, t2) -> A (aux n' t1, aux n' t2) + | B -> B + | P -> P + in aux 0 +;; + +let subst = subst 0 false;; + +let mk_lambda t = L (lift 1 t) ;; + +let subst_conv sub = + let rec aux p = function + | [] -> p, [] + | t::tms -> + let p, tms = aux p tms in + let p, t = subst false sub p t in + p, t :: tms + in aux +;; + +let subst_in_problem (sub: var * t) (p: problem) = +print_endline ("SUBST IN PROBLEM: " ^ string_of_t p (V (fst sub)) ^ " |-> " ^ string_of_t p (snd sub)); +(* BUG QUI FIXME!!!! *) + let rec mix l1 l2 = match l1, l2 with + | [], l2 -> l2 + | x::xs, _::ys -> x:: (mix xs ys) + | _ -> assert false in + let p = {p with stepped=(fst sub)::p.stepped} in + let p, conv = subst_conv sub p p.conv in + let p, div = subst true sub p p.div in + let conv = List.rev (mix (List.rev conv) (List.rev p.conv)) in + let p = {p with div; conv} in + (* print_endline ("after sub: \n" ^ string_of_problem p); *) + {p with sigma=sub::p.sigma} +;; + +(* FIXME *) +let unify_terms p v1 v2 = + if List.mem v1 p.stepped + then problem_fail p "The collapse of a match came after too many steps :("; + subst_in_problem (v1, V v2) p +;; + +let rec unify p = + let rec give_duplicates = + let rec aux' t = function + | [] -> [], None + | (b',t',c')::ts -> if t = t' (* FIXME! eta-eq here *) then ts, Some (b',c') else ( + let ts, res = aux' t ts in (b',t',c')::ts, res) in + let rec aux = function + | [] -> [], None + | (b,t,c)::rest -> ( + match aux' t rest with + | rest, None -> aux rest + | rest, Some(b',c') -> (b || b', t, c) :: rest, Some(c', c) + ) in + function + | [] -> [], None + | (orig,branches) :: ms -> + match aux branches with + | _, None -> let ms, res = give_duplicates ms in (orig,branches) :: ms, res + | branches', Some subst -> (orig,branches') :: ms, Some subst in + let matches, vars_to_be_unified = give_duplicates p.matches in + let p = {p with matches=matches} in + match vars_to_be_unified with + | None -> p + | Some(t', t) -> + (* print_endline ("> unify " ^ string_of_t p (t') ^ " with " ^ string_of_t p t); *) + unify (unify_terms p t' t) +;; + +let problem_done p = + let condition (b, t, cont) = + (b && t = B) || + (not (List.mem cont p.stepped)) || + is_var t in + let all_separated = List.for_all (fun (_, lst) -> List.for_all condition lst) p.matches in + all_separated && p.div = B +;; + +let free_vars p t = + let rec aux level = function + | V v -> if v >= level then [v] else [] + | A(t1,t2) -> (aux level t1) @ (aux level t2) + | L t -> aux (level+1) t + | B | P -> [] + in Util.sort_uniq (aux 0 t) +;; + +let visible_vars p t = + let rec aux = function + | V v -> [v] + | A(t1,t2) -> (aux t1) @ (aux t2) + | B | P + | L _ -> [] + (* | Ptr n -> aux (get_conv p n) *) + in Util.sort_uniq (aux t) +;; + + +let rec simple_explode p = + match p.div with + | V var -> + let subst = var, B in + sanity (subst_in_problem subst p) + | _ -> p + +and sanity p = + (* Sanity checks: *) + if (function | P | L _ -> true | _ -> false) p.div then problem_fail p "p.div converged"; + if List.mem B p.conv then problem_fail p "p.conv diverged"; + let solvable (b,t,c) = (b && not (List.mem c p.stepped)) || is_inert p t in + if not (List.for_all (fun (_, lst) -> List.for_all solvable lst) p.matches) + then problem_fail p "Unsolvable discrimination"; + + let p = unify p in + print_endline (string_of_problem p); (* non cancellare *) + let p = if problem_done p then raise (Done p.sigma) else p in + let p = if is_var p.div then simple_explode p else p in + p +;; + +let print_cmd s1 s2 = print_endline (">> " ^ s1 ^ " " ^ s2);; + +let rec hd_args t = match t with + | V v -> v, [] + | A(t1,t2) -> let a, b = hd_args t1 in a, b @ [t2] + | _ -> -666, [] +;; + +let max_arity_of_var v = + let rec aux level = + function + | V _ -> 0 + | A _ as t -> print_string (string_of_t dummy_p t); let hd, args = hd_args t in + let acc = if hd = level + v then List.length args else 0 in + List.fold_right (max ++ (aux level)) args acc + | L t -> aux (level + 1) t + | P | B -> 0 + in aux 0 +;; + +let ignore var n p = + print_cmd "EAT" ("on " ^ string_of_t p (V var) ^ " (of:" ^ string_of_int n ^ ")"); + let rec aux m t = + if m = 0 + then lift n t + else L (aux (m-1) t) in + let p, fresh = freshvar p in + let subst = var, aux n (V fresh) in + sanity (subst_in_problem subst p) +;; + + + +let eat var p = + print_cmd "EAT" ("var " ^ string_of_t p (V var)); + let rec is_hd v' = function + | A (t,_) -> is_hd v' t + | V v -> v' = v + | _ -> false in + let rec app_length = function + | A (t,_) -> 1 + app_length t + | _ -> 0 in + let rec find_app_no = function + | V _ | L _ | P | B -> 0 + | A (t1,t2) as t -> + max (max (find_app_no t1) (find_app_no t2)) + (if is_hd var t1 then app_length t else 0) + in let n = List.fold_right (max ++ find_app_no) (all_terms p) 0 in + let rec aux m t = + if m = 0 + then lift n t + else L (aux (m-1) t) in + let p, fresh = freshvar p in + let subst = var, aux n (V fresh) in + sanity (subst_in_problem subst p) +;; + +(* let explode p = + let fv1 = visible_vars p p.div in + let fv2 = List.concat (List.map (visible_vars p) p.conv) in + let fv = List.filter (fun x -> not (List.mem x fv2)) fv1 in + let fv = List.filter ((<) p.orig_freshno) fv in + match fv with + | var::_ -> + print_cmd "EXPLODE" ("on " ^ string_of_t p (V var)); + let subst = var, B in + sanity (subst_in_problem subst p) + | _ -> raise (Fail (-1,"premature explosion")) +;; *) + +(* let step var p = + print_cmd "STEP" ("on " ^ string_of_t p (V var)); + let matches = (var,[])::p.matches in + let p = {p with matches;stepped=var::p.stepped} in + let subst = var, V var in + sanity (subst_in_problem subst p) +;; *) + +let choose n p = + print_cmd "CHOOSE" ("#" ^ string_of_int n); + let rec aux n t = match t with + | V _ -> 0, t + | A(t1,_) -> let n', t' = aux n t1 in if n = n' then n', t' else n'+1, t + | _ -> assert false + in let n', div = aux n p.div in + if n' <> n then problem_fail p "wrong choose"; + let p = {p with div} in + sanity p +;; + +let apply var appk p = + print_cmd "APPLY" + (string_of_t p (V var) ^ " applies no." ^ string_of_int appk ^ " fresh variables"); + let rec mk_freshvars n p = + if n = 0 + then p, [] + else + let p, vs = mk_freshvars (n-1) p in + let p, v = freshvar p in + p, V(v)::vs in + let p, vars = mk_freshvars appk p in + let p, t = mk_apps false p (V 0) (List.map (lift 1) vars) in + let t = L (A (lift 1 (V var), t)) in + let subst = var, t in + sanity (subst_in_problem subst p) +;; + +let find_arities_after_app p = + let rec aux level n = function + | L t -> assert (n > 0); max_arity_of_var level t :: aux (level+1) (n-1) t + | _ -> Array.to_list (Array.make n 0) + in aux 0 +;; +let find_all_first_args_of v = + let rec aux level = function + | L t -> aux (level+1) t + | V _ -> [] + | A(V v', t2) -> (if v + level = v' then [t2] else []) @ aux level t2 + | A(t1,t2) -> aux level t1 @ aux level t2 + | _ -> [] + in aux 0 +;; + +let step' var p = + let appk = p.k_lam + p.k_app + 1 in + print_cmd "STEP'" ("on " ^ string_of_t p (V var) ^ " and applies no." ^ string_of_int appk ^ " fresh variables"); + let p, vars = (* +1 below because of lifting *) + Array.fold_left (fun (p,vars) _ -> let p, v = freshvar p in p, (v+1)::vars) + (p, []) (Array.make appk ()) in + let p, t = mk_apps false p (V 0) (List.map (fun x -> V x) vars) in + + let first_args = Util.sort_uniq (List.fold_right ((@) ++ (find_all_first_args_of var)) (all_terms p) []) in + let map = List.fold_left (fun acc t -> let acc' = find_arities_after_app p appk t in List.map (fun (x,y) -> max x y) (List.combine acc acc')) (Array.to_list (Array.make appk 0)) first_args in + let arities = List.combine (List.map ((+) (-1)) vars) map in + + (* let p, var' = freshvar p in *) + let p, var' = p, var in + let matches = (var', []) :: p.matches in + let p = {p with matches; arities=arities@p.arities} in + let t = L (A (lift 1 (V var'), t)) in + let subst = var, t in + sanity (subst_in_problem subst p) +;; + +let perm var n p = + if n = 1 then p else ( + print_cmd "PERM" ("on " ^ string_of_t p (V var) ^ " (of:" ^ string_of_int n ^ ")"); + (* let p, v = freshvar p in *) + let p, v = p, var in + let rec aux' m t = if m < 0 then t else A(aux' (m-1) t, V m) in + let rec aux m t = + if m = 0 + then aux' (n-1) t + else L (aux (m-1) t) in + let t = aux n (lift n (V v)) in + let subst = var, t in + (* let p = {p with arities=(v, List.assoc var p.arities)::p.arities} in *) + sanity (subst_in_problem subst p) +) ;; + +let free_vars_of_p p = + Util.sort_uniq (Util.concat_map (free_vars p) (all_terms p));; + +let rec applied_vars p = function +| B | P -> [] +| L _ -> [] (* ??? *) +| V _ -> [] +| A(V v,t2) -> v :: applied_vars p t2 +| A(t1,t2) -> applied_vars p t1 @ applied_vars p t2 +;; + +let applied_vars_of_p p = + Util.sort_uniq (Util.concat_map (applied_vars p) (all_terms p));; + +let rec auto p = + let aux f var = + try + auto (f var); () + with + (* | Done _ as d -> raise d *) + | Fail(_, s) -> print_endline ("<<< Backtracking because: " ^ s) in + print_endline ">>> auto called"; + (* Compute useful free variables *) + let fv = applied_vars_of_p p in + let fv = List.filter (fun v -> not (List.mem v p.stepped)) fv in + List.iter (fun v -> print_string ("@`" ^ string_of_int v)) fv; + let fv0 = List.filter (fun v -> List.assoc v p.arities > 0) fv in (* remove variable with arity left 0, cannot step there *) + if fv0 = [] then (print_endline "warning! empty step fv0"; List.iter (fun v -> print_string ("@`" ^ string_of_int v)) fv); + let permute_and_step p v = + let step'' problem prm var = + let problem = perm var prm problem in + (* let _ = read_line () in *) + let problem = step' var problem in + problem in + let arity = List.assoc v p.arities in + let _, perms = Array.fold_left (fun (arity, acc) () -> let a = arity + 1 in a, a::acc) (1,[1]) (Array.make (arity-1) ()) in + List.iter (fun perm -> aux (step'' p perm) v) perms + in + List.iter (permute_and_step p) fv0; + List.iter (aux (fun v -> eat v p)) fv; + (* mancano: applicazioni e choose; ??? *) +;; + +let parse strs = + let rec aux level = function + | Parser.Lam t -> L (aux (level + 1) t) + | Parser.App (t1, t2) -> + if level = 0 then snd (mk_app false dummy_p (aux level t1) (aux level t2)) + else A(aux level t1, aux level t2) + | Parser.Var v -> V v + in let (tms, free) = Parser.parse_many strs + in (List.map (aux 0) tms, free) +;; + +let magic6 div conv cmds = + print_hline (); + let all_tms, var_names = parse (div :: conv) in + let div, conv = List.hd all_tms, List.tl all_tms in + let varno = List.length var_names in + let k_app, k_lam = List.fold_left (fun (a, b) t -> let a', b' = consts t in max a a', max b b') (0,0) all_tms in + let p = {orig_freshno=varno; freshno=1+varno; div; conv; matches=[]; sigma=[]; stepped=[];k_app;k_lam;arities=[]} in + let fv = Util.sort_uniq (Util.concat_map (free_vars p) all_tms) in + let arities = List.map (fun var -> var, k_app) fv in + let p = {p with arities} in + let p = try + let subst = Util.index_of "BOMB" var_names, L B in + let p = subst_in_problem subst p in p + with Not_found -> p in + let p = sanity p in + try + problem_fail (List.fold_left (|>) p cmds) "Problem not completed" + with + | Done _ -> () +;; + +let auto div conv = + print_hline (); + let all_tms, var_names = parse (div :: conv) in + let div, conv = List.hd all_tms, List.tl all_tms in + let varno = List.length var_names in + let k_app, k_lam = List.fold_left (fun (a, b) t -> let a', b' = consts t in max a a', max b b') (0,0) all_tms in + let p = {orig_freshno=varno; freshno=1+varno; div; conv; matches=[]; sigma=[]; stepped=[];k_app;k_lam;arities=[]} in + let fv = Util.sort_uniq (Util.concat_map (free_vars p) all_tms) in + let max_arity_of_var_in_p var p = + 1 + List.fold_right (max ++ (max_arity_of_var var)) (all_terms p) 0 in + let arities = List.map (fun var -> var, max_arity_of_var_in_p var p) fv in + let p = {p with arities} in + let p = try + let subst = Util.index_of "BOMB" var_names, L B in + let p = subst_in_problem subst p in p + with Not_found -> p in + let p = sanity p in + try + auto p; + failwith "auto failed." + with + | Done _ -> print_endline "<<< auto ok >>>"; (* TODO: print and verify substitution *) +;; + +(* let interactive div conv cmds = + print_hline (); + let all_tms, var_names = parse (div @ conv) in + let div, conv = list_split (List.length div) all_tms in + let varno = List.length var_names in + let p = {orig_freshno=varno; freshno=1+varno; div; conv; matches=[]; sigma=[]} in + (* activate bombs *) + let p = try + let subst = Util.index_of "BOMB" var_names, L B in + subst_in_problem subst p + with Not_found -> p in + (* activate pacmans *) + let p = try + let subst = Util.index_of "PACMAN" var_names, P in + let p = subst_in_problem subst p in + (print_endline ("after subst in problem " ^ string_of_problem p); p) + with Not_found -> p in + (* initial sanity check *) + let p = sanity p in + let p = List.fold_left (|>) p cmds in + let rec f p cmds = + let nth spl n = int_of_string (List.nth spl n) in + let read_cmd () = + let s = read_line () in + let spl = Str.split (Str.regexp " +") s in + s, let uno = List.hd spl in + try if uno = "explode" then explode + else if uno = "ignore" then ignore (nth spl 1) (nth spl 2) + else if uno = "step" then step (nth spl 1) + else if uno = "perm" then perm (nth spl 1) (nth spl 2) + else if uno = "apply" then apply (nth spl 1) (nth spl 2) + (* else if uno = "forget" then forget (nth spl 1) (nth spl 2) *) + else if uno = "id" then id (nth spl 1) + else failwith "Wrong input." + with Failure s -> print_endline s; (fun x -> x) in + let str, cmd = read_cmd () in + let cmds = (" " ^ str ^ ";")::cmds in + try + let p = cmd p in f p cmds + with + | Done -> print_endline "Done! Commands history: "; List.iter print_endline (List.rev cmds) + in f p [] +;; *) + +let _ = auto + "x x" + [ "_. BOMB" ] + (* [ eat 1 ] *) +;; + + +let _ = auto + "x y BOMB b" + [ "x BOMB y c" ] + (* [ perm 1 3; step' 8 ; eat 4; eat 5; eat 15; ] *) +;; + + +let _ = auto + "x BOMB a1 c" + [ "x y BOMB d"; "x BOMB a2 c" ] + (* [ perm 1 3 ; step' 10 ; eat 4; eat 6; step' 17; eat 3; eat 7; eat 27; ] *) +;; + + +let _ = auto + "x (x x)" + [ "x x" ; "x x x" ] + (* [ + step' 1; + eat 6; eat 9; eat 13; +]*) +;; + + +(* let _ = auto + "x (_.BOMB)" + [ "x (_._. BOMB)" ] + (* [ apply 1 2; ] *) +;; *) + + +let _ = auto + "x (_.y)" + [ "y (_. x)" ] + (* [ apply 1 1; ignore 1 1; explode; ] *) +;; + + +let _ = auto + "y (x a1 BOMB c) (x BOMB b1 d)" + [ "y (x a2 BOMB c) (x BOMB b1 d)"; + "y (x a1 BOMB c) (x BOMB b2 d)";] + (* [perm 2 3; + step 12; + perm 17 2; + step 19; + step 18; + ignore 22 1; + ignore 21 1; + ignore 24 1; + ignore 25 1; + step 1; + step 32; + explode; + ] *) +;; + +let _ = auto +"PACMAN (x x x)" ["PACMAN (x x)"];; + +(* +let _ = magic6 + ["z (y x)"] + [ "z (y (x.x))"; "y (_. BOMB)" ] + [ apply 2 1; step 3; explode; ] +;; + +let _ = magic6 + ["y x"] + [ "y (x.x)"; "x (_. BOMB)" ] + [ apply 1 1; ignore 2 1; step 1; explode; ] +;; + +let _ = magic6 + ["z (y x)"] + [ "z (y (x.x))"; "y (_. BOMB)" ] + [ step 1; explode; apply 2 1; id 2; ignore 3 1; ] +;; + +let _ = magic6 + ["y (x a)"] + [ "y (x b)"; "x BOMB" ] [ + id 2; + step 1; + explode; +];; + +magic6 + ["y (x a)"] [ "y (x b)"; "x BOMB"; "y a" ] + [ + apply 1 1; + perm 2 2; + ignore 9 1; + step 10; + explode; + ];; +(* "y (a c)" +[ "y (b c)"; "y (x a)"; "y (x b)"; "x BOMB" ] *) + +magic6 +["x a (x (a.y BOMB))"] +[ "x b"; "x (y c)"; "x (y d)" ] +[apply 1 1; +apply 2 1; +explode;] +(* [ +step 1; +step 3; +explode' 10; +(* ma si puo' fare anche senza forget *) *) +(* ] *) +;; + +(* dipendente dalla codifica? no, ma si risolve solo con id *) +magic6 + ["y a"] ["y b"; "x (y (_.BOMB))"] +[ +apply 1 1; +apply 2 1; +explode; +];; + (* [id 1; explode];; *) + +magic6 + ["PACMAN (x x x)"] ["PACMAN (x x)"] + [ + ignore 2 2; + explode; + ];; *) + +print_hline(); +print_endline "ALL DONE. " diff --git a/ocaml/lambda3.ml b/ocaml/lambda3.ml deleted file mode 100644 index f61e1e5..0000000 --- a/ocaml/lambda3.ml +++ /dev/null @@ -1,550 +0,0 @@ -open Util -open Util.Vars -open Pure -open Num - -type problem = - { freshno: int - ; ps: i_n_var list (* the n-th inert must become n *) - ; sigma: (int * nf) list (* the computed substitution *) - ; deltas: (int * nf) list ref list (* collection of all branches *) - } - -let print_problem {freshno; ps; deltas} = - let deltas = String.concat "\n" (List.map (fun r -> String.concat " <> " (List.map (fun (i,_) -> string_of_int i) !r)) deltas) in - let l = Array.to_list (Array.init (freshno + 1) string_of_var) in - deltas ^ (if deltas = "" then "" else "\n") ^ - String.concat "\n" (List.mapi (fun i t -> string_of_int i ^ ": " ^ print ~l (t :> nf)) ps) -;; - -let make_fresh_var freshno = - freshno+1, freshno+1 - -let make_fresh_vars p m = - let rec aux = - function - 0 -> p.freshno,[] - | n when n > 0 -> - let freshno,vars = aux (n-1) in - let freshno,v = make_fresh_var freshno in - freshno,`Var v::vars - | _ -> assert false in - let freshno,vars = aux m in - {p with freshno}, vars - -let simple_expand_match ps = - let rec aux level = function - | #i_num_var as t -> aux_i_num_var level t - | `Lam(b,t) -> `Lam(b, aux (level+1) t) - and aux_i_num_var level = function - | `Match(u,bs_lift,bs,args) as torig -> - let u = aux_i_num_var level u in - bs := List.map (fun (n, x) -> n, aux 0 x) !bs; - (try - (match u with - | #i_n_var as u -> - let i = index_of (lift (-level) u) (ps :> nf list) (* can raise Not_found *) - in let t = mk_match (`N i) bs_lift bs args in - if t <> torig then - aux level (t :> nf) - else raise Not_found - | _ -> raise Not_found) - with Not_found -> - `Match(cast_to_i_num_var u,bs_lift,bs,List.map (aux level) args)) - | `I(k,args) -> `I(k,Listx.map (aux level) args) - | `N _ | `Var _ as t -> t -in aux_i_num_var 0;; - -let rec super_simplify_ps ps it = - let it' = List.map (fun t -> cast_to_i_num_var (simple_expand_match ps t)) (it :> i_num_var list) in - if it <> it' then super_simplify_ps ps it' else it' - -let super_simplify ({ps} as p) = - let ps = super_simplify_ps p.ps (p.ps :> i_num_var list) in - {p with ps=List.map cast_to_i_n_var ps} - -let subst_in_problem x inst ({freshno; ps; sigma} as p) = - let len_ps = List.length ps in -(*(let l = Array.to_list (Array.init (freshno + 1) string_of_var) in -prerr_endline ("# INST0: " ^ string_of_var x ^ " := " ^ print ~l inst));*) - let rec aux ((freshno,acc_ps,acc_new_ps) as acc) = - function - [] -> acc - | t::todo_ps -> -(*prerr_endline ("EXPAND t:" ^ print (t :> nf));*) - let t = subst false x inst (t :> nf) in -(*prerr_endline ("SUBSTITUTED t:" ^ print (t :> nf));*) - let freshno,new_t,acc_new_ps = - expand_match (freshno,acc_ps@`Var(max_int/3)::todo_ps,acc_new_ps) t - in - aux (freshno,acc_ps@[new_t],acc_new_ps) todo_ps - - and expand_match ((freshno,acc_ps, acc_new_ps) as acc) t = - match t with - | `Match(u',bs_lift,bs,args) -> - let freshno,u,acc_new_ps = expand_match acc (u' :> nf) in - let acc_new_ps,i = - match u with - `N i -> acc_new_ps,i - | _ -> - let ps = List.map (fun t -> cast_to_i_num_var (subst false x inst (t:> nf))) (acc_ps@acc_new_ps) in - let super_simplified_ps = super_simplify_ps ps ps in -(*prerr_endline ("CERCO u:" ^ print (fst u :> nf)); -List.iter (fun x -> prerr_endline ("IN: " ^ print (fst x :> nf))) ps; -List.iter (fun x -> prerr_endline ("IN2: " ^ print (fst x :> nf))) super_simplified_ps;*) - match index_of_opt ~eq:eta_eq super_simplified_ps u with - Some i -> acc_new_ps, i - | None -> acc_new_ps@[u], len_ps + List.length acc_new_ps - in - let freshno= - if List.exists (fun (j,_) -> i=j) !bs then - freshno - else - let freshno,v = make_fresh_var freshno in - bs := !bs @ [i, `Var v] ; - freshno in -(*prerr_endlie ("t DA RIDURRE:" ^ print (`Match(`N i,arity,bs_lift,bs,args) :> nf) ^ " more_args=" ^ string_of_int more_args);*) - let t = mk_match (`N i) bs_lift bs args in -(*prerr_endline ("NUOVO t:" ^ print (fst t :> nf) ^ " more_args=" ^ string_of_int (snd t));*) - expand_match (freshno,acc_ps,acc_new_ps) t - | `Lam _ -> - (* the cast will fail *) - (* freshno,(cast_to_i_n_var t),acc_new_ps *) - assert false - | #i_n_var as x -> - let x = simple_expand_match (acc_ps@acc_new_ps) x in - freshno,cast_to_i_num_var x,acc_new_ps in - let freshno,old_ps,new_ps = aux (freshno,[],[]) (ps :> i_num_var list) in - let ps = List.map cast_to_i_n_var (old_ps @ new_ps) in -(let l = Array.to_list (Array.init (freshno + 1) string_of_var) in -prerr_endline ("# INST: " ^ string_of_var x ^ " := " ^ print ~l inst)); - let p = {p with freshno; ps; sigma = sigma@[x,inst]} in - let p = super_simplify p in -prerr_endline (print_problem p); p - -exception Dangerous - -let rec dangerous arities showstoppers = - function - `N _ - | `Var _ - | `Lam _ -> () - | `Match(t,liftno,bs,args) -> - (* CSC: XXX partial dependency on the encoding *) - (match t with - `N _ -> List.iter (dangerous arities showstoppers) args - | `Match _ as t -> dangerous arities showstoppers t ; List.iter (dangerous arities showstoppers) args - | `Var x -> dangerous_inert arities showstoppers x args 2 (* 2 coming from Scott's encoding *) - | `I(x,args') -> dangerous_inert arities showstoppers x (Listx.to_list args' @ args) 2 (* 2 coming from Scott's encoding *) - ) - | `I(k,args) -> dangerous_inert arities showstoppers k (Listx.to_list args) 0 - -and dangerous_inert arities showstoppers k args more_args = - List.iter (dangerous arities showstoppers) args ; - if List.mem k showstoppers then raise Dangerous else - try - let _,_,y = List.find (fun (v,_,_) -> v=k) arities in - let arity = match y with `Var _ -> 0 | `I(_,args) -> Listx.length args | _ -> assert false in - if List.length args + more_args > arity then raise Dangerous else () - with - Not_found -> () - -(* inefficient algorithm *) -let edible arities showstoppers ps = - let rec aux showstoppers = - function - [] -> showstoppers - | x::xs when List.exists (fun y -> hd_of x = Some y) showstoppers -> - (* se la testa di x e' uno show-stopper *) - let new_showstoppers = sort_uniq (showstoppers @ free_vars (x :> nf)) in - (* aggiungi tutte le variabili libere di x *) - if List.length showstoppers <> List.length new_showstoppers then - aux new_showstoppers ps - else - aux showstoppers xs - | x::xs -> - match hd_of x with - None -> aux showstoppers xs - | Some h -> - try - dangerous arities showstoppers (x : i_n_var :> nf) ; - aux showstoppers xs - with - Dangerous -> - aux (sort_uniq (h::showstoppers)) ps - in - aux showstoppers ps - -let precompute_edible_data {ps} xs = - List.map (fun x -> - let y = List.find (fun y -> hd_of y = Some x) ps in - x, index_of ~eq:eta_eq y ps, y) xs -;; - -let critical_showstoppers p = - let p = super_simplify p in - let showstoppers_step = - List.concat (List.map (fun bs -> - let heads = List.map (fun (i,_) -> List.nth p.ps i) !bs in - let heads = List.sort compare (filter_map hd_of heads) in - snd (split_duplicates heads) - ) p.deltas) in - let showstoppers_step = sort_uniq showstoppers_step in - let showstoppers_eat = - let heads_and_arities = - List.sort (fun (k,_) (h,_) -> compare k h) - (filter_map (function `Var k -> Some (k,0) | `I(k,args) -> Some (k,Listx.length args) | _ -> None ) p.ps) in - let rec multiple_arities = - function - [] - | [_] -> [] - | (x,i)::(y,j)::tl when x = y && i <> j -> - x::multiple_arities tl - | _::tl -> multiple_arities tl in - multiple_arities heads_and_arities in - - let showstoppers_eat = sort_uniq showstoppers_eat in - 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 v)) showstoppers_step; - List.iter (fun v -> prerr_endline ("DANGEROUS EAT: " ^ string_of_var v)) showstoppers_eat; - p, showstoppers_step, showstoppers_eat - ;; - -let eat p = - let ({ps} as p), showstoppers_step, showstoppers_eat = critical_showstoppers p in - 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 = edible arities showstoppers ps in - let l = List.filter (fun (x,_,_) -> not (List.mem x showstoppers)) arities in - let p = - List.fold_left (fun p (x,pos,(xx : i_n_var)) -> - let n = match xx with `I(_,args) -> Listx.length args | _ -> 0 in - let v = `N(pos) in - let inst = make_lams v n in -(let l = Array.to_list (Array.init (p.freshno + 1) string_of_var) in - prerr_endline ("# INST_IN_EAT: " ^ string_of_var x ^ " := " ^ print ~l inst)); - (* CSC: XXX to avoid applied numbers in safe positions that - trigger assert failures subst_in_problem x inst p*) - { p with sigma = p.sigma @ [x,inst] } - ) p l in - let ps = - List.map (fun t -> - try - let _,j,_ = List.find (fun (h,_,_) -> hd_of t = Some h) l in - `N j - with Not_found -> t - ) ps in - List.iter - (fun bs -> - bs := - List.map - (fun (n,t as res) -> - match List.nth ps n with - `N m -> m,t - | _ -> res - ) !bs - ) p.deltas ; - let p = { p with ps } in - if l <> [] then prerr_endline (print_problem p); - if List.for_all (function `N _ -> true | _ -> false) ps then - `Finished p - else - `Continue p - -let instantiate p x n = - let p,vars = make_fresh_vars p n in - let freshno,zero = make_fresh_var p.freshno in - let p = {p with freshno} in - let zero = Listx.Nil (`Var zero) in - let args = if n = 0 then zero else Listx.append zero (Listx.from_list vars) in - let bs = ref [] in - let inst = `Lam(false,`Match(`I(0,Listx.map (lift 1) args),1,bs,[])) in - let p = {p with deltas=bs::p.deltas} in - subst_in_problem x inst p -;; - -let compute_special_k tms = - let rec aux k (t: nf) = Pervasives.max k (match t with - | `Lam(b,t) -> aux (k + if b then 1 else 0) t - | `I(n, tms) -> Listx.max (Listx.map (aux 0) tms) - | `Match(t, liftno, bs, args) -> - List.fold_left max 0 (List.map (aux 0) ((t :> nf)::args@List.map snd !bs)) - | `N _ -> 0 - | `Var _ -> 0 - ) in Listx.max (Listx.map (aux 0) tms) -;; - -let auto_instantiate (n,p) = - let ({ps} as 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 y); y - | [], [] -> - let heads = List.sort compare (filter_map (fun t -> match t with `Var _ -> None | x -> hd_of x) ps) in - (match heads with - [] -> assert false - | x::_ -> - prerr_endline ("INSTANTIATING TO EAT " ^ string_of_var x); - x) - | x::_, _ -> - prerr_endline ("INSTANTIATING " ^ string_of_var x); - 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 = - try - (match hd_of (List.find (fun t -> compute_special_k (Listx.Nil (t :> nf)) > 0) ps) with - None -> assert false - | Some x -> - prerr_endline ("INSTANTIATING AND HOPING " ^ string_of_var x); - x) - with - Not_found -> x -in -(* Instantiate in decreasing order of compute_special_k -1:15m14s 2:13m14s 3:4m55s 4:4m43s 5:4m34s 6:6m28s 7:3m31s -let x = - try - (match hd_of (snd (List.hd (List.sort (fun c1 c2 -> - compare (fst c1) (fst c2)) (filter_map (function `I _ as t -> Some (compute_special_k (Listx.Nil (t :> nf)),t) | _ -> None) ps)))) with - None -> assert false - | Some x -> - prerr_endline ("INSTANTIATING AND HOPING " ^ string_of_var x); - x) - with - Not_found -> x -in*) - let special_k = - compute_special_k (Listx.from_list (p.ps :> nf list) )in - if special_k < n then - prerr_endline ("@@@@ NEW INSTANTIATE PHASE (" ^ string_of_int special_k ^ ") @@@@"); - let p = instantiate p x special_k in - special_k,p - -let problem_measure {ps} = - (* let rec term_size_i_n_var = - function - | `I(v,nfs) -> - (Listx.length nfs) * - (List.fold_right (fun (a,b) c -> 10 + ((a+1) * term_size b) + c) (List.mapi (fun x y -> (x,y)) (Listx.to_list nfs)) 0) - | `Var _ -> 1 - | `N _ -> 0 - and term_size = - function - | #i_n_var as t -> term_size_i_n_var t - | `Match(t,lift,bs,args) -> 1 + (term_size (t :> nf)) + 1 + (List.fold_right ((+) ++ term_size) args 0) - | `Lam(b,t) -> (if b then 0 else 1) + term_size t - (* in List.fold_right ((+) ++ term_size_i_n_var) ps 0;; *) - in ... *) - 0 - -let rec auto_eat (n,({ps} as p)) = - match eat p with - `Finished p -> p - | `Continue p -> - let p' = auto_instantiate (n,p) in - let m' = problem_measure (snd p') in - let delta = m' - problem_measure p in - (if delta >= 0 - then print_endline ("$$$$ MEASURE DID NOT DECREASE (after inst) delta=" ^ string_of_int delta)); - let p'' = auto_eat p' in - (if m' <= problem_measure p'' - then print_endline ("$$$$ MEASURE DID NOT DECREASE (after eat) $$$")); - p'' -;; - -let auto p n = - prerr_endline ("@@@@ FIRST INSTANTIATE PHASE (" ^ string_of_int n ^ ") @@@@"); - auto_eat (n,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 = - let rec aux = function - | `N n -> `N (List.nth perm n) - | `I _ | `Var _ -> assert false - | `Lam(v,t) -> `Lam(v, aux t) - | `Match(_,_,bs,_) as t -> (bs := List.map (fun (n,t) -> (List.nth perm n, t)) !bs); t - in List.map (fun (n,t) -> (n,aux t)) - in - let deltas' = List.mapi (fun n d -> (n, List.map fst !d)) p.deltas in - let maxs = Array.to_list (Array.init (List.length deltas') (fun _ -> 0)) in - let max = Listx.max (Listx.from_list ( - List.concat (List.map snd deltas') - )) in - let perm,_ = List.fold_left (fun (perm, maxs) (curr_n:int) -> - let containing = filter_map (fun (i, bs) -> if List.mem curr_n bs then Some i else None) deltas' in - (* (prerr_endline (string_of_int curr_n ^ " occurs in: " ^ (String.concat " " (List.map string_of_int containing)))); *) - let neww = Listx.max (Listx.from_list (List.mapi (fun n max -> if List.mem n containing then max else 0) maxs)) in - let maxs = List.mapi (fun i m -> if List.mem i containing then neww+1 else m) maxs in - (neww::perm, maxs) - ) ([],maxs) (Array.to_list (Array.init (max+1) (fun x -> x))) in - replace_in_sigma (List.rev perm) p.sigma -;; - -prerr_endline "########## main ##########";; - -(* Commands: - v ==> v := \a. a k1 .. kn \^m.0 - + ==> v := \^k. numero for every v such that ... - * ==> tries v as long as possible and then +v as long as possible -*) -let main problems = - let rec aux ({ps} as p) n l = - if List.for_all (function `N _ -> true | _ -> false) ps then begin - assert (l = []); - p - end else - let _ = prerr_endline (print_problem p) in - let x,l = - match l with - | cmd::l -> cmd,l - | [] -> read_line (),[] in - let cmd = - if x = "+" then - `DoneWith - else if x = "*" then - `Auto - else - `Step x in - match cmd with - | `DoneWith -> assert false (*aux (eat p) n l*) (* CSC: TODO *) - | `Step x -> - let x = var_of_string x in - aux (instantiate p x n) n l - | `Auto -> aux (auto p n) n l - in - List.iter - (fun (p,n,cmds) -> - let p_finale = aux p n cmds in - let freshno,sigma = p_finale.freshno, p_finale.sigma in - prerr_endline "------- ------"; - prerr_endline (print_problem p); - prerr_endline "---------------------"; - let l = Array.to_list (Array.init (freshno + 1) string_of_var) in - List.iter (fun (x,inst) -> prerr_endline (string_of_var x ^ " := " ^ print ~l inst)) sigma; -(* - prerr_endline "----------------------"; - let ps = - List.fold_left (fun ps (x,inst) -> - (* CSC: XXXX Is the subst always sorted correctly? Otherwise, implement a recursive subst *) - (* In this non-recursive version, the intermediate states may containt Matchs *) - List.map (fun t -> let t = subst false x inst (t :> nf) in cast_to_i_num_var t) ps) - (p.ps :> i_num_var list) sigma in - prerr_endline (print_problem {p with ps= List.map (function t -> cast_to_i_n_var t) ps; freshno}); - List.iteri (fun i (n,more_args) -> assert (more_args = 0 && n = `N i)) ps ; -*) - prerr_endline "-------------------"; - let sigma = optimize_numerals p_finale in (* optimize numerals *) - let l = Array.to_list (Array.init (freshno + 1) string_of_var) in - List.iter (fun (x,inst) -> prerr_endline (string_of_var x ^ " := " ^ print ~l inst)) sigma; - prerr_endline "------------------"; - let ps = List.map (fun t -> ToScott.t_of_nf (t :> nf)) p.ps in - let sigma = List.map (fun (x,inst) -> x, ToScott.t_of_nf inst) sigma in - (*let ps_ok = List.fold_left (fun ps (x,inst) -> - List.map (Pure.subst false x inst) ps) ps sigma in*) - let e = - let rec aux n = - if n > freshno then - [] - else - let e = aux (n+1) in - (try - e,Pure.lift (-n-1) (let t = (snd (List.find (fun (i,_) -> i = n) sigma)) in prerr_endline (string_of_var n ^ " := " ^ Pure.print t); t),[] - with - Not_found -> [],Pure.V n,[])::e - in - aux 0 in -(* - prerr_endline "------------------"; -let rec print_e e = - "[" ^ String.concat ";" (List.map (fun (e,t,[]) -> print_e e ^ ":" ^ Pure.print t) e) ^ "]" -in - prerr_endline (print_e e); - List.iter (fun (t,t_ok) -> - prerr_endline ("T0= " ^ Pure.print t ^ "\nTM= " ^ Pure.print (Pure.unwind (e,t,[])) ^ "\nOM= " ^ Pure.print t_ok); - (*assert (Pure.unwind (e,t,[]) = t_ok)*) - ) (List.combine ps ps_ok); -*) - prerr_endline "-----------------"; - List.iteri (fun i n -> - (*prerr_endline ((string_of_int i) ^ "::: " ^ (Pure.print n));*) - let t = Pure.mwhd (e,n,[]) in - prerr_endline ((string_of_int i) ^ ":: " ^ (Pure.print t)); - assert (t = Scott.mk_n i) - ) ps ; - prerr_endline "-------- --------" - ) problems - -(********************** problems *******************) - -let zero = `Var 0;; - -let append_zero = - function - | `I _ - | `Var _ as i -> cast_to_i_n_var (mk_app i zero) - | _ -> assert false -;; - -type t = problem * int * string list;; - -let magic strings cmds = - let tms, _ = parse' strings in (* *) - let tms = sort_uniq ~compare:eta_compare tms in - let special_k = compute_special_k (Listx.from_list tms) in (* compute special K *) - let fv = sort_uniq (List.concat (List.map free_vars tms)) in (* free variables *) - let tms = List.map cast_to_i_n_var tms in (* cast nf list -> i_n_var list *) - let ps = List.map append_zero tms in (* crea lista applicando zeri o dummies *) - (*let _ = prerr_endline ("Free vars: " ^ String.concat ", " (List.map string_of_var fv)) in*) - let freshno = Listx.max (Listx.from_list fv) in - let dummy = `Var (max_int / 2) in - let deltas = [ ref (Array.to_list (Array.init (List.length ps) (fun i -> i, dummy))) ] in - {freshno; ps; sigma=[] ; deltas}, special_k, cmds -;; - -let magic_conv ~div:_ ~conv:_ ~nums:_ _ = assert false;; diff --git a/ocaml/lambda3.ml.ar b/ocaml/lambda3.ml.ar deleted file mode 100644 index 39e77a7..0000000 --- a/ocaml/lambda3.ml.ar +++ /dev/null @@ -1,550 +0,0 @@ -open Util -open Util.Vars -open Pure -open Num - -type problem = - { freshno: int - ; ps: i_n_var list (* the n-th inert must become n *) - ; sigma: (int * nf) list (* the computed substitution *) - ; deltas: (int * nf) list ref list (* collection of all branches *) - } - -let print_problem {freshno; ps; deltas} = - let deltas = String.concat "\n" (List.map (fun r -> String.concat " <> " (List.map (fun (i,_) -> string_of_int i) !r)) deltas) in - let l = Array.to_list (Array.init (freshno + 1) string_of_var) in - deltas ^ (if deltas = "" then "" else "\n") ^ - String.concat "\n" (List.mapi (fun i t -> string_of_int i ^ ": " ^ print ~l (t :> nf)) ps) -;; - -let make_fresh_var freshno = - freshno+1, freshno+1 - -let make_fresh_vars p m = - let rec aux = - function - 0 -> p.freshno,[] - | n when n > 0 -> - let freshno,vars = aux (n-1) in - let freshno,v = make_fresh_var freshno in - freshno,`Var (0,v)::vars - | _ -> assert false in - let freshno,vars = aux m in - {p with freshno}, vars - -let simple_expand_match ps = - let rec aux level = function - | #i_num_var as t -> aux_i_num_var level t - | `Lam(b,t) -> `Lam(b, aux (level+1) t) - and aux_i_num_var level = function - | `Match(ar,u,bs_lift,bs,args) as torig -> - let u = aux_i_num_var level u in - bs := List.map (fun (n, x) -> n, aux 0 x) !bs; - (try - (match u with - | #i_n_var as u -> - let i = index_of (lift (-level) u) (ps :> nf list) (* can raise Not_found *) - in let t = mk_match ar (`N i) bs_lift bs args in - if t <> torig then - aux level (t :> nf) - else raise Not_found - | _ -> raise Not_found) - with Not_found -> - `Match(ar,cast_to_i_num_var u,bs_lift,bs,List.map (aux level) args)) - | `I(ar,k,args) -> `I(ar,k,Listx.map (aux level) args) - | `N _ | `Var _ as t -> t -in aux_i_num_var 0;; - -let rec super_simplify_ps ps it = - let it' = List.map (fun t -> cast_to_i_num_var (simple_expand_match ps t)) (it :> i_num_var list) in - if it <> it' then super_simplify_ps ps it' else it' - -let super_simplify ({ps} as p) = - let ps = super_simplify_ps p.ps (p.ps :> i_num_var list) in - {p with ps=List.map cast_to_i_n_var ps} - -let subst_in_problem x inst ({freshno; ps; sigma} as p) = - let len_ps = List.length ps in -(*(let l = Array.to_list (Array.init (freshno + 1) string_of_var) in -prerr_endline ("# INST0: " ^ string_of_var x ^ " := " ^ print ~l inst));*) - let rec aux ((freshno,acc_ps,acc_new_ps) as acc) = - function - [] -> acc - | t::todo_ps -> -(*prerr_endline ("EXPAND t:" ^ print (t :> nf));*) - let t = subst false x inst (t :> nf) in -(*prerr_endline ("SUBSTITUTED t:" ^ print (t :> nf));*) - let freshno,new_t,acc_new_ps = - expand_match (freshno,acc_ps@`Var(-1,max_int/3)::todo_ps,acc_new_ps) t - in - aux (freshno,acc_ps@[new_t],acc_new_ps) todo_ps - - and expand_match ((freshno,acc_ps, acc_new_ps) as acc) t = - match t with - | `Match(ar,u',bs_lift,bs,args) -> - let freshno,u,acc_new_ps = expand_match acc (u' :> nf) in - let acc_new_ps,i = - match u with - `N i -> acc_new_ps,i - | _ -> - let ps = List.map (fun t -> cast_to_i_num_var (subst false x inst (t:> nf))) (acc_ps@acc_new_ps) in - let super_simplified_ps = super_simplify_ps ps ps in -(*prerr_endline ("CERCO u:" ^ print (fst u :> nf)); -List.iter (fun x -> prerr_endline ("IN: " ^ print (fst x :> nf))) ps; -List.iter (fun x -> prerr_endline ("IN2: " ^ print (fst x :> nf))) super_simplified_ps;*) - match index_of_opt ~eq:eta_eq super_simplified_ps u with - Some i -> acc_new_ps, i - | None -> acc_new_ps@[u], len_ps + List.length acc_new_ps - in - let freshno= - if List.exists (fun (j,_) -> i=j) !bs then - freshno - else - let freshno,v = make_fresh_var freshno in - bs := !bs @ [i, `Var (ar - 1,v)] ; - freshno in -(*prerr_endlie ("t DA RIDURRE:" ^ print (`Match(`N i,arity,bs_lift,bs,args) :> nf) ^ " more_args=" ^ string_of_int more_args);*) - let t = mk_match ar (`N i) bs_lift bs args in -(*prerr_endline ("NUOVO t:" ^ print (fst t :> nf) ^ " more_args=" ^ string_of_int (snd t));*) - expand_match (freshno,acc_ps,acc_new_ps) t - | `Lam _ -> - (* the cast will fail *) - (* freshno,(cast_to_i_n_var t),acc_new_ps *) - assert false - | #i_n_var as x -> - let x = simple_expand_match (acc_ps@acc_new_ps) x in - freshno,cast_to_i_num_var x,acc_new_ps in - let freshno,old_ps,new_ps = aux (freshno,[],[]) (ps :> i_num_var list) in - let ps = List.map cast_to_i_n_var (old_ps @ new_ps) in -(let l = Array.to_list (Array.init (freshno + 1) string_of_var) in -prerr_endline ("# INST: " ^ string_of_var x ^ " := " ^ print ~l inst)); - let p = {p with freshno; ps; sigma = sigma@[x,inst]} in - let p = super_simplify p in -prerr_endline (print_problem p); p - -exception Dangerous - -let rec dangerous arities showstoppers = - function - `N _ - | `Var _ - | `Lam _ -> () - | `Match(_,t,liftno,bs,args) -> - (* CSC: XXX partial dependency on the encoding *) - (match t with - `N _ -> List.iter (dangerous arities showstoppers) args - | `Match _ as t -> dangerous arities showstoppers t ; List.iter (dangerous arities showstoppers) args - | `Var (_,x) -> dangerous_inert arities showstoppers x args 2 (* 2 coming from Scott's encoding *) - | `I(_,x,args') -> dangerous_inert arities showstoppers x (Listx.to_list args' @ args) 2 (* 2 coming from Scott's encoding *) - ) - | `I(_,k,args) -> dangerous_inert arities showstoppers k (Listx.to_list args) 0 - -and dangerous_inert arities showstoppers k args more_args = - List.iter (dangerous arities showstoppers) args ; - if List.mem k showstoppers then raise Dangerous else - try - let _,_,y = List.find (fun (v,_,_) -> v=k) arities in - let arity = match y with `Var _ -> 0 | `I(_,_,args) -> Listx.length args | _ -> assert false in - if List.length args + more_args > arity then raise Dangerous else () - with - Not_found -> () - -(* inefficient algorithm *) -let edible arities showstoppers ps = - let rec aux showstoppers = - function - [] -> showstoppers - | x::xs when List.exists (fun y -> hd_of x = Some y) showstoppers -> - (* se la testa di x e' uno show-stopper *) - let new_showstoppers = sort_uniq (showstoppers @ free_vars (x :> nf)) in - (* aggiungi tutte le variabili libere di x *) - if List.length showstoppers <> List.length new_showstoppers then - aux new_showstoppers ps - else - aux showstoppers xs - | x::xs -> - match hd_of x with - None -> aux showstoppers xs - | Some h -> - try - dangerous arities showstoppers (x : i_n_var :> nf) ; - aux showstoppers xs - with - Dangerous -> - aux (sort_uniq (h::showstoppers)) ps - in - aux showstoppers ps - -let precompute_edible_data {ps} xs = - List.map (fun x -> - let y = List.find (fun y -> hd_of y = Some x) ps in - x, index_of ~eq:eta_eq y ps, y) xs -;; - -let critical_showstoppers p = - let p = super_simplify p in - let showstoppers_step = - List.concat (List.map (fun bs -> - let heads = List.map (fun (i,_) -> List.nth p.ps i) !bs in - let heads = List.sort compare (filter_map hd_of heads) in - snd (split_duplicates heads) - ) p.deltas) in - let showstoppers_step = sort_uniq showstoppers_step in - let showstoppers_eat = - let heads_and_arities = - List.sort (fun (k,_) (h,_) -> compare k h) - (filter_map (function `Var (_,k) -> Some (k,0) | `I(_,k,args) -> Some (k,Listx.length args) | _ -> None ) p.ps) in - let rec multiple_arities = - function - [] - | [_] -> [] - | (x,i)::(y,j)::tl when x = y && i <> j -> - x::multiple_arities tl - | _::tl -> multiple_arities tl in - multiple_arities heads_and_arities in - - let showstoppers_eat = sort_uniq showstoppers_eat in - 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 v)) showstoppers_step; - List.iter (fun v -> prerr_endline ("DANGEROUS EAT: " ^ string_of_var v)) showstoppers_eat; - p, showstoppers_step, showstoppers_eat - ;; - -let eat p = - let ({ps} as p), showstoppers_step, showstoppers_eat = critical_showstoppers p in - 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 = edible arities showstoppers ps in - let l = List.filter (fun (x,_,_) -> not (List.mem x showstoppers)) arities in - let p = - List.fold_left (fun p (x,pos,(xx : i_n_var)) -> - let n = match xx with `I(_,_,args) -> Listx.length args | _ -> 0 in - let v = `N(pos) in - let inst = make_lams v n in -(let l = Array.to_list (Array.init (p.freshno + 1) string_of_var) in - prerr_endline ("# INST_IN_EAT: " ^ string_of_var x ^ " := " ^ print ~l inst)); - (* CSC: XXX to avoid applied numbers in safe positions that - trigger assert failures subst_in_problem x inst p*) - { p with sigma = p.sigma @ [x,inst] } - ) p l in - let ps = - List.map (fun t -> - try - let _,j,_ = List.find (fun (h,_,_) -> hd_of t = Some h) l in - `N j - with Not_found -> t - ) ps in - List.iter - (fun bs -> - bs := - List.map - (fun (n,t as res) -> - match List.nth ps n with - `N m -> m,t - | _ -> res - ) !bs - ) p.deltas ; - let p = { p with ps } in - if l <> [] then prerr_endline (print_problem p); - if List.for_all (function `N _ -> true | _ -> false) ps then - `Finished p - else - `Continue p - -let instantiate p x n = - let p,vars = make_fresh_vars p n in - let freshno,zero = make_fresh_var p.freshno in - let p = {p with freshno} in - let zero = Listx.Nil (`Var (0,zero)) in - let args = if n = 0 then zero else Listx.append zero (Listx.from_list vars) in - let bs = ref [] in - let inst = `Lam(false,`Match(-1,`I(-1,0,Listx.map (lift 1) args),1,bs,[])) in - let p = {p with deltas=bs::p.deltas} in - subst_in_problem x inst p -;; - -let compute_special_k tms = - let rec aux k (t: nf) = Pervasives.max k (match t with - | `Lam(b,t) -> aux (k + if b then 1 else 0) t - | `I(_, n, tms) -> Listx.max (Listx.map (aux 0) tms) - | `Match(_, t, liftno, bs, args) -> - List.fold_left max 0 (List.map (aux 0) ((t :> nf)::args@List.map snd !bs)) - | `N _ -> 0 - | `Var _ -> 0 - ) in Listx.max (Listx.map (aux 0) tms) -;; - -let auto_instantiate (n,p) = - let ({ps} as 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 y); y - | [], [] -> - let heads = List.sort compare (filter_map (fun t -> match t with `Var _ -> None | x -> hd_of x) ps) in - (match heads with - [] -> assert false - | x::_ -> - prerr_endline ("INSTANTIATING TO EAT " ^ string_of_var x); - x) - | x::_, _ -> - prerr_endline ("INSTANTIATING " ^ string_of_var x); - 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 = - try - (match hd_of (List.find (fun t -> compute_special_k (Listx.Nil (t :> nf)) > 0) ps) with - None -> assert false - | Some x -> - prerr_endline ("INSTANTIATING AND HOPING " ^ string_of_var x); - x) - with - Not_found -> x -in -(* Instantiate in decreasing order of compute_special_k -1:15m14s 2:13m14s 3:4m55s 4:4m43s 5:4m34s 6:6m28s 7:3m31s -let x = - try - (match hd_of (snd (List.hd (List.sort (fun c1 c2 -> - compare (fst c1) (fst c2)) (filter_map (function `I _ as t -> Some (compute_special_k (Listx.Nil (t :> nf)),t) | _ -> None) ps)))) with - None -> assert false - | Some x -> - prerr_endline ("INSTANTIATING AND HOPING " ^ string_of_var x); - x) - with - Not_found -> x -in*) - let special_k = - compute_special_k (Listx.from_list (p.ps :> nf list) )in - if special_k < n then - prerr_endline ("@@@@ NEW INSTANTIATE PHASE (" ^ string_of_int special_k ^ ") @@@@"); - let p = instantiate p x special_k in - special_k,p - -let problem_measure {ps} = - (* let rec term_size_i_n_var = - function - | `I(v,nfs) -> - (Listx.length nfs) * - (List.fold_right (fun (a,b) c -> 10 + ((a+1) * term_size b) + c) (List.mapi (fun x y -> (x,y)) (Listx.to_list nfs)) 0) - | `Var _ -> 1 - | `N _ -> 0 - and term_size = - function - | #i_n_var as t -> term_size_i_n_var t - | `Match(t,lift,bs,args) -> 1 + (term_size (t :> nf)) + 1 + (List.fold_right ((+) ++ term_size) args 0) - | `Lam(b,t) -> (if b then 0 else 1) + term_size t - (* in List.fold_right ((+) ++ term_size_i_n_var) ps 0;; *) - in ... *) - 0 - -let rec auto_eat (n,({ps} as p)) = - match eat p with - `Finished p -> p - | `Continue p -> - let p' = auto_instantiate (n,p) in - let m' = problem_measure (snd p') in - let delta = m' - problem_measure p in - (if delta >= 0 - then print_endline ("$$$$ MEASURE DID NOT DECREASE (after inst) delta=" ^ string_of_int delta)); - let p'' = auto_eat p' in - (if m' <= problem_measure p'' - then print_endline ("$$$$ MEASURE DID NOT DECREASE (after eat) $$$")); - p'' -;; - -let auto p n = - prerr_endline ("@@@@ FIRST INSTANTIATE PHASE (" ^ string_of_int n ^ ") @@@@"); - auto_eat (n,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 = - let rec aux = function - | `N n -> `N (List.nth perm n) - | `I _ | `Var _ -> assert false - | `Lam(v,t) -> `Lam(v, aux t) - | `Match(_,_,_,bs,_) as t -> (bs := List.map (fun (n,t) -> (List.nth perm n, t)) !bs); t - in List.map (fun (n,t) -> (n,aux t)) - in - let deltas' = List.mapi (fun n d -> (n, List.map fst !d)) p.deltas in - let maxs = Array.to_list (Array.init (List.length deltas') (fun _ -> 0)) in - let max = Listx.max (Listx.from_list ( - List.concat (List.map snd deltas') - )) in - let perm,_ = List.fold_left (fun (perm, maxs) (curr_n:int) -> - let containing = filter_map (fun (i, bs) -> if List.mem curr_n bs then Some i else None) deltas' in - (* (prerr_endline (string_of_int curr_n ^ " occurs in: " ^ (String.concat " " (List.map string_of_int containing)))); *) - let neww = Listx.max (Listx.from_list (List.mapi (fun n max -> if List.mem n containing then max else 0) maxs)) in - let maxs = List.mapi (fun i m -> if List.mem i containing then neww+1 else m) maxs in - (neww::perm, maxs) - ) ([],maxs) (Array.to_list (Array.init (max+1) (fun x -> x))) in - replace_in_sigma (List.rev perm) p.sigma -;; - -prerr_endline "########## main ##########";; - -(* Commands: - v ==> v := \a. a k1 .. kn \^m.0 - + ==> v := \^k. numero for every v such that ... - * ==> tries v as long as possible and then +v as long as possible -*) -let main problems = - let rec aux ({ps} as p) n l = - if List.for_all (function `N _ -> true | _ -> false) ps then begin - assert (l = []); - p - end else - let _ = prerr_endline (print_problem p) in - let x,l = - match l with - | cmd::l -> cmd,l - | [] -> read_line (),[] in - let cmd = - if x = "+" then - `DoneWith - else if x = "*" then - `Auto - else - `Step x in - match cmd with - | `DoneWith -> assert false (*aux (eat p) n l*) (* CSC: TODO *) - | `Step x -> - let x = var_of_string x in - aux (instantiate p x n) n l - | `Auto -> aux (auto p n) n l - in - List.iter - (fun (p,n,cmds) -> - let p_finale = aux p n cmds in - let freshno,sigma = p_finale.freshno, p_finale.sigma in - prerr_endline "------- ------"; - prerr_endline (print_problem p); - prerr_endline "---------------------"; - let l = Array.to_list (Array.init (freshno + 1) string_of_var) in - List.iter (fun (x,inst) -> prerr_endline (string_of_var x ^ " := " ^ print ~l inst)) sigma; -(* - prerr_endline "----------------------"; - let ps = - List.fold_left (fun ps (x,inst) -> - (* CSC: XXXX Is the subst always sorted correctly? Otherwise, implement a recursive subst *) - (* In this non-recursive version, the intermediate states may containt Matchs *) - List.map (fun t -> let t = subst false x inst (t :> nf) in cast_to_i_num_var t) ps) - (p.ps :> i_num_var list) sigma in - prerr_endline (print_problem {p with ps= List.map (function t -> cast_to_i_n_var t) ps; freshno}); - List.iteri (fun i (n,more_args) -> assert (more_args = 0 && n = `N i)) ps ; -*) - prerr_endline "-------------------"; - let sigma = optimize_numerals p_finale in (* optimize numerals *) - let l = Array.to_list (Array.init (freshno + 1) string_of_var) in - List.iter (fun (x,inst) -> prerr_endline (string_of_var x ^ " := " ^ print ~l inst)) sigma; - prerr_endline "------------------"; - let ps = List.map (fun t -> ToScott.t_of_nf (t :> nf)) p.ps in - let sigma = List.map (fun (x,inst) -> x, ToScott.t_of_nf inst) sigma in - (*let ps_ok = List.fold_left (fun ps (x,inst) -> - List.map (Pure.subst false x inst) ps) ps sigma in*) - let e = - let rec aux n = - if n > freshno then - [] - else - let e = aux (n+1) in - (try - e,Pure.lift (-n-1) (let t = (snd (List.find (fun (i,_) -> i = n) sigma)) in prerr_endline (string_of_var n ^ " := " ^ Pure.print t); t),[] - with - Not_found -> [],Pure.V n,[])::e - in - aux 0 in -(* - prerr_endline "------------------"; -let rec print_e e = - "[" ^ String.concat ";" (List.map (fun (e,t,[]) -> print_e e ^ ":" ^ Pure.print t) e) ^ "]" -in - prerr_endline (print_e e); - List.iter (fun (t,t_ok) -> - prerr_endline ("T0= " ^ Pure.print t ^ "\nTM= " ^ Pure.print (Pure.unwind (e,t,[])) ^ "\nOM= " ^ Pure.print t_ok); - (*assert (Pure.unwind (e,t,[]) = t_ok)*) - ) (List.combine ps ps_ok); -*) - prerr_endline "-----------------"; - List.iteri (fun i n -> - (*prerr_endline ((string_of_int i) ^ "::: " ^ (Pure.print n));*) - let t = Pure.mwhd (e,n,[]) in - prerr_endline ((string_of_int i) ^ ":: " ^ (Pure.print t)); - assert (t = Scott.mk_n i) - ) ps ; - prerr_endline "-------- --------" - ) problems - -(********************** problems *******************) - -let zero = `Var (0,0);; - -let append_zero = - function - | `I _ - | `Var _ as i -> cast_to_i_n_var (mk_app i zero) - | _ -> assert false -;; - -type t = problem * int * string list;; - -let magic strings cmds = - let tms, _ = parse' strings in (* *) - let tms = sort_uniq ~compare:eta_compare tms in - let special_k = compute_special_k (Listx.from_list tms) in (* compute special K *) - let fv = sort_uniq (List.concat (List.map free_vars tms)) in (* free variables *) - let tms = List.map cast_to_i_n_var tms in (* cast nf list -> i_n_var list *) - let ps = List.map append_zero tms in (* crea lista applicando zeri o dummies *) - (*let _ = prerr_endline ("Free vars: " ^ String.concat ", " (List.map string_of_var fv)) in*) - let freshno = Listx.max (Listx.from_list fv) in - let dummy = `Var (-1,max_int / 2) in - let deltas = [ ref (Array.to_list (Array.init (List.length ps) (fun i -> i, dummy))) ] in - {freshno; ps; sigma=[] ; deltas}, special_k, cmds -;; - -let magic_conv ~div:_ ~conv:_ ~nums:_ _ = assert false;; diff --git a/ocaml/lambda3.mli b/ocaml/lambda3.mli deleted file mode 100644 index cbaf41c..0000000 --- a/ocaml/lambda3.mli +++ /dev/null @@ -1 +0,0 @@ -include Discriminator.Discriminator diff --git a/ocaml/lambda4.ml b/ocaml/lambda4.ml deleted file mode 100644 index 6b59ed9..0000000 --- a/ocaml/lambda4.ml +++ /dev/null @@ -1,1032 +0,0 @@ -open Util -open Util.Vars -open Pure -open Num - -let bomb = ref(`Var ~-1);; - -type var = int;; - -type problem = - { freshno: int - ; div: i_var option (* None = bomb *) - ; conv: i_n_var list (* the inerts that must converge *) - ; ps: i_n_var list (* the n-th inert must become n *) - ; sigma: (var * nf) list (* the computed substitution *) - ; deltas: (int * nf) list ref list (* collection of all branches *) - (* ; steps: int (* the bound on the number of steps *) *) - ; arities: int list - ; special_k: int - } - -let string_of_nf {freshno} t = - let l = Array.to_list (Array.init (freshno + 1) string_of_var) in - print ~l (t :> nf) -;; - -(* let heads = Util.sort_uniq (List.map hd_of_i_var p.ps) in -for all head - List.map (fun (_, bs) -> List.map (fun (x,_) -> List.nth p.ps x) !bs) p.deltas *) - -(* let ($) f x = f x;; *) - - -let subterms tms freshno = - let apply_var = - let no = ref freshno in - function t -> incr no; mk_app t (`Var !no) in - let applicative hd args = snd ( - List.fold_left (fun (hd, acc) t -> let hd = mk_app hd t in hd, hd::acc) (hd, []) args) in - let rec aux t = match t with - | `Var _ -> [] - | `I(v,ts) -> - (* applicative (`Var v) (Listx.to_list ts) @ *) - Util.concat_map aux (Listx.to_list ts) @ List.map apply_var (Listx.to_list ts) - | `Lam(_,t) -> aux (lift ~-1 t) - | `Match(u,bs_lift,bs,args) -> - aux (u :> nf) @ - (* applicative (`Match(u,bs_lift,bs,[])) args @ *) - Util.concat_map aux args @ List.map apply_var args - (* @ Util.concat_map (aux ++ (lift bs_lift) ++ snd) !bs *) - | `N _ -> [] - in let tms' = (* Util.sort_uniq ~compare:eta_compare*) (Util.concat_map aux tms) in - tms @ tms' - (* List.map (fun (t, v) -> match t with `N _ -> t | _ -> mk_app t v) (List.combine tms (List.mapi (fun i _ -> `Var(freshno+i)) tms)) *) -;; - -let all_terms p = -(match p.div with None -> [] | Some t -> [(t :> i_n_var)]) -@ p.conv -@ p.ps -;; - -let problem_measure p = - (* let l = Array.to_list (Array.init (p.freshno + 1) string_of_var) in *) - let open Listx in - (* aux |t1;t2| e' numero di step per portare la diff in testa - INVARIANTE: t1 t2 - *) - let rec aux t1 t2 = - match t1, t2 with - | `I(v1,nfs1), `I(v2,nfs2) -> - if v1 <> v2 - then 0 else 1 + find_first_diff (to_list nfs1, to_list nfs2) - | `Match (t1,bs_lift,bs,args), `Match (t2,bs_lift',bs',args') -> - if bs != bs' then 0 (* TODO *) - else if eta_eq (t1 :> nf) (t2 :> nf) then 1 + find_first_diff (args, args') else aux (t1 :> nf) (t2 :> nf) (* TODO *) - | `Match _, _ - | _, `Match _ -> 0 (* FIXME!!! *) - | `Lam(_,t1), `Lam(_,t2) -> aux t1 t2 - | _ -> 0 - and find_first_diff = function - | [], [] -> assert false - | [], t::_ - | t::_, [] -> 1 - | t1::ts1, t2::ts2 -> - if eta_eq (t1 :> nf) (t2 :> nf) then 1 + find_first_diff (ts1, ts2) else aux t1 t2 - (* no. di step da fare per separare t1 e t2 *) - in let diff t1 t2 = ( - let res = if eta_eq t1 t2 then 0 else aux t1 t2 in - (* if res <> 0 then prerr_endline ("diff (" ^ print ~l t1 ^ ") (" ^ print ~l t2 ^ ") = " ^ string_of_int res); *) - res - ) - (* aux calcola la somma delle differenze tra i termini in una lista (quadratico) *) - in let rec sum = function - | [] -> 0 - | x::xs -> List.fold_right ((+) ++ (diff (x :> nf))) (xs :> nf list) (sum xs) - in let subterms = subterms ((all_terms p) :> nf list) p.freshno - (* let subterms = sort_uniq ~compare:eta_compare subterms in *) - in let a = sum subterms - in let b = List.fold_right (fun bs -> (+) (sum (List.map ((List.nth p.ps) ++ fst) !bs))) p.deltas 0 - in let _ = prerr_endline ("Computed measure: " ^ string_of_int a ^ "," ^ string_of_int b) - in a + b -;; - -(* AC MEASURE *) -module ACMeasure = struct -type var = int;; - -type state = { - freshno : int; - arities : int list; - p : problem; -} - -let string_of_state s = - "STATE\n - arities: " ^ - String.concat " " (List.mapi (fun v n -> "`"^string_of_var v ^ "=" ^ string_of_int n) s.p.arities) -;; - -let rec get_var_of_match bs p = - let rec aux = function - | (v,`Lam(_,`Match(_,_,bs',_)))::sigma -> if bs = bs' then v else aux sigma - | _::sigma -> aux sigma - | [] -> assert false - in aux p.sigma -;; - -let mk_freshvar s = - let freshno = s.freshno + 1 in - {s with freshno}, freshno -;; - -let rec mk_apps vmap (h : nf) (args : var list) = - let aux l = Listx.from_list (List.map (fun x -> `Var x) l) in - match h,args with - | _, [] -> vmap, h - | `I(n,args'), _ -> vmap, `I(n, Listx.append (aux args) args') - | `Var n, _ -> vmap, `I(n, aux args) - | `Lam(_,nf), a::args -> mk_apps (a::vmap) (lift ~-1 nf) args - | `Match(t,lift,bs,args'), _ -> vmap, `Match(t,lift,bs,List.append args' (Listx.to_list (aux args))) - | _ -> assert false -;; - -let mk_freshvars s n = Array.fold_right (fun () (s,acc) -> let s, v = mk_freshvar s in s, v::acc ) (Array.make n ()) (s, []) -;; - -let get_arity_of_var p v t = - (* prerr_endline (string_of_nf p t); *) - let rec aux level = function - | `Var _ | `N _-> 0 - | `I(v', tms) as t -> - max - (if v + level = v' then ( - (* prerr_endline("found applied " ^ string_of_var v ^" in "^print (lift (-level) t)); *) - Listx.length tms) else 0) - (aux_listx level tms) - | `Lam(_,t) -> aux (level + 1) t - | `Match(t, liftno, bs, args) -> max (aux level (t :> nf)) (aux_list level args) - and aux_listx level listx = Listx.fold_left (fun x t -> max x (aux level t)) 0 listx - and aux_list level lst = List.fold_left (fun x t -> max x (aux level t)) 0 lst - in aux 0 t -;; - -(* let mk_apps t args = List.fold_left mk_app t args;; *) - -let first_arg = function - | Listx.Nil x - | Listx.Cons(x,_) -> x -;; - -let find_first_args var = - let rec aux level : nf -> nf list = function - | `Var _ | `N _ -> [] - | `I(v, args) -> (if var + level = v then [first_arg args] else []) @ (Util.concat_map (aux level) (Listx.to_list args)) - | `Lam(_,t) -> aux (level+1) t - | `Match(t, liftno, bs, args) -> aux level (t :> nf) @ (Util.concat_map (aux level) (args)) - in aux 0 -;; - -let remove_lambdas k t = - let rec aux = function - | `Lam(_,t) -> aux t - | _ as t -> t - in lift (-k) (aux t) -;; - -let get_arity_of_continuation p v = - if !bomb = `Var v then 0 else ( - let bs = List.find (fun bs -> List.exists (fun (_,t) -> t = `Var v) !bs) p.deltas in - let orig = get_var_of_match bs p in - List.nth p.arities orig - ) -;; - -let fix_arities p v freshvars = - let all_terms = (all_terms p :> nf list) in - let args = Util.concat_map (find_first_args v) all_terms in - let k = List.length freshvars in - let args = List.map (remove_lambdas k) args in - prerr_endline ("delifted lambdas in which to look for "^ string_of_var v); - (* List.iter (fun t -> prerr_endline(strilogng_of_nf p t)) args; *) - (* assert (List.length args > 0); *) - List.iter (fun v -> prerr_endline ("var to fix: fresh " ^ string_of_var v)) freshvars; - let find_arities_args v = let i = List.fold_left (fun x t -> max x (get_arity_of_var p v t)) 0 args in prerr_endline ("found arity in args of " ^ string_of_var (List.nth (List.rev freshvars) (v+1)) ^ ": " ^ string_of_int i); i in - (* let find_arities_all v = List.fold_left (fun x t -> max x (get_arity_of_var p v t)) 0 all_terms in *) - let arities = List.mapi (fun var () -> - if var < List.length p.arities - then List.nth p.arities var - else if List.mem var freshvars - then 1 + find_arities_args (Util.index_of var (List.rev freshvars) - 1) - (* else find_arities_all var *) - else (get_arity_of_continuation p var) - 1 - ) (Array.to_list (Array.make (p.freshno+1) ())) in - assert (List.length arities = (p.freshno + 1)); - (* prerr_endline ("arities added : " ^ string_of_int (List.length freshvars)); *) - (* List.iter (fun (v,n) -> prerr_endline(string_of_int v ^ "=" ^ string_of_int n)) arities; *) - {p with arities} -;; - -let measure = - let rec aux (s:state) vmap = - let p = s.p in - let realvar vmap v = - (* prerr_endline ("waant " ^ string_of_int v ^ "; we have "^ string_of_int (List.length vmap)); *) - if v < 0 then List.nth vmap (-1-v) else v in - function - | `Var _ | `N _-> 0 - | `I(v, tms) -> assert (List.length s.arities = (s.freshno + 1)); 1 + - let v = realvar vmap v in - (* prerr_endline ("lookup for arity of " ^ string_of_int v ^ "with freshno =" ^ string_of_int s.freshno ^ " and length = " ^ string_of_int (List.length s.arities)); *) - let arity = List.nth s.arities v in - 1 + if arity = 0 then 0 else ( - let first, rest = (match tms with - | Listx.Nil x -> x, [] - | Listx.Cons(a,b) -> a, Listx.to_list b) in - ( - let s, vars = mk_freshvars s (1+s.p.special_k) in - let vmap, t = mk_apps vmap first (vars) in - let arities = List.mapi (fun v () -> - if v < List.length s.arities - then List.nth s.arities v - else get_arity_of_var p (realvar vmap v) t - ) (Array.to_list (Array.make (s.freshno + 1) ())) in - (* let arities = (List.map (fun v -> v, get_arity_of_var p (realvar vmap' v) t) vars) in *) - (* let arities = arities @ s.arities in *) - let s = {s with arities} in - aux s vmap t - ) + ( - let s, fresh = mk_freshvar s in - let arities = s.arities @ [arity - 1] in - let s = {s with arities} in - if rest = [] then aux s vmap (`Var fresh) else - aux s vmap (`I (fresh, Listx.from_list rest)) - ) - ) - | `Match(t, _, bs, rest) -> - let tmp = aux s vmap (t :> nf) in - let s, fresh = mk_freshvar s in - let arity = List.nth s.arities (get_var_of_match bs s.p) in - let arities = s.arities @ [arity - 1] in - let s = {s with arities} in - tmp + if rest = [] then aux s vmap (`Var(fresh)) else - aux s vmap (`I(fresh, Listx.from_list rest)) - | `Lam _ -> assert false - in fun s -> aux s [] -;; - - -(* let measure p = - let rec m = function - | `N _ | `Var _ -> 0 - | `I(_,args) -> - let args = Listx.to_list args in - List.fold_left (fun acc t -> acc + m t) (1 + Listx.length args) args - | `Lam(_,t) -> m t - | `Match(t, lft, bs, rest) -> - (* let var = get_var_of_match bs p in *) - let args = rest in m (t :> nf) + List.fold_left (fun acc t -> acc + m t) (aux args) args - -and aux = function - | [] -> 0 - | x::xs -> m x + if aux xs = 0 then 0 else 1 + aux xs -in m -;;*) - -let measure_many s tms = List.fold_left (fun x t -> x + (measure s t)) 0 tms;; - -let map_max f l = List.fold_left (fun x t -> max x (f t)) 0 l;; - -let measure_of_problem p = - let tms = (all_terms p :> nf list) in - let freshno = p.freshno in - let arities = p.arities in - let s = {arities; freshno; p} in - prerr_endline (string_of_state s); - let l = Array.to_list (Array.init (freshno + 1) string_of_var) in - List.iter (fun t -> prerr_endline (string_of_int (measure s t) ^ " ::" ^ print ~l t)) tms; - let m = measure_many s tms in - (* prerr_endline (string_of_int m); *) - m -;; -end;; - -let measure_of_problem = ACMeasure.measure_of_problem;; -let problem_measure = measure_of_problem;; -(* AC MEASURE *) - -let print_problem label ({freshno; div; conv; ps; deltas} as p) = - (* assert (p.steps > List.length p.sigma); *) - let measure = try - problem_measure p - with - | _ -> -1 in - Console.print_hline (); - prerr_endline ("\n||||| Displaying problem: " ^ label ^ " |||||"); - let nl = "\n| " in - let deltas = String.concat nl (List.map (fun r -> String.concat " <> " (List.map (fun (i,_) -> string_of_int i) !r)) deltas) in - let l = Array.to_list (Array.init (freshno + 1) string_of_var) in - nl ^ - (* (string_of_int (steps - List.length p.sigma)) ^ " steps left;" ^ *) - "measure="^string_of_int measure ^" freshno = " ^ string_of_int freshno - ^ nl ^ "\b> DISCRIMINATING SETS (deltas)" - ^ nl ^ deltas ^ (if deltas = "" then "" else nl) - ^ "\b> DIVERGENT" ^ nl - ^ "*: " ^ (match div with None -> "*" | Some div -> print ~l (div :> nf)) ^ "\n| " - ^ "\b> CONVERGENT" ^ nl - ^ String.concat "\n| " (List.map (fun t -> "_: " ^ (if t = `N (-1) then "_" else print ~l (t :> nf))) conv) ^ - (if conv = [] then "" else "\n| ") - ^ "\b> NUMERIC" ^ nl - ^ String.concat "\n| " (List.mapi (fun i t -> string_of_int i ^ ": " ^ print ~l (t :> nf)) ps) - ^ nl -;; - - -let failwithProblem p reason = - print_endline (print_problem "FAIL" p); - failwith reason -;; - -let make_fresh_var p = - let freshno = p.freshno + 1 in - {p with freshno}, `Var freshno -;; - -let make_fresh_vars p m = - Array.fold_left - (* fold_left vs. fold_right hides/shows the bug in problem q7 *) - (fun (p, vars) _ -> let p, var = make_fresh_var p in p, var::vars) - (p, []) - (Array.make m ()) -;; - -let simple_expand_match ps = - let rec aux level = function - | #i_num_var as t -> aux_i_num_var level t - | `Lam(b,t) -> `Lam(b, aux (level+1) t) - and aux_i_num_var level = function - | `Match(u,bs_lift,bs,args) as torig -> - let u = aux_i_num_var level u in - bs := List.map (fun (n, x) -> n, aux 0 x) !bs; - (try - (match u with - | #i_n_var as u -> - let i = index_of (lift (-level) u) (ps :> nf list) (* can raise Not_found *) - in let t = mk_match (`N i) bs_lift bs args in - if t <> torig then - aux level (t :> nf) - else raise Not_found - | _ -> raise Not_found) - with Not_found -> - `Match(cast_to_i_num_var u,bs_lift,bs,List.map (aux level) args)) - | `I(k,args) -> `I(k,Listx.map (aux level) args) - | `N _ | `Var _ as t -> t -in aux_i_num_var 0;; - -let fixpoint f = - let rec aux x = let x' = f x in if x <> x' then aux x' else x in aux -;; - -let rec super_simplify_ps ps = - fixpoint (List.map (cast_to_i_num_var ++ (simple_expand_match ps))) -;; - -let super_simplify ({div; ps; conv} as p) = - let ps = super_simplify_ps p.ps (p.ps :> i_num_var list) in - let conv = super_simplify_ps ps (p.conv :> i_num_var list) in - let div = option_map (fun div -> - let divs = super_simplify_ps p.ps ([div] :> i_num_var list) in - List.hd divs) div in - {p with div=option_map cast_to_i_var div; ps=List.map cast_to_i_n_var ps; conv=List.map cast_to_i_n_var conv} - -exception ExpandedToLambda;; - -let subst_in_problem x inst ({freshno; div; conv; ps; sigma} as p) = - let len_ps = List.length ps in -(*(let l = Array.to_list (Array.init (freshno + 1) string_of_var) in -prerr_endline ("# INST0: " ^ string_of_var x ^ " := " ^ print ~l inst));*) - let rec aux ((freshno,acc_ps,acc_new_ps) as acc) = - function - | [] -> acc - | t::todo_ps -> -(*prerr_endline ("EXPAND t:" ^ print (t :> nf));*) - let t = subst false x inst (t :> nf) in -(*prerr_endline ("SUBSTITUTED t:" ^ print (t :> nf));*) - let freshno,new_t,acc_new_ps = - expand_match (freshno,acc_ps@`Var(max_int/3)::todo_ps,acc_new_ps) t - in - aux (freshno,acc_ps@[new_t],acc_new_ps) todo_ps - - (* cut&paste from aux above *) - and aux' ps ((freshno,acc_conv,acc_new_ps) as acc) = - function - | [] -> acc - | t::todo_conv -> -(*prerr_endline ("EXPAND t:" ^ print (t :> nf));*) - (* try *) - let t = subst false x inst (t :> nf) in -(*prerr_endline ("SUBSTITUTED t:" ^ print (t :> nf));*) - let freshno,new_t,acc_new_ps = - expand_match (freshno,ps,acc_new_ps) t - in - aux' ps (freshno,acc_conv@[new_t],acc_new_ps) todo_conv - (* with ExpandedToLambda -> aux' ps (freshno,acc_conv@[`N(-1)],acc_new_ps) todo_conv *) - - (* cut&paste from aux' above *) - and aux'' ps (freshno,acc_new_ps) = - function - | None -> freshno, None, acc_new_ps - | Some t -> - let t = subst false x inst (t :> nf) in - let freshno,new_t,acc_new_ps = - expand_match (freshno,ps,acc_new_ps) t - in - freshno,Some new_t,acc_new_ps - - and expand_match ((freshno,acc_ps,acc_new_ps) as acc) t = - match t with - | `Match(u',bs_lift,bs,args) -> - let freshno,u,acc_new_ps = expand_match acc (u' :> nf) in - let acc_new_ps,i = - match u with - | `N i -> acc_new_ps,i - | _ -> - let ps = List.map (fun t -> cast_to_i_num_var (subst false x inst (t:> nf))) (acc_ps@acc_new_ps) in - let super_simplified_ps = super_simplify_ps ps ps in -(*prerr_endline ("CERCO u:" ^ print (fst u :> nf)); -List.iter (fun x -> prerr_endline ("IN: " ^ print (fst x :> nf))) ps; -List.iter (fun x -> prerr_endline ("IN2: " ^ print (fst x :> nf))) super_simplified_ps;*) - match index_of_opt ~eq:eta_eq super_simplified_ps u with - Some i -> acc_new_ps, i - | None -> acc_new_ps@[u], len_ps + List.length acc_new_ps - in - let freshno= - if List.exists (fun (j,_) -> i=j) !bs then - freshno - else - let freshno,v = freshno+1, `Var (freshno+1) in (* make_fresh_var freshno in *) - bs := !bs @ [i, v] ; - freshno in -(*prerr_endlie ("t DA RIDURRE:" ^ print (`Match(`N i,arity,bs_lift,bs,args) :> nf) ^ " more_args=" ^ string_of_int more_args);*) - let t = mk_match (`N i) bs_lift bs args in -(*prerr_endline ("NUOVO t:" ^ print (fst t :> nf) ^ " more_args=" ^ string_of_int (snd t));*) - expand_match (freshno,acc_ps,acc_new_ps) t - | `Lam _ -> raise ExpandedToLambda - | #i_n_var as x -> - let x = simple_expand_match (acc_ps@acc_new_ps) x in - freshno,cast_to_i_num_var x,acc_new_ps in - - let freshno,old_ps,new_ps = aux (freshno,[],[]) (ps :> i_num_var list) in - let freshno,conv,new_ps = aux' old_ps (freshno,[],new_ps) (conv :> i_num_var list) in - let freshno,div,new_ps = aux'' old_ps (freshno,new_ps) (div :> i_num_var option) in - let div = option_map cast_to_i_var div in - let ps = List.map cast_to_i_n_var (old_ps @ new_ps) in - let conv = List.map cast_to_i_n_var conv in -(let l = Array.to_list (Array.init (freshno + 1) string_of_var) in -prerr_endline ("# INST: " ^ string_of_var x ^ " := " ^ print ~l inst)); - let p = {p with freshno; div; conv; ps} in - ( (* check if double substituting a variable *) - if List.exists (fun (x',_) -> x = x') sigma - then failwithProblem p "Variable replaced twice" - ); - let p = {p with sigma = sigma@[x,inst]} in - let p = super_simplify p in - print_endline (print_problem "instantiate" p); - p -;; - -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 | _ -> assert false in - arity + if pos = -1 then - 1 else 0 -;; - -let rec dangerous arities showstoppers = - function - `N _ - | `Var _ - | `Lam _ -> () - | `Match(t,liftno,bs,args) -> - (* CSC: XXX partial dependency on the encoding *) - (match t with - `N _ -> List.iter (dangerous arities showstoppers) args - | `Match _ as t -> dangerous arities showstoppers t ; List.iter (dangerous arities showstoppers) args - | `Var x -> dangerous_inert arities showstoppers x args 2 (* 2 coming from Scott's encoding *) - | `I(x,args') -> dangerous_inert arities showstoppers x (Listx.to_list args' @ args) 2 (* 2 coming from Scott's encoding *) - ) - | `I(k,args) -> dangerous_inert arities showstoppers k (Listx.to_list args) 0 - -and dangerous_inert arities showstoppers k args more_args = - List.iter (dangerous arities showstoppers) args ; - if List.mem k showstoppers then raise Dangerous else - try - let arity = arity_of arities k in - if List.length args + more_args > arity then raise Dangerous else () - with - Not_found -> () - -(* cut & paste from above *) -let rec dangerous_conv arities showstoppers = - function - `N _ - | `Var _ - | `Lam _ -> [] - | `Match(t,liftno,bs,args) -> - (* CSC: XXX partial dependency on the encoding *) - (match t with - `N _ -> concat_map (dangerous_conv arities showstoppers) args - | `Match _ as t -> dangerous_conv arities showstoppers t @ concat_map (dangerous_conv arities showstoppers) args - | `Var x -> dangerous_inert_conv arities showstoppers x args 2 (* 2 coming from Scott's encoding *) - | `I(x,args') -> dangerous_inert_conv arities showstoppers x (Listx.to_list args' @ args) 2 (* 2 coming from Scott's encoding *) - ) - | `I(k,args) -> dangerous_inert_conv arities showstoppers k (Listx.to_list args) 0 - -and dangerous_inert_conv arities showstoppers k args more_args = - concat_map (dangerous_conv arities showstoppers) args @ - if List.mem k showstoppers then k :: concat_map free_vars args else - try - let arity = arity_of arities k in - prerr_endline ("dangerous_inert_conv: ar=" ^ string_of_int arity ^ " k="^string_of_var k ^ " listlenargs=" ^ (string_of_int (List.length args)) ); - if List.length args + more_args > arity then k :: concat_map free_vars args else [] - with - Not_found -> [] - -(* inefficient algorithm *) -let rec edible arities div ps conv showstoppers = - let rec aux showstoppers = - function - [] -> showstoppers - | x::xs when List.exists (fun y -> hd_of x = Some y) showstoppers -> - (* se la testa di x e' uno show-stopper *) - let new_showstoppers = sort_uniq (showstoppers @ free_vars (x :> nf)) in - (* aggiungi tutte le variabili libere di x *) - if List.length showstoppers <> List.length new_showstoppers then - aux new_showstoppers ps - else - aux showstoppers xs - | x::xs -> - match hd_of x with - None -> aux showstoppers xs - | Some h -> - try - dangerous arities showstoppers (x : i_n_var :> nf) ; - 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 arities showstoppers) (conv :> nf 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 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 arities div ps conv 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 i, tm = Util.findi (fun y -> hd_of y = Some hd) ps in - hd, i, tm - ) xs -;; - -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 - let showstoppers_step = - concat_map (fun bs -> - let heads = List.map (fun (i,_) -> List.nth p.ps i) !bs in - let heads = List.sort compare (hd_of_div @ filter_map hd_of heads) in - snd (split_duplicates heads) - ) p.deltas @ - if List.exists (fun t -> [hd_of t] = List.map (fun x -> Some x) hd_of_div) p.conv - then hd_of_div else [] in - let showstoppers_step = sort_uniq showstoppers_step in - let showstoppers_eat = - let heads_and_arities = - List.sort (fun (k,_) (h,_) -> compare k h) - (filter_map (function `Var k -> Some (k,0) | `I(k,args) -> Some (k,Listx.length args) | _ -> None ) p.ps) in - let rec multiple_arities = - function - [] - | [_] -> [] - | (x,i)::(y,j)::tl when x = y && i <> j -> - x::multiple_arities tl - | _::tl -> multiple_arities tl in - multiple_arities heads_and_arities in - - let showstoppers_eat = sort_uniq showstoppers_eat in - 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 v)) showstoppers_step; - List.iter (fun v -> prerr_endline ("DANGEROUS EAT: " ^ string_of_var v)) showstoppers_eat; - p, showstoppers_step, showstoppers_eat - ;; - -let eat p = - let ({ps} as p), showstoppers_step, showstoppers_eat = critical_showstoppers p in - 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 arities p.div ps p.conv showstoppers in - let l = List.filter (fun (x,_,_) -> not (List.mem x showstoppers)) 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 -(let l = Array.to_list (Array.init (p.freshno + 1) string_of_var) in -prerr_endline ("# INST_IN_EAT: " ^ string_of_var x ^ " := " ^ print ~l inst)); - { p with sigma = p.sigma @ [x,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 - `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 - then p - else - let n = match div with `I(_,args) -> Listx.length args | `Var _ -> 0 in - let p, bomb' = make_fresh_var p in - (if !bomb <> `Var (-1) then - failwithProblem p - ("Bomb was duplicated! It was " ^ string_of_nf p !bomb ^ - ", tried to change it to " ^ string_of_nf p bomb')); - bomb := bomb'; - prerr_endline ("Just created bomb var: " ^ string_of_nf p !bomb); - let x = hd_of_i_var div in - let inst = make_lams !bomb n in - prerr_endline ("# INST (div): " ^ string_of_var x ^ " := " ^ string_of_nf p inst); - let p = {p with div=None} in - (* subst_in_problem (hd_of_i_var div) inst p in *) - {p with sigma=p.sigma@[x,inst]} 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 l))) dangerous_conv; in - 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 - t) - with Not_found -> match hd_of t with - | None -> assert (t = `N ~-1); t - | Some h -> - prerr_endline ("FREEZING " ^ string_of_var h); - `N ~-1 (* convergent dummy*) - ) (List.combine showstoppers_conv p.conv) in - List.iter - (fun bs -> - bs := - List.map - (fun (n,t as res) -> - match List.nth ps n with - `N m -> m,t - | _ -> res - ) !bs - ) p.deltas ; - let old_conv = p.conv in - let p = { p with ps; conv } in - if l <> [] || old_conv <> conv - then print_endline (print_problem "eat" p); - if List.for_all (function `N _ -> true | _ -> false) ps && p.div = None then - `Finished p - else - `Continue p - -let instantiate p x n = - (if `Var x = !bomb - then failwithProblem p ("BOMB (" ^ string_of_nf p !bomb ^ ") cannot be instantiated!")); - prerr_endline ("stepping on " ^ string_of_var x); - (if List.nth p.arities x <= 0 then failwith "stepped on a varible of arity <= 0"); - let p,vars = make_fresh_vars p n in - let p,zero' = make_fresh_var p in - let zero = Listx.Nil zero' in - let args = if n = 0 then zero else Listx.append zero (Listx.from_list vars) in - let bs = ref [] in - let inst = `Lam(false,`Match(`I(0,Listx.map (lift 1) args),1,bs,[])) in - let p = {p with deltas=bs::p.deltas} in - let p = ACMeasure.fix_arities p x (List.map (function `Var x -> x | _ -> assert false) (Listx.to_list args)) in - let p = subst_in_problem x inst p in - p -;; - -let auto_instantiate (n,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 y); y - | [], [] -> - let heads = List.sort compare (filter_map (fun t -> match t with `Var _ -> None | x -> hd_of x) ((match p.div with Some t -> [(t :> i_n_var)] | _ -> []) @ p.ps)) in - (match heads with - [] -> assert false - | x::_ -> - prerr_endline ("INSTANTIATING TO EAT " ^ string_of_var x); - x) - | x::_, _ -> - prerr_endline ("INSTANTIATING " ^ string_of_var x); - 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 = - try - match hd_of (List.find (fun t -> compute_special_k (Listx.Nil (t :> nf)) > 0) (all_terms p)) with - None -> assert false - | Some x -> - prerr_endline ("INSTANTIATING AND HOPING " ^ string_of_var x); - x - with - Not_found -> x -in -(* Instantiate in decreasing order of compute_special_k -1:15m14s 2:13m14s 3:4m55s 4:4m43s 5:4m34s 6:6m28s 7:3m31s -let x = - try - (match hd_of (snd (List.hd (List.sort (fun c1 c2 -> - compare (fst c1) (fst c2)) (filter_map (function `I _ as t -> Some (compute_special_k (Listx.Nil (t :> nf)),t) | _ -> None) (all_terms p))))) with - None -> assert false - | Some x -> - prerr_endline ("INSTANTIATING AND HOPING " ^ string_of_var x); - 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 p = instantiate p x special_k in - special_k,p - - -let rec auto_eat (n,({ps} as p)) = - prerr_endline "{{{{{{{{ Computing measure before auto_instantiate }}}}}}"; - let p = ACMeasure.fix_arities p (-1) [] in - let m = problem_measure p in - let (n,p') = auto_instantiate (n,p) in - match eat p' with - `Finished p -> p - | `Continue p -> - prerr_endline "{{{{{{{{ Computing measure inafter auto_instantiate }}}}}}"; - let p = ACMeasure.fix_arities p (-1) [] in - let delta = m - problem_measure p in - if delta <= 0 then ( - (* failwithProblem p *) - prerr_endline - ("Measure did not decrease (delta=" ^ string_of_int delta ^ ")")) - else prerr_endline ("$ Measure decreased by " ^ string_of_int delta); - (* let p' = {p' with steps=(p'.steps - 1)} in *) - (* (if p'.steps < 0 then prerr_endline ">>>>>>>>>> STEPS ARE OVER <<<<<<<<<" - (*failwithProblem p' "steps are over. sorry."*) ); *) - auto_eat (n,p) -;; - -let auto p n = - prerr_endline ("@@@@ FIRST INSTANTIATE PHASE (" ^ string_of_int n ^ ") @@@@"); - match eat p with - `Finished p -> p - | `Continue p -> auto_eat (n,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 = - let rec aux = function - | `N n -> `N (List.nth perm n) - | `I _ -> assert false - | `Var _ as t -> t - | `Lam(v,t) -> `Lam(v, aux t) - | `Match(_,_,bs,_) as t -> (bs := List.map (fun (n,t) -> (List.nth perm n, t)) !bs); t - in List.map (fun (n,t) -> (n,aux t)) - in - let deltas' = List.mapi (fun n d -> (n, List.map fst !d)) p.deltas in - let maxs = Array.to_list (Array.init (List.length deltas') (fun _ -> 0)) in - let max = List.fold_left max 0 (concat_map snd deltas') in - let perm,_ = List.fold_left (fun (perm, maxs) (curr_n:int) -> - let containing = filter_map (fun (i, bs) -> if List.mem curr_n bs then Some i else None) deltas' in - (* (prerr_endline (string_of_int curr_n ^ " occurs in: " ^ (String.concat " " (List.map string_of_int containing)))); *) - let neww = List.fold_left Pervasives.max 0 (List.mapi (fun n max -> if List.mem n containing then max else 0) maxs) in - let maxs = List.mapi (fun i m -> if List.mem i containing then neww+1 else m) maxs in - (neww::perm, maxs) - ) ([],maxs) (Array.to_list (Array.init (max+1) (fun x -> x))) in - replace_in_sigma (List.rev perm) p.sigma -;; - -let env_of_sigma freshno sigma should_explode = - let rec aux n = - if n > freshno then - [] - else - let e = aux (n+1) in - (try - e,Pure.lift (-n-1) (snd (List.find (fun (i,_) -> i = n) sigma)),[] - with - Not_found -> - if should_explode && `Var n = !bomb - then ([], (let f t = Pure.A(t,t) in f (Pure.L (f (Pure.V 0)))), []) - else ([],Pure.V n,[]))::e - in aux 0 -;; - -prerr_endline "########## main ##########";; - -(* Commands: - v ==> v := \a. a k1 .. kn \^m.0 - + ==> v := \^k. numero for every v such that ... - * ==> tries v as long as possible and then +v as long as possible -*) -let main problems = - let rec aux ({ps} as p) n l = - if List.for_all (function `N _ -> true | _ -> false) ps && p.div = None then begin - p - end else - let _ = print_endline (print_problem "main" p) in - let x,l = - match l with - | cmd::l -> cmd,l - | [] -> read_line (),[] in - let cmd = - if x = "+" then - `DoneWith - else if x = "*" then - `Auto - else - `Step x in - match cmd with - | `DoneWith -> assert false (*aux (eat p) n l*) (* CSC: TODO *) - | `Step x -> - let x = var_of_string x in - aux (instantiate p x n) n l - | `Auto -> aux (auto p n) n l - in - List.iter - (fun (p,n,cmds) -> - Console.print_hline(); - bomb := `Var (-1); - let p_finale = aux p n cmds in - let freshno,sigma = p_finale.freshno, p_finale.sigma in - prerr_endline ("------- ------\n " - (* ^ (string_of_int (p.steps - (List.length p_finale.sigma))) ^ " steps of "^ (string_of_int p.steps) ^"." *) - ); - (* print_endline (print_problem "Original problem" p); *) - prerr_endline "---------------------"; - let l = Array.to_list (Array.init (freshno + 1) string_of_var) in - prerr_endline (" BOMB == " ^ print ~l !bomb); - prerr_endline "---------------------"; - List.iter (fun (x,inst) -> prerr_endline (string_of_var x ^ " := " ^ print ~l inst)) sigma; -(* - prerr_endline "----------------------"; - let ps = - List.fold_left (fun ps (x,inst) -> - (* CSC: XXXX Is the subst always sorted correctly? Otherwise, implement a recursive subst *) - (* In this non-recursive version, the intermediate states may containt Matchs *) - List.map (fun t -> let t = subst false x inst (t :> nf) in cast_to_i_num_var t) ps) - (p.ps :> i_num_var list) sigma in - print_endline (print_problem {p with ps= List.map (function t -> cast_to_i_n_var t) ps; freshno}); - List.iteri (fun i (n,more_args) -> assert (more_args = 0 && n = `N i)) ps ; -*) - prerr_endline "-------------------"; - let sigma = optimize_numerals p_finale in (* optimize numerals *) - let l = Array.to_list (Array.init (freshno + 1) string_of_var) in - List.iter (fun (x,inst) -> prerr_endline (string_of_var x ^ " := " ^ print ~l inst)) sigma; - prerr_endline "------------------"; - let div = option_map (fun div -> ToScott.t_of_nf (div :> nf)) p.div in - let conv = List.map (fun t -> ToScott.t_of_nf (t :> nf)) p.conv in - let ps = List.map (fun t -> ToScott.t_of_nf (t :> nf)) p.ps in - let sigma = List.map (fun (x,inst) -> x, ToScott.t_of_nf inst) sigma in - (*let ps_ok = List.fold_left (fun ps (x,inst) -> - List.map (Pure.subst false x inst) ps) ps sigma in*) - let e = env_of_sigma freshno sigma true in - let e' = env_of_sigma freshno sigma false in - -(* - prerr_endline "------------------"; -let rec print_e e = - "[" ^ String.concat ";" (List.map (fun (e,t,[]) -> print_e e ^ ":" ^ Pure.print t) e) ^ "]" -in - prerr_endline (print_e e); - List.iter (fun (t,t_ok) -> - prerr_endline ("T0= " ^ Pure.print t ^ "\nTM= " ^ Pure.print (Pure.unwind (e,t,[])) ^ "\nOM= " ^ Pure.print t_ok); - (*assert (Pure.unwind (e,t,[]) = t_ok)*) - ) (List.combine ps ps_ok); -*) - prerr_endline "-----------------"; - (function Some div -> - print_endline (Pure.print div); - let t = Pure.mwhd (e',div,[]) in - prerr_endline ("*:: " ^ (Pure.print t)); - prerr_endline (print !bomb); - assert (t = ToScott.t_of_nf (!bomb:>nf)) - | None -> ()) div; - List.iter (fun n -> - prerr_endline ("_::: " ^ (Pure.print n)); - let t = Pure.mwhd (e,n,[]) in - prerr_endline ("_:: " ^ (Pure.print t)) - ) conv ; - List.iteri (fun i n -> - prerr_endline ((string_of_int i) ^ "::: " ^ (Pure.print n)); - let t = Pure.mwhd (e,n,[]) in - prerr_endline ((string_of_int i) ^ ":: " ^ (Pure.print t)); - assert (t = Scott.mk_n i) - ) ps ; - prerr_endline "-------- --------" - ) problems - -(********************** problems *******************) - -let zero = `Var 0;; - -let append_zero = - function - | `I _ - | `Var _ as i -> cast_to_i_n_var (mk_app i zero) - | _ -> assert false -;; - - -type t = problem * int * string list;; - -let magic_conv ~div ~conv ~nums cmds = - let all_tms = (match div with None -> [] | Some div -> [div]) @ nums @ conv in - let all_tms, var_names = parse' all_tms in - let div, (tms, conv) = match div with - | None -> None, list_cut (List.length nums, all_tms) - | Some _ -> Some (List.hd all_tms), list_cut (List.length nums, List.tl all_tms) in - - if match div with None -> false | Some div -> List.exists (eta_subterm div) (tms@conv) - then ( - prerr_endline "--- TEST SKIPPED ---"; - {freshno=0; div=None; conv=[]; ps=[]; sigma=[]; deltas=[]; arities=[]; special_k=(-1);}, 0, [] - ) else - let tms = sort_uniq ~compare:eta_compare tms in - let special_k = compute_special_k (Listx.from_list all_tms) in (* compute initial special K *) - (* casts *) - let div = option_map cast_to_i_var div in - let conv = List.map cast_to_i_n_var conv in - let tms = List.map cast_to_i_n_var tms in - - let ps = List.map append_zero tms in (* crea lista applicando zeri o dummies *) - let freshno = List.length var_names in - let sigma = [] in - let deltas = - let dummy = `Var (max_int / 2) in - [ ref (Array.to_list (Array.init (List.length ps) (fun i -> i, dummy))) ] in - let p = {freshno; div; conv; ps; sigma; deltas; special_k; arities=[]} in - let arities = - List.mapi (fun i () -> ACMeasure.map_max (ACMeasure.get_arity_of_var p i) ((all_terms p) :> nf list)) (Array.to_list (Array.make (freshno+1) ())) in - let p = {p with arities} in - p, special_k, cmds -;; - -let magic strings cmds = magic_conv None [] strings cmds;; diff --git a/ocaml/lambda4.mli b/ocaml/lambda4.mli deleted file mode 100644 index cbaf41c..0000000 --- a/ocaml/lambda4.mli +++ /dev/null @@ -1 +0,0 @@ -include Discriminator.Discriminator