lgalgo.cpp
来自「FreeFem++可以生成高质量的有限元网格。可以用于流体力学」· C++ 代码 · 共 299 行
CPP
299 行
// -*- Mode : c++ -*-//// SUMMARY : // USAGE : // ORG : // AUTHOR : Frederic Hecht// E-MAIL : hecht@ann.jussieu.fr///* This file is part of Freefem++ Freefem++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. Freefem++ is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Freefem++; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */#include <iostream>#include <cfloat>using namespace std;#include "error.hpp"#include "AFunction.hpp"#include "rgraph.hpp"#include "RNM.hpp"#include "MatriceCreuse_tpl.hpp"#include "Mesh3dn.hpp"#include "MeshPoint.hpp"#include "lgfem.hpp"#include "lgmesh3.hpp"#include "lgsolver.hpp"#include "problem.hpp"#include "NRJ.hpp"#include "RosenBrock.hpp"#include "LineSearch.hpp"#include "CubicLS.hpp"#include "BrentLS.hpp"#include "Optima.hpp"#include "BFGS.hpp"//#include "CG.hpp"#include "NewtonRaphson.hpp"//template<class R>extern Block *currentblock;typedef double R;class PrintErrorCompileNewtow : public E_F0info { public: typedef double Result; static E_F0 * f(const basicAC_F0 & args) { lgerror("\n\n *** change Newtow in Newton .\n *** Bad name in previous version,\n *** sorry FH.\n\n"); return 0; } static ArrayOfaType typeargs() {return ArrayOfaType(true);} operator aType () const { return atype<double>();} };class OptimAlgo : public OneOperator { public: typedef KN<R> Kn; typedef KN_<R> Kn_; typedef R REAL; typedef Param<REAL> PARAM; typedef KN<REAL> VECT; typedef KNM<REAL> MAT; typedef VirtualMatrice<REAL> VMAT; const int cas; class E_LCG: public E_F0mps { public: const int cas; static basicAC_F0::name_and_type name_param[] ; static const int n_name_param =3; Expression nargs[n_name_param]; Expression X; C_F0 inittheparam,theparam,closetheparam; Expression J,dJ,hJ; long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;} R arg(int i,Stack stack,R a) const{ return nargs[i] ? GetAny<R>( (*nargs[i])(stack) ): a;} class lgNRJ : public tNRJ<PARAM,VECT,VMAT,REAL> { private: Stack stack; Expression J,dJ,hJ,theparame; VECT * gg; protected: void setparam( const Param<R>& x ) { KN<double> *p=GetAny<KN<double> *>( (*theparame)(stack) ); ffassert( p->N() == x.N()); *p =x; } public: lgNRJ(Stack s,int n,Expression t,Expression JJ,Expression dJJ,Expression hJJ) : tNRJ<PARAM,VECT,VMAT,REAL>(n), stack(s), J(JJ),dJ(dJJ),hJ(hJJ),theparame(t), gg(0) { if(dJ) gg=new VECT(n); } ~lgNRJ() { if(gg) delete gg;} REAL Val(const Param<R>& x) { setparam(x); assert(J); R ret= GetAny<R>( (*J)(stack)); WhereStackOfPtr2Free(stack)->clean(); return ret; } VECT* Gradient(const Param<R>& x) { setparam(x); if ( dJ) { *gg=GetAny<Kn>( (*dJ)(stack)); WhereStackOfPtr2Free(stack)->clean(); } return gg ; //dJ ? GetAny<Kn*>( (*dJ)(stack)) :0;} } VMAT* Hessian(const Param<R>& x) { setparam(x); if (!hJ) return 0; Matrice_Creuse<R> * M= GetAny<Matrice_Creuse<R> *>( (*hJ)(stack)); WhereStackOfPtr2Free(stack)->clean(); assert(M && M->A ); return (VirtualMatrice<R>*) M->A;} }; E_LCG(const basicAC_F0 & args,int cc) : cas(cc) { int nbj= args.size()-1; Block::open(currentblock); // make a new block to X = to<Kn*>(args[nbj]); C_F0 X_n(args[nbj],"n"); // the expression to init the theparam of all inittheparam = currentblock->NewVar<LocalVariable>("the parameter",atype<KN<R> *>(),X_n); theparam = currentblock->Find("the parameter"); // the expression for the parameter args.SetNameParam(n_name_param,name_param,nargs); const Polymorphic * opJ=0; const Polymorphic * opdJ=0; const Polymorphic * ophJ=0; if (nbj>0) { opJ= dynamic_cast<const Polymorphic *>(args[0].LeftValue()); assert(opJ); } if (nbj>1) { opdJ= dynamic_cast<const Polymorphic *>(args[1].LeftValue()); assert(opdJ); } if (nbj>2) { ophJ= dynamic_cast<const Polymorphic *>(args[2].LeftValue()); assert(ophJ); } J=dJ=hJ=0; J= to<R>(C_F0(opJ,"(",theparam)); if(opdJ) dJ= to<Kn>(C_F0(opdJ,"(",theparam));// Modif FH 17102005 (a verifier) to<Kn*> ->to<Kn> if(ophJ) hJ= to< Matrice_Creuse<R> *>(C_F0(ophJ,"(",theparam)); closetheparam=currentblock->close(currentblock); // the cleanning block expression /* if (nargs[2]) { const Polymorphic * op= dynamic_cast<const Polymorphic *>(nargs[2]); assert(op); C = op->Find("(",ArrayOfaType(atype<Kn* >(),false)); } else C =0; */ } virtual AnyType operator()(Stack stack) const { WhereStackOfPtr2Free(stack)=new StackOfPtr2Free(stack);// FH mars 2005 typedef LineSearch<PARAM,VECT,MAT,VMAT,REAL> LS; typedef CubicLineSearch<LS> CLS; KN<double> * delta =0; R tol=arg(0,stack,1E-6); int itMax=arg(1,stack,100L); int itMaxLine=arg(2,stack,100L); bool verbose=verbosity>3; try { Kn &x = *GetAny<Kn *>((*X)(stack)); const int n=x.N(); //Kn * para = GetAny<KN<double>*>( inittheparam.eval(stack) ) ; // do allocation Param<R> param(x); lgNRJ nrj1(stack,n,theparam,J,dJ,hJ); if (!dJ) delta = new KN<double>(n); CLS ls( & nrj1,itMaxLine,delta); REAL initialNrj = nrj1.getVal(param); Optima<LS> *opt=0; if(cas==1) opt=new BFGS<LS>((CLS*)&ls,itMax,tol,verbose); else if(cas==2) opt=new Newt<LS>((CLS*)&ls,itMax,tol,verbose); else ErrorExec("lgalgo: Case no available Sorry internal bug",cas); param = opt->optimizer(param); REAL finalNrj = nrj1.getVal(param); if(verbosity) cout <<endl<<"*** RESULTS SUMMARY ***"<<endl; if(verbosity>1) { cout <<" The number of call to NRJ : "<< nrj1.Appel_Val() << endl; cout <<" The number of call to gradient : "<< nrj1.Appel_Grad() << endl; cout <<" The number of call to hessian : "<< nrj1.Appel_Hess() << endl; } if(verbosity>2) { cout <<"Normalized residue : "; affiche(opt->allResidue()); } if(verbosity) { cout <<" Initial NRJ value : " << initialNrj << endl; cout <<" Final NRJ value : " << finalNrj << endl;} delete opt; /// cout<<"The final optimized parameters : "<<param; x=param; } catch (...) { closetheparam.eval(stack); // clean memory WhereStackOfPtr2Free(stack)->clean(); // FH mars 2005 if( delta) delete delta; throw ; } if( delta) delete delta; closetheparam.eval(stack); // clean memory WhereStackOfPtr2Free(stack)->clean(); // FH mars 2005 return 0L; //SetAny<long>(0); Modif FH july 2005 } operator aType () const { return atype<long>();} }; E_F0 * code(const basicAC_F0 & args) const { return new E_LCG(args,cas);} OptimAlgo(int c) : OneOperator(atype<long>(), atype<Polymorphic*>(), atype<KN<R> *>()),cas(c){} OptimAlgo(int c,int cc) : OneOperator(atype<long>(), atype<Polymorphic*>(), atype<Polymorphic*>(), atype<KN<R> *>()),cas(c){} OptimAlgo(int c,int cc,int ccc) : OneOperator(atype<long>(), atype<Polymorphic*>(), atype<Polymorphic*>(), atype<Polymorphic*>(), atype<KN<R> *>()),cas(c){} };//template<class R>basicAC_F0::name_and_type OptimAlgo::E_LCG::name_param[]= { { "eps", &typeid(double) }, { "nbiter",&typeid(long) }, { "nbiterline",&typeid(long)}};void init_algo(){ Global.Add("BFGS","(",new OptimAlgo(1,1)); // j + dJ Global.Add("Newton","(",new OptimAlgo(2,2,2)); // j + dJ Global.Add("Newtow","(",new OneOperatorCode<PrintErrorCompileNewtow>); // error }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?