MilesCranmer commited on
Commit
931a410
2 Parent(s): 8f44d1a 9f27d22

Merge pull request #1 from MilesCranmer/insertionOp

Browse files

Add insertion op; improve deletion op; add new way to simplify constants

Files changed (5) hide show
  1. README.md +7 -5
  2. eureqa.jl +188 -28
  3. eureqa.py +29 -19
  4. hyperparamopt.py +1 -0
  5. operators.jl +2 -2
README.md CHANGED
@@ -59,11 +59,11 @@ which gives:
59
  ### API
60
 
61
  What follows is the API reference for running the numpy interface.
62
- Note that most parameters here
63
- have been tuned with ~1000 trials over several example
64
- equations, so you likely don't need to tune them yourself.
65
  However, you should adjust `threads`, `niterations`,
66
- `binary_operators`, `unary_operators`, and `maxsize` to your requirements.
 
67
 
68
  The program will output a pandas DataFrame containing the equations,
69
  mean square error, and complexity. It will also dump to a csv
@@ -148,7 +148,7 @@ pd.DataFrame, Results dataframe, giving complexity, MSE, and equations
148
  # TODO
149
 
150
  - [ ] Make scaling of changes to constant a hyperparameter
151
- - [ ] Update hall of fame every iteration
152
  - [ ] Calculate feature importances of future mutations, by looking at correlation between residual of model, and the features.
153
  - Store feature importances of future, and periodically update it.
154
  - [ ] Implement more parts of the original Eureqa algorithms: https://www.creativemachineslab.com/eureqa.html
@@ -162,6 +162,8 @@ pd.DataFrame, Results dataframe, giving complexity, MSE, and equations
162
  - Current most expensive operations:
163
  - [ ] Calculating the loss function - there is duplicate calculations happening.
164
  - [x] Declaration of the weights array every iteration
 
 
165
  - [x] Record very best individual in each population, and return at end.
166
  - [x] Write our own tree copy operation; deepcopy() is the slowest operation by far.
167
  - [x] Hyperparameter tune
 
59
  ### API
60
 
61
  What follows is the API reference for running the numpy interface.
62
+ You likely don't need to tune the hyperparameters yourself,
63
+ but if you would like, you can use `hyperopt.py` as an example.
 
64
  However, you should adjust `threads`, `niterations`,
65
+ `binary_operators`, `unary_operators`, and `maxsize`
66
+ to your requirements.
67
 
68
  The program will output a pandas DataFrame containing the equations,
69
  mean square error, and complexity. It will also dump to a csv
 
148
  # TODO
149
 
150
  - [ ] Make scaling of changes to constant a hyperparameter
151
+ - [ ] Update hall of fame every iteration?
152
  - [ ] Calculate feature importances of future mutations, by looking at correlation between residual of model, and the features.
153
  - Store feature importances of future, and periodically update it.
154
  - [ ] Implement more parts of the original Eureqa algorithms: https://www.creativemachineslab.com/eureqa.html
 
162
  - Current most expensive operations:
163
  - [ ] Calculating the loss function - there is duplicate calculations happening.
164
  - [x] Declaration of the weights array every iteration
165
+ - [x] Add a node at the top of a tree
166
+ - [x] Insert a node at the top of a subtree
167
  - [x] Record very best individual in each population, and return at end.
168
  - [x] Write our own tree copy operation; deepcopy() is the slowest operation by far.
169
  - [x] Hyperparameter tune
eureqa.jl CHANGED
@@ -3,6 +3,22 @@ import Optim
3
  const maxdegree = 2
4
  const actualMaxsize = maxsize + maxdegree
5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  id = (x,) -> x
7
  const nuna = size(unaops)[1]
8
  const nbin = size(binops)[1]
@@ -211,7 +227,6 @@ end
211
 
212
  # Evaluate an equation over an array of datapoints
213
  function evalTreeArray(tree::Node)::Array{Float32, 1}
214
- len = size(X)[1]
215
  if tree.degree == 0
216
  if tree.constant
217
  return ones(Float32, len) .* tree.val
@@ -225,21 +240,10 @@ function evalTreeArray(tree::Node)::Array{Float32, 1}
225
  end
226
  end
227
 
