Can I add roll as a custom unary operator #426
-
Hi! Forgive me if my question is dumb - am very new to I would like to implement a custom unary operator unary_operators=[
"roll(x) = vcat(x[end:end], x[1:end - 1])",
], Basically I tried to implement the roll function in julia (implemented with This run into errors:
I know that what I am doing is probably wrong. My questions is actually whether this is achievable. If so, how to do that? Thanks! |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 3 replies
-
Hi @breakds, All operators are only defined on 1 or 2 real numbers. So you cannot, by default, define operators on vectors like in your example. However, this is possible by writing your own custom evaluation scheme. Take a look at https://astroautomata.com/PySR/api/#the-objective for an example, and also https://astroautomata.com/PySR/backend/ for info about customizing behavior. You would essentially need to write a custom Basically, you would edit function _eval_tree_array(
tree::Node{T}, cX::AbstractMatrix{T}, operators::OperatorEnum, ::Val{turbo}
)::Tuple{AbstractVector{T},Bool} where {T<:Number,turbo}
# First, we see if there are only constants in the tree - meaning
# we can just return the constant result.
if tree.degree == 0
return deg0_eval(tree, cX)
elseif tree.degree == 1
op = operators.unaops[tree.op]
# op(x), for any x.
(cumulator, complete) = _eval_tree_array(tree.l, cX, operators, Val(turbo))
@return_on_false complete cumulator
@return_on_nonfinite_array cumulator
return deg1_eval(cumulator, op, Val(turbo))
elseif tree.degree == 2
op = operators.binops[tree.op]
(cumulator_l, complete) = _eval_tree_array(tree.l, cX, operators, Val(turbo))
@return_on_false complete cumulator_l
@return_on_nonfinite_array cumulator_l
(cumulator_r, complete) = _eval_tree_array(tree.r, cX, operators, Val(turbo))
@return_on_false complete cumulator_r
@return_on_nonfinite_array cumulator_r
# op(x, y), for any x or y
return deg2_eval(cumulator_l, cumulator_r, op, Val(turbo))
end
end and then write a custom import DynamicExpressions.EvaluateEquationModule: deg1_eval
# Add an additional method to `deg1_eval` to customize the behavior for roll:
function deg1_eval(cumulator::AbstractVector{T}, ::typeof(roll), ::Val{turbo}) where {T<:Number,turbo}
cumulator = roll(cumulator)
return (cumulator, true)
end This is needed because the normal roll(x) = vcat(x[end:end], x[1:end - 1]) In Julia you can write specialized methods for particular types of arguments. In this case |
Beta Was this translation helpful? Give feedback.
-
Thanks a lot for the prompt response, @MilesCranmer ! Seems that after running Appreciate your help! |
Beta Was this translation helpful? Give feedback.
Hi @breakds,
All operators are only defined on 1 or 2 real numbers. So you cannot, by default, define operators on vectors like in your example.
However, this is possible by writing your own custom evaluation scheme. Take a look at https://astroautomata.com/PySR/api/#the-objective for an example, and also https://astroautomata.com/PySR/backend/ for info about customizing behavior.
You would essentially need to write a custom
eval_tree_array
that can handleroll
.Basically, you would edit
_eval_tree_array
in DynamicExpressions.jl to be (copying from https://github.com/SymbolicML/DynamicExpressions.jl/blob/46388518281b0be12479afcb3a3b8bdabc361ccd/src/EvaluateEquation.jl and then simplifying)…