Is it possible to set the attribute of optimizer in the iteration of _solve_in_sequence in Lexicographic?

For the following code

using JuMP
import HiGHS
import MultiObjectiveAlgorithms as MOA
model = JuMP.Model(() -> MOA.Optimizer(HiGHS.Optimizer))
set_attribute(model, MOA.Algorithm(), MOA.Lexicographic())

Is it possible to set the attribute of optimizer in the iteration of _solve_in_sequence in Lexicographic? For example, modify the time_limit.I would like to modify the code above to achieve something similar to the following sample code:

for i in sequence
    if  i <= 2
        set_attribute(model, "time_limit", 1000.0)
    else 
        set_attribute(model, "time_limit", 500.0)
    end
    
    if _time_limit_exceeded(model, start_time)
        status = MOI.TIME_LIMIT
        break
    end
    # ....
end

Hi @Hongliang_Yang,

No, it’s not possible. You’ll need to manually code the algorithm if you want to do something like that.

Is it possible to give some detailed tips or sample code? Thanks for your help. @odow

The source code is

but that might be a bit complicated to be helpful.

One approach is to write a new algorithm,

import MultiObjectiveAlgorithms as MOA
import MathOptInterface as MOI
import Combinatorics

mutable struct CustomLexicographic <: MOA.AbstractAlgorithm end

function MOA.optimize_multiobjective!(
    algorithm::CustomLexicographic,
    model::MOA.Optimizer,
)
    start_time = time()
    sequence = 1:MOI.output_dimension(model.f)
    solutions = MOA.SolutionPoint[]
    status = MOI.OPTIMAL
    for sequence in Combinatorics.permutations(sequence)
        status, solution =
            _solve_in_sequence(algorithm, model, sequence, start_time)
        if !isempty(solution)
            push!(solutions, solution[1])
        end
        if !MOA._is_scalar_status_optimal(status)
            break
        end
    end
    sense = MOI.get(model.inner, MOI.ObjectiveSense())
    return status, MOA.filter_nondominated(sense, solutions)
end

function _solve_in_sequence(
    ::CustomLexicographic,
    model::MOA.Optimizer,
    sequence::AbstractVector{Int},
    start_time::Float64,
)
    variables = MOI.get(model.inner, MOI.ListOfVariableIndices())
    constraints = Any[]
    scalars = MOI.Utilities.eachscalar(model.f)
    solution = MOA.SolutionPoint[]
    status = MOI.OPTIMAL
    for i in sequence
        if MOA._time_limit_exceeded(model, start_time)
            status = MOI.TIME_LIMIT
            break
        end
        f = scalars[i]
        # Do something here...
        MOI.set(model.inner, MOI.ObjectiveFunction{typeof(f)}(), f)
        MOI.optimize!(model.inner)
        status = MOI.get(model.inner, MOI.TerminationStatus())
        primal_status = MOI.get(model.inner, MOI.PrimalStatus())
        if MOA._is_scalar_status_feasible_point(primal_status)
            X, Y = MOA._compute_point(model, variables, model.f)
            solution = [MOA.SolutionPoint(X, Y)]
        end
        if !MOA._is_scalar_status_optimal(status)
            break
        end
        X, Y = MOA._compute_point(model, variables, f)
        rtol = 1e-3
        set = if MOI.get(model.inner, MOI.ObjectiveSense()) == MOI.MIN_SENSE
            MOI.LessThan(Y + rtol * abs(Y))
        else
            MOI.GreaterThan(Y - rtol * abs(Y))
        end
        ci = MOI.Utilities.normalize_and_add_constraint(model, f, set)
        push!(constraints, ci)
    end
    for c in constraints
        MOI.delete(model, c)
    end
    return status, solution
end

and then use

set_attribute(model, MOA.Algorithm(), CustomLexicographic())

Alternatively, you would just code something in JuMP, don’t use MOA:

using JuMP, HiGHS
model = Model(HiGHS.Optimizer)
@variable(model, x[1:3] >= 0)
# ... build model ...
objectives = [x[1], 2 * x[2], x[3] + 1]
solutions = Any[]
for o in objectives
    @objective(model, Min, o)
    # set_attribute(...)  # stuff here
    optimize!(model)
    push!(solutions, value.(x))
    @constraint(model, o <= objective_value(model))
end

@odow Thanks for the answer, the method you provided for using MOA is exactly what we are trying. However, I don’t know how to modify the attribute of the optimizer in the _solve_in_sequence function, and have tried several methods that have failed. For example,

set_attribute(model.inner, “time_limit”, 500.0)

I solved it using MOI.set, thanks for your help.

1 Like