Index: /nodes/channelga.ml
===================================================================
--- /nodes/channelga.ml	(revision 1990)
+++ /nodes/channelga.ml	(revision 1991)
@@ -16,4 +16,13 @@
       can see eachother, so they should be apart)
 
+   special cases:
+     - on node x, interfaces y and z are well separated and can live on the
+       same channel
+     - interface x on node y will bother interface z on node w and need to
+       be on separate channels
+     - on node x, channels y, z and w are not usable
+     - node x y and z should be treated as one node
+     - if at all possible, do not put accesspoints above channel 11
+
  - install an O'Caml compiler. /usr/ports/lang/ocaml/ in FreeBSD, ocaml in
    Debian.
@@ -33,7 +42,7 @@
 (* a few constants suitable for twiddling *)
 (** How large a population should the system maintain? *)
-let population_size = 100
+let population_size = 20
 (** How long should the system iterate after an improvement? *)
-and max_stagnant_iterations = 10000
+and max_stagnant_iterations = 2000
 (** What is the chance for an ESSID to channel assignment to mutate to a 
     random channel? *)
@@ -69,4 +78,18 @@
 (** The global groups hash, mapping from essid to group struct. *)
 let groups = Hashtbl.create 4
+
+let nointerference = Hashtbl.create 4
+let unusable = Hashtbl.create 4
+let interference = []
+
+let scoretable = [ ((<=) 2,  1);
+		   ((==) 2, -30);
+		   ((==) 1, -70);
+		   ((==) 0, -100) ]
+let rec runtable t diff =
+     match t with
+	[]		-> assert false
+     | (cond, s)::xs	-> if (cond diff) then s
+			   else runtable xs diff
 
 (* some convenience functions *)
@@ -91,4 +114,9 @@
 let copyarray src dest = Array.blit src 0 dest 0 (Array.length src)
 
+let in_list l i = try
+			let _ = List.find ((==) i) l in
+			true
+		  with Not_found -> false
+
 (** Given a list, return a list of pairs with all possible combinations of 
    items from the given list *)
@@ -99,17 +127,12 @@
 
 (** Given a configuration and two wi's, return the score *)
-let wi_score c wi1 wi2 =
-	let scoretable = [ ((<=) 2,  1);
-			   ((==) 2, -1);
-			   ((==) 1, -5);
-			   ((==) 0, -10) ] in
+let wi_score c unusable nointerference wi1 wi2 =
 	let channel1 = c wi1.wi_essid in
 	let channel2 = c wi2.wi_essid in
 	let diff = abs (channel1 - channel2) in
-	let rec runtable t = match t with
-				[]		-> assert false
-			     | (cond, s)::xs	-> if (cond diff) then s
-						   else runtable xs in
-	runtable scoretable;;
+	let is_unusable = in_list unusable in
+	if (is_unusable channel1) || (is_unusable channel2) then -10000
+	else if in_list nointerference (maketuple wi1 wi2) then 1
+	else runtable scoretable diff;;
 
 (** Given a configuration and a node, return the score. this is simply the sum of
@@ -117,17 +140,29 @@
    efficiency *)
 let node_score c n =
-	let foldfunc acc (wi1, wi2) = acc + (wi_score c wi1 wi2) in
+	let nointerference_ = try Hashtbl.find nointerference n.node_name
+			      with Not_found -> [] in
+	let unusable_ = try Hashtbl.find unusable n.node_name
+			with Not_found -> [] in
+	let foldfunc acc (wi1, wi2) = acc + (wi_score c unusable_ nointerference_ wi1 wi2) in
 	let base_score = List.fold_left foldfunc 0 (combinations n.node_wis) in
 	base_score * (List.length n.node_wis)
+
+let test_interference c (wi1, wi2) = 
+	let channel1 = c wi1.wi_essid in
+	let channel2 = c wi2.wi_essid in
+	let diff = abs (channel1 - channel2) in
+	runtable scoretable diff
 
 (** Given a list of nodes and a configuration, return the score for the whole
     configuration. This is the sum of the scores for all nodes. *)
 let score_configuration ns c =
-	let foldfunc acc n = acc + (node_score (Hashtbl.find c) n) in
+	let mapper = Hashtbl.find c in
+	let foldfunc acc n = acc + (node_score mapper n) in
 	let nodescores = List.fold_left foldfunc 0 ns in
-	nodescores
+	let interference_penalty = List.fold_left (fun a i -> a + test_interference mapper i) 0 interference in
+	nodescores + interference_penalty;;
 
 (** Given a filename, return a list of all the lines in the file with the given
-   filename *)
+   filename. Don't count on the order of the lines in the result. *)
 let snarf_lines fname =
 	let infile = open_in fname in
