Pareto optimal points in multi objective optimization (3 objectives)

217 views Asked by At

I have a multi objective optimization problem with 3 objectives. I applied Conic Scalarization since I am not quite sure whether it is convex or not. Anyway, in the end, I have a Excel sheet that have z1, z2 and z3 scores of Conic Scalarization. But, the problem is that Excel sheet has 6050 rows. Hence, I am not quite sure how I can get pareto optimal points and dominated points to plot them in a 3D graph. Of course it is possible to just draw the plot with all, but I want to use hue to separate pareto optimal points and dominated points after identifying them. I exported the scores to Excel, but I will plot them in Python. Hence, I would be glad that is there any code or approach you may share with me to get pareto optimal points and dominated points in Excel or in Python.

Thanks in advance,

Note: You may find the same question I asked in GAMS forum. Because I used GAMS to solve the MOOP. However, I am not familiar with the answer [ 1 ] in that forum. Hence, I also ask it here to be able to get a Python code or an explanation how I can give my Excel file to "pareto.py" that was suggested in GAMS Forum.

1

There are 1 answers

0
MSS On

You can read z1, z2 and z3 scores from excel into a pandas dataframe in python. Then find pareto points and dominated points and plot them from python.

import pandas as pd
import numpy as np
import plotly.graph_objects as go

# Step 1: Read criteria from Excel file
df = pd.read_excel('criteria.xlsx')

# Step 2: Define your criteria for optimality
#  we want to minimize z1, z2, and z3.
# Hence, we'll negate the values to turn it into a maximization problem.
df['z1'] = -df['z1']
df['z2'] = -df['z2']
df['z3'] = -df['z3']

# Step 3: Normalize the data if needed
# If criteria are on different scales, you might want to normalize them.

# Step 4: Sort the DataFrame based on each criterion in descending order
df_sorted = df.sort_values(by=['z1', 'z2', 'z3'], ascending=False)

# Step 5: Find the Pareto optimal rows using vectorized operations
is_pareto_optimal = np.ones(df_sorted.shape[0], dtype=bool)
current_max_2 = float('-inf')
current_max_3 = float('-inf')

for i in range(df_sorted.shape[0]):
    if df_sorted.iloc[i]['z2'] <= current_max_2 or df_sorted.iloc[i]['z3'] <= current_max_3:
        is_pareto_optimal[i] = False
    else:
        current_max_2 = df_sorted.iloc[i]['z2']
        current_max_3 = df_sorted.iloc[i]['z3']

pareto_optimal_indices = df_sorted[is_pareto_optimal].index
dominated_indices = df_sorted[~is_pareto_optimal].index

# The `pareto_optimal_indices` array contains the index of rows that form the Pareto front in sorted dataframe.
# The `dominated_indices` array contains the index of rows that are dominated in the sorted dataframe.

# Step 6: Plot the data using Plotly
fig = go.Figure()

# Plot Pareto optimal rows
fig.add_trace(go.Scatter3d(
    x=df.loc[pareto_optimal_indices, 'z1'],
    y=df.loc[pareto_optimal_indices, 'z2'],
    z=df.loc[pareto_optimal_indices, 'z3'],
    mode='markers',
    name='Pareto Optimal',
    marker=dict(
        color='green',
        size=6
    )
))

# Plot dominated rows
fig.add_trace(go.Scatter3d(
    x=df.loc[dominated_indices, 'z1'],
    y=df.loc[dominated_indices, 'z2'],
    z=df.loc[dominated_indices, 'z3'],
    mode='markers',
    name='Dominated',
    marker=dict(
        color='red',
        size=6
    )
))

# Update layout for better visualization
fig.update_layout(scene=dict(
    xaxis_title='z1',
    yaxis_title='z2',
    zaxis_title='z3'
))

# Show the plot
fig.show()