AutonLabTruth commited on
Commit
4fca5d2
1 Parent(s): 921343f

Refactored iterate to simulated annealing

Browse files
Files changed (2) hide show
  1. julia/simulatedAnnealing.jl +125 -0
  2. julia/sr.jl +1 -128
julia/simulatedAnnealing.jl ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Go through one simulated annealing mutation cycle
2
+ # exp(-delta/T) defines probability of accepting a change
3
+ function iterate(member::PopMember, T::Float32, curmaxsize::Integer, frequencyComplexity::Array{Float32, 1})::PopMember
4
+ prev = member.tree
5
+ tree = prev
6
+ #TODO - reconsider this
7
+ if batching
8
+ beforeLoss = scoreFuncBatch(prev)
9
+ else
10
+ beforeLoss = member.score
11
+ end
12
+
13
+ mutationChoice = rand()
14
+ #More constants => more likely to do constant mutation
15
+ weightAdjustmentMutateConstant = min(8, countConstants(prev))/8.0
16
+ cur_weights = copy(mutationWeights) .* 1.0
17
+ cur_weights[1] *= weightAdjustmentMutateConstant
18
+ n = countNodes(prev)
19
+ depth = countDepth(prev)
20
+
21
+ # If equation too big, don't add new operators
22
+ if n >= curmaxsize || depth >= maxdepth
23
+ cur_weights[3] = 0.0
24
+ cur_weights[4] = 0.0
25
+ end
26
+ cur_weights /= sum(cur_weights)
27
+ cweights = cumsum(cur_weights)
28
+
29
+ successful_mutation = false
30
+ #TODO: Currently we dont take this \/ into account
31
+ is_success_always_possible = true
32
+ attempts = 0
33
+ max_attempts = 10
34
+
35
+ #############################################
36
+ # Mutations
37
+ #############################################
38
+ while (!successful_mutation) && attempts < max_attempts
39
+ tree = copyNode(prev)
40
+ successful_mutation = true
41
+ if mutationChoice < cweights[1]
42
+ tree = mutateConstant(tree, T)
43
+
44
+ is_success_always_possible = true
45
+ # Mutating a constant shouldn't invalidate an already-valid function
46
+
47
+ elseif mutationChoice < cweights[2]
48
+ tree = mutateOperator(tree)
49
+
50
+ is_success_always_possible = true
51
+ # Can always mutate to the same operator
52
+
53
+ elseif mutationChoice < cweights[3]
54
+ if rand() < 0.5
55
+ tree = appendRandomOp(tree)
56
+ else
57
+ tree = prependRandomOp(tree)
58
+ end
59
+ is_success_always_possible = false
60
+ # Can potentially have a situation without success
61
+ elseif mutationChoice < cweights[4]
62
+ tree = insertRandomOp(tree)
63
+ is_success_always_possible = false
64
+ elseif mutationChoice < cweights[5]
65
+ tree = deleteRandomOp(tree)
66
+ is_success_always_possible = true
67
+ elseif mutationChoice < cweights[6]
68
+ tree = simplifyTree(tree) # Sometimes we simplify tree
69
+ tree = combineOperators(tree) # See if repeated constants at outer levels
70
+ return PopMember(tree, beforeLoss)
71
+
72
+ is_success_always_possible = true
73
+ # Simplification shouldn't hurt complexity; unless some non-symmetric constraint
74
+ # to commutative operator...
75
+
76
+ elseif mutationChoice < cweights[7]
77
+ tree = genRandomTree(5) # Sometimes we generate a new tree completely tree
78
+
79
+ is_success_always_possible = true
80
+ else # no mutation applied
81
+ return PopMember(tree, beforeLoss)
82
+ end
83
+
84
+ # Check for illegal equations
85
+ for i=1:nbin
86
+ if successful_mutation && flagBinOperatorComplexity(tree, i)
87
+ successful_mutation = false
88
+ end
89
+ end
90
+ for i=1:nuna
91
+ if successful_mutation && flagUnaOperatorComplexity(tree, i)
92
+ successful_mutation = false
93
+ end
94
+ end
95
+
96
+ attempts += 1
97
+ end
98
+ #############################################
99
+
100
+ if !successful_mutation
101
+ return PopMember(copyNode(prev), beforeLoss)
102
+ end
103
+
104
+ if batching
105
+ afterLoss = scoreFuncBatch(tree)
106
+ else
107
+ afterLoss = scoreFunc(tree)
108
+ end
109
+
110
+ if annealing
111
+ delta = afterLoss - beforeLoss
112
+ probChange = exp(-delta/(T*alpha))
113
+ if useFrequency
114
+ oldSize = countNodes(prev)
115
+ newSize = countNodes(tree)
116
+ probChange *= frequencyComplexity[oldSize] / frequencyComplexity[newSize]
117
+ end
118
+
119
+ return_unaltered = (isnan(afterLoss) || probChange < rand())
120
+ if return_unaltered
121
+ return PopMember(copyNode(prev), beforeLoss)
122
+ end
123
+ end
124
+ return PopMember(tree, afterLoss)
125
+ end
julia/sr.jl CHANGED
@@ -33,138 +33,11 @@ include("halloffame.jl")
33
 
