OpenNL linear system solving library

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 toolsThree.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

おすすめ

転載: blog.csdn.net/shebao3333/article/details/135448851