OpenNL is a C development library for solving large sparse linear systems. It includes an easy-to-use API for assembling matrices, and a variety of iterative solvers for symmetric and asymmetric systems. The OpenNL API is declared in geogram/NL/nl.h .
Recommended NSDT tools : Three.js AI texture development kit - YOLO synthetic data generator - GLTF/GLB online editing - 3D model format online conversion - programmable 3D scene editor - REVIT export 3D model plug-in - 3D model semantic search engine
1. Solve linear systems
Let's start with a simple example. Suppose you want to solve the following linear system:
[ 1 2 ] [x] [5]
[ 3 4 ] [y] = [6]
First, you need to declare the variable that will store the solution of the system. Then, we create an OpenNL context and declare the number of variables:
double x,y;
nlNewContext();
nlSolverParameteri(NL_NB_VARIABLES, 2);
Now we can build the linear system. Linear systems are built line by line. OpenNL has a state machine controlled by nlBegin()
, nlEnd()
calls. Looks similar to OpenGL 2.x, but OpenNL builds sparse matrices instead of graphics primitives:
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);
Next we solve the system:
nlSolve();
x = nlGetVariable(0);
y = nlGetVariable(1);
Finally, we remove the OpenNL context:
nlDeleteContext(nlGetCurrent());
2. Least squares regression
OpenNL has a special least squares mode that assembles normal equations (least squares). Suppose you have a file where each line contains X,Y point coordinates, and you want to find the equation of the line that best fits the data points y=ax+b
. As before, we create an OpenNL context and declare the number of variables. Additionally, we activate least squares mode:
nlNewContext();
nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE);
nlSolverParameteri(NL_NB_VARIABLES, 2);
We then read the file and assemble the matrix based on the file data:
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);
Just like the previous example, we can now solve the system:
nlSolve();
a = nlGetVariable(0);
b = nlGetVariable(1);
And don't forget to close the input file and delete the OpenNL context:
fclose(input);
nlDeleteContext(nlGetCurrent());
3. Least squares regression with locked variables
As shown in the previous example, we assume that we have a file in which each line contains the X,Y point coordinates, and we still want to find the equation of the line that best fits the data points y=ax+b
, but this time we have an additional constraint: the slope of the line a should equal 1. The OpenNL context is initialized as before:
FILE* input = fopen("datapoints.dat", "r");
double X,Y;
nlNewContext();
nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE);
nlSolverParameteri(NL_NB_VARIABLES, 2);
When we build the system, we lock variable 0 (corresponding to a) and set its value (1.0) like this:
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);
Then the rest is the same as before:
nlSolve();
a = nlGetVariable(0);
b = nlGetVariable(1);
fclose(input);
nlDeleteContext(nlGetCurrent());
Original link: Solving linear systems with OpenNL - BimAnt