Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve convergence performance(array dimensions question) #723

Closed
quant12345 opened this issue Sep 7, 2023 · 0 comments
Closed

Improve convergence performance(array dimensions question) #723

quant12345 opened this issue Sep 7, 2023 · 0 comments

Comments

@quant12345
Copy link

quant12345 commented Sep 7, 2023

Hi, everyone!

I want to contribute to the code. The convergence function found here has three loops.

By applying numpy vector operations, I was able to speed up the calculation of the function. The code below calculates
the old and new functions and prints the times and comparisons. Keep in mind that numpy calculations a little differently,
so there are differences after the decimal point after 14 sign.

convergence function
def convergence(first_front, optimal_front):
    """Given a Pareto front `first_front` and the optimal Pareto front,
    this function returns a metric of convergence
    of the front as explained in the original NSGA-II article by K. Deb.
    The smaller the value is, the closer the front is to the optimal one.
    """

    import numpy as np
    import datetime

    now = datetime.datetime.now()

    distances = []

    for ind in first_front:
        distances.append(float("inf"))
        for opt_ind in optimal_front:
            dist = 0.
            for i in range(len(opt_ind)):
                dist += (ind.fitness.values[i] - opt_ind[i])**2
            if dist < distances[-1]:
                distances[-1] = dist
        distances[-1] = sqrt(distances[-1])

    cgo = sum(distances) / len(distances)

    time_old = datetime.datetime.now() - now


    now = datetime.datetime.now()

    first_front_ = np.array([i.fitness.values for i in first_front])
    optimal_front_ = np.array(optimal_front)

    diff_pow = (first_front_[:, np.newaxis] - optimal_front_) ** 2

    sum_dp = np.sum(diff_pow, axis=2)

    min_sq = np.sqrt(np.min(sum_dp, axis=1))

    cgn = np.sum(min_sq) / len(first_front_)

    time_new = datetime.datetime.now() - now

    print('time_old', time_old)
    print('time_new', time_new)

    print('value - old', cgo)
    print('value - new', cgn)

    print('attitude time_old/time_new', time_old/time_new)

    return sum(distances) / len(distances)

The arrays first_front, optimal_front in the example are two-dimensional. Can they have more dimensions or how to
run different options? To be sure that the function will work correctly with the new version.

To call the function, I used the code that is located here.

I uncommented some of the rows
if __name__ == "__main__":
    with open("zdt1_front.json") as optimal_front_data:
        optimal_front = json.load(optimal_front_data)
    # Use 500 of the 1000 points in the json file
    optimal_front = sorted(optimal_front[i] for i in range(0, len(optimal_front), 2))

    pop, stats = main()
    pop.sort(key=lambda x: x.fitness.values)

    #print('pop', pop)
    #print('optimal_front', optimal_front)

    # print(stats)
    print("Convergence: ", convergence(pop, optimal_front))

The results with different settings are as follows:

NGEN = 250
MU = 100
CXPB = 0.9

time_old 0:00:00.103891
time_new 0:00:00.003604
value - old 0.0015263450771942537
value - new 0.0015263450771942542
attitude time_old/time_new 28.826581576026637
Convergence:  0.0015263450771942537

NGEN = 1500
MU = 600
CXPB = 0.9

time_old 0:00:00.599092
time_new 0:00:00.060543
value - old 0.000946517439696646
value - new 0.0009465174396966452
attitude time_old/time_new 9.895314074294303
Convergence:  0.000946517439696646
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant