Я пишу функцию для оценки и возврата нелинейной системы уравнений и выдачи якобиана.Затем я планирую вызвать функцию в цикле while
, чтобы использовать метод Ньютона для решения системы уравнений.
Я использовал пакет numpy и перечитал его документацию, попытался ограничить число итераций, изменил значение dtype
в массиве и провел поиск в Интернете, чтобы выяснить, есть ли у кого-то еще подобная проблема.
Эта функция предназначена для решения неоклассической модели роста (проблема в макроэкономике) за конечное время, T. Набор уравнений включает уравнения Тейлера, T ограничения и одно терминальное условие.Таким образом, результатом должен быть массив длиной 2T + 1, содержащий значения уравнений, и (2T + 1) x (2T + 1) якобиева матрица.
Когда я пытаюсь запустить функцию для малыхмассив (массивы длиной 1 и 3) работает отлично.Как только я пытаюсь получить массив длиной 5 или более, я сталкиваюсь с RuntimeWarnings.
import numpy as np
def solver(args, params):
b,s,a,d = params[0], params[1], params[2], params[3]
guess = np.copy(args)
#Euler
euler = guess[:len(guess)//2]**(-sigma) - beta*guess[1:len(guess)//2+1]**(-sigma)*(1-delta+alpha*guess[len(guess)//2+1:]**(alpha-1))
#Budget Constraint
kzero_to_T = np.concatenate(([k0], guess[len(guess)//2+1:]))
bc_t = guess[:len(guess)//2] + guess[len(guess)//2+1:] - kzero_to_T[:-1]**alpha - (1-delta)*kzero_to_T[:-1]
bc_f = guess[len(guess)//2] -kzero_to_T[-1]**alpha - kzero_to_T[-1]*(1-delta)
bc = np.hstack((bc_t, bc_f))
Evals = np.concatenate((euler, bc))
# top half of the jacobian
jac_dot_5 = np.zeros((len(args)//2, len(args)))
for t in range(len(args)//2):
for i in range(len(args)):
if t == i and len(args)//2+(i+1)<=len(args):
jac_dot_5[t][t] = -sigma*args[t]**(-sigma-1)
jac_dot_5[t][t+1] = sigma*beta*args[t+1]*(1-delta+alpha*args[len(args)//2+(t+1)]**(alpha-1))
jac_dot_5[t][len(args)//2+(t+1)] = beta*args[t+1]**(-sigma)*alpha*(alpha-1)*args[len(args)//2+(t+1)]
# bottom half of the jacobian
jac_dot_1 = np.zeros((len(args)//2, len(args)))
for u in range(len(args)//2):
for v in range(len(args)):
if u==v and u>=1 and (len(args)//2 + u+1 < len(args)):
jac_dot_1[u][u] = 1
jac_dot_1[u][len(args)//2+(u)] = 1
jac_dot_1[u][len(args)//2+(u+1)] = -alpha*args[len(args)//2 + (u+1)]**(alpha-1) -(1-delta)
jac_dot_1[0][0] = 1
jac_dot_1[0][len(args)//2 +1] = 1
# last row of the jacobian
final_bc = np.zeros((1,len(args)))
final_bc[0][len(args)//2] = 1
final_bc[0][-1] = -alpha*args[-1]**(alpha-1) -(1-delta)
jac2Tn1 = np.concatenate((jac_dot_5, jac_dot_1, final_bc), axis=0)
point = coll.namedtuple('point', ['Output', 'Jacobian', 'Euler', 'BC'])
result = point(Output = Evals, Jacobian = jac2Tn1, Euler=euler, BC=bc )
return result
Код для реализации алгоритма:
p = (beta, sigma, alpha, delta)
for i in range(20):
k0 = np.linspace(2.49, 9.96, 20)[i]
vars0 = np.array([1,1,1,1,1], dtype=float)
vars1 = np.array([20,20,20,20,20], dtype=float)
Iter2= 0
while abs(solver(vars1,p).Output).max()>1e-8 and Iter2<300:
Iter2+=1
inv_jac1 = np.linalg.inv(solver(vars0,p).Jacobian)
vars1 = vars0 - inv_jac1@solver(vars0,p).Output
vars0=vars1
if Iter2 == 100:
break
Я ожидаю, что результат будет vars1
содержащий обновленные значения.Фактический результат составляет array([nan, nan, nan, nan, nan])
.Способ, которым была написана функция, должен быть в состоянии дать выходные данные для входных данных произвольных догадок длиной 2T + 1, где T - количество периодов времени.
Я получаю три сообщения об ошибках во время выполнения цикла:
C:\Users\Peter\Anaconda3\lib\site-packages\ipykernel_launcher.py:19: RuntimeWarning: invalid value encountered in power
C:\Users\Peter\Anaconda3\lib\site-packages\ipykernel_launcher.py:23: RuntimeWarning: invalid value encountered in power
C:\Users\Peter\Anaconda3\lib\site-packages\ipykernel_launcher.py:41: RuntimeWarning: invalid value encountered in double_scalars
Я пытался закодировать свою проблему с нуля, и я не мог сделать ее короче - мне нужны оба,оценки уравнений и якобиана для реализации алгоритма.Из моего тестирования похоже, что в какой-то момент результаты уравнения (запись solver(vars0,p).Output
) становятся nan,
, но я не уверен, почему это произойдет, массив должен приблизиться к 0 в соответствии с условием abs(solver(vars1,p).Output).max()>1e-8
, а затем простовырваться из петли.