在 CHOLMOD 或 SuiteSparseQR 中创建稀疏矩阵

发布于 2024-11-08 13:33:08 字数 235 浏览 0 评论 0原文

SparseSuiteQR 中,我可以找到的所有示例都使用 stdin 或读取的文件创建稀疏矩阵。有人可以提供一个如何直接在 C++ 中创建一个简单的示例吗?

更好的是,在 CHOLMOD 文档中,提到了 matlab 中可用的稀疏2函数,其行为与稀疏函数相同。这可以在C++中使用吗?

In SparseSuiteQR, all of the examples I can find use stdin or a file read to create a sparse matrix. Could someone provide a simple example of how to create one directly in C++?

Even better, in the CHOLMOD documentation, there is mention of a sparse2 function available in matlab, which behaves the same as the sparse. Can this be used in C++?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

看海 2024-11-15 13:33:08

SuiteSparseQR 使用的数据结构(例如 cholmod_sparse)在 CHOLMOD 库中定义。您可以在 CHOLMOD 文档中找到有关它的更多信息,该文档比 SuiteSparseQR 中的文档大得多。

The data structures used by SuiteSparseQR (e.g. cholmod_sparse) are defined in the CHOLMOD library. You can find more information about it on the CHOLMOD documentation, which is much larger than the one from SuiteSparseQR.

樱娆 2024-11-15 13:33:08

我假设您尝试解决线性系统,请参阅 Tim Davies 的 CSparse 包,或者 boost 矩阵库,它也具有与 umfpack 和一些 lapack 函数接口的数字绑定 AFAIK...

I am assuming that you try to solve a linear system, see the CSparse package from Tim Davies, or boost matrix libraries which also have numeric bindings which interface umfpack and some lapack functions AFAIK...

黎夕旧梦 2024-11-15 13:33:08

CHOLMOD 是一个非常棒的项目 - 感谢 Tim Davis :)

令人惊讶的是 GitHub 上有很多使用 CHOLMOD 的代码,但是你必须登录 GitHub 并知道你在寻找什么!

因此,在爬取 CHOLMOD 文档和源代码,然后在 GitHub 中搜索使用 CHOLMOD 的源代码之后,您就会知道该怎么做。

但对于大多数想要/需要一个简单示例的开发人员来说,如下所示。

*请注意,您的情况可能会有所不同,具体取决于您编译 SuiteSparse 的方式。
(您可能需要使用 cholmod_ 变体(不带 l),即不是 cholmod_l_;并使用 int用于索引,而不是long int)。

// example.cpp
#include "SuiteSparseQR.hpp"
#include "SuiteSparse_config.h"

int main (int argc, char **argv)
{
  cholmod_common Common, *cc;
  cholmod_sparse *A;
  cholmod_dense *X, *B;

  // start CHOLMOD
  cc = &Common;
  cholmod_l_start (cc);

  /* A =
      [
        1.1,  0.0, -0.5,  0.7
        0.0, -2.0,  0.0,  0.0
        0.0,  0.0,  0.9,  0.0
        0.0,  0.0,  0.0,  0.6
      ]
  */
  int m = 4;   // num rows in A
  int n = 4;   // num cols in A
  int nnz = 6; // num non-zero elements in A
  int unsymmetric = 0; // A is non-symmetric: see cholmod.h > search for `stype` for more details

  // In coordinate form (COO) a.k.a. triplet form (zero-based indexing)
  int i[nnz] = {0, 1, 0, 2, 0, 3}; // row indices
  int j[nnz] = {0, 1, 2, 2, 3, 3}; // col indices
  double x[nnz] = {1.1, -2.0, -0.5, 0.9, 0.7, 0.6}; // values

  // Set up the cholmod matrix in COO/triplet form
  cholmod_triplet *T = cholmod_l_allocate_triplet(m, n, nnz, unsymmetric, CHOLMOD_REAL, cc);
  T->nnz = nnz;

  for (int ind = 0; ind < nnz; ind++)
  {
    ((long int *) T->i)[ind] = i[ind];     // Notes:
    ((long int *) T->j)[ind] = j[ind];     // (1) casting necessary because these are void* (see cholmod.h)
    ((double *) T->x)[ind] = x[ind];       // (2) direct assignment will cause memory corruption
  }                                        // (3) long int for index pointers corresponds to usage of cholmod_l_* functions

  // convert COO/triplet to CSC (compressed sparse column) format
  A = (cholmod_sparse *) cholmod_l_triplet_to_sparse(T, nnz, cc);
  // note: if you already know CSC format you can skip the triplet allocation and instead use cholmod_allocate_sparse
  //       and assign the member variables: see cholmod.h > cholmod_sparse_struct definition

  // B = ones (size (A,1),1)
  B = cholmod_l_ones (A->nrow, 1, A->xtype, cc);

  // X = A\B
  X = SuiteSparseQR <double> (A, B, cc);

  // Print contents of X
  printf("X = [\n");
  for (int ind = 0; ind < n; ind++)
  {
    printf("%f\n", ((double *) X->x)[ind]);
  }
  printf("]\n");
  fflush(stdout);

  // free everything and finish CHOLMOD
  cholmod_l_free_triplet (&T, cc);
  cholmod_l_free_sparse (&A, cc);
  cholmod_l_free_dense (&X, cc);
  cholmod_l_free_dense (&B, cc);
  cholmod_l_finish (cc);
  return 0;
}

