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
Code: Alles auswählen
# Define model parameters here
params = np.array([100,1.03,1.02,0.95])
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
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.
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()
Liebe Grüße,
Lanceister