diff --git a/opti_prod.py b/opti_prod.py index cb33863..8a84dba 100644 --- a/opti_prod.py +++ b/opti_prod.py @@ -2,6 +2,7 @@ import numpy as np import matplotlib.pyplot as plt import PyQt5 as qt +# Valeurs des constantes de l'exemple du cours ptot = 1000 # [MW] p2max = 400 # [MW] p23max = 500 @@ -15,15 +16,19 @@ def C2(x): return 20*x + 0.02*x**2 def f(x): + # Lagrangien pour une optimisation simple de la production return C1(x[0]) + C2(x[1]) + x[2] * (ptot - x[0] - x[1]) def f2(x): + # Lagrangien pour une optimisation avec contrainte de production max return f(x[0:3]) - abs(x[3]) * (p2max - x[1]) def f3(x): + # Lagrangien pour une optimisation avec contrainte de production et de transport max return f(x[0:3]) - abs(x[3]) * (p23max - t21 * x[0] - t22 * x[1]) def grad(f, x, h=1e-4): + # Il y a surement des librairies qui font ça mieux, mais c'était plus rapide d'écrire cette fonction que de chercher dans la doc res = [] for i in range(len(x)): delta = f(x[:i] + [x[i] + h / 2] + x[i+1:]) - f(x[:i] + [x[i] - h / 2] + x[i+1:]) @@ -31,57 +36,68 @@ def grad(f, x, h=1e-4): return res def norm(x): + # Idem, flemme d'utiliser des arrays et de lire la doc np n = 0 for d in x: n += d**2 return np.sqrt(n) -def g(x): - return norm(grad(f, x, h=1e-5)) - -def g2(x): - return norm(grad(f2, x, h=1e-6)) - -def g3(x): - return norm(grad(f3, x, h=1e-6)) +def adaptation_f(f): + # Permet de lancer la descente de gradient sur la norme du gradient du lagrangien + l = lambda x : norm(grad(f, x, h=1e-6)) # Un pas plus faible va créer des divergences + return l def minimize(f, x0, h=1e-4, step=1e-1, tol=1e-8, N=1e4, echo=False): + # Initialisation x = x0 g = grad(f, x, h) n = 0 - prev = norm(g) + 2*tol + prev = norm(g) + 2*tol # Très moche mais j'ai pas le temps de faire un truc plus élégant while abs(norm(g) - prev) > tol: - n += 1 + # Mise à jour de la variable de suivi de convergence prev = norm(g) - for i in range(len(x)): - x[i] -= g[i] * step + + # Calcul + for i in range(len(x)): # Moche mais flemme de rendre ça joli + x[i] -= g[i] * step # Descente de gradient classique g = grad(f, x, h) + # Print pour debug if (n % 100 == 0) and echo: print("Itération ", n) print("norm(g) = ", norm(g)) print("prev = ", prev) print("x = ", x) print("g = ", g) + + # Système anti boucle infinie if n > N: return x + n += 1 + return x -def custom_minimize(f, x0): +def custom_minimize(f, x0, echo=False): res_app = minimize(f, x0, step=5e-1) - print(res_app) + if echo: + print(res_app) res_app = minimize(f, res_app, step=1e-3, tol=1e-12, h=1e-5) - print(res_app) + if echo: + print(res_app) res_app = minimize(f, res_app, step=1e-5, tol=1e-14, h=1e-5) - print(res_app) + if echo: + print(res_app) res_app = minimize(f, res_app, step=1e-6, tol=1e-16, h=5e-6) - print(res_app) + if echo: + print(res_app) return res_app +print("Cas sans contraintes") +print(custom_minimize(adaptation_f(f), [0, 0, 0])) -print(minimize(g, [0, 0, 0])) +print("Cas avec contrainte de production") +print(custom_minimize(adaptation_f(f2), [0, 0, 0, 0.01])) -custom_minimize(g2, [0, 0, 0, 0.01]) - -custom_minimize(g3, [0, 0, 0, 0.01]) \ No newline at end of file +print("Cas avec contraintes de production et de transport") +print(custom_minimize(adaptation_f(f3), [0, 0, 0, 0.01])) \ No newline at end of file