@@ -108,6 +108,7 @@ mutable struct Optimizer <: MOI.AbstractOptimizer
108108 time_limit_sec:: Union{Nothing,Float64}
109109 solve_time:: Float64
110110 ideal_point:: Vector{Float64}
111+ compute_ideal_point:: Bool
111112
112113 function Optimizer (optimizer_factory)
113114 return new (
@@ -119,6 +120,7 @@ mutable struct Optimizer <: MOI.AbstractOptimizer
119120 nothing ,
120121 NaN ,
121122 Float64[],
123+ default (ComputeIdealPoint ()),
122124 )
123125 end
124126end
@@ -130,6 +132,7 @@ function MOI.empty!(model::Optimizer)
130132 model. termination_status = MOI. OPTIMIZE_NOT_CALLED
131133 model. solve_time = NaN
132134 empty! (model. ideal_point)
135+ model. compute_ideal_point = default (ComputeIdealPoint ())
133136 return
134137end
135138
@@ -139,7 +142,8 @@ function MOI.is_empty(model::Optimizer)
139142 isempty (model. solutions) &&
140143 model. termination_status == MOI. OPTIMIZE_NOT_CALLED &&
141144 isnan (model. solve_time) &&
142- isempty (model. ideal_point)
145+ isempty (model. ideal_point) &&
146+ model. compute_ideal_point == default (ComputeIdealPoint ())
143147end
144148
145149MOI. supports_incremental_interface (:: Optimizer ) = true
@@ -351,6 +355,33 @@ struct LexicographicAllPermutations <: AbstractAlgorithmAttribute end
351355
352356default (:: LexicographicAllPermutations ) = true
353357
358+ """
359+ ComputeIdealPoint <: AbstractOptimizerAttribute -> Bool
360+
361+ Controls whether to compute the ideal point.
362+
363+ Defaults to true`.
364+
365+ If this attribute is set to `true`, the ideal point can be queried using the
366+ `MOI.ObjectiveBound` attribute.
367+
368+ Computing the ideal point requires as many solves as the dimension of the
369+ objective function. Thus, if you do not need the ideal point information, you
370+ can improve the performance of MOA by setting this attribute to `false`.
371+ """
372+ struct ComputeIdealPoint <: MOI.AbstractOptimizerAttribute end
373+
374+ default (:: ComputeIdealPoint ) = true
375+
376+ MOI. supports (:: Optimizer , :: ComputeIdealPoint ) = true
377+
378+ function MOI. set (model:: Optimizer , :: ComputeIdealPoint , value:: Bool )
379+ model. compute_ideal_point = value
380+ return
381+ end
382+
383+ MOI. get (model:: Optimizer , :: ComputeIdealPoint ) = model. compute_ideal_point
384+
354385# ## RawOptimizerAttribute
355386
356387function MOI. supports (model:: Optimizer , attr:: MOI.RawOptimizerAttribute )
@@ -530,16 +561,12 @@ function MOI.delete(model::Optimizer, ci::MOI.ConstraintIndex)
530561 return
531562end
532563
533- function MOI. optimize! (model:: Optimizer )
534- start_time = time ()
535- empty! (model. solutions)
536- model. termination_status = MOI. OPTIMIZE_NOT_CALLED
537- if model. f === nothing
538- model. termination_status = MOI. INVALID_MODEL
539- return
540- end
564+ function _compute_ideal_point (model:: Optimizer )
541565 objectives = MOI. Utilities. eachscalar (model. f)
542566 model. ideal_point = fill (NaN , length (objectives))
567+ if ! MOI. get (model, ComputeIdealPoint ())
568+ return
569+ end
543570 for (i, f) in enumerate (objectives)
544571 MOI. set (model. inner, MOI. ObjectiveFunction {typeof(f)} (), f)
545572 MOI. optimize! (model. inner)
@@ -548,6 +575,18 @@ function MOI.optimize!(model::Optimizer)
548575 model. ideal_point[i] = MOI. get (model. inner, MOI. ObjectiveValue ())
549576 end
550577 end
578+ return
579+ end
580+
581+ function MOI. optimize! (model:: Optimizer )
582+ start_time = time ()
583+ empty! (model. solutions)
584+ model. termination_status = MOI. OPTIMIZE_NOT_CALLED
585+ if model. f === nothing
586+ model. termination_status = MOI. INVALID_MODEL
587+ return
588+ end
589+ _compute_ideal_point (model)
551590 algorithm = something (model. algorithm, default (Algorithm ()))
552591 status, solutions = optimize_multiobjective! (algorithm, model)
553592 model. termination_status = status
0 commit comments