MilesCranmer commited on
Commit
6dfed1b
·
unverified ·
2 Parent(s): 116eee1 5824cd8

Merge pull request #608 from MilesCranmer/dimensionless-constants

Browse files

Add dimensionless constants mode; update Python version constraints

.github/workflows/CI.yml CHANGED
@@ -32,12 +32,12 @@ jobs:
32
  strategy:
33
  matrix:
34
  julia-version: ['1']
35
- python-version: ['3.11']
36
  os: [ubuntu-latest]
37
  test-id: [main]
38
  include:
39
  - julia-version: '1.6'
40
- python-version: '3.7'
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.11']
103
  julia-version: ['1']
104
  include:
105
  - os: ubuntu-latest
106
- python-version: '3.7'
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.11']
126
  os: ['ubuntu-latest']
127
 
128
  steps:
@@ -181,8 +181,8 @@ jobs:
181
  strategy:
182
  matrix:
183
  python-version:
184
- - '3.11'
185
- - '3.7'
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.7' }}
203
  - name: "Run mypy"
204
  run: python -m mypy --install-types --non-interactive pysr
205
- if: ${{ matrix.python-version != '3.7' }}
206
  - name: "Run compatible mypy"
207
  run: python -m mypy --ignore-missing-imports pysr
208
- if: ${{ matrix.python-version == '3.7' }}
 
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.11']
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.7', '3.11']
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.9']
27
- python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
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.11']
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.11.6]
22
- julia-version: [1.9.4]
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
@@ -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
 
 
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.7
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.3"
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.7"
15
  classifiers = [
16
  "Programming Language :: Python :: 3",
17
  "Operating System :: OS Independent",
@@ -34,4 +34,5 @@ profile = "black"
34
  dev-dependencies = [
35
  "pre-commit>=3.7.0",
36
  "ipython>=8.23.0",
 
37
  ]
 
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
  ]
pysr/julia_import.py CHANGED
@@ -35,32 +35,15 @@ else:
35
  os.environ[k] = os.environ.get(k, default)
36
 
37
 
 
 
 
 
 
38
  from juliacall import Main as jl # type: ignore
39
 
40
  jl_version = (jl.VERSION.major, jl.VERSION.minor, jl.VERSION.patch)
41
 
42
- # Next, automatically load the juliacall extension if we're in a Jupyter notebook
43
- autoload_extensions = os.environ.get("PYSR_AUTOLOAD_EXTENSIONS", "yes")
44
- if autoload_extensions in {"yes", ""} and jl_version >= (1, 9, 0):
45
- try:
46
- get_ipython = sys.modules["IPython"].get_ipython
47
-
48
- if "IPKernelApp" not in get_ipython().config:
49
- raise ImportError("console")
50
-
51
- print(
52
- "Detected Jupyter notebook. Loading juliacall extension. Set `PYSR_AUTOLOAD_EXTENSIONS=no` to disable."
53
- )
54
-
55
- # TODO: Turn this off if juliacall does this automatically
56
- get_ipython().run_line_magic("load_ext", "juliacall")
57
- except Exception:
58
- pass
59
- elif autoload_extensions not in {"no", "yes", ""}:
60
- warnings.warn(
61
- "PYSR_AUTOLOAD_EXTENSIONS environment variable is set to something other than 'yes' or 'no' or ''."
62
- )
63
-
64
  jl.seval("using SymbolicRegression")
65
  SymbolicRegression = jl.SymbolicRegression
66
 
 
35
  os.environ[k] = os.environ.get(k, default)
36
 
37
 
38
+ autoload_extensions = os.environ.get("PYSR_AUTOLOAD_EXTENSIONS")
39
+ if autoload_extensions is not None:
40
+ # Deprecated; so just pass to juliacall
41
+ os.environ["PYTHON_JULIACALL_AUTOLOAD_IPYTHON_EXTENSION"] = autoload_extensions
42
+
43
  from juliacall import Main as jl # type: ignore
44
 
45
  jl_version = (jl.VERSION.major, jl.VERSION.minor, jl.VERSION.patch)
46
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  jl.seval("using SymbolicRegression")
48
  SymbolicRegression = jl.SymbolicRegression
49
 
pysr/juliapkg.json CHANGED
@@ -3,7 +3,7 @@
3
  "packages": {
4
  "SymbolicRegression": {
5
  "uuid": "8254be44-1295-4e6a-a16d-46603ac705cb",
6
- "version": "=0.24.3"
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
@@ -328,6 +328,9 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
328
  dimensional_constraint_penalty : float
329
  Additive penalty for if dimensional analysis of an expression fails.
330
  By default, this is `1000.0`.
 
 
 
331
  use_frequency : bool
332
  Whether to measure the frequency of complexities, and use that
333
  instead of parsimony to explore equation space. Will naturally
@@ -688,6 +691,7 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
688
  complexity_of_variables: Union[int, float] = 1,
689
  parsimony: float = 0.0032,
690
  dimensional_constraint_penalty: Optional[float] = None,
 
691
  use_frequency: bool = True,
692
  use_frequency_in_tournament: bool = True,
693
  adaptive_parsimony_scaling: float = 20.0,
@@ -783,6 +787,7 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
783
  self.complexity_of_variables = complexity_of_variables
784
  self.parsimony = parsimony
785
  self.dimensional_constraint_penalty = dimensional_constraint_penalty
 
786
  self.use_frequency = use_frequency
787
  self.use_frequency_in_tournament = use_frequency_in_tournament
788
  self.adaptive_parsimony_scaling = adaptive_parsimony_scaling
@@ -1654,6 +1659,7 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator):
1654
  # These have the same name:
1655
  parsimony=self.parsimony,
1656
  dimensional_constraint_penalty=self.dimensional_constraint_penalty,
 
1657
  alpha=self.alpha,
1658
  maxdepth=maxdepth,
1659
  fast_cycle=self.fast_cycle,
 
328
  dimensional_constraint_penalty : float
329
  Additive penalty for if dimensional analysis of an expression fails.
330
  By default, this is `1000.0`.
331
+ dimensionless_constants_only : bool
332
+ Whether to only search for dimensionless constants, if using units.
333
+ Default is `False`.
334
  use_frequency : bool
335
  Whether to measure the frequency of complexities, and use that
336
  instead of parsimony to explore equation space. Will naturally
 
691
  complexity_of_variables: Union[int, float] = 1,
692
  parsimony: float = 0.0032,
693
  dimensional_constraint_penalty: Optional[float] = None,
694
+ dimensionless_constants_only: bool = False,
695
  use_frequency: bool = True,
696
  use_frequency_in_tournament: bool = True,
697
  adaptive_parsimony_scaling: float = 20.0,
 
787
  self.complexity_of_variables = complexity_of_variables
788
  self.parsimony = parsimony
789
  self.dimensional_constraint_penalty = dimensional_constraint_penalty
790
+ self.dimensionless_constants_only = dimensionless_constants_only
791
  self.use_frequency = use_frequency
792
  self.use_frequency_in_tournament = use_frequency_in_tournament
793
  self.adaptive_parsimony_scaling = adaptive_parsimony_scaling
 
1659
  # These have the same name:
1660
  parsimony=self.parsimony,
1661
  dimensional_constraint_penalty=self.dimensional_constraint_penalty,
1662
+ dimensionless_constants_only=self.dimensionless_constants_only,
1663
  alpha=self.alpha,
1664
  maxdepth=maxdepth,
1665
  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.19
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"