0

I'm trying to get a better handle on DEAP. I want to make a genetic algorithm that has words as individuals as a population and it maximizes this by checking how far in distance(read: spelling) these words are from a given "maximal word". This is what I have done so far following examples in the documentation

import random
from randomwordgenerator import randomwordgenerator

from deap import base
from deap import creator
from deap import tools

creator.create("FitnessMax", base.Fitness, weights=("hot",))
creator.create("Individual", str, fitness=creator.FitnessMax)

toolbox = base.Toolbox()
toolbox.register("attr_str", randomwordgenerator.generate_random_words)
toolbox.register("individual", tools.initRepeat, creator.Individual,
                 toolbox.attr_str, n=1)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)

ind = toolbox.individual()
print(ind)

where I get confused is when I print(ind) I get this output

<generator object initRepeat.<locals>.<genexpr> at 0x10407d888>

When I change the code to the example code however(seen below)

import random

from deap import base
from deap import creator
from deap import tools

IND_SIZE = 5

creator.create("FitnessMin", base.Fitness, weights=(-1.0, -1.0))
creator.create("Individual", list, fitness=creator.FitnessMin)

toolbox = base.Toolbox()
toolbox.register("attr_float", random.random)
toolbox.register("individual", tools.initRepeat, creator.Individual,
                 toolbox.attr_float, n=IND_SIZE)

ind1 = toolbox.individual()
print(ind1)

this is the output

[0.6047278872004169, 0.8976450330325899, 0.9795210255969901, 0.5752663675034192, 0.8511975930513275]

I'm really confused as to why my example doesn't just print a string, can anyone glean some insight into this? Unfortunately they don't have examples of using strings as individuals so I'm trying to debug it on my own but am having a tough time. Any help is appreciated

sf8193
  • 575
  • 1
  • 6
  • 25

1 Answers1

2

After much debate, here is the explanation as to why it will not work. The Individual is declared using the base class str, which is fine for your intent and purposes. However, when you register the individual method in the toolbox, you then use tools.initRepeat which provides a generator as an argument to the container. For individuals based on the list class this would be fine since the generator is then evaluated and stored within the list. However, since yours is based on str, the implicit conversion performed by python simply returns the string "", but does not go through the content of the generator to populate your individual. Since it seems that the tools provided by DEAP are not suited for your problem, I would suggest you write you own script for generating a population and/or individual. The following should answer your constraints:

from randomwordgenerator.randomwordgenerator import generate_random_words

from deap import base
from deap import creator
from deap import tools

POP_SIZE = 10

creator.create("FitnessMax", base.Fitness, weights=(1,))
creator.create("Individual", str, fitness=creator.FitnessMax)

toolbox = base.Toolbox()
toolbox.register("attr_str", generate_random_words, n=1)

ind = creator.Individual(toolbox.attr_str())
pop = [creator.Individual(toolbox.attr_str()) for _ in range(POP_SIZE)]

print(ind)
print(pop)

This will generate a population as a list of random words, which you can then evaluate.

domochevski
  • 553
  • 5
  • 13
  • I actually want each individual to be a word, in my case this would be a string, rather than a list of words. the "Individual" function calls "attr_str" which creates 1 random word – sf8193 Jul 21 '18 at 01:02
  • Actually, I tried this and it worked, but I am confused by it because randomwordgenerator.generate_random_words seems to return a string – sf8193 Jul 21 '18 at 01:41
  • 1
    @Sam If you want the individual to be a simple world, then the base class should be `str`, but you should not use `tools.initRepeat` to initialize the individual. Instead simply calling `randomwordgenerator.generate_random_words` should do the trick. – domochevski Jul 21 '18 at 01:46
  • i'm not sure I understand. do you mean `toolbox.register("individual", randomwordgenerator.generate_random_words, creator.Individual)` ? because for some reason this then complains about arguments too generate_random_words , I think because i'm passing creator.Individual as an argument into it – sf8193 Jul 21 '18 at 02:02
  • @Sam I edited the answer to include a way to build an individual based on the `str` class rather than having to deal with a list. Hope this helps. – domochevski Jul 22 '18 at 17:46
  • this does help, if there is anyway you could help with this as well I would greatly appreciate it.[question on initRepeat](https://stackoverflow.com/questions/51466649/python-deap-library-how-to-access-initrepeat-mapping) – sf8193 Jul 22 '18 at 18:40
  • The code you edited does not work. If you run it you don't get a random word with a value for fitness, rather you just get what looks like a pointer to a function. Output looks like this `functools.partial()` – sf8193 Jul 22 '18 at 21:14
  • @Sam Well that's what you get for being lazy. I didn't want to install the randomwordgenerator module, so did test the code. You have to actually call the `attr_str` function to get what you want. Edited the answer. It should work now. – domochevski Jul 23 '18 at 19:17