Closed meyde closed 1 year ago
bruteforce fix: just split the IfElse.ifelse into 2: IfElse.ifelse(var_a>0,IfElse.ifelse(var_b>0,1,0),0)
i still need to automatically do it for when i encounter a ":AND:" or an ":OR:", but that should not be too problematic.
This issue doesn't ring a bell. I suggest that you proceed with the transfer of the repo in the WorldDynamics organization so that I'll ping the others to have a look.
@aurorarossi @piluc @paulobruno does this ring any bell? Perhaps we encountered something similar before.
Yes, I have encountered this problem, but I can't remember how I fixed it. I will look into it.
I didn't reopen it since Mael did fix it in the way he explains, but we can compare with the solution we found back then.
Ok, I found where it happens when implementing Earth4All.jl
.
It was in the function pulse
, see the closed issue https://github.com/worlddynamics/Earth4All.jl/issues/5.
Emanule's version works by using register
, but in the end we used Pierluigi's version.
Ok, so in principle one can replace IfElse.ifelse(var_a > 0 && var_b <0,1,0)
with
f(x,y) = x > 0 && y < 0 ? 1 : 0
@register_symbolic f(x,y)
@meyde, in the OP, you mention something similar, but there you write @register symbolic And(a,b)
without underscore. Maybe there was a typo?
this was a typo in the comment, the problem here was not the register symbolic syntax, but that i did not encapsulate the fucntion large enough; i just did the "&&", so in the ifelse function there was a mistake.
and while this works for the pulse function, i don't think it is really more efficient to automatise this for every "&&" and "||".
right now what i'm doing is after the parsing, i do a BFS looking for if_then_else functions (as it's only here we can have ":AND:" and ":OR:" instruction, and change the children nodes of the if_then_else accordingly, creating nested if_then_elses
ModelingToolkit does not support boolean operations, whereas Vensim does. this leads to some problem.
example of a failed code: @variables var_a @variables var_b @variables var_c
var_c ~ IfElse.ifelse(var_a > 0 && var_b <0,1,0)
this fails with "TypeError: non-boolean (Num) used in boolean expression"
one fix i tried is registering an "And" function:
And(a,b)= a && b @register symbolic And(a,b)
[...]
var_c ~ IfElse.ifelse(And(var_a>0,var_b<0),1,0)
this fails with MethodError: no method matching ifelse(::SymbolicUtils.BasicSymbolic{Real}, ::Float64, ::Float64)