gpt4 book ai didi

用于具有导数的 GSL 根查找算法的 C++ 包装器

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:17:26 27 4
gpt4 key购买 nike

因此,虽然我很高兴在 Stack Overflow 上找到了很多答案,但我决定是时候自己问一个问题了。
我正在尝试使用 a root finding algorithm with derivatives .根据 GSL,我必须提前定义函数及其导数。但我想知道是否可以使用包装器更优雅地完成此操作。

前段时间我发现了一个非常方便的 template (GSL C++ wrapper)这适用于一个功能,例如集成并且我大量使用它。

现在我想知道是否可以扩展这种方法为 GSL 提供两个函数,即函数本身及其派生函数。

编辑:解决方案

template <typename F, typename G>
class gsl_root_deriv : public gsl_function_fdf
{
private:
const F& _f;
const G& _df;

static double invoke_f(double x, void* params){
return static_cast<gsl_root_deriv*>(params) -> _f(x);
}

static double invoke_df(double x, void* params){
return static_cast<gsl_root_deriv*>(params) -> _df(x);
}

static void invoke_fdf(double x, void* params, double* f, double* df){
(*f) = static_cast<gsl_root_deriv*>(params) -> _f(x);
(*df) = static_cast<gsl_root_deriv*>(params) -> _df(x);
}

public:
gsl_root_deriv(const F& f_init, const G& df_init)
: _f(f_init), _df(df_init)
{
f = &gsl_root_deriv::invoke_f;
df = &gsl_root_deriv::invoke_df;
fdf = &gsl_root_deriv::invoke_fdf;
params = this;
}
};

还有一个类似于 the example from the GSL 的最小示例:

#include <iostream>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_roots.h>
#include <memory>

#include "gsl_root_deriv.h"

int main()
{
auto f = [](double x) -> double { return 0.25 * x*x - 1.0; };
auto df = [](double x) -> double { return 0.5 * x; };

gsl_root_deriv<decltype(f),decltype(df)> Fp(f,df);

int status(0), iter(0), max_iter(100);

const gsl_root_fdfsolver_type* T( gsl_root_fdfsolver_newton);

std::unique_ptr<gsl_root_fdfsolver,void(*)(gsl_root_fdfsolver*)>
s(gsl_root_fdfsolver_alloc(T),gsl_root_fdfsolver_free);

double x_0(0.0), x(5.0);

gsl_root_fdfsolver_set( s.get(), &Fp, x );

do
{
iter++;
std::cout << "Iteration " << iter << std::endl;
status = gsl_root_fdfsolver_iterate( s.get() );
x_0 = x;
x = gsl_root_fdfsolver_root( s.get() );
status = gsl_root_test_delta( x, x_0, 0.0, 1.0e-3 );
} while( status == GSL_CONTINUE && iter < max_iter );

std::cout << "Converged to root " << x << std::endl;

return 0;
}

亲切的问候,
——克劳斯

最佳答案

你需要做一些修改

Gsl fdf结构如下

struct gsl_function_fdf_struct 
{
double (* f) (double x, void * params);
double (* df) (double x, void * params);
void (* fdf) (double x, void * params, double * f, double * df);
void * params;
};

typedef struct gsl_function_fdf_struct gsl_function_fdf ;

如果您了解包装器的实际作用,那么您会发现泛化非常简单

class gsl_function_fdf_pp : public gsl_function_fdf
{
public:
gsl_function_fdf_pp
(
std::function<double(double)> const& kf,
std::function<double(double)> const& kdf
) : _f(kf), _df(kdf)
{
f = &gsl_function_fdf_pp::invoke;
df = &gsl_function_fdf_pp::invoke2;
fdf = &gsl_function_fdf_pp::invoke3;
params=this;
}
private:
std::function<double(double)> _f;
std::function<double(double)> _df;

static double invoke(double x, void *params)
{
return static_cast<gsl_function_fdf_pp*>(params)->_f(x);
}

static double invoke2(double x, void *params)
{
return static_cast<gsl_function_fdf_pp*>(params)->_df(x);
}

static void invoke3(double x, void * params, double* f, double* df)
{
(*f) = static_cast<gsl_function_fdf_pp*>(params)->_f(x);
(*df) = static_cast<gsl_function_fdf_pp*>(params)->_df(x);
}
};

模板版本。

template< typename F, typename U >  class gsl_function_fdf_pp : public gsl_function_fdf 
{
public:
gsl_function_fdf_pp(const F& kf, const U& kdf) : _f(kf), _df(kdf)
{
f = &gsl_function_fdf_pp::invoke;
df = &gsl_function_fdf_pp::invoke2;
fdf = &gsl_function_fdf_pp::invoke3;
params=this;
}
private:
const F& _f;
const U& _df;

static double invoke(double x, void *params)
{
return static_cast<gsl_function_fdf_pp*>(params)->_f(x);
}

static double invoke2(double x, void *params)
{
return static_cast<gsl_function_fdf_pp*>(params)->_df(x);
}

static void invoke3(double x, void * params, double* f, double* df)
{
(*f) = static_cast<gsl_function_fdf_pp*>(params)->_f(x);
(*df) = static_cast<gsl_function_fdf_pp*>(params)->_df(x);
}
};

EDIT2:修复了 2 个小问题后,这个例子就可以运行了

int main()
{
auto f = [](double x)->double{ return x*x; };
auto df = [](double x)->double{ return 2.0 * x; };

gsl_function_fdf_pp<decltype(f),decltype(df)> Fp(f,df);

return 0;
}

关于用于具有导数的 GSL 根查找算法的 C++ 包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24594152/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com