(* Created Nov 26, 2009 THALES Compute irreducible cyclic fans. *) (* Needs. k nodes, k edges {i,i+1}, cyclic map on both Each node is 2, 2h0 or free. Each node is flat or not flat. Each edge is in G or not, Each edge is 2, 2h0, or free. *) open List;; (* from lpproc.ml *) let upto = let rec rangeA a i j = if (i >= j) then a else rangeA ((j-1)::a) i (j-1) in rangeA [] 0;; (* minimal fan definition *) type node_t = N2 | N2h0 | Nfree;; type edge_t = E2 | E2h0 | Gset;; type minimal_fan = { node : node_t list; nodeflats : bool list; edge : edge_t list; };; let mk_minimal_fan nhts nflts e = { node = nhts; nodeflats = nflts; edge = e; };; (* generating minimal_fan *) let node_of_int i = if (i=0) then N2 else if (i=1) then N2h0 else Nfree;; let edge_of_int i = if (i=0) then E2 else if (i=1) then E2h0 else Gset;; let bool_of_int i = if (i=0) then false else true;; let base modulus len k = let rec baselist modulus len k acc = if len <= 0 then acc else if (k=0) then baselist modulus (len-1) 0 (0::acc) else baselist modulus (len - 1) (k/modulus) ((k mod modulus) :: acc) in baselist modulus len k [];; let rec pow base exp = if exp = 0 then 1 else base*(pow base (exp-1));; let mk_x len (a,b,c) (r,s,t) = let (n,nf,e) = (base a len r, base b len s, base c len t) in mk_minimal_fan (map node_of_int n) (map bool_of_int nf) (map edge_of_int e);; (* reading data from a record *) let kn mf = length (mf.node);; let sn mf = List.length (filter ((=) Gset) mf.edge);; let rn mf = kn mf - sn mf;; let posmod i m = let j = i mod m in if (j<0) then j+m else j;; let part xs i = nth xs (posmod i (length xs));; let number mf = upto(length mf.edge);; let g_edge mf i = (part mf.edge i = Gset);; (* let nong_edge mf i = not(g_edge mf i);; *) let gminimal_edge mf i = not(part mf.edge i = E2h0);; let flat_node mf i = part mf.nodeflats i;; let nonflat_node mf i = not(flat_node mf i);; let bound_node mf i = not(part mf.node i = Nfree);; (* irreducibility *) (* extreme_edge is built into construction of edge types *) let card mf = (sn mf <= 3) && (3 <= sn mf + rn mf) && (rn mf + 2 * sn mf <= 6);; let extreme_edge mf = true;; let flat_exists mf = let has i = (kn mf <= 4) or flat_node mf i or flat_node mf (i+1) or flat_node mf (i+2) or flat_node mf (i+3) in for_all has (number mf);; let no_triple_flat mf = let triple_flat i = flat_node mf i && flat_node mf (i+1) && flat_node mf (i+2) in not (exists triple_flat (number mf));; let balance mf = let es = mf.edge in let has_balance i = (part es i = part es (i+1)) or (part es i = Gset) or (part es (i+1) = Gset) in for_all has_balance (number mf);; let g_flat mf = let gg = g_edge mf in let nf = nonflat_node mf in let has_gflat i = nf i or nf (i+1) or not(gg (i-1) or gg i or gg(i+1) ) in for_all has_gflat (number mf);; let flat_middle mf = let nf = nonflat_node mf in let has i = nf i or nf (i+1) or (part mf.edge i = E2 ) in for_all has (number mf);; let minimal_node mf = let has i = (part mf.node i = N2) or (gminimal_edge mf i) or (gminimal_edge mf (i-1)) in for_all has (number mf);; let minimal_node_flat mf = let has i = (nonflat_node mf i) or (part mf.node i = N2) or (gminimal_edge mf i && gminimal_edge mf (i-1)) in for_all has (number mf);; let flat_extremal mf = let has i = nonflat_node mf i or nonflat_node mf (i+1) or bound_node mf i or bound_node mf (i+1) in for_all has (number mf);; let extremal_node mf = let has i = flat_node mf i or flat_node mf (i+1) or flat_node mf (i+2) or bound_node mf (i+1) in for_all has (number mf);; let flat_extremal_node mf = let has i = flat_node mf i or nonflat_node mf (i+1) or flat_node mf (i+2) or flat_node mf (i+3) or bound_node mf (i+1) or bound_node mf (i+2) in for_all has (number mf);; let flat_extremal_node_sym mf = let has i = flat_node mf i or flat_node mf (i+1) or nonflat_node mf (i+2) or flat_node mf (i+3) or bound_node mf (i+1) or bound_node mf (i+2) in for_all has (number mf);; let flat_count mf = length (filter not mf.nodeflats) > 2;; let irreducible = fold_right (fun r s m -> r m && s m) [card;extreme_edge;flat_exists;no_triple_flat;balance;g_flat; flat_middle;minimal_node;minimal_node_flat;flat_extremal; extremal_node;flat_extremal_node;flat_extremal_node_sym; flat_count] (fun t->true);; (* symmetry reductions, add to the list of solutions only if it is shift-distinct from other solutions *) let shift_one (x::xs) = xs @ [x];; let shift a = { node = shift_one a.node; nodeflats = shift_one a.nodeflats; edge = shift_one a.edge };; let rec shiftk k a = if (k<=0) then a else shift (shiftk (k-1) a);; let add_if_new a xs = if (exists (fun i -> mem (shiftk i a) xs) (upto (kn a))) then xs else a::xs;; let add_if_irred a xs = if (irreducible a ) then add_if_new a xs else xs;; (* let add_if_irred a xs = if (irreducible a ) then a ::xs else xs;; *) let rec mk_all mkfn (imin,jmin,kmin) (imax,jmax,kmax) (i, j, k) acc = let acc' = add_if_irred (mkfn (i, j, k)) acc in let mka = mk_all mkfn (imin,jmin,kmin) (imax,jmax,kmax) in if (k+1 < kmax) then mka (i,j,(k+1)) acc' else if (j+1 < jmax) then mka (i,(j+1),kmin) acc' else if (i+1 < imax) then mka ((i+1),jmin,kmin) acc' else acc';; (* no flats *) let a3 = mk_all (mk_x 3 (3,1,3)) (0,0,0) (pow 3 3,1,pow 3 3) (0,0,0) [];; length a3;; (* no flats *) let a4nf = mk_all (mk_x 4 (3,1,3)) (0,0,0) (pow 3 4,1,pow 3 4) (0,0,0) [];; length a4nf;; (* exactly one flat *) let a4f = mk_all (mk_x 4 (3,2,3)) (0,1,0) (pow 3 4,2,pow 3 4) (0,1,0) [];; length a4f;; (* no Gset *) (* let a5ng =mk_all (mk_x 5 (3,2,2)) (0,0,0) (pow 3 5,pow 2 5,pow 2 5) (0,0,0) [];; length a5ng;; *) let a5 = mk_all (mk_x 5 (3,2,3)) (0,0,0) (pow 3 5,pow 2 5,pow 3 5) (0,0,0) [];; length a5;; (* no Gset *) let a6 = mk_all (mk_x 6 (3,2,2)) (0,0,0) (pow 3 6,pow 2 6,pow 2 6) (0,0,0) [];; length a6;; (* degrees of freedom *) let freedom a = (kn a) - 3 + length (filter ((=) Nfree) a.node) - length (filter (fun t->t) a.nodeflats);; map freedom a4nf;;