// @(#)root/mathmore:$Id$
// Author: L. Moneta  03/2011

 /**********************************************************************
  *                                                                    *
  * Copyright (c) 2004 ROOT Foundation,  CERN/PH-SFT                   *
  *                                                                    *
  * This library is free software; you can redistribute it and/or      *
  * modify it under the terms of the GNU General Public License        *
  * as published by the Free Software Foundation; either version 2     *
  * of the License, or (at your option) any later version.             *
  *                                                                    *
  * This library 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   *
  * General Public License for more details.                           *
  *                                                                    *
  * You should have received a copy of the GNU General Public License  *
  * along with this library (see file COPYING); if not, write          *
  * to the Free Software Foundation, Inc., 59 Temple Place, Suite      *
  * 330, Boston, MA 02111-1307 USA, or contact the author.             *
  *                                                                    *
  **********************************************************************/

// Header file for class GSLMultiRootFinder
//

#ifndef ROOT_Math_GSLMultiRootFinder
#define ROOT_Math_GSLMultiRootFinder



#ifndef ROOT_Math_IFunction
#include "Math/IFunction.h"
#endif

#ifndef ROOT_Math_WrappedFunction
#include "Math/WrappedFunction.h"
#endif

#include <vector>

#include <iostream>

namespace ROOT {
namespace Math {


   class GSLMultiRootBaseSolver;



//________________________________________________________________________________________________________
  /**
     Class for  Multidimensional root finding algorithms bassed on GSL. This class is used to solve a
     non-linear system of equations:

     f1(x1,....xn) = 0
     f2(x1,....xn) = 0
     ..................
     fn(x1,....xn) = 0

     See the GSL <A HREF="http://www.gnu.org/software/gsl/manual/html_node/Multidimensional-Root_002dFinding.html"> online manual</A> for
     information on the GSL MultiRoot finding algorithms

     The available GSL algorithms require the derivatives of the supplied functions or not (they are
     computed internally by GSL). In the first case the user needs to provide a list of multidimensional functions implementing the
     gradient interface (ROOT::Math::IMultiGradFunction) while in the second case it is enough to supply a list of
     functions impelmenting the ROOT::Math::IMultiGenFunction interface.
     The available algorithms requiring derivatives (see also the GSL
     <A HREF="http://www.gnu.org/software/gsl/manual/html_node/Algorithms-using-Derivatives.html">documentation</A> )
     are the followings:
     <ul>
         <li><tt>ROOT::Math::GSLMultiRootFinder::kHybridSJ</tt>  with name <it>"HybridSJ"</it>: modified Powell's hybrid
     method as implemented in HYBRJ in MINPACK
         <li><tt>ROOT::Math::GSLMultiRootFinder::kHybridJ</tt>  with name <it>"HybridJ"</it>: unscaled version of the
     previous algorithm</li>
         <li><tt>ROOT::Math::GSLMultiRootFinder::kNewton</tt>  with name <it>"Newton"</it>: Newton method </li>
         <li><tt>ROOT::Math::GSLMultiRootFinder::kGNewton</tt>  with name <it>"GNewton"</it>: modified Newton method </li>
     </ul>
     The algorithms without derivatives (see also the GSL
     <A HREF="http://www.gnu.org/software/gsl/manual/html_node/Algorithms-without-Derivatives.html">documentation</A> )
     are the followings:
     <ul>
         <li><tt>ROOT::Math::GSLMultiRootFinder::kHybridS</tt>  with name <it>"HybridS"</it>: same as HybridSJ but using
     finate difference approximation for the derivatives</li>
         <li><tt>ROOT::Math::GSLMultiRootFinder::kHybrid</tt>  with name <it>"Hybrid"</it>: unscaled version of the
     previous algorithm</li>
         <li><tt>ROOT::Math::GSLMultiRootFinder::kDNewton</tt>  with name <it>"DNewton"</it>: discrete Newton algorithm </li>
         <li><tt>ROOT::Math::GSLMultiRootFinder::kBroyden</tt>  with name <it>"Broyden"</it>: Broyden algorithm </li>
     </ul>

     @ingroup MultiRoot
  */


 class GSLMultiRootFinder {

 public:

   /**
      enumeration specifying the types of GSL multi root finders
      requiring the derivatives
      @ingroup MultiRoot
   */
    enum EDerivType {
       kHybridSJ,
       kHybridJ,
       kNewton,
       kGNewton
    };
    /**
       enumeration specifying the types of GSL multi root finders
       which do not require the derivatives
       @ingroup MultiRoot
    */
    enum EType {
       kHybridS,
       kHybrid,
       kDNewton,
       kBroyden
    };



