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_FUNC
00034 #define __RVL_FUNC
00035
00036 #include "op.hh"
00037 #include "blockop.hh"
00038
00039 namespace RVL {
00040
00041 template<class Scalar>
00042 class FunctionalEvaluation;
00043
00044 template<class Scalar>
00045 class Functional;
00046
00047 template<class Scalar>
00048 class FcnlOpComp;
00049
00050 template<class Scalar>
00051 class LinCombFunctional;
00052
00098 template<class Scalar>
00099 class Functional: public Writeable {
00100
00101 friend class FunctionalEvaluation<Scalar>;
00102 friend class FcnlOpComp<Scalar>;
00103 friend class LinCombFunctional<Scalar>;
00104
00105 protected:
00106
00113 virtual void apply(const Vector<Scalar> & x,
00114 Scalar & val) const = 0;
00115
00117 virtual void applyGradient(const Vector<Scalar> & x,
00118 Vector<Scalar> & g) const = 0;
00119
00121 virtual void applyHessian(const Vector<Scalar> & x,
00122 const Vector<Scalar> & dx,
00123 Vector<Scalar> & dy) const = 0;
00124
00129 void export_apply(Functional<Scalar> const & f,
00130 const Vector<Scalar> & x,
00131 Scalar & val) const {
00132 f.apply(x,val);
00133 }
00134
00135 void export_applyGradient(Functional<Scalar> const & f,
00136 const Vector<Scalar> & x,
00137 Vector<Scalar> & g) const {
00138 f.applyGradient(x,g);
00139 }
00140
00141 void export_applyHessian(Functional<Scalar> const & f,
00142 const Vector<Scalar> & x,
00143 const Vector<Scalar> & dx,
00144 Vector<Scalar> & dy) const {
00145 f.applyHessian(x,dx,dy);
00146 }
00147
00154 #ifndef RVL_OPERATOR_NEW_ENABLED
00155 void * operator new(size_t size) {
00156 void * ptr;
00157 ptr = (void *) ::new unsigned char[size];
00158 return ptr;
00159 }
00160 #endif
00161
00167 virtual Functional<Scalar> * clone() const = 0;
00168
00169 void export_clone(Functional<Scalar> const & fref,
00170 Functional<Scalar> ** f) const {
00171 try {
00172 if (*f) {
00173 RVLException e;
00174 e<<"Error: Functional::export_clone\n";
00175 e<<"cannot clone to a non-null pointer\n";
00176 throw e;
00177 }
00178 *f = fref.clone();
00179 }
00180 catch (RVLException & e) {
00181 e<<"\ncalled from Functional::export_clone\n";
00182 throw e;
00183 }
00184 }
00185
00186 public:
00187
00188 Functional() {}
00189
00190 Functional(const Functional<Scalar> &) {}
00191
00192 virtual ~Functional() {}
00193
00194
00195 virtual const Space<Scalar> & getDomain() const = 0;
00196
00207 virtual Scalar getMaxStep(const Vector<Scalar> & x,
00208 const Vector<Scalar> & dx) const {
00209 return numeric_limits<Scalar>::max();
00210 }
00211
00237 };
00238
00239 template<class Scalar>
00240 class FunctionalProductDomainEvaluation;
00241
00243 template<class Scalar>
00244 class FunctionalProductDomain: public Functional<Scalar> {
00245
00246 friend class FunctionalEvaluation<Scalar>;
00247 friend class FunctionalProductDomainEvaluation<Scalar>;
00248
00249 protected:
00250
00255 virtual void applyPartialGradient(int i,
00256 const Vector<Scalar> & x,
00257 Vector<Scalar> & g) const = 0;
00258
00259 void export_applyPartialGradient(FunctionalProductDomain<Scalar> const & f,
00260 int i,
00261 const Vector<Scalar> & x,
00262 Vector<Scalar> & g) const {
00263 try {
00264 f.applyPartialGradient(i,x,g);
00265 }
00266 catch (RVLException & e) {
00267 e<<"\ncalled from export_applyPartialGradient\n";
00268 throw e;
00269 }
00270 }
00271
00275 virtual void applyGradient(const Vector<Scalar> & x,
00276 Vector<Scalar> & g) const {
00277 try {
00278 Components<Scalar> cx(x);
00279 applyPartialGradient(0,cx[0],g);
00280 Vector<Scalar> tmp(g);
00281 for (int i=1;i<cx.getSize();i++) {
00282 applyPartialGradient(i,cx[i],tmp);
00283 g.linComb(ScalarFieldTraits<Scalar>::One(),tmp);
00284 }
00285 }
00286 catch (RVLException & e) {
00287 e<<"\ncalled from FunctionalProductDomain::applyGradient\n";
00288 throw e;
00289 }
00290 }
00291
00300 virtual void applyPartialHessian(int i,
00301 int j,
00302 const Vector<Scalar> & x,
00303 const Vector<Scalar> & dxj,
00304 Vector<Scalar> & dxi) const = 0;
00305
00306 void export_applyPartialHessian(FunctionalProductDomain<Scalar> const & f,
00307 int i,
00308 int j,
00309 const Vector<Scalar> & x,
00310 const Vector<Scalar> & dxj,
00311 Vector<Scalar> & dxi) const {
00312 try {
00313 f.applyPartialHessian(i,j,x,dxj,dxi);
00314 }
00315 catch (RVLException & e) {
00316 e<<"\ncalled from export_applyPartialHessian\n";
00317 throw e;
00318 }
00319 }
00320
00325 virtual void applyHessian(const Vector<Scalar> & x,
00326 const Vector<Scalar> & yin,
00327 Vector<Scalar> & yout) const {
00328 try {
00329 Components<Scalar> cyin(yin);
00330 Components<Scalar> cyout(yout);
00331 for (int i=0; i<cyin.getSize(); i++) {
00332 cyout[i].zero();
00333 Vector<Scalar> tmp(this->getProductDomain()[i]);
00334 for (int j=0; j<cyin.getSize(); j++) {
00335 applyPartialHessian(i,j,x,cyin[j],tmp);
00336 cyout[i].linComb(ScalarFieldTraits<Scalar>::One(),tmp);
00337 }
00338 }
00339 }
00340 catch (RVLException & e) {
00341 e<<"\ncalled from FunctionalProductDomain::applyHessian\n";
00342 throw e;
00343 }
00344 }
00345 virtual FunctionalProductDomain<Scalar> * clonePD() const = 0;
00346 Functional<Scalar> * clone() const { return clonePD(); }
00347
00348 public:
00349
00350
00351 FunctionalProductDomain() {}
00352
00353 FunctionalProductDomain(const FunctionalProductDomain<Scalar> &) {}
00354
00355 virtual ~FunctionalProductDomain() {}
00356
00359 const Space<Scalar> & getDomain() const {
00360 return getProductDomain();
00361 }
00366 virtual const ProductSpace<Scalar> & getProductDomain() const = 0;
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00410 };
00411
00412 template<class Scalar>
00413 class HessianEvaluation;
00414
00415 template<class Scalar>
00416 class PartialHessianEvaluation;
00417
00423 template<class Scalar>
00424 class FunctionalEvaluation: public Writeable {
00425
00426 friend class HessianEvaluation<Scalar>;
00427 friend class PartialHessianEvaluation<Scalar>;
00428 friend class FcnlOpComp<Scalar>;
00429 typedef typename ScalarFieldTraits<Scalar>::AbsType NormRetType;
00430
00431 private:
00432
00433
00434 const Functional<Scalar> & fref;
00435 WatchedVecRef<Scalar> wx;
00436 mutable Functional<Scalar> * f;
00437
00438 mutable Scalar val;
00439 mutable bool applied;
00440 mutable Vector<Scalar> grad;
00441 mutable bool gapplied;
00442 mutable NormRetType gnorm;
00443 mutable bool gnormapplied;
00444
00445
00446 FunctionalEvaluation();
00447
00448 void reset() const {
00449 try {
00450 if (f) delete f;
00451 f = fref.clone();
00452 applied=false;
00453 gapplied=false;
00454 gnormapplied=false;
00455 }
00456 catch (RVLException & e) {
00457 e<<"\ncalled from FunctionalEvaluation::reset\n";
00458 throw e;
00459 }
00460 }
00461
00462 protected:
00463
00464
00465 Components<Scalar> cg;
00466 HessianEvaluation<Scalar> hess;
00467
00468
00469 void applyHessian(const Vector<Scalar> & yin,
00470 Vector<Scalar> & yout) const {
00471 try {
00472 if (wx.update()) reset();
00473 f->applyHessian(wx.get(),yin,yout);
00474 }
00475 catch (RVLException & e) {
00476 e<<"\ncalled from FunctionalEvaluation::applyHessian()\n";
00477 throw e;
00478 }
00479 }
00480
00488 const ProductSpace<Scalar> & getProductDomain() const {
00489
00490 try {
00491 const FunctionalProductDomain<Scalar> & pf =
00492 dynamic_cast<const FunctionalProductDomain<Scalar> &>(fref);
00493 return pf.getProductDomain();
00494 }
00495 catch (bad_cast) {
00496 RVLException e;
00497 e<<"Error: FunctionalEvaluation::getProductDomain\n";
00498 e<<"referenced Functional does not have ProductSpace domain\n";
00499 throw e;
00500 }
00501 catch (RVLException & e) {
00502 e<<"\ncalled from FunctionalEvaluation::getProductDomain\n";
00503 throw e;
00504 }
00505 }
00506
00507
00508 Vector<Scalar> const & getPartialGradient(int i) const {
00509 try {
00510 if (wx.update()) reset();
00511 if (!gapplied) {
00512
00513 f->applyGradient(wx.get(),grad);
00514 gapplied=true;
00515
00516 }
00517 return cg[i];
00518 }
00519 catch (RVLException & e) {
00520 e<<"\ncalled from FunctionalEvaluation::getPartialGradient\n";
00521 throw e;
00522 }
00523 }
00524
00528 void applyPartialHessian(int i,
00529 int j,
00530 const Vector<Scalar> & dxi,
00531 Vector<Scalar> & dxj) const {
00532 try {
00533 if (wx.update()) reset();
00534 FunctionalProductDomain<Scalar> * pf = NULL;
00535 if ((pf = dynamic_cast<FunctionalProductDomain<Scalar> *>(f))) {
00536 pf->applyPartialHessian(i,j,wx.get(),dxi,dxj);
00537 }
00538 else {
00539 RVLException e;
00540 e<<"Error: FunctionalEvaluation::applyPartialHessian\n";
00541 e<<"referenced Functional does not have ProductSpace domain\n";
00542 e<<"so Hessian block structure not defined\n";
00543 throw e;
00544 }
00545 }
00546 catch (RVLException & e) {
00547 e<<"\ncalled from FunctionalEvaluation";
00548 e<<"::applyHessianBloack()\n";
00549 throw e;
00550 }
00551 }
00552
00559 #ifndef RVL_OPERATOR_NEW_ENABLED
00560 void * operator new(size_t size) {
00561 void * ptr;
00562 ptr = (void *) ::new unsigned char[size];
00563 return ptr;
00564 }
00565 #endif
00566
00567 public:
00568
00574 FunctionalEvaluation(const Functional<Scalar> & _f,
00575 const Vector<Scalar> & x)
00576 : fref(_f), wx(x), f(_f.clone()),
00577 applied(false), grad(fref.getDomain()),
00578 gapplied(false), gnormapplied(false),
00579 cg(grad), hess(*this)
00580 {
00581 grad.zero();
00582
00583 if (x.getSpace() != fref.getDomain()) {
00584 RVLException e;
00585 e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
00586 e<<"Error: FunctionalEvaluation constructor\n";
00587 e<<"-- input not in domain of Functional \n";
00588 e<<"**********************\n";
00589 e<<"*** this fnctnl: ***\n";
00590 e<<"**********************\n";
00591 fref.write(e);
00592 e<<"**********************\n";
00593 e<<"*** domain space: ***\n";
00594 e<<"**********************\n";
00595 fref.getDomain().write(e);
00596 e<<"**********************\n";
00597 e<<"*** input space: ***\n";
00598 e<<"**********************\n";
00599 x.getSpace().write(e);
00600 e<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
00601 throw e;
00602 }
00603
00604 }
00605
00606 FunctionalEvaluation(const FunctionalEvaluation<Scalar> & ev)
00607 : wx(ev.wx), f(ev.fref.clone()), fref(ev.fref),
00608 applied(false),
00609 grad(fref.getDomain()),
00610 cg(grad), gapplied(false), gnormapplied(false),
00611 hess(*this) { grad.zero(); }
00612
00613 virtual ~FunctionalEvaluation() {
00614 if (f) delete f;
00615 }
00616
00618 const Space<Scalar> & getDomain() const {
00619 try { return fref.getDomain(); }
00620 catch (RVLException & e) {
00621 e<<"\ncalled from FunctionalEvaluation::getDomain\n";
00622 throw e;
00623 }
00624 }
00625
00629 Scalar getMaxStep(const Vector<Scalar> & dx) const {
00630 const Vector<Scalar> & fruit = getPoint();
00631 return fref.getMaxStep(fruit,dx);
00632 }
00633
00635 Vector<Scalar> & getPoint() { return wx.get(); }
00636 Vector<Scalar> const & getPoint() const { return wx.get(); }
00637
00641 Scalar getValue() const {
00642 try {
00643 if (wx.update()) {
00644 reset();
00645 }
00646 if (!applied) {
00647 f->apply(wx.get(),val);
00648 applied = true;
00649 }
00650 return val;
00651 }
00652 catch (RVLException & e) {
00653 e<<"\ncalled from FunctionalEvaluation::getValue()\n";
00654 throw e;
00655 }
00656 }
00657
00663 Vector<Scalar> const & getGradient() const {
00664 try {
00665 if (wx.update()) {
00666 reset();
00667 }
00668 if (!gapplied) {
00669 grad.zero();
00670 f->applyGradient(wx.get(),grad);
00671 gapplied=true;
00672 }
00673 return grad;
00674 }
00675 catch (RVLException & e) {
00676 e<<"\ncalled from FunctionalEvaluation::getGradient\n";
00677 throw e;
00678 }
00679 }
00680
00686 Scalar getGradientNorm() const {
00687 try {
00688 if (wx.update()) {
00689 reset();
00690 }
00691 if (!gnormapplied) {
00692 gnorm = getGradient().norm();
00693 gnormapplied = true;
00694 }
00695 return gnorm;
00696 }
00697 catch (RVLException & e) {
00698 e<<"\ncalled from FunctionalEvaluation::getGradientNorm\n";
00699 throw e;
00700 }
00701 }
00702
00709 LinearOp<Scalar> const & getHessian() const { return hess; }
00710
00714 Functional<Scalar> const & getFunctional() const { return *f; }
00715
00716 ostream & write(ostream & str) const {
00717 str<<"Functional Evaluation:"<<endl;
00718 str<<" functional"<<endl;
00719 fref.write(str);
00720 str<<" evaluated at\n";
00721 wx.get().write(str);
00722 return str;
00723 }
00724 };
00725
00730 template<class Scalar>
00731 class HessianEvaluation: public BlockLinearOp<Scalar> {
00732
00733 private:
00734
00735 FunctionalEvaluation<Scalar> const & fx;
00736 StdProductSpace<Scalar> unique_dom;
00737
00738
00739 HessianEvaluation();
00740 HessianEvaluation(const HessianEvaluation<Scalar> & h)
00741 : fx(h.fx), unique_dom(h.unique_dom) {}
00742
00743 protected:
00744
00745 BlockLinearOp<Scalar> * cloneBlockLinearOp() const {
00746 return new HessianEvaluation<Scalar>(*this);
00747 }
00748
00749 LinearOp<Scalar> * clone() const {
00750 return cloneBlockLinearOp();
00751 }
00752
00753 void apply(int i, int j,
00754 const Vector<Scalar> & xj,
00755 Vector<Scalar> & yi) const {
00756 try {
00757 fx.applyPartialHessian(i,j,xj,yi);
00758 }
00759 catch (RVLException & e) {
00760 if (i != 0 || j != 0) {
00761 RVLException e;
00762 e<<"Error: HessianEvaluation::apply(i,j,...)\n";
00763 e<<" eval not product domain - i="<<i<<" j="<<j<<" not allowed\n";
00764 e<<" must both be = 0\n";
00765 throw e;
00766 }
00767 fx.applyHessian(xj,yi);
00768 }
00769 }
00770
00771
00772 void applyAdj(int i, int j,
00773 const Vector<Scalar> & yi,
00774 Vector<Scalar> & xj) const {
00775 try {
00776 fx.applyPartialHessian(j,i,yi,xj);
00777 }
00778 catch (RVLException & e) {
00779 if (i != 0 || j != 0) {
00780 RVLException e;
00781 e<<"Error: HessianEvaluation::applyAdj(i,j,...)\n";
00782 e<<" eval not product domain - i="<<i<<" j="<<j<<" not allowed\n";
00783 e<<" must both be = 0\n";
00784 throw e;
00785 }
00786 fx.applyHessian(yi,xj);
00787 }
00788 }
00789
00790 public:
00791
00792 HessianEvaluation(FunctionalEvaluation<Scalar> const & _fx)
00793 : fx(_fx),
00794 unique_dom(fx.getDomain())
00795 {}
00796 ~HessianEvaluation() {}
00797
00798
00799 const Space<Scalar> & getDomain() const { return fx.getDomain(); }
00800 const ProductSpace<Scalar> & getProductDomain() const {
00801 try {
00802 return fx.getProductDomain();
00803 }
00804 catch (RVLException & e) {
00805 return unique_dom;
00806 }
00807 }
00808
00809
00810
00811
00812
00813
00814
00815
00816 const Space<Scalar> & getRange() const { return fx.getDomain(); }
00817 const ProductSpace<Scalar> & getProductRange() const {
00818 try {
00819 return fx.getProductDomain();
00820 }
00821 catch (RVLException & e) {
00822 return unique_dom;
00823 }
00824 }
00825
00826
00827
00828
00829
00830
00831
00832
00834 ostream & write(ostream & str) const {
00835 str<<"Hessian operator"<<endl;
00836 str<<"part of functional evaluation"<<endl;
00837 fx.write(str);
00838 return str;
00839 }
00840 };
00841
00845 template<class Scalar>
00846 class FunctionalProductDomainEvaluation:
00847 public FunctionalEvaluation<Scalar> {
00848
00849 private:
00850
00851
00852 FunctionalProductDomainEvaluation();
00853 FunctionalProductDomainEvaluation
00854 (const FunctionalProductDomainEvaluation<Scalar> &);
00855
00856 public:
00857
00858 FunctionalProductDomainEvaluation(FunctionalProductDomain<Scalar> & _f,
00859 const Vector<Scalar> & _x)
00860 : FunctionalEvaluation<Scalar>(_f,_x) {}
00861
00862 ~FunctionalProductDomainEvaluation() {}
00863
00864
00865
00867 Vector<Scalar> const & getPartialGradient(int i) const {
00868 try {
00869 return FunctionalEvaluation<Scalar>::getPartialGradient(i);
00870 }
00871 catch (RVLException & e) {
00872 e<<"\ncalled from FunctionalProductDomainEvaluation";
00873 e<<"::getPartialGradient\n";
00874 throw e;
00875 }
00876 }
00877
00881 const BlockLinearOp<Scalar> & getPartialHessian() const {
00882 return FunctionalEvaluation<Scalar>::hess; }
00883
00884 ostream & write(ostream & str) const {
00885 str<<"Functional Evaluation with Product Domain; as"<<"\n";
00886 return FunctionalEvaluation<Scalar>::write(str);
00887 }
00888 };
00889
00921 template<class Scalar>
00922 class LinCombFunctional: public Functional<Scalar> {
00923 private:
00924
00925 mutable std::vector<Functional<Scalar> *> fnvec;
00926 mutable std::vector<Scalar> wtvec;
00927 mutable bool applied;
00928
00930 void setNext(Scalar a, Functional<Scalar> & fn) {
00931 try {
00932 if (applied) {
00933 RVLException e;
00934 e<<"Error: LinCombFunctional::setNext\n";
00935 e<<"object already initialized - non-initialization method called\n";
00936 e<<"further alteration to object data not allowed\n";
00937 throw e;
00938 }
00939 if (fnvec.size() > 0) {
00940 if (fn.getDomain() != fnvec[0]->getDomain()) {
00941 RVLException e;
00942 e<<"Error: LinCombOp::setNext\n";
00943 e<<"domain of input Functional incompatible with reference (summand 0)\n";
00944 e<<"*** input Functional:\n";
00945 fn.write(e);
00946 e<<"*** reference Functional:\n";
00947 fnvec[0]->write(e);
00948 throw e;
00949 }
00950 }
00951 wtvec.push_back(a);
00952 fnvec.push_back(fn.clone());
00953 }
00954 catch (RVLException & e) {
00955 e<<"\ncalled from LinCombFunctional::setNext\n";
00956 throw e;
00957 }
00958 }
00959
00960 protected:
00961
00962 void apply(const Vector<Scalar> & x,
00963 Scalar & val) const {
00964 try {
00965
00966 if (fnvec.size()<1) {
00967 RVLException e;
00968 e<<"Error: LinCombFcnl::apply\n";
00969 e<<"not initialized\n";
00970 throw e;
00971 }
00972 applied = true;
00973 this->export_apply(*(fnvec[0]),x,val);
00974 val *= wtvec[0];
00975 if (fnvec.size() > 1) {
00976 Scalar tmp;
00977 for (int i=1; i<fnvec.size(); i++) {
00978 this->export_apply(*(fnvec[i]),x,tmp);
00979 val += wtvec[i]*tmp;
00980 }
00981 }
00982 }
00983 catch (RVLException & e) {
00984 e<<"\ncalled from LinCombFunctional::apply\n";
00985 throw e;
00986 }
00987 }
00988
00989 void applyGradient(const Vector<Scalar> & x,
00990 Vector<Scalar> & g) const {
00991 try {
00992 if (fnvec.size()<1) {
00993 RVLException e;
00994 e<<"Error: LinCombFcnl::applyGradient\n";
00995 e<<"not initialized\n";
00996 throw e;
00997 }
00998 applied = true;
00999 this->export_applyGradient(*(fnvec[0]),x,g);
01000 g.scale(wtvec[0]);
01001 if (fnvec.size() > 1) {
01002 Vector<Scalar> tmp(fnvec[0]->getDomain());
01003 for (int i=1; i<fnvec.size(); i++) {
01004 this->export_applyGradient(*(fnvec[i]),x,tmp);
01005 g.linComb(wtvec[i],tmp);
01006 }
01007 }
01008 }
01009 catch (RVLException & e) {
01010 e<<"\ncalled from LinCombFunctional::applyDeriv\n";
01011 throw e;
01012 }
01013 }
01014
01015 void applyHessian(const Vector<Scalar> & x,
01016 const Vector<Scalar> & dx,
01017 Vector<Scalar> & dy) const {
01018 try {
01019 if (fnvec.size()<1) {
01020 RVLException e;
01021 e<<"Error: LinCombOp::applyHessian\n";
01022 e<<"not initialized\n";
01023 throw e;
01024 }
01025 applied = true;
01026 this->export_applyHessian(*(fnvec[0]),x,dx,dy);
01027 dy.scale(wtvec[0]);
01028 if (fnvec.size() > 1) {
01029 Vector<Scalar> tmp(fnvec[0]->getDomain());
01030 for (int i=1; i<fnvec.size(); i++) {
01031 this->export_applyHessian(*(fnvec[i]),x,dx,tmp);
01032 dy.linComb(wtvec[i],tmp);
01033 }
01034 }
01035 }
01036 catch (RVLException & e) {
01037 e<<"\ncalled from LinCombFunctional::applyHessian\n";
01038 throw e;
01039 }
01040 }
01041
01042 Functional<Scalar> * clone() const {
01043 applied = true;
01044 return new LinCombFunctional<Scalar>(*this);
01045 }
01046
01047 public:
01048
01049 LinCombFunctional() {}
01050 LinCombFunctional(LinCombFunctional<Scalar> const & fn) {
01051 try {
01052 for (int i=0;i<fn.fnvec.size(); i++) {
01053 fnvec.push_back(fn.fnvec[i]->clone());
01054 wtvec.push_back(fn.wtvec[i]);
01055 }
01056 }
01057 catch (RVLException & e) {
01058 e<<"\ncalled from LinCombFunctional copy constructor\n";
01059 throw e;
01060 }
01061 }
01062
01063 LinCombFunctional(Scalar a1,const Functional<Scalar> & fn1,
01064 Scalar a2,const Functional<Scalar> & fn2)
01065 : fnvec(2), wtvec(2) {
01066 try {
01067 if (fn1.getDomain() != fn2.getDomain()) {
01068 RVLException e;
01069 e<<"Error: LinCombFunctional pair constructor\n";
01070 e<<"domains do not matcth\n";
01071 e<<"first Functional:\n";
01072 fn1.write(e);
01073 e<<"second Functional:\n";
01074 fn2.write(e);
01075 throw e;
01076 }
01077 fnvec[0] = fn1.clone();
01078 fnvec[1] = fn2.clone();
01079 wtvec[0] = a1;
01080 wtvec[1] = a2;
01081 }
01082 catch (RVLException & e) {
01083 e<<"\ncalled from LinCombFunctional pair constructor\n";
01084 throw e;
01085 }
01086 }
01087
01088 ~LinCombFunctional() {
01089 for (int i=0;i<fnvec.size(); i++) if (fnvec[i]) delete fnvec[i];
01090 }
01091
01093 const Space<Scalar> & getDomain() const {
01094 try {
01095 if (fnvec.size()<1) {
01096 RVLException e;
01097 e<<"Error: LinCombFunctional::getDomain\n";
01098 e<<"object not initialized\n";
01099 throw e;
01100 }
01101 applied = true;
01102 return fnvec[0]->getDomain();
01103 }
01104 catch (RVLException & e) {
01105 e<<"\ncalled from LinCombFunctional::getDomain\n";
01106 throw e;
01107 }
01108 }
01109
01110 ostream & write(ostream & str) const {
01111 str<<"LinCombFunctional: linear combination of scalar-valued functions\n";
01112 if (fnvec.size()<1) {
01113 str<<"not initialized\n";
01114 }
01115 else {
01116 for (int i=0;i<fnvec.size();i++) {
01117 str<<" --- Functional "<<i<<" with weight "<<wtvec[i]<<"\n";
01118 fnvec[i]->write(str);
01119 }
01120 }
01121 return str;
01122 }
01123 };
01124
01151 template<class Scalar, class DataType = Scalar>
01152 class StdFOFunctional : public Functional<Scalar> {
01153 protected:
01154 FunctionObjectScalarRedn<Scalar> & f;
01155 FunctionObject & gradf;
01156 FunctionObject & hessf;
01157 Space<Scalar> const & dom;
01158
01162 virtual void apply(const Vector<Scalar> & x,
01163 Scalar & val) const {
01164
01165 x.eval(f);
01166 val = f.getValue();
01167
01168
01169
01170
01171
01172
01173
01174 }
01175
01177 virtual void applyGradient(const Vector<Scalar> & x,
01178 Vector<Scalar> & g) const {
01179 g.eval(gradf,x);
01180 }
01181
01183 virtual void applyHessian(const Vector<Scalar> & x,
01184 const Vector<Scalar> & dx,
01185 Vector<Scalar> & dy) const {
01186 dy.eval(hessf,x,dx);
01187 }
01188
01194 virtual Functional<Scalar> * clone() const {
01195 return new StdFOFunctional<Scalar,DataType>(*this);
01196 }
01197
01198 StdFOFunctional();
01199 public:
01200
01203 StdFOFunctional( FunctionObjectScalarRedn<Scalar> & f_,
01204 FunctionObject & gradf_,
01205 FunctionObject & hessf_,
01206 const Space<Scalar> & dom_)
01207 : f(f_), gradf(gradf_), hessf(hessf_), dom(dom_) {}
01208
01209 StdFOFunctional( const StdFOFunctional<Scalar, DataType> & s)
01210 : f(s.f), gradf(s.gradf), hessf(s.hessf), dom(s.dom) {}
01211
01212 ~StdFOFunctional() {}
01213
01214
01215 virtual const Space<Scalar> & getDomain() const { return dom; }
01216
01217 virtual ostream & write(ostream & str) const {
01218 str << "StdFOFunctional with f = ";
01219 f.write(str);
01220 str << "\n gradf = ";
01221 gradf.write(str);
01222 str << "\n hessf = ";
01223 hessf.write(str);
01224 return str;
01225 }
01226 };
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01668 template<class Scalar>
01669 class NullFunctional : public Functional<Scalar> {
01670
01671 private:
01672
01673 Space<Scalar> const & dom;
01674
01675 NullFunctional();
01676
01677 protected:
01679 virtual void apply(const Vector<Scalar> & x,
01680 Scalar & val) const {
01681 val = 0;
01682 }
01683
01685 virtual void applyGradient(const Vector<Scalar> & x,
01686 Vector<Scalar> & g) const {
01687 g.zero();
01688 }
01689
01691 virtual void applyHessian(const Vector<Scalar> & x,
01692 const Vector<Scalar> & dx,
01693 Vector<Scalar> & dy) const {
01694 dy.zero();
01695 }
01696
01697 public:
01698
01699 NullFunctional(const Space<Scalar> & sp)
01700 : dom(sp) {}
01701
01702 NullFunctional(const Functional<Scalar> & _f)
01703 : dom(_f.getDomain()) {}
01704
01705 ~NullFunctional() { }
01706
01711 virtual Functional<Scalar> * clone() const {
01712 return new NullFunctional<Scalar>(*this);
01713 }
01714
01715
01716 virtual const Space<Scalar> & getDomain() const {
01717 return dom;
01718 }
01719
01720 virtual ostream & write(ostream & str) const {
01721 str << "NullFunctional on space\n ";
01722 dom.write(str);
01723 str << " \n";
01724 return str;
01725 }
01726 };
01727
01742 template<class Scalar>
01743 class FcnlOpComp: public Functional<Scalar> {
01744
01745 private:
01746
01747 Functional<Scalar> const & f;
01748 Operator<Scalar> const & op;
01749 mutable FunctionalEvaluation<Scalar> * fneval;
01750 mutable OperatorEvaluation<Scalar> * opeval;
01751
01752 protected:
01753
01754 void apply(const Vector<Scalar> & x,
01755 Scalar & val) const {
01756 try {
01757 if (!opeval)
01758 opeval = new OperatorEvaluation<Scalar>(op,x);
01759 if (!fneval)
01760 fneval = new FunctionalEvaluation<Scalar>(f,opeval->getValue());
01761
01762 val=fneval->getValue();
01763
01764
01765 }
01766 catch (RVLException & e) {
01767 e<<"\ncalled from FcnlOpComp::apply\n";
01768 throw e;
01769 }
01770 }
01771
01773 virtual void applyGradient(const Vector<Scalar> & x,
01774 Vector<Scalar> & g) const {
01775 try {
01776 if (!opeval)
01777 opeval = new OperatorEvaluation<Scalar>(op,x);
01778 if (!fneval)
01779 fneval = new FunctionalEvaluation<Scalar>(f,opeval->getValue());
01780 Vector<Scalar> const & gtmp = fneval->getGradient();
01781 opeval->getDeriv().applyAdjOp(gtmp,g);
01782
01783
01784 }
01785 catch (RVLException & e) {
01786 e<<"\ncalled from FcnlOpComp::applyGradient\n";
01787 throw e;
01788 }
01789 }
01790
01791 virtual void applyHessian(const Vector<Scalar> & x,
01792 const Vector<Scalar> & dx,
01793 Vector<Scalar> & dy) const {
01794
01795 try {
01796 if (!opeval)
01797 opeval = new OperatorEvaluation<Scalar>(op,x);
01798 if (!fneval)
01799 fneval = new FunctionalEvaluation<Scalar>(f,opeval->getValue());
01800 Vector<Scalar> tmp1(op.getRange());
01801 Vector<Scalar> tmp2(op.getRange());
01802 opeval->getDeriv().applyOp(dx,tmp1);
01803 fneval->getHessian().applyOp(tmp1,tmp2);
01804 opeval->getDeriv().applyAdjOp(tmp2,dy);
01805
01806
01807 }
01808 catch (RVLException & e) {
01809 e<<"\ncalled from FcnlOpComp::applyHessian\n";
01810 throw e;
01811 }
01812 }
01813
01819 virtual Functional<Scalar> * clone() const {
01820
01821 return new FcnlOpComp<Scalar>(*this);
01822 }
01823
01824 public:
01825
01826 FcnlOpComp(const Functional<Scalar> & fref,
01827 const Operator<Scalar> & opref)
01828 : f(fref), op(opref),
01829 fneval(NULL), opeval(NULL) {}
01830
01831 FcnlOpComp(const FcnlOpComp<Scalar> & c)
01832 : f(c.f), op(c.op), fneval(NULL), opeval(NULL) {
01833 #if 0
01834 cerr<<"\n\n***************************\n";
01835 cerr<<"NEW FCNLOPCOMP:\n";
01836 cerr<<"FCNL:\n";
01837 f.write(cerr);
01838 cerr<<"\nOP:\n";
01839 op.write(cerr);
01840 cerr<<"\n***************************\n\n";
01841 #endif
01842 }
01843
01844 ~FcnlOpComp() {
01845 if (fneval) delete fneval;
01846 if (opeval) delete opeval;
01847 }
01848
01850 const Space<Scalar> & getDomain() const {
01851 try {
01852 return op.getDomain();
01853 }
01854 catch (RVLException & e) {
01855 e<<"\ncalled from FcnlOpComp::getDomain\n";
01856 throw e;
01857 }
01858 }
01859
01860 virtual Scalar getMaxStep(const Vector<Scalar> & x,
01861 const Vector<Scalar> & dx) const {
01862 try {
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886 return op.getMaxStep(x,dx);
01887 }
01888 catch (RVLException & e) {
01889 e<<"\ncalled from FcnlOpComp::getMaxStep\n";
01890 throw e;
01891 }
01892 }
01893
01896 OperatorEvaluation<Scalar> const & getOpEval() const {
01897 if (opeval) return *opeval;
01898 RVLException e;
01899 e<<"Error: FcnlOpComp::getOpEval\n";
01900 e<<" apparently not yet evaluated so operator evaluation component\n";
01901 e<<" not available\n";
01902 throw e;
01903 }
01904
01907 FunctionalEvaluation<Scalar> const & getFcnlEval() const {
01908 if (fneval) return *fneval;
01909 RVLException e;
01910 e<<"Error: FcnlOpComp::getFcnlEval\n";
01911 e<<" apparently not yet evaluated so functional evaluation component\n";
01912 e<<" not available\n";
01913 throw e;
01914 }
01915
01916 ostream & write(ostream & str) const {
01917 str<<"FcnlOpComp: Functional-Operator composition\n";
01918 str<<"operator:\n";
01919 op.write(str);
01920 str<<"followed by functional:\n";
01921 f.write(str);
01922 return str;
01923 }
01924
01925 };
01926
01928 template<typename Scalar>
01929 class RestrictFcnl: public Functional<Scalar> {
01930
01931 private:
01932
01933 FunctionalProductDomain<Scalar> const & f;
01934 mutable Vector<Scalar> xx;
01935 mutable Components<Scalar> cxx;
01936
01937 protected:
01938
01939 void apply(Vector<Scalar> const & x,
01940 Scalar & val) const {
01941 try {
01942 cxx[1].copy(x);
01943 export_apply(f, xx, val);
01944 }
01945 catch (RVLException & e) {
01946 e<<"\ncalled from RestrictFcnl::apply\n";
01947 throw e;
01948 }
01949 }
01950
01951
01952
01953
01954 void applyGradient(Vector<Scalar> const & x,
01955 Vector<Scalar> & g) const {
01956 try {
01957 cxx[1].copy(x);
01958 export_applyPartialGradient(f, 1, xx, g);
01959 }
01960 catch (RVLException & e) {
01961 e<<"\ncalled from RestrictFcnl::applyGradient\n";
01962 throw e;
01963 }
01964 }
01965
01966 void applyHessian(Vector<Scalar> const & x,
01967 Vector<Scalar> const & dx,
01968 Vector<Scalar> & dy) const {
01969 try {
01970 cxx[1].copy(x);
01971 export_applyPartialHessian(f, 1, 1, xx, dx, dy);
01972 }
01973 catch (RVLException & e) {
01974 e<<"\ncalled from RestrictFcnl::applyHessian\n";
01975 throw e;
01976 }
01977 }
01978
01979 Functional<Scalar> * clone() const {
01980 return new RestrictFcnl(*this);
01981 }
01982
01983 public:
01984
01985 RestrictFcnl(FunctionalProductDomain<Scalar> const & _f,
01986 Vector<Scalar> const & x0)
01987 : f(_f), xx(_f.getDomain()), cxx(xx) {
01988 try {
01989 int ncomp = f.getProductDomain().getSize();
01990 if (ncomp != 2) {
01991 RVLException e;
01992 e<<"ERROR: RestrictFcnl constructor\n";
01993 e<<" input FcnlProdDom has domain with "<<ncomp<<" components\n";
01994 e<<" current implementation implementation allows only 2, with";
01995 e<<" first restricted\n";
01996 e<<" FcnlProdDom:\n";
01997 f.write(e);
01998 throw e;
01999 }
02000 cxx[1].copy(x0);
02001 }
02002 catch (RVLException & e) {
02003 e<<"\ncalled from RestrictFcnl constructor\n";
02004 throw e;
02005 }
02006 }
02007
02008 RestrictFcnl(RestrictFcnl<Scalar> const & g): f(g.f), xx(g.xx) {}
02009
02010 ~RestrictFcnl() {}
02011
02012 Space<Scalar> const & getDomain() { return f.getDomain(); }
02013
02014 Scalar getMaxStep(const Vector<Scalar> & x,
02015 const Vector<Scalar> & dx) const {
02016 try {
02017
02018 cxx[1].copy(x);
02019 Vector<Scalar> dxx(f.getDomain(),true);
02020 Components<Scalar> cdxx(dxx);
02021 dxx[1].copy(dx);
02022 return f.getMaxStep(xx,dxx);
02023 }
02024 catch (RVLException & e) {
02025 e<<"\ncalled from RestrictFcnl::getMaxStep\n";
02026 throw e;
02027 }
02028 }
02029
02030 ostream & write(ostream & str) const {
02031 str<<"RestrictFcnl with components\n";
02032 str<<" Vector:\n";
02033 xx.write(str);
02034 str<<" FcnlProdDom:\n";
02035 f.write(str);
02036 return str;
02037 }
02038 };
02039
02040 }
02041
02042 #endif
02043
02044
02045
02046
02047