NSDT工具推荐Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - AI模型在线查看 - Three.js虚拟轴心开发包 - 3D模型在线减面 - STL模型在线切割 - 3D道路快速建模

OpenNL 是一个用于求解大型稀疏线性系统的C开发库。 它包括一个易于使用的用于组装矩阵的 API,以及用于对称和非对称系统的各种迭代求解器。 OpenNL API 在 geogram/NL/nl.h 中声明。

1、求解线性系统

让我们从一个简单的例子开始。 假设你要求解以下线性系统:

   [ 1 2 ] [x]   [5]
   [ 3 4 ] [y] = [6]

首先,你需要声明将存储系统解的变量。 然后,我们创建一个 OpenNL 上下文,并声明变量的数量:

  double x,y;
  nlNewContext();
  nlSolverParameteri(NL_NB_VARIABLES, 2);

现在我们可以构建线性系统了。 线性系统是逐行构建的。 OpenNL 有一个状态机,由 nlBegin()nlEnd() 调用控制。看起来与 OpenGL 2.x 类似,但OpenNL构建稀疏矩阵而不是图形基元:

  nlBegin(NL_SYSTEM);
  nlBegin(NL_MATRIX);
  nlBegin(NL_ROW);
  nlCoefficient(0, 1.0);
  nlCoefficient(1, 2.0);
  nlRightHandSide(5.0);
  nlEnd(NL_ROW);
  nlBegin(NL_ROW);
  nlCoefficient(0, 3.0);
  nlCoefficient(1, 4.0);
  nlRightHandSide(6.0);
  nlEnd(NL_ROW);
  nlEnd(NL_MATRIX);
  nlEnd(NL_SYSTEM);

接下来我们对系统进行求解:

  nlSolve();
  x = nlGetVariable(0);
  y = nlGetVariable(1);

最后,我们删除 OpenNL 上下文:

  nlDeleteContext(nlGetCurrent());

2、最小二乘回归

OpenNL 有一个特殊的最小二乘模式,可以组装正规方程(最小二乘)。 假设你有一个文件,其中每条线上都包含 X,Y 点坐标,并且想要找到最适合数据点的线方程 y=ax+b。 和之前一样,我们创建一个 OpenNL 上下文并声明变量的数量。 此外,我们激活最小二乘模式:

   nlNewContext();
   nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE);
   nlSolverParameteri(NL_NB_VARIABLES, 2);

然后,我们读取文件并根据文件数据组装矩阵:

  FILE* input = fopen("datapoints.dat", "r");
  double X,Y; // current datapoint
  nlBegin(NL_SYSTEM);
  nlBegin(NL_MATRIX);
  while(!feof(input)) {
     fread(input, "%f %f", &X, &Y);
     nlBegin(NL_ROW);
     nlCoefficient(0, X);
     nlCoefficient(1, 1.0);
     nlRightHandSide(Y);
     nlEnd(NL_ROW);
  }
  nlEnd(NL_MATRIX);
  nlEnd(NL_SYSTEM);

就像前面的例子一样,我们现在可以求解系统:

  nlSolve();
  a = nlGetVariable(0);
  b = nlGetVariable(1);

并且不要忘记关闭输入文件并删除 OpenNL 上下文:

  fclose(input);
  nlDeleteContext(nlGetCurrent());

3、具有锁定变量的最小二乘回归

如前面的示例所示,我们假设有一个文件,其中每条线上都包含 X,Y 点坐标,并且我们仍然希望找到最适合数据点的线方程 y=ax+b,但这一次我们有附加约束:直线的斜率 a 应等于 1。OpenNL 上下文的初始化与之前一样:

  FILE* input = fopen("datapoints.dat", "r");
  double X,Y; 
  nlNewContext();
  nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE);
  nlSolverParameteri(NL_NB_VARIABLES, 2);

当我们构建系统时,我们锁定变量 0(对应于 a)并设置其值(1.0),如下所示:

  nlBegin(NL_SYSTEM);
  nlLockVariable(0);
  nlSetVariable(0, 1.0);
  nlBegin(NL_MATRIX);
  while(!feof(input)) {
     fread(input, "%f %f", &X, &Y);
     nlBegin(NL_ROW);
     nlCoefficient(0, X);
     nlCoefficient(1, 1.0);
     nlRightHandSide(Y);
     nlEnd(NL_ROW);
  }
  nlEnd(NL_MATRIX);
  nlEnd(NL_SYSTEM);

然后剩下的就和以前一样了:

  nlSolve();
  a = nlGetVariable(0);
  b = nlGetVariable(1);
  fclose(input);
  nlDeleteContext(nlGetCurrent());

原文链接:Solving Linear Systems with OpenNL

BimAnt翻译整理,转载请标明出处