228
- # Sum of square error between two arrays
229
- function SSE(x::Array{Float32}, y::Array{Float32})::Float32
230
- diff = (x - y)
231
- return sum(diff .* diff)
232
- end
233
-
234
- # Mean of square error between two arrays
235
- function MSE(x::Array{Float32}, y::Array{Float32})::Float32
236
- return SSE(x, y)/size(x)[1]
237
- end
238
-
239
  # Score an equation
240
  function scoreFunc(tree::Node)::Float32
241
  try
242
- return MSE(evalTreeArray(tree), y) + countNodes(tree)*parsimony
243
  catch error
244
  if isa(error, DomainError)
245
  return 1f9
@@ -290,17 +294,55 @@ function appendRandomOp(tree::Node)::Node
290
  return tree
291
  end
292
 
293
- # Select a random node, and replace it an the subtree
294
- # with a variable or constant
295
- function deleteRandomOp(tree::Node)::Node
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
296
  node = randomNode(tree)
297
- # Can "delete" variable or constant too
298
- if rand() > 0.5
299
- val = Float32(randn())
 
 
 
 
 
 
 
 
300
  else
301
- val = rand(1:nvar)
 
 
 
302
  end
303
- newnode = Node(val)
304
  node.l = newnode.l
305
  node.r = newnode.r
306
  node.op = newnode.op
@@ -310,6 +352,120 @@ function deleteRandomOp(tree::Node)::Node
310
  return tree
311
  end
312
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313
 
314
  # Simplify tree
315
  function simplifyTree(tree::Node)::Node
