Graphviz 15.1.1~dev.20260630.1303
Loading...
Searching...
No Matches
sparse_solve.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11#include "config.h"
12
13#include <assert.h>
14#include <string.h>
16#include <sfdpgen/sfdp.h>
17#include <math.h>
18#include <common/arith.h>
19#include <common/types.h>
20#include <common/globals.h>
21#include <util/alloc.h>
22
23/* #define DEBUG_PRINT */
24
25static double *diag_precon(const double *diag, double *x, double *y) {
26 int i, m;
27 m = (int) diag[0];
28 diag++;
29 for (i = 0; i < m; i++) y[i] = x[i]*diag[i];
30 return y;
31}
32
34 int j, *ia = A->ia, *ja = A->ja;
35 const size_t m = A->m;
36 double *a = A->a;
37
38 assert(A->type == MATRIX_TYPE_REAL);
39
40 assert(a);
41
42 double *data = gv_calloc(A->m + 1, sizeof(double));
43 double *diag = data;
44
45 diag[0] = m;
46 diag++;
47 for (size_t i = 0; i < m; i++){
48 diag[i] = 1.;
49 for (j = ia[i]; j < ia[i+1]; j++){
50 if ((int)i == ja[j] && fabs(a[j]) > 0) diag[i] = 1./a[j];
51 }
52 }
53
54 return data;
55}
56
57static double conjugate_gradient(SparseMatrix A, const double *precon, size_t n,
58 double *x, double *rhs, double tol,
59 double maxit) {
60 double res, alpha;
61 double rho, rho_old = 1, res0, beta;
62 int iter = 0;
63
64 double *z = gv_calloc(n, sizeof(double));
65 double *r = gv_calloc(n, sizeof(double));
66 double *p = gv_calloc(n, sizeof(double));
67 double *q = gv_calloc(n, sizeof(double));
68
70 r = vector_subtract_to(n, rhs, r);
71
72 res0 = res = sqrt(vector_product((int)n, r, r)) / (double)n;
73#ifdef DEBUG_PRINT
74 if (Verbose){
75 fprintf(stderr,
76 "on entry, cg iter = %d of %.0f, residual = %g, tol = %g\n",
77 iter, maxit, res, tol);
78 }
79#endif
80
81 while ((iter++) < maxit && res > tol*res0){
82 z = diag_precon(precon, r, z);
83 rho = vector_product((int)n, r, z);
84
85 if (iter > 1){
86 beta = rho/rho_old;
87 p = vector_saxpy(n, z, p, beta);
88 } else {
89 memcpy(p, z, sizeof(double)*n);
90 }
91
93
94 alpha = rho / vector_product((int)n, p, q);
95
96 x = vector_saxpy2(n, x, p, alpha);
97 r = vector_saxpy2(n, r, q, -alpha);
98
99 res = sqrt(vector_product((int)n, r, r)) / (double)n;
100
101 rho_old = rho;
102 }
103 free(z); free(r); free(p); free(q);
104#ifdef DEBUG
105 _statistics[0] += iter - 1;
106#endif
107
108#ifdef DEBUG_PRINT
109 if (Verbose){
110 fprintf(stderr, " cg iter = %d, residual = %g, relative res = %g\n", iter, res, res/res0);
111 }
112#endif
113 return res;
114}
115
116static double cg(SparseMatrix A, const double *precond, size_t n, int dim,
117 double *x0, double *rhs, double tol, double maxit) {
118 double res = 0;
119 int k;
120 double *x = gv_calloc(n, sizeof(double));
121 double *b = gv_calloc(n, sizeof(double));
122 for (k = 0; k < dim; k++){
123 for (size_t i = 0; i < n; i++) {
124 x[i] = x0[(int)i * dim + k];
125 b[i] = rhs[(int)i * dim + k];
126 }
127
128 res += conjugate_gradient(A, precond, n, x, b, tol, maxit);
129 for (size_t i = 0; i < n; i++) {
130 rhs[(int)i * dim + k] = x[i];
131 }
132 }
133 free(x);
134 free(b);
135 return res;
136}
137
138double SparseMatrix_solve(SparseMatrix A, int dim, double *x0, double *rhs,
139 double tol, double maxit) {
140 const size_t n = A->m;
141
142 double *precond = diag_precon_new(A);
143 double res = cg(A, precond, n, dim, x0, rhs, tol, maxit);
144 free(precond);
145 return res;
146}
147
void SparseMatrix_multiply_vector(SparseMatrix A, double *v, double **res)
@ MATRIX_TYPE_REAL
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
#define A(n, t)
Definition expr.h:76
double * vector_saxpy(size_t n, double *x, double *y, double beta)
y = x+beta*y
Definition general.c:40
double vector_product(int n, double *x, double *y)
Definition general.c:33
double * vector_subtract_to(size_t n, double *x, double *y)
y = x-y
Definition general.c:28
double * vector_saxpy2(size_t n, double *x, double *y, double beta)
x = x+beta*y
Definition general.c:46
static bool Verbose
Definition gml2gv.c:26
void free(void *)
static int z
static const int dim
static const int maxit
Definition power.c:18
#define alpha
Definition shapes.c:4034
static double conjugate_gradient(SparseMatrix A, const double *precon, size_t n, double *x, double *rhs, double tol, double maxit)
static double cg(SparseMatrix A, const double *precond, size_t n, int dim, double *x0, double *rhs, double tol, double maxit)
static double * diag_precon_new(SparseMatrix A)
double SparseMatrix_solve(SparseMatrix A, int dim, double *x0, double *rhs, double tol, double maxit)
static double * diag_precon(const double *diag, double *x, double *y)
static const double tol
graphs, nodes and edges info: Agraphinfo_t, Agnodeinfo_t and Agedgeinfo_t