Changeset 1979 in genesis


Ignore:
Timestamp:
Apr 11, 2004, 1:05:07 AM (21 years ago)
Author:
lodewijk
Message:

het doet wat, en wat het doet doet het een hele hoop sneller dan de Python versie.

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
    125(* a few constants *)
    226let population_size = 20
     
    428and mutation_rate = 0.05;;
    529
    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 *)
    833type 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};;
     38type group = {
     39        group_essid: string;
     40        mutable group_wis: wi list;
     41};;
     42type node = {
     43        node_name: string;
     44        node_wis: wi list;
    1845};;
    1946
     
    2148let groups = Hashtbl.create 4;;
    2249
    23 type score = int
    24  and channel = int;;
    25 
     50(* some convenience functions *)
    2651let compose f g = fun x -> f(g(x));;
    2752let ($) = compose;;
    2853let maketuple a b = (a, b);;
     54let head = List.hd;;
     55let tail = List.tl;;
    2956(* given a hashtable, return all the keys as a list *)
    3057let keys t = Hashtbl.fold (fun k d a -> k::a) t [];;
     
    3764        match l with
    3865          []    -> []
    39         | x::xs -> (List.map (maketuple x) xs)@(combinations xs)
    40 ;;
     66        | x::xs -> (List.map (maketuple x) xs)@(combinations xs);;
    4167
    4268(* given a configuration and two wi's, return the score *)
    4369let wi_score c wi1 wi2 =
    44         let scoretable = [ ((>) 2,  1);
     70        let scoretable = [ ((<=) 2,  1);
    4571                           ((==) 2, -1);
    4672                           ((==) 1, -5);
    4773                           ((==) 0, -10) ] in
    48         let channel1 = c !(wi1.group) in
    49         let channel2 = c !(wi2.group) in
     74        let channel1 = c wi1.wi_essid in
     75        let channel2 = c wi2.wi_essid in
    5076        let diff = abs (channel1 - channel2) in
    5177        let rec runtable t = match t with
     
    5581        runtable scoretable;;
    5682
     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 *)
    5786let node_score c n =
    5887        let foldfunc acc (wi1, wi2) = acc + (wi_score c wi1 wi2) in
    59         List.fold_left foldfunc 0 (combinations n.nodewis);;
     88        List.fold_left foldfunc 0 (combinations n.node_wis);;
    6089
    6190let 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
    6492        List.fold_left foldfunc 0 ns;;
    65 
    66 let add_wi_to_node n (w: wi) = { n with nodewis = (w::n.nodewis) };;
    6793
    6894(* given a filename, return a list of all the lines in the file with the given
     
    78104        with End_of_file -> !result
    79105
     106let 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
     119let 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
    80130let 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)
    84133        ;;
    85134
    86 let random_configuration =
     135let random_configuration groups =
    87136        let conf = Hashtbl.create 30 in
    88137        Hashtbl.iter (fun k d -> Hashtbl.add conf k (1 + (Random.int 12))) groups;
    89138        conf
    90139
     140(* Mutate the configuration in the given population at the given offset *)
    91141let mutate p i =
    92142        Hashtbl.iter (fun essid chan -> let f = Random.float 1.0 in
     
    94144                                          Hashtbl.replace p.(i) essid (1 + (Random.int 13))) p.(i);;
    95145
     146let 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
    96152let main =
    97         List.iter parse_file (snarf_lines Sys.argv.(1));
     153        parse_file Sys.argv.(1);
    98154        Random.self_init();
    99         let population = Array.init population_size (fun _ -> random_configuration) in
     155        let population = Array.init population_size (fun _ -> random_configuration groups) in
    100156        let last_high_score = ref (-1000000) in
    101157        let iterations_since_new_high_score = ref 0 in
     158        let generation = ref 0 in
    102159        let all_nodes = values nodes in
    103160        while !iterations_since_new_high_score < max_stagnant_iterations do
     
    112169                let score_pop = Array.map (fun c -> ((score_configuration c all_nodes), c)) population in
    113170                (* 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);
    115173                (* now look at the best score and update the highscore if
    116174                   necessary *)
     
    120178                        iterations_since_new_high_score := 0
    121179                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
    126189        done;
    127         ()
    128 ;;
     190        print_conf population.(0);;
    129191
    130192main
Note: See TracChangeset for help on using the changeset viewer.