Exemplo n.º 1
0
        /// <summary>
        /// Calls the managed lmmin API ported from the lmfit package
        /// </summary>
        /// <param name="f">The user supplied function to update the residue vector</param>
        /// <param name="parameters">initial guess for the parameters</param>
        /// <param name="mData">Number of data points == number of equations == length of the residue vector</param>
        /// <returns>Optimization outcome and optimal paramters, if successful</returns>
        private OptimizationResult CallManagedSolver(Action <double[], double[]> f, double[] parameters, int mData)
        {
            // build control structure understood by lmmin
            LMControlStruct ctrl = new LMControlStruct {
                ftol       = this.Ftol,
                gtol       = this.Gtol,
                xtol       = this.Xtol,
                patience   = this.Patience,
                epsilon    = this.Epsilon,
                msgfile    = IntPtr.Zero,
                m_maxpri   = -1,
                n_maxpri   = -1,
                scale_diag = this.ScaleDiagonal ? 1 : 0,
                stepbound  = this.InitialStepbound,
                verbosity  = this.VerboseOutput ? 3 : 0
            };

            LMStatusStruct stat = new LMStatusStruct();

            // LMMin modifies optimizedPars => copy parameters
            var optimizedPars = new double[parameters.Length];

            parameters.CopyTo(optimizedPars, 0);
            LMMinManaged.LMMin(parameters.Length, optimizedPars, mData, f, ref ctrl, ref stat);

            // extract results from lmmin's result data struct
            return(new OptimizationResult(
                       optimizedPars,
                       stat.fnorm,
                       stat.nfev,
                       (SolverStatus)stat.outcome,
                       LMSolver.outcomeMessages[stat.outcome],
                       stat.userbreak > 0 ? true : false
                       ));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Calls the native lmmin API from the lmfit package
        /// </summary>
        /// <param name="f">The user supplied function to update the residue vector</param>
        /// <param name="parameters">initial guess for the parameters</param>
        /// <param name="mData">Number of data points == number of equations == length of the residue vector</param>
        /// <returns>Optimization outcome and optimal paramters, if successful</returns>
        private OptimizationResult CallNativeSolver(
            Action <double[], double[]> f, double[] parameters,
            int mData)
        {
            // build control structure understood by lmmin
            LMControlStruct ctrl = new LMControlStruct {
                ftol       = this.Ftol,
                gtol       = this.Gtol,
                xtol       = this.Xtol,
                patience   = this.Patience,
                epsilon    = this.Epsilon,
                msgfile    = IntPtr.Zero,
                m_maxpri   = -1,
                n_maxpri   = -1,
                scale_diag = this.ScaleDiagonal ? 1 : 0,
                stepbound  = this.InitialStepbound,
                verbosity  = this.VerboseOutput ? 3 : 0
            };

            LMStatusStruct stat = new LMStatusStruct();

            OptimizationResult result = null;

            using (var pool = new PinnedArrayPool <double>()) {
                // optimizedPars must be pinned, because
                // the first callback-call (== call to f) passes a
                // pointer to optimizedPars in "par" parameter ("working space")
                var optimizedPars = pool.AllocatePinnedArray(parameters.Length);
                parameters.CopyTo(optimizedPars, 0);

                // call native lmmin from lmfit package (modifies optimizedPars)
                LMFit.lmmin(
                    optimizedPars.Array.Length,
                    optimizedPars.Address,
                    mData,
                    IntPtr.Zero,
                    // translate Action<double[], double[]> to LMDelegate:
                    (par, m_dat, dataPtr, fvec, userbreak) => f(pool[par], pool[fvec]),
                    ref ctrl,
                    ref stat,
                    pool.Calloc,
                    pool.Free);

                // extract results from lmmin's result data struct
                result = new OptimizationResult(
                    optimizedPars,
                    stat.fnorm,
                    stat.nfev,
                    (SolverStatus)stat.outcome,
                    LMSolver.outcomeMessages[stat.outcome],
                    stat.userbreak > 0 ? true : false
                    );

                // pinned managed arrays allocated by lmmin may be garbage collected
                // starting from here (if unpinned and not referenced anymore)
                pool.UnpinArray(optimizedPars);
                GC.KeepAlive(pool); // really neccessary?
            }

            return(result);
        }