-2

In a genetic algorithm I have a list indis (population) of candidate solutions represented by objects of type indi. To make the selection straight forward, I want to sort these individuals by a fitness value. Once sorted they should have a new index representing their fitness.

indi.getFitness()  # Returns the fitness.
indi.setId(index)  # sets the index

My initial approach is insufficient, as it doesn't include the sorting:

idx=0
for indi in self.indis: 
    indi.setId(idx)
    idx += 1

Question is: how can I sort by fitness and re-index to make the best solution index 0?

Oliver Prislan
  • 320
  • 4
  • 12
  • 3
    No, it can't. `setId` alters its invoking object; a comprehension is intended to return a collection of values. Writing a comprehension *specifically* for side effects is *uuuuglyy*. Perhaps you want the `map` method -- see any tutorial on `map`. – Prune Oct 10 '20 at 17:25
  • You changed the question significantly after I posted my answer. That's not cool, although I'm not too bothered. If you want to change the scope, you should ask a new question instead, although it's already been asked: [How to sort a list of objects based on an attribute of the objects?](https://stackoverflow.com/q/403421/4518341) – wjandrea Nov 19 '20 at 22:09
  • @wjandera, I'm sorry - they blocked me for the reason, that my questions weren't clear, so I tried the best to rephrase the question to be more specific - nevertheless your contribution was valuable thank you! – Oliver Prislan Nov 20 '20 at 15:30

2 Answers2

2

No, don't use a comprehension for side-effects.

However, you can make it cleaner with enumerate:

for idx, indi in enumerate(self.indis):
    indi.setId(idx)
wjandrea
  • 28,235
  • 9
  • 60
  • 81
0

As lists come with the build-in sort method, one can use a lambda function calling the fitness method getFitness(). In this case it is important to use the reverse=True option as highest fitness mean lowest cost. The re-indexing is implemented as suggested by wjandrea.

def sortByFitness(self):        # sorted population for single generation
    # highest fitness has lowest cost
    self.indis.sort(key=lambda x: x.getFitness(), reverse=True)
    for idx, indi in enumerate(self.indis):
        indi.setId(idx)
wjandrea
  • 28,235
  • 9
  • 60
  • 81
Oliver Prislan
  • 320
  • 4
  • 12