OpenNL 是一个用于求解大型稀疏线性系统的C开发库。 它包括一个易于使用的用于组装矩阵的 API,以及用于对称和非对称系统的各种迭代求解器。 OpenNL API 在?geogram/NL/nl.h?中声明。
NSDT工具推荐:?Three.js AI纹理开发包?-?YOLO合成数据生成器?-?GLTF/GLB在线编辑?-?3D模型格式在线转换?-?可编程3D场景编辑器?-?REVIT导出3D模型插件?-?3D模型语义搜索引擎?
让我们从一个简单的例子开始。 假设你要求解以下线性系统:
[ 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());
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());
如前面的示例所示,我们假设有一个文件,其中每条线上都包含 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());