This file is indexed.

/usr/share/pyshared/openopt/solvers/Standalone/galileo_oo.py is in python-openopt 0.38+svn1589-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
#from numpy import asfarray, argmax, sign, inf, log10
from openopt.kernel.baseSolver import baseSolver
from numpy import asfarray,  inf,  atleast_1d
from openopt.kernel.setDefaultIterFuncs import SMALL_DELTA_X,  SMALL_DELTA_F

class galileo(baseSolver):
    __name__ = 'galileo'
    __license__ = "GPL"
    __authors__ = 'Donald Goodman, dgoodman-at-cs.msstate.edu, connected to OO by Dmitrey'
    __alg__ = "Genetic Algorithm, same as ga2, the C++ canonical genetic algorithm lib, also by Donald Goodman"
    iterfcnConnected = True
    __homepage__ = 'http://www.cs.msstate.edu/~dgoodman'

    __info__ = """
    requires finite lb, ub: lb <= x <= ub
    """
    __optionalDataThatCanBeHandled__ = ['lb', 'ub']
    __isIterPointAlwaysFeasible__ = lambda self, p: True

    population = 15
    crossoverRate = 1.0 # 1.0 means always
    mutationRate = 0.05 # not very often
    useInteger = False # use float by default
    _requiresFiniteBoxBounds = True


    def __init__(self):pass
    def __solver__(self, p):

        p.kernelIterFuncs.pop(SMALL_DELTA_X)
        p.kernelIterFuncs.pop(SMALL_DELTA_F)
        p.ff = inf

        #create an initial population of 10 chromosomes
        P = Population(self.population)# CHECKME! is the Population size optimal?

        #use fitness as our evaluation function
        P.evalFunc = lambda x: -p.f(x) # fitness

        #minimum values the genes can take
        P.chromoMinValues = p.lb.tolist()

        #maximum values the genes can take
        P.chromoMaxValues = p.ub.tolist()

        #use integers instead of floats
        P.useInteger = self.useInteger

        #crossover
        P.crossoverRate = self.crossoverRate

        #mutate, but not very often
        P.mutationRate = self.mutationRate

        #use roulette (monte carlo) selection
        P.selectFunc = P.select_Roulette

        #use a full replacement size
        P.replacementSize = P.numChromosomes

        #use one point crossover
        P.crossoverFunc = P.crossover_OnePoint

        #use the default mutation routines
        P.mutateFunc = P.mutate_Default

        #use steady-state replacement with no duplication
        P.replaceFunc = P.replace_SteadyStateNoDuplicates

        #finish initializing the population. THIS MUST BE CALLED after settings the
        #variables above, but before actually running the GA!
        P.prepPopulation()
        #for 50 epochs

        for itn in range(p.maxIter+1):
          #evaluate each chromosomes
          P.evaluate()
          #apply selection
          P.select()
          #apply crossover
          P.crossover()
          #apply mutation
          P.mutate()
          #apply replacement
          P.replace()
          #print the best fit individual, and its fitness
          fval = asfarray(-P.maxFitness)
          if p.ff > fval:
              p.xf,  p.ff = asfarray(P.bestFitIndividual.genes), fval
          p.iterfcn(asfarray(P.bestFitIndividual.genes), fval)

          if p.istop:
              #p.xk,  p.fk = p.xf,  p.ff
              return



from random import Random

