Graphviz 14.1.3~dev.20260126.0926
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 v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.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 i, j, m = A->m, *ia = A->ia, *ja = A->ja;
35 double *a = A->a;
36
37 assert(A->type == MATRIX_TYPE_REAL);
38
39 assert(a);
40
41 double *data = gv_calloc(A->m + 1, sizeof(double));
42 double *diag = data;
43
44 diag[0] = m;
45 diag++;
46 for (i = 0; i < m; i++){
47 diag[i] = 1.;
48 for (j = ia[i]; j < ia[i+1]; j++){
49 if (i == ja[j] && fabs(a[j]) > 0) diag[i] = 1./a[j];
50 }
51 }
52
53 return data;
54}
55
56static double conjugate_gradient(SparseMatrix A, const double *precon, int n,
57 double *x, double *rhs, double tol,
58 double maxit) {
59 double res, alpha;
60 double rho, rho_old = 1, res0, beta;
61 int iter = 0;
62
63 double *z = gv_calloc(n, sizeof(double));
64 double *r = gv_calloc(n, sizeof(double));
65 double *p = gv_calloc(n, sizeof(double));
66 double *q = gv_calloc(n, sizeof(double));
67
69 r = vector_subtract_to(n, rhs, r);
70
71 res0 = res = sqrt(vector_product(n, r, r))/n;
72#ifdef DEBUG_PRINT
73 if (Verbose){
74 fprintf(stderr,
75 "on entry, cg iter = %d of %.0f, residual = %g, tol = %g\n",
76 iter, maxit, res, tol);
77 }
78#endif
79
80 while ((iter++) < maxit && res > tol*res0){
81 z = diag_precon(precon, r, z);
82 rho = vector_product(n, r, z);
83
84 if (iter > 1){
85 beta = rho/rho_old;
86 p = vector_saxpy(n, z, p, beta);
87 } else {
88 memcpy(p, z, sizeof(double)*n);
89 }
90
92
93 alpha = rho/vector_product(n, p, q);
94
95 x = vector_saxpy2(n, x, p, alpha);
96 r = vector_saxpy2(n, r, q, -alpha);
97
98 res = sqrt(vector_product(n, r, r))/n;
99
100 rho_old = rho;
101 }
102 free(z); free(r); free(p); free(q);
103#ifdef DEBUG
104 _statistics[0] += iter - 1;
105#endif
106
107#ifdef DEBUG_PRINT
108 if (Verbose){
109 fprintf(stderr, " cg iter = %d, residual = %g, relative res = %g\n", iter, res, res/res0);
110 }
111#endif
112 return res;
113}
114
115static double cg(SparseMatrix A, const double *precond, int n, int dim,
116 double *x0, double *rhs, double tol, double maxit) {
117 double res = 0;
118 int k, i;
119 double *x = gv_calloc(n, sizeof(double));
120 double *b = gv_calloc(n, sizeof(double));
121 for (k = 0; k < dim; k++){
122 for (i = 0; i < n; i++) {
123 x[i] = x0[i*dim+k];
124 b[i] = rhs[i*dim+k];
125 }
126
127 res += conjugate_gradient(A, precond, n, x, b, tol, maxit);
128 for (i = 0; i < n; i++) {
129 rhs[i*dim+k] = x[i];
130 }
131 }
132 free(x);
133 free(b);
134 return res;
135}
136
137double SparseMatrix_solve(SparseMatrix A, int dim, double *x0, double *rhs,
138 double tol, double maxit) {
139 int n = A->m;
140
141 double *precond = diag_precon_new(A);
142 double res = cg(A, precond, n, dim, x0, rhs, tol, maxit);
143 free(precond);
144 return res;
145}
146
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(int n, double *x, double *y, double beta)
Definition general.c:41
double * vector_saxpy2(int n, double *x, double *y, double beta)
Definition general.c:48
double vector_product(int n, double *x, double *y)
Definition general.c:34
double * vector_subtract_to(int n, double *x, double *y)
Definition general.c:28
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:4058
static double conjugate_gradient(SparseMatrix A, const double *precon, int n, double *x, double *rhs, double tol, double maxit)
static double * diag_precon_new(SparseMatrix A)
static double cg(SparseMatrix A, const double *precond, int n, int dim, double *x0, double *rhs, double tol, double maxit)
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