MilesCranmer commited on
Commit
a4bb529
1 Parent(s): 139b8d0

Run in `Main`

Browse files
Files changed (3) hide show
  1. pysr/julia_helpers.py +7 -4
  2. pysr/sr.py +14 -18
  3. pysr/test/test.py +6 -6
pysr/julia_helpers.py CHANGED
@@ -11,11 +11,8 @@ if os.environ.get("PYTHON_JULIACALL_HANDLE_SIGNALS", "yes") != "yes":
11
 
12
  os.environ["PYTHON_JULIACALL_HANDLE_SIGNALS"] = "yes"
13
 
14
- import juliacall
15
  import juliapkg
16
-
17
- jl = juliacall.newmodule("PySR")
18
-
19
  from juliacall import convert as jl_convert
20
 
21
  jl.seval("using PythonCall: PythonCall")
@@ -53,3 +50,9 @@ def _backend_version_assertion():
53
  def _load_cluster_manager(cluster_manager):
54
  jl.seval(f"using ClusterManagers: addprocs_{cluster_manager}")
55
  return jl.seval(f"addprocs_{cluster_manager}")
 
 
 
 
 
 
 
11
 
12
  os.environ["PYTHON_JULIACALL_HANDLE_SIGNALS"] = "yes"
13
 
 
14
  import juliapkg
15
+ from juliacall import Main as jl
 
 
16
  from juliacall import convert as jl_convert
17
 
18
  jl.seval("using PythonCall: PythonCall")
 
50
  def _load_cluster_manager(cluster_manager):
51
  jl.seval(f"using ClusterManagers: addprocs_{cluster_manager}")
52
  return jl.seval(f"addprocs_{cluster_manager}")
53
+
54
+
55
+ def jl_array(x):
56
+ if x is None:
57
+ return None
58
+ return jl_convert(jl.Array, x)
pysr/sr.py CHANGED
@@ -37,6 +37,7 @@ from .julia_helpers import (
37
  _escape_filename,
38
  _load_cluster_manager,
39
  jl,
 
40
  jl_convert,
41
  )
