Skip to content

Commit

Permalink
NIMBUS changes.
Browse files Browse the repository at this point in the history
Added arguments to the NIMBUS functions that use scalarization functions
to be able to pass optional kwargs to the scalarization functions.
  • Loading branch information
gialmisi committed Apr 25, 2024
1 parent 5534f8c commit 0ee742a
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 10 deletions.
26 changes: 18 additions & 8 deletions desdeo/mcdm/nimbus.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def solve_intermediate_solutions(
solution_1: dict[str, VariableType],
solution_2: dict[str, VariableType],
num_desired: int,
scalarization_options: dict | None = None,
create_solver: CreateSolverType | None = None,
solver_options: SolverOptions | None = None,
) -> list[SolverResults]:
Expand All @@ -55,6 +56,8 @@ def solve_intermediate_solutions(
solution_2 (dict[str, VariableType]): the second of the solutions between which the intermediate
solutions are to be generated.
num_desired (int): the number of desired intermediate solutions to be generated. Must be at least `1`.
scalarization_options (dict | None, optional): optional kwargs passed to the scalarization function.
Defaults to None.
create_solver (CreateSolverType | None, optional): a function that given a problem, will return a solver.
If not given, an appropriate solver will be automatically determined based on the features of `problem`.
Defaults to None.
Expand All @@ -71,7 +74,7 @@ def solve_intermediate_solutions(
raise NimbusError(msg)

init_solver = guess_best_solver(problem) if create_solver is None else create_solver
_solver_options = None if solver_options is None else solver_options
_solver_options = None if solver_options is None or create_solver is None else solver_options

# compute the element-wise difference between each solution (in the decision space)
solution_1_arr = variable_dict_to_numpy_array(problem, solution_1)
Expand Down Expand Up @@ -102,7 +105,7 @@ def solve_intermediate_solutions(
# add scalarization
# TODO(gialmisi): add logic that selects correct variant of the ASF
# depending on problem properties (either diff or non-diff)
asf_problem, target = add_asf_diff(problem, "target", rp)
asf_problem, target = add_asf_diff(problem, "target", rp, **(scalarization_options or {}))

solver = init_solver(asf_problem, _solver_options)

Expand Down Expand Up @@ -223,8 +226,9 @@ def solve_sub_problems(
current_objectives: dict[str, float],
reference_point: dict[str, float],
num_desired: int,
create_solver: CreateSolverType,
solver_options: SolverOptions,
scalarization_options: dict | None = None,
create_solver: CreateSolverType | None = None,
solver_options: SolverOptions | None = None,
) -> list[SolverResults]:
r"""Solves a desired number of sub-problems as defined in the NIMBUS methods.
Expand Down Expand Up @@ -256,6 +260,8 @@ def solve_sub_problems(
the reference point.
num_desired (int): the number of desired solutions to be solved. Solves as
many scalarized problems. The value must be in the range 1-4.
scalarization_options (dict | None, optional): optional kwargs passed to the scalarization function.
Defaults to None.
create_solver (CreateSolverType | None, optional): a function that given a problem, will return a solver.
If not given, an appropriate solver will be automatically determined based on the features of `problem`.
Defaults to None.
Expand Down Expand Up @@ -294,7 +300,9 @@ def solve_sub_problems(
# solve the nimbus scalarization problem, this is done always
add_nimbus_sf = add_nimbus_sf_diff if is_smooth else add_nimbus_sf_nondiff

problem_w_nimbus, nimbus_target = add_nimbus_sf(problem, "nimbus_sf", classifications, current_objectives)
problem_w_nimbus, nimbus_target = add_nimbus_sf(
problem, "nimbus_sf", classifications, current_objectives, **(scalarization_options or {})
)
nimbus_solver = init_solver(problem_w_nimbus, _solver_options)

solutions.append(nimbus_solver.solve(nimbus_target))
Expand All @@ -303,7 +311,7 @@ def solve_sub_problems(
# solve STOM
add_stom_sf = add_stom_sf_diff if is_smooth else add_stom_sf_nondiff

problem_w_stom, stom_target = add_stom_sf(problem, "stom_sf", reference_point)
problem_w_stom, stom_target = add_stom_sf(problem, "stom_sf", reference_point, **(scalarization_options or {}))
stom_solver = init_solver(problem_w_stom, _solver_options)

solutions.append(stom_solver.solve(stom_target))
Expand All @@ -312,7 +320,7 @@ def solve_sub_problems(
# solve ASF
add_asf = add_asf_diff if is_smooth else add_asf_nondiff

problem_w_asf, asf_target = add_asf(problem, "asf", reference_point)
problem_w_asf, asf_target = add_asf(problem, "asf", reference_point, **(scalarization_options or {}))
asf_solver = init_solver(problem_w_asf, _solver_options)

solutions.append(asf_solver.solve(asf_target))
Expand All @@ -321,7 +329,9 @@ def solve_sub_problems(
# solve GUESS
add_guess_sf = add_guess_sf_diff if is_smooth else add_guess_sf_nondiff

problem_w_guess, guess_target = add_guess_sf(problem, "guess_sf", reference_point)
problem_w_guess, guess_target = add_guess_sf(
problem, "guess_sf", reference_point, **(scalarization_options or {})
)
guess_solver = init_solver(problem_w_guess, _solver_options)

solutions.append(guess_solver.solve(guess_target))
Expand Down
11 changes: 9 additions & 2 deletions tests/test_nimbus.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ def test_solve_sub_problems():
first_rp = {"f_1": 0.6, "f_2": initial_fs["f_2"], "f_3": 0.6}

num_desired = 4
solutions = solve_sub_problems(problem, initial_fs, first_rp, num_desired, PyomoIpoptSolver, solver_options)
solutions = solve_sub_problems(
problem, initial_fs, first_rp, num_desired, create_solver=PyomoIpoptSolver, solver_options=solver_options
)

assert len(solutions) == num_desired

Expand Down Expand Up @@ -182,7 +184,12 @@ def test_article_example():

num_desired_start = 2
results = solve_sub_problems(
problem, starting_point, starting_rp, num_desired_start, PyomoIpoptSolver, IpoptOptions()
problem,
starting_point,
starting_rp,
num_desired_start,
create_solver=PyomoIpoptSolver,
solver_options=IpoptOptions(),
)

fs = results[0].optimal_objectives
Expand Down

0 comments on commit 0ee742a

Please sign in to comment.