Optimierung mit mehreren Variablen und Constraints

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
Lanceister
User
Beiträge: 1
Registriert: Dienstag 28. April 2020, 13:51

Hallo zusammen,

Für einen Kurs an meiner Uni muss ich eine Optimierungsaufgabe mithilfe von scipy/numpy und matplotlib lösen.
Allerdings haben wir die Optimierung von Funktionen bisher nur mit einzelnen Variablen + Parametern gelöst, jedoch nicht
mit mehreren Variablen + Parametern.
Ebenfalls ist das meine erste richtige Anwendung von Python, ich bin also noch ziemlich unerfahren...

Ich habe jetzt bereits einige Stunden herumprobiert, komme jedoch einfach nicht weiter...

Code: Alles auswählen

# Write all import statements here

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize
Die Modellparameter lauten y = 100 , z = 1.03 , n = 1.02 und beta = 0.95

Code: Alles auswählen

# Define model parameters here

params = np.array([100,1.03,1.02,0.95])
Die Entsprechende Funktion lautet U(c1,c2,c3) = c1 ^ (1/2) + beta * c2 ^ (1/2) + beta ² * (c3 ^ (1/2))
Mit den Constraints: c1 + q = y
c2 <= (n/z) * q
c3 = (n²/z²) * q - (n/z) * c2

Hierbei stehen c1, c2 und c3 für den Konsum sowie q für das gesparte Kapital.
Ziel der Aufgabe ist es, unter den Nebenbedingungen die Funktion zu maximieren bzw. die maximierenden Variablen c1,c2,c3 und q zu ermitteln. Da bereits def U(sol, params) vorgegeben war, habe ich die 4 Variablen sol zugewiesen: (sol[0] steht für c1, sol[1] für c2, sol[2] für c3 und sol[3] für q.

Code: Alles auswählen

 
 def U(sol,params):
    """
    Returns the lifetime utility of a young person as a function of his consumption and money holdings (sol)
    
    as well as the parameters of the model (params)
    
    """
    y, z, n, beta = params

    return - (sol[0] ** (1/2) + beta * sol[1] ** (1/2) + (beta ** 2) * sol[2] ** (1/2))
    # Write your code here

    
def V(params):
    """
    Returns the solution to the optimization problem as a function of the parameters of the model
    
    """
    y, z, n, beta = params
    cons = ({'type': 'eq', 'fun': lambda sol: sol[0] + sol[3] - y},
           {'type': 'ineq', 'fun': lambda sol: sol[1] - (n/z) * sol},
           {'type': 'eq', 'fun': lambda sol: sol[2] - ((n ** 2)/(z ** 2)) * sol[3] + (n/z) * sol[1]})
    bnd = [(0,np.inf),(0,np.inf),(0,np.inf),(0,np.inf)]
    lös = minimize(lambda sol, params: -U(sol,params), x0=[25,25,25,25], method='SLSQP', args=params, constraints=cons, bounds=bnd, options={'disp': True,'ftol': 1e-10})
    return lös
    # Write your code here
    
Anschließend soll die Funktion geplottet werden, doch hier erhalte ich immer den selben Fehlerterm

Code: Alles auswählen

z_grid = np.linspace(1.0,3.0,100)
q_star = np.zeros(len(z_grid))
c_1 = np.zeros(len(z_grid))
c_2 = np.zeros(len(z_grid))
c_3 = np.zeros(len(z_grid))
u = np.zeros(len(z_grid))

for i, z in enumerate(z_grid):
    params[1] = z
    q_star[i] = V(params).x
    c_1[i] = params[0] - q_star[i]
    c_2[i] = q_star[i] * params[2] / params[1]
    c_3[i] = ((params[2] ** 2) / (params[1] ** 2)) * q_star[i] - (params[2] / params[1]) * ((V(params).x[1] * q_star[i]))
    u[i] = U(q_star,params)

c = c_1 + c_2 + c_3
Iteration limit exceeded    (Exit mode 9)
            Current function value: 14.262500001558012
            Iterations: 101
            Function evaluations: 1262
            Gradient evaluations: 98
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars

The above exception was the direct cause of the following exception:

ValueError                                Traceback (most recent call last)
<ipython-input-196-1e981037e672> in <module>
      8 for i, z in enumerate(z_grid):
      9     params[1] = z
---> 10     q_star[i] = V(params).x
     11     c_1[i] = params[0] - q_star[i]
     12     c_2[i] = q_star[i] * params[2] / params[1]

ValueError: setting an array element with a sequence.

Und auch der entsprechende Plot ist lediglich eine gerade Linie...

Code: Alles auswählen

 
 plt.figure(figsize=(9,6))
plt.plot(z_grid,c_1,label=r'$c_1$')
plt.plot(z_grid,c_2,label=r'$c_2$')
plt.plot(z_grid,c_3,label=r'$c_3$')
plt.ylabel(r'Real consumption, c',fontsize='12')
plt.xlabel(r'Money growth rate, $z$',fontsize='12')
plt.legend(loc='best',fontsize='12')
plt.show()
 
Ich wäre wirklich froh wenn mir jemand sagen kann wo mein Fehler liegt!

Liebe Grüße,

Lanceister
Sirius3
User
Beiträge: 18220
Registriert: Sonntag 21. Oktober 2012, 17:20

Benutze keine Abkürzungen, das macht den Code schwer lesbar. Was hat die Sonne (sol) oder Löß mit der Aufgabe zu tun? Geht es um Landwirtschaft? Aber dann kommt plötzlich der BND ins Spiel.
Um Hauptprogramm ist es ungünstig, dass Du V mehrmals mit den gleichen Parametern aufrufst. Hast Du Dir dessen Rückgabewert schon einmal angeschaut? Dann sollte klar sein, warum da mehr als Ein Wert in x steht und Du das nicht EINEM Element Deines Arrays zuweisen kannst.
Antworten