假设您已成功编译 SuiteSparse 并将 example.cpp 保存在基本目录中,则以下内容应该有效(在 Linux 上):

gcc example.cpp -I./include -L./lib -lcholmod -lspqr -lsuitesparseconfig -o example
#Add SuiteSpare libraries to your `ld` search path if necessary
LD_LIBRARY_PATH=$(pwd)/lib
export LD_LIBRARY_PATH
./example

输出:

X = [
0.353535
-0.500000
1.111111
1.666667
]

CHOLMOD is a pretty awesome project - thanks Tim Davis :)

There is surprisingly a lot of code on GitHub that makes use of CHOLMOD, but you have to be logged into GitHub and know what you're looking for!

So, after crawling through CHOLMOD documentation and source code and then searching through GitHub for source code that uses CHOLMOD you would find out what to do.

But for most developers who want/need a quick example, here it is below.

*Note that your mileage might vary depending on how you compiled SuiteSparse.
(You might need to use the cholmod_ variant (without the l), i.e. not cholmod_l_; and use int for indexing, not long int).

// example.cpp
#include "SuiteSparseQR.hpp"
#include "SuiteSparse_config.h"

int main (int argc, char **argv)
{
  cholmod_common Common, *cc;
  cholmod_sparse *A;
  cholmod_dense *X, *B;

  // start CHOLMOD
  cc = &Common;
  cholmod_l_start (cc);

  /* A =
      [
        1.1,  0.0, -0.5,  0.7
        0.0, -2.0,  0.0,  0.0
        0.0,  0.0,  0.9,  0.0
        0.0,  0.0,  0.0,  0.6
      ]
  */
  int m = 4;   // num rows in A
  int n = 4;   // num cols in A
  int nnz = 6; // num non-zero elements in A
  int unsymmetric = 0; // A is non-symmetric: see cholmod.h > search for `stype` for more details

  // In coordinate form (COO) a.k.a. triplet form (zero-based indexing)
  int i[nnz] = {0, 1, 0, 2, 0, 3}; // row indices
  int j[nnz] = {0, 1, 2, 2, 3, 3}; // col indices
  double x[nnz] = {1.1, -2.0, -0.5, 0.9, 0.7, 0.6}; // values

  // Set up the cholmod matrix in COO/triplet form
  cholmod_triplet *T = cholmod_l_allocate_triplet(m, n, nnz, unsymmetric, CHOLMOD_REAL, cc);
  T->nnz = nnz;

  for (int ind = 0; ind < nnz; ind++)
  {
    ((long int *) T->i)[ind] = i[ind];     // Notes:
    ((long int *) T->j)[ind] = j[ind];     // (1) casting necessary because these are void* (see cholmod.h)
    ((double *) T->x)[ind] = x[ind];       // (2) direct assignment will cause memory corruption
  }                                        // (3) long int for index pointers corresponds to usage of cholmod_l_* functions

  // convert COO/triplet to CSC (compressed sparse column) format
  A = (cholmod_sparse *) cholmod_l_triplet_to_sparse(T, nnz, cc);
  // note: if you already know CSC format you can skip the triplet allocation and instead use cholmod_allocate_sparse
  //       and assign the member variables: see cholmod.h > cholmod_sparse_struct definition

  // B = ones (size (A,1),1)
  B = cholmod_l_ones (A->nrow, 1, A->xtype, cc);

  // X = A\B
  X = SuiteSparseQR <double> (A, B, cc);

  // Print contents of X
  printf("X = [\n");
  for (int ind = 0; ind < n; ind++)
  {
    printf("%f\n", ((double *) X->x)[ind]);
  }
  printf("]\n");
  fflush(stdout);

  // free everything and finish CHOLMOD
  cholmod_l_free_triplet (&T, cc);
  cholmod_l_free_sparse (&A, cc);
  cholmod_l_free_dense (&X, cc);
  cholmod_l_free_dense (&B, cc);
  cholmod_l_finish (cc);
  return 0;
}

Supposing you have compiled SuiteSparse successfully and you have saved example.cpp in the base directory, then the following should work (on Linux):

gcc example.cpp -I./include -L./lib -lcholmod -lspqr -lsuitesparseconfig -o example
#Add SuiteSpare libraries to your `ld` search path if necessary
LD_LIBRARY_PATH=$(pwd)/lib
export LD_LIBRARY_PATH
./example

Output:

X = [
0.353535
-0.500000
1.111111
1.666667
]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文