    /// create a multi-root finder based on an algorithm not requiring function derivative
    GSLMultiRootFinder(EType type);

    /// create a multi-root finder based on an algorithm requiring function derivative
    GSLMultiRootFinder(EDerivType type);

    /*
      create a multi-root finder using a string.
      The names are those defined in the GSL manuals
      after having remived the GSL prefix (gsl_multiroot_fsolver).
      Default algorithm  is "hybrids" (without derivative).
    */
    GSLMultiRootFinder(const char * name = 0);

    /// destructor
    virtual ~GSLMultiRootFinder();

 private:
    // usually copying is non trivial, so we make this unaccessible
    GSLMultiRootFinder(const GSLMultiRootFinder &);
    GSLMultiRootFinder & operator = (const GSLMultiRootFinder &);

 public:

    /// set the type for an algorithm without derivatives
    void SetType(EType type) {
       fType = type; fUseDerivAlgo = false;
    }

    /// set the type of algorithm using derivatives
    void SetType(EDerivType type) {
       fType = type; fUseDerivAlgo = true;
    }

    /// set the type using a string
    void SetType(const char * name);

    /*
       add the list of functions f1(x1,..xn),...fn(x1,...xn). The list must contain pointers of
       ROOT::Math::IMultiGenFunctions. The method requires the
       the begin and end of the list iterator.
       The list can be any stl container or a simple array of  ROOT::Math::IMultiGenFunctions* or
       whatever implementing an iterator.
       If using a derivative type algorithm the function pointers must implement the
       ROOT::Math::IMultiGradFunction interface
    */
    template<class FuncIterator>
    bool SetFunctionList( FuncIterator begin, FuncIterator end) {
       bool ret = true;
       for (FuncIterator itr = begin; itr != end; ++itr) {
          const ROOT::Math::IMultiGenFunction * f = *itr;
          ret &= AddFunction( *f);
       }
       return ret;
    }

    /*
      add (set) a single function fi(x1,...xn) which is part of the system of
       specifying the begin and end of the iterator.
       If using a derivative type algorithm the function must implement the
       ROOT::Math::IMultiGradFunction interface
       Return the current number of function in the list and 0 if failed to add the function
     */
    int AddFunction( const ROOT::Math::IMultiGenFunction & func);

    /// same method as before but using any function implementing
    /// the operator(), so can be wrapped in a IMultiGenFunction interface
    template <class Function>
    int AddFunction( Function & f, int ndim) {
       // no need to care about lifetime of wfunc. It will be cloned inside AddFunction
       WrappedMultiFunction<Function &> wfunc(f, ndim);
       return AddFunction(wfunc);
    }

    /**
       return the number of sunctions set in the class.
       The number must be equal to the dimension of the functions
     */
    unsigned  int Dim() const { return fFunctions.size(); }

    /// clear list of functions
    void Clear();

    /// return the root X values solving the system
    const double * X() const;

    /// return the function values f(X) solving the system
    /// i.e. they must be close to zero at the solution
    const double * FVal() const;

    /// return the last step size
    const double * Dx() const;


    /**
       Find the root starting from the point X;
       Use the number of iteration and tolerance if given otherwise use
       default parameter values which can be defined by
       the static method SetDefault...
    */
    bool Solve(const double * x,  int maxIter = 0, double absTol = 0, double relTol = 0);

    /// Return number of iterations
    int Iterations() const {
       return fIter;
    }

    /// Return the status of last root finding
    int Status() const { return fStatus; }

    /// Return the algorithm name
    const char * Name() const;

    /*
       set print level
       level = 0  quiet (no messages print)
             = 1  print only the result
             = 3  max debug. Print result at each iteration
    */
    void SetPrintLevel(int level) { fPrintLevel = level; }

    /// return the print level
    int PrintLevel() const { return fPrintLevel; }


    //-- static methods to set configurations

    /// set tolerance (absolute and relative)
    /// relative tolerance is only use to verify the convergence
    /// do it is a minor parameter
    static void SetDefaultTolerance(double abstol, double reltol = 0 );

    /// set maximum number of iterations
    static void SetDefaultMaxIterations(int maxiter);

    /// print iteration state
    void PrintState(std::ostream & os = std::cout);


 protected:

    // return type given a name
    std::pair<bool,int> GetType(const char * name);
    // clear list of functions
    void ClearFunctions();


