Using DEAP's GP tools to evolve social networks

87 views
Skip to first unread message

Rodolphe Coulon

unread,
Aug 18, 2014, 6:47:18 PM8/18/14
to deap-...@googlegroups.com
Hello all,

A couple of months ago, I've been working on a GA to evolve networks to fit a multi-objective fitness. Thanks to you guy, I manage to get it running.

Here's the code: https://gist.github.com/cmd-ntrf/7848947

Unfortunately, even after hundreds of generations, the found solutions were less than satisfactory. Digging a little, I now understand that using a string of bits to code my individuals is probably not a good idea, since mutation (flip bit) and cross-over (two-point) on a bit string don't acknowledge the important structural features of networks.

As this Stack Overflow discussion (http://stackoverflow.com/questions/3160619/applying-crossover-and-mutation-to-a-graph-genetic-algorithm/3160709#comment39529178_3160709) suggests, cross-over and mutation should be done on sub-networks to really make sense, and GP should actually provide a better approach to mating and mutating networks.

Unlike GP, my situation (individuals are social networks, undirected, let's say, and are evaluated by networkx metrics) does not involve input or output... And trees are not *exactly* graphs... can DEAP's GP be used in this context anyway?

If so, I'd have a few technical questions, but I'll spear you for now :)

Thanks!!!

Rodolphe Coulon

unread,
Aug 19, 2014, 6:28:47 PM8/19/14
to deap-...@googlegroups.com
Hello all,


I'm changing my code to call a MyContainer class for mutating and mating my individuals exactly as I want. Although, this is important, I need DEAP to do the rest of the GA stuff.

This is my implementation so far, I keep getting "unbound method initIndividual() must be called with MyContainer instance as first argument (got type instance instead)" errors:


Is there anything obviously wrong with it?

Cheers!

Rodolphe Coulon

unread,
Aug 19, 2014, 6:56:50 PM8/19/14
to deap-...@googlegroups.com
Sorry, this is confusing, but as you saw, I gave up on GP. My graphs don't have input or outputs...

François-Michel De Rainville

unread,
Aug 20, 2014, 10:01:13 AM8/20/14
to deap-...@googlegroups.com
What your are currently doing is :

class MyClass(object):
    def mutate(self):
        # some mutation
        pass

MyClass.mutation()

This code is invalid Python code. You call a instance method like you would call a static method. This would be the right way to call your function.

my_instance = MyClass()
my_instance.mutate()

DEAP expect functions not methods see this. You must take the mutation and crossover operations out of you containre. What you can do is to have public attributes in your container and retreive them in you mutation/crossover operations.

I hope it helps,
François-Michel

Rodolphe Coulon

unread,
Aug 20, 2014, 12:51:54 PM8/20/14
to deap-...@googlegroups.com
Great, thank you so much François-Michel (especially since this was a Python error, unrelated to DEAP...),

I updated my Gist:
https://gist.github.com/rodolpheg/7a31e3d4a8344af2309f

Where I now have an error in utils.py:
"n = int(math.floor(1 + math.sqrt(1 + 8 * len(ind))/2))
TypeError: object of type 'MyContainer' has no len()"

I guess I don't really understand what's being passed to "my_instance.mutation" by "pop = algorithms.varAnd(pop, toolbox, .05, .5)". In fact, what is actually being passed for mating and mutation? An object containing all individuals? I currently use the function mutation(ind,pb) as if I was dealing with one individual to mutate...

I can't find anything that could help me understand this in the doc, sorry if I didn't look hard enough... :)

Thanks!!!

François-Michel De Rainville

unread,
Aug 20, 2014, 1:12:12 PM8/20/14
to deap-...@googlegroups.com
For the current error, your class does not define any __len__ method.

For the last error I was wrong. You can register the class method but be very carefull as what is going to be passed as self argument!! You should revert to what you had with MyContainer.mutating if you find it suits your need.

The prefered way for mutations and crossovers is to register function not methods in the toolbox.

Cheers,
François-Michel


--
You received this message because you are subscribed to the Google Groups "deap-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to deap-users+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Rodolphe Coulon

unread,
Aug 20, 2014, 1:30:15 PM8/20/14
to deap-...@googlegroups.com
Oh alright, thanks, I think I'll stay with the updated version as it seems to work better for now.

About the len() issue though, I'm not sure to understand why len(), which is, I think, standard in Python, doesn't work once inside a class, but I'll take the question to Stack Overflow as it's not DEAP focused...

François-Michel De Rainville

unread,
Aug 20, 2014, 1:40:22 PM8/20/14
to deap-...@googlegroups.com
Here is a tutorial on class magic methods. Uder the hood the list class defines a __len__ method that gets called by the function len(). When you do len(myobject it calls myobject.__len__().

Still for you first error, I think it is necessary that you make many tests as what is passed as arguments and what is the current object that is worked on. In fact, what you are doing for variations is:

obj1 = MyContainer()

# toolbos registrations with obj1

obj2 = MyContainer()
obj3 = MyContainer()

obj1.mutating(obj2)
obj1.mating(obj2, obj3)

This, if not manipulated carefully, can produce a lot of strange behaviours!

Best regards,
François-Michel

Rodolphe Coulon

unread,
Aug 20, 2014, 2:30:38 PM8/20/14
to deap-...@googlegroups.com
Ouch, yes, that can get really messy... Well, I'll try and get the evolution running before worrying about this....

The magic method works like... a charm :D I'm learning, little by little... Cheers!

Well... I now manage to pass an individual to the custom mutation, the mutation happens, but then, I get this new error: 'array.array' object has no attribute 'fitness'. My individuals are numpy arrays, sure. Does this error have anything to do with the fact that I re-create a new individual when mutation happens, individual which would be lacking, because of the mutation operations, the fitness value its non-mutated old self had?

If so, can I just do:

def mutation(self,ind):

fitnessvalues = ind.fitness.values
        bin = ind
        #do mutation stuff to bin
        bin.fitness.values = fitnessvalues
       return bin,

This doesn't seem to work...
Reply all
Reply to author
Forward
0 new messages