このライブラリは、人気のあるmath.jsライブラリの拡張機能です。単純な数学関数の積分を見つけることができるintegral
関数を追加します。また、使用される統合ルールでも柔軟であり、標準ルールの代わりに、または標準ルールに加えてカスタムルールを使用できます。
このソフトウェアはまだベータ版と見なされていることに注意してください。したがって、バグや大まかなエッジに出くわした場合は、問題を提出してください!
パッケージをインストールするには、以下を使用してください。
npm install mathjs-simple-integral
拡張機能をMath.jsに登録するには、以下を使用してください。
math . import ( require ( 'mathjs-simple-integral' ) ) ;
これにより、Math.jsに関数math.integral
が追加されます。
この拡張機能の基本的な使用法は非常に簡単です。インテグランド( Node
または文字列として)と統合変数( SymbolNode
または文字列として)を提供するだけです。
math . integral ( 'x^2' , 'x' ) ; // 'x ^ 3 / 3'
math . integral ( '1/x' , 'x' ) ; // 'log(abs(x))'
math . integral ( 'e^x' , 'x' ) ; // 'e^x'
math . integral ( 'cos(2*x+pi/6)' , 'x' ) ; // 'sin(2 * x + pi / 6) / 2'
integral
与えられた式の積分を見つけることができない場合、エラーが発生します。
math . integral ( 'e^(x^2)' ) ; // Error: Unable to find integral of "e ^ (x ^ 2)" with respect to "x"
デフォルトでは、統合プロセスが扱いにくい式を生成できるため、出力でintegral
math.simplify
実行します。ただし、 simplify
がオプションの3番目のパラメーターにfalse
に設定されたoptions
オブジェクトを渡すことにより、 integral
から生の未成年の出力を取得することができます。
math . integral ( 'x^2' , 'x' , { simplify : false } ) ; // '1 / (2 + 1) * x ^ (2 + 1)'
math . integral ( '1/(2*x)' , 'x' , { simplify : false } ) ; // '2 ^ -1 * log(abs(x))'
この実装では、統合ルールは、パラメーター(1) expr
、統合される式として使用する関数として定義されます。 (2) context
、統合のコンテキスト。 (3) subIntegral
、積分のサブエクスペッションまたは書き換えの形を統合しようとする関数。統合ルールは、計算された積分、またはそれが見つからない場合はnull
返します。既に実装されている多くの標準統合( math.integral.rules
にあります)に加えて、統合ルールのカスタムセットを指定できます。
たとえば、上部の不完全なガンマ関数を表すカスタム関数myUpperGamma
を追加したとします。これは、それを統合するためのサポートを追加したいと考えています。特に、このルールを実装したいと考えていますintegral("myUpperGamma(s,x)", "x") = x*myUpperGamma(s,x) - myUpperGamma(s+1, x)
(ここで確認)。まず、このルールを関数として書きましょう。
var myUpperGammaRule = function ( expr , context , subIntegral ) {
// Ensure we are trying to integrate a FunctionNode
if ( expr . type === "FunctionNode" ) {
// Ensure we are trying to integrate 'myUpperGamma' and that it has 2 arguments
if ( expr . name === "myUpperGamma" && expr . args . length === 2 ) {
// Ensure that the first argument is constant and the second one is
// the variable of integration
if ( context . isConstant ( expr . args [ 0 ] ) && expr . args [ 1 ] . equals ( context . variable ) ) {
// Yay, we matched 'myUpperGamma(s,x)', so we know the integral!
return new OperatorNode ( '-' , 'subtract' , [
new OperatorNode ( '*' , 'multiply' , [
context . variable ,
new FunctionNode ( 'myUpperGamma' , [
expr . args [ 0 ] ,
context . variable
] )
] ) ,
new FunctionNode ( 'myUpperGamma' , [
new OperatorNode ( '+' , 'add' , [
expr . args [ 0 ] ,
new ConstantNode ( 1 )
] ) ,
context . variable
] )
] ) ;
}
}
}
// Our rule, didn't apply :(
// return undefined
}
これにより、カスタム統合ルールができたので、標準ルールのリストに追加し、この複合リストを使用してmyUpperGamma
が関与する統合を見つけることができます。
// Define our integration rules to include our custom rule
var options = { rules : math . integral . rules . concat ( [ myUpperGammaRule ] ) } ;
// Compute integrals of our function!
math . integral ( 'myUpperGamma(a,x)' , 'x' , options ) ;
// 'x*myUpperGamma(a,x) - myUpperGamma(a+1,x)'
math . integral ( 'myUpperGamma(a^2,x) + 13' , 'x' , options ) ;
// 'x*myUpperGamma(a^2,x) - myUpperGamma(a^2+1,x) + 13*x'
math . integral ( 'myUpperGamma(a,5*x+99)' , 'x' , options ) ;
// '((5*x+99) * myUpperGamma(a, 5*x+99) - myUpperGamma(a+1, 5*x+99)) / 5'
math . integral ( 'sqrt(myUpperGamma(a,x)) * sqrt(myUpperGamma(a,x))' , 'x' , options ) ;
// 'x*myUpperGamma(a,x) - myUpperGamma(a+1,x)'
myUpperGamma
に加えて、別のカスタム関数mySum
あります。Add add
同様に、さまざまな数の引数を受け入れて引数を追加しますが、他の非数学的な機能も実行します(評価前に各引数をログに記録するなど、または、その議論がNaN
であることを確認するために確認してください)。これで、 mySum
上の積分の直線性を表すルールをインテグレーターに追加できます。
// integral(mySum(f(x), g(x), ...), x) = mySum(integral(f(x), x), integral(g(x), x), ...)
function mySumRule ( expr , context , subIntegral ) {
// Ensure we are trying to integrate a FunctionNode
if ( expr . type === "FunctionNode" ) {
// Ensure we are trying to integrate 'mySum'
if ( expr . name === "mySum" ) {
// Try to find integrals of all the terms in the sum
var termIntegrals = expr . args . map ( function ( term ) {
return subIntegral ( term , context , 'sum rule (mySum)' ) ;
} ) ;
// Only if all terms had integrals did we actually find an integral
if ( termIntegrals . every ( function ( termInt ) { return ! ! termInt ; } ) ) {
// Yay, we found the integral!
return new FunctionNode ( 'mySum' , termIntegrals ) ;
}
}
}
// return undefined
}
subIntegral
ルコールバックを使用して、すべての用語の積分を合計で見つける方法に注意し、すべての個々の用語を統合できる場合にのみ、 mySum
式全体の積分を返します。これで、両方のカスタムルールを使用すると、 mySum
とmyUpperGamma
の両方と式を統合できます。
var options = { rules : math . integral . rules . concat ( [ myUpperGammaRule , mySumRule ] ) } ;
math . integral ( "mySum(3*x^2, x, 1/x, 1)" , "x" , options ) ;
// 'mySum(x^3, x^2/2, log(abs(x)), x)'
math . integral ( "mySum(2*x, myUpperGamma(a,x))" , "x" , options ) ;
// 'mySum(x^2, x*myUpperGamma(a,x) - myUpperGamma(a+1,x))'
オプションオブジェクトには、 true
に設定されている場合、インテグレーターに「作業を表示」するように指示するプロパティdebugPrint
を持つことができます。つまり、撮影したすべての手順と特定の統合で適用されるすべてのルールをコンソールに印刷します。たとえば、 integral("x^2 + sin(pi*x)", "x", {debugPrint: true})
、コンソールで次の出力を生成します。
find integral of (x ^ 2) + (sin(pi * x)) dx
sum rule: find integral of x ^ 2 dx
Computed: (1 / (2 + 1)) * (x ^ (2 + 1))
sum rule: find integral of sin(pi * x) dx
linear substitution: find integral of sin(x) dx
Computed: -(cos(x))
Computed: (-(cos(pi * x))) / (pi * 1)
Computed: ((1 / (2 + 1)) * (x ^ (2 + 1))) + ((-(cos(pi * x))) / (pi * 1))
debugPrint
使用することは、統合ルールがどのように相互作用して組み合わせて統合を見つけるかを学ぶ良い方法であり、カスタム統合ルールを開発するときに非常に役立ちます。
この実装で使用される統合アルゴリズムは、深度最初の検索メモ化パターンマッチングに基づいています。各パターンは、積分を直接計算するか、積分を積分しやすい式に書き換えたり、それの積分を計算したりしようとする関数として指定されています。インテグレーターのコアはルール不可知論です。デフォルトでは、 integral.rules
に保存されている一連の標準統合ルールを使用しますが、カスタムルールを使用することはサポートされています(カスタムルールセクションを参照)。
Integrandsのメモ化は、サブ発現の一般的な積分のスピードアップだけでなく、2つのルールが互いに取り消された場合に無限のループを防ぎます(1つが指数を増やし、もう1つがこれらの一般的な要因を組み合わせた場合など)。ただし、このアルゴリズムは、新しいユニークなインテグランドのすべてのアプリケーションを生成して、無限の数を適用できるルール(またはいくつかの相互作用するルール)の影響を受けやすいです。このようなルールにより、インテグレーターは無期限に再発します(または、すべてのスタックスペースまたはメモリが消費されるまで)。
このアプローチの単純さ(およびこのパッケージの開発の相対的な初期段階)により、この現在の実装には多くの制限があります。不完全なリストを提供するには、現在、以下をサポートするルールはありません。
2 * x * cos(x^2)
3 * x^2 * e^(x^3)
x * ln(x)
x^3 * e^x
cos(x) * tan(x)
のような式に必要な三角測定の単純化e ^ -(x^2)
erf
を統合しますこれらのケースのいずれかを処理するルールを実装する場合(またはその他の厄介なサポートされていないケース)、プルリクエストを送信してください!
Copyright(c)2018 Joel Hoover([email protected])
Apacheライセンス、バージョン2.0(「ライセンス」)に基づいてライセンスされています。ライセンスに準拠している場合を除き、このファイルを使用することはできません。ライセンスのコピーを取得できます
http://www.apache.org/licenses/license-2.0
適用法で要求されていないか、書面で合意されていない限り、ライセンスに基づいて配布されたソフトウェアは、明示または黙示のいずれかの保証または条件なしに、「現状のまま」に基づいて配布されます。ライセンスに基づく権限と制限を管理する特定の言語のライセンスを参照してください。