00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef __RVL_GRADTEST
00034 #define __RVL_GRADTEST
00035
00036 #include "functional.hh"
00037
00038 namespace RVL {
00039
00050 template<class Scalar>
00051 bool GradientTest(Functional<Scalar> const & f,
00052 const Vector<Scalar> & y,
00053 const Vector<Scalar> & p,
00054 ostream & str,
00055 int n=11,
00056 Scalar hmin=0.1,
00057 Scalar hmax=1.0,
00058 Scalar minrat=1.95) {
00059
00060 try {
00061
00062 bool success = false;
00063
00064 if (!y.inSpace(f.getDomain())) {
00065 RVLException e; e<<"Error in GradientTest: \n";
00066 e<<"base vector is not in Domain\n";
00067 throw e;
00068 }
00069 if (!p.inSpace(f.getDomain())) {
00070 RVLException e; e<<"Error in GradientTest: \n";
00071 e<<"direction vector is not in Domain\n";
00072 throw e;
00073 }
00074
00075 if (hmax <= hmin) {
00076 Scalar temp = hmax;
00077 hmax = hmin;
00078 hmin = temp;
00079 }
00080 if (hmin <= 0.0) {
00081 hmin = 0.1;
00082 hmax = 1.0;
00083 }
00084 if (n < 2) {
00085 RVLException e;
00086 e<<"RVL::GradientTest:\n";
00087 e<<" test not performed because number of samples = "<<n<<" too small\n";
00088 throw e;
00089 }
00090
00091 Scalar hlimit1;
00092 Scalar hlimit2;
00093 hlimit1 = f.getMaxStep(y,p);
00094
00095 {
00096 Vector<Scalar> ptemp(f.getDomain());
00097 Scalar one = ScalarFieldTraits<Scalar>::One();
00098 ptemp.scale(-one,p);
00099 hlimit2 = f.getMaxStep(y,ptemp);
00100 }
00101
00102 Scalar hlimit = min(hlimit1,hlimit2);
00103 if (hlimit <= 0.0) {
00104 RVLException e; e<<"Error in GradientTest:\n";
00105 e<<" direction is not feasible\n";
00106 throw e;
00107 }
00108 if (hmax >= hlimit) {
00109 hmax = 0.99*hlimit;
00110 if (hmin >= hmax) hmin = hmax/n;
00111 }
00112
00113 Vector<Scalar> x1(f.getDomain());
00114 Vector<Scalar> x2(f.getDomain());
00115 Vector<Scalar> dx(f.getDomain());
00116
00117 FunctionalEvaluation<Scalar> F1(f,x1);
00118 FunctionalEvaluation<Scalar> F2(f,x2);
00119
00120 Scalar s = 0.0;
00121 {
00122 FunctionalEvaluation<Scalar> Fy(f,y);
00123 s = (Fy.getGradient()).inner(p);
00124 }
00125
00126 int nd;
00127 if (numeric_precision<Scalar>()==1) nd = 8;
00128 if (numeric_precision<Scalar>()==2) nd = 16;
00129
00130 int oldprecision = str.precision(nd);
00131
00132 int rflag = 1;
00133
00134 if (abs(s) < numeric_limits<Scalar>::epsilon()) {
00135 rflag = 0;
00136 str << "GradientTest: norm of first "
00137 "variation is too small; displaying absolute error"
00138 << endl;
00139 }
00140
00141 str<<endl<<"Gradient Computation Check"<<endl<<endl;
00142
00143 if (rflag)
00144 str << setw(8) << "h" << setw(nd+7) << " norm of diff."
00145 << setw(nd+8) << "rel. error" << setw(nd+6)
00146 << "convg. rate" << endl;
00147 else
00148 str << setw(8) << "h" << setw(nd+7) << " norm of diff."
00149 << setw(nd+6) << "convg. rate" << endl;
00150 int i;
00151 Scalar hstep = (hmax-hmin)/(n-1);
00152 Scalar n1p=1.0;
00153 Scalar tn;
00154
00155 for(i=n-1;i>=0;i--) {
00156
00157 Scalar h = hmin+i*hstep;
00158 x1.copy(y);
00159 x2.copy(y);
00160 x1.linComb(-h,p);
00161 x2.linComb(h,p);
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 Scalar ds = (F2.getValue()-F1.getValue())/(2.0*h);
00174
00175 Scalar n1 = abs(s-ds);
00176 if (i<n-1 && !ProtectedDivision(n1p,n1,tn)) {
00177 Scalar rat = log(tn)/log((h+hstep)/h);
00178 if (rat > minrat) success = true;
00179 if (rflag)
00180 str << setprecision(6) << setw(8) << h << " "
00181 << setprecision(nd) << setw(nd+6) << n1
00182 << setw(nd+8) << n1/abs(s) << setw(nd+6)
00183 << rat << endl;
00184 else
00185 str << setprecision(6) << setw(8) << h << " "
00186 << setprecision(nd) << setw(nd+6) << n1
00187 << setw(nd+6) << rat
00188 << endl;
00189 }
00190 else {
00191 char * jnk = new char[nd];
00192 for (int ii=0;ii<nd;ii++) {
00193 jnk[ii]='-';
00194 }
00195 jnk[nd-1]='\0';
00196 if (rflag)
00197 str << setprecision(6) << setw(8) << h << " "
00198 << setprecision(nd) << setw(nd+6) << n1
00199 << setw(nd+8) << n1/abs(s) << setw(nd+6)
00200 << jnk << endl;
00201 else
00202 str << setprecision(6) << setw(8) << h << " "
00203 << setprecision(nd) << setw(nd+6) << n1 << " "
00204 << setw(nd+6) << jnk << endl;
00205 delete [] jnk;
00206 }
00207 n1p=n1;
00208
00209 }
00210 str.precision(oldprecision);
00211 return success;
00212 }
00213 catch (RVLException & e) {
00214 e<<"\ncalled from GradientTest\n";
00215 throw e;
00216 }
00217 }
00218
00219 }
00220
00221 #endif