C++ Ceres Solver C++;:分段错误:11

C++ Ceres Solver C++;:分段错误:11,c++,optimization,google-analytics,mathematical-optimization,ceres-solver,C++,Optimization,Google Analytics,Mathematical Optimization,Ceres Solver,我试图用谷歌的Ceres解算器来解一个非线性系统。以下示例来自本页: 我首先创建一个名为MatlabExample的类,在这里我计算残差和雅可比数: class MatlabExample : public SizedCostFunction<2,2> { public: virtual ~MatlabExample() {} virtual bool Evaluate(double const* const* parameters, doub

我试图用谷歌的Ceres解算器来解一个非线性系统。以下示例来自本页:

我首先创建一个名为
MatlabExample
的类,在这里我计算
残差
雅可比数

class MatlabExample
: public SizedCostFunction<2,2> {
public:
virtual ~MatlabExample() {}
virtual bool Evaluate(double const* const* parameters,
                    double* residuals,
                    double** jacobians) const {

double x1 = parameters[0][0];
double x2 = parameters[0][1];

residuals[0] = 2*x1+x1*x2-2;
residuals[1] = 2*x2-x1*pow(x2,2)-2 ;

if (jacobians != NULL && jacobians[0] != NULL) {
  jacobians[0][0] = 2+x2;
  jacobians[0][1] = x1;
  jacobians[1][0] = -pow(x2,2);
  jacobians[1][1] = 2-2*x1*x2;
}

return true;
}
};
类MatlabExample
:公共大小的成本函数{
公众:
虚拟~MatlabExample(){}
虚拟布尔求值(双常数*常数*参数,
双*残差,
双**雅可比数)常数{
双x1=参数[0][0];
双x2=参数[0][1];
残差[0]=2*x1+x1*x2-2;
残差[1]=2*x2-x1*pow(x2,2)-2;
if(雅可比数!=NULL&&jacobians[0]!=NULL){
雅可比[0][0]=2+x2;
雅可比[0][1]=x1;
雅可比[1][0]=-pow(x2,2);
雅可比[1][1]=2-2*x1*x2;
}
返回true;
}
};
主要文件如下:

int main(int argc, char** argv) {
  google::InitGoogleLogging(argv[0]);

  double x[] = { 0.0,0.0 };

  Problem problem;
  CostFunction* cost_function = new MatlabExample;
  problem.AddResidualBlock(cost_function, NULL, &x);
  Solver::Options options;
  options.minimizer_progress_to_stdout = true;
  Solver::Summary summary;
  Solve(options, &problem, &summary);

  std::cout << summary.BriefReport() << "\n";

  return 0;
}
int main(int argc,char**argv){
google::InitGoogleLogging(argv[0]);
双x[]={0.0,0.0};
问题;
成本函数*成本函数=新MatlabExample;
问题.AddResidualBlock(cost_函数,NULL,&x);
解算器::选项;
options.minimizer\u progress\u to\u stdout=true;
解算器:总结;
解决(选项、问题和总结);

std::cout您访问雅可比数组时出错。原因如下

当您添加残差块时,您告诉Ceres,成本函数仅取决于一个大小为2的参数块,并生成大小为2的残差

jacobians数组是一个行主jacobians数组。每个参数块一个。因此,在本例中,它的大小为1,并包含一个指向大小为4的数组的指针,该数组应包含行主jacobians

您的雅可比填充代码应该改为

if (jacobians != NULL && jacobians[0] != NULL) {
  jacobians[0][0] = 2+x2;
  jacobians[0][1] = x1;
  jacobians[0][2] = -pow(x2,2);
  jacobians[0][3] = 2-2*x1*x2;
}

double const*const*parameters
-哇。你为什么要这样做?为什么不直接传递一个
std::array
std::vector
(可能通过const引用)?吹毛求疵:宁愿
nullptr
而不是
NULL
。我们不再生活在C++98中。因为抽象类“SizedCostFunction”以这种方式定义了虚拟函数“Evaluate”。我没有办法改变这一点,因为它来自CERESolver。我扩展了这个文件:对
雅可比人
的空检查是可行的毫无价值。这并不能充分确定
jacobians
是否适用于您如何使用它。谢谢。因此,这样做意味着
jacobians[0][0]=df1/x1
jacobians[0][1]=df1/x2
jacobians[0][2]=df2/x1
,以及
jacobians[0][3]=d f2/x2
。我们确定这个顺序吗?是的,Ceres中的雅可比矩阵是行主矩阵。很遗憾,Ceres包装器的作者没有将
double**
包装在一个类中,因此至少可以使用
size()
或类似的函数来验证维度大小。