Graphviz 14.1.2~dev.20260123.1158
Loading...
Searching...
No Matches
conjgrad.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 <neatogen/matrix_ops.h>
14#include <neatogen/conjgrad.h>
15#include <stdbool.h>
16#include <stdlib.h>
17#include <util/alloc.h>
18
19/*************************
20** C.G. method - SPARSE *
21*************************/
22
24 (vtx_data * A, double *x, double *b, int n, double tol,
25 int max_iterations) {
26 /* Solves Ax=b using Conjugate-Gradients method */
27 /* 'x' and 'b' are orthogonalized against 1 */
28
29 int i, rv = 0;
30
31 double alpha, beta, r_r, r_r_new, p_Ap;
32 double *r = gv_calloc(n, sizeof(double));
33 double *p = gv_calloc(n, sizeof(double));
34 double *Ap = gv_calloc(n, sizeof(double));
35 double *Ax = gv_calloc(n, sizeof(double));
36 double *alphap = gv_calloc(n, sizeof(double));
37
38 double *orth_b = gv_calloc(n, sizeof(double));
39 copy_vector(n, b, orth_b);
40 orthog1(n, orth_b);
41 orthog1(n, x);
42 right_mult_with_vector(A, n, x, Ax);
43 vectors_subtraction(n, orth_b, Ax, r);
44 copy_vector(n, r, p);
45 r_r = vectors_inner_product(n, r, r);
46
47 for (i = 0; i < max_iterations && max_abs(n, r) > tol; i++) {
48 right_mult_with_vector(A, n, p, Ap);
49 p_Ap = vectors_inner_product(n, p, Ap);
50 if (p_Ap == 0)
51 break; /*exit(1); */
52 alpha = r_r / p_Ap;
53
54 /* derive new x: */
55 vectors_scalar_mult(n, p, alpha, alphap);
56 vectors_addition(n, x, alphap, x);
57
58 /* compute values for next iteration: */
59 if (i < max_iterations - 1) { /* not last iteration */
60 vectors_scalar_mult(n, Ap, alpha, Ap);
61 vectors_subtraction(n, r, Ap, r); /* fast computation of r, the residual */
62
63 r_r_new = vectors_inner_product(n, r, r);
64 if (r_r == 0) {
65 agerrorf("conjugate_gradient: unexpected length 0 vector\n");
66 rv = 1;
67 goto cleanup0;
68 }
69 beta = r_r_new / r_r;
70 r_r = r_r_new;
71 vectors_scalar_mult(n, p, beta, p);
72 vectors_addition(n, r, p, p);
73 }
74 }
75
76cleanup0 :
77 free(r);
78 free(p);
79 free(Ap);
80 free(Ax);
81 free(alphap);
82 free(orth_b);
83
84 return rv;
85}
86
87
88/****************************
89** C.G. method - DENSE *
90****************************/
91
93 (float **A, double *x, double *b, int n, double tol,
94 int max_iterations, bool ortho1) {
95 /* Solves Ax=b using Conjugate-Gradients method */
96 /* 'x' and 'b' are orthogonalized against 1 if 'ortho1=true' */
97
98 int i, rv = 0;
99
100 double alpha, beta, r_r, r_r_new, p_Ap;
101 double *r = gv_calloc(n, sizeof(double));
102 double *p = gv_calloc(n, sizeof(double));
103 double *Ap = gv_calloc(n, sizeof(double));
104 double *Ax = gv_calloc(n, sizeof(double));
105 double *alphap = gv_calloc(n, sizeof(double));
106
107 double *orth_b = gv_calloc(n, sizeof(double));
108 copy_vector(n, b, orth_b);
109 if (ortho1) {
110 orthog1(n, orth_b);
111 orthog1(n, x);
112 }
113 right_mult_with_vector_f(A, n, x, Ax);
114 vectors_subtraction(n, orth_b, Ax, r);
115 copy_vector(n, r, p);
116 r_r = vectors_inner_product(n, r, r);
117
118 for (i = 0; i < max_iterations && max_abs(n, r) > tol; i++) {
119 right_mult_with_vector_f(A, n, p, Ap);
120 p_Ap = vectors_inner_product(n, p, Ap);
121 if (p_Ap == 0)
122 break; /*exit(1); */
123 alpha = r_r / p_Ap;
124
125 /* derive new x: */
126 vectors_scalar_mult(n, p, alpha, alphap);
127 vectors_addition(n, x, alphap, x);
128
129 /* compute values for next iteration: */
130 if (i < max_iterations - 1) { /* not last iteration */
131 vectors_scalar_mult(n, Ap, alpha, Ap);
132 vectors_subtraction(n, r, Ap, r); /* fast computation of r, the residual */
133
134 // Alternative accurate, but slow, computation of the residual - r
135 /* right_mult_with_vector(A, n, x, Ax); */
136 /* vectors_subtraction(n,b,Ax,r); */
137
138 r_r_new = vectors_inner_product(n, r, r);
139 if (r_r == 0) {
140 rv = 1;
141 agerrorf("conjugate_gradient: unexpected length 0 vector\n");
142 goto cleanup1;
143 }
144 beta = r_r_new / r_r;
145 r_r = r_r_new;
146 vectors_scalar_mult(n, p, beta, p);
147 vectors_addition(n, r, p, p);
148 }
149 }
151 free(r);
152 free(p);
153 free(Ap);
154 free(Ax);
155 free(alphap);
156 free(orth_b);
157
158 return rv;
159}
160
161int
162conjugate_gradient_mkernel(float *A, float *x, float *b, int n,
163 double tol, int max_iterations)
164{
165 /* Solves Ax=b using Conjugate-Gradients method */
166 /* A is a packed symmetric matrix */
167 // matrix A is “packed” (only upper triangular portion exists, row-major)
168
169 int i, rv = 0;
170
171 double alpha, beta, r_r, r_r_new, p_Ap;
172 float *r = gv_calloc(n, sizeof(float));
173 float *p = gv_calloc(n, sizeof(float));
174 float *Ap = gv_calloc(n, sizeof(float));
175 float *Ax = gv_calloc(n, sizeof(float));
176
177 /* centering x and b */
178 orthog1f(n, x);
179 orthog1f(n, b);
180
181 right_mult_with_vector_ff(A, n, x, Ax);
182 /* centering Ax */
183 orthog1f(n, Ax);
184
185
186 vectors_subtractionf(n, b, Ax, r);
187 copy_vectorf(n, r, p);
188
189 r_r = vectors_inner_productf(n, r, r);
190
191 for (i = 0; i < max_iterations && max_absf(n, r) > tol; i++) {
192 orthog1f(n, p);
193 orthog1f(n, x);
194 orthog1f(n, r);
195
196 right_mult_with_vector_ff(A, n, p, Ap);
197 /* centering Ap */
198 orthog1f(n, Ap);
199
200 p_Ap = vectors_inner_productf(n, p, Ap);
201 if (p_Ap == 0)
202 break;
203 alpha = r_r / p_Ap;
204
205 /* derive new x: */
206 vectors_mult_additionf(n, x, (float) alpha, p);
207
208 /* compute values for next iteration: */
209 if (i < max_iterations - 1) { /* not last iteration */
210 vectors_mult_additionf(n, r, (float) -alpha, Ap);
211
212
213 r_r_new = vectors_inner_productf(n, r, r);
214
215 if (r_r == 0) {
216 rv = 1;
217 agerrorf("conjugate_gradient: unexpected length 0 vector\n");
218 goto cleanup2;
219 }
220 beta = r_r_new / r_r;
221 r_r = r_r_new;
222
223 for (size_t j = 0; j < (size_t)n; ++j) {
224 p[j] = (float)beta * p[j] + r[j];
225 }
226 }
227 }
228
229cleanup2 :
230 free(r);
231 free(p);
232 free(Ap);
233 free(Ax);
234 return rv;
235}
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
int conjugate_gradient(vtx_data *A, double *x, double *b, int n, double tol, int max_iterations)
Definition conjgrad.c:24
int conjugate_gradient_mkernel(float *A, float *x, float *b, int n, double tol, int max_iterations)
Definition conjgrad.c:162
int conjugate_gradient_f(float **A, double *x, double *b, int n, double tol, int max_iterations, bool ortho1)
Definition conjgrad.c:93
#define A(n, t)
Definition expr.h:76
void free(void *)
void agerrorf(const char *fmt,...)
Definition agerror.c:167
double vectors_inner_product(int n, const double *vector1, const double *vector2)
Definition matrix_ops.c:324
void orthog1f(int n, float *vec)
Definition matrix_ops.c:383
void right_mult_with_vector(vtx_data *matrix, int n, double *vector, double *result)
Definition matrix_ops.c:262
void copy_vector(int n, const double *restrict source, double *restrict dest)
Definition matrix_ops.c:318
void right_mult_with_vector_f(float **matrix, int n, double *vector, double *result)
Definition matrix_ops.c:277
double max_absf(int n, float *vector)
Definition matrix_ops.c:484
void orthog1(int n, double *vec)
Definition matrix_ops.c:229
void copy_vectorf(int n, float *source, float *dest)
Definition matrix_ops.c:452
void right_mult_with_vector_ff(float *packed_matrix, int n, float *vector, float *result)
Definition matrix_ops.c:402
void vectors_mult_additionf(int n, float *vector1, float alpha, float *vector2)
Definition matrix_ops.c:444
double max_abs(int n, double *vector)
Definition matrix_ops.c:335
void vectors_subtraction(int n, double *vector1, double *vector2, double *result)
Definition matrix_ops.c:292
void vectors_addition(int n, double *vector1, double *vector2, double *result)
Definition matrix_ops.c:302
void vectors_scalar_mult(int n, const double *vector, double alpha, double *result)
Definition matrix_ops.c:310
void vectors_subtractionf(int n, float *vector1, float *vector2, float *result)
Definition matrix_ops.c:426
double vectors_inner_productf(int n, float *vector1, float *vector2)
Definition matrix_ops.c:459
static void cleanup2(graph_t *g, int64_t nc)
Definition mincross.c:918
static void cleanup1(graph_t *g)
Definition rank.c:80
#define alpha
Definition shapes.c:4058
static const double tol