~ubuntu-branches/ubuntu/saucy/deap/saucy

« back to all changes in this revision

Viewing changes to doc/knapsack.rst

  • Committer: Package Import Robot
  • Author(s): Miriam Ruiz, Jakub Wilk, Miriam Ruiz
  • Date: 2011-11-17 11:53:15 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20111117115315-k9lkwpqcbsq8n0q7
Tags: 0.7.1-1
[ Jakub Wilk ]
* Add Vcs-* fields.

[ Miriam Ruiz ]
* New Upstream Release
* Upgraded Standards-Version from 3.9.1 to 3.9.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
==============================
2
 
Individual Inheriting from Set
3
 
==============================
4
 
 
5
 
Again for this example we will use a very simple problem, the 0-1 Knapsack. The purpose of this example is to show the simplicity of EAP and the ease to inherit from anyting else than a simple list or array.
6
 
 
7
 
Many evolutionary algorithm textbooks mention that the best way to have an efficient algorithm to have a representation close the problem. Here, what can be closer to a bag than a set? Lets make our individuals inherit from the :class:`set` class. ::
8
 
 
9
 
    creator.create("Fitness", base.Fitness, weights=(-1.0, 1.0))
10
 
    creator.create("Individual", set, fitness=creator.Fitness)
11
 
    creator.create("Population", list)
12
 
 
13
 
That's it. You now have individuals that are in fact sets, they have the usual attribute :attr:`fitness` that shall contain an individual. The fitness is a minimization of the first objective (the weight of the bag) and a maximization of the second objective (the value of the bag). Finally, the last line is simply to pretty print the :class:`Population`\ 's type whith function :func:`type`. We will now create a dictionary of 100 items to map the values and weights. ::
14
 
 
15
 
    # The items' name is an integer, and value is a (weight, value) 2-uple
16
 
    items = dict([(i, (random.randint(1, 10), random.uniform(0, 100))) for i in xrange(100)])
17
 
 
18
 
We now need to initialize a population and the individuals there in. For this we will need a :class:`~eap.toolbox.Toolbox` to register our generators since sets can also be created with an input iterable. ::
19
 
 
20
 
    tools = toolbox.Toolbox()
21
 
    
22
 
    # Attribute generator
23
 
    tools.register("attr_item", random.choice, items.keys())
24
 
    
25
 
    # Structure initializers
26
 
    tools.register("individual", creator.Individual, content_init=tools.attr_item, size_init=30)
27
 
    tools.register("population", creator.Population, content_init=tools.individual, size_init=100)
28
 
 
29
 
A population is now initialized with ::
30
 
 
31
 
    pop = tools.population()
32
 
    
33
 
Voilà! The *last* thing to do is to define our evaluation function ::
34
 
 
35
 
    def evalKnapsack(individual):
36
 
        weight = 0.0
37
 
        value = 0.0
38
 
        for item in individual:
39
 
            weight += items[item][0]
40
 
            value += items[item][1]
41
 
        if len(individual) > MAX_ITEM or weight > MAX_WEIGHT:
42
 
            return 10000, 0             # Ensure overweighted bags are dominated
43
 
        return weight, value
44
 
 
45
 
Everything is ready for evolution. Ho no wait, since EAP's developpers are lazy, there is no crossover and mutation operators that can be applyed directly on sets available. Lets build some then. A crossover may be, for example, producing two child from two parents, the first child would be the intersection of the two sets and the second child their absolute difference. ::
46
 
 
47
 
    def cxSet(ind1, ind2):
48
 
        """Apply a crossover operation on input sets. The first child is the
49
 
        intersection of the two sets, the second child is the difference of the
50
 
        two sets.
51
 
        """
52
 
        temp = set(ind1)                # Used in order to keep type
53
 
        ind1 &= ind2                    # Intersection (inplace)
54
 
        ind2 ^= temp                    # Symmetric Difference (inplace)
55
 
 
56
 
And a mutation operator could randomly add or remove an element from the set input individual. ::
57
 
 
58
 
    def mutSet(individual):
59
 
        """Mutation that pops or add an element."""
60
 
        if random.random() < 0.5:
61
 
            if len(individual) > 0:     # Cannont pop from an empty set
62
 
                mutant.pop()
63
 
        else:
64
 
            mutant.add(random.choice(items.keys()))
65
 
 
66
 
From here, everything else is just as usual, register the operators in the toolbox, and use or write an algorithm. Here we will use the Mu+Lambda algorithm and the SPEA-II selection sheme. ::
67
 
 
68
 
    tools.register("evaluate", evalKnapsack)
69
 
    tools.register("mate", cxSet)
70
 
    tools.register("mutate", mutSet)
71
 
    tools.register("select", toolbox.spea2)
72
 
    
73
 
    pop = tools.population()
74
 
    hof = ParetoFront()
75
 
    
76
 
    algorithms.eaMuPlusLambda(tools, pop, 50, 100, 0.7, 0.2, 50, hof)
77
 
 
78
 
Finally, a :class:`~eap.halloffame.ParetoFront` may be used to retreive the best individuals of the evolution. The complete `Knapsack Genetic Algorithm <http://deap.googlecode.com/hg/examples/ga_onemax.py>`_ code is available.