 private:

    int fIter;           // current numer of iterations
    int fStatus;         // current status
    int fPrintLevel;     // print level

    // int fMaxIter;        // max number of iterations
    // double fAbsTolerance;  // absolute tolerance
    // double fRelTolerance;  // relative tolerance
    int fType;            // type of algorithm
    bool fUseDerivAlgo; // algorithm using derivative

    GSLMultiRootBaseSolver * fSolver;
    std::vector<ROOT::Math::IMultiGenFunction *> fFunctions;   //! transient Vector of the functions


 };

   // use typedef for most sensible name
   typedef GSLMultiRootFinder MultiRootFinder;

} // namespace Math
} // namespace ROOT


#endif /* ROOT_Math_GSLMultiRootFinder */
 GSLMultiRootFinder.h:1
 GSLMultiRootFinder.h:2
 GSLMultiRootFinder.h:3
 GSLMultiRootFinder.h:4
 GSLMultiRootFinder.h:5
 GSLMultiRootFinder.h:6
 GSLMultiRootFinder.h:7
 GSLMultiRootFinder.h:8
 GSLMultiRootFinder.h:9
 GSLMultiRootFinder.h:10
 GSLMultiRootFinder.h:11
 GSLMultiRootFinder.h:12
 GSLMultiRootFinder.h:13
 GSLMultiRootFinder.h:14
 GSLMultiRootFinder.h:15
 GSLMultiRootFinder.h:16
 GSLMultiRootFinder.h:17
 GSLMultiRootFinder.h:18
 GSLMultiRootFinder.h:19
 GSLMultiRootFinder.h:20
 GSLMultiRootFinder.h:21
 GSLMultiRootFinder.h:22
 GSLMultiRootFinder.h:23
 GSLMultiRootFinder.h:24
 GSLMultiRootFinder.h:25
 GSLMultiRootFinder.h:26
 GSLMultiRootFinder.h:27
 GSLMultiRootFinder.h:28
 GSLMultiRootFinder.h:29
 GSLMultiRootFinder.h:30
 GSLMultiRootFinder.h:31
 GSLMultiRootFinder.h:32
 GSLMultiRootFinder.h:33
 GSLMultiRootFinder.h:34
 GSLMultiRootFinder.h:35
 GSLMultiRootFinder.h:36
 GSLMultiRootFinder.h:37
 GSLMultiRootFinder.h:38
 GSLMultiRootFinder.h:39
 GSLMultiRootFinder.h:40
 GSLMultiRootFinder.h:41
 GSLMultiRootFinder.h:42
 GSLMultiRootFinder.h:43
 GSLMultiRootFinder.h:44
 GSLMultiRootFinder.h:45
 GSLMultiRootFinder.h:46
 GSLMultiRootFinder.h:47
 GSLMultiRootFinder.h:48
 GSLMultiRootFinder.h:49
 GSLMultiRootFinder.h:50
 GSLMultiRootFinder.h:51
 GSLMultiRootFinder.h:52
 GSLMultiRootFinder.h:53
 GSLMultiRootFinder.h:54
 GSLMultiRootFinder.h:55
 GSLMultiRootFinder.h:56
 GSLMultiRootFinder.h:57
 GSLMultiRootFinder.h:58
 GSLMultiRootFinder.h:59
 GSLMultiRootFinder.h:60
 GSLMultiRootFinder.h:61
 GSLMultiRootFinder.h:62
 GSLMultiRootFinder.h:63
 GSLMultiRootFinder.h:64
 GSLMultiRootFinder.h:65
 GSLMultiRootFinder.h:66
 GSLMultiRootFinder.h:67
 GSLMultiRootFinder.h:68
 GSLMultiRootFinder.h:69
 GSLMultiRootFinder.h:70
 GSLMultiRootFinder.h:71
 GSLMultiRootFinder.h:72
 GSLMultiRootFinder.h:73
 GSLMultiRootFinder.h:74
 GSLMultiRootFinder.h:75
 GSLMultiRootFinder.h:76
 GSLMultiRootFinder.h:77
 GSLMultiRootFinder.h:78
 GSLMultiRootFinder.h:79
 GSLMultiRootFinder.h:80
 GSLMultiRootFinder.h:81
 GSLMultiRootFinder.h:82
 GSLMultiRootFinder.h:83
 GSLMultiRootFinder.h:84
 GSLMultiRootFinder.h:85
 GSLMultiRootFinder.h:86
 GSLMultiRootFinder.h:87
 GSLMultiRootFinder.h:88
 GSLMultiRootFinder.h:89
 GSLMultiRootFinder.h:90
 GSLMultiRootFinder.h:91
 GSLMultiRootFinder.h:92
 GSLMultiRootFinder.h:93
 GSLMultiRootFinder.h:94
 GSLMultiRootFinder.h:95
 GSLMultiRootFinder.h:96
 GSLMultiRootFinder.h:97
 GSLMultiRootFinder.h:98
 GSLMultiRootFinder.h:99
 GSLMultiRootFinder.h:100
 GSLMultiRootFinder.h:101
 GSLMultiRootFinder.h:102
 GSLMultiRootFinder.h:103
 GSLMultiRootFinder.h:104
 GSLMultiRootFinder.h:105
 GSLMultiRootFinder.h:106
 GSLMultiRootFinder.h:107
 GSLMultiRootFinder.h:108
 GSLMultiRootFinder.h:109
 GSLMultiRootFinder.h:110
 GSLMultiRootFinder.h:111
 GSLMultiRootFinder.h:112
 GSLMultiRootFinder.h:113
 GSLMultiRootFinder.h:114
 GSLMultiRootFinder.h:115
 GSLMultiRootFinder.h:116
 GSLMultiRootFinder.h:117
 GSLMultiRootFinder.h:118
 GSLMultiRootFinder.h:119
 GSLMultiRootFinder.h:120
 GSLMultiRootFinder.h:121
 GSLMultiRootFinder.h:122
 GSLMultiRootFinder.h:123
 GSLMultiRootFinder.h:124
 GSLMultiRootFinder.h:125
 GSLMultiRootFinder.h:126
 GSLMultiRootFinder.h:127
 GSLMultiRootFinder.h:128
 GSLMultiRootFinder.h:129
 GSLMultiRootFinder.h:130
 GSLMultiRootFinder.h:131
 GSLMultiRootFinder.h:132
 GSLMultiRootFinder.h:133
 GSLMultiRootFinder.h:134
 GSLMultiRootFinder.h:135
 GSLMultiRootFinder.h:136
 GSLMultiRootFinder.h:137
 GSLMultiRootFinder.h:138
 GSLMultiRootFinder.h:139
 GSLMultiRootFinder.h:140
 GSLMultiRootFinder.h:141
 GSLMultiRootFinder.h:142
 GSLMultiRootFinder.h:143
 GSLMultiRootFinder.h:144
 GSLMultiRootFinder.h:145
 GSLMultiRootFinder.h:146
 GSLMultiRootFinder.h:147
 GSLMultiRootFinder.h:148
 GSLMultiRootFinder.h:149
 GSLMultiRootFinder.h:150
 GSLMultiRootFinder.h:151
 GSLMultiRootFinder.h:152
 GSLMultiRootFinder.h:153
 GSLMultiRootFinder.h:154
 GSLMultiRootFinder.h:155
 GSLMultiRootFinder.h:156
 GSLMultiRootFinder.h:157
 GSLMultiRootFinder.h:158
 GSLMultiRootFinder.h:159
 GSLMultiRootFinder.h:160
 GSLMultiRootFinder.h:161
 GSLMultiRootFinder.h:162
 GSLMultiRootFinder.h:163
 GSLMultiRootFinder.h:164
 GSLMultiRootFinder.h:165
 GSLMultiRootFinder.h:166
 GSLMultiRootFinder.h:167
 GSLMultiRootFinder.h:168
 GSLMultiRootFinder.h:169
 GSLMultiRootFinder.h:170
 GSLMultiRootFinder.h:171
 GSLMultiRootFinder.h:172
 GSLMultiRootFinder.h:173
 GSLMultiRootFinder.h:174
 GSLMultiRootFinder.h:175
 GSLMultiRootFinder.h:176
 GSLMultiRootFinder.h:177
 GSLMultiRootFinder.h:178
 GSLMultiRootFinder.h:179
 GSLMultiRootFinder.h:180
 GSLMultiRootFinder.h:181
 GSLMultiRootFinder.h:182
 GSLMultiRootFinder.h:183
 GSLMultiRootFinder.h:184
 GSLMultiRootFinder.h:185
 GSLMultiRootFinder.h:186
 GSLMultiRootFinder.h:187
 GSLMultiRootFinder.h:188
 GSLMultiRootFinder.h:189
 GSLMultiRootFinder.h:190
 GSLMultiRootFinder.h:191
 GSLMultiRootFinder.h:192
 GSLMultiRootFinder.h:193
 GSLMultiRootFinder.h:194
 GSLMultiRootFinder.h:195
 GSLMultiRootFinder.h:196
 GSLMultiRootFinder.h:197
 GSLMultiRootFinder.h:198
 GSLMultiRootFinder.h:199
 GSLMultiRootFinder.h:200
 GSLMultiRootFinder.h:201
 GSLMultiRootFinder.h:202
 GSLMultiRootFinder.h:203
 GSLMultiRootFinder.h:204
 GSLMultiRootFinder.h:205
 GSLMultiRootFinder.h:206
 GSLMultiRootFinder.h:207
 GSLMultiRootFinder.h:208
 GSLMultiRootFinder.h:209
 GSLMultiRootFinder.h:210
 GSLMultiRootFinder.h:211
 GSLMultiRootFinder.h:212
 GSLMultiRootFinder.h:213
 GSLMultiRootFinder.h:214
 GSLMultiRootFinder.h:215
 GSLMultiRootFinder.h:216
 GSLMultiRootFinder.h:217
 GSLMultiRootFinder.h:218
 GSLMultiRootFinder.h:219
 GSLMultiRootFinder.h:220
 GSLMultiRootFinder.h:221
 GSLMultiRootFinder.h:222
 GSLMultiRootFinder.h:223
 GSLMultiRootFinder.h:224
 GSLMultiRootFinder.h:225
 GSLMultiRootFinder.h:226
 GSLMultiRootFinder.h:227
 GSLMultiRootFinder.h:228
 GSLMultiRootFinder.h:229
 GSLMultiRootFinder.h:230
 GSLMultiRootFinder.h:231
 GSLMultiRootFinder.h:232
 GSLMultiRootFinder.h:233
 GSLMultiRootFinder.h:234
 GSLMultiRootFinder.h:235
 GSLMultiRootFinder.h:236
 GSLMultiRootFinder.h:237
 GSLMultiRootFinder.h:238
 GSLMultiRootFinder.h:239
 GSLMultiRootFinder.h:240
 GSLMultiRootFinder.h:241
 GSLMultiRootFinder.h:242
 GSLMultiRootFinder.h:243
 GSLMultiRootFinder.h:244
 GSLMultiRootFinder.h:245
 GSLMultiRootFinder.h:246
 GSLMultiRootFinder.h:247
 GSLMultiRootFinder.h:248
 GSLMultiRootFinder.h:249
 GSLMultiRootFinder.h:250
 GSLMultiRootFinder.h:251
 GSLMultiRootFinder.h:252
 GSLMultiRootFinder.h:253
 GSLMultiRootFinder.h:254
 GSLMultiRootFinder.h:255
 GSLMultiRootFinder.h:256
 GSLMultiRootFinder.h:257
 GSLMultiRootFinder.h:258
 GSLMultiRootFinder.h:259
 GSLMultiRootFinder.h:260
 GSLMultiRootFinder.h:261
 GSLMultiRootFinder.h:262
 GSLMultiRootFinder.h:263
 GSLMultiRootFinder.h:264
 GSLMultiRootFinder.h:265
 GSLMultiRootFinder.h:266
 GSLMultiRootFinder.h:267
 GSLMultiRootFinder.h:268
 GSLMultiRootFinder.h:269
 GSLMultiRootFinder.h:270
 GSLMultiRootFinder.h:271
 GSLMultiRootFinder.h:272
 GSLMultiRootFinder.h:273
 GSLMultiRootFinder.h:274
 GSLMultiRootFinder.h:275
 GSLMultiRootFinder.h:276
 GSLMultiRootFinder.h:277
 GSLMultiRootFinder.h:278
 GSLMultiRootFinder.h:279
 GSLMultiRootFinder.h:280
 GSLMultiRootFinder.h:281
 GSLMultiRootFinder.h:282
 GSLMultiRootFinder.h:283
 GSLMultiRootFinder.h:284
 GSLMultiRootFinder.h:285
 GSLMultiRootFinder.h:286
 GSLMultiRootFinder.h:287
 GSLMultiRootFinder.h:288
 GSLMultiRootFinder.h:289
 GSLMultiRootFinder.h:290
 GSLMultiRootFinder.h:291
 GSLMultiRootFinder.h:292
 GSLMultiRootFinder.h:293
 GSLMultiRootFinder.h:294
 GSLMultiRootFinder.h:295
 GSLMultiRootFinder.h:296
 GSLMultiRootFinder.h:297
 GSLMultiRootFinder.h:298