Spaces:
Sleeping
Sleeping
Commit
·
41cab3e
1
Parent(s):
9d82fc3
Vectorize evaluation; get 5x speedup
Browse files- benchmarktimes.txt +1 -0
- eureqa.jl +32 -26
benchmarktimes.txt
CHANGED
|
@@ -1 +1,2 @@
|
|
| 1 |
The median time is TrialEstimate(3.136 s)
|
|
|
|
|
|
| 1 |
The median time is TrialEstimate(3.136 s)
|
| 2 |
+
The median time is TrialEstimate(611.157 ms)
|
eureqa.jl
CHANGED
|
@@ -44,17 +44,17 @@ mutable struct Node
|
|
| 44 |
#Holds operators, variables, constants in a tree
|
| 45 |
degree::Integer #0 for constant/variable, 1 for cos/sin, 2 for +/* etc.
|
| 46 |
val::Union{Float32, Integer} #Either const value, or enumerates variable
|
| 47 |
-
constant::Bool #false if variable
|
| 48 |
op::Function #enumerates operator (for degree=1,2)
|
| 49 |
l::Union{Node, Nothing}
|
| 50 |
r::Union{Node, Nothing}
|
| 51 |
-
|
| 52 |
Node(val::Float32) = new(0, val, true, id, nothing, nothing)
|
| 53 |
Node(val::Integer) = new(0, val, false, id, nothing, nothing)
|
| 54 |
Node(op, l::Node) = new(1, 0.0f0, false, op, l, nothing)
|
| 55 |
Node(op, l::Union{Float32, Integer}) = new(1, 0.0f0, false, op, Node(l), nothing)
|
| 56 |
Node(op, l::Node, r::Node) = new(2, 0.0f0, false, op, l, r)
|
| 57 |
-
|
| 58 |
#Allow to pass the leaf value without additional node call:
|
| 59 |
Node(op, l::Union{Float32, Integer}, r::Node) = new(2, 0.0f0, false, op, Node(l), r)
|
| 60 |
Node(op, l::Node, r::Union{Float32, Integer}) = new(2, 0.0f0, false, op, l, Node(r))
|
|
@@ -121,15 +121,15 @@ function randomNode(tree::Node)::Node
|
|
| 121 |
if tree.degree == 2
|
| 122 |
c = countNodes(tree.r)
|
| 123 |
end
|
| 124 |
-
|
| 125 |
i = rand(1:1+b+c)
|
| 126 |
if i <= b
|
| 127 |
return randomNode(tree.l)
|
| 128 |
elseif i == b + 1
|
| 129 |
return tree
|
| 130 |
end
|
| 131 |
-
|
| 132 |
-
return randomNode(tree.r)
|
| 133 |
end
|
| 134 |
|
| 135 |
# Count the number of unary operators in the equation
|
|
@@ -193,7 +193,7 @@ function mutateConstant(
|
|
| 193 |
tree::Node, T::Float32,
|
| 194 |
probNegate::Float32=0.01f0)::Node
|
| 195 |
# T is between 0 and 1.
|
| 196 |
-
|
| 197 |
if countConstants(tree) == 0
|
| 198 |
return tree
|
| 199 |
end
|
|
@@ -201,22 +201,22 @@ function mutateConstant(
|
|
| 201 |
while node.degree != 0 || node.constant == false
|
| 202 |
node = randomNode(tree)
|
| 203 |
end
|
| 204 |
-
|
| 205 |
bottom = 0.1f0
|
| 206 |
maxChange = T + 1.0f0 + bottom
|
| 207 |
factor = maxChange^Float32(rand())
|
| 208 |
makeConstBigger = rand() > 0.5
|
| 209 |
-
|
| 210 |
-
if makeConstBigger
|
| 211 |
node.val *= factor
|
| 212 |
else
|
| 213 |
node.val /= factor
|
| 214 |
end
|
| 215 |
-
|
| 216 |
if rand() > probNegate
|
| 217 |
node.val *= -1
|
| 218 |
end
|
| 219 |
-
|
| 220 |
return tree
|
| 221 |
end
|
| 222 |
|
|
@@ -224,11 +224,18 @@ end
|
|
| 224 |
function evalTreeArray(
|
| 225 |
tree::Node,
|
| 226 |
x::Array{Float32, 2})::Array{Float32, 1}
|
| 227 |
-
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
|
| 231 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 232 |
end
|
| 233 |
|
| 234 |
# Sum of square error between two arrays
|
|
@@ -260,7 +267,7 @@ function appendRandomOp(tree::Node)::Node
|
|
| 260 |
while node.degree != 0
|
| 261 |
node = randomNode(tree)
|
| 262 |
end
|
| 263 |
-
|
| 264 |
choice = rand()
|
| 265 |
makeNewBinOp = choice < nbin/nops
|
| 266 |
if rand() > 0.5
|
|
@@ -273,7 +280,7 @@ function appendRandomOp(tree::Node)::Node
|
|
| 273 |
else
|
| 274 |
right = rand(1:nvar)
|
| 275 |
end
|
| 276 |
-
|
| 277 |
if makeNewBinOp
|
| 278 |
newnode = Node(
|
| 279 |
binops[rand(1:length(binops))],
|
|
@@ -324,14 +331,14 @@ function iterate(
|
|
| 324 |
mult::Float32=0.1f0
|
| 325 |
)::Node
|
| 326 |
prev = deepcopy(tree)
|
| 327 |
-
|
| 328 |
mutationChoice = rand()
|
| 329 |
weight_for_constant = min(8, countConstants(tree))
|
| 330 |
weights = [weight_for_constant, 1, 1, 1, 2]
|
| 331 |
weights /= sum(weights)
|
| 332 |
cweights = cumsum(weights)
|
| 333 |
n = countNodes(tree)
|
| 334 |
-
|
| 335 |
if mutationChoice < cweights[1]
|
| 336 |
tree = mutateConstant(tree, T)
|
| 337 |
elseif mutationChoice < cweights[2]
|
|
@@ -343,7 +350,7 @@ function iterate(
|
|
| 343 |
else
|
| 344 |
tree = tree
|
| 345 |
end
|
| 346 |
-
|
| 347 |
try
|
| 348 |
beforeLoss = scoreFunc(prev, X, y, parsimony=mult)
|
| 349 |
afterLoss = scoreFunc(tree, X, y, parsimony=mult)
|
|
@@ -381,7 +388,7 @@ mutable struct PopMember
|
|
| 381 |
tree::Node
|
| 382 |
score::Float32
|
| 383 |
birth::Int32
|
| 384 |
-
|
| 385 |
PopMember(t) = new(t, scoreFunc(t, X, y, parsimony=parsimony), round(Int32, 1e3*(time()-1.6e9))
|
| 386 |
)
|
| 387 |
end
|
|
@@ -391,11 +398,11 @@ end
|
|
| 391 |
mutable struct Population
|
| 392 |
members::Array{PopMember, 1}
|
| 393 |
n::Integer
|
| 394 |
-
|
| 395 |
Population(pop::Array{PopMember, 1}) = new(pop, size(pop)[1])
|
| 396 |
Population(npop::Integer) = new([PopMember(genRandomTree(3)) for i=1:npop], npop)
|
| 397 |
Population(npop::Integer, nlength::Integer) = new([PopMember(genRandomTree(nlength)) for i=1:npop], npop)
|
| 398 |
-
|
| 399 |
end
|
| 400 |
|
| 401 |
# Sample 10 random members of the population, and make a new one
|
|
@@ -465,4 +472,3 @@ function run(
|
|
| 465 |
end
|
| 466 |
return pop
|
| 467 |
end
|
| 468 |
-
|
|
|
|
| 44 |
#Holds operators, variables, constants in a tree
|
| 45 |
degree::Integer #0 for constant/variable, 1 for cos/sin, 2 for +/* etc.
|
| 46 |
val::Union{Float32, Integer} #Either const value, or enumerates variable
|
| 47 |
+
constant::Bool #false if variable
|
| 48 |
op::Function #enumerates operator (for degree=1,2)
|
| 49 |
l::Union{Node, Nothing}
|
| 50 |
r::Union{Node, Nothing}
|
| 51 |
+
|
| 52 |
Node(val::Float32) = new(0, val, true, id, nothing, nothing)
|
| 53 |
Node(val::Integer) = new(0, val, false, id, nothing, nothing)
|
| 54 |
Node(op, l::Node) = new(1, 0.0f0, false, op, l, nothing)
|
| 55 |
Node(op, l::Union{Float32, Integer}) = new(1, 0.0f0, false, op, Node(l), nothing)
|
| 56 |
Node(op, l::Node, r::Node) = new(2, 0.0f0, false, op, l, r)
|
| 57 |
+
|
| 58 |
#Allow to pass the leaf value without additional node call:
|
| 59 |
Node(op, l::Union{Float32, Integer}, r::Node) = new(2, 0.0f0, false, op, Node(l), r)
|
| 60 |
Node(op, l::Node, r::Union{Float32, Integer}) = new(2, 0.0f0, false, op, l, Node(r))
|
|
|
|
| 121 |
if tree.degree == 2
|
| 122 |
c = countNodes(tree.r)
|
| 123 |
end
|
| 124 |
+
|
| 125 |
i = rand(1:1+b+c)
|
| 126 |
if i <= b
|
| 127 |
return randomNode(tree.l)
|
| 128 |
elseif i == b + 1
|
| 129 |
return tree
|
| 130 |
end
|
| 131 |
+
|
| 132 |
+
return randomNode(tree.r)
|
| 133 |
end
|
| 134 |
|
| 135 |
# Count the number of unary operators in the equation
|
|
|
|
| 193 |
tree::Node, T::Float32,
|
| 194 |
probNegate::Float32=0.01f0)::Node
|
| 195 |
# T is between 0 and 1.
|
| 196 |
+
|
| 197 |
if countConstants(tree) == 0
|
| 198 |
return tree
|
| 199 |
end
|
|
|
|
| 201 |
while node.degree != 0 || node.constant == false
|
| 202 |
node = randomNode(tree)
|
| 203 |
end
|
| 204 |
+
|
| 205 |
bottom = 0.1f0
|
| 206 |
maxChange = T + 1.0f0 + bottom
|
| 207 |
factor = maxChange^Float32(rand())
|
| 208 |
makeConstBigger = rand() > 0.5
|
| 209 |
+
|
| 210 |
+
if makeConstBigger
|
| 211 |
node.val *= factor
|
| 212 |
else
|
| 213 |
node.val /= factor
|
| 214 |
end
|
| 215 |
+
|
| 216 |
if rand() > probNegate
|
| 217 |
node.val *= -1
|
| 218 |
end
|
| 219 |
+
|
| 220 |
return tree
|
| 221 |
end
|
| 222 |
|
|
|
|
| 224 |
function evalTreeArray(
|
| 225 |
tree::Node,
|
| 226 |
x::Array{Float32, 2})::Array{Float32, 1}
|
| 227 |
+
len = ones(size(x))[2]
|
| 228 |
+
if tree.degree == 0
|
| 229 |
+
if tree.constant
|
| 230 |
+
return ones(Float32, len) .* tree.val
|
| 231 |
+
else
|
| 232 |
+
return ones(Float32, len) .* x[:, tree.val]
|
| 233 |
+
end
|
| 234 |
+
elseif tree.degree == 1
|
| 235 |
+
return tree.op.(evalTree(tree.l, x))
|
| 236 |
+
else
|
| 237 |
+
return tree.op.(evalTree(tree.l, x), evalTree(tree.r, x))
|
| 238 |
+
end
|
| 239 |
end
|
| 240 |
|
| 241 |
# Sum of square error between two arrays
|
|
|
|
| 267 |
while node.degree != 0
|
| 268 |
node = randomNode(tree)
|
| 269 |
end
|
| 270 |
+
|
| 271 |
choice = rand()
|
| 272 |
makeNewBinOp = choice < nbin/nops
|
| 273 |
if rand() > 0.5
|
|
|
|
| 280 |
else
|
| 281 |
right = rand(1:nvar)
|
| 282 |
end
|
| 283 |
+
|
| 284 |
if makeNewBinOp
|
| 285 |
newnode = Node(
|
| 286 |
binops[rand(1:length(binops))],
|
|
|
|
| 331 |
mult::Float32=0.1f0
|
| 332 |
)::Node
|
| 333 |
prev = deepcopy(tree)
|
| 334 |
+
|
| 335 |
mutationChoice = rand()
|
| 336 |
weight_for_constant = min(8, countConstants(tree))
|
| 337 |
weights = [weight_for_constant, 1, 1, 1, 2]
|
| 338 |
weights /= sum(weights)
|
| 339 |
cweights = cumsum(weights)
|
| 340 |
n = countNodes(tree)
|
| 341 |
+
|
| 342 |
if mutationChoice < cweights[1]
|
| 343 |
tree = mutateConstant(tree, T)
|
| 344 |
elseif mutationChoice < cweights[2]
|
|
|
|
| 350 |
else
|
| 351 |
tree = tree
|
| 352 |
end
|
| 353 |
+
|
| 354 |
try
|
| 355 |
beforeLoss = scoreFunc(prev, X, y, parsimony=mult)
|
| 356 |
afterLoss = scoreFunc(tree, X, y, parsimony=mult)
|
|
|
|
| 388 |
tree::Node
|
| 389 |
score::Float32
|
| 390 |
birth::Int32
|
| 391 |
+
|
| 392 |
PopMember(t) = new(t, scoreFunc(t, X, y, parsimony=parsimony), round(Int32, 1e3*(time()-1.6e9))
|
| 393 |
)
|
| 394 |
end
|
|
|
|
| 398 |
mutable struct Population
|
| 399 |
members::Array{PopMember, 1}
|
| 400 |
n::Integer
|
| 401 |
+
|
| 402 |
Population(pop::Array{PopMember, 1}) = new(pop, size(pop)[1])
|
| 403 |
Population(npop::Integer) = new([PopMember(genRandomTree(3)) for i=1:npop], npop)
|
| 404 |
Population(npop::Integer, nlength::Integer) = new([PopMember(genRandomTree(nlength)) for i=1:npop], npop)
|
| 405 |
+
|
| 406 |
end
|
| 407 |
|
| 408 |
# Sample 10 random members of the population, and make a new one
|
|
|
|
| 472 |
end
|
| 473 |
return pop
|
| 474 |
end
|
|
|