Mercurial > forge
view main/optim/inst/polyfitinf.m @ 9930:d30cfca46e8a octave-forge
optim: upgrade license to GPLv3+ and mention on DESCRIPTION the other package licenses
author | carandraug |
---|---|
date | Fri, 30 Mar 2012 15:14:48 +0000 |
parents | ce0e14f1bcce |
children |
line wrap: on
line source
## Copyright (c) 1998-2011 Andrew V. Knyazev <andrew.knyazev@ucdenver.edu> ## All rights reserved. ## ## Redistribution and use in source and binary forms, with or without", ## modification, are permitted provided that the following conditions are met: ## ## 1 Redistributions of source code must retain the above copyright notice, ## this list of conditions and the following disclaimer. ## 2 Redistributions in binary form must reproduce the above copyright ## notice, this list of conditions and the following disclaimer in the ## documentation and/or other materials provided with the distribution. ## 3 Neither the name of the author nor the names of its contributors may be ## used to endorse or promote products derived from this software without ## specific prior written permission. ## ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' ## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ## ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ## ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ## SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ## CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. % function [A,REF,HMAX,H,R,EQUAL] = polyfitinf(M,N,K,X,Y,EPSH,MAXIT,REF0) % % Best polynomial approximation in discrete uniform norm % % INPUT VARIABLES: % % M : degree of the fitting polynomial % N : number of data points % X(N) : x-coordinates of data points % Y(N) : y-coordinates of data points % K : character of the polynomial: % K = 0 : mixed parity polynomial % K = 1 : odd polynomial ( X(1) must be > 0 ) % K = 2 : even polynomial ( X(1) must be >= 0 ) % EPSH : tolerance for leveling. A useful value for 24-bit % mantissa is EPSH = 2.0E-7 % MAXIT : upper limit for number of exchange steps % REF0(M2): initial alternating set ( N-vector ). This is an % OPTIONAL argument. The length M2 is given by: % M2 = M + 2 , if K = 0 % M2 = integer part of (M+3)/2 , if K = 1 % M2 = 2 + M/2 (M must be even) , if K = 2 % % OUTPUT VARIABLES: % % A : polynomial coefficients of the best approximation % in order of increasing powers: % p*(x) = A(1) + A(2)*x + A(3)*x^2 + ... % REF : selected alternating set of points % HMAX : maximum deviation ( uniform norm of p* - f ) % H : pointwise approximation errors % R : total number of iterations % EQUAL : success of failure of algorithm % EQUAL=1 : succesful % EQUAL=0 : convergence not acheived % EQUAL=-1: input error % EQUAL=-2: algorithm failure % % Relies on function EXCH, provided below. % % Example: % M = 5; N = 10000; K = 0; EPSH = 10^-12; MAXIT = 10; % X = linspace(-1,1,N); % uniformly spaced nodes on [-1,1] % k=1; Y = abs(X).^k; % the function Y to approximate % [A,REF,HMAX,H,R,EQUAL] = polyfitinf(M,N,K,X,Y,EPSH,MAXIT); % p = polyval(A,X); plot(X,Y,X,p) % p is the best approximation % % Note: using an even value of M, e.g., M=2, in the example above, makes % the algorithm to fail with EQUAL=-2, because of collocation, which % appears because both the appriximating function and the polynomial are % even functions. The way aroung it is to approximate only the right half % of the function, setting K = 2 : even polynomial. For example: % % N = 10000; K = 2; EPSH = 10^-12; MAXIT = 10; X = linspace(0,1,N); % for i = 1:2 % k = 2*i-1; Y = abs(X).^k; % for j = 1:4 % M = 2^j; % [~,~,HMAX] = polyfitinf(M,N,K,X,Y,EPSH,MAXIT); % approxerror(i,j) = HMAX; % end % end % disp('Table 3.1 from Approximation theory and methods, M.J.D.POWELL, p. 27'); % disp(' '); % disp(' n K=1 K=3'); % disp(' '); format short g; % disp([(2.^(1:4))' approxerror']); % % ALGORITHM: % % Computation of the polynomial that best approximates the data (X,Y) % in the discrete uniform norm, i.e. the polynomial with the minimum % value of max{ | p(x_i) - y_i | , x_i in X } . That polynomial, also % known as minimax polynomial, is obtained by the exchange algorithm, % a finite iterative process requiring, at most, % n % ( ) iterations ( usually p = M + 2. See also function EXCH ). % p % since this number can be very large , the routine may not converge % within MAXIT iterations . The other possibility of failure occurs % when there is insufficient floating point precision for the input % data chosen. % % CREDITS: This routine was developed and modified as % computer assignments in Approximation Theory courses by % Prof. Andrew Knyazev, University of Colorado Denver, USA. % % Team Fall 98 (Revision 1.0): % Chanchai Aniwathananon % Crhistopher Mehl % David A. Duran % Saulo P. Oliveira % % Team Spring 11 (Revision 1.1): Manuchehr Aminian % % The algorithm and the comments are based on a FORTRAN code written % by Joseph C. Simpson. The code is available on Netlib repository: % http://www.netlib.org/toms/501 % See also: Communications of the ACM, V14, pp.355-356(1971) % % NOTES: % % 1) A may contain the collocation polynomial % 2) If MAXIT is exceeded, REF contains a new reference set % 3) M, EPSH and REF can be altered during the execution % 4) To keep consistency to the original code , EPSH can be % negative. However, the use of REF0 is *NOT* determined by % EPSH< 0, but only by its inclusion as an input parameter. % % Some parts of the code can still take advantage of vectorization. % % Revision 1.0 from 1998 is a direct human translation of % the FORTRAN code http://www.netlib.org/toms/501 % Revision 1.1 is a clean-up and technical update. % Tested on MATLAB Version 7.11.0.584 (R2010b) and % GNU Octave Version 3.2.4 % $Revision: 1.1 $ $Date: 2011/08/3 $ % ************************************ beginning of POLYFITINF function [A,REF,HMAX,H,R,EQUAL] = polyfitinf(M,N,K,X,Y,EPSH,MAXIT,REF0) % Preassign output variables A,REF,HMAX,H,R,EQUAL in case of error return A = []; REF = []; HMAX = []; H = []; R = 0; EQUAL = -2; %%%% end preassignment % Setting M with respect to K MOLD = M; switch K case 1 K0 = 0; K1 = 1; Q1 = 1; Q2 = 2; M = (M-Q1)/2; case 2 K0 = 0; K1 = 0; Q1 = 0; Q2 = 2; % If the user has input odd M, but wants an even polynomial, % subtract 1 from M to prevent errors later. The outputs should be % mathematically equivalent. if mod(M,2) == 1 M = M-1; end M = (M-Q1)/2; otherwise if (K ~= 0) warning('polyfitinf:MixedParity','Using mixed parity polynomial...'); end K0 = 1; K1 = 0; Q1 = 0; Q2 = 1; end P = M + 2; % Check input data consistency if ( (length(X) ~= N) || (length(Y) ~= N) ) error('Input Error: check data lengths'); end if (P > N) error('Input Error: insufficient data points'); end if (M < 0) error('Input Error: insufficient degree'); end if ( (K == 2) && (X(1) < 0) ) || ( (K == 1) && (X(1) <= 0) ) error('Input Error: X(1) inconsistent with parity'); end if any(diff(X)<0) error('Input Error: Abscissae out of order'); end ITEMP = MOLD + 1; A = zeros(1,ITEMP); ITEMP = P + 2; Z = zeros(1,ITEMP); Z(1) = 0; Z(ITEMP) = N + 1; EPSH = abs(EPSH); % Read initial reference set into Z, if available. if (nargin == 8) J = 0; Z(2:(P+1))= REF0(1:P); % Check if REF is monotonically increasing if ( any(diff(REF0) < 0) || any(REF0 > J) ) error('Input Error : Bad initial reference set'); end else % Loads Z with the points closest to the Chebychev abscissas X1 = X(1); XE = X(N); % Setting parity-dependent parameters if (K0 == 1) XA = XE + X1; XE = XE - X1; Q = pi/(M + 1.0); else XA = 0.; XE = XE + XE; ITEMP = 2*(M+1) + Q1; Q = pi/(ITEMP); end % Calculate the J-th Chebyshev abcissa and load Z(J+1) % with the appropriate index from the data abcissas for JJ = 1:P J = P + 1 - JJ; X1 = XA + XE*( cos(Q*(P-J)) ); ITEMP = J + 2; R = Z(ITEMP); HIGH = R - 1; FLAG = 1; if (HIGH >= 2) II = 2; while ( (II <= HIGH) && (FLAG == 1) ) I = HIGH + 2 - II; ITEMP = I - 1; % If the Chebyschev abscissa is bracketed by % two input abcissas, get out of the while loop if (X(I)+X(ITEMP) <= X1) FLAG = 0; end II = II + 1; end end if (FLAG == 1) I = 1; end ITEMP = J + 1; if (I < R) Z(ITEMP) = I; else Z(ITEMP) = R - 1; end end % If the lower Chebyshev abcissas are less than X(1), % load the lower elements of Z with the lowest points IND = find(Z(2:end) >= (1:(length(Z)-1))); try TEMP = IND(1); % If IND is empty, do nothing. catch exception % The catch will be that IND is an empty array. if strcmpi(exception.identifier,'MATLAB:badsubscript') % This will be the exception. Do nothing. end end if TEMP~=1 Z(2:TEMP) = (1:(TEMP-1))'; end end % M1 entry. Initialize variables to prepare for exchange iteration ITEMP = M + 1; % Zero the AA array AA = zeros(1,ITEMP); % Load H with the ordinates and XX(I) with the abscissas if the % polynomial is mixed . If it is even or odd , load XX with the % squares of the abscissas. H(1:N) = Y(1:N); if (K0 <=0) XX(1:N) = X(1:N).^2; else XX(1:N) = X(1:N); end B1 = 0; B2 = 0; B3 = 0; R = -1; T = 0.; % Iteration entry. R is the iteration index C = zeros(1,P); D = zeros(1,P); DAA = zeros(1,M+1); FLAG = 1; while ( (R < MAXIT) && (FLAG == 1) ) R = R + 1; % LABEL 350 %S = 1.; % Computation of div. differences schemes if (K1 > 0) % If the polynomial is mixed or even: %for I = 1:P % S = -S; % ITEMP = I + 1; % J = Z(ITEMP); % Q = X(J); % C(I) = (H(J) + S*T)/Q; % D(I) = S/Q; %end I = (1:P); S = (-1).^I; ITEMP = I+1; J = Z(ITEMP); C(I) = (H(J) + S*T)./X(J); D(I) = S./Q; clear I ITEMP S J else % If the polynomial is odd: %for I = 1:P % S = -S; % ITEMP = I + 1; % ITEMP = Z(ITEMP); % C(I) = H(ITEMP) + S*T; % D(I) = S; %end I = (1:P); S = (-1).^I; ITEMP = I+1; C(I) = H( Z(ITEMP) ) + S.*T; D(I) = S; clear I ITEMP S end for I = 2:P for JJ = I:P J = P + I - JJ; ITEMP = J + 1; ITEMP = Z(ITEMP); QD = XX(ITEMP); ITEMP = 2 + J - I; ITEMP = Z(ITEMP); QD = QD - XX(ITEMP); ITEMP = J - 1; C(J) = (C(J)-C(ITEMP))/QD; D(J) = (D(J)-D(ITEMP))/QD; end end DT = -C(P)/D(P); T = T + DT; % Computation of polynomial coefficients HIGH = M + 1; for II = 1:HIGH I = HIGH - II; ITEMP = I + 1; DAA(ITEMP) = C(ITEMP) + DT*D(ITEMP); ITEMP = I + 2; ITEMP = Z(ITEMP); QD = XX(ITEMP); LOW = I + 1; if (M >= LOW) DAA(LOW:M) = DAA(LOW:M) - QD*DAA(((LOW:M)+1)); end end AA(1:HIGH) = AA(1:HIGH) + DAA(1:HIGH); % Evaluation of the polynomial to get the approximation errors MAXX = 0.; H = zeros(1,N); for I = 1:N SD = AA(HIGH); QD = XX(I); if (M > 0) for J = M:-1:1 SD = SD*QD + AA(J); end end if (K1 > 0) % If the polynomial is odd, multiply SD by X(I) SD = SD*X(I); end QD = Y(I) - SD; H(I) = Y(I) - SD; if (abs(QD) > MAXX) % Load MAXX with the largest magnitude % of the approximation array MAXX = abs(QD); end end % Test for alternating signs ITEMP = Z(2); if (H(ITEMP) == 0.) % This represents a case where the polynomial % exactly predicts a data point warning('polyfitinf:Collocation','Collocation has occured.'); if (B3 > 0) B3 = -1; FLAG = 0; else B3 = 1; if (EPSH < MAXX) warning('polyfitinf:AnotherTry','1 more attempt with middle points'); LOW = (N+1)/2 - (P+1)/2 + 1; HIGH = LOW + P; Z(LOW:HIGH) = ( (LOW:HIGH) -1); else disp('Normal Exit.'); FLAG = 0; end end else if (H(ITEMP) > 0.) J = -1; else J = 1; end I = 2; FLAG2 = 1; while ( (I <= P) && (FLAG2 == 1) ) ITEMP = I + 1; ITEMP = Z(ITEMP); if (H(ITEMP) == 0.) J = 0; warning('polyfitinf:Collocation','Collocation has occured.'); if (B3 > 0) B3 = -1; FLAG = 0; else B3 = 1; if (EPSH < MAXX) warning('polyfitinf:AnotherTry','1 more attempt with middle points'); LOW = (N+1)/2 - (P+1)/2 + 1; HIGH = LOW + P; Z(LOW:HIGH) = ( (LOW:HIGH) -1); else disp('Normal Exit.'); FLAG = 0; end end FLAG2 = 0; else if (H(ITEMP) < 0) JJ = -1; else JJ = 1; end if (J~=JJ) % Error entry: bad accuracy for calculation B1 = 1; FLAG2 = 0; FLAG = 0; else J = -J; end end I = I + 1; end % end of while % Search for another reference if (FLAG2*FLAG == 1) [H,Z,EQUAL] = exch(N, P, EPSH, H, Z); if (EQUAL > 0) FLAG = 0; else if (R >= MAXIT) B2 = 1; FLAG = 0; end end end end % end of if over H(ITEMP) end; % end of iteration loop % M2 entry; load output variables and return HIGH = M + 1; % Load the coefficients into A array A(Q1 + Q2*(((1:HIGH)-1)) + 1) = AA(1:HIGH); % Load REF with the final reference points REF(1:P) = Z((1:P) + 1); HMAX = MAXX; if (B3 < 0) EQUAL = -2; warning('polyfitinf:Collocation','polyfitinf terminates'); end if (B1 > 0) EQUAL = -2; warning('polyfitinf:NoAlternatingSigns','Alternating signs not observed'); end if (B2 > 0) EQUAL = 0; warning('polyfitinf:MaxIterationsReached','MAXIT was reached, current ref. set saved in REF.'); end % Reverse the order of A to make it compatible with MATLAB'S polyval() function. A = A(end:-1:1); endfunction % ****************************************** end of POLYFITINF function [H,Z,EQUAL] = exch(N, P, EPSH, H, Z) % function [H,Z,EQUAL] = exch(N, P, EPSH, H, Z) % % EXCH: exchange algorithm % % INPUT VARIABLES: % N : number of data points % P : number of reference points % EPSH : tolerance for leveling. % Z : old reference indices % % OUTPUT VARIABLES: % H : pointwise approximation errors % Z : new reference indices % EQUAL : EQUAL=1 : normal exchange % EQUAL=0 : old and new references are equal % % CREDITS: This routine was developed and modified as % computer assignments in Approximation Theory courses by % Prof. Andrew Knyazev, University of Colorado Denver, USA. % % Team Fall 98 (Revision 1.0): % Chanchai Aniwathananon % Crhistopher Mehl % David A. Duran % Saulo P. Oliveira % % Team Spring 11 (Revision 1.1): Manuchehr Aminian % % The algorithm and the comments are based on a FORTRAN code written % by Joseph C. Simpson. The code is available on Netlib repository: % http://www.netlib.org/toms/501 % See also: Communications of the ACM, V14, pp.355-356(1971) % % Revision 1.0 from 1998 is a direct human translation of % the FORTRAN code http://www.netlib.org/toms/501 % Revision 1.1 is a clean-up and technical update. % Tested on MATLAB Version 7.11.0.584 (R2010b) and % GNU Octave Version 3.2.4 % License: BSD % Copyright 1998-2011 Andrew V. Knyazev % $Revision: 1.1 $ $Date: 2011/05/17 $ % ************************************ beginning of exch EQUAL = 0; L = 0; ITEMP = Z(2); % SIG is arbitrarily chosen equal to the sign of the input % point. This will be adjusted later if necessary. if (H(ITEMP) <= 0) SIG = 1.; else SIG = -1.; end % The next loop prescans Z to insure it is a proper choice, i.e % resets Z if necessary so that maximum error points are chosen, % given the sign convention mentioned above. In order to work % properly, this section requires Z(1) = 0 and Z(P+2) = N + 1 . for I = 1:P MAXX = 0.; SIG = -SIG; ITEMP = I + 2; ZE = Z(ITEMP) - 1; LOW = Z(I) + 1; % Scan the open point interval containing only the 1th initial % reference point. In the interval pick the point with largest % magnitude and correct sign. Most of the sorting occurs in % this section. SIG contains the sign assumed for H(I). for J = LOW:ZE if (SIG*(H(J)-MAXX) > 0) MAXX = H(J); INDEX = J; end end ITEMP = I + 1; ITEMP = Z(ITEMP); MAXL = abs(MAXX); % If the MAX error is significantly greater than the % input point, switch to this point. if (abs( MAXX - H(ITEMP) )/MAXL > EPSH) ITEMP = I + 1; Z(ITEMP) = INDEX; L = 1; end end % MAXL = 0.; MAXR = 0.; ITEMP = P + 1; LOW = Z(ITEMP) + 1; % if (LOW <= N) % Find the error with largest abs value and proper sign % from among the points above the last reference point. % This section is necessary because the set of points % chosen may begin with the wrong sign alternation. for J = LOW:N if (SIG*(MAXR-H(J)) > 0) MAXR = H(J); INDR = J; end end end % Find the error with largest abs value and proper sign % from among the points below the 1st reference point. % This section is necessary by the same reason as above. ITEMP = Z(2); HZ1 = H(ITEMP); HIGH = ITEMP -1; if (HIGH > 0) if (HZ1 < 0) SIG = -1.; elseif (HZ1 == 0) SIG = 0.; else SIG = 1.; end for J = 1:HIGH if (SIG*(MAXL-H(J)) > 0) MAXL = H(J); INDL = J; end end end % MAXL and MAXR contain the magnitude of the significant % errors outside the reference point set. If either is % zero, the reference point set extends to the end point % on that side of the interval. MAXL = abs(MAXL); MAXR = abs(MAXR); HZ1 = abs(HZ1); ITEMP = P + 1; ITEMP = Z(ITEMP); HZP = abs(H(ITEMP)); % L = 0 implies that the previous prescan did not change % any points. If L = 0 and MAXL, MAXR are not significant % if compared with upper and lower reference point errors, % respectively, use the EQUAL exit. FLAG1 = 1; if (L == 0) if ( (MAXL == 0) || (EPSH >= (MAXL-HZP)/MAXL) ) if ( (MAXR == 0) || (EPSH >= (MAXR-HZ1)/MAXR) ) FLAG1 = 0; EQUAL = 1; end end end if ( (MAXL == 0) && (MAXR == 0) ) FLAG1 = 0; end if ( (MAXL > MAXR) && (MAXL <= HZP) && (MAXR < HZ1) ) FLAG1 = 0; end if ( (MAXL <= MAXR) && (MAXR <= HZ1) && (MAXL < HZP) ) FLAG1 = 0; end % If a point outside the present reference set must be % included, (i.e. the sign of the 1st point previously % assumed is wrong) shift to the side of largest % relative error first. if (FLAG1 == 1) FLAG2 = 1; if ( (MAXL > MAXR) && (MAXL > HZP) ) FLAG2 = 0; end if ( (MAXL <= MAXR) && (MAXR <= HZ1) ) FLAG2 = 0; end if (FLAG2 == 1) % SHR entry. This section inserts a point from % above the prescan point set INDEX = Z(2); % shift point set down, dropping the lowest point Z(2:P) = Z((2:P)+1); ITEMP = P + 1; % add the next high point Z(ITEMP)=INDR; % if MAXL > 0 replace reference points from the left, % stopping the 1st time the candidate for replacement % is greater than in magnitude than the prospective % replacee. Alternation of signs is preserved because % non-replacement immediately terminates the process. if (MAXL > 0) I = 2; FLAG3 = 1; while ( (I <= P) && (FLAG3 == 1) ) ITEMP = Z(I); if ( abs(H(INDL)) >= abs(H(ITEMP)) ) J = Z(I); Z(I) = INDL; INDL = INDEX; INDEX = J; else FLAG3 = 0; end I = I + 1; end end else % SHL entry. This section inserts a point from below the % prescan point set. ITEMP = P + 1 ; INDEX = Z(ITEMP); Z((2:P)+1) = Z(2:P); % store lowest point in Z(2) Z(2) = INDL; % if MAXR > 0 replace reference points from the right, % stopping the 1st time the candidate for replacement % is greater than in magnitude than the prospective % replacee. if (MAXR > 0) II = 2; FLAG3 = 1; while ( (II <= P) && (FLAG3 == 1) ) I = P + 2 - II; ITEMP = I + 1; HIGH = Z(ITEMP); if ( abs(H(INDR)) >= abs(H(HIGH)) ) J = Z(ITEMP); Z(ITEMP) = INDR; INDR = INDEX; INDEX = J; else FLAG3 = 0; end II = II + 1; end end end end endfunction % ****************************************** end of exch