34
  include("complexityChecks.jl")
35
 
36
-
37
- # Go through one simulated annealing mutation cycle
38
- # exp(-delta/T) defines probability of accepting a change
39
- function iterate(member::PopMember, T::Float32, curmaxsize::Integer, frequencyComplexity::Array{Float32, 1})::PopMember
40
- prev = member.tree
41
- tree = prev
42
- #TODO - reconsider this
43
- if batching
44
- beforeLoss = scoreFuncBatch(prev)
45
- else
46
- beforeLoss = member.score
47
- end
48
-
49
- mutationChoice = rand()
50
- #More constants => more likely to do constant mutation
51
- weightAdjustmentMutateConstant = min(8, countConstants(prev))/8.0
52
- cur_weights = copy(mutationWeights) .* 1.0
53
- cur_weights[1] *= weightAdjustmentMutateConstant
54
- n = countNodes(prev)
55
- depth = countDepth(prev)
56
-
57
- # If equation too big, don't add new operators
58
- if n >= curmaxsize || depth >= maxdepth
59
- cur_weights[3] = 0.0
60
- cur_weights[4] = 0.0
61
- end
62
- cur_weights /= sum(cur_weights)
63
- cweights = cumsum(cur_weights)
64
-
65
- successful_mutation = false
66
- #TODO: Currently we dont take this \/ into account
67
- is_success_always_possible = true
68
- attempts = 0
69
- max_attempts = 10
70
-
71
- #############################################
72
- # Mutations
73
- #############################################
74
- while (!successful_mutation) && attempts < max_attempts
75
- tree = copyNode(prev)
76
- successful_mutation = true
77
- if mutationChoice < cweights[1]
78
- tree = mutateConstant(tree, T)
79
-
80
- is_success_always_possible = true
81
- # Mutating a constant shouldn't invalidate an already-valid function
82
-
83
- elseif mutationChoice < cweights[2]
84
- tree = mutateOperator(tree)
85
-
86
- is_success_always_possible = true
87
- # Can always mutate to the same operator
88
-
89
- elseif mutationChoice < cweights[3]
90
- if rand() < 0.5
91
- tree = appendRandomOp(tree)
92
- else
93
- tree = prependRandomOp(tree)
94
- end
95
- is_success_always_possible = false
96
- # Can potentially have a situation without success
97
- elseif mutationChoice < cweights[4]
98
- tree = insertRandomOp(tree)
99
- is_success_always_possible = false
100
- elseif mutationChoice < cweights[5]
101
- tree = deleteRandomOp(tree)
102
- is_success_always_possible = true
103
- elseif mutationChoice < cweights[6]
104
- tree = simplifyTree(tree) # Sometimes we simplify tree
105
- tree = combineOperators(tree) # See if repeated constants at outer levels
106
- return PopMember(tree, beforeLoss)
107
-
108
- is_success_always_possible = true
109
- # Simplification shouldn't hurt complexity; unless some non-symmetric constraint
110
- # to commutative operator...
111
-
112
- elseif mutationChoice < cweights[7]
113
- tree = genRandomTree(5) # Sometimes we generate a new tree completely tree
114
-
115
- is_success_always_possible = true
116
- else # no mutation applied
117
- return PopMember(tree, beforeLoss)
118
- end
119
-
120
- # Check for illegal equations
121
- for i=1:nbin
122
- if successful_mutation && flagBinOperatorComplexity(tree, i)
123
- successful_mutation = false
124
- end
125
- end
126
- for i=1:nuna
127
- if successful_mutation && flagUnaOperatorComplexity(tree, i)
128
- successful_mutation = false
129
- end
130
- end
131
-
132
- attempts += 1
133
- end
134
- #############################################
135
-
136
- if !successful_mutation
137
- return PopMember(copyNode(prev), beforeLoss)
138
- end
139
-
140
- if batching
141
- afterLoss = scoreFuncBatch(tree)
142
- else
143
- afterLoss = scoreFunc(tree)
144
- end
145
-
146
- if annealing
147
- delta = afterLoss - beforeLoss
148
- probChange = exp(-delta/(T*alpha))
149
- if useFrequency
150
- oldSize = countNodes(prev)
151
- newSize = countNodes(tree)
152
- probChange *= frequencyComplexity[oldSize] / frequencyComplexity[newSize]
153
- end
154
-
155
- return_unaltered = (isnan(afterLoss) || probChange < rand())
156
- if return_unaltered
157
- return PopMember(copyNode(prev), beforeLoss)
158
- end
159
- end
160
- return PopMember(tree, afterLoss)
161
- end
162
-
163
 
164
  include("Population.jl")
165
 
166
 
167
-
168
  # Pass through the population several times, replacing the oldest
169
  # with the fittest of a small subsample
170
  function regEvolCycle(pop::Population, T::Float32, curmaxsize::Integer,
 
33
 
34
  include("complexityChecks.jl")
35
 
36
+ include("simulatedAnnealing.jl")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
  include("Population.jl")
39
 
40
 
 
41
  # Pass through the population several times, replacing the oldest
42
  # with the fittest of a small subsample
43
  function regEvolCycle(pop::Population, T::Float32, curmaxsize::Integer,