Skip to content
Snippets Groups Projects
Select Git revision
  • a53636e24ecbb9d521598a0c76a86a25a11f2a95
  • master default protected
  • 6.x protected
  • madysson
  • 5.x protected
  • asm
  • time-varying-information-set
  • 4.6 protected
  • dynare_minreal
  • dragonfly
  • various_fixes
  • 4.5 protected
  • clang+openmp
  • exo_steady_state
  • declare_vars_in_model_block
  • julia
  • error_msg_undeclared_model_vars
  • static_aux_vars
  • slice
  • aux_func
  • penalty
  • 6.4 protected
  • 6.3 protected
  • 6.2 protected
  • 6.1 protected
  • 6.0 protected
  • 6-beta2 protected
  • 6-beta1 protected
  • 5.5 protected
  • 5.4 protected
  • 5.3 protected
  • 5.2 protected
  • 5.1 protected
  • 5.0 protected
  • 5.0-rc1 protected
  • 4.7-beta3 protected
  • 4.7-beta2 protected
  • 4.7-beta1 protected
  • 4.6.4 protected
  • 4.6.3 protected
  • 4.6.2 protected
41 results

CheckPath.m

Blame
  • nlsolve.cpp 5.46 KiB
    // Copyright (C) 2006, Ondra Kamenik
    
    // $Id: nlsolve.cpp 762 2006-05-22 13:00:07Z kamenik $
    
    #include "nlsolve.h"
    #include "dynare_exception.h"
    
    #include <cmath>
    
    using namespace ogu;
    
    /** This should not be greater than DBL_EPSILON^(1/2). */
    double GoldenSectionSearch::tol = 1.e-4;
    
    /** This is equal to the golden section ratio. */
    double GoldenSectionSearch::golden = (3.-std::sqrt(5.))/2;
    
    double GoldenSectionSearch::search(OneDFunction& f, double x1, double x2)
    {
    	double b;
    	if (init_bracket(f, x1, x2, b)) {
    		double fb = f.eval(b);
    		double f1 = f.eval(x1);
    		f.eval(x2);
    		double dx;
    		do {
    			double w = (b-x1)/(x2-x1);
    			dx = std::abs((1-2*w)*(x2-x1));
    			double x;
    			if (b-x1 > x2-b)
    				x = b - dx;
    			else
    				x = b + dx;
    			double fx = f.eval(x);
    			if (! std::isfinite(fx))
    				return x1;
    			if (b-x1 > x2-b) {
    				// x is on the left from b
    				if (f1 > fx && fx < fb) {
    					// pickup bracket [f1,fx,fb]
    					x2 = b;
    					fb = fx;
    					b = x;
    				} else {
    					// pickup bracket [fx,fb,fx2]
    					f1 = fx;
    					x1 = x;
    				}
    			} else {
    				// x is on the right from b
    				if (f1 > fb && fb < fx) {
    					// pickup bracket [f1,fb,fx]
    					x2 = x;
    				} else {
    					// pickup bracket [fb,fx,f2]
    					f1 = fb;
    					x1 = b;
    					fb = fx;
    					b = x;
    				}
    			}
    		} while(dx > tol);
    	}
    	return b;
    }
    
    bool GoldenSectionSearch::init_bracket(OneDFunction& f, double x1, double& x2, double& b)
    {
    	double f1 = f.eval(x1);
    	if (! std::isfinite(f1))
    		throw DynareException(__FILE__, __LINE__,
    							  "Safer point not finite in GoldenSectionSearch::init_bracket");
    
    	int cnt = 0;
    	bool bracket_found = false;
    	do {
    		bool finite_found = search_for_finite(f, x1, x2, b);
    		if (! finite_found) {
    			b = x1;
    			return false;
    		}
    		double f2 = f.eval(x2);
    		double fb = f.eval(b);
    		double bsym = 2*x2 - b;
    		double fbsym = f.eval(bsym);
    		// now we know that f1, f2, and fb are finite
    		if (std::isfinite(fbsym)) {
    			// we have four numbers f1, fb, f2, fbsym, we test for the
    			// following combinations to find the bracket:
    			// [f1,f2,fbsym], [f1,fb,fbsym] and [f1,fb,fbsym]
    			if (f1 > f2 && f2 < fbsym) {
    				bracket_found = true;
    				b = x2;
    				x2 = bsym;
    			} else if (f1 > fb && fb < fbsym) {
    				bracket_found = true;
    				x2 = bsym;
    			} else if (f1 > fb && fb < f2) {
    				bracket_found = true;
    			} else {
    				double newx2 = b;
    				// choose the smallest value in case we end
    				if (f1 > fbsym) {
    					// the smallest value is on the other end, we do
    					// not want to continue
    					b = bsym;
    					return false;
    				} else
    					b = x1;
    					// move x2 to b in case we continue 
    					x2 = newx2;
    			}
    		} else {
    			// we have only three numbers, we test for the bracket,
    			// and if not found, we set b as potential result and
    			// shorten x2 as potential init value for next cycle
    			if (f1 > fb && fb < f2)
    				bracket_found = true;
    			else {
    				double newx2 = b;
    				// choose the smaller value in case we end
    				if (f1 > f2)
    					b = x2;
    				else
    					b = x1;
    				// move x2 to b in case we continue
    				x2 = newx2;
    			}
    		}
    		cnt++;
    	} while (! bracket_found && cnt < 5);
    	
    	return bracket_found;
    }
    
    /** This moves x2 toward to x1 until the function at x2 is finite and
     * b as a golden section between x1 and x2 yields also finite f. */
    bool GoldenSectionSearch::search_for_finite(OneDFunction& f, double x1, double& x2, double&b)
    {
    	int cnt = 0;
    	bool found = false;
    	do {
    		double f2 = f.eval(x2);
    		b = (1-golden)*x1 + golden*x2;
    		double fb = f.eval(b);
    		found = std::isfinite(f2) && std::isfinite(fb);
    		if (! found)
    			x2 = b;
    		cnt++;
    	} while (! found && cnt < 5);
    
    	return found;
    }
    
    void VectorFunction::check_for_eval(const ConstVector& in, Vector& out) const
    {
    	if (inDim() != in.length() || outDim() != out.length())
    		throw DynareException(__FILE__, __LINE__,
    							  "Wrong dimensions in VectorFunction::check_for_eval");
    }
    
    double NLSolver::eval(double lambda)
    {
    	Vector xx((const Vector&)x);
    	xx.add(1-lambda, xcauchy);
    	xx.add(lambda, xnewton);
    	Vector ff(func.outDim());
    	func.eval(xx, ff);
    	return ff.dot(ff);
    }
    
    bool NLSolver::solve(Vector& xx, int& iter)
    {
    	JournalRecord rec(journal);
    	rec << "Iter   lambda      residual" << endrec;
    	JournalRecord rec1(journal);
    	rec1 << "---------------------------" << endrec;
    	char tmpbuf[14];
    
    	x = (const Vector&)xx;
    	iter = 0;
    	// setup fx
    	Vector fx(func.outDim());
    	func.eval(x, fx);
    	if (!fx.isFinite())
    		throw DynareException(__FILE__,__LINE__,
    							  "Initial guess does not yield finite residual in NLSolver::solve");
    	bool converged = fx.getMax() < tol;
    	JournalRecord rec2(journal);
    	sprintf(tmpbuf, "%10.6g", fx.getMax());
    	rec2 << iter << "         N/A   " << tmpbuf << endrec;
    	while (! converged && iter < max_iter) {
    		// setup Jacobian
    		jacob.eval(x);
    		// calculate cauchy step
    		Vector g(func.inDim());
    		g.zeros();
    		ConstTwoDMatrix(jacob).multaVecTrans(g, fx);
    		Vector Jg(func.inDim());
    		Jg.zeros();
    		ConstTwoDMatrix(jacob).multaVec(Jg, g);
    		double m = -g.dot(g)/Jg.dot(Jg);
    		xcauchy = (const Vector&) g;
    		xcauchy.mult(m);
    		// calculate newton step
    		xnewton = (const Vector&) fx;
    		ConstTwoDMatrix(jacob).multInvLeft(xnewton);
    		xnewton.mult(-1);
    
    		// line search
    		double lambda = GoldenSectionSearch::search(*this, 0, 1);
    		x.add(1-lambda, xcauchy);
    		x.add(lambda, xnewton);
    		// evaluate func
    		func.eval(x, fx);
    		converged = fx.getMax() < tol;
    
    		// iter
    		iter++;
    
    		JournalRecord rec3(journal);
    		sprintf(tmpbuf, "%10.6g", fx.getMax());
    		rec3 << iter << "    " << lambda << "   " << tmpbuf << endrec;
    	}
    	xx = (const Vector&)x;
    
    	return converged;
    }