00001 /* Numerical Methods, S06 00002 * Note 8, Function optimization using the downhill Simplex method. 00003 * Peter Seidler 00004 * Source Code taken from: http://whome.phys.au.dk/~seidler/numeric/ */ 00005 00006 #include "simplex.h" 00007 //#include "CoordNodeFunctions.h" 00008 #include <NeighborCache.h> 00009 00010 #include <cmath> 00011 00012 using namespace std; 00013 00014 00015 /*************************** 00016 * Simplex class defintions. 00017 ***************************/ 00018 00019 Simplex::Simplex(int dimension) 00020 { 00021 dim = dimension; 00022 nverts = dim+1; 00023 verts = new Vec_DP*[nverts]; 00024 for (int i=0; i<nverts; i++) 00025 verts[i] = new Vec_DP(dim); 00026 } 00027 00028 Simplex::~Simplex() 00029 { 00030 for (int i=0; i<nverts; i++) 00031 delete verts[i]; 00032 delete[] verts; 00033 } 00034 00035 int Simplex::high(double* val) const 00036 { 00037 double test; 00038 double max = functionObject->f(*verts[0]); 00039 int idx = 0; 00040 for (int i=1; i<nverts; i++) { 00041 test = functionObject->f(*verts[i]); 00042 if (test > max) { 00043 max = test; 00044 idx = i; 00045 } 00046 } 00047 if (0 != val) 00048 *val = max; 00049 return idx; 00050 } 00051 00052 int Simplex::low(double* val) const 00053 { 00054 double test; 00055 double min = functionObject->f(*verts[0]);; 00056 int idx = 0; 00057 for (int i=1; i<nverts; i++) { 00058 test = functionObject->f(*verts[i]); 00059 if (test < min) { 00060 min = test; 00061 idx = i; 00062 } 00063 } 00064 if (0 != val) 00065 *val = min; 00066 return idx; 00067 } 00068 00069 void Simplex::centroid(Vec_DP& vec) const 00070 { 00071 Vec_DP ce(dim); 00072 int hi = high(); 00073 00074 for (int i=0; i<nverts; i++) 00075 if (i != hi) 00076 ce += *verts[i]; 00077 00078 vec = ce / (nverts-1); 00079 } 00080 00081 // Size is defined to be sum of distances from centroid to 00082 // all points in simplex. 00083 double Simplex::size() const 00084 { 00085 Vec_DP ce(dim); 00086 centroid(ce); 00087 double dp, size = 0; 00088 00089 for (int i=0; i<nverts; i++) { 00090 dp = dot(*verts[i]-ce, *verts[i]-ce); 00091 size += sqrt(dp); 00092 } 00093 return size; 00094 } 00095 00096 int Simplex::reflect() 00097 { 00098 int hi = high(); 00099 Vec_DP ce(dim); 00100 00101 centroid(ce); 00102 *verts[hi] = ce + (ce - *verts[hi]); 00103 return hi; 00104 } 00105 00106 int Simplex::reflect_exp() 00107 { 00108 int hi = high(); 00109 Vec_DP ce(dim); 00110 00111 centroid(ce); 00112 *verts[hi] = ce + 2*(ce - *verts[hi]); 00113 return hi; 00114 } 00115 00116 int Simplex::contract() 00117 { 00118 int hi = high(); 00119 Vec_DP ce(dim); 00120 00121 centroid(ce); 00122 *verts[hi] = ce + 0.5*(*verts[hi] - ce); 00123 return hi; 00124 } 00125 00126 void Simplex::reduce() 00127 { 00128 int lo = low(); 00129 00130 for (int i = 0; i<nverts; i++) { 00131 if (i != lo) { 00132 *verts[i] = 0.5 * (*verts[i] + *verts[lo]); 00133 } 00134 } 00135 } 00136 00137