Graphviz 12.0.1~dev.20240716.0800
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 <assert.h>
12#include <cgraph/alloc.h>
13#include <string.h>
15#include <sfdpgen/sfdp.h>
16#include <math.h>
17#include <common/arith.h>
18#include <common/types.h>
19#include <common/globals.h>
20
21/* #define DEBUG_PRINT */
22
23static double *diag_precon(const double *diag, double *x, double *y) {
24 int i, m;
25 m = (int) diag[0];
26 diag++;
27 for (i = 0; i < m; i++) y[i] = x[i]*diag[i];
28 return y;
29}
30
32 int i, j, m = A->m, *ia = A->ia, *ja = A->ja;
33 double *a = A->a;
34
35 assert(A->type == MATRIX_TYPE_REAL);
36
37 assert(a);
38
39 double *data = gv_calloc(A->m + 1, sizeof(double));
40 double *diag = data;
41
42 diag[0] = m;
43 diag++;
44 for (i = 0; i < m; i++){
45 diag[i] = 1.;
46 for (j = ia[i]; j < ia[i+1]; j++){
47 if (i == ja[j] && fabs(a[j]) > 0) diag[i] = 1./a[j];
48 }
49 }
50
51 return data;
52}
53
54static double conjugate_gradient(SparseMatrix A, const double *precon, int n,
55 double *x, double *rhs, double tol,
56 double maxit) {
57 double res, alpha;
58 double rho, rho_old = 1, res0, beta;
59 int iter = 0;
60
61 double *z = gv_calloc(n, sizeof(double));
62 double *r = gv_calloc(n, sizeof(double));
63 double *p = gv_calloc(n, sizeof(double));
64 double *q = gv_calloc(n, sizeof(double));
65
67 r = vector_subtract_to(n, rhs, r);
68
69 res0 = res = sqrt(vector_product(n, r, r))/n;
70#ifdef DEBUG_PRINT
71 if (Verbose){
72 fprintf(stderr,
73 "on entry, cg iter = %d of %.0f, residual = %g, tol = %g\n",
74 iter, maxit, res, tol);
75 }
76#endif
77
78 while ((iter++) < maxit && res > tol*res0){
79 z = diag_precon(precon, r, z);
80 rho = vector_product(n, r, z);
81
82 if (iter > 1){
83 beta = rho/rho_old;
84 p = vector_saxpy(n, z, p, beta);
85 } else {
86 memcpy(p, z, sizeof(double)*n);
87 }
88
90
91 alpha = rho/vector_product(n, p, q);
92
93 x = vector_saxpy2(n, x, p, alpha);
94 r = vector_saxpy2(n, r, q, -alpha);
95
96 res = sqrt(vector_product(n, r, r))/n;
97
98 rho_old = rho;
99 }
100 free(z); free(r); free(p); free(q);
101#ifdef DEBUG
102 _statistics[0] += iter - 1;
103#endif
104
105#ifdef DEBUG_PRINT
106 if (Verbose){
107 fprintf(stderr, " cg iter = %d, residual = %g, relative res = %g\n", iter, res, res/res0);
108 }
109#endif
110 return res;
111}
112
113static double cg(SparseMatrix A, const double *precond, int n, int dim,
114 double *x0, double *rhs, double tol, double maxit) {
115 double res = 0;
116 int k, i;
117 double *x = gv_calloc(n, sizeof(double));
118 double *b = gv_calloc(n, sizeof(double));
119 for (k = 0; k < dim; k++){
120 for (i = 0; i < n; i++) {
121 x[i] = x0[i*dim+k];
122 b[i] = rhs[i*dim+k];
123 }
124
125 res += conjugate_gradient(A, precond, n, x, b, tol, maxit);
126 for (i = 0; i < n; i++) {
127 rhs[i*dim+k] = x[i];
128 }
129 }
130 free(x);
131 free(b);
132 return res;
133}
134
135double SparseMatrix_solve(SparseMatrix A, int dim, double *x0, double *rhs,
136 double tol, double maxit) {
137 int n = A->m;
138
139 double *precond = diag_precon_new(A);
140 double res = cg(A, precond, n, dim, x0, rhs, tol, maxit);
141 free(precond);
142 return res;
143}
144
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:64
double * vector_saxpy2(int n, double *x, double *y, double beta)
Definition general.c:71
double vector_product(int n, double *x, double *y)
Definition general.c:57
double * vector_subtract_to(int n, double *x, double *y)
Definition general.c:51
static int Verbose
Definition gml2gv.c:22
void free(void *)
static int z
static const int maxit
Definition power.c:16
#define alpha
Definition shapes.c:4068
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
Definition legal.c:50
graphs, nodes and edges info: Agraphinfo_t, Agnodeinfo_t and Agedgeinfo_t