@@ -7,6 +7,7 @@ module MultiObjectiveAlgorithms
77
88import Combinatorics
99import MathOptInterface as MOI
10+ import Printf
1011
1112"""
1213 struct SolutionPoint
@@ -170,22 +171,30 @@ mutable struct Optimizer <: MOI.AbstractOptimizer
170171 f:: Union{Nothing,MOI.AbstractVectorFunction}
171172 solutions:: Vector{SolutionPoint}
172173 termination_status:: MOI.TerminationStatusCode
174+ silent:: Bool
173175 time_limit_sec:: Union{Nothing,Float64}
176+ start_time:: Float64
174177 solve_time:: Float64
175178 ideal_point:: Vector{Float64}
176179 compute_ideal_point:: Bool
177180 subproblem_count:: Int
178181 optimizer_factory:: Any
179182
180183 function Optimizer (optimizer_factory)
184+ inner = MOI. instantiate (optimizer_factory; with_cache_type = Float64)
185+ if MOI. supports (inner, MOI. Silent ())
186+ MOI. set (inner, MOI. Silent (), true )
187+ end
181188 return new (
182- MOI . instantiate (optimizer_factory; with_cache_type = Float64) ,
189+ inner ,
183190 nothing ,
184191 nothing ,
185192 SolutionPoint[],
186193 MOI. OPTIMIZE_NOT_CALLED,
194+ false ,
187195 nothing ,
188196 NaN ,
197+ NaN ,
189198 Float64[],
190199 _default (ComputeIdealPoint ()),
191200 0 ,
@@ -200,6 +209,7 @@ function MOI.empty!(model::Optimizer)
200209 empty! (model. solutions)
201210 model. termination_status = MOI. OPTIMIZE_NOT_CALLED
202211 model. solve_time = NaN
212+ model. start_time = NaN
203213 empty! (model. ideal_point)
204214 model. subproblem_count = 0
205215 return
@@ -220,6 +230,17 @@ function MOI.copy_to(dest::Optimizer, src::MOI.ModelLike)
220230 return MOI. Utilities. default_copy_to (dest, src)
221231end
222232
233+ # ## Silent
234+
235+ MOI. supports (:: Optimizer , :: MOI.Silent ) = true
236+
237+ MOI. get (model:: Optimizer , :: MOI.Silent ) = model. silent
238+
239+ function MOI. set (model:: Optimizer , :: MOI.Silent , value:: Bool )
240+ model. silent = value
241+ return
242+ end
243+
223244# ## TimeLimitSec
224245
225246function MOI. supports (model:: Optimizer , attr:: MOI.TimeLimitSec )
@@ -646,9 +667,9 @@ function optimize_inner!(model::Optimizer)
646667 return
647668end
648669
649- function _compute_ideal_point (model:: Optimizer , start_time )
670+ function _compute_ideal_point (model:: Optimizer )
650671 for (i, f) in enumerate (MOI. Utilities. eachscalar (model. f))
651- if _check_premature_termination (model, start_time ) != = nothing
672+ if _check_premature_termination (model) != = nothing
652673 return
653674 end
654675 if ! isnan (model. ideal_point[i])
@@ -733,11 +754,11 @@ function _check_interrupt(f)
733754 end
734755end
735756
736- function _check_premature_termination (model:: Optimizer , start_time :: Float64 )
757+ function _check_premature_termination (model:: Optimizer )
737758 return _check_interrupt () do
738759 time_limit = MOI. get (model, MOI. TimeLimitSec ())
739760 if time_limit != = nothing
740- time_remaining = time_limit - (time () - start_time)
761+ time_remaining = time_limit - (time () - model . start_time)
741762 if time_remaining <= 0
742763 return MOI. TIME_LIMIT
743764 end
@@ -754,8 +775,82 @@ function MOI.optimize!(model::Optimizer)
754775 return
755776end
756777
778+ function _print_header (io:: IO , model:: Optimizer )
779+ rule = " -" ^ (7 + 13 * (MOI. output_dimension (model. f) + 1 ))
780+ println (io, rule)
781+ println (io, " MultiObjectiveAlgorithms.jl" )
782+ println (io, rule)
783+ println (
784+ io,
785+ " Algorithm: " ,
786+ replace (
787+ string (typeof (model. algorithm)),
788+ " MultiObjectiveAlgorithms." => " " ,
789+ ),
790+ )
791+ println (io, rule)
792+ print (io, " solve #" )
793+ for i in 1 : MOI. output_dimension (model. f)
794+ print (io, lpad (" Obj. $i " , 13 ))
795+ end
796+ println (io, " Time " )
797+ println (io, rule)
798+ return
799+ end
800+
801+ function _print_footer (io:: IO , model:: Optimizer )
802+ rule = " -" ^ (7 + 13 * (MOI. output_dimension (model. f) + 1 ))
803+ println (io, rule)
804+ println (io, " TerminationStatus: " , model. termination_status)
805+ println (io, " ResultCount: " , length (model. solutions))
806+ println (io, rule)
807+ return
808+ end
809+
810+ """
811+ _log_subproblem_solve(model::Optimizer, variables::Vector{MOI.VariableIndex})
812+
813+ Log the solution. We don't have a pre-computed point, so compute one from the
814+ variable values.
815+ """
816+ function _log_subproblem_solve (model:: Optimizer , arg)
817+ if ! model. silent
818+ _log_subproblem_inner (model, arg)
819+ end
820+ return
821+ end
822+
823+ # Variables; compute the associated Y
824+ function _log_subproblem_inner (model:: Optimizer , x:: Vector{MOI.VariableIndex} )
825+ _, Y = _compute_point (model, x, model. f)
826+ _log_subproblem_solve (model, Y)
827+ return
828+ end
829+
830+ # We have a pre-computed point.
831+ function _log_subproblem_inner (model:: Optimizer , Y:: Vector )
832+ print (_format (model. subproblem_count), " " )
833+ for y in Y
834+ print (" " , _format (y))
835+ end
836+ println (" " , _format (time () - model. start_time))
837+ return
838+ end
839+
840+ # Assume the subproblem failed to solve.
841+ function _log_subproblem_inner (model:: Optimizer , msg:: String )
842+ print (_format (model. subproblem_count), " " )
843+ print (rpad (msg, 13 * MOI. output_dimension (model. f)))
844+ println (" " , _format (time () - model. start_time))
845+ return
846+ end
847+
848+ _format (x:: Int ) = Printf. @sprintf (" %5d" , x)
849+
850+ _format (x:: Float64 ) = Printf. @sprintf (" % .5e" , x)
851+
757852function _optimize! (model:: Optimizer )
758- start_time = time ()
853+ model . start_time = time ()
759854 empty! (model. solutions)
760855 model. termination_status = MOI. OPTIMIZE_NOT_CALLED
761856 model. subproblem_count = 0
@@ -764,6 +859,9 @@ function _optimize!(model::Optimizer)
764859 empty! (model. ideal_point)
765860 return
766861 end
862+ if ! model. silent
863+ _print_header (stdout , model)
864+ end
767865 # We need to clear the ideal point prior to starting the solve. Algorithms
768866 # may update this during the solve, otherwise we will update it at the end.
769867 model. ideal_point = fill (NaN , MOI. output_dimension (model. f))
@@ -774,13 +872,16 @@ function _optimize!(model::Optimizer)
774872 model. solutions = solutions
775873 _sort! (model. solutions, MOI. get (model, MOI. ObjectiveSense ()))
776874 end
875+ if ! model. silent
876+ _print_footer (stdout , model)
877+ end
777878 if MOI. get (model, ComputeIdealPoint ())
778- _compute_ideal_point (model, start_time )
879+ _compute_ideal_point (model)
779880 end
780881 if MOI. supports (model. inner, MOI. TimeLimitSec ())
781882 MOI. set (model. inner, MOI. TimeLimitSec (), nothing )
782883 end
783- model. solve_time = time () - start_time
884+ model. solve_time = time () - model . start_time
784885 return
785886end
786887
0 commit comments