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 #ifndef __LS
00033 #define __LS
00034
00035 #include "op.hh"
00036 #include "functional.hh"
00037
00038 namespace RVL {
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00051 template<class Scalar>
00052 class ShiftOperator: public Operator<Scalar> {
00053
00054 private:
00055
00056 const Vector<Scalar> & d;
00057
00058 ShiftOperator();
00059
00060 protected:
00061
00062 void apply(const Vector<Scalar> & x,
00063 Vector<Scalar> & y) const {
00064 try {
00065 y.copy(x);
00066 y.linComb(-1.0,d);
00067 }
00068 catch (RVLException & e) {
00069 e<<"\ncalled from ShiftOperator::apply\n";
00070 throw e;
00071 }
00072 }
00073
00074 void applyDeriv(const Vector<Scalar> & x,
00075 const Vector<Scalar> & dx,
00076 Vector<Scalar> & dy) const {
00077 try {
00078 dy.copy(dx);
00079 }
00080 catch (RVLException & e) {
00081 e<<"\ncalled from ShiftOperator::applyDeriv\n";
00082 throw e;
00083 }
00084 }
00085
00086 void applyAdjDeriv(const Vector<Scalar> & x,
00087 const Vector<Scalar> & dy,
00088 Vector<Scalar> & dx) const {
00089 try {
00090 dx.copy(dy);
00091 }
00092 catch (RVLException & e) {
00093 e<<"\ncalled from ShiftOperator::applyAdjDeriv\n";
00094 throw e;
00095 }
00096 }
00097
00098
00099 virtual Operator<Scalar> * clone() const {
00100 return new ShiftOperator<Scalar>(*this);
00101 }
00102
00103 public:
00105 ShiftOperator(const Vector<Scalar> & dd): d(dd) {}
00106 ShiftOperator(const ShiftOperator<Scalar> & a): d(a.d) {}
00107 ~ShiftOperator() {}
00108
00110 const Space<Scalar> & getDomain() const { return d.getSpace(); }
00111 const Space<Scalar> & getRange() const { return d.getSpace(); }
00112
00113 ostream & write(ostream & str) const {
00114 str<<"Shift Operator"<<"\n";
00115 str<<"*** shift vector\n";
00116 d.write(str);
00117 return str;
00118 }
00119 };
00120
00123 template<class Scalar>
00124 class ResidualOperator: public Operator<Scalar> {
00125
00126 private:
00127
00128 Vector<Scalar> const & d;
00129 Operator<Scalar> const & G;
00130
00131 ResidualOperator();
00132
00133 protected:
00134
00135 void apply(const Vector<Scalar> & x,
00136 Vector<Scalar> & y) const {
00137 try {
00138 this->export_apply(G,x,y);
00139 y.linComb(-1.0,d);
00140 }
00141 catch (RVLException & e) {
00142 e<<"\ncalled from ResidualOperator::apply\n";
00143 throw e;
00144 }
00145 }
00146
00147 void applyDeriv(const Vector<Scalar> & x,
00148 const Vector<Scalar> & dx,
00149 Vector<Scalar> & dy) const {
00150 try {
00151 this->export_applyDeriv(G,x,dx,dy);
00152 }
00153 catch (RVLException & e) {
00154 e<<"\ncalled from ResidualOperator::applyDeriv\n";
00155 throw e;
00156 }
00157 }
00158
00159 void applyAdjDeriv(const Vector<Scalar> & x,
00160 const Vector<Scalar> & dy,
00161 Vector<Scalar> & dx) const {
00162 try {
00163 this->export_applyAdjDeriv(G,x,dy,dx);
00164 }
00165 catch (RVLException & e) {
00166 e<<"\ncalled from ResidualOperator::applyAdjDeriv\n";
00167 throw e;
00168 }
00169 }
00170
00171
00172 virtual Operator<Scalar> * clone() const {
00173 return new ResidualOperator<Scalar>(*this);
00174 }
00175
00176 public:
00178 ResidualOperator(Operator<Scalar> const & GG,
00179 Vector<Scalar> const & dd): d(dd), G(GG) {
00180 if (G.getRange() != d.getSpace()) {
00181 RVLException e;
00182 e<<"Error: ResidualOperator constructor\n";
00183 e<<"input vector not in range of operator\n";
00184 e<<"input vector:\n";
00185 d.write(e);
00186 e<<"operator:\n";
00187 G.write(e);
00188 throw e;
00189 }
00190 }
00191 ResidualOperator(ResidualOperator<Scalar> const & a): d(a.d), G(a.G) {}
00192 ~ResidualOperator() {}
00193
00195 const Space<Scalar> & getDomain() const { return G.getDomain(); }
00196 const Space<Scalar> & getRange() const { return G.getRange(); }
00197
00198 Scalar getMaxStep(const Vector<Scalar> & x,
00199 const Vector<Scalar> & dx) const {
00200 return G.getMaxStep(x,dx);
00201 }
00202
00203 ostream & write(ostream & str) const {
00204 str<<"Residual Operator"<<"\n";
00205 str<<"*** data vector:\n";
00206 d.write(str);
00207 str<<"*** operator:\n";
00208 G.write(str);
00209 return str;
00210 }
00211 };
00212
00222 template<class Scalar>
00223 class EuclideanForm: public Functional<Scalar> {
00224
00225 private:
00226
00227 const Space<Scalar> & sp;
00228 EuclideanForm();
00229
00230 protected:
00231
00232 void apply(const Vector<Scalar> & x,
00233 Scalar & val) const {
00234 try {
00235 if (sp != x.getSpace()) {
00236 RVLException e;
00237 e<<"Error: EuclideanForm::apply\n";
00238 e<<"input vector not in domain\n";
00239 throw e;
00240 }
00241 val = 0.5*x.inner(x);
00242 }
00243 catch(RVLException & e) {
00244 e<<"\ncalled from EuclideanForm::apply\n";
00245 throw e;
00246 }
00247 }
00248
00249 void applyGradient(const Vector<Scalar> & x,
00250 Vector<Scalar> & g) const {
00251 try {
00252 if (sp != x.getSpace()) {
00253 RVLException e;
00254 e<<"Error: EuclideanForm::applyGradient\n";
00255 e<<"input vector not in domain\n";
00256 throw e;
00257 }
00258 g.copy(x);
00259 }
00260 catch(RVLException & e) {
00261 e<<"\ncalled from EuclideanForm::applyGradient\n";
00262 throw e;
00263 }
00264 }
00265
00266 void applyHessian(const Vector<Scalar> & x,
00267 const Vector<Scalar> & delx,
00268 Vector<Scalar> & dely) const {
00269 try {
00270 if (sp != delx.getSpace()) {
00271 RVLException e;
00272 e<<"Error: EuclideanForm::applyHessian\n";
00273 e<<"input vector not in domain\n";
00274 throw e;
00275 }
00276 dely.copy(delx);
00277 }
00278 catch (RVLException & e) {
00279 e<<"\ncalled from EuclideanForm::applyGradient\n";
00280 throw e;
00281 }
00282 }
00283
00284
00285 virtual Functional<Scalar> * clone() const {
00286 return new EuclideanForm<Scalar>(*this);
00287 }
00288
00289 public:
00290
00291 EuclideanForm(const Space<Scalar> & _sp): sp(_sp) { testRealOnly<Scalar>(); }
00292 EuclideanForm(const EuclideanForm<Scalar> & q): sp(q.sp) { testRealOnly<Scalar>(); }
00293 ~EuclideanForm() {}
00294
00295
00296 const Space<Scalar> & getDomain() const { return sp; }
00297
00298 ostream & write(ostream & str) const {
00299 str<<"Euclidean quadratic form - length squared\n";
00300 return str;
00301 }
00302 };
00303
00313 template<class Scalar>
00314 class QuadraticForm: public Functional<Scalar> {
00315
00316 private:
00317
00318 const LinearOp<Scalar> & A;
00319 mutable Vector<Scalar> r;
00320 mutable bool applied;
00321
00322 QuadraticForm();
00323
00324 protected:
00325
00326 void apply(const Vector<Scalar> & x,
00327 Scalar & val) const {
00328 try {
00329 if (!applied) {
00330 A.applyOp(x,r);
00331 applied = true;
00332 }
00333 val = 0.5*r.normsq();;
00334 }
00335 catch(RVLException & e) {
00336 e<<"\ncalled from QuadraticForm::apply\n";
00337 throw e;
00338 }
00339 }
00340
00341 void applyGradient(const Vector<Scalar> & x,
00342 Vector<Scalar> & g) const {
00343 try {
00344 if (!applied) {
00345 A.applyOp(x,r);
00346 applied = true;
00347 }
00348 A.applyAdjOp(r,g);
00349 }
00350 catch(RVLException & e) {
00351 e<<"\ncalled from QuadraticForm::applyGradient\n";
00352 throw e;
00353 }
00354 }
00355
00356 void applyHessian(const Vector<Scalar> & x,
00357 const Vector<Scalar> & delx,
00358 Vector<Scalar> & dely) const {
00359 try {
00360 Vector<Scalar> z(A.getRange());
00361 A.applyOp(delx,z);
00362 A.applyAdjOp(z,dely);
00363 }
00364 catch (RVLException & e) {
00365 e<<"\ncalled from QuadraticForm::applyGradient\n";
00366 throw e;
00367 }
00368 }
00369
00370
00371 virtual Functional<Scalar> * clone() const {
00372 return new QuadraticForm<Scalar>(*this);
00373 }
00374
00375 public:
00376
00377 QuadraticForm(const LinearOp<Scalar> & AA)
00378 : A(AA), r(A.getDomain()), applied(false) { testRealOnly<Scalar>(); }
00379
00380 QuadraticForm(const QuadraticForm<Scalar> & q)
00381 : A(q.A), r(A.getDomain()), applied(false) { testRealOnly<Scalar>(); }
00382
00383 ~QuadraticForm() {}
00384
00385 const Space<Scalar> & getDomain() const { return A.getDomain(); }
00386
00387 ostream & write(ostream & str) const {
00388 str<<"Quadratic form with operator\n";
00389 A.write(str);
00390 return str;
00391 }
00392 };
00393
00403 template<class Scalar>
00404 class ShiftedQuadraticForm: public Functional<Scalar> {
00405
00406 private:
00407
00408 const LinearOp<Scalar> & A;
00409 const Vector<Scalar> & b;
00410 mutable Vector<Scalar> r;
00411 mutable bool applied;
00412
00413 ShiftedQuadraticForm();
00414
00415 protected:
00416
00417 void apply(const Vector<Scalar> & x,
00418 Scalar & val) const {
00419 try {
00420 if (!applied) {
00421 A.applyOp(x,r);
00422 r.linComb(-1.0,b);
00423 applied = true;
00424 }
00425 val = 0.5*r.normsq();
00426 }
00427 catch(RVLException & e) {
00428 e<<"\ncalled from QuadraticForm::apply\n";
00429 throw e;
00430 }
00431 }
00432
00433 void applyGradient(const Vector<Scalar> & x,
00434 Vector<Scalar> & g) const {
00435 try {
00436 if (!applied) {
00437 A.applyOp(x,r);
00438 r.linComb(-1.0,b);
00439 applied = true;
00440 }
00441 A.applyAdjOp(r,g);
00442 }
00443 catch(RVLException & e) {
00444 e<<"\ncalled from QuadraticForm::applyGradient\n";
00445 throw e;
00446 }
00447 }
00448
00449 void applyHessian(const Vector<Scalar> & x,
00450 const Vector<Scalar> & delx,
00451 Vector<Scalar> & dely) const {
00452 try {
00453 Vector<Scalar> z(A.getRange());
00454 A.applyOp(delx,z);
00455 A.applyAdjOp(z,dely);
00456 }
00457 catch (RVLException & e) {
00458 e<<"\ncalled from QuadraticForm::applyGradient\n";
00459 throw e;
00460 }
00461 }
00462
00463
00464 virtual Functional<Scalar> * clone() const {
00465 return new ShiftedQuadraticForm<Scalar>(*this);
00466 }
00467
00468 public:
00469
00470 ShiftedQuadraticForm(const LinearOp<Scalar> & AA,
00471 const Vector<Scalar> & bb)
00472 : A(AA), b(bb), r(A.getRange()), applied(false) { testRealOnly<Scalar>(); }
00473
00474 ShiftedQuadraticForm(const ShiftedQuadraticForm<Scalar> & q)
00475 : A(q.A), b(q.b), r(A.getRange()), applied(false) { testRealOnly<Scalar>(); }
00476
00477 ~ShiftedQuadraticForm() { }
00478
00479 const Space<Scalar> & getDomain() const { return A.getDomain(); }
00480
00481 ostream & write(ostream & str) const {
00482 str<<"ShiftedQuadratic form with linear operator\n";
00483 A.write(str);
00484 str<<"and shift vector\n";
00485 b.write(str);
00486 return str;
00487 }
00488 };
00489
00507 template<class Scalar>
00508 class LeastSquaresFcnlGN: public Functional<Scalar> {
00509
00510 private:
00511
00512 EuclideanForm<Scalar> sql;
00513 FcnlOpComp<Scalar> work;
00514
00515
00516 LeastSquaresFcnlGN();
00517
00518 protected:
00519
00520 void apply(Vector<Scalar> const & x,
00521 Scalar & val) const {
00522 try {
00523 this->export_apply(work,x,val);
00524 }
00525 catch (RVLException e) {
00526 e<<"\ncalled from LeastSquaresFcnlGN::apply\n";
00527 throw e;
00528 }
00529 }
00530 void applyGradient(Vector<Scalar> const & x,
00531 Vector<Scalar> & g) const {
00532 try {
00533 this->export_applyGradient(work,x,g);
00534 }
00535 catch (RVLException e) {
00536 e<<"\ncalled from LeastSquaresFcnlGN::applyGradient\n";
00537 throw e;
00538 }
00539 }
00540 void applyHessian(Vector<Scalar> const & x,
00541 Vector<Scalar> const & dx,
00542 Vector<Scalar> & dy) const {
00543 try {
00544 this->export_applyHessian(work,x,dx,dy);
00545 }
00546 catch (RVLException e) {
00547 e<<"\ncalled from LeastSquaresFcnlGN::applyHessian\n";
00548 throw e;
00549 }
00550 }
00551
00552 virtual Functional<Scalar> * clone() const {
00553 return new LeastSquaresFcnlGN<Scalar>(*this);
00554 }
00555
00556 public:
00557
00559 LeastSquaresFcnlGN(Operator<Scalar> const & op)
00560 : sql(op.getRange()), work(sql,op) {
00561 testRealOnly<Scalar>();
00562 }
00564 LeastSquaresFcnlGN(const LeastSquaresFcnlGN<Scalar> & J)
00565 : sql(J.sql), work(J.work) { testRealOnly<Scalar>(); }
00566
00567
00568 virtual ~LeastSquaresFcnlGN() {}
00569
00570 Space<Scalar> const & getDomain() const { return work.getDomain(); }
00571
00572 Scalar getMaxStep(const Vector<Scalar> & x,
00573 const Vector<Scalar> & dx) const {
00574 try {
00575 return work.getMaxStep(x,dx);
00576 }
00577 catch (RVLException & e) {
00578 e<<"\ncalled from LeastSquaresFcnlGN::getMaxStep\n";
00579 throw e;
00580 }
00581 }
00582
00583 ostream & write(ostream & str) const {
00584 str<<"Least-Squares Gauss-Newton functional: expressed as = \n";
00585 work.write(str);
00586 return str;
00587 }
00588 };
00589
00607 template<class Scalar>
00608 class StdLeastSquaresFcnlGN: public Functional<Scalar> {
00609
00610 private:
00611
00612
00613 EuclideanForm<Scalar> sql;
00614 ResidualOperator<Scalar> res;
00615 FcnlOpComp<Scalar> work;
00616
00617
00618 StdLeastSquaresFcnlGN();
00619
00620 protected:
00621
00622 void apply(Vector<Scalar> const & x,
00623 Scalar & val) const {
00624 try {
00625 this->export_apply(work,x,val);
00626 }
00627 catch (RVLException e) {
00628 e<<"\ncalled from StdLeastSquaresFcnlGN::apply\n";
00629 throw e;
00630 }
00631 }
00632 void applyGradient(Vector<Scalar> const & x,
00633 Vector<Scalar> & g) const {
00634 try {
00635 this->export_applyGradient(work,x,g);
00636 }
00637 catch (RVLException e) {
00638 e<<"\ncalled from StdLeastSquaresFcnlGN::applyGradient\n";
00639 throw e;
00640 }
00641 }
00642 void applyHessian(Vector<Scalar> const & x,
00643 Vector<Scalar> const & dx,
00644 Vector<Scalar> & dy) const {
00645 try {
00646 this->export_applyHessian(work,x,dx,dy);
00647 }
00648 catch (RVLException e) {
00649 e<<"\ncalled from StdLeastSquaresFcnlGN::applyHessian\n";
00650 throw e;
00651 }
00652 }
00653
00654 virtual Functional<Scalar> * clone() const {
00655 return new StdLeastSquaresFcnlGN<Scalar>(*this);
00656 }
00657
00658 public:
00659
00661 StdLeastSquaresFcnlGN(Operator<Scalar> const & oper,
00662 Vector<Scalar> const & d)
00663 : sql(oper.getRange()),
00664 res(oper,d),
00665 work(sql,res) {
00666 testRealOnly<Scalar>();
00667 }
00668
00670 StdLeastSquaresFcnlGN(const StdLeastSquaresFcnlGN<Scalar> & JJ)
00671 : sql(JJ.sql),
00672 res(JJ.res),
00673 work(JJ.work) {
00674 testRealOnly<Scalar>();
00675 }
00676
00677
00678 virtual ~StdLeastSquaresFcnlGN() {}
00679
00680 Space<Scalar> const & getDomain() const { return work.getDomain(); }
00681
00682 Scalar getMaxStep(const Vector<Scalar> & x,
00683 const Vector<Scalar> & dx) const {
00684 try {
00685 return res.getMaxStep(x,dx);
00686 }
00687 catch (RVLException & e) {
00688 e<<"\ncalled from StdLeastSquaresFcnlGN::getMaxStep\n";
00689 throw e;
00690 }
00691 }
00692
00693 ostream & write(ostream & str) const {
00694 str<<"Standard Least-Squares Gauss-Newton functional\n";
00695 str<<"based on ResidualOperator\n";
00696 res.write(str);
00697 return str;
00698 }
00699 };
00700
00722 template<class Scalar>
00723 class RegLeastSquaresFcnlGN: public Functional<Scalar> {
00724
00725 private:
00726
00727
00728 RegLeastSquaresFcnlGN();
00729 StdLeastSquaresFcnlGN<Scalar> f1;
00730 ShiftedQuadraticForm<Scalar> f2;
00731 Scalar lambda;
00732 LinCombFunctional<Scalar> work;
00733
00734 protected:
00735
00736 void apply(Vector<Scalar> const & x,
00737 Scalar & val) const {
00738 try {
00739 this->export_apply(work,x,val);
00740 }
00741 catch (RVLException e) {
00742 e<<"\ncalled from RegLeastSquaresFcnlGN::apply\n";
00743 throw e;
00744 }
00745 }
00746 void applyGradient(Vector<Scalar> const & x,
00747 Vector<Scalar> & g) const {
00748 try {
00749 this->export_applyGradient(work,x,g);
00750 }
00751 catch (RVLException e) {
00752 e<<"\ncalled from RegLeastSquaresFcnlGN::applyGradient\n";
00753 throw e;
00754 }
00755 }
00756 void applyHessian(Vector<Scalar> const & x,
00757 Vector<Scalar> const & dx,
00758 Vector<Scalar> & dy) const {
00759 try {
00760 this->export_applyHessian(work,x,dx,dy);
00761 }
00762 catch (RVLException e) {
00763 e<<"\ncalled from RegLeastSquaresFcnlGN::applyHessian\n";
00764 throw e;
00765 }
00766 }
00767
00768 virtual Functional<Scalar> * clone() const {
00769 return new RegLeastSquaresFcnlGN<Scalar>(*this);
00770 }
00771
00772 public:
00773
00775 RegLeastSquaresFcnlGN(Operator<Scalar> const & oper,
00776 LinearOp<Scalar> const & reg,
00777 Vector<Scalar> const & d,
00778 Vector<Scalar> const & r0,
00779 Scalar lam)
00780 : f1(oper,d), f2(reg,r0), lambda(lam), work(1.0,f1,lam,f2) {
00781 try {
00782 testRealOnly<Scalar>();
00783 }
00784 catch (RVLException & e) {
00785 e<<"\ncalled from RegLeastSquaresFcnlGN constructor\n";
00786 throw e;
00787 }
00788 }
00789
00791 RegLeastSquaresFcnlGN(const RegLeastSquaresFcnlGN<Scalar> & rls)
00792 : f1(rls.f1), f2(rls.f2), lambda(rls.lambda), work(rls.work) {
00793 testRealOnly<Scalar>();
00794 }
00795
00796
00797 virtual ~RegLeastSquaresFcnlGN() {}
00798
00799 Space<Scalar> const & getDomain() const { return work.getDomain(); }
00800
00801 ostream & write(ostream & str) const {
00802 str<<"Regularized Least-Squares Gauss-Newton functional. realized as\n";
00803 work.write(str);
00804 return str;
00805 }
00806 };
00807
00808
00809
00810
00817 template<typename Scalar>
00818 class FunctionalBd: public Functional<Scalar> {
00819
00820 private:
00821
00822
00823 Functional<Scalar> * f;
00824 RVL::Oracle<Vector<Scalar> > const & b;
00825
00826 protected:
00827
00828 void apply(const Vector<Scalar> & x,
00829 Scalar & val) const {
00830 try {
00831 val=numeric_limits<Scalar>::max();
00832 if (!b.isFeasible(x)) return;
00833 RVL::Functional<Scalar>::export_apply(*f,x,val);
00834 }
00835 catch (RVLException & e) {
00836 val=numeric_limits<Scalar>::max();
00837 }
00838 }
00839
00840 void applyGradient(const Vector<Scalar> & x,
00841 Vector<Scalar> & g) const {
00842 try {
00843 if (!b.isFeasible(x)) {
00844 RVLException e;
00845 e<<"Error: FuncionalBd::applyGradient\n";
00846 e<<"infeasible point\n";
00847 throw e;
00848 }
00849 RVL::Functional<Scalar>::export_applyGradient(*f,x,g);
00850 }
00851 catch (RVLException & e) {
00852 e<<"\ncalled from FunctionalBd::applyGradient\n";
00853 throw e;
00854 }
00855 }
00856
00857 void applyHessian(const Vector<Scalar> & x,
00858 const Vector<Scalar> & dx,
00859 Vector<Scalar> & dy) const {
00860 try {
00861 if (!b.isFeasible(x)) {
00862 RVLException e;
00863 e<<"Error: FuncionalBd::applyHessian\n";
00864 e<<"infeasible point\n";
00865 throw e;
00866 }
00867 RVL::Functional<Scalar>::export_applyHessian(*f,x,dx,dy);
00868 }
00869 catch (RVLException & e) {
00870 e<<"\ncalled from FunctionalBd::applyHessian\n";
00871 throw e;
00872 }
00873
00874 }
00875
00876
00877 virtual Functional<Scalar> * clone() const {
00878 return new FunctionalBd(*this);
00879 }
00880
00881 public:
00882
00883 FunctionalBd(Functional<Scalar> const & _f,
00884 RVL::Oracle<Vector<Scalar> > const & _b)
00885 : f(NULL), b(_b) { testRealOnly<Scalar>(); this->export_clone(_f,&f); }
00886
00887 FunctionalBd(FunctionalBd<Scalar> const & a)
00888 : f(NULL), b(a.b) { testRealOnly<Scalar>(); this->export_clone(*(a.f),&f); }
00889
00890 ~FunctionalBd() { if (f) delete f; }
00891
00892 Space<Scalar> const & getDomain() const { return f->getDomain(); }
00893 Scalar getMaxStep(Vector<Scalar> const & x,
00894 Vector<Scalar> const & dx) const {
00895 return f->getMaxStep(x,dx);
00896 }
00897
00898 Functional<Scalar> const & getFunctional() const { return *f; }
00899
00900 ostream & write(ostream & str) const {
00901 str<<"FunctionalBd: functional returning infty at infeasible points\n";
00902 str<<"data member Functional:\n";
00903 f->write(str);
00904 str<<"bounds test:\n";
00905 b.write(str);
00906 return str;
00907 }
00908
00909 };
00910
00914 template<typename Scalar>
00915 class ULBoundsTest: public RVL::Oracle<Vector<Scalar> > {
00916
00917 private:
00918 Vector<Scalar> const & ub;
00919 Vector<Scalar> const & lb;
00920 FunctionObjectScalarRedn<Scalar> & minfo;
00921
00922 public:
00923
00924 ULBoundsTest(Vector<Scalar> const & _lb,
00925 Vector<Scalar> const & _ub,
00926 FunctionObjectScalarRedn<Scalar> & _minfo)
00927 : ub(_ub), lb(_lb), minfo(_minfo) {
00928 testRealOnly<Scalar>();
00929 if (lb.getSpace() != ub.getSpace()) {
00930 RVLException e;
00931 e<<"Error: ULBoundsTest constructor\n";
00932 e<<"upper, lower bound Vectors not in same Space\n";
00933 e<<"lower bd vector:\n";
00934 lb.write(e);
00935 e<<"upper bd vector:\n";
00936 ub.write(e);
00937 throw e;
00938 }
00939 minfo.setValue();
00940 }
00941
00942 ULBoundsTest(ULBoundsTest<Scalar> const & t)
00943 : lb(t.lb), ub(t.ub), minfo(t.minfo) {
00944 testRealOnly<Scalar>();
00945 minfo.setValue();
00946 }
00947
00948 ~ULBoundsTest() {}
00949
00950 bool isFeasible(Vector<Scalar> const & x) const {
00951
00952
00953 try {
00954 if (x.getSpace() != lb.getSpace()) return false;
00955 Vector<Scalar> work(x.getSpace());
00956 Components<Scalar> cwork(work);
00957
00958 float one = ScalarFieldTraits<float>::One();
00959 float zip = ScalarFieldTraits<float>::Zero();
00960 int size = cwork.getSize();
00961 float valmin = zip;
00962 minfo.setValue(zip);
00963 work.copy(x);
00964 work.linComb(one,ub,-one);
00965 for(int i=0; i< size; i++) {
00966 cwork[i].eval(minfo);
00967
00968 if (minfo.getValue() < valmin)
00969 valmin = minfo.getValue();
00970 }
00971
00972 work.copy(x);
00973 work.linComb(-one,lb);
00974 for(int i=0; i<size; i++){
00975 cwork[i].eval(minfo);
00976
00977 if (minfo.getValue() < valmin)
00978 valmin = minfo.getValue();
00979 }
00980
00981 if (valmin<zip) return false;
00982
00983 return true;
00984 }
00985 catch (RVLException & e) {
00986 return false;
00987 }
00988 }
00989
00990 ostream & write(ostream & str) const {
00991 str<<"Standard upper/lower bounds test\n";
00992 str<<"Lower bound vector:\n";
00993 lb.write(str);
00994 str<<"upper bound vector:\n";
00995 ub.write(str);
00996 str<<"min function:\n";
00997 minfo.write(str);
00998 return str;
00999 }
01000 };
01001 }
01002 #endif