diff --git a/docs/src/develop/extensions.md b/docs/src/develop/extensions.md index ab9ce8bf..6a75b029 100644 --- a/docs/src/develop/extensions.md +++ b/docs/src/develop/extensions.md @@ -755,22 +755,14 @@ extended using the following steps: 5. If appropriate and NOT a [`JuMPBackend`](@ref), extend the following: - [`transformation_model`](@ref transformation_model(::AbstractTransformationBackend)) - [`transformation_data`](@ref transformation_data(::AbstractTransformationBackend)) - - [`JuMP.set_attribute`](@ref JuMP.set_attribute(::AbstractTransformationBackend, ::Any, ::Any)) - - [`JuMP.get_attribute`](@ref JuMP.get_attribute(::AbstractTransformationBackend, ::Any)) + - [`JuMP.set_attribute`](@ref JuMP.set_attribute(::AbstractTransformationBackend, ::Any, ::Any)) (including the suggested attributes) + - [`JuMP.get_attribute`](@ref JuMP.get_attribute(::AbstractTransformationBackend, ::Any)) (including the suggested attributes) - [`JuMP.optimize!`](@ref JuMP.optimize!(::AbstractTransformationBackend)) - [`JuMP.set_optimizer`](@ref JuMP.set_optimizer(::AbstractTransformationBackend, ::Any)) - - [`JuMP.set_silent`](@ref JuMP.set_silent(::AbstractTransformationBackend)) - - [`JuMP.unset_silent`](@ref JuMP.unset_silent(::AbstractTransformationBackend)) - - [`JuMP.set_time_limit_sec`](@ref JuMP.set_time_limit_sec(::AbstractTransformationBackend, ::Any)) - - [`JuMP.time_limit_sec`](@ref JuMP.time_limit_sec(::AbstractTransformationBackend)) - - [`JuMP.unset_time_limit_sec`](@ref JuMP.unset_time_limit_sec(::AbstractTransformationBackend)) - - [`JuMP.solver_name`](@ref JuMP.solver_name(::AbstractTransformationBackend)) - [`JuMP.bridge_constraints`](@ref JuMP.bridge_constraints(::AbstractTransformationBackend)) - [`JuMP.add_bridge`](@ref JuMP.add_bridge(::AbstractTransformationBackend, ::Any)) - [`JuMP.print_active_bridges`](@ref JuMP.print_active_bridges(::IO,::AbstractTransformationBackend)) - [`JuMP.print_active_bridges`](@ref JuMP.print_active_bridges(::IO,::AbstractTransformationBackend)) - - [`JuMP.set_string_names_on_creation`](@ref JuMP.set_string_names_on_creation(::AbstractTransformationBackend)) - - [`JuMP.set_string_names_on_creation`](@ref JuMP.set_string_names_on_creation(::AbstractTransformationBackend, ::Any)) - [`JuMP.compute_conflict!`](@ref JuMP.compute_conflict!(::AbstractTransformationBackend)) - [`JuMP.copy_conflict`](@ref JuMP.copy_conflict(::AbstractTransformationBackend)) - [`JuMP.mode`](@ref JuMP.mode(::AbstractTransformationBackend)) @@ -785,21 +777,7 @@ extended using the following steps: - [`InfiniteOpt.expression_supports`](@ref) - [`InfiniteOpt.constraint_supports`](@ref) 8. As appropriate and if NOT a `JuMPBackend`, extend the following: - - [`JuMP.termination_status`](@ref JuMP.termination_status(::AbstractTransformationBackend)) - - [`JuMP.raw_status`](@ref JuMP.raw_status(::AbstractTransformationBackend)) - - [`JuMP.solve_time`](@ref JuMP.solve_time(::AbstractTransformationBackend)) - - [`JuMP.simplex_iterations`](@ref JuMP.simplex_iterations(::AbstractTransformationBackend)) - - [`JuMP.barrier_iterations`](@ref JuMP.barrier_iterations(::AbstractTransformationBackend)) - - [`JuMP.node_count`](@ref JuMP.node_count(::AbstractTransformationBackend)) - - [`JuMP.objective_bound`](@ref JuMP.objective_bound(::AbstractTransformationBackend)) - - [`JuMP.relative_gap`](@ref JuMP.relative_gap(::AbstractTransformationBackend)) - - [`JuMP.result_count`](@ref JuMP.result_count(::AbstractTransformationBackend)) - - [`JuMP.primal_status`](@ref JuMP.primal_status(::AbstractTransformationBackend)) - - [`JuMP.dual_status`](@ref JuMP.dual_status(::AbstractTransformationBackend)) - - [`JuMP.has_values`](@ref JuMP.has_values(::AbstractTransformationBackend)) - - [`JuMP.has_duals`](@ref JuMP.has_duals(::AbstractTransformationBackend)) - - [`JuMP.objective_value`](@ref JuMP.objective_value(::AbstractTransformationBackend)) - - [`JuMP.dual_objective_value`](@ref JuMP.dual_objective_value(::AbstractTransformationBackend)) + - The remaining result related attributes listed in [`JuMP.get_attribute`](@ref JuMP.get_attribute(::AbstractTransformationBackend, ::Any)) - [`JuMP.lp_sensitivity_report`](@ref JuMP.lp_sensitivity_report(::AbstractTransformationBackend)) 9. If Step 6 was skipped and/or the backend is NOT a `JuMPBackend` then extend the following: - [`InfiniteOpt.map_value`](@ref) (enables `JuMP.value`) @@ -1067,7 +1045,6 @@ are enabled via Step 6 where we extend: - [`transformation_variable`](@ref transformation_variable(::GeneralVariableRef, ::AbstractTransformationBackend)) - [`transformation_expression`](@ref transformation_expression(::Any, ::AbstractTransformationBackend)) - [`transformation_constraint`](@ref transformation_constraint(::InfOptConstraintRef, ::AbstractTransformationBackend)) -[`transformation_expression`](@ref), and [`transformation_constraint`](@ref) to return the variable(s)/expression(s)/constraint(s) in the backend. These will use the `DeterministicData` and should error if no mapping can be found. diff --git a/docs/src/guide/derivative.md b/docs/src/guide/derivative.md index 2b58e651..ada20e37 100644 --- a/docs/src/guide/derivative.md +++ b/docs/src/guide/derivative.md @@ -1,6 +1,6 @@ ```@meta DocTestFilters = [r"≥|>=", r" == | = ", r" ∈ | in ", r" for all | ∀ ", r"d|∂", - r"integral|∫", r".*scalar_parameters.jl:790"] + r"integral|∫", r".*scalar_parameters.jl:785"] ``` # [Derivative Operators](@id deriv_docs) @@ -503,7 +503,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:790 +└ @ InfiniteOpt ~/work/infiniteopt/InfiniteOpt.jl/src/scalar_parameters.jl:785 julia> has_derivative_constraints(d1) false diff --git a/docs/src/manual/backend.md b/docs/src/manual/backend.md index d26d6ab6..a2c86c15 100644 --- a/docs/src/manual/backend.md +++ b/docs/src/manual/backend.md @@ -24,15 +24,13 @@ supports(::InfOptConstraintRef) JuMP.set_optimizer(::InfiniteModel, ::Any) JuMP.set_silent(::InfiniteModel) JuMP.unset_silent(::InfiniteModel) -JuMP.set_time_limit_sec(::InfiniteModel, ::Any) +JuMP.set_time_limit_sec(::InfiniteModel, ::Real) JuMP.unset_time_limit_sec(::InfiniteModel) JuMP.time_limit_sec(::InfiniteModel) JuMP.solver_name(model::InfiniteModel) JuMP.mode(::InfiniteModel) JuMP.compute_conflict!(::InfiniteModel) JuMP.copy_conflict(::InfiniteModel) -JuMP.set_string_names_on_creation(::InfiniteModel) -JuMP.set_string_names_on_creation(::InfiniteModel, ::Any) JuMP.bridge_constraints(::InfiniteModel) JuMP.add_bridge(::InfiniteModel, ::Any) JuMP.print_active_bridges(::IO, ::InfiniteModel, ::Vararg{Any}) @@ -57,17 +55,9 @@ Base.empty!(::AbstractTransformationBackend) build_transformation_backend!(::InfiniteModel, ::AbstractTransformationBackend) JuMP.optimize!(::AbstractTransformationBackend) JuMP.set_optimizer(::AbstractTransformationBackend, ::Any) -JuMP.set_silent(::AbstractTransformationBackend) -JuMP.unset_silent(::AbstractTransformationBackend) -JuMP.set_time_limit_sec(::AbstractTransformationBackend, ::Any) -JuMP.unset_time_limit_sec(::AbstractTransformationBackend) -JuMP.time_limit_sec(::AbstractTransformationBackend) -JuMP.solver_name(model::AbstractTransformationBackend) JuMP.mode(::AbstractTransformationBackend) JuMP.compute_conflict!(::AbstractTransformationBackend) JuMP.copy_conflict(::AbstractTransformationBackend) -JuMP.set_string_names_on_creation(::AbstractTransformationBackend) -JuMP.set_string_names_on_creation(::AbstractTransformationBackend, ::Any) JuMP.bridge_constraints(::AbstractTransformationBackend) JuMP.add_bridge(::AbstractTransformationBackend, ::Any) JuMP.print_active_bridges(::IO, ::AbstractTransformationBackend, ::Vararg{Any}) @@ -75,7 +65,7 @@ JuMP.print_bridge_graph(::IO, ::AbstractTransformationBackend) JuMP.backend(::AbstractTransformationBackend) JuMP.unsafe_backend(::AbstractTransformationBackend) transformation_variable(::GeneralVariableRef, ::AbstractTransformationBackend) -transformation_expression(::JuMP.AbstractJuMPScalar, ::AbstractTransformationBackend) +transformation_expression(::Any, ::AbstractTransformationBackend) transformation_constraint(::InfOptConstraintRef, ::AbstractTransformationBackend) variable_supports(::Any, ::AbstractTransformationBackend) expression_supports(::Any, ::AbstractTransformationBackend) diff --git a/docs/src/manual/constraint.md b/docs/src/manual/constraint.md index 1cc6dc44..73e49dd3 100644 --- a/docs/src/manual/constraint.md +++ b/docs/src/manual/constraint.md @@ -33,6 +33,9 @@ has_domain_restrictions domain_restrictions JuMP.normalized_rhs(::InfOptConstraintRef) JuMP.normalized_coefficient(::InfOptConstraintRef, ::GeneralVariableRef) +parameter_group_int_indices(::InfOptConstraintRef) +core_object(::InfOptConstraintRef) +is_variable_domain_constraint ``` ## Modification diff --git a/docs/src/manual/derivative.md b/docs/src/manual/derivative.md index a024c20d..98afcb4e 100644 --- a/docs/src/manual/derivative.md +++ b/docs/src/manual/derivative.md @@ -27,6 +27,8 @@ all_derivatives parameter_refs(::DerivativeRef) parameter_list(::DerivativeRef) raw_parameter_refs(::DerivativeRef) +parameter_group_int_indices(::DerivativeRef) +core_object(::DerivativeRef) ``` ## Modification diff --git a/docs/src/manual/expression.md b/docs/src/manual/expression.md index 5228d35b..9b59a891 100644 --- a/docs/src/manual/expression.md +++ b/docs/src/manual/expression.md @@ -28,6 +28,7 @@ used_by_semi_infinite_variable(::ParameterFunctionRef) used_by_derivative(::ParameterFunctionRef) used_by_measure(::ParameterFunctionRef) used_by_constraint(::ParameterFunctionRef) +parameter_group_int_indices(::ParameterFunctionRef) ``` ### Modification @@ -57,6 +58,8 @@ parameter_refs(::Union{JuMP.GenericAffExpr, JuMP.GenericNonlinearExpr, JuMP.Gene restrict(::JuMP.AbstractJuMPScalar) map_expression map_expression_to_ast +all_expression_variables +parameter_group_int_indices(::Any) ``` ## GeneralVariableRef User Methods @@ -158,6 +161,11 @@ JuMP.set_integer(::GeneralVariableRef) JuMP.IntegerRef(::GeneralVariableRef) JuMP.unset_integer(::GeneralVariableRef) constant_over_collocation(::GeneralVariableRef, ::GeneralVariableRef) +core_object +core_object(::GeneralVariableRef) +parameter_group_int_indices(::GeneralVariableRef) +InfiniteOpt.parameter_group_int_index +InfiniteOpt.parameter_group_int_index(::GeneralVariableRef) ``` ## Developer Internal Methods @@ -166,9 +174,7 @@ InfiniteOpt._add_data_object InfiniteOpt._data_dictionary InfiniteOpt._data_object InfiniteOpt._delete_data_object -InfiniteOpt._core_variable_object -InfiniteOpt._core_variable_object(::GeneralVariableRef) -InfiniteOpt._set_core_variable_object +InfiniteOpt._set_core_object InfiniteOpt._infinite_variable_dependencies InfiniteOpt._infinite_variable_dependencies(::GeneralVariableRef) InfiniteOpt._semi_infinite_variable_dependencies @@ -187,6 +193,4 @@ InfiniteOpt._derivative_constraint_dependencies InfiniteOpt._derivative_constraint_dependencies(::GeneralVariableRef) InfiniteOpt._parameter_number InfiniteOpt._parameter_number(::GeneralVariableRef) -InfiniteOpt._object_number -InfiniteOpt._object_number(::GeneralVariableRef) ``` diff --git a/docs/src/manual/finite_parameter.md b/docs/src/manual/finite_parameter.md index 17ceba51..c1b5d050 100644 --- a/docs/src/manual/finite_parameter.md +++ b/docs/src/manual/finite_parameter.md @@ -22,4 +22,5 @@ methods available for finite parameters (i.e., any method typed for parameter_value(::FiniteParameterRef) JuMP.set_value(::FiniteParameterRef, ::Real) used_by_objective(::FiniteParameterRef) +core_object(::FiniteParameterRef) ``` diff --git a/docs/src/manual/measure.md b/docs/src/manual/measure.md index 73107f2a..2a35c386 100644 --- a/docs/src/manual/measure.md +++ b/docs/src/manual/measure.md @@ -103,6 +103,8 @@ used_by_derivative(::MeasureRef) used_by_constraint(::MeasureRef) used_by_measure(::MeasureRef) used_by_objective(::MeasureRef) +core_object(::MeasureRef) +parameter_group_int_indices(::MeasureRef) ``` ## Modification diff --git a/docs/src/manual/model.md b/docs/src/manual/model.md index 67a0bcd8..54472688 100644 --- a/docs/src/manual/model.md +++ b/docs/src/manual/model.md @@ -10,6 +10,8 @@ JuMP.object_dictionary(::InfiniteModel) has_internal_supports Base.empty!(::InfiniteModel) JuMP.set_optimize_hook(::InfiniteModel, ::Union{Function, Nothing}) +parameter_refs(::InfiniteModel) +parameter_group_indices ``` ## Abstract Dependencies diff --git a/docs/src/manual/parameter.md b/docs/src/manual/parameter.md index e0db04bd..556f02d9 100644 --- a/docs/src/manual/parameter.md +++ b/docs/src/manual/parameter.md @@ -58,6 +58,8 @@ used_by_parameter_function(::IndependentParameterRef) used_by_derivative(::IndependentParameterRef) used_by_measure(::ScalarParameterRef) used_by_constraint(::ScalarParameterRef) +parameter_group_int_index(::IndependentParameterRef) +core_object(::IndependentParameterRef) ``` ### Dependent Parameters @@ -83,6 +85,8 @@ used_by_parameter_function(::DependentParameterRef) used_by_derivative(::DependentParameterRef) used_by_measure(::DependentParameterRef) used_by_constraint(::DependentParameterRef) +parameter_group_int_index(::DependentParameterRef) +core_object(::DependentParameterRef) ``` ## Modification diff --git a/docs/src/manual/result.md b/docs/src/manual/result.md index a314a810..e14e1103 100644 --- a/docs/src/manual/result.md +++ b/docs/src/manual/result.md @@ -8,6 +8,7 @@ JuMP.termination_status(::InfiniteModel) JuMP.raw_status(::InfiniteModel) JuMP.primal_status(::InfiniteModel) JuMP.dual_status(::InfiniteModel) +JuMP.is_solved_and_feasible(::InfiniteModel) ``` ## General @@ -57,25 +58,10 @@ InfOptSensitivityReport ## Transformation Backend Extension API ```@docs -JuMP.termination_status(::AbstractTransformationBackend) -JuMP.raw_status(::AbstractTransformationBackend) -JuMP.primal_status(::AbstractTransformationBackend) -JuMP.dual_status(::AbstractTransformationBackend) -JuMP.solve_time(::AbstractTransformationBackend) -JuMP.relative_gap(::AbstractTransformationBackend) -JuMP.simplex_iterations(::AbstractTransformationBackend) -JuMP.barrier_iterations(::AbstractTransformationBackend) -JuMP.node_count(::AbstractTransformationBackend) -JuMP.result_count(::AbstractTransformationBackend) -JuMP.objective_bound(::AbstractTransformationBackend) -JuMP.objective_value(::AbstractTransformationBackend) -JuMP.dual_objective_value(::AbstractTransformationBackend) -JuMP.has_values(::AbstractTransformationBackend) map_value(::Any, ::AbstractTransformationBackend) map_infinite_parameter_value map_reduced_cost(::GeneralVariableRef, ::AbstractTransformationBackend) map_optimizer_index(::GeneralVariableRef, ::AbstractTransformationBackend) -JuMP.has_duals(::AbstractTransformationBackend) map_dual(::InfOptConstraintRef, ::AbstractTransformationBackend) map_shadow_price(::InfOptConstraintRef, ::AbstractTransformationBackend) map_optimizer_index(::InfOptConstraintRef, ::AbstractTransformationBackend) diff --git a/docs/src/manual/variable.md b/docs/src/manual/variable.md index 04693eaa..9b0c66ae 100644 --- a/docs/src/manual/variable.md +++ b/docs/src/manual/variable.md @@ -91,6 +91,8 @@ is_used(::Union{InfiniteVariableRef, DerivativeRef}) used_by_derivative(::Union{DerivativeRef, InfiniteVariableRef}) used_by_point_variable(::Union{InfiniteVariableRef, DerivativeRef}) used_by_semi_infinite_variable(::Union{InfiniteVariableRef, DerivativeRef}) +parameter_group_int_indices(::InfiniteVariableRef) +core_object(::InfiniteVariableRef) ``` ### Semi-Infinite @@ -116,6 +118,8 @@ raw_parameter_refs(::SemiInfiniteVariableRef) eval_supports(::SemiInfiniteVariableRef) is_used(::SemiInfiniteVariableRef) used_by_derivative(::SemiInfiniteVariableRef) +parameter_group_int_indices(::SemiInfiniteVariableRef) +core_object(::SemiInfiniteVariableRef) ``` ### Point @@ -123,6 +127,12 @@ used_by_derivative(::SemiInfiniteVariableRef) infinite_variable_ref(::PointVariableRef) parameter_values(::PointVariableRef) raw_parameter_values(::PointVariableRef) +core_object(::PointVariableRef) +``` + +### Finite +```@docs +core_object(::FiniteVariableRef) ``` ## Modification diff --git a/src/TranscriptionOpt/measures.jl b/src/TranscriptionOpt/measures.jl index 9fcf3dd1..0bab4fc1 100644 --- a/src/TranscriptionOpt/measures.jl +++ b/src/TranscriptionOpt/measures.jl @@ -25,7 +25,7 @@ function InfiniteOpt.add_point_variable( inf_model = JuMP.owner_model(ivref) inf_model_index = get(inf_model.point_lookup, (ivref, support), nothing) if !isnothing(inf_model_index) - return InfiniteOpt._make_variable_ref(inf_model, inf_model_index) + return InfiniteOpt.GeneralVariableRef(inf_model, inf_model_index) else # make negative index to not conflict with the InfiniteModel raw_index = data.last_point_index -= 1 @@ -66,7 +66,7 @@ function InfiniteOpt.add_semi_infinite_variable( inf_model = JuMP.owner_model(ivref) inf_model_index = get(inf_model.semi_lookup, (ivref, eval_supps), nothing) if !isnothing(inf_model_index) - return InfiniteOpt._make_variable_ref(inf_model, inf_model_index) + return InfiniteOpt.GeneralVariableRef(inf_model, inf_model_index) else # make negative index to not conflict with the InfiniteModel semi_infinite_vars = data.semi_infinite_vars diff --git a/src/TranscriptionOpt/model.jl b/src/TranscriptionOpt/model.jl index d24683aa..e47d880f 100644 --- a/src/TranscriptionOpt/model.jl +++ b/src/TranscriptionOpt/model.jl @@ -179,11 +179,10 @@ function JuMP.show_backend_summary( # reformulation information data = transcription_data(backend) supp_tuple = data.supports - obj_idxs = InfiniteOpt._param_object_indices(model) + prefs = InfiniteOpt.parameter_refs(model) for (i, supps) in enumerate(supp_tuple) # support info - pref_group = InfiniteOpt._make_param_tuple_element(model, obj_idxs[i]) - param_name = InfiniteOpt._get_param_group_name(pref_group) + param_name = InfiniteOpt._get_param_group_name(prefs[i]) println(io, " `", param_name, "` transcribed over ", length(supps) - 1, " supports") # TODO add approximation method info (requires InfiniteOpt refactoring) end @@ -353,9 +352,9 @@ function transcription_variable( label::Type{<:InfiniteOpt.AbstractSupportLabel}, ndarray::Bool ) - # get the object numbers of the expression and form the support iterator - obj_nums = InfiniteOpt._object_numbers(fref) - support_indices = support_index_iterator(backend, obj_nums) + # get the parameter group integer indices of the expression and form the support iterator + group_int_idxs = InfiniteOpt.parameter_group_int_indices(fref) + support_indices = support_index_iterator(backend, group_int_idxs) vals = Vector{Float64}(undef, length(support_indices)) check_labels = length(vals) > 1 && !_ignore_label(backend, label) label_inds = ones(Bool, length(vals)) @@ -443,7 +442,7 @@ function InfiniteOpt.variable_supports( label::Type{<:InfiniteOpt.AbstractSupportLabel} = InfiniteOpt.PublicLabel, ndarray::Bool = false ) - vref = InfiniteOpt._make_variable_ref(JuMP.owner_model(dvref), JuMP.index(dvref)) + vref = InfiniteOpt.GeneralVariableRef(JuMP.owner_model(dvref), JuMP.index(dvref)) if !haskey(transcription_data(backend).infvar_mappings, vref) error("Variable reference $vref not used in transcription backend.") elseif !haskey(transcription_data(backend).infvar_supports, vref) @@ -475,9 +474,9 @@ function InfiniteOpt.variable_supports( label::Type{<:InfiniteOpt.AbstractSupportLabel} = InfiniteOpt.PublicLabel, ndarray::Bool = false ) - # get the object numbers of the expression and form the support iterator - obj_nums = sort(InfiniteOpt._object_numbers(dvref)) - support_indices = support_index_iterator(backend, obj_nums) + # get the parameter group integer indices of the expression and form the support iterator + group_int_idxs = sort(InfiniteOpt.parameter_group_int_indices(dvref)) + support_indices = support_index_iterator(backend, group_int_idxs) supps = Vector{Tuple}(undef, length(support_indices)) check_labels = length(supps) > 1 && !_ignore_label(backend, label) param_supps = parameter_supports(backend) @@ -487,7 +486,7 @@ function InfiniteOpt.variable_supports( if check_labels && !any(l -> l <: label, index_to_labels(backend, idx)) @inbounds label_inds[i] = false end - @inbounds supps[i] = Tuple(param_supps[j][idx[j]] for j in obj_nums) + @inbounds supps[i] = Tuple(param_supps[j][idx[j]] for j in group_int_idxs) end # return the supports if ndarray @@ -637,7 +636,7 @@ function InfiniteOpt.variable_supports( label::Type{<:InfiniteOpt.AbstractSupportLabel} = InfiniteOpt.PublicLabel, ndarray::Bool = false ) - mref = InfiniteOpt._make_variable_ref(JuMP.owner_model(dmref), JuMP.index(dmref)) + mref = InfiniteOpt.GeneralVariableRef(JuMP.owner_model(dmref), JuMP.index(dmref)) if !haskey(transcription_data(backend).measure_mappings, mref) error("Measure reference $mref not used in transcription backend.") elseif !haskey(transcription_data(backend).measure_supports, mref) @@ -710,9 +709,9 @@ function transcription_expression( label::Type{<:InfiniteOpt.AbstractSupportLabel} = InfiniteOpt.PublicLabel, ndarray::Bool = false ) - # get the object numbers of the expression and form the support iterator - obj_nums = InfiniteOpt._object_numbers(expr) - support_indices = support_index_iterator(backend, obj_nums) + # get the parameter group integer indices of the expression and form the support iterator + group_int_idxs = InfiniteOpt.parameter_group_int_indices(expr) + support_indices = support_index_iterator(backend, group_int_idxs) exprs = Vector{JuMP.AbstractJuMPScalar}(undef, length(support_indices)) check_labels = length(exprs) > 1 && !_ignore_label(backend, label) label_inds = ones(Bool, length(exprs)) @@ -795,9 +794,9 @@ function InfiniteOpt.expression_supports( label::Type{<:InfiniteOpt.AbstractSupportLabel} = InfiniteOpt.PublicLabel, ndarray::Bool = false ) - # get the object numbers of the expression and form the support iterator - obj_nums = sort(InfiniteOpt._object_numbers(expr)) - support_indices = support_index_iterator(backend, obj_nums) + # get the parameter group integer indices of the expression and form the support iterator + group_int_idxs = sort(InfiniteOpt.parameter_group_int_indices(expr)) + support_indices = support_index_iterator(backend, group_int_idxs) supps = Vector{Tuple}(undef, length(support_indices)) check_labels = length(supps) > 1 && !_ignore_label(backend, label) param_supps = parameter_supports(backend) @@ -807,7 +806,7 @@ function InfiniteOpt.expression_supports( if check_labels && !any(l -> l <: label, index_to_labels(backend, idx)) @inbounds label_inds[i] = false end - @inbounds supps[i] = Tuple(param_supps[j][idx[j]] for j in obj_nums) + @inbounds supps[i] = Tuple(param_supps[j][idx[j]] for j in group_int_idxs) end # return the supports if ndarray @@ -961,12 +960,12 @@ function parameter_supports(backend::TranscriptionBackend) end """ - support_index_iterator(backend::TranscriptionBackend, [obj_nums::Vector{Int}])::CartesianIndices + support_index_iterator(backend::TranscriptionBackend, [group_int_idxs::Vector{Int}])::CartesianIndices Return the `CartesianIndices` that determine the indices of the unique combinations -of `TranscriptionData.supports` stored in `backend`. If `obj_nums` is specified, +of `TranscriptionData.supports` stored in `backend`. If `group_int_idxs` is specified, then the indices will only include the tuple elements uses indices are included -in the object numbers `obj_nums` and all others will be assigned the last index +in the parameter group integer indices `group_int_idxs` and all others will be assigned the last index which should correspond to an appropriately sized placeholder comprised of `NaN`s. Note this method assumes that [`set_parameter_supports`](@ref) has already been called and that the last elements of each support vector contains a placeholder @@ -977,16 +976,16 @@ function support_index_iterator(backend::TranscriptionBackend) return CartesianIndices(ntuple(i -> 1:length(raw_supps[i])-1, length(raw_supps))) end -# Generate for a subset of object numbers (use last index as placeholder --> support with NaNs) +# Generate for a subset of parameter group integer indices (use last index as placeholder --> support with NaNs) function support_index_iterator( backend::TranscriptionBackend, - obj_nums::Vector{Int} + group_int_idxs::Vector{Int} ) raw_supps = parameter_supports(backend) lens = map(i -> length(i), raw_supps) # prepare the indices of each support combo # note that the actual supports are from 1:length-1 and the placeholders are at the ends - return CartesianIndices(ntuple(i -> i in obj_nums ? (1:lens[i]-1) : (lens[i]:lens[i]), + return CartesianIndices(ntuple(i -> i in group_int_idxs ? (1:lens[i]-1) : (lens[i]:lens[i]), length(raw_supps))) end @@ -1031,17 +1030,17 @@ function _get_array_type(array::Array{T, N}) where {T, N} return T end -## Helper functions to consistently get object numbers +## Helper functions to consistently get parameter group integer indices # Fallback -function _get_object_numbers(ref) - return InfiniteOpt._object_numbers(ref) +function _getparameter_group_int_indices(ref) + return InfiniteOpt.parameter_group_int_indices(ref) end # Expressions -function _get_object_numbers( +function _getparameter_group_int_indices( expr::Union{JuMP.GenericAffExpr, JuMP.GenericQuadExpr} ) - return sort(InfiniteOpt._object_numbers(expr)) + return sort(InfiniteOpt.parameter_group_int_indices(expr)) end """ @@ -1060,15 +1059,15 @@ numbers. Thus, independent infinite parameters will each get their own dimension parameter group will have its own dimension. """ function make_ndarray(backend::TranscriptionBackend, ref, info::Vector, label::DataType) - # get the object numbers - obj_nums = _get_object_numbers(ref) + # get the parameter group integer indices + group_int_idxs = _getparameter_group_int_indices(ref) # return result if it is from a finite object - if isempty(obj_nums) + if isempty(group_int_idxs) return info end # determine the dimensions of the new array raw_supps = parameter_supports(backend) - dims = Tuple(length(raw_supps[i]) - 1 for i in eachindex(raw_supps) if i in obj_nums) + dims = Tuple(length(raw_supps[i]) - 1 for i in eachindex(raw_supps) if i in group_int_idxs) # check that the lengths match (otherwise we'll have some sparse set) # TODO add capability to avoid this problem (make reduced array by looking at the supports) if length(info) != prod(dims) @@ -1082,12 +1081,12 @@ function make_ndarray(backend::TranscriptionBackend, ref, info::Vector, label::D narray[idx] = info[i] end # rearrange the array as needed to match the object number order - sorted_array = issorted(obj_nums) ? narray : permutedims(narray, sortperm(obj_nums)) + sorted_array = issorted(group_int_idxs) ? narray : permutedims(narray, sortperm(group_int_idxs)) # consider the label specified (this will enforce the intersection of labels) if _ignore_label(backend, label) return sorted_array else - labels = transcription_data(backend).support_labels[obj_nums] + labels = transcription_data(backend).support_labels[group_int_idxs] inds = map(sets -> findall(s -> any(l -> l <: label, s), sets), labels) return sorted_array[inds...] end diff --git a/src/TranscriptionOpt/transcribe.jl b/src/TranscriptionOpt/transcribe.jl index e2b4e4d8..49452d7d 100644 --- a/src/TranscriptionOpt/transcribe.jl +++ b/src/TranscriptionOpt/transcribe.jl @@ -49,7 +49,7 @@ Collect the infinite parameter supports stored in their respective dictionaries form `model` and process them into a tuple of vectors where each vector contains the collected supports of a particular infinite parameter. These support collections are ordered in accordance with the definition order of the -parameters (i.e., their object numbers). A support collection assocciated with +parameters (i.e., their group integer indices). A support collection assocciated with an independent will be a `Vector{Float64}` and a support collection associated with a group of dependent parameters will be a `Vector{Vector{Float64}}`. Note that each collection vector will include an extra final placeholder element @@ -63,7 +63,7 @@ function set_parameter_supports( model::InfiniteOpt.InfiniteModel ) # gather the basic information - param_indices = InfiniteOpt._param_object_indices(model) + param_indices = InfiniteOpt.parameter_group_indices(model) prefs = map(idx -> _temp_parameter_ref(model, idx), param_indices) data = transcription_data(backend) # check and add supports to prefs as needed @@ -101,7 +101,7 @@ function transcribe_finite_variables!( model::InfiniteOpt.InfiniteModel ) for (idx, object) in InfiniteOpt._data_dictionary(model, InfiniteOpt.FiniteVariable) - hvref = InfiniteOpt._make_variable_ref(model, idx) + hvref = InfiniteOpt.GeneralVariableRef(model, idx) v = JuMP.ScalarVariable(object.variable.info) vref = JuMP.add_variable(backend.model, v, object.name) transcription_data(backend).finvar_mappings[hvref] = vref @@ -151,7 +151,7 @@ function transcribe_infinite_variables!( base_name = object.name param_nums = var.parameter_nums # prepare for iterating over its supports - supp_indices = support_index_iterator(backend, var.object_nums) + supp_indices = support_index_iterator(backend, var.group_int_idxs) vrefs = Vector{JuMP.VariableRef}(undef, length(supp_indices)) labels = Vector{Set{DataType}}(undef, length(supp_indices)) lookup_dict = Dict{Vector{Float64}, Int}() @@ -167,7 +167,7 @@ function transcribe_infinite_variables!( @inbounds labels[counter] = index_to_labels(backend, i) end # save the transcription information - ivref = InfiniteOpt._make_variable_ref(model, idx) + ivref = InfiniteOpt.GeneralVariableRef(model, idx) data = transcription_data(backend) data.infvar_lookup[ivref] = lookup_dict data.infvar_mappings[ivref] = vrefs @@ -195,9 +195,9 @@ end function _transcribe_derivative_variable(dref, d, backend) base_name = InfiniteOpt.variable_string(MIME("text/plain"), dispatch_variable_ref(dref)) param_nums = InfiniteOpt._parameter_numbers(d.variable_ref) - obj_nums = InfiniteOpt._object_numbers(d.variable_ref) + group_int_idxs = InfiniteOpt.parameter_group_int_indices(d.variable_ref) # prepare for iterating over its supports - supp_indices = support_index_iterator(backend, obj_nums) + supp_indices = support_index_iterator(backend, group_int_idxs) vrefs = Vector{JuMP.VariableRef}(undef, length(supp_indices)) labels = Vector{Set{DataType}}(undef, length(supp_indices)) lookup_dict = Dict{Vector{Float64}, Int}() @@ -242,7 +242,7 @@ function transcribe_derivative_variables!( ) for (idx, object) in InfiniteOpt._data_dictionary(model, InfiniteOpt.Derivative) # get the basic derivative information - dref = InfiniteOpt._make_variable_ref(model, idx) + dref = InfiniteOpt.GeneralVariableRef(model, idx) d = object.variable method = InfiniteOpt.derivative_method(dref) # if needed process lower order derivatives @@ -275,7 +275,7 @@ function _set_semi_infinite_variable_mapping( ivref_param_nums = InfiniteOpt._parameter_numbers(ivref) eval_supps = var.eval_supports # prepare for iterating over its supports - supp_indices = support_index_iterator(backend, var.object_nums) + supp_indices = support_index_iterator(backend, var.group_int_idxs) vrefs = Vector{JuMP.VariableRef}(undef, length(supp_indices)) labels = Vector{Set{DataType}}(undef, length(supp_indices)) lookup_dict = Dict{Vector{Float64}, Int}() @@ -340,7 +340,7 @@ function transcribe_semi_infinite_variables!( for (idx, object) in InfiniteOpt._data_dictionary(model, InfiniteOpt.SemiInfiniteVariable) # get the basic variable information var = object.variable - rvref = InfiniteOpt._make_variable_ref(model, idx) + rvref = InfiniteOpt.GeneralVariableRef(model, idx) # setup the mappings idx_type = InfiniteOpt._index_type(InfiniteOpt.infinite_variable_ref(rvref)) _set_semi_infinite_variable_mapping(backend, var, rvref, idx_type) @@ -411,7 +411,7 @@ function transcribe_point_variables!( supp = var.parameter_values # find the corresponding variable record the mapping vref = lookup_by_support(ivref, backend, supp) - pvref = InfiniteOpt._make_variable_ref(model, idx) + pvref = InfiniteOpt.GeneralVariableRef(model, idx) transcription_data(backend).finvar_mappings[pvref] = vref # update the info constraints as needed _update_point_info(pvref, vref) @@ -562,7 +562,7 @@ function transcribe_measures!( new_expr = InfiniteOpt.expand_measure(meas.func, meas.data, backend) end # prepare to transcribe over the supports - supp_indices = support_index_iterator(backend, meas.object_nums) + supp_indices = support_index_iterator(backend, meas.group_int_idxs) exprs = Vector{JuMP.AbstractJuMPScalar}(undef, length(supp_indices)) labels = Vector{Set{DataType}}(undef, length(supp_indices)) lookup_dict = Dict{Vector{Float64}, Int}() @@ -575,7 +575,7 @@ function transcribe_measures!( @inbounds labels[counter] = index_to_labels(backend, i) end # save the transcription information - mref = InfiniteOpt._make_variable_ref(model, idx) + mref = InfiniteOpt.GeneralVariableRef(model, idx) data = transcription_data(backend) data.measure_lookup[mref] = lookup_dict data.measure_mappings[mref] = exprs @@ -755,10 +755,10 @@ function transcribe_constraints!( constr = object.constraint func = JuMP.jump_function(constr) set = JuMP.moi_set(constr) - obj_nums = object.object_nums - cref = InfiniteOpt._make_constraint_ref(model, idx) + group_int_idxs = object.group_int_idxs + cref = InfiniteOpt.InfOptConstraintRef(model, idx) # prepare the iteration helpers - supp_indices = support_index_iterator(backend, obj_nums) + supp_indices = support_index_iterator(backend, group_int_idxs) crefs = Vector{JuMP.ConstraintRef}(undef, length(supp_indices)) supps = Vector{Tuple}(undef, length(supp_indices)) labels = Vector{Set{DataType}}(undef, length(supp_indices)) @@ -773,7 +773,7 @@ function transcribe_constraints!( if !isnothing(info_ref) @inbounds crefs[counter] = info_ref @inbounds supps[counter] = Tuple(param_supps[j][i[j]] - for j in obj_nums) + for j in group_int_idxs) @inbounds labels[counter] = index_to_labels(backend, i) counter += 1 end @@ -796,7 +796,7 @@ function transcribe_constraints!( set, raw_supp, new_name) @inbounds crefs[counter] = new_cref @inbounds supps[counter] = Tuple(param_supps[j][i[j]] - for j in obj_nums) + for j in group_int_idxs) @inbounds labels[counter] = index_to_labels(backend, i) counter += 1 end @@ -837,7 +837,7 @@ function transcribe_derivative_evaluations!( ) for (idx, object) in InfiniteOpt._data_dictionary(model, InfiniteOpt.Derivative) # get the basic variable information - dref = InfiniteOpt._make_variable_ref(model, idx) + dref = InfiniteOpt.GeneralVariableRef(model, idx) pref = dispatch_variable_ref(object.variable.parameter_ref) method = InfiniteOpt.derivative_method(pref) order = object.variable.order @@ -847,13 +847,13 @@ function transcribe_derivative_evaluations!( vref = object.variable.variable_ref if !InfiniteOpt.allows_high_order_derivatives(method) && order > 1 d_idx = model.deriv_lookup[vref, object.variable.parameter_ref, order - 1] - vref = InfiniteOpt._make_variable_ref(model, d_idx) + vref = InfiniteOpt.GeneralVariableRef(model, d_idx) end exprs = InfiniteOpt.evaluate_derivative(dref, vref, method, backend) # prepare the iteration helpers - param_obj_num = InfiniteOpt._object_number(pref) - obj_nums = filter(!isequal(param_obj_num), InfiniteOpt._object_numbers(dref)) - supp_indices = support_index_iterator(backend, obj_nums) + param_group_int_idx = InfiniteOpt.parameter_group_int_index(pref) + group_int_idxs = filter(!isequal(param_group_int_idx), InfiniteOpt.parameter_group_int_indices(dref)) + supp_indices = support_index_iterator(backend, group_int_idxs) # transcribe the constraints set = MOI.EqualTo(0.0) for i in supp_indices @@ -886,19 +886,19 @@ function transcribe_variable_collocation_restictions!( data = transcription_data(backend) set = MOI.EqualTo(0.0) for (pidx, vidxs) in model.piecewise_vars - pref = InfiniteOpt._make_variable_ref(model, pidx) + pref = InfiniteOpt.GeneralVariableRef(model, pidx) if !InfiniteOpt.has_generative_supports(pref) continue end - obj_num = InfiniteOpt._object_number(pref) - supps = reverse!(data.supports[obj_num][1:end-1]) - labels = reverse!(data.support_labels[obj_num][1:end-1]) + group_int_idx = InfiniteOpt.parameter_group_int_index(pref) + supps = reverse!(data.supports[group_int_idx][1:end-1]) + labels = reverse!(data.support_labels[group_int_idx][1:end-1]) @assert any(l -> l <: InfiniteOpt.PublicLabel, first(labels)) v_manip = GeneralVariableRef(model, -1, IndependentParameterIndex) # placeholder for vidx in vidxs - vref = InfiniteOpt._make_variable_ref(model, vidx) - obj_nums = filter(!isequal(obj_num), InfiniteOpt._object_numbers(vref)) - supp_indices = support_index_iterator(backend, obj_nums) + vref = InfiniteOpt.GeneralVariableRef(model, vidx) + group_int_idxs = filter(!isequal(group_int_idx), InfiniteOpt.parameter_group_int_indices(vref)) + supp_indices = support_index_iterator(backend, group_int_idxs) for (s, ls) in zip(supps, labels) if any(l -> l <: InfiniteOpt.PublicLabel, ls) v_manip = InfiniteOpt.make_reduced_expr(vref, pref, s, backend) diff --git a/src/array_parameters.jl b/src/array_parameters.jl index 627cd70a..adc319e1 100644 --- a/src/array_parameters.jl +++ b/src/array_parameters.jl @@ -15,7 +15,7 @@ function _add_data_object( object::MultiParameterData ) index = MOIUC.add_item(model.dependent_params, object) - push!(model.param_object_indices, index) + push!(model.param_group_indices, index) return index end @@ -43,8 +43,14 @@ function _data_object(pref::DependentParameterRef) return object end -# Extend _core_variable_object -function _core_variable_object(pref::DependentParameterRef) +""" + core_object(pref::DependentParameterRef)::DependentParameters + +Retrieve the underlying core `DependentParameters` object for `pref`. Note that +this object applies to `pref` and the other infinite parameters it is coupled +with. This is intended as an advanced method for developers. +""" +function core_object(pref::DependentParameterRef) return _data_object(pref).parameters end @@ -285,11 +291,11 @@ function add_parameters( error("The amounts of names and dependent parameters do not match.") end # make the parameter model object - obj_num = length(_param_object_indices(model)) + 1 + group_int_idx = length(parameter_group_indices(model)) + 1 first_param_num = model.last_param_num + 1 last_param_num = model.last_param_num += num_params param_nums = first_param_num:last_param_num - data_object = MultiParameterData(params, obj_num, param_nums, names) + data_object = MultiParameterData(params, group_int_idx, param_nums, names) # add the data object to the model and make the references obj_index = _add_data_object(model, data_object) # reset the name dictionary @@ -386,7 +392,7 @@ julia> used_by_infinite_variable(pref) true ``` """ -function used_by_infinite_variable(pref::DependentParameterRef)::Bool +function used_by_infinite_variable(pref::DependentParameterRef) return !isempty(_infinite_variable_dependencies(pref)) end @@ -402,7 +408,7 @@ julia> used_by_parameter_function(pref) true ``` """ -function used_by_parameter_function(pref::DependentParameterRef)::Bool +function used_by_parameter_function(pref::DependentParameterRef) return !isempty(_parameter_function_dependencies(pref)) end @@ -418,7 +424,7 @@ julia> used_by_measure(pref) true ``` """ -function used_by_measure(pref::DependentParameterRef)::Bool +function used_by_measure(pref::DependentParameterRef) return !isempty(_measure_dependencies(pref)) end @@ -434,7 +440,7 @@ julia> used_by_constraint(pref) false ``` """ -function used_by_constraint(pref::DependentParameterRef)::Bool +function used_by_constraint(pref::DependentParameterRef) return !isempty(_constraint_dependencies(pref)) end @@ -450,12 +456,12 @@ julia> used_by_derivative(pref) false ``` """ -function used_by_derivative(pref::DependentParameterRef)::Bool +function used_by_derivative(pref::DependentParameterRef) return !isempty(_derivative_dependencies(pref)) end # Extend used by objective -used_by_objective(pref::DependentParameterRef)::Bool = false +used_by_objective(pref::DependentParameterRef) = false """ is_used(pref::DependentParameterRef)::Bool @@ -469,7 +475,7 @@ julia> is_used(pref) true ``` """ -function is_used(pref::DependentParameterRef)::Bool +function is_used(pref::DependentParameterRef) return used_by_measure(pref) || used_by_constraint(pref) || used_by_infinite_variable(pref) || used_by_derivative(pref) || used_by_parameter_function(pref) @@ -479,37 +485,41 @@ end # PARAMETER OBJECT METHODS ################################################################################ # Extend _parameter_number -function _parameter_number(pref::DependentParameterRef)::Int +function _parameter_number(pref::DependentParameterRef) return _data_object(pref).parameter_nums[_param_index(pref)] end # Extend _parameter_numbers -function _parameter_numbers(pref::DependentParameterRef)::Vector{Int} +function _parameter_numbers(pref::DependentParameterRef) return [_parameter_number(pref)] end -# Extend _object_number -function _object_number(pref::DependentParameterRef)::Int - return _data_object(pref).object_num +""" + parameter_group_int_index(pref::DependentParameterRef)::Int + +Return the infinite parameter group integer index that corresponds to `pref`. +""" +function parameter_group_int_index(pref::DependentParameterRef) + return _data_object(pref).group_int_idx end -# Extend _object_numbers -function _object_numbers(pref::DependentParameterRef)::Vector{Int} - return [_object_number(pref)] +# Extend parameter_group_int_indices +function parameter_group_int_indices(pref::DependentParameterRef) + return [parameter_group_int_index(pref)] end ## Set helper methods for adapting data_objects with parametric changes # No change needed function _adaptive_data_update(pref::DependentParameterRef, params::P, - data::MultiParameterData{P})::Nothing where {P <: DependentParameters} + data::MultiParameterData{P}) where {P <: DependentParameters} data.parameters = params return end # Reconstruction is necessary function _adaptive_data_update(pref::DependentParameterRef, params::P1, - data::MultiParameterData{P2})::Nothing where {P1, P2} - new_data = MultiParameterData(params, data.object_num, data.parameter_nums, + data::MultiParameterData{P2}) where {P1, P2} + new_data = MultiParameterData(params, data.group_int_idx, data.parameter_nums, data.names, data.parameter_func_indices, data.infinite_var_indices, data.derivative_indices, data.measure_indices, @@ -520,9 +530,11 @@ function _adaptive_data_update(pref::DependentParameterRef, params::P1, return end -# Extend _set_core_variable_object -function _set_core_variable_object(pref::DependentParameterRef, - params::DependentParameters)::Nothing +# Extend _set_core_object +function _set_core_object( + pref::DependentParameterRef, + params::DependentParameters + ) _adaptive_data_update(pref, params, _data_object(pref)) return end @@ -560,7 +572,7 @@ end # Get the raw derivative method vector function _derivative_methods(pref::DependentParameterRef) - return _core_variable_object(pref).derivative_methods + return core_object(pref).derivative_methods end """ @@ -598,7 +610,7 @@ function _adaptive_method_update(pref, new_methods = [i == _param_index(pref) ? method : m for (i, m) in enumerate(methods)] new_params = DependentParameters(p.domain, p.supports, p.sig_digits, new_methods) - _set_core_variable_object(pref, new_params) + _set_core_object(pref, new_params) return end @@ -616,14 +628,15 @@ julia> set_derivative_method(d, FiniteDifference()) ``` """ -function set_derivative_method(pref::DependentParameterRef, +function set_derivative_method( + pref::DependentParameterRef, method::AbstractDerivativeMethod - )::Nothing + ) if !(method isa NonGenerativeDerivativeMethod) error("Must specify a subtype of `NonGenerativeDerivativeMethod` for " * "for a dependent parameter.") end - _adaptive_method_update(pref, _core_variable_object(pref), method) + _adaptive_method_update(pref, core_object(pref), method) _reset_derivative_constraints(pref) if is_used(pref) set_transformation_backend_ready(JuMP.owner_model(pref), false) @@ -645,9 +658,10 @@ julia> set_all_derivative_methods(model, OrthogonalCollocation(2)) ``` """ -function set_all_derivative_methods(model::InfiniteModel, +function set_all_derivative_methods( + model::InfiniteModel, method::AbstractDerivativeMethod - )::Nothing + ) for pref in all_parameters(model, InfiniteParameter) set_derivative_method(pref, method) end @@ -659,14 +673,12 @@ end ################################################################################ ## Get the individual infinite domain if possible # raw_domain -function _parameter_domain(pref::DependentParameterRef)::InfiniteArrayDomain - return _core_variable_object(pref).domain +function _parameter_domain(pref::DependentParameterRef) + return core_object(pref).domain end # CollectionDomain -function _parameter_domain(domain::CollectionDomain{S}, - pref::DependentParameterRef - )::S where {S <: InfiniteScalarDomain} +function _parameter_domain(domain::CollectionDomain, pref::DependentParameterRef) return collection_domains(domain)[_param_index(pref)] end @@ -690,14 +702,12 @@ julia> infinite_domain(x[1]) [-1, 1] ``` """ -function infinite_domain(pref::DependentParameterRef)::InfiniteScalarDomain +function infinite_domain(pref::DependentParameterRef) return _parameter_domain(_parameter_domain(pref), pref) end # Check that prefs are complete -function _check_complete_param_array( - prefs::AbstractArray{<:DependentParameterRef} - )::Nothing +function _check_complete_param_array(prefs::AbstractArray{<:DependentParameterRef}) if length(prefs) != _num_parameters(first(prefs)) error("Dimensions of parameter container and the infinite domain do not " * "match, ensure all related dependent parameters are included.") @@ -721,21 +731,22 @@ dim: 2 ) ``` """ -function infinite_domain(prefs::AbstractArray{<:DependentParameterRef} - )::InfiniteArrayDomain +function infinite_domain(prefs::AbstractArray{<:DependentParameterRef}) _check_complete_param_array(prefs) return _parameter_domain(first(prefs)) end # Update the underlying domain and delete the supports -function _update_parameter_domain(pref::DependentParameterRef, - new_domain::InfiniteArrayDomain)::Nothing - old_params = _core_variable_object(pref) +function _update_parameter_domain( + pref::DependentParameterRef, + new_domain::InfiniteArrayDomain + ) + old_params = core_object(pref) new_supports = Dict{Vector{Float64}, Set{DataType}}() sig_figs = significant_digits(pref) methods = _derivative_methods(pref) new_params = DependentParameters(new_domain, new_supports, sig_figs, methods) - _set_core_variable_object(pref, new_params) + _set_core_object(pref, new_params) for i in 1:length(new_domain) idx = DependentParameterIndex(JuMP.index(pref).object_index, i) p = DependentParameterRef(JuMP.owner_model(pref), idx) @@ -766,8 +777,10 @@ julia> infinite_domain(x[1]) [0, 2] ``` """ -function set_infinite_domain(pref::DependentParameterRef, - domain::InfiniteScalarDomain)::Nothing +function set_infinite_domain( + pref::DependentParameterRef, + domain::InfiniteScalarDomain + ) old_domain = _parameter_domain(pref) if !(old_domain isa CollectionDomain) error("Cannot set the individual infinite domain of $pref if the " * @@ -798,8 +811,10 @@ measures. julia> set_infinite_domain(x, CollectionDomain([IntervalDomain(0, 1), IntervalDomain(0, 2)])) ``` """ -function set_infinite_domain(prefs::AbstractArray{<:DependentParameterRef}, - domain::InfiniteArrayDomain)::Nothing +function set_infinite_domain( + prefs::AbstractArray{<:DependentParameterRef}, + domain::InfiniteArrayDomain + ) if any(used_by_measure(pref) for pref in prefs) error("Cannot override the infinite domain of $prefs since it is used by " * "a measure.") @@ -824,7 +839,7 @@ julia> has_lower_bound(x[1]) true ``` """ -function JuMP.has_lower_bound(pref::DependentParameterRef)::Bool +function JuMP.has_lower_bound(pref::DependentParameterRef) domain = _parameter_domain(pref) if domain isa CollectionDomain return JuMP.has_lower_bound(collection_domains(domain)[_param_index(pref)]) @@ -846,7 +861,7 @@ julia> lower_bound(x[1]) 0.0 ``` """ -function JuMP.lower_bound(pref::DependentParameterRef)::Number +function JuMP.lower_bound(pref::DependentParameterRef) if !JuMP.has_lower_bound(pref) error("Parameter $(pref) does not have a lower bound.") end @@ -871,7 +886,7 @@ julia> lower_bound(t) -1.0 ``` """ -function JuMP.set_lower_bound(pref::DependentParameterRef, lower::Real)::Nothing +function JuMP.set_lower_bound(pref::DependentParameterRef, lower::Real) domain = infinite_domain(pref) new_domain = JuMP.set_lower_bound(domain, lower) set_infinite_domain(pref, new_domain) @@ -893,8 +908,8 @@ julia> has_upper_bound(x[1]) true ``` """ -function JuMP.has_upper_bound(pref::DependentParameterRef)::Bool - domain = _core_variable_object(pref).domain +function JuMP.has_upper_bound(pref::DependentParameterRef) + domain = core_object(pref).domain if domain isa CollectionDomain return JuMP.has_upper_bound(collection_domains(domain)[_param_index(pref)]) else @@ -915,7 +930,7 @@ julia> upper_bound(x[1]) 0.0 ``` """ -function JuMP.upper_bound(pref::DependentParameterRef)::Number +function JuMP.upper_bound(pref::DependentParameterRef) if !JuMP.has_upper_bound(pref) error("Parameter $(pref) does not have a upper bound.") end @@ -940,7 +955,7 @@ julia> upper_bound(t) -1.0 ``` """ -function JuMP.set_upper_bound(pref::DependentParameterRef, upper::Real)::Nothing +function JuMP.set_upper_bound(pref::DependentParameterRef, upper::Real) domain = infinite_domain(pref) new_domain = JuMP.set_upper_bound(domain, upper) set_infinite_domain(pref, new_domain) @@ -951,9 +966,8 @@ end # SUPPORT METHODS ################################################################################ # Get the raw supports -function _parameter_supports(pref::DependentParameterRef - )::Dict{Vector{Float64}, Set{DataType}} - return _core_variable_object(pref).supports +function _parameter_supports(pref::DependentParameterRef) + return core_object(pref).supports end """ @@ -967,8 +981,8 @@ julia> significant_digits(x[1]) 12 ``` """ -function significant_digits(pref::DependentParameterRef)::Int - return _core_variable_object(pref).sig_digits +function significant_digits(pref::DependentParameterRef) + return core_object(pref).sig_digits end """ @@ -989,8 +1003,10 @@ julia> num_supports(x[1], label = MCSample) 0 ``` """ -function num_supports(pref::DependentParameterRef; - label::Type{<:AbstractSupportLabel} = PublicLabel)::Int +function num_supports( + pref::DependentParameterRef; + label::Type{<:AbstractSupportLabel} = PublicLabel + ) supp_dict = _parameter_supports(pref) if label == All || (!has_internal_supports(pref) && label == PublicLabel) return length(supp_dict) @@ -1015,9 +1031,10 @@ julia> num_supports(x) 2 ``` """ -function num_supports(prefs::AbstractArray{<:DependentParameterRef}; +function num_supports( + prefs::AbstractArray{<:DependentParameterRef}; label::Type{<:AbstractSupportLabel} = PublicLabel - )::Int + ) _check_complete_param_array(prefs) return num_supports(first(prefs), label = label) end @@ -1033,7 +1050,7 @@ julia> has_supports(x[1]) true ``` """ -has_supports(pref::DependentParameterRef)::Bool = !isempty(_parameter_supports(pref)) +has_supports(pref::DependentParameterRef) = !isempty(_parameter_supports(pref)) """ has_supports(prefs::AbstractArray{<:DependentParameterRef})::Bool @@ -1047,7 +1064,7 @@ julia> has_supports(x) true ``` """ -function has_supports(prefs::AbstractArray{<:DependentParameterRef})::Bool +function has_supports(prefs::AbstractArray{<:DependentParameterRef}) _check_complete_param_array(prefs) return has_supports(first(prefs)) end @@ -1069,8 +1086,10 @@ julia> supports(x[1]) 1.0 ``` """ -function supports(pref::DependentParameterRef; - label::Type{<:AbstractSupportLabel} = PublicLabel)::Vector{Float64} +function supports( + pref::DependentParameterRef; + label::Type{<:AbstractSupportLabel} = PublicLabel + ) supp_dict = _parameter_supports(pref) pindex = _param_index(pref) if label == All || (!has_internal_supports(pref) && label == PublicLabel) @@ -1102,9 +1121,10 @@ julia> supports(x) # columns are supports 0.0 1.0 ``` """ -function supports(prefs::AbstractArray{<:DependentParameterRef}; - label::Type{<:AbstractSupportLabel} = PublicLabel - )::Vector{<:AbstractArray{<:Real}} +function supports( + prefs::AbstractArray{<:DependentParameterRef}; + label::Type{<:AbstractSupportLabel} = PublicLabel + ) _check_complete_param_array(prefs) inds = Collections.indices(prefs) supp_dict = _parameter_supports(first(prefs)) @@ -1117,9 +1137,10 @@ function supports(prefs::AbstractArray{<:DependentParameterRef}; end # Dispatch for Vectors to make predictable matrix outputs -function supports(prefs::Vector{DependentParameterRef}; - label::Type{<:AbstractSupportLabel} = PublicLabel - )::Array{Float64, 2} +function supports( + prefs::Vector{DependentParameterRef}; + label::Type{<:AbstractSupportLabel} = PublicLabel + ) if !has_supports(prefs) return zeros(Float64, _num_parameters(first(prefs)), 0) elseif label == All || (!has_internal_supports(first(prefs)) && label == PublicLabel) @@ -1141,16 +1162,18 @@ function supports(prefs::Vector{DependentParameterRef}; end # Define method for overriding the current supports -function _update_parameter_supports(prefs::AbstractArray{<:DependentParameterRef}, - supports::Array{<:Real, 2}, - label::Type{<:AbstractSupportLabel})::Nothing +function _update_parameter_supports( + prefs::AbstractArray{<:DependentParameterRef}, + supports::Array{<:Real, 2}, + label::Type{<:AbstractSupportLabel} + ) domain = _parameter_domain(first(prefs)) new_supps = Dict{Vector{Float64}, Set{DataType}}(s => Set([label]) for s in eachcol(supports)) sig_figs = significant_digits(first(prefs)) methods = _derivative_methods(first(prefs)) new_params = DependentParameters(domain, new_supps, sig_figs, methods) - _set_core_variable_object(first(prefs), new_params) + _set_core_object(first(prefs), new_params) _set_has_internal_supports(first(prefs), label <: InternalLabel) for pref in prefs _reset_derivative_constraints(pref) @@ -1165,7 +1188,7 @@ end function _make_support_matrix( supports::Vector{<:AbstractArray{<:Real}}, inds::Collections.ContainerIndices - )::Array{Float64, 2} + ) supp_inds = Collections.indices(first(supports)) supp_inds == inds || error("Inconsistent support indices") lens = [length(supp) for supp in supports] @@ -1218,7 +1241,7 @@ function set_supports( supports::Vector{<:AbstractArray{<:Real}}; force::Bool = false, label::Type{<:AbstractSupportLabel} = UserDefined - )::Nothing + ) inds = Collections.indices(prefs) supps = _make_support_matrix(supports, inds) set_supports(Collections.vectorize(prefs, inds), supps, force = force, @@ -1232,7 +1255,7 @@ function set_supports( supports::Array{<:Real, 2}; force::Bool = false, label::Type{<:AbstractSupportLabel} = UserDefined - )::Nothing + ) domain = infinite_domain(prefs) # this does a check on prefs if has_supports(prefs) && !force error("Unable set supports for $prefs since they already have supports." * @@ -1293,7 +1316,7 @@ function add_supports( supports::Vector{<:AbstractArray{<:Real}}; label::Type{<:AbstractSupportLabel} = UserDefined, # interal keyword args check::Bool = true - )::Nothing + ) inds = Collections.indices(prefs) supps = _make_support_matrix(supports, inds) add_supports(Collections.vectorize(prefs, inds), supps, label = label, @@ -1307,7 +1330,7 @@ function add_supports( supports::Array{<:Real, 2}; label::Type{<:AbstractSupportLabel} = UserDefined, # internal keyword args check::Bool = true - )::Nothing + ) domain = infinite_domain(prefs) # this does a check on prefs if check && !supports_in_domain(supports, domain) error("Supports violate the domain of the infinite domain.") @@ -1361,7 +1384,7 @@ julia> delete_supports(w) function delete_supports( prefs::AbstractArray{<:DependentParameterRef}; label::Type{<:AbstractSupportLabel} = All - )::Nothing + ) _check_complete_param_array(prefs) supp_dict = _parameter_supports(first(prefs)) for pref in prefs @@ -1414,7 +1437,7 @@ function generate_and_add_supports!( prefs::AbstractArray{<:DependentParameterRef}, domain::InfiniteArrayDomain; num_supports::Int = DefaultNumSupports - )::Nothing + ) new_supps, label = generate_supports(domain, num_supports = num_supports, sig_digits = significant_digits(first(prefs))) @@ -1429,7 +1452,7 @@ function generate_and_add_supports!( domain::InfiniteArrayDomain, method::Type{<:AbstractSupportLabel}; num_supports::Int = DefaultNumSupports - )::Nothing + ) new_supps, label = generate_supports(domain, method, num_supports = num_supports, sig_digits = significant_digits(first(prefs))) @@ -1465,7 +1488,7 @@ function fill_in_supports!( prefs::AbstractArray{<:DependentParameterRef}; num_supports::Int = DefaultNumSupports, modify::Bool = true - )::Nothing + ) domain = infinite_domain(prefs) # does check for bad container current_amount = InfiniteOpt.num_supports(first(prefs)) if (modify || current_amount == 0) && (current_amount < num_supports) @@ -1507,7 +1530,7 @@ function fill_in_supports!( model::InfiniteModel; num_supports::Int = DefaultNumSupports, modify::Bool = true - )::Nothing + ) # fill in the the supports of each independent parameter for (key, _) in model.independent_params pref = dispatch_variable_ref(model, key) @@ -1552,7 +1575,7 @@ julia> num_parameters(model, IndependentParameter) function num_parameters( model::InfiniteModel, type::Type{InfOptParameter} = InfOptParameter - )::Int + ) num_pars = num_parameters(model, IndependentParameter) num_pars += num_parameters(model, FiniteParameter) num_pars += num_parameters(model, DependentParameters) @@ -1563,7 +1586,7 @@ end function num_parameters( model::InfiniteModel, type::Type{C} - )::Int where {C <: ScalarParameter} + ) where {C <: ScalarParameter} return length(_data_dictionary(model, type)) end @@ -1571,7 +1594,7 @@ end function num_parameters( model::InfiniteModel, type::Type{ScalarParameter} - )::Int + ) num_pars = num_parameters(model, FiniteParameter) num_pars += num_parameters(model, IndependentParameter) return num_pars @@ -1581,7 +1604,7 @@ end function num_parameters( model::InfiniteModel, type::Type{DependentParameters} - )::Int + ) num_pars = 0 for (_, object) in _data_dictionary(model, type) num_pars += length(object.names) @@ -1593,7 +1616,7 @@ end function num_parameters( model::InfiniteModel, type::Type{InfiniteParameter} - )::Int + ) num_pars = num_parameters(model, IndependentParameter) num_pars += num_parameters(model, DependentParameters) return num_pars @@ -1632,7 +1655,7 @@ julia> all_parameters(model, FiniteParameter) function all_parameters( model::InfiniteModel, type::Type{InfOptParameter} = InfOptParameter - )::Vector{GeneralVariableRef} + ) prefs_list = all_parameters(model, IndependentParameter) append!(prefs_list, all_parameters(model, DependentParameters)) append!(prefs_list, all_parameters(model, FiniteParameter)) @@ -1643,10 +1666,10 @@ end function all_parameters( model::InfiniteModel, type::Type{C} - )::Vector{GeneralVariableRef} where {C <: InfOptParameter} + ) where {C <: InfOptParameter} prefs_list = Vector{GeneralVariableRef}(undef, num_parameters(model, type)) for (i, (index, _)) in enumerate(_data_dictionary(model, type)) - prefs_list[i] = _make_parameter_ref(model, index) + prefs_list[i] = GeneralVariableRef(model, index) end return prefs_list end @@ -1655,7 +1678,7 @@ end function all_parameters( model::InfiniteModel, type::Type{ScalarParameter} - )::Vector{GeneralVariableRef} + ) prefs_list = all_parameters(model, IndependentParameter) append!(prefs_list, all_parameters(model, FiniteParameter)) return prefs_list @@ -1665,13 +1688,13 @@ end function all_parameters( model::InfiniteModel, type::Type{DependentParameters} - )::Vector{GeneralVariableRef} + ) prefs_list = Vector{GeneralVariableRef}(undef, num_parameters(model, type)) counter = 1 for (index, object) in _data_dictionary(model, type) for i in eachindex(object.names) dep_idx = DependentParameterIndex(index, i) - prefs_list[counter] = _make_parameter_ref(model, dep_idx) + prefs_list[counter] = GeneralVariableRef(model, dep_idx) counter += 1 end end @@ -1682,7 +1705,7 @@ end function all_parameters( model::InfiniteModel, type::Type{InfiniteParameter} - )::Vector{GeneralVariableRef} + ) prefs_list = all_parameters(model, DependentParameters) append!(prefs_list, all_parameters(model, IndependentParameter)) return prefs_list @@ -1727,10 +1750,10 @@ Subject to function JuMP.delete( model::InfiniteModel, prefs::AbstractArray{<:DependentParameterRef} - )::Nothing + ) @assert JuMP.is_valid(model, first(prefs)) "Parameter references are invalid." _check_complete_param_array(prefs) - gvrefs = [_make_parameter_ref(model, JuMP.index(pref)) for pref in prefs] + gvrefs = [GeneralVariableRef(model, JuMP.index(pref)) for pref in prefs] # ensure deletion is okay (prefs are not used by measure data) for pref in gvrefs for mindex in _measure_dependencies(pref) @@ -1758,7 +1781,7 @@ function JuMP.delete( _update_constraints(model, pref) end # get the object and parameter numbers - obj_num = _object_number(first(prefs)) + group_int_idx = parameter_group_int_index(first(prefs)) param_nums = collect(_data_object(first(prefs)).parameter_nums) # delete derivatives that depend on any of these parameters for pref in gvrefs @@ -1768,7 +1791,7 @@ function JuMP.delete( end # delete parameter information stored in model _delete_data_object(first(prefs)) - # update the object numbers and parameter numbers - _update_model_numbers(model, obj_num, param_nums) + # update the parameter group integer indices and parameter numbers + _update_model_numbers(model, group_int_idx, param_nums) return end diff --git a/src/backends.jl b/src/backends.jl index 4a0a671c..7575a86f 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -161,15 +161,34 @@ end Retrieve some attribute `attr` from the `backend`. This is a general purpose method typically used to query optimizer related information. -This serves as an extension point for new backend types. No extension -is needed for [`JuMPBackend`](@ref)s. +This serves as an extension point for new backend types. New backends +should include extensions for the following attributes as appropriate: + - `MOI.Silent` + - `MOI.TimeLimitSec` + - `MOI.RawOptimizerAttribute` + - `MOI.SolverName` + - `MOI.TerminationStatus` + - `MOI.RawStatusString` + - `MOI.PrimalStatus` + - `MOI.DualStatus` + - `MOI.SolveTimeSec` + - `MOI.ResultCount` + - `MOI.SimplexIterations` + - `MOI.BarrierIterations` + - `MOI.NodeCount` + - `MOI.ObjectiveBound` + - `MOI.RelativeGap` + - `MOI.ObjectiveValue` + - `MOI.DualObjectiveValue` + +No extension is needed for [`JuMPBackend`](@ref)s. """ function JuMP.get_attribute( backend::AbstractTransformationBackend, attr ) error("`JuMP.get_attribute` not implemented for transformation backends " * - "of type `$(typeof(backend))`.") + "of type `$(typeof(backend))` with attribute `$attr`.") end """ @@ -187,6 +206,9 @@ julia> get_attribute(model, MOI.TimeLimitSec()) function JuMP.get_attribute(model::InfiniteModel, attr) return JuMP.get_attribute(model.backend, attr) end +function JuMP.get_attribute(model::InfiniteModel, attr::String) + return JuMP.get_attribute(model.backend, MOI.RawOptimizerAttribute(attr)) +end function JuMP.get_optimizer_attribute(model::InfiniteModel, attr) return JuMP.get_attribute(model, attr) end @@ -196,8 +218,13 @@ end Specify some attribute `attr` to the `backend`. This is a general purpose method typically used to set optimizer related information. -This serves as an extension point for new backend types. No extension -is needed for [`JuMPBackend`](@ref)s. +This serves as an extension point for new backend types. New backends +should include extensions for attributes of type: + - `MOI.Silent` + - `MOI.TimeLimitSec` + - `MOI.RawOptimizerAttribute` + +No extension is needed for [`JuMPBackend`](@ref)s. """ function JuMP.set_attribute( backend::AbstractTransformationBackend, @@ -205,7 +232,7 @@ function JuMP.set_attribute( value ) error("`JuMP.set_attribute` not implemented for transformation backends " * - "of type `$(typeof(backend))`.") + "of type `$(typeof(backend))` with attribute `$attr`.") end """ @@ -222,6 +249,9 @@ julia> set_attribute(model, MOI.TimeLimitSec(), 42.0) function JuMP.set_attribute(model::InfiniteModel, attr, value) return JuMP.set_attribute(model.backend, attr, value) end +function JuMP.set_attribute(model::InfiniteModel, attr::String, value) + return JuMP.set_attribute(model.backend, MOI.RawOptimizerAttribute(attr), value) +end function JuMP.set_optimizer_attribute(model::InfiniteModel, attr, value) return JuMP.set_attribute(model, attr, value) end @@ -387,75 +417,116 @@ end ################################################################################ # JUMP-BASED OPTIMIZER API ################################################################################ -# Single argument methods -for func in (:set_silent, :unset_silent, :bridge_constraints, - :unset_time_limit_sec, :time_limit_sec, :solver_name, :backend, - :mode, :unsafe_backend, :compute_conflict!, :copy_conflict, - :set_string_names_on_creation) +# 1 arg setters +for (func, Attr, val) in ( + (:set_silent, :Silent, true), + (:unset_silent, :Silent, false), + (:unset_time_limit_sec, :TimeLimitSec, nothing) + ) @eval begin @doc """ - JuMP.$($func)(backend::AbstractTransformationBackend) + JuMP.$($func)(model::InfiniteModel) - Implment `JuMP.$($func)` for transformation backends. If applicable, this - should be extended for new backend types. No extension is needed for - [`JuMPBackend`](@ref)s. + Extend [`JuMP.$($func)`](https://jump.dev/JuMP.jl/v1/api/JuMP/#$($func)) + to accept `InfiniteModel`s. This relies on the underlying transformation + backend supporting `JuMP.set_attribute` with attribute `$(MOI.$Attr)()`. """ - function JuMP.$func(backend::AbstractTransformationBackend) - error("`JuMP.$($func)` not defined for backends of type " * - "`$(typeof(backend))`.") - end - - # Define for JuMPBackend - function JuMP.$func(backend::JuMPBackend) - return JuMP.$func(backend.model) + function JuMP.$func(model::InfiniteModel) + return JuMP.set_attribute(model.backend, MOI.$Attr(), $val) end + end +end +# 1 arg getters +for (func, Attr) in ((:time_limit_sec, :TimeLimitSec), (:solver_name, :SolverName)) + @eval begin @doc """ JuMP.$($func)(model::InfiniteModel) Extend [`JuMP.$($func)`](https://jump.dev/JuMP.jl/v1/api/JuMP/#$($func)) to accept `InfiniteModel`s. This relies on the underlying transformation - backend supporting `JuMP.$($func)`. + backend supporting `JuMP.get_attribute` with attribute `$(MOI.$Attr)()`. """ function JuMP.$func(model::InfiniteModel) - return JuMP.$func(model.backend) - end + return JuMP.get_attribute(model.backend, MOI.$Attr()) + end end end -# Two argument setters -for func in (:set_time_limit_sec, :set_string_names_on_creation, :add_bridge) +""" + JuMP.set_time_limit_sec(model::InfiniteModel, value::Real) + +Extend [`JuMP.set_time_limit_sec`](https://jump.dev/JuMP.jl/v1/api/JuMP/#set_time_limit_sec) +to accept `InfiniteModel`s. This relies on the underlying transformation +backend supporting `JuMP.set_attribute` with attribute `MOI.TimeLimitSec()`. +""" +function JuMP.set_time_limit_sec(model::InfiniteModel, value::Real) + return JuMP.set_attribute(model.backend, MOI.TimeLimitSec(), Float64(value)) +end + +# Single argument methods that don't rely on `[get/set]_attribute` +for func in (:bridge_constraints, :backend, :mode, :unsafe_backend, + :compute_conflict!, :copy_conflict) @eval begin @doc """ - JuMP.$($func)(backend::AbstractTransformationBackend, value) + JuMP.$($func)(backend::AbstractTransformationBackend) - Implment `JuMP.$($func)` for transformation backends. If applicable, this - should be extended for new backend types. No extension is needed for - [`JuMPBackend`](@ref)s. + Implement [`JuMP.$($func)`](https://jump.dev/JuMP.jl/v1/api/JuMP/#$($func)) + for transformation backends. If applicable, this should be extended for + new backend types. No extension is needed for [`JuMPBackend`](@ref)s. """ - function JuMP.$func(backend::AbstractTransformationBackend, value) + function JuMP.$func(backend::AbstractTransformationBackend) error("`JuMP.$($func)` not defined for backends of type " * - "`$(typeof(backend))`.") + "`$(typeof(backend))`.") end # Define for JuMPBackend - function JuMP.$func(backend::JuMPBackend, value) - return JuMP.$func(backend.model, value) + function JuMP.$func(backend::JuMPBackend) + return JuMP.$func(backend.model) end @doc """ - JuMP.$($func)(model::InfiniteModel, value) + JuMP.$($func)(model::InfiniteModel) Extend [`JuMP.$($func)`](https://jump.dev/JuMP.jl/v1/api/JuMP/#$($func)) to accept `InfiniteModel`s. This relies on the underlying transformation backend supporting `JuMP.$($func)`. """ - function JuMP.$func(model::InfiniteModel, value) - return JuMP.$func(model.backend, value) + function JuMP.$func(model::InfiniteModel) + return JuMP.$func(model.backend) end end end + +""" + JuMP.add_bridge(backend::AbstractTransformationBackend, value) + +Implement [`JuMP.add_bridge`](https://jump.dev/JuMP.jl/v1/api/JuMP/#add_bridge) +for transformation backends. If applicable, this should be extended for +new backend types. No extension is needed for [`JuMPBackend`](@ref)s. +""" +function JuMP.add_bridge(backend::AbstractTransformationBackend, value) + error("`JuMP.add_bridge` not defined for backends of type " * + "`$(typeof(backend))`.") +end + +# Define for JuMPBackend +function JuMP.add_bridge(backend::JuMPBackend, value) + return JuMP.add_bridge(backend.model, value) +end + +""" + JuMP.add_bridge(model::InfiniteModel, value) + +Extend [`JuMP.add_bridge`](https://jump.dev/JuMP.jl/v1/api/JuMP/#add_bridge) +to accept `InfiniteModel`s. This relies on the underlying transformation +backend supporting `JuMP.add_bridge`. +""" +function JuMP.add_bridge(model::InfiniteModel, value) + return JuMP.add_bridge(model.backend, value) +end + """ JuMP.print_active_bridges( io::IO, diff --git a/src/constraints.jl b/src/constraints.jl index 76fd8a23..8efc96f7 100644 --- a/src/constraints.jl +++ b/src/constraints.jl @@ -73,11 +73,40 @@ function _data_object(cref::InfOptConstraintRef) return object end -# Return the core constraint object -function _core_constraint_object(cref::InfOptConstraintRef) +""" + JuMP.constraint_object(cref::InfOptConstraintRef)::JuMP.AbstractConstraint + +Extend `JuMP.constraint_object` to return the constraint object associated with +`cref`. + +**Example** +```julia-repl +julia> @infinite_parameter(model, t in [0, 10]); + +julia> @variable(model, x <= 1); + +julia> cref = UpperBoundRef(x); + +julia> obj = constraint_object(cref) +ScalarConstraint{GeneralVariableRef,MathOptInterface.LessThan{Float64}}(x, +MathOptInterface.LessThan{Float64}(1.0)) +``` +""" +function JuMP.constraint_object(cref::InfOptConstraintRef) return _data_object(cref).constraint end +""" + core_object(cref::InfOptConstraintRef)::JuMP.AbstractConstraint + +Return the core underlying constraint object for `cref`. +This is intended for the developer API. For general usage, +[`JuMP.constraint_object`](@ref) should be used instead. +""" +function core_object(cref::InfOptConstraintRef) + return JuMP.constraint_object(cref::InfOptConstraintRef) +end + ## Set helper methods for adapting data_objects with parametric changes # No change needed function _adaptive_data_update( @@ -95,14 +124,14 @@ function _adaptive_data_update( c::C1, data::ConstraintData{C2} ) where {C1, C2} - new_data = ConstraintData(c, data.object_nums, data.name, + new_data = ConstraintData(c, data.group_int_idxs, data.name, data.measure_indices, data.is_info_constraint) _data_dictionary(cref)[JuMP.index(cref)] = new_data return end # Update the core constraint object -function _set_core_constraint_object( +function _set_core_object( cref::InfOptConstraintRef, constr::JuMP.AbstractConstraint ) @@ -111,9 +140,13 @@ function _set_core_constraint_object( return end -# Extend _object_numbers -function _object_numbers(cref::InfOptConstraintRef) - return _data_object(cref).object_nums +""" + parameter_group_int_indices(cref::InfOptConstraintRef)::Vector{Int} + +Return the list of infinite parameter group integer indices used by `cref`. +""" +function parameter_group_int_indices(cref::InfOptConstraintRef) + return _data_object(cref).group_int_idxs end # Extend _measure_dependencies @@ -121,8 +154,17 @@ function _measure_dependencies(cref::InfOptConstraintRef) return _data_object(cref).measure_indices end -# Return if this constraint is an info constraint -function _is_info_constraint(cref::InfOptConstraintRef) +""" + is_variable_domain_constraint(cref::InfOptConstraintRef)::Bool + +Returns a `Bool` whether `cref` was created based on a variable's +domain. For instance, it could be the upper bound of a variable +`y(t)` which is normally queried via `UpperBoundRef`. This is +intended as a helper function for developers of new +transformation backends which typically ignore these constraints, +since they are taken care of when the variables are processed. +""" +function is_variable_domain_constraint(cref::InfOptConstraintRef) return _data_object(cref).is_info_constraint end @@ -289,16 +331,21 @@ function JuMP.add_constraint( is_info_constr::Bool = false ) # gather the unique list of variable references for testing and mapping - vrefs = _all_function_variables(JuMP.jump_function(c)) + vrefs = all_expression_variables(JuMP.jump_function(c)) # test in the model for vref in vrefs JuMP.check_belongs_to_model(vref, model) end - # get the parameter object numbers - object_nums = sort!(_object_numbers(vrefs)) + # get the parameter group integer indices + group_int_idxs = sort!(parameter_group_int_indices(vrefs)) # add the constaint to the model - constr_object = ConstraintData(c, object_nums, name, MeasureIndex[], - is_info_constr) + constr_object = ConstraintData( + c, + group_int_idxs, + name, + MeasureIndex[], + is_info_constr + ) cindex = _add_data_object(model, constr_object) cref = InfOptConstraintRef(model, cindex) # update the variable mappings and model status @@ -349,31 +396,6 @@ function JuMP.is_valid( JuMP.index(cref) in keys(_data_dictionary(cref))) end -""" - JuMP.constraint_object(cref::InfOptConstraintRef)::JuMP.AbstractConstraint - -Extend `JuMP.constraint_object` to return the constraint object associated with -`cref`. - -**Example** -```julia-repl -julia> @infinite_parameter(model, t in [0, 10]); - -julia> @variable(model, x <= 1); - -julia> cref = UpperBoundRef(x); - -julia> obj = constraint_object(cref) -ScalarConstraint{GeneralVariableRef,MathOptInterface.LessThan{Float64}}(x, -MathOptInterface.LessThan{Float64}(1.0)) -``` -""" -function JuMP.constraint_object( - cref::InfOptConstraintRef - ) - return _core_constraint_object(cref) -end - """ JuMP.name(cref::InfOptConstraintRef)::String @@ -458,7 +480,7 @@ function JuMP.set_normalized_rhs( _enforce_rhs_set(JuMP.moi_set(old_constr)) new_set = _set_set_value(JuMP.moi_set(old_constr), value) new_constr = JuMP.ScalarConstraint(JuMP.jump_function(old_constr), new_set) - _set_core_constraint_object(cref, new_constr) + _set_core_object(cref, new_constr) return end @@ -524,7 +546,7 @@ function JuMP.set_normalized_coefficient( new_func = _set_variable_coefficient!(JuMP.jump_function(old_constr), variable, value) # checks valid new_constr = JuMP.ScalarConstraint(new_func, JuMP.moi_set(old_constr)) - _set_core_constraint_object(cref, new_constr) + _set_core_object(cref, new_constr) return end @@ -544,13 +566,6 @@ function JuMP.normalized_coefficient( return _affine_coefficient(func, variable) # checks valid end -# Return the appropriate constraint reference given the index and model -function _make_constraint_ref(model::InfiniteModel, - index::InfOptConstraintIndex - ) - return InfOptConstraintRef(model, index) -end - """ JuMP.constraint_by_name(model::InfiniteModel, name::String)::Union{InfOptConstraintRef, Nothing} @@ -587,7 +602,7 @@ function JuMP.constraint_by_name( elseif index == InfOptConstraintIndex(-1) error("Multiple constraints have the name $name.") else - return _make_constraint_ref(model, index) + return InfOptConstraintRef(model, index) end end @@ -692,7 +707,7 @@ function JuMP.all_constraints( for (index, object) in model.constraints if isa(JuMP.jump_function(object.constraint), function_type) && isa(JuMP.moi_set(object.constraint), set_type) - constr_list[counter] = _make_constraint_ref(model, index) + constr_list[counter] = InfOptConstraintRef(model, index) counter += 1 end end @@ -714,7 +729,7 @@ end # All the constraints function JuMP.all_constraints(model::InfiniteModel) - return [_make_constraint_ref(model, idx) for (idx, _) in model.constraints] + return [InfOptConstraintRef(model, idx) for (idx, _) in model.constraints] end """ @@ -758,8 +773,10 @@ julia> parameter_refs(cref) """ function parameter_refs(cref::InfOptConstraintRef) model = JuMP.owner_model(cref) - obj_indices = _param_object_indices(model)[_object_numbers(cref)] - return Tuple(_make_param_tuple_element(model, idx) for idx in obj_indices) + prefs = parameter_refs(model) + group_int_idxs = parameter_group_int_indices(cref) + length(prefs) == length(group_int_idxs) && return prefs + return prefs[group_int_idxs] end ################################################################################ @@ -956,8 +973,8 @@ function JuMP.delete(model::InfiniteModel, cref::InfOptConstraintRef) # check valid reference @assert JuMP.is_valid(model, cref) "Invalid constraint reference." # update variable dependencies - constr = _core_constraint_object(cref) - all_vrefs = _all_function_variables(JuMP.jump_function(constr)) + constr = JuMP.constraint_object(cref) + all_vrefs = all_expression_variables(JuMP.jump_function(constr)) for vref in all_vrefs filter!(e -> e != JuMP.index(cref), _constraint_dependencies(vref)) end diff --git a/src/datatypes.jl b/src/datatypes.jl index b5fce1b3..e459985f 100644 --- a/src/datatypes.jl +++ b/src/datatypes.jl @@ -556,8 +556,8 @@ A mutable `DataType` for storing `ScalarParameter`s and their data. **Fields** - `parameter::P`: The scalar parameter. -- `object_num::Int`: The location of the corresponding `ObjectIndex` in - `InfiniteModel.param_object_indices` (given by `InfiniteModel.last_object_num`). +- `group_int_idx::Int`: The location of the corresponding `ObjectIndex` in + `InfiniteModel.param_group_indices`. - `parameter_num::Int`: Given by `InfiniteModel.last_param_num` (updated when prior parameters are deleted) - `name::String`: The name used for printing. @@ -577,7 +577,7 @@ A mutable `DataType` for storing `ScalarParameter`s and their data. """ mutable struct ScalarParameterData{P <: ScalarParameter} <: AbstractDataObject parameter::P - object_num::Int + group_int_idx::Int parameter_num::Int name::String parameter_func_indices::Vector{ParameterFunctionIndex} @@ -593,16 +593,28 @@ mutable struct ScalarParameterData{P <: ScalarParameter} <: AbstractDataObject end # Convenient constructor -function ScalarParameterData(param::P, - object_num::Int, - parameter_num::Int, - name::String = "" - ) where {P <: ScalarParameter} - return ScalarParameterData{P}(param, object_num, parameter_num, name, - ParameterFunctionIndex[], InfiniteVariableIndex[], - DerivativeIndex[], MeasureIndex[], - InfOptConstraintIndex[], false, MeasureIndex[], - false, false, false) +function ScalarParameterData( + param::P, + group_int_idx::Int, + parameter_num::Int, + name::String = "" + ) where {P <: ScalarParameter} + return ScalarParameterData{P}( + param, + group_int_idx, + parameter_num, + name, + ParameterFunctionIndex[], + InfiniteVariableIndex[], + DerivativeIndex[], + MeasureIndex[], + InfOptConstraintIndex[], + false, + MeasureIndex[], + false, + false, + false + ) end """ @@ -612,8 +624,8 @@ A mutable `DataType` for storing [`DependentParameters`](@ref) and their data. **Fields** - `parameters::P`: The parameter collection. -- `object_num::Int`: The location of the corresponding `ObjectIndex` in - `InfiniteModel.param_object_indices` (given by `InfiniteModel.last_object_num`). +- `group_int_idx::Int`: The location of the corresponding `ObjectIndex` in + `InfiniteModel.param_group_indices`. - `parameter_nums::UnitRange{Int}`: Given by `InfiniteModel.last_param_num` (updated when prior parameters are deleted) - `names::Vector{String}`: The names used for printing each parameter. @@ -631,7 +643,7 @@ A mutable `DataType` for storing [`DependentParameters`](@ref) and their data. """ mutable struct MultiParameterData{P <: DependentParameters} <: AbstractDataObject parameters::P - object_num::Int + group_int_idx::Int parameter_nums::UnitRange{Int} names::Vector{String} parameter_func_indices::Vector{ParameterFunctionIndex} @@ -644,17 +656,24 @@ mutable struct MultiParameterData{P <: DependentParameters} <: AbstractDataObjec end # Convenient constructor -function MultiParameterData(params::P, - object_num::Int, - parameter_nums::UnitRange{Int}, - names::Vector{String}, - ) where {P <: DependentParameters} - return MultiParameterData{P}(params, object_num, parameter_nums, names, - ParameterFunctionIndex[], InfiniteVariableIndex[], - [DerivativeIndex[] for i in eachindex(names)], - [MeasureIndex[] for i in eachindex(names)], - [InfOptConstraintIndex[] for i in eachindex(names)], - false, zeros(Bool, length(names))) +function MultiParameterData( + params::P, + group_int_idx::Int, + parameter_nums::UnitRange{Int}, + names::Vector{String}, + ) where {P <: DependentParameters} + return MultiParameterData{P}( + params, + group_int_idx, + parameter_nums, names, + ParameterFunctionIndex[], + InfiniteVariableIndex[], + [DerivativeIndex[] for i in eachindex(names)], + [MeasureIndex[] for i in eachindex(names)], + [InfOptConstraintIndex[] for i in eachindex(names)], + false, + zeros(Bool, length(names)) + ) end ################################################################################ @@ -704,15 +723,15 @@ incorporated in expressions via [`ParameterFunctionRef`](@ref)s. - `func::F`: The function the takes infinite parameters as input and provide a scalar number as output. - `parameter_refs::VT`: The infinite parameter references that serve as - inputs to `func`. Their formatting is analagous - to those of infinite variables. + inputs to `func`. Their formatting is analagous + to those of infinite variables. - `parameter_nums::Vector{Int}`: The parameter numbers of `parameter_refs`. -- `object_nums::Vector{Int}`: The parameter object numbers associated with `parameter_refs`. +- `group_int_idxs::Vector{Int}`: The parameter group integer indices associated with `parameter_refs`. """ struct ParameterFunction{F <: Function, VT <: Collections.VectorTuple} func::F parameter_refs::VT - object_nums::Vector{Int} + group_int_idxs::Vector{Int} parameter_nums::Vector{Int} end @@ -762,14 +781,14 @@ support vector as input. - `parameter_refs::VT`: The infinite parameter references that parameterize the variable. - `parameter_nums::Vector{Int}`: The parameter numbers of `parameter_refs`. -- `object_nums::Vector{Int}`: The parameter object numbers associated with `parameter_refs`. +- `group_int_idxs::Vector{Int}`: The parameter group integer indices associated with `parameter_refs`. - `is_vector_start::Bool`: Does the start function take support values formatted as vectors? """ struct InfiniteVariable{F <: Function, VT <: Collections.VectorTuple} <: JuMP.AbstractVariable info::JuMP.VariableInfo{Float64, Float64, Float64, F} parameter_refs::VT parameter_nums::Vector{Int} - object_nums::Vector{Int} + group_int_idxs::Vector{Int} is_vector_start::Bool end @@ -785,14 +804,14 @@ infinite variable. to the evaluation supports. - `parameter_nums::Vector{Int}`: The parameter numbers associated with the evaluated `parameter_refs`. -- `object_nums::Vector{Int}`: The parameter object numbers associated with the +- `group_int_idxs::Vector{Int}`: The parameter group integer indices associated with the evaluated `parameter_refs`. """ struct SemiInfiniteVariable{I <: JuMP.AbstractVariableRef} <: JuMP.AbstractVariable infinite_variable_ref::I eval_supports::Dict{Int, Float64} parameter_nums::Vector{Int} - object_nums::Vector{Int} + group_int_idxs::Vector{Int} end """ @@ -1111,22 +1130,22 @@ and is enacted on `func` when the measure is evaluated (expended). - `func::T` The `InfiniteOpt` expression to be measured. - `data::V` Data of the abstraction as described in a `AbstractMeasureData` concrete subtype. -- `object_nums::Vector{Int}`: The parameter object numbers of the evaluated - measure expression (i.e., the object numbers of +- `group_int_idxs::Vector{Int}`: The parameter group integer indices of the evaluated + measure expression (i.e., the group integer indices of `func` excluding those that belong to `data`). - `parameter_nums::Vector{Int}`: The parameter numbers that parameterize the evaluated measure expression. (i.e., the parameter numbers of `func` excluding those that belong to `data`). - `constant_func::Bool`: Indicates if `func` is not parameterized by the infinite - parameters in `data`. (i.e., do the object numbers of + parameters in `data`. (i.e., do the group integer indices of `func` and `data` have no intersection?) This is useful to enable analytic evaluations if possible. """ struct Measure{T <: JuMP.AbstractJuMPScalar, V <: AbstractMeasureData} func::T data::V - object_nums::Vector{Int} + group_int_idxs::Vector{Int} parameter_nums::Vector{Int} constant_func::Bool end @@ -1188,8 +1207,8 @@ A mutable `DataType` for storing constraints and their data. **Fields** - `constraint::C`: The constraint. -- `object_nums::Vector{Int}`: The object numbers of the parameter objects that the - constraint depends on. +- `group_int_idxs::Vector{Int}`: The group integer indices of the parameter objects that the + constraint depends on. - `name::String`: The name used for printing. - `measure_indices::Vector{MeasureIndex}`: Indices of dependent measures. - `is_info_constraint::Bool`: Is this is constraint based on variable info @@ -1197,7 +1216,7 @@ A mutable `DataType` for storing constraints and their data. """ mutable struct ConstraintData{C <: JuMP.AbstractConstraint} <: AbstractDataObject constraint::C - object_nums::Vector{Int} + group_int_idxs::Vector{Int} name::String measure_indices::Vector{MeasureIndex} is_info_constraint::Bool @@ -1333,7 +1352,7 @@ mutable struct InfiniteModel <: JuMP.AbstractModel finite_params::MOIUC.CleverDict{FiniteParameterIndex, ScalarParameterData{FiniteParameter}} name_to_param::Union{Dict{String, AbstractInfOptIndex}, Nothing} last_param_num::Int - param_object_indices::Vector{Union{IndependentParameterIndex, DependentParametersIndex}} + param_group_indices::Vector{Union{IndependentParameterIndex, DependentParametersIndex}} param_functions::MOIUC.CleverDict{ParameterFunctionIndex, <:ParameterFunctionData} piecewise_vars::Dict{IndependentParameterIndex, Set{InfiniteVariableIndex}} @@ -1508,7 +1527,7 @@ function Base.empty!(model::InfiniteModel) empty!(model.finite_params) model.name_to_param = nothing model.last_param_num = 0 - empty!(model.param_object_indices) + empty!(model.param_group_indices) empty!(model.param_functions) empty!(model.piecewise_vars) # variables @@ -1544,7 +1563,57 @@ end # Define basic accessors _last_param_num(model::InfiniteModel) = model.last_param_num -_param_object_indices(model::InfiniteModel) = model.param_object_indices + +""" + parameter_group_indices(model::InfiniteModel)::Vector{Union{IndependentParameterIndex, DependentParametersIndex}} + +Return a list the indices that correspond to the independent infinite parameter +groups that have been added to `model`. This provides the infinite parameter +indicies that correspond to the integer indices reported by +[`parameter_group_int_indices`](@ref). For instance, a group integer index of +`2` corresponds to the infinite parameter index stored at +`parameter_group_indices(model)[2]`. This is intended for advanced users writing +new types of [`AbstractTransformationBackend`](@ref)s. +""" +parameter_group_indices(model::InfiniteModel) = model.param_group_indices + +## Return an element of a parameter reference tuple given the model and index +# IndependentParameterIndex +function _make_param_tuple_element( + model::InfiniteModel, + idx::IndependentParameterIndex, + ) + return GeneralVariableRef(model, idx) +end +# DependentParametersIndex +function _make_param_tuple_element( + model::InfiniteModel, + idx::DependentParametersIndex, + ) + num_params = length(model.dependent_params[idx].parameter_nums) + return [GeneralVariableRef(model, idx.value, DependentParameterIndex, i) + for i in 1:num_params] +end + +""" + parameter_refs(model::InfiniteModel)::Tuple + +Returns a tuple of the infinite parameters used by `model`. + +For developers, note that the integer index of each element is what is referred +to as an infinite parameter group integer index which corresponds to +[`parameter_group_int_indices`](@ref). + +**Example** +```julia-repl +julia> parameter_refs(model) +(t, x) +``` +""" +function parameter_refs(model::InfiniteModel) + group_idxs = parameter_group_indices(model) + return Tuple(_make_param_tuple_element(model, idx) for idx in group_idxs) +end ################################################################################ # OBJECT REFERENCES @@ -1560,6 +1629,11 @@ via [`dispatch_variable_ref`](@ref) to obtain the correct subtype of construct expressions using concrete containers unlike previous versions of `InfiniteOpt` which provides us a significant performance boost. +A convenient constructor is: +```julia + GeneralVariableRef(model::InfiniteModel, index::ObjectIndex) +``` + **Fields** - `model::InfiniteModel`: Infinite model. - `raw_index::Int64`: The raw index to be used in the `index_type` constructor. @@ -1576,6 +1650,12 @@ struct GeneralVariableRef <: JuMP.AbstractVariableRef index_type::DataType, param_index::Int = -1) return new(model, Int64(raw_index), index_type, param_index) end + function GeneralVariableRef(model::InfiniteModel, index::ObjectIndex) + return new(model, Int64(index.value), typeof(index), -1) + end + function GeneralVariableRef(model::InfiniteModel, index::DependentParameterIndex) + return new(model, index.object_index.value, typeof(index), index.param_index) + end end """ diff --git a/src/derivatives.jl b/src/derivatives.jl index 27fab67d..c6930a86 100644 --- a/src/derivatives.jl +++ b/src/derivatives.jl @@ -35,14 +35,19 @@ function _data_object(dref::DerivativeRef) return object end -# Extend _core_variable_object -function _core_variable_object(dref::DerivativeRef) +""" + core_object(dref::DerivativeRef)::Derivative + +Retrieve the underlying core [`Derivative`](@ref) object for `dref`. +This is intended as an advanced method for developers. +""" +function core_object(dref::DerivativeRef) return _data_object(dref).variable end # Define getter function for deriv.is_vector_start function _is_vector_start(dref::DerivativeRef) - return _core_variable_object(dref).is_vector_start + return core_object(dref).is_vector_start end """ @@ -58,7 +63,7 @@ x(t) ``` """ function derivative_argument(dref::DerivativeRef) - return _core_variable_object(dref).variable_ref + return core_object(dref).variable_ref end """ @@ -73,7 +78,7 @@ julia> derivative_order(dref) ``` """ function derivative_order(dref::DerivativeRef) - return _core_variable_object(dref).order + return core_object(dref).order end """ @@ -89,7 +94,7 @@ t ``` """ function operator_parameter(dref::DerivativeRef) - return _core_variable_object(dref).parameter_ref + return core_object(dref).parameter_ref end """ @@ -110,9 +115,13 @@ function derivative_method(dref::DerivativeRef) return derivative_method(operator_parameter(dref)) end -# Extend _object_numbers -function _object_numbers(dref::DerivativeRef) - return _object_numbers(derivative_argument(dref)) +""" + parameter_group_int_indices(dref::DerivativeRef)::Vector{Int} + +Return the list of infinite parameter group integer indices used by `dref`. +""" +function parameter_group_int_indices(dref::DerivativeRef) + return parameter_group_int_indices(derivative_argument(dref)) end # Extend _parameter_numbers @@ -175,8 +184,8 @@ function _adaptive_data_update( return end -# Extend _set_core_variable_object for DerivativeRefs -function _set_core_variable_object(dref::DerivativeRef, d::Derivative) +# Extend _set_core_object for DerivativeRefs +function _set_core_object(dref::DerivativeRef, d::Derivative) _adaptive_data_update(dref, d, _data_object(dref)) return end @@ -354,18 +363,18 @@ function add_derivative(model::InfiniteModel, d::Derivative, name::String = "") # update the derivative lookup dict model.deriv_lookup[(d.variable_ref, d.parameter_ref, d.order)] = dindex # add the info constraints - gvref = _make_variable_ref(model, dindex) + gvref = GeneralVariableRef(model, dindex) _set_info_constraints(d.info, gvref, dref) else dref = DerivativeRef(model, existing_index) - gvref = _make_variable_ref(model, existing_index) + gvref = GeneralVariableRef(model, existing_index) old_info = _variable_info(dref) if old_info.has_lb || old_info.has_ub || old_info.has_fix || old_info.has_start @warn "Overwriting $dref, any previous properties (e.g., lower bound " * "or start value) will be lost/changed." end _update_info_constraints(d.info, gvref, dref) - _set_core_variable_object(dref, d) + _set_core_object(dref, d) if !isempty(name) set_name(dref, name) end @@ -389,7 +398,7 @@ function _build_add_derivative(vref, pref, order) d = Derivative(info, true, vref, pref, order) return add_derivative(model, d) else - return _make_variable_ref(model, dindex) + return GeneralVariableRef(model, dindex) end end @@ -635,7 +644,7 @@ function _update_variable_info( order = derivative_order(dref) is_vect_func = _is_vector_start(dref) new_deriv = Derivative(_format_infinite_info(info), is_vect_func, vref, pref, order) - _set_core_variable_object(dref, new_deriv) + _set_core_object(dref, new_deriv) return end @@ -671,7 +680,7 @@ function set_start_value_function( pref = operator_parameter(dref) order = derivative_order(dref) new_deriv = Derivative(new_info, is_vect_func, vref, pref, order) - _set_core_variable_object(dref, new_deriv) + _set_core_object(dref, new_deriv) return end @@ -696,7 +705,7 @@ function reset_start_value_function(dref::DerivativeRef)::Nothing pref = operator_parameter(dref) order = derivative_order(dref) new_deriv = Derivative(new_info, true, vref, pref, order) - _set_core_variable_object(dref, new_deriv) + _set_core_object(dref, new_deriv) return end @@ -740,7 +749,7 @@ julia> all_derivatives(model) function all_derivatives(model::InfiniteModel)::Vector{GeneralVariableRef} vrefs_list = Vector{GeneralVariableRef}(undef, num_derivatives(model)) for (i, (index, _)) in enumerate(_data_dictionary(model, Derivative)) - vrefs_list[i] = _make_variable_ref(model, index) + vrefs_list[i] = GeneralVariableRef(model, index) end return vrefs_list end @@ -763,7 +772,7 @@ added directly to the `InfiniteModel` associated with `dref`. An empty vector is returned is there are no such constraints. """ function derivative_constraints(dref::DerivativeRef)::Vector{InfOptConstraintRef} - return [_make_constraint_ref(JuMP.owner_model(dref), idx) + return [InfOptConstraintRef(JuMP.owner_model(dref), idx) for idx in _derivative_constraint_dependencies(dref)] end diff --git a/src/expressions.jl b/src/expressions.jl index 0c0ac31f..19aaa9ca 100644 --- a/src/expressions.jl +++ b/src/expressions.jl @@ -35,19 +35,28 @@ function _data_object(fref::ParameterFunctionRef) return object end -# Extend _core_variable_object -function _core_variable_object(fref::ParameterFunctionRef) +""" + core_object(fref::ParameterFunctionRef)::ParameterFunction + +Retrieve the underlying core [`ParameterFucntion`](@ref) object for `fref`. +This is intended as an advanced method for developers. +""" +function core_object(fref::ParameterFunctionRef) return _data_object(fref).func end -# Extend _object_numbers -function _object_numbers(fref::ParameterFunctionRef)::Vector{Int} - return _core_variable_object(fref).object_nums +""" + parameter_group_int_indices(fref::ParameterFunctionRef)::Vector{Int} + +Return the list of infinite parameter group integer indices used by `fref`. +""" +function parameter_group_int_indices(fref::ParameterFunctionRef) + return core_object(fref).group_int_idxs end # Extend _parameter_numbers -function _parameter_numbers(fref::ParameterFunctionRef)::Vector{Int} - return _core_variable_object(fref).parameter_nums +function _parameter_numbers(fref::ParameterFunctionRef) + return core_object(fref).parameter_nums end """ @@ -99,15 +108,15 @@ function build_parameter_function( "arguments `" * join(Tuple(prefs), ", ") * "` are checked via a ", "numeric support (each parameter is a `Float64`) of the same format.") end - # get the parameter object numbers - object_nums = Int[] + # get the parameter group integer indices + group_int_idxs = Int[] for pref in prefs - union!(object_nums, _object_number(pref)) + union!(group_int_idxs, parameter_group_int_index(pref)) end # get the parameter numbers param_nums = [_parameter_number(pref) for pref in prefs] # make the variable and return - return ParameterFunction(func, prefs, object_nums, param_nums) + return ParameterFunction(func, prefs, group_int_idxs, param_nums) end # Fallback for weird macro inputs @@ -157,7 +166,7 @@ function add_parameter_function( findex = _add_data_object(model, data_object) fref = ParameterFunctionRef(model, findex) _update_param_var_mapping(fref, pfunc.parameter_refs) - return _make_variable_ref(model, findex) + return GeneralVariableRef(model, findex) end """ @@ -257,7 +266,7 @@ where [`parameter_refs`](@ref parameter_refs(::ParameterFunctionRef)) is intended as the preferred user function. """ function raw_parameter_refs(fref::ParameterFunctionRef) - return _core_variable_object(fref).parameter_refs + return core_object(fref).parameter_refs end """ @@ -295,7 +304,7 @@ Returns the raw function behind `fref` that takes a particular support of `fref` infinite parameters as input. """ function raw_function(fref::ParameterFunctionRef) - return _core_variable_object(fref).func + return core_object(fref).func end """ @@ -306,7 +315,7 @@ point that matches the format of the infinite parameter tuple given when the `fr was defined. This is essentially equivalent to `raw_function(fref)(supps...)`. """ function call_function(fref::ParameterFunctionRef, supps...)::Float64 - pfunc = _core_variable_object(fref) + pfunc = core_object(fref) return pfunc.func(supps...) end @@ -430,7 +439,7 @@ function JuMP.delete(model::InfiniteModel, fref::ParameterFunctionRef)::Nothing for pref in all_prefs filter!(e -> e != JuMP.index(fref), _parameter_function_dependencies(pref)) end - gvref = _make_variable_ref(model, JuMP.index(fref)) + gvref = GeneralVariableRef(model, JuMP.index(fref)) # delete associated semi-infinite variables and mapping for index in _semi_infinite_variable_dependencies(fref) JuMP.delete(model, dispatch_variable_ref(model, index)) @@ -451,23 +460,23 @@ function JuMP.delete(model::InfiniteModel, fref::ParameterFunctionRef)::Nothing _remove_variable(func, gvref) new_meas = build_measure(func, data) end - _set_core_variable_object(mref, new_meas) + _set_core_object(mref, new_meas) end # remove from constraints if used for cindex in copy(_constraint_dependencies(fref)) - cref = _make_constraint_ref(model, cindex) + cref = InfOptConstraintRef(model, cindex) func = JuMP.jump_function(JuMP.constraint_object(cref)) if func isa GeneralVariableRef set = JuMP.moi_set(JuMP.constraint_object(cref)) new_func = zero(JuMP.GenericAffExpr{Float64, GeneralVariableRef}) new_constr = JuMP.ScalarConstraint(new_func, set) - _set_core_constraint_object(cref, new_constr) - empty!(_object_numbers(cref)) + _set_core_object(cref, new_constr) + empty!(parameter_group_int_indices(cref)) elseif func isa AbstractArray && any(isequal(gvref), func) JuMP.delete(model, cref) else _remove_variable(func, gvref) - _data_object(cref).object_nums = sort(_object_numbers(func)) + _data_object(cref).group_int_idxs = sort(parameter_group_int_indices(func)) end end # delete the data object @@ -544,19 +553,36 @@ end ################################################################################ # VARIABLE LIST MAKING ################################################################################ -## Determine which variables are present in a function +""" + all_expression_variables(expr::JuMP.AbstractJuMPScalar)::Vector + +Returns a vector of all the variable references contained in `expr`. + +**Example** +```julia-repl +julia> all_expr_variables(y^2 + z - t) +3-element Array{GeneralVariableRef,1}: + y(t) + z + t +``` +""" +function all_expression_variables(f) + error("`all_expression_variables` not defined for expression of type $(typeof(f)).") +end + # GeneralVariableRef -function _all_function_variables(f::GeneralVariableRef) +function all_expression_variables(f::GeneralVariableRef) return [f] end # GenericAffExpr -function _all_function_variables(f::JuMP.GenericAffExpr) +function all_expression_variables(f::JuMP.GenericAffExpr) return collect(keys(f.terms)) end # GenericQuadExpr -function _all_function_variables(f::JuMP.GenericQuadExpr) +function all_expression_variables(f::JuMP.GenericQuadExpr) vref_set = Set(keys(f.aff.terms)) for (pair, _) in f.terms push!(vref_set, pair.a, pair.b) @@ -565,34 +591,37 @@ function _all_function_variables(f::JuMP.GenericQuadExpr) end # NonlinearExpr or array of expressions -function _all_function_variables(f::Union{JuMP.GenericNonlinearExpr, AbstractArray}) +function all_expression_variables(f::Union{JuMP.GenericNonlinearExpr, AbstractArray}) vref_set = Set{GeneralVariableRef}() _interrogate_variables(v -> push!(vref_set, v), f) return collect(vref_set) end -# Fallback -function _all_function_variables(f) - error("`_all_function_variables` not defined for expression of type $(typeof(f)).") -end - ################################################################################ -# OBJECT/PARAMETER NUMBER METHODS +# GROUP/PARAMETER NUMBER METHODS ################################################################################ -## Return the unique set of object numbers in an expression +## Return the unique set of parameter group integer indices in an expression # Dispatch fallback (--> should be defined for each non-empty variable type) -_object_numbers(v::DispatchVariableRef) = Int[] +parameter_group_int_indices(v::DispatchVariableRef) = Int[] -# GeneralVariableRef -function _object_numbers(v::GeneralVariableRef) - return _object_numbers(dispatch_variable_ref(v)) +""" + parameter_group_int_indices(vref::GeneralVariableRef)::Vector{Int} + +Return the list of infinite parameter group integer indices used by `vref`. +""" +function parameter_group_int_indices(v::GeneralVariableRef) + return parameter_group_int_indices(dispatch_variable_ref(v)) end -# Other -function _object_numbers(expr) - obj_nums = Set{Int}() - _interrogate_variables(v -> union!(obj_nums, _object_numbers(v)), expr) - return collect(obj_nums) +""" + parameter_group_int_indices(expr::JuMP.AbstractJuMPScalar)::Vector{Int} + +Return the list of infinite parameter group integer indices used by `expr`. +""" +function parameter_group_int_indices(expr) + group_int_idxs = Set{Int}() + _interrogate_variables(v -> union!(group_int_idxs, parameter_group_int_indices(v)), expr) + return collect(group_int_idxs) end ## Return the unique set of parameter numbers in an expression @@ -852,7 +881,7 @@ function restrict(expr::JuMP.AbstractJuMPScalar, supps...) end # restrict the expression using supps and return return map_expression(expr) do v - if isempty(_object_numbers(v)) + if isempty(parameter_group_int_indices(v)) return v else return restrict(v, supps...) @@ -959,24 +988,6 @@ end ################################################################################ # PARAMETER REFERENCE METHODS ################################################################################ -## Return an element of a parameter reference tuple given the model and index -# IndependentParameterIndex -function _make_param_tuple_element(model::InfiniteModel, - idx::IndependentParameterIndex, - )::GeneralVariableRef - return _make_parameter_ref(model, idx) -end - -# DependentParametersIndex -function _make_param_tuple_element(model::InfiniteModel, - idx::DependentParametersIndex, - )::Vector{GeneralVariableRef} - dpref = DependentParameterRef(model, DependentParameterIndex(idx, 1)) - num_params = _num_parameters(dpref) - return [GeneralVariableRef(model, idx.value, DependentParameterIndex, i) - for i in 1:num_params] -end - """ parameter_refs(expr)::Tuple @@ -993,163 +1004,9 @@ function parameter_refs( expr::Union{JuMP.GenericAffExpr, JuMP.GenericQuadExpr, JuMP.GenericNonlinearExpr} ) model = JuMP.owner_model(expr) - if isnothing(model) - return () - else - obj_nums = sort!(_object_numbers(expr)) - obj_indices = _param_object_indices(model)[obj_nums] - return Tuple(_make_param_tuple_element(model, idx) for idx in obj_indices) - end + isnothing(model) && return () + prefs = parameter_refs(model) + group_int_idxs = parameter_group_int_indices(expr) + length(prefs) == length(group_int_idxs) && return prefs + return Tuple(prefs[i] for i in eachindex(prefs) if i in group_int_idxs) end - -################################################################################ -# VARIABLE ITERATION (IN PROGRESS) -################################################################################ -# struct Variables{T} -# expr::T -# end - -# function Base.iterate(itr::Variables{<:JuMP.AbstractVariableRef}) -# return itr.tree_root, nothing -# end - -# function Base.iterate(itr::Variables{<:JuMP.AbstractVariableRef}, ::Nothing) -# return -# end - -# Base.length(itr::Variables{<:JuMP.AbstractVariableRef}) = 1 -# Base.eltype(::Variables{V}) where {V <: JuMP.AbstractVariableRef} = V - -# function Base.iterate(itr::Variables{<:JuMP.GenericAffExpr}) -# out = iterate(itr.expr.terms) -# return out === nothing ? out : (out[1][1], out[2]) -# end - -# function Base.iterate(itr::Variables{<:JuMP.GenericAffExpr}, state) -# out = iterate(itr.expr.terms, state) -# return out === nothing ? out : (out[1][1], out[2]) -# end - -# Base.length(itr::Variables{<:JuMP.GenericAffExpr}) = length(itr.expr.terms) -# Base.eltype(::Variables{JuMP.GenericAffExpr{C, V}}) where {C, V} = V - -# mutable struct _QuadItrData{V <: JuMP.AbstractVariableRef} -# state::Int -# use_aff::Bool -# has_prev_term::Bool -# next_term::V -# end - -# function Base.iterate(itr::Variables{JuMP.GenericQuadExpr{C, V}}) where {C, V} -# out = iterate(itr.expr.terms) -# if out === nothing -# aff_out = iterate(itr.expr.aff.terms) -# if aff_out === nothing -# return -# else -# return aff_out[1][1], _QuadItrData{V}(aff_out[2], true, false, aff_out[1][1]) -# end -# end -# return out[1][1].a, _QuadItrData{V}(out[2], false, true, out[1][1].b) -# end - -# function Base.iterate(itr::Variables{<:JuMP.GenericQuadExpr}, state) -# if state.has_prev_term -# state.has_prev_term = false -# return state.next_term, state -# elseif !state.use_aff -# out = iterate(itr.expr.terms, state.state) -# if out === nothing -# aff_out = iterate(itr.expr.aff.terms) -# if aff_out === nothing -# return -# else -# state.use_aff = true -# state.state = aff_out[2] -# return aff_out[1][1], state -# end -# end -# state.state = out[2] -# state.has_prev_term = true -# state.next_term = out[1][1].b -# return out[1][1].a, state -# else -# out = iterate(itr.expr.aff.terms, state.state) -# if out === nothing -# return -# else -# state.state = out[2] -# return out[1][1], state -# end -# end -# end - -# function Base.length(itr::Variables{<:JuMP.GenericQuadExpr}) -# return 2 * length(itr.expr.terms) + length(itr.expr.aff.terms) -# end -# Base.eltype(::Variables{JuMP.GenericQuadExpr{C, V}}) where {C, V} = V - -# mutable struct _NLPItrData -# leaf_itr::AbstractTrees.Leaves{_LCRST.Node{NodeData}} -# state::_LCRST.Node{NodeData} -# has_internal::Bool -# internal_itr::Any -# internal_state::Any -# end - -# function _process_itr(raw::GeneralVariableRef, state) -# state.has_internal = false -# return raw -# end - -# function _process_itr(::Real, state) -# out = iterate(state.leaf_itr, state.state) -# out === nothing && return -# state.state = out[2] -# raw = _node_value(out[1].data) -# return _process_itr(raw, state) -# end - -# function _process_itr(raw, state) -# itr = Variables(raw) -# out = iterate(itr) -# if out === nothing -# new_out = iterate(state.leaf_itr, state.state) -# new_out === nothing && return -# state.state = new_out[2] -# raw = _node_value(new_out[1].data) -# return _process_itr(raw, state) -# else -# state.internal_itr = itr -# state.has_internal = true -# state.internal_state = out[2] -# return out[1] -# end -# end - -# function Base.iterate(itr::Variables{NLPExpr}) -# leaf_itr = AbstractTrees.Leaves(itr.expr.tree_root) -# out = iterate(leaf_itr) -# out === nothing && return -# state = _NLPItrData(leaf_itr, out[2], false, nothing, nothing) -# raw = _process_itr(_node_value(out[1].data), state) -# return raw === nothing ? raw : (raw, state) -# end - -# function Base.iterate(itr::Variables{NLPExpr}, state) -# if state.has_internal -# int_out = iterate(state.internal_itr, state.internal_state) -# if int_out !== nothing -# state.internal_state = int_out[2] -# return int_out[1], state -# end -# end -# out = iterate(state.leaf_itr, state.state) -# out === nothing && return -# state.state = out[2] -# raw = _process_itr(_node_value(out[1].data), state) -# return raw === nothing ? raw : (raw, state) -# end - -# Base.IteratorSize(::Variables{NLPExpr}) = Base.SizeUnknown() -# Base.eltype(::Variables{NLPExpr}) = GeneralVariableRef diff --git a/src/finite_variables.jl b/src/finite_variables.jl index 119c896e..67a28e12 100644 --- a/src/finite_variables.jl +++ b/src/finite_variables.jl @@ -2,10 +2,7 @@ # CORE DISPATCHVARIABLEREF METHOD EXTENSIONS ################################################################################ # Extend dispatch_variable_ref -function dispatch_variable_ref( - model::InfiniteModel, - index::FiniteVariableIndex - )::FiniteVariableRef +function dispatch_variable_ref(model::InfiniteModel, index::FiniteVariableIndex) return FiniteVariableRef(model, index) end @@ -13,29 +10,22 @@ end function _add_data_object( model::InfiniteModel, object::VariableData{<:JuMP.ScalarVariable} - )::FiniteVariableIndex + ) return MOIUC.add_item(model.finite_vars, object) end # Extend _data_dictionary (type based) -function _data_dictionary( - model::InfiniteModel, - ::Type{FiniteVariable} - )::MOIUC.CleverDict{FiniteVariableIndex, VariableData{JuMP.ScalarVariable{Float64, Float64, Float64, Float64}}} +function _data_dictionary(model::InfiniteModel, ::Type{FiniteVariable}) return model.finite_vars end # Extend _data_dictionary (reference based) -function _data_dictionary( - vref::FiniteVariableRef - )::MOIUC.CleverDict{FiniteVariableIndex, VariableData{JuMP.ScalarVariable{Float64, Float64, Float64, Float64}}} +function _data_dictionary(vref::FiniteVariableRef) return JuMP.owner_model(vref).finite_vars end # Extend _data_object -function _data_object( - vref::FiniteVariableRef - )::VariableData{JuMP.ScalarVariable{Float64, Float64, Float64, Float64}} +function _data_object(vref::FiniteVariableRef) object = get(_data_dictionary(vref), JuMP.index(vref), nothing) if isnothing(object) error("Invalid finite variable reference, cannot find ", @@ -45,10 +35,13 @@ function _data_object( return object end -# Extend _core_variable_object -function _core_variable_object( - vref::FiniteVariableRef - )::JuMP.ScalarVariable{Float64, Float64, Float64, Float64} +""" + core_object(vref::FiniteVariableRef)::JuMP.ScalarVariable + +Retrieve the underlying core `JuMP.ScalarVariable` object for `vref`. +This is intended as an advanced method for developers. +""" +function core_object(vref::FiniteVariableRef) return _data_object(vref).variable end @@ -58,15 +51,13 @@ end ## Process the variable to use the correct info # All Floats function _process_scalar_var( - v::V - )::V where {V <: JuMP.ScalarVariable{Float64, Float64, Float64, Float64}} + v::JuMP.ScalarVariable{Float64, Float64, Float64, Float64} + ) return v end # Other -function _process_scalar_var( - v::JuMP.ScalarVariable - )::JuMP.ScalarVariable{Float64, Float64, Float64, Float64} +function _process_scalar_var(v::JuMP.ScalarVariable) return JuMP.ScalarVariable(_make_float_info(v.info)) end @@ -92,12 +83,12 @@ function JuMP.add_variable( model::InfiniteModel, var::JuMP.ScalarVariable, name::String = "" - )::GeneralVariableRef + ) new_var = _process_scalar_var(var) data_object = VariableData(new_var, name) vindex = _add_data_object(model, data_object) vref = FiniteVariableRef(model, vindex) - gvref = _make_variable_ref(model, vindex) + gvref = GeneralVariableRef(model, vindex) _set_info_constraints(new_var.info, gvref, vref) model.name_to_var = nothing return gvref @@ -110,8 +101,8 @@ end function _update_variable_info( vref::FiniteVariableRef, info::JuMP.VariableInfo - )::Nothing - _set_core_variable_object(vref, JuMP.ScalarVariable(info)) + ) + _set_core_object(vref, JuMP.ScalarVariable(info)) return end @@ -119,7 +110,7 @@ end # DELETION ################################################################################ # Extend _delete_variable_dependencies (for use with JuMP.delete) -function _delete_variable_dependencies(vref::FiniteVariableRef)::Nothing +function _delete_variable_dependencies(vref::FiniteVariableRef) # remove variable info constraints associated with vref _delete_info_constraints(vref) return diff --git a/src/general_variables.jl b/src/general_variables.jl index 68920d98..66f92df9 100644 --- a/src/general_variables.jl +++ b/src/general_variables.jl @@ -270,33 +270,33 @@ end # CORE OBJECT METHODS ################################################################################ """ - _core_variable_object(vref::DispatchVariableRef)::Union{InfOptParameter, InfOptVariable, Measure} + core_object(vref::DispatchVariableRef)::Union{InfOptParameter, InfOptVariable, Measure} Return the core object that `vref` points to. This needs to be extended for type of `vref`. This should use `_data_object` to access the data object where the variable object is stored. """ -function _core_variable_object end +function core_object end """ - _core_variable_object(vref::GeneralVariableRef)::Union{InfOptParameter, InfOptVariable, Measure} + core_object(vref::GeneralVariableRef)::Union{InfOptParameter, InfOptVariable, Measure} Return the core object that `vref` points to. This is enabled -with appropriate definitions of `_core_variable_object` for the +with appropriate definitions of `core_object` for the underlying `DispatchVariableRef`, otherwise an `MethodError` is thrown. """ -function _core_variable_object(vref::GeneralVariableRef) - return _core_variable_object(dispatch_variable_ref(vref)) +function core_object(vref::GeneralVariableRef) + return core_object(dispatch_variable_ref(vref)) end """ - _set_core_variable_object(vref::DispatchVariableRef, object)::Nothing + _set_core_object(vref::DispatchVariableRef, object)::Nothing Sets the core object that `vref` points to `object`. This needs to be extended for types of `vref` and `object`. This should use `_data_object` to access the data object where the variable object is stored. """ -function _set_core_variable_object end +function _set_core_object end ################################################################################ # DEPENDENCY METHODS @@ -438,23 +438,23 @@ function _parameter_number(pref::GeneralVariableRef)::Int end """ - _object_number(pref::DispatchVariableRef)::Int + parameter_group_int_index(pref::DispatchVariableRef)::Int -Return the object number for `pref` assuming it is an infinite +Return the parameter group integer index for `pref` assuming it is an infinite parameter. This needs to be defined for the type of `pref`. This should use the `_data_object` to get the number. """ -function _object_number end +function parameter_group_int_index end """ - _object_number(pref::GeneralVariableRef)::Int + parameter_group_int_index(pref::GeneralVariableRef)::Int -Return the object number for `pref` assuming it is an infinite -parameter. It relies on `_object_number` being properly defined for the +Return the group integer index for `pref` assuming it is an infinite +parameter. It relies on `parameter_group_int_index` being properly defined for the underlying `DispatchVariableRef`, otherwise an `MethodError` is thrown. """ -function _object_number(pref::GeneralVariableRef)::Int - return _object_number(dispatch_variable_ref(pref)) +function parameter_group_int_index(pref::GeneralVariableRef)::Int + return parameter_group_int_index(dispatch_variable_ref(pref)) end # Define 1 argument user method wrappers and their fallbacks diff --git a/src/infinite_variables.jl b/src/infinite_variables.jl index c8643a4a..1769e823 100644 --- a/src/infinite_variables.jl +++ b/src/infinite_variables.jl @@ -43,24 +43,33 @@ function _data_object(vref::InfiniteVariableRef) return object end -# Extend _core_variable_object -function _core_variable_object(vref::InfiniteVariableRef) +""" + core_object(vref::InfiniteVariableRef)::InfiniteVariable + +Retrieve the underlying core [`InfiniteVariable`](@ref) object for `vref`. +This is intended as an advanced method for developers. +""" +function core_object(vref::InfiniteVariableRef) return _data_object(vref).variable end -# Extend _object_numbers -function _object_numbers(vref::InfiniteVariableRef) - return _core_variable_object(vref).object_nums +""" + parameter_group_int_indices(vref::InfiniteVariableRef)::Vector{Int} + +Return the list of infinite parameter group integer indices used by `vref`. +""" +function parameter_group_int_indices(vref::InfiniteVariableRef) + return core_object(vref).group_int_idxs end # Extend _parameter_numbers function _parameter_numbers(vref::InfiniteVariableRef) - return _core_variable_object(vref).parameter_nums + return core_object(vref).parameter_nums end # Define getter function for var.is_vector_start function _is_vector_start(vref::InfiniteVariableRef) - return _core_variable_object(vref).is_vector_start + return core_object(vref).is_vector_start end ## Set helper methods for adapting data_objects with parametric changes @@ -91,8 +100,8 @@ function _adaptive_data_update( return end -# Extend _set_core_variable_object for InfiniteVariableRefs -function _set_core_variable_object( +# Extend _set_core_object for InfiniteVariableRefs +function _set_core_object( vref::InfiniteVariableRef, var::InfiniteVariable ) @@ -280,15 +289,15 @@ function JuMP.build_variable( _check_parameter_tuple(_error, prefs) # check and format the info (accounting for start value functions) new_info, is_vect_func = _check_and_format_infinite_info(_error, info, prefs) - # get the parameter object numbers - object_nums = Int[] + # get the parameter group integer indices + group_int_idxs = Int[] for pref in prefs - union!(object_nums, _object_number(pref)) + union!(group_int_idxs, parameter_group_int_index(pref)) end # make the variable and return return InfiniteVariable(new_info, prefs, [_parameter_number(pref) for pref in prefs], - object_nums, is_vect_func) + group_int_idxs, is_vect_func) end # check the pref tuple contains only valid parameters @@ -349,7 +358,7 @@ function JuMP.add_variable( vindex = _add_data_object(model, data_object) vref = InfiniteVariableRef(model, vindex) _update_param_var_mapping(vref, v.parameter_refs) - gvref = _make_variable_ref(model, vindex) + gvref = GeneralVariableRef(model, vindex) _set_info_constraints(v.info, gvref, vref) model.name_to_var = nothing return gvref @@ -566,7 +575,7 @@ where [`parameter_refs`](@ref parameter_refs(vref::InfiniteVariableRef)) is intended as the preferred user function. """ function raw_parameter_refs(vref::InfiniteVariableRef) - return _core_variable_object(vref).parameter_refs + return core_object(vref).parameter_refs end """ @@ -636,11 +645,11 @@ function _update_variable_info( ) prefs = raw_parameter_refs(vref) param_nums = _parameter_numbers(vref) - obj_nums = _object_numbers(vref) + group_int_idxs = parameter_group_int_indices(vref) is_vect_func = _is_vector_start(vref) new_var = InfiniteVariable(_format_infinite_info(info), prefs, param_nums, - obj_nums, is_vect_func) - _set_core_variable_object(vref, new_var) + group_int_idxs, is_vect_func) + _set_core_object(vref, new_var) return end @@ -710,10 +719,10 @@ function set_start_value_function( info.upper_bound, info.has_fix, info.fixed_value, true, start, info.binary, info.integer) new_info, is_vect_func = _check_and_format_infinite_info(error, temp_info, prefs) - obj_nums = _object_numbers(vref) + group_int_idxs = parameter_group_int_indices(vref) param_nums = _parameter_numbers(vref) - new_var = InfiniteVariable(new_info, prefs, param_nums, obj_nums, is_vect_func) - _set_core_variable_object(vref, new_var) + new_var = InfiniteVariable(new_info, prefs, param_nums, group_int_idxs, is_vect_func) + _set_core_object(vref, new_var) # TODO update point variable start values as appropriate return end @@ -737,10 +746,10 @@ function reset_start_value_function(vref::InfiniteVariableRef) info.upper_bound, info.has_fix, info.fixed_value, false, start_func, info.binary, info.integer) prefs = raw_parameter_refs(vref) - obj_nums = _object_numbers(vref) + group_int_idxs = parameter_group_int_indices(vref) param_nums = _parameter_numbers(vref) - new_var = InfiniteVariable(new_info, prefs, param_nums, obj_nums, true) - _set_core_variable_object(vref, new_var) + new_var = InfiniteVariable(new_info, prefs, param_nums, group_int_idxs, true) + _set_core_object(vref, new_var) # TODO update point variable start values as appropriate return end diff --git a/src/measure_expansions.jl b/src/measure_expansions.jl index c8eff25a..1babe417 100644 --- a/src/measure_expansions.jl +++ b/src/measure_expansions.jl @@ -48,7 +48,7 @@ function make_point_variable_ref( var = PointVariable(_make_float_info(info), ivref, support) return JuMP.add_variable(write_model, var; add_support = false) else - return _make_variable_ref(write_model, pindex) + return GeneralVariableRef(write_model, pindex) end end @@ -142,7 +142,7 @@ function make_semi_infinite_variable_ref( var = JuMP.build_variable(error, ivref, eval_supps, check = false) return JuMP.add_variable(write_model, var, add_support = false) else - return _make_variable_ref(write_model, existing_index) + return GeneralVariableRef(write_model, existing_index) end end @@ -942,18 +942,18 @@ function expand_all_measures!(model::InfiniteModel) old_constr = object.constraint set = JuMP.moi_set(old_constr) # clear the old dependencies - old_vrefs = _all_function_variables(JuMP.jump_function(old_constr)) + old_vrefs = all_expression_variables(JuMP.jump_function(old_constr)) for vref in old_vrefs filter!(e -> e != cindex, _constraint_dependencies(vref)) end # expand the expression new_func = expand_measures(JuMP.jump_function(old_constr), model) - vrefs = _all_function_variables(new_func) + vrefs = all_expression_variables(new_func) # make the new constraint object new_constr = JuMP.build_constraint(error, new_func, set) # update the constraint data - cref = _make_constraint_ref(model, cindex) - _set_core_constraint_object(cref, new_constr) + cref = InfOptConstraintRef(model, cindex) + _set_core_object(cref, new_constr) empty!(object.measure_indices) _update_var_constr_mapping(vrefs, cref) end diff --git a/src/measures.jl b/src/measures.jl index 6dec53f5..b4e18021 100644 --- a/src/measures.jl +++ b/src/measures.jl @@ -43,19 +43,28 @@ function _data_object(mref::MeasureRef) return object end -# Extend _core_variable_object -function _core_variable_object(mref::MeasureRef) +""" + core_object(mref::MeasureRef)::Measure + +Retrieve the underlying core [`Measure`](@ref) object for `vref`. +This is intended as an advanced method for developers. +""" +function core_object(mref::MeasureRef) return _data_object(mref).measure end -# Extend _object_numbers -function _object_numbers(mref::MeasureRef)::Vector{Int} - return _core_variable_object(mref).object_nums +""" + parameter_group_int_indices(mref::MeasureRef)::Vector{Int} + +Return the list of infinite parameter group integer indices used by `mref`. +""" +function parameter_group_int_indices(mref::MeasureRef) + return core_object(mref).group_int_idxs end # Extend _parameter_numbers -function _parameter_numbers(mref::MeasureRef)::Vector{Int} - return _core_variable_object(mref).parameter_nums +function _parameter_numbers(mref::MeasureRef) + return core_object(mref).parameter_nums end ## Set helper methods for adapting data_objects with parametric changes @@ -74,7 +83,7 @@ function _adaptive_data_update( mref::MeasureRef, m::M1, data::MeasureData{M2} - )::Nothing where {M1, M2} + ) where {M1, M2} new_data = MeasureData(m, data.name, data.measure_indices, data.constraint_indices, data.derivative_indices, data.in_objective) @@ -83,26 +92,23 @@ function _adaptive_data_update( end # Update the core measure object -function _set_core_variable_object( - mref::MeasureRef, - meas::Measure - )::Nothing +function _set_core_object(mref::MeasureRef, meas::Measure) _adaptive_data_update(mref, meas, _data_object(mref)) return end # Extend _measure_dependencies -function _measure_dependencies(mref::MeasureRef)::Vector{MeasureIndex} +function _measure_dependencies(mref::MeasureRef) return _data_object(mref).measure_indices end # Extend _constraint_dependencies -function _constraint_dependencies(mref::MeasureRef)::Vector{InfOptConstraintIndex} +function _constraint_dependencies(mref::MeasureRef) return _data_object(mref).constraint_indices end # Extend _derivative_dependencies -function _derivative_dependencies(mref::MeasureRef)::Vector{DerivativeIndex} +function _derivative_dependencies(mref::MeasureRef) return _data_object(mref).derivative_indices end @@ -759,14 +765,14 @@ function build_measure( expr::JuMP.AbstractJuMPScalar, data::AbstractMeasureData ) - vrefs = _all_function_variables(expr) - expr_obj_nums = _object_numbers(expr) + vrefs = all_expression_variables(expr) + expr_group_int_idxs = parameter_group_int_indices(expr) expr_param_nums = _parameter_numbers(expr) prefs = parameter_refs(data) - data_obj_nums = _object_numbers(prefs) + data_group_int_idxs = parameter_group_int_indices(prefs) data_param_nums = [_parameter_number(pref) for pref in prefs] - # NOTE setdiff! cannot be used here since it modifies object_nums of expr if expr is a single infinite variable - obj_nums = sort(setdiff(expr_obj_nums, data_obj_nums)) + # NOTE setdiff! cannot be used here since it modifies group_int_idxs of expr if expr is a single infinite variable + group_int_idxs = sort(setdiff(expr_group_int_idxs, data_group_int_idxs)) param_nums = sort(setdiff(expr_param_nums, data_param_nums)) # check if analytic method should be applied lb_nan = isnan(first(JuMP.lower_bound(data))) @@ -774,7 +780,7 @@ function build_measure( # NOTE intersect! cannot be used here since it modifies parameter_nums of expr if expr is a single infinite variable constant_func = isempty(intersect(expr_param_nums, data_param_nums)) && ((!lb_nan && !ub_nan) || _is_expect(data)) - return Measure(expr, data, obj_nums, param_nums, constant_func) + return Measure(expr, data, group_int_idxs, param_nums, constant_func) end ################################################################################ @@ -1016,7 +1022,7 @@ function add_measure( name::String = "measure" )::GeneralVariableRef # get the expression variables and check validity - vrefs = _all_function_variables(meas.func) + vrefs = all_expression_variables(meas.func) for vref in vrefs JuMP.check_belongs_to_model(vref, model) end @@ -1036,7 +1042,7 @@ function add_measure( # add the measure to the model object = MeasureData(meas, name) mindex = _add_data_object(model, object) - mref = _make_variable_ref(model, mindex) + mref = GeneralVariableRef(model, mindex) # update mappings for vref in union!(vrefs, prefs) push!(_measure_dependencies(vref), mindex) @@ -1057,7 +1063,7 @@ y(x, t) + 2 ``` """ function measure_function(mref::MeasureRef)::JuMP.AbstractJuMPScalar - return _core_variable_object(mref).func + return core_object(mref).func end """ @@ -1074,7 +1080,7 @@ FunctionalDiscreteMeasureData{Vector{GeneralVariableRef},Vector{Float64}} ``` """ function measure_data(mref::MeasureRef)::AbstractMeasureData - return _core_variable_object(mref).data + return core_object(mref).data end """ @@ -1089,7 +1095,7 @@ false ``` """ function is_analytic(mref::MeasureRef)::Bool - return _core_variable_object(mref).constant_func + return core_object(mref).constant_func end ## Return an element of a parameter reference tuple given the model, index, and parameter numbers @@ -1098,8 +1104,8 @@ function _make_param_tuple_element( model::InfiniteModel, idx::IndependentParameterIndex, param_nums::Vector{Int} - )::GeneralVariableRef - return _make_parameter_ref(model, idx) + ) + return GeneralVariableRef(model, idx) end # DependentParametersIndex @@ -1107,7 +1113,7 @@ function _make_param_tuple_element( model::InfiniteModel, idx::DependentParametersIndex, param_nums::Vector{Int} - )::Union{GeneralVariableRef, Vector{GeneralVariableRef}} + ) dpref = DependentParameterRef(model, DependentParameterIndex(idx, 1)) el_param_nums = _data_object(dpref).parameter_nums prefs = [GeneralVariableRef(model, idx.value, DependentParameterIndex, i) @@ -1131,7 +1137,7 @@ julia> parameter_refs(meas) """ function parameter_refs(mref::MeasureRef) model = JuMP.owner_model(mref) - obj_indices = _param_object_indices(model)[_object_numbers(mref)] + obj_indices = parameter_group_indices(model)[parameter_group_int_indices(mref)] param_nums = _parameter_numbers(mref) return Tuple(_make_param_tuple_element(model, idx, param_nums) for idx in obj_indices) @@ -1250,7 +1256,7 @@ julia> used_by_measure(mref) true ``` """ -function used_by_measure(mref::MeasureRef)::Bool +function used_by_measure(mref::MeasureRef) return !isempty(_measure_dependencies(mref)) end @@ -1265,7 +1271,7 @@ julia> used_by_constraint(mref) false ``` """ -function used_by_constraint(mref::MeasureRef)::Bool +function used_by_constraint(mref::MeasureRef) return !isempty(_constraint_dependencies(mref)) end @@ -1280,7 +1286,7 @@ julia> used_by_objective(mref) true ``` """ -function used_by_objective(mref::MeasureRef)::Bool +function used_by_objective(mref::MeasureRef) return _data_object(mref).in_objective end @@ -1295,7 +1301,7 @@ julia> used_by_derivative(mref) true ``` """ -function used_by_derivative(mref::MeasureRef)::Bool +function used_by_derivative(mref::MeasureRef) return !isempty(_derivative_dependencies(mref)) end @@ -1310,7 +1316,7 @@ julia> is_used(mref) true ``` """ -function is_used(mref::MeasureRef)::Bool +function is_used(mref::MeasureRef) return used_by_measure(mref) || used_by_constraint(mref) || used_by_objective(mref) || used_by_derivative(mref) end @@ -1329,7 +1335,7 @@ julia> num_measures(model) 2 ``` """ -function num_measures(model::InfiniteModel)::Int +function num_measures(model::InfiniteModel) return length(_data_dictionary(model, Measure)) end @@ -1346,10 +1352,10 @@ julia> all_measures(model) 𝔼{x}[w(t, x)] ``` """ -function all_measures(model::InfiniteModel)::Vector{GeneralVariableRef} +function all_measures(model::InfiniteModel) vrefs_list = Vector{GeneralVariableRef}(undef, num_measures(model)) for (i, (index, _)) in enumerate(_data_dictionary(model, Measure)) - vrefs_list[i] = _make_variable_ref(model, index) + vrefs_list[i] = GeneralVariableRef(model, index) end return vrefs_list end @@ -1384,13 +1390,13 @@ Subject to g(0.5) = 0 ``` """ -function JuMP.delete(model::InfiniteModel, mref::MeasureRef)::Nothing +function JuMP.delete(model::InfiniteModel, mref::MeasureRef) @assert JuMP.is_valid(model, mref) "Invalid measure reference." # Reset the transcription status if is_used(mref) set_transformation_backend_ready(model, false) end - gvref = _make_variable_ref(JuMP.owner_model(mref), JuMP.index(mref)) + gvref = GeneralVariableRef(JuMP.owner_model(mref), JuMP.index(mref)) # Remove from dependent measures if there are any for mindex in _measure_dependencies(mref) meas_ref = dispatch_variable_ref(model, mindex) @@ -1403,24 +1409,24 @@ function JuMP.delete(model::InfiniteModel, mref::MeasureRef)::Nothing _remove_variable(func, gvref) new_meas = build_measure(func, data) end - _set_core_variable_object(meas_ref, new_meas) + _set_core_object(meas_ref, new_meas) end # Remove from dependent constraints if there are any for cindex in copy(_constraint_dependencies(mref)) - cref = _make_constraint_ref(model, cindex) + cref = InfOptConstraintRef(model, cindex) func = JuMP.jump_function(JuMP.constraint_object(cref)) if func isa GeneralVariableRef set = JuMP.moi_set(JuMP.constraint_object(cref)) new_func = zero(JuMP.GenericAffExpr{Float64, GeneralVariableRef}) new_constr = JuMP.ScalarConstraint(new_func, set) - _set_core_constraint_object(cref, new_constr) - empty!(_object_numbers(cref)) + _set_core_object(cref, new_constr) + empty!(parameter_group_int_indices(cref)) empty!(_measure_dependencies(cref)) elseif func isa AbstractArray && any(isequal(gvref), func) JuMP.delete(model, cref) else _remove_variable(func, gvref) - _data_object(cref).object_nums = sort(_object_numbers(func)) + _data_object(cref).group_int_idxs = sort(parameter_group_int_indices(func)) filter!(e -> e != JuMP.index(mref), _measure_dependencies(cref)) end end @@ -1440,7 +1446,7 @@ function JuMP.delete(model::InfiniteModel, mref::MeasureRef)::Nothing end # Update that the variables used by it are no longer used by it prefs = parameter_refs(measure_data(mref)) - vrefs = _all_function_variables(measure_function(mref)) + vrefs = all_expression_variables(measure_function(mref)) union!(vrefs, prefs) for vref in vrefs filter!(e -> e != JuMP.index(mref), _measure_dependencies(vref)) diff --git a/src/objective.jl b/src/objective.jl index 9d0d68eb..81d2500f 100644 --- a/src/objective.jl +++ b/src/objective.jl @@ -93,16 +93,16 @@ function JuMP.set_objective_function( func::JuMP.AbstractJuMPScalar )::Nothing # gather the unique list of variable references for testing and mapping - new_vrefs = _all_function_variables(func) + new_vrefs = all_expression_variables(func) # test in the model for vref in new_vrefs JuMP.check_belongs_to_model(vref, model) end - if !isempty(_object_numbers(new_vrefs)) + if !isempty(parameter_group_int_indices(new_vrefs)) error("Objective function cannot contain infinite parameters/variables.") end # delete old mappings - old_vrefs = _all_function_variables(JuMP.objective_function(model)) + old_vrefs = all_expression_variables(JuMP.objective_function(model)) for vref in old_vrefs _data_object(vref).in_objective = false end @@ -136,7 +136,7 @@ julia> objective_function(model) """ function JuMP.set_objective_function(model::InfiniteModel, func::Real)::Nothing # delete old mappings - old_vrefs = _all_function_variables(JuMP.objective_function(model)) + old_vrefs = all_expression_variables(JuMP.objective_function(model)) for vref in old_vrefs _data_object(vref).in_objective = false end diff --git a/src/point_variables.jl b/src/point_variables.jl index 688196e6..565fc2bb 100644 --- a/src/point_variables.jl +++ b/src/point_variables.jl @@ -45,9 +45,13 @@ function _data_object( return object end -# Extend _core_variable_object -function _core_variable_object(vref::PointVariableRef - )::PointVariable{GeneralVariableRef} +""" + core_object(vref::PointVariableRef)::PointVariable + +Retrieve the underlying core [`PointVariable`] object for `vref`. +This is intended as an advanced method for developers. +""" +function core_object(vref::PointVariableRef) return _data_object(vref).variable end @@ -323,8 +327,8 @@ function _update_info_constraints(info::JuMP.VariableInfo, gvref, vref)::Nothing constr = JuMP.ScalarConstraint(gvref, MOI.GreaterThan(info.lower_bound)) if old_info.has_lb cindex = _lower_bound_index(vref) - cref = _make_constraint_ref(model, cindex) - _set_core_constraint_object(cref, constr) + cref = InfOptConstraintRef(model, cindex) + _set_core_object(cref, constr) else cref = JuMP.add_constraint(model, constr, is_info_constr = true) _set_lower_bound_index(vref, JuMP.index(cref)) @@ -339,8 +343,8 @@ function _update_info_constraints(info::JuMP.VariableInfo, gvref, vref)::Nothing constr = JuMP.ScalarConstraint(gvref, MOI.LessThan(info.upper_bound)) if old_info.has_ub cindex = _upper_bound_index(vref) - cref = _make_constraint_ref(model, cindex) - _set_core_constraint_object(cref, constr) + cref = InfOptConstraintRef(model, cindex) + _set_core_object(cref, constr) else cref = JuMP.add_constraint(model, constr, is_info_constr = true) _set_upper_bound_index(vref, JuMP.index(cref)) @@ -355,8 +359,8 @@ function _update_info_constraints(info::JuMP.VariableInfo, gvref, vref)::Nothing constr = JuMP.ScalarConstraint(gvref, MOI.EqualTo(info.fixed_value)) if old_info.has_fix cindex = _fix_index(vref) - cref = _make_constraint_ref(model, cindex) - _set_core_constraint_object(cref, constr) + cref = InfOptConstraintRef(model, cindex) + _set_core_object(cref, constr) else cref = JuMP.add_constraint(model, constr, is_info_constr = true) _set_fix_index(vref, JuMP.index(cref)) @@ -440,10 +444,10 @@ function JuMP.add_variable( end _update_infinite_point_mapping(vref, divref) model.point_lookup[(ivref, v.parameter_values)] = vindex - gvref = _make_variable_ref(model, vindex) + gvref = GeneralVariableRef(model, vindex) _set_info_constraints(v.info, gvref, vref) else - gvref = _make_variable_ref(model, existing_index) + gvref = GeneralVariableRef(model, existing_index) if update_info vref = PointVariableRef(model, existing_index) _update_info_constraints(v.info, gvref, vref) @@ -477,7 +481,7 @@ T(t) ``` """ function infinite_variable_ref(vref::PointVariableRef)::GeneralVariableRef - return _core_variable_object(vref).infinite_variable_ref + return core_object(vref).infinite_variable_ref end @@ -487,7 +491,7 @@ end Return the raw support point values associated with the point variable `vref`. """ function raw_parameter_values(vref::PointVariableRef)::Vector{Float64} - return _core_variable_object(vref).parameter_values + return core_object(vref).parameter_values end """ @@ -520,7 +524,7 @@ function _update_variable_param_values( info = _variable_info(vref) ivref = infinite_variable_ref(vref) new_var = PointVariable(info, ivref, pref_vals) - _set_core_variable_object(vref, new_var) + _set_core_object(vref, new_var) return end @@ -535,7 +539,7 @@ function _update_variable_info( ivref = infinite_variable_ref(vref) param_values = raw_parameter_values(vref) new_var = PointVariable(info, ivref, param_values) - _set_core_variable_object(vref, new_var) + _set_core_object(vref, new_var) return end diff --git a/src/results.jl b/src/results.jl index 45d7fcd1..5e24123f 100644 --- a/src/results.jl +++ b/src/results.jl @@ -1,81 +1,167 @@ ################################################################################ # MODEL QUERIES ################################################################################ -# Simple model queries -for func in (:termination_status, :raw_status, :solve_time, :simplex_iterations, - :barrier_iterations, :node_count, :objective_bound, :relative_gap, - :result_count) - @eval begin - @doc """ - JuMP.$($func)(backend::AbstractTransformationBackend) - - Implment `JuMP.$($func)` for transformation backends. If applicable, this - should be extended for new backend types. No extension is needed for - [`JuMPBackend`](@ref)s. - """ - function JuMP.$func(backend::AbstractTransformationBackend) - error("`JuMP.$($func)` not defined for backends of type " * - "`$(typeof(backend))`.") - end +# Ensure results are reliable +function _check_result_is_current(model::InfiniteModel, func) + if JuMP.termination_status(model) == MOI.OPTIMIZE_NOT_CALLED + error("Unable to query `$func` since up-to-date solution results " * + "are not available. This is likely because the transformation " * + "backend has not been built and optimized yet, or the model " * + "has been modified since the backend was optimized.") + end + return +end - # Define for JuMPBackend - function JuMP.$func(backend::JuMPBackend) - return JuMP.$func(backend.model) - end +# Make `get_attribute` check for reliability +function JuMP.get_attribute(model::InfiniteModel, attr::MOI.TerminationStatus) + if !transformation_backend_ready(model) + return MOI.OPTIMIZE_NOT_CALLED + end + return JuMP.get_attribute(model.backend, attr) +end +function JuMP.get_attribute(model::InfiniteModel, attr::MOI.ResultCount) + if JuMP.termination_status(model) == MOI.OPTIMIZE_NOT_CALLED + return 0 + end + return JuMP.get_attribute(model.backend, attr) +end +function JuMP.get_attribute(model::InfiniteModel, attr::MOI.RawStatusString) + if JuMP.termination_status(model) == MOI.OPTIMIZE_NOT_CALLED + return "optimize not called" + end + return JuMP.get_attribute(model.backend, attr) +end +function JuMP.get_attribute( + model::InfiniteModel, + attr::Union{MOI.PrimalStatus, MOI.DualStatus} + ) + if JuMP.termination_status(model) == MOI.OPTIMIZE_NOT_CALLED + return MOI.NO_SOLUTION + end + return JuMP.get_attribute(model.backend, attr) +end +function JuMP.get_attribute( + model::InfiniteModel, + attr::MOI.AbstractModelAttribute + ) + if MOI.is_set_by_optimize(attr) + _check_result_is_current(model::InfiniteModel, attr) + end + return JuMP.get_attribute(model.backend, attr) +end +# Simple model queries +for (func, Attr) in ( + (:termination_status, :TerminationStatus), + (:raw_status, :RawStatusString), + (:solve_time, :SolveTimeSec), + (:simplex_iterations, :SimplexIterations), + (:barrier_iterations, :BarrierIterations), + (:node_count, :NodeCount), + (:objective_bound, :ObjectiveBound), + (:relative_gap, :RelativeGap), + (:result_count, :ResultCount) + ) + @eval begin @doc """ JuMP.$($func)(model::InfiniteModel) Extend [`JuMP.$($func)`](https://jump.dev/JuMP.jl/v1/api/JuMP/#$($func)) for `InfiniteModel`s in accordance with that reported by its transformation backend. Errors if such a query is not supported or if - the transformation backend hasn't be solved. + the transformation backend hasn't been solved. """ function JuMP.$func(model::InfiniteModel) - return JuMP.$func(model.backend) + JuMP.get_attribute(model, MOI.$Attr()) end end end # Simple result dependent model queries -for func in (:primal_status, :dual_status, :has_values, :has_duals, - :objective_value, :dual_objective_value) +for (func, Attr) in ( + (:primal_status, :PrimalStatus), + (:dual_status, :DualStatus), + (:objective_value, :ObjectiveValue), + (:dual_objective_value, :DualObjectiveValue) + ) @eval begin @doc """ - JuMP.$($func)(backend::AbstractTransformationBackend; [kwargs...]) + JuMP.$($func)(model::InfiniteModel; result::Int = 1) - Implment `JuMP.$($func)` for transformation backends. If applicable, this - should be extended for new backend types. No extension is needed for - [`JuMPBackend`](@ref)s. As needed keyword arguments can be added. - `JuMPBackend`s use the `result::Int = 1` keyword argument. + Extend [`JuMP.$($func)`](https://jump.dev/JuMP.jl/v1/api/JuMP/#$($func)) + for `InfiniteModel`s in accordance with that reported by its + transformation backend. Errors if such a query is not supported or if the + transformation backend hasn't be solved. Accepts keyword `result` + to access the solution index of interest (if the solver/backend supports + multiple solutions). """ - function JuMP.$func(backend::AbstractTransformationBackend; kwargs...) - error("`JuMP.$($func)` not defined for backends of type " * - "`$(typeof(backend))`.") - end - - # Define for JuMPBackend - function JuMP.$func(backend::JuMPBackend; kwargs...) - return JuMP.$func(backend.model; kwargs...) + function JuMP.$func(model::InfiniteModel; result::Int = 1) + return JuMP.get_attribute(model, MOI.$Attr(result)) end + end +end +# Simple result dependent model queries +for (func, Attr) in ((:has_values, :PrimalStatus), (:has_duals, :DualStatus)) + @eval begin @doc """ - JuMP.$($func)(model::InfiniteModel; [kwargs...]) + JuMP.$($func)(model::InfiniteModel; result::Int = 1) Extend [`JuMP.$($func)`](https://jump.dev/JuMP.jl/v1/api/JuMP/#$($func)) for `InfiniteModel`s in accordance with that reported by its transformation backend. Errors if such a query is not supported or if the - transformation backend hasn't be solved. Accepts keywords depending - on the backend. JuMP-based backends use the `result::Int = 1` keyword - argument to access the solution index of interest (if the solver supports + transformation backend hasn't be solved. Accepts keyword `result` + to access the solution index of interest (if the solver/backend supports multiple solutions). """ - function JuMP.$func(model::InfiniteModel; kwargs...) - return JuMP.$func(model.backend; kwargs...) + function JuMP.$func(model::InfiniteModel; result::Int = 1) + return JuMP.get_attribute(model, MOI.$Attr(result)) != MOI.NO_SOLUTION end end end +""" + JuMP.is_solved_and_feasible( + model::InfiniteModel; + [dual::Bool = false, + allow_local::Bool = true, + allow_almost::Bool = false, + result::Int = 1] + )::Bool + +Extend [`JuMP.is_solved_and_feasible`](https://jump.dev/JuMP.jl/v1/api/JuMP/#is_solved_and_feasible)) +for `model`. See the JuMP docs details. +For new transformation backend types, this relies on `JuMP.termination_status`, +`JuMP.primal_status`, and `JuMP.dual_status`. +""" +function JuMP.is_solved_and_feasible( + model::InfiniteModel; + dual::Bool = false, + allow_local::Bool = true, + allow_almost::Bool = false, + result::Int = 1 + ) + status = JuMP.termination_status(model) + ret = + (status == MOI.OPTIMAL) || + (allow_local && (status == MOI.LOCALLY_SOLVED)) || + (allow_almost && (status == MOI.ALMOST_OPTIMAL)) || + (allow_almost && allow_local && (status == MOI.ALMOST_LOCALLY_SOLVED)) + if ret + primal = JuMP.primal_status(model; result) + ret &= + (primal == MOI.FEASIBLE_POINT) || + (allow_almost && (primal == MOI.NEARLY_FEASIBLE_POINT)) + end + if ret && dual + dual_stat = JuMP.dual_status(model; result) + ret &= + (dual_stat == MOI.FEASIBLE_POINT) || + (allow_almost && (dual_stat == MOI.NEARLY_FEASIBLE_POINT)) + end + return ret +end + ################################################################################ # VALUE QUERIES ################################################################################ @@ -224,6 +310,7 @@ julia> value(z) ``` """ function JuMP.value(vref::GeneralVariableRef; kwargs...) + _check_result_is_current(JuMP.owner_model(vref), JuMP.value) return _get_value(vref, _index_type(vref); kwargs...) end @@ -286,6 +373,7 @@ function JuMP.value( return JuMP.constant(expr) # otherwise let's call map_value else + _check_result_is_current(model, JuMP.value) return map_value(expr, model.backend; kwargs...) end end @@ -331,7 +419,9 @@ julia> value(c1) ``` """ function JuMP.value(cref::InfOptConstraintRef; kwargs...) - return map_value(cref, JuMP.owner_model(cref).backend; kwargs...) + model = JuMP.owner_model(cref) + _check_result_is_current(model, JuMP.value) + return map_value(cref, model.backend; kwargs...) end ################################################################################ @@ -404,7 +494,9 @@ for (Ref, func, mapper) in ( all be called with the same keyword arguments for consistency. """ function JuMP.$func(ref::$Ref; kwargs...) - backend = JuMP.owner_model(ref).backend + model = JuMP.owner_model(ref) + backend = model.backend + _check_result_is_current(model, JuMP.$func) return $(Symbol(string("map_", func)))(ref, backend; kwargs...) end end @@ -492,7 +584,9 @@ julia> dual(c1) ``` """ function JuMP.dual(cref::InfOptConstraintRef; kwargs...) - return map_dual(cref, JuMP.owner_model(cref).backend; kwargs...) + model = JuMP.owner_model(cref) + _check_result_is_current(model, JuMP.dual) + return map_dual(cref, model.backend; kwargs...) end # Error redirect for variable call @@ -596,5 +690,6 @@ julia> report[x] ``` """ function JuMP.lp_sensitivity_report(model::InfiniteModel; atol::Float64 = 1e-8) + _check_result_is_current(model, JuMP.lp_sensitivity_report) return JuMP.lp_sensitivity_report(model.backend; atol = atol) end diff --git a/src/scalar_parameters.jl b/src/scalar_parameters.jl index 424ad781..57617a07 100644 --- a/src/scalar_parameters.jl +++ b/src/scalar_parameters.jl @@ -22,7 +22,7 @@ function _add_data_object( object::ScalarParameterData{<:IndependentParameter} ) index = MOIUC.add_item(model.independent_params, object) - push!(model.param_object_indices, index) + push!(model.param_group_indices, index) return index end @@ -65,13 +65,23 @@ end ################################################################################ # CORE OBJECT METHODS ################################################################################ -# Extend _core_variable_object for IndependentParameterRefs -function _core_variable_object(pref::IndependentParameterRef) +""" + core_object(pref::IndependentParameterRef)::IndependentParameter + +Retrieve the underlying core [`IndependentParameter`] object for `pref`. +This is intended as an advanced method for developers. +""" +function core_object(pref::IndependentParameterRef) return _data_object(pref).parameter end -# Extend _core_variable_object for FiniteParameterRefs -function _core_variable_object(pref::FiniteParameterRef) +""" + core_object(pref::FiniteParameterRef)::FiniteParameter + +Retrieve the underlying core [`FiniteParameter`] object for `pref`. +This is intended as an advanced method for developers. +""" +function core_object(pref::FiniteParameterRef) return _data_object(pref).parameter end @@ -85,14 +95,18 @@ function _parameter_numbers(pref::IndependentParameterRef) return [_parameter_number(pref)] end -# Extend _object_number -function _object_number(pref::IndependentParameterRef) - return _data_object(pref).object_num +""" + `parameter_group_int_index(pref::IndependentParameterRef)::Int + +Return the infinite parameter group integer index corresponding to `pref`. +""" +function parameter_group_int_index(pref::IndependentParameterRef) + return _data_object(pref).group_int_idx end -# Extend _object_numbers -function _object_numbers(pref::IndependentParameterRef) - return [_object_number(pref)] +# Extend parameter_group_int_indices +function parameter_group_int_indices(pref::IndependentParameterRef) + return [parameter_group_int_index(pref)] end ## Set helper methods for adapting data_objects with parametric changes @@ -112,7 +126,7 @@ function _adaptive_data_update( param::P1, data::ScalarParameterData{P2} ) where {P1, P2} - new_data = ScalarParameterData(param, data.object_num, data.parameter_num, + new_data = ScalarParameterData(param, data.group_int_idx, data.parameter_num, data.name, data.parameter_func_indices, data.infinite_var_indices, data.derivative_indices, data.measure_indices, @@ -125,8 +139,8 @@ function _adaptive_data_update( return end -# Extend _set_core_variable_object for ScalarParameterRefs -function _set_core_variable_object( +# Extend _set_core_object for ScalarParameterRefs +function _set_core_object( pref::ScalarParameterRef, param::ScalarParameter ) @@ -269,9 +283,9 @@ function add_parameter( p::IndependentParameter, name::String = "" ) - obj_num = length(_param_object_indices(model)) + 1 + group_int_idx = length(parameter_group_indices(model)) + 1 param_num = model.last_param_num += 1 - data_object = ScalarParameterData(p, obj_num, param_num, name) + data_object = ScalarParameterData(p, group_int_idx, param_num, name) obj_index = _add_data_object(model, data_object) model.name_to_param = nothing return GeneralVariableRef(model, obj_index.value, typeof(obj_index)) @@ -311,38 +325,32 @@ end # PARAMETER DEPENDENCIES ################################################################################ # Extend _infinite_variable_dependencies -function _infinite_variable_dependencies(pref::ScalarParameterRef - )::Vector{InfiniteVariableIndex} +function _infinite_variable_dependencies(pref::ScalarParameterRef) return _data_object(pref).infinite_var_indices end # Extend _parameter_function_dependencies -function _parameter_function_dependencies(pref::ScalarParameterRef - )::Vector{ParameterFunctionIndex} +function _parameter_function_dependencies(pref::ScalarParameterRef) return _data_object(pref).parameter_func_indices end # Extend _derivative_dependencies -function _derivative_dependencies(pref::ScalarParameterRef - )::Vector{DerivativeIndex} +function _derivative_dependencies(pref::ScalarParameterRef) return _data_object(pref).derivative_indices end # Extend _measure_dependencies -function _measure_dependencies(pref::ScalarParameterRef - )::Vector{MeasureIndex} +function _measure_dependencies(pref::ScalarParameterRef) return _data_object(pref).measure_indices end # Extend _constraint_dependencies -function _constraint_dependencies(pref::ScalarParameterRef - )::Vector{InfOptConstraintIndex} +function _constraint_dependencies(pref::ScalarParameterRef) return _data_object(pref).constraint_indices end # Extend _generative_measures -function _generative_measures(pref::ScalarParameterRef - )::Vector{MeasureIndex} +function _generative_measures(pref::ScalarParameterRef) return _data_object(pref).generative_measures end @@ -360,7 +368,7 @@ julia> used_by_infinite_variable(t) true ``` """ -function used_by_infinite_variable(pref::IndependentParameterRef)::Bool +function used_by_infinite_variable(pref::IndependentParameterRef) return !isempty(_infinite_variable_dependencies(pref)) end @@ -378,12 +386,12 @@ julia> used_by_parameter_function(t) false ``` """ -function used_by_parameter_function(pref::IndependentParameterRef)::Bool +function used_by_parameter_function(pref::IndependentParameterRef) return !isempty(_parameter_function_dependencies(pref)) end # FiniteParameter -used_by_parameter_function(pref::FiniteParameterRef)::Bool = false +used_by_parameter_function(pref::FiniteParameterRef) = false """ used_by_measure(pref::Union{IndependentParameterRef, FiniteParameterRef})::Bool @@ -396,7 +404,7 @@ julia> used_by_measure(t) false ``` """ -function used_by_measure(pref::ScalarParameterRef)::Bool +function used_by_measure(pref::ScalarParameterRef) return !isempty(_measure_dependencies(pref)) end @@ -411,7 +419,7 @@ julia> used_by_constraint(t) true ``` """ -function used_by_constraint(pref::ScalarParameterRef)::Bool +function used_by_constraint(pref::ScalarParameterRef) return !isempty(_constraint_dependencies(pref)) end @@ -424,12 +432,12 @@ Return true if `pref` is used by the objective function. ```julia-repl ``` """ -function used_by_objective(pref::FiniteParameterRef)::Bool +function used_by_objective(pref::FiniteParameterRef) return _data_object(pref).in_objective end # IndependentParameter -used_by_objective(::IndependentParameterRef)::Bool = false +used_by_objective(::IndependentParameterRef) = false """ used_by_derivative(pref::IndependentParameterRef)::Bool @@ -442,12 +450,12 @@ julia> used_by_derivative(t) false ``` """ -function used_by_derivative(pref::IndependentParameterRef)::Bool +function used_by_derivative(pref::IndependentParameterRef) return !isempty(_derivative_dependencies(pref)) end # FiniteParameter -used_by_derivative(::FiniteParameterRef)::Bool = false +used_by_derivative(::FiniteParameterRef) = false """ is_used(pref::Union{IndependentParameterRef, FiniteParameterRef})::Bool @@ -460,7 +468,7 @@ julia> is_used(t) true ``` """ -function is_used(pref::ScalarParameterRef)::Bool +function is_used(pref::ScalarParameterRef) return used_by_measure(pref) || used_by_constraint(pref) || used_by_infinite_variable(pref) || used_by_objective(pref) || used_by_derivative(pref) || used_by_parameter_function(pref) @@ -482,7 +490,7 @@ julia> name(t) "t" ``` """ -function JuMP.name(pref::ScalarParameterRef)::String +function JuMP.name(pref::ScalarParameterRef) object = get(_data_dictionary(pref), JuMP.index(pref), nothing) return isnothing(object) ? "" : object.name end @@ -501,35 +509,22 @@ julia> name(t) "time" ``` """ -function JuMP.set_name(pref::ScalarParameterRef, name::String)::Nothing +function JuMP.set_name(pref::ScalarParameterRef, name::String) _data_object(pref).name = name JuMP.owner_model(pref).name_to_param = nothing return end -# Make a parameter reference -function _make_parameter_ref(model::InfiniteModel, - index::AbstractInfOptIndex)::GeneralVariableRef - return GeneralVariableRef(model, MOIUC.key_to_index(index), typeof(index)) -end - -function _make_parameter_ref(model::InfiniteModel, - index::DependentParameterIndex - )::GeneralVariableRef - return GeneralVariableRef(model, MOIUC.key_to_index(index.object_index), - typeof(index), index.param_index) -end - # Get the name_to_param Dictionary -function _param_name_dict(model::InfiniteModel - )::Union{Dict{String, AbstractInfOptIndex}, Nothing} +function _param_name_dict(model::InfiniteModel) return model.name_to_param end # Update name_to_param -function _update_param_name_dict(model::InfiniteModel, +function _update_param_name_dict( + model::InfiniteModel, param_dict::MOIUC.CleverDict{K, V} - )::Nothing where {K, V <: ScalarParameterData} + ) where {K, V <: ScalarParameterData} name_dict = _param_name_dict(model) for (index, data_object) in param_dict param_name = data_object.name @@ -545,9 +540,10 @@ function _update_param_name_dict(model::InfiniteModel, return end -function _update_param_name_dict(model::InfiniteModel, +function _update_param_name_dict( + model::InfiniteModel, param_dict::MOIUC.CleverDict{K, V} - )::Nothing where {K, V <: MultiParameterData} + ) where {K, V <: MultiParameterData} name_dict = _param_name_dict(model) for (index, data_object) in param_dict param_nums = data_object.parameter_nums @@ -580,8 +576,7 @@ julia> parameter_by_name(model, "t") t ``` """ -function parameter_by_name(model::InfiniteModel, - name::String)::Union{GeneralVariableRef, Nothing} +function parameter_by_name(model::InfiniteModel, name::String) if isnothing(_param_name_dict(model)) model.name_to_param = Dict{String, AbstractInfOptIndex}() _update_param_name_dict(model, model.independent_params) @@ -594,7 +589,7 @@ function parameter_by_name(model::InfiniteModel, elseif index == IndependentParameterIndex(-1) error("Multiple parameters have the name $name.") else - return _make_parameter_ref(model, index) + return GeneralVariableRef(model, index) end end @@ -602,12 +597,12 @@ end # GENERATIVE SUPPORT FUNCTIONS ################################################################################ # Extend copy for NoGenerativeSupports -function Base.copy(d::NoGenerativeSupports)::NoGenerativeSupports +function Base.copy(d::NoGenerativeSupports) return NoGenerativeSupports() end # Extend copy for UniformGenerativeInfo -function Base.copy(d::UniformGenerativeInfo)::UniformGenerativeInfo +function Base.copy(d::UniformGenerativeInfo) return UniformGenerativeInfo(copy(d.support_basis), d.label) end @@ -624,12 +619,12 @@ function support_label(info::AbstractGenerativeInfo) end # UniformGenerativeInfo -function support_label(info::UniformGenerativeInfo)::DataType +function support_label(info::UniformGenerativeInfo) return info.label end # NoGenerativeSupports -function support_label(info::NoGenerativeSupports)::DataType +function support_label(info::NoGenerativeSupports) return _NoLabel end @@ -638,8 +633,8 @@ end Return the generative support information associated with `pref`. """ -function generative_support_info(pref::IndependentParameterRef)::AbstractGenerativeInfo - return _core_variable_object(pref).generative_supp_info +function generative_support_info(pref::IndependentParameterRef) + return core_object(pref).generative_supp_info end """ @@ -648,19 +643,18 @@ end Return whether generative supports have been added to `pref` in accordance with its generative support info. """ -function has_generative_supports(pref::IndependentParameterRef)::Bool +function has_generative_supports(pref::IndependentParameterRef) return _data_object(pref).has_generative_supports end # Specify if a parameter has generative supports -function _set_has_generative_supports(pref::IndependentParameterRef, - status::Bool)::Nothing +function _set_has_generative_supports(pref::IndependentParameterRef, status::Bool) _data_object(pref).has_generative_supports = status return end # Reset (remove) the generative supports if needed -function _reset_generative_supports(pref::IndependentParameterRef)::Nothing +function _reset_generative_supports(pref::IndependentParameterRef) if has_generative_supports(pref) label = support_label(generative_support_info(pref)) delete_supports(pref, label = label) # this also calls _set_has_generative_supports @@ -669,15 +663,17 @@ function _reset_generative_supports(pref::IndependentParameterRef)::Nothing end # Specify the generative_support_info -function _set_generative_support_info(pref::IndependentParameterRef, - info::AbstractGenerativeInfo)::Nothing +function _set_generative_support_info( + pref::IndependentParameterRef, + info::AbstractGenerativeInfo + ) sig_digits = significant_digits(pref) method = derivative_method(pref) domain = _parameter_domain(pref) supps = _parameter_supports(pref) new_param = IndependentParameter(domain, supps, sig_digits, method, info) _reset_generative_supports(pref) - _set_core_variable_object(pref, new_param) + _set_core_object(pref, new_param) if is_used(pref) set_transformation_backend_ready(JuMP.owner_model(pref), false) end @@ -703,8 +699,7 @@ function make_generative_supports(info::AbstractGenerativeInfo, pref, supps) end # UniformGenerativeInfo -function make_generative_supports(info::UniformGenerativeInfo, - pref, supps)::Vector{Float64} +function make_generative_supports(info::UniformGenerativeInfo, pref, supps) # collect the preliminaries basis = info.support_basis num_internal = length(basis) @@ -723,7 +718,7 @@ end ## Define internal dispatch methods for adding generative supports # AbstractGenerativeInfo -function _add_generative_supports(pref, info::AbstractGenerativeInfo)::Nothing +function _add_generative_supports(pref, info::AbstractGenerativeInfo) if !has_generative_supports(pref) existing_supps = supports(pref, label = All) supps = make_generative_supports(info, pref, existing_supps) @@ -734,7 +729,7 @@ function _add_generative_supports(pref, info::AbstractGenerativeInfo)::Nothing end # NoGenerativeSupports -function _add_generative_supports(pref, info::NoGenerativeSupports)::Nothing +function _add_generative_supports(pref, info::NoGenerativeSupports) return end @@ -746,7 +741,7 @@ generative support info using [`make_generative_supports`](@ref) and add them to `pref`. This is intended as an internal function, but can be useful user defined transformation backend extensions that utlize our support system. """ -function add_generative_supports(pref::IndependentParameterRef)::Nothing +function add_generative_supports(pref::IndependentParameterRef) info = generative_support_info(pref) _add_generative_supports(pref, info) return @@ -756,13 +751,12 @@ end # DERIVATIVE METHOD FUNCTIONS ################################################################################ # Determine if any derivatives have derivative constraints -function has_derivative_constraints(pref::IndependentParameterRef)::Bool +function has_derivative_constraints(pref::IndependentParameterRef) return _data_object(pref).has_deriv_constrs end # Make update function for whether it has derivative supports -function _set_has_derivative_constraints(pref::IndependentParameterRef, - status::Bool)::Nothing +function _set_has_derivative_constraints(pref::IndependentParameterRef, status::Bool) _data_object(pref).has_deriv_constrs = status return end @@ -779,13 +773,14 @@ julia> derivative_method(pref) FiniteDifference(Backward, true) ``` """ -function derivative_method(pref::IndependentParameterRef)::AbstractDerivativeMethod - return _core_variable_object(pref).derivative_method +function derivative_method(pref::IndependentParameterRef) + return core_object(pref).derivative_method end # Make method to reset derivative constraints (supports are handled separately) -function _reset_derivative_constraints(pref::Union{IndependentParameterRef, - DependentParameterRef})::Nothing +function _reset_derivative_constraints( + pref::Union{IndependentParameterRef, DependentParameterRef} + ) if has_derivative_constraints(pref) @warn("Support/method changes will invalidate existing derivative evaluation " * "constraints that have been added to the InfiniteModel. Thus, " * @@ -815,10 +810,11 @@ julia> set_derivative_method(d, OrthogonalCollocation(2)) ``` """ -function set_derivative_method(pref::IndependentParameterRef, +function set_derivative_method( + pref::IndependentParameterRef, method::NonGenerativeDerivativeMethod - )::Nothing - old_param = _core_variable_object(pref) + ) + old_param = core_object(pref) domain = _parameter_domain(pref) supps = _parameter_supports(pref) sig_figs = significant_digits(pref) @@ -831,7 +827,7 @@ function set_derivative_method(pref::IndependentParameterRef, new_param = IndependentParameter(domain, supps, sig_figs, method, info) end _reset_derivative_constraints(pref) - _set_core_variable_object(pref, new_param) + _set_core_object(pref, new_param) if is_used(pref) set_transformation_backend_ready(JuMP.owner_model(pref), false) end @@ -839,23 +835,24 @@ function set_derivative_method(pref::IndependentParameterRef, end # GenerativeDerivativeMethod -function set_derivative_method(pref::IndependentParameterRef, +function set_derivative_method( + pref::IndependentParameterRef, method::GenerativeDerivativeMethod - )::Nothing + ) new_info = generative_support_info(method) old_info = generative_support_info(pref) if !isempty(_generative_measures(pref)) && new_info != old_info error("Generative derivative method conflicts with existing generative " * "measures.") end - old_param = _core_variable_object(pref) + old_param = core_object(pref) domain = _parameter_domain(pref) supps = _parameter_supports(pref) sig_figs = significant_digits(pref) new_param = IndependentParameter(domain, supps, sig_figs, method, new_info) _reset_derivative_constraints(pref) _reset_generative_supports(pref) - _set_core_variable_object(pref, new_param) + _set_core_object(pref, new_param) if is_used(pref) set_transformation_backend_ready(JuMP.owner_model(pref), false) end @@ -863,21 +860,23 @@ function set_derivative_method(pref::IndependentParameterRef, end ################################################################################ -# SET FUNCTIONS +# INFINITE DOMAIN FUNCTIONS ################################################################################ # Internal functions -function _parameter_domain(pref::IndependentParameterRef)::InfiniteScalarDomain - return _core_variable_object(pref).domain +function _parameter_domain(pref::IndependentParameterRef) + return core_object(pref).domain end -function _update_parameter_domain(pref::IndependentParameterRef, - domain::AbstractInfiniteDomain)::Nothing +function _update_parameter_domain( + pref::IndependentParameterRef, + domain::AbstractInfiniteDomain + ) # old supports will always be discarded sig_digits = significant_digits(pref) method = derivative_method(pref) info = generative_support_info(pref) new_param = IndependentParameter(domain, DataStructures.SortedDict{Float64, Set{DataType}}(), sig_digits, method, info) - _set_core_variable_object(pref, new_param) + _set_core_object(pref, new_param) _reset_derivative_constraints(pref) _set_has_generative_supports(pref, false) _set_has_internal_supports(pref, false) @@ -898,7 +897,7 @@ julia> infinite_domain(t) [0, 1] ``` """ -function infinite_domain(pref::IndependentParameterRef)::InfiniteScalarDomain +function infinite_domain(pref::IndependentParameterRef) return _parameter_domain(pref) end @@ -917,8 +916,10 @@ julia> infinite_domain(t) [0, 2] ``` """ -function set_infinite_domain(pref::IndependentParameterRef, - domain::InfiniteScalarDomain)::Nothing +function set_infinite_domain( + pref::IndependentParameterRef, + domain::InfiniteScalarDomain + ) if used_by_measure(pref) error("$pref is used by a measure so changing its " * "infinite domain is not allowed.") @@ -944,7 +945,7 @@ julia> has_lower_bound(t) true ``` """ -function JuMP.has_lower_bound(pref::IndependentParameterRef)::Bool +function JuMP.has_lower_bound(pref::IndependentParameterRef) domain = _parameter_domain(pref) return JuMP.has_lower_bound(domain) end @@ -962,7 +963,7 @@ julia> lower_bound(t) 0.0 ``` """ -function JuMP.lower_bound(pref::IndependentParameterRef)::Real +function JuMP.lower_bound(pref::IndependentParameterRef) domain = _parameter_domain(pref) if !JuMP.has_lower_bound(pref) error("Parameter $(pref) does not have a lower bound.") @@ -986,7 +987,7 @@ julia> lower_bound(t) -1.0 ``` """ -function JuMP.set_lower_bound(pref::IndependentParameterRef, lower::Real)::Nothing +function JuMP.set_lower_bound(pref::IndependentParameterRef, lower::Real) domain = _parameter_domain(pref) new_domain = JuMP.set_lower_bound(domain, lower) _update_parameter_domain(pref, new_domain) @@ -1007,7 +1008,7 @@ julia> has_upper_bound(t) true ``` """ -function JuMP.has_upper_bound(pref::IndependentParameterRef)::Bool +function JuMP.has_upper_bound(pref::IndependentParameterRef) domain = _parameter_domain(pref) return JuMP.has_upper_bound(domain) end @@ -1027,7 +1028,7 @@ julia> upper_bound(t) 1.0 ``` """ -function JuMP.upper_bound(pref::IndependentParameterRef)::Real +function JuMP.upper_bound(pref::IndependentParameterRef) domain = _parameter_domain(pref) if !JuMP.has_upper_bound(pref) error("Parameter $(pref) does not have a upper bound.") @@ -1051,7 +1052,7 @@ julia> upper_bound(t) 2.0 ``` """ -function JuMP.set_upper_bound(pref::IndependentParameterRef, upper::Real)::Nothing +function JuMP.set_upper_bound(pref::IndependentParameterRef, upper::Real) domain = _parameter_domain(pref) new_domain = JuMP.set_upper_bound(domain, upper) _update_parameter_domain(pref, new_domain) @@ -1063,19 +1064,21 @@ end ################################################################################ # Internal functions function _parameter_supports(pref::IndependentParameterRef) - return _core_variable_object(pref).supports + return core_object(pref).supports end -function _parameter_support_values(pref::IndependentParameterRef)::Vector{Float64} +function _parameter_support_values(pref::IndependentParameterRef) return collect(keys(_parameter_supports(pref))) end -function _update_parameter_supports(pref::IndependentParameterRef, - supports::DataStructures.SortedDict{Float64, Set{DataType}})::Nothing +function _update_parameter_supports( + pref::IndependentParameterRef, + supports::DataStructures.SortedDict{Float64, Set{DataType}} + ) domain = _parameter_domain(pref) method = derivative_method(pref) sig_figs = significant_digits(pref) info = generative_support_info(pref) new_param = IndependentParameter(domain, supports, sig_figs, method, info) - _set_core_variable_object(pref, new_param) + _set_core_object(pref, new_param) _reset_derivative_constraints(pref) _set_has_generative_supports(pref, false) if is_used(pref) @@ -1092,7 +1095,7 @@ default. """ function has_internal_supports( pref::Union{IndependentParameterRef, DependentParameterRef} - )::Bool + ) return _data_object(pref).has_internal_supports end @@ -1100,7 +1103,7 @@ end function _set_has_internal_supports( pref::Union{IndependentParameterRef, DependentParameterRef}, status::Bool - )::Nothing + ) _data_object(pref).has_internal_supports = status return end @@ -1116,8 +1119,8 @@ julia> significant_digits(t) 12 ``` """ -function significant_digits(pref::IndependentParameterRef)::Int - return _core_variable_object(pref).sig_digits +function significant_digits(pref::IndependentParameterRef) + return core_object(pref).sig_digits end """ @@ -1135,8 +1138,10 @@ julia> num_supports(t) 2 ``` """ -function num_supports(pref::IndependentParameterRef; - label::Type{<:AbstractSupportLabel} = PublicLabel)::Int +function num_supports( + pref::IndependentParameterRef; + label::Type{<:AbstractSupportLabel} = PublicLabel + ) supports_dict = _parameter_supports(pref) if label == All || (!has_internal_supports(pref) && label == PublicLabel) return length(supports_dict) @@ -1156,7 +1161,7 @@ julia> has_supports(t) true ``` """ -has_supports(pref::IndependentParameterRef)::Bool = !isempty(_parameter_supports(pref)) +has_supports(pref::IndependentParameterRef) = !isempty(_parameter_supports(pref)) """ supports(pref::IndependentParameterRef; @@ -1177,8 +1182,10 @@ julia> supports(t) 1.0 ``` """ -function supports(pref::IndependentParameterRef; - label::Type{<:AbstractSupportLabel} = PublicLabel)::Vector{Float64} +function supports( + pref::IndependentParameterRef; + label::Type{<:AbstractSupportLabel} = PublicLabel + ) if label == All || (!has_internal_supports(pref) && label == PublicLabel) return _parameter_support_values(pref) else @@ -1187,9 +1194,11 @@ function supports(pref::IndependentParameterRef; end # Return a matrix os supports when given a vector of IndependentParameterRefs (for measures) -function supports(prefs::Vector{IndependentParameterRef}; - label::Type{<:AbstractSupportLabel} = PublicLabel, - use_combinatorics::Bool = true)::Matrix{Float64} +function supports( + prefs::Vector{IndependentParameterRef}; + label::Type{<:AbstractSupportLabel} = PublicLabel, + use_combinatorics::Bool = true + ) # generate the support matrix considering all the unique combinations if use_combinatorics supp_list = Tuple(supports(p, label = label) for p in prefs) @@ -1238,10 +1247,12 @@ julia> supports(t) 1 ``` """ -function set_supports(pref::IndependentParameterRef, supports::Vector{<:Real}; - force::Bool = false, - label::Type{<:AbstractSupportLabel} = UserDefined - )::Nothing +function set_supports( + pref::IndependentParameterRef, + supports::Vector{<:Real}; + force::Bool = false, + label::Type{<:AbstractSupportLabel} = UserDefined + ) if has_supports(pref) && !force error("Unable set supports for $pref since it already has supports." * " Consider using `add_supports` or use `force = true` to " * @@ -1287,10 +1298,11 @@ julia> supports(t) 1.0 ``` """ -function add_supports(pref::IndependentParameterRef, - supports::Union{Real, Vector{<:Real}}; - label::Type{<:AbstractSupportLabel} = UserDefined, - check::Bool = true)::Nothing +function add_supports( + pref::IndependentParameterRef, + supports::Union{Real, Vector{<:Real}}; + label::Type{<:AbstractSupportLabel} = UserDefined, + check::Bool = true) domain = infinite_domain(pref) supports = round.(supports, sigdigits = significant_digits(pref)) check && _check_supports_in_bounds(error, supports, domain) @@ -1332,8 +1344,10 @@ julia> supports(t) ERROR: Parameter t does not have supports. ``` """ -function delete_supports(pref::IndependentParameterRef; - label::Type{<:AbstractSupportLabel} = All)::Nothing +function delete_supports( + pref::IndependentParameterRef; + label::Type{<:AbstractSupportLabel} = All + ) supp_dict = _parameter_supports(pref) if has_derivative_constraints(pref) @warn("Deleting supports invalidated derivative evaluations. Thus, these " * @@ -1371,8 +1385,10 @@ function delete_supports(pref::IndependentParameterRef; end # Make dispatch for an array of parameters -function delete_supports(prefs::AbstractArray{<:IndependentParameterRef}; - label::Type{<:AbstractSupportLabel} = All)::Nothing +function delete_supports( + prefs::AbstractArray{<:IndependentParameterRef}; + label::Type{<:AbstractSupportLabel} = All + ) delete_supports.(prefs, label = label) return end @@ -1389,8 +1405,8 @@ julia> value(cost) 42.0 ``` """ -function parameter_value(pref::FiniteParameterRef)::Real - return _core_variable_object(pref).value +function parameter_value(pref::FiniteParameterRef) + return core_object(pref).value end """ @@ -1407,7 +1423,7 @@ julia> value(cost) 27.0 ``` """ -function JuMP.set_value(pref::FiniteParameterRef, value::Real)::Nothing +function JuMP.set_value(pref::FiniteParameterRef, value::Real) _data_object(pref).parameter = FiniteParameter(value) if is_used(pref) set_transformation_backend_ready(JuMP.owner_model(pref), false) @@ -1441,9 +1457,11 @@ julia> supports(x) ``` """ -function fill_in_supports!(pref::IndependentParameterRef; - num_supports::Int = DefaultNumSupports, - modify::Bool = true)::Nothing +function fill_in_supports!( + pref::IndependentParameterRef; + num_supports::Int = DefaultNumSupports, + modify::Bool = true + ) domain = infinite_domain(pref) current_amount = length(_parameter_supports(pref)) if (modify || current_amount == 0) && current_amount < num_supports @@ -1467,10 +1485,11 @@ Most extensions that empoy user-defined infinite domains can typically enable th by extending [`generate_support_values`](@ref). Errors if the infinite domain type is not recognized. """ -function generate_and_add_supports!(pref::IndependentParameterRef, - domain::AbstractInfiniteDomain; - num_supports::Int = DefaultNumSupports, - adding_extra::Bool = false)::Nothing +function generate_and_add_supports!( + pref::IndependentParameterRef, + domain::AbstractInfiniteDomain; + num_supports::Int = DefaultNumSupports, + adding_extra::Bool = false) sig_digits = significant_digits(pref) if isa(domain, IntervalDomain) && adding_extra supports, label = generate_support_values(domain, MCSample, @@ -1486,11 +1505,12 @@ function generate_and_add_supports!(pref::IndependentParameterRef, end # Dispatch with method -function generate_and_add_supports!(pref::IndependentParameterRef, - domain::AbstractInfiniteDomain, - method::Type{<:AbstractSupportLabel}; - num_supports::Int = DefaultNumSupports, - adding_extra::Bool = false)::Nothing +function generate_and_add_supports!( + pref::IndependentParameterRef, + domain::AbstractInfiniteDomain, + method::Type{<:AbstractSupportLabel}; + num_supports::Int = DefaultNumSupports, + adding_extra::Bool = false) sig_digits = significant_digits(pref) supports, label = generate_supports(domain, method, num_supports = num_supports, @@ -1504,8 +1524,7 @@ end ################################################################################ # Check if parameter is used by measure data and error if it is to prevent bad # deleting behavior -function _check_param_in_data(pref::GeneralVariableRef, - data::AbstractMeasureData)::Nothing +function _check_param_in_data(pref::GeneralVariableRef, data::AbstractMeasureData) prefs = parameter_refs(data) if isequal(pref, prefs) || any(isequal(pref), prefs) error("Unable to delete `$pref` since it is used to evaluate measures.") @@ -1514,8 +1533,7 @@ function _check_param_in_data(pref::GeneralVariableRef, end # Update the dependent measures -function _update_measures(model::InfiniteModel, - pref::GeneralVariableRef)::Nothing +function _update_measures(model::InfiniteModel, pref::GeneralVariableRef) for mindex in _measure_dependencies(pref) mref = dispatch_variable_ref(model, mindex) func = measure_function(mref) @@ -1523,7 +1541,7 @@ function _update_measures(model::InfiniteModel, data = measure_data(mref) new_func = zero(JuMP.GenericAffExpr{Float64, GeneralVariableRef}) new_meas = Measure(new_func, data, Int[], Int[], true) - _set_core_variable_object(mref, new_meas) + _set_core_object(mref, new_meas) else _remove_variable(func, pref) end @@ -1532,17 +1550,16 @@ function _update_measures(model::InfiniteModel, end # Update the dependent constraints -function _update_constraints(model::InfiniteModel, - pref::GeneralVariableRef)::Nothing +function _update_constraints(model::InfiniteModel, pref::GeneralVariableRef) for cindex in copy(_constraint_dependencies(pref)) - cref = _make_constraint_ref(model, cindex) + cref = InfOptConstraintRef(model, cindex) func = JuMP.jump_function(JuMP.constraint_object(cref)) if func isa GeneralVariableRef set = JuMP.moi_set(JuMP.constraint_object(cref)) new_func = zero(JuMP.GenericAffExpr{Float64, GeneralVariableRef}) new_constr = JuMP.ScalarConstraint(new_func, set) - _set_core_constraint_object(cref, new_constr) - empty!(_object_numbers(cref)) + _set_core_object(cref, new_constr) + empty!(parameter_group_int_indices(cref)) elseif func isa AbstractArray && any(isequal(pref), func) JuMP.delete(model, cref) else @@ -1553,7 +1570,7 @@ function _update_constraints(model::InfiniteModel, end # Remove given object/parameter number and update the list -function _update_number_list(nums::Vector{Int}, list::Vector{Int})::Nothing +function _update_number_list(nums::Vector{Int}, list::Vector{Int}) filter!(e -> !(e in nums), list) max_num = maximum(nums) for i in eachindex(list) @@ -1564,49 +1581,52 @@ function _update_number_list(nums::Vector{Int}, list::Vector{Int})::Nothing return end -# Update the model with the removed parameter/object numbers -function _update_model_numbers(model::InfiniteModel, obj_num::Int, - param_nums::Vector{Int})::Nothing +# Update the model with the removed parameter number(s) and parameter group index +function _update_model_numbers( + model::InfiniteModel, + group_int_idx::Int, + param_nums::Vector{Int} + ) # update the independent parameters for (_, object) in _data_dictionary(model, IndependentParameter) - if object.object_num > obj_num - object.object_num -= 1 + if object.group_int_idx > group_int_idx + object.group_int_idx -= 1 object.parameter_num -= length(param_nums) end end # update the dependent parameters for (_, object) in _data_dictionary(model, DependentParameters) - if object.object_num > obj_num - object.object_num -= 1 + if object.group_int_idx > group_int_idx + object.group_int_idx -= 1 object.parameter_nums = object.parameter_nums .- length(param_nums) end end # update the infinite parameter functions for (_, object) in model.param_functions - _update_number_list([obj_num], object.func.object_nums) + _update_number_list([group_int_idx], object.func.group_int_idxs) _update_number_list(param_nums, object.func.parameter_nums) end # update the infinite variables for vref in JuMP.all_variables(model, InfiniteVariable) - _update_number_list([obj_num], _object_numbers(vref)) + _update_number_list([group_int_idx], parameter_group_int_indices(vref)) _update_number_list(param_nums, _parameter_numbers(vref)) end # update the semi-infinite variables for vref in JuMP.all_variables(model, SemiInfiniteVariable) - _update_number_list([obj_num], _object_numbers(vref)) + _update_number_list([group_int_idx], parameter_group_int_indices(vref)) _update_number_list(param_nums, _parameter_numbers(vref)) end # update the measures for mref in all_measures(model) - _update_number_list([obj_num], _object_numbers(mref)) + _update_number_list([group_int_idx], parameter_group_int_indices(mref)) _update_number_list(param_nums, _parameter_numbers(mref)) end # update the constraints for (_, object) in model.constraints - _update_number_list([obj_num], object.object_nums) + _update_number_list([group_int_idx], object.group_int_idxs) end # update the central info - deleteat!(_param_object_indices(model), obj_num) + deleteat!(parameter_group_indices(model), group_int_idx) model.last_param_num -= length(param_nums) return end @@ -1630,12 +1650,9 @@ datatypes are used. julia> delete(model, x) ``` """ -function JuMP.delete( - model::InfiniteModel, - pref::IndependentParameterRef - )::Nothing +function JuMP.delete(model::InfiniteModel, pref::IndependentParameterRef) @assert JuMP.is_valid(model, pref) "Parameter reference is invalid." - gvref = _make_parameter_ref(JuMP.owner_model(pref), JuMP.index(pref)) + gvref = GeneralVariableRef(JuMP.owner_model(pref), JuMP.index(pref)) # ensure deletion is okay (pref isn't used by measure data) for mindex in _measure_dependencies(pref) data = measure_data(dispatch_variable_ref(model, mindex)) @@ -1664,22 +1681,22 @@ function JuMP.delete( # update constraints in mapping to remove the parameter _update_constraints(model, gvref) # delete parameter information stored in model - obj_num = _object_number(pref) + group_int_idx = parameter_group_int_index(pref) param_nums = _parameter_numbers(pref) _delete_data_object(pref) - # update the object numbers and parameter numbers - _update_model_numbers(model, obj_num, param_nums) + # update the parameter group integer indices and parameter numbers + _update_model_numbers(model, group_int_idx, param_nums) return end # FiniteParameterRef -function JuMP.delete(model::InfiniteModel, pref::FiniteParameterRef)::Nothing +function JuMP.delete(model::InfiniteModel, pref::FiniteParameterRef) @assert JuMP.is_valid(model, pref) "Parameter reference is invalid." # update transformation backend status if is_used(pref) set_transformation_backend_ready(model, false) end - gvref = _make_parameter_ref(model, JuMP.index(pref)) + gvref = GeneralVariableRef(model, JuMP.index(pref)) # delete dependence of measures on pref _update_measures(model, gvref) # update constraints in mapping to remove the parameter diff --git a/src/semi_infinite_variables.jl b/src/semi_infinite_variables.jl index 1d6076bd..51a8aa5d 100644 --- a/src/semi_infinite_variables.jl +++ b/src/semi_infinite_variables.jl @@ -58,8 +58,13 @@ with `expand_measure`. """ function internal_semi_infinite_variable end -# Extend _core_variable_object -function _core_variable_object(vref::SemiInfiniteVariableRef) +""" + core_object(vref::SemiInfiniteVariableRef)::SemiInfiniteVariable + +Retrieve the underlying core [`SemiInfiniteVariable`] object for `vref`. +This is intended as an advanced method for developers. +""" +function core_object(vref::SemiInfiniteVariableRef) if !haskey(_data_dictionary(vref), JuMP.index(vref)) model = JuMP.owner_model(vref) return internal_semi_infinite_variable(vref, model.backend) @@ -68,14 +73,18 @@ function _core_variable_object(vref::SemiInfiniteVariableRef) end end -# Extend _object_numbers -function _object_numbers(vref::SemiInfiniteVariableRef)::Vector{Int} - return _core_variable_object(vref).object_nums +""" + parameter_group_int_indices(vref::SemiInfiniteVariableRef)::Vector{Int} + +Return the list of infinite parameter group integer indices used by `vref`. +""" +function parameter_group_int_indices(vref::SemiInfiniteVariableRef) + return core_object(vref).group_int_idxs end # Extend _parameter_numbers -function _parameter_numbers(vref::SemiInfiniteVariableRef)::Vector{Int} - return _core_variable_object(vref).parameter_nums +function _parameter_numbers(vref::SemiInfiniteVariableRef) + return core_object(vref).parameter_nums end ################################################################################ @@ -230,11 +239,11 @@ function JuMP.build_variable( end end end - # get the parameter object numbers of the dependencies - object_nums = Int[] + # get the parameter group integer indices of the dependencies + group_int_idxs = Int[] for i in eachindex(prefs) if !haskey(eval_supports, i) - union!(object_nums, _object_number(prefs[i])) + union!(group_int_idxs, parameter_group_int_index(prefs[i])) end end # get the parameter numbers @@ -246,7 +255,7 @@ function JuMP.build_variable( eval_supports[k] = round(v, sigdigits = significant_digits(prefs[k])) end # build the variable - return SemiInfiniteVariable(ivref, eval_supports, param_nums, object_nums) + return SemiInfiniteVariable(ivref, eval_supports, param_nums, group_int_idxs) end ## Make dispatch functions to add semi-infinite variable based supports @@ -338,7 +347,7 @@ function JuMP.add_variable( model.semi_infinite_vars[vindex].name = name end end - return _make_variable_ref(model, vindex) + return GeneralVariableRef(model, vindex) end ################################################################################ @@ -357,7 +366,7 @@ g(t, x) ``` """ function infinite_variable_ref(vref::SemiInfiniteVariableRef)::GeneralVariableRef - return _core_variable_object(vref).infinite_variable_ref + return core_object(vref).infinite_variable_ref end """ @@ -374,7 +383,7 @@ Dict{Int64,Float64} with 1 entry: ``` """ function eval_supports(vref::SemiInfiniteVariableRef)::Dict{Int, Float64} - return _core_variable_object(vref).eval_supports + return core_object(vref).eval_supports end """ diff --git a/src/show.jl b/src/show.jl index cc64f08c..679a08be 100644 --- a/src/show.jl +++ b/src/show.jl @@ -644,11 +644,11 @@ function JuMP.constraint_string(print_mode, in_math_mode = false ) # get the function and set strings - func_str = JuMP.function_string(print_mode, _core_constraint_object(cref)) - in_set_str = JuMP.in_set_string(print_mode, _core_constraint_object(cref)) + func_str = JuMP.function_string(print_mode, JuMP.constraint_object(cref)) + in_set_str = JuMP.in_set_string(print_mode, JuMP.constraint_object(cref)) # check if constraint if finite - obj_nums = _object_numbers(cref) - if isempty(obj_nums) + group_int_idxs = parameter_group_int_indices(cref) + if isempty(group_int_idxs) bound_str = "" else # get the parameter restrictions if there are any @@ -656,7 +656,7 @@ function JuMP.constraint_string(print_mode, # prepare the parameter domains model = JuMP.owner_model(cref) bound_str = string(", ", _math_symbol(print_mode, :for_all), " ") - for index in _param_object_indices(model)[_object_numbers(cref)] + for index in parameter_group_indices(model)[parameter_group_int_indices(cref)] bound_str *= string(_param_domain_string(print_mode, model, index, restrictions), ", ") end @@ -690,7 +690,7 @@ function JuMP.constraints_string(print_mode, model::InfiniteModel)::Vector{Strin # produce a string for each constraint counter = 1 for (index, object) in model.constraints - cref = _make_constraint_ref(model, index) + cref = InfOptConstraintRef(model, index) strings[counter] = JuMP.constraint_string(print_mode, cref, in_math_mode = true) counter += 1 diff --git a/src/variable_basics.jl b/src/variable_basics.jl index 11c2b3de..ce0d9c50 100644 --- a/src/variable_basics.jl +++ b/src/variable_basics.jl @@ -185,14 +185,6 @@ function JuMP.set_name(vref::DecisionVariableRef, name::String)::Nothing return end -# Make a variable reference -function _make_variable_ref( - model::InfiniteModel, - index::ObjectIndex - )::GeneralVariableRef - return GeneralVariableRef(model, index.value, typeof(index)) -end - # Get the name_to_var Dictionary function _var_name_dict( model::InfiniteModel @@ -252,7 +244,7 @@ function JuMP.variable_by_name( elseif index == FiniteVariableIndex(-1) error("Multiple variables have the name $name.") else - return _make_variable_ref(model, index) + return GeneralVariableRef(model, index) end end @@ -260,19 +252,16 @@ end # PARAMETER REFERENCES ################################################################################ # Extend parameter_refs for variables (this serves as a fallback for finite types) -function parameter_refs(vref::FiniteRef)::Tuple +function parameter_refs(vref::FiniteRef) return () end ################################################################################ # VARIABLE OBJECT MODIFICATION ################################################################################ -# Extend _set_core_variable_object -function _set_core_variable_object( - vref::DecisionVariableRef, - object::JuMP.AbstractVariable - )::Nothing - _data_object(vref).variable = object +# Extend _set_core_object +function _set_core_object(vref::DecisionVariableRef, obj::JuMP.AbstractVariable) + _data_object(vref).variable = obj return end @@ -280,8 +269,8 @@ end # VARIABLE INFO METHODS ################################################################################ # Get info -function _variable_info(vref::UserDecisionVariableRef)::JuMP.VariableInfo - return _core_variable_object(vref).info +function _variable_info(vref::UserDecisionVariableRef) + return core_object(vref).info end """ @@ -296,7 +285,7 @@ julia> has_lower_bound(vref) true ``` """ -function JuMP.has_lower_bound(vref::UserDecisionVariableRef)::Bool +function JuMP.has_lower_bound(vref::UserDecisionVariableRef) return _variable_info(vref).has_lb end @@ -312,7 +301,7 @@ julia> lower_bound(vref) 0.0 ``` """ -function JuMP.lower_bound(vref::UserDecisionVariableRef)::Float64 +function JuMP.lower_bound(vref::UserDecisionVariableRef) if !JuMP.has_lower_bound(vref) error("Variable $(vref) does not have a lower bound.") end @@ -331,7 +320,7 @@ end function _set_lower_bound_index( vref::UserDecisionVariableRef, cindex::Union{InfOptConstraintIndex, Nothing} - )::Nothing + ) _data_object(vref).lower_bound_index = cindex return end @@ -350,18 +339,15 @@ julia> lower_bound(vref) -1.0 ``` """ -function JuMP.set_lower_bound( - vref::UserDecisionVariableRef, - lower::Real - )::Nothing +function JuMP.set_lower_bound(vref::UserDecisionVariableRef, lower::Real) newset = MOI.GreaterThan(convert(Float64, lower)) model = JuMP.owner_model(vref) - gvref = _make_variable_ref(model, JuMP.index(vref)) + gvref = GeneralVariableRef(model, JuMP.index(vref)) new_constr = JuMP.ScalarConstraint(gvref, newset) if JuMP.has_lower_bound(vref) cindex = _lower_bound_index(vref) - cref = _make_constraint_ref(model, cindex) - _set_core_constraint_object(cref, new_constr) + cref = InfOptConstraintRef(model, cindex) + _set_core_object(cref, new_constr) set_transformation_backend_ready(model, false) else @assert !JuMP.is_fixed(vref) "$vref is fixed, cannot set lower bound." @@ -388,10 +374,10 @@ bound of `vref`. var ≥ 0.0 ``` """ -function JuMP.LowerBoundRef(vref::UserDecisionVariableRef)::InfOptConstraintRef +function JuMP.LowerBoundRef(vref::UserDecisionVariableRef) cindex = _lower_bound_index(vref) model = JuMP.owner_model(vref) - return _make_constraint_ref(model, cindex) + return InfOptConstraintRef(model, cindex) end """ @@ -408,7 +394,7 @@ julia> has_lower_bound(vref) false ``` """ -function JuMP.delete_lower_bound(vref::UserDecisionVariableRef)::Nothing +function JuMP.delete_lower_bound(vref::UserDecisionVariableRef) JuMP.delete(JuMP.owner_model(vref), JuMP.LowerBoundRef(vref)) _set_lower_bound_index(vref, nothing) info = _variable_info(vref) @@ -432,7 +418,7 @@ julia> has_upper_bound(vref) true ``` """ -function JuMP.has_upper_bound(vref::UserDecisionVariableRef)::Bool +function JuMP.has_upper_bound(vref::UserDecisionVariableRef) return _variable_info(vref).has_ub end @@ -448,7 +434,7 @@ julia> upper_bound(vref) 0.0 ``` """ -function JuMP.upper_bound(vref::UserDecisionVariableRef)::Float64 +function JuMP.upper_bound(vref::UserDecisionVariableRef) if !JuMP.has_upper_bound(vref) error("Variable $(vref) does not have a upper bound.") end @@ -486,18 +472,15 @@ julia> upper_bound(vref) 1.0 ``` """ -function JuMP.set_upper_bound( - vref::UserDecisionVariableRef, - upper::Real - )::Nothing +function JuMP.set_upper_bound(vref::UserDecisionVariableRef, upper::Real) newset = MOI.LessThan(convert(Float64, upper)) model = JuMP.owner_model(vref) - gvref = _make_variable_ref(model, JuMP.index(vref)) + gvref = GeneralVariableRef(model, JuMP.index(vref)) new_constr = JuMP.ScalarConstraint(gvref, newset) if JuMP.has_upper_bound(vref) cindex = _upper_bound_index(vref) - cref = _make_constraint_ref(model, cindex) - _set_core_constraint_object(cref, new_constr) + cref = InfOptConstraintRef(model, cindex) + _set_core_object(cref, new_constr) set_transformation_backend_ready(model, false) else @assert !JuMP.is_fixed(vref) "$vref is fixed, cannot set upper bound." @@ -525,10 +508,10 @@ julia> cref = UpperBoundRef(vref) var ≤ 1.0 ``` """ -function JuMP.UpperBoundRef(vref::UserDecisionVariableRef)::InfOptConstraintRef +function JuMP.UpperBoundRef(vref::UserDecisionVariableRef) cindex = _upper_bound_index(vref) model = JuMP.owner_model(vref) - return _make_constraint_ref(model, cindex) + return InfOptConstraintRef(model, cindex) end """ @@ -545,7 +528,7 @@ julia> has_upper_bound(vref) false ``` """ -function JuMP.delete_upper_bound(vref::UserDecisionVariableRef)::Nothing +function JuMP.delete_upper_bound(vref::UserDecisionVariableRef) JuMP.delete(JuMP.owner_model(vref), JuMP.UpperBoundRef(vref)) _set_upper_bound_index(vref, nothing) info = _variable_info(vref) @@ -569,7 +552,7 @@ julia> is_fixed(vref) true ``` """ -JuMP.is_fixed(vref::UserDecisionVariableRef)::Bool = _variable_info(vref).has_fix +JuMP.is_fixed(vref::UserDecisionVariableRef) = _variable_info(vref).has_fix """ JuMP.fix_value(vref::UserDecisionVariableRef)::Float64 @@ -583,7 +566,7 @@ julia> fix_value(vref) 0.0 ``` """ -function JuMP.fix_value(vref::UserDecisionVariableRef)::Float64 +function JuMP.fix_value(vref::UserDecisionVariableRef) if !JuMP.is_fixed(vref) error("Variable $(vref) is not fixed.") end @@ -591,7 +574,7 @@ function JuMP.fix_value(vref::UserDecisionVariableRef)::Float64 end # Extend to return the index of the fix constraint associated with `vref`. -function _fix_index(vref::UserDecisionVariableRef)::InfOptConstraintIndex +function _fix_index(vref::UserDecisionVariableRef) if !JuMP.is_fixed(vref) error("Variable $(vref) is not fixed.") end @@ -602,7 +585,7 @@ end function _set_fix_index( vref::UserDecisionVariableRef, cindex::Union{InfOptConstraintIndex, Nothing} - )::Nothing + ) _data_object(vref).fix_index = cindex return end @@ -631,15 +614,15 @@ function JuMP.fix( vref::UserDecisionVariableRef, value::Real; force::Bool = false - )::Nothing + ) new_set = MOI.EqualTo(convert(Float64, value)) model = JuMP.owner_model(vref) - gvref = _make_variable_ref(model, JuMP.index(vref)) + gvref = GeneralVariableRef(model, JuMP.index(vref)) new_constr = JuMP.ScalarConstraint(gvref, new_set) if JuMP.is_fixed(vref) # Update existing fixing constraint. cindex = _fix_index(vref) - cref = _make_constraint_ref(model, cindex) - _set_core_constraint_object(cref, new_constr) + cref = InfOptConstraintRef(model, cindex) + _set_core_object(cref, new_constr) set_transformation_backend_ready(model, false) else # Add a new fixing constraint. if JuMP.has_upper_bound(vref) || JuMP.has_lower_bound(vref) @@ -680,10 +663,10 @@ julia> cref = FixRef(vref) var = 1.0 ``` """ -function JuMP.FixRef(vref::UserDecisionVariableRef)::InfOptConstraintRef +function JuMP.FixRef(vref::UserDecisionVariableRef) cindex = _fix_index(vref) model = JuMP.owner_model(vref) - return _make_constraint_ref(model, cindex) + return InfOptConstraintRef(model, cindex) end """ @@ -699,7 +682,7 @@ julia> is_fixed(vref) false ``` """ -function JuMP.unfix(vref::UserDecisionVariableRef)::Nothing +function JuMP.unfix(vref::UserDecisionVariableRef) JuMP.delete(JuMP.owner_model(vref), JuMP.FixRef(vref)) _set_fix_index(vref, nothing) info = _variable_info(vref) @@ -723,7 +706,7 @@ julia> start_value(vref) 0.0 ``` """ -function JuMP.start_value(vref::UserDecisionVariableRef)::Union{Nothing, Float64} +function JuMP.start_value(vref::UserDecisionVariableRef) if _variable_info(vref).has_start return _variable_info(vref).start else @@ -745,10 +728,7 @@ julia> start_value(vref) 1.0 ``` """ -function JuMP.set_start_value( - vref::UserDecisionVariableRef, - value::Real - )::Nothing +function JuMP.set_start_value(vref::UserDecisionVariableRef, value::Real) info = _variable_info(vref) set_transformation_backend_ready(JuMP.owner_model(vref), false) _update_variable_info(vref, @@ -771,7 +751,7 @@ binary. true ``` """ -JuMP.is_binary(vref::UserDecisionVariableRef)::Bool = _variable_info(vref).binary +JuMP.is_binary(vref::UserDecisionVariableRef) = _variable_info(vref).binary # Extend to return the index of the binary constraint associated with `vref`. function _binary_index(vref::UserDecisionVariableRef)::InfOptConstraintIndex @@ -785,7 +765,7 @@ end function _set_binary_index( vref::UserDecisionVariableRef, cindex::Union{InfOptConstraintIndex, Nothing} - )::Nothing + ) _data_object(vref).zero_one_index = cindex return end @@ -804,14 +784,14 @@ julia> is_binary(vref) true ``` """ -function JuMP.set_binary(vref::UserDecisionVariableRef)::Nothing +function JuMP.set_binary(vref::UserDecisionVariableRef) if JuMP.is_binary(vref) return elseif JuMP.is_integer(vref) error("Cannot set the variable_ref $(vref) to binary as it " * "is already integer.") end - gvref = _make_variable_ref(JuMP.owner_model(vref), JuMP.index(vref)) + gvref = GeneralVariableRef(JuMP.owner_model(vref), JuMP.index(vref)) cref = JuMP.add_constraint(JuMP.owner_model(vref), JuMP.ScalarConstraint(gvref, MOI.ZeroOne()), is_info_constr = true) @@ -837,10 +817,10 @@ julia> cref = BinaryRef(vref) var binary ``` """ -function JuMP.BinaryRef(vref::UserDecisionVariableRef)::InfOptConstraintRef +function JuMP.BinaryRef(vref::UserDecisionVariableRef) cindex = _binary_index(vref) model = JuMP.owner_model(vref) - return _make_constraint_ref(model, cindex) + return InfOptConstraintRef(model, cindex) end """ @@ -856,7 +836,7 @@ julia> is_binary(vref) false ``` """ -function JuMP.unset_binary(vref::UserDecisionVariableRef)::Nothing +function JuMP.unset_binary(vref::UserDecisionVariableRef) JuMP.delete(JuMP.owner_model(vref), JuMP.BinaryRef(vref)) _set_binary_index(vref, nothing) info = _variable_info(vref) @@ -880,12 +860,12 @@ julia> is_integer(vref) true ``` """ -function JuMP.is_integer(vref::UserDecisionVariableRef)::Bool +function JuMP.is_integer(vref::UserDecisionVariableRef) return _variable_info(vref).integer end # Extend to return the index of the integer constraintassociated with `vref`. -function _integer_index(vref::UserDecisionVariableRef)::InfOptConstraintIndex +function _integer_index(vref::UserDecisionVariableRef) if !JuMP.is_integer(vref) error("Variable $(vref) is not an integer.") end @@ -896,7 +876,7 @@ end function _set_integer_index( vref::UserDecisionVariableRef, cindex::Union{InfOptConstraintIndex, Nothing} - )::Nothing + ) _data_object(vref).integrality_index = cindex return end @@ -915,14 +895,14 @@ julia> is_integer(vref) true ``` """ -function JuMP.set_integer(vref::UserDecisionVariableRef)::Nothing +function JuMP.set_integer(vref::UserDecisionVariableRef) if JuMP.is_integer(vref) return elseif JuMP.is_binary(vref) error("Cannot set the variable_ref $(vref) to integer as it " * "is already binary.") end - gvref = _make_variable_ref(JuMP.owner_model(vref), JuMP.index(vref)) + gvref = GeneralVariableRef(JuMP.owner_model(vref), JuMP.index(vref)) cref = JuMP.add_constraint(JuMP.owner_model(vref), JuMP.ScalarConstraint(gvref, MOI.Integer()), is_info_constr = true) @@ -948,10 +928,10 @@ julia> cref = IntegerRef(vref) var integer ``` """ -function JuMP.IntegerRef(vref::UserDecisionVariableRef)::InfOptConstraintRef +function JuMP.IntegerRef(vref::UserDecisionVariableRef) cindex = _integer_index(vref) model = JuMP.owner_model(vref) - return _make_constraint_ref(model, cindex) + return InfOptConstraintRef(model, cindex) end """ @@ -967,7 +947,7 @@ julia> is_integer(vref) false ``` """ -function JuMP.unset_integer(vref::UserDecisionVariableRef)::Nothing +function JuMP.unset_integer(vref::UserDecisionVariableRef) JuMP.delete(JuMP.owner_model(vref), JuMP.IntegerRef(vref)) _set_integer_index(vref, nothing) info = _variable_info(vref) @@ -1007,7 +987,7 @@ julia> num_variables(model, InfiniteVariable) 2 ``` """ -function JuMP.num_variables(model::InfiniteModel)::Int +function JuMP.num_variables(model::InfiniteModel) num_vars = JuMP.num_variables(model, InfiniteVariable) num_vars += JuMP.num_variables(model, SemiInfiniteVariable) num_vars += JuMP.num_variables(model, PointVariable) @@ -1016,8 +996,7 @@ function JuMP.num_variables(model::InfiniteModel)::Int end # Particular variable types -function JuMP.num_variables(model::InfiniteModel, - type::Type{C})::Int where {C} +function JuMP.num_variables(model::InfiniteModel, type::Type{C}) where {C} return length(_data_dictionary(model, type)) end @@ -1047,7 +1026,7 @@ julia> all_variables(model, PointVariable) y(0) ``` """ -function JuMP.all_variables(model::InfiniteModel)::Vector{GeneralVariableRef} +function JuMP.all_variables(model::InfiniteModel) vrefs_list = JuMP.all_variables(model, InfiniteVariable) append!(vrefs_list, JuMP.all_variables(model, SemiInfiniteVariable)) append!(vrefs_list, JuMP.all_variables(model, PointVariable)) @@ -1056,12 +1035,10 @@ function JuMP.all_variables(model::InfiniteModel)::Vector{GeneralVariableRef} end # Particular variable types -function JuMP.all_variables(model::InfiniteModel, - type::Type{C} - )::Vector{GeneralVariableRef} where {C} +function JuMP.all_variables(model::InfiniteModel, type::Type{C}) where {C} vrefs_list = Vector{GeneralVariableRef}(undef, JuMP.num_variables(model, type)) for (i, (index, _)) in enumerate(_data_dictionary(model, type)) - vrefs_list[i] = _make_variable_ref(model, index) + vrefs_list[i] = GeneralVariableRef(model, index) end return vrefs_list end @@ -1070,7 +1047,7 @@ end # DELETION ################################################################################ # Helper function to delete the info constraints -function _delete_info_constraints(vref::UserDecisionVariableRef)::Nothing +function _delete_info_constraints(vref::UserDecisionVariableRef) # remove variable info constraints associated with vref if JuMP.has_lower_bound(vref) JuMP.delete_lower_bound(vref) @@ -1114,7 +1091,7 @@ Subject to z ≥ 42.0 ``` """ -function JuMP.delete(model::InfiniteModel, vref::DecisionVariableRef)::Nothing +function JuMP.delete(model::InfiniteModel, vref::DecisionVariableRef) @assert JuMP.is_valid(model, vref) "Variable is invalid." # update the transformation backend status if is_used(vref) @@ -1122,7 +1099,7 @@ function JuMP.delete(model::InfiniteModel, vref::DecisionVariableRef)::Nothing end # delete attributes specific to the variable type _delete_variable_dependencies(vref) - gvref = _make_variable_ref(model, JuMP.index(vref)) + gvref = GeneralVariableRef(model, JuMP.index(vref)) # remove from measures if used for mindex in _measure_dependencies(vref) mref = dispatch_variable_ref(model, mindex) @@ -1135,25 +1112,25 @@ function JuMP.delete(model::InfiniteModel, vref::DecisionVariableRef)::Nothing _remove_variable(func, gvref) new_meas = build_measure(func, data) end - _set_core_variable_object(mref, new_meas) + _set_core_object(mref, new_meas) end # remove from constraints if used for cindex in copy(_constraint_dependencies(vref)) # copy in case a constraint is deleted - cref = _make_constraint_ref(model, cindex) + cref = InfOptConstraintRef(model, cindex) func = JuMP.jump_function(JuMP.constraint_object(cref)) if func isa GeneralVariableRef set = JuMP.moi_set(JuMP.constraint_object(cref)) new_func = zero(JuMP.GenericAffExpr{Float64, GeneralVariableRef}) new_constr = JuMP.ScalarConstraint(new_func, set) - _set_core_constraint_object(cref, new_constr) - empty!(_object_numbers(cref)) + _set_core_object(cref, new_constr) + empty!(parameter_group_int_indices(cref)) elseif func isa AbstractArray && any(isequal(gvref), func) JuMP.delete(model, cref) else _remove_variable(func, gvref) - # update the object numbers if vref is infinite + # update the parameter group integer indices if vref is infinite if vref isa Union{InfiniteVariableRef, SemiInfiniteVariableRef, DerivativeRef} - _data_object(cref).object_nums = sort(_object_numbers(func)) + _data_object(cref).group_int_idxs = sort(parameter_group_int_indices(func)) end end end diff --git a/test/MeasureToolbox/expectations.jl b/test/MeasureToolbox/expectations.jl index 175a99b7..14543cd1 100644 --- a/test/MeasureToolbox/expectations.jl +++ b/test/MeasureToolbox/expectations.jl @@ -49,7 +49,7 @@ end warn = "Cannot specify a nonzero `num_supports` for individual " * "dependent parameters." @test_logs (:warn, warn) expect(inf, xi[1], num_supports = 3) - @test !InfiniteOpt._is_expect(InfiniteOpt._core_variable_object(expect(inf, y)).data) + @test !InfiniteOpt._is_expect(core_object(expect(inf, y)).data) @test 𝔼(inf, x) isa GeneralVariableRef # test with new pdf diff --git a/test/TranscriptionOpt/model.jl b/test/TranscriptionOpt/model.jl index 7117c377..fe669a25 100644 --- a/test/TranscriptionOpt/model.jl +++ b/test/TranscriptionOpt/model.jl @@ -72,11 +72,11 @@ end @testset "_get_array_type" begin @test IOTO._get_array_type(ones(Bool, 2)) == Bool end - # test _get_object_numbers - @testset "_get_object_numbers" begin - @test IOTO._get_object_numbers(x) == [1, 2] - @test IOTO._get_object_numbers(y) == [] - @test IOTO._get_object_numbers(y + x) == [1, 2] + # test _getparameter_group_int_indices + @testset "_getparameter_group_int_indices" begin + @test IOTO._getparameter_group_int_indices(x) == [1, 2] + @test IOTO._getparameter_group_int_indices(y) == [] + @test IOTO._getparameter_group_int_indices(y + x) == [1, 2] end # test make_ndarray @testset "make_ndarray" begin diff --git a/test/TranscriptionOpt/transcribe.jl b/test/TranscriptionOpt/transcribe.jl index 684e1ed8..8f8728b6 100644 --- a/test/TranscriptionOpt/transcribe.jl +++ b/test/TranscriptionOpt/transcribe.jl @@ -40,7 +40,7 @@ end # test _format_infinite_info @testset "_format_infinite_info" begin - var = InfiniteOpt._core_variable_object(y) + var = core_object(y) @test !IOTO._format_infinite_info(var, [0., 0.5, 0.75]).has_lb @test !IOTO._format_infinite_info(var, [0., 0.5, 0.75]).has_ub @test IOTO._format_infinite_info(var, [0., 0.5, 0.75]).has_fix @@ -49,7 +49,7 @@ @test IOTO._format_infinite_info(var, [0., 0.5, 0.75]).start == 1.25 @test IOTO._format_infinite_info(var, [0., 0.5, 0.75]).binary @test !IOTO._format_infinite_info(var, [0., 0.5, 0.75]).integer - var = InfiniteOpt._core_variable_object(x) + var = core_object(x) @test IOTO._format_infinite_info(var, [0.]).has_lb @test IOTO._format_infinite_info(var, [0.]).lower_bound == 0 @test !IOTO._format_infinite_info(var, [0.]).has_ub @@ -76,7 +76,7 @@ end # test _format_derivative_info @testset "_format_derivative_info" begin - der = InfiniteOpt._core_variable_object(dy) + der = core_object(dy) @test !IOTO._format_derivative_info(der, [0., 0.5, 0.75]).has_lb @test !IOTO._format_derivative_info(der, [0., 0.5, 0.75]).has_ub @test !IOTO._format_derivative_info(der, [0., 0.5, 0.75]).has_fix @@ -84,7 +84,7 @@ @test IOTO._format_derivative_info(der, [0., 0.5, 0.75]).start == 1.25 @test !IOTO._format_derivative_info(der, [0., 0.5, 0.75]).binary @test !IOTO._format_derivative_info(der, [0., 0.5, 0.75]).integer - der = InfiniteOpt._core_variable_object(dx) + der = core_object(dx) @test IOTO._format_derivative_info(der, [0.]).has_lb @test IOTO._format_derivative_info(der, [0.]).lower_bound == 0 @test !IOTO._format_derivative_info(der, [0.]).has_ub @@ -263,38 +263,38 @@ end # test _get_info_constr_from_var @testset "_get_info_constr_from_var" begin # lower bounds - set = moi_set(InfiniteOpt._core_constraint_object(LowerBoundRef(x))) + set = moi_set(constraint_object(LowerBoundRef(x))) expected = LowerBoundRef(IOTO.lookup_by_support(x, tb, [1., 1., 1.])) @test IOTO._get_info_constr_from_var(tb, x, set, [1., 1., 1.]) == expected @test IOTO._get_info_constr_from_var(tb, x, set, [0., 0., 0.]) isa Nothing # upper bounds - set = moi_set(InfiniteOpt._core_constraint_object(UpperBoundRef(x))) + set = moi_set(constraint_object(UpperBoundRef(x))) expected = UpperBoundRef(IOTO.lookup_by_support(x, tb, [0., 1., 1.])) @test IOTO._get_info_constr_from_var(tb, x, set, [1., 1., 0.]) == expected @test IOTO._get_info_constr_from_var(tb, x, set, [0., 0., 0.]) isa Nothing - set = moi_set(InfiniteOpt._core_constraint_object(UpperBoundRef(yf))) + set = moi_set(constraint_object(UpperBoundRef(yf))) expected = UpperBoundRef(yft) @test IOTO._get_info_constr_from_var(tb, y, set, [1., 1., 1.]) == expected # fix - set = moi_set(InfiniteOpt._core_constraint_object(FixRef(y))) + set = moi_set(constraint_object(FixRef(y))) expected = FixRef(IOTO.lookup_by_support(y, tb, [0.])) @test IOTO._get_info_constr_from_var(tb, y, set, [1., 1., 0.]) == expected @test IOTO._get_info_constr_from_var(tb, y, set, [0., 0., 1.]) isa Nothing - set = moi_set(InfiniteOpt._core_constraint_object(FixRef(x0))) + set = moi_set(constraint_object(FixRef(x0))) expected = FixRef(x0t) @test IOTO._get_info_constr_from_var(tb, x, set, [0., 0., 0.]) == expected # binary - set = moi_set(InfiniteOpt._core_constraint_object(BinaryRef(x0))) + set = moi_set(constraint_object(BinaryRef(x0))) expected = BinaryRef(IOTO.lookup_by_support(x, tb, [0., 0., 0.])) @test IOTO._get_info_constr_from_var(tb, x, set, [0., 0., 0.]) == expected @test IOTO._get_info_constr_from_var(tb, x, set, [1., 1., 1.]) isa Nothing @test IOTO._get_info_constr_from_var(tb, z, set, [1., 1., 1.]) == BinaryRef(zt) # integer - set = moi_set(InfiniteOpt._core_constraint_object(IntegerRef(x))) + set = moi_set(constraint_object(IntegerRef(x))) expected = IntegerRef(IOTO.lookup_by_support(x, tb, [0., 1., 1.])) @test IOTO._get_info_constr_from_var(tb, x, set, [1., 1., 0.]) == expected @test IOTO._get_info_constr_from_var(tb, x, set, [0., 0., 0.]) isa Nothing - set = moi_set(InfiniteOpt._core_constraint_object(IntegerRef(yf))) + set = moi_set(constraint_object(IntegerRef(yf))) expected = IntegerRef(yft) @test IOTO._get_info_constr_from_var(tb, yf, set, [1., 1., 1.]) == expected end @@ -609,7 +609,7 @@ end @test isa(build_transformation_backend!(m), Nothing) @test transformation_backend_ready(m) @test num_variables(m.backend.model) == 44 - @test time_limit_sec(m.backend) == 42 + @test time_limit_sec(m.backend.model) == 42 # test bad keyword @test_throws ErrorException build_transformation_backend!(m, bad = 42) end \ No newline at end of file diff --git a/test/array_parameters.jl b/test/array_parameters.jl index 57a3e477..7f85aa50 100644 --- a/test/array_parameters.jl +++ b/test/array_parameters.jl @@ -20,7 +20,7 @@ # test _add_data_object @testset "_add_data_object" begin @test InfiniteOpt._add_data_object(m, object) == obj_idx - @test InfiniteOpt._param_object_indices(m)[end] == obj_idx + @test InfiniteOpt.parameter_group_indices(m)[end] == obj_idx end # test _data_dictionary @testset "_data_dictionary" begin @@ -36,8 +36,8 @@ end # test _core_variable_object @testset "_core_variable_object" begin - @test InfiniteOpt._core_variable_object(pref) == params - @test InfiniteOpt._core_variable_object(gvref) == params + @test core_object(pref) == params + @test core_object(gvref) == params end # test _num_parameters @testset "_num_parameters" begin @@ -136,21 +136,21 @@ end prefs = [GeneralVariableRef(m, 1, DependentParameterIndex, i) for i in 1:2] params = InfiniteOpt._build_parameters(error, [domain1, domain1], inds1) @test isequal(add_parameters(m, params, ["", ""]), prefs) - @test InfiniteOpt._param_object_indices(m) == [index(prefs[1]).object_index] + @test InfiniteOpt.parameter_group_indices(m) == [index(prefs[1]).object_index] @test InfiniteOpt._last_param_num(m) == 2 @test name.(prefs) == ["", ""] # test vector build prefs = [GeneralVariableRef(m, 2, DependentParameterIndex, i) for i in 1:2] params = InfiniteOpt._build_parameters(error, [domain2, domain2], inds1) @test isequal(add_parameters(m, params, ["p1", "p2"]), prefs) - @test InfiniteOpt._param_object_indices(m)[2] == index(prefs[1]).object_index + @test InfiniteOpt.parameter_group_indices(m)[2] == index(prefs[1]).object_index @test InfiniteOpt._last_param_num(m) == 4 @test name.(prefs) == ["p1", "p2"] # test array build prefs = [GeneralVariableRef(m, 3, DependentParameterIndex, i) for i in 1:4] params = InfiniteOpt._build_parameters(error, [domain3 for i in 1:4], inds2) @test isequal(add_parameters(m, params, ["p$i" for i in 1:4]), prefs) - @test InfiniteOpt._param_object_indices(m)[3] == index(prefs[1]).object_index + @test InfiniteOpt.parameter_group_indices(m)[3] == index(prefs[1]).object_index @test InfiniteOpt._last_param_num(m) == 8 @test name.(prefs) == ["p$i" for i in 1:4] # test name error @@ -200,15 +200,15 @@ end prefs = [GeneralVariableRef(m, 1, DependentParameterIndex, i) for i in 1:2] @test isequal(@infinite_parameter(m, a[1:2] ~ dist1, num_supports = 10), prefs) @test name.(prefs) == ["a[1]", "a[2]"] - @test length(InfiniteOpt._core_variable_object(prefs[1]).supports) == 10 - @test WeightedSample in first(InfiniteOpt._core_variable_object(prefs[1]).supports)[2] - @test InfiniteOpt._core_variable_object(prefs[1]).domain.domains == domain5.domains + @test length(core_object(prefs[1]).supports) == 10 + @test WeightedSample in first(core_object(prefs[1]).supports)[2] + @test core_object(prefs[1]).domain.domains == domain5.domains # test another explicit build prefs = [GeneralVariableRef(m, 2, DependentParameterIndex, i) for i in 1:2] expected = JuMPC.DenseAxisArray(prefs, 3:4) @test isequal(@infinite_parameter(m, b[3:4] in domain2, supports = 0), expected) @test name.(prefs) == ["b[3]", "b[4]"] - @test InfiniteOpt._core_variable_object(prefs[1]).supports == Dict{Vector{Float64}, Set{DataType}}(zeros(2) => Set([UserDefined])) + @test core_object(prefs[1]).supports == Dict{Vector{Float64}, Set{DataType}}(zeros(2) => Set([UserDefined])) # test explicit build with some args prefs = [GeneralVariableRef(m, 3, DependentParameterIndex, i) for i in 1:2] expected = convert(JuMPC.SparseAxisArray, prefs) @@ -220,15 +220,15 @@ end prefs = [GeneralVariableRef(m, 4, DependentParameterIndex, i) for i in 1:2] @test isequal(@infinite_parameter(m, d[1:2] in [0, 1], num_supports = 10), prefs) @test name.(prefs) == ["d[1]", "d[2]"] - @test length(InfiniteOpt._core_variable_object(prefs[1]).supports) == 10 - @test UniformGrid in first(InfiniteOpt._core_variable_object(prefs[1]).supports)[2] - @test InfiniteOpt._core_variable_object(prefs[1]).domain.domains == domain1.domains + @test length(core_object(prefs[1]).supports) == 10 + @test UniformGrid in first(core_object(prefs[1]).supports)[2] + @test core_object(prefs[1]).domain.domains == domain1.domains # test test anonymous prefs = [GeneralVariableRef(m, 5, DependentParameterIndex, i) for i in 1:4] prefs = reshape(prefs, (2, 2)) @test isequal(@infinite_parameter(m, [1:2, 1:2], distribution = dist3), prefs) @test name.(prefs) == ["" ""; "" ""] - @test isempty(InfiniteOpt._core_variable_object(prefs[1]).supports) + @test isempty(core_object(prefs[1]).supports) # test anonymous with domain keyword prefs = [GeneralVariableRef(m, 6, DependentParameterIndex, i) for i in 1:2] @test isequal(@infinite_parameter(m, [1:2], domain = sdomain2, @@ -442,17 +442,17 @@ end @test InfiniteOpt._parameter_numbers(prefs[2]) == [2] @test InfiniteOpt._parameter_numbers(gvrefs[1]) == [1] end - # test _object_number - @testset "_object_number" begin - @test InfiniteOpt._object_number(prefs[1]) == 1 - @test InfiniteOpt._object_number(prefs[2]) == 1 - @test InfiniteOpt._object_number(gvrefs[1]) == 1 + # test parameter_group_int_index + @testset "parameter_group_int_index" begin + @test InfiniteOpt.parameter_group_int_index(prefs[1]) == 1 + @test InfiniteOpt.parameter_group_int_index(prefs[2]) == 1 + @test InfiniteOpt.parameter_group_int_index(gvrefs[1]) == 1 end - # test _object_numbers - @testset "_object_numbers" begin - @test InfiniteOpt._object_numbers(prefs[1]) == [1] - @test InfiniteOpt._object_numbers(prefs[2]) == [1] - @test InfiniteOpt._object_numbers(gvrefs[1]) == [1] + # test parameter_group_int_indices + @testset "parameter_group_int_indices" begin + @test InfiniteOpt.parameter_group_int_indices(prefs[1]) == [1] + @test InfiniteOpt.parameter_group_int_indices(prefs[2]) == [1] + @test InfiniteOpt.parameter_group_int_indices(gvrefs[1]) == [1] end # test _adaptive_data_update @testset "_adaptive_data_update" begin @@ -462,16 +462,16 @@ end domain = MultiDistributionDomain(MvNormal([0, 0], LinearAlgebra.Diagonal(map(abs2, [1, 1])))) ps = DependentParameters(domain, Dict{Vector{Float64}, Set{DataType}}(), 10, methods) @test InfiniteOpt._adaptive_data_update(prefs[2], ps, data) isa Nothing - @test InfiniteOpt._core_variable_object(prefs[2]) == ps + @test core_object(prefs[2]) == ps end - # test _set_core_variable_object - @testset "_set_core_variable_object" begin + # test _set_core_object + @testset "_set_core_object" begin # test with different type - @test InfiniteOpt._set_core_variable_object(prefs[1], params) isa Nothing - @test InfiniteOpt._core_variable_object(prefs[2]) == params + @test InfiniteOpt._set_core_object(prefs[1], params) isa Nothing + @test core_object(prefs[2]) == params # test with same type - @test InfiniteOpt._set_core_variable_object(prefs[2], params) isa Nothing - @test InfiniteOpt._core_variable_object(prefs[1]) == params + @test InfiniteOpt._set_core_object(prefs[2], params) isa Nothing + @test core_object(prefs[1]) == params end end @@ -522,11 +522,11 @@ end # test _adaptive_method_update @testset "_adaptive_method_update" begin # same type - params = InfiniteOpt._core_variable_object(prefs[1]) + params = core_object(prefs[1]) @test InfiniteOpt._adaptive_method_update(prefs[1], params, TestMethod()) isa Nothing @test derivative_method(prefs[1]) isa TestMethod # different type - params = InfiniteOpt._core_variable_object(prefs[1]) + params = core_object(prefs[1]) method = InfiniteOpt.DefaultDerivativeMethod @test InfiniteOpt._adaptive_method_update(prefs[2], params, method) isa Nothing @test InfiniteOpt._derivative_methods(prefs[1]) == [TestMethod(), method] @@ -1030,4 +1030,8 @@ end @testset "all_parameters (InfiniteParameter)" begin @test isequal(all_parameters(m, InfiniteParameter), [prefs1; [prefs2...]; pref]) end + # test parameter_refs + @testset "parameter_refs" begin + @test parameter_refs(m) == (prefs1, vec(prefs2), pref) + end end diff --git a/test/backend_setup.jl b/test/backend_setup.jl index e19c1734..49feff56 100644 --- a/test/backend_setup.jl +++ b/test/backend_setup.jl @@ -53,6 +53,8 @@ @test get_optimizer_attribute(m, MOI.TimeLimitSec()) == 12 @test set_attributes(m, MOI.TimeLimitSec() => 10.) isa Nothing @test get_attribute(m, MOI.TimeLimitSec()) == 10 + @test set_attribute(m, "something", 42) isa Nothing + @test get_attribute(m, "something") == 42 end # Base.empty! @testset "Base.empty!" begin @@ -69,11 +71,9 @@ end bmodel = Model(mockoptimizer) jump_backend = JuMPBackend{TestJuMPTag}(bmodel, 42) set_time_limit_sec(bmodel, 10) - @testset "Single Argument Methods" begin - for f in (set_silent, unset_silent, bridge_constraints, - time_limit_sec, unset_time_limit_sec, solver_name, backend, - JuMP.mode, unsafe_backend, compute_conflict!, copy_conflict, - set_string_names_on_creation) + @testset "Single Argument Direct Methods" begin + for f in (bridge_constraints, backend, JuMP.mode, unsafe_backend, + compute_conflict!, copy_conflict) @test_throws ErrorException f(TestBackend()) if f != copy_conflict @test f(jump_backend) == f(bmodel) @@ -84,19 +84,43 @@ end end end end + @testset "JuMP.set_silent" begin + @test set_silent(m) isa Nothing + @test get_attribute(m, MOI.Silent()) + @test set_silent(InfiniteModel(jump_backend)) isa Nothing + @test get_attribute(jump_backend, MOI.Silent()) + @test_throws ErrorException set_silent(InfiniteModel(TestBackend())) + end + @testset "JuMP.unset_silent" begin + @test unset_silent(m) isa Nothing + @test !get_attribute(m, MOI.Silent()) + @test unset_silent(InfiniteModel(jump_backend)) isa Nothing + @test !get_attribute(jump_backend, MOI.Silent()) + @test_throws ErrorException unset_silent(InfiniteModel(TestBackend())) + end + @testset "JuMP.time_limit_sec" begin + @test time_limit_sec(m) isa Nothing + @test time_limit_sec(InfiniteModel(jump_backend)) == 10 + @test_throws ErrorException time_limit_sec(InfiniteModel(TestBackend())) + end @testset "JuMP.set_time_limit_sec" begin - @test_throws ErrorException set_time_limit_sec(TestBackend(), 42) - @test set_time_limit_sec(jump_backend, 42) isa Nothing - @test time_limit_sec(jump_backend) == 42 + @test_throws ErrorException set_time_limit_sec(InfiniteModel(TestBackend()), 42) + @test set_time_limit_sec(InfiniteModel(jump_backend), 42) isa Nothing + @test time_limit_sec(bmodel) == 42 @test set_time_limit_sec(m, 42) isa Nothing @test time_limit_sec(m) == 42 end - @testset "JuMP.set_string_names_on_creation" begin - @test_throws ErrorException set_string_names_on_creation(TestBackend(), false) - @test set_string_names_on_creation(jump_backend, false) isa Nothing - @test set_string_names_on_creation(jump_backend) == false - @test set_string_names_on_creation(m, true) isa Nothing - @test set_string_names_on_creation(m) == true + @testset "JuMP.unset_time_limit_sec" begin + @test unset_time_limit_sec(m) isa Nothing + @test time_limit_sec(m) isa Nothing + @test unset_time_limit_sec(InfiniteModel(jump_backend)) isa Nothing + @test time_limit_sec(bmodel) isa Nothing + @test_throws ErrorException unset_time_limit_sec(InfiniteModel(TestBackend())) + end + @testset "JuMP.solver_name" begin + @test solver_name(m) == get_attribute(m.backend, MOI.SolverName()) + @test solver_name(InfiniteModel(jump_backend)) == solver_name(bmodel) + @test_throws ErrorException solver_name(InfiniteModel(TestBackend())) end @testset "JuMP.add_bridge" begin bridge = MOI.Bridges.Variable.VectorizeBridge @@ -123,7 +147,7 @@ end bmodel2 = Model() jump_backend2 = JuMPBackend{TestJuMPTag}(bmodel2, 42) @test set_optimizer(jump_backend2, mockoptimizer) isa Nothing - @test solver_name(jump_backend2) == "Mock" + @test solver_name(jump_backend2.model) == "Mock" m2 = InfiniteModel() @test set_optimizer(m2, mockoptimizer) isa Nothing @test solver_name(m) == "Mock" diff --git a/test/constraints.jl b/test/constraints.jl index e7b92f5e..fe0ce869 100644 --- a/test/constraints.jl +++ b/test/constraints.jl @@ -43,29 +43,33 @@ @test InfiniteOpt._data_object(cref) === object @test_throws ErrorException InfiniteOpt._data_object(bad_cref) end - # _core_constraint_object - @testset "_core_constraint_object" begin - @test InfiniteOpt._core_constraint_object(cref) === con + # constraint_object + @testset "JuMP.constraint_object" begin + @test constraint_object(cref) === con end - # _set_core_constraint_object - @testset "_set_core_constraint_object" begin - @test InfiniteOpt._set_core_constraint_object(cref, con) isa Nothing + # core_object + @testset "core_object" begin + @test core_object(cref) === con + end + # _set_core_object + @testset "_set_core_object" begin + @test InfiniteOpt._set_core_object(cref, con) isa Nothing con2 = ScalarConstraint(zero(AffExpr), MOI.LessThan(0.0)) - @test InfiniteOpt._set_core_constraint_object(cref, con2) isa Nothing - @test InfiniteOpt._core_constraint_object(cref) === con2 - @test InfiniteOpt._set_core_constraint_object(cref, con) isa Nothing - @test InfiniteOpt._core_constraint_object(cref) === con + @test InfiniteOpt._set_core_object(cref, con2) isa Nothing + @test constraint_object(cref) === con2 + @test InfiniteOpt._set_core_object(cref, con) isa Nothing + @test constraint_object(cref) === con end - # _object_numbers - @testset "_object_numbers" begin - @test InfiniteOpt._object_numbers(cref) == [] + # parameter_group_int_indices + @testset "parameter_group_int_indices" begin + @test InfiniteOpt.parameter_group_int_indices(cref) == [] end # _measure_dependencies @testset "_measure_dependencies" begin @test InfiniteOpt._measure_dependencies(cref) == MeasureIndex[] end - @testset "_is_info_constraint" begin - @test !InfiniteOpt._is_info_constraint(cref) + @testset "is_variable_domain_constraint" begin + @test !is_variable_domain_constraint(cref) end # constraint_object @testset "JuMP.constraint_object" begin @@ -90,10 +94,6 @@ @testset "domain_restrictions" begin @test domain_restrictions(cref) == DomainRestrictions() end - # _make_constraint_ref - @testset "_make_constraint_ref" begin - @test InfiniteOpt._make_constraint_ref(m, idx) == cref - end # constraint_by_name @testset "JuMP.constraint_by_name" begin # test normal @@ -247,7 +247,7 @@ end cref = InfOptConstraintRef(m, idx) @test add_constraint(m, con, "d") == cref @test name(cref) == "d" - @test !InfiniteOpt._is_info_constraint(cref) + @test !is_variable_domain_constraint(cref) @test !transformation_backend_ready(m) @test used_by_constraint(pt) # test vector constraint @@ -264,14 +264,14 @@ end idx = InfOptConstraintIndex(5) cref = InfOptConstraintRef(m, idx) @test @constraint(m, f, x + pt -2 <= 2) == cref - @test InfiniteOpt._core_constraint_object(cref) isa ScalarConstraint + @test constraint_object(cref) isa ScalarConstraint # test restricted scalar constraint rs = DomainRestrictions(par => [0, 1]) idx = InfOptConstraintIndex(6) cref = InfOptConstraintRef(m, idx) @test @constraint(m, g, inf + meas - dinf <= 2, rs) == cref - @test InfiniteOpt._object_numbers(cref) == [1] - @test InfiniteOpt._core_constraint_object(cref) isa ScalarConstraint + @test InfiniteOpt.parameter_group_int_indices(cref) == [1] + @test constraint_object(cref) isa ScalarConstraint @test used_by_constraint(dinf) end end diff --git a/test/datatypes.jl b/test/datatypes.jl index c01eaaf7..d6641add 100644 --- a/test/datatypes.jl +++ b/test/datatypes.jl @@ -190,7 +190,7 @@ end mockoptimizer = () -> MOIU.MockOptimizer(MOIU.UniversalFallback(MOIU.Model{Float64}()), eval_objective_value=false) # test optimizer constructors - @test solver_name(InfiniteModel(mockoptimizer).backend) == "Mock" + @test solver_name(InfiniteModel(mockoptimizer).backend.model) == "Mock" m = InfiniteModel(); @test isa(Base.broadcastable(m), Base.RefValue{InfiniteModel}) @test length(JuMP.object_dictionary(m)) == 0 @@ -198,7 +198,7 @@ end @test InfiniteModel(mockoptimizer, add_bridges = false) isa InfiniteModel # test accessors @test InfiniteOpt._last_param_num(m) == 0 - @test InfiniteOpt._param_object_indices(m) isa Vector{Union{IndependentParameterIndex, DependentParametersIndex}} + @test InfiniteOpt.parameter_group_indices(m) isa Vector{Union{IndependentParameterIndex, DependentParametersIndex}} # test other methods @test empty!(InfiniteModel(mockoptimizer)).backend isa TranscriptionBackend @test variable_ref_type(InfiniteModel) == GeneralVariableRef diff --git a/test/deletion.jl b/test/deletion.jl index 7dbb174f..4a04fb8f 100644 --- a/test/deletion.jl +++ b/test/deletion.jl @@ -224,29 +224,29 @@ end @test InfiniteOpt._update_measures(m, par2) isa Nothing @test isequal_canonical(measure_function(dmref), inf + par - x + rv + par3 + fin) @test isequal(measure_function(dmref2), zero(JuMP.GenericAffExpr{Float64, GeneralVariableRef})) - @test InfiniteOpt._object_numbers(dmref) == [2, 3, 4] - @test InfiniteOpt._object_numbers(dmref2) == [] + @test InfiniteOpt.parameter_group_int_indices(dmref) == [2, 3, 4] + @test InfiniteOpt.parameter_group_int_indices(dmref2) == [] @test InfiniteOpt._parameter_numbers(dmref) == [2, 3, 4, 5] @test InfiniteOpt._parameter_numbers(dmref2) == [] # undo changes meas = Measure(inf + par - x + rv + par2 + par3 + fin, data, [2, 4], [2, 5], false) - InfiniteOpt._set_core_variable_object(dmref, meas) + InfiniteOpt._set_core_object(dmref, meas) meas = Measure(par2, data, [2], [2], false) - InfiniteOpt._set_core_variable_object(dmref2, meas) + InfiniteOpt._set_core_object(dmref2, meas) end # test _update_constraints @testset "_update_constraints" begin @test InfiniteOpt._update_constraints(m, par2) isa Nothing @test isequal_canonical(jump_function(constraint_object(con)), inf2 + inf4 + par3 + fin) @test isequal(jump_function(constraint_object(con2)), zero(JuMP.GenericAffExpr{Float64, GeneralVariableRef})) - @test isempty(setdiff(InfiniteOpt._object_numbers(con), [1, 2, 3, 4])) - @test InfiniteOpt._object_numbers(con2) == [] + @test isempty(setdiff(InfiniteOpt.parameter_group_int_indices(con), [1, 2, 3, 4])) + @test InfiniteOpt.parameter_group_int_indices(con2) == [] @test !is_valid(m, con3) # undo changes constr = ScalarConstraint(inf2 + inf4 - par2 + par3 + fin, MOI.LessThan(0.)) - InfiniteOpt._set_core_constraint_object(con, constr) + InfiniteOpt._set_core_object(con, constr) constr = ScalarConstraint(par2, MOI.GreaterThan(0.)) - InfiniteOpt._set_core_constraint_object(con2, constr) + InfiniteOpt._set_core_object(con2, constr) unregister(m, :con3) @constraint(m, con3, [par2, par2] in MOI.Zeros(2)) end @@ -284,30 +284,30 @@ end @test isequal(jump_function(constraint_object(con2)),zero(JuMP.GenericAffExpr{Float64, GeneralVariableRef})) expected = [IndependentParameterIndex(1), DependentParametersIndex(1), IndependentParameterIndex(3)] - @test InfiniteOpt._param_object_indices(m) == expected + @test InfiniteOpt.parameter_group_indices(m) == expected @test InfiniteOpt._last_param_num(m) == 4 - @test InfiniteOpt._object_number(dpar) == 1 - @test InfiniteOpt._object_number(dpars[1]) == 2 - @test InfiniteOpt._object_number(dpar3) == 3 + @test InfiniteOpt.parameter_group_int_index(dpar) == 1 + @test InfiniteOpt.parameter_group_int_index(dpars[1]) == 2 + @test InfiniteOpt.parameter_group_int_index(dpar3) == 3 @test InfiniteOpt._parameter_number(dpar3) == 4 @test InfiniteOpt._parameter_number(dpars[2]) == 3 @test InfiniteOpt._parameter_numbers(dinf4) == [1, 2, 3] - @test isempty(setdiff(InfiniteOpt._object_numbers(inf3), [1, 2])) + @test isempty(setdiff(InfiniteOpt.parameter_group_int_indices(inf3), [1, 2])) @test InfiniteOpt._parameter_numbers(dinf) == [1] - @test isempty(setdiff(InfiniteOpt._object_numbers(drv), [1, 2])) - @test InfiniteOpt._object_numbers(dmref) == [3] + @test isempty(setdiff(InfiniteOpt.parameter_group_int_indices(drv), [1, 2])) + @test InfiniteOpt.parameter_group_int_indices(dmref) == [3] @test InfiniteOpt._parameter_numbers(dmref) == [4] - @test isempty(setdiff(InfiniteOpt._object_numbers(con), [1, 2, 3])) - @test isempty(InfiniteOpt._object_numbers(con2)) + @test isempty(setdiff(InfiniteOpt.parameter_group_int_indices(con), [1, 2, 3])) + @test isempty(InfiniteOpt.parameter_group_int_indices(con2)) @test !is_valid(m, con3) # test special measure case with single parameter (possible through # multiple deletions) and with single parameter in constraint @test isa(delete(m, par3), Nothing) @test isequal_canonical(measure_function(dmref), inf + par - x + rv + fin) @test isequal_canonical(jump_function(constraint_object(con)), inf4 + fin) - @test isempty(setdiff(InfiniteOpt._object_numbers(con), [1, 2])) + @test isempty(setdiff(InfiniteOpt.parameter_group_int_indices(con), [1, 2])) expected = [IndependentParameterIndex(1), DependentParametersIndex(1)] - @test InfiniteOpt._param_object_indices(m) == expected + @test InfiniteOpt.parameter_group_indices(m) == expected @test InfiniteOpt._last_param_num(m) == 3 @test InfiniteOpt._parameter_number(dpars[2]) == 3 @test InfiniteOpt._parameter_numbers(dinf4) == [1, 2, 3] @@ -400,16 +400,16 @@ end @test isequal_canonical(measure_function(dmref), inf + par - x) @test isequal_canonical(jump_function(constraint_object(con)), inf2 - par2) expected = [IndependentParameterIndex(1), IndependentParameterIndex(2)] - @test InfiniteOpt._param_object_indices(m) == expected + @test InfiniteOpt.parameter_group_indices(m) == expected @test InfiniteOpt._last_param_num(m) == 2 - @test InfiniteOpt._object_number(dpar) == 1 - @test InfiniteOpt._object_number(dpar2) == 2 + @test InfiniteOpt.parameter_group_int_index(dpar) == 1 + @test InfiniteOpt.parameter_group_int_index(dpar2) == 2 @test InfiniteOpt._parameter_number(dpar2) == 2 - @test isempty(setdiff(InfiniteOpt._object_numbers(dinf2), [1, 2])) + @test isempty(setdiff(InfiniteOpt.parameter_group_int_indices(dinf2), [1, 2])) @test InfiniteOpt._parameter_numbers(dinf) == [1] - @test InfiniteOpt._object_numbers(dmref) == [] + @test InfiniteOpt.parameter_group_int_indices(dmref) == [] @test InfiniteOpt._parameter_numbers(dmref) == [] - @test isempty(setdiff(InfiniteOpt._object_numbers(con), [1, 2])) + @test isempty(setdiff(InfiniteOpt.parameter_group_int_indices(con), [1, 2])) @test !is_valid(m, con2) # test assertion error @test_throws AssertionError delete(m, pars) @@ -441,18 +441,18 @@ end @test isa(delete(m, rv), Nothing) @test !is_valid(m, d1) @test isequal_canonical(measure_function(meas), inf + par - x) - @test InfiniteOpt._object_numbers(meas) == [2] + @test InfiniteOpt.parameter_group_int_indices(meas) == [2] @test isequal_canonical(jump_function(constraint_object(con)), x + 0) - @test InfiniteOpt._object_numbers(con) == [] + @test InfiniteOpt.parameter_group_int_indices(con) == [] @test InfiniteOpt._semi_infinite_variable_dependencies(inf) == [JuMP.index(rv2)] @test !haskey(InfiniteOpt._data_dictionary(m, SemiInfiniteVariable), JuMP.index(rv)) @test !is_valid(m, rv) # test deletion of special cases @test isa(delete(m, rv2), Nothing) @test isequal(measure_function(meas2), zero(JuMP.GenericAffExpr{Float64, GeneralVariableRef})) - @test InfiniteOpt._object_numbers(meas2) == [] + @test InfiniteOpt.parameter_group_int_indices(meas2) == [] @test isequal(jump_function(constraint_object(con2)), zero(JuMP.GenericAffExpr{Float64, GeneralVariableRef})) - @test InfiniteOpt._object_numbers(con2) == [] + @test InfiniteOpt.parameter_group_int_indices(con2) == [] @test InfiniteOpt._semi_infinite_variable_dependencies(inf) == [] @test !haskey(InfiniteOpt._data_dictionary(m, SemiInfiniteVariable), JuMP.index(rv2)) @test isempty(m.semi_lookup) @@ -519,9 +519,9 @@ end @test isa(delete(m, x), Nothing) @test num_constraints(m) == 4 @test isequal_canonical(measure_function(meas1), y + par) - @test InfiniteOpt._object_numbers(meas1) == [] + @test InfiniteOpt.parameter_group_int_indices(meas1) == [] @test isequal_canonical(jump_function(constraint_object(con1)), y + par) - @test InfiniteOpt._object_numbers(con1) == [1] + @test InfiniteOpt.parameter_group_int_indices(con1) == [1] @test isequal_canonical(objective_function(m), y + 0) @test !haskey(InfiniteOpt._data_dictionary(m, PointVariable), JuMP.index(x)) @test !is_valid(m, con3) @@ -564,9 +564,9 @@ end @test isa(delete(m, x), Nothing) @test num_constraints(m) == 4 @test isequal_canonical(measure_function(meas1), y + par) - @test InfiniteOpt._object_numbers(meas1) == [] + @test InfiniteOpt.parameter_group_int_indices(meas1) == [] @test isequal_canonical(jump_function(constraint_object(con1)), y + par) - @test InfiniteOpt._object_numbers(con1) == [1] + @test InfiniteOpt.parameter_group_int_indices(con1) == [1] @test InfiniteOpt._infinite_variable_dependencies(par) == [index(y)] @test !is_valid(m, rv) @test !is_valid(m, x0) @@ -579,11 +579,11 @@ end @test num_constraints(m) == 2 @test isequal_canonical(measure_function(meas1), par + 0) @test isequal(measure_function(meas2), zero(JuMP.GenericAffExpr{Float64, GeneralVariableRef})) - @test InfiniteOpt._object_numbers(meas1) == [] + @test InfiniteOpt.parameter_group_int_indices(meas1) == [] @test isequal_canonical(jump_function(constraint_object(con1)), par + 0) @test isequal(jump_function(constraint_object(con2)), zero(JuMP.GenericAffExpr{Float64, GeneralVariableRef})) - @test InfiniteOpt._object_numbers(con1) == [1] - @test InfiniteOpt._object_numbers(con2) == [] + @test InfiniteOpt.parameter_group_int_indices(con1) == [1] + @test InfiniteOpt.parameter_group_int_indices(con2) == [] @test InfiniteOpt._infinite_variable_dependencies(par) == [] @test !haskey(InfiniteOpt._data_dictionary(m, InfiniteVariable), JuMP.index(y)) @test isempty(m.piecewise_vars) @@ -619,9 +619,9 @@ end @test isa(delete(m, d1), Nothing) @test num_constraints(m) == 7 @test isequal_canonical(measure_function(meas1), y + par) - @test InfiniteOpt._object_numbers(meas1) == [] + @test InfiniteOpt.parameter_group_int_indices(meas1) == [] @test isequal_canonical(jump_function(constraint_object(con1)), d2 + par) - @test InfiniteOpt._object_numbers(con1) == [1] + @test InfiniteOpt.parameter_group_int_indices(con1) == [1] @test InfiniteOpt._derivative_dependencies(par) == [index(d2)] @test !is_valid(m, rv) @test !is_valid(m, dx0) @@ -636,11 +636,11 @@ end @test num_constraints(m) == 7 @test isequal_canonical(measure_function(meas1), y + par) @test isequal(measure_function(meas2), zero(JuMP.GenericAffExpr{Float64, GeneralVariableRef})) - @test InfiniteOpt._object_numbers(meas1) == [] + @test InfiniteOpt.parameter_group_int_indices(meas1) == [] @test isequal_canonical(jump_function(constraint_object(con1)), par + 0) @test isequal(jump_function(constraint_object(con2)), zero(JuMP.GenericAffExpr{Float64, GeneralVariableRef})) - @test InfiniteOpt._object_numbers(con1) == [1] - @test InfiniteOpt._object_numbers(con2) == [] + @test InfiniteOpt.parameter_group_int_indices(con1) == [1] + @test InfiniteOpt.parameter_group_int_indices(con2) == [] @test InfiniteOpt._derivative_dependencies(par) == [] @test !haskey(InfiniteOpt._data_dictionary(m, Derivative), JuMP.index(d2)) @test !haskey(m.deriv_lookup, (y, par, 2)) @@ -710,9 +710,9 @@ end # test deletion of meas1 @test isa(delete(m, meas1), Nothing) @test isequal_canonical(measure_function(meas3), x0 + 0) - @test InfiniteOpt._object_numbers(meas3) == [] + @test InfiniteOpt.parameter_group_int_indices(meas3) == [] @test isequal_canonical(jump_function(constraint_object(con1)), x0 + 0) - @test InfiniteOpt._object_numbers(con1) == [] + @test InfiniteOpt.parameter_group_int_indices(con1) == [] @test isequal_canonical(objective_function(m), x0 + 0) @test InfiniteOpt._measure_dependencies(x) == [JuMP.index(meas), JuMP.index(meas2), JuMP.index(meas6)] @test InfiniteOpt._measure_dependencies(y) == [JuMP.index(meas6)] @@ -724,9 +724,9 @@ end set_objective_function(m, meas2) @test isa(delete(m, meas2), Nothing) @test isequal(measure_function(meas4), zero(JuMP.GenericAffExpr{Float64, GeneralVariableRef})) - @test InfiniteOpt._object_numbers(meas4) == [] + @test InfiniteOpt.parameter_group_int_indices(meas4) == [] @test isequal(jump_function(constraint_object(con2)), zero(JuMP.GenericAffExpr{Float64, GeneralVariableRef})) - @test InfiniteOpt._object_numbers(con2) == [] + @test InfiniteOpt.parameter_group_int_indices(con2) == [] @test isequal(objective_function(m), zero(JuMP.GenericAffExpr{Float64, GeneralVariableRef})) @test InfiniteOpt._measure_dependencies(x) == [JuMP.index(meas), JuMP.index(meas6)] @test InfiniteOpt._measure_dependencies(y) == [JuMP.index(meas6)] diff --git a/test/derivatives.jl b/test/derivatives.jl index 3dd34b6e..4ee46834 100644 --- a/test/derivatives.jl +++ b/test/derivatives.jl @@ -60,18 +60,18 @@ end # _core_variable_object @testset "_core_variable_object" begin - @test InfiniteOpt._core_variable_object(dref) === deriv - @test InfiniteOpt._core_variable_object(gvref) === deriv + @test core_object(dref) === deriv + @test core_object(gvref) === deriv end - # _set_core_variable_object - @testset "_set_core_variable_object" begin - @test InfiniteOpt._set_core_variable_object(dref, deriv) isa Nothing - @test InfiniteOpt._set_core_variable_object(dref, deriv2) isa Nothing - @test InfiniteOpt._set_core_variable_object(dref, deriv) isa Nothing + # _set_core_object + @testset "_set_core_object" begin + @test InfiniteOpt._set_core_object(dref, deriv) isa Nothing + @test InfiniteOpt._set_core_object(dref, deriv2) isa Nothing + @test InfiniteOpt._set_core_object(dref, deriv) isa Nothing end - # _object_numbers - @testset "_object_numbers" begin - @test InfiniteOpt._object_numbers(dref) == [1] + # parameter_group_int_indices + @testset "parameter_group_int_indices" begin + @test InfiniteOpt.parameter_group_int_indices(dref) == [1] end # _parameter_numbers @testset "_parameter_numbers" begin @@ -176,10 +176,6 @@ @test isequal(parameter_list(dref), [a]) @test isequal(parameter_list(gvref), [a]) end - # _make_variable_ref - @testset "_make_variable_ref" begin - @test isequal(InfiniteOpt._make_variable_ref(m, idx), gvref) - end # _var_name_dict @testset "_var_name_dict" begin @test InfiniteOpt._var_name_dict(m) isa Nothing @@ -263,10 +259,10 @@ end # test normal idx = DerivativeIndex(1) dref = DerivativeRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = GeneralVariableRef(m, idx) @test isequal(add_derivative(m, d, "name"), gvref) @test haskey(InfiniteOpt._data_dictionary(dref), idx) - @test InfiniteOpt._core_variable_object(dref) == d + @test core_object(dref) == d @test InfiniteOpt._derivative_dependencies(pref) == [idx] @test InfiniteOpt._derivative_dependencies(x) == [idx] @test name(dref) == "name" @@ -276,7 +272,7 @@ end # test info addition functions idx = DerivativeIndex(2) dref = DerivativeRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = GeneralVariableRef(m, idx) @test isequal(add_derivative(m, d, "name"), gvref) @test !transformation_backend_ready(m) @test InfiniteOpt._derivative_dependencies(prefs[1]) == [idx] @@ -313,11 +309,11 @@ end # test redundant build idx = DerivativeIndex(1) dref = DerivativeRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = GeneralVariableRef(m, idx) d = Derivative(info4, false, x, pref, 1) @test isequal(add_derivative(m, d, "name2"), gvref) @test haskey(InfiniteOpt._data_dictionary(dref), idx) - @test InfiniteOpt._core_variable_object(dref) == d + @test core_object(dref) == d @test name(dref) == "name2" @test lower_bound(dref) == 0 # test redundant build with warning @@ -328,7 +324,7 @@ end "or start value) will be lost/changed." @test_logs (:warn, warn) add_derivative(m, d, "name3") @test haskey(InfiniteOpt._data_dictionary(dref), idx) - @test InfiniteOpt._core_variable_object(dref) == d + @test core_object(dref) == d @test name(dref) == "name3" end # test JuMP.add_variable @@ -338,10 +334,10 @@ end # test normal idx = DerivativeIndex(3) dref = DerivativeRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = GeneralVariableRef(m, idx) @test isequal(add_variable(m, d, "name"), gvref) @test haskey(InfiniteOpt._data_dictionary(dref), idx) - @test InfiniteOpt._core_variable_object(dref) == d + @test core_object(dref) == d @test InfiniteOpt._derivative_dependencies(prefs[2]) == [idx] @test InfiniteOpt._derivative_dependencies(x) == [DerivativeIndex(i) for i = 1:3] @test name(dref) == "name" @@ -563,7 +559,7 @@ end # test simple anon case idx = DerivativeIndex(1) dref = DerivativeRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = GeneralVariableRef(m, idx) @test isequal(@variable(m, variable_type = Deriv(y, t)), gvref) @test isequal(derivative_argument(dref), y) @test isequal(operator_parameter(dref), t) @@ -571,7 +567,7 @@ end # test anon with changes to fixed idx = DerivativeIndex(2) dref = DerivativeRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = GeneralVariableRef(m, idx) @test isequal(@variable(m, variable_type = Deriv(y, x[1], 3), lower_bound = -5, upper_bound = 10, start = 2), gvref) @test isequal(derivative_argument(dref), y) @@ -583,7 +579,7 @@ end # test regular with alias idx = DerivativeIndex(1) dref = DerivativeRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = GeneralVariableRef(m, idx) @test isequal(@variable(m, dx <= 0, Deriv(y, t)), gvref) @test isequal(derivative_argument(dref), y) @test isequal(operator_parameter(dref), t) @@ -597,7 +593,7 @@ end # test anon array with one parameter idxs = [DerivativeIndex(3), DerivativeIndex(4)] drefs = [DerivativeRef(m, idx) for idx in idxs] - gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs] + gvrefs = [GeneralVariableRef(m, idx) for idx in idxs] @test isequal(@variable(m, [i = 1:2], Deriv(q[i], t), lower_bound = 0), gvrefs) @test isequal(derivative_argument(drefs[1]), q[1]) @test isequal(operator_parameter(drefs[2]), t) @@ -605,7 +601,7 @@ end # test explicit array idxs = [DerivativeIndex(5), DerivativeIndex(6)] drefs = [DerivativeRef(m, idx) for idx in idxs] - gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs] + gvrefs = [GeneralVariableRef(m, idx) for idx in idxs] @test isequal(@variable(m, q4[i = 1:2] == 3, Deriv(q[i+1], x[i])), gvrefs) @test isequal(derivative_argument(drefs[1]), q[2]) @test isequal(operator_parameter(drefs[2]), x[2]) @@ -614,7 +610,7 @@ end # test semi anon array idxs = [DerivativeIndex(7), DerivativeIndex(8)] drefs = [DerivativeRef(m, idx) for idx in idxs] - gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs] + gvrefs = [GeneralVariableRef(m, idx) for idx in idxs] @test isequal(@variable(m, [i = 1:2], Deriv(q[i], x[i]), lower_bound = -5), gvrefs) @test isequal(derivative_argument(drefs[2]), q[2]) @test isequal(operator_parameter(drefs[1]), x[1]) diff --git a/test/expressions.jl b/test/expressions.jl index 719257bd..97b40fec 100644 --- a/test/expressions.jl +++ b/test/expressions.jl @@ -47,12 +47,12 @@ end # _core_variable_object @testset "_core_variable_object" begin - @test InfiniteOpt._core_variable_object(fref) === func - @test InfiniteOpt._core_variable_object(gvref) === func + @test core_object(fref) === func + @test core_object(gvref) === func end - # _object_numbers - @testset "_object_numbers" begin - @test InfiniteOpt._object_numbers(fref) == [1] + # parameter_group_int_indices + @testset "parameter_group_int_indices" begin + @test InfiniteOpt.parameter_group_int_indices(fref) == [1] end # _parameter_numbers @testset "_parameter_numbers" begin @@ -382,8 +382,8 @@ end end end -# Test _all_function_variables -@testset "_all_function_variables" begin +# Test all_expression_variables +@testset "all_expression_variables" begin # initialize model and references m = InfiniteModel() @infinite_parameter(m, par in [0, 1]) @@ -395,14 +395,14 @@ end object = MeasureData(meas, "test") mindex = MeasureIndex(1) @test InfiniteOpt._add_data_object(m, object) == mindex - meas = InfiniteOpt._make_variable_ref(m, mindex) + meas = InfiniteOpt.GeneralVariableRef(m, mindex) dinf = @deriv(inf, par) # test for variable reference @testset "Variable" begin - @test isequal(InfiniteOpt._all_function_variables(par), [par]) - @test isequal(InfiniteOpt._all_function_variables(inf), [inf]) - @test isequal(InfiniteOpt._all_function_variables(meas), [meas]) - @test isequal(InfiniteOpt._all_function_variables(dinf), [dinf]) + @test isequal(all_expression_variables(par), [par]) + @test isequal(all_expression_variables(inf), [inf]) + @test isequal(all_expression_variables(meas), [meas]) + @test isequal(all_expression_variables(dinf), [dinf]) end # test for GenericAffExpr @testset "AffExpr" begin @@ -410,9 +410,9 @@ end aff1 = meas + 2par + finite - dinf aff2 = zero(GenericAffExpr{Float64, GeneralVariableRef}) # test expressions - @test isempty(setdiff(InfiniteOpt._all_function_variables(aff1), + @test isempty(setdiff(all_expression_variables(aff1), [meas, par, finite, dinf])) - @test InfiniteOpt._all_function_variables(aff2) == GeneralVariableRef[] + @test all_expression_variables(aff2) == GeneralVariableRef[] end # test for GenericQuadExpr @testset "QuadExpr" begin @@ -421,11 +421,11 @@ end quad2 = pt^2 + inf * pt quad3 = zero(GenericQuadExpr{Float64, GeneralVariableRef}) # test expressions - @test isempty(setdiff(InfiniteOpt._all_function_variables(quad1), + @test isempty(setdiff(all_expression_variables(quad1), [meas, par, finite, dinf, pt, inf])) - @test isempty(setdiff(InfiniteOpt._all_function_variables(quad2), + @test isempty(setdiff(all_expression_variables(quad2), [pt, inf])) - @test InfiniteOpt._all_function_variables(quad3) == GeneralVariableRef[] + @test all_expression_variables(quad3) == GeneralVariableRef[] end # test for Array of expressions @testset "AbstractArray" begin @@ -433,9 +433,9 @@ end ex1 = [inf, pt] ex2 = [inf + pt, meas + pt] # test expressions - @test isempty(setdiff(InfiniteOpt._all_function_variables(ex1), + @test isempty(setdiff(all_expression_variables(ex1), [pt, inf])) - @test isempty(setdiff(InfiniteOpt._all_function_variables(ex2), + @test isempty(setdiff(all_expression_variables(ex2), [pt, inf, meas])) end # test for Array of expressions @@ -443,18 +443,18 @@ end # make expressions nlp = sin(pt) + inf / pt # test expressions - @test isempty(setdiff(InfiniteOpt._all_function_variables(nlp), + @test isempty(setdiff(all_expression_variables(nlp), [pt, inf])) end # test backup @testset "Fallback" begin @variable(Model(), x) - @test_throws ErrorException InfiniteOpt._all_function_variables(x) + @test_throws ErrorException all_expression_variables(x) end end -# Test _object_numbers -@testset "_object_numbers" begin +# Test parameter_group_int_indices +@testset "parameter_group_int_indices" begin # initialize model and references m = InfiniteModel() @infinite_parameter(m, par in [0, 1]) @@ -467,21 +467,21 @@ end red = add_variable(m, var) # test for finite variable reference @testset "FiniteVariable" begin - @test InfiniteOpt._object_numbers(pt) == [] - @test InfiniteOpt._object_numbers(finite) == [] + @test InfiniteOpt.parameter_group_int_indices(pt) == [] + @test InfiniteOpt.parameter_group_int_indices(finite) == [] end # test for infinite variable reference @testset "InfiniteVariable" begin - @test InfiniteOpt._object_numbers(inf) == [1] + @test InfiniteOpt.parameter_group_int_indices(inf) == [1] end # test for parameter reference @testset "Parameter" begin - @test InfiniteOpt._object_numbers(par) == [1] - @test InfiniteOpt._object_numbers(pars[1]) == [2] + @test InfiniteOpt.parameter_group_int_indices(par) == [1] + @test InfiniteOpt.parameter_group_int_indices(pars[1]) == [2] end # test for semi-infinite variable reference @testset "SemiInfiniteInfinite" begin - @test InfiniteOpt._object_numbers(red) == [2] + @test InfiniteOpt.parameter_group_int_indices(red) == [2] end # test for GenericAffExpr @testset "AffExpr" begin @@ -489,8 +489,8 @@ end aff1 = inf + inf2 + pt - 3 aff2 = pt + finite - 2 # test expressions - @test sort!(InfiniteOpt._object_numbers(aff1)) == [1, 2] - @test InfiniteOpt._object_numbers(aff2) == [] + @test sort!(InfiniteOpt.parameter_group_int_indices(aff1)) == [1, 2] + @test InfiniteOpt.parameter_group_int_indices(aff2) == [] end # test for GenericQuadExpr @testset "QuadExpr" begin @@ -498,15 +498,15 @@ end quad1 = inf * inf2 + inf + inf2 + pt - 3 - par quad2 = pt * pt + pt + finite - 2 # test expressions - @test sort!(InfiniteOpt._object_numbers(quad1)) == [1, 2] - @test InfiniteOpt._object_numbers(quad2) == [] + @test sort!(InfiniteOpt.parameter_group_int_indices(quad1)) == [1, 2] + @test InfiniteOpt.parameter_group_int_indices(quad2) == [] end # test for GenericNonlinearExpr @testset "GenericNonlinearExpr" begin # make expressions nlp = sin(inf) / pt # test expressions - @test InfiniteOpt._object_numbers(nlp) == [1] + @test InfiniteOpt.parameter_group_int_indices(nlp) == [1] end end diff --git a/test/extensions.jl b/test/extensions.jl index 5aeb9890..f0672484 100644 --- a/test/extensions.jl +++ b/test/extensions.jl @@ -304,6 +304,7 @@ end @test dual(c1) == [-1, -1] @test dual(c2) == [0., -1.] @test dual(c3) == [0., -1.] + @test is_solved_and_feasible(m) # @test optimizer_index(x) == optimizer_index.(transformation_variable(x)) # @test optimizer_index(x0) == optimizer_index(transformation_variable(x0)) # @test optimizer_index(y) == optimizer_index(transformation_variable(y)) diff --git a/test/extensions/backend.jl b/test/extensions/backend.jl index 34667be5..7c20a005 100644 --- a/test/extensions/backend.jl +++ b/test/extensions/backend.jl @@ -75,6 +75,7 @@ InfiniteOpt.transformation_model(backend::NewReformBackend) = backend.model InfiniteOpt.transformation_data(backend::NewReformBackend) = backend.data # Extend JuMP.[get/set]_attribute such to pass and retrieve settings for the backend +# See the docstrings for information on specific MOI attributes that need to be accounted for # Not necessary for `JuMPBackend`s function JuMP.get_attribute(backend::NewReformBackend, attr) # REPLACE WITH ACTUAL @@ -148,10 +149,8 @@ end # To the extend desired, extend any or all of the JuMP API below # Not needed for `JuMPBackend`s -for func in (:set_silent, :unset_silent, :bridge_constraints, - :unset_time_limit_sec, :time_limit_sec, :solver_name, :backend, - :mode, :unsafe_backend, :compute_conflict!, :copy_conflict, - :set_string_names_on_creation) +for func in (:bridge_constraints, :backend, :mode, :unsafe_backend, + :compute_conflict!, :copy_conflict) @eval begin # EXTEND FUNCTION AS APPROPRIATE function JuMP.$func(backend::NewReformBackend) @@ -159,11 +158,21 @@ for func in (:set_silent, :unset_silent, :bridge_constraints, end end end -for func in (:set_time_limit_sec, :set_string_names_on_creation, :add_bridge) +# EXTEND FUNCTION AS APPROPRIATE +function JuMP.add_bridge(backend::NewReformBackend, value) + return JuMP.add_bridge(backend.model, value) +end +for Attr in (:Silent, :TimeLimitSec, :SolverName) @eval begin # EXTEND FUNCTION AS APPROPRIATE - function JuMP.$func(backend::NewReformBackend, value) - return JuMP.$func(backend.model, value) + function JuMP.get_attribute(backend::NewReformBackend, attr::MOI.$Attr) + return JuMP.get_attribute(backend.model, attr) + end + if MOI.$Attr != MOI.SolverName + # EXTEND FUNCTION AS APPROPRIATE + function JuMP.set_attribute(backend::NewReformBackend, attr::MOI.$Attr, value) + return JuMP.set_attribute(backend.model, attr, value) + end end end end @@ -231,7 +240,7 @@ function InfiniteOpt.variable_supports( ) # REPLACE BELOW WITH ACTUAL CORRESPONDENCE TO THE INFINITE VARIABLE SUPPORT VALUES map_dict = backend.data.infvar_to_supports - gvref = InfiniteOpt._make_variable_ref(owner_model(vref), index(vref)) + gvref = InfiniteOpt.GeneralVariableRef(owner_model(vref), index(vref)) haskey(map_dict, gvref) || error("Variable $gvref not used in the backend.") return map_dict[gvref] end @@ -244,7 +253,7 @@ function InfiniteOpt.variable_supports( ) # REPLACE BELOW WITH ACTUAL CORRESPONDENCE TO THE INFINITE VARIABLE SUPPORT VALUES map_dict = backend.data.meas_to_supports - gvref = InfiniteOpt._make_variable_ref(owner_model(mref), index(mref)) + gvref = InfiniteOpt.GeneralVariableRef(owner_model(mref), index(mref)) haskey(map_dict, gvref) || error("Variable $gvref not used in the backend.") return map_dict[gvref] end @@ -272,24 +281,24 @@ function InfiniteOpt.constraint_supports( end # As desired and as appropriate extend any or all of the following JuMP query API -# Not required for `JuMPBackend`S -for func in (:termination_status, :raw_status, :solve_time, :simplex_iterations, - :barrier_iterations, :node_count, :objective_bound, :relative_gap, - :result_count) +# Note `TerminationStatus` is not optional (unless it is a `JuMPBackend`) +# Not required for `JuMPBackend`s +for Attr in (:TerminationStatus, :RawStatusString, :SolveTimeSec, :SimplexIterations, + :BarrierIterations, :NodeCount, :ObjectiveBound, :RelativeGap, + :ResultCount) @eval begin # EXTEND AS NEEDED - function JuMP.$func(backend::NewReformBackend) - return JuMP.$func(backend.model) + function JuMP.get_attribute(backend::NewReformBackend, attr::MOI.$Attr) + return JuMP.get_attribute(backend.model, attr) end end end # Simple result dependent model queries -for func in (:primal_status, :dual_status, :has_values, :has_duals, - :objective_value, :dual_objective_value) +for Attr in (:PrimalStatus, :DualStatus, :ObjectiveValue, :DualObjectiveValue) @eval begin # EXTEND AS NEEDED - function JuMP.$func(backend::NewReformBackend; kwargs...) - return JuMP.$func(backend.model; kwargs...) + function JuMP.get_attribute(backend::NewReformBackend, attr::MOI.$Attr) + return JuMP.get_attribute(backend.model, attr) end end end diff --git a/test/finite_variables.jl b/test/finite_variables.jl index 6e6ee7d4..2669df55 100644 --- a/test/finite_variables.jl +++ b/test/finite_variables.jl @@ -49,8 +49,8 @@ end # _core_variable_object @testset "_core_variable_object" begin - @test InfiniteOpt._core_variable_object(vref) === var - @test InfiniteOpt._core_variable_object(gvref) === var + @test core_object(vref) === var + @test core_object(gvref) === var end @testset "_variable_info" begin @test InfiniteOpt._variable_info(vref) == info @@ -60,9 +60,9 @@ @test isa(InfiniteOpt._update_variable_info(vref, new_info), Nothing) @test InfiniteOpt._variable_info(vref) == new_info end - # _set_core_variable_object - @testset "_set_core_variable_object" begin - @test InfiniteOpt._set_core_variable_object(vref, var) isa Nothing + # _set_core_object + @testset "_set_core_object" begin + @test InfiniteOpt._set_core_object(vref, var) isa Nothing end # JuMP.name @testset "JuMP.name" begin @@ -83,10 +83,6 @@ @test parameter_refs(vref) == () @test parameter_refs(gvref) == () end - # _make_variable_ref - @testset "_make_variable_ref" begin - @test isequal(InfiniteOpt._make_variable_ref(m, idx), gvref) - end # _var_name_dict @testset "_var_name_dict" begin @test InfiniteOpt._var_name_dict(m) isa Nothing @@ -137,7 +133,7 @@ end @testset "JuMP.add_variable" begin idx = FiniteVariableIndex(1) vref = FiniteVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = GeneralVariableRef(m, idx) v = build_variable(error, info) @test isequal(add_variable(m, v, "name"), gvref) @test haskey(InfiniteOpt._data_dictionary(vref), idx) @@ -147,7 +143,7 @@ end # test info addition functions idx = FiniteVariableIndex(2) vref = FiniteVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = GeneralVariableRef(m, idx) @test isequal(add_variable(m, v, "name"), gvref) @test !transformation_backend_ready(m) # lower bound @@ -195,7 +191,7 @@ end # test regular idx = FiniteVariableIndex(1) vref = FiniteVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = GeneralVariableRef(m, idx) @test isequal(@variable(m, x >= 1, Bin), gvref) @test name(vref) == "x" @test lower_bound(vref) == 1 @@ -203,7 +199,7 @@ end # test anan idx = FiniteVariableIndex(2) vref = FiniteVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = GeneralVariableRef(m, idx) @test isequal(@variable(m, binary = true, lower_bound = 1, base_name = "x"), gvref) @test name(vref) == "x" @@ -212,7 +208,7 @@ end # test array idxs = [FiniteVariableIndex(3), FiniteVariableIndex(4)] vrefs = [FiniteVariableRef(m, idx) for idx in idxs] - gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs] + gvrefs = [GeneralVariableRef(m, idx) for idx in idxs] @test isequal(@variable(m, y[1:2] == 2, Int), gvrefs) @test name(vrefs[1]) == "y[1]" @test fix_value(vrefs[2]) == 2 diff --git a/test/general_variables.jl b/test/general_variables.jl index 0c09f33e..2db62b23 100644 --- a/test/general_variables.jl +++ b/test/general_variables.jl @@ -165,7 +165,7 @@ end gvref = GeneralVariableRef(m, 1, TestIndex) # test _core_variable_object (GeneralVariableRef) @testset "_core_variable_object (GeneralVariableRef)" begin - @test_throws MethodError InfiniteOpt._core_variable_object(gvref) + @test_throws MethodError core_object(gvref) end end @@ -253,9 +253,9 @@ end @testset "_parameter_number" begin @test_throws MethodError InfiniteOpt._parameter_number(gvref) end - # test _object_number - @testset "_object_number" begin - @test_throws MethodError InfiniteOpt._object_number(gvref) + # test parameter_group_int_index + @testset "parameter_group_int_index" begin + @test_throws MethodError InfiniteOpt.parameter_group_int_index(gvref) end # test 1 argument methods and fallbacks for f in (:significant_digits, :parameter_value, :derivative_method, diff --git a/test/infinite_variables.jl b/test/infinite_variables.jl index ecaae5fe..d6b4266d 100644 --- a/test/infinite_variables.jl +++ b/test/infinite_variables.jl @@ -59,18 +59,18 @@ end # _core_variable_object @testset "_core_variable_object" begin - @test InfiniteOpt._core_variable_object(vref) === var - @test InfiniteOpt._core_variable_object(gvref) === var + @test core_object(vref) === var + @test core_object(gvref) === var end - # _set_core_variable_object - @testset "_set_core_variable_object" begin - @test InfiniteOpt._set_core_variable_object(vref, var) isa Nothing - @test InfiniteOpt._set_core_variable_object(vref, var2) isa Nothing - @test InfiniteOpt._set_core_variable_object(vref, var) isa Nothing + # _set_core_object + @testset "_set_core_object" begin + @test InfiniteOpt._set_core_object(vref, var) isa Nothing + @test InfiniteOpt._set_core_object(vref, var2) isa Nothing + @test InfiniteOpt._set_core_object(vref, var) isa Nothing end - # _object_numbers - @testset "_object_numbers" begin - @test InfiniteOpt._object_numbers(vref) == [1:6...] + # parameter_group_int_indices + @testset "parameter_group_int_indices" begin + @test InfiniteOpt.parameter_group_int_indices(vref) == [1:6...] end # _parameter_numbers @testset "_parameter_numbers" begin @@ -148,9 +148,9 @@ @test isa(set_name(gvref, "new"), Nothing) @test name(vref) == "new" end - # _make_variable_ref - @testset "_make_variable_ref" begin - @test isequal(InfiniteOpt._make_variable_ref(m, idx), gvref) + # GeneralVariableRef + @testset "GeneralVariableRef" begin + @test isequal(InfiniteOpt.GeneralVariableRef(m, idx), gvref) end # _var_name_dict @testset "_var_name_dict" begin @@ -291,7 +291,7 @@ end tuple = IC.VectorTuple(prefs) @test isequal(build_variable(error, info, Infinite(prefs)).parameter_refs, tuple) @test isequal(build_variable(error, info, Infinite(prefs)).parameter_nums, [3, 4]) - @test isequal(build_variable(error, info, Infinite(prefs)).object_nums, [3]) + @test isequal(build_variable(error, info, Infinite(prefs)).group_int_idxs, [3]) end # _check_parameters_valid @testset "_check_parameters_valid" begin @@ -333,10 +333,10 @@ end # test normal idx = InfiniteVariableIndex(1) vref = InfiniteVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) @test isequal(add_variable(m, v, "name"), gvref) @test haskey(InfiniteOpt._data_dictionary(vref), idx) - @test InfiniteOpt._core_variable_object(vref) == v + @test core_object(vref) == v @test InfiniteOpt._infinite_variable_dependencies(pref) == [idx] @test name(vref) == "name" # prepare infinite variable with all the possible info additions @@ -344,7 +344,7 @@ end # test info addition functions idx = InfiniteVariableIndex(2) vref = InfiniteVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) @test isequal(add_variable(m, v, "name"), gvref) @test !transformation_backend_ready(m) @test !InfiniteOpt._is_vector_start(vref) @@ -388,7 +388,7 @@ end # test integer addition functions idx = InfiniteVariableIndex(3) vref = InfiniteVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) @test isequal(add_variable(m, v, "name"), gvref) @test !transformation_backend_ready(m) @test InfiniteOpt._is_vector_start(vref) @@ -416,13 +416,13 @@ end # test basic defaults idx = InfiniteVariableIndex(1) vref = InfiniteVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) @test isequal(@variable(m, variable_type = Infinite(t)), gvref) @test name(vref) == "" # test more tuple input and variable details idx = InfiniteVariableIndex(2) vref = InfiniteVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) @test isequal(@variable(m, variable_type = Infinite(t, x), base_name = "test", binary = true), gvref) @test name(vref) == "test" @@ -430,13 +430,13 @@ end # test nonanonymous with simple single arg idx = InfiniteVariableIndex(3) vref = InfiniteVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) @test isequal(@variable(m, a, Infinite(x)), gvref) @test name(vref) == "a" # test nonanonymous with complex single arg idx = InfiniteVariableIndex(4) vref = InfiniteVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) @test isequal(@variable(m, 0 <= b <= 1, Infinite(x)), gvref) @test name(vref) == "b" @test lower_bound(vref) == 0 @@ -444,21 +444,21 @@ end # test nonanonymous with reversed single arg idx = InfiniteVariableIndex(5) vref = InfiniteVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) @test isequal(@variable(m, 0 <= c, Infinite(t)), gvref) @test name(vref) == "c" @test lower_bound(vref) == 0 # test multi-argument expr 1 idx = InfiniteVariableIndex(6) vref = InfiniteVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) @test isequal(@variable(m, d == 0, Infinite(t), Int, base_name = "test"), gvref) @test name(vref) == "test" @test fix_value(vref) == 0 # test single start value idx = InfiniteVariableIndex(7) vref = InfiniteVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) @test isequal(@variable(m, aa, Infinite(t), Int, start = 42), gvref) @test name(vref) == "aa" @test start_value_function(vref) isa Function @@ -467,7 +467,7 @@ end # test function start value idx = InfiniteVariableIndex(8) vref = InfiniteVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) func = (a) -> a @test isequal(@variable(m, ab, Infinite(t), Int, start = func), gvref) @test name(vref) == "ab" @@ -479,19 +479,19 @@ end # test anonymous array idxs = [InfiniteVariableIndex(9), InfiniteVariableIndex(10)] vrefs = [InfiniteVariableRef(m, idx) for idx in idxs] - gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs] + gvrefs = [InfiniteOpt.GeneralVariableRef(m, idx) for idx in idxs] @test isequal(@variable(m, [1:2], variable_type = Infinite(t)), gvrefs) @test name(vrefs[1]) == "" # test basic param expression idxs = [InfiniteVariableIndex(11), InfiniteVariableIndex(12)] vrefs = [InfiniteVariableRef(m, idx) for idx in idxs] - gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs] + gvrefs = [InfiniteOpt.GeneralVariableRef(m, idx) for idx in idxs] @test isequal(@variable(m, e[1:2], variable_type = Infinite(t, x)), gvrefs) @test name(vrefs[2]) == "e[2]" # test comparison without params idxs = [InfiniteVariableIndex(13), InfiniteVariableIndex(14)] vrefs = [InfiniteVariableRef(m, idx) for idx in idxs] - gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs] + gvrefs = [InfiniteOpt.GeneralVariableRef(m, idx) for idx in idxs] @test isequal(@variable(m, 0 <= f[1:2] <= 1, Infinite(t, x)), gvrefs) @test name(vrefs[2]) == "f[2]" @test lower_bound(vrefs[1]) == 0 @@ -499,7 +499,7 @@ end # test comparison with call idxs = [InfiniteVariableIndex(15), InfiniteVariableIndex(16)] vrefs = [InfiniteVariableRef(m, idx) for idx in idxs] - gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs] + gvrefs = [InfiniteOpt.GeneralVariableRef(m, idx) for idx in idxs] @test @variable(m, 0 <= g[1:2] <= 1, Infinite(t)) == gvrefs @test name(vrefs[1]) == "g[1]" @test lower_bound(vrefs[1]) == 0 @@ -507,14 +507,14 @@ end # test fixed idxs = [InfiniteVariableIndex(17), InfiniteVariableIndex(18)] vrefs = [InfiniteVariableRef(m, idx) for idx in idxs] - gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs] + gvrefs = [InfiniteOpt.GeneralVariableRef(m, idx) for idx in idxs] @test isequal(@variable(m, h[i = 1:2] == ones(2)[i], Infinite(t)), gvrefs) @test name(vrefs[1]) == "h[1]" @test fix_value(vrefs[1]) == 1 # test containers idxs = [InfiniteVariableIndex(19), InfiniteVariableIndex(20)] vrefs = [InfiniteVariableRef(m, idx) for idx in idxs] - gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs] + gvrefs = [InfiniteOpt.GeneralVariableRef(m, idx) for idx in idxs] svrefs = convert(JuMP.Containers.SparseAxisArray, gvrefs) @test @variable(m, [1:2], Infinite(t), container = SparseAxisArray) isa JuMPC.SparseAxisArray @@ -522,7 +522,7 @@ end # test scalar starts idxs = [InfiniteVariableIndex(21), InfiniteVariableIndex(22)] vrefs = [InfiniteVariableRef(m, idx) for idx in idxs] - gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs] + gvrefs = [InfiniteOpt.GeneralVariableRef(m, idx) for idx in idxs] starts = [2, 5] @test isequal(@variable(m, w[i = 1:2], Infinite(t), start = starts[i]), gvrefs) @test start_value_function(vrefs[1])([0]) == 2 @@ -530,7 +530,7 @@ end # test mixed starts idxs = [InfiniteVariableIndex(23), InfiniteVariableIndex(24)] vrefs = [InfiniteVariableRef(m, idx) for idx in idxs] - gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs] + gvrefs = [InfiniteOpt.GeneralVariableRef(m, idx) for idx in idxs] starts = [(a) -> 2, 5] @test isequal(@variable(m, cat[i = 1:2], Infinite(t), start = starts[i]), gvrefs) @@ -539,7 +539,7 @@ end # test with set idxs = [InfiniteVariableIndex(i) for i in 25:27] vrefs = [InfiniteVariableRef(m, idx) for idx in idxs] - gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs] + gvrefs = [InfiniteOpt.GeneralVariableRef(m, idx) for idx in idxs] @test isequal(gvrefs, @variable(m, [1:3], Infinite(t), set = SecondOrderCone())) @test num_constraints(m, Vector{GeneralVariableRef}, MOI.SecondOrderCone) == 1 end diff --git a/test/macro_expressions.jl b/test/macro_expressions.jl index 20bbf27e..8fcbb021 100644 --- a/test/macro_expressions.jl +++ b/test/macro_expressions.jl @@ -11,7 +11,7 @@ object = MeasureData(meas, "test") mindex = MeasureIndex(1) @test InfiniteOpt._add_data_object(m, object) == mindex - meas = InfiniteOpt._make_variable_ref(m, mindex) + meas = GeneralVariableRef(m, mindex) # test addition @testset "Add" begin # test infinite + measure @@ -99,7 +99,7 @@ end object = MeasureData(meas, "test") mindex = MeasureIndex(1) @test InfiniteOpt._add_data_object(m, object) == mindex - meas = InfiniteOpt._make_variable_ref(m, mindex) + meas = GeneralVariableRef(m, mindex) aff1 = (inf + pt) - 2 aff2 = finite - pt aff3 = (finite - meas) + 1 @@ -187,7 +187,7 @@ end object = MeasureData(meas, "test") mindex = MeasureIndex(1) @test InfiniteOpt._add_data_object(m, object) == mindex - meas = InfiniteOpt._make_variable_ref(m, mindex) + meas = GeneralVariableRef(m, mindex) aff1 = (inf + pt) - 2 aff2 = finite - pt aff3 = (finite - meas) + 1 @@ -275,7 +275,7 @@ end object = MeasureData(meas, "test") mindex = MeasureIndex(1) @test InfiniteOpt._add_data_object(m, object) == mindex - meas = InfiniteOpt._make_variable_ref(m, mindex) + meas = GeneralVariableRef(m, mindex) aff1 = (inf + pt) - 2 aff2 = finite - pt aff3 = (finite - meas) + 1 @@ -424,7 +424,7 @@ end object = MeasureData(meas, "test") mindex = MeasureIndex(1) @test InfiniteOpt._add_data_object(m, object) == mindex - meas = InfiniteOpt._make_variable_ref(m, mindex) + meas = GeneralVariableRef(m, mindex) aff1 = (inf + pt) - 2 aff2 = finite - pt aff3 = (finite - meas) + 1 @@ -532,7 +532,7 @@ end object = MeasureData(meas, "test") mindex = MeasureIndex(1) @test InfiniteOpt._add_data_object(m, object) == mindex - meas = InfiniteOpt._make_variable_ref(m, mindex) + meas = GeneralVariableRef(m, mindex) aff1 = (inf + pt) - 2 aff2 = finite - pt aff3 = (finite - meas) + 1 @@ -638,7 +638,7 @@ end object = MeasureData(meas, "test") mindex = MeasureIndex(1) @test InfiniteOpt._add_data_object(m, object) == mindex - meas = InfiniteOpt._make_variable_ref(m, mindex) + meas = GeneralVariableRef(m, mindex) aff1 = (inf + pt) - 2 aff2 = finite - pt aff3 = (finite - meas) + 1 @@ -756,7 +756,7 @@ end object = MeasureData(meas, "test") mindex = MeasureIndex(1) @test InfiniteOpt._add_data_object(m, object) == mindex - meas = InfiniteOpt._make_variable_ref(m, mindex) + meas = GeneralVariableRef(m, mindex) aff1 = (inf + pt) - 2 aff2 = finite - pt aff3 = (finite - meas) + 1 @@ -875,7 +875,7 @@ end object = MeasureData(meas, "test") mindex = MeasureIndex(1) @test InfiniteOpt._add_data_object(m, object) == mindex - meas = InfiniteOpt._make_variable_ref(m, mindex) + meas = GeneralVariableRef(m, mindex) aff1 = (inf + pt) - 2 aff2 = finite - pt aff3 = (finite - meas) + 1 diff --git a/test/measures.jl b/test/measures.jl index 99e387ce..6483867e 100644 --- a/test/measures.jl +++ b/test/measures.jl @@ -30,22 +30,22 @@ end # test _core_variable_object @testset "_core_variable_object" begin - @test InfiniteOpt._core_variable_object(mref) == meas - @test InfiniteOpt._core_variable_object(gvref) == meas + @test core_object(mref) == meas + @test core_object(gvref) == meas end # test _parameter_numbers @testset "_parameter_numbers" begin @test InfiniteOpt._parameter_numbers(mref) == [1] @test InfiniteOpt._parameter_numbers(gvref) == [1] end - # test _object_numbers - @testset "_object_numbers" begin - @test InfiniteOpt._object_numbers(mref) == [1] - @test InfiniteOpt._object_numbers(gvref) == [1] + # test parameter_group_int_indices + @testset "parameter_group_int_indices" begin + @test InfiniteOpt.parameter_group_int_indices(mref) == [1] + @test InfiniteOpt.parameter_group_int_indices(gvref) == [1] end - # test _set_core_variable_object - @testset "_set_core_variable_object" begin - @test InfiniteOpt._set_core_variable_object(mref, meas) isa Nothing + # test _set_core_object + @testset "_set_core_object" begin + @test InfiniteOpt._set_core_object(mref, meas) isa Nothing end # _measure_dependencies @testset "_measure_dependencies" begin @@ -704,11 +704,11 @@ end # test scalar FunctionalDiscreteMeasureData mref6 = GeneralVariableRef(m, 5, MeasureIndex) @test isequal(measure(inf, data4), mref6) - @test InfiniteOpt._core_variable_object(mref6).data.label == UniformGrid + @test core_object(mref6).data.label == UniformGrid # test multidim FunctionalDiscreteMeasureData mref7 = GeneralVariableRef(m, 6, MeasureIndex) @test isequal(measure(inf5, data5), mref7) - @test InfiniteOpt._core_variable_object(mref7).data.label == WeightedSample + @test core_object(mref7).data.label == WeightedSample # test analytic evaluation @test measure(x, data) isa GeneralVariableRef @test is_analytic(measure(x, data)) diff --git a/test/operators.jl b/test/operators.jl index ec50b79d..e291f02c 100644 --- a/test/operators.jl +++ b/test/operators.jl @@ -12,7 +12,7 @@ object = MeasureData(meas, "test") mindex = MeasureIndex(1) @test InfiniteOpt._add_data_object(m, object) == mindex - meas = InfiniteOpt._make_variable_ref(m, mindex) + meas = InfiniteOpt.GeneralVariableRef(m, mindex) # test addition @testset "Base.:+" begin # test infinite + measure @@ -98,7 +98,7 @@ end object = MeasureData(meas, "test") mindex = MeasureIndex(1) @test InfiniteOpt._add_data_object(m, object) == mindex - meas = InfiniteOpt._make_variable_ref(m, mindex) + meas = InfiniteOpt.GeneralVariableRef(m, mindex) aff1 = (inf + pt) - 2 aff2 = finite - pt aff3 = (finite - meas) + 1 @@ -180,7 +180,7 @@ end object = MeasureData(meas, "test") mindex = MeasureIndex(1) @test InfiniteOpt._add_data_object(m, object) == mindex - meas = InfiniteOpt._make_variable_ref(m, mindex) + meas = InfiniteOpt.GeneralVariableRef(m, mindex) aff1 = (inf + pt) - 2 aff2 = finite - pt aff3 = (finite - meas) + 1 @@ -263,7 +263,7 @@ end object = MeasureData(meas, "test") mindex = MeasureIndex(1) @test InfiniteOpt._add_data_object(m, object) == mindex - meas = InfiniteOpt._make_variable_ref(m, mindex) + meas = InfiniteOpt.GeneralVariableRef(m, mindex) aff1 = (inf + pt) - 2 aff2 = finite - pt aff3 = (finite - meas) + 1 @@ -407,7 +407,7 @@ end object = MeasureData(meas, "test") mindex = MeasureIndex(1) @test InfiniteOpt._add_data_object(m, object) == mindex - meas = InfiniteOpt._make_variable_ref(m, mindex) + meas = InfiniteOpt.GeneralVariableRef(m, mindex) aff1 = (inf + pt) - 2 aff2 = finite - pt aff3 = (finite - meas) + 1 @@ -508,7 +508,7 @@ end object = MeasureData(meas, "test") mindex = MeasureIndex(1) @test InfiniteOpt._add_data_object(m, object) == mindex - meas = InfiniteOpt._make_variable_ref(m, mindex) + meas = InfiniteOpt.GeneralVariableRef(m, mindex) aff1 = (inf + pt) - 2 aff2 = finite - pt aff3 = (finite - meas) + 1 @@ -609,7 +609,7 @@ end object = MeasureData(meas, "test") mindex = MeasureIndex(1) @test InfiniteOpt._add_data_object(m, object) == mindex - meas = InfiniteOpt._make_variable_ref(m, mindex) + meas = InfiniteOpt.GeneralVariableRef(m, mindex) aff1 = (inf + pt) - 2 aff2 = finite - pt aff3 = (finite - meas) + 1 @@ -722,7 +722,7 @@ end object = MeasureData(meas, "test") mindex = MeasureIndex(1) @test InfiniteOpt._add_data_object(m, object) == mindex - meas = InfiniteOpt._make_variable_ref(m, mindex) + meas = InfiniteOpt.GeneralVariableRef(m, mindex) aff1 = (inf + pt) - 2 aff2 = finite - pt aff3 = (finite - meas) + 1 @@ -835,7 +835,7 @@ end object = MeasureData(meas, "test") mindex = MeasureIndex(1) @test InfiniteOpt._add_data_object(m, object) == mindex - meas = InfiniteOpt._make_variable_ref(m, mindex) + meas = InfiniteOpt.GeneralVariableRef(m, mindex) aff1 = (inf + pt) - 2 aff2 = finite - pt aff3 = (finite - meas) + 1 diff --git a/test/point_variables.jl b/test/point_variables.jl index e61e9992..33146d50 100644 --- a/test/point_variables.jl +++ b/test/point_variables.jl @@ -51,12 +51,12 @@ end # _core_variable_object @testset "_core_variable_object" begin - @test InfiniteOpt._core_variable_object(vref) === var - @test InfiniteOpt._core_variable_object(gvref) === var + @test core_object(vref) === var + @test core_object(gvref) === var end - # _set_core_variable_object - @testset "_set_core_variable_object" begin - @test InfiniteOpt._set_core_variable_object(vref, var) isa Nothing + # _set_core_object + @testset "_set_core_object" begin + @test InfiniteOpt._set_core_object(vref, var) isa Nothing end @testset "_variable_info" begin @test InfiniteOpt._variable_info(vref) == info @@ -118,9 +118,9 @@ @test isa(set_name(gvref, "a"), Nothing) @test name(vref) == "a" end - # _make_variable_ref - @testset "_make_variable_ref" begin - @test isequal(InfiniteOpt._make_variable_ref(m, idx), gvref) + # GeneralVariableRef + @testset "GeneralVariableRef" begin + @test isequal(InfiniteOpt.GeneralVariableRef(m, idx), gvref) end # _var_name_dict @testset "_var_name_dict" begin @@ -359,7 +359,7 @@ end v = build_variable(error, info, Point(ivref, 0, 1)) idx = PointVariableIndex(1) vref = PointVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) @test isequal(add_variable(m, v, "name"), gvref) @test haskey(InfiniteOpt._data_dictionary(vref), idx) @test supports(pref) == [0] @@ -371,7 +371,7 @@ end # test info addition functions idx = PointVariableIndex(2) vref = PointVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) @test isequal(add_variable(m, v, "name"), gvref) @test !transformation_backend_ready(m) # lower bound @@ -415,7 +415,7 @@ end # test integer addition functions idx = PointVariableIndex(3) vref = PointVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) @test isequal(add_variable(m, v, "name"), gvref) @test !transformation_backend_ready(m) cindex = InfOptConstraintIndex(8) @@ -432,7 +432,7 @@ end v = build_variable(error, info, Point(ivref, 0, 1)) idx = PointVariableIndex(1) vref = PointVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) @test isequal(add_variable(m, v, "name2"), gvref) @test haskey(InfiniteOpt._data_dictionary(vref), idx) @test supports(pref) == [0, 1] @@ -443,7 +443,7 @@ end v = build_variable(error, info4, Point(ivref, 0, 1)) idx = PointVariableIndex(1) vref = PointVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) @test isequal(add_variable(m, v), gvref) @test haskey(InfiniteOpt._data_dictionary(vref), idx) @test supports(pref) == [0, 1] @@ -464,7 +464,7 @@ end v = build_variable(error, info5, Point(ivref, 0, 1)) idx = PointVariableIndex(1) vref = PointVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) @test isequal(add_variable(m, v, "name4"), gvref) @test haskey(InfiniteOpt._data_dictionary(vref), idx) @test supports(pref) == [0, 1] @@ -485,7 +485,7 @@ end v = build_variable(error, info, Point(ivref, 0, 1)) idx = PointVariableIndex(1) vref = PointVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) @test isequal(add_variable(m, v, "name5"), gvref) @test haskey(InfiniteOpt._data_dictionary(vref), idx) @test supports(pref) == [0, 1] @@ -501,7 +501,7 @@ end v = build_variable(error, info, Point(ivref2, 0, [1, 1])) idx = PointVariableIndex(4) vref = PointVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) @test isequal(add_variable(m, v, "name"), gvref) @test haskey(InfiniteOpt._data_dictionary(vref), idx) @test supports(pref) == [0, 1] @@ -523,7 +523,7 @@ end # test simple anon case idx = PointVariableIndex(1) vref = PointVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) @test isequal(@variable(m, variable_type = Point(z, 0, [0, 0])), gvref) @test isequal(infinite_variable_ref(vref), z) @test parameter_values(vref) == (0, [0, 0]) @@ -533,7 +533,7 @@ end # test anon with changes to fixed idx = PointVariableIndex(2) vref = PointVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) @test isequal(@variable(m, variable_type = Point(z, 0, [1, 1]), lower_bound = -5, binary = true), gvref) @test isequal(infinite_variable_ref(vref), z) @@ -544,7 +544,7 @@ end # test regular with alias idx = PointVariableIndex(1) vref = PointVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) @test isequal(@variable(m, z0, Point(z, 0, [0, 0]), Bin), gvref) @test isequal(infinite_variable_ref(vref), z) @test parameter_values(vref) == (0, [0, 0]) @@ -554,7 +554,7 @@ end # test regular with semi anon idx = PointVariableIndex(1) vref = PointVariableRef(m, idx) - gvref = InfiniteOpt._make_variable_ref(m, idx) + gvref = InfiniteOpt.GeneralVariableRef(m, idx) @test isequal(@variable(m, variable_type = Point(z, 0, [0, 0]), base_name = "z0", binary = true), gvref) @test isequal(infinite_variable_ref(vref), z) @@ -568,7 +568,7 @@ end # test anon array with one infvar idxs = [PointVariableIndex(1), PointVariableIndex(1)] vrefs = [PointVariableRef(m, idx) for idx in idxs] - gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs] + gvrefs = [InfiniteOpt.GeneralVariableRef(m, idx) for idx in idxs] @test isequal(@variable(m, [1:2], Point(z, 0, [0, 0])), gvrefs) @test isequal(infinite_variable_ref(vrefs[1]), z) @test parameter_values(vrefs[2]) == (0, [0, 0]) @@ -577,7 +577,7 @@ end # test anon array with different inf vars idxs = [PointVariableIndex(3), PointVariableIndex(4)] vrefs = [PointVariableRef(m, idx) for idx in idxs] - gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs] + gvrefs = [InfiniteOpt.GeneralVariableRef(m, idx) for idx in idxs] @test isequal(@variable(m, [i = 1:2], Point(z2[i], 0)), gvrefs) @test isequal(infinite_variable_ref(vrefs[1]), z2[1]) @test isequal(infinite_variable_ref(vrefs[2]), z2[2]) @@ -587,7 +587,7 @@ end # test array with same infvar idxs = [PointVariableIndex(1), PointVariableIndex(5)] vrefs = [PointVariableRef(m, idx) for idx in idxs] - gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs] + gvrefs = [InfiniteOpt.GeneralVariableRef(m, idx) for idx in idxs] @test isequal(@variable(m, a[i = 1:2], Point(z, -1 + i, [0, 0]), Bin), gvrefs) @test isequal(infinite_variable_ref(vrefs[1]), z) @test parameter_values(vrefs[2]) == (1, [0, 0]) @@ -597,7 +597,7 @@ end # test test array with differnt infvars idxs = [PointVariableIndex(3), PointVariableIndex(4)] vrefs = [PointVariableRef(m, idx) for idx in idxs] - gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs] + gvrefs = [InfiniteOpt.GeneralVariableRef(m, idx) for idx in idxs] @test isequal(@variable(m, b[i = 1:2] >= -5, Point(z2[i], 0)), gvrefs) @test isequal(infinite_variable_ref(vrefs[1]), z2[1]) @test isequal(infinite_variable_ref(vrefs[2]), z2[2]) @@ -607,7 +607,7 @@ end # test semi anon array idxs = [PointVariableIndex(6), PointVariableIndex(7)] vrefs = [PointVariableRef(m, idx) for idx in idxs] - gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs] + gvrefs = [InfiniteOpt.GeneralVariableRef(m, idx) for idx in idxs] @test isequal(@variable(m, [i = 1:2], Point(z2[i], 1), lower_bound = -5), gvrefs) @test isequal(infinite_variable_ref(vrefs[1]), z2[1]) @test isequal(infinite_variable_ref(vrefs[2]), z2[2]) diff --git a/test/results.jl b/test/results.jl index 855ee084..cf3633db 100644 --- a/test/results.jl +++ b/test/results.jl @@ -10,8 +10,23 @@ @objective(m, Min, g^2) @constraint(m, c1, 2 * inf * g <= 1) tb = m.backend - JuMP.optimize!(m) + + # test not optimized yet + set_objective_sense(m, MOI.MAX_SENSE) + @testset "Not solved yet" begin + for f in (solve_time, simplex_iterations, + barrier_iterations, node_count) + @test_throws ErrorException f(m) + end + @test termination_status(m) == MOI.OPTIMIZE_NOT_CALLED + @test result_count(m) == 0 + @test raw_status(m) == "optimize not called" + @test primal_status(m) == MOI.NO_SOLUTION + @test dual_status(m) == MOI.NO_SOLUTION + end + # setup the results + JuMP.optimize!(m) mockoptimizer = JuMP.backend(tb).optimizer.model MOI.set(mockoptimizer, MOI.TerminationStatus(), MOI.OPTIMAL) MOI.set(mockoptimizer, MOI.RawStatusString(), "solver specific string") @@ -25,10 +40,21 @@ MOI.set(mockoptimizer, MOI.RelativeGap(), 9.0) MOI.set(mockoptimizer, MOI.NodeCount(), Int64(2)) MOI.set(mockoptimizer, MOI.SolveTimeSec(), 0.42) + + # make model to set fallbacks + test_model = InfiniteModel(TestBackend()) + set_transformation_backend_ready(test_model, true) + # test termination_status @testset "JuMP.termination_status" begin @test termination_status(m) == MOI.OPTIMAL end + # test is_solved_and_feasible + @testset "JuMP.is_solved_and_feasible" begin + @test is_solved_and_feasible(m) + @test !is_solved_and_feasible(test_model) + @test is_solved_and_feasible(test_model, allow_almost = true, dual = true) + end # test primal_status @testset "JuMP.primal_status" begin @test primal_status(m) == MOI.FEASIBLE_POINT @@ -69,10 +95,20 @@ end # test fallbacks @testset "Fallbacks" begin - for f in (termination_status, raw_status, solve_time, simplex_iterations, + for f in (raw_status, solve_time, simplex_iterations, barrier_iterations, node_count, result_count) - @test_throws ErrorException f(TestBackend()) + @test_throws ErrorException f(test_model) + end + end + # test model not up to date + set_objective_sense(m, MOI.MAX_SENSE) + @testset "Not up-to-date" begin + for f in (solve_time, simplex_iterations, + barrier_iterations, node_count) + @test_throws ErrorException f(m) end + @test raw_status(m) == "optimize not called" + @test result_count(m) == 0 end end @@ -99,10 +135,13 @@ end MOI.set(mockoptimizer, MOI.PrimalStatus(), MOI.FEASIBLE_POINT) MOI.set(mockoptimizer, MOI.DualStatus(), MOI.FEASIBLE_POINT) MOI.set(mockoptimizer, MOI.ConstraintDual(), JuMP.optimizer_index(c1), -2.0) + # make model to set fallbacks + test_model = InfiniteModel(TestBackend()) + # test objective_bound @testset "JuMP.objective_bound" begin @test objective_bound(m) == 2.0 end - # test objective_bound + # test objective_value @testset "JuMP.objective_value" begin @test objective_value(m) == -1. end @@ -113,7 +152,14 @@ end # test fallbacks @testset "Fallbacks" begin for f in (objective_bound, objective_value, dual_objective_value) - @test_throws ErrorException f(TestBackend()) + @test_throws ErrorException f(test_model) + end + end + # test model not up to date + set_objective_sense(m, MOI.MAX_SENSE) + @testset "Not up-to-date" begin + for f in (objective_bound, objective_value, dual_objective_value) + @test_throws ErrorException f(m) end end end @@ -228,6 +274,13 @@ end @testset "JuMP.dual" begin @test_throws ErrorException dual(g) end + # test model not up to date + set_objective_sense(m, MOI.MAX_SENSE) + @testset "Not up-to-date" begin + @test_throws ErrorException value(inf) + @test_throws ErrorException reduced_cost(inf) + @test_throws ErrorException optimizer_index(inf) + end end # Test expression/measure queries @@ -289,6 +342,12 @@ end @testset "JuMP.dual" begin @test_throws ErrorException dual(meas1) end + # test model not up to date + set_objective_sense(m, MOI.MAX_SENSE) + @testset "Not up-to-date" begin + @test_throws ErrorException value(meas1) + @test value(zero(AffExpr) + 1) == 1 + end end # Test constraint queries @@ -382,6 +441,13 @@ end @test shadow_price(c4) == [-2, -3] @test_throws ErrorException InfiniteOpt.map_shadow_price(c1, TestBackend()) end + # test model not up to date + set_objective_sense(m, MOI.MAX_SENSE) + @testset "Not up-to-date" begin + @test_throws ErrorException dual(c1) + @test_throws ErrorException shadow_price(c1) + @test_throws ErrorException optimizer_index(c1) + end end # Test LP sensitivity methods @@ -442,4 +508,9 @@ end @test lp_sensitivity_report(m)[g] == (0, 0) @test lp_sensitivity_report(m)[inf, label = UserDefined] == [(0, 0), (0, 0)] @test lp_sensitivity_report(m)[inf, ndarray = true] == [(0, 0), (0, 0)] + # test model not up to date + set_objective_sense(m, MOI.MIN_SENSE) + @testset "Not up-to-date" begin + @test_throws ErrorException lp_sensitivity_report(m) + end end \ No newline at end of file diff --git a/test/scalar_parameters.jl b/test/scalar_parameters.jl index 546c367a..8396be0c 100644 --- a/test/scalar_parameters.jl +++ b/test/scalar_parameters.jl @@ -29,7 +29,7 @@ @testset "_add_data_object" begin @test InfiniteOpt._add_data_object(m, ind_object) == ind_idx @test InfiniteOpt._add_data_object(m, fin_object) == fin_idx - @test InfiniteOpt._param_object_indices(m)[end] == ind_idx + @test InfiniteOpt.parameter_group_indices(m)[end] == ind_idx end # test _data_dictionary @testset "_data_dictionary" begin @@ -51,10 +51,10 @@ end # test _core_variable_object @testset "_core_variable_object" begin - @test InfiniteOpt._core_variable_object(ind_pref) == ind_param - @test InfiniteOpt._core_variable_object(ind_gvref) == ind_param - @test InfiniteOpt._core_variable_object(fin_pref) == fin_param - @test InfiniteOpt._core_variable_object(fin_gvref) == fin_param + @test core_object(ind_pref) == ind_param + @test core_object(ind_gvref) == ind_param + @test core_object(fin_pref) == fin_param + @test core_object(fin_gvref) == fin_param end # test _parameter_number @testset "_parameter_number" begin @@ -66,15 +66,15 @@ @test InfiniteOpt._parameter_numbers(ind_pref) == [1] @test InfiniteOpt._parameter_numbers(ind_gvref) == [1] end - # test _object_number - @testset "_object_number" begin - @test InfiniteOpt._object_number(ind_pref) == 1 - @test InfiniteOpt._object_number(ind_gvref) == 1 + # test parameter_group_int_index + @testset "parameter_group_int_index" begin + @test InfiniteOpt.parameter_group_int_index(ind_pref) == 1 + @test InfiniteOpt.parameter_group_int_index(ind_gvref) == 1 end - # test _object_numbers - @testset "_object_numbers" begin - @test InfiniteOpt._object_numbers(ind_pref) == [1] - @test InfiniteOpt._object_numbers(ind_gvref) == [1] + # test parameter_group_int_indices + @testset "parameter_group_int_indices" begin + @test InfiniteOpt.parameter_group_int_indices(ind_pref) == [1] + @test InfiniteOpt.parameter_group_int_indices(ind_gvref) == [1] end # test _adaptive_data_update @testset "_adaptive_data_update" begin @@ -82,17 +82,17 @@ p = IndependentParameter(IntervalDomain(0, 2), supps_dict, 12, method, info) data = InfiniteOpt._data_object(ind_pref) @test InfiniteOpt._adaptive_data_update(ind_pref, p, data) isa Nothing - @test InfiniteOpt._core_variable_object(ind_pref) == p + @test core_object(ind_pref) == p # test change of different types p = IndependentParameter(IntervalDomain(0, 2), supps_dict, 12, TestMethod(), info) data = InfiniteOpt._data_object(ind_pref) @test InfiniteOpt._adaptive_data_update(ind_pref, p, data) isa Nothing - @test InfiniteOpt._core_variable_object(ind_pref) == p + @test core_object(ind_pref) == p end - # test _set_core_variable_object - @testset "_set_core_variable_object" begin - @test InfiniteOpt._set_core_variable_object(ind_pref, ind_param) isa Nothing - @test InfiniteOpt._set_core_variable_object(fin_pref, fin_param) isa Nothing + # test _set_core_object + @testset "_set_core_object" begin + @test InfiniteOpt._set_core_object(ind_pref, ind_param) isa Nothing + @test InfiniteOpt._set_core_object(fin_pref, fin_param) isa Nothing end # test _delete_data_object @testset "_delete_data_object" begin @@ -215,12 +215,12 @@ end method, geninfo) expected = GeneralVariableRef(m, 1, IndependentParameterIndex, -1) @test isequal(add_parameter(m, param), expected) - @test InfiniteOpt._core_variable_object(expected) == param - @test InfiniteOpt._param_object_indices(m)[InfiniteOpt._object_number(expected)] == index(expected) + @test core_object(expected) == param + @test InfiniteOpt.parameter_group_indices(m)[InfiniteOpt.parameter_group_int_index(expected)] == index(expected) param = FiniteParameter(1.5) expected = GeneralVariableRef(m, 1, FiniteParameterIndex, -1) @test isequal(add_parameter(m, param), expected) - @test InfiniteOpt._core_variable_object(expected) == param + @test core_object(expected) == param end end @@ -310,10 +310,6 @@ end @test isa(set_name(dpref, "test"), Nothing) @test name(dpref) == "test" end - # _make_parameter_ref - @testset "_make_parameter_ref" begin - @test InfiniteOpt._make_parameter_ref(m, IndependentParameterIndex(1)) == pref - end # _param_name_dict @testset "_param_name_dict" begin @test isa(InfiniteOpt._param_name_dict(m), Nothing) @@ -343,17 +339,17 @@ end @testset "Single" begin pref = GeneralVariableRef(m, 1, IndependentParameterIndex) @test isequal(@infinite_parameter(m, a in [0, 1]), pref) - @test InfiniteOpt._core_variable_object(pref).domain == IntervalDomain(0, 1) + @test core_object(pref).domain == IntervalDomain(0, 1) @test name(pref) == "a" pref = GeneralVariableRef(m, 2, IndependentParameterIndex) @test isequal(@infinite_parameter(m, b ~ Normal(), supports = [1; 2]), pref) - @test InfiniteOpt._core_variable_object(pref).domain == UniDistributionDomain(Normal()) - @test InfiniteOpt._core_variable_object(pref).supports == SortedDict(i => Set{DataType}([UserDefined]) for i in [1,2]) + @test core_object(pref).domain == UniDistributionDomain(Normal()) + @test core_object(pref).supports == SortedDict(i => Set{DataType}([UserDefined]) for i in [1,2]) pref = GeneralVariableRef(m, 3, IndependentParameterIndex) @test isequal(@infinite_parameter(m, c ∈ IntervalDomain(0, 1)), pref) - @test InfiniteOpt._core_variable_object(pref).domain == IntervalDomain(0, 1) + @test core_object(pref).domain == IntervalDomain(0, 1) pref = GeneralVariableRef(m, 4, IndependentParameterIndex) @test isequal(@infinite_parameter(m; domain = IntervalDomain(0, 1), @@ -363,54 +359,54 @@ end pref = GeneralVariableRef(m, 5, IndependentParameterIndex) @test isequal(@infinite_parameter(m, distribution = Normal()), pref) @test name(pref) == "" - @test InfiniteOpt._core_variable_object(pref).domain == UniDistributionDomain(Normal()) + @test core_object(pref).domain == UniDistributionDomain(Normal()) pref = GeneralVariableRef(m, 6, IndependentParameterIndex) @test isequal(@infinite_parameter(m, z in [0, 1], derivative_method = TestMethod()), pref) - @test InfiniteOpt._core_variable_object(pref).domain == IntervalDomain(0, 1) + @test core_object(pref).domain == IntervalDomain(0, 1) @test name(pref) == "z" @test derivative_method(pref) isa TestMethod - @test InfiniteOpt._param_object_indices(m)[InfiniteOpt._object_number(pref)] == index(pref) + @test InfiniteOpt.parameter_group_indices(m)[InfiniteOpt.parameter_group_int_index(pref)] == index(pref) end # multiple parameters @testset "Array" begin prefs = [GeneralVariableRef(m, i, IndependentParameterIndex) for i in 7:8] @test isequal(@infinite_parameter(m, e[1:2] in [0, 1], independent = true), prefs) - @test InfiniteOpt._core_variable_object(prefs[1]).domain == IntervalDomain(0, 1) - @test InfiniteOpt._core_variable_object(prefs[2]).domain == IntervalDomain(0, 1) + @test core_object(prefs[1]).domain == IntervalDomain(0, 1) + @test core_object(prefs[2]).domain == IntervalDomain(0, 1) prefs = [GeneralVariableRef(m, i, IndependentParameterIndex) for i in 9:10] @test isequal(@infinite_parameter(m, [1:2]; domain = IntervalDomain(0, 1), independent = true), prefs) - @test InfiniteOpt._core_variable_object(prefs[1]).domain == IntervalDomain(0, 1) - @test InfiniteOpt._core_variable_object(prefs[2]).domain == IntervalDomain(0, 1) + @test core_object(prefs[1]).domain == IntervalDomain(0, 1) + @test core_object(prefs[2]).domain == IntervalDomain(0, 1) prefs = [GeneralVariableRef(m, i, IndependentParameterIndex) for i in 11:12] domains = [IntervalDomain(0, 1), IntervalDomain(-1, 2)] @test isequal(@infinite_parameter(m, f[i = 1:2], domain = domains[i], independent = true), prefs) - @test InfiniteOpt._core_variable_object(prefs[1]).domain == IntervalDomain(0, 1) - @test InfiniteOpt._core_variable_object(prefs[2]).domain == IntervalDomain(-1, 2) + @test core_object(prefs[1]).domain == IntervalDomain(0, 1) + @test core_object(prefs[2]).domain == IntervalDomain(-1, 2) prefs = [GeneralVariableRef(m, i, IndependentParameterIndex) for i in 13:14] @test isequal(@infinite_parameter(m, [i = 1:2], domain = domains[i], independent = true), prefs) - @test InfiniteOpt._core_variable_object(prefs[1]).domain == IntervalDomain(0, 1) - @test InfiniteOpt._core_variable_object(prefs[2]).domain == IntervalDomain(-1, 2) + @test core_object(prefs[1]).domain == IntervalDomain(0, 1) + @test core_object(prefs[2]).domain == IntervalDomain(-1, 2) prefs = [GeneralVariableRef(m, i, IndependentParameterIndex) for i in 15:16] @test isequal(@infinite_parameter(m, g[i = 1:2] in [1 - i, i], independent = true), prefs) - @test InfiniteOpt._core_variable_object(prefs[1]).domain == IntervalDomain(0, 1) - @test InfiniteOpt._core_variable_object(prefs[2]).domain == IntervalDomain(-1, 2) + @test core_object(prefs[1]).domain == IntervalDomain(0, 1) + @test core_object(prefs[2]).domain == IntervalDomain(-1, 2) prefs = [GeneralVariableRef(m, i, IndependentParameterIndex) for i in 17:18] prefs = convert(JuMP.Containers.SparseAxisArray, prefs) @test all(isequal.(@infinite_parameter(m, i[1:2] ~ Normal(); independent = true, container = SparseAxisArray), prefs)) - @test InfiniteOpt._core_variable_object(prefs[1]).domain == UniDistributionDomain(Normal()) - @test InfiniteOpt._core_variable_object(prefs[2]).domain == UniDistributionDomain(Normal()) - @test InfiniteOpt._param_object_indices(m)[InfiniteOpt._object_number(prefs[2])] == index(prefs[2]) + @test core_object(prefs[1]).domain == UniDistributionDomain(Normal()) + @test core_object(prefs[2]).domain == UniDistributionDomain(Normal()) + @test InfiniteOpt.parameter_group_indices(m)[InfiniteOpt.parameter_group_int_index(prefs[2])] == index(prefs[2]) end # test for errors @testset "Errors" begin @@ -615,7 +611,7 @@ end 2.5 => Set([InternalLabel]), 5 => Set([All])) new_param = IndependentParameter(IntervalDomain(0, 5), supps, 6, method, info) - InfiniteOpt._set_core_variable_object(dpref, new_param) + InfiniteOpt._set_core_object(dpref, new_param) push!(InfiniteOpt._measure_dependencies(dpref), MeasureIndex(-1)) # test Base.copy @testset "Base.copy" begin @@ -1013,17 +1009,17 @@ end # test anonymous definition pref = GeneralVariableRef(m, 1, FiniteParameterIndex) @test @finite_parameter(m, 42) == pref - @test InfiniteOpt._core_variable_object(pref).value == 42 + @test core_object(pref).value == 42 @test name(pref) == "" # test vector anonymous definition prefs = [GeneralVariableRef(m, i, FiniteParameterIndex) for i in 2:3] @test @finite_parameter(m, [1:2] == 42; base_name = "a") == prefs - @test InfiniteOpt._core_variable_object(prefs[1]).value == 42 + @test core_object(prefs[1]).value == 42 @test name.(prefs) == ["a[1]", "a[2]"] # test named definition pref = GeneralVariableRef(m, 4, FiniteParameterIndex) @test @finite_parameter(m, b == 42) == pref - @test InfiniteOpt._core_variable_object(pref).value == 42 + @test core_object(pref).value == 42 @test name(pref) == "b" @test m[:b] == pref # test named vector definition @@ -1031,7 +1027,7 @@ end prefs = convert(JuMPC.SparseAxisArray, prefs) @test @finite_parameter(m, c[i = 1:2] == [3, 7][i], container = SparseAxisArray) == prefs - @test InfiniteOpt._core_variable_object(prefs[2]).value == 7 + @test core_object(prefs[2]).value == 7 @test name(prefs[2]) == "c[2]" end # initialize the model diff --git a/test/semi_infinite_variables.jl b/test/semi_infinite_variables.jl index d80c54e9..b80685f2 100644 --- a/test/semi_infinite_variables.jl +++ b/test/semi_infinite_variables.jl @@ -51,12 +51,12 @@ end # _core_variable_object @testset "_core_variable_object" begin - @test InfiniteOpt._core_variable_object(vref) === var - @test InfiniteOpt._core_variable_object(gvref) === var + @test core_object(vref) === var + @test core_object(gvref) === var end - # _set_core_variable_object - @testset "_set_core_variable_object" begin - @test InfiniteOpt._set_core_variable_object(vref, var) isa Nothing + # _set_core_object + @testset "_set_core_object" begin + @test InfiniteOpt._set_core_object(vref, var) isa Nothing end # _measure_dependencies @testset "_measure_dependencies" begin @@ -73,9 +73,9 @@ @test InfiniteOpt._derivative_dependencies(vref) == DerivativeIndex[] @test InfiniteOpt._derivative_dependencies(gvref) == DerivativeIndex[] end - # _object_numbers - @testset "_object_numbers" begin - @test InfiniteOpt._object_numbers(vref) == [2] + # parameter_group_int_indices + @testset "parameter_group_int_indices" begin + @test InfiniteOpt.parameter_group_int_indices(vref) == [2] end # _parameter_numbers @testset "_parameter_numbers" begin @@ -121,9 +121,9 @@ @test name(vref) == "a" @test name(bad_vref) == "" end - # _make_variable_ref - @testset "_make_variable_ref" begin - @test isequal(InfiniteOpt._make_variable_ref(m, idx), gvref) + # GeneralVariableRef + @testset "GeneralVariableRef" begin + @test isequal(InfiniteOpt.GeneralVariableRef(m, idx), gvref) end # _var_name_dict @testset "_var_name_dict" begin @@ -204,7 +204,7 @@ end # test JuMP.build_variable @testset "JuMP.build_variable" begin # test errors - dvref = InfiniteOpt._make_variable_ref(m, FiniteVariableIndex(1)) + dvref = InfiniteOpt.GeneralVariableRef(m, FiniteVariableIndex(1)) @test_throws ErrorException build_variable(error, dvref, eval_supps) eval_supps[6] = 1 @test_throws ErrorException build_variable(error, ivref, eval_supps) @@ -215,8 +215,8 @@ end # test normal @test isequal(build_variable(error, ivref, eval_supps).infinite_variable_ref, ivref) @test build_variable(error, ivref, eval_supps).eval_supports === eval_supps - @test build_variable(error, ivref, eval_supps).object_nums == [2] - @test build_variable(error, ivref, eval_supps, check = false).object_nums == [2] + @test build_variable(error, ivref, eval_supps).group_int_idxs == [2] + @test build_variable(error, ivref, eval_supps, check = false).group_int_idxs == [2] @test build_variable(error, ivref, eval_supps, check = false).parameter_nums == [2] end # test JuMP.add_variable @@ -236,7 +236,7 @@ end @test supports(b[2]) == [1] @test supports(c) == zeros(2, 1) @test supports(b[1]) == [] - @test InfiniteOpt._object_numbers(vref) == [2] + @test InfiniteOpt.parameter_group_int_indices(vref) == [2] @test InfiniteOpt._semi_infinite_variable_dependencies(ivref) == [idx] # test with set name (redundant add) @test isequal(add_variable(m, var, "cat"), gvref) diff --git a/test/utilities.jl b/test/utilities.jl index 0964673e..a6c6ded9 100644 --- a/test/utilities.jl +++ b/test/utilities.jl @@ -62,6 +62,11 @@ InfiniteOpt.support_label(::TestGenMethod) = InternalLabel # Define test functions function new_fn end +# Define some fallbacks for TestBackend +JuMP.get_attribute(::TestBackend, ::MOI.TerminationStatus) = MOI.ALMOST_LOCALLY_SOLVED +JuMP.get_attribute(::TestBackend, ::MOI.PrimalStatus) = MOI.NEARLY_FEASIBLE_POINT +JuMP.get_attribute(::TestBackend, ::MOI.DualStatus) = MOI.NEARLY_FEASIBLE_POINT + # Helper function to test IO methods work correctly function show_test(mode, obj, exp_str::String; repl=:both) if mode == MIME("text/plain") @@ -133,11 +138,11 @@ function _update_variable_param_refs(vref::InfiniteVariableRef, # get basic information info = InfiniteOpt._variable_info(vref) param_nums = [InfiniteOpt._parameter_number(pref) for pref in prefs] - # get the parameter object numbers - object_nums = InfiniteOpt._object_numbers(parameter_list(prefs)) + # get the parameter group integer indices + group_int_idxs = InfiniteOpt.parameter_group_int_indices(parameter_list(prefs)) is_vect_func = InfiniteOpt._is_vector_start(vref) - new_var = InfiniteVariable(info, prefs, param_nums, object_nums, is_vect_func) - InfiniteOpt._set_core_variable_object(vref, new_var) + new_var = InfiniteVariable(info, prefs, param_nums, group_int_idxs, is_vect_func) + InfiniteOpt._set_core_object(vref, new_var) return end diff --git a/test/variable_info.jl b/test/variable_info.jl index a1f55976..628a2c8f 100644 --- a/test/variable_info.jl +++ b/test/variable_info.jl @@ -8,12 +8,6 @@ vref1 = dispatch_variable_ref(gvref1) vref2 = dispatch_variable_ref(gvref2) vref3 = dispatch_variable_ref(gvref3) - # _make_constraint_ref - @testset "_temp_constraint_ref" begin - cindex = InfOptConstraintIndex(1) - expected = InfOptConstraintRef(m, cindex) - @test InfiniteOpt._make_constraint_ref(m, cindex) == expected - end # is_fixed @testset "JuMP.is_fixed" begin @test is_fixed(vref3) @@ -68,7 +62,7 @@ cref = LowerBoundRef(vref1) @test InfiniteOpt._data_object(cref).is_info_constraint @test !transformation_backend_ready(m) - @test InfiniteOpt._core_constraint_object(cref) == ScalarConstraint(gvref1, MOI.GreaterThan(1.)) + @test constraint_object(cref) == ScalarConstraint(gvref1, MOI.GreaterThan(1.)) # test changing lower bound @test isa(set_lower_bound(vref2, 1.5), Nothing) @test has_lower_bound(vref2) @@ -76,7 +70,7 @@ cref = LowerBoundRef(vref2) @test InfiniteOpt._data_object(cref).is_info_constraint @test !transformation_backend_ready(m) - @test InfiniteOpt._core_constraint_object(cref) == ScalarConstraint(gvref2, MOI.GreaterThan(1.5)) + @test constraint_object(cref) == ScalarConstraint(gvref2, MOI.GreaterThan(1.5)) # test fixed variable error @test_throws AssertionError set_lower_bound(vref3, 0) end @@ -146,7 +140,7 @@ end cref = UpperBoundRef(vref1) @test InfiniteOpt._data_object(cref).is_info_constraint @test !transformation_backend_ready(m) - @test InfiniteOpt._core_constraint_object(cref) == ScalarConstraint(gvref1, MOI.LessThan(1.)) + @test constraint_object(cref) == ScalarConstraint(gvref1, MOI.LessThan(1.)) # test changing upper bound @test isa(set_upper_bound(vref2, 1.5), Nothing) @test has_upper_bound(vref2) @@ -154,7 +148,7 @@ end cref = UpperBoundRef(vref2) @test InfiniteOpt._data_object(cref).is_info_constraint @test !transformation_backend_ready(m) - @test InfiniteOpt._core_constraint_object(cref) == ScalarConstraint(gvref2, MOI.LessThan(1.5)) + @test constraint_object(cref) == ScalarConstraint(gvref2, MOI.LessThan(1.5)) # test fixed variable error @test_throws AssertionError set_upper_bound(vref3, 0) end @@ -219,7 +213,7 @@ end cref = FixRef(vref1) @test InfiniteOpt._data_object(cref).is_info_constraint @test !transformation_backend_ready(m) - @test InfiniteOpt._core_constraint_object(cref) == ScalarConstraint(gvref1, MOI.EqualTo(1.)) + @test constraint_object(cref) == ScalarConstraint(gvref1, MOI.EqualTo(1.)) # test changing fix @test isa(fix(gvref2, 1.5), Nothing) @test is_fixed(vref2) @@ -227,7 +221,7 @@ end cref = FixRef(vref2) @test InfiniteOpt._data_object(cref).is_info_constraint @test !transformation_backend_ready(m) - @test InfiniteOpt._core_constraint_object(cref) == ScalarConstraint(gvref2, MOI.EqualTo(1.5)) + @test constraint_object(cref) == ScalarConstraint(gvref2, MOI.EqualTo(1.5)) # add lower and upper bounds to vars 3 and 4 set_lower_bound(vref3, 0.0) set_upper_bound(vref4, 0.0) @@ -241,7 +235,7 @@ end cref = FixRef(vref3) @test InfiniteOpt._data_object(cref).is_info_constraint @test !transformation_backend_ready(m) - @test InfiniteOpt._core_constraint_object(cref) == ScalarConstraint(gvref3, MOI.EqualTo(1.)) + @test constraint_object(cref) == ScalarConstraint(gvref3, MOI.EqualTo(1.)) # test forcing with upper @test isa(fix(gvref4, 1.5, force = true), Nothing) @test is_fixed(vref4) @@ -249,7 +243,7 @@ end cref = FixRef(vref4) @test InfiniteOpt._data_object(cref).is_info_constraint @test !transformation_backend_ready(m) - @test InfiniteOpt._core_constraint_object(cref) == ScalarConstraint(gvref4, MOI.EqualTo(1.5)) + @test constraint_object(cref) == ScalarConstraint(gvref4, MOI.EqualTo(1.5)) end end @@ -362,14 +356,14 @@ end cref = BinaryRef(vref1) @test InfiniteOpt._data_object(cref).is_info_constraint @test !transformation_backend_ready(m) - @test InfiniteOpt._core_constraint_object(cref) == ScalarConstraint(gvref1, MOI.ZeroOne()) + @test constraint_object(cref) == ScalarConstraint(gvref1, MOI.ZeroOne()) # test setting binary again @test isa(set_binary(gvref2), Nothing) @test is_binary(vref2) cref = BinaryRef(vref2) @test InfiniteOpt._data_object(cref).is_info_constraint @test !transformation_backend_ready(m) - @test InfiniteOpt._core_constraint_object(cref) == ScalarConstraint(gvref2, MOI.ZeroOne()) + @test constraint_object(cref) == ScalarConstraint(gvref2, MOI.ZeroOne()) # test integer variable error @test_throws ErrorException set_binary(vref3) end @@ -425,14 +419,14 @@ end cref = IntegerRef(vref1) @test InfiniteOpt._data_object(cref).is_info_constraint @test !transformation_backend_ready(m) - @test InfiniteOpt._core_constraint_object(cref) == ScalarConstraint(gvref1, MOI.Integer()) + @test constraint_object(cref) == ScalarConstraint(gvref1, MOI.Integer()) # test setting integer again @test isa(set_integer(gvref2), Nothing) @test is_integer(vref2) cref = IntegerRef(vref2) @test InfiniteOpt._data_object(cref).is_info_constraint @test !transformation_backend_ready(m) - @test InfiniteOpt._core_constraint_object(cref) == ScalarConstraint(gvref2, MOI.Integer()) + @test constraint_object(cref) == ScalarConstraint(gvref2, MOI.Integer()) # test integer variable error @test_throws ErrorException set_integer(vref3) end