source: genesis/nodes/channelga.py@ 1928

Last change on this file since 1928 was 1928, checked in by lodewijk, 21 years ago

prutsel voor kanalenplanning uit te rekenen

File size: 7.0 KB
Line 
1# experiment met een genetisch algoritme voor de kanalenplanning
2# het genetische zit er nu nauwelijks in, en wat er in zit is ongetwijfeld
3# fout. wat er wel goed in zit is het parseren van de bestaande situatie en
4# het scoren van (nu random) configuraties.
5
6# de score functie is nu redelijk simplistisch:
7# - de score van een combinatie van twee interfaces op een node is 1 als er
8# twee of meer kanalen tussen zitten, en -1 als dat niet zo is
9# - de score van een node is de som van de scores van alle combinaties van
10# interfaces van die node, maal het aantal interfaces. dat laatste omdat
11# een positieve score hebben knapper is met meer interfaces dan met minder,
12# dus dat moet beloond. een negatieve score is erger met meer interfaces
13# (belangrijker node, waarschijnlijk) dan met minder, dus dat moet
14# bestraft.
15# - de totale score is de som van de scores van de nodes
16#
17# het stukje "genetisch" aan het einde is afgeraffeld. mutation en
18# recombination gebeuren op de oplossing zelf ipv op een bitstring
19# representatie. selection is dom en neemt gewoon de helft beste oplossingen.
20import re
21import random
22
23# deze twee zijn nodig voor de evaluatie van een configuratie
24nodes = {} # lijst van Node instanties
25groups = [] # lijst van Group instanties
26
27population = []
28
29# gegeven een lijst, geef de lijst zonder dubbele elementen
30def uniq(l):
31 d = {}
32 for e in l:
33 d[e] = 1
34 return d.keys()
35
36class Node:
37 def __init__(self, name, wis):
38 self.name = name
39 self.wis = wis
40 for wi in wis:
41 wi.setNode(self)
42 def wi_byname(self, name):
43 wi = filter(lambda wi: wi.name == name, self.wis)
44 assert len(wi) == 1
45 return wi[0]
46 def score(self):
47 score = 0
48 for i in range(len(self.wis)):
49 wi_i = self.wis[i]
50 if wi_i.group == None:
51 # orphaned interface
52 continue
53 if wi_i.group.channel == None:
54 print "huh?"
55 for j in range(len(self.wis)):
56 if i != j:
57 wi_j = self.wis[j]
58 if wi_j.group == None:
59 continue
60 diff = abs(wi_i.group.channel - wi_j.group.channel)
61 if diff > 2:
62 score = score + 1
63 else:
64 score = score - 1
65 score = score * len(self.wis)
66 return score
67
68class WI:
69 def __init__(self, name):
70 self.name = name
71 self.node = None
72 self.group = None
73 self.omni = 0
74 def setNode(self, node):
75 self.node = node
76 def setGroup(self, group):
77 self.group = group
78
79class WIGroup:
80 def __init__(self, name):
81 self.name = name
82 self.wis = []
83 self.channel = None
84 def add_wi(self, wi):
85 self.wis.append(wi)
86 wi.setGroup(self)
87
88class Configuration:
89 def __init__(self):
90 self.conf = None
91 self.calculated_score = None
92 def copy(self):
93 c = Configuration()
94 c.conf = self.conf[:]
95 c.calculated_score = None
96 return c
97 def randomize(self):
98 self.conf = [random.randint(1, 13) for i in range(len(groups))]
99 self.calculated_score = None
100 def score(self):
101 assert len(self.conf) == len(groups)
102 if self.calculated_score != None:
103 return self.calculated_score
104 for i in range(len(self.conf)):
105 groups[i].channel = self.conf[i]
106 score = 0
107 for node in nodes.values():
108 score = score + node.score()
109 self.calculated_score = score
110 return score
111 def mutate(self, rate):
112 for i in range(len(groups)):
113 if random.random() <= rate:
114 self.conf[i] = random.randint(1, 13)
115 def crossover(self, partner, numpoints):
116 # pick the crossover points
117 points = [random.randint(0, len(groups) - 1) for i in range(numpoints)]
118 points.sort()
119 conf = []
120 who = 0
121 lastpoint = 0
122 while len(points):
123 point = points.pop(0)
124 if who == 0:
125 l = self.conf[lastpoint:point]
126 who = 1
127 else:
128 l = partner.conf[lastpoint:point]
129 who = 0
130 conf.extend(l)
131 lastpoint = point
132 if who == 0:
133 l = self.conf[lastpoint:]
134 else:
135 l = partner.conf[lastpoint:]
136 conf.extend(l)
137 assert len(conf) == len(groups)
138 self.conf = conf
139
140
141# BEGIN UGLY PARSING CODE
142
143ipdict = {}
144ipnr_node = {}
145node_ipnr = {}
146node_links = {}
147
148def parse_wleiden_conf(lines):
149 ipnr = None
150 wi = None
151 peer = None
152 omni = 0
153 for l in lines:
154 if wi != None:
155 match = re.match("^\EW.*", l)
156 if match != None:
157 wi = None
158 ipnr = None
159 peer = None
160 continue
161 match = re.match("^SDESC=omni.*", l)
162 if match != None:
163 omni = 1
164 match = re.match("^IP=([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*).*", l)
165 if match != None:
166 ipnr = match.group(1)
167 if not node_ipnr.has_key(nodename):
168 node_ipnr[nodename] = []
169 node_ipnr[nodename].append(ipnr)
170 ipnr_node[ipnr] = nodename
171 match = re.match("^POINT_TO_POINT=([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*).*", l)
172 if match != None:
173 peer = match.group(1)
174 if not node_links.has_key(nodename):
175 node_links[nodename] = []
176 node_links[nodename].append( (peer, wi) )
177 else:
178 match = re.match("^\$nodename='([^']*)';.*", l)
179 if match != None:
180 nodename = match.group(1).lower()
181 match = re.match("^\$config{'(wi[0-9]*).*", l)
182 if match != None:
183 wi = match.group(1)
184 omni = 0
185
186# gegeven een file met filenames van wleiden.conf's, parseer ze allemaal en
187# vul de datastructuren
188def parse_metafile(filename):
189 for fname in open(filename).readlines():
190 parse_wleiden_conf(open(fname[:-1]).readlines())
191 for nodename in node_ipnr.keys():
192 wis = []
193 if node_links.has_key(nodename):
194 d = {}
195 for peer, wi in node_links[nodename]:
196 if not d.has_key(wi):
197 wis.append(WI(wi))
198 d[wi] = 1
199 node = Node(nodename, wis)
200 nodes[nodename] = node
201
202 for nodename in node_links.keys():
203 node = nodes[nodename]
204
205 for peerip, winame in node_links[nodename]:
206 wi = node.wi_byname(winame)
207 if not ipnr_node.has_key(peerip):
208 print "Warning: node %s links to phantom IP %s" % (nodename, peerip)
209 continue
210 peername = ipnr_node[peerip]
211 bail = 0
212 for peerspeerip, peerswiname in node_links[peername]:
213 if not ipnr_node.has_key(peerspeerip):
214 print "Warning: node %s links to phantom IP %s" % (nodename, peerspeerip)
215 bail = 1
216 break
217 if ipnr_node[peerspeerip] == nodename:
218 break
219 if bail:
220 continue
221 peer = nodes[peername]
222 peerwi = peer.wi_byname(peerswiname)
223 # komt wi voor deze node al voor in de bestaande
224 # groepen?
225 group = None
226 for i in range(len(groups)):
227 if filter(lambda wi: wi.node.name == nodename and wi.name == winame, groups[i].wis) != []:
228 group = groups[i]
229 break
230 if group == None:
231 for i in range(len(groups)):
232 if filter(lambda wi: wi.node.name == peername and wi.name == peerswiname, groups[i].wis) != []:
233 group = groups[i]
234 break
235 if group == None:
236 # nee. maak een groep en voeg beide
237 # endpoints toe
238 group = WIGroup('foo')
239 group.add_wi(wi)
240 groups.append(group)
241 group.add_wi(peerwi)
242 for group in groups:
243 group.wis = uniq(group.wis)
244
245# END UGLY PARSING CODE
246
247parse_metafile('l')
248
249for i in range(20):
250 conf = Configuration()
251 conf.randomize()
252 population.append(conf)
253
254while 1:
255 for i in range(10):
256 p = population[i].copy()
257 population[i].crossover(population[i + 10], 8)
258 population[i + 10] = p
259 population[i + 10].mutate(0.01)
260 population.sort(lambda a, b: cmp(b.score(), a.score()))
261 print population[0].score(), population[0].conf
Note: See TracBrowser for help on using the repository browser.