Spaces:
Sleeping
Sleeping
AutonLabTruth
commited on
Commit
•
4fca5d2
1
Parent(s):
921343f
Refactored iterate to simulated annealing
Browse files- julia/simulatedAnnealing.jl +125 -0
- 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,
|