Monotone kubisk interpolation
Inom det matematiska området för numerisk analys är monoton kubisk interpolation en variant av kubisk interpolation som bevarar monotoniteten hos datamängden som interpoleras .
Monotonicitet bevaras genom linjär interpolation men garanteras inte av kubisk interpolation .
Monotone kubisk Hermite interpolation
Monotone interpolation kan åstadkommas med kubisk Hermite spline med tangenterna modifierade för att säkerställa monotoniteten hos den resulterande Hermite spline.
En algoritm är också tillgänglig för monoton kvintisk Hermite-interpolation.
Interpolant val
Det finns flera sätt att välja interpolerande tangenter för varje datapunkt. Detta avsnitt kommer att beskriva användningen av Fritsch–Carlson-metoden. Observera att endast ett pass av algoritmen krävs.
Låt datapunkterna vara indexerade i sorterad ordning för .
- Beräkna lutningarna för sekantlinjerna mellan på varandra följande punkter:
för .
-
Dessa tilldelningar är provisoriska och kan ersättas i de återstående stegen. Initiera tangenterna vid varje inre datapunkt som medelvärdet av sekanterna,
för . För endpoints, använd ensidiga skillnader:
Om och har motsatta tecken, sätt ..
-
För , där någonsin (där alltid två på varandra följande är lika), set eftersom spline som förbinder dessa punkter måste vara platt för att bevara monotoniteten. Ignorera steg 4 och 5 för de .
- Låt
Om antingen eller är negativ, är indatapunkterna inte strikt monotona, och är ett lokalt extremum. I sådana fall bitvisa monotona kurvor fortfarande genereras genom att välja om eller om , även om strikt monotoni inte är möjlig globalt..
- För att förhindra överskjutning och säkerställa monotonitet måste minst ett av följande tre villkor vara uppfyllt:
- (a) funktionen
, eller
- (b) eller (
- c) .
- Endast villkor (a) är tillräckligt för att säkerställa strikt monotoni: måste vara positivt.
- Ett enkelt sätt att uppfylla denna begränsning är att begränsa vektorn till en cirkel med radie 3. Det vill säga, om ställ sedan in
och skala om tangenterna via,
.
- Alternativt är det tillräckligt att begränsa och . För att åstadkomma detta om in .
- (a) funktionen
Kubisk interpolation
Efter förbearbetningen ovan är utvärdering av den interpolerade spline ekvivalent med cubic Hermite spline , med hjälp av data , och för .
För att utvärdera vid , hitta indexet i sekvensen där ligger mellan och , det vill säga: . Beräkna
då är det interpolerade värdet
där är basfunktionerna för den kubiska Hermite spline .
Exempel implementering
Följande JavaScript- implementering tar en datamängd och producerar en monoton kubisk spline-interpolantfunktion:
0
0 0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0 0
0
/* * Monotone kubisk spline-interpolation * Användningsexempel listat längst ner; detta är ett fullt fungerande paket. Till exempel * kan detta utföras antingen på webbplatser som * https://www.programiz.com/javascript/online-compiler/ * eller med nodeJS. */ function DEBUG ( s ) { /* Avkommentera följande för att möjliggöra utförlig utmatning av lösaren: */ //console.log(s); } var outputCounter = ; var createInterpolant = funktion ( xs , ys ) { var i , length = xs . längd ; // Deal with length issues if ( length != ys . length ) { throw 'Behöver ett lika stort antal xs och ys.' ; } if ( längd === ) { return funktion ( x ) { return ; }; } if ( längd === 1 ) { // Impl: Förberäkning av resultatet förhindrar problem om ys muteras senare och tillåter sophämtning av ys // Impl: Unary plus konverterar korrekt värden till tal var result = + ys [ ]; return funktion ( x ) { returnera resultat ; }; } // Ordna om xs och ys så att xs sorteras var indexes = []; för ( i = ; i < längd ; i ++ ) { index . trycka ( i ); } index . sort ( funktion ( a , b ) { return xs [ a ] < xs [ b ] ? - 1 : 1 ; }); var oldXs = xs , oldYs = ys ; // Impl: Att skapa nya arrayer förhindrar också problem om inmatningsarrayerna muteras senare xs = []; ys = []; // Impl: Unary plus konverterar korrekt värden till tal för ( i = ; i < längd ; i ++ ) { xs [ i ] = + oldXs [ indexerar [ i ]]; ys [ i ] = + oldYs [ indexerar [ i ]]; } DEBUG ( "debug: xs = [ " + xs + " ]" ) DEBUG ( "debug: ys = [ " + ys + " ]" ) // Få på varandra följande skillnader och lutningar var dys = [], dxs = [] , ms = []; för ( i = ; i < längd - 1 ; i ++ ) { var dx = xs [ i + 1 ] - xs [ i ], dy = ys [ i + 1 ] - ys [ i ]; dxs [ i ] = dx ; dys [ i ] = dy ; ms [ i ] = dy / dx ; } // Få grad-1 koefficienter var c1s = [ ms [ ]]; för ( i = ; i < dxs . längd - 1 ; i ++ ) { var m = ms [ i ], mNext = ms [ i + 1 ]; if ( m * mNext <= ) { c1s [ i ] = ; } else { var dx_ = dxs [ i ], dxNext = dxs [ i + 1 ], common = dx_ + dxNext ; c1s [ i ] = 3 * common / (( common + dxNext ) / m + ( common + dx_ ) / mNext ); } } c1s . push ( ms [ ms . längd - 1 ]); DEBUG ( "debug: dxs = [ " + dxs + " ]" ) DEBUG ( "debug: ms = [ " + ms + " ]" ) DEBUG ( "debug: c1s.length = " + c1s . length ) DEBUG ( " debug: c1s = [ " + c1s + " ]" ) // Få grad-2 och grad-3 koefficienter var c2s = [], c3s = []; för ( i = ; i < cls . längd - 1 ; i ++ ) { var c1 = c1s [ i ]; var m_ = ms [ i ]; var invDx = 1 / dxs [ i ]; var common_ = c1 + c1s [ i + 1 ] - m_ - m_ ; DEBUG ( "debug: " + i + ". c1 = " + c1 ); DEBUG ( "debug: " + i + ". m_ = " + m_ ); DEBUG ( "debug: " + i + ". invDx = " + invDx ); DEBUG ( "debug: " + i + ". common_ = " + common_ ); c2s [ i ] = ( m_ - c1 - common_ ) * invDx ; c3s [ i ] = common_ * invDx * invDx ; } DEBUG ( "debug: c2s = [ " + c2s + " ]" ) DEBUG ( "debug: c3s = [ " + c3s + " ]" ) // Returnera interpolant funktion returfunktion ( x ) { // Punkten längst till höger i datasetet ska ge ett exakt resultat var i = xs . längd - 1 ; // Avkommentera följande för att endast returnera det interpolerade värdet. //if (x == xs[i]) { returnera ys[i]; } // Sök efter intervallet x är i, returnera motsvarande y om x är ett av de ursprungliga xs var low = , mid , high = c3s . längd - 1 ; while ( låg <= hög ) { mid = Math . golv ( 0,5 * ( låg + hög )); var xHere = xs [ miden ]; if ( xHere < x ) { low = mid + 1 ; } else if ( xHere > x ) { high = mid - 1 ; } else { // Avkommentera följande för att endast returnera det interpolerade värdet. //retur ys[miden]; låg = c3s . längd - 1 ; hög = medel ; bryta ; } } i = Matte . max ( , hög ); // Interpolera var diff = x - xs [ i ]; outputCounter ++ ; var interpolatedValue = ys [ i ] + diff * ( c1s [ i ] + diff * ( c2s [ i ] + diff * c3s [ i ])); // Värdet på interpolatorns derivata vid denna punkt. var derivativeValue = c1s [ i ] + diff * ( 2 * c2s [ i ] + diff * 3 * c3s [ i ]); DEBUG ( "debug: #" + outputCounter + ". x = " + x + ". i = " + i + ", diff = " + diff + ", interpolatedValue = " + interpolatedValue + ", derivativeValue = " + derivativeValue ) ; // Avkommentera följande för att endast returnera det interpolerade värdet. // returnera interpolatedValue; return [ interpoleratVärde , derivatVärde ]; }; }; /* Användningsexempel nedan kommer att uppskatta x^2 för 0 <= x <= 4. Kommandoradsanvändningsexempel (kräver installation av nodejs): node monotone-cubic-spline.js */ var X = [ , 1 , 2 , 3 4 ] ; var F = [ , 1 , 4 , 9 , 16 ]; var f = skapa Interpolant ( X , F ); var N = X . längd ; konsol . log ( " # BLOCK 0 :: Data för monotone-cubic-spline.js" ) ; konsol . log ( "X" + "\t" + "F" ); for ( var i = ; i < N ; i += 1 ) { konsol . log ( F [ i ] + '\t' + X [ i ]); } konsolen . log ( "" ); konsol . log ( "" ); konsol . log ( "# BLOCK 1 :: Interpolerad data för monotone-cubic-spline.js" ) ; konsol . log ( " x " + "\t\t" + " P(x) " + "\t\t" + "dP(x)/dx " ); var meddelande = '' ; var M = 25 ; för ( vari = ; i < = M ; i + = 1 ) { varx = X [ ] + ( X [ N - 1 ] -X [ ] ) * i / M ; var rvals = f ( x ); var P = rvals [ ]; var D = rvals [ 1 ]; meddelande += x . toPrecision ( 15 ) + '\t' + P . toPrecision ( 15 ) + '\t' + D . toPrecision ( 15 ) + '\n' ; } konsolen . log ( meddelande );
- Fritsch, FN; Carlson, RE (1980). "Monotone bitvis kubisk interpolation". SIAM Journal on Numerical Analysis . SIAM. 17 (2): 238–246. doi : 10.1137/0717021 .
- Dougherty, RL; Edelman, A.; Hyman, JM (april 1989). "Positivitets-, monotoni- eller konvexitetsbevarande kubisk och kvintisk Hermite-interpolation" . Beräkningsmatematik . 52 (186): 471–494. doi : 10.2307/2008477 .
externa länkar
- GPLv 2 licensierad C++ implementering: MonotCubicInterpolator.cpp MonotCubicInterpolator.hpp