सी + लाइब्रेरी संख्यात्मक इंटरग्रेशन के लिए (चतुर्थांश)


10

न्यूमेरिकल इंटीग्रेशन (क्वाडरेचर) के लिए मेरे पास अपना छोटा सबरूटीन है, जो कि 1967 में बुलिरस्च एंड स्टोअर द्वारा प्रकाशित ALGOL प्रोग्राम का C ++ रूपांतरण है (न्यूमेरिस मैथिक, 9, 27-2-278)।

मैं एक अधिक आधुनिक (अनुकूली) एल्गोरिथ्म में अपग्रेड करना चाहूंगा और आश्चर्यचकित करूंगा कि क्या कोई (फ्री) सी ++ लाइब्रेरी हैं जो इस तरह की सुविधा प्रदान करती हैं। मुझे जीएसएल (जो कि सी) के रूप में देखा गया था, लेकिन यह एक भयानक एपीआई के साथ आता है (हालांकि अंक अच्छा हो सकता है)। क्या कुछ और है?

एक उपयोगी एपीआई इस तरह दिखेगा:

double quadrature(double lower_integration_limit,
                  double upper_integration_limit,
                  std::function<double(double)> const&func,
                  double desired_error_bound_relative=1.e-12,
                  double desired_error_bound_absolute=0,
                  double*error_estimate=nullptr);

7
एक तरफ के रूप में, आप पाएंगे कि कम्प्यूटेशनल विज्ञान में कई सर्वोत्तम कार्यान्वयनों में "खराब" एपीआई का बस है, क्योंकि वे महीनों या वर्षों के बजाय अन्य सॉफ्टवेयरों से विकसित हुए हैं। मुझे लगता है कि यह स्वीकार्य होगा, और संभावना है कि आपके लिए एक रैपर एपीआई लिखना, और आंतरिक रूप से कम साफ एपीआई को कॉल करना। यह आपको अपने प्राथमिक कोड में एक अच्छा एपीआई का लाभ देता है, और आपको केवल एक फ़ंक्शन को फिर से लिखने के साथ अलग-अलग क्वाड्रेट लाइब्रेरी के बीच आसानी से स्विच करने की अनुमति देता है।
गॉड्रिक सीयर

1
@GodricSeer अगर यह इतना आसान था, तो मैं यह करूँगा। हालाँकि, यह नहीं है। जीएसएल एपीआई को एक पूर्व-आवंटित बफर की आवश्यकता होती है, जिनमें से संभवतः कुछ भी उपयोग नहीं किया जाता है, लेकिन जो संभवतः बहुत छोटा हो सकता है (अधिक मेमोरी के साथ किसी अन्य कॉल की आवश्यकता होती है)। एक उचित कार्यान्वयन पुनरावर्ती होगा, कोई आवंटन की आवश्यकता नहीं है, स्टैक पर सभी डेटा रखें, और एक स्वच्छ एपीआई प्रदान करें।
वाल्टर

1
@GodricSeer जीएसएल एपीआई के साथ एक और गंभीर समस्या यह है कि यह केवल राज्य के बिना कार्यों को स्वीकार करता है (क्योंकि यह एक साधारण फ़ंक्शन पॉइंटर का उपयोग करता है)। इसके साथ राज्य के कार्यों के लिए थ्रेडसेफ़ एपीआई बनाना आवश्यक रूप से अक्षम है।
वाल्टर

2
मैं Godric Seer से सहमत हूं, रैपर लिखना सबसे अच्छा विकल्प है। मुझे नहीं लगता कि यह सही है कि "जीएसएल केवल राज्य के बिना कार्यों को स्वीकार करता है": यहां डॉक्स में कहा गया gsl_functionहै कि यह एक फ़ंक्शन सूचक है जिसमें कुछ अपारदर्शी डेटा सूचक होते हैं, जिसमें आपका राज्य हो सकता है। दूसरा, मनमाने ढंग से बड़े काम करने वाले बफ़र्स को आवंटित करने के बारे में (री-) कुछ दक्षता चिंताएं हैं, इसलिए उस हिस्से में कम से कम कुछ वैध औचित्य है।
किरिल

1
जीएसएल के पूर्व-आवंटित बफर के बारे में एक और टिप्पणी। कार्यक्षेत्र का आकार अधिकतम अंतरालों के संदर्भ में परिभाषित किया गया है - चूंकि आप चाहते हैं कि चतुर्थांश की दिनचर्या वैसे भी विफल हो जाए अगर इसमें बहुत अधिक अनुकूली द्वि घातुमान लिया जाए, तो बस कार्यक्षेत्र के आकार को कुछ ऊपरी सीमाओं पर सेट करें। जब आप "उचित" कार्यान्वयन के बारे में बात करते हैं, तो जीएसएल यहां "सही" बात करता है, यह वर्तमान में सबसे बड़ी त्रुटि के साथ अंतराल को द्विभाजित करता है, जिसका अर्थ है कि इसे अब तक के सभी अंतरालों का ट्रैक रखना है। यदि आप स्टैक पर सभी डेटा रखते हैं, तो आप स्टैक मेमोरी को चला सकते हैं, यह वास्तव में बेहतर नहीं है।
किरिल

जवाबों:


3

