MilesCranmer commited on
Commit
a3a2513
1 Parent(s): 9b9db9e

Allow numpy arrays to be passed

Browse files
Files changed (4) hide show
  1. README.md +6 -1
  2. eureqa.jl +0 -1
  3. eureqa.py +79 -8
  4. operators.jl +1 -0
README.md CHANGED
@@ -21,7 +21,8 @@ usage: eureqa.py [-h] [--threads THREADS] [--parsimony PARSIMONY]
21
  [--fractionReplaced FRACTIONREPLACED] [--migration MIGRATION]
22
  [--hofMigration HOFMIGRATION]
23
  [--shouldOptimizeConstants SHOULDOPTIMIZECONSTANTS]
24
- [--annealing ANNEALING]
 
25
  [--binary-operators BINARY_OPERATORS [BINARY_OPERATORS ...]]
26
  [--unary-operators UNARY_OPERATORS]
27
 
@@ -56,6 +57,10 @@ optional arguments:
56
  that much) (default: True)
57
  --annealing ANNEALING
58
  Whether to use simulated annealing (default: True)
 
 
 
 
59
  --binary-operators BINARY_OPERATORS [BINARY_OPERATORS ...]
60
  Binary operators. Make sure they are defined in
61
  operators.jl (default: ['plus', 'mul'])
 
21
  [--fractionReplaced FRACTIONREPLACED] [--migration MIGRATION]
22
  [--hofMigration HOFMIGRATION]
23
  [--shouldOptimizeConstants SHOULDOPTIMIZECONSTANTS]
24
+ [--annealing ANNEALING] [--equation_file EQUATION_FILE]
25
+ [--test TEST]
26
  [--binary-operators BINARY_OPERATORS [BINARY_OPERATORS ...]]
27
  [--unary-operators UNARY_OPERATORS]
28
 
 
57
  that much) (default: True)
58
  --annealing ANNEALING
59
  Whether to use simulated annealing (default: True)
60
+ --equation_file EQUATION_FILE
61
+ File to dump best equations to (default:
62
+ hall_of_fame.csv)
63
+ --test TEST Which test to run (default: simple1)
64
  --binary-operators BINARY_OPERATORS [BINARY_OPERATORS ...]
65
  Binary operators. Make sure they are defined in
66
  operators.jl (default: ['plus', 'mul'])
eureqa.jl CHANGED
@@ -557,7 +557,6 @@ function fullRun(niterations::Integer;
557
  verbosity::Integer=0,
558
  topn::Integer=10
559
  )
560
- debug(verbosity, "Lets try to learn (x2^2 + cos(x3)) using regularized evolution from scratch")
561
  debug(verbosity, "Running with $nthreads threads")
562
  # Generate random initial populations
563
  allPops = [Population(npop, 3) for j=1:nthreads]
 
557
  verbosity::Integer=0,
558
  topn::Integer=10
559
  )
 
560
  debug(verbosity, "Running with $nthreads threads")
561
  # Generate random initial populations
562
  allPops = [Population(npop, 3) for j=1:nthreads]
eureqa.py CHANGED
@@ -2,9 +2,11 @@ import os
2
  from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
3
  from collections import namedtuple
4
  import pathlib
 
 
5
 
6
 
