MilesCranmer commited on
Commit
7f5b38a
1 Parent(s): 9fa51a8

Add feature to set arbitrary variable names

Browse files
Files changed (4) hide show
  1. README.md +2 -2
  2. julia/sr.jl +5 -1
  3. pysr/sr.py +10 -0
  4. setup.py +1 -1
README.md CHANGED
@@ -304,14 +304,14 @@ pd.DataFrame, Results dataframe, giving complexity, MSE, and equations
304
  - [x] Use @fastmath
305
  - [x] Try @spawn over each sub-population. Do random sort, compute mutation for each, then replace 10% oldest.
306
  - [x] Control max depth, rather than max number of nodes?
 
307
  - [ ] Sort these todo lists by priority
308
 
309
  ## Feature ideas
310
 
311
  - [ ] Sympy printing
312
- - [ ] Allow user to pass names for variables - use these when printing
313
  - [ ] Hierarchical model, so can re-use functional forms. Output of one equation goes into second equation?
314
- - [ ] Call function to read from csv after running
315
  - [ ] Add function to plot equations
316
  - [ ] Refresh screen rather than dumping to stdout?
317
  - [ ] Add ability to save state from python
 
304
  - [x] Use @fastmath
305
  - [x] Try @spawn over each sub-population. Do random sort, compute mutation for each, then replace 10% oldest.
306
  - [x] Control max depth, rather than max number of nodes?
307
+ - [x] Allow user to pass names for variables - use these when printing
308
  - [ ] Sort these todo lists by priority
309
 
310
  ## Feature ideas
311
 
312
  - [ ] Sympy printing
 
313
  - [ ] Hierarchical model, so can re-use functional forms. Output of one equation goes into second equation?
314
+ - [ ] Call function to read from csv after running, so dont need to run again
315
  - [ ] Add function to plot equations
316
  - [ ] Refresh screen rather than dumping to stdout?
317
  - [ ] Add ability to save state from python
julia/sr.jl CHANGED
@@ -121,7 +121,11 @@ function stringTree(tree::Node)::String
121
  if tree.constant
122
  return string(tree.val)
123
  else
124
- return "x$(tree.val - 1)"
 
 
 
 
125
  end
126
  elseif tree.degree == 1
127
  return "$(unaops[tree.op])($(stringTree(tree.l)))"
 
121
  if tree.constant
122
  return string(tree.val)
123
  else
124
+ if useVarMap
125
+ return varMap[tree.val]
126
+ else
127
+ return "x$(tree.val - 1)"
128
+ end
129
  end
130
  elseif tree.degree == 1
131
  return "$(unaops[tree.op])($(stringTree(tree.l)))"
pysr/sr.py CHANGED
@@ -75,6 +75,7 @@ def pysr(X=None, y=None, weights=None,
75
  maxsize=20,
76
  fast_cycle=False,
77
  maxdepth=None,
 
78
  threads=None, #deprecated
79
  julia_optimization=3,
80
  ):
@@ -135,6 +136,8 @@ def pysr(X=None, y=None, weights=None,
135
  :param fast_cycle: bool, (experimental) - batch over population subsamples. This
136
  is a slightly different algorithm than regularized evolution, but does cycles
137
  15% faster. May be algorithmically less efficient.
 
 
138
  :param julia_optimization: int, Optimization level (0, 1, 2, 3)
139
  :returns: pd.DataFrame, Results dataframe, giving complexity, MSE, and equations
140
  (as strings).
@@ -153,6 +156,8 @@ def pysr(X=None, y=None, weights=None,
153
  if weights is not None:
154
  assert len(weights.shape) == 1
155
  assert X.shape[0] == weights.shape[0]
 
 
156
 
157
  if populations is None:
158
  populations = procs
@@ -222,6 +227,7 @@ const nrestarts = {nrestarts:d}
222
  const perturbationFactor = {perturbationFactor:f}f0
223
  const annealing = {"true" if annealing else "false"}
224
  const weighted = {"true" if weights is not None else "false"}
 
225
  const mutationWeights = [
226
  {weightMutateConstant:f},
227
  {weightMutateOperator:f},
@@ -248,6 +254,10 @@ const y = convert(Array{Float32, 1}, """f"{y_str})"
248
  def_datasets += """
249
  const weights = convert(Array{Float32, 1}, """f"{weight_str})"
250
 
 
 
 
 
251
  with open(f'/tmp/.hyperparams_{rand_string}.jl', 'w') as f:
252
  print(def_hyperparams, file=f)
253
 
 
75
  maxsize=20,
76
  fast_cycle=False,
77
  maxdepth=None,
78
+ variable_names=[],
79
  threads=None, #deprecated
80
  julia_optimization=3,
81
  ):
 
136
  :param fast_cycle: bool, (experimental) - batch over population subsamples. This
137
  is a slightly different algorithm than regularized evolution, but does cycles
138
  15% faster. May be algorithmically less efficient.
139
+ :param variable_names: list, a list of names for the variables, other
140
+ than "x0", "x1", etc.
141
  :param julia_optimization: int, Optimization level (0, 1, 2, 3)
142
  :returns: pd.DataFrame, Results dataframe, giving complexity, MSE, and equations
143
  (as strings).
 
156
  if weights is not None:
157
  assert len(weights.shape) == 1
158
  assert X.shape[0] == weights.shape[0]
159
+ if len(variable_names) != 0:
160
+ assert len(variable_names) == X.shape[1]
161
 
162
  if populations is None:
163
  populations = procs
 
227
  const perturbationFactor = {perturbationFactor:f}f0
228
  const annealing = {"true" if annealing else "false"}
229
  const weighted = {"true" if weights is not None else "false"}
230
+ const useVarMap = {"false" if len(variable_names) == 0 else "true"}
231
  const mutationWeights = [
232
  {weightMutateConstant:f},
233
  {weightMutateOperator:f},
 
254
  def_datasets += """
255
  const weights = convert(Array{Float32, 1}, """f"{weight_str})"
256
 
257
+ if len(variable_names) != 0:
258
+ def_hyperparams += f"""
259
+ const varMap = {'["' + '", "'.join(variable_names) + '"]'}"""
260
+
261
  with open(f'/tmp/.hyperparams_{rand_string}.jl', 'w') as f:
262
  print(def_hyperparams, file=f)
263
 
setup.py CHANGED
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
 
6
  setuptools.setup(
7
  name="pysr", # Replace with your own username
8
- version="0.3.18",
9
  author="Miles Cranmer",
10
  author_email="miles.cranmer@gmail.com",
11
  description="Simple and efficient symbolic regression",
 
5
 
6
  setuptools.setup(
7
  name="pysr", # Replace with your own username
8
+ version="0.3.19",
9
  author="Miles Cranmer",
10
  author_email="miles.cranmer@gmail.com",
11
  description="Simple and efficient symbolic regression",