|
Graphviz
2.29.20120523.0446
|
00001 /* $Id$ $Revision$ */ 00002 /* vim:set shiftwidth=4 ts=8: */ 00003 00004 /************************************************************************* 00005 * Copyright (c) 2011 AT&T Intellectual Property 00006 * All rights reserved. This program and the accompanying materials 00007 * are made available under the terms of the Eclipse Public License v1.0 00008 * which accompanies this distribution, and is available at 00009 * http://www.eclipse.org/legal/epl-v10.html 00010 * 00011 * Contributors: See CVS logs. Details at http://www.graphviz.org/ 00012 *************************************************************************/ 00013 00014 00015 #include "matrix_ops.h" 00016 #include "conjgrad.h" 00017 /* #include <math.h> */ 00018 #include <stdlib.h> 00019 00020 00021 /************************* 00022 ** C.G. method - SPARSE * 00023 *************************/ 00024 00025 int conjugate_gradient 00026 (vtx_data * A, double *x, double *b, int n, double tol, 00027 int max_iterations) { 00028 /* Solves Ax=b using Conjugate-Gradients method */ 00029 /* 'x' and 'b' are orthogonalized against 1 */ 00030 00031 int i, rv = 0; 00032 00033 double alpha, beta, r_r, r_r_new, p_Ap; 00034 double *r = N_GNEW(n, double); 00035 double *p = N_GNEW(n, double); 00036 double *Ap = N_GNEW(n, double); 00037 double *Ax = N_GNEW(n, double); 00038 double *alphap = N_GNEW(n, double); 00039 00040 double *orth_b = N_GNEW(n, double); 00041 copy_vector(n, b, orth_b); 00042 orthog1(n, orth_b); 00043 orthog1(n, x); 00044 right_mult_with_vector(A, n, x, Ax); 00045 vectors_subtraction(n, orth_b, Ax, r); 00046 copy_vector(n, r, p); 00047 r_r = vectors_inner_product(n, r, r); 00048 00049 for (i = 0; i < max_iterations && max_abs(n, r) > tol; i++) { 00050 right_mult_with_vector(A, n, p, Ap); 00051 p_Ap = vectors_inner_product(n, p, Ap); 00052 if (p_Ap == 0) 00053 break; /*exit(1); */ 00054 alpha = r_r / p_Ap; 00055 00056 /* derive new x: */ 00057 vectors_scalar_mult(n, p, alpha, alphap); 00058 vectors_addition(n, x, alphap, x); 00059 00060 /* compute values for next iteration: */ 00061 if (i < max_iterations - 1) { /* not last iteration */ 00062 vectors_scalar_mult(n, Ap, alpha, Ap); 00063 vectors_subtraction(n, r, Ap, r); /* fast computation of r, the residual */ 00064 00065 /* Alternaive accurate, but slow, computation of the residual - r */ 00066 /* right_mult_with_vector(A, n, x, Ax); */ 00067 /* vectors_subtraction(n,b,Ax,r); */ 00068 00069 r_r_new = vectors_inner_product(n, r, r); 00070 if (r_r == 0) { 00071 agerr (AGERR, "conjugate_gradient: unexpected length 0 vector\n"); 00072 rv = 1; 00073 goto cleanup0; 00074 } 00075 beta = r_r_new / r_r; 00076 r_r = r_r_new; 00077 vectors_scalar_mult(n, p, beta, p); 00078 vectors_addition(n, r, p, p); 00079 } 00080 } 00081 00082 cleanup0 : 00083 free(r); 00084 free(p); 00085 free(Ap); 00086 free(Ax); 00087 free(alphap); 00088 free(orth_b); 00089 00090 return rv; 00091 } 00092 00093 00094 /**************************** 00095 ** C.G. method - DENSE * 00096 ****************************/ 00097 00098 int conjugate_gradient_f 00099 (float **A, double *x, double *b, int n, double tol, 00100 int max_iterations, boolean ortho1) { 00101 /* Solves Ax=b using Conjugate-Gradients method */ 00102 /* 'x' and 'b' are orthogonalized against 1 if 'ortho1=true' */ 00103 00104 int i, rv = 0; 00105 00106 double alpha, beta, r_r, r_r_new, p_Ap; 00107 double *r = N_GNEW(n, double); 00108 double *p = N_GNEW(n, double); 00109 double *Ap = N_GNEW(n, double); 00110 double *Ax = N_GNEW(n, double); 00111 double *alphap = N_GNEW(n, double); 00112 00113 double *orth_b = N_GNEW(n, double); 00114 copy_vector(n, b, orth_b); 00115 if (ortho1) { 00116 orthog1(n, orth_b); 00117 orthog1(n, x); 00118 } 00119 right_mult_with_vector_f(A, n, x, Ax); 00120 vectors_subtraction(n, orth_b, Ax, r); 00121 copy_vector(n, r, p); 00122 r_r = vectors_inner_product(n, r, r); 00123 00124 for (i = 0; i < max_iterations && max_abs(n, r) > tol; i++) { 00125 right_mult_with_vector_f(A, n, p, Ap); 00126 p_Ap = vectors_inner_product(n, p, Ap); 00127 if (p_Ap == 0) 00128 break; /*exit(1); */ 00129 alpha = r_r / p_Ap; 00130 00131 /* derive new x: */ 00132 vectors_scalar_mult(n, p, alpha, alphap); 00133 vectors_addition(n, x, alphap, x); 00134 00135 /* compute values for next iteration: */ 00136 if (i < max_iterations - 1) { /* not last iteration */ 00137 vectors_scalar_mult(n, Ap, alpha, Ap); 00138 vectors_subtraction(n, r, Ap, r); /* fast computation of r, the residual */ 00139 00140 /* Alternaive accurate, but slow, computation of the residual - r */ 00141 /* right_mult_with_vector(A, n, x, Ax); */ 00142 /* vectors_subtraction(n,b,Ax,r); */ 00143 00144 r_r_new = vectors_inner_product(n, r, r); 00145 if (r_r == 0) { 00146 rv = 1; 00147 agerr (AGERR, "conjugate_gradient: unexpected length 0 vector\n"); 00148 goto cleanup1; 00149 } 00150 beta = r_r_new / r_r; 00151 r_r = r_r_new; 00152 vectors_scalar_mult(n, p, beta, p); 00153 vectors_addition(n, r, p, p); 00154 } 00155 } 00156 cleanup1: 00157 free(r); 00158 free(p); 00159 free(Ap); 00160 free(Ax); 00161 free(alphap); 00162 free(orth_b); 00163 00164 return rv; 00165 } 00166 00167 int 00168 conjugate_gradient_mkernel(float *A, float *x, float *b, int n, 00169 double tol, int max_iterations) 00170 { 00171 /* Solves Ax=b using Conjugate-Gradients method */ 00172 /* A is a packed symmetric matrix */ 00173 /* matrux A is "packed" (only upper triangular portion exists, row-major); */ 00174 00175 int i, rv = 0; 00176 00177 double alpha, beta, r_r, r_r_new, p_Ap; 00178 float *r = N_NEW(n, float); 00179 float *p = N_NEW(n, float); 00180 float *Ap = N_NEW(n, float); 00181 float *Ax = N_NEW(n, float); 00182 00183 /* centering x and b */ 00184 orthog1f(n, x); 00185 orthog1f(n, b); 00186 00187 right_mult_with_vector_ff(A, n, x, Ax); 00188 /* centering Ax */ 00189 orthog1f(n, Ax); 00190 00191 00192 vectors_substractionf(n, b, Ax, r); 00193 copy_vectorf(n, r, p); 00194 00195 r_r = vectors_inner_productf(n, r, r); 00196 00197 for (i = 0; i < max_iterations && max_absf(n, r) > tol; i++) { 00198 orthog1f(n, p); 00199 orthog1f(n, x); 00200 orthog1f(n, r); 00201 00202 right_mult_with_vector_ff(A, n, p, Ap); 00203 /* centering Ap */ 00204 orthog1f(n, Ap); 00205 00206 p_Ap = vectors_inner_productf(n, p, Ap); 00207 if (p_Ap == 0) 00208 break; 00209 alpha = r_r / p_Ap; 00210 00211 /* derive new x: */ 00212 vectors_mult_additionf(n, x, (float) alpha, p); 00213 00214 /* compute values for next iteration: */ 00215 if (i < max_iterations - 1) { /* not last iteration */ 00216 vectors_mult_additionf(n, r, (float) -alpha, Ap); 00217 00218 00219 r_r_new = vectors_inner_productf(n, r, r); 00220 00221 if (r_r == 0) { 00222 rv = 1; 00223 agerr (AGERR, "conjugate_gradient: unexpected length 0 vector\n"); 00224 goto cleanup2; 00225 } 00226 beta = r_r_new / r_r; 00227 r_r = r_r_new; 00228 00229 vectors_scalar_multf(n, p, (float) beta, p); 00230 00231 vectors_additionf(n, r, p, p); 00232 } 00233 } 00234 00235 cleanup2 : 00236 free(r); 00237 free(p); 00238 free(Ap); 00239 free(Ax); 00240 return rv; 00241 }
1.7.5