Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/src/guide/derivative.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
```@meta
DocTestFilters = [r"≥|>=", r" == | = ", r" ∈ | in ", r" for all | ∀ ", r"d|∂",
r"integral|∫", r".*scalar_parameters.jl:813"]
r"integral|∫", r".*scalar_parameters.jl:807"]
```

# [Derivative Operators](@id deriv_docs)
Expand Down Expand Up @@ -509,7 +509,7 @@ julia> derivative_constraints(d1)

julia> add_supports(t, 0.2)
┌ Warning: Support/method changes will invalidate existing derivative evaluation constraints that have been added to the InfiniteModel. Thus, these are being deleted.
└ @ InfiniteOpt ~/work/infiniteopt/InfiniteOpt.jl/src/scalar_parameters.jl:813
└ @ InfiniteOpt ~/work/infiniteopt/InfiniteOpt.jl/src/scalar_parameters.jl:807

julia> has_derivative_constraints(d1)
false
Expand Down
2 changes: 0 additions & 2 deletions docs/src/manual/expression.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,4 @@ InfiniteOpt._constraint_dependencies
InfiniteOpt._constraint_dependencies(::GeneralVariableRef)
InfiniteOpt._derivative_constraint_dependencies
InfiniteOpt._derivative_constraint_dependencies(::GeneralVariableRef)
InfiniteOpt._parameter_number
InfiniteOpt._parameter_number(::GeneralVariableRef)
```
13 changes: 9 additions & 4 deletions src/TranscriptionOpt/measures.jl
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,12 @@ function InfiniteOpt.add_semi_infinite_variable(
InfiniteOpt.SemiInfiniteVariableIndex
)
push!(semi_infinite_vars, var)
ivref_param_nums = InfiniteOpt._parameter_numbers(ivref)
param_nums = var.parameter_nums
ivref_pref_supp_idxs = data.infvar_param_idxs[ivref]
pref_supp_idxs = [
ivref_pref_supp_idxs[i]
for i in eachindex(ivref_pref_supp_idxs)
if isnan(eval_supp[i])
]
supp_indices = support_index_iterator(backend, var.group_int_idxs)
if ivref.index_type == InfiniteOpt.ParameterFunctionIndex &&
!data.update_parameter_functions
Expand All @@ -95,9 +99,9 @@ function InfiniteOpt.add_semi_infinite_variable(
sizehint!(lookup_dict, length(supp_indices))
for i in supp_indices
raw_supp = index_to_support(backend, i)
ivref_supp = [isnan(s) ? raw_supp[ivref_param_nums[j]] : s
ivref_supp = [isnan(s) ? raw_supp[ivref_pref_supp_idxs[j]] : s
for (j, s) in enumerate(eval_supp)]
supp = raw_supp[param_nums]
supp = raw_supp[pref_supp_idxs]
lookup_dict[supp] = lookup_by_support(ivref, backend, ivref_supp)
end
if val_type == JuMP.VariableRef
Expand All @@ -106,6 +110,7 @@ function InfiniteOpt.add_semi_infinite_variable(
data.pfunc_lookup[rvref] = lookup_dict
end
data.semi_lookup[(ivref, eval_supp)] = rvref
data.infvar_param_idxs[rvref] = pref_supp_idxs
return rvref
end
end
6 changes: 6 additions & 0 deletions src/TranscriptionOpt/model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ mutable struct TranscriptionData

# Metadata
valid_indices::Dict{Any, Array{Bool}}
infvar_param_idxs::Dict{InfiniteOpt.GeneralVariableRef, Vector{Int}}

# Internal variables (created via internal measure expansions)
semi_infinite_vars::Vector{InfiniteOpt.SemiInfiniteVariable{InfiniteOpt.GeneralVariableRef}}
Expand All @@ -45,6 +46,7 @@ mutable struct TranscriptionData
# Collected Supports
supports::Tuple
support_labels::Tuple
param_to_support_idx::Dict{InfiniteOpt.GeneralVariableRef, Int}
has_internal_supports::Bool

# Default constructor
Expand All @@ -61,6 +63,7 @@ mutable struct TranscriptionData
Dict{InfiniteOpt.GeneralVariableRef, Float64}(),
# meta data
Dict{Any, Array{Bool}}(),
Dict{InfiniteOpt.GeneralVariableRef, Vector{Int}}(),
# internal variables
Vector{InfiniteOpt.SemiInfiniteVariable{InfiniteOpt.GeneralVariableRef}}(),
Dict{Tuple{InfiniteOpt.GeneralVariableRef, Vector{Float64}}, InfiniteOpt.GeneralVariableRef}(),
Expand All @@ -76,6 +79,7 @@ mutable struct TranscriptionData
# support storage
(),
(),
Dict{InfiniteOpt.GeneralVariableRef, Int}(),
false,
)
end
Expand All @@ -90,6 +94,7 @@ function Base.empty!(data::TranscriptionData)
empty!(data.pfunc_lookup)
empty!(data.point_pfunc_mappings)
empty!(data.valid_indices)
empty!(data.infvar_param_idxs)
empty!(data.semi_infinite_vars)
empty!(data.semi_lookup)
data.last_point_index = 0
Expand All @@ -101,6 +106,7 @@ function Base.empty!(data::TranscriptionData)
empty!(data.constr_supports)
data.supports = ()
data.support_labels = ()
empty!(data.param_to_support_idx)
data.has_internal_supports = false
return data
end
Expand Down
89 changes: 53 additions & 36 deletions src/TranscriptionOpt/transcribe.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ function set_parameter_supports(
end for (i, group) in enumerate(prefs))
data.supports = supps
data.support_labels = labels
# Add the paramter index mapping
vt_prefs = InfiniteOpt.Collections.VectorTuple(prefs)
idx = 1
for p in vt_prefs
data.param_to_support_idx[p] = idx
idx += 1
end
return
end

Expand Down Expand Up @@ -110,8 +117,8 @@ end
const _MaxNumParamsForPrinting = 4

# Make variable name with infinite parameters values directly if possible
function _make_var_name(base_name, param_nums, tuple_supp, var_idx)
if length(param_nums) <= _MaxNumParamsForPrinting
function _make_var_name(base_name, pref_supp_idxs, tuple_supp, var_idx)
if length(pref_supp_idxs) <= _MaxNumParamsForPrinting
return string(base_name, "(", join(tuple_supp, ", "), ")")
else
return string(base_name, "[", join(var_idx, ", "), "]")
Expand Down Expand Up @@ -141,10 +148,10 @@ function transcribe_parameter_functions!(
# get the basic parameter function information
pf = object.func
base_name = object.name
param_nums = pf.parameter_nums
group_idxs = pf.group_int_idxs
prefs = pf.parameter_refs
data = transcription_data(backend)
pref_supp_idxs = Int[data.param_to_support_idx[p] for p in prefs]
# prepare for iterating over its supports
supp_indices = support_index_iterator(backend, group_idxs)
dims = size(supp_indices)[group_idxs]
Expand All @@ -155,12 +162,12 @@ function transcribe_parameter_functions!(
lookup_dict = sizehint!(Dict{Vector{Float64}, val_type}(), length(vrefs))
# Create a parameter for each support
for i in supp_indices
supp = index_to_support(backend, i)[param_nums]
supp = index_to_support(backend, i)[pref_supp_idxs]
var_idx = i.I[group_idxs]
tuple_supp = Tuple(supp, prefs)
p_value = pf(tuple_supp...)
if data.update_parameter_functions
p_name = _make_var_name(base_name, param_nums, tuple_supp, var_idx)
p_name = _make_var_name(base_name, pref_supp_idxs, tuple_supp, var_idx)
jump_pref = JuMP.@variable(
backend.model,
base_name = p_name,
Expand All @@ -182,6 +189,7 @@ function transcribe_parameter_functions!(
end
data.infvar_mappings[pfref] = vrefs
data.infvar_supports[pfref] = supps
data.infvar_param_idxs[pfref] = pref_supp_idxs
end
return
end
Expand Down Expand Up @@ -217,9 +225,11 @@ end

# Helper function for transcribing infinite variables/derivatives
function _transcribe_infinite_variable(backend, vref, base_name, info)
param_nums = InfiniteOpt._parameter_numbers(vref)
# basic information
group_idxs = InfiniteOpt.parameter_group_int_indices(vref)
prefs = InfiniteOpt.raw_parameter_refs(vref)
data = transcription_data(backend)
pref_supp_idxs = Int[data.param_to_support_idx[p] for p in prefs]
# prepare for iterating over its supports
supp_indices = support_index_iterator(backend, group_idxs)
dims = size(supp_indices)[group_idxs]
Expand All @@ -229,23 +239,23 @@ function _transcribe_infinite_variable(backend, vref, base_name, info)
lookup_dict = sizehint!(Dict{Vector{Float64}, JuMP.VariableRef}(), length(vrefs))
# create a variable for each support
for i in supp_indices
supp = index_to_support(backend, i)[param_nums]
supp = index_to_support(backend, i)[pref_supp_idxs]
new_info = _format_infinite_info(info, supp)
var_idx = i.I[group_idxs]
tuple_supp = Tuple(supp, prefs)
name = _make_var_name(base_name, param_nums, tuple_supp, var_idx)
name = _make_var_name(base_name, pref_supp_idxs, tuple_supp, var_idx)
var = JuMP.ScalarVariable(new_info)
jump_vref = JuMP.add_variable(backend.model, var, name)
@inbounds vrefs[var_idx...] = jump_vref
lookup_dict[supp] = jump_vref
@inbounds supps[var_idx...] = tuple_supp
end
# save the transcription information
data = transcription_data(backend)
gvref = InfiniteOpt.GeneralVariableRef(vref)
data.infvar_lookup[gvref] = lookup_dict
data.infvar_mappings[gvref] = vrefs
data.infvar_supports[gvref] = supps
data.infvar_param_idxs[gvref] = pref_supp_idxs
return
end

Expand Down Expand Up @@ -379,11 +389,12 @@ function transcribe_semi_infinite_variables!(
rvref = InfiniteOpt.GeneralVariableRef(model, idx)
# setup the mappings
ivref = var.infinite_variable_ref
param_nums = var.parameter_nums
ivref_param_nums = InfiniteOpt._parameter_numbers(ivref)
eval_supp = var.eval_support
group_idxs = var.group_int_idxs
prefs = InfiniteOpt.raw_parameter_refs(var)
data = transcription_data(backend)
pref_supp_idxs = Int[data.param_to_support_idx[p] for p in prefs]
ivref_pref_supp_idxs = data.infvar_param_idxs[ivref]
# prepare for iterating over its supports
data = transcription_data(backend)
supp_indices = support_index_iterator(backend, group_idxs)
Expand All @@ -403,8 +414,8 @@ function transcribe_semi_infinite_variables!(
raw_supp = index_to_support(backend, i)
var_idx = i.I[group_idxs]
# map to the current transcription variable
supp = raw_supp[param_nums]
ivref_supp = [isnan(s) ? raw_supp[ivref_param_nums[j]] : s
supp = raw_supp[pref_supp_idxs]
ivref_supp = [isnan(s) ? raw_supp[ivref_pref_supp_idxs[j]] : s
for (j, s) in enumerate(eval_supp)]
jump_vref = lookup_by_support(ivref, backend, ivref_supp)
@inbounds vrefs[var_idx...] = jump_vref
Expand All @@ -421,6 +432,7 @@ function transcribe_semi_infinite_variables!(
else
data.pfunc_lookup[rvref] = lookup_dict
end
data.infvar_param_idxs[rvref] = pref_supp_idxs
end
return
end
Expand Down Expand Up @@ -499,20 +511,15 @@ function transcription_expression(
index_type::Type{V},
backend::TranscriptionBackend,
support::Vector{Float64}
) where {V <: Union{InfVarIndex, InfiniteOpt.ParameterFunctionIndex, InfiniteOpt.MeasureIndex}}
param_nums = InfiniteOpt._parameter_numbers(vref)
return lookup_by_support(vref, index_type, backend, support[param_nums])
end

# Semi-Infinite variables
function transcription_expression(
vref::InfiniteOpt.GeneralVariableRef,
index_type::Type{InfiniteOpt.SemiInfiniteVariableIndex},
backend::TranscriptionBackend,
support::Vector{Float64}
)
param_nums = InfiniteOpt._parameter_numbers(vref)
return lookup_by_support(vref, index_type, backend, support[param_nums])
) where {V <: Union{
InfVarIndex,
InfiniteOpt.ParameterFunctionIndex,
InfiniteOpt.MeasureIndex,
InfiniteOpt.SemiInfiniteVariableIndex}
}
data = transcription_data(backend)
pref_supp_idxs = data.infvar_param_idxs[vref]
return lookup_by_support(vref, index_type, backend, support[pref_supp_idxs])
end

# Point variables, finite variables and finite parameters
Expand All @@ -532,8 +539,8 @@ function transcription_expression(
backend::TranscriptionBackend,
support::Vector{Float64}
) where {V <: InfiniteOpt.InfiniteParameterIndex}
param_num = InfiniteOpt._parameter_number(vref)
return support[param_num]
data = transcription_data(backend)
return support[data.param_to_support_idx[vref]]
end

# AffExpr and QuadExpr and NonlinearExpr
Expand All @@ -544,7 +551,8 @@ function transcription_expression(
)
return InfiniteOpt.map_expression(
v -> transcription_expression(v, backend, support),
expr)
expr
)
end

# Real Number
Expand Down Expand Up @@ -584,6 +592,8 @@ function transcribe_measures!(
group_idxs = meas.group_int_idxs
mref = InfiniteOpt.GeneralVariableRef(model, idx)
prefs = InfiniteOpt.raw_parameter_refs(mref)
data = transcription_data(backend)
pref_supp_idxs = Int[data.param_to_support_idx[p] for p in prefs]
# expand the measure
if meas.constant_func
new_expr = InfiniteOpt.analytic_expansion(meas.func, meas.data, backend)
Expand All @@ -602,15 +612,15 @@ function transcribe_measures!(
raw_supp = index_to_support(backend, i)
expr_idx = i.I[group_idxs]
@inbounds exprs[expr_idx...] = transcription_expression(new_expr, backend, raw_supp)
supp = raw_supp[meas.parameter_nums]
supp = raw_supp[pref_supp_idxs]
lookup_dict[supp] = lin_idx
@inbounds supps[expr_idx...] = Tuple(supp, prefs)
end
# save the transcription information
data = transcription_data(backend)
data.measure_lookup[mref] = lookup_dict
data.measure_mappings[mref] = exprs
data.measure_supports[mref] = supps
data.infvar_param_idxs[mref] = pref_supp_idxs
end
return
end
Expand Down Expand Up @@ -698,13 +708,19 @@ function _get_info_constr_from_var(
return JuMP.is_integer(trans_vref) ? JuMP.IntegerRef(trans_vref) : nothing
end

# Get the parameter support indexing for a restriction
function _pref_supp_idxs(constr::InfiniteOpt.DomainRestrictedConstraint, data)
prefs = constr.restriction.parameter_refs
return [data.param_to_support_idx[p] for p in prefs]
end
_pref_supp_idxs(constr, data) = Int[]

# Determine if a given raw support satisfies constraint domain restrictions
function _support_in_restrictions(
constr::InfiniteOpt.DomainRestrictedConstraint,
support::Vector{Float64}
)
restriction = constr.restriction
return restriction(support[restriction.parameter_nums])
return constr.restriction(support)
end
function _support_in_restrictions(
constr::JuMP.AbstractConstraint,
Expand Down Expand Up @@ -799,6 +815,7 @@ function transcribe_constraints!(
set = JuMP.moi_set(constr)
group_idxs = object.group_int_idxs
cref = InfiniteOpt.InfOptConstraintRef(model, idx)
data = transcription_data(backend)
# prepare the iteration helpers
supp_indices = support_index_iterator(backend, group_idxs)
dims = size(supp_indices)[group_idxs]
Expand All @@ -825,11 +842,12 @@ function transcribe_constraints!(
else
# get basic setup information
name = object.name
pref_supp_idxs = _pref_supp_idxs(constr, data)
for i in supp_indices
raw_supp = index_to_support(backend, i)
# ensure the support satisfies parameter bounds and then add it
con_idx = i.I[group_idxs]
if _support_in_restrictions(constr, raw_supp)
if _support_in_restrictions(constr, raw_supp[pref_supp_idxs])
new_name = if isempty(name)
""
elseif isempty(group_idxs)
Expand All @@ -849,7 +867,6 @@ function transcribe_constraints!(
end
# truncate the arrays in case not all the supports satisfied the bounds
# and save
data = transcription_data(backend)
if !all(valid_idxs)
data.constr_mappings[cref] = crefs[valid_idxs]
data.constr_supports[cref] = supps[valid_idxs]
Expand Down
Loading
Loading