I need to recreate the piecewise polynomial coefficients from values of the evaluated piecewise polynomial. I want to create an equivalent pp struct.
The pp has been stored as values sampled to enable a unique fit of each polynomial segment (i.e. values at the break times, and 4 internal points for each 6th order polynomial segment: 6 values, 6 polynomial coefficients to solve).
I thought I could use polyfit() on each break interval of samples to get each segment's polynomial coefficients, then use mkpp(). Scaled and centred, or not, the polyfit() coefficients in pp form do not reproduce the original samples, but evaluating polyval(polyfit()) for each segment does. I'm not clear why there's a difference.
What have I missed? Can it be done without the Curve Fitting Tool box?
An example for a single 6th order polynomial, split into 3 segments shows the discrepancy:
% Define polynomial coefs, x and y
p = [1, 2, 3, 4, 5, 6];x = -5:10;y = polyval(p, x);% Define a pp form with knots at -5, 0, 5, 10
d = 1;knotInterval = 5;breaks = -5:knotInterval:10;pieces = length(breaks)-1;coefs = nan(pieces*d, length(p));coefsScaled = nan(pieces*d, length(p));mu = nan(pieces*d, 2);yPolyval = nan(pieces, knotInterval+1);% For the 6 (x,y) values in each pp break interval, fit an order 6
% polynomial, centered and scaled polynomial, and evaluate the standard
% fitted polynomial.
for nPiece = 1:pieces idxPiece = x >= breaks(nPiece) & x <= breaks(nPiece+1); coefs(nPiece, :) = polyfit(x(idxPiece), y(idxPiece), length(p)-1); [coefsScaled(nPiece, :), ~, mu(nPiece, :)] = polyfit(x(idxPiece), y(idxPiece), length(p)-1); yPolyval(nPiece,:) = polyval(coefs(nPiece, :), x(idxPiece));end% Build pp for the coefs and scaled coefs
pp = mkpp(breaks, coefs, d);ppScaled = mkpp(breaks, coefsScaled, d);% Plot the original data, and the fitted pp and polynomials
xPolyval = [-5:0; 0:5; 5:10];plot(x, y, 'x-', x, ppval(pp, x), 'o--', x, ppval(ppScaled, x), '^--', ... xPolyval(1, :), yPolyval(1, :), 'sq-.', xPolyval(2, :), yPolyval(2, :), 'sq-.', ... xPolyval(3, :), yPolyval(3, :), 'sq-.')ylim(1e5*[-1, 3])legend({'True data', 'pp', 'ppScaled', ... 'Recovered polyval 1', 'Recovered polyval 2', 'Recovered polyval 3'})
Best Answer