Skip to content

Operators

Pre-defined

First, note that pretty much any valid Julia function which takes one or two scalars as input, and returns on scalar as output, is likely to be a valid operator[1]. A selection of these and other valid operators are stated below.

Also, note that it's a good idea to not use too many operators, since it can exponentially increase the search space.

Unary Operators

BasicExp/LogTrigHyperbolicSpecialRounding
negexpsinsinherfround
squarelogcoscosherfcfloor
cubelog10tantanhgammaceil
cbrtlog2asinasinhrelu
sqrtlog1pacosacoshsinc
absatanatanh
sign
inv

Binary Operators

ArithmeticComparisonLogic
+maxlogical_or[2]
-minlogical_and[3]
*>[4]
/>=
^<
<=
cond[5]
mod

Higher Arity Operators

Ternary
clamp
fma / muladd
max
min

Note that to use operators with arity 3 or more, you must use the operators parameter instead of the *ary_operators parameters, and pass operators as a dictionary with the arity as key:

python
operators={
    1: ["sin"], 2: ["+", "-", "*"], 3: ["clamp"]
},

Custom

Instead of passing a predefined operator as a string, you can just define a custom function as Julia code. For example:

python
    PySRRegressor(
        ...,
        unary_operators=["myfunction(x) = x^2"],
        binary_operators=["myotherfunction(x, y) = x^2*y"],
        extra_sympy_mappings={
            "myfunction": lambda x: x**2,
            "myotherfunction": lambda x, y: x**2 * y,
        },
    )

Make sure that it works with Float32 as a datatype (for default precision, or Float64 if you set precision=64). That means you need to write 1.5f3 instead of 1.5e3, if you write any constant numbers, or simply convert a result to Float64(...).

PySR expects that operators not throw an error for any input value over the entire real line from -3.4e38 to +3.4e38. Thus, for invalid inputs, such as negative numbers to a sqrt function, you may simply return a NaN of the same type as the input. For example,

julia
my_sqrt(x) = x >= 0 ? sqrt(x) : convert(typeof(x), NaN)

would be a valid operator. The genetic algorithm will preferentially selection expressions which avoid any invalid values over the training dataset.


  1. However, you will need to define a sympy equivalent in extra_sympy_mapping if you want to use a function not in the above list. ↩︎

  2. logical_or is equivalent to (x, y) -> (x > 0 || y > 0) ? 1 : 0 ↩︎

  3. logical_and is equivalent to (x, y) -> (x > 0 && y > 0) ? 1 : 0 ↩︎

  4. > is equivalent to (x, y) -> x > y ? 1 : 0 ↩︎

  5. cond is equivalent to (x, y) -> x > 0 ? y : 0 ↩︎