# ModelingToolkit + IntervalConstraintProgramming: how to build expressions and contractors without "world age" problems or ambiguities

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
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...)

constraint_expression = constraint(x)
# 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

You should

1 Like

``````using ModelingToolkit
using IntervalArithmetic
using IntervalConstraintProgramming

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...)

constraint_expression = constraint(x)
# 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