Spaces:
Running
Running
MilesCranmer
commited on
Merge tag 'v0.18.4' into cleanup
Browse files- .github/workflows/CI.yml +10 -10
- .github/workflows/CI_Windows.yml +1 -1
- .github/workflows/CI_docker_large_nightly.yml +1 -1
- .github/workflows/CI_large_nightly.yml +2 -2
- .github/workflows/CI_mac.yml +1 -1
- .github/workflows/docker_deploy.yml +2 -2
- docs/examples.md +3 -1
- environment.yml +1 -1
- pyproject.toml +3 -2
- pysr/julia_import.py +5 -22
- pysr/juliapkg.json +1 -1
- pysr/param_groupings.yml +1 -0
- pysr/sr.py +6 -0
- pysr/test/test_startup.py +0 -4
- requirements.txt +1 -1
.github/workflows/CI.yml
CHANGED
@@ -32,12 +32,12 @@ jobs:
|
|
32 |
strategy:
|
33 |
matrix:
|
34 |
julia-version: ['1']
|
35 |
-
python-version: ['3.
|
36 |
os: [ubuntu-latest]
|
37 |
test-id: [main]
|
38 |
include:
|
39 |
- julia-version: '1.6'
|
40 |
-
python-version: '3.
|
41 |
os: ubuntu-latest
|
42 |
test-id: include
|
43 |
- julia-version: '1'
|
@@ -99,11 +99,11 @@ jobs:
|
|
99 |
strategy:
|
100 |
matrix:
|
101 |
os: ['ubuntu-latest']
|
102 |
-
python-version: ['3.
|
103 |
julia-version: ['1']
|
104 |
include:
|
105 |
- os: ubuntu-latest
|
106 |
-
python-version: '3.
|
107 |
julia-version: '1.6'
|
108 |
steps:
|
109 |
- uses: actions/checkout@v4
|
@@ -122,7 +122,7 @@ jobs:
|
|
122 |
shell: bash -l {0}
|
123 |
strategy:
|
124 |
matrix:
|
125 |
-
python-version: ['3.
|
126 |
os: ['ubuntu-latest']
|
127 |
|
128 |
steps:
|
@@ -181,8 +181,8 @@ jobs:
|
|
181 |
strategy:
|
182 |
matrix:
|
183 |
python-version:
|
184 |
-
- '3.
|
185 |
-
- '3.
|
186 |
os: ['ubuntu-latest']
|
187 |
|
188 |
steps:
|
@@ -199,10 +199,10 @@ jobs:
|
|
199 |
pip install mypy
|
200 |
- name: "Install additional dependencies"
|
201 |
run: python -m pip install jax jaxlib torch
|
202 |
-
if: ${{ matrix.python-version != '3.
|
203 |
- name: "Run mypy"
|
204 |
run: python -m mypy --install-types --non-interactive pysr
|
205 |
-
if: ${{ matrix.python-version != '3.
|
206 |
- name: "Run compatible mypy"
|
207 |
run: python -m mypy --ignore-missing-imports pysr
|
208 |
-
if: ${{ matrix.python-version == '3.
|
|
|
32 |
strategy:
|
33 |
matrix:
|
34 |
julia-version: ['1']
|
35 |
+
python-version: ['3.12']
|
36 |
os: [ubuntu-latest]
|
37 |
test-id: [main]
|
38 |
include:
|
39 |
- julia-version: '1.6'
|
40 |
+
python-version: '3.8'
|
41 |
os: ubuntu-latest
|
42 |
test-id: include
|
43 |
- julia-version: '1'
|
|
|
99 |
strategy:
|
100 |
matrix:
|
101 |
os: ['ubuntu-latest']
|
102 |
+
python-version: ['3.12']
|
103 |
julia-version: ['1']
|
104 |
include:
|
105 |
- os: ubuntu-latest
|
106 |
+
python-version: '3.8'
|
107 |
julia-version: '1.6'
|
108 |
steps:
|
109 |
- uses: actions/checkout@v4
|
|
|
122 |
shell: bash -l {0}
|
123 |
strategy:
|
124 |
matrix:
|
125 |
+
python-version: ['3.12']
|
126 |
os: ['ubuntu-latest']
|
127 |
|
128 |
steps:
|
|
|
181 |
strategy:
|
182 |
matrix:
|
183 |
python-version:
|
184 |
+
- '3.12'
|
185 |
+
- '3.8'
|
186 |
os: ['ubuntu-latest']
|
187 |
|
188 |
steps:
|
|
|
199 |
pip install mypy
|
200 |
- name: "Install additional dependencies"
|
201 |
run: python -m pip install jax jaxlib torch
|
202 |
+
if: ${{ matrix.python-version != '3.8' }}
|
203 |
- name: "Run mypy"
|
204 |
run: python -m mypy --install-types --non-interactive pysr
|
205 |
+
if: ${{ matrix.python-version != '3.8' }}
|
206 |
- name: "Run compatible mypy"
|
207 |
run: python -m mypy --ignore-missing-imports pysr
|
208 |
+
if: ${{ matrix.python-version == '3.8' }}
|
.github/workflows/CI_Windows.yml
CHANGED
@@ -30,7 +30,7 @@ jobs:
|
|
30 |
strategy:
|
31 |
matrix:
|
32 |
julia-version: ['1']
|
33 |
-
python-version: ['3.
|
34 |
os: [windows-latest]
|
35 |
|
36 |
steps:
|
|
|
30 |
strategy:
|
31 |
matrix:
|
32 |
julia-version: ['1']
|
33 |
+
python-version: ['3.12']
|
34 |
os: [windows-latest]
|
35 |
|
36 |
steps:
|
.github/workflows/CI_docker_large_nightly.yml
CHANGED
@@ -19,7 +19,7 @@ jobs:
|
|
19 |
fail-fast: false
|
20 |
matrix:
|
21 |
julia-version: ['1.6', '1']
|
22 |
-
python-version: ['3.
|
23 |
os: [ubuntu-latest]
|
24 |
arch: ['linux/amd64', 'linux/arm64']
|
25 |
|
|
|
19 |
fail-fast: false
|
20 |
matrix:
|
21 |
julia-version: ['1.6', '1']
|
22 |
+
python-version: ['3.8', '3.12']
|
23 |
os: [ubuntu-latest]
|
24 |
arch: ['linux/amd64', 'linux/arm64']
|
25 |
|
.github/workflows/CI_large_nightly.yml
CHANGED
@@ -23,8 +23,8 @@ jobs:
|
|
23 |
strategy:
|
24 |
fail-fast: false
|
25 |
matrix:
|
26 |
-
julia-version: ['1.6', '1.8', '1.
|
27 |
-
python-version: ['3.
|
28 |
os: [ubuntu-latest, macos-latest, windows-latest]
|
29 |
|
30 |
steps:
|
|
|
23 |
strategy:
|
24 |
fail-fast: false
|
25 |
matrix:
|
26 |
+
julia-version: ['1.6', '1.8', '1.10']
|
27 |
+
python-version: ['3.8', '3.10', '3.12']
|
28 |
os: [ubuntu-latest, macos-latest, windows-latest]
|
29 |
|
30 |
steps:
|
.github/workflows/CI_mac.yml
CHANGED
@@ -30,7 +30,7 @@ jobs:
|
|
30 |
strategy:
|
31 |
matrix:
|
32 |
julia-version: ['1']
|
33 |
-
python-version: ['3.
|
34 |
os: [macos-latest]
|
35 |
|
36 |
steps:
|
|
|
30 |
strategy:
|
31 |
matrix:
|
32 |
julia-version: ['1']
|
33 |
+
python-version: ['3.12']
|
34 |
os: [macos-latest]
|
35 |
|
36 |
steps:
|
.github/workflows/docker_deploy.yml
CHANGED
@@ -18,8 +18,8 @@ jobs:
|
|
18 |
matrix:
|
19 |
os: [ubuntu-latest]
|
20 |
arch: [linux/amd64]
|
21 |
-
python-version: [3.
|
22 |
-
julia-version: [1.
|
23 |
steps:
|
24 |
- name: Checkout
|
25 |
uses: actions/checkout@v4
|
|
|
18 |
matrix:
|
19 |
os: [ubuntu-latest]
|
20 |
arch: [linux/amd64]
|
21 |
+
python-version: [3.12.3]
|
22 |
+
julia-version: [1.10.3]
|
23 |
steps:
|
24 |
- name: Checkout
|
25 |
uses: actions/checkout@v4
|
docs/examples.md
CHANGED
@@ -428,7 +428,7 @@ the evaluation, as we simply evaluated each argument and divided the result) int
|
|
428 |
`((2.3554819 + -0.3554746) - (x1 * (x0 * x0)))` and
|
429 |
`(-1.0000019 - (x2 * x2))`, meaning that our discovered equation is
|
430 |
equal to:
|
431 |
-
$\frac{x_0^2 x_1 - 2.0000073}{x_2^2
|
432 |
is nearly the same as the true equation!
|
433 |
|
434 |
## 10. Dimensional constraints
|
@@ -520,6 +520,8 @@ a constant `"2.6353e-22[m s⁻²]"`.
|
|
520 |
|
521 |
Note that this expression has a large dynamic range so may be difficult to find. Consider searching with a larger `niterations` if needed.
|
522 |
|
|
|
|
|
523 |
|
524 |
## 11. Additional features
|
525 |
|
|
|
428 |
`((2.3554819 + -0.3554746) - (x1 * (x0 * x0)))` and
|
429 |
`(-1.0000019 - (x2 * x2))`, meaning that our discovered equation is
|
430 |
equal to:
|
431 |
+
$\frac{x_0^2 x_1 - 2.0000073}{x_2^2 + 1.0000019}$, which
|
432 |
is nearly the same as the true equation!
|
433 |
|
434 |
## 10. Dimensional constraints
|
|
|
520 |
|
521 |
Note that this expression has a large dynamic range so may be difficult to find. Consider searching with a larger `niterations` if needed.
|
522 |
|
523 |
+
Note that you can also search for exclusively dimensionless constants by settings
|
524 |
+
`dimensionless_constants_only` to `true`.
|
525 |
|
526 |
## 11. Additional features
|
527 |
|
environment.yml
CHANGED
@@ -2,7 +2,7 @@ name: test
|
|
2 |
channels:
|
3 |
- conda-forge
|
4 |
dependencies:
|
5 |
-
- python>=3.
|
6 |
- sympy>=1.0.0,<2.0.0
|
7 |
- pandas>=0.21.0,<3.0.0
|
8 |
- numpy>=1.13.0,<2.0.0
|
|
|
2 |
channels:
|
3 |
- conda-forge
|
4 |
dependencies:
|
5 |
+
- python>=3.8
|
6 |
- sympy>=1.0.0,<2.0.0
|
7 |
- pandas>=0.21.0,<3.0.0
|
8 |
- numpy>=1.13.0,<2.0.0
|
pyproject.toml
CHANGED
@@ -4,14 +4,14 @@ build-backend = "setuptools.build_meta"
|
|
4 |
|
5 |
[project]
|
6 |
name = "pysr"
|
7 |
-
version = "0.18.
|
8 |
authors = [
|
9 |
{name = "Miles Cranmer", email = "[email protected]"},
|
10 |
]
|
11 |
description = "Simple and efficient symbolic regression"
|
12 |
readme = {file = "README.md", content-type = "text/markdown"}
|
13 |
license = {file = "LICENSE"}
|
14 |
-
requires-python = ">=3.
|
15 |
classifiers = [
|
16 |
"Programming Language :: Python :: 3",
|
17 |
"Operating System :: OS Independent",
|
@@ -34,5 +34,6 @@ profile = "black"
|
|
34 |
dev-dependencies = [
|
35 |
"pre-commit>=3.7.0",
|
36 |
"ipython>=8.23.0",
|
|
|
37 |
"mypy>=1.10.0",
|
38 |
]
|
|
|
4 |
|
5 |
[project]
|
6 |
name = "pysr"
|
7 |
+
version = "0.18.4"
|
8 |
authors = [
|
9 |
{name = "Miles Cranmer", email = "[email protected]"},
|
10 |
]
|
11 |
description = "Simple and efficient symbolic regression"
|
12 |
readme = {file = "README.md", content-type = "text/markdown"}
|
13 |
license = {file = "LICENSE"}
|
14 |
+
requires-python = ">=3.8"
|
15 |
classifiers = [
|
16 |
"Programming Language :: Python :: 3",
|
17 |
"Operating System :: OS Independent",
|
|
|
34 |
dev-dependencies = [
|
35 |
"pre-commit>=3.7.0",
|
36 |
"ipython>=8.23.0",
|
37 |
+
"ipykernel>=6.29.4",
|
38 |
"mypy>=1.10.0",
|
39 |
]
|
pysr/julia_import.py
CHANGED
@@ -36,6 +36,11 @@ else:
|
|
36 |
os.environ[k] = os.environ.get(k, default)
|
37 |
|
38 |
|
|
|
|
|
|
|
|
|
|
|
39 |
from juliacall import Main as jl # type: ignore
|
40 |
|
41 |
jl: Any = jl # type: ignore
|
@@ -43,28 +48,6 @@ jl: Any = jl # type: ignore
|
|
43 |
|
44 |
jl_version = (jl.VERSION.major, jl.VERSION.minor, jl.VERSION.patch)
|
45 |
|
46 |
-
# Next, automatically load the juliacall extension if we're in a Jupyter notebook
|
47 |
-
autoload_extensions = os.environ.get("PYSR_AUTOLOAD_EXTENSIONS", "yes")
|
48 |
-
if autoload_extensions in {"yes", ""} and jl_version >= (1, 9, 0):
|
49 |
-
try:
|
50 |
-
get_ipython = sys.modules["IPython"].get_ipython
|
51 |
-
|
52 |
-
if "IPKernelApp" not in get_ipython().config:
|
53 |
-
raise ImportError("console")
|
54 |
-
|
55 |
-
print(
|
56 |
-
"Detected Jupyter notebook. Loading juliacall extension. Set `PYSR_AUTOLOAD_EXTENSIONS=no` to disable."
|
57 |
-
)
|
58 |
-
|
59 |
-
# TODO: Turn this off if juliacall does this automatically
|
60 |
-
get_ipython().run_line_magic("load_ext", "juliacall")
|
61 |
-
except Exception:
|
62 |
-
pass
|
63 |
-
elif autoload_extensions not in {"no", "yes", ""}:
|
64 |
-
warnings.warn(
|
65 |
-
"PYSR_AUTOLOAD_EXTENSIONS environment variable is set to something other than 'yes' or 'no' or ''."
|
66 |
-
)
|
67 |
-
|
68 |
jl.seval("using SymbolicRegression")
|
69 |
SymbolicRegression = jl.SymbolicRegression
|
70 |
|
|
|
36 |
os.environ[k] = os.environ.get(k, default)
|
37 |
|
38 |
|
39 |
+
autoload_extensions = os.environ.get("PYSR_AUTOLOAD_EXTENSIONS")
|
40 |
+
if autoload_extensions is not None:
|
41 |
+
# Deprecated; so just pass to juliacall
|
42 |
+
os.environ["PYTHON_JULIACALL_AUTOLOAD_IPYTHON_EXTENSION"] = autoload_extensions
|
43 |
+
|
44 |
from juliacall import Main as jl # type: ignore
|
45 |
|
46 |
jl: Any = jl # type: ignore
|
|
|
48 |
|
49 |
jl_version = (jl.VERSION.major, jl.VERSION.minor, jl.VERSION.patch)
|
50 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
jl.seval("using SymbolicRegression")
|
52 |
SymbolicRegression = jl.SymbolicRegression
|
53 |
|
pysr/juliapkg.json
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
"packages": {
|
4 |
"SymbolicRegression": {
|
5 |
"uuid": "8254be44-1295-4e6a-a16d-46603ac705cb",
|
6 |
-
"version": "=0.24.
|
7 |
},
|
8 |
"Serialization": {
|
9 |
"uuid": "9e88b42a-f829-5b0c-bbe9-9e923198166b",
|
|
|
3 |
"packages": {
|
4 |
"SymbolicRegression": {
|
5 |
"uuid": "8254be44-1295-4e6a-a16d-46603ac705cb",
|
6 |
+
"version": "=0.24.4"
|
7 |
},
|
8 |
"Serialization": {
|
9 |
"uuid": "9e88b42a-f829-5b0c-bbe9-9e923198166b",
|
pysr/param_groupings.yml
CHANGED
@@ -14,6 +14,7 @@
|
|
14 |
- loss_function
|
15 |
- model_selection
|
16 |
- dimensional_constraint_penalty
|
|
|
17 |
- Working with Complexities:
|
18 |
- parsimony
|
19 |
- constraints
|
|
|
14 |
- loss_function
|
15 |
- model_selection
|
16 |
- dimensional_constraint_penalty
|
17 |
+
- dimensionless_constants_only
|
18 |
- Working with Complexities:
|
19 |
- parsimony
|
20 |
- constraints
|
pysr/sr.py
CHANGED
@@ -337,6 +337,9 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
|
|
337 |
dimensional_constraint_penalty : float
|
338 |
Additive penalty for if dimensional analysis of an expression fails.
|
339 |
By default, this is `1000.0`.
|
|
|
|
|
|
|
340 |
use_frequency : bool
|
341 |
Whether to measure the frequency of complexities, and use that
|
342 |
instead of parsimony to explore equation space. Will naturally
|
@@ -707,6 +710,7 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
|
|
707 |
complexity_of_variables: Union[int, float] = 1,
|
708 |
parsimony: float = 0.0032,
|
709 |
dimensional_constraint_penalty: Optional[float] = None,
|
|
|
710 |
use_frequency: bool = True,
|
711 |
use_frequency_in_tournament: bool = True,
|
712 |
adaptive_parsimony_scaling: float = 20.0,
|
@@ -802,6 +806,7 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
|
|
802 |
self.complexity_of_variables = complexity_of_variables
|
803 |
self.parsimony = parsimony
|
804 |
self.dimensional_constraint_penalty = dimensional_constraint_penalty
|
|
|
805 |
self.use_frequency = use_frequency
|
806 |
self.use_frequency_in_tournament = use_frequency_in_tournament
|
807 |
self.adaptive_parsimony_scaling = adaptive_parsimony_scaling
|
@@ -1693,6 +1698,7 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
|
|
1693 |
# These have the same name:
|
1694 |
parsimony=self.parsimony,
|
1695 |
dimensional_constraint_penalty=self.dimensional_constraint_penalty,
|
|
|
1696 |
alpha=self.alpha,
|
1697 |
maxdepth=maxdepth,
|
1698 |
fast_cycle=self.fast_cycle,
|
|
|
337 |
dimensional_constraint_penalty : float
|
338 |
Additive penalty for if dimensional analysis of an expression fails.
|
339 |
By default, this is `1000.0`.
|
340 |
+
dimensionless_constants_only : bool
|
341 |
+
Whether to only search for dimensionless constants, if using units.
|
342 |
+
Default is `False`.
|
343 |
use_frequency : bool
|
344 |
Whether to measure the frequency of complexities, and use that
|
345 |
instead of parsimony to explore equation space. Will naturally
|
|
|
710 |
complexity_of_variables: Union[int, float] = 1,
|
711 |
parsimony: float = 0.0032,
|
712 |
dimensional_constraint_penalty: Optional[float] = None,
|
713 |
+
dimensionless_constants_only: bool = False,
|
714 |
use_frequency: bool = True,
|
715 |
use_frequency_in_tournament: bool = True,
|
716 |
adaptive_parsimony_scaling: float = 20.0,
|
|
|
806 |
self.complexity_of_variables = complexity_of_variables
|
807 |
self.parsimony = parsimony
|
808 |
self.dimensional_constraint_penalty = dimensional_constraint_penalty
|
809 |
+
self.dimensionless_constants_only = dimensionless_constants_only
|
810 |
self.use_frequency = use_frequency
|
811 |
self.use_frequency_in_tournament = use_frequency_in_tournament
|
812 |
self.adaptive_parsimony_scaling = adaptive_parsimony_scaling
|
|
|
1698 |
# These have the same name:
|
1699 |
parsimony=self.parsimony,
|
1700 |
dimensional_constraint_penalty=self.dimensional_constraint_penalty,
|
1701 |
+
dimensionless_constants_only=self.dimensionless_constants_only,
|
1702 |
alpha=self.alpha,
|
1703 |
maxdepth=maxdepth,
|
1704 |
fast_cycle=self.fast_cycle,
|
pysr/test/test_startup.py
CHANGED
@@ -118,10 +118,6 @@ class TestStartup(unittest.TestCase):
|
|
118 |
code="import juliacall; import pysr",
|
119 |
msg="juliacall module already imported.",
|
120 |
),
|
121 |
-
dict(
|
122 |
-
code='import os; os.environ["PYSR_AUTOLOAD_EXTENSIONS"] = "foo"; import pysr',
|
123 |
-
msg="PYSR_AUTOLOAD_EXTENSIONS environment variable is set",
|
124 |
-
),
|
125 |
]
|
126 |
for warning_test in warning_tests:
|
127 |
result = subprocess.run(
|
|
|
118 |
code="import juliacall; import pysr",
|
119 |
msg="juliacall module already imported.",
|
120 |
),
|
|
|
|
|
|
|
|
|
121 |
]
|
122 |
for warning_test in warning_tests:
|
123 |
result = subprocess.run(
|
requirements.txt
CHANGED
@@ -2,7 +2,7 @@ sympy>=1.0.0,<2.0.0
|
|
2 |
pandas>=0.21.0,<3.0.0
|
3 |
numpy>=1.13.0,<2.0.0
|
4 |
scikit_learn>=1.0.0,<2.0.0
|
5 |
-
juliacall==0.9.
|
6 |
click>=7.0.0,<9.0.0
|
7 |
setuptools>=50.0.0
|
8 |
typing_extensions>=4.0.0,<5.0.0; python_version < "3.8"
|
|
|
2 |
pandas>=0.21.0,<3.0.0
|
3 |
numpy>=1.13.0,<2.0.0
|
4 |
scikit_learn>=1.0.0,<2.0.0
|
5 |
+
juliacall==0.9.20
|
6 |
click>=7.0.0,<9.0.0
|
7 |
setuptools>=50.0.0
|
8 |
typing_extensions>=4.0.0,<5.0.0; python_version < "3.8"
|