<jupyter_start><jupyter_text>Example on using the scalarization methods for scalarizing and minimizing a problem which is based on discrete dataIn this example, we will go through the following two topics: 1. How to define a scalarization method for scalarizing discrete data representing a multiobjective optimization problem; 2. How to find a solution to the scalarized problem.We will start by defining simple 2-dimensional data representing a set of Pareto optimal solutions.<jupyter_code>import numpy as np
import matplotlib.pyplot as plt

f1 = np.linspace(1, 100, 50)
f2 = f1[::-1]**2

plt.scatter(f1, f2)
plt.title("Pareto front")
plt.xlabel("f1")
plt.ylabel("f2")
plt.show()<jupyter_output><empty_output><jupyter_text>Let us pretend the points represent the Pareto front for a problem with two objectives to be minimized. We can easily determine the ideal and nadir points as follows:<jupyter_code>pfront = np.stack((f1, f2)).T

ideal = np.min(pfront, axis=0)
nadir = np.max(pfront, axis=0)

print(f"Ideal point: {ideal}")
print(f"Nadir point: {nadir}")

plt.scatter(f1, f2, label="Pareto front")
plt.scatter(ideal[0], ideal[1], label="ideal")
plt.scatter(nadir[0], nadir[1], label="nadir")
plt.title("Pareto front")
plt.xlabel("f1")
plt.ylabel("f2")
plt.legend()
plt.show()<jupyter_output>Ideal point: [1. 1.]
Nadir point: [  100. 10000.]<jupyter_text>Next, suppose we would like to find a solution close to the point (80, 2500), let us define that point as a reference point.<jupyter_code>z = np.array([80, 2500])<jupyter_output><empty_output><jupyter_text>Clearly, `z` is not on the Pareto front. We can find a closest solution by scalarizing the problem using an achievement scalarizing function (ASF) and minimizing the related achievement scalarizing optimization problem. We will do that next.<jupyter_code>from desdeo_tools.scalarization.ASF import PointMethodASF
from desdeo_tools.scalarization.Scalarizer import DiscreteScalarizer
from desdeo_tools.solver.ScalarSolver import DiscreteMinimizer

# define the achievement scalarizing function
asf = PointMethodASF(nadir, ideal)
# the scalarizer
dscalarizer = DiscreteScalarizer(asf, scalarizer_args={"reference_point": z})
# the solver (minimizer)
dminimizer = DiscreteMinimizer(dscalarizer)

solution_i = dminimizer.minimize(pfront)

print(f"Index of the objective vector minimizing the ASF problem: {solution_i}")<jupyter_output>Index of the objective vector minimizing the ASF problem: 32<jupyter_text>When a scalar problem is minimized using a `DiscreteMinimizer`, the result will be the index of the objective vector in the supplied `vector` argument minimizing the `DiscreteScalarizer` defined in `DiscreteMinimizer`. This is done because it is assumed that the corresponding decision variables are also kept in a vector somewhere, and the variables are ordered in a manner where the `i`th elementin `vectors` corresponds to the `i`th variables in the vector storing the variables.Anyway, let us plot the solution:<jupyter_code>plt.scatter(f1, f2, label="Pareto front")
plt.scatter(ideal[0], ideal[1], label="ideal")
plt.scatter(nadir[0], nadir[1], label="nadir")
plt.scatter(pfront[solution_i][0], pfront[solution_i][1], label="Preferred solution")
plt.scatter(z[0], z[1], label="Reference point")
plt.title("Pareto front")
plt.xlabel("f1")
plt.ylabel("f2")
plt.legend()
plt.show()<jupyter_output><empty_output><jupyter_text>Suppose now that there is the following constraint to our problem: values of `f1` should be less than 50 or more than 77. We can easily deal with this situation as well, and we will conclude our example here.<jupyter_code># define the constraint function, it should return either True of False for each
# objective vector defined in its argument.
def con(fs):
    fs = np.atleast_2d(fs)

    return np.logical_or(fs[:, 0] < 50, fs[:, 0] > 77)

dminimizer_con = DiscreteMinimizer(dscalarizer, con)

solution_con = dminimizer_con.minimize(pfront)

mask = con(pfront)
plt.scatter(f1[mask], f2[mask], label="Pareto front with constraint")
plt.scatter(ideal[0], ideal[1], label="ideal")
plt.scatter(nadir[0], nadir[1], label="nadir")
plt.scatter(pfront[solution_i][0], pfront[solution_i][1], label="Preferred solution wihtout constraint")
plt.scatter(pfront[solution_con][0], pfront[solution_con][1], label="Preferred solution with constraint", color="black")
plt.scatter(z[0], z[1], label="Reference point")
plt.title("Pareto front")
plt.xlabel("f1")
plt.ylabel("f2")
plt.legend()
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11052048726467331, 'fraction_numerical': 0.020376522702104098, 'mean_word_length': 6.680272108843537, 'pattern_counts': {'":': 1, '<': 24, '<?xml version=': 0, '>': 24, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '452842', 'license': 'MIT', 'n_tokens_mistral': 1563, 'n_tokens_neox': 1447, 'n_words': 475, 'path': 'docs/notebooks/Discrete_solver.ipynb', 'repo_name': 'ppouyaa/desdeo-tools', 'size': '4515'}