7
- def eureqa(threads=4, parsimony=1e-3, alpha=10,
8
  maxsize=20, migration=True,
9
  hofMigration=True, fractionReplacedHof=0.1,
10
  shouldOptimizeConstants=True,
@@ -12,8 +14,64 @@ def eureqa(threads=4, parsimony=1e-3, alpha=10,
12
  unary_operators=["cos", "exp", "sin"],
13
  niterations=20, npop=100, annealing=True,
14
  ncyclesperiteration=5000, fractionReplaced=0.1,
15
- topn=10, equation_file='hall_of_fame.csv'
 
16
  ):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
  def_hyperparams = f"""
19
  include("operators.jl")
@@ -48,12 +106,18 @@ def eureqa(threads=4, parsimony=1e-3, alpha=10,
48
  ##################
49
  """
50
 
 
 
 
 
 
 
51
  def_datasets = """
52
  # Here is the function we want to learn (x2^2 + cos(x3) + 5)
53
  ##########################
54
  # # Dataset to learn
55
- const X = convert(Array{Float32, 2}, randn(100, 5)*2)
56
- const y = convert(Array{Float32, 1}, ((cx,)->cx^2).(X[:, 2]) + cos.(X[:, 3]) .- 5)
57
  ##########################
58
  """
59
 
@@ -63,18 +127,24 @@ def eureqa(threads=4, parsimony=1e-3, alpha=10,
63
  with open('.dataset.jl', 'w') as f:
64
  print(def_datasets, file=f)
65
 
66
- command = ' '.join([
67
  f'cd {pathlib.Path(__file__).parent.absolute()}', #Move to filepath of code
68
  '&&',
69
  'julia -O3',
70
  f'--threads {threads}',
71
  '-e',
72
- f'\'include("eureqa.jl"); fullRun({niterations:d}, npop={npop:d}, annealing={"true" if annealing else "false"}, ncyclesperiteration={ncyclesperiteration:d}, fractionReplaced={fractionReplaced:f}f0, verbosity=round(Int32, 1e9), topn={topn:d})\''
73
  '&&',
74
  f'cd {pathlib.Path().absolute()}',
75
- ])
76
  import os
77
- os.system(command)
 
 
 
 
 
 
78
 
79
 
80
 
@@ -97,6 +167,7 @@ if __name__ == "__main__":
97
  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)")
98
  parser.add_argument("--annealing", type=bool, default=True, help="Whether to use simulated annealing")
99
  parser.add_argument("--equation_file", type=str, default='hall_of_fame.csv', help="File to dump best equations to")
 
100
 
101
  parser.add_argument(
102
  "--binary-operators", type=str, nargs="+", default=["plus", "mul"],
 
2
  from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
3
  from collections import namedtuple
4
  import pathlib
5
+ import numpy as np
6
+ import pandas as pd
7
 
8
 
9
+ def eureqa(X=None, y=None, threads=4, parsimony=1e-3, alpha=10,
10
  maxsize=20, migration=True,
11
  hofMigration=True, fractionReplacedHof=0.1,
12
  shouldOptimizeConstants=True,
 
14
  unary_operators=["cos", "exp", "sin"],
15
  niterations=20, npop=100, annealing=True,
16
  ncyclesperiteration=5000, fractionReplaced=0.1,
17
+ topn=10, equation_file='hall_of_fame.csv',
18
+ test='simple1'
19
  ):
20
+ """Either provide a 2D numpy array for X, 1D array for y, or declare a test to run.
21
+
22
+ --threads THREADS Number of threads (default: 4)
23
+ --parsimony PARSIMONY
24
+ How much to punish complexity (default: 0.001)
25
+ --alpha ALPHA Scaling of temperature (default: 10)
26
+ --maxsize MAXSIZE Max size of equation (default: 20)
27
+ --niterations NITERATIONS
28
+ Number of total migration periods (default: 20)
29
+ --npop NPOP Number of members per population (default: 100)
30
+ --ncyclesperiteration NCYCLESPERITERATION
31
+ Number of evolutionary cycles per migration (default:
32
+ 5000)
33
+ --topn TOPN How many best species to distribute from each
34
+ population (default: 10)
35
+ --fractionReplacedHof FRACTIONREPLACEDHOF
36
+ Fraction of population to replace with hall of fame
37
+ (default: 0.1)
38
+ --fractionReplaced FRACTIONREPLACED
39
+ Fraction of population to replace with best from other
40
+ populations (default: 0.1)
41
+ --migration MIGRATION
42
+ Whether to migrate (default: True)
43
+ --hofMigration HOFMIGRATION
44
+ Whether to have hall of fame migration (default: True)
45
+ --shouldOptimizeConstants SHOULDOPTIMIZECONSTANTS
46
+ Whether to use classical optimization on constants
47
+ before every migration (doesn't impact performance
48
+ that much) (default: True)
49
+ --annealing ANNEALING
50
+ Whether to use simulated annealing (default: True)
51
+ --equation_file EQUATION_FILE
52
+ File to dump best equations to (default:
53
+ hall_of_fame.csv)
54
+ --test TEST Which test to run (default: simple1)
55
+ --binary-operators BINARY_OPERATORS [BINARY_OPERATORS ...]
56
+ Binary operators. Make sure they are defined in
57
+ operators.jl (default: ['plus', 'mul'])
58
+ --unary-operators UNARY_OPERATORS
59
+ Unary operators. Make sure they are defined in
60
+ operators.jl (default: ['exp', 'sin', 'cos'])
61
+ """
62
+
63
+ if isinstance(binary_operators, str): binary_operators = [binary_operators]
64
+ if isinstance(unary_operators, str): unary_operators = [unary_operators]
65
+
66
+ if X is None:
67
+ if test == 'simple1':
68
+ eval_str = "X[:, 2]**2 + np.cos(X[:, 3]) - 5"
69
+ elif test == 'simple2':
70
+ eval_str = "X[:, 2]**3.5 + 1/abs(X[:, 0])"
71
+
72
+ X = np.random.randn(100, 5)*3
73
+ y = eval(eval_str)
74
+ print("Runing on", eval_str)
75
 
76
  def_hyperparams = f"""
77
  include("operators.jl")
 
106
  ##################
107
  """
108
 
109
+ assert len(X.shape) == 2
110
+ assert len(y.shape) == 1
111
+
112
+ X_str = str(X.tolist()).replace('],', '];').replace(',', '')
113
+ y_str = str(y.tolist())
114
+
115
  def_datasets = """
116
  # Here is the function we want to learn (x2^2 + cos(x3) + 5)
117
  ##########################
118
  # # Dataset to learn
119
+ const X = convert(Array{Float32, 2}, """f"{X_str})""""
120
+ const y = convert(Array{Float32, 1}, """f"{y_str})""""
121
  ##########################
122
  """
123
 
 
127
  with open('.dataset.jl', 'w') as f:
128
  print(def_datasets, file=f)
129
 
130
+ command = [
131
  f'cd {pathlib.Path(__file__).parent.absolute()}', #Move to filepath of code
132
  '&&',
133
  'julia -O3',
134
  f'--threads {threads}',
135
  '-e',
136
+ f'\'include("eureqa.jl"); fullRun({niterations:d}, npop={npop:d}, annealing={"true" if annealing else "false"}, ncyclesperiteration={ncyclesperiteration:d}, fractionReplaced={fractionReplaced:f}f0, verbosity=round(Int32, 1e9), topn={topn:d})\'',
137
  '&&',
138
  f'cd {pathlib.Path().absolute()}',
139
+ ]
140
  import os
141
+ cur_cmd = ' '.join(command[:-2])
142
+ print("Running on", cur_cmd)
143
+ os.system(cur_cmd)
144
+ output = pd.read_csv(equation_file, sep="|")
145
+ os.system(command[-1])
146
+ return output
147
+
148
 
149
 
150
 
 
167
  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)")
168
  parser.add_argument("--annealing", type=bool, default=True, help="Whether to use simulated annealing")
169
  parser.add_argument("--equation_file", type=str, default='hall_of_fame.csv', help="File to dump best equations to")
170
+ parser.add_argument("--test", type=str, default='simple1', help="Which test to run")
171
 
172
  parser.add_argument(
173
  "--binary-operators", type=str, nargs="+", default=["plus", "mul"],
operators.jl CHANGED
@@ -2,3 +2,4 @@
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;
 
 
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;