From fe186d681e4afdd319a193cbb05b77d14e011d48 Mon Sep 17 00:00:00 2001 From: MilesCranmer Date: Sun, 28 Apr 2024 06:09:15 +0100 Subject: [PATCH 1/7] feat: add `dimensionless_constants_only` with new backend --- docs/examples.md | 2 ++ pyproject.toml | 2 +- pysr/juliapkg.json | 2 +- pysr/param_groupings.yml | 1 + pysr/sr.py | 6 ++++++ 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/examples.md b/docs/examples.md index 69fb98f8d..eb9551eac 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -520,6 +520,8 @@ a constant `"2.6353e-22[m s⁻²]"`. Note that this expression has a large dynamic range so may be difficult to find. Consider searching with a larger `niterations` if needed. +Note that you can also search for exclusively dimensionless constants by settings +`dimensionless_constants_only` to `true`. ## 11. Additional features diff --git a/pyproject.toml b/pyproject.toml index f2c465e1a..3a0d9d35d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "pysr" -version = "0.18.3" +version = "0.18.4" authors = [ {name = "Miles Cranmer", email = "miles.cranmer@gmail.com"}, ] diff --git a/pysr/juliapkg.json b/pysr/juliapkg.json index 8ce86a56d..db8de4ec1 100644 --- a/pysr/juliapkg.json +++ b/pysr/juliapkg.json @@ -3,7 +3,7 @@ "packages": { "SymbolicRegression": { "uuid": "8254be44-1295-4e6a-a16d-46603ac705cb", - "version": "=0.24.3" + "version": "=0.24.4" }, "Serialization": { "uuid": "9e88b42a-f829-5b0c-bbe9-9e923198166b", diff --git a/pysr/param_groupings.yml b/pysr/param_groupings.yml index 5c7dc4780..0ff9d63da 100644 --- a/pysr/param_groupings.yml +++ b/pysr/param_groupings.yml @@ -14,6 +14,7 @@ - loss_function - model_selection - dimensional_constraint_penalty + - dimensionless_constants_only - Working with Complexities: - parsimony - constraints diff --git a/pysr/sr.py b/pysr/sr.py index cb3a05c66..2f976ec1e 100644 --- a/pysr/sr.py +++ b/pysr/sr.py @@ -328,6 +328,9 @@ class PySRRegressor(MultiOutputMixin, RegressorMixin, BaseEstimator): dimensional_constraint_penalty : float Additive penalty for if dimensional analysis of an expression fails. By default, this is `1000.0`. + dimensionless_constants_only : bool + Whether to only search for dimensionless constants, if using units. + Default is `False`. use_frequency : bool Whether to measure the frequency of complexities, and use that instead of parsimony to explore equation space. Will naturally @@ -688,6 +691,7 @@ def __init__( complexity_of_variables: Union[int, float] = 1, parsimony: float = 0.0032, dimensional_constraint_penalty: Optional[float] = None, + dimensionless_constants_only: bool = False, use_frequency: bool = True, use_frequency_in_tournament: bool = True, adaptive_parsimony_scaling: float = 20.0, @@ -783,6 +787,7 @@ def __init__( self.complexity_of_variables = complexity_of_variables self.parsimony = parsimony self.dimensional_constraint_penalty = dimensional_constraint_penalty + self.dimensionless_constants_only = dimensionless_constants_only self.use_frequency = use_frequency self.use_frequency_in_tournament = use_frequency_in_tournament self.adaptive_parsimony_scaling = adaptive_parsimony_scaling @@ -1654,6 +1659,7 @@ def _run(self, X, y, mutated_params, weights, seed): # These have the same name: parsimony=self.parsimony, dimensional_constraint_penalty=self.dimensional_constraint_penalty, + dimensionless_constants_only=self.dimensionless_constants_only, alpha=self.alpha, maxdepth=maxdepth, fast_cycle=self.fast_cycle, From a664d90a35884a761353f2ce7ef85d9ebd6ac95b Mon Sep 17 00:00:00 2001 From: MilesCranmer Date: Thu, 2 May 2024 18:30:35 +0100 Subject: [PATCH 2/7] chore: move autload extensions to juliacall; update juliacall --- pysr/julia_import.py | 27 +++++---------------------- requirements.txt | 2 +- 2 files changed, 6 insertions(+), 23 deletions(-) diff --git a/pysr/julia_import.py b/pysr/julia_import.py index dc881bf21..f1c155136 100644 --- a/pysr/julia_import.py +++ b/pysr/julia_import.py @@ -35,32 +35,15 @@ os.environ[k] = os.environ.get(k, default) +autoload_extensions = os.environ.get("PYSR_AUTOLOAD_EXTENSIONS") +if autoload_extensions is not None: + # Deprecated; so just pass to juliacall + os.environ["PYTHON_JULIACALL_AUTOLOAD_IPYTHON_EXTENSION"] = autoload_extensions + from juliacall import Main as jl # type: ignore jl_version = (jl.VERSION.major, jl.VERSION.minor, jl.VERSION.patch) -# Next, automatically load the juliacall extension if we're in a Jupyter notebook -autoload_extensions = os.environ.get("PYSR_AUTOLOAD_EXTENSIONS", "yes") -if autoload_extensions in {"yes", ""} and jl_version >= (1, 9, 0): - try: - get_ipython = sys.modules["IPython"].get_ipython - - if "IPKernelApp" not in get_ipython().config: - raise ImportError("console") - - print( - "Detected Jupyter notebook. Loading juliacall extension. Set `PYSR_AUTOLOAD_EXTENSIONS=no` to disable." - ) - - # TODO: Turn this off if juliacall does this automatically - get_ipython().run_line_magic("load_ext", "juliacall") - except Exception: - pass -elif autoload_extensions not in {"no", "yes", ""}: - warnings.warn( - "PYSR_AUTOLOAD_EXTENSIONS environment variable is set to something other than 'yes' or 'no' or ''." - ) - jl.seval("using SymbolicRegression") SymbolicRegression = jl.SymbolicRegression diff --git a/requirements.txt b/requirements.txt index 27e6ce514..58ee1c411 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ sympy>=1.0.0,<2.0.0 pandas>=0.21.0,<3.0.0 numpy>=1.13.0,<2.0.0 scikit_learn>=1.0.0,<2.0.0 -juliacall==0.9.19 +juliacall==0.9.20 click>=7.0.0,<9.0.0 setuptools>=50.0.0 typing_extensions>=4.0.0,<5.0.0; python_version < "3.8" From bedf08534a5d12ed5877708d202ca9d84674ad38 Mon Sep 17 00:00:00 2001 From: MilesCranmer Date: Thu, 2 May 2024 18:38:42 +0100 Subject: [PATCH 3/7] chore: update python version constraints --- .github/workflows/CI.yml | 20 +++++++++---------- .github/workflows/CI_Windows.yml | 2 +- .github/workflows/CI_docker_large_nightly.yml | 2 +- .github/workflows/CI_large_nightly.yml | 4 ++-- .github/workflows/CI_mac.yml | 2 +- .github/workflows/docker_deploy.yml | 4 ++-- environment.yml | 2 +- pyproject.toml | 2 +- 8 files changed, 19 insertions(+), 19 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index b0624df88..1965d7810 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -32,12 +32,12 @@ jobs: strategy: matrix: julia-version: ['1'] - python-version: ['3.11'] + python-version: ['3.12'] os: [ubuntu-latest] test-id: [main] include: - julia-version: '1.6' - python-version: '3.7' + python-version: '3.8' os: ubuntu-latest test-id: include - julia-version: '1' @@ -99,11 +99,11 @@ jobs: strategy: matrix: os: ['ubuntu-latest'] - python-version: ['3.11'] + python-version: ['3.12'] julia-version: ['1'] include: - os: ubuntu-latest - python-version: '3.7' + python-version: '3.8' julia-version: '1.6' steps: - uses: actions/checkout@v4 @@ -122,7 +122,7 @@ jobs: shell: bash -l {0} strategy: matrix: - python-version: ['3.11'] + python-version: ['3.12'] os: ['ubuntu-latest'] steps: @@ -181,8 +181,8 @@ jobs: strategy: matrix: python-version: - - '3.11' - - '3.7' + - '3.12' + - '3.8' os: ['ubuntu-latest'] steps: @@ -199,10 +199,10 @@ jobs: pip install mypy - name: "Install additional dependencies" run: python -m pip install jax jaxlib torch - if: ${{ matrix.python-version != '3.7' }} + if: ${{ matrix.python-version != '3.8' }} - name: "Run mypy" run: python -m mypy --install-types --non-interactive pysr - if: ${{ matrix.python-version != '3.7' }} + if: ${{ matrix.python-version != '3.8' }} - name: "Run compatible mypy" run: python -m mypy --ignore-missing-imports pysr - if: ${{ matrix.python-version == '3.7' }} + if: ${{ matrix.python-version == '3.8' }} diff --git a/.github/workflows/CI_Windows.yml b/.github/workflows/CI_Windows.yml index c687b1790..49b471eed 100644 --- a/.github/workflows/CI_Windows.yml +++ b/.github/workflows/CI_Windows.yml @@ -30,7 +30,7 @@ jobs: strategy: matrix: julia-version: ['1'] - python-version: ['3.11'] + python-version: ['3.12'] os: [windows-latest] steps: diff --git a/.github/workflows/CI_docker_large_nightly.yml b/.github/workflows/CI_docker_large_nightly.yml index 2077247e7..561ce1551 100644 --- a/.github/workflows/CI_docker_large_nightly.yml +++ b/.github/workflows/CI_docker_large_nightly.yml @@ -19,7 +19,7 @@ jobs: fail-fast: false matrix: julia-version: ['1.6', '1'] - python-version: ['3.7', '3.11'] + python-version: ['3.8', '3.12'] os: [ubuntu-latest] arch: ['linux/amd64', 'linux/arm64'] diff --git a/.github/workflows/CI_large_nightly.yml b/.github/workflows/CI_large_nightly.yml index 973e25411..cbd9a7ef3 100644 --- a/.github/workflows/CI_large_nightly.yml +++ b/.github/workflows/CI_large_nightly.yml @@ -23,8 +23,8 @@ jobs: strategy: fail-fast: false matrix: - julia-version: ['1.6', '1.8', '1.9'] - python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] + julia-version: ['1.6', '1.8', '1.10'] + python-version: ['3.8', '3.10', '3.12'] os: [ubuntu-latest, macos-latest, windows-latest] steps: diff --git a/.github/workflows/CI_mac.yml b/.github/workflows/CI_mac.yml index 4c4a52908..e9763f0c7 100644 --- a/.github/workflows/CI_mac.yml +++ b/.github/workflows/CI_mac.yml @@ -30,7 +30,7 @@ jobs: strategy: matrix: julia-version: ['1'] - python-version: ['3.11'] + python-version: ['3.12'] os: [macos-latest] steps: diff --git a/.github/workflows/docker_deploy.yml b/.github/workflows/docker_deploy.yml index 6942944fd..097697010 100644 --- a/.github/workflows/docker_deploy.yml +++ b/.github/workflows/docker_deploy.yml @@ -18,8 +18,8 @@ jobs: matrix: os: [ubuntu-latest] arch: [linux/amd64] - python-version: [3.11.6] - julia-version: [1.9.4] + python-version: [3.12.3] + julia-version: [1.10.3] steps: - name: Checkout uses: actions/checkout@v4 diff --git a/environment.yml b/environment.yml index 610662e4d..24ba80de2 100644 --- a/environment.yml +++ b/environment.yml @@ -2,7 +2,7 @@ name: test channels: - conda-forge dependencies: - - python>=3.7 + - python>=3.8 - sympy>=1.0.0,<2.0.0 - pandas>=0.21.0,<3.0.0 - numpy>=1.13.0,<2.0.0 diff --git a/pyproject.toml b/pyproject.toml index 3a0d9d35d..550054815 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ authors = [ description = "Simple and efficient symbolic regression" readme = {file = "README.md", content-type = "text/markdown"} license = {file = "LICENSE"} -requires-python = ">=3.7" +requires-python = ">=3.8" classifiers = [ "Programming Language :: Python :: 3", "Operating System :: OS Independent", From f8e5f79dd3657b341ebd54c959729ee8ac309f7e Mon Sep 17 00:00:00 2001 From: MilesCranmer Date: Thu, 2 May 2024 18:54:34 +0100 Subject: [PATCH 4/7] chore: add ipykernel as dev dependency --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 550054815..94851ea67 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,4 +34,5 @@ profile = "black" dev-dependencies = [ "pre-commit>=3.7.0", "ipython>=8.23.0", + "ipykernel>=6.29.4", ] From 07a359d2efdcaf580da2890c9623ea382d331c75 Mon Sep 17 00:00:00 2001 From: MilesCranmer Date: Thu, 2 May 2024 19:45:28 +0100 Subject: [PATCH 5/7] fix: try moving to python juliapkg.json --- pyproject.toml | 1 - pysr/__init__.py | 9 ++++++++- pysr/juliapkg.json | 13 ------------- requirements.txt | 1 + 4 files changed, 9 insertions(+), 15 deletions(-) delete mode 100644 pysr/juliapkg.json diff --git a/pyproject.toml b/pyproject.toml index 94851ea67..85dfed46c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,6 @@ dynamic = ["dependencies"] [tool.setuptools] packages = ["pysr", "pysr._cli", "pysr.test"] include-package-data = false -package-data = {pysr = ["juliapkg.json"]} [tool.setuptools.dynamic] dependencies = {file = "requirements.txt"} diff --git a/pysr/__init__.py b/pysr/__init__.py index e71e19905..b90f6ef85 100644 --- a/pysr/__init__.py +++ b/pysr/__init__.py @@ -1,3 +1,11 @@ +import juliapkg + +juliapkg.require_julia("~1.6.7, ~1.7, ~1.8, ~1.9, =1.10.0, ^1.10.3") +juliapkg.add( + "SymbolicRegression", "8254be44-1295-4e6a-a16d-46603ac705cb", version="=0.24.4" +) +juliapkg.add("Serialization", "9e88b42a-f829-5b0c-bbe9-9e923198166b", version="1") + # This must be imported as early as possible to prevent # library linking issues caused by numpy/pytorch/etc. importing # old libraries: @@ -18,7 +26,6 @@ "sklearn_monkeypatch", "sympy2jax", "sympy2torch", - "Problem", "install", "PySRRegressor", "best", diff --git a/pysr/juliapkg.json b/pysr/juliapkg.json deleted file mode 100644 index db8de4ec1..000000000 --- a/pysr/juliapkg.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "julia": "~1.6.7, ~1.7, ~1.8, ~1.9, =1.10.0, ^1.10.3", - "packages": { - "SymbolicRegression": { - "uuid": "8254be44-1295-4e6a-a16d-46603ac705cb", - "version": "=0.24.4" - }, - "Serialization": { - "uuid": "9e88b42a-f829-5b0c-bbe9-9e923198166b", - "version": "1" - } - } -} diff --git a/requirements.txt b/requirements.txt index 58ee1c411..97081bb64 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,7 @@ pandas>=0.21.0,<3.0.0 numpy>=1.13.0,<2.0.0 scikit_learn>=1.0.0,<2.0.0 juliacall==0.9.20 +juliapkg==0.1.11 click>=7.0.0,<9.0.0 setuptools>=50.0.0 typing_extensions>=4.0.0,<5.0.0; python_version < "3.8" From 84bbcf78c072441b3fdbfb523a4d86882e945d91 Mon Sep 17 00:00:00 2001 From: MilesCranmer Date: Sat, 4 May 2024 21:35:13 +0100 Subject: [PATCH 6/7] test: remove old AUTOLOAD test --- pysr/test/test_startup.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pysr/test/test_startup.py b/pysr/test/test_startup.py index 3d716b515..8a93ad3a3 100644 --- a/pysr/test/test_startup.py +++ b/pysr/test/test_startup.py @@ -118,10 +118,6 @@ def test_bad_startup_options(self): code="import juliacall; import pysr", msg="juliacall module already imported.", ), - dict( - code='import os; os.environ["PYSR_AUTOLOAD_EXTENSIONS"] = "foo"; import pysr', - msg="PYSR_AUTOLOAD_EXTENSIONS environment variable is set", - ), ] for warning_test in warning_tests: result = subprocess.run( From 5824cd8eb28968a9e0f84e2ab37af1bef9461008 Mon Sep 17 00:00:00 2001 From: MilesCranmer Date: Sat, 4 May 2024 21:50:38 +0100 Subject: [PATCH 7/7] Revert "fix: try moving to python juliapkg.json" This reverts commit 07a359d2efdcaf580da2890c9623ea382d331c75. --- pyproject.toml | 1 + pysr/__init__.py | 9 +-------- pysr/juliapkg.json | 13 +++++++++++++ requirements.txt | 1 - 4 files changed, 15 insertions(+), 9 deletions(-) create mode 100644 pysr/juliapkg.json diff --git a/pyproject.toml b/pyproject.toml index 85dfed46c..94851ea67 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,6 +22,7 @@ dynamic = ["dependencies"] [tool.setuptools] packages = ["pysr", "pysr._cli", "pysr.test"] include-package-data = false +package-data = {pysr = ["juliapkg.json"]} [tool.setuptools.dynamic] dependencies = {file = "requirements.txt"} diff --git a/pysr/__init__.py b/pysr/__init__.py index b90f6ef85..e71e19905 100644 --- a/pysr/__init__.py +++ b/pysr/__init__.py @@ -1,11 +1,3 @@ -import juliapkg - -juliapkg.require_julia("~1.6.7, ~1.7, ~1.8, ~1.9, =1.10.0, ^1.10.3") -juliapkg.add( - "SymbolicRegression", "8254be44-1295-4e6a-a16d-46603ac705cb", version="=0.24.4" -) -juliapkg.add("Serialization", "9e88b42a-f829-5b0c-bbe9-9e923198166b", version="1") - # This must be imported as early as possible to prevent # library linking issues caused by numpy/pytorch/etc. importing # old libraries: @@ -26,6 +18,7 @@ "sklearn_monkeypatch", "sympy2jax", "sympy2torch", + "Problem", "install", "PySRRegressor", "best", diff --git a/pysr/juliapkg.json b/pysr/juliapkg.json new file mode 100644 index 000000000..db8de4ec1 --- /dev/null +++ b/pysr/juliapkg.json @@ -0,0 +1,13 @@ +{ + "julia": "~1.6.7, ~1.7, ~1.8, ~1.9, =1.10.0, ^1.10.3", + "packages": { + "SymbolicRegression": { + "uuid": "8254be44-1295-4e6a-a16d-46603ac705cb", + "version": "=0.24.4" + }, + "Serialization": { + "uuid": "9e88b42a-f829-5b0c-bbe9-9e923198166b", + "version": "1" + } + } +} diff --git a/requirements.txt b/requirements.txt index 97081bb64..58ee1c411 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,6 @@ pandas>=0.21.0,<3.0.0 numpy>=1.13.0,<2.0.0 scikit_learn>=1.0.0,<2.0.0 juliacall==0.9.20 -juliapkg==0.1.11 click>=7.0.0,<9.0.0 setuptools>=50.0.0 typing_extensions>=4.0.0,<5.0.0; python_version < "3.8"