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