How an XLEMOO method can be used as an interactive multiobjective optimization method
In this example, we can see how an XLEMOO method can be used as an interactive multiobjective optimization method accepting reference points as preferences.
Imports
Below, we define the import needed to define our LEMOO model.
[1]:
import sys
sys.path.append("../../../XLEMOO")
import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)
warnings.filterwarnings("ignore", category=FutureWarning)
from XLEMOO.LEMOO import EAParams, MLParams, LEMParams, LEMOO, PastGeneration
from XLEMOO.fitness_indicators import asf_wrapper
from XLEMOO.selection import SelectNBest
from XLEMOO.utilities import parse_skoped_rules, complete_missing_rules, print_rules
from desdeo_emo.recombination import SBX_xover, BP_mutation
from desdeo_tools.scalarization.ASF import PointMethodASF
from desdeo_problem.testproblems import vehicle_crashworthiness
import numpy as np
from imodels import SkopeRulesClassifier
Initialize the problem
Next, we initialize a simple test problem with 3 objective functions and 5 variables. We use the vehicle crash worthiness problem.
[2]:
n_objectives = 3
n_variables = 5
problem = vehicle_crashworthiness()
Initialize an XLEMOO method
Now we are ready to define our LEMOO method. We start by defining the parameters of our model. In lem_params general parameters related to the LEMOO method are defined. In ea_params, parameters specific to the evolutionary phase of our LEMOO method are defined, and in ml_params parameters specific to the learning phase of the method are defined. For additional information about these parameters, see the API documentation of the XLEMOO framework.
[3]:
ideal = np.array([1600.0, 6.0, 0.038])
nadir = np.array([1700.0, 12.0, 0.2])
ref_point = np.array([1670.0, 7.61449, 0.085]) # the reference point
# define the achievement scalarizing function as the fitness function
ref_asf = asf_wrapper(PointMethodASF(ideal=ideal, nadir=nadir), {"reference_point": ref_point})
fitness_fun = ref_asf
lem_params = LEMParams(
use_darwin=True,
use_ml=True,
fitness_indicator=fitness_fun,
ml_probe = 1,
ml_threshold = None,
darwin_probe = None,
darwin_threshold = None,
total_iterations=10,
)
ea_params = EAParams(
population_size=50,
cross_over_op=SBX_xover(),
mutation_op=BP_mutation(problem.get_variable_lower_bounds(), problem.get_variable_upper_bounds()),
selection_op=SelectNBest(None, 50), # keep population size constant
population_init_design="LHSDesign",
iterations_per_cycle=19,
)
ml = SkopeRulesClassifier(precision_min=0.1, n_estimators=30, max_features=None, max_depth=None, bootstrap=True, bootstrap_features=True, random_state=1)
ml_params = MLParams(
H_split=0.20,
L_split=0.20,
ml_model=ml,
instantiation_factor=10,
generation_lookback=0,
ancestral_recall=0,
unique_only=True,
iterations_per_cycle=1,
)
lemoo = LEMOO(problem, lem_params, ea_params, ml_params)
Run the XLEMOO method
We run our XLEMOO method for a set number of iterations in each mode. The printed output shows how many iterations were spent in each mode.
[4]:
lemoo.run_iterations()
[4]:
{'darwin_mode': 190, 'learning_mode': 10, 'total_iterations': 10}
Extract and print the rules from skope-rules and complete missing rules
Utilizing the trained XLEMOO model and helper functions imported earlier, we can extract the rules in a human readable format.
[5]:
rules_for_vars = parse_skoped_rules(lemoo=lemoo, problem=problem)
rules_for_vars = complete_missing_rules(lemoo=lemoo, rules_for_vars=rules_for_vars)
print(f"Best solution x = {lemoo._generation_history[-1].individuals[0]}")
print(f"Best objective vector z = {lemoo._generation_history[-1].objectives_fitnesses[0]}")
print_rules(lemoo=lemoo, rules_for_vars=rules_for_vars, tex=False)
Best solution x = [1.003578 2.9999997 1. 1.28857973 1.06367798]
Best objective vector z = [1.66887224e+03 7.51755804e+00 8.31730144e-02]
RULES:
Var Lower(R) Upper(R) Lower(P) Upper(P)
X_0 1.00315 (1.0) 1.0036 (1.0) 1.00358 1.00358
X_1 2.99921 (1.0) 3.0 (-1) 3.0 3.0
X_2 1.0 (0.49) 1.7036 (1.0) 1.0 1.0
X_3 1.1918 (0.984) 1.5508 (1.0) 1.28858 1.28858
X_4 1.04039 (1.0) 1.06792 (1.0) 1.06368 1.06368
Modify variables and explore a new solution
We may then modify the variables to explore new solutions.
[6]:
x_new = np.atleast_2d([1.00184, 2.7135, 1.00000, 1.21741, 1.02602])
z_new = problem.evaluate(x_new).objectives
print(z_new)
[[1.66748556e+03 7.54345501e+00 9.49552335e-02]]
Or we may specify a new reference point and run the XLEMOO method again.