Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.9 regression: calling function from within function is not same as calling from REPL #49756

Closed
odow opened this issue May 11, 2023 · 3 comments
Labels
regression Regression in behavior compared to a previous version

Comments

@odow
Copy link
Contributor

odow commented May 11, 2023

We have a very weird bug in the new Julia 1.9 release with InfiniteOpt: infiniteopt/InfiniteOpt.jl#316.

cc @pulsipher

The behavior is different when a function from JuMP is called within a function, or when called by the REPL.

Here's the a reproducible example. You'll need:

import Pkg; Pkg.add("InfiniteOpt")
(ifo) pkg> st
Status `/private/tmp/ifo/Project.toml`
  [20393b10] InfiniteOpt v0.5.7

julia> versioninfo()
Julia Version 1.9.0
Commit 8e630552924 (2023-05-07 11:25 UTC)
Platform Info:
  OS: macOS (x86_64-apple-darwin22.4.0)
  CPU: 8 × Intel(R) Core(TM) i5-8259U CPU @ 2.30GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-14.0.6 (ORCJIT, skylake)
  Threads: 1 on 8 virtual cores

julia> using InfiniteOpt

julia> function my_add_variable(model, v)
           y = InfiniteOpt.dispatch_variable_ref(v.infinite_variable_ref)
           JuMP.check_belongs_to_model(y, model)
           return
       end
my_add_variable (generic function with 1 method)

julia> m1 = InfiniteOpt.InfiniteModel();

julia> InfiniteOpt.@infinite_parameter(m1, p in [0, 1]);

julia> InfiniteOpt.@variable(m1, x, Infinite(p));

julia> v = JuMP.build_variable(
           error, 
           JuMP.VariableInfo(false, 0.0, false, 0.0, false, 0.0, false, 0.0, false, false), 
           InfiniteOpt.Point(x, 0.5),
       );

julia> m2 = InfiniteOpt.InfiniteModel();

julia> my_add_variable(m2, v)  # INCORRECT: When called via a function, does not error

julia> y = dispatch_variable_ref(v.infinite_variable_ref)
x(p)

julia> JuMP.check_belongs_to_model(y, m2)  # CORRECT: When called via REPL, does error
ERROR: VariableNotOwned{InfiniteVariableRef}(x(p))
Stacktrace:
 [1] check_belongs_to_model(v::InfiniteVariableRef, model::InfiniteModel)
   @ JuMP ~/.julia/packages/JuMP/AKvOr/src/variables.jl:282
 [2] top-level scope
   @ REPL[12]:1

I can't seem to reduce this down to a simpler example.

JuMP.check_belongs_to_model is https://github.com/jump-dev/JuMP.jl/blob/dd66846cd28b9cc65b82b8d6bb8de67162c83f8b/src/variables.jl#L280-L284
which is basically just

if owner_model(v) !== model
    throw(VariableNotOwned(v))
end

but if you replace the JuMP.check_belongs_to_model call with owner_model(v) !== model then things are the same.

@KristofferC
Copy link
Member

KristofferC commented May 11, 2023

Bisected to b3f25d7

cc @Keno

@odow
Copy link
Contributor Author

odow commented May 11, 2023

This wasn't reported earlier because despite InfiniteOpt testing on nightly, recent commits were passing:
https://github.com/infiniteopt/InfiniteOpt.jl/actions/runs/4878443048/jobs/8704079025

But I don't know if this was something that was fixed on master that needs back porting to 1.9, or if the bug is still there and it just doesn't trigger on CI for some reason.

On a recent nightly, I still get the bug:

julia> using InfiniteOpt

julia> function my_add_variable(model, v)
           y = InfiniteOpt.dispatch_variable_ref(v.infinite_variable_ref)
           JuMP.check_belongs_to_model(y, model)
           return
       end
my_add_variable (generic function with 1 method)

julia> m1 = InfiniteOpt.InfiniteModel();

julia> InfiniteOpt.@infinite_parameter(m1, p in [0, 1]);

julia> InfiniteOpt.@variable(m1, x, Infinite(p));

julia> v = JuMP.build_variable(
           error, 
           JuMP.VariableInfo(false, 0.0, false, 0.0, false, 0.0, false, 0.0, false, false), 
           InfiniteOpt.Point(x, 0.5),
       );

julia> m2 = InfiniteOpt.InfiniteModel();

julia> my_add_variable(m2, v)  # INCORRECT: When called via a function, does not error

julia> y = dispatch_variable_ref(v.infinite_variable_ref)
x(p)

julia> JuMP.check_belongs_to_model(y, m2)  # CORRECT: When called via REPL, does error
ERROR: VariableNotOwned{InfiniteVariableRef}(x(p))
Stacktrace:
 [1] check_belongs_to_model(v::InfiniteVariableRef, model::InfiniteModel)
   @ JuMP ~/.julia/packages/JuMP/AKvOr/src/variables.jl:282
 [2] top-level scope
   @ REPL[13]:1

julia> versioninfo()
Julia Version 1.10.0-DEV.1151
Commit b4d15302517 (2023-04-29 23:21 UTC)
Platform Info:
  OS: macOS (x86_64-apple-darwin21.5.0)
  CPU: 8 × Intel(R) Core(TM) i5-8259U CPU @ 2.30GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-14.0.6 (ORCJIT, skylake)
  Threads: 1 on 8 virtual cores

@brenhinkeller brenhinkeller added the regression Regression in behavior compared to a previous version label Aug 4, 2023
@vtjnash
Copy link
Member

vtjnash commented Feb 6, 2024

Correctly fails in v1.11. There have been many fixes to the effects system, particular for errors

julia> my_add_variable(m2, v)  # INCORRECT: When called via a function, does not error
ERROR: VariableNotOwned{InfiniteVariableRef}(x(p)): the variable x(p) cannot be used in this model because
it belongs to a different model.

@vtjnash vtjnash closed this as completed Feb 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
regression Regression in behavior compared to a previous version
Projects
None yet
Development

No branches or pull requests

4 participants