我想使用两个boost库来执行任务,我不确定如何继续。
我有一行函数代码,给出了N,x和B值的答案:
double ans = cdf(boost::math::binomial mybinom(N, x), B);
让我们将其表示为ans = f(B,N,x)。
我想找到它的根,即x的值,在该值处,函数例如是y = f(x),导致y = 0.
我的代码,形式为y = f(B,N,x)涉及一个小的重新排列以否定ans:
double myfun = function(B, N, x, ans){
double output = (cdf(boost::math::binomial mybinom(N, x), B) - ans);
return output;
}
到目前为止一切顺利。现在我知道在Boost中,根头中的算法将帮助我们找到根,所以在阅读时我看到TOMS算法748将接受因为它的主要参数'f'是一元函子。一个例子如下:
#include <iostream>
#include <sstream>
#include <string>
#include <boost/math/tools/roots.hpp>
class Test {
public:
double operator()(const double x) {
return x * cos(x);
}
};
// see:
// http://www.boost.org/doc/libs/1_47_0/libs/math/doc/sf_and_dist/html/math_toolkit/toolkit/internals1/roots2.html
int main(int argc, char** argv) {
Test t;
typedef std::pair<double, double> Result;
boost::uintmax_t max_iter=500;
boost::math::tools::eps_tolerance<double> tol(30);
Result r1 = boost::math::tools::toms748_solve(t, 1.0, 2.0, tol, max_iter);
std::cout << "root bracketed: [ " << r1.first << " , " << r1.second << " ]" << std::endl;
std::cout << "f("<< r1.first << ")=" << t(r1.first) << std::endl;
std::cout << "f("<< r1.second << ")=" << t(r1.second) << std::endl;
std::cout << "max_iter=" << max_iter << std::endl;
return 0;
}
好的,现在我遇到了问题。我看到的每个例子(对于这个和类似的算法)都需要一个一元仿函数。并显示一个只有x作为参数的函数,例如x * cos(x)
。但是你看到我的函数有参数B,N,x和ans。那么如何从f(B,N,x,ans)得到一元函子,即f(x),使得boost算法可以接受它作为输入来找到根?
我想到的一件事可能是(我在这里不知道因为我从未听说过一个一元仿函数),从我收集到的,一元函子是类,类可以有函数和变量,那么可以设计一元仿函数类,所以在创建时,你提供B和N以及ans,其值是成员变量,然后一元仿函数的double operator()(const double x){}
内的函数可以使用B和N和ans因为它们是成员变量而不需要在运算符中提供,因此是一元的。因此,就我而言,我在创建对象时指定B和N变量,但就boost算法和一元运算符而言,它们是成员变量,并且只是函数体内已有的值?
我想象的是:
class Test {
public:
double operator()(const double x) {
return (cdf(boost::math::binomial mybinom(N, x), B) - ans);
}
private:
int B;
int N;
double ans;
};
我在这里是正确的路线还是我在错误的树上咆哮?
- 编辑 -
以下是我目前为解决此问题而制作的代码:
#include <iostream>
#include <boost/math/distributions/binomial.hpp>
#include <boost/math/tools/roots.hpp>
class MyBinom
{
public:
MyBinom(int n, int b, double p);
double operator()(const double x);
private:
int N;
int B;
double P;
};
MyBinom::MyBinom(int n, int b, double p)
: N(n), B(b), P(p)
{/* Body intentionally empty */}
double MyBinom::operator()(const double x)
{
boost::math::binomial myBinomial(N, x);
return (cdf(myBinomial, B) - P);
}
int main()
{
MyBinom myBinom95(4715, 75, 0.95); // Create the Class with the unary operator.
boost::uintmax_t max_iter=500; // Set max iterations.
boost::math::tools::eps_tolerance<double> tol(30); //Set the eps tolerance.
std::pair<double, double> r1 = boost::math::tools::toms748_solve(myBinom95, 0, 1, tol, max_iter); // use the toms solve algorithm.
std::cout << "Let's take a look at the root" << std::endl;
std::cout << "root bracketed: [ " << r1.first << " , " << r1.second << " ]" << std::endl;
std::cout << "f("<< r1.first << ")=" << myBinom95(r1.first) << std::endl;
std::cout << "f("<< r1.second << ")=" << myBinom95(r1.second) << std::endl;
std::cout << "max_iter=" << max_iter << std::endl;
return 0;
}
然而它无法编译 - 与增强标题有关:
$ g++ main.cpp -o test
In file included from /usr/include/boost/math/tools/roots.hpp:32:0,
from /usr/include/boost/math/special_functions/detail/igamma_inverse.hpp:16,
from /usr/include/boost/math/special_functions/gamma.hpp:1528,
from /usr/include/boost/math/special_functions/beta.hpp:15,
from /usr/include/boost/math/distributions/binomial.hpp:83,
from main.cpp:2:
/usr/include/boost/math/tools/toms748_solve.hpp: In function 'std::pair<T, T> boost::math::tools::toms748_solve(F, const T&, const T&, Tol, uintmax_t&, const Policy&) [with F = MyBinom, T = int, Tol = boost::math::tools::eps_tolerance<double>, Policy = boost::math::policies::policy<boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy>, uintmax_t = long unsigned int]':
/usr/include/boost/math/tools/toms748_solve.hpp:475:71: instantiated from 'std::pair<T, T> boost::math::tools::toms748_solve(F, const T&, const T&, Tol, uintmax_t&) [with F = MyBinom, T = int, Tol = boost::math::tools::eps_tolerance<double>, uintmax_t = long unsigned int]'
main.cpp:41:100: instantiated from here
/usr/include/boost/math/tools/toms748_solve.hpp:467:81: error: no matching function for call to 'toms748_solve(MyBinom&, const int&, const int&, double, double, boost::math::tools::eps_tolerance<double>&, uintmax_t&, const boost::math::policies::policy<boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy>&)'
/usr/include/boost/math/tools/toms748_solve.hpp:467:81: note: candidates are:
/usr/include/boost/math/tools/toms748_solve.hpp:283:17: note: template<class F, class T, class Tol, class Policy> std::pair<T, T> boost::math::tools::toms748_solve(F, const T&, const T&, const T&, const T&, Tol, uintmax_t&, const Policy&)
/usr/include/boost/math/tools/toms748_solve.hpp:458:24: note: template<class F, class T, class Tol> std::pair<T, T> boost::math::tools::toms748_solve(F, const T&, const T&, const T&, const T&, Tol, uintmax_t&)
/usr/include/boost/math/tools/toms748_solve.hpp:464:24: note: template<class F, class T, class Tol, class Policy> std::pair<T, T> boost::math::tools::toms748_solve(F, const T&, const T&, Tol, uintmax_t&, const Policy&)
/usr/include/boost/math/tools/toms748_solve.hpp:473:24: note: template<class F, class T, class Tol> std::pair<T, T> boost::math::tools::toms748_solve(F, const T&, const T&, Tol, uintmax_t&)
谢谢, 本。
答案 0 :(得分:2)
以下是正确的:
class Test {
public:
Test(int B, int N, int ans) : B(B), N(N), ans(ans) {}
double operator()(const double x) const {
return (cdf(boost::math::binomial mybinom(N, x), B) - ans);
}
private:
int B;
int N;
double ans;
};
请注意,大多数情况下,Functor都会被复制,所以如果你想要检索一些'可变'信息(就像调用你的仿函数多少次),你必须传递一个额外的指针(一个更简单的计数器是不够的)