Hi,
I’m facing a problem of “world age” that my Julia experience doesn’t allow me to comprehend very well. Here is a MWE that uses the ModelingToolkit and IntervalConstraintProgramming packages:
using ModelingToolkit
using IntervalArithmetic
using IntervalConstraintProgramming
# dynamic reformulation of the expression by adding a slack
function add_slack(constraint_expression)
new_variable = @variables s
return (constraint_expression - s, new_variable[1])
end
# contract the box wrt the constraint
function contract(box, constraint_expression, variables)
contractor = Contractor(variables, constraint_expression)
box = contractor(0..0, box)
return box
end
function constraint(x)
return x[1]*x[2]
end
# create the original variables
variables = @variables x[1:2]
# flatten to an array
variables = vcat(variables...)
# add the slack
constraint_expression = constraint(x)
(constraint_expression, new_variable) = add_slack(constraint_expression)
# create the array [x1, x2, s]
append!(variables, new_variable)
# create a box and contract it wrt constraint
box = IntervalBox(0..1, 0..1, 0..1)
box = contract(box, constraint_expression, variables)
I define a problem, reformulate it somehow (here I add a slack variable, but I could add arbitrarily many variables), generate a contractor and call it.
I get this error:
ERROR: LoadError: MethodError: no method matching (::IntervalConstraintProgramming.var"#31#32")(::IntervalBox{3,Float64})
The applicable method may be too new: running in world age 27984, while current world is 27986.
Somehow my logic is not Julia-compliant I must say that the scope of the ModelingToolkit variables eludes me.
Can you help me out? If possible, I’d like to keep the same structure (problem definition + reformulation + creation of contractor independently).
Thanks,
Charlie
Whatever is evaling in there, make it not use eval and instead use Runtime generated functions.
As Chris suggests, the problem is that Contractor
is using eval
to evaluate an expression, but then you are immediately calling contractor
within the same function.
To avoid the world-age problem you need to return to the “top level” before using a function created by eval
. Maybe we should indeed be using RuntimeGeneratedFunctions instead of eval.
1 Like
Thanks for your answers! I tried something like this:
using ModelingToolkit
using IntervalArithmetic
using IntervalConstraintProgramming
function add_slack(constraint_expression)
new_variable = @variables s
return (constraint_expression - s, new_variable[1])
end
function create_contractor(variables, constraint_expression)
return Contractor(variables, constraint_expression)
end
function constraint(x)
return x[1]*x[2]
end
function main()
# create the original variables
variables = @variables x[1:2]
# flatten to an array
variables = vcat(variables...)
# add the slack
constraint_expression = constraint(x)
(constraint_expression, new_variable) = add_slack(constraint_expression)
# create the array [x1, x2, s]
append!(variables, new_variable)
# create a box and contract it wrt constraint
box = IntervalBox(0..1, 0..1, 0..1)
contractor = create_contractor(variables, constraint_expression)
box = contractor(0..0, box)
println(box)
return box
end
main()
with the same result. What happens is absolutely not intuitive for me. The Contractor is now created and called in 2 different functions
That’s still the same world age. You want to call contractor
via Base.invokelatest(contractor, 0..0, box)
, but note that this will infer to Any
and have some overhead.
Or just don’t put it in a main function.
But @dpsanders knows what’s up and this’ll presumably get fixed in the package soon.
2 Likes
You’re still inside the main()
function. You don’t get back to top level (global scope).
Got it this time Thanks a lot!
1 Like