Perpustakaan ini adalah ekstensi untuk Perpustakaan Math.js yang populer. Ini menambahkan fungsi integral
yang mampu menemukan integral dari fungsi matematika sederhana. Ini juga fleksibel dalam aturan integrasi yang digunakan, memungkinkan aturan khusus untuk digunakan alih -alih atau sebagai tambahan untuk aturan standar.
Perhatikan bahwa perangkat lunak ini masih dianggap beta, jadi jika Anda menemukan bug atau tepi kasar, silakan kirimkan masalah!
Untuk menginstal paket, gunakan yang berikut:
npm install mathjs-simple-integral
Untuk mendaftarkan ekstensi dengan Math.js, gunakan yang berikut:
math . import ( require ( 'mathjs-simple-integral' ) ) ;
Ini akan menambah fungsi math.integral
ke Math.js.
Penggunaan dasar ekstensi ini sangat mudah: cukup berikan integrand (baik sebagai Node
atau string) dan variabel integrasi (baik sebagai SymbolNode
atau string):
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'
Jika integral
tidak dapat menemukan integral dari ekspresi yang diberikan, itu akan melempar kesalahan:
math . integral ( 'e^(x^2)' ) ; // Error: Unable to find integral of "e ^ (x ^ 2)" with respect to "x"
Secara default, integral
menjalankan math.simplify
pada output, karena proses integrasi dapat menghasilkan beberapa ekspresi yang sulit. Namun, dimungkinkan untuk mendapatkan output mentah dan tidak tersederhanakan dari integral
dengan meneruskan objek options
dengan simplify
diatur ke false
ke parameter ketiga opsional:
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))'
Dalam implementasi ini, aturan integrasi didefinisikan sebagai fungsi yang mengambil sebagai parameter (1) expr
, ekspresi yang akan diintegrasikan; (2) context
, konteks integrasi; dan (3) subIntegral
, suatu fungsi yang mencoba mengintegrasikan subekspresi atau bentuk integral yang ditulis ulang. Aturan integrasi kemudian mengembalikan integral yang dihitung, atau null
jika tidak dapat menemukannya. Selain banyak integrasi standar yang sudah diimplementasikan (terletak di math.integral.rules
), seperangkat aturan integrasi khusus dapat ditentukan.
Misalnya, misalkan kami menambahkan fungsi kustom myUpperGamma
yang mewakili fungsi gamma yang tidak lengkap, dan kami sekarang ingin menambahkan dukungan untuk mengintegrasikannya, terutama kami ingin mengimplementasikan aturan ini: integral("myUpperGamma(s,x)", "x") = x*myUpperGamma(s,x) - myUpperGamma(s+1, x)
(verifikasi di sini). Pertama, mari kita tulis aturan ini sebagai suatu fungsi:
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
}
Sekarang kami memiliki aturan integrasi khusus kami, kami dapat menambahkannya ke daftar aturan standar dan menggunakan daftar gabungan ini untuk menemukan integral yang melibatkan 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)'
Sekarang anggaplah selain myUpperGamma
kita memiliki fungsi kustom lain mySum
: seperti add
, itu akan menerima sejumlah argumen variabel dan menambahkan argumen bersama-sama, tetapi juga melakukan beberapa fungsi non-matematika lainnya (seperti mencatat setiap argumen sebelum evaluasi, atau memeriksa untuk memastikan bahwa tidak ada argumennya yang NaN
). Sekarang, kita dapat menambahkan aturan ke integrator yang mewakili linearitas integral di atas 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
}
Perhatikan bagaimana kami menggunakan panggilan balik subIntegral
untuk menemukan integral dari semua istilah dalam jumlah, dan kemudian mengembalikan integral untuk seluruh ekspresi mySum
hanya jika semua istilah individu dapat diintegrasikan. Sekarang, jika kami menggunakan kedua aturan khusus kami, kami dapat mengintegrasikan ekspresi dengan mySum
dan 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))'
Objek Opsi dapat memiliki debugPrint
properti yang, jika diatur ke true
, akan menginstruksikan integrator untuk "menunjukkan pekerjaannya": yaitu, itu akan mencetak ke konsol semua langkah yang diambil dan semua aturan yang diterapkan dalam integrasi tertentu. Misalnya, integral("x^2 + sin(pi*x)", "x", {debugPrint: true})
menghasilkan output berikut pada konsol:
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))
Menggunakan debugPrint
adalah cara yang baik untuk mempelajari bagaimana aturan integrasi berinteraksi dan menggabungkan untuk menemukan integral, dan sangat membantu ketika mengembangkan aturan integrasi khusus.
Algoritma integrasi yang digunakan oleh implementasi ini didasarkan pada pencocokan pola memoisasi pencarian pertama. Setiap pola ditentukan sebagai fungsi yang berupaya menghitung integral secara langsung, atau untuk menulis ulang atau membagi integrand menjadi ekspresi yang lebih mudah diintegrasikan, dan menghitung integral dari itu. Inti dari integrator adalah aturan agnostik: secara default menggunakan serangkaian aturan integrasi standar yang disimpan di integral.rules
, meskipun menggunakan aturan khusus didukung (lihat bagian Aturan Kustom).
Memoisasi integrand tidak hanya menawarkan percepatan untuk integral umum sub-ekspresi, tetapi juga mencegah loop tak terbatas jika dua aturan saling membatalkan (seperti jika satu melipatgandakan eksponen, dan yang lain menggabungkan faktor-faktor umum ini). Namun, algoritma ini masih rentan terhadap aturan (atau beberapa aturan yang berinteraksi) yang dapat menerapkan jumlah tak terbatas yang menghasilkan integrand baru yang unik setiap aplikasi; Aturan seperti itu akan menyebabkan integrator mengulangi tanpa batas waktu (atau, sampai semua ruang tumpukan atau memori dikonsumsi).
Karena kesederhanaan pendekatan ini (dan tahap awal pengembangan paket ini), ada banyak keterbatasan dalam implementasi saat ini. Untuk memberikan daftar yang tidak lengkap, saat ini tidak ada aturan untuk mendukung yang berikut:
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)
dan sejenisnya menggunakan erf
Jika menerapkan aturan untuk menangani salah satu kasus ini (atau kasus lain yang tidak didukung secara keriting), silakan kirimkan permintaan tarik!
Hak Cipta (C) 2018 Joel Hoover ([email protected])
Berlisensi di bawah lisensi Apache, versi 2.0 ("lisensi"); Anda tidak boleh menggunakan file ini kecuali sesuai dengan lisensi. Anda dapat memperoleh salinan lisensi di
http://www.apache.org/licenses/license-2.0
Kecuali diharuskan oleh hukum yang berlaku atau disepakati secara tertulis, perangkat lunak yang didistribusikan di bawah lisensi didistribusikan berdasarkan "sebagaimana adanya", tanpa jaminan atau ketentuan dalam bentuk apa pun, baik tersurat maupun tersirat. Lihat lisensi untuk bahasa spesifik yang mengatur izin dan batasan di bawah lisensi.