Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 17 additions & 19 deletions src/algorithms/DominguezRios.jl
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,12 @@ end

function _select_next_box(L::Vector{Vector{_DominguezRiosBox}}, k::Int)
p = length(L)
if any(.!isempty.(L))
@assert any(!isempty(l) for l in L)
k = k % p + 1
while isempty(L[k])
k = k % p + 1
while isempty(L[k])
k = k % p + 1
end
i = argmax([B.priority for B in L[k]])
end
i = argmax([B.priority for B in L[k]])
return i, k
end

Expand Down Expand Up @@ -190,7 +189,7 @@ function minimize_multiobjective!(algorithm::DominguezRios, model::Optimizer)
end
i, k = _select_next_box(L, k)
B = L[k][i]
# We're goign to scale `w` here by `scale` instead of the usual
# We're going to scale `w` here by `scale` instead of the usual
# `1 / max(...)`. It will show up in a few places bbelow.
w = scale ./ max.(1, B.u - yI)
constraints = [
Expand All @@ -208,19 +207,18 @@ function minimize_multiobjective!(algorithm::DominguezRios, model::Optimizer)
new_f = t_max + ϵ * sum(w[i] * (scalars[i] - yI[i]) for i in 1:n)
MOI.set(model.inner, MOI.ObjectiveFunction{typeof(new_f)}(), new_f)
MOI.optimize!(model.inner)
if _is_scalar_status_optimal(model)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: in what situations can this model not be OPTIMAL? And if it isn't, what should we do with the box?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the other option is

@@ -207,7 +208,11 @@ function minimize_multiobjective!(algorithm::DominguezRios, model::Optimizer)
         new_f = t_max + ϵ * sum(w[i] * (scalars[i] - yI[i]) for i in 1:n)
         MOI.set(model.inner, MOI.ObjectiveFunction{typeof(new_f)}(), new_f)
         MOI.optimize!(model.inner)
-        @assert _is_scalar_status_optimal(model)
+        if !_is_scalar_status_optimal(model)
+            deleteat!(L[k], i)
+            MOI.delete.(model.inner, constraints)
+            continue
+        end
         X, Y = _compute_point(model, variables, model.f)
         obj = MOI.get(model.inner, MOI.ObjectiveValue())
         # We need to undo the scaling of the scalar objective. There's no

The tolerance issue with HiGHS means that we discard some points, so we find 36 solutions instead of 43:

Test Failed at /Users/oscar/.julia/dev/MultiObjectiveAlgorithms/test/vOptLib.jl:41
  Expression: MOI.get(model, MOI.ResultCount()) >= length(solutions)
   Evaluated: 36 >= 43

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The paper says
image
but this is true in theory but not always numerically.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the model should always be feasible (in theory) as long as the feasible set of the original problem is nonempty. The result is used to figure out the location of the nondominated point (whether it is in the box that we are currently looking into to find nondominated points). So it can be infeasible at the very beginning and can return an empty nondominated set.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the whole problem is infeasible, then we'll catch that in the ideal point computation.

Problem still remains: what if the problem is feasible but our solver fails for some boxes. Perhaps the right behavior is to just skip some? If we error completely, we ignore the fact that this is a nice anytime algorithm with a bunch of good solutions already.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the whole problem is infeasible, then we'll catch that in the ideal point computation.

Yes, that is true.

Problem still remains: what if the problem is feasible but our solver fails for some boxes. Perhaps the right behavior is to just skip some? If we error completely, we ignore the fact that this is a nice anytime algorithm with a bunch of good solutions already.

Maybe the fact that we are not applying the reduction rule of the algorithm and deleting the only problematic box is fine. Should we mention somewhere that this is an anytime algorithm and best suited for use with SolutionLimitor TimeLimit? If someone wants to get all the nondominated solutions, they should use something else. That is actually one of the things I want to explain in the talk.

X, Y = _compute_point(model, variables, model.f)
obj = MOI.get(model.inner, MOI.ObjectiveValue())
# We need to undo the scaling of the scalar objective. There's no
# need to unscale `Y` because we have evaluated this explicitly from
# the modified `model.f`.
obj /= scale
if (obj < 1) && all(yI .< B.u)
push!(solutions, SolutionPoint(X, Y))
_update!(L, Y, yI, yN)
else
deleteat!(L[k], i)
end
@assert _is_scalar_status_optimal(model)
X, Y = _compute_point(model, variables, model.f)
obj = MOI.get(model.inner, MOI.ObjectiveValue())
# We need to undo the scaling of the scalar objective. There's no
# need to unscale `Y` because we have evaluated this explicitly from
# the modified `model.f`.
obj /= scale
if (obj < 1) && all(yI .< B.u)
push!(solutions, SolutionPoint(X, Y))
_update!(L, Y, yI, yN)
else
deleteat!(L[k], i)
end
MOI.delete.(model.inner, constraints)
end
Expand Down
4 changes: 2 additions & 2 deletions test/algorithms/DominguezRios.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ end

function test_vOptLib_runtests()
model = MOA.Optimizer(HiGHS.Optimizer)
MOI.set(model, MOI.RawOptimizerAttribute("presolve"), "off")
MOI.set(model, MOA.Algorithm(), MOA.DominguezRios())
MOI.set(model, MOI.Silent(), true)
# TODO(odow): it doesn't terminate
# vOptLib.run_tests(model)
vOptLib.run_tests(model)
return
end

Expand Down
Loading