pythonmatplotlibvisualizationgenetic-programmingdeap

How to plot multi-objectives pareto frontier with DEAP in Python


For the project I was working on, I set 3 different objectives as optimization target in DEAP, an evolution framework based on Python.

It can cope with multi-objectives problem using algorithm like NSGA-II. Is there anyway to generate the pareto frontier surface for the visualizing the results.


Solution

  • Following a recipe in this link (not my own) to calculate the Pareto Points you could do:

    def simple_cull(inputPoints, dominates):
        paretoPoints = set()
        candidateRowNr = 0
        dominatedPoints = set()
        while True:
            candidateRow = inputPoints[candidateRowNr]
            inputPoints.remove(candidateRow)
            rowNr = 0
            nonDominated = True
            while len(inputPoints) != 0 and rowNr < len(inputPoints):
                row = inputPoints[rowNr]
                if dominates(candidateRow, row):
                    # If it is worse on all features remove the row from the array
                    inputPoints.remove(row)
                    dominatedPoints.add(tuple(row))
                elif dominates(row, candidateRow):
                    nonDominated = False
                    dominatedPoints.add(tuple(candidateRow))
                    rowNr += 1
                else:
                    rowNr += 1
    
            if nonDominated:
                # add the non-dominated point to the Pareto frontier
                paretoPoints.add(tuple(candidateRow))
    
            if len(inputPoints) == 0:
                break
        return paretoPoints, dominatedPoints
    
    def dominates(row, candidateRow):
        return sum([row[x] >= candidateRow[x] for x in range(len(row))]) == len(row)  
    
    import random
    inputPoints = [[random.randint(70,100) for i in range(3)] for j in range(500)]
    paretoPoints, dominatedPoints = simple_cull(inputPoints, dominates)
    
    import matplotlib.pyplot as plt
    from mpl_toolkits.mplot3d import Axes3D
    
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    dp = np.array(list(dominatedPoints))
    pp = np.array(list(paretoPoints))
    print(pp.shape,dp.shape)
    ax.scatter(dp[:,0],dp[:,1],dp[:,2])
    ax.scatter(pp[:,0],pp[:,1],pp[:,2],color='red')
    
    import matplotlib.tri as mtri
    triang = mtri.Triangulation(pp[:,0],pp[:,1])
    ax.plot_trisurf(triang,pp[:,2],color='red')
    plt.show()
    

    , you will notice that the last part is applying a triangulation to the Pareto points and plotting it as a triangular surface. The results is this (where the red shape is the Pareto front):

    Pareto front in matplotlib

    EDIT: Also you might want to take a look at this (although it seems to be for 2D spaces).