Đánh giá số tích phân dao động cao


11

Trong khóa học nâng cao này về các ứng dụng của lý thuyết hàm phức tạp tại một điểm trong bài tập tích phân có tính dao động cao

I(λ)=cos(λcosx)sinxxdx

phải được tính gần đúng cho các giá trị lớn của bằng phương pháp điểm yên trong mặt phẳng phức.λ

Do tính chất dao động cao của nó, tích phân này rất khó đánh giá bằng hầu hết các phương pháp khác. Đây là hai mảnh của đồ thị của integrand cho ở các tỷ lệ khác nhau:λ=10

cos (10 cos (x)) tội lỗi (x) / x

Một xấp xỉ thứ tự tiệm cận gần đúng là

I1(λ)=cos(λ14π)2πλ

và một sàng lọc (nhỏ hơn nhiều) thêm thuật ngữ

I2(λ)=18sin(λ14π)2πλ3

Biểu đồ các giá trị gần đúng dưới dạng hàm của trông như sau:λ

Tôi (lambda) khoảng

Bây giờ đến câu hỏi của tôi: để xem trực quan mức độ gần đúng tốt như thế nào, tôi muốn so sánh nó với "giá trị thực" của tích phân, hay chính xác hơn là xấp xỉ tốt với cùng một tích phân bằng thuật toán độc lập. Do sự nhỏ bé của hiệu chỉnh dưới nền, tôi sẽ mong đợi điều này thực sự gần gũi.

Tôi đã cố gắng đánh giá tích phân cho một số bằng các thuật toán khác, nhưng rất ít thành công: Mathicala và Matlab sử dụng bộ tích phân số mặc định không quản lý để tạo ra một giá trị có ý nghĩa (và báo cáo rõ ràng điều này), mpmath sử dụng cả hai hàm mũ Thay thế và phương pháp Gauss-Legendre tạo ra kết quả rất ồn, mặc dù nó có xu hướng dao động nhẹ xung quanh các giá trị mà phương pháp điểm yên ngựa đưa ra, vì biểu đồ này có thể hiển thị:λtanh(sinh)

mpmath khoảng

Cuối cùng tôi đã thử vận ​​may với một nhà tích hợp Monte-Carlo sử dụng mẫu quan trọng mà tôi đã triển khai, nhưng tôi cũng không quản lý để có được bất kỳ kết quả ổn định nào.

Có ai có ý tưởng về cách tích phân này có thể được đánh giá độc lập cho bất kỳ giá trị cố định nào của hay không?λ>1


Là chức năng thậm chí?
nicoguaro

Vâng, nó là chẵn
doetoe

Bạn đã thử biến tích phân của mình thành ODE chưa?
nicoguaro

1
Không, phân biệt wrt và sau đó giải phương trình vi phân bằng số. x
nicoguaro

1
Âm mưu đầu tiên của bạn dường như hiển thị một chức năng khác với tích phân của bạn. Cụ thể, dường như có thay thế bằng . Tức là cốt truyện có chức năngλλxx(cos(λxcosx)sincx)
Ruslan

Câu trả lời:


12

Sử dụng định lý Plancherel để đánh giá tích phân này.

Ý tưởng cơ bản là cho hai hàm ,f,g

I=f(x)g(x)dx=F(k)G(k)dk

Trong đó là các biến đổi Fourier của . Cả hai chức năng của bạn đều có sự hỗ trợ tương đối nhỏ trong miền phổ. Ở đây, và nên có một biến đổi Fourier phân tích (hoặc sê-ri ), như mở rộng Jacobi-Anger . Bạn có thể cắt bớt chuỗi vô hạn ở khoảng do sự phân rã theo cấp số nhân của hàm Besselcho. Hi vọng điêu nay co ich.F,Gf,gsinx/xrect(k)cos(λcosx)λ|Jn(x)|n>|x|

Chỉnh sửa : Trên thực tế, bạn nên sử dụng các biểu diễn chuỗi Fourier ở đây thay vì các biến đổi. Đường dẫn biến đổi dẫn đến việc tạo ra biểu diễn tiệm cận mà bạn đã có (hóa ra đây chỉ là ). Định lý Plancherel ở trên cũng hoạt động cho chuỗi Fourier với miền tích hợp trên tích phân cuối cùng.πJ0(λ)[0,2π]


Cảm ơn, đây là một ý tưởng rất tốt!
doetoe

7

Chìa khóa để đánh giá các tích phân dao động là cắt ngắn tích phân ở đúng điểm. Trong ví dụ này, bạn cần chọn giới hạn trên của biểu mẫu Trước khi giải thích lý do tại sao nó nên hoạt động, trước tiên hãy cho tôi thấy rằng nó thực sự mang lại kết quả tốt.

πN+π2

Tiệm cận

Rất dễ đoán rằng chuỗi tiệm cận có dạng Để kiểm tra số lượng điều đó là đủ để biểu thị sự khác biệt giữa một biểu thức tiệm cận và tích phân hàng đầu.

I(λ)2πλ[cos(λπ4)+c1sin(λπ4)λ+c2cos(λπ4)λ2+c3sin(λπ4)λ3+]
c1=18

int := NIntegrate[Cos[l*Cos[x]]*Sinc[x], {x, 0, 20.5*Pi}]; 
Plot[{l*(Sqrt[2*l/Pi]*int - Cos[l-Pi/4]), Sin[l-Pi/4]/8}, {l, Pi/4, 20}]

Là một đầu ra, bạn nhận được một sin khá trùng khớp với cái bạn đã dẫn ở trên.

18

Nếu bạn muốn tìm các hệ số sau, một đoạn mã phức tạp hơn một chút nếu cần. Ý tưởng của mã dưới đây là lấy một số giá trị giới hạn trên cao và "trung bình" kết quả của chúng.

J[l_?NumericQ] := Block[{n=500},
  f[k_] := NIntegrate[Cos[l*Cos[x]]*Sinc[x], {x,0,(n+k)*Pi+Pi/2},
  Method->{"DoubleExponential"}, AccuracyGoal->14, MaxRecursion->100];
  1/2*((f[0]+f[1])/2+(f[1]+f[2])/2)
]
t = Table[{l, l^2*(Sqrt[2*l/Pi]*J[l] - Cos[l-Pi/4] - 1/8*Sin[l-Pi/4]/l)}, 
    {l, 4*Pi+Pi/4, 12*Pi+Pi/4, Pi/36}];
Fit[t, Table[Cos[l-Pi/4+Pi/2*n]/l^n, {n, 0, 10}], l]

Điều đó tạo ra câu trả lời sau đây.

c2=9128,c3=751024,c4=367532768,

Giải trình

Ví dụ đơn giản

Để minh họa, tôi sẽ sử dụng ví dụ đơn giản hơn về sin - tích phân Hãy để tôi tưởng tượng rằng tôi quan tâm đến giá trị , nhưng tôi không biết điều đó.

S(x)=0xsin(y)ydy.
S()=π2

sin

Bạn thấy rằng dao động xung quanh giá trị giới hạn của nó tương tự như cách các tổng của một phần xen kẽ trong chuỗi ký hiệu dao động với mức cắt trên. Khi bạn muốn ước tính tổng đó, theo phương pháp tăng tốc chuỗi Euler, bạn nên lấy Hoặc về mặt hàm sin - tích phân, bạn nên tích hợp nó đến điểm giữa cực đại và cực tiểu của dao động. Vì nó được nhìn thấy rõ ràng từ cốt truyện, điểm này được ước tính bởi cho các giá trị lớn của đối số. Tổng quát hơn, điểm như vậy là điểm trong đóxảy raS(x)

SN=n=1N(1)nn.
SSN+12(1)N+1N+1.
S(x)0πN+π2sinxxdx
max|S(x)|

Vấn đề của bạn

Quay trở lại tích phân từ khóa học của Konstantin và Yar Tư, bạn có thể thấy rằng nó hoạt động chính xác giống như sin - không thể tách rời như một hàm của giới hạn trên. Điều đó có nghĩa là bạn chỉ cần tính các giá trị với . Dưới đây là biểu đồ của một số giá trị như vậy với .

Ix0(λ)=20x0cos(λcos(x))sinc(x)dx
x0=πN+π2λ=12π

tab = Table[{x0, 2*NIntegrate[Cos[12*Pi*Cos[x]]*Sinc[x], {x, 0, x0}, 
     Method->{"DoubleExponential"}, AccuracyGoal->12, MaxRecursion->100]},
    {x0, 10*Pi+Pi/2, 30*Pi+Pi/2, Pi}];
tab1 = Table[(tab[[i]] + tab[[i+1]])/2, {i,1,Length[tab]-1}];
ListPlot[{tab, tab1}]

acc

Ở đây bạn có thể thấy kết quả của một phương pháp tăng tốc khác. Tôi sắp xếp lại một phần tổng theo cách sau và thu được chuỗi mới hội tụ nhanh hơn nhiều. Thủ thuật đó cũng có ích nếu bạn muốn đánh giá tích phân với độ chính xác cao.

SN=12(SN+SN+1)
SN


Đẹp! Là những người hướng dẫn của khóa học giáo sư thực tế của bạn? Khóa học của họ thật tuyệt vời, mặc dù rất khó khăn và có nhịp độ nhanh
doetoe

@doetoe vâng, tôi là học sinh của Konstantin. Anh ấy chia sẻ với tôi một liên kết đến câu hỏi của bạn.
David Saykin

6

Phương pháp của Ooura cho tích phân sin Fourier hoạt động ở đây, xem:

Ooura, Takuya và Masatake Mori, một công thức hàm mũ đôi mạnh mẽ cho các tích phân loại Fourier. Tạp chí toán học tính toán và ứng dụng 112.1-2 (1999): 229-241.

Tôi đã viết một triển khai của thuật toán này nhưng không bao giờ thực hiện để có được nó nhanh chóng (bằng cách nói các nút / trọng lượng bộ đệm), nhưng dù sao, tôi đang nhận được kết quả nhất quán ở mọi thứ ngoài độ chính xác nổi:

float     = 0.0154244
double    = 0.943661538060268
long dbl  = 0.943661538066058702
quad      = 0.943661538066060288748574485677942
oct       = 0.943661538066060288748574485680878906503533004997613278231689169604876
asymptotic= 0.944029734

Đây là mã:

#include <iostream>
#include <boost/math/quadrature/ooura_fourier_integrals.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/multiprecision/float128.hpp>
#include <boost/multiprecision/cpp_bin_float.hpp>

template<class Real>
Real asymptotic(Real lambda) {
    using std::sin;
    using std::cos;
    using boost::math::constants::pi;
    Real I1 = cos(lambda - pi<Real>()/4)*sqrt(2*pi<Real>()/lambda);
    Real I2 = sin(lambda - pi<Real>()/4)*sqrt(2*pi<Real>()/(lambda*lambda*lambda))/8;
    return I1 + I2;
}

template<class Real>
Real osc(Real lambda) {
    using std::cos;
    using boost::math::quadrature::ooura_fourier_sin;
    auto f = [&lambda](Real x)->Real { return cos(lambda*cos(x))/x; };
    Real omega = 1;
    Real Is = ooura_fourier_sin<decltype(f), Real>(f, omega);
    return 2*Is;
}

template<class Real>
void print(Real val) {
   std::cout << std::defaultfloat;
   std::cout << std::setprecision(std::numeric_limits<Real>::digits10);
   std::cout <<  val <<  " = " << std::hexfloat << val;
}

int main() {
    using boost::multiprecision::float128;
    float128  s = 7;
    std::cout << "Asymptotic = " << std::setprecision(std::numeric_limits<float128>::digits10) << asymptotic(s) << "\n";
    std::cout << "float precision = ";
    print(osc(7.0f));
    std::cout << "\n";
    std::cout << "double precision= ";
    print(osc(7.0));
    std::cout << "\n";
    std::cout << "long double     = ";
    print(osc(7.0L));
    std::cout << "\n";
    print(osc(s));

    print(osc(boost::multiprecision::cpp_bin_float_oct(7)));
    std::cout << "\n";
}

Bạn thực sự không thể thấy sự khác biệt giữa cầu phương và tiệm cận vì chúng nằm ngay trên nhau trừ khi : λ0nhập mô tả hình ảnh ở đây


Cảm ơn, điều này thực sự tốt đẹp! Tôi chưa làm cho nó hoạt động được, cài đặt tăng cường của tôi không tương thích, nhưng tôi đang tải xuống phiên bản mới nhất ngay bây giờ.
doetoe

Chỉ cần chắc chắn: trong 23 bạn có cos (lambda * cos (x)) / x, không có yếu tố sin (x) từ integrand. Có phải ooura_fourier_sin giả định yếu tố này sin (x) để nhân số nguyên được truyền cho nó?
doetoe

Tôi đã làm cho nó hoạt động. Nó và các phần phụ thuộc của nó dường như chỉ là tiêu đề, vì vậy tôi thậm chí không phải cài đặt hoặc biên dịch (ngoại trừ phần thực thi). Tôi hy vọng nó sẽ được bao gồm trong boost!
doetoe

@doetoe: Có, yếu tố được ẩn và được tích hợp vào các trọng số cầu phương. Tôi đang xem xét để tăng tốc nó bằng cách cấu trúc lại nó để lưu các nút và trọng lượng; chúng ta sẽ thấy! sin(x)
dùng14717

@doetoe: Nó được hợp nhất vào Boost 1.71. API khác một chút so với câu trả lời này.
user14717
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.