2017-06-12 1 views
2

En Python, en utilisant SciPy, j'ai besoin de trouver le maximum d'une fonction Q*((1+y)*2-3*Q-0.1)-y**2 Compte tenu de la restriction (1-z)*(Q*((1+y)*2-3*Q-0.1))-y**2=0. Pour z je voudrais entrer quelques valeurs pour trouver les arguments qui maximisent la fonction donné cette valeur de z.Optimisation contrainte en python

J'ai essayé de nombreuses façons d'utiliser les fonctions d'optimisation de SciPy, mais je n'arrive pas à comprendre comment procéder. J'ai réussi à le faire en utilisant WolframAlpha, mais cela ne me donne pas une réponse aux questions qui suivent sur celui-ci.

Tentative:

from scipy.optimize import minimize 

def equilibrium(z): 
    #Objective function 
    min_prof = lambda(Q,y): -1*(Q*((1+y)*2-3*Q-0.1)-y**2) 

    #initial guess 
    x0 = (0.6,0.9) 

    #Restriction function 
    cons = ({'type': 'eq', 'fun': lambda (Q,y): (1-z)*(Q*((1+y)*2-3*Q-0.1))-y**2}) 

    #y between 0 and 1, Q between 0 and 4 
    bnds = ((0,4),(0,1)) 

    res = minimize(min_prof,x0, method='SLSQP', bounds=bnds ,constraints=cons) 

    return res.x 

from numpy import arange 

range_z = arange(0,1,0.001) 

print equilibrium(range_z) 

Erreur:

--------------------------------------------------------------------------- 
ValueError        Traceback (most recent call last) 
<ipython-input-20-527013574373> in <module>() 
    21 range_z = arange(0,1,0.01) 
    22 
---> 23 print equilibrium(range_z) 

<ipython-input-20-527013574373> in equilibrium(z) 
    14  bnds = ((0,4),(0,1)) 
    15 
---> 16  res = minimize(min_prof,x0, method='SLSQP', bounds=bnds ,constraints=cons) 
    17 
    18  return res.x 

/Users/Joost/anaconda/lib/python2.7/site-packages/scipy/optimize/_minimize.pyc in minimize(fun, x0, args, method, jac, hess, hessp, bounds, constraints, tol, callback, options) 
    456  elif meth == 'slsqp': 
    457   return _minimize_slsqp(fun, x0, args, jac, bounds, 
--> 458        constraints, callback=callback, **options) 
    459  elif meth == 'dogleg': 
    460   return _minimize_dogleg(fun, x0, args, jac, hess, 

/Users/Joost/anaconda/lib/python2.7/site-packages/scipy/optimize/slsqp.pyc in _minimize_slsqp(func, x0, args, jac, bounds, constraints, maxiter, ftol, iprint, disp, eps, callback, **unknown_options) 
    324    + 2*meq + n1 + ((n+1)*n)//2 + 2*m + 3*n + 3*n1 + 1 
    325  len_jw = mineq 
--> 326  w = zeros(len_w) 
    327  jw = zeros(len_jw) 
    328 

ValueError: negative dimensions are not allowed 
+0

Le lien ci-dessus fournit un exemple d'effectuer une optimisation sous contrainte. Si vous tentez de résoudre votre problème et que vous rencontrez un problème, partagez votre tentative de code et l'erreur spécifique que vous rencontrez et nous pouvons vous aider à partir de là. – CoryKramer

+0

@CoryKramer J'ai reformulé mon problème, j'obtiens la solution maintenant pour avoir une valeur particulière pour 'z' (qui était de 0.3), maintenant je voudrais étudier comment ces optima réagissent à la valeur de' z'. –

Répondre

0

Vous devez évaluer votre fonction pour une z à la fois. Une modification minimale pour faire fonctionner votre code est le suivant:

print [equilibrium(z) for z in z_range] 

Dans votre code actuel de la fonction décrivant les contraintes renvoie un vecteur au lieu d'un scalaire, ce qui conduit au message d'erreur.

Au lieu d'optimiser numériquement vous pourriez noter que votre problème est résoluble analytiquement:

a = 0.1 
Q = (6-3*a+3**.5 *(4-4*a+a**2-4*z+4*a*z-a**2 *z)**.5)/(6*(2+z)) 
y = Q*(1-z)+(Q*(-1+z)*(-2+a+Q*(2+z)))**.5 

Vous pouvez le tester et de vous convaincre qu'il donne le même résultat (mise à la précision numérique), puis l'optimisation numérique. (J'ai testé pour z = 0.745 - vous devez vérifier la dérivée 2ème pour sélectionner le maximum correct généralement, mais cela est faisable.)