home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 10 / 10.iso / l / l455 / 5.ddi / SPLINES.DI$ / TSPDEM.M < prev    next >
Encoding:
Text File  |  1993-03-11  |  10.8 KB  |  313 lines

  1. %TSPDEM    Demonstrate tensor product splines.
  2. % Copyright (c) 1990-92 by Carl de Boor and The MathWorks, Inc.
  3.                                     % latest change: May 24, 1991
  4. clc;clg;echo on;home
  5. % Since the toolbox can handle splines with  v e c t o r  coefficients, it is
  6. % easy to implement interpolation or approximation to gridded data by tensor
  7. % product splines.
  8. % Consider, for example, least-squares approximation to given data
  9. %  z(i,j) = f(x(i),y(j)), i=1,...,I, j=1,...,J , e.g.,
  10.  
  11. x = sort([[0:10]/10,.03 .07, .93 .97]);
  12. y = sort([[0:6]/6,.03 .07, .93 .97]);
  13. z = franke(x'*ones(1,length(y)),ones(length(x),1)*y);
  14.  
  15. %  Here is a plot of the data ..
  16.  
  17. pause                                               %Touch any key to continue
  18.  
  19. mesh(z,[50,50]);pause
  20.  
  21. % It doesn't give an accurate image of the data because the MATLAB function
  22. %  mesh  has no facilities for data from a  n o n uniform rectangular grid.
  23. % I chose point density somewhat higher near the boundary, to pin down the
  24. % approximation there.
  25.  
  26. pause                                               %Touch any key to continue
  27.  
  28. % Next, we choose some appropriate knot sequence and spline order for the 
  29. % y-direction, e.g.,
  30.  
  31. ky = 3; knotsy = augknt([0,.25,.5,.75,1],ky);
  32.  
  33. % Then
  34.  
  35. sp=spap2(knotsy,ky,y,z);
  36.  
  37. % provides a spline approximation to all the curves  (y,z(i,:)) .
  38. % In particular, the statement
  39.  
  40. yy=[-.1:.05:1.1];
  41. vals = fnval(sp,yy);
  42.  
  43. % provides the array  vals , whose entry  vals(i,j)  can be taken as an
  44. % approximation to the value  f(x(i),yy(j))  of the underlying function
  45. %  f  at the mesh-point (x(i),yy(j)) .  This is evident when we plot  vals  
  46. % using  mesh :
  47.  
  48. pause                                               %Touch any key to continue
  49.  
  50. mesh(vals,[50,50]);pause
  51.  
  52. % Note that, for each  x(i) , both the first two and the last two values
  53. % are zero since both the first two and the last two points in  yy  are
  54. % outside the basic interval for the spline in  sp .
  55.  
  56. % Note also the ridges. They confirm that we are plotting here smooth curves in
  57. % one direction only.
  58.  
  59. pause
  60.  
  61. % To get an actual surface, you now have to go a step further.  Look at the
  62. % coefficients  coefsy  of the spline in  sp :
  63.  
  64. [ignored,coefsy]=spbrk(sp);
  65.  
  66. % Abstractly, you can think of the spline in  sp  as the function
  67.  
  68. %       y |--> sum_r coefsy(r,:) B_{r,ky}(y) 
  69.  
  70. % with the i-th entry  coefsy(r,i)  of the vector coefficient  coefsy(r,:)
  71. % corresponding to  x(i) , all  i .  This suggests approximating each 
  72. % coefficient vector  coefsy(r,:)  by a spline of the same order  kx  and with 
  73. % the same appropriate knot sequence  knotsx :
  74.  
  75. kx = 4; knotsx=augknt([0:.2:1],kx);
  76. sp2=spap2(knotsx,kx,x,coefsy');
  77.  
  78. pause                                               %Touch any key to continue
  79.  
  80. % Note that  spap2(knots,k,x,fx)  expects  fx(:,j)  to be the datum at  x(j) ,
  81. % i.e., expects each  c o l u m n  of  fx  to be a datum. Since we wanted to 
  82. % fit the data  coefsy(r,:)  at  x(r) , all  r , we have to present  spap2  
  83. % with the  t r a n s p o s e  of  coefsy .
  84.  
  85. % Now consider the transpose   coefs = cxy'  of the coefficients  cxy  of the 
  86. % resulting spline `curve' :
  87.  
  88. [ignored,cxy]=spbrk(sp2);
  89. coefs=cxy';
  90.  
  91. % It provides the  b i v a r i a t e  spline approximation
  92. %     (x,y) |--> sum_q sum_r coefs(q,r) B_{q,kx}(x) B_{r,ky}(y)
  93. % to the original data
  94. %    (x(i),y(j)) |-->  z(x(i),y(j)) .
  95.  
  96. pause                                               %Touch any key to continue
  97.  
  98. % To evaluate this spline surface at the grid (xv(i),yv(j)), e.g., the grid
  99.  
  100. xv=[0:.025:1];yv=[0:.025:1];
  101.  
  102. % you can do the following:
  103.  
  104. values = spcol(knotsx,kx,xv)*coefs*spcol(knotsy,ky,yv)';
  105.  
  106. % Here is the mesh-plot of these values: 
  107.  
  108. pause                                               %Touch any key to continue
  109.  
  110. mesh(values,[50,50]);pause
  111.  
  112. % This makes good sense since  spcol(knotsx,kx,xv)  is the matrix whose
  113. % (i,q)-entry equals the value  B_{q,kx}(xv(i))  at  xv(i)  of the  q-th 
  114. % B-spline of order  kx  for the knot sequence  knotsx .
  115.  
  116. pause                                               %Touch any key to continue
  117.  
  118. % Since the matrices  spcol(knotsx,kx,xv)  and  spcol(knotsy,ky,yv)  are 
  119. % banded, it may be more efficient (though perhaps more memory-consuming)
  120. % for `large'  xv  and  yv  to make use of   fnval , as follows:
  121.  
  122. value2=fnval(spmak(knotsx,fnval(spmak(knotsy,coefs),yv)'),xv)';
  123.  
  124.  
  125. % Here is a check, viz. the  r e l a t i v e  difference between the values 
  126. % computed in these two different ways:
  127.  
  128. disp( max(max(abs(values-value2)))/max(max(abs(values))) )
  129.  
  130. pause                                               %Touch any key to continue
  131.  
  132. % Here is also a plot of the error, i.e., the difference between the given data
  133. % and the value of the approximation at those data points:
  134.  
  135. errors = z -  spcol(knotsx,kx,x)*coefs*spcol(knotsy,ky,y)';
  136.  
  137. pause                                               %Touch any key to continue
  138.  
  139. mesh(errors,[50,50]);pause
  140.  
  141. % The  r e l a t i v e  error is of size
  142. disp( max(max(abs(errors)))/max(max(abs(z))) )
  143.  
  144. % This is perhaps not too impressive. On the other hand, we used only ...
  145. disp(size(coefs))
  146. % ... coefficients to fit a data array of size
  147. disp(size(z))
  148.  
  149.  
  150. pause                                               %Touch any key to continue
  151.  
  152. %    The approach followed here seems  b i a s e d :  We first think of the
  153. % given data  z  as describing a vector-valued function of  y , and then we
  154. % treat the matrix formed by the vector coefficients of the approximating 
  155. % curve as describing a vector-valued function of  x .
  156.  
  157. %    What happens when we take things in the opposite order, i.e., think of
  158. %  z  as describing a vector-valued function of  x , and then treat the matrix
  159. % made up from the vector coefficients of the approximating curve as describing
  160. % a vector-valued function of  y ?
  161.  
  162. %    Perhaps surprisingly, the final approximation is the same (up to
  163. % roundoff). Here is the numerical experiment.
  164.  
  165. %    First, we fit a spline curve to the data, but this time with  x  as the
  166. % independent variable, hence it is the   r o w s  of  z  which now become the
  167. % data points. Correspondingly, we must supply  z' (rather than  z ) to spap2:
  168.  
  169. pause                                               %Touch any key to continue
  170.  
  171. spb=spap2(knotsx,kx,x,z');
  172.  
  173. % ... thus obtaining a spline approximation to all the curves  (x,z(:,j)) .
  174. % In particular, the statement
  175.  
  176. valsb = (fnval(spb,xv))';
  177.  
  178. % provides the array  valsb , whose entry  valsb(i,j)  can be taken as an
  179. % approximation to the value  f(xv(i),y(j))  of the underlying function
  180. %  f  at the mesh-point (xv(i),y(j)) .  This is evident when we plot  valsb  
  181. % using  mesh :
  182.  
  183. pause                                               %Touch any key to continue
  184.  
  185. mesh(valsb,[50,50]);pause
  186.  
  187. % Note the ridges. They confirm that we are plotting here smooth curves in
  188. % one direction only.
  189.  
  190. pause                                               %Touch any key to continue
  191.  
  192. % Here, for a quick comparison is the earlier mesh of curves, with the smooth
  193. % curves running in the other direction:
  194.  
  195. pause                                               %Touch any key to continue
  196.  
  197. mesh(vals,[50,50]);pause
  198.  
  199. %    Now comes the second step, to get the actual surface. First, extract 
  200. % the coefficients:
  201.  
  202. [ignored,coefsx]=spbrk(spb);
  203.  
  204. % Abstractly, you can think of the spline in  spb  as the function
  205.  
  206. %       x |--> sum_r coefsx(r,:) B_{r,kx}(x) 
  207.  
  208. % with the j-th entry  coefsy(r,j)  of the vector coefficient  coefsx(r,:)
  209. % corresponding to  y(j) , all  j .  Thus we now fit each
  210. % coefficient vector  coefsx(r,:)  by a spline of the same order  ky  and with 
  211. % the same (appropriate) knot sequence  knotsy :
  212.  
  213. spb2=spap2(knotsy,ky,y,coefsx');
  214.  
  215. pause                                               %Touch any key to continue
  216.  
  217. % Note that we need again to transpose the coefficient array from  spb , 
  218. % since  spap2  takes the columns of that last input argument as the data 
  219. % points.  
  220.  
  221. % Correspondingly, there is no need now to transpose the coefficient array
  222. %  coefsb  of the resulting  `curve':
  223.  
  224. [ignored,coefsb]=spbrk(spb2);
  225.  
  226. %    The claim is that  coefsb  equals the earlier coefficient array  coefs
  227. % (up to round-off), and here is the test:
  228.  
  229. disp( max(max(abs(coefs - coefsb))) )
  230.  
  231. %     Not bad, eh? - See the User's Guide for an explanation.
  232.  
  233. %  Thus, the  b i v a r i a t e  spline approximation
  234. %     (x,y) |--> sum_q sum_r coefsb(q,r) B_{q,kx}(x) B_{r,ky}(y)
  235. % to the original data
  236. %    (x(i),y(j)) |-->  z(x(i),y(j)) 
  237. %
  238. % obtained coincides with the earlier one (which generated  coefs  rather than
  239. %  coefsb ).
  240.  
  241.  
  242. pause                                               %Touch any key to continue
  243.  
  244. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  245.  
  246. %    Since the data come from a smooth function, we should be interpolating
  247. % it, i.e., use  spapi  instead of  spap2 , or, equivalently, use  spap2
  248. % with the appropriate knot sequences. For illustration, here is the same 
  249. % process done with  spapi .
  250.  
  251. pause                                               %Touch any key to continue
  252.  
  253. % To recall, the data points were
  254. % x = sort([[0:10]/10,.03 .07, .93 .97]);
  255. % y = sort([[0:6]/6,.03 .07, .93 .97]);
  256.  
  257. % We use again quadratic splines in  y , hence use knots midway between data
  258. % points:
  259.  
  260. ly = length(y);
  261. knotsy = augknt(sort([0 1 (y(2:(ly-2))+y(3:(ly-1)))/2]),ky);
  262.  
  263. spi=spapi(knotsy,y,z);
  264. [ignored,coefsy] = spbrk(spi);
  265. pause                                               %Touch any key to continue
  266.  
  267. % We use again cubics in  x , and use the not-a-knot condition, therefore use
  268. % all but the second and the second-last data point as knots:
  269.  
  270. lx = length(x);
  271. knotsx = augknt(x([1,[3:(lx-2)],lx]),kx);
  272. spi2 = spapi(knotsx,x,coefsy');
  273.  
  274. [ignored,cxy] = spbrk(spi2);
  275. icoefs = cxy';
  276.  
  277. pause                                               %Touch any key to continue
  278.  
  279. % We are ready to evaluate the interpolant at a fine mesh:
  280.  
  281. ivalues = spcol(knotsx,kx,xv)*icoefs*spcol(knotsy,ky,yv)';
  282.  
  283. % Here is the mesh-plot of these values: 
  284.  
  285. pause                                               %Touch any key to continue
  286.  
  287. mesh(ivalues,[50,50]);pause
  288.  
  289.  
  290. % Its error, as an approximation to the Franke function, is computed next:
  291.  
  292. fvalues = franke(xv'*ones(1,length(yv)),ones(length(xv),1)*yv);
  293. error =  fvalues - ivalues;
  294.  
  295. % The error is of  r e l a t i v e  size ... 
  296. disp( max(max(abs(error)))/max(max(abs(fvalues))) )
  297.  
  298. %  ... which is better than the error at the data points of the
  299. % earlier least-squares approximation. For comparison, here is also the 
  300. % overall relative error of that least-squares approximation:
  301.  
  302. disp( max(max(abs(fvalues-values)))/max(max(abs(fvalues))) )
  303. pause                                               %Touch any key to continue
  304.  
  305.