在C

时间:2016-03-07 00:18:50

标签: c debugging qr-decomposition

问题已解决

似乎我意外地写了j,它应该在0行

matrix_column_subtract(Q,i,matrix_column_multiply(T,0,r),j);

哪个应该是

matrix_column_subtract(Q,i,matrix_column_multiply(T,0,r),0);

我正在使用我的矩阵实现和各种辅助函数在C中实现QR分解。我编写了主要功能,通过使用Gram-Schmidt过程将矩阵A分解为两个矩阵Q和R:

qr

matrix.c

#define TYPE double
#define FLAG "%7.3f"

typedef struct {
  TYPE **array;    /* Pointer to an array of type TYPE */
  int rows;       /* Number of rows */
  int cols;       /* Number of columns */
} matrix;

/* Decomposes the matrix A into QR */
void QRdecompose(matrix *A, matrix *Q, matrix *R) {

  /* Using the Gram-Schmidt process */

  /* Temporary vector T and S used in calculations */
  matrix *T = create_matrix(A->rows, 1);
  matrix *S = create_matrix(A->rows, 1);

  for (int i = 0; i < A->cols; i++) {

    //Qi = Ui
    matrix_copy_column(A,i,Q,i);

    for (int j = 0; j < i; j++) {

      //r[j,i] = Qj^T * Ui
      matrix_copy_column(Q,j,T,0);
      matrix_copy_column(A,i,S,0);
      TYPE r = 0;
      for (int k=0; k<A->rows; k++) {
        r += T->array[k][0] * S->array[k][0];
      }

      R->array[j][i] = r;
      matrix_column_subtract(Q,i,matrix_column_multiply(T,0,r),j);

    }

    //r[i,i] = ||Qi||
    R->array[i][i] = vector_length(Q,i);
    //Qi = Qi/r[i,i]
    matrix_column_divide(Q,i,R->array[i][i]);

  }

  //free_matrix(T);
  //free_matrix(S);

}

我创建和使用的函数是

/* Creates a matrix and returns a pointer to the struct */
matrix* create_matrix(int rows, int cols) {

  /* Allocate memory for the matrix struct */
  matrix *array = malloc(sizeof(matrix));

  array->rows = rows;
  array->cols = cols;

  /* Allocate enough memory for all the rows in the first matrix */
  array->array = calloc(rows, sizeof(TYPE*));

  /* Enough memory for all the columns */
  for (int i=0; i<rows; i++) {
    array->array[i] = calloc(cols,sizeof(TYPE));
  }

  return array;
}

/* Creates a matrix from a stack based array and returns a pointer to the struct */
matrix* create_matrix_from_array(int rows, int cols, TYPE m[][cols]) {

  /* Allocate memory for the matrix struct */
  matrix *array = malloc(sizeof(matrix));
  array->rows = rows;
  array->cols = cols;

  /* Allocate memory for the matrix */
  array->array = malloc(sizeof(TYPE*) * rows);

  /* Allocate memory for each array inside the matrix */
  for (int i=0; i<rows; i++) {
    array->array[i] = malloc(sizeof(TYPE) * cols);
  }

  /* Populate the matrix with m's values */
  for (int row = 0; row < rows; row++) {
    for (int col = 0; col < cols; col++) {
      array->array[row][col] = m[row][col];
    }
  }

  return array;
}
/* Copies a matrix column from msrc at column col1 to mdst at column col2 */
void matrix_copy_column(matrix *msrc, int col1, matrix *mdst,int col2) {
  for (int i=0; i<msrc->rows; i++) {
    mdst->array[i][col2] = msrc->array[i][col1];
  }
}

/* Subtracts m2's column c2 from m1's column c1 */
matrix* matrix_column_subtract(matrix *m1, int c1, matrix *m2, int c2) {
  for (int i=0; i<m1->rows; i++) {
      m1->array[i][c1] -= m2->array[i][c2];
  }
  return m1;
}

/* Returns the length of the vector column in m */
double vector_length(matrix *m,int column) {
  double length = 0;
  for (int row=0; row<m->rows; row++) {
    length += m->array[row][column] * m->array[row][column];
  }
  return sqrt(length);
}

/* Divides the matrix column c in m by k */
matrix* matrix_column_divide(matrix *m, int c, TYPE k) {
  for (int i=0; i<m->rows; i++) {
    m->array[i][c] /= k;
  }
  return m;
}

/* Multiplies the matrix column c in m by k */
matrix* matrix_column_multiply(matrix *m, int c, TYPE k) {
  for (int i=0; i<m->rows; i++) {
    m->array[i][c] *= k;
  }
  return m;
}

/* Debugging purposes only */
void print_matrix(matrix *m) {
  for (int row = 0; row < m->rows; row++) {
    printf("[");
    for (int col = 0; col < m->cols - 1; col++) {
      printf(FLAG", ", m->array[row][col]);
    }
    printf(FLAG, m->array[row][m->cols-1]);
    printf("]\n");
  }
  printf("\n");
}

然而,我的QRdecompose()函数中存在一个错误,其中Q矩阵的最后一列是不正确的,即值不同。我在Eclipse中使用GDB进行了4个小时的调试,但是我真的被卡住了,所以我想我会转向SE寻求帮助。

的main.c

int main(int argc, const char **argv) {

  TYPE a[3][3] = { { 12, -51, 4 }, { 6, 167, -68 }, { -4, 24, -41 } };

  matrix *A = create_matrix_from_array(3,3,a);
  matrix *Q = create_matrix(3,3);
  matrix *R = create_matrix(3,3);
  QRdecompose(A,Q,R);

  print_matrix(A);
  print_matrix(Q);
  print_matrix(R);
  return 0;

}

我使用矩阵测试了我的代码:

matrix

我的程序输出产生

Q
[  0.857,  -0.394,   0.204]
[  0.429,   0.903,  -0.792]
[ -0.286,   0.171,  -0.575]

R
[ 14.000,  21.000, -14.000]
[  0.000, 175.000, -70.000]
[  0.000,   0.000,  78.262]

实际答案应该是

 Q

 0.857 -0.394 -0.331
 0.429  0.903  0.034
-0.286  0.171 -0.943

 R

 14.000  21.000 -14.000
  0.000 175.000 -70.000
  0.000   0.000  35.000

Q的行/列在模型答案中可能有所不同,但我的输出的实际行/列仍然正确,除了最后一列。

问题似乎发生在第一个循环的最后一次迭代中;我在里面打印了矩阵R:

[ 14.000,   0.000,   0.000]
[  0.000,   0.000,   0.000]
[  0.000,   0.000,   0.000]

[ 14.000,  21.000,   0.000]
[  0.000, 175.000,   0.000]
[  0.000,   0.000,   0.000]

[ 14.000,  21.000, -14.000]
[  0.000, 175.000, -70.000]
[  0.000,   0.000,  78.262]

我不确定我的辅助函数中是否有任何错误,因为我在开始测试代码之前检查了它们,但是QRdecompose()函数内部的逻辑似乎有些偏差。除了我还没有涉及的内存泄漏。任何人都可以在QRdecompose中看到任何问题()我错过了什么吗?

抱歉代码量很大 非常感谢帮助!

0 个答案:

没有答案