Changeset 1979 in genesis
- Timestamp:
- Apr 11, 2004, 1:05:07 AM (21 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
nodes/channelga.ml
r1973 r1979 1 (** 2 experiment met evolutionary programming voor de kanalenplanning 3 het genetische zit er nu nauwelijks in, en wat er in zit is ongetwijfeld 4 fout. wat er wel goed in zit is het parseren van de bestaande situatie en 5 het scoren van (nu random) configuraties. 6 7 de score functie is nu redelijk simplistisch: 8 - de score van een combinatie van twee interfaces op een node is 1 als er 9 twee of meer kanalen tussen zitten, en -1 als er 1 kanaal tussen zit, -5 10 als er geen kanaal tussen zit en -10 als de kanalen hetzelfde zijn 11 - de score van een node is de som van de scores van alle combinaties van 12 interfaces van die node, maal het aantal interfaces. dat laatste omdat 13 een positieve score hebben knapper is met meer interfaces dan met minder, 14 dus dat moet beloond. een negatieve score is erger met meer interfaces 15 (belangrijker node, waarschijnlijk) dan met minder, dus dat moet 16 bestraft. 17 - de totale score is de som van de scores van de nodes 18 19 het stukje "genetisch" aan het einde is afgeraffeld. mutation en 20 recombination gebeuren op de oplossing zelf ipv op een bitstring 21 representatie. selection is dom en neemt gewoon de helft beste oplossingen. 22 23 lvoge@cs.vu.nl *) 24 1 25 (* a few constants *) 2 26 let population_size = 20 … … 4 28 and mutation_rate = 0.05;; 5 29 6 (* the type definitions. note the 'and' to string them together in a mutually 7 recursive blob so wi and node can refer to eachother *) 30 (* the type definitions. note that Caml has trouble with mutually recursive 31 data structures. you can define them, you just can't ever instantiate them. 32 this is why the fields in wi are all loose references by way of strings *) 8 33 type wi = { 9 winame: string; 10 node: node ref; 11 group: group ref; 12 } and group = { 13 essid: string; 14 groupwis: wi ref list; 15 } and node = { 16 nodename: string; 17 nodewis: wi list; 34 wi_name: string; 35 wi_nodename: string; 36 wi_essid: string; 37 };; 38 type group = { 39 group_essid: string; 40 mutable group_wis: wi list; 41 };; 42 type node = { 43 node_name: string; 44 node_wis: wi list; 18 45 };; 19 46 … … 21 48 let groups = Hashtbl.create 4;; 22 49 23 type score = int 24 and channel = int;; 25 50 (* some convenience functions *) 26 51 let compose f g = fun x -> f(g(x));; 27 52 let ($) = compose;; 28 53 let maketuple a b = (a, b);; 54 let head = List.hd;; 55 let tail = List.tl;; 29 56 (* given a hashtable, return all the keys as a list *) 30 57 let keys t = Hashtbl.fold (fun k d a -> k::a) t [];; … … 37 64 match l with 38 65 [] -> [] 39 | x::xs -> (List.map (maketuple x) xs)@(combinations xs) 40 ;; 66 | x::xs -> (List.map (maketuple x) xs)@(combinations xs);; 41 67 42 68 (* given a configuration and two wi's, return the score *) 43 69 let wi_score c wi1 wi2 = 44 let scoretable = [ (( >)2, 1);70 let scoretable = [ ((<=) 2, 1); 45 71 ((==) 2, -1); 46 72 ((==) 1, -5); 47 73 ((==) 0, -10) ] in 48 let channel1 = c !(wi1.group)in49 let channel2 = c !(wi2.group)in74 let channel1 = c wi1.wi_essid in 75 let channel2 = c wi2.wi_essid in 50 76 let diff = abs (channel1 - channel2) in 51 77 let rec runtable t = match t with … … 55 81 runtable scoretable;; 56 82 83 (* given a configuration and a node, return the score. this is simply the sum of 84 the scores of all the combinations of interfaces, written down as a fold for 85 efficiency *) 57 86 let node_score c n = 58 87 let foldfunc acc (wi1, wi2) = acc + (wi_score c wi1 wi2) in 59 List.fold_left foldfunc 0 (combinations n.node wis);;88 List.fold_left foldfunc 0 (combinations n.node_wis);; 60 89 61 90 let score_configuration c (ns: node list) = 62 let mapper g = Hashtbl.find c g.essid in 63 let foldfunc acc n = acc + (node_score mapper n) in 91 let foldfunc acc n = acc + (node_score (Hashtbl.find c) n) in 64 92 List.fold_left foldfunc 0 ns;; 65 66 let add_wi_to_node n (w: wi) = { n with nodewis = (w::n.nodewis) };;67 93 68 94 (* given a filename, return a list of all the lines in the file with the given … … 78 104 with End_of_file -> !result 79 105 106 let parse_pair nodename (wname, gname) = 107 let new_wi = { wi_name = wname; wi_nodename = nodename; wi_essid = gname} in 108 let foo = try 109 let group = Hashtbl.find groups gname in 110 group.group_wis <- new_wi::group.group_wis; 111 with Not_found -> 112 let group = { group_essid = gname; group_wis = [ new_wi ] } in 113 print_string "added group "; 114 print_string gname; 115 print_newline(); 116 Hashtbl.add groups gname group in 117 new_wi 118 119 let parse_fields fields = 120 let nodename = head fields in 121 let rec makepairs l = match l with 122 [] -> [] 123 | x::[] -> assert false 124 | a::b::xs -> (a, b)::(makepairs xs) in 125 let wis = List.map (parse_pair nodename) (makepairs (tail fields)) in 126 let sorted_wis = List.sort compare wis in 127 let node = { node_name = nodename; node_wis = sorted_wis } in 128 Hashtbl.add nodes nodename node 129 80 130 let parse_file fname = 81 let bogus_node = { nodename = "foo"; nodewis = [] } in 82 Hashtbl.add nodes fname bogus_node; 83 Hashtbl.add groups fname 1; 131 let spacere = Str.regexp " " in 132 List.iter (parse_fields $ (Str.split spacere)) (snarf_lines fname) 84 133 ;; 85 134 86 let random_configuration =135 let random_configuration groups = 87 136 let conf = Hashtbl.create 30 in 88 137 Hashtbl.iter (fun k d -> Hashtbl.add conf k (1 + (Random.int 12))) groups; 89 138 conf 90 139 140 (* Mutate the configuration in the given population at the given offset *) 91 141 let mutate p i = 92 142 Hashtbl.iter (fun essid chan -> let f = Random.float 1.0 in … … 94 144 Hashtbl.replace p.(i) essid (1 + (Random.int 13))) p.(i);; 95 145 146 let print_conf conf = 147 let print_wi wi = wi.wi_name ^ ": " ^ (string_of_int (Hashtbl.find conf wi.wi_essid)) in 148 let wis node = List.fold_left (fun acc wi -> acc ^ " " ^ (print_wi wi)) "" node.node_wis in 149 let sorted_nodes = List.sort (fun a b -> compare (a.node_name) (b.node_name)) (values nodes) in 150 List.iter (fun n -> print_string (n.node_name ^ ":" ^ (wis n) ^ "\n")) sorted_nodes 151 96 152 let main = 97 List.iter parse_file (snarf_lines Sys.argv.(1));153 parse_file Sys.argv.(1); 98 154 Random.self_init(); 99 let population = Array.init population_size (fun _ -> random_configuration ) in155 let population = Array.init population_size (fun _ -> random_configuration groups) in 100 156 let last_high_score = ref (-1000000) in 101 157 let iterations_since_new_high_score = ref 0 in 158 let generation = ref 0 in 102 159 let all_nodes = values nodes in 103 160 while !iterations_since_new_high_score < max_stagnant_iterations do … … 112 169 let score_pop = Array.map (fun c -> ((score_configuration c all_nodes), c)) population in 113 170 (* sort on the first field *) 114 Array.sort (fun x y -> compare (fst x) (fst y)) score_pop; 171 Array.sort (fun x y -> compare (fst y) (fst x)) score_pop; 172 Array.blit (Array.map snd score_pop) 0 population 0 (Array.length score_pop); 115 173 (* now look at the best score and update the highscore if 116 174 necessary *) … … 120 178 iterations_since_new_high_score := 0 121 179 end; 122 (*print_int high_score;*) 123 print_int !iterations_since_new_high_score; 124 print_newline(); 125 incr iterations_since_new_high_score 180 assert (!last_high_score >= high_score); 181 if (!generation mod 10) == 0 then begin 182 print_int !generation; 183 print_string ": "; 184 print_int !last_high_score; 185 print_newline(); 186 end; 187 incr iterations_since_new_high_score; 188 incr generation 126 189 done; 127 () 128 ;; 190 print_conf population.(0);; 129 191 130 192 main
Note:
See TracChangeset
for help on using the changeset viewer.