MilesCranmer / PySR

High-Performance Symbolic Regression in Python and Julia
https://astroautomata.com/PySR
Apache License 2.0
2.19k stars 207 forks source link

[BUG] Using Round #269

Closed mikamyrseth closed 1 year ago

mikamyrseth commented 1 year ago

Hi,

I've wanted to experiment with using round, floor and ceil operators, which seem to be working fine in Julia, but gives an error when evaluated to Sympy. I assume I need to use some kind of sympy mapping to mitigate this error, but I can't really figure out what the correct mapping would be.

I've tried: lambda x: x.round() lambda x: round(x) sp.round

Any ideas?

Version (please include the following information):

Traceback (most recent call last): File "/Users/mika/gutta-skriver-master/masters.py", line 128, in main() File "/Users/mika/gutta-skriver-master/masters.py", line 41, in main model.run_model( File "/Users/mika/gutta-skriver-master/CustomTypes/Model.py", line 123, in run_model model, prediction = symbolic_regression( File "/Users/mika/gutta-skriver-master/CustomTypes/Model.py", line 1048, in symbolic_regression model.fit(X=X_train, y=Y_train) File "/Users/mika/.pyenv/versions/3.10.2/lib/python3.10/site-packages/pysr/sr.py", line 1792, in fit self._run(X, y, mutated_params, weights=weights, seed=seed) File "/Users/mika/.pyenv/versions/3.10.2/lib/python3.10/site-packages/pysr/sr.py", line 1666, in run self.equations = self.get_hof() File "/Users/mika/.pyenv/versions/3.10.2/lib/python3.10/site-packages/pysr/sr.py", line 2118, in get_hof eqn = sympify(eqn_row["equation"], locals=local_sympy_mappings) File "/Users/mika/.pyenv/versions/3.10.2/lib/python3.10/site-packages/sympy/core/sympify.py", line 496, in sympify expr = parse_expr(a, local_dict=locals, transformations=transformations, evaluate=evaluate) File "/Users/mika/.pyenv/versions/3.10.2/lib/python3.10/site-packages/sympy/parsing/sympy_parser.py", line 1101, in parse_expr raise e from ValueError(f"Error from parse_expr with transformed code: {code!r}") File "/Users/mika/.pyenv/versions/3.10.2/lib/python3.10/site-packages/sympy/parsing/sympy_parser.py", line 1092, in parse_expr rv = eval_expr(code, local_dict, global_dict) File "/Users/mika/.pyenv/versions/3.10.2/lib/python3.10/site-packages/sympy/parsing/sympy_parser.py", line 907, in eval_expr expr = eval( File "", line 1, in File "/Users/mika/.pyenv/versions/3.10.2/lib/python3.10/site-packages/sympy/core/expr.py", line 3814, in round raise TypeError("Cannot round symbolic expression") TypeError: Cannot round symbolic expression

MilesCranmer commented 1 year ago

I don’t see any symbolic round for sympy. You could write your own sympy function though:

class round(sympy.Function):
    ...

which you could then pass as round to extra_sympy_functions. It will just show up in the output.

MilesCranmer commented 1 year ago

Would be nice to have this as a built-in though. If you get something working want to submit a PR? I will otherwise get to this eventually

MilesCranmer commented 1 year ago

Hey @mikamyrseth,

I figured out how to do this. While sympy does not have round, it does have ceiling. So, you can write:

import sympy

round = lambda x: sympy.ceiling(x - 0.5)

This works with symbolic expressions too:

In [5]: x = sympy.symbols("x")

In [6]: round(x * 2.1)
Out[6]: ceiling(2.1*x - 0.5)

(which is correct)

Let me know if there are any other issues! Cheers, Miles