class Chromosome:
  """The Chromosome class represents a single chromosome in a population.
  A Chromosome contains some number of genes (Python objects), and can
  be treated as a list, with indices and slices and all that good stuff
  """

  def __init__(self):
    """Constructs a new Chromosome instance"""
    self.genes = []
    self.geneMaxValues = []
    self.geneMinValues = []
    self.fitness = None
    self.evalFunc = None
    self.parent = None

  def __str__(self):
    return self.genes.__str__()

  def randomInit(self, generator, intValues = 1):
    """Randomly initializes all genes within the ranges set with
    setMinValues and setMaxValues. generator should be an instance
    of Random from the random module. Doing things this way allows for
    thread safety. If intValues is set to 1, random
    integers will be created, else random floating point values will
    be generated.
    """
    #first, are the lists empty?
    minlen = len(self.geneMinValues)
    maxlen = len(self.geneMaxValues)
    if (minlen == 0) or (minlen != maxlen):
      return
    randFunc = None
    if intValues == 1:
      randFunc = generator.randint
    else:
      randFunc = generator.uniform
    self.genes = []
    for i in range(minlen):
      self.genes.append(randFunc(self.geneMinValues[i], self.geneMaxValues[i]))

    self.fitness = None

  def evaluate(self):
    """Calls evalFunc for this chromosome, and caches the fitness value
    returned. Returns None if evalFunc is not yet defined.
    """
    if self.evalFunc != None:
      self.fitness = self.evalFunc(self.genes)
      return self.fitness
    else:
      return None

  def getFitness(self):
    """Calls evaluate if there is no cached value, otherwise returns the cached
    fitness value.
    """
    if self.fitness != None:
      return self.fitness
    else:
      return self.evaluate()

  def copy(self):
    """Duplicates the chromosome.
    """
    retval = Chromosome()
    for item in self.__dict__:
      retval.__dict__[item] = self.__dict__[item]
    return retval

  def __len__(self):
    return len(self.genes)

  def __getitem__(self, key):
    retval = self.copy()
    retval.genes = [self.genes[key]]
    retval.geneMinValues = [self.geneMinValues[key]]
    retval.geneMaxValues = [self.geneMaxValues[key]]
    retval.fitness = None
    return retval

  def __setitem__(self, key, value):
    return self.genes.__setitem__(key, value)

  def __getslice__(self, i, j):
    retval = self.copy()
    retval.genes = self.genes[i:j]
    retval.geneMinValues = self.geneMinValues[i:j]
    retval.geneMaxValues = self.geneMaxValues[i:j]
    retval.fitness = None
    return retval
    return self.genes.__getslice__(i, j)

  def __contains__(self, item):
    return self.genes.__contains__(item)

  def __add__(self, other):
    retval = self.copy()
    retval.genes = self.genes + other.genes
    retval.geneMinValues = self.geneMinValues + other.geneMinValues
    retval.geneMaxValues = self.geneMaxValues + other.geneMaxValues
    retval.fitness = None
    return retval

  def __cmp__(self, other):
    s1 = self.getFitness()
    s2 = other.getFitness()
    return s1-s2

  def isIdentical(self, other):
    """If the genes in self and other are identical, returns 0
    """
    return (self.genes == other.genes)