@@ -355,12 +511,15 @@ function iterate(
355
  tree = mutateOperator(tree)
356
  elseif mutationChoice < cweights[3] && n < maxsize
357
  tree = appendRandomOp(tree)
358
- elseif mutationChoice < cweights[4]
359
- tree = deleteRandomOp(tree)
360
  elseif mutationChoice < cweights[5]
 
 
361
  tree = simplifyTree(tree) # Sometimes we simplify tree
 
362
  return tree
363
- elseif mutationChoice < cweights[6]
364
  tree = genRandomTree(5) # Sometimes we simplify tree
365
  else
366
  return tree
@@ -608,14 +767,15 @@ function fullRun(niterations::Integer;
608
  debug(verbosity, "-----------------------------------------")
609
  debug(verbosity, "Complexity \t MSE \t Equation")
610
  println(io,"Complexity|MSE|Equation")
611
- for size=1:maxsize
612
  if hallOfFame.exists[size]
613
  member = hallOfFame.members[size]
614
- numberSmallerAndBetter = sum([member.score > hallOfFame.members[i].score for i=1:(size-1)])
 
615
  betterThanAllSmaller = (numberSmallerAndBetter == 0)
616
  if betterThanAllSmaller
617
- debug(verbosity, "$size \t $(member.score-parsimony*size) \t $(stringTree(member.tree))")
618
- println(io, "$size|$(member.score-parsimony*size)|$(stringTree(member.tree))")
619
  push!(dominating, member)
620
  end
621
  end
 
3
  const maxdegree = 2
4
  const actualMaxsize = maxsize + maxdegree
5
 
6
+
7
+ # Sum of square error between two arrays
8
+ function SSE(x::Array{Float32}, y::Array{Float32})::Float32
9
+ diff = (x - y)
10
+ return sum(diff .* diff)
11
+ end
12
+
13
+ # Mean of square error between two arrays
14
+ function MSE(x::Array{Float32}, y::Array{Float32})::Float32
15
+ return SSE(x, y)/size(x)[1]
16
+ end
17
+
18
+ const len = size(X)[1]
19
+ const avgy = sum(y)/len
20
+ const baselineSSE = SSE(y, convert(Array{Float32, 1}, ones(len) .* avgy))
21
+
22
  id = (x,) -> x
23
  const nuna = size(unaops)[1]
24
  const nbin = size(binops)[1]
 
227
 
228
  # Evaluate an equation over an array of datapoints
229
  function evalTreeArray(tree::Node)::Array{Float32, 1}
 
230
  if tree.degree == 0
231
  if tree.constant
232
  return ones(Float32, len) .* tree.val
 
240
  end
241
  end
242
 
 
 
 
 
 
 
 
 
 
 
 
243
  # Score an equation
244
  function scoreFunc(tree::Node)::Float32
245
  try
246
+ return SSE(evalTreeArray(tree), y)/baselineSSE + countNodes(tree)*parsimony
247
  catch error
248
  if isa(error, DomainError)
249
  return 1f9
 
294
  return tree
295
  end
296
 
297
+ # Add random node to the top of a tree
298
+ function popRandomOp(tree::Node)::Node
299
+ node = tree
300
+ choice = rand()
301
+ makeNewBinOp = choice < nbin/nops
302
+ left = tree
303
+
304
+ if makeNewBinOp
305
+ right = randomConstantNode()
306
+ newnode = Node(
307
+ binops[rand(1:length(binops))],
308
+ left,
309
+ right
310
+ )
311
+ else
312
+ newnode = Node(
313
+ unaops[rand(1:length(unaops))],
314
+ left
315
+ )
316
+ end
317
+ node.l = newnode.l
318
+ node.r = newnode.r
319
+ node.op = newnode.op
320
+ node.degree = newnode.degree
321
+ node.val = newnode.val
322
+ node.constant = newnode.constant
323
+ return node
324
+ end
325
+
326
+ # Insert random node
327
+ function insertRandomOp(tree::Node)::Node
328
  node = randomNode(tree)
329
+ choice = rand()
330
+ makeNewBinOp = choice < nbin/nops
331
+ left = copyNode(node)
332
+
333
+ if makeNewBinOp
334
+ right = randomConstantNode()
335
+ newnode = Node(
336
+ binops[rand(1:length(binops))],
337
+ left,
338
+ right
339
+ )
340
  else
341
+ newnode = Node(
342
+ unaops[rand(1:length(unaops))],
343
+ left
344
+ )
345
  end
 
346
  node.l = newnode.l
347
  node.r = newnode.r
348
  node.op = newnode.op
 
352
  return tree
353
  end
354
 
355
+ function randomConstantNode()::Node
356
+ if rand() > 0.5
357
+ val = Float32(randn())
358
+ else
359
+ val = rand(1:nvar)
360
+ end
361
+ newnode = Node(val)
362
+ return newnode
363
+ end
364
+
365
+ # Return a random node from the tree with parent
366
+ function randomNodeAndParent(tree::Node, parent::Union{Node, Nothing})::Tuple{Node, Union{Node, Nothing}}
367
+ if tree.degree == 0
368
+ return tree, parent
369
+ end
370
+ a = countNodes(tree)
371
+ b = 0
372
+ c = 0
373
+ if tree.degree >= 1
374
+ b = countNodes(tree.l)
375
+ end
376
+ if tree.degree == 2
377
+ c = countNodes(tree.r)
378
+ end
379
+
380
+ i = rand(1:1+b+c)
381
+ if i <= b
382
+ return randomNodeAndParent(tree.l, tree)
383
+ elseif i == b + 1
384
+ return tree, parent
385
+ end
386
+
387
+ return randomNodeAndParent(tree.r, tree)
388
+ end
389
+
390
+ # Select a random node, and replace it an the subtree
391
+ # with a variable or constant
392
+ function deleteRandomOp(tree::Node)::Node
393
+ node, parent = randomNodeAndParent(tree, nothing)
394
+ isroot = (parent == nothing)
395
+
396
+ if node.degree == 0
397
+ # Replace with new constant
398
+ newnode = randomConstantNode()
399
+ node.l = newnode.l
400
+ node.r = newnode.r
401
+ node.op = newnode.op
402
+ node.degree = newnode.degree
403
+ node.val = newnode.val
404
+ node.constant = newnode.constant
405
+ elseif node.degree == 1
406
+ # Join one of the children with the parent
407
+ if isroot
408
+ return node.l
409
+ elseif parent.l == node
410
+ parent.l = node.l
411
+ else
412
+ parent.r = node.l
413
+ end
414
+ else
415
+ # Join one of the children with the parent
416
+ if rand() < 0.5
417
+ if isroot
418
+ return node.l
419
+ elseif parent.l == node
420
+ parent.l = node.l
421
+ else
422
+ parent.r = node.l
423
+ end
424
+ else
425
+ if isroot
426
+ return node.r
427
+ elseif parent.l == node
428
+ parent.l = node.r
429
+ else
430
+ parent.r = node.r
431
+ end
432
+ end
433
+ end
434
+ return tree
435
+ end
436
+
437
+ # Simplify tree
438
+ function combineOperators(tree::Node)::Node
439
+ # (const (+*) const) already accounted for
440
+ # ((const + var) + const) => (const + var)
441
+ # ((const * var) * const) => (const * var)
442
+ # (anything commutative!)
443
+ if tree.degree == 2 && (tree.op == plus || tree.op == mult)
444
+ op = tree.op
445
+ if tree.l.constant || tree.r.constant
446
+ # Put the constant in r
447
+ if tree.l.constant
448
+ tmp = tree.r
449
+ tree.r = tree.l
450
+ tree.l = tmp
451
+ end
452
+ topconstant = tree.r.val
453
+ # Simplify down first
454
+ tree.l = combineOperators(tree.l)
455
+ below = tree.l
456
+ if below.degree == 2 && below.op == op
457
+ if below.l.constant
458
+ tree = below
459
+ tree.l.val = op(tree.l.val, topconstant)
460
+ elseif below.r.constant
461
+ tree = below
462
+ tree.r.val = op(tree.r.val, topconstant)
463
+ end
464
+ end
465
+ end
466
+ end
467
+ return tree
468
+ end
469
 
470
  # Simplify tree
471
  function simplifyTree(tree::Node)::Node
 
511
  tree = mutateOperator(tree)
512
  elseif mutationChoice < cweights[3] && n < maxsize
513
  tree = appendRandomOp(tree)
514
+ elseif mutationChoice < cweights[4] && n < maxsize
515
+ tree = insertRandomOp(tree)
516
  elseif mutationChoice < cweights[5]
517
+ tree = deleteRandomOp(tree)
518
+ elseif mutationChoice < cweights[6]
519
  tree = simplifyTree(tree) # Sometimes we simplify tree
520
+ tree = combineOperators(tree) # See if repeated constants at outer levels
521
  return tree
522
+ elseif mutationChoice < cweights[7]
523
  tree = genRandomTree(5) # Sometimes we simplify tree
524
  else
525
  return tree
 
767
  debug(verbosity, "-----------------------------------------")
768
  debug(verbosity, "Complexity \t MSE \t Equation")
769
  println(io,"Complexity|MSE|Equation")
770
+ for size=1:actualMaxsize
771
  if hallOfFame.exists[size]
772
  member = hallOfFame.members[size]
773
+ curMSE = MSE(evalTreeArray(member.tree), y)
774
+ numberSmallerAndBetter = sum([curMSE > MSE(evalTreeArray(hallOfFame.members[i].tree), y) for i=1:(size-1)])
775
  betterThanAllSmaller = (numberSmallerAndBetter == 0)
776
  if betterThanAllSmaller
777
+ debug(verbosity, "$size \t $(curMSE) \t $(stringTree(member.tree))")
778
+ println(io, "$size|$(curMSE)|$(stringTree(member.tree))")
779
  push!(dominating, member)
780
  end
781
  end
eureqa.py CHANGED
@@ -6,27 +6,26 @@ import numpy as np
6
  import pandas as pd
7
 
8
  # Dumped from hyperparam optimization
9
- default_alpha = 5.429178
10
- default_annealing = 1.000000
11
- default_fractionReplaced = 0.415076
12
- default_fractionReplacedHof = 0.031713
13
- default_ncyclesperiteration = 1614.000000
14
- default_niterations = 25.000000
15
- default_npop = 300.000000
16
- default_parsimony = 0.001861
17
- default_topn = 9.000000
18
- default_weightAddNode = 3.788920
19
- default_weightDeleteNode = 2.553399
20
- default_weightDoNothing = 0.498528
21
- default_weightMutateConstant = 2.081372
22
- default_weightMutateOperator = 2.003413
23
- default_weightRandomize = 4.679883
24
- default_weightSimplify = 0.009620
25
- default_result = -1.183938
26
 
27
  def eureqa(X=None, y=None, threads=4,
28
  niterations=20,
29
- ncyclesperiteration=int(default_ncyclesperiteration),
30
  binary_operators=["plus", "mult"],
31
  unary_operators=["cos", "exp", "sin"],
32
  alpha=default_alpha,
@@ -40,6 +39,7 @@ def eureqa(X=None, y=None, threads=4,
40
  shouldOptimizeConstants=True,
41
  topn=int(default_topn),
42
  weightAddNode=default_weightAddNode,
 
43
  weightDeleteNode=default_weightDeleteNode,
44
  weightDoNothing=default_weightDoNothing,
45
  weightMutateConstant=default_weightMutateConstant,
@@ -84,6 +84,7 @@ def eureqa(X=None, y=None, threads=4,
84
  constants (Nelder-Mead/Newton) at the end of each iteration.
85
  :param topn: int, How many top individuals migrate from each population.
86
  :param weightAddNode: float, Relative likelihood for mutation to add a node
 
87
  :param weightDeleteNode: float, Relative likelihood for mutation to delete a node
88
  :param weightDoNothing: float, Relative likelihood for mutation to leave the individual
89
  :param weightMutateConstant: float, Relative likelihood for mutation to change
@@ -141,6 +142,7 @@ const mutationWeights = [
141
  {weightMutateConstant:f},
142
  {weightMutateOperator:f},
143
  {weightAddNode:f},
 
144
  {weightDeleteNode:f},
145
  {weightSimplify:f},
146
  {weightRandomize:f},
@@ -199,10 +201,18 @@ if __name__ == "__main__":
199
  parser.add_argument("--maxsize", type=int, default=20, help="Max size of equation")
200
  parser.add_argument("--niterations", type=int, default=20, help="Number of total migration periods")
201
  parser.add_argument("--npop", type=int, default=int(default_npop), help="Number of members per population")
202
- parser.add_argument("--ncyclesperiteration", type=int, default=int(default_ncyclesperiteration), help="Number of evolutionary cycles per migration")
203
  parser.add_argument("--topn", type=int, default=int(default_topn), help="How many best species to distribute from each population")
204
  parser.add_argument("--fractionReplacedHof", type=float, default=default_fractionReplacedHof, help="Fraction of population to replace with hall of fame")
205
  parser.add_argument("--fractionReplaced", type=float, default=default_fractionReplaced, help="Fraction of population to replace with best from other populations")
 
 
 
 
 
 
 
 
206
  parser.add_argument("--migration", type=bool, default=True, help="Whether to migrate")
207
  parser.add_argument("--hofMigration", type=bool, default=True, help="Whether to have hall of fame migration")
208
  parser.add_argument("--shouldOptimizeConstants", type=bool, default=True, help="Whether to use classical optimization on constants before every migration (doesn't impact performance that much)")
 
6
  import pandas as pd
7
 
8
  # Dumped from hyperparam optimization
9
+ default_alpha = 5
10
+ default_fractionReplaced = 0.30
11
+ default_fractionReplacedHof = 0.05
12
+ default_npop = 200
13
+ default_weightAddNode = 1
14
+ default_weightInsertNode = 1
15
+ default_weightDeleteNode = 1
16
+ default_weightMutateConstant = 10
17
+ default_weightMutateOperator = 1
18
+ default_weightRandomize = 1
19
+ default_weightSimplify = 0.1
20
+ default_weightDoNothing = 1
21
+ default_result = 1
22
+ default_topn = 10
23
+ default_parsimony = 0.0
24
+
 
25
 
26
  def eureqa(X=None, y=None, threads=4,
27
  niterations=20,
28
+ ncyclesperiteration=10000,
29
  binary_operators=["plus", "mult"],
30
  unary_operators=["cos", "exp", "sin"],
31
  alpha=default_alpha,
 
39
  shouldOptimizeConstants=True,
40
  topn=int(default_topn),
41
  weightAddNode=default_weightAddNode,
42
+ weightInsertNode=default_weightInsertNode,
43
  weightDeleteNode=default_weightDeleteNode,
44
  weightDoNothing=default_weightDoNothing,
45
  weightMutateConstant=default_weightMutateConstant,
 
84
  constants (Nelder-Mead/Newton) at the end of each iteration.
85
  :param topn: int, How many top individuals migrate from each population.
86
  :param weightAddNode: float, Relative likelihood for mutation to add a node
87
+ :param weightInsertNode: float, Relative likelihood for mutation to insert a node
88
  :param weightDeleteNode: float, Relative likelihood for mutation to delete a node
89
  :param weightDoNothing: float, Relative likelihood for mutation to leave the individual
90
  :param weightMutateConstant: float, Relative likelihood for mutation to change
 
142
  {weightMutateConstant:f},
143
  {weightMutateOperator:f},
144
  {weightAddNode:f},
145
+ {weightInsertNode:f},
146
  {weightDeleteNode:f},
147
  {weightSimplify:f},
148
  {weightRandomize:f},
 
201
  parser.add_argument("--maxsize", type=int, default=20, help="Max size of equation")
202
  parser.add_argument("--niterations", type=int, default=20, help="Number of total migration periods")
203
  parser.add_argument("--npop", type=int, default=int(default_npop), help="Number of members per population")
204
+ parser.add_argument("--ncyclesperiteration", type=int, default=10000, help="Number of evolutionary cycles per migration")
205
  parser.add_argument("--topn", type=int, default=int(default_topn), help="How many best species to distribute from each population")
206
  parser.add_argument("--fractionReplacedHof", type=float, default=default_fractionReplacedHof, help="Fraction of population to replace with hall of fame")
207
  parser.add_argument("--fractionReplaced", type=float, default=default_fractionReplaced, help="Fraction of population to replace with best from other populations")
208
+ parser.add_argument("--weightAddNode", type=float, default=default_weightAddNode)
209
+ parser.add_argument("--weightInsertNode", type=float, default=default_weightInsertNode)
210
+ parser.add_argument("--weightDeleteNode", type=float, default=default_weightDeleteNode)
211
+ parser.add_argument("--weightMutateConstant", type=float, default=default_weightMutateConstant)
212
+ parser.add_argument("--weightMutateOperator", type=float, default=default_weightMutateOperator)
213
+ parser.add_argument("--weightRandomize", type=float, default=default_weightRandomize)
214
+ parser.add_argument("--weightSimplify", type=float, default=default_weightSimplify)
215
+ parser.add_argument("--weightDoNothing", type=float, default=default_weightDoNothing)
216
  parser.add_argument("--migration", type=bool, default=True, help="Whether to migrate")
217
  parser.add_argument("--hofMigration", type=bool, default=True, help="Whether to have hall of fame migration")
218
  parser.add_argument("--shouldOptimizeConstants", type=bool, default=True, help="Whether to use classical optimization on constants before every migration (doesn't impact performance that much)")
hyperparamopt.py CHANGED
@@ -117,6 +117,7 @@ space = {
117
  'weightMutateConstant': hp.lognormal('weightMutateConstant', np.log(4.0), 1.0),
118
  'weightMutateOperator': hp.lognormal('weightMutateOperator', np.log(0.5), 1.0),
119
  'weightAddNode': hp.lognormal('weightAddNode', np.log(0.5), 1.0),
 
120
  'weightDeleteNode': hp.lognormal('weightDeleteNode', np.log(0.5), 1.0),
121
  'weightSimplify': hp.lognormal('weightSimplify', np.log(0.05), 1.0),
122
  'weightRandomize': hp.lognormal('weightRandomize', np.log(0.25), 1.0),
 
117
  'weightMutateConstant': hp.lognormal('weightMutateConstant', np.log(4.0), 1.0),
118
  'weightMutateOperator': hp.lognormal('weightMutateOperator', np.log(0.5), 1.0),
119
  'weightAddNode': hp.lognormal('weightAddNode', np.log(0.5), 1.0),
120
+ 'weightInsertNode': hp.lognormal('weightInsertNode', np.log(0.5), 1.0),
121
  'weightDeleteNode': hp.lognormal('weightDeleteNode', np.log(0.5), 1.0),
122
  'weightSimplify': hp.lognormal('weightSimplify', np.log(0.05), 1.0),
123
  'weightRandomize': hp.lognormal('weightRandomize', np.log(0.25), 1.0),
operators.jl CHANGED
@@ -1,6 +1,6 @@
1
  # Define allowed operators. Any julia operator can also be used.
2
- plus(x::Float32, y::Float32)::Float32 = x+y
3
- mult(x::Float32, y::Float32)::Float32 = x*y
4
  pow(x::Float32, y::Float32)::Float32 = sign(x)*abs(x)^y
5
  div(x::Float32, y::Float32)::Float32 = x/y
6
  loga(x::Float32)::Float32 = log(abs(x) + 1)
 
1
  # Define allowed operators. Any julia operator can also be used.
2
+ plus(x::Float32, y::Float32)::Float32 = x+y #Do not change the name of this operator.
3
+ mult(x::Float32, y::Float32)::Float32 = x*y #Do not change the name of this operator.
4
  pow(x::Float32, y::Float32)::Float32 = sign(x)*abs(x)^y
5
  div(x::Float32, y::Float32)::Float32 = x/y
6
  loga(x::Float32)::Float32 = log(abs(x) + 1)