Skip to content

Commit

Permalink
Merge branch 'v0.7.x-release'
Browse files Browse the repository at this point in the history
  • Loading branch information
manuelma committed Nov 22, 2024
2 parents 1f67784 + 2900340 commit c546ca4
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 60 deletions.
2 changes: 2 additions & 0 deletions src/SpineInterface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export add_object_parameter_values!
export add_object_parameter_defaults!
export add_object!
export add_objects!
export add_parameter_values!
export add_relationship_parameter_values!
export add_relationship_parameter_defaults!
export add_relationship!
Expand All @@ -57,6 +58,7 @@ export db_api
export db_value
export db_value_and_type
export difference
export dimensions
export duration
export end_
export export_data
Expand Down
16 changes: 13 additions & 3 deletions src/api/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -531,9 +531,10 @@ function add_objects!(object_class::ObjectClass, objects::Array)
end

function add_object_parameter_values!(object_class::ObjectClass, parameter_values::Dict; merge_values=false)
add_objects!(object_class, collect(keys(parameter_values)))
add_objects!(object_class, only.(keys(parameter_values)))
do_merge! = merge_values ? mergewith!(merge!) : merge!
for (obj, vals) in parameter_values
obj = only(obj)
do_merge!(object_class.parameter_values[obj], vals)
end
end
Expand Down Expand Up @@ -586,6 +587,13 @@ function add_relationship!(relationship_class::RelationshipClass, relationship::
add_relationships!(relationship_class, [relationship])
end

function add_parameter_values!(cls::ObjectClass, vals; kwargs...)
add_object_parameter_values!(cls, vals; kwargs...)
end
function add_parameter_values!(cls::RelationshipClass, vals; kwargs...)
add_relationship_parameter_values!(cls, vals; kwargs...)
end

"""
object_classes(m=@__MODULE__)
Expand Down Expand Up @@ -708,7 +716,9 @@ function add_dimension!(cls::RelationshipClass, name::Symbol, obj)
nothing
end

const __active_env = Ref(:base)
dimensions(cls::RelationshipClass) = cls.object_class_names

const __active_env = Ref(:__base__)

function _activate_env(env::Symbol)
__active_env[] = env
Expand All @@ -724,4 +734,4 @@ function with_env(f::Function, env::Symbol)
finally
_activate_env(prev_env)
end
end
end
2 changes: 2 additions & 0 deletions src/base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,8 @@ Base.max(x::Call, y::Call) = Call(max, [x, y])
Base.max(x::Call, y) = Call(max, [x, y])
Base.max(x, y::Call) = Call(max, [x, y])

Base.round(x::Call, r=RoundToZero) = Call(round, [x, r])

_arg(x::Call) = _arg(x.func, x)
_arg(::Nothing, x) = x.args[1]
_arg(::T, x) where T = x
Expand Down
115 changes: 60 additions & 55 deletions src/update_model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,16 @@ import .JuMP: MOI, MOIU, _MA as MutableArithmetics

_Constant = Union{Number,UniformScaling}

const _si_ext_lock = ReentrantLock()

struct SpineInterfaceExt
lower_bound::Dict{VariableRef,Any}
upper_bound::Dict{VariableRef,Any}
fixer::Dict{VariableRef,Any}
SpineInterfaceExt() = new(Dict(), Dict(), Dict())
end

function _get_si_ext!(f, m)
lock(_si_ext_lock) do
ext = get!(m.ext, :spineinterface) do
SpineInterfaceExt()
end
f(ext)
function _get_si_ext!(m)
get!(m.ext, :spineinterface) do
SpineInterfaceExt()
end
end

Expand Down Expand Up @@ -143,26 +138,28 @@ Base.show(io::IO, upd::_ObjectiveCoefficientUpdate) = print(
(upd::_VariableLBUpdate)() = _set_lower_bound(upd.variable, realize(upd.call, upd))
(upd::_VariableUBUpdate)() = _set_upper_bound(upd.variable, realize(upd.call, upd))
(upd::_VariableFixValueUpdate)() = _fix(upd, realize(upd.call, upd))
(upd::_ObjectiveCoefficientUpdate)() = set_objective_coefficient(upd.model, upd.variable, realize(upd.call, upd))
function (upd::_ObjectiveCoefficientUpdate)()
set_objective_coefficient(upd.model, upd.variable, _realize_finite(upd.call, upd))
end
function (upd::_ConstraintCoefficientUpdate)()
set_normalized_coefficient(upd.constraint[], upd.variable, realize(upd.call, upd))
set_normalized_coefficient(upd.constraint[], upd.variable, _realize_finite(upd.call, upd))
end
(upd::_RHSUpdate)() = set_normalized_rhs(upd.constraint[], realize(upd.call, upd))
(upd::_RHSUpdate)() = set_normalized_rhs(upd.constraint[], _realize_finite(upd.call, upd))
function (upd::_LowerBoundUpdate)()
constraint = upd.constraint[]
model = owner_model(constraint)
upper = MOI.get(model, MOI.ConstraintSet(), constraint).upper
MOI.set(model, MOI.ConstraintSet(), constraint, MOI.Interval(realize(upd.call, upd), upper))
MOI.set(model, MOI.ConstraintSet(), constraint, MOI.Interval(_realize_finite(upd.call, upd), upper))
end
function (upd::_UpperBoundUpdate)()
constraint = upd.constraint[]
model = owner_model(constraint)
lower = MOI.get(model, MOI.ConstraintSet(), constraint).lower
MOI.set(model, MOI.ConstraintSet(), constraint, MOI.Interval(lower, realize(upd.call, upd)))
MOI.set(model, MOI.ConstraintSet(), constraint, MOI.Interval(lower, _realize_finite(upd.call, upd)))
end
(upd::_ExprBoundUpdate)() = _set_expr_bound(upd.constraint, upd.coefficient_updates, realize(upd.call, upd))
function (upd::_PausableConstraintCoefficientUpdate)()
new_coef = realize(upd.call, upd)
new_coef = _realize_finite(upd.call, upd)
upd.paused[] || set_normalized_coefficient(upd.constraint, upd.variable, new_coef)
end

Expand All @@ -186,9 +183,8 @@ function _set_lower_bound(var, lb)
if is_fixed(var)
# Save bound
m = owner_model(var)
_get_si_ext!(m) do ext
ext.lower_bound[var] = lb
end
ext = _get_si_ext!(m)
ext.lower_bound[var] = lb
elseif isfinite(lb)
set_lower_bound(var, lb)
end
Expand All @@ -210,9 +206,8 @@ function _set_upper_bound(var, ub)
if is_fixed(var)
# Save bound
m = owner_model(var)
_get_si_ext!(m) do ext
ext.upper_bound[var] = ub
end
ext =_get_si_ext!(m)
ext.upper_bound[var] = ub
elseif isfinite(ub)
set_upper_bound(var, ub)
end
Expand All @@ -236,41 +231,39 @@ _fix(_upd, ::Nothing) = nothing
function _fix(upd, fix_value)
var = upd.variable
m = owner_model(var)
_get_si_ext!(m) do ext
if !isnan(fix_value)
# Save bounds, remove them and then fix the value
if has_lower_bound(var)
ext.lower_bound[var] = lower_bound(var)
delete_lower_bound(var)
end
if has_upper_bound(var)
ext.upper_bound[var] = upper_bound(var)
delete_upper_bound(var)
end
fix(var, fix_value)
ext.fixer[var] = upd
elseif is_fixed(var) && get(ext.fixer, var, nothing) === upd
# Unfix the variable and restore saved bounds
unfix(var)
lb = pop!(ext.lower_bound, var, NaN)
ub = pop!(ext.upper_bound, var, NaN)
if isfinite(lb)
set_lower_bound(var, lb)
end
if isfinite(ub)
set_upper_bound(var, ub)
end
ext.fixer[var] = nothing
ext = _get_si_ext!(m)
if !isnan(fix_value)
# Save bounds, remove them and then fix the value
if has_lower_bound(var)
ext.lower_bound[var] = lower_bound(var)
delete_lower_bound(var)
end
if has_upper_bound(var)
ext.upper_bound[var] = upper_bound(var)
delete_upper_bound(var)
end
fix(var, fix_value)
ext.fixer[var] = upd
elseif is_fixed(var) && get(ext.fixer, var, nothing) === upd
# Unfix the variable and restore saved bounds
unfix(var)
lb = pop!(ext.lower_bound, var, NaN)
ub = pop!(ext.upper_bound, var, NaN)
if isfinite(lb)
set_lower_bound(var, lb)
end
if isfinite(ub)
set_upper_bound(var, ub)
end
ext.fixer[var] = nothing
end
end

function fixer(var)
m = owner_model(var)
_get_si_ext!(m) do ext
upd = get(ext.fixer, var, nothing)
upd isa AbstractUpdate ? upd.call : nothing
end
ext = _get_si_ext!(m)
upd = get(ext.fixer, var, nothing)
upd isa AbstractUpdate ? upd.call : nothing
end

_Sense = Union{typeof(==),typeof(<=),typeof(>=)}
Expand Down Expand Up @@ -406,28 +399,40 @@ end
# realize
function realize(s::_GreaterThanCall, con_ref)
c = MOI.constant(s)
MOI.GreaterThan(Float64(realize(c, _RHSUpdate(con_ref, c))))
MOI.GreaterThan(Float64(_realize_finite(c, _RHSUpdate(con_ref, c))))
end
function realize(s::_LessThanCall, con_ref)
c = MOI.constant(s)
MOI.LessThan(Float64(realize(c, _RHSUpdate(con_ref, c))))
MOI.LessThan(Float64(_realize_finite(c, _RHSUpdate(con_ref, c))))
end
function realize(s::_EqualToCall, con_ref)
c = MOI.constant(s)
MOI.EqualTo(Float64(realize(c, _RHSUpdate(con_ref, c))))
MOI.EqualTo(Float64(_realize_finite(c, _RHSUpdate(con_ref, c))))
end
function realize(s::_CallInterval, con_ref)
l, u = s.lower, s.upper
MOI.Interval(Float64(realize(l, _LowerBoundUpdate(con_ref, l))), Float64(realize(u, _UpperBoundUpdate(con_ref, u))))
MOI.Interval(
Float64(_realize_finite(l, _LowerBoundUpdate(con_ref, l))),
Float64(_realize_finite(u, _UpperBoundUpdate(con_ref, u))),
)
end
function realize(e::GenericAffExpr{C,VariableRef}, model_or_con_ref=nothing) where {C}
constant = Float64(realize(e.constant))
constant = Float64(_realize_finite(e.constant))
terms = OrderedDict{VariableRef,Float64}(
var => realize(coef, _coefficient_update(model_or_con_ref, var, coef)) for (var, coef) in e.terms
var => _realize_finite(coef, _coefficient_update(model_or_con_ref, var, coef)) for (var, coef) in e.terms
)
GenericAffExpr(constant, terms)
end

function _realize_finite(x, upd=nothing)
v = realize(x, upd)
isfinite(v) && return v
error(
"the expression below resulted in a non-finite value - this is probably due to missing time-series data:\n\n$x"
)
end


_coefficient_update(m::Model, v, coef) = _ObjectiveCoefficientUpdate(m, v, coef)
_coefficient_update(cr::Ref{ConstraintRef}, v, coef) = _ConstraintCoefficientUpdate(cr, v, coef)
_coefficient_update(::Nothing, _v, _coef) = nothing
Expand Down
5 changes: 3 additions & 2 deletions src/util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ function _do_get_pvals(pvals_by_entity, entity)
end
end

_find_match(pvals_by_entity, x) = nothing
_find_match(pvals_by_entity, ::Missing) = nothing
_find_match(pvals_by_entity, ::NTuple{N,Missing}) where N = nothing
function _find_match(pvals_by_entity, objects::Tuple)
Expand Down Expand Up @@ -112,7 +113,7 @@ end

_do_realize(x, _upd) = x
_do_realize(call::Call, upd) = _do_realize(call.func, call, upd)
_do_realize(::Nothing, call, _upd) = call.args[1]
_do_realize(::Nothing, call, _upd) = realize(call.args[1])
function _do_realize(pv::T, call, upd) where T<:ParameterValue
pv(upd; call.kwargs...)
end
Expand All @@ -129,7 +130,7 @@ function _do_realize(::T, call, upd) where T<:Function
continue
else
# no children, realize value
current.value[] = _do_realize(current.call, upd)
current.value[] = realize(current.call, upd)
end
current.parent === nothing && break
if current.child_number < length(current.parent.call.args)
Expand Down

0 comments on commit c546ca4

Please sign in to comment.