class Population:
  """The Population class represents an entire population of a single
  generation of Chromosomes. This population is replaced with each iteration
  of the algorithm. Functions are provided for storing generations for later
  analysis or retrieval, or for reloading the population from some point.
  All of the high level functionality is in this
  class: generally speaking, you will almost never call a function from any
  of the other classes.
  """

  def __init__(self, numChromosomes):
    """Constructs a population of chromosomes, with numChromosomes as the
    size of the population. Note that prepPopulation must also be called
    after all user defined variables have been set, to finish initialization.
    """
    self.numChromosomes = numChromosomes
    self.currentGeneration = []
    self.nextGeneration = []
    self.chromoMaxValues = []
    self.chromoMinValues = []

    self.mutationRate = 0.0
    self.crossoverRate = 0.0
    self.replacementSize = 0
    self.useInteger = 0
    self.isSorted = 0

    self.crossoverCount = 0
    self.mutationCount = 0

    self.evalFunc = None
    self.mutateFunc = None
    self.selectFunc = None
    self.crossoverFunc = None
    self.replaceFunc = None

    self.generator = Random()

    self.minFitness = None
    self.maxFitness = None
    self.avgFitness = None
    self.sumFitness = None
    self.bestFitIndividual = None

  def prepPopulation(self):
    """Radnomly initializes each chromosome according to the values in
    chromosMinValues and chromosMaxValues.
    """
    if (len(self.chromoMinValues) != len(self.chromoMaxValues)) or (len(self.chromoMinValues) == 0):
      return None

    self.currentGeneration = []

    for i in range(self.numChromosomes):
      c = Chromosome()
      c.geneMinValues = self.chromoMinValues
      c.geneMaxValues = self.chromoMaxValues
      c.randomInit(self.generator, self.useInteger)
      c.evalFunc = self.evalFunc
      self.currentGeneration.append(c)

    return 1

  def evaluate(self):
    """Evaluates each chromosome. Since fitness values are cached, don't
    hesistate to call many times. Also calculates sumFitness, avgFitness,
    maxFitness, minFitness, and finds bestFitIndividual, for your convienence.
    Be sure to assign an evalFunc
    """

    self.sumFitness = 0.0
    self.avgFitness = 0.0
    self.maxFitness = self.currentGeneration[0].getFitness()
    self.minFitness = self.currentGeneration[0].getFitness()
    self.bestFitIndividual = self.currentGeneration[0]

    for chromo in self.currentGeneration:
      f = chromo.getFitness()
      self.sumFitness = self.sumFitness + f
      if f > self.maxFitness:
        self.maxFitness = f
        self.bestFitIndividual = chromo
      elif f < self.minFitness: self.minFitness = f

    self.avgFitness = self.sumFitness/len(self.currentGeneration)

  def mutate(self):
    """At probability mutationRate, mutates each gene of each chromosome. That
    is, each gene has a mutationRate chance of being randomly re-initialized.
    Right now, only mutate_Default is available for assignment to mutateFunc.
    """

    self.mutationCount = 0
    for i in range(self.replacementSize):
      self.nextGeneration[i] = self.mutateFunc(self.nextGeneration[i])

  def select(self):
    """Selects chromosomes from currentGeneration for placement into
    nextGeneration based on selectFunc.
    """

    self.nextGeneration = []
    for i in range(0, self.replacementSize, 2):
      s1 = self.selectFunc()
      s2 = self.selectFunc()
      s1.parent = (s1, s1)
      s2.parent = (s2, s2)
      self.nextGeneration.append(s1)
      self.nextGeneration.append(s2)

  def crossover(self):
    """Performs crossover on pairs of chromos in nextGeneration with probability
    crossoverRate. Calls crossoverFunc, which must be set; current choices are
    crossover_OnePoint, crossover_TwoPoint and crossover_Uniform.
    """

    self.crossCount = 0
    for i in range(0, self.replacementSize, 2):
      (a,b) = self.crossoverFunc(self.nextGeneration[i], self.nextGeneration[i+1])
      (self.nextGeneration[i],self.nextGeneration[i+1]) = (a,b)

  def replace(self):
    """Replaces currentGeneration with nextGeneration according to the rules
    set forth in replaceFunc. Right now, replaceFunc can take the values of
    replace_SteadyState, replace_SteadyStateNoDuplicates and
    replace_Generational.
    """

    return self.replaceFunc()

  def select_Roulette(self):
    """Perform Roulette (Monte Carlo) selection. Assign this function to
    selectFunc to use.
    In essence, we construct a big roulette wheel, with a slot for each
    individual. The size of each slot is proportional to the relative fitness
    of that individual. The wheel is then spun! whee! The more fit individuals
    have a greater chance of landing under the pointer. The individual that
    lands under the pointer is returned.
    """

    partialSum = 0.0
    #spin the wheel!!
    wheelPosition = self.generator.uniform(0, self.sumFitness)
    i = 0
    for chromo in self.currentGeneration:
      partialSum = partialSum + chromo.getFitness()
      if partialSum >= wheelPosition:
        return chromo
      i = i + 1
    return self.currentGeneration[-1]

  def select_Ranked(self):
    """Currently does nothing. Hrm.
    """
    return None

  def crossover_OnePoint(self, chromo1, chromo2):
    """A crossover function that can be assigned to crossoverFunc. This one
    takes two chromosomes, cuts them at some random point, and swaps the parts
    creating two new chromosomes, which are returned in a tuple. Note
    that there is only a crossoverRate chance of crossover happening.
    """
    prob = self.generator.random()
    if prob <= self.crossoverRate:
      self.crossoverCount = self.crossoverCount + 1
      cutPoint = self.generator.randint(0, len(chromo1)-1)
      newchromo1 = chromo1[:cutPoint]+chromo2[cutPoint:]
      newchromo2 = chromo2[:cutPoint]+chromo1[cutPoint:]
      return (newchromo1, newchromo2)
    else:
      return (chromo1, chromo2)


    """A crossover function that can be assigned to crossoverFunc. This one
    takes two chromosomes, cuts them at two random points (creating three
    parts for each chromosomes), and swaps the parts around, creating two
    new chromosomes, which are returned in a tuple. Note
    that there is only a crossoverRate chance of crossover happening.
    """
    prob = self.generator.random()
    if prob <= self.crossoverRate:
      self.crossoverCount = self.crossoverCount + 1
      cutPoint1 = self.generator.randint(0, len(chromo1)-1)
      cutPoint2 = self.generator.randint(1, len(chromo1))
      if cutPoint2 < cutPoint1:
        temp = cutPoint1
        cutPoint1 = cutPoint2
        cutPoint2 = temp

      newchromo1 = chromo1[:cutPoint1]+chromo2[cutPoint1:cutPoint2]+chromo1[cutPoint2:]
      newchromo2 = chromo2[:cutPoint1]+chromo1[cutPoint1:cutPoint2]+chromo2[cutPoint2:]

      return (newchromo1, newchromo2)
    else:
      return (chromo1, chromo2)

  def crossover_Uniform(self, chromo1, chromo2):
    """A crossover function that can be assigned to crossoverFunc. Creates
    two new chromosomes by flippinng a coin for each gene. If the coin is heads,
    the gene values in chromo1 and chromo2 are swapped (otherwise they are
    left alone). The two new chromosomes are returned in a tuple. Note
    that there is only a crossoverRate chance of crossover happening.
    """

    prob = self.generator.random()
    if prob <= self.crossoverRate:
      self.crossoverCount = self.crossoverCount + 1
      newchromo1 = chromo1.copy()
      newchromo2 = chromo2.copy()
      for i in range(len(chromo1)):
        #flip a coin...1 we switch, 0 we do nothing
        coin = self.generator.randint(0,1)
        if coin == 1:
          temp = newchromo1.genes[i]
          newchromo1.genes[i] = newchromo2.genes[i]
          newchromo2.genes[i] = temp
      return (newchromo1, newchromo2)
    else:
      return (chromo1, chromo2)

  def mutate_Default(self, chromo):
    """Mutation function that can be assigned to mutateFunc. For each gene
    on each chromosome, there is a mutationRate chance that it will be
    randomly re-initialized. The chromosome is returned.
    """
    for i in range(len(chromo.genes)):
      prob = self.generator.random()
      if prob <= self.mutationRate:
        #then we mutate!
        self.mutationCount = self.mutationCount + 1
        f = 0
        if self.useInteger:
          f = self.generator.randint(self.chromoMinValues[i], self.chromoMaxValues[i])
        else:
          f = self.generator.uniform(self.chromoMinValues[i], self.chromoMaxValues[i])
        chromo.genes[i] = f
    return chromo

  def replace_SteadyState(self):
    """Replacement function that can be assigned to replaceFunc. Takes the
    values in nextGeneration, sticks them into currentGeneration, sorts
    currentGeneration, and lops off enough of the least fit individuals
    to reduce the size of currentGeneration back to numChromosomes.
    """

    for chromo in self.nextGeneration:
      self.currentGeneration.append(chromo)
    self.currentGeneration.sort()
    self.currentGeneration.reverse()
    self.currentGeneration = self.currentGeneration[:self.numChromosomes]
    self.nextGeneration = []

  def replace_SteadyStateNoDuplicates(self):
    """Replacement function that can be assigned to replaceFunc. Same as
    replace_SteadyState, exccept that duplicate chromosomes are not inserted
    back into the currentGeneration.
    """
    #this one is like above, but no duplicates are allowed!
    for chromo in self.nextGeneration:
      flag = 0
      for chromo2 in self.currentGeneration:
        if chromo.isIdentical(chromo2):
          flag = 1
      if flag == 0:
        self.currentGeneration.append(chromo)
    self.currentGeneration.sort()
    self.currentGeneration.reverse()
    self.currentGeneration = self.currentGeneration[:self.numChromosomes]
    self.nextGeneration = []

  def replace_Generational(self):
    """Replacement function that can be assigned to replaceFunc. Wholesale
    replacement of currentGeneration with nextGeneration. assumes that
    replacementSize is equal to numChromosomes; otherwise, the
    currentGeneration will shrink in size to replacementSize in size.
    """
    self.currentGeneration = self.nextGeneration[:]
    self.nextGeneration = []