def test_cheby_shape(self): n, a, b = 7, 0, 2 basis = BasisChebyshev(n, a, b) assert_equal(basis.nodes.size, n) assert_equal(basis.Phi().shape, (n, n)) assert_equal(basis._diff(0, 2).shape, (n - 2, n)) assert_equal(basis._diff(0, -3).shape, (n + 3, n)) assert_equal(basis().shape, (n, )) nx = 24 x = np.linspace(a, b, nx) assert_equal(basis.Phi(x).shape, (nx, n)) assert_equal(basis.Phi(x, 1).shape, (nx, n)) assert_equal(basis.Phi(x, -1).shape, (nx, n)) assert_equal(basis(x).shape, (nx, ))
F = BasisChebyshev(10, -1, 1, f=f) x = np.linspace(-1, 1, 1001) plt.figure() plt.plot(x, F(x) - f(x)) plt.title('Figure 6.11 Approximation Error') plt.show() ''' # Example p147 r, k, eta, s0 = 0.1, 0.5, 5 ,1 T, n = 1, 15 tnodes = BasisChebyshev(n - 1, 0, T).nodes F = BasisChebyshev(n, 0, T, y=np.ones((2, n))) def resid(c, tnodes, T, n, F, r, k, eta, s0): F.c = np.reshape(c[:], (2, n)) (p, s), d = F(tnodes, [[0, 1]]) d[0] -= (r * p + k) d[1] += p ** -eta (p_0, p_T), (s_0, s_T) = F([0, T]) return np.r_[d.flatten(), s_0 - s0, s_T] storage = NLP(resid, F.c.flatten(), tnodes, T, n, F, r, k, eta, s0) c = storage.broyden(print=True) F.c = np.reshape(c, (2, n))
m = 1001 x = np.linspace(a, b, m) # ### % Plot monomial basis functions # In[6]: Phi = np.array([x**j for j in np.arange(n)]) basisplot(x, Phi, 'Monomial Basis Functions on [0,1]') # ### % Plot Chebychev basis functions and nodes # In[7]: B = BasisChebyshev(n, a, b) basisplot(x, B.Phi(x).T, 'Chebychev Polynomial Basis Functions on [0,1]') nodeplot(B.nodes, 'Chebychev Nodes on [0,1]') # ### % Plot linear spline basis functions and nodes # In[8]: L = BasisSpline(n, a, b, k=1) basisplot(x, L.Phi(x).T.toarray(), 'Linear Spline Basis Functions on [0,1]') nodeplot(L.nodes, 'Linear Spline Standard Nodes on [0,1]') # ### % Plot cubic spline basis functions and nodes # In[9]:
practical applications, the function to be approximated will not possess a known closed-form. In order to carry out the exercise, one must first code the function to be approximated at arbitrary points. Let's begin: """ # Function to be approximated f = lambda x: np.sin(x[0]) / np.exp(x[1]) # Set the points of approximation interval: a = -1 # left points b = 1 # right points # Choose an approximation scheme. In this case, let us use an 11 by 11 Chebychev approximation scheme: n = 11 # order of approximation basis = BasisChebyshev( [n, n], a, b) # write n twice to indicate the two dimensions. a and b are expanded # Compute the basis coefficients c. There are various way to do this: # One may compute the standard approximation nodes x and corresponding interpolation matrix Phi and function values y # and use: x = basis.nodes Phi = basis.Phi(x) # input x may be omitted if evaluating at the basis nodes y = f(x) c = np.linalg.solve(Phi, y) print('Interpolation coeff =\n ', c) # Alternatively, one may compute the standard approximation nodes x and corresponding function values y and use these # values to create an BasisChebyshev object with keyword argument y: x = basis.nodes y = f(x)
from demos.setup import np, plt from compecon import BasisChebyshev from compecon.tools import nodeunif from mpl_toolkits.mplot3d import Axes3D from matplotlib import cm """ Approximating using the CompEcon toolbox """ '''Univariate approximation''' # Define function and derivative f1 = lambda x: np.exp(-2 * x) d1 = lambda x: -2 * np.exp(-2 * x) # Fit approximant n, a, b = 10, -1, 1 f1fit = BasisChebyshev(n, a, b, f=f1) # Graph approximation error for function and derivative axopts = {'xlabel': 'x', 'ylabel': 'Error', 'xticks': [-1, 0, 1]} x = np.linspace(a, b, 1001) fig = plt.figure(figsize=[12, 6]) ax1 = fig.add_subplot(121, title='Function approximation error', **axopts) ax1.axhline(linestyle='--', color='gray', linewidth=2) ax1.plot(f1fit.nodes, np.zeros_like(f1fit.nodes), 'ro', markersize=12) ax1.plot(x, f1fit(x) - f1(x)) ax2 = fig.add_subplot(122, title='Derivative approximation error', **axopts) ax2.plot(x, np.zeros_like(x), '--', color='gray', linewidth=2) ax2.plot(f1fit.nodes, np.zeros_like(f1fit.nodes), 'ro', markersize=12) ax2.plot(x, f1fit(x, 1) - d1(x)) ''' Bivariate Interpolation ''' # Define function
sigma = 0.08 * np.identity(2), # shock covariance matrix delta = 0.9 # discount factor # Continuous State Shock Distribution m = [3, 3] # number of shocks mu = [0, 0] # means of shocks [e, w] = qnwnorm(m, mu, sigma) # shocks and probabilities # Approximation Structure n = 21 # number of collocation coordinates, per dimension smin = [-2, -3] # minimum states smax = [2, 3] # maximum states basis = BasisChebyshev(n, smin, smax, method='complete', labels=['GDP gap', 'inflation']) # basis functions print(basis) def bounds(s, i, j): lb = np.zeros_like(s[0]) ub = np.full(lb.shape, np.inf) return lb, ub def reward(s, x, i, j): s = s - sbar # todo make sure they broadcast (:,ones(1,n))' f = np.zeros_like(s[0])
""" from compecon import BasisChebyshev import numpy as np import matplotlib.pyplot as plt """ EXAMPLE 1: Using BasisChebyshev to interpolate a 1-D function with a Chebyshev basis PROBLEM: Interpolate the function y = f(x) = 1 + sin(2*x) on the domain [0,pi], using 5 Gaussian nodes. """ # First, create the function f f = lambda x: 1 + np.sin(2 * x) # and the Chebyshev basis B. If the type of nodes is unspecified, Gaussian is computed by default F = BasisChebyshev(5, 0, np.pi, f=f) # Interpolation matrix and nodes: Obtain the interpolation matrix Phi, evaluated at the basis nodes. # The basis nodes are: xnodes = F.nodes # and the basis coefficients are c = F.c # Next plot the function f and its approximation. To evaluate the function defined by the basis B and coefficients c # at values xx we use the interpolation method: # We also plot the residuals, showing the residuals at the interpolating nodes (zero by construction) xx = np.linspace(F.a, F.b, 121) f_approx = F(xx)
# Construct uniform grid for error ploting x = nodeunif(2001, a, b) def subfig(k, x, y, xlim, ylim, title): plt.subplot(2, 2, k) plt.plot(x, y) plt.xlim(xlim) plt.ylim(ylim) plt.title(title) for ifunc, ff in enumerate(funcs): # Construct interpolants C = BasisChebyshev(n, a, b, f=ff) S = BasisSpline(n, a, b, f=ff) L = BasisSpline(n, a, b, k=1, f=ff) # Compute actual and fitted values on grid y = ff(x) # actual yc = C(x) # Chebychev approximant ys = S(x) # cubic spline approximant yl = L(x) # linear spline approximant # Plot function approximations plt.figure() ymin = np.floor(y.min()) ymax = np.ceil(y.max()) xlim = [a, b] ylim = [-0.2, 1.2] if ifunc == 2 else [ymin, ymax]
# In[2]: def resid(c): Q.c = c q = Q(p) return p + q / (-3.5 * p**(-4.5)) - np.sqrt(q) - q**2 # ### Approximation structure # In[3]: n, a, b = 21, 0.5, 2.5 Q = BasisChebyshev(n, a, b) c0 = np.zeros(n) c0[0] = 2 p = Q.nodes # ### Solve for effective supply function # In[4]: monopoly = NLP(resid) Q.c = monopoly.broyden(c0) # ### Setup plot # In[5]:
# In[3]: D = lambda p: p**(-eta) # ### Approximation structure # # A degree-25 Chebychev basis on the interval [0.5, 3.0] is selected; also, the associated collocation nodes `p` are computed. # In[4]: n, a, b = 25, 0.5, 2.0 S = BasisChebyshev(n, a, b, labels=['price'], y=np.ones(n)) p = S.nodes # In[5]: S2 = BasisChebyshev(n, a, b, labels=['price'], l=['supply']) S2.y = np.ones_like(p) # ### Residual function # # Suppose, for example, that # # \begin{equation}
return g # Set degree of approximation and endpoints of approximation interval a = -1 # left endpoint b = 1 # right endpoint n = 10 # order of interpolatioin # Construct refined uniform grid for error ploting x = nodeunif(1001, a, b) # Compute actual and fitted values on grid y, d, s = f(x) # actual # Construct and evaluate Chebychev interpolant C = BasisChebyshev(n, a, b, f=f) # chose basis functions yc = C(x) # values dc = C(x, 1) # first derivative sc = C(x, 2) # second derivative # Construct and evaluate cubic spline interpolant S = BasisSpline(n, a, b, f=f) # chose basis functions ys = S(x) # values ds = S(x, 1) # first derivative ss = S(x, 2) # second derivative # Plot function approximation error plt.figure() plt.subplot(2, 1, 1), plt.plot(x, y - yc[0]) plt.ylabel('Chebychev')
alpha = 2 f = lambda x: np.exp(-alpha * x) F = BasisChebyshev(10, -1, 1, f=f) x = np.linspace(-1, 1, 1001) plt.figure() plt.plot(x, F(x) - f(x)) plt.title('Figure 6.11 Approximation Error') plt.show() ''' # Example p147 r, k, eta, s0 = 0.1, 0.5, 5, 1 T, n = 1, 15 tnodes = BasisChebyshev(n - 1, 0, T).nodes F = BasisChebyshev(n, 0, T, y=np.ones((2, n))) def resid(c, tnodes, T, n, F, r, k, eta, s0): F.c = np.reshape(c[:], (2, n)) (p, s), d = F(tnodes, [[0, 1]]) d[0] -= (r * p + k) d[1] += p**-eta (p_0, p_T), (s_0, s_T) = F([0, T]) return np.r_[d.flatten(), s_0 - s0, s_T] storage = NLP(resid, F.c.flatten(), tnodes, T, n, F, r, k, eta, s0) c = storage.broyden(print=True) F.c = np.reshape(c, (2, n))
# In[2]: def resid(c): Q.c = c q = Q(p) return p + q / (-3.5 * p **(-4.5)) - np.sqrt(q) - q ** 2 # ### Approximation structure # In[3]: n, a, b = 21, 0.5, 2.5 Q = BasisChebyshev(n, a, b) c0 = np.zeros(n) c0[0] = 2 p = Q.nodes # ### Solve for effective supply function # In[4]: monopoly = NLP(resid) Q.c = monopoly.broyden(c0) # ### Setup plot
b = [2, -3] # recreational user benefit function parameters ymean = 1.0 # mean rainfall sigma = 0.2 # rainfall volatility delta = 0.9 # discount factor # Continuous State Shock Distribution m = 3 # number of rainfall shocks e, w = qnwlogn(m, np.log(ymean) - sigma**2 / 2, sigma**2) # rainfall shocks and proabilities # Approximation Structure n = 15 # number of collocation nodes smin = 2 # minimum state smax = 10 # maximum state basis = BasisChebyshev(n, smin, smax, labels=['reservoir']) # basis functions def bounds(s, i, j): return np.zeros_like(s), s.copy() def reward(s, x, i, j): a0, a1 = a b0, b1 = b f = 1.2 * (a0 / (1 + a1)) * x**(1 + a1) + (b0 / (1 + b1)) * (s - x)**(1 + b1) fx = 1.2 * a0 * x**a1 - b0 * (s - x)**b1 fxx = 1.2 * a0 * a1 * x**(a1 - 1) + b0 * b1 * (s - x)**(b1 - 1) return f, fx, fxx
from demos.setup import np, plt, demo ## FORMULATION # Model Parameters alpha = 4.0 # growth function parameter beta = 1.0 # growth function parameter gamma = 0.5 # relative risk aversion kappa = 0.2 # unit cost of harvest delta = 0.9 # discount factor # Approximation Structure n = 8 # number of collocation nodes smin = 6 # minimum state smax = 9 # maximum state basis = BasisChebyshev(n, smin, smax, labels=['available']) # basis functions # Model Structure def bounds(s, i, j): return np.zeros_like(s), s[:] # important!!, pass a copy of s def reward(s, q, i, j): f = (q**(1 - gamma)) / (1 - gamma) - kappa * q fx = q**(-gamma) - kappa fxx = -gamma * q**(-gamma - 1) return f, fx, fxx
s stock of wealth Actions k capital investment Parameters beta capital production elasticity delta discount factor """ from demos.setup import demo, np, plt from compecon import BasisChebyshev, DPmodel, DPoptions, qnwnorm # =========== Approximation Structure n, smin, smax = 15, 0.2, 1.0 basis = BasisChebyshev(n, smin, smax, labels=['Wealth']) snodes = basis.nodes # =========== Model specification beta, delta = 0.5, 0.9 def bounds(s, i, j): return np.zeros_like(s), s[:] def reward(s, k, i, j): sk = s - k f = np.log(sk) fx= - sk ** -1
nrmunif, nrmcheb, conunif, concheb = (np.zeros(nn) for k in range(4)) # Compute approximation errors on refined grid and interpolation matrix condition numbers for i in range(nn): # Uniform-node monomial-basis approximant xnodes = np.linspace(a, b, n[i]) c = np.polyfit(xnodes, runge(xnodes), n[i]) yfit = np.polyval(c, x) phi = xnodes.reshape(-1, 1)**np.arange(n[i]) errunif[i] = yfit - y nrmunif[i] = np.log10(norm(yfit - y, np.inf)) conunif[i] = np.log10(cond(phi, 2)) # Chebychev-node Chebychev-basis approximant yapprox = BasisChebyshev(n[i], a, b, f=runge) yfit = yapprox( x) # [0] no longer needed? # index zero is to eliminate one dimension phi = yapprox.Phi() errcheb[i] = yfit - y nrmcheb[i] = np.log10(norm(yfit - y, np.inf)) concheb[i] = np.log10(cond(phi, 2)) # Plot Chebychev- and uniform node polynomial approximation errors ax2 = fig1.add_subplot( 212, title="Runge's Function $11^{th}$-Degree\nPolynomial Approximation Error.", xlabel='x', ylabel='Error') ax2.axhline(color='gray', linestyle='--') ax2.plot(x, errcheb[4], label='Chebychev Nodes')
# In[1]: import numpy as np import matplotlib.pyplot as plt from compecon import BasisChebyshev, NLP, demo # ### Approximation structure # In[2]: n, a, b = 31, 1, 5 F = BasisChebyshev(n, a, b) # define basis functions x = F.nodes # compute standard nodes # ### Residual function # In[3]: def resid(c): F.c = c # update basis coefficients f = F(x) # interpolate at basis nodes x return f ** -2 + f ** -5 - 2 * x # ### Compute function inverse
d11 = lambda x: -cos(x[0]) / exp(x[1]) d12 = lambda x: sin(x[0]) / exp(x[1]) d22 = lambda x: cos(x[0]) / exp(x[1]) # Set the points of approximation interval: # In[3]: a, b = 0, 1 # Choose an approximation scheme. In this case, let us use an 6 by 6 Chebychev approximation scheme: # In[4]: n = 6 # order of approximation basis = BasisChebyshev([n, n], a, b) # write n twice to indicate the two dimensions. # a and b are broadcast. # ### Compute the basis coefficients c. # There are various way to do this: # * One may compute the standard approximation nodes `x` and corresponding interpolation matrix `Phi` and function values `y` and use: # In[5]: x = basis.nodes Phi = basis.Phi(x) # input x may be omitted if evaluating at the basis nodes y = f(x) c = np.linalg.solve(Phi, y)
from demos.setup import np, plt, demo ## FORMULATION # Model Parameters alpha = 0.2 # relative risk aversion beta = 0.5 # capital production elasticity gamma = 0.9 # capital survival rate sigma = 0.1 # production shock volatility delta = 0.9 # discount factor # Approximation Structure n = 10 # number of collocation nodes smin = 5 # minimum wealth smax = 10 # maximum wealth basis = BasisChebyshev(n, smin, smax, labels=['wealth']) # basis functions # Continuous State Shock Distribution m = 5 # number of production shocks e, w = qnwlogn(m, -sigma**2 / 2, sigma**2) # production shocks and probabilities # Model specification def bounds(s, i, j): return np.zeros_like(s), 0.99 * s def reward(s, k, i, j): sk = s - k
from nose.tools import * import numpy as np from compecon import BasisChebyshev ''' test for size of Diff operator ''' n, a, b = 7, 0, 2 Phi = BasisChebyshev(n, a, b) def test_Diff(): assert_equal(Phi._diff(0, 2).shape, (n - 2, n)) assert_equal(Phi._diff(0, -3).shape, (n + 3, n)) ''' test for shape of interpolation matrix ''' nx = 24 x = np.linspace(a, b, nx) def test_Phi(): assert_equal(Phi(x).shape, (nx, n)) assert_equal(Phi().shape, (n, n))