42
  from .utils import (
@@ -1618,8 +1619,8 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
1618
  options = SymbolicRegression.Options(
1619
  binary_operators=jl.seval(str(binary_operators).replace("'", "")),
1620
  unary_operators=jl.seval(str(unary_operators).replace("'", "")),
1621
- bin_constraints=jl_convert(jl.Vector, bin_constraints),
1622
- una_constraints=jl_convert(jl.Vector, una_constraints),
1623
  complexity_of_operators=complexity_of_operators,
1624
  complexity_of_constants=self.complexity_of_constants,
1625
  complexity_of_variables=self.complexity_of_variables,
@@ -1684,16 +1685,16 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
1684
  np_dtype = {32: np.complex64, 64: np.complex128}[self.precision]
1685
 
1686
  # This converts the data into a Julia array:
1687
- jl_X = jl_convert(jl.Array, np.array(X, dtype=np_dtype).T)
1688
  if len(y.shape) == 1:
1689
- jl_y = jl_convert(jl.Vector, np.array(y, dtype=np_dtype))
1690
  else:
1691
- jl_y = jl_convert(jl.Array, np.array(y, dtype=np_dtype).T)
1692
  if weights is not None:
1693
  if len(weights.shape) == 1:
1694
- jl_weights = jl_convert(jl.Vector, np.array(weights, dtype=np_dtype))
1695
  else:
1696
- jl_weights = jl_convert(jl.Array, np.array(weights, dtype=np_dtype).T)
1697
  else:
1698
  jl_weights = None
1699
 
@@ -1711,17 +1712,12 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
1711
  if len(y.shape) > 1:
1712
  # We set these manually so that they respect Python's 0 indexing
1713
  # (by default Julia will use y1, y2...)
1714
- jl_y_variable_names = jl_convert(
1715
- jl.Vector, [f"y{_subscriptify(i)}" for i in range(y.shape[1])]
1716
  )
1717
  else:
1718
  jl_y_variable_names = None
1719
 
1720
- jl_feature_names = jl_convert(jl.Vector, self.feature_names_in_.tolist())
1721
- jl_display_feature_names = jl_convert(
1722
- jl.Vector, self.display_feature_names_in_.tolist()
1723
- )
1724
-
1725
  PythonCall.GC.disable()
1726
  # Call to Julia backend.
1727
  # See https://github.com/MilesCranmer/SymbolicRegression.jl/blob/master/src/SymbolicRegression.jl
@@ -1730,11 +1726,11 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
1730
  jl_y,
1731
  weights=jl_weights,
1732
  niterations=int(self.niterations),
1733
- variable_names=jl_feature_names,
1734
- display_variable_names=jl_display_feature_names,
1735
  y_variable_names=jl_y_variable_names,
1736
- X_units=self.X_units_,
1737
- y_units=self.y_units_,
1738
  options=options,
1739
  numprocs=cprocs,
1740
  parallelism=parallelism,
 
37
  _escape_filename,
38
  _load_cluster_manager,
39
  jl,
40
+ jl_array,
41
  jl_convert,
42
  )
43
  from .utils import (
 
1619
  options = SymbolicRegression.Options(
1620
  binary_operators=jl.seval(str(binary_operators).replace("'", "")),
1621
  unary_operators=jl.seval(str(unary_operators).replace("'", "")),
1622
+ bin_constraints=jl_array(bin_constraints),
1623
+ una_constraints=jl_array(una_constraints),
1624
  complexity_of_operators=complexity_of_operators,
1625
  complexity_of_constants=self.complexity_of_constants,
1626
  complexity_of_variables=self.complexity_of_variables,
 
1685
  np_dtype = {32: np.complex64, 64: np.complex128}[self.precision]
1686
 
1687
  # This converts the data into a Julia array:
1688
+ jl_X = jl_array(np.array(X, dtype=np_dtype).T)
1689
  if len(y.shape) == 1:
1690
+ jl_y = jl_array(np.array(y, dtype=np_dtype))
1691
  else:
1692
+ jl_y = jl_array(np.array(y, dtype=np_dtype).T)
1693
  if weights is not None:
1694
  if len(weights.shape) == 1:
1695
+ jl_weights = jl_array(np.array(weights, dtype=np_dtype))
1696
  else:
1697
+ jl_weights = jl_array(np.array(weights, dtype=np_dtype).T)
1698
  else:
1699
  jl_weights = None
1700
 
 
1712
  if len(y.shape) > 1:
1713
  # We set these manually so that they respect Python's 0 indexing
1714
  # (by default Julia will use y1, y2...)
1715
+ jl_y_variable_names = jl_array(
1716
+ [f"y{_subscriptify(i)}" for i in range(y.shape[1])]
1717
  )
1718
  else:
1719
  jl_y_variable_names = None
1720
 
 
 
 
 
 
1721
  PythonCall.GC.disable()
1722
  # Call to Julia backend.
1723
  # See https://github.com/MilesCranmer/SymbolicRegression.jl/blob/master/src/SymbolicRegression.jl
 
1726
  jl_y,
1727
  weights=jl_weights,
1728
  niterations=int(self.niterations),
1729
+ variable_names=jl_array(self.feature_names_in_.tolist()),
1730
+ display_variable_names=jl_array(self.display_feature_names_in_.tolist()),
1731
  y_variable_names=jl_y_variable_names,
1732
+ X_units=jl_array(self.X_units_),
1733
+ y_units=jl_array(self.y_units_),
1734
  options=options,
1735
  numprocs=cprocs,
1736
  parallelism=parallelism,
pysr/test/test.py CHANGED
@@ -106,11 +106,11 @@ class TestPipeline(unittest.TestCase):
106
  warm_start=True,
107
  )
108
  model.fit(self.X, y)
109
- from pysr.sr import Main
110
 
111
  # We should have that the model state is now a Float64 hof:
112
- Main.test_state = model.raw_julia_state_
113
- self.assertTrue(Main.eval("typeof(test_state[2]).parameters[1] == Float64"))
114
 
115
  def test_multioutput_custom_operator_quiet_custom_complexity(self):
116
  y = self.X[:, [0, 1]] ** 2
@@ -229,11 +229,11 @@ class TestPipeline(unittest.TestCase):
229
  early_stop_condition=None,
230
  )
231
  # Check that the the julia state is saved:
232
- from pysr.sr import Main
233
 
234
  # We should have that the model state is now a Float32 hof:
235
- Main.test_state = regressor.raw_julia_state_
236
- self.assertTrue(Main.eval("typeof(test_state[2]).parameters[1] == Float32"))
237
  # This should exit almost immediately, and use the old equations
238
  regressor.fit(X, y)
239
 
 
106
  warm_start=True,
107
  )
108
  model.fit(self.X, y)
109
+ from pysr.sr import jl
110
 
111
  # We should have that the model state is now a Float64 hof:
112
+ jl.test_state = model.raw_julia_state_
113
+ self.assertTrue(jl.seval("typeof(test_state[2]).parameters[1] == Float64"))
114
 
115
  def test_multioutput_custom_operator_quiet_custom_complexity(self):
116
  y = self.X[:, [0, 1]] ** 2
 
229
  early_stop_condition=None,
230
  )
231
  # Check that the the julia state is saved:
232
+ from pysr.sr import jl
233
 
234
  # We should have that the model state is now a Float32 hof:
235
+ jl.test_state = regressor.raw_julia_state_
236
+ self.assertTrue(jl.eval("typeof(test_state[2]).parameters[1] == Float32"))
237
  # This should exit almost immediately, and use the old equations
238
  regressor.fit(X, y)
239