Odeint पर एक नज़र डालें । यह अब बूस्ट का हिस्सा है और इसमें दूसरों के बीच बुलरिस्क-स्टोअर एल्गोरिदम शामिल है। शुरू करने के लिए आप यहां एक बहुत ही सरल उदाहरण देख सकते हैं ।


3
Odeint के लिए अवलोकन का पहला वाक्य है: "odeint साधारण अंतर समीकरणों के प्रारंभिक मूल्य की समस्याओं (IVP) को हल करने के लिए एक पुस्तकालय है।" जहाँ तक मुझे जानकारी है, इस पुस्तकालय का उपयोग किसी ज्ञात कार्य के चतुर्थांश के लिए नहीं किया जा सकता है। क्या आपके पास एक उदाहरण है जहां इसका उपयोग द्विघात के लिए किया गया है?
बिल ग्रीन

1
मुझे लगता है कि (मैं स्वयं पुस्तकालय का उपयोग नहीं करता हूं) कि इसमें न्यूट्रॉन-कोट्स, रोमबर्ग या गॉसियन क्वाडरेचर जैसे क्वॉड्रिज़ के लिए एल्गोरिदम शामिल नहीं हैं, लेकिन यह देखते हुए कि प्रश्न में ग्रैग-बुलरिस्च-स्टीयर विधि का उल्लेख है, मुझे लगा कि समस्या हाथ में है एक ODE एकीकरण था।
Zythos

2

एमएफईएम [1] में आसानी से उपयोग किए जाने वाले द्विघात कार्य हैं (दोनों सर्फेस और वॉल्यूमेट्रिक तत्वों के लिए)। हम उन्हें विभिन्न कार्यों के लिए उपयोग करने में सक्षम थे।

[१] http://mfem.org/


2

आप जीएसएल क्वाडचर फ़ंक्शन के आसपास आसानी से एक पतली सी ++ रैपर लिख सकते हैं। निम्नलिखित को C ++ 11 की आवश्यकता है।

#include <iostream>
#include <cmath>

#include <functional>
#include <memory>
#include <utility>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_integration.h>

template < typename F >
class gsl_quad
{
  F f;
  int limit;
  std::unique_ptr < gsl_integration_workspace,
                    std::function < void(gsl_integration_workspace*) >
                    > workspace;

  static double gsl_wrapper(double x, void * p)
  {
    gsl_quad * t = reinterpret_cast<gsl_quad*>(p);
    return t->f(x);
  }

public:
  gsl_quad(F f, int limit)
    : f(f)
    , limit(limit)
    , workspace(gsl_integration_workspace_alloc(limit), gsl_integration_workspace_free)
  {}

  double integrate(double min, double max, double epsabs, double epsrel)
  {
    gsl_function gsl_f;
    gsl_f.function = &gsl_wrapper;
    gsl_f.params = this;

    double result, error;
    if ( !std::isinf(min) && !std::isinf(max) )
    {
      gsl_integration_qags ( &gsl_f, min, max,
                             epsabs, epsrel, limit,
                             workspace.get(), &result, &error );
    }
    else if ( std::isinf(min) && !std::isinf(max) )
    {
      gsl_integration_qagil( &gsl_f, max,
                             epsabs, epsrel, limit,
                             workspace.get(), &result, &error );
    }
    else if ( !std::isinf(min) && std::isinf(max) )
    {
      gsl_integration_qagiu( &gsl_f, min,
                             epsabs, epsrel, limit,
                             workspace.get(), &result, &error );
    }
    else
    {
      gsl_integration_qagi ( &gsl_f,
                             epsabs, epsrel, limit,
                             workspace.get(), &result, &error );
    }

    return result;
  }
};

template < typename F >
double quad(F func,
            std::pair<double,double> const& range,
            double epsabs = 1.49e-8, double epsrel = 1.49e-8,
            int limit = 50)
{
  return gsl_quad<F>(func, limit).integrate(range.first, range.second, epsabs, epsrel);
}

int main()
{
  std::cout << "\\int_0^1 x^2 dx = "
            << quad([](double x) { return x*x; }, {0,1}) << '\n'
            << "\\int_1^\\infty x^{-2} dx = "
            << quad([](double x) { return 1/(x*x); }, {1,INFINITY}) << '\n'
            << "\\int_{-\\infty}^\\infty \\exp(-x^2) dx = "
            << quad([](double x) { return std::exp(-x*x); }, {-INFINITY,INFINITY}) << '\n';
}

उत्पादन

\int_0^1 x^2 dx = 0.333333
\int_1^\infty x^{-2} dx = 1
\int_{-\infty}^\infty \exp(-x^2) dx = 1.77245

1

मुझे Cubature पुस्तकालय के साथ सफलता मिली है (यह C में लिखा है, हालांकि)। यह अपेक्षाकृत कम संख्या के आयामों के साथ बहुआयामी एकीकरण के उद्देश्य से है।

HIntLib पुस्तकालय सी में लिखा है ++ और यह अनुकूली क्षेत्रकलन (cubature) के लिए दिनचर्या है।


1

की जाँच करें https://github.com/tbs1980/NumericalIntegration । यह क्वाडपैक (जो जीएसएल भी आधारित है) पर आधारित है, और इसमें कुछ साफ-सुथरी आधुनिक विशेषताएं हैं, जैसे कि ईजेन, मल्टीपर्स सपोर्ट।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.