@@ -15,31 +15,6 @@ function _halfspaces(IPS::Vector{Vector{Float64}})
1515 return [(- H_i. a, - H_i. β) for H_i in H]
1616end
1717
18- function _compute_anchors (model:: MOA.Optimizer )
19- anchors = Dict {Vector{Float64},Dict{MOI.VariableIndex,Float64}} ()
20- n = MOI. output_dimension (model. f)
21- scalars = MOI. Utilities. scalarize (model. f)
22- variables = MOI. get (model. inner, MOI. ListOfVariableIndices ())
23- yI, yUB = zeros (n), zeros (n)
24- for (i, f_i) in enumerate (scalars)
25- MOI. set (model. inner, MOI. ObjectiveFunction {typeof(f_i)} (), f_i)
26- MOI. optimize! (model. inner)
27- # status check
28- X, Y = MOA. _compute_point (model, variables, model. f)
29- model. ideal_point[i] = Y[i]
30- yI[i] = Y[i]
31- anchors[Y] = X
32- MOI. set (model. inner, MOI. ObjectiveSense (), MOI. MAX_SENSE)
33- MOI. optimize! (model. inner)
34- # status check
35- _, Y = MOA. _compute_point (model, variables, f_i)
36- yUB[i] = Y
37- MOI. set (model. inner, MOI. ObjectiveSense (), MOI. MIN_SENSE)
38- end
39-
40- return yI, yUB, anchors
41- end
42-
4318function _distance (w̄, b̄, OPS, model)
4419 n = MOI. output_dimension (model. f)
4520 optimizer = typeof (model. inner. optimizer)
6540
6641function _select_next_halfspace (H, OPS, model)
6742 distances = [_distance (w, b, OPS, model) for (w, b) in H]
68- @info " Distances: $(Dict (zip (H, distances))) "
6943 index = argmax (distances)
7044 w, b = H[index]
7145 return distances[index], w, b
@@ -75,24 +49,45 @@ function MOA.minimize_multiobjective!(
7549 algorithm:: MOA.Sandwiching ,
7650 model:: MOA.Optimizer ,
7751)
78- @assert MOI. get (model. inner, MOI. ObjectiveSense ()) == MOI. MIN_SENSE
79- ε = algorithm. precision
52+ @assert MOI. get (model. inner, MOI. ObjectiveSense ()) == MOI. MIN_SENSE
8053 start_time = time ()
8154 solutions = Dict {Vector{Float64},Dict{MOI.VariableIndex,Float64}} ()
8255 variables = MOI. get (model. inner, MOI. ListOfVariableIndices ())
8356 n = MOI. output_dimension (model. f)
8457 scalars = MOI. Utilities. scalarize (model. f)
85- yI, yUB, anchors = _compute_anchors (model)
86- merge! (solutions, anchors)
87- @info " yI: $(yI) "
88- @info " yUB: $(yUB) "
89- IPS = [yUB, keys (anchors)... ]
58+ status = MOI. OPTIMAL
9059 OPS = Tuple{Vector{Float64},Float64}[]
91- for i in 1 : n
60+ anchors = Dict {Vector{Float64},Dict{MOI.VariableIndex,Float64}} ()
61+ yI, yUB = zeros (n), zeros (n)
62+ for (i, f_i) in enumerate (scalars)
63+ MOI. set (model. inner, MOI. ObjectiveFunction {typeof(f_i)} (), f_i)
64+ MOI. optimize! (model. inner)
65+ status = MOI. get (model. inner, MOI. TerminationStatus ())
66+ if ! MOA. _is_scalar_status_optimal (model)
67+ return status, nothing
68+ end
69+ X, Y = MOA. _compute_point (model, variables, model. f)
70+ model. ideal_point[i] = Y[i]
71+ yI[i] = Y[i]
72+ anchors[Y] = X
73+ MOI. set (model. inner, MOI. ObjectiveSense (), MOI. MAX_SENSE)
74+ MOI. optimize! (model. inner)
75+ status = MOI. get (model. inner, MOI. TerminationStatus ())
76+ if ! MOA. _is_scalar_status_optimal (model)
77+ MOA. _warn_on_nonfinite_anti_ideal (algorithm, MOI. MIN_SENSE, i)
78+ return status, nothing
79+ end
80+ _, Y = MOA. _compute_point (model, variables, f_i)
81+ yUB[i] = Y
82+ MOI. set (model. inner, MOI. ObjectiveSense (), MOI. MIN_SENSE)
9283 e_i = Float64 .(1 : n .== i)
9384 push! (OPS, (e_i, yI[i])) # e_i' * y >= yI_i
9485 push! (OPS, (- e_i, - yUB[i])) # -e_i' * y >= -yUB_i ⟹ e_i' * y <= yUB_i
9586 end
87+ @info " yI: $(yI) "
88+ @info " yUB: $(yUB) "
89+ IPS = [yUB, keys (anchors)... ]
90+ merge! (solutions, anchors)
9691 @info " IPS: $(IPS) "
9792 @info " OPS: $(OPS) "
9893 u = MOI. add_variables (model. inner, n)
@@ -110,19 +105,28 @@ function MOA.minimize_multiobjective!(
110105 H = _halfspaces (IPS)
111106 count = 0
112107 while ! isempty (H)
108+ if MOA. _time_limit_exceeded (model, start_time)
109+ status = MOI. TIME_LIMIT
110+ break
111+ end
113112 count += 1
114113 @info " -- Iteration #$(count) --"
115114 @info " HalfSpaces: $(H) "
116115 δ, w, b = _select_next_halfspace (H, OPS, model)
117116 @info " Selected halfspace: w: $(w) , b: $(b) "
118117 @info " δ: $(δ) "
119- if δ - 1e-3 <= ε # added some convergence tolerance
118+ if δ - 1e-3 <= algorithm . precision # added some convergence tolerance
120119 break
121120 end
122121 # would not terminate when precision is set to 0
123122 new_f = sum (w[i] * (scalars[i] + u[i]) for i in 1 : n) # w' * (f(x) + u)
124123 MOI. set (model. inner, MOI. ObjectiveFunction {typeof(new_f)} (), new_f)
125124 MOI. optimize! (model. inner)
125+ status = MOI. get (model. inner, MOI. TerminationStatus ())
126+ if ! MOA. _is_scalar_status_optimal (model)
127+ MOA. _warn_on_nonfinite_anti_ideal (algorithm, MOI. MIN_SENSE, i)
128+ return status, nothing
129+ end
126130 β̄ = MOI. get (model. inner, MOI. ObjectiveValue ())
127131 @info " β̄: $(β̄) "
128132 X, Y = MOA. _compute_point (model, variables, model. f)
@@ -134,9 +138,6 @@ function MOA.minimize_multiobjective!(
134138 @info " IPS: $(IPS) "
135139 @info " OPS: $(OPS) "
136140 H = _halfspaces (IPS)
137- if count == 10
138- break
139- end
140141 end
141142 MOI. delete .(model. inner, f_constraints)
142143 MOI. delete .(model. inner, u_constraints)
0 commit comments