File size: 3,742 Bytes
2a2a517
cedbbde
6e5f7ce
2a2a517
5e2a70f
 
 
 
b18ab5a
5e2a70f
 
cedbbde
5e2a70f
 
a369299
c3d240e
 
 
 
 
 
311797d
c3d240e
 
 
382662a
 
cedbbde
382662a
 
5e2a70f
 
382662a
 
 
c3d240e
cedbbde
16c9195
 
 
 
cedbbde
382662a
2a2a517
382662a
cedbbde
 
5e2a70f
 
d3f2b30
 
 
 
 
5e2a70f
 
 
 
 
 
c862e70
5e2a70f
 
 
 
 
 
c862e70
5e2a70f
 
 
 
 
9c27796
382662a
5e2a70f
 
 
 
 
 
382662a
b364345
5e2a70f
 
311797d
5e2a70f
 
 
311797d
5e2a70f
 
 
6e5f7ce
9c27796
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
include("eureqa.jl")
import Optim

const nthreads = Threads.nthreads()

# List of the best members seen all time
mutable struct HallOfFame
    members::Array{PopMember, 1}
    exists::Array{Bool, 1} #Whether it has been set

    # Arranged by complexity - store one at each.
    HallOfFame() = new([PopMember(Node(1f0), 1f9) for i=1:actualMaxsize], [false for i=1:actualMaxsize])
end


function fullRun(niterations::Integer;
                npop::Integer=300,
                annealing::Bool=true,
                ncyclesperiteration::Integer=3000,
                fractionReplaced::Float32=0.1f0,
                verbosity::Integer=0,
                topn::Integer=10
               )
    debug(verbosity, "Lets try to learn (x2^2 + cos(x3)) using regularized evolution from scratch")
    debug(verbosity, "Running with $nthreads threads")
    # Generate random initial populations
    allPops = [Population(npop, 3) for j=1:nthreads]
    bestSubPops = [Population(1) for j=1:nthreads]
    # Repeat this many evolutions; we collect and migrate the best
    # each time.
    hallOfFame = HallOfFame()

    for k=1:niterations
        # Spawn threads to run indepdent evolutions, then gather them
        @inbounds Threads.@threads for i=1:nthreads
            allPops[i] = run(allPops[i], ncyclesperiteration, annealing, verbosity=verbosity)
            bestSubPops[i] = bestSubPop(allPops[i], topn=topn)
            if shouldOptimizeConstants
                for j=1:bestSubPops[i].n
                    bestSubPops[i].members[j] = optimizeConstants(bestSubPops[i].members[j])
                end
            end
        end

        # Get best 10 models from each evolution. Copy because we re-assign later.
        # bestPops = deepcopy(Population([member for pop in allPops for member in bestSubPop(pop).members]))
        bestPops = deepcopy(Population([member for pop in bestSubPops for member in pop.members]))

        #Update hall of fame
        for member in bestPops.members
            size = countNodes(member.tree)
            if member.score < hallOfFame.members[size].score
                hallOfFame.members[size] = deepcopy(member)
                hallOfFame.exists[size] = true
            end
        end

        dominating = PopMember[]
        debug(verbosity, "Hall of Fame:")
        debug(verbosity, "-----------------------------------------")
        debug(verbosity, "Complexity \t MSE \t Equation")
        for size=1:maxsize
            if hallOfFame.exists[size]
                member = hallOfFame.members[size]
                numberSmallerAndBetter = sum([member.score > hallOfFame.members[i].score for i=1:(size-1)])
                betterThanAllSmaller = (numberSmallerAndBetter == 0)
                if betterThanAllSmaller
                    debug(verbosity, "$size \t $(member.score-parsimony*size) \t $(stringTree(member.tree))")
                    push!(dominating, member)
                end
            end
        end
        debug(verbosity, "")

        # Migration
        if migration
            for j=1:nthreads
                for k in rand(1:npop, Integer(npop*fractionReplaced))
                    # Copy in case one gets used twice
                    allPops[j].members[k] = deepcopy(bestPops.members[rand(1:size(bestPops.members)[1])])
                end
            end
        end

        # Hall of fame migration
        if hofMigration && size(dominating)[1] > 0
            for j=1:nthreads
                for k in rand(1:npop, Integer(npop*fractionReplacedHof))
                    # Copy in case one gets used twice
                    allPops[j].members[k] = deepcopy(dominating[rand(1:size(dominating)[1])])
                end
            end
        end
    end
end