Cách đây không lâu, tôi đã thực hiện một số nghiên cứu về lý thuyết số giải tích. Đó chỉ là vì lợi ích của riêng tôi ở nhà vào buổi tối. Đó chỉ là một dự án sở thích để thỏa mãn trí tò mò của tôi
Vấn đề
Tại một thời điểm nào đó, tôi gặp phải một tích phân kép khó chịu và tôi muốn kiểm tra xem những gì tôi tìm được có thực sự đúng hay không. Để thêm một số ngữ cảnh cho người đọc quan tâm, tôi đã cố gắng tìm một công thức cho số lượng các số nguyên tố sinh đôi bên dưới một số đã cho bằng cách sử dụng hàm đếm số nguyên tố và một số kỹ thuật từ giải tích phức… Phew. , bây giờ thì đã hết cách, hãy tiếp tục với câu chuyện
Vì vậy, người ta sẽ làm gì khi đối mặt với một vấn đề như vậy liên quan đến một chức năng không liên tục cao? . Trong trường hợp của tôi, ngôn ngữ lập trình của tôi là Python, vì vậy tôi đã tạo một tệp python trống với hy vọng quá trình này chỉ mất từ 10 đến 15 phút
tôi đã sai. Nguyên nhân? . Vấn đề là khi tôi muốn tích hợp chúng
“Thông thường, các thư viện liên quan đến khoa học hoặc dữ liệu của Python sẽ tiết kiệm thời gian, nhưng lần này nó đã làm tôi thất bại. ”
Bây giờ, SciPy có một gói [tất nhiên] cho loại thứ này được gọi là quad. Và đó là lý do tại sao ban đầu tôi nghĩ rằng nó sẽ dễ dàng. Thông thường, các thư viện liên quan đến khoa học hoặc dữ liệu của Python tiết kiệm thời gian và thường rất dễ sử dụng, nhưng lần này tôi đã thất bại. Vấn đề là tích phân của tôi [tích phân kép của tôi] có một cực trong khoảng tích phân
Một sự tương tự đơn giản
Giả sử bạn muốn tính tích phân sau
Tôi thực sự đã thử ví dụ này và nó không hoạt động. Hàm này hoàn toàn hữu hạn trong một lân cận xung quanh 0 nhưng khi tôi thử tính toán nó, tôi liên tục nhận được giá trị nan. Tôi ngay lập tức hiểu chuyện gì đang xảy ra
SciPy đang sử dụng thứ gì đó như tổng Riemann hoặc quy tắc Hình thang để tính tích phân và yêu cầu thuật toán chia khoảng tích phân thành nhiều khoảng nhỏ. Việc tính diện tích của các hình chữ nhật nhỏ tương ứng đòi hỏi nó phải tính giá trị hàm của tất cả các điểm cuối khoảng này — một trong số chúng là [rất gần] bằng không
Và tất nhiên, cố gắng chia cho 0 trong Python sẽ ném ZeroDivisonError. Hóa ra, ít nhất theo tài liệu của SciPy, nên có một số cách xung quanh nó. Ví dụ, người ta có thể chỉ định các cực đã biết [tất nhiên điều này đòi hỏi chúng ta phải biết các cực của hàm không phải lúc nào cũng đúng], nhưng một lần nữa, điều đó không hoạt động với tích phân kép của tôi [mặc dù nó thực sự hoạt động đối với tích phân kép].
Kế hoạch
Điểm của tất cả các giới thiệu này là như sau
- Một công cụ tích hợp số chỉ nên quan tâm đến sự hội tụ — chứ không phải các cực
- Bạn không cần phải tự tìm các cực hoặc thậm chí nghĩ về chúng
- Bạn muốn thứ gì đó có thể hack được mà bạn có thể sửa đổi để phù hợp với nhu cầu của mình. g. sửa đổi lỗi so với tham số thời gian chạy [chúng ta sẽ tìm hiểu vấn đề này một chút]
- Các lỗi phải có ý nghĩa và dễ hiểu
Tại thời điểm này, tôi đã rất thất vọng, vì vậy tôi quyết định tự xây dựng một công cụ
Sau khi nhận ra rằng tôi phải làm điều này, tôi cần phải đi lấy thêm một ít cà phê và suy nghĩ về một thiết kế cho công cụ này. Tất nhiên bạn có thể làm điều này theo nhiều cách khác nhau. Tôi đã sử dụng phương pháp nhẹ nhất vì tôi tin rằng một công cụ như vậy cần phải điều chỉnh liên tục để phù hợp với nhu cầu của người dùng
Hãy xây dựng nó
Tôi quyết định thiết kế hướng đối tượng, chọn xây dựng một lớp xung quanh chức năng được tích hợp. Tôi đã làm điều này để người dùng có thể dễ dàng thêm nhiều tính năng hơn vào nó trong tương lai và để lưu thông tin meta về phép tính, chẳng hạn như khoảng thời gian lỗi, v.v.
Mật mã
Hãy bắt đầu với những điều cơ bản. Trước hết, chương trình này chỉ thực sự phụ thuộc vào Numpy. Tuy nhiên, để thuận tiện, chúng tôi sẽ nhập quad
Nếu bạn chưa cài đặt các gói này, bạn có thể cài đặt chúng bằng
pip install numpy quad
hoặc pip3 tùy thuộc vào hệ điều hành của bạn
Để mã trong bài viết này hoạt động, bạn cần chạy mã đó bằng Python 3
Hãy tạo lớp Tích hợp
Một vài nhận xét theo thứ tự ở đây. Đầu tiên, tôi ghi lại lỗi và bạn sẽ thấy tại sao trong giây lát. Thứ hai, chúng tôi có một thuộc tính dấu hiệu được xác định. Điều này là do khi các giới hạn của phép hoán đổi tích phân, thì dấu của giá trị cũng vậy và chúng ta cần có khả năng tính tích phân khi giới hạn dưới lớn hơn giới hạn trên. Điều này tất nhiên chỉ để cho bạn thấy làm thế nào bạn có thể làm điều này
Và bây giờ là phương pháp tích hợp chính [đơn]
Tôi đã sử dụng quy tắc hình thang ở đây [nếu bạn không nhớ, về cơ bản đây là trung bình cộng của tổng Riemann trái và phải], nhưng điều đó không có gì ngạc nhiên. Bạn có thể thắc mắc tại sao tôi có một mệnh đề try/ngoại trừ lớn xung quanh. Đó thực sự là một trong những điểm chính. Những gì nó làm là nếu có một phép chia cho 0 ẩn trong đó, thì nó sẽ bị bỏ qua một cách duyên dáng mà không cần đầu vào từ người dùng
Chúng tôi cũng thấy rằng chúng tôi đã lưu trữ lỗi nếu một người muốn tính toán theo số học khoảng hoặc chỉ kiểm tra xem kết quả chính xác như thế nào
Điều đó tốt thôi, nhưng chúng ta sử dụng công cụ của mình như thế nào?
Điều này trở nên dễ dàng ngay bây giờ, bất chấp biểu thức “0/0” khi x = 0
và bây giờ chúng tôi nhận được câu trả lời khoảng 1. 892166. Khá tốt
Nhưng chúng ta chưa xong đâu, nhớ không?
Vì vậy, chúng ta cần tổng quát hóa mã này để tính tích phân kép, nhưng trước tiên, hãy đảm bảo rằng chúng ta hiểu các lỗi có thể mắc phải. Để làm được điều đó, chúng ta cần xây dựng một lớp lỗi tùy chỉnh trong Python. Điều này thật dễ dàng, chúng tôi chỉ kế thừa từ Ngoại lệ
Ngoài ra, vì các khoảng thời gian đầu vào bây giờ phải là một tham số của loại danh sách danh sách [hoặc một cái gì đó tương tự], nên một giải pháp khả thi là như sau
Ghi chú. Đây hoàn toàn không phải là mã hiệu suất và nếu muốn, chúng tôi có thể tối ưu hóa mã này bằng e. g. vector hóa trong Numpy
Điều đó đang được nói, bạn có thể điều chỉnh tham số độ chính xác để phù hợp với nhu cầu của mình. Giá trị càng cao, tích phân sẽ càng chính xác, nhưng sẽ mất nhiều thời gian hơn để tính toán. Đó là nơi thuộc tính lỗi xuất hiện. Bạn có thể thử làm bài tập để tối ưu hóa mã này
Nếu muốn, tất nhiên chúng ta có thể tổng quát hóa điều này thành tích phân ba, v.v. nhưng đối với phạm vi của bài viết này, hãy tập trung vào những cái đơn và đôi
Hãy sử dụng công cụ hoàn toàn mới của chúng tôi
Vì vậy, hãy để tôi chỉ cho bạn cách nó hoạt động
Giả sử bạn đang làm việc trên một dự án bằng Python và đột nhiên, bạn gặp phải vấn đề tính gần đúng tích phân sau
Chà, bây giờ bạn đã có công cụ cho công việc. Ở đầu tệp của bạn, hãy nhập công cụ tích hợp mới của bạn
Xa hơn nữa trong dự án, bây giờ bạn có thể giải quyết nó
Điều này mang lại một đầu ra của
The result is 3.1415926535897944The accuracy of this result is -1.7319479184152442e-14
Điều này là khá d… gần. Để so sánh với thỏa thuận thực sự, sự khởi đầu thực sự của số pi là 3. 141592653589793238… và phạm vi lỗi của chúng tôi tất nhiên đã cho chúng tôi biết chính xác điều đó— cụ thể là, chúng tôi đã tính đúng 14 chữ số đầu tiên [Ít nhất là trong giới hạn tích hợp của chúng tôi - chúng tôi cần cẩn thận một chút trong ví dụ của mình vì về mặt kỹ thuật, chúng tôi đang thiếu “các đuôi . Tất nhiên, việc tăng tham số độ chính xác hoặc giới hạn của tích phân cho vấn đề đó sẽ cho chúng ta nhiều chữ số hơn đúng không
Nhưng đây là điểm quan trọng
Mặc dù tích phân kép ở trên phải được tính trên toàn bộ mặt phẳng thực, nhưng chúng ta có thể đảm bảo rằng trong khoảng của mình, chúng ta có thể tiến gần đến giá trị thực một cách tùy ý — và chúng ta có thể kiểm tra điều đó nhờ thuộc tính sai số của mình. Vì vậy, đó là vấn đề trao đổi độ chính xác cho thời gian chạy
Bây giờ tôi có thể quay lại công việc của mình và hy vọng rằng nếu bạn gặp phải một số vấn đề theo hướng này hoặc nếu bạn chỉ muốn tìm hiểu thêm về Python, vui lòng sử dụng hoặc mở rộng mã này
Bạn có thể sao chép toàn bộ kho lưu trữ tại đây
Sau 7 cốc cà phê, giờ tôi có thể yên tâm đi ngủ. Tôi chỉ hy vọng rằng tôi sẽ không bị Riemann điên truy đuổi trong những giấc mơ của tôi