4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

初 LAPACK!で DGELS (QR 分解もしくは LQ 分解)による最小二乗法を実装してみた

Posted at

LAPACK インストール

HomeBrew (macOS)

$ brew install lapack

そのあと,次の環境変数にそれぞれ追加します。

CFLAGS = $CFLAGS -I/usr/local/opt/lapack/include
CPPFLAGS = $CPPFLAGS -I/usr/local/opt/lapack/include
LDFLAGS = $LDFLAGS -L/usr/local/opt/lapack/lib

apt (Ubuntu)

$ apt install liblapack-dev

環境変数はメモし忘れました。

最小二乗法プログラム

lsm.c
# include <stdlib.h>
# include <stdio.h>
# ifdef __linux__
  #include <lapacke.h>
# else
  #include <lapack.h>
# endif

void dgels(char *trans, 
  lapack_int *m, lapack_int *n, lapack_int *nrhs,
  double *a, lapack_int *lda,
  double *b, lapack_int *ldb,
  double *work, lapack_int *lwork,
  lapack_int *info )
{
  LAPACK_dgels(trans, m, n, nrhs, a, lda, b, ldb, work, lwork, info);
}

extern void print_matrix(char *description, int m, int n, double *a, int lda);

int max(const int m, const int n)
{
  if (m > n) {
    return m;
  } else {
    return n;
  }
}

int min(const int m, const int n)
{
  if (m < n) {
    return m;
  } else {
    return n;
  }
}

int main() {
  char *trans = "No transpose";
  int m = 5;
  int n = 2;
  int nrhs = 1;

  int lda = max(1, m);
  int ldb = max(max(1, m), n);
  int lwork = max(1, min(m, n) + max(min(m, n), nrhs));
  int info;

  // double work[max(1, lwork)];
  double *work;
  work = (double *)malloc(sizeof(double) * max(1, lwork));

  // double a[m * n];
  double *a;
  a = (double *)malloc(sizeof(double) * m * n);

  // double b[m];
  double *b;
  b = (double *)malloc(sizeof(double) * m);

  a[0] = 1;
  a[1] = 1;
  a[2] = 1;
  a[3] = 1;
  a[4] = 1;

  a[5] = 50.0;
  a[6] = 60.0;
  a[7] = 70.0;
  a[8] = 80.0;
  a[9] = 90.0;

  b[0] = 40.0;
  b[1] = 70.0;
  b[2] = 90.0;
  b[3] = 60.0;
  b[4] = 100.0;

  print_matrix("a" , m, n, a, lda);
  print_matrix("b" , m, 1, b, ldb);

  dgels( "No transpose", &m, &n, &nrhs, 
    a, &lda, b, &ldb, work, &lwork,
    &info );

  if(info > 0) {
    /*
     * a の三角因子の info で示される対角要素が 0 であるため,
     * a は最大階数を持たない。
     * すなわち最小二乗法は計算できない。
     */
    exit(1);
  }

  // print_matrix("a" , m, n, a, lda);
  print_matrix("the least squares", n, nrhs, b, ldb);

  return 0;
}

void print_matrix(char* description, int m, int n, double* a, int lda)
{
  int i, j;
  printf("\n %s\n", description);
  for(i = 0; i < m; i++) {
    for(j = 0; j < n; j++) {
      printf(" %6.2f", a[i + j * lda]);
    }
    printf("\n");
  }
}

コンパイル方法

$ cc $CFLAGS lsm.c -o lsm $LDFLAGS -llapack

実行方法

$ ./lsm

実行結果


 a
   1.00  50.00
   1.00  60.00
   1.00  70.00
   1.00  80.00
   1.00  90.00

 b
  40.00
  70.00
  90.00
  60.00
 100.00

 the least squares
  -5.00
   1.10

y = ax + b に対して,a = 1.10, b = -5.00 ということです。

計算速度とかは求めていません。

参考文献

最初に見つけた DGELS のプログラム例です。

最初に見つけた DGELS で最小二乗法をしているプログラム例です。ただし三次元でした。

最終的なデータはここから取りました。

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?