23024 lines
1.3 MiB
Plaintext
23024 lines
1.3 MiB
Plaintext
//+------------------------------------------------------------------+
|
|
//| alglib.mqh |
|
|
//| Copyright 2003-2012 Sergey Bochkanov (ALGLIB project) |
|
|
//| Copyright 2012-2017, MetaQuotes Software Corp. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
//| Implementation of ALGLIB library in MetaQuotes Language 5 |
|
|
//| |
|
|
//| The features of the library include: |
|
|
//| - Linear algebra (direct algorithms, EVD, SVD) |
|
|
//| - Solving systems of linear and non-linear equations |
|
|
//| - Interpolation |
|
|
//| - Optimization |
|
|
//| - FFT (Fast Fourier Transform) |
|
|
//| - Numerical integration |
|
|
//| - Linear and nonlinear least-squares fitting |
|
|
//| - Ordinary differential equations |
|
|
//| - Computation of special functions |
|
|
//| - Descriptive statistics and hypothesis testing |
|
|
//| - Data analysis - classification, regression |
|
|
//| - Implementing linear algebra algorithms, interpolation, etc. |
|
|
//| in high-precision arithmetic (using MPFR) |
|
|
//| |
|
|
//| This file 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 (www.fsf.org); either |
|
|
//| version 2 of the License, or (at your option) any later version. |
|
|
//| |
|
|
//| This program 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. |
|
|
//+------------------------------------------------------------------+
|
|
#include <Object.mqh>
|
|
#include "alglibmisc.mqh"
|
|
#include "dataanalysis.mqh"
|
|
#include "diffequations.mqh"
|
|
#include "delegatefunctions.mqh"
|
|
#include "fasttransforms.mqh"
|
|
#include "integration.mqh"
|
|
#include "interpolation.mqh"
|
|
//+------------------------------------------------------------------+
|
|
//| The main class, which includes functions for users |
|
|
//+------------------------------------------------------------------+
|
|
class CAlglib
|
|
{
|
|
public:
|
|
//--- constructor, destructor
|
|
CAlglib(void);
|
|
~CAlglib(void);
|
|
//--- function of package alglibmisc
|
|
//--- high quality random number generator
|
|
static void HQRndRandomize(CHighQualityRandStateShell &state);
|
|
static void HQRndSeed(const int s1,const int s2,CHighQualityRandStateShell &state);
|
|
static double HQRndUniformR(CHighQualityRandStateShell &state);
|
|
static int HQRndUniformI(CHighQualityRandStateShell &state,const int n);
|
|
static double HQRndNormal(CHighQualityRandStateShell &state);
|
|
static void HQRndUnit2(CHighQualityRandStateShell &state,double &x,double &y);
|
|
static void HQRndNormal2(CHighQualityRandStateShell &state,double &x1,double &x2);
|
|
static double HQRndExponential(CHighQualityRandStateShell &state,const double lambdav);
|
|
//--- build KD-trees
|
|
static void KDTreeSerialize(CKDTreeShell &obj,string &s_out);
|
|
static void KDTreeUnserialize(string s_in,CKDTreeShell &obj);
|
|
static void KDTreeBuild(CMatrixDouble &xy,const int n,const int nx,const int ny,const int normtype,CKDTreeShell &kdt);
|
|
static void KDTreeBuild(CMatrixDouble &xy,const int nx,const int ny,const int normtype,CKDTreeShell &kdt);
|
|
static void KDTreeBuildTagged(CMatrixDouble &xy,int &tags[],const int n,const int nx,const int ny,const int normtype,CKDTreeShell &kdt);
|
|
static void KDTreeBuildTagged(CMatrixDouble &xy,int &tags[],const int nx,const int ny,const int normtype,CKDTreeShell &kdt);
|
|
static int KDTreeQueryKNN(CKDTreeShell &kdt,double &x[],const int k,const bool selfmatch);
|
|
static int KDTreeQueryKNN(CKDTreeShell &kdt,double &x[],const int k);
|
|
static int KDTreeQueryRNN(CKDTreeShell &kdt,double &x[],const double r,const bool selfmatch);
|
|
static int KDTreeQueryRNN(CKDTreeShell &kdt,double &x[],const double r);
|
|
static int KDTreeQueryAKNN(CKDTreeShell &kdt,double &x[],const int k,const bool selfmatch,const double eps);
|
|
static int KDTreeQueryAKNN(CKDTreeShell &kdt,double &x[],const int k,const double eps);
|
|
static void KDTreeQueryResultsX(CKDTreeShell &kdt,CMatrixDouble &x);
|
|
static void KDTreeQueryResultsXY(CKDTreeShell &kdt,CMatrixDouble &xy);
|
|
static void KDTreeQueryResultsTags(CKDTreeShell &kdt,int &tags[]);
|
|
static void KDTreeQueryResultsDistances(CKDTreeShell &kdt,double &r[]);
|
|
static void KDTreeQueryResultsXI(CKDTreeShell &kdt,CMatrixDouble &x);
|
|
static void KDTreeQueryResultsXYI(CKDTreeShell &kdt,CMatrixDouble &xy);
|
|
static void KDTreeQueryResultsTagsI(CKDTreeShell &kdt,int &tags[]);
|
|
static void KDTreeQueryResultsDistancesI(CKDTreeShell &kdt,double &r[]);
|
|
//--- function of package dataanalysis
|
|
//--- data analysis
|
|
static void DSOptimalSplit2(double &a[],int &c[],const int n,int &info,double &threshold,double &pal,double &pbl,double &par,double &pbr,double &cve);
|
|
static void DSOptimalSplit2Fast(double &a[],int &c[],int &tiesbuf[],int &cntbuf[],double &bufr[],int &bufi[],const int n,const int nc,const double alpha,int &info,double &threshold,double &rms,double &cvrms);
|
|
//--- decision forest
|
|
static void DFSerialize(CDecisionForestShell &obj,string &s_out);
|
|
static void DFUnserialize(const string s_in,CDecisionForestShell &obj);
|
|
static void DFBuildRandomDecisionForest(CMatrixDouble &xy,const int npoints,const int nvars,const int nclasses,const int ntrees,const double r,int &info,CDecisionForestShell &df,CDFReportShell &rep);
|
|
static void DFBuildRandomDecisionForestX1(CMatrixDouble &xy,const int npoints,const int nvars,const int nclasses,const int ntrees,int nrndvars,const double r,int &info,CDecisionForestShell &df,CDFReportShell &rep);
|
|
static void DFProcess(CDecisionForestShell &df,double &x[],double &y[]);
|
|
static void DFProcessI(CDecisionForestShell &df,double &x[],double &y[]);
|
|
static double DFRelClsError(CDecisionForestShell &df,CMatrixDouble &xy,const int npoints);
|
|
static double DFAvgCE(CDecisionForestShell &df,CMatrixDouble &xy,const int npoints);
|
|
static double DFRMSError(CDecisionForestShell &df,CMatrixDouble &xy,const int npoints);
|
|
static double DFAvgError(CDecisionForestShell &df,CMatrixDouble &xy,const int npoints);
|
|
static double DFAvgRelError(CDecisionForestShell &df,CMatrixDouble &xy,const int npoints);
|
|
//--- middle and clusterization
|
|
static void KMeansGenerate(CMatrixDouble &xy,const int npoints,const int nvars,const int k,const int restarts,int &info,CMatrixDouble &c,int &xyc[]);
|
|
//--- Fisher LDA functions
|
|
static void FisherLDA(CMatrixDouble &xy,const int npoints,const int nvars,const int nclasses,int &info,double &w[]);
|
|
static void FisherLDAN(CMatrixDouble &xy,const int npoints,const int nvars,const int nclasses,int &info,CMatrixDouble &w);
|
|
//--- linear regression
|
|
static void LRBuild(CMatrixDouble &xy,const int npoints,const int nvars,int &info,CLinearModelShell &lm,CLRReportShell &ar);
|
|
static void LRBuildS(CMatrixDouble &xy,double &s[],const int npoints,const int nvars,int &info,CLinearModelShell &lm,CLRReportShell &ar);
|
|
static void LRBuildZS(CMatrixDouble &xy,double &s[],const int npoints,const int nvars,int &info,CLinearModelShell &lm,CLRReportShell &ar);
|
|
static void LRBuildZ(CMatrixDouble &xy,const int npoints,const int nvars,int &info,CLinearModelShell &lm,CLRReportShell &ar);
|
|
static void LRUnpack(CLinearModelShell &lm,double &v[],int &nvars);
|
|
static void LRPack(double &v[],const int nvars,CLinearModelShell &lm);
|
|
static double LRProcess(CLinearModelShell &lm,double &x[]);
|
|
static double LRRMSError(CLinearModelShell &lm,CMatrixDouble &xy,const int npoints);
|
|
static double LRAvgError(CLinearModelShell &lm,CMatrixDouble &xy,const int npoints);
|
|
static double LRAvgRelError(CLinearModelShell &lm,CMatrixDouble &xy,const int npoints);
|
|
//--- multilayer perceptron
|
|
static void MLPSerialize(CMultilayerPerceptronShell &obj,string &s_out);
|
|
static void MLPUnserialize(const string s_in,CMultilayerPerceptronShell &obj);
|
|
static void MLPCreate0(const int nin,const int nout,CMultilayerPerceptronShell &network);
|
|
static void MLPCreate1(const int nin,int nhid,const int nout,CMultilayerPerceptronShell &network);
|
|
static void MLPCreate2(const int nin,const int nhid1,const int nhid2,const int nout,CMultilayerPerceptronShell &network);
|
|
static void MLPCreateB0(const int nin,const int nout,const double b,const double d,CMultilayerPerceptronShell &network);
|
|
static void MLPCreateB1(const int nin,int nhid,const int nout,const double b,const double d,CMultilayerPerceptronShell &network);
|
|
static void MLPCreateB2(const int nin,const int nhid1,const int nhid2,const int nout,const double b,const double d,CMultilayerPerceptronShell &network);
|
|
static void MLPCreateR0(const int nin,const int nout,double a,const double b,CMultilayerPerceptronShell &network);
|
|
static void MLPCreateR1(const int nin,int nhid,const int nout,const double a,const double b,CMultilayerPerceptronShell &network);
|
|
static void MLPCreateR2(const int nin,const int nhid1,const int nhid2,const int nout,const double a,const double b,CMultilayerPerceptronShell &network);
|
|
static void MLPCreateC0(const int nin,const int nout,CMultilayerPerceptronShell &network);
|
|
static void MLPCreateC1(const int nin,int nhid,const int nout,CMultilayerPerceptronShell &network);
|
|
static void MLPCreateC2(const int nin,const int nhid1,const int nhid2,const int nout,CMultilayerPerceptronShell &network);
|
|
static void MLPRandomize(CMultilayerPerceptronShell &network);
|
|
static void MLPRandomizeFull(CMultilayerPerceptronShell &network);
|
|
static void MLPProperties(CMultilayerPerceptronShell &network,int &nin,int &nout,int &wcount);
|
|
static bool MLPIsSoftMax(CMultilayerPerceptronShell &network);
|
|
static int MLPGetLayersCount(CMultilayerPerceptronShell &network);
|
|
static int MLPGetLayerSize(CMultilayerPerceptronShell &network,const int k);
|
|
static void MLPGetInputScaling(CMultilayerPerceptronShell &network,const int i,double &mean,double &sigma);
|
|
static void MLPGetOutputScaling(CMultilayerPerceptronShell &network,const int i,double &mean,double &sigma);
|
|
static void MLPGetNeuronInfo(CMultilayerPerceptronShell &network,const int k,const int i,int &fkind,double &threshold);
|
|
static double MLPGetWeight(CMultilayerPerceptronShell &network,const int k0,const int i0,const int k1,const int i1);
|
|
static void MLPSetInputScaling(CMultilayerPerceptronShell &network,const int i,const double mean,const double sigma);
|
|
static void MLPSetOutputScaling(CMultilayerPerceptronShell &network,const int i,const double mean,const double sigma);
|
|
static void MLPSetNeuronInfo(CMultilayerPerceptronShell &network,const int k,const int i,int fkind,double threshold);
|
|
static void MLPSetWeight(CMultilayerPerceptronShell &network,const int k0,const int i0,const int k1,const int i1,const double w);
|
|
static void MLPActivationFunction(const double net,const int k,double &f,double &df,double &d2f);
|
|
static void MLPProcess(CMultilayerPerceptronShell &network,double &x[],double &y[]);
|
|
static void MLPProcessI(CMultilayerPerceptronShell &network,double &x[],double &y[]);
|
|
static double MLPError(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int ssize);
|
|
static double MLPErrorN(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int ssize);
|
|
static int MLPClsError(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int ssize);
|
|
static double MLPRelClsError(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int npoints);
|
|
static double MLPAvgCE(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int npoints);
|
|
static double MLPRMSError(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int npoints);
|
|
static double MLPAvgError(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int npoints);
|
|
static double MLPAvgRelError(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int npoints);
|
|
static void MLPGrad(CMultilayerPerceptronShell &network,double &x[],double &desiredy[],double &e,double &grad[]);
|
|
static void MLPGradN(CMultilayerPerceptronShell &network,double &x[],double &desiredy[],double &e,double &grad[]);
|
|
static void MLPGradBatch(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int ssize,double &e,double &grad[]);
|
|
static void MLPGradNBatch(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int ssize,double &e,double &grad[]);
|
|
static void MLPHessianNBatch(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int ssize,double &e,double &grad[],CMatrixDouble &h);
|
|
static void MLPHessianBatch(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int ssize,double &e,double &grad[],CMatrixDouble &h);
|
|
//--- logit model functions
|
|
static void MNLTrainH(CMatrixDouble &xy,const int npoints,const int nvars,const int nclasses,int &info,CLogitModelShell &lm,CMNLReportShell &rep);
|
|
static void MNLProcess(CLogitModelShell &lm,double &x[],double &y[]);
|
|
static void MNLProcessI(CLogitModelShell &lm,double &x[],double &y[]);
|
|
static void MNLUnpack(CLogitModelShell &lm,CMatrixDouble &a,int &nvars,int &nclasses);
|
|
static void MNLPack(CMatrixDouble &a,const int nvars,const int nclasses,CLogitModelShell &lm);
|
|
static double MNLAvgCE(CLogitModelShell &lm,CMatrixDouble &xy,const int npoints);
|
|
static double MNLRelClsError(CLogitModelShell &lm,CMatrixDouble &xy,const int npoints);
|
|
static double MNLRMSError(CLogitModelShell &lm,CMatrixDouble &xy,const int npoints);
|
|
static double MNLAvgError(CLogitModelShell &lm,CMatrixDouble &xy,const int npoints);
|
|
static double MNLAvgRelError(CLogitModelShell &lm,CMatrixDouble &xy,const int ssize);
|
|
static int MNLClsError(CLogitModelShell &lm,CMatrixDouble &xy,const int npoints);
|
|
//--- Markov chains
|
|
static void MCPDCreate(const int n,CMCPDStateShell &s);
|
|
static void MCPDCreateEntry(const int n,const int entrystate,CMCPDStateShell &s);
|
|
static void MCPDCreateExit(const int n,const int exitstate,CMCPDStateShell &s);
|
|
static void MCPDCreateEntryExit(const int n,const int entrystate,const int exitstate,CMCPDStateShell &s);
|
|
static void MCPDAddTrack(CMCPDStateShell &s,CMatrixDouble &xy,const int k);
|
|
static void MCPDAddTrack(CMCPDStateShell &s,CMatrixDouble &xy);
|
|
static void MCPDSetEC(CMCPDStateShell &s,CMatrixDouble &ec);
|
|
static void MCPDAddEC(CMCPDStateShell &s,const int i,const int j,const double c);
|
|
static void MCPDSetBC(CMCPDStateShell &s,CMatrixDouble &bndl,CMatrixDouble &bndu);
|
|
static void MCPDAddBC(CMCPDStateShell &s,const int i,const int j,const double bndl,const double bndu);
|
|
static void MCPDSetLC(CMCPDStateShell &s,CMatrixDouble &c,int &ct[],const int k);
|
|
static void MCPDSetLC(CMCPDStateShell &s,CMatrixDouble &c,int &ct[]);
|
|
static void MCPDSetTikhonovRegularizer(CMCPDStateShell &s,const double v);
|
|
static void MCPDSetPrior(CMCPDStateShell &s,CMatrixDouble &pp);
|
|
static void MCPDSetPredictionWeights(CMCPDStateShell &s,double &pw[]);
|
|
static void MCPDSolve(CMCPDStateShell &s);
|
|
static void MCPDResults(CMCPDStateShell &s,CMatrixDouble &p,CMCPDReportShell &rep);
|
|
//--- training neural networks
|
|
static void MLPTrainLM(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int npoints,const double decay,const int restarts,int &info,CMLPReportShell &rep);
|
|
static void MLPTrainLBFGS(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int npoints,const double decay,const int restarts,const double wstep,int maxits,int &info,CMLPReportShell &rep);
|
|
static void MLPTrainES(CMultilayerPerceptronShell &network,CMatrixDouble &trnxy,const int trnsize,CMatrixDouble &valxy,const int valsize,const double decay,const int restarts,int &info,CMLPReportShell &rep);
|
|
static void MLPKFoldCVLBFGS(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int npoints,const double decay,const int restarts,const double wstep,const int maxits,const int foldscount,int &info,CMLPReportShell &rep,CMLPCVReportShell &cvrep);
|
|
static void MLPKFoldCVLM(CMultilayerPerceptronShell &network,CMatrixDouble &xy,const int npoints,const double decay,const int restarts,const int foldscount,int &info,CMLPReportShell &rep,CMLPCVReportShell &cvrep);
|
|
//--- neural networks ensemble functions
|
|
static void MLPECreate0(const int nin,const int nout,const int ensemblesize,CMLPEnsembleShell &ensemble);
|
|
static void MLPECreate1(const int nin,int nhid,const int nout,const int ensemblesize,CMLPEnsembleShell &ensemble);
|
|
static void MLPECreate2(const int nin,const int nhid1,const int nhid2,const int nout,const int ensemblesize,CMLPEnsembleShell &ensemble);
|
|
static void MLPECreateB0(const int nin,const int nout,const double b,const double d,const int ensemblesize,CMLPEnsembleShell &ensemble);
|
|
static void MLPECreateB1(const int nin,int nhid,const int nout,const double b,const double d,const int ensemblesize,CMLPEnsembleShell &ensemble);
|
|
static void MLPECreateB2(const int nin,const int nhid1,const int nhid2,const int nout,const double b,const double d,const int ensemblesize,CMLPEnsembleShell &ensemble);
|
|
static void MLPECreateR0(const int nin,const int nout,const double a,const double b,const int ensemblesize,CMLPEnsembleShell &ensemble);
|
|
static void MLPECreateR1(const int nin,int nhid,const int nout,const double a,const double b,const int ensemblesize,CMLPEnsembleShell &ensemble);
|
|
static void MLPECreateR2(const int nin,const int nhid1,const int nhid2,const int nout,const double a,const double b,const int ensemblesize,CMLPEnsembleShell &ensemble);
|
|
static void MLPECreateC0(const int nin,const int nout,const int ensemblesize,CMLPEnsembleShell &ensemble);
|
|
static void MLPECreateC1(const int nin,int nhid,const int nout,const int ensemblesize,CMLPEnsembleShell &ensemble);
|
|
static void MLPECreateC2(const int nin,const int nhid1,const int nhid2,const int nout,const int ensemblesize,CMLPEnsembleShell &ensemble);
|
|
static void MLPECreateFromNetwork(CMultilayerPerceptronShell &network,const int ensemblesize,CMLPEnsembleShell &ensemble);
|
|
static void MLPERandomize(CMLPEnsembleShell &ensemble);
|
|
static void MLPEProperties(CMLPEnsembleShell &ensemble,int &nin,int &nout);
|
|
static bool MLPEIsSoftMax(CMLPEnsembleShell &ensemble);
|
|
static void MLPEProcess(CMLPEnsembleShell &ensemble,double &x[],double &y[]);
|
|
static void MLPEProcessI(CMLPEnsembleShell &ensemble,double &x[],double &y[]);
|
|
static double MLPERelClsError(CMLPEnsembleShell &ensemble,CMatrixDouble &xy,const int npoints);
|
|
static double MLPEAvgCE(CMLPEnsembleShell &ensemble,CMatrixDouble &xy,const int npoints);
|
|
static double MLPERMSError(CMLPEnsembleShell &ensemble,CMatrixDouble &xy,const int npoints);
|
|
static double MLPEAvgError(CMLPEnsembleShell &ensemble,CMatrixDouble &xy,const int npoints);
|
|
static double MLPEAvgRelError(CMLPEnsembleShell &ensemble,CMatrixDouble &xy,const int npoints);
|
|
static void MLPEBaggingLM(CMLPEnsembleShell &ensemble,CMatrixDouble &xy,const int npoints,const double decay,const int restarts,int &info,CMLPReportShell &rep,CMLPCVReportShell &ooberrors);
|
|
static void MLPEBaggingLBFGS(CMLPEnsembleShell &ensemble,CMatrixDouble &xy,const int npoints,const double decay,const int restarts,const double wstep,const int maxits,int &info,CMLPReportShell &rep,CMLPCVReportShell &ooberrors);
|
|
static void MLPETrainES(CMLPEnsembleShell &ensemble,CMatrixDouble &xy,const int npoints,const double decay,const int restarts,int &info,CMLPReportShell &rep);
|
|
//--- principal components analysis
|
|
static void PCABuildBasis(CMatrixDouble &x,const int npoints,const int nvars,int &info,double &s2[],CMatrixDouble &v);
|
|
//--- function of package diffequations
|
|
static void ODESolverRKCK(double &y[],const int n,double &x[],const int m,const double eps,const double h,CODESolverStateShell &state);
|
|
static void ODESolverRKCK(double &y[],double &x[],const double eps,const double h,CODESolverStateShell &state);
|
|
static bool ODESolverIteration(CODESolverStateShell &state);
|
|
static void ODESolverSolve(CODESolverStateShell &state,CNDimensional_ODE_RP &diff,CObject &obj);
|
|
static void ODESolverResults(CODESolverStateShell &state,int &m,double &xtbl[],CMatrixDouble &ytbl,CODESolverReportShell &rep);
|
|
//--- function of package fasttransforms
|
|
//--- fast Fourier transform
|
|
static void FFTC1D(complex &a[],const int n);
|
|
static void FFTC1D(complex &a[]);
|
|
static void FFTC1DInv(complex &a[],const int n);
|
|
static void FFTC1DInv(complex &a[]);
|
|
static void FFTR1D(double &a[],const int n,complex &f[]);
|
|
static void FFTR1D(double &a[],complex &f[]);
|
|
static void FFTR1DInv(complex &f[],const int n,double &a[]);
|
|
static void FFTR1DInv(complex &f[],double &a[]);
|
|
//--- convolution
|
|
static void ConvC1D(complex &a[],const int m,complex &b[],const int n,complex &r[]);
|
|
static void ConvC1DInv(complex &a[],const int m,complex &b[],const int n,complex &r[]);
|
|
static void ConvC1DCircular(complex &s[],const int m,complex &r[],const int n,complex &c[]);
|
|
static void ConvC1DCircularInv(complex &a[],const int m,complex &b[],const int n,complex &r[]);
|
|
static void ConvR1D(double &a[],const int m,double &b[],const int n,double &r[]);
|
|
static void ConvR1DInv(double &a[],const int m,double &b[],const int n,double &r[]);
|
|
static void ConvR1DCircular(double &s[],const int m,double &r[],const int n,double &c[]);
|
|
static void ConvR1DCircularInv(double &a[],const int m,double &b[],const int n,double &r[]);
|
|
static void CorrC1D(complex &signal[],const int n,complex &pattern[],const int m,complex &r[]);
|
|
static void CorrC1DCircular(complex &signal[],const int m,complex &pattern[],const int n,complex &c[]);
|
|
static void CorrR1D(double &signal[],const int n,double &pattern[],const int m,double &r[]);
|
|
static void CorrR1DCircular(double &signal[],const int m,double &pattern[],const int n,double &c[]);
|
|
//--- fast Hartley transform
|
|
static void FHTR1D(double &a[],const int n);
|
|
static void FHTR1DInv(double &a[],const int n);
|
|
//--- function of package integration
|
|
//--- Gauss quadrature formula
|
|
static void GQGenerateRec(double &alpha[],double &beta[],const double mu0,const int n,int &info,double &x[],double &w[]);
|
|
static void GQGenerateGaussLobattoRec(double &alpha[],double &beta[],const double mu0,const double a,const double b,const int n,int &info,double &x[],double &w[]);
|
|
static void GQGenerateGaussRadauRec(double &alpha[],double &beta[],const double mu0,const double a,const int n,int &info,double &x[],double &w[]);
|
|
static void GQGenerateGaussLegendre(const int n,int &info,double &x[],double &w[]);
|
|
static void GQGenerateGaussJacobi(const int n,const double alpha,const double beta,int &info,double &x[],double &w[]);
|
|
static void GQGenerateGaussLaguerre(const int n,const double alpha,int &info,double &x[],double &w[]);
|
|
static void GQGenerateGaussHermite(const int n,int &info,double &x[],double &w[]);
|
|
//--- Gauss-Kronrod quadrature formula
|
|
static void GKQGenerateRec(double &alpha[],double &beta[],const double mu0,const int n,int &info,double &x[],double &wkronrod[],double &wgauss[]);
|
|
static void GKQGenerateGaussLegendre(const int n,int &info,double &x[],double &wkronrod[],double &wgauss[]);
|
|
static void GKQGenerateGaussJacobi(const int n,const double alpha,const double beta,int &info,double &x[],double &wkronrod[],double &wgauss[]);
|
|
static void GKQLegendreCalc(const int n,int &info,double &x[],double &wkronrod[],double &wgauss[]);
|
|
static void GKQLegendreTbl(const int n,double &x[],double &wkronrod[],double &wgauss[],double &eps);
|
|
//--- auto Gauss-Kronrod
|
|
static void AutoGKSmooth(const double a,const double b,CAutoGKStateShell &state);
|
|
static void AutoGKSmoothW(const double a,const double b,double xwidth,CAutoGKStateShell &state);
|
|
static void AutoGKSingular(const double a,const double b,const double alpha,const double beta,CAutoGKStateShell &state);
|
|
static bool AutoGKIteration(CAutoGKStateShell &state);
|
|
static void AutoGKIntegrate(CAutoGKStateShell &state,CIntegrator1_Func &func,CObject &obj);
|
|
static void AutoGKResults(CAutoGKStateShell &state,double &v,CAutoGKReportShell &rep);
|
|
//--- function of package interpolation
|
|
//--- inverse distance weighting interpolation
|
|
static double IDWCalc(CIDWInterpolantShell &z,double &x[]);
|
|
static void IDWBuildModifiedShepard(CMatrixDouble &xy,const int n,const int nx,const int d,const int nq,const int nw,CIDWInterpolantShell &z);
|
|
static void IDWBuildModifiedShepardR(CMatrixDouble &xy,const int n,const int nx,const double r,CIDWInterpolantShell &z);
|
|
static void IDWBuildNoisy(CMatrixDouble &xy,const int n,const int nx,const int d,const int nq,const int nw,CIDWInterpolantShell &z);
|
|
//--- rational interpolation
|
|
static double BarycentricCalc(CBarycentricInterpolantShell &b,const double t);
|
|
static void BarycentricDiff1(CBarycentricInterpolantShell &b,const double t,double &f,double &df);
|
|
static void BarycentricDiff2(CBarycentricInterpolantShell &b,const double t,double &f,double &df,double &d2f);
|
|
static void BarycentricLinTransX(CBarycentricInterpolantShell &b,const double ca,const double cb);
|
|
static void BarycentricLinTransY(CBarycentricInterpolantShell &b,const double ca,const double cb);
|
|
static void BarycentricUnpack(CBarycentricInterpolantShell &b,int &n,double &x[],double &y[],double &w[]);
|
|
static void BarycentricBuildXYW(double &x[],double &y[],double &w[],const int n,CBarycentricInterpolantShell &b);
|
|
static void BarycentricBuildFloaterHormann(double &x[],double &y[],const int n,const int d,CBarycentricInterpolantShell &b);
|
|
//--- polynomial interpolant
|
|
static void PolynomialBar2Cheb(CBarycentricInterpolantShell &p,const double a,const double b,double &t[]);
|
|
static void PolynomialCheb2Bar(double &t[],const int n,const double a,const double b,CBarycentricInterpolantShell &p);
|
|
static void PolynomialCheb2Bar(double &t[],const double a,const double b,CBarycentricInterpolantShell &p);
|
|
static void PolynomialBar2Pow(CBarycentricInterpolantShell &p,const double c,const double s,double &a[]);
|
|
static void PolynomialBar2Pow(CBarycentricInterpolantShell &p,double &a[]);
|
|
static void PolynomialPow2Bar(double &a[],const int n,const double c,const double s,CBarycentricInterpolantShell &p);
|
|
static void PolynomialPow2Bar(double &a[],CBarycentricInterpolantShell &p);
|
|
static void PolynomialBuild(double &x[],double &y[],const int n,CBarycentricInterpolantShell &p);
|
|
static void PolynomialBuild(double &x[],double &y[],CBarycentricInterpolantShell &p);
|
|
static void PolynomialBuildEqDist(const double a,const double b,double &y[],const int n,CBarycentricInterpolantShell &p);
|
|
static void PolynomialBuildEqDist(const double a,const double b,double &y[],CBarycentricInterpolantShell &p);
|
|
static void PolynomialBuildCheb1(const double a,const double b,double &y[],const int n,CBarycentricInterpolantShell &p);
|
|
static void PolynomialBuildCheb1(const double a,const double b,double &y[],CBarycentricInterpolantShell &p);
|
|
static void PolynomialBuildCheb2(const double a,const double b,double &y[],const int n,CBarycentricInterpolantShell &p);
|
|
static void PolynomialBuildCheb2(const double a,const double b,double &y[],CBarycentricInterpolantShell &p);
|
|
static double PolynomialCalcEqDist(const double a,const double b,double &f[],const int n,const double t);
|
|
static double PolynomialCalcEqDist(const double a,const double b,double &f[],const double t);
|
|
static double PolynomialCalcCheb1(const double a,const double b,double &f[],const int n,const double t);
|
|
static double PolynomialCalcCheb1(const double a,const double b,double &f[],const double t);
|
|
static double PolynomialCalcCheb2(const double a,const double b,double &f[],const int n,const double t);
|
|
static double PolynomialCalcCheb2(const double a,const double b,double &f[],const double t);
|
|
//--- 1-dimensional spline interpolation
|
|
static void Spline1DBuildLinear(double &x[],double &y[],const int n,CSpline1DInterpolantShell &c);
|
|
static void Spline1DBuildLinear(double &x[],double &y[],CSpline1DInterpolantShell &c);
|
|
static void Spline1DBuildCubic(double &x[],double &y[],const int n,const int boundltype,const double boundl,const int boundrtype,const double boundr,CSpline1DInterpolantShell &c);
|
|
static void Spline1DBuildCubic(double &x[],double &y[],CSpline1DInterpolantShell &c);
|
|
static void Spline1DGridDiffCubic(double &x[],double &y[],const int n,const int boundltype,const double boundl,const int boundrtype,const double boundr,double &d[]);
|
|
static void Spline1DGridDiffCubic(double &x[],double &y[],double &d[]);
|
|
static void Spline1DGridDiff2Cubic(double &x[],double &y[],const int n,const int boundltype,const double boundl,const int boundrtype,const double boundr,double &d1[],double &d2[]);
|
|
static void Spline1DGridDiff2Cubic(double &x[],double &y[],double &d1[],double &d2[]);
|
|
static void Spline1DConvCubic(double &x[],double &y[],const int n,const int boundltype,const double boundl,const int boundrtype,const double boundr,double &x2[],int n2,double &y2[]);
|
|
static void Spline1DConvCubic(double &x[],double &y[],double &x2[],double &y2[]);
|
|
static void Spline1DConvDiffCubic(double &x[],double &y[],const int n,const int boundltype,const double boundl,const int boundrtype,const double boundr,double &x2[],int n2,double &y2[],double &d2[]);
|
|
static void Spline1DConvDiffCubic(double &x[],double &y[],double &x2[],double &y2[],double &d2[]);
|
|
static void Spline1DConvDiff2Cubic(double &x[],double &y[],const int n,const int boundltype,const double boundl,const int boundrtype,const double boundr,double &x2[],const int n2,double &y2[],double &d2[],double &dd2[]);
|
|
static void Spline1DConvDiff2Cubic(double &x[],double &y[],double &x2[],double &y2[],double &d2[],double &dd2[]);
|
|
static void Spline1DBuildCatmullRom(double &x[],double &y[],const int n,const int boundtype,const double tension,CSpline1DInterpolantShell &c);
|
|
static void Spline1DBuildCatmullRom(double &x[],double &y[],CSpline1DInterpolantShell &c);
|
|
static void Spline1DBuildHermite(double &x[],double &y[],double &d[],const int n,CSpline1DInterpolantShell &c);
|
|
static void Spline1DBuildHermite(double &x[],double &y[],double &d[],CSpline1DInterpolantShell &c);
|
|
static void Spline1DBuildAkima(double &x[],double &y[],const int n,CSpline1DInterpolantShell &c);
|
|
static void Spline1DBuildAkima(double &x[],double &y[],CSpline1DInterpolantShell &c);
|
|
static double Spline1DCalc(CSpline1DInterpolantShell &c,const double x);
|
|
static void Spline1DDiff(CSpline1DInterpolantShell &c,const double x,double &s,double &ds,double &d2s);
|
|
static void Spline1DUnpack(CSpline1DInterpolantShell &c,int &n,CMatrixDouble &tbl);
|
|
static void Spline1DLinTransX(CSpline1DInterpolantShell &c,const double a,const double b);
|
|
static void Spline1DLinTransY(CSpline1DInterpolantShell &c,const double a,const double b);
|
|
static double Spline1DIntegrate(CSpline1DInterpolantShell &c,const double x);
|
|
//--- least squares fitting
|
|
static void PolynomialFit(double &x[],double &y[],const int n,const int m,int &info,CBarycentricInterpolantShell &p,CPolynomialFitReportShell &rep);
|
|
static void PolynomialFit(double &x[],double &y[],const int m,int &info,CBarycentricInterpolantShell &p,CPolynomialFitReportShell &rep);
|
|
static void PolynomialFitWC(double &x[],double &y[],double &w[],const int n,double &xc[],double &yc[],int &dc[],const int k,const int m,int &info,CBarycentricInterpolantShell &p,CPolynomialFitReportShell &rep);
|
|
static void PolynomialFitWC(double &x[],double &y[],double &w[],double &xc[],double &yc[],int &dc[],const int m,int &info,CBarycentricInterpolantShell &p,CPolynomialFitReportShell &rep);
|
|
static void BarycentricFitFloaterHormannWC(double &x[],double &y[],double &w[],const int n,double &xc[],double &yc[],int &dc[],const int k,const int m,int &info,CBarycentricInterpolantShell &b,CBarycentricFitReportShell &rep);
|
|
static void BarycentricFitFloaterHormann(double &x[],double &y[],const int n,const int m,int &info,CBarycentricInterpolantShell &b,CBarycentricFitReportShell &rep);
|
|
static void Spline1DFitPenalized(double &x[],double &y[],const int n,const int m,const double rho,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep);
|
|
static void Spline1DFitPenalized(double &x[],double &y[],const int m,const double rho,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep);
|
|
static void Spline1DFitPenalizedW(double &x[],double &y[],double &w[],const int n,const int m,const double rho,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep);
|
|
static void Spline1DFitPenalizedW(double &x[],double &y[],double &w[],const int m,const double rho,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep);
|
|
static void Spline1DFitCubicWC(double &x[],double &y[],double &w[],const int n,double &xc[],double &yc[],int &dc[],const int k,const int m,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep);
|
|
static void Spline1DFitCubicWC(double &x[],double &y[],double &w[],double &xc[],double &yc[],int &dc[],const int m,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep);
|
|
static void Spline1DFitHermiteWC(double &x[],double &y[],double &w[],const int n,double &xc[],double &yc[],int &dc[],const int k,const int m,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep);
|
|
static void Spline1DFitHermiteWC(double &x[],double &y[],double &w[],double &xc[],double &yc[],int &dc[],const int m,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep);
|
|
static void Spline1DFitCubic(double &x[],double &y[],const int n,const int m,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep);
|
|
static void Spline1DFitCubic(double &x[],double &y[],const int m,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep);
|
|
static void Spline1DFitHermite(double &x[],double &y[],const int n,const int m,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep);
|
|
static void Spline1DFitHermite(double &x[],double &y[],const int m,int &info,CSpline1DInterpolantShell &s,CSpline1DFitReportShell &rep);
|
|
static void LSFitLinearW(double &y[],double &w[],CMatrixDouble &fmatrix,const int n,const int m,int &info,double &c[],CLSFitReportShell &rep);
|
|
static void LSFitLinearW(double &y[],double &w[],CMatrixDouble &fmatrix,int &info,double &c[],CLSFitReportShell &rep);
|
|
static void LSFitLinearWC(double &y[],double &w[],CMatrixDouble &fmatrix,CMatrixDouble &cmatrix,const int n,const int m,const int k,int &info,double &c[],CLSFitReportShell &rep);
|
|
static void LSFitLinearWC(double &y[],double &w[],CMatrixDouble &fmatrix,CMatrixDouble &cmatrix,int &info,double &c[],CLSFitReportShell &rep);
|
|
static void LSFitLinear(double &y[],CMatrixDouble &fmatrix,const int n,const int m,int &info,double &c[],CLSFitReportShell &rep);
|
|
static void LSFitLinear(double &y[],CMatrixDouble &fmatrix,int &info,double &c[],CLSFitReportShell &rep);
|
|
static void LSFitLinearC(double &y[],CMatrixDouble &fmatrix,CMatrixDouble &cmatrix,const int n,const int m,const int k,int &info,double &c[],CLSFitReportShell &rep);
|
|
static void LSFitLinearC(double &y[],CMatrixDouble &fmatrix,CMatrixDouble &cmatrix,int &info,double &c[],CLSFitReportShell &rep);
|
|
static void LSFitCreateWF(CMatrixDouble &x,double &y[],double &w[],double &c[],const int n,const int m,const int k,const double diffstep,CLSFitStateShell &state);
|
|
static void LSFitCreateWF(CMatrixDouble &x,double &y[],double &w[],double &c[],const double diffstep,CLSFitStateShell &state);
|
|
static void LSFitCreateF(CMatrixDouble &x,double &y[],double &c[],const int n,const int m,const int k,const double diffstep,CLSFitStateShell &state);
|
|
static void LSFitCreateF(CMatrixDouble &x,double &y[],double &c[],const double diffstep,CLSFitStateShell &state);
|
|
static void LSFitCreateWFG(CMatrixDouble &x,double &y[],double &w[],double &c[],const int n,const int m,const int k,const bool cheapfg,CLSFitStateShell &state);
|
|
static void LSFitCreateWFG(CMatrixDouble &x,double &y[],double &w[],double &c[],const bool cheapfg,CLSFitStateShell &state);
|
|
static void LSFitCreateFG(CMatrixDouble &x,double &y[],double &c[],const int n,const int m,const int k,const bool cheapfg,CLSFitStateShell &state);
|
|
static void LSFitCreateFG(CMatrixDouble &x,double &y[],double &c[],const bool cheapfg,CLSFitStateShell &state);
|
|
static void LSFitCreateWFGH(CMatrixDouble &x,double &y[],double &w[],double &c[],const int n,const int m,const int k,CLSFitStateShell &state);
|
|
static void LSFitCreateWFGH(CMatrixDouble &x,double &y[],double &w[],double &c[],CLSFitStateShell &state);
|
|
static void LSFitCreateFGH(CMatrixDouble &x,double &y[],double &c[],const int n,const int m,const int k,CLSFitStateShell &state);
|
|
static void LSFitCreateFGH(CMatrixDouble &x,double &y[],double &c[],CLSFitStateShell &state);
|
|
static void LSFitSetCond(CLSFitStateShell &state,const double epsf,const double epsx,const int maxits);
|
|
static void LSFitSetStpMax(CLSFitStateShell &state,const double stpmax);
|
|
static void LSFitSetXRep(CLSFitStateShell &state,const bool needxrep);
|
|
static void LSFitSetScale(CLSFitStateShell &state,double &s[]);
|
|
static void LSFitSetBC(CLSFitStateShell &state,double &bndl[],double &bndu[]);
|
|
static bool LSFitIteration(CLSFitStateShell &state);
|
|
static void LSFitFit(CLSFitStateShell &state,CNDimensional_PFunc &func,CNDimensional_Rep &rep,bool rep_status,CObject &obj);
|
|
static void LSFitFit(CLSFitStateShell &state,CNDimensional_PFunc &func,CNDimensional_PGrad &grad,CNDimensional_Rep &rep,bool rep_status,CObject &obj);
|
|
static void LSFitFit(CLSFitStateShell &state,CNDimensional_PFunc &func,CNDimensional_PGrad &grad,CNDimensional_PHess &hess,CNDimensional_Rep &rep,bool rep_status,CObject &obj);
|
|
static void LSFitResults(CLSFitStateShell &state,int &info,double &c[],CLSFitReportShell &rep);
|
|
//--- parametric spline
|
|
static void PSpline2Build(CMatrixDouble &xy,const int n,const int st,const int pt,CPSpline2InterpolantShell &p);
|
|
static void PSpline3Build(CMatrixDouble &xy,const int n,const int st,const int pt,CPSpline3InterpolantShell &p);
|
|
static void PSpline2BuildPeriodic(CMatrixDouble &xy,const int n,const int st,const int pt,CPSpline2InterpolantShell &p);
|
|
static void PSpline3BuildPeriodic(CMatrixDouble &xy,const int n,const int st,const int pt,CPSpline3InterpolantShell &p);
|
|
static void PSpline2ParameterValues(CPSpline2InterpolantShell &p,int &n,double &t[]);
|
|
static void PSpline3ParameterValues(CPSpline3InterpolantShell &p,int &n,double &t[]);
|
|
static void PSpline2Calc(CPSpline2InterpolantShell &p,const double t,double &x,double &y);
|
|
static void PSpline3Calc(CPSpline3InterpolantShell &p,const double t,double &x,double &y,double &z);
|
|
static void PSpline2Tangent(CPSpline2InterpolantShell &p,const double t,double &x,double &y);
|
|
static void PSpline3Tangent(CPSpline3InterpolantShell &p,const double t,double &x,double &y,double &z);
|
|
static void PSpline2Diff(CPSpline2InterpolantShell &p,const double t,double &x,double &dx,double &y,double &dy);
|
|
static void PSpline3Diff(CPSpline3InterpolantShell &p,const double t,double &x,double &dx,double &y,double &dy,double &z,double &dz);
|
|
static void PSpline2Diff2(CPSpline2InterpolantShell &p,const double t,double &x,double &dx,double &d2x,double &y,double &dy,double &d2y);
|
|
static void PSpline3Diff2(CPSpline3InterpolantShell &p,const double t,double &x,double &dx,double &d2x,double &y,double &dy,double &d2y,double &z,double &dz,double &d2z);
|
|
static double PSpline2ArcLength(CPSpline2InterpolantShell &p,const double a,const double b);
|
|
static double PSpline3ArcLength(CPSpline3InterpolantShell &p,const double a,const double b);
|
|
//--- 2-dimensional spline interpolation
|
|
static void Spline2DBuildBilinear(double &x[],double &y[],CMatrixDouble &f,const int m,const int n,CSpline2DInterpolantShell &c);
|
|
static void Spline2DBuildBicubic(double &x[],double &y[],CMatrixDouble &f,const int m,const int n,CSpline2DInterpolantShell &c);
|
|
static double Spline2DCalc(CSpline2DInterpolantShell &c,const double x,const double y);
|
|
static void Spline2DDiff(CSpline2DInterpolantShell &c,const double x,const double y,double &f,double &fx,double &fy,double &fxy);
|
|
static void Spline2DUnpack(CSpline2DInterpolantShell &c,int &m,int &n,CMatrixDouble &tbl);
|
|
static void Spline2DLinTransXY(CSpline2DInterpolantShell &c,const double ax,const double bx,const double ay,const double by);
|
|
static void Spline2DLinTransF(CSpline2DInterpolantShell &c,const double a,const double b);
|
|
static void Spline2DResampleBicubic(CMatrixDouble &a,const int oldheight,const int oldwidth,CMatrixDouble &b,const int newheight,const int newwidth);
|
|
static void Spline2DResampleBilinear(CMatrixDouble &a,const int oldheight,const int oldwidth,CMatrixDouble &b,const int newheight,const int newwidth);
|
|
//--- function of package linalg
|
|
//--- working with matrix forms
|
|
static void CMatrixTranspose(const int m,const int n,CMatrixComplex &a,const int ia,const int ja,CMatrixComplex &b,const int ib,const int jb);
|
|
static void RMatrixTranspose(const int m,const int n,CMatrixDouble &a,const int ia,const int ja,CMatrixDouble &b,const int ib,const int jb);
|
|
static void CMatrixCopy(const int m,const int n,CMatrixComplex &a,const int ia,const int ja,CMatrixComplex &b,const int ib,const int jb);
|
|
static void RMatrixCopy(const int m,const int n,CMatrixDouble &a,const int ia,const int ja,CMatrixDouble &b,const int ib,const int jb);
|
|
static void CMatrixRank1(const int m,const int n,CMatrixComplex &a,const int ia,const int ja,complex &u[],const int iu,complex &v[],const int iv);
|
|
static void RMatrixRank1(const int m,const int n,CMatrixDouble &a,const int ia,const int ja,double &u[],const int iu,double &v[],const int iv);
|
|
static void CMatrixMVect(const int m,const int n,CMatrixComplex &a,const int ia,const int ja,const int opa,complex &x[],const int ix,complex &y[],const int iy);
|
|
static void RMatrixMVect(const int m,const int n,CMatrixDouble &a,const int ia,const int ja,const int opa,double &x[],const int ix,double &y[],const int iy);
|
|
static void CMatrixRightTrsM(const int m,const int n,CMatrixComplex &a,const int i1,const int j1,const bool isupper,const bool isunit,const int optype,CMatrixComplex &x,const int i2,const int j2);
|
|
static void CMatrixLeftTrsM(const int m,const int n,CMatrixComplex &a,const int i1,const int j1,const bool isupper,const bool isunit,const int optype,CMatrixComplex &x,const int i2,const int j2);
|
|
static void RMatrixRightTrsM(const int m,const int n,CMatrixDouble &a,const int i1,const int j1,const bool isupper,const bool isunit,const int optype,CMatrixDouble &x,const int i2,const int j2);
|
|
static void RMatrixLeftTrsM(const int m,const int n,CMatrixDouble &a,const int i1,const int j1,const bool isupper,const bool isunit,const int optype,CMatrixDouble &x,const int i2,const int j2);
|
|
static void CMatrixSyrk(const int n,const int k,const double alpha,CMatrixComplex &a,const int ia,const int ja,const int optypea,const double beta,CMatrixComplex &c,const int ic,const int jc,const bool isupper);
|
|
static void RMatrixSyrk(const int n,const int k,const double alpha,CMatrixDouble &a,const int ia,const int ja,const int optypea,const double beta,CMatrixDouble &c,const int ic,const int jc,const bool isupper);
|
|
static void CMatrixGemm(const int m,const int n,const int k,complex &alpha,CMatrixComplex &a,const int ia,const int ja,const int optypea,CMatrixComplex &b,const int ib,const int jb,const int optypeb,complex &beta,CMatrixComplex &c,const int ic,const int jc);
|
|
static void RMatrixGemm(const int m,const int n,const int k,const double alpha,CMatrixDouble &a,const int ia,const int ja,const int optypea,CMatrixDouble &b,const int ib,const int jb,const int optypeb,const double beta,CMatrixDouble &c,const int ic,const int jc);
|
|
//--- orthogonal factorizations
|
|
static void RMatrixQR(CMatrixDouble &a,const int m,const int n,double &tau[]);
|
|
static void RMatrixLQ(CMatrixDouble &a,const int m,const int n,double &tau[]);
|
|
static void CMatrixQR(CMatrixComplex &a,const int m,const int n,complex &tau[]);
|
|
static void CMatrixLQ(CMatrixComplex &a,const int m,const int n,complex &tau[]);
|
|
static void RMatrixQRUnpackQ(CMatrixDouble &a,const int m,const int n,double &tau[],const int qcolumns,CMatrixDouble &q);
|
|
static void RMatrixQRUnpackR(CMatrixDouble &a,const int m,const int n,CMatrixDouble &r);
|
|
static void RMatrixLQUnpackQ(CMatrixDouble &a,const int m,const int n,double &tau[],const int qrows,CMatrixDouble &q);
|
|
static void RMatrixLQUnpackL(CMatrixDouble &a,const int m,const int n,CMatrixDouble &l);
|
|
static void CMatrixQRUnpackQ(CMatrixComplex &a,const int m,const int n,complex &tau[],const int qcolumns,CMatrixComplex &q);
|
|
static void CMatrixQRUnpackR(CMatrixComplex &a,const int m,const int n,CMatrixComplex &r);
|
|
static void CMatrixLQUnpackQ(CMatrixComplex &a,const int m,const int n,complex &tau[],const int qrows,CMatrixComplex &q);
|
|
static void CMatrixLQUnpackL(CMatrixComplex &a,const int m,const int n,CMatrixComplex &l);
|
|
static void RMatrixBD(CMatrixDouble &a,const int m,const int n,double &tauq[],double &taup[]);
|
|
static void RMatrixBDUnpackQ(CMatrixDouble &qp,const int m,const int n,double &tauq[],const int qcolumns,CMatrixDouble &q);
|
|
static void RMatrixBDMultiplyByQ(CMatrixDouble &qp,const int m,const int n,double &tauq[],CMatrixDouble &z,const int zrows,const int zcolumns,const bool fromtheright,const bool dotranspose);
|
|
static void RMatrixBDUnpackPT(CMatrixDouble &qp,const int m,const int n,double &taup[],const int ptrows,CMatrixDouble &pt);
|
|
static void RMatrixBDMultiplyByP(CMatrixDouble &qp,const int m,const int n,double &taup[],CMatrixDouble &z,const int zrows,const int zcolumns,const bool fromtheright,const bool dotranspose);
|
|
static void RMatrixBDUnpackDiagonals(CMatrixDouble &b,const int m,const int n,bool &isupper,double &d[],double &e[]);
|
|
static void RMatrixHessenberg(CMatrixDouble &a,const int n,double &tau[]);
|
|
static void RMatrixHessenbergUnpackQ(CMatrixDouble &a,const int n,double &tau[],CMatrixDouble &q);
|
|
static void RMatrixHessenbergUnpackH(CMatrixDouble &a,const int n,CMatrixDouble &h);
|
|
static void SMatrixTD(CMatrixDouble &a,const int n,const bool isupper,double &tau[],double &d[],double &e[]);
|
|
static void SMatrixTDUnpackQ(CMatrixDouble &a,const int n,const bool isupper,double &tau[],CMatrixDouble &q);
|
|
static void HMatrixTD(CMatrixComplex &a,const int n,const bool isupper,complex &tau[],double &d[],double &e[]);
|
|
static void HMatrixTDUnpackQ(CMatrixComplex &a,const int n,const bool isupper,complex &tau[],CMatrixComplex &q);
|
|
//--- eigenvalues and eigenvectors
|
|
static bool SMatrixEVD(CMatrixDouble &a,const int n,int zneeded,const bool isupper,double &d[],CMatrixDouble &z);
|
|
static bool SMatrixEVDR(CMatrixDouble &a,const int n,int zneeded,const bool isupper,double b1,double b2,int &m,double &w[],CMatrixDouble &z);
|
|
static bool SMatrixEVDI(CMatrixDouble &a,const int n,int zneeded,const bool isupper,const int i1,const int i2,double &w[],CMatrixDouble &z);
|
|
static bool HMatrixEVD(CMatrixComplex &a,const int n,const int zneeded,const bool isupper,double &d[],CMatrixComplex &z);
|
|
static bool HMatrixEVDR(CMatrixComplex &a,const int n,const int zneeded,const bool isupper,double b1,double b2,int &m,double &w[],CMatrixComplex &z);
|
|
static bool HMatrixEVDI(CMatrixComplex &a,const int n,const int zneeded,const bool isupper,const int i1,const int i2,double &w[],CMatrixComplex &z);
|
|
static bool SMatrixTdEVD(double &d[],double &e[],const int n,const int zneeded,CMatrixDouble &z);
|
|
static bool SMatrixTdEVDR(double &d[],double &e[],const int n,const int zneeded,const double a,const double b,int &m,CMatrixDouble &z);
|
|
static bool SMatrixTdEVDI(double &d[],double &e[],const int n,const int zneeded,const int i1,const int i2,CMatrixDouble &z);
|
|
static bool RMatrixEVD(CMatrixDouble &a,const int n,const int vneeded,double &wr[],double &wi[],CMatrixDouble &vl,CMatrixDouble &vr);
|
|
//--- random matrix generation
|
|
static void RMatrixRndOrthogonal(const int n,CMatrixDouble &a);
|
|
static void RMatrixRndCond(const int n,const double c,CMatrixDouble &a);
|
|
static void CMatrixRndOrthogonal(const int n,CMatrixComplex &a);
|
|
static void CMatrixRndCond(const int n,const double c,CMatrixComplex &a);
|
|
static void SMatrixRndCond(const int n,const double c,CMatrixDouble &a);
|
|
static void SPDMatrixRndCond(const int n,const double c,CMatrixDouble &a);
|
|
static void HMatrixRndCond(const int n,const double c,CMatrixComplex &a);
|
|
static void HPDMatrixRndCond(const int n,const double c,CMatrixComplex &a);
|
|
static void RMatrixRndOrthogonalFromTheRight(CMatrixDouble &a,const int m,const int n);
|
|
static void RMatrixRndOrthogonalFromTheLeft(CMatrixDouble &a,const int m,const int n);
|
|
static void CMatrixRndOrthogonalFromTheRight(CMatrixComplex &a,const int m,const int n);
|
|
static void CMatrixRndOrthogonalFromTheLeft(CMatrixComplex &a,const int m,const int n);
|
|
static void SMatrixRndMultiply(CMatrixDouble &a,const int n);
|
|
static void HMatrixRndMultiply(CMatrixComplex &a,const int n);
|
|
//--- triangular factorizations
|
|
static void RMatrixLU(CMatrixDouble &a,const int m,const int n,int &pivots[]);
|
|
static void CMatrixLU(CMatrixComplex &a,const int m,const int n,int &pivots[]);
|
|
static bool HPDMatrixCholesky(CMatrixComplex &a,const int n,const bool isupper);
|
|
static bool SPDMatrixCholesky(CMatrixDouble &a,const int n,const bool isupper);
|
|
//--- estimate of the condition numbers
|
|
static double RMatrixRCond1(CMatrixDouble &a,const int n);
|
|
static double RMatrixRCondInf(CMatrixDouble &a,const int n);
|
|
static double SPDMatrixRCond(CMatrixDouble &a,const int n,const bool isupper);
|
|
static double RMatrixTrRCond1(CMatrixDouble &a,const int n,const bool isupper,const bool isunit);
|
|
static double RMatrixTrRCondInf(CMatrixDouble &a,const int n,const bool isupper,const bool isunit);
|
|
static double HPDMatrixRCond(CMatrixComplex &a,const int n,const bool isupper);
|
|
static double CMatrixRCond1(CMatrixComplex &a,const int n);
|
|
static double CMatrixRCondInf(CMatrixComplex &a,const int n);
|
|
static double RMatrixLURCond1(CMatrixDouble &lua,const int n);
|
|
static double RMatrixLURCondInf(CMatrixDouble &lua,const int n);
|
|
static double SPDMatrixCholeskyRCond(CMatrixDouble &a,const int n,const bool isupper);
|
|
static double HPDMatrixCholeskyRCond(CMatrixComplex &a,const int n,const bool isupper);
|
|
static double CMatrixLURCond1(CMatrixComplex &lua,const int n);
|
|
static double CMatrixLURCondInf(CMatrixComplex &lua,const int n);
|
|
static double CMatrixTrRCond1(CMatrixComplex &a,const int n,const bool isupper,const bool isunit);
|
|
static double CMatrixTrRCondInf(CMatrixComplex &a,const int n,const bool isupper,const bool isunit);
|
|
//--- matrix inversion
|
|
static void RMatrixLUInverse(CMatrixDouble &a,int &pivots[],const int n,int &info,CMatInvReportShell &rep);
|
|
static void RMatrixLUInverse(CMatrixDouble &a,int &pivots[],int &info,CMatInvReportShell &rep);
|
|
static void RMatrixInverse(CMatrixDouble &a,const int n,int &info,CMatInvReportShell &rep);
|
|
static void RMatrixInverse(CMatrixDouble &a,int &info,CMatInvReportShell &rep);
|
|
static void CMatrixLUInverse(CMatrixComplex &a,int &pivots[],const int n,int &info,CMatInvReportShell &rep);
|
|
static void CMatrixLUInverse(CMatrixComplex &a,int &pivots[],int &info,CMatInvReportShell &rep);
|
|
static void CMatrixInverse(CMatrixComplex &a,const int n,int &info,CMatInvReportShell &rep);
|
|
static void CMatrixInverse(CMatrixComplex &a,int &info,CMatInvReportShell &rep);
|
|
static void SPDMatrixCholeskyInverse(CMatrixDouble &a,const int n,const bool isupper,int &info,CMatInvReportShell &rep);
|
|
static void SPDMatrixCholeskyInverse(CMatrixDouble &a,int &info,CMatInvReportShell &rep);
|
|
static void SPDMatrixInverse(CMatrixDouble &a,const int n,const bool isupper,int &info,CMatInvReportShell &rep);
|
|
static void SPDMatrixInverse(CMatrixDouble &a,int &info,CMatInvReportShell &rep);
|
|
static void HPDMatrixCholeskyInverse(CMatrixComplex &a,const int n,const bool isupper,int &info,CMatInvReportShell &rep);
|
|
static void HPDMatrixCholeskyInverse(CMatrixComplex &a,int &info,CMatInvReportShell &rep);
|
|
static void HPDMatrixInverse(CMatrixComplex &a,const int n,const bool isupper,int &info,CMatInvReportShell &rep);
|
|
static void HPDMatrixInverse(CMatrixComplex &a,int &info,CMatInvReportShell &rep);
|
|
static void RMatrixTrInverse(CMatrixDouble &a,const int n,const bool isupper,const bool isunit,int &info,CMatInvReportShell &rep);
|
|
static void RMatrixTrInverse(CMatrixDouble &a,const bool isupper,int &info,CMatInvReportShell &rep);
|
|
static void CMatrixTrInverse(CMatrixComplex &a,const int n,const bool isupper,const bool isunit,int &info,CMatInvReportShell &rep);
|
|
static void CMatrixTrInverse(CMatrixComplex &a,const bool isupper,int &info,CMatInvReportShell &rep);
|
|
//--- singular value decomposition of a bidiagonal matrix
|
|
static bool RMatrixBdSVD(double &d[],double &e[],const int n,const bool isupper,bool isfractionalaccuracyrequired,CMatrixDouble &u,const int nru,CMatrixDouble &c,const int ncc,CMatrixDouble &vt,const int ncvt);
|
|
//--- singular value decomposition
|
|
static bool RMatrixSVD(CMatrixDouble &a,const int m,const int n,const int uneeded,const int vtneeded,const int additionalmemory,double &w[],CMatrixDouble &u,CMatrixDouble &vt);
|
|
//--- calculation determinant of the matrix
|
|
static double RMatrixLUDet(CMatrixDouble &a,int &pivots[],const int n);
|
|
static double RMatrixLUDet(CMatrixDouble &a,int &pivots[]);
|
|
static double RMatrixDet(CMatrixDouble &a,const int n);
|
|
static double RMatrixDet(CMatrixDouble &a);
|
|
static complex CMatrixLUDet(CMatrixComplex &a,int &pivots[],const int n);
|
|
static complex CMatrixLUDet(CMatrixComplex &a,int &pivots[]);
|
|
static complex CMatrixDet(CMatrixComplex &a,const int n);
|
|
static complex CMatrixDet(CMatrixComplex &a);
|
|
static double SPDMatrixCholeskyDet(CMatrixDouble &a,const int n);
|
|
static double SPDMatrixCholeskyDet(CMatrixDouble &a);
|
|
static double SPDMatrixDet(CMatrixDouble &a,const int n,const bool isupper);
|
|
static double SPDMatrixDet(CMatrixDouble &a);
|
|
//--- generalized symmetric positive definite eigenproblem
|
|
static bool SMatrixGEVD(CMatrixDouble &a,const int n,const bool isuppera,CMatrixDouble &b,const bool isupperb,const int zneeded,const int problemtype,double &d[],CMatrixDouble &z);
|
|
static bool SMatrixGEVDReduce(CMatrixDouble &a,const int n,const bool isuppera,CMatrixDouble &b,const bool isupperb,const int problemtype,CMatrixDouble &r,bool &isupperr);
|
|
//--- update of the inverse matrix by the Sherman-Morrison formula
|
|
static void RMatrixInvUpdateSimple(CMatrixDouble &inva,const int n,const int updrow,const int updcolumn,const double updval);
|
|
static void RMatrixInvUpdateRow(CMatrixDouble &inva,const int n,const int updrow,double &v[]);
|
|
static void RMatrixInvUpdateColumn(CMatrixDouble &inva,const int n,const int updcolumn,double &u[]);
|
|
static void RMatrixInvUpdateUV(CMatrixDouble &inva,const int n,double &u[],double &v[]);
|
|
//--- Schur decomposition
|
|
static bool RMatrixSchur(CMatrixDouble &a,const int n,CMatrixDouble &s);
|
|
//--- function of package optimization
|
|
//--- conjugate gradient method
|
|
static void MinCGCreate(const int n,double &x[],CMinCGStateShell &state);
|
|
static void MinCGCreate(double &x[],CMinCGStateShell &state);
|
|
static void MinCGCreateF(const int n,double &x[],double diffstep,CMinCGStateShell &state);
|
|
static void MinCGCreateF(double &x[],double diffstep,CMinCGStateShell &state);
|
|
static void MinCGSetCond(CMinCGStateShell &state,double epsg,double epsf,double epsx,int maxits);
|
|
static void MinCGSetScale(CMinCGStateShell &state,double &s[]);
|
|
static void MinCGSetXRep(CMinCGStateShell &state,bool needxrep);
|
|
static void MinCGSetCGType(CMinCGStateShell &state,int cgtype);
|
|
static void MinCGSetStpMax(CMinCGStateShell &state,double stpmax);
|
|
static void MinCGSuggestStep(CMinCGStateShell &state,double stp);
|
|
static void MinCGSetPrecDefault(CMinCGStateShell &state);
|
|
static void MinCGSetPrecDiag(CMinCGStateShell &state,double &d[]);
|
|
static void MinCGSetPrecScale(CMinCGStateShell &state);
|
|
static bool MinCGIteration(CMinCGStateShell &state);
|
|
static void MinCGOptimize(CMinCGStateShell &state,CNDimensional_Func &func,CNDimensional_Rep &rep,bool rep_status,CObject &obj);
|
|
static void MinCGOptimize(CMinCGStateShell &state,CNDimensional_Grad &grad,CNDimensional_Rep &rep,bool rep_status,CObject &obj);
|
|
static void MinCGResults(CMinCGStateShell &state,double &x[],CMinCGReportShell &rep);
|
|
static void MinCGResultsBuf(CMinCGStateShell &state,double &x[],CMinCGReportShell &rep);
|
|
static void MinCGRestartFrom(CMinCGStateShell &state,double &x[]);
|
|
//--- bound constrained optimization with additional linear equality and inequality constraints
|
|
static void MinBLEICCreate(const int n,double &x[],CMinBLEICStateShell &state);
|
|
static void MinBLEICCreate(double &x[],CMinBLEICStateShell &state);
|
|
static void MinBLEICCreateF(const int n,double &x[],double diffstep,CMinBLEICStateShell &state);
|
|
static void MinBLEICCreateF(double &x[],double diffstep,CMinBLEICStateShell &state);
|
|
static void MinBLEICSetBC(CMinBLEICStateShell &state,double &bndl[],double &bndu[]);
|
|
static void MinBLEICSetLC(CMinBLEICStateShell &state,CMatrixDouble &c,int &ct[],const int k);
|
|
static void MinBLEICSetLC(CMinBLEICStateShell &state,CMatrixDouble &c,int &ct[]);
|
|
static void MinBLEICSetInnerCond(CMinBLEICStateShell &state,const double epsg,const double epsf,const double epsx);
|
|
static void MinBLEICSetOuterCond(CMinBLEICStateShell &state,const double epsx,const double epsi);
|
|
static void MinBLEICSetScale(CMinBLEICStateShell &state,double &s[]);
|
|
static void MinBLEICSetPrecDefault(CMinBLEICStateShell &state);
|
|
static void MinBLEICSetPrecDiag(CMinBLEICStateShell &state,double &d[]);
|
|
static void MinBLEICSetPrecScale(CMinBLEICStateShell &state);
|
|
static void MinBLEICSetMaxIts(CMinBLEICStateShell &state,const int maxits);
|
|
static void MinBLEICSetXRep(CMinBLEICStateShell &state,bool needxrep);
|
|
static void MinBLEICSetStpMax(CMinBLEICStateShell &state,double stpmax);
|
|
static bool MinBLEICIteration(CMinBLEICStateShell &state);
|
|
static void MinBLEICOptimize(CMinBLEICStateShell &state,CNDimensional_Func &func,CNDimensional_Rep &rep,bool rep_status,CObject &obj);
|
|
static void MinBLEICOptimize(CMinBLEICStateShell &state,CNDimensional_Grad &grad,CNDimensional_Rep &rep,bool rep_status,CObject &obj);
|
|
static void MinBLEICResults(CMinBLEICStateShell &state,double &x[],CMinBLEICReportShell &rep);
|
|
static void MinBLEICResultsBuf(CMinBLEICStateShell &state,double &x[],CMinBLEICReportShell &rep);
|
|
static void MinBLEICRestartFrom(CMinBLEICStateShell &state,double &x[]);
|
|
//--- limited memory BFGS method for large scale optimization
|
|
static void MinLBFGSCreate(const int n,const int m,double &x[],CMinLBFGSStateShell &state);
|
|
static void MinLBFGSCreate(const int m,double &x[],CMinLBFGSStateShell &state);
|
|
static void MinLBFGSCreateF(const int n,const int m,double &x[],const double diffstep,CMinLBFGSStateShell &state);
|
|
static void MinLBFGSCreateF(const int m,double &x[],const double diffstep,CMinLBFGSStateShell &state);
|
|
static void MinLBFGSSetCond(CMinLBFGSStateShell &state,const double epsg,const double epsf,const double epsx,const int maxits);
|
|
static void MinLBFGSSetXRep(CMinLBFGSStateShell &state,const bool needxrep);
|
|
static void MinLBFGSSetStpMax(CMinLBFGSStateShell &state,const double stpmax);
|
|
static void MinLBFGSSetScale(CMinLBFGSStateShell &state,double &s[]);
|
|
static void MinLBFGSSetPrecDefault(CMinLBFGSStateShell &state);
|
|
static void MinLBFGSSetPrecCholesky(CMinLBFGSStateShell &state,CMatrixDouble &p,const bool isupper);
|
|
static void MinLBFGSSetPrecDiag(CMinLBFGSStateShell &state,double &d[]);
|
|
static void MinLBFGSSetPrecScale(CMinLBFGSStateShell &state);
|
|
static bool MinLBFGSIteration(CMinLBFGSStateShell &state);
|
|
static void MinLBFGSOptimize(CMinLBFGSStateShell &state,CNDimensional_Func &func,CNDimensional_Rep &rep,bool rep_status,CObject &obj);
|
|
static void MinLBFGSOptimize(CMinLBFGSStateShell &state,CNDimensional_Grad &grad,CNDimensional_Rep &rep,bool rep_status,CObject &obj);
|
|
static void MinLBFGSResults(CMinLBFGSStateShell &state,double &x[],CMinLBFGSReportShell &rep);
|
|
static void MinLBFGSresultsbuf(CMinLBFGSStateShell &state,double &x[],CMinLBFGSReportShell &rep);
|
|
static void MinLBFGSRestartFrom(CMinLBFGSStateShell &state,double &x[]);
|
|
//--- constrained quadratic programming
|
|
static void MinQPCreate(const int n,CMinQPStateShell &state);
|
|
static void MinQPSetLinearTerm(CMinQPStateShell &state,double &b[]);
|
|
static void MinQPSetQuadraticTerm(CMinQPStateShell &state,CMatrixDouble &a,const bool isupper);
|
|
static void MinQPSetQuadraticTerm(CMinQPStateShell &state,CMatrixDouble &a);
|
|
static void MinQPSetStartingPoint(CMinQPStateShell &state,double &x[]);
|
|
static void MinQPSetOrigin(CMinQPStateShell &state,double &xorigin[]);
|
|
static void MinQPSetAlgoCholesky(CMinQPStateShell &state);
|
|
static void MinQPSetBC(CMinQPStateShell &state,double &bndl[],double &bndu[]);
|
|
static void MinQPOptimize(CMinQPStateShell &state);
|
|
static void MinQPResults(CMinQPStateShell &state,double &x[],CMinQPReportShell &rep);
|
|
static void MinQPResultsBuf(CMinQPStateShell &state,double &x[],CMinQPReportShell &rep);
|
|
//--- Levenberg-Marquardt method
|
|
static void MinLMCreateVJ(const int n,const int m,double &x[],CMinLMStateShell &state);
|
|
static void MinLMCreateVJ(const int m,double &x[],CMinLMStateShell &state);
|
|
static void MinLMCreateV(const int n,const int m,double &x[],double diffstep,CMinLMStateShell &state);
|
|
static void MinLMCreateV(const int m,double &x[],const double diffstep,CMinLMStateShell &state);
|
|
static void MinLMCreateFGH(const int n,double &x[],CMinLMStateShell &state);
|
|
static void MinLMCreateFGH(double &x[],CMinLMStateShell &state);
|
|
static void MinLMSetCond(CMinLMStateShell &state,const double epsg,const double epsf,const double epsx,const int maxits);
|
|
static void MinLMSetXRep(CMinLMStateShell &state,const bool needxrep);
|
|
static void MinLMSetStpMax(CMinLMStateShell &state,const double stpmax);
|
|
static void MinLMSetScale(CMinLMStateShell &state,double &s[]);
|
|
static void MinLMSetBC(CMinLMStateShell &state,double &bndl[],double &bndu[]);
|
|
static void MinLMSetAccType(CMinLMStateShell &state,const int acctype);
|
|
static bool MinLMIteration(CMinLMStateShell &state);
|
|
static void MinLMOptimize(CMinLMStateShell &state,CNDimensional_FVec &fvec,CNDimensional_Rep &rep,bool rep_status,CObject &obj);
|
|
static void MinLMOptimize(CMinLMStateShell &state,CNDimensional_FVec &fvec,CNDimensional_Jac &jac,CNDimensional_Rep &rep,bool rep_status,CObject &obj);
|
|
static void MinLMOptimize(CMinLMStateShell &state,CNDimensional_Func &func,CNDimensional_Grad &grad,CNDimensional_Hess &hess,CNDimensional_Rep &rep,bool rep_status,CObject &obj);
|
|
static void MinLMOptimize(CMinLMStateShell &state,CNDimensional_Func &func,CNDimensional_Jac &jac,CNDimensional_Rep &rep,bool rep_status,CObject &obj);
|
|
static void MinLMOptimize(CMinLMStateShell &state,CNDimensional_Func &func,CNDimensional_Grad &grad,CNDimensional_Jac &jac,CNDimensional_Rep &rep,bool rep_status,CObject &obj);
|
|
static void MinLMResults(CMinLMStateShell &state,double &x[],CMinLMReportShell &rep);
|
|
static void MinLMResultsBuf(CMinLMStateShell &state,double &x[],CMinLMReportShell &rep);
|
|
static void MinLMRestartFrom(CMinLMStateShell &state,double &x[]);
|
|
static void MinLMCreateVGJ(const int n,const int m,double &x[],CMinLMStateShell &state);
|
|
static void MinLMCreateVGJ(const int m,double &x[],CMinLMStateShell &state);
|
|
static void MinLMCreateFGJ(const int n,const int m,double &x[],CMinLMStateShell &state);
|
|
static void MinLMCreateFGJ(const int m,double &x[],CMinLMStateShell &state);
|
|
static void MinLMCreateFJ(const int n,const int m,double &x[],CMinLMStateShell &state);
|
|
static void MinLMCreateFJ(const int m,double &x[],CMinLMStateShell &state);
|
|
//--- optimization
|
|
static void MinLBFGSSetDefaultPreconditioner(CMinLBFGSStateShell &state);
|
|
static void MinLBFGSSetCholeskyPreconditioner(CMinLBFGSStateShell &state,CMatrixDouble &p,bool isupper);
|
|
static void MinBLEICSetBarrierWidth(CMinBLEICStateShell &state,const double mu);
|
|
static void MinBLEICSetBarrierDecay(CMinBLEICStateShell &state,const double mudecay);
|
|
static void MinASACreate(const int n,double &x[],double &bndl[],double &bndu[],CMinASAStateShell &state);
|
|
static void MinASACreate(double &x[],double &bndl[],double &bndu[],CMinASAStateShell &state);
|
|
static void MinASASetCond(CMinASAStateShell &state,const double epsg,const double epsf,const double epsx,const int maxits);
|
|
static void MinASASetXRep(CMinASAStateShell &state,const bool needxrep);
|
|
static void MinASASetAlgorithm(CMinASAStateShell &state,const int algotype);
|
|
static void MinASASetStpMax(CMinASAStateShell &state,const double stpmax);
|
|
static bool MinASAIteration(CMinASAStateShell &state);
|
|
static void MinASAOptimize(CMinASAStateShell &state,CNDimensional_Grad &grad,CNDimensional_Rep &rep,bool rep_status,CObject &obj);
|
|
static void MinASAResults(CMinASAStateShell &state,double &x[],CMinASAReportShell &rep);
|
|
static void MinASAResultsBuf(CMinASAStateShell &state,double &x[],CMinASAReportShell &rep);
|
|
static void MinASARestartFrom(CMinASAStateShell &state,double &x[],double &bndl[],double &bndu[]);
|
|
//--- function of package solvers
|
|
//--- dense solver
|
|
static void RMatrixSolve(CMatrixDouble &a,const int n,double &b[],int &info,CDenseSolverReportShell &rep,double &x[]);
|
|
static void RMatrixSolveM(CMatrixDouble &a,const int n,CMatrixDouble &b,const int m,const bool rfs,int &info,CDenseSolverReportShell &rep,CMatrixDouble &x);
|
|
static void RMatrixLUSolve(CMatrixDouble &lua,int &p[],const int n,double &b[],int &info,CDenseSolverReportShell &rep,double &x[]);
|
|
static void RMatrixLUSolveM(CMatrixDouble &lua,int &p[],const int n,CMatrixDouble &b,const int m,int &info,CDenseSolverReportShell &rep,CMatrixDouble &x);
|
|
static void RMatrixMixedSolve(CMatrixDouble &a,CMatrixDouble &lua,int &p[],const int n,double &b[],int &info,CDenseSolverReportShell &rep,double &x[]);
|
|
static void RMatrixMixedSolveM(CMatrixDouble &a,CMatrixDouble &lua,int &p[],const int n,CMatrixDouble &b,const int m,int &info,CDenseSolverReportShell &rep,CMatrixDouble &x);
|
|
static void CMatrixSolveM(CMatrixComplex &a,const int n,CMatrixComplex &b,const int m,const bool rfs,int &info,CDenseSolverReportShell &rep,CMatrixComplex &x);
|
|
static void CMatrixSolve(CMatrixComplex &a,const int n,complex &b[],int &info,CDenseSolverReportShell &rep,complex &x[]);
|
|
static void CMatrixLUSolveM(CMatrixComplex &lua,int &p[],const int n,CMatrixComplex &b,const int m,int &info,CDenseSolverReportShell &rep,CMatrixComplex &x);
|
|
static void CMatrixLUSolve(CMatrixComplex &lua,int &p[],const int n,complex &b[],int &info,CDenseSolverReportShell &rep,complex &x[]);
|
|
static void CMatrixMixedSolveM(CMatrixComplex &a,CMatrixComplex &lua,int &p[],const int n,CMatrixComplex &b,const int m,int &info,CDenseSolverReportShell &rep,CMatrixComplex &x);
|
|
static void CMatrixMixedSolve(CMatrixComplex &a,CMatrixComplex &lua,int &p[],const int n,complex &b[],int &info,CDenseSolverReportShell &rep,complex &x[]);
|
|
static void SPDMatrixSolveM(CMatrixDouble &a,const int n,const bool isupper,CMatrixDouble &b,const int m,int &info,CDenseSolverReportShell &rep,CMatrixDouble &x);
|
|
static void SPDMatrixSolve(CMatrixDouble &a,const int n,const bool isupper,double &b[],int &info,CDenseSolverReportShell &rep,double &x[]);
|
|
static void SPDMatrixCholeskySolveM(CMatrixDouble &cha,const int n,const bool isupper,CMatrixDouble &b,const int m,int &info,CDenseSolverReportShell &rep,CMatrixDouble &x);
|
|
static void SPDMatrixCholeskySolve(CMatrixDouble &cha,const int n,const bool isupper,double &b[],int &info,CDenseSolverReportShell &rep,double &x[]);
|
|
static void HPDMatrixSolveM(CMatrixComplex &a,const int n,const bool isupper,CMatrixComplex &b,const int m,int &info,CDenseSolverReportShell &rep,CMatrixComplex &x);
|
|
static void HPDMatrixSolve(CMatrixComplex &a,const int n,const bool isupper,complex &b[],int &info,CDenseSolverReportShell &rep,complex &x[]);
|
|
static void HPDMatrixCholeskySolveM(CMatrixComplex &cha,const int n,const bool isupper,CMatrixComplex &b,const int m,int &info,CDenseSolverReportShell &rep,CMatrixComplex &x);
|
|
static void HPDMatrixCholeskySolve(CMatrixComplex &cha,const int n,const bool isupper,complex &b[],int &info,CDenseSolverReportShell &rep,complex &x[]);
|
|
static void RMatrixSolveLS(CMatrixDouble &a,const int nrows,const int ncols,double &b[],const double threshold,int &info,CDenseSolverLSReportShell &rep,double &x[]);
|
|
//--- solving systems of nonlinear equations
|
|
static void NlEqCreateLM(const int n,const int m,double &x[],CNlEqStateShell &state);
|
|
static void NlEqCreateLM(const int m,double &x[],CNlEqStateShell &state);
|
|
static void NlEqSetCond(CNlEqStateShell &state,const double epsf,const int maxits);
|
|
static void NlEqSetXRep(CNlEqStateShell &state,const bool needxrep);
|
|
static void NlEqSetStpMax(CNlEqStateShell &state,const double stpmax);
|
|
static bool NlEqIteration(CNlEqStateShell &state);
|
|
static void NlEqSolve(CNlEqStateShell &state,CNDimensional_Func &func,CNDimensional_Jac &jac,CNDimensional_Rep &rep,bool rep_status,CObject &obj);
|
|
static void NlEqResults(CNlEqStateShell &state,double &x[],CNlEqReportShell &rep);
|
|
static void NlEqResultsBuf(CNlEqStateShell &state,double &x[],CNlEqReportShell &rep);
|
|
static void NlEqRestartFrom(CNlEqStateShell &state,double &x[]);
|
|
//--- function of package specialfunctions
|
|
//--- gamma function
|
|
static double GammaFunction(const double x);
|
|
static double LnGamma(const double x,double &sgngam);
|
|
//--- normal distribution
|
|
static double ErrorFunction(const double x);
|
|
static double ErrorFunctionC(const double x);
|
|
static double NormalDistribution(const double x);
|
|
static double InvErF(double e);
|
|
static double InvNormalDistribution(const double y0);
|
|
//--- incomplete gamma function
|
|
static double IncompleteGamma(const double a,const double x);
|
|
static double IncompleteGammaC(const double a,const double x);
|
|
static double InvIncompleteGammaC(const double a,const double y0);
|
|
//--- airy function
|
|
static void Airy(const double x,double &ai,double &aip,double &bi,double &bip);
|
|
//--- Bessel function
|
|
static double BesselJ0(const double x);
|
|
static double BesselJ1(const double x);
|
|
static double BesselJN(const int n,const double x);
|
|
static double BesselY0(const double x);
|
|
static double BesselY1(const double x);
|
|
static double BesselYN(const int n,const double x);
|
|
static double BesselI0(const double x);
|
|
static double BesselI1(const double x);
|
|
static double BesselK0(const double x);
|
|
static double BesselK1(const double x);
|
|
static double BesselKN(const int nn,const double x);
|
|
//--- beta function
|
|
static double Beta(const double a,const double b);
|
|
static double IncompleteBeta(const double a,const double b,const double x);
|
|
static double InvIncompleteBeta(const double a,const double b,double y);
|
|
//--- binomial distribution
|
|
static double BinomialDistribution(const int k,const int n,const double p);
|
|
static double BinomialComplDistribution(const int k,const int n,const double p);
|
|
static double InvBinomialDistribution(const int k,const int n,const double y);
|
|
//--- Chebyshev polynom
|
|
static double ChebyshevCalculate(int r,const int n,const double x);
|
|
static double ChebyshevSum(double &c[],const int r,const int n,const double x);
|
|
static void ChebyshevCoefficients(const int n,double &c[]);
|
|
static void FromChebyshev(double &a[],const int n,double &b[]);
|
|
//--- chi-square distribution
|
|
static double ChiSquareDistribution(const double v,const double x);
|
|
static double ChiSquareComplDistribution(const double v,const double x);
|
|
static double InvChiSquareDistribution(const double v,const double y);
|
|
//--- Dawson's Integral
|
|
static double DawsonIntegral(const double x);
|
|
//--- elliptic integral
|
|
static double EllipticIntegralK(const double m);
|
|
static double EllipticIntegralKhighPrecision(const double m1);
|
|
static double IncompleteEllipticIntegralK(const double phi,const double m);
|
|
static double EllipticIntegralE(const double m);
|
|
static double IncompleteEllipticIntegralE(const double phi,const double m);
|
|
//--- exponential integral
|
|
static double ExponentialIntegralEi(const double x);
|
|
static double ExponentialIntegralEn(const double x,const int n);
|
|
//--- F distribution functions
|
|
static double FDistribution(const int a,const int b,const double x);
|
|
static double FComplDistribution(const int a,const int b,const double x);
|
|
static double InvFDistribution(const int a,const int b,const double y);
|
|
//--- Fresnel integral
|
|
static void FresnelIntegral(const double x,double &c,double &s);
|
|
//--- Hermite polynomial
|
|
static double HermiteCalculate(const int n,const double x);
|
|
static double HermiteSum(double &c[],const int n,const double x);
|
|
static void HermiteCoefficients(const int n,double &c[]);
|
|
//--- Jacobian elliptic functions
|
|
static void JacobianEllipticFunctions(const double u,const double m,double &sn,double &cn,double &dn,double &ph);
|
|
//--- Laguerre polynomial
|
|
static double LaguerreCalculate(const int n,const double x);
|
|
static double LaguerreSum(double &c[],const int n,const double x);
|
|
static void LaguerreCoefficients(const int n,double &c[]);
|
|
//--- Legendre polynomial
|
|
static double LegendreCalculate(const int n,const double x);
|
|
static double LegendreSum(double &c[],const int n,const double x);
|
|
static void LegendreCoefficients(const int n,double &c[]);
|
|
//--- Poisson distribution
|
|
static double PoissonDistribution(const int k,const double m);
|
|
static double PoissonComplDistribution(const int k,const double m);
|
|
static double InvPoissonDistribution(const int k,const double y);
|
|
//--- psi function
|
|
static double Psi(const double x);
|
|
//--- Student's t distribution
|
|
static double StudenttDistribution(const int k,const double t);
|
|
static double InvStudenttDistribution(const int k,const double p);
|
|
//--- trigonometric integrals
|
|
static void SineCosineIntegrals(const double x,double &si,double &ci);
|
|
static void HyperbolicSineCosineIntegrals(const double x,double &shi,double &chi);
|
|
//--- function of package statistics
|
|
//--- basic statistics methods
|
|
static void SampleMoments(const double &x[],const int n,double &mean,double &variance,double &skewness,double &kurtosis);
|
|
static void SampleMoments(const double &x[],double &mean,double &variance,double &skewness,double &kurtosis);
|
|
static void SampleAdev(const double &x[],const int n,double &adev);
|
|
static void SampleAdev(const double &x[],double &adev);
|
|
static void SampleMedian(const double &x[],const int n,double &median);
|
|
static void SampleMedian(const double &x[],double &median);
|
|
static void SamplePercentile(const double &x[],const int n,const double p,double &v);
|
|
static void SamplePercentile(const double &x[],const double p,double &v);
|
|
static double Cov2(const double &x[],const double &y[],const int n);
|
|
static double Cov2(const double &x[],const double &y[]);
|
|
static double PearsonCorr2(const double &x[],const double &y[],const int n);
|
|
static double PearsonCorr2(const double &x[],const double &y[]);
|
|
static double SpearmanCorr2(const double &x[],const double &y[],const int n);
|
|
static double SpearmanCorr2(const double &x[],const double &y[]);
|
|
static void CovM(const CMatrixDouble &x,const int n,const int m,CMatrixDouble &c);
|
|
static void CovM(const CMatrixDouble &x,CMatrixDouble &c);
|
|
static void PearsonCorrM(const CMatrixDouble &x,const int n,const int m,CMatrixDouble &c);
|
|
static void PearsonCorrM(CMatrixDouble &x,CMatrixDouble &c);
|
|
static void SpearmanCorrM(const CMatrixDouble &x,const int n,const int m,CMatrixDouble &c);
|
|
static void SpearmanCorrM(const CMatrixDouble &x,CMatrixDouble &c);
|
|
static void CovM2(const CMatrixDouble &x,const CMatrixDouble &y,const int n,const int m1,const int m2,CMatrixDouble &c);
|
|
static void CovM2(const CMatrixDouble &x,const CMatrixDouble &y,CMatrixDouble &c);
|
|
static void PearsonCorrM2(const CMatrixDouble &x,const CMatrixDouble &y,const int n,const int m1,const int m2,CMatrixDouble &c);
|
|
static void PearsonCorrM2(const CMatrixDouble &x,const CMatrixDouble &y,CMatrixDouble &c);
|
|
static void SpearmanCorrM2(const CMatrixDouble &x,const CMatrixDouble &y,const int n,const int m1,const int m2,CMatrixDouble &c);
|
|
static void SpearmanCorrM2(const CMatrixDouble &x,const CMatrixDouble &y,CMatrixDouble &c);
|
|
//--- correlation tests
|
|
static void PearsonCorrelationSignificance(const double r,const int n,double &bothTails,double &leftTail,double &rightTail);
|
|
static void SpearmanRankCorrelationSignificance(const double r,const int n,double &bothTails,double &leftTail,double &rightTail);
|
|
//--- Jarque-Bera test
|
|
static void JarqueBeraTest(const double &x[],const int n,double &p);
|
|
//--- Mann-Whitney U-test
|
|
static void MannWhitneyUTest(const double &x[],const int n,const double &y[],const int m,double &bothTails,double &leftTail,double &rightTail);
|
|
//--- sign test
|
|
static void OneSampleSignTest(const double &x[],const int n,const double median,double &bothTails,double &leftTail,double &rightTail);
|
|
//--- Studentt Tests
|
|
static void StudentTest1(const double &x[],const int n,const double mean,double &bothTails,double &leftTail,double &rightTail);
|
|
static void StudentTest2(const double &x[],const int n,const double &y[],const int m,double &bothTails,double &leftTail,double &rightTail);
|
|
static void UnequalVarianceTest(const double &x[],const int n,const double &y[],const int m,double &bothTails,double &leftTail,double &rightTail);
|
|
//--- variance tests
|
|
static void FTest(const double &x[],const int n,const double &y[],const int m,double &bothTails,double &leftTail,double &rightTail);
|
|
static void OneSampleVarianceTest(double &x[],int n,double variance,double &bothTails,double &leftTail,double &rightTail);
|
|
//--- Wilcoxon signed-rank test
|
|
static void WilcoxonSignedRankTest(const double &x[],const int n,const double e,double &bothTails,double &leftTail,double &rightTail);
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| Constructor without parameters |
|
|
//+------------------------------------------------------------------+
|
|
CAlglib::CAlglib(void)
|
|
{
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Destructor |
|
|
//+------------------------------------------------------------------+
|
|
CAlglib::~CAlglib(void)
|
|
{
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| HQRNDState initialization with random values which come from |
|
|
//| standard RNG. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::HQRndRandomize(CHighQualityRandStateShell &state)
|
|
{
|
|
//--- function call
|
|
CHighQualityRand::HQRndRandomize(state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| HQRNDState initialization with seed values |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::HQRndSeed(const int s1,const int s2,CHighQualityRandStateShell &state)
|
|
{
|
|
//--- function call
|
|
CHighQualityRand::HQRndSeed(s1,s2,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function generates random real number in (0,1), |
|
|
//| not including interval boundaries |
|
|
//| State structure must be initialized with HQRNDRandomize() or |
|
|
//| HQRNDSeed(). |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::HQRndUniformR(CHighQualityRandStateShell &state)
|
|
{
|
|
//--- return result
|
|
return(CHighQualityRand::HQRndUniformR(state.GetInnerObj()));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function generates random integer number in [0, N) |
|
|
//| 1. N must be less than HQRNDMax-1. |
|
|
//| 2. State structure must be initialized with HQRNDRandomize() or |
|
|
//| HQRNDSeed() |
|
|
//+------------------------------------------------------------------+
|
|
static int CAlglib::HQRndUniformI(CHighQualityRandStateShell &state,const int n)
|
|
{
|
|
//--- return result
|
|
return(CHighQualityRand::HQRndUniformI(state.GetInnerObj(),n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Random number generator: normal numbers |
|
|
//| This function generates one random number from normal |
|
|
//| distribution. |
|
|
//| Its performance is equal to that of HQRNDNormal2() |
|
|
//| State structure must be initialized with HQRNDRandomize() or |
|
|
//| HQRNDSeed(). |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::HQRndNormal(CHighQualityRandStateShell &state)
|
|
{
|
|
//--- return result
|
|
return(CHighQualityRand::HQRndNormal(state.GetInnerObj()));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Random number generator: random X and Y such that X^2+Y^2=1 |
|
|
//| State structure must be initialized with HQRNDRandomize() or |
|
|
//| HQRNDSeed(). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::HQRndUnit2(CHighQualityRandStateShell &state,
|
|
double &x,double &y)
|
|
{
|
|
//--- initialization
|
|
x=0;
|
|
y=0;
|
|
//--- function call
|
|
CHighQualityRand::HQRndUnit2(state.GetInnerObj(),x,y);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Random number generator: normal numbers |
|
|
//| This function generates two independent random numbers from |
|
|
//| normal distribution. Its performance is equal to that of |
|
|
//| HQRNDNormal() |
|
|
//| State structure must be initialized with HQRNDRandomize() or |
|
|
//| HQRNDSeed(). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::HQRndNormal2(CHighQualityRandStateShell &state,
|
|
double &x1,double &x2)
|
|
{
|
|
//--- initialization
|
|
x1=0;
|
|
x2=0;
|
|
//--- function call
|
|
CHighQualityRand::HQRndNormal2(state.GetInnerObj(),x1,x2);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Random number generator: exponential distribution |
|
|
//| State structure must be initialized with HQRNDRandomize() or |
|
|
//| HQRNDSeed(). |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::HQRndExponential(CHighQualityRandStateShell &state,
|
|
const double lambdav)
|
|
{
|
|
//--- return result
|
|
return(CHighQualityRand::HQRndExponential(state.GetInnerObj(),lambdav));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function serializes data structure to string. |
|
|
//| Important properties of s_out: |
|
|
//| * it contains alphanumeric characters, dots, underscores, minus |
|
|
//| signs |
|
|
//| * these symbols are grouped into words, which are separated by |
|
|
//| spaces and Windows-style (CR+LF) newlines |
|
|
//| * although serializer uses spaces and CR+LF as separators, you |
|
|
//| can replace any separator character by arbitrary combination |
|
|
//| of spaces, tabs, Windows or Unix newlines. It allows flexible |
|
|
//| reformatting of the string in case you want to include it into |
|
|
//| text or XML file. But you should not insert separators into the|
|
|
//| middle of the "words" nor you should change case of letters. |
|
|
//| * s_out can be freely moved between 32-bit and 64-bit systems, |
|
|
//| little and big endian machines, and so on. You can serialize |
|
|
//| structure on 32-bit machine and unserialize it on 64-bit one |
|
|
//| (or vice versa), or serialize it on SPARC and unserialize on |
|
|
//| x86. You can also serialize it in C# version of ALGLIB and |
|
|
//| unserialize in C++ one, and vice versa. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::KDTreeSerialize(CKDTreeShell &obj,string &s_out)
|
|
{
|
|
//--- object of class
|
|
CSerializer s;
|
|
s.Alloc_Start();
|
|
//--- function call
|
|
CNearestNeighbor::KDTreeAlloc(s,obj.GetInnerObj());
|
|
s.SStart_Str();
|
|
//--- function call
|
|
CNearestNeighbor::KDTreeSerialize(s,obj.GetInnerObj());
|
|
s.Stop();
|
|
//--- get result
|
|
s_out=s.Get_String();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function unserializes data structure from string. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::KDTreeUnserialize(string s_in,CKDTreeShell &obj)
|
|
{
|
|
//--- object of class
|
|
CSerializer s;
|
|
s.UStart_Str(s_in);
|
|
//--- function call
|
|
CNearestNeighbor::KDTreeUnserialize(s,obj.GetInnerObj());
|
|
s.Stop();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| KD-tree creation |
|
|
//| This subroutine creates KD-tree from set of X-values and optional|
|
|
//| Y-values |
|
|
//| INPUT PARAMETERS |
|
|
//| XY - dataset, array[0..N-1,0..NX+NY-1]. |
|
|
//| one row corresponds to one point. |
|
|
//| first NX columns contain X-values, next NY (NY |
|
|
//| may be zero) |
|
|
//| columns may contain associated Y-values |
|
|
//| N - number of points, N>=1 |
|
|
//| NX - space dimension, NX>=1. |
|
|
//| NY - number of optional Y-values, NY>=0. |
|
|
//| NormType- norm type: |
|
|
//| * 0 denotes infinity-norm |
|
|
//| * 1 denotes 1-norm |
|
|
//| * 2 denotes 2-norm (Euclidean norm) |
|
|
//| OUTPUT PARAMETERS |
|
|
//| KDT - KD-tree |
|
|
//| NOTES |
|
|
//| 1. KD-tree creation have O(N*logN) complexity and |
|
|
//| O(N*(2*NX+NY)) memory requirements. |
|
|
//| 2. Although KD-trees may be used with any combination of N and |
|
|
//| NX, they are more efficient than brute-force search only when |
|
|
//| N >> 4^NX. So they are most useful in low-dimensional tasks |
|
|
//| (NX=2, NX=3). NX=1 is another inefficient case, because |
|
|
//| simple binary search (without additional structures) is |
|
|
//| much more efficient in such tasks than KD-trees. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::KDTreeBuild(CMatrixDouble &xy,const int n,const int nx,
|
|
const int ny,const int normtype,CKDTreeShell &kdt)
|
|
{
|
|
//--- function call
|
|
CNearestNeighbor::KDTreeBuild(xy,n,nx,ny,normtype,kdt.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| KD-tree creation |
|
|
//| This subroutine creates KD-tree from set of X-values and optional|
|
|
//| Y-values |
|
|
//| INPUT PARAMETERS |
|
|
//| XY - dataset, array[0..N-1,0..NX+NY-1]. |
|
|
//| one row corresponds to one point. |
|
|
//| first NX columns contain X-values, next NY (NY |
|
|
//| may be zero) |
|
|
//| columns may contain associated Y-values |
|
|
//| N - number of points, N>=1 |
|
|
//| NX - space dimension, NX>=1. |
|
|
//| NY - number of optional Y-values, NY>=0. |
|
|
//| NormType- norm type: |
|
|
//| * 0 denotes infinity-norm |
|
|
//| * 1 denotes 1-norm |
|
|
//| * 2 denotes 2-norm (Euclidean norm) |
|
|
//| OUTPUT PARAMETERS |
|
|
//| KDT - KD-tree |
|
|
//| NOTES |
|
|
//| 1. KD-tree creation have O(N*logN) complexity and |
|
|
//| O(N*(2*NX+NY)) memory requirements. |
|
|
//| 2. Although KD-trees may be used with any combination of N and |
|
|
//| NX, they are more efficient than brute-force search only when |
|
|
//| N >> 4^NX. So they are most useful in low-dimensional tasks |
|
|
//| (NX=2, NX=3). NX=1 is another inefficient case, because |
|
|
//| simple binary search (without additional structures) is |
|
|
//| much more efficient in such tasks than KD-trees. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::KDTreeBuild(CMatrixDouble &xy,const int nx,const int ny,
|
|
const int normtype,CKDTreeShell &kdt)
|
|
{
|
|
//--- create a variable
|
|
int n=CAp::Rows(xy);
|
|
//--- function call
|
|
CNearestNeighbor::KDTreeBuild(xy,n,nx,ny,normtype,kdt.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| KD-tree creation |
|
|
//| This subroutine creates KD-tree from set of X-values, integer |
|
|
//| tags and optional Y-values |
|
|
//| INPUT PARAMETERS |
|
|
//| XY - dataset, array[0..N-1,0..NX+NY-1]. |
|
|
//| one row corresponds to one point. |
|
|
//| first NX columns contain X-values, next NY (NY |
|
|
//| may be zero) |
|
|
//| columns may contain associated Y-values |
|
|
//| Tags - tags, array[0..N-1], contains integer tags |
|
|
//| associated with points. |
|
|
//| N - number of points, N>=1 |
|
|
//| NX - space dimension, NX>=1. |
|
|
//| NY - number of optional Y-values, NY>=0. |
|
|
//| NormType- norm type: |
|
|
//| * 0 denotes infinity-norm |
|
|
//| * 1 denotes 1-norm |
|
|
//| * 2 denotes 2-norm (Euclidean norm) |
|
|
//| OUTPUT PARAMETERS |
|
|
//| KDT - KD-tree |
|
|
//| NOTES |
|
|
//| 1. KD-tree creation have O(N*logN) complexity and |
|
|
//| O(N*(2*NX+NY)) memory requirements. |
|
|
//| 2. Although KD-trees may be used with any combination of N and |
|
|
//| NX, they are more efficient than brute-force search only when |
|
|
//| N >> 4^NX. So they are most useful in low-dimensional tasks |
|
|
//| (NX=2, NX=3). NX=1 is another inefficient case, because simple|
|
|
//| binary search (without additional structures) is much more |
|
|
//| efficient in such tasks than KD-trees. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::KDTreeBuildTagged(CMatrixDouble &xy,int &tags[],
|
|
const int n,const int nx,
|
|
const int ny,const int normtype,
|
|
CKDTreeShell &kdt)
|
|
{
|
|
//--- function call
|
|
CNearestNeighbor::KDTreeBuildTagged(xy,tags,n,nx,ny,normtype,kdt.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| KD-tree creation |
|
|
//| This subroutine creates KD-tree from set of X-values, integer |
|
|
//| tags and optional Y-values |
|
|
//| INPUT PARAMETERS |
|
|
//| XY - dataset, array[0..N-1,0..NX+NY-1]. |
|
|
//| one row corresponds to one point. |
|
|
//| first NX columns contain X-values, next NY (NY |
|
|
//| may be zero) |
|
|
//| columns may contain associated Y-values |
|
|
//| Tags - tags, array[0..N-1], contains integer tags |
|
|
//| associated with points. |
|
|
//| N - number of points, N>=1 |
|
|
//| NX - space dimension, NX>=1. |
|
|
//| NY - number of optional Y-values, NY>=0. |
|
|
//| NormType- norm type: |
|
|
//| * 0 denotes infinity-norm |
|
|
//| * 1 denotes 1-norm |
|
|
//| * 2 denotes 2-norm (Euclidean norm) |
|
|
//| OUTPUT PARAMETERS |
|
|
//| KDT - KD-tree |
|
|
//| NOTES |
|
|
//| 1. KD-tree creation have O(N*logN) complexity and |
|
|
//| O(N*(2*NX+NY)) memory requirements. |
|
|
//| 2. Although KD-trees may be used with any combination of N and |
|
|
//| NX, they are more efficient than brute-force search only when |
|
|
//| N >> 4^NX. So they are most useful in low-dimensional tasks |
|
|
//| (NX=2, NX=3). NX=1 is another inefficient case, because simple|
|
|
//| binary search (without additional structures) is much more |
|
|
//| efficient in such tasks than KD-trees. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::KDTreeBuildTagged(CMatrixDouble &xy,int &tags[],
|
|
const int nx,const int ny,
|
|
const int normtype,CKDTreeShell &kdt)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
if((CAp::Rows(xy)!=CAp::Len(tags)))
|
|
{
|
|
Print(__FUNCTION__+": looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
n=CAp::Rows(xy);
|
|
//--- function call
|
|
CNearestNeighbor::KDTreeBuildTagged(xy,tags,n,nx,ny,normtype,kdt.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| K-NN query: K nearest neighbors |
|
|
//| INPUT PARAMETERS |
|
|
//| KDT - KD-tree |
|
|
//| X - point, array[0..NX-1]. |
|
|
//| K - number of neighbors to return, K>=1 |
|
|
//| SelfMatch - whether self-matches are allowed: |
|
|
//| * if True, nearest neighbor may be the point |
|
|
//| itself (if it exists in original dataset) |
|
|
//| * if False, then only points with non-zero |
|
|
//| distance are returned |
|
|
//| * if not given, considered True |
|
|
//| RESULT |
|
|
//| number of actual neighbors found (either K or N, if K>N). |
|
|
//| This subroutine performs query and stores its result in the |
|
|
//| internal structures of the KD-tree. You can use following |
|
|
//| subroutines to obtain these results: |
|
|
//| * KDTreeQueryResultsX() to get X-values |
|
|
//| * KDTreeQueryResultsXY() to get X- and Y-values |
|
|
//| * KDTreeQueryResultsTags() to get tag values |
|
|
//| * KDTreeQueryResultsDistances() to get distances |
|
|
//+------------------------------------------------------------------+
|
|
static int CAlglib::KDTreeQueryKNN(CKDTreeShell &kdt,double &x[],
|
|
const int k,const bool selfmatch)
|
|
{
|
|
//--- return result
|
|
return(CNearestNeighbor::KDTreeQueryKNN(kdt.GetInnerObj(),x,k,selfmatch));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| K-NN query: K nearest neighbors |
|
|
//| INPUT PARAMETERS |
|
|
//| KDT - KD-tree |
|
|
//| X - point, array[0..NX-1]. |
|
|
//| K - number of neighbors to return, K>=1 |
|
|
//| SelfMatch - whether self-matches are allowed: |
|
|
//| * if True, nearest neighbor may be the point |
|
|
//| itself (if it exists in original dataset) |
|
|
//| * if False, then only points with non-zero |
|
|
//| distance are returned |
|
|
//| * if not given, considered True |
|
|
//| RESULT |
|
|
//| number of actual neighbors found (either K or N, if K>N). |
|
|
//| This subroutine performs query and stores its result in the |
|
|
//| internal structures of the KD-tree. You can use following |
|
|
//| subroutines to obtain these results: |
|
|
//| * KDTreeQueryResultsX() to get X-values |
|
|
//| * KDTreeQueryResultsXY() to get X- and Y-values |
|
|
//| * KDTreeQueryResultsTags() to get tag values |
|
|
//| * KDTreeQueryResultsDistances() to get distances |
|
|
//+------------------------------------------------------------------+
|
|
static int CAlglib::KDTreeQueryKNN(CKDTreeShell &kdt,double &x[],const int k)
|
|
{
|
|
//--- create a variable
|
|
bool selfmatch=true;
|
|
//--- return result
|
|
return(CNearestNeighbor::KDTreeQueryKNN(kdt.GetInnerObj(),x,k,selfmatch));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| R-NN query: all points within R-sphere centered at X |
|
|
//| INPUT PARAMETERS |
|
|
//| KDT - KD-tree |
|
|
//| X - point, array[0..NX-1]. |
|
|
//| R - radius of sphere (in corresponding norm), R>0|
|
|
//| SelfMatch - whether self-matches are allowed: |
|
|
//| * if True, nearest neighbor may be the point |
|
|
//| itself (if it exists in original dataset) |
|
|
//| * if False, then only points with non-zero |
|
|
//| distance are returned |
|
|
//| * if not given, considered True |
|
|
//| RESULT |
|
|
//| number of neighbors found, >=0 |
|
|
//| This subroutine performs query and stores its result in the |
|
|
//| internal structures of the KD-tree. You can use following |
|
|
//| subroutines to obtain actual results: |
|
|
//| * KDTreeQueryResultsX() to get X-values |
|
|
//| * KDTreeQueryResultsXY() to get X- and Y-values |
|
|
//| * KDTreeQueryResultsTags() to get tag values |
|
|
//| * KDTreeQueryResultsDistances() to get distances |
|
|
//+------------------------------------------------------------------+
|
|
static int CAlglib::KDTreeQueryRNN(CKDTreeShell &kdt,double &x[],
|
|
const double r,const bool selfmatch)
|
|
{
|
|
//--- return result
|
|
return(CNearestNeighbor::KDTreeQueryRNN(kdt.GetInnerObj(),x,r,selfmatch));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| R-NN query: all points within R-sphere centered at X |
|
|
//| INPUT PARAMETERS |
|
|
//| KDT - KD-tree |
|
|
//| X - point, array[0..NX-1]. |
|
|
//| R - radius of sphere (in corresponding norm), R>0|
|
|
//| SelfMatch - whether self-matches are allowed: |
|
|
//| * if True, nearest neighbor may be the point |
|
|
//| itself (if it exists in original dataset) |
|
|
//| * if False, then only points with non-zero |
|
|
//| distance are returned |
|
|
//| * if not given, considered True |
|
|
//| RESULT |
|
|
//| number of neighbors found, >=0 |
|
|
//| This subroutine performs query and stores its result in the |
|
|
//| internal structures of the KD-tree. You can use following |
|
|
//| subroutines to obtain actual results: |
|
|
//| * KDTreeQueryResultsX() to get X-values |
|
|
//| * KDTreeQueryResultsXY() to get X- and Y-values |
|
|
//| * KDTreeQueryResultsTags() to get tag values |
|
|
//| * KDTreeQueryResultsDistances() to get distances |
|
|
//+------------------------------------------------------------------+
|
|
static int CAlglib::KDTreeQueryRNN(CKDTreeShell &kdt,double &x[],const double r)
|
|
{
|
|
//--- create a variable
|
|
bool selfmatch=true;
|
|
//--- return result
|
|
return(CNearestNeighbor::KDTreeQueryRNN(kdt.GetInnerObj(),x,r,selfmatch));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| K-NN query: approximate K nearest neighbors |
|
|
//| INPUT PARAMETERS |
|
|
//| KDT - KD-tree |
|
|
//| X - point, array[0..NX-1]. |
|
|
//| K - number of neighbors to return, K>=1 |
|
|
//| SelfMatch - whether self-matches are allowed: |
|
|
//| * if True, nearest neighbor may be the point |
|
|
//| itself (if it exists in original dataset) |
|
|
//| * if False, then only points with non-zero |
|
|
//| distance are returned |
|
|
//| * if not given, considered True |
|
|
//| Eps - approximation factor, Eps>=0. eps-approximate|
|
|
//| nearest neighbor is a neighbor whose distance|
|
|
//| from X is at most (1+eps) times distance of |
|
|
//| true nearest neighbor. |
|
|
//| RESULT |
|
|
//| number of actual neighbors found (either K or N, if K>N). |
|
|
//| NOTES |
|
|
//| significant performance gain may be achieved only when Eps is|
|
|
//| on the order of magnitude of 1 or larger. |
|
|
//| This subroutine performs query and stores its result in the |
|
|
//| internal structures of the KD-tree. You can use following |
|
|
//| these subroutines to obtain results: |
|
|
//| * KDTreeQueryResultsX() to get X-values |
|
|
//| * KDTreeQueryResultsXY() to get X- and Y-values |
|
|
//| * KDTreeQueryResultsTags() to get tag values |
|
|
//| * KDTreeQueryResultsDistances() to get distances |
|
|
//+------------------------------------------------------------------+
|
|
static int CAlglib::KDTreeQueryAKNN(CKDTreeShell &kdt,double &x[],
|
|
const int k,const bool selfmatch,
|
|
const double eps)
|
|
{
|
|
//--- return result
|
|
return(CNearestNeighbor::KDTreeQueryAKNN(kdt.GetInnerObj(),x,k,selfmatch,eps));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| K-NN query: approximate K nearest neighbors |
|
|
//| INPUT PARAMETERS |
|
|
//| KDT - KD-tree |
|
|
//| X - point, array[0..NX-1]. |
|
|
//| K - number of neighbors to return, K>=1 |
|
|
//| SelfMatch - whether self-matches are allowed: |
|
|
//| * if True, nearest neighbor may be the point |
|
|
//| itself (if it exists in original dataset) |
|
|
//| * if False, then only points with non-zero |
|
|
//| distance are returned |
|
|
//| * if not given, considered True |
|
|
//| Eps - approximation factor, Eps>=0. eps-approximate|
|
|
//| nearest neighbor is a neighbor whose distance|
|
|
//| from X is at most (1+eps) times distance of |
|
|
//| true nearest neighbor. |
|
|
//| RESULT |
|
|
//| number of actual neighbors found (either K or N, if K>N). |
|
|
//| NOTES |
|
|
//| significant performance gain may be achieved only when Eps is|
|
|
//| on the order of magnitude of 1 or larger. |
|
|
//| This subroutine performs query and stores its result in the |
|
|
//| internal structures of the KD-tree. You can use following |
|
|
//| these subroutines to obtain results: |
|
|
//| * KDTreeQueryResultsX() to get X-values |
|
|
//| * KDTreeQueryResultsXY() to get X- and Y-values |
|
|
//| * KDTreeQueryResultsTags() to get tag values |
|
|
//| * KDTreeQueryResultsDistances() to get distances |
|
|
//+------------------------------------------------------------------+
|
|
static int CAlglib::KDTreeQueryAKNN(CKDTreeShell &kdt,double &x[],
|
|
const int k,const double eps)
|
|
{
|
|
//--- create a variable
|
|
bool selfmatch=true;
|
|
//--- return result
|
|
return(CNearestNeighbor::KDTreeQueryAKNN(kdt.GetInnerObj(),x,k,selfmatch,eps));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| X-values from last query |
|
|
//| INPUT PARAMETERS |
|
|
//| KDT - KD-tree |
|
|
//| X - possibly pre-allocated buffer. If X is too small |
|
|
//| to store result, it is resized. If size(X) is |
|
|
//| enough to store result, it is left unchanged. |
|
|
//| OUTPUT PARAMETERS |
|
|
//| X - rows are filled with X-values |
|
|
//| NOTES |
|
|
//| 1. points are ordered by distance from the query point (first = |
|
|
//| closest) |
|
|
//| 2. if XY is larger than required to store result, only leading |
|
|
//| part will be overwritten; trailing part will be left |
|
|
//| unchanged. So if on input XY = [[A,B],[C,D]], and result is |
|
|
//| [1,2], then on exit we will get XY = [[1,2],[C,D]]. This is |
|
|
//| done purposely to increase performance; if you want function |
|
|
//| to resize array according to result size, use function with |
|
|
//| same name and suffix 'I'. |
|
|
//| SEE ALSO |
|
|
//| * KDTreeQueryResultsXY() X- and Y-values |
|
|
//| * KDTreeQueryResultsTags() tag values |
|
|
//| * KDTreeQueryResultsDistances() distances |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::KDTreeQueryResultsX(CKDTreeShell &kdt,CMatrixDouble &x)
|
|
{
|
|
//--- function call
|
|
CNearestNeighbor::KDTreeQueryResultsX(kdt.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
//+------------------------------------------------------------------+
|
|
//| X- and Y-values from last query |
|
|
//| INPUT PARAMETERS |
|
|
//| KDT - KD-tree |
|
|
//| XY - possibly pre-allocated buffer. If XY is too small|
|
|
//| to store result, it is resized. If size(XY) is |
|
|
//| enough to store result, it is left unchanged. |
|
|
//| OUTPUT PARAMETERS |
|
|
//| XY - rows are filled with points: first NX columns |
|
|
//| with X-values, next NY columns - with Y-values. |
|
|
//| NOTES |
|
|
//| 1. points are ordered by distance from the query point (first = |
|
|
//| closest) |
|
|
//| 2. if XY is larger than required to store result, only leading |
|
|
//| part will be overwritten; trailing part will be left |
|
|
//| unchanged. So if on input XY = [[A,B],[C,D]], and result is |
|
|
//| [1,2], then on exit we will get XY = [[1,2],[C,D]]. This is |
|
|
//| done purposely to increase performance; if you want function |
|
|
//| to resize array according to result size, use function with |
|
|
//| same name and suffix 'I'. |
|
|
//| SEE ALSO |
|
|
//| * KDTreeQueryResultsX() X-values |
|
|
//| * KDTreeQueryResultsTags() tag values |
|
|
//| * KDTreeQueryResultsDistances() distances |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::KDTreeQueryResultsXY(CKDTreeShell &kdt,CMatrixDouble &xy)
|
|
{
|
|
//--- function call
|
|
CNearestNeighbor::KDTreeQueryResultsXY(kdt.GetInnerObj(),xy);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Tags from last query |
|
|
//| INPUT PARAMETERS |
|
|
//| KDT - KD-tree |
|
|
//| Tags - possibly pre-allocated buffer. If X is too small |
|
|
//| to store result, it is resized. If size(X) is |
|
|
//| enough to store result, it is left unchanged. |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Tags - filled with tags associated with points, |
|
|
//| or, when no tags were supplied, with zeros |
|
|
//| NOTES |
|
|
//| 1. points are ordered by distance from the query point (first |
|
|
//| = closest) |
|
|
//| 2. if XY is larger than required to store result, only leading |
|
|
//| part will be overwritten; trailing part will be left |
|
|
//| unchanged. So if on input XY = [[A,B],[C,D]], and result is |
|
|
//| [1,2], then on exit we will get XY = [[1,2],[C,D]]. This is |
|
|
//| done purposely to increase performance; if you want function |
|
|
//| to resize array according to result size, use function with |
|
|
//| same name and suffix 'I'. |
|
|
//| SEE ALSO |
|
|
//| * KDTreeQueryResultsX() X-values |
|
|
//| * KDTreeQueryResultsXY() X- and Y-values |
|
|
//| * KDTreeQueryResultsDistances() distances |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::KDTreeQueryResultsTags(CKDTreeShell &kdt,int &tags[])
|
|
{
|
|
//--- function call
|
|
CNearestNeighbor::KDTreeQueryResultsTags(kdt.GetInnerObj(),tags);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Distances from last query |
|
|
//| INPUT PARAMETERS |
|
|
//| KDT - KD-tree |
|
|
//| R - possibly pre-allocated buffer. If X is too small |
|
|
//| to store result, it is resized. If size(X) is |
|
|
//| enough to store result, it is left unchanged. |
|
|
//| OUTPUT PARAMETERS |
|
|
//| R - filled with distances (in corresponding norm) |
|
|
//| NOTES |
|
|
//| 1. points are ordered by distance from the query point (first |
|
|
//| = closest) |
|
|
//| 2. if XY is larger than required to store result, only leading |
|
|
//| part will be overwritten; trailing part will be left |
|
|
//| unchanged. So if on input XY = [[A,B],[C,D]], and result is |
|
|
//| [1,2], then on exit we will get XY = [[1,2],[C,D]]. This is |
|
|
//| done purposely to increase performance; if you want function |
|
|
//| to resize array according to result size, use function with |
|
|
//| same name and suffix 'I'. |
|
|
//| SEE ALSO |
|
|
//| * KDTreeQueryResultsX() X-values |
|
|
//| * KDTreeQueryResultsXY() X- and Y-values |
|
|
//| * KDTreeQueryResultsTags() tag values |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::KDTreeQueryResultsDistances(CKDTreeShell &kdt,double &r[])
|
|
{
|
|
//--- function call
|
|
CNearestNeighbor::KDTreeQueryResultsDistances(kdt.GetInnerObj(),r);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| X-values from last query; 'interactive' variant for languages |
|
|
//| like Python which support constructs like "X = |
|
|
//| KDTreeQueryResultsXI(KDT)" and interactive mode of interpreter. |
|
|
//| This function allocates new array on each call, so it is |
|
|
//| significantly slower than its 'non-interactive' counterpart, but |
|
|
//| it is more convenient when you call it from command line. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::KDTreeQueryResultsXI(CKDTreeShell &kdt,CMatrixDouble &x)
|
|
{
|
|
//--- function call
|
|
CNearestNeighbor::KDTreeQueryResultsXI(kdt.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| XY-values from last query; 'interactive' variant for languages |
|
|
//| like Python which support constructs like "XY = |
|
|
//| KDTreeQueryResultsXYI(KDT)" and interactive mode of interpreter. |
|
|
//| This function allocates new array on each call, so it is |
|
|
//| significantly slower than its 'non-interactive' counterpart, but |
|
|
//| it is more convenient when you call it from command line. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::KDTreeQueryResultsXYI(CKDTreeShell &kdt,CMatrixDouble &xy)
|
|
{
|
|
//--- function call
|
|
CNearestNeighbor::KDTreeQueryResultsXYI(kdt.GetInnerObj(),xy);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Tags from last query; 'interactive' variant for languages like |
|
|
//| Python which support constructs like "Tags = |
|
|
//| KDTreeQueryResultsTagsI(KDT)" and interactive mode of |
|
|
//| interpreter. |
|
|
//| This function allocates new array on each call, so it is |
|
|
//| significantly slower than its 'non-interactive' counterpart, but |
|
|
//| it is more convenient when you call it from command line. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::KDTreeQueryResultsTagsI(CKDTreeShell &kdt,int &tags[])
|
|
{
|
|
//--- function call
|
|
CNearestNeighbor::KDTreeQueryResultsTagsI(kdt.GetInnerObj(),tags);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Distances from last query; 'interactive' variant for languages |
|
|
//| like Python which support constructs like "R = |
|
|
//| KDTreeQueryResultsDistancesI(KDT)" and interactive mode of |
|
|
//| interpreter. |
|
|
//| This function allocates new array on each call, so it is |
|
|
//| significantly slower than its 'non-interactive' counterpart, but |
|
|
//| it is more convenient when you call it from command line. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::KDTreeQueryResultsDistancesI(CKDTreeShell &kdt,double &r[])
|
|
{
|
|
//--- function call
|
|
CNearestNeighbor::KDTreeQueryResultsDistancesI(kdt.GetInnerObj(),r);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Optimal binary classification |
|
|
//| Algorithms finds optimal (=with minimal cross-entropy) binary |
|
|
//| partition. |
|
|
//| Internal subroutine. |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - array[0..N-1], variable |
|
|
//| C - array[0..N-1], class numbers (0 or 1). |
|
|
//| N - array size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - completetion code: |
|
|
//| * -3, all values of A[] are same (partition is |
|
|
//| impossible) |
|
|
//| * -2, one of C[] is incorrect (<0, >1) |
|
|
//| * -1, incorrect pararemets were passed (N<=0). |
|
|
//| * 1, OK |
|
|
//| Threshold- partiton boundary. Left part contains values |
|
|
//| which are strictly less than Threshold. Right |
|
|
//| part contains values which are greater than or |
|
|
//| equal to Threshold. |
|
|
//| PAL, PBL- probabilities P(0|v<Threshold) and |
|
|
//| P(1|v<Threshold) |
|
|
//| PAR, PBR- probabilities P(0|v>=Threshold) and |
|
|
//| P(1|v>=Threshold) |
|
|
//| CVE - cross-validation estimate of cross-entropy |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::DSOptimalSplit2(double &a[],int &c[],const int n,
|
|
int &info,double &threshold,
|
|
double &pal,double &pbl,double &par,
|
|
double &pbr,double &cve)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
threshold=0;
|
|
pal=0;
|
|
pbl=0;
|
|
par=0;
|
|
pbr=0;
|
|
cve=0;
|
|
//--- function call
|
|
CBdSS::DSOptimalSplit2(a,c,n,info,threshold,pal,pbl,par,pbr,cve);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Optimal partition, internal subroutine. Fast version. |
|
|
//| Accepts: |
|
|
//| A array[0..N-1] array of attributes array[0..N-1]|
|
|
//| C array[0..N-1] array of class labels |
|
|
//| TiesBuf array[0..N] temporaries (ties) |
|
|
//| CntBuf array[0..2*NC-1] temporaries (counts) |
|
|
//| Alpha centering factor (0<=alpha<=1, |
|
|
//| recommended value - 0.05) |
|
|
//| BufR array[0..N-1] temporaries |
|
|
//| BufI array[0..N-1] temporaries |
|
|
//| Output: |
|
|
//| Info error code (">0"=OK, "<0"=bad) |
|
|
//| RMS training set RMS error |
|
|
//| CVRMS leave-one-out RMS error |
|
|
//| Note: |
|
|
//| content of all arrays is changed by subroutine; |
|
|
//| it doesn't allocate temporaries. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::DSOptimalSplit2Fast(double &a[],int &c[],int &tiesbuf[],
|
|
int &cntbuf[],double &bufr[],
|
|
int &bufi[],const int n,
|
|
const int nc,const double alpha,
|
|
int &info,double &threshold,
|
|
double &rms,double &cvrms)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
threshold=0;
|
|
rms=0;
|
|
cvrms=0;
|
|
//--- function call
|
|
CBdSS::DSOptimalSplit2Fast(a,c,tiesbuf,cntbuf,bufr,bufi,n,nc,alpha,info,threshold,rms,cvrms);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function serializes data structure to string. |
|
|
//| Important properties of s_out: |
|
|
//| * it contains alphanumeric characters, dots, underscores, minus |
|
|
//| signs |
|
|
//| * these symbols are grouped into words, which are separated by |
|
|
//| spaces and Windows-style (CR+LF) newlines |
|
|
//| * although serializer uses spaces and CR+LF as separators, you|
|
|
//| can replace any separator character by arbitrary combination of|
|
|
//| spaces, tabs, Windows or Unix newlines. It allows flexible |
|
|
//| reformatting of the string in case you want to include it into |
|
|
//| text or XML file. But you should not insert separators into the|
|
|
//| middle of the "words" nor you should change case of letters. |
|
|
//| * s_out can be freely moved between 32-bit and 64-bit systems, |
|
|
//| little and big endian machines, and so on. You can serialize |
|
|
//| structure on 32-bit machine and unserialize it on 64-bit one |
|
|
//| (or vice versa), or serialize it on SPARC and unserialize on |
|
|
//| x86. You can also serialize it in C# version of ALGLIB and |
|
|
//| unserialize in C++ one, and vice versa. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::DFSerialize(CDecisionForestShell &obj,string &s_out)
|
|
{
|
|
//--- create a variable
|
|
CSerializer s;
|
|
//--- serialization start
|
|
s.Alloc_Start();
|
|
//--- function call
|
|
CDForest::DFAlloc(s,obj.GetInnerObj());
|
|
//--- serialization
|
|
s.SStart_Str();
|
|
//--- function call
|
|
CDForest::DFSerialize(s,obj.GetInnerObj());
|
|
//--- stop
|
|
s.Stop();
|
|
//--- change value
|
|
s_out=s.Get_String();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function unserializes data structure from string. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::DFUnserialize(const string s_in,CDecisionForestShell &obj)
|
|
{
|
|
//--- create a variable
|
|
CSerializer s;
|
|
//--- unserialization
|
|
s.UStart_Str(s_in);
|
|
//--- function call
|
|
CDForest::DFUnserialize(s,obj.GetInnerObj());
|
|
//--- stop
|
|
s.Stop();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine builds random decision forest. |
|
|
//| INPUT PARAMETERS: |
|
|
//| XY - training set |
|
|
//| NPoints - training set size, NPoints>=1 |
|
|
//| NVars - number of independent variables, NVars>=1 |
|
|
//| NClasses - task type: |
|
|
//| * NClasses=1 - regression task with one |
|
|
//| dependent variable |
|
|
//| * NClasses>1 - classification task with |
|
|
//| NClasses classes. |
|
|
//| NTrees - number of trees in a forest, NTrees>=1. |
|
|
//| recommended values: 50-100. |
|
|
//| R - percent of a training set used to build |
|
|
//| individual trees. 0<R<=1. |
|
|
//| recommended values: 0.1 <= R <= 0.66. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - return code: |
|
|
//| * -2, if there is a point with class number |
|
|
//| outside of [0..NClasses-1]. |
|
|
//| * -1, if incorrect parameters was passed |
|
|
//| (NPoints<1, NVars<1, NClasses<1, |
|
|
//| NTrees<1, R<=0 or R>1). |
|
|
//| * 1, if task has been solved |
|
|
//| DF - model built |
|
|
//| Rep - training report, contains error on a training|
|
|
//| set and out-of-bag estimates of |
|
|
//| generalization error. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::DFBuildRandomDecisionForest(CMatrixDouble &xy,const int npoints,
|
|
const int nvars,const int nclasses,
|
|
const int ntrees,const double r,
|
|
int &info,CDecisionForestShell &df,
|
|
CDFReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDForest::DFBuildRandomDecisionForest(xy,npoints,nvars,nclasses,ntrees,r,info,df.GetInnerObj(),rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine builds random decision forest. |
|
|
//| This function gives ability to tune number of variables used when|
|
|
//| choosing best split. |
|
|
//| INPUT PARAMETERS: |
|
|
//| XY - training set |
|
|
//| NPoints - training set size, NPoints>=1 |
|
|
//| NVars - number of independent variables, NVars>=1 |
|
|
//| NClasses - task type: |
|
|
//| * NClasses=1 - regression task with one |
|
|
//| dependent variable |
|
|
//| * NClasses>1 - classification task with |
|
|
//| NClasses classes. |
|
|
//| NTrees - number of trees in a forest, NTrees>=1. |
|
|
//| recommended values: 50-100. |
|
|
//| NRndVars - number of variables used when choosing best |
|
|
//| split |
|
|
//| R - percent of a training set used to build |
|
|
//| individual trees. 0<R<=1. |
|
|
//| recommended values: 0.1 <= R <= 0.66. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - return code: |
|
|
//| * -2, if there is a point with class number |
|
|
//| outside of [0..NClasses-1]. |
|
|
//| * -1, if incorrect parameters was passed |
|
|
//| (NPoints<1, NVars<1, NClasses<1, |
|
|
//| NTrees<1, R<=0 or R>1). |
|
|
//| * 1, if task has been solved |
|
|
//| DF - model built |
|
|
//| Rep - training report, contains error on a training|
|
|
//| set and out-of-bag estimates of |
|
|
//| generalization error. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::DFBuildRandomDecisionForestX1(CMatrixDouble &xy,
|
|
const int npoints,
|
|
const int nvars,
|
|
const int nclasses,
|
|
const int ntrees,
|
|
int nrndvars,
|
|
const double r,
|
|
int &info,
|
|
CDecisionForestShell &df,
|
|
CDFReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDForest::DFBuildRandomDecisionForestX1(xy,npoints,nvars,nclasses,ntrees,nrndvars,r,info,df.GetInnerObj(),rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Procesing |
|
|
//| INPUT PARAMETERS: |
|
|
//| DF - decision forest model |
|
|
//| X - input vector, array[0..NVars-1]. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Y - result. Regression estimate when solving |
|
|
//| regression task, vector of posterior |
|
|
//| probabilities for classification task. |
|
|
//| See also DFProcessI. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::DFProcess(CDecisionForestShell &df,double &x[],
|
|
double &y[])
|
|
{
|
|
//--- function call
|
|
CDForest::DFProcess(df.GetInnerObj(),x,y);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 'interactive' variant of DFProcess for languages like Python |
|
|
//| which support constructs like "Y = DFProcessI(DF,X)" and |
|
|
//| interactive mode of interpreter |
|
|
//| This function allocates new array on each call, so it is |
|
|
//| significantly slower than its 'non-interactive' counterpart, but |
|
|
//| it is more convenient when you call it from command line. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::DFProcessI(CDecisionForestShell &df,
|
|
double &x[],double &y[])
|
|
{
|
|
//--- function call
|
|
CDForest::DFProcessI(df.GetInnerObj(),x,y);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Relative classification error on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| DF - decision forest model |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| percent of incorrectly classified cases. |
|
|
//| Zero if model solves regression task. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::DFRelClsError(CDecisionForestShell &df,CMatrixDouble &xy,
|
|
const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CDForest::DFRelClsError(df.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Average cross-entropy (in bits per element) on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| DF - decision forest model |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| CrossEntropy/(NPoints*LN(2)). |
|
|
//| Zero if model solves regression task. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::DFAvgCE(CDecisionForestShell &df,CMatrixDouble &xy,
|
|
const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CDForest::DFAvgCE(df.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| RMS error on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| DF - decision forest model |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| root mean square error. |
|
|
//| Its meaning for regression task is obvious. As for |
|
|
//| classification task,RMS error means error when estimating |
|
|
//| posterior probabilities. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::DFRMSError(CDecisionForestShell &df,CMatrixDouble &xy,
|
|
const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CDForest::DFRMSError(df.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Average error on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| DF - decision forest model |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| Its meaning for regression task is obvious. As for |
|
|
//| classification task, it means average error when estimating |
|
|
//| posterior probabilities. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::DFAvgError(CDecisionForestShell &df,CMatrixDouble &xy,
|
|
const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CDForest::DFAvgError(df.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Average relative error on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| DF - decision forest model |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| Its meaning for regression task is obvious. As for |
|
|
//| classification task, it means average relative error when |
|
|
//| estimating posterior probability of belonging to the correct |
|
|
//| class. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::DFAvgRelError(CDecisionForestShell &df,CMatrixDouble &xy,
|
|
const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CDForest::DFAvgRelError(df.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| k-means++ clusterization |
|
|
//| INPUT PARAMETERS: |
|
|
//| XY - dataset, array [0..NPoints-1,0..NVars-1]. |
|
|
//| NPoints - dataset size, NPoints>=K |
|
|
//| NVars - number of variables, NVars>=1 |
|
|
//| K - desired number of clusters, K>=1 |
|
|
//| Restarts - number of restarts, Restarts>=1 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - return code: |
|
|
//| * -3, if task is degenerate (number of |
|
|
//| distinct points is less than K) |
|
|
//| * -1, if incorrect |
|
|
//| NPoints/NFeatures/K/Restarts was passed|
|
|
//| * 1, if subroutine finished successfully |
|
|
//| C - array[0..NVars-1,0..K-1].matrix whose columns|
|
|
//| store cluster's centers |
|
|
//| XYC - array[NPoints], which contains cluster |
|
|
//| indexes |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::KMeansGenerate(CMatrixDouble &xy,const int npoints,
|
|
const int nvars,const int k,
|
|
const int restarts,int &info,
|
|
CMatrixDouble &c,int &xyc[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CKMeans::KMeansGenerate(xy,npoints,nvars,k,restarts,info,c,xyc);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Multiclass Fisher LDA |
|
|
//| Subroutine finds coefficients of linear combination which |
|
|
//| optimally separates training set on classes. |
|
|
//| INPUT PARAMETERS: |
|
|
//| XY - training set, array[0..NPoints-1,0..NVars]. |
|
|
//| First NVars columns store values of |
|
|
//| independent variables, next column stores |
|
|
//| number of class (from 0 to NClasses-1) which |
|
|
//| dataset element belongs to. Fractional values|
|
|
//| are rounded to nearest integer. |
|
|
//| NPoints - training set size, NPoints>=0 |
|
|
//| NVars - number of independent variables, NVars>=1 |
|
|
//| NClasses - number of classes, NClasses>=2 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - return code: |
|
|
//| * -4, if internal EVD subroutine hasn't |
|
|
//| converged |
|
|
//| * -2, if there is a point with class number |
|
|
//| outside of [0..NClasses-1]. |
|
|
//| * -1, if incorrect parameters was passed |
|
|
//| (NPoints<0, NVars<1, NClasses<2) |
|
|
//| * 1, if task has been solved |
|
|
//| * 2, if there was a multicollinearity in |
|
|
//| training set, but task has been solved.|
|
|
//| W - linear combination coefficients, |
|
|
//| array[0..NVars-1] |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::FisherLDA(CMatrixDouble &xy,const int npoints,
|
|
const int nvars,const int nclasses,
|
|
int &info,double &w[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CLDA::FisherLDA(xy,npoints,nvars,nclasses,info,w);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| N-dimensional multiclass Fisher LDA |
|
|
//| Subroutine finds coefficients of linear combinations which |
|
|
//| optimally separates |
|
|
//| training set on classes. It returns N-dimensional basis whose |
|
|
//| vector are sorted |
|
|
//| by quality of training set separation (in descending order). |
|
|
//| INPUT PARAMETERS: |
|
|
//| XY - training set, array[0..NPoints-1,0..NVars]. |
|
|
//| First NVars columns store values of |
|
|
//| independent variables, next column stores |
|
|
//| number of class (from 0 to NClasses-1) which |
|
|
//| dataset element belongs to. Fractional values|
|
|
//| are rounded to nearest integer. |
|
|
//| NPoints - training set size, NPoints>=0 |
|
|
//| NVars - number of independent variables, NVars>=1 |
|
|
//| NClasses - number of classes, NClasses>=2 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - return code: |
|
|
//| * -4, if internal EVD subroutine hasn't |
|
|
//| converged |
|
|
//| * -2, if there is a point with class number |
|
|
//| outside of [0..NClasses-1]. |
|
|
//| * -1, if incorrect parameters was passed |
|
|
//| (NPoints<0, NVars<1, NClasses<2) |
|
|
//| * 1, if task has been solved |
|
|
//| * 2, if there was a multicollinearity in |
|
|
//| training set, but task has been solved.|
|
|
//| W - basis, array[0..NVars-1,0..NVars-1] |
|
|
//| columns of matrix stores basis vectors, |
|
|
//| sorted by quality of training set separation |
|
|
//| (in descending order) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::FisherLDAN(CMatrixDouble &xy,const int npoints,
|
|
const int nvars,const int nclasses,
|
|
int &info,CMatrixDouble &w)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CLDA::FisherLDAN(xy,npoints,nvars,nclasses,info,w);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Linear regression |
|
|
//| Subroutine builds model: |
|
|
//| Y = A(0)*X[0] + ... + A(N-1)*X[N-1] + A(N) |
|
|
//| and model found in ALGLIB format, covariation matrix, training |
|
|
//| set errors (rms, average, average relative) and leave-one-out |
|
|
//| cross-validation estimate of the generalization error. CV |
|
|
//| estimate calculated using fast algorithm with O(NPoints*NVars) |
|
|
//| complexity. |
|
|
//| When covariation matrix is calculated standard deviations of|
|
|
//| function values are assumed to be equal to RMS error on the |
|
|
//| training set. |
|
|
//| INPUT PARAMETERS: |
|
|
//| XY - training set, array [0..NPoints-1,0..NVars]: |
|
|
//| * NVars columns - independent variables |
|
|
//| * last column - dependent variable |
|
|
//| NPoints - training set size, NPoints>NVars+1 |
|
|
//| NVars - number of independent variables |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - return code: |
|
|
//| * -255, in case of unknown internal error |
|
|
//| * -4, if internal SVD subroutine haven't |
|
|
//| converged |
|
|
//| * -1, if incorrect parameters was passed |
|
|
//| (NPoints<NVars+2, NVars<1). |
|
|
//| * 1, if subroutine successfully finished |
|
|
//| LM - linear model in the ALGLIB format. Use |
|
|
//| subroutines of this unit to work with the |
|
|
//| model. |
|
|
//| AR - additional results |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LRBuild(CMatrixDouble &xy,const int npoints,const int nvars,
|
|
int &info,CLinearModelShell &lm,CLRReportShell &ar)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CLinReg::LRBuild(xy,npoints,nvars,info,lm.GetInnerObj(),ar.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Linear regression |
|
|
//| Variant of LRBuild which uses vector of standatd deviations |
|
|
//| (errors in function values). |
|
|
//| INPUT PARAMETERS: |
|
|
//| XY - training set, array [0..NPoints-1,0..NVars]: |
|
|
//| * NVars columns - independent variables |
|
|
//| * last column - dependent variable |
|
|
//| S - standard deviations (errors in function |
|
|
//| values) array[0..NPoints-1], S[i]>0. |
|
|
//| NPoints - training set size, NPoints>NVars+1 |
|
|
//| NVars - number of independent variables |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - return code: |
|
|
//| * -255, in case of unknown internal error |
|
|
//| * -4, if internal SVD subroutine haven't |
|
|
//| converged |
|
|
//| * -1, if incorrect parameters was passed |
|
|
//| (NPoints<NVars+2, NVars<1). |
|
|
//| * -2, if S[I]<=0 |
|
|
//| * 1, if subroutine successfully finished |
|
|
//| LM - linear model in the ALGLIB format. Use |
|
|
//| subroutines of this unit to work with the |
|
|
//| model. |
|
|
//| AR - additional results |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LRBuildS(CMatrixDouble &xy,double &s[],const int npoints,
|
|
const int nvars,int &info,CLinearModelShell &lm,
|
|
CLRReportShell &ar)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CLinReg::LRBuildS(xy,s,npoints,nvars,info,lm.GetInnerObj(),ar.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Like LRBuildS, but builds model |
|
|
//| Y=A(0)*X[0] + ... + A(N-1)*X[N-1] |
|
|
//| i.m_e. with zero constant term. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LRBuildZS(CMatrixDouble &xy,double &s[],const int npoints,
|
|
const int nvars,int &info,CLinearModelShell &lm,
|
|
CLRReportShell &ar)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CLinReg::LRBuildZS(xy,s,npoints,nvars,info,lm.GetInnerObj(),ar.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Like LRBuild but builds model |
|
|
//| Y=A(0)*X[0] + ... + A(N-1)*X[N-1] |
|
|
//| i.m_e. with zero constant term. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LRBuildZ(CMatrixDouble &xy,const int npoints,
|
|
const int nvars,int &info,CLinearModelShell &lm,
|
|
CLRReportShell &ar)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CLinReg::LRBuildZ(xy,npoints,nvars,info,lm.GetInnerObj(),ar.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Unpacks coefficients of linear model. |
|
|
//| INPUT PARAMETERS: |
|
|
//| LM - linear model in ALGLIB format |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| V - coefficients,array[0..NVars] |
|
|
//| constant term (intercept) is stored in the |
|
|
//| V[NVars]. |
|
|
//| NVars - number of independent variables (one less |
|
|
//| than number of coefficients) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LRUnpack(CLinearModelShell &lm,double &v[],int &nvars)
|
|
{
|
|
//--- initialization
|
|
nvars=0;
|
|
//--- function call
|
|
CLinReg::LRUnpack(lm.GetInnerObj(),v,nvars);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| "Packs" coefficients and creates linear model in ALGLIB format |
|
|
//| (LRUnpack reversed). |
|
|
//| INPUT PARAMETERS: |
|
|
//| V - coefficients, array[0..NVars] |
|
|
//| NVars - number of independent variables |
|
|
//| OUTPUT PAREMETERS: |
|
|
//| LM - linear model. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LRPack(double &v[],const int nvars,CLinearModelShell &lm)
|
|
{
|
|
//--- function call
|
|
CLinReg::LRPack(v,nvars,lm.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Procesing |
|
|
//| INPUT PARAMETERS: |
|
|
//| LM - linear model |
|
|
//| X - input vector, array[0..NVars-1]. |
|
|
//| Result: |
|
|
//| value of linear model regression estimate |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::LRProcess(CLinearModelShell &lm,double &x[])
|
|
{
|
|
//--- return result
|
|
return(CLinReg::LRProcess(lm.GetInnerObj(),x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| RMS error on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| LM - linear model |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| root mean square error. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::LRRMSError(CLinearModelShell &lm,CMatrixDouble &xy,
|
|
const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CLinReg::LRRMSError(lm.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Average error on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| LM - linear model |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| average error. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::LRAvgError(CLinearModelShell &lm,CMatrixDouble &xy,
|
|
const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CLinReg::LRAvgError(lm.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| RMS error on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| LM - linear model |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| average relative error. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::LRAvgRelError(CLinearModelShell &lm,CMatrixDouble &xy,
|
|
const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CLinReg::LRAvgRelError(lm.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function serializes data structure to string. |
|
|
//| Important properties of s_out: |
|
|
//| * it contains alphanumeric characters, dots, underscores, minus |
|
|
//| signs |
|
|
//| * these symbols are grouped into words, which are separated by |
|
|
//| spaces and Windows-style (CR+LF) newlines |
|
|
//| * although serializer uses spaces and CR+LF as separators, you|
|
|
//| can replace any separator character by arbitrary combination of|
|
|
//| spaces, tabs, Windows or Unix newlines. It allows flexible |
|
|
//| reformatting of the string in case you want to include it into |
|
|
//| text or XML file. But you should not insert separators into the|
|
|
//| middle of the "words" nor you should change case of letters. |
|
|
//| * s_out can be freely moved between 32-bit and 64-bit systems, |
|
|
//| little and big endian machines, and so on. You can serialize |
|
|
//| structure on 32-bit machine and unserialize it on 64-bit one |
|
|
//| (or vice versa), or serialize it on SPARC and unserialize on |
|
|
//| x86. You can also serialize it in C# version of ALGLIB and |
|
|
//| unserialize in C++ one, and vice versa. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPSerialize(CMultilayerPerceptronShell &obj,string &s_out)
|
|
{
|
|
//--- create a variable
|
|
CSerializer s;
|
|
//--- serialization start
|
|
s.Alloc_Start();
|
|
//--- function call
|
|
CMLPBase::MLPAlloc(s,obj.GetInnerObj());
|
|
//--- serialization
|
|
s.SStart_Str();
|
|
//--- function call
|
|
CMLPBase::MLPSerialize(s,obj.GetInnerObj());
|
|
//--- stop
|
|
s.Stop();
|
|
//--- change value
|
|
s_out=s.Get_String();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function unserializes data structure from string. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPUnserialize(const string s_in,CMultilayerPerceptronShell &obj)
|
|
{
|
|
//--- create a variable
|
|
CSerializer s;
|
|
//--- unserialization
|
|
s.UStart_Str(s_in);
|
|
//--- function call
|
|
CMLPBase::MLPUnserialize(s,obj.GetInnerObj());
|
|
//--- stop
|
|
s.Stop();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Creates neural network with NIn inputs, NOut outputs, |
|
|
//| without hidden layers, with linear output layer. Network weights |
|
|
//| are filled with small random values. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPCreate0(const int nin,const int nout,
|
|
CMultilayerPerceptronShell &network)
|
|
{
|
|
//--- function call
|
|
CMLPBase::MLPCreate0(nin,nout,network.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Same as MLPCreate0, but with one hidden layer (NHid neurons) with|
|
|
//| non-linear activation function. Output layer is linear. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPCreate1(const int nin,int nhid,const int nout,
|
|
CMultilayerPerceptronShell &network)
|
|
{
|
|
//--- function call
|
|
CMLPBase::MLPCreate1(nin,nhid,nout,network.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Same as MLPCreate0,but with two hidden layers (NHid1 and NHid2 |
|
|
//| neurons) with non-linear activation function. Output layer is |
|
|
//| linear. |
|
|
//| $ALL |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPCreate2(const int nin,const int nhid1,const int nhid2,
|
|
const int nout,CMultilayerPerceptronShell &network)
|
|
{
|
|
//--- function call
|
|
CMLPBase::MLPCreate2(nin,nhid1,nhid2,nout,network.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Creates neural network with NIn inputs, NOut outputs, without |
|
|
//| hidden layers with non-linear output layer. Network weights are |
|
|
//| filled with small random values. |
|
|
//| Activation function of the output layer takes values: |
|
|
//| (B, +INF), if D>=0 |
|
|
//| or |
|
|
//| (-INF, B), if D<0. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPCreateB0(const int nin,const int nout,const double b,
|
|
const double d,CMultilayerPerceptronShell &network)
|
|
{
|
|
//--- function call
|
|
CMLPBase::MLPCreateB0(nin,nout,b,d,network.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Same as MLPCreateB0 but with non-linear hidden layer. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPCreateB1(const int nin,int nhid,const int nout,
|
|
const double b,const double d,
|
|
CMultilayerPerceptronShell &network)
|
|
{
|
|
//--- function call
|
|
CMLPBase::MLPCreateB1(nin,nhid,nout,b,d,network.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Same as MLPCreateB0 but with two non-linear hidden layers. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPCreateB2(const int nin,const int nhid1,const int nhid2,
|
|
const int nout,const double b,const double d,
|
|
CMultilayerPerceptronShell &network)
|
|
{
|
|
//--- function call
|
|
CMLPBase::MLPCreateB2(nin,nhid1,nhid2,nout,b,d,network.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Creates neural network with NIn inputs, NOut outputs, |
|
|
//| without hidden layers with non-linear output layer. Network |
|
|
//| weights are filled with small random values. Activation function |
|
|
//| of the output layer takes values [A,B]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPCreateR0(const int nin,const int nout,double a,
|
|
const double b,CMultilayerPerceptronShell &network)
|
|
{
|
|
//--- function call
|
|
CMLPBase::MLPCreateR0(nin,nout,a,b,network.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Same as MLPCreateR0,but with non-linear hidden layer. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPCreateR1(const int nin,int nhid,const int nout,
|
|
const double a,const double b,
|
|
CMultilayerPerceptronShell &network)
|
|
{
|
|
//--- function call
|
|
CMLPBase::MLPCreateR1(nin,nhid,nout,a,b,network.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Same as MLPCreateR0,but with two non-linear hidden layers. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPCreateR2(const int nin,const int nhid1,const int nhid2,
|
|
const int nout,const double a,const double b,
|
|
CMultilayerPerceptronShell &network)
|
|
{
|
|
//--- function call
|
|
CMLPBase::MLPCreateR2(nin,nhid1,nhid2,nout,a,b,network.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Creates classifier network with NIn inputs and NOut possible |
|
|
//| classes. |
|
|
//| Network contains no hidden layers and linear output layer with |
|
|
//| SOFTMAX-normalization (so outputs sums up to 1.0 and converge to |
|
|
//| posterior probabilities). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPCreateC0(const int nin,const int nout,
|
|
CMultilayerPerceptronShell &network)
|
|
{
|
|
//--- function call
|
|
CMLPBase::MLPCreateC0(nin,nout,network.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Same as MLPCreateC0,but with one non-linear hidden layer. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPCreateC1(const int nin,int nhid,const int nout,
|
|
CMultilayerPerceptronShell &network)
|
|
{
|
|
//--- function call
|
|
CMLPBase::MLPCreateC1(nin,nhid,nout,network.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Same as MLPCreateC0, but with two non-linear hidden layers. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPCreateC2(const int nin,const int nhid1,const int nhid2,
|
|
const int nout,CMultilayerPerceptronShell &network)
|
|
{
|
|
//--- function call
|
|
CMLPBase::MLPCreateC2(nin,nhid1,nhid2,nout,network.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Randomization of neural network weights |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPRandomize(CMultilayerPerceptronShell &network)
|
|
{
|
|
//--- function call
|
|
CMLPBase::MLPRandomize(network.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Randomization of neural network weights and standartisator |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPRandomizeFull(CMultilayerPerceptronShell &network)
|
|
{
|
|
//--- function call
|
|
CMLPBase::MLPRandomizeFull(network.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Returns information about initialized network: number of inputs, |
|
|
//| outputs, weights. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPProperties(CMultilayerPerceptronShell &network,
|
|
int &nin,int &nout,int &wcount)
|
|
{
|
|
//--- initialization
|
|
nin=0;
|
|
nout=0;
|
|
wcount=0;
|
|
//--- function call
|
|
CMLPBase::MLPProperties(network.GetInnerObj(),nin,nout,wcount);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Tells whether network is SOFTMAX-normalized (i.m_e. classifier) |
|
|
//| or not. |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::MLPIsSoftMax(CMultilayerPerceptronShell &network)
|
|
{
|
|
//--- return result
|
|
return(CMLPBase::MLPIsSoftMax(network.GetInnerObj()));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function returns total number of layers (including input, |
|
|
//| hidden and output layers). |
|
|
//+------------------------------------------------------------------+
|
|
static int CAlglib::MLPGetLayersCount(CMultilayerPerceptronShell &network)
|
|
{
|
|
//--- return result
|
|
return(CMLPBase::MLPGetLayersCount(network.GetInnerObj()));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function returns size of K-th layer. |
|
|
//| K=0 corresponds to input layer, K=CNT-1 corresponds to output |
|
|
//| layer. |
|
|
//| Size of the output layer is always equal to the number of |
|
|
//| outputs, although when we have softmax-normalized network, last |
|
|
//| neuron doesn't have any connections - it is just zero. |
|
|
//+------------------------------------------------------------------+
|
|
static int CAlglib::MLPGetLayerSize(CMultilayerPerceptronShell &network,
|
|
const int k)
|
|
{
|
|
//--- return result
|
|
return(CMLPBase::MLPGetLayerSize(network.GetInnerObj(),k));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function returns offset/scaling coefficients for I-th input |
|
|
//| of the network. |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - network |
|
|
//| I - input index |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Mean - mean term |
|
|
//| Sigma - sigma term,guaranteed to be nonzero. |
|
|
//| I-th input is passed through linear transformation |
|
|
//| IN[i]=(IN[i]-Mean)/Sigma |
|
|
//| before feeding to the network |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPGetInputScaling(CMultilayerPerceptronShell &network,
|
|
const int i,double &mean,double &sigma)
|
|
{
|
|
//--- initialization
|
|
mean=0;
|
|
sigma=0;
|
|
//--- function call
|
|
CMLPBase::MLPGetInputScaling(network.GetInnerObj(),i,mean,sigma);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function returns offset/scaling coefficients for I-th output|
|
|
//| of the network. |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - network |
|
|
//| I - input index |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Mean - mean term |
|
|
//| Sigma - sigma term, guaranteed to be nonzero. |
|
|
//| I-th output is passed through linear transformation |
|
|
//| OUT[i] = OUT[i]*Sigma+Mean |
|
|
//| before returning it to user. In case we have SOFTMAX-normalized |
|
|
//| network, we return (Mean,Sigma)=(0.0,1.0). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPGetOutputScaling(CMultilayerPerceptronShell &network,
|
|
const int i,double &mean,double &sigma)
|
|
{
|
|
//--- initialization
|
|
mean=0;
|
|
sigma=0;
|
|
//--- function call
|
|
CMLPBase::MLPGetOutputScaling(network.GetInnerObj(),i,mean,sigma);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function returns information about Ith neuron of Kth layer |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - network |
|
|
//| K - layer index |
|
|
//| I - neuron index (within layer) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| FKind - activation function type (used by |
|
|
//| MLPActivationFunction()) this value is zero |
|
|
//| for input or linear neurons |
|
|
//| Threshold - also called offset, bias |
|
|
//| zero for input neurons |
|
|
//| NOTE: this function throws exception if layer or neuron with |
|
|
//| given index do not exists. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPGetNeuronInfo(CMultilayerPerceptronShell &network,
|
|
const int k,const int i,int &fkind,
|
|
double &threshold)
|
|
{
|
|
//--- initialization
|
|
fkind=0;
|
|
threshold=0;
|
|
//--- function call
|
|
CMLPBase::MLPGetNeuronInfo(network.GetInnerObj(),k,i,fkind,threshold);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function returns information about connection from I0-th |
|
|
//| neuron of K0-th layer to I1-th neuron of K1-th layer. |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - network |
|
|
//| K0 - layer index |
|
|
//| I0 - neuron index (within layer) |
|
|
//| K1 - layer index |
|
|
//| I1 - neuron index (within layer) |
|
|
//| RESULT: |
|
|
//| connection weight (zero for non-existent connections) |
|
|
//| This function: |
|
|
//| 1. throws exception if layer or neuron with given index do not |
|
|
//| exists. |
|
|
//| 2. returns zero if neurons exist, but there is no connection |
|
|
//| between them |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::MLPGetWeight(CMultilayerPerceptronShell &network,
|
|
const int k0,const int i0,const int k1,
|
|
const int i1)
|
|
{
|
|
//--- return result
|
|
return(CMLPBase::MLPGetWeight(network.GetInnerObj(),k0,i0,k1,i1));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets offset/scaling coefficients for I-th input of |
|
|
//| the network. |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - network |
|
|
//| I - input index |
|
|
//| Mean - mean term |
|
|
//| Sigma - sigma term (if zero,will be replaced by 1.0) |
|
|
//| NTE: I-th input is passed through linear transformation |
|
|
//| IN[i]=(IN[i]-Mean)/Sigma |
|
|
//| before feeding to the network. This function sets Mean and Sigma.|
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPSetInputScaling(CMultilayerPerceptronShell &network,
|
|
const int i,const double mean,
|
|
const double sigma)
|
|
{
|
|
//--- function call
|
|
CMLPBase::MLPSetInputScaling(network.GetInnerObj(),i,mean,sigma);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets offset/scaling coefficients for I-th output of|
|
|
//| the network. |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - network |
|
|
//| I - input index |
|
|
//| Mean - mean term |
|
|
//| Sigma - sigma term (if zero, will be replaced by 1.0)|
|
|
//| OUTPUT PARAMETERS: |
|
|
//| NOTE: I-th output is passed through linear transformation |
|
|
//| OUT[i] = OUT[i]*Sigma+Mean |
|
|
//| before returning it to user. This function sets Sigma/Mean. In |
|
|
//| case we have SOFTMAX-normalized network, you can not set (Sigma, |
|
|
//| Mean) to anything other than(0.0,1.0) - this function will throw |
|
|
//| exception. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPSetOutputScaling(CMultilayerPerceptronShell &network,
|
|
const int i,const double mean,
|
|
const double sigma)
|
|
{
|
|
//--- function call
|
|
CMLPBase::MLPSetOutputScaling(network.GetInnerObj(),i,mean,sigma);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function modifies information about Ith neuron of Kth layer |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - network |
|
|
//| K - layer index |
|
|
//| I - neuron index (within layer) |
|
|
//| FKind - activation function type (used by |
|
|
//| MLPActivationFunction()) this value must be |
|
|
//| zero for input neurons (you can not set |
|
|
//| activation function for input neurons) |
|
|
//| Threshold - also called offset, bias |
|
|
//| this value must be zero for input neurons |
|
|
//| (you can not set threshold for input neurons)|
|
|
//| NOTES: |
|
|
//| 1. this function throws exception if layer or neuron with given |
|
|
//| index do not exists. |
|
|
//| 2. this function also throws exception when you try to set |
|
|
//| non-linear activation function for input neurons (any kind |
|
|
//| of network) or for output neurons of classifier network. |
|
|
//| 3. this function throws exception when you try to set non-zero |
|
|
//| threshold for input neurons (any kind of network). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPSetNeuronInfo(CMultilayerPerceptronShell &network,
|
|
const int k,const int i,int fkind,
|
|
double threshold)
|
|
{
|
|
//--- function call
|
|
CMLPBase::MLPSetNeuronInfo(network.GetInnerObj(),k,i,fkind,threshold);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function modifies information about connection from I0-th |
|
|
//| neuron of K0-th layer to I1-th neuron of K1-th layer. |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - network |
|
|
//| K0 - layer index |
|
|
//| I0 - neuron index (within layer) |
|
|
//| K1 - layer index |
|
|
//| I1 - neuron index (within layer) |
|
|
//| W - connection weight (must be zero for |
|
|
//| non-existent connections) |
|
|
//| This function: |
|
|
//| 1. throws exception if layer or neuron with given index do not |
|
|
//| exists. |
|
|
//| 2. throws exception if you try to set non-zero weight for |
|
|
//| non-existent connection |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPSetWeight(CMultilayerPerceptronShell &network,
|
|
const int k0,const int i0,const int k1,
|
|
const int i1,const double w)
|
|
{
|
|
//--- function call
|
|
CMLPBase::MLPSetWeight(network.GetInnerObj(),k0,i0,k1,i1,w);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Neural network activation function |
|
|
//| INPUT PARAMETERS: |
|
|
//| NET - neuron input |
|
|
//| K - function index (zero for linear function) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| F - function |
|
|
//| DF - its derivative |
|
|
//| D2F - its second derivative |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPActivationFunction(const double net,const int k,
|
|
double &f,double &df,double &d2f)
|
|
{
|
|
//--- initialization
|
|
f=0;
|
|
df=0;
|
|
d2f=0;
|
|
//--- function call
|
|
CMLPBase::MLPActivationFunction(net,k,f,df,d2f);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Procesing |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - neural network |
|
|
//| X - input vector, array[0..NIn-1]. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Y - result. Regression estimate when solving |
|
|
//| regression task, vector of posterior |
|
|
//| probabilities for classification task. |
|
|
//| See also MLPProcessI |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPProcess(CMultilayerPerceptronShell &network,
|
|
double &x[],double &y[])
|
|
{
|
|
//--- function call
|
|
CMLPBase::MLPProcess(network.GetInnerObj(),x,y);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 'interactive' variant of MLPProcess for languages like Python |
|
|
//| which support constructs like "Y = MLPProcess(NN,X)" and |
|
|
//| interactive mode of the interpreter |
|
|
//| This function allocates new array on each call, so it is |
|
|
//| significantly slower than its 'non-interactive' counterpart, |
|
|
//| but it is more convenient when you call it from command line. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPProcessI(CMultilayerPerceptronShell &network,
|
|
double &x[],double &y[])
|
|
{
|
|
//--- function call
|
|
CMLPBase::MLPProcessI(network.GetInnerObj(),x,y);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Error function for neural network,internal subroutine. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::MLPError(CMultilayerPerceptronShell &network,
|
|
CMatrixDouble &xy,const int ssize)
|
|
{
|
|
//--- return result
|
|
return(CMLPBase::MLPError(network.GetInnerObj(),xy,ssize));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Natural error function for neural network,internal subroutine. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::MLPErrorN(CMultilayerPerceptronShell &network,
|
|
CMatrixDouble &xy,const int ssize)
|
|
{
|
|
//--- return result
|
|
return(CMLPBase::MLPErrorN(network.GetInnerObj(),xy,ssize));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Classification error |
|
|
//+------------------------------------------------------------------+
|
|
static int CAlglib::MLPClsError(CMultilayerPerceptronShell &network,
|
|
CMatrixDouble &xy,const int ssize)
|
|
{
|
|
//--- return result
|
|
return(CMLPBase::MLPClsError(network.GetInnerObj(),xy,ssize));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Relative classification error on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - network |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| percent of incorrectly classified cases. Works both for |
|
|
//| classifier networks and general purpose networks used as |
|
|
//| classifiers. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::MLPRelClsError(CMultilayerPerceptronShell &network,
|
|
CMatrixDouble &xy,const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CMLPBase::MLPRelClsError(network.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Average cross-entropy (in bits per element) on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - neural network |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| CrossEntropy/(NPoints*LN(2)). |
|
|
//| Zero if network solves regression task. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::MLPAvgCE(CMultilayerPerceptronShell &network,
|
|
CMatrixDouble &xy,const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CMLPBase::MLPAvgCE(network.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| RMS error on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - neural network |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| root mean square error. |
|
|
//| Its meaning for regression task is obvious. As for |
|
|
//| classification task,RMS error means error when estimating |
|
|
//| posterior probabilities. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::MLPRMSError(CMultilayerPerceptronShell &network,
|
|
CMatrixDouble &xy,const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CMLPBase::MLPRMSError(network.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Average error on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - neural network |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| Its meaning for regression task is obvious. As for |
|
|
//| classification task,it means average error when estimating |
|
|
//| posterior probabilities. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::MLPAvgError(CMultilayerPerceptronShell &network,
|
|
CMatrixDouble &xy,const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CMLPBase::MLPAvgError(network.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Average relative error on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - neural network |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| Its meaning for regression task is obvious. As for |
|
|
//| classification task, it means average relative error when |
|
|
//| estimating posterior probability of belonging to the correct |
|
|
//| class. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::MLPAvgRelError(CMultilayerPerceptronShell &network,
|
|
CMatrixDouble &xy,const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CMLPBase::MLPAvgRelError(network.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Gradient calculation |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - network initialized with one of the network |
|
|
//| creation funcs |
|
|
//| X - input vector, length of array must be at least |
|
|
//| NIn |
|
|
//| DesiredY- desired outputs, length of array must be at least|
|
|
//| NOut |
|
|
//| Grad - possibly preallocated array. If size of array is |
|
|
//| smaller than WCount, it will be reallocated. It |
|
|
//| is recommended to reuse previously allocated |
|
|
//| array to reduce allocation overhead. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) |
|
|
//| Grad - gradient of E with respect to weights of network,|
|
|
//| array[WCount] |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPGrad(CMultilayerPerceptronShell &network,double &x[],
|
|
double &desiredy[],double &e,double &grad[])
|
|
{
|
|
//--- initialization
|
|
e=0;
|
|
//--- function call
|
|
CMLPBase::MLPGrad(network.GetInnerObj(),x,desiredy,e,grad);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Gradient calculation (natural error function is used) |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - network initialized with one of the network |
|
|
//| creation funcs |
|
|
//| X - input vector, length of array must be at least |
|
|
//| NIn |
|
|
//| DesiredY- desired outputs, length of array must be at least|
|
|
//| NOut |
|
|
//| Grad - possibly preallocated array. If size of array is |
|
|
//| smaller than WCount, it will be reallocated. It |
|
|
//| is recommended to reuse previously allocated |
|
|
//| array to reduce allocation overhead. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| E - error function, sum-of-squares for regression |
|
|
//| networks, cross-entropy for classification |
|
|
//| networks. |
|
|
//| Grad - gradient of E with respect to weights of network,|
|
|
//| array[WCount] |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPGradN(CMultilayerPerceptronShell &network,double &x[],
|
|
double &desiredy[],double &e,double &grad[])
|
|
{
|
|
//--- initialization
|
|
e=0;
|
|
//--- function call
|
|
CMLPBase::MLPGradN(network.GetInnerObj(),x,desiredy,e,grad);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Batch gradient calculation for a set of inputs/outputs |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - network initialized with one of the network |
|
|
//| creation funcs |
|
|
//| XY - set of inputs/outputs; one sample = one row; |
|
|
//| first NIn columns contain inputs, |
|
|
//| next NOut columns - desired outputs. |
|
|
//| SSize - number of elements in XY |
|
|
//| Grad - possibly preallocated array. If size of array is |
|
|
//| smaller than WCount, it will be reallocated. It |
|
|
//| is recommended to reuse previously allocated |
|
|
//| array to reduce allocation overhead. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| E - error function, SUM(sqr(y[i]-desiredy[i])/2,i) |
|
|
//| Grad - gradient of E with respect to weights of network,|
|
|
//| array[WCount] |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPGradBatch(CMultilayerPerceptronShell &network,
|
|
CMatrixDouble &xy,const int ssize,
|
|
double &e,double &grad[])
|
|
{
|
|
//--- initialization
|
|
e=0;
|
|
//--- function call
|
|
CMLPBase::MLPGradBatch(network.GetInnerObj(),xy,ssize,e,grad);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Batch gradient calculation for a set of inputs/outputs |
|
|
//| (natural error function is used) |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - network initialized with one of the network |
|
|
//| creation funcs |
|
|
//| XY - set of inputs/outputs; one sample=one row; |
|
|
//| first NIn columns contain inputs, |
|
|
//| next NOut columns - desired outputs. |
|
|
//| SSize - number of elements in XY |
|
|
//| Grad - possibly preallocated array. If size of array is |
|
|
//| smaller than WCount, it will be reallocated. It |
|
|
//| is recommended to reuse previously allocated |
|
|
//| array to reduce allocation overhead. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| E - error function, sum-of-squares for regression |
|
|
//| networks, cross-entropy for classification |
|
|
//| networks. |
|
|
//| Grad - gradient of E with respect to weights of network,|
|
|
//| array[WCount] |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPGradNBatch(CMultilayerPerceptronShell &network,
|
|
CMatrixDouble &xy,const int ssize,
|
|
double &e,double &grad[])
|
|
{
|
|
//--- initialization
|
|
e=0;
|
|
//--- function call
|
|
CMLPBase::MLPGradNBatch(network.GetInnerObj(),xy,ssize,e,grad);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Batch Hessian calculation (natural error function) using |
|
|
//| R-algorithm. Internal subroutine. |
|
|
//| Hessian calculation based on R-algorithm described in |
|
|
//| "Fast Exact Multiplication by the Hessian", |
|
|
//| B. A. Pearlmutter, |
|
|
//| Neural Computation, 1994. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPHessianNBatch(CMultilayerPerceptronShell &network,
|
|
CMatrixDouble &xy,const int ssize,
|
|
double &e,double &grad[],
|
|
CMatrixDouble &h)
|
|
{
|
|
//--- initialization
|
|
e=0;
|
|
//--- function call
|
|
CMLPBase::MLPHessianNBatch(network.GetInnerObj(),xy,ssize,e,grad,h);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Batch Hessian calculation using R-algorithm. |
|
|
//| Internal subroutine. |
|
|
//| Hessian calculation based on R-algorithm described in |
|
|
//| "Fast Exact Multiplication by the Hessian", |
|
|
//| B. A. Pearlmutter, |
|
|
//| Neural Computation, 1994. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPHessianBatch(CMultilayerPerceptronShell &network,
|
|
CMatrixDouble &xy,const int ssize,
|
|
double &e,double &grad[],CMatrixDouble &h)
|
|
{
|
|
//--- initialization
|
|
e=0;
|
|
//--- function call
|
|
CMLPBase::MLPHessianBatch(network.GetInnerObj(),xy,ssize,e,grad,h);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine trains logit model. |
|
|
//| INPUT PARAMETERS: |
|
|
//| XY - training set, array[0..NPoints-1,0..NVars] |
|
|
//| First NVars columns store values of |
|
|
//| independent variables, next column stores |
|
|
//| number of class (from 0 to NClasses-1) which |
|
|
//| dataset element belongs to. Fractional values|
|
|
//| are rounded to nearest integer. |
|
|
//| NPoints - training set size, NPoints>=1 |
|
|
//| NVars - number of independent variables, NVars>=1 |
|
|
//| NClasses - number of classes, NClasses>=2 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - return code: |
|
|
//| * -2, if there is a point with class number |
|
|
//| outside of [0..NClasses-1]. |
|
|
//| * -1, if incorrect parameters was passed |
|
|
//| (NPoints<NVars+2, NVars<1, NClasses<2).|
|
|
//| * 1, if task has been solved |
|
|
//| LM - model built |
|
|
//| Rep - training report |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MNLTrainH(CMatrixDouble &xy,const int npoints,
|
|
const int nvars,const int nclasses,
|
|
int &info,CLogitModelShell &lm,
|
|
CMNLReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CLogit::MNLTrainH(xy,npoints,nvars,nclasses,info,lm.GetInnerObj(),rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Procesing |
|
|
//| INPUT PARAMETERS: |
|
|
//| LM - logit model, passed by non-constant reference |
|
|
//| (some fields of structure are used as temporaries|
|
|
//| when calculating model output). |
|
|
//| X - input vector, array[0..NVars-1]. |
|
|
//| Y - (possibly) preallocated buffer; if size of Y is |
|
|
//| less than NClasses, it will be reallocated.If it |
|
|
//| is large enough, it is NOT reallocated, so we |
|
|
//| can save some time on reallocation. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Y - result, array[0..NClasses-1] |
|
|
//| Vector of posterior probabilities for |
|
|
//| classification task. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MNLProcess(CLogitModelShell &lm,double &x[],double &y[])
|
|
{
|
|
//--- function call
|
|
CLogit::MNLProcess(lm.GetInnerObj(),x,y);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 'interactive' variant of MNLProcess for languages like Python |
|
|
//| which support constructs like "Y=MNLProcess(LM,X)" and |
|
|
//| interactive mode of the interpreter |
|
|
//| This function allocates new array on each call, so it is |
|
|
//| significantly slower than its 'non-interactive' counterpart, |
|
|
//| but it is more convenient when you call it from command line. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MNLProcessI(CLogitModelShell &lm,double &x[],double &y[])
|
|
{
|
|
//--- function call
|
|
CLogit::MNLProcessI(lm.GetInnerObj(),x,y);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Unpacks coefficients of logit model. Logit model have form: |
|
|
//| P(class=i) = S(i) / (S(0) + S(1) + ... +S(M-1)) |
|
|
//| S(i) = Exp(A[i,0]*X[0] + ... + A[i,N-1]*X[N-1] + A[i,N]), |
|
|
//| when i<M-1 |
|
|
//| S(M-1) = 1 |
|
|
//| INPUT PARAMETERS: |
|
|
//| LM - logit model in ALGLIB format |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| V - coefficients, array[0..NClasses-2,0..NVars] |
|
|
//| NVars - number of independent variables |
|
|
//| NClasses - number of classes |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MNLUnpack(CLogitModelShell &lm,CMatrixDouble &a,
|
|
int &nvars,int &nclasses)
|
|
{
|
|
//--- initialization
|
|
nvars=0;
|
|
nclasses=0;
|
|
//--- function call
|
|
CLogit::MNLUnpack(lm.GetInnerObj(),a,nvars,nclasses);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| "Packs" coefficients and creates logit model in ALGLIB format |
|
|
//| (MNLUnpack reversed). |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - model (see MNLUnpack) |
|
|
//| NVars - number of independent variables |
|
|
//| NClasses - number of classes |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| LM - logit model. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MNLPack(CMatrixDouble &a,const int nvars,
|
|
const int nclasses,CLogitModelShell &lm)
|
|
{
|
|
//--- function call
|
|
CLogit::MNLPack(a,nvars,nclasses,lm.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Average cross-entropy (in bits per element) on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| LM - logit model |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| CrossEntropy/(NPoints*ln(2)). |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::MNLAvgCE(CLogitModelShell &lm,CMatrixDouble &xy,
|
|
const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CLogit::MNLAvgCE(lm.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Relative classification error on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| LM - logit model |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| percent of incorrectly classified cases. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::MNLRelClsError(CLogitModelShell &lm,CMatrixDouble &xy,
|
|
const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CLogit::MNLRelClsError(lm.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| RMS error on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| LM - logit model |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| root mean square error (error when estimating posterior |
|
|
//| probabilities). |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::MNLRMSError(CLogitModelShell &lm,CMatrixDouble &xy,
|
|
const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CLogit::MNLRMSError(lm.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Average error on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| LM - logit model |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| average error (error when estimating posterior |
|
|
//| probabilities). |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::MNLAvgError(CLogitModelShell &lm,CMatrixDouble &xy,
|
|
const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CLogit::MNLAvgError(lm.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Average relative error on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| LM - logit model |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| average relative error (error when estimating posterior |
|
|
//| probabilities). |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::MNLAvgRelError(CLogitModelShell &lm,CMatrixDouble &xy,
|
|
const int ssize)
|
|
{
|
|
//--- return result
|
|
return(CLogit::MNLAvgRelError(lm.GetInnerObj(),xy,ssize));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Classification error on test set = MNLRelClsError*NPoints |
|
|
//+------------------------------------------------------------------+
|
|
static int CAlglib::MNLClsError(CLogitModelShell &lm,CMatrixDouble &xy,
|
|
const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CLogit::MNLClsError(lm.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| DESCRIPTION: |
|
|
//| This function creates MCPD (Markov Chains for Population Data) |
|
|
//| solver. |
|
|
//| This solver can be used to find transition matrix P for |
|
|
//| N-dimensional prediction problem where transition from X[i] to |
|
|
//| X[i+1] is modelled as X[i+1] = P*X[i] |
|
|
//| where X[i] and X[i+1] are N-dimensional population vectors |
|
|
//| (components of each X are non-negative), and P is a N*N |
|
|
//| transition matrix (elements of are non-negative, each column |
|
|
//| sums to 1.0). |
|
|
//| Such models arise when when: |
|
|
//| * there is some population of individuals |
|
|
//| * individuals can have different states |
|
|
//| * individuals can transit from one state to another |
|
|
//| * population size is constant, i.e. there is no new individuals |
|
|
//| and no one leaves population |
|
|
//| * you want to model transitions of individuals from one state |
|
|
//| into another |
|
|
//| USAGE: |
|
|
//| Here we give very brief outline of the MCPD. We strongly |
|
|
//| recommend you to read examples in the ALGLIB Reference Manual |
|
|
//| and to read ALGLIB User Guide on data analysis which is |
|
|
//| available at http://www.alglib.net/dataanalysis/ |
|
|
//| 1. User initializes algorithm state with MCPDCreate() call |
|
|
//| 2. User adds one or more tracks - sequences of states which |
|
|
//| describe evolution of a system being modelled from different |
|
|
//| starting conditions |
|
|
//| 3. User may add optional boundary, equality and/or linear |
|
|
//| constraints on the coefficients of P by calling one of the |
|
|
//| following functions: |
|
|
//| * MCPDSetEC() to set equality constraints |
|
|
//| * MCPDSetBC() to set bound constraints |
|
|
//| * MCPDSetLC() to set linear constraints |
|
|
//| 4. Optionally, user may set custom weights for prediction errors |
|
|
//| (by default, algorithm assigns non-equal, automatically chosen|
|
|
//| weights for errors in the prediction of different components |
|
|
//| of X). It can be done with a call of |
|
|
//| MCPDSetPredictionWeights() function. |
|
|
//| 5. User calls MCPDSolve() function which takes algorithm state |
|
|
//| and pointer (delegate, etc.) to callback function which |
|
|
//| calculates F/G. |
|
|
//| 6. User calls MCPDResults() to get solution |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - problem dimension, N>=1 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure stores algorithm state |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MCPDCreate(const int n,CMCPDStateShell &s)
|
|
{
|
|
//--- function call
|
|
CMarkovCPD::MCPDCreate(n,s.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| DESCRIPTION: |
|
|
//| This function is a specialized version of MCPDCreate() function, |
|
|
//| and we recommend you to read comments for this function for |
|
|
//| general information about MCPD solver. |
|
|
//| This function creates MCPD (Markov Chains for Population Data) |
|
|
//| solver for "Entry-state" model, i.e. model where transition from |
|
|
//| X[i] to X[i+1] is modelled as |
|
|
//| X[i+1] = P*X[i] |
|
|
//| where |
|
|
//| X[i] and X[i+1] are N-dimensional state vectors |
|
|
//| P is a N*N transition matrix |
|
|
//| and one selected component of X[] is called "entry" state and |
|
|
//| is treated in a special way: |
|
|
//| system state always transits from "entry" state to some |
|
|
//| another state |
|
|
//| system state can not transit from any state into "entry" |
|
|
//| state |
|
|
//| Such conditions basically mean that row of P which corresponds to|
|
|
//| "entry" state is zero. |
|
|
//| Such models arise when: |
|
|
//| * there is some population of individuals |
|
|
//| * individuals can have different states |
|
|
//| * individuals can transit from one state to another |
|
|
//| * population size is NOT constant - at every moment of time |
|
|
//| there is some (unpredictable) amount of "new" individuals, |
|
|
//| which can transit into one of the states at the next turn, but |
|
|
//| still no one leaves population |
|
|
//| * you want to model transitions of individuals from one state |
|
|
//| into another |
|
|
//| * but you do NOT want to predict amount of "new" individuals |
|
|
//| because it does not depends on individuals already present |
|
|
//| (hence system can not transit INTO entry state - it can only |
|
|
//| transit FROM it). |
|
|
//| This model is discussed in more details in the ALGLIB User Guide |
|
|
//| (see http://www.alglib.net/dataanalysis/ for more data). |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - problem dimension, N>=2 |
|
|
//| EntryState- index of entry state, in 0..N-1 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure stores algorithm state |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MCPDCreateEntry(const int n,const int entrystate,
|
|
CMCPDStateShell &s)
|
|
{
|
|
//--- function call
|
|
CMarkovCPD::MCPDCreateEntry(n,entrystate,s.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| DESCRIPTION: |
|
|
//| This function is a specialized version of MCPDCreate() function, |
|
|
//| and we recommend you to read comments for this function for |
|
|
//| general information about MCPD solver. |
|
|
//| This function creates MCPD (Markov Chains for Population Data) |
|
|
//| solver for "Exit-state" model, i.e. model where transition from |
|
|
//| X[i] to X[i+1] is modelled as |
|
|
//| X[i+1] = P*X[i] |
|
|
//| where |
|
|
//| X[i] and X[i+1] are N-dimensional state vectors |
|
|
//| P is a N*N transition matrix |
|
|
//| and one selected component of X[] is called "exit" state and |
|
|
//| is treated in a special way: |
|
|
//| system state can transit from any state into "exit" state |
|
|
//| system state can not transit from "exit" state into any other|
|
|
//| state transition operator discards "exit" state (makes it |
|
|
//| zero at each turn) |
|
|
//| Such conditions basically mean that column of P which |
|
|
//| corresponds to "exit" state is zero. Multiplication by such P |
|
|
//| may decrease sum of vector components. |
|
|
//| Such models arise when: |
|
|
//| * there is some population of individuals |
|
|
//| * individuals can have different states |
|
|
//| * individuals can transit from one state to another |
|
|
//| * population size is NOT constant - individuals can move into |
|
|
//| "exit" state and leave population at the next turn, but there |
|
|
//| are no new individuals |
|
|
//| * amount of individuals which leave population can be predicted |
|
|
//| * you want to model transitions of individuals from one state |
|
|
//| into another (including transitions into the "exit" state) |
|
|
//| This model is discussed in more details in the ALGLIB User Guide |
|
|
//| (see http://www.alglib.net/dataanalysis/ for more data). |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - problem dimension, N>=2 |
|
|
//| ExitState- index of exit state, in 0..N-1 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure stores algorithm state |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MCPDCreateExit(const int n,const int exitstate,
|
|
CMCPDStateShell &s)
|
|
{
|
|
//--- function call
|
|
CMarkovCPD::MCPDCreateExit(n,exitstate,s.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| DESCRIPTION: |
|
|
//| This function is a specialized version of MCPDCreate() function, |
|
|
//| and we recommend you to read comments for this function for |
|
|
//| general information about MCPD solver. |
|
|
//| This function creates MCPD (Markov Chains for Population Data) |
|
|
//| solver for "Entry-Exit-states" model, i.e. model where transition|
|
|
//| from X[i] to X[i+1] is modelled as |
|
|
//| X[i+1] = P*X[i] |
|
|
//| where |
|
|
//| X[i] and X[i+1] are N-dimensional state vectors |
|
|
//| P is a N*N transition matrix |
|
|
//| one selected component of X[] is called "entry" state and is a |
|
|
//| treated in special way: |
|
|
//| system state always transits from "entry" state to some |
|
|
//| another state |
|
|
//| system state can not transit from any state into "entry" |
|
|
//| state |
|
|
//| and another one component of X[] is called "exit" state and is |
|
|
//| treated in a special way too: |
|
|
//| system state can transit from any state into "exit" state |
|
|
//| system state can not transit from "exit" state into any other|
|
|
//| state transition operator discards "exit" state (makes it |
|
|
//| zero at each turn) |
|
|
//| Such conditions basically mean that: |
|
|
//| row of P which corresponds to "entry" state is zero |
|
|
//| column of P which corresponds to "exit" state is zero |
|
|
//| Multiplication by such P may decrease sum of vector components. |
|
|
//| Such models arise when: |
|
|
//| * there is some population of individuals |
|
|
//| * individuals can have different states |
|
|
//| * individuals can transit from one state to another |
|
|
//| * population size is NOT constant |
|
|
//| * at every moment of time there is some (unpredictable) amount |
|
|
//| of "new" individuals, which can transit into one of the states |
|
|
//| at the next turn |
|
|
//| * some individuals can move (predictably) into "exit" state |
|
|
//| and leave population at the next turn |
|
|
//| * you want to model transitions of individuals from one state |
|
|
//| into another, including transitions from the "entry" state and |
|
|
//| into the "exit" state. |
|
|
//| * but you do NOT want to predict amount of "new" individuals |
|
|
//| because it does not depends on individuals already present |
|
|
//| (hence system can not transit INTO entry state - it can only |
|
|
//| transit FROM it). |
|
|
//| This model is discussed in more details in the ALGLIB User |
|
|
//| Guide (see http://www.alglib.net/dataanalysis/ for more data). |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - problem dimension, N>=2 |
|
|
//| EntryState- index of entry state, in 0..N-1 |
|
|
//| ExitState- index of exit state, in 0..N-1 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure stores algorithm state |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MCPDCreateEntryExit(const int n,const int entrystate,
|
|
const int exitstate,CMCPDStateShell &s)
|
|
{
|
|
//--- function call
|
|
CMarkovCPD::MCPDCreateEntryExit(n,entrystate,exitstate,s.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function is used to add a track - sequence of system states |
|
|
//| at the different moments of its evolution. |
|
|
//| You may add one or several tracks to the MCPD solver. In case you|
|
|
//| have several tracks, they won't overwrite each other. For |
|
|
//| example, if you pass two tracks, A1-A2-A3 (system at t=A+1, t=A+2|
|
|
//| and t=A+3) and B1-B2-B3, then solver will try to model |
|
|
//| transitions from t=A+1 to t=A+2, t=A+2 to t=A+3, t=B+1 to t=B+2, |
|
|
//| t=B+2 to t=B+3. But it WONT mix these two tracks - i.e. it wont |
|
|
//| try to model transition from t=A+3 to t=B+1. |
|
|
//| INPUT PARAMETERS: |
|
|
//| S - solver |
|
|
//| XY - track, array[K,N]: |
|
|
//| * I-th row is a state at t=I |
|
|
//| * elements of XY must be non-negative (exception |
|
|
//| will be thrown on negative elements) |
|
|
//| K - number of points in a track |
|
|
//| * if given, only leading K rows of XY are used |
|
|
//| * if not given, automatically determined from |
|
|
//| size of XY |
|
|
//| NOTES: |
|
|
//| 1. Track may contain either proportional or population data: |
|
|
//| * with proportional data all rows of XY must sum to 1.0, i.e. |
|
|
//| we have proportions instead of absolute population values |
|
|
//| * with population data rows of XY contain population counts |
|
|
//| and generally do not sum to 1.0 (although they still must be|
|
|
//| non-negative) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MCPDAddTrack(CMCPDStateShell &s,CMatrixDouble &xy,
|
|
const int k)
|
|
{
|
|
//--- function call
|
|
CMarkovCPD::MCPDAddTrack(s.GetInnerObj(),xy,k);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function is used to add a track - sequence of system states |
|
|
//| at the different moments of its evolution. |
|
|
//| You may add one or several tracks to the MCPD solver. In case you|
|
|
//| have several tracks, they won't overwrite each other. For |
|
|
//| example, if you pass two tracks, A1-A2-A3 (system at t=A+1, t=A+2|
|
|
//| and t=A+3) and B1-B2-B3, then solver will try to model |
|
|
//| transitions from t=A+1 to t=A+2, t=A+2 to t=A+3, t=B+1 to t=B+2, |
|
|
//| t=B+2 to t=B+3. But it WONT mix these two tracks - i.e. it wont |
|
|
//| try to model transition from t=A+3 to t=B+1. |
|
|
//| INPUT PARAMETERS: |
|
|
//| S - solver |
|
|
//| XY - track, array[K,N]: |
|
|
//| * I-th row is a state at t=I |
|
|
//| * elements of XY must be non-negative (exception |
|
|
//| will be thrown on negative elements) |
|
|
//| K - number of points in a track |
|
|
//| * if given, only leading K rows of XY are used |
|
|
//| * if not given, automatically determined from |
|
|
//| size of XY |
|
|
//| NOTES: |
|
|
//| 1. Track may contain either proportional or population data: |
|
|
//| * with proportional data all rows of XY must sum to 1.0, i.e. |
|
|
//| we have proportions instead of absolute population values |
|
|
//| * with population data rows of XY contain population counts |
|
|
//| and generally do not sum to 1.0 (although they still must be|
|
|
//| non-negative) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MCPDAddTrack(CMCPDStateShell &s,CMatrixDouble &xy)
|
|
{
|
|
//--- create a variable
|
|
int k;
|
|
//--- initialization
|
|
k=CAp::Rows(xy);
|
|
//--- function call
|
|
CMarkovCPD::MCPDAddTrack(s.GetInnerObj(),xy,k);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function is used to add equality constraints on the elements|
|
|
//| of the transition matrix P. |
|
|
//| MCPD solver has four types of constraints which can be placed |
|
|
//| on P: |
|
|
//| * user-specified equality constraints (optional) |
|
|
//| * user-specified bound constraints (optional) |
|
|
//| * user-specified general linear constraints (optional) |
|
|
//| * basic constraints (always present): |
|
|
//| * non-negativity: P[i,j]>=0 |
|
|
//| * consistency: every column of P sums to 1.0 |
|
|
//| Final constraints which are passed to the underlying optimizer |
|
|
//| are calculated as intersection of all present constraints. For |
|
|
//| example, you may specify boundary constraint on P[0,0] and |
|
|
//| equality one: |
|
|
//| 0.1<=P[0,0]<=0.9 |
|
|
//| P[0,0]=0.5 |
|
|
//| Such combination of constraints will be silently reduced to their|
|
|
//| intersection, which is P[0,0]=0.5. |
|
|
//| This function can be used to place equality constraints on |
|
|
//| arbitrary subset of elements of P. Set of constraints is |
|
|
//| specified by EC, which may contain either NAN's or finite numbers|
|
|
//| from [0,1]. NAN denotes absence of constraint, finite number |
|
|
//| denotes equality constraint on specific element of P. |
|
|
//| You can also use MCPDAddEC() function which allows to ADD |
|
|
//| equality constraint for one element of P without changing |
|
|
//| constraints for other elements. |
|
|
//| These functions (MCPDSetEC and MCPDAddEC) interact as follows: |
|
|
//| * there is internal matrix of equality constraints which is |
|
|
//| stored in the MCPD solver |
|
|
//| * MCPDSetEC() replaces this matrix by another one (SET) |
|
|
//| * MCPDAddEC() modifies one element of this matrix and leaves |
|
|
//| other ones unchanged (ADD) |
|
|
//| * thus MCPDAddEC() call preserves all modifications done by |
|
|
//| previous calls, while MCPDSetEC() completely discards all |
|
|
//| changes done to the equality constraints. |
|
|
//| INPUT PARAMETERS: |
|
|
//| S - solver |
|
|
//| EC - equality constraints, array[N,N]. Elements of EC |
|
|
//| can be either NAN's or finite numbers from [0,1].|
|
|
//| NAN denotes absence of constraints, while finite |
|
|
//| value denotes equality constraint on the |
|
|
//| corresponding element of P. |
|
|
//| NOTES: |
|
|
//| 1. infinite values of EC will lead to exception being thrown. |
|
|
//| Values less than 0.0 or greater than 1.0 will lead to error code |
|
|
//| being returned after call to MCPDSolve(). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MCPDSetEC(CMCPDStateShell &s,CMatrixDouble &ec)
|
|
{
|
|
//--- function call
|
|
CMarkovCPD::MCPDSetEC(s.GetInnerObj(),ec);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function is used to add equality constraints on the elements|
|
|
//| of the transition matrix P. |
|
|
//| MCPD solver has four types of constraints which can be placed |
|
|
//| on P: |
|
|
//| * user-specified equality constraints (optional) |
|
|
//| * user-specified bound constraints (optional) |
|
|
//| * user-specified general linear constraints (optional) |
|
|
//| * basic constraints (always present): |
|
|
//| * non-negativity: P[i,j]>=0 |
|
|
//| * consistency: every column of P sums to 1.0 |
|
|
//| Final constraints which are passed to the underlying optimizer |
|
|
//| are calculated as intersection of all present constraints. For |
|
|
//| example, you may specify boundary constraint on P[0,0] and |
|
|
//| equality one: |
|
|
//| 0.1<=P[0,0]<=0.9 |
|
|
//| P[0,0]=0.5 |
|
|
//| Such combination of constraints will be silently reduced to their|
|
|
//| intersection, which is P[0,0]=0.5. |
|
|
//| This function can be used to ADD equality constraint for one |
|
|
//| element of P without changing constraints for other elements. |
|
|
//| You can also use MCPDSetEC() function which allows you to specify|
|
|
//| arbitrary set of equality constraints in one call. |
|
|
//| These functions (MCPDSetEC and MCPDAddEC) interact as follows: |
|
|
//| * there is internal matrix of equality constraints which is |
|
|
//| stored in the MCPD solver |
|
|
//| * MCPDSetEC() replaces this matrix by another one (SET) |
|
|
//| * MCPDAddEC() modifies one element of this matrix and leaves |
|
|
//| other ones unchanged (ADD) |
|
|
//| * thus MCPDAddEC() call preserves all modifications done by |
|
|
//| previous calls, while MCPDSetEC() completely discards all |
|
|
//| changes done to the equality constraints. |
|
|
//| INPUT PARAMETERS: |
|
|
//| S - solver |
|
|
//| I - row index of element being constrained |
|
|
//| J - column index of element being constrained |
|
|
//| C - value (constraint for P[I,J]). Can be either NAN |
|
|
//| (no constraint) or finite value from [0,1]. |
|
|
//| NOTES: |
|
|
//| 1. infinite values of C will lead to exception being thrown. |
|
|
//| Values less than 0.0 or greater than 1.0 will lead to error code |
|
|
//| being returned after call to MCPDSolve(). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MCPDAddEC(CMCPDStateShell &s,const int i,const int j,
|
|
const double c)
|
|
{
|
|
//--- function call
|
|
CMarkovCPD::MCPDAddEC(s.GetInnerObj(),i,j,c);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function is used to add bound constraints on the elements |
|
|
//| of the transition matrix P. |
|
|
//| MCPD solver has four types of constraints which can be placed |
|
|
//| on P: |
|
|
//| * user-specified equality constraints (optional) |
|
|
//| * user-specified bound constraints (optional) |
|
|
//| * user-specified general linear constraints (optional) |
|
|
//| * basic constraints (always present): |
|
|
//| * non-negativity: P[i,j]>=0 |
|
|
//| * consistency: every column of P sums to 1.0 |
|
|
//| Final constraints which are passed to the underlying optimizer |
|
|
//| are calculated as intersection of all present constraints. For |
|
|
//| example, you may specify boundary constraint on P[0,0] and |
|
|
//| equality one: |
|
|
//| 0.1<=P[0,0]<=0.9 |
|
|
//| P[0,0]=0.5 |
|
|
//| Such combination of constraints will be silently reduced to their|
|
|
//| intersection, which is P[0,0]=0.5. |
|
|
//| This function can be used to place bound constraints on arbitrary|
|
|
//| subset of elements of P. Set of constraints is specified by |
|
|
//| BndL/BndU matrices, which may contain arbitrary combination of |
|
|
//| finite numbers or infinities (like -INF<x<=0.5 or 0.1<=x<+INF). |
|
|
//| You can also use MCPDAddBC() function which allows to ADD bound |
|
|
//| constraint for one element of P without changing constraints for |
|
|
//| other elements. |
|
|
//| These functions (MCPDSetBC and MCPDAddBC) interact as follows: |
|
|
//| * there is internal matrix of bound constraints which is stored |
|
|
//| in the MCPD solver |
|
|
//| * MCPDSetBC() replaces this matrix by another one (SET) |
|
|
//| * MCPDAddBC() modifies one element of this matrix and leaves |
|
|
//| other ones unchanged (ADD) |
|
|
//| * thus MCPDAddBC() call preserves all modifications done by |
|
|
//| previous calls, while MCPDSetBC() completely discards all |
|
|
//| changes done to the equality constraints. |
|
|
//| INPUT PARAMETERS: |
|
|
//| S - solver |
|
|
//| BndL - lower bounds constraints, array[N,N]. Elements of|
|
|
//| BndL can be finite numbers or -INF. |
|
|
//| BndU - upper bounds constraints, array[N,N]. Elements of|
|
|
//| BndU can be finite numbers or +INF. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MCPDSetBC(CMCPDStateShell &s,CMatrixDouble &bndl,
|
|
CMatrixDouble &bndu)
|
|
{
|
|
//--- function call
|
|
CMarkovCPD::MCPDSetBC(s.GetInnerObj(),bndl,bndu);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function is used to add bound constraints on the elements |
|
|
//| of the transition matrix P. |
|
|
//| MCPD solver has four types of constraints which can be placed |
|
|
//| on P: |
|
|
//| * user-specified equality constraints (optional) |
|
|
//| * user-specified bound constraints (optional) |
|
|
//| * user-specified general linear constraints (optional) |
|
|
//| * basic constraints (always present): |
|
|
//| * non-negativity: P[i,j]>=0 |
|
|
//| * consistency: every column of P sums to 1.0 |
|
|
//| Final constraints which are passed to the underlying optimizer |
|
|
//| are calculated as intersection of all present constraints. For |
|
|
//| example, you may specify boundary constraint on P[0,0] and |
|
|
//| equality one: |
|
|
//| 0.1<=P[0,0]<=0.9 |
|
|
//| P[0,0]=0.5 |
|
|
//| Such combination of constraints will be silently reduced to their|
|
|
//| intersection, which is P[0,0]=0.5. |
|
|
//| This function can be used to ADD bound constraint for one element|
|
|
//| of P without changing constraints for other elements. |
|
|
//| You can also use MCPDSetBC() function which allows to place bound|
|
|
//| constraints on arbitrary subset of elements of P. Set of |
|
|
//| constraints is specified by BndL/BndU matrices, which may |
|
|
//| contain arbitrary combination of finite numbers or infinities |
|
|
//| (like -INF<x<=0.5 or 0.1<=x<+INF). |
|
|
//| These functions (MCPDSetBC and MCPDAddBC) interact as follows: |
|
|
//| * there is internal matrix of bound constraints which is stored |
|
|
//| in the MCPD solver |
|
|
//| * MCPDSetBC() replaces this matrix by another one (SET) |
|
|
//| * MCPDAddBC() modifies one element of this matrix and leaves |
|
|
//| other ones unchanged (ADD) |
|
|
//| * thus MCPDAddBC() call preserves all modifications done by |
|
|
//| previous calls, while MCPDSetBC() completely discards all |
|
|
//| changes done to the equality constraints. |
|
|
//| INPUT PARAMETERS: |
|
|
//| S - solver |
|
|
//| I - row index of element being constrained |
|
|
//| J - column index of element being constrained |
|
|
//| BndL - lower bound |
|
|
//| BndU - upper bound |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MCPDAddBC(CMCPDStateShell &s,const int i,const int j,
|
|
const double bndl,const double bndu)
|
|
{
|
|
//--- function call
|
|
CMarkovCPD::MCPDAddBC(s.GetInnerObj(),i,j,bndl,bndu);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function is used to set linear equality/inequality |
|
|
//| constraints on the elements of the transition matrix P. |
|
|
//| This function can be used to set one or several general linear |
|
|
//| constraints on the elements of P. Two types of constraints are |
|
|
//| supported: |
|
|
//| * equality constraints |
|
|
//| * inequality constraints (both less-or-equal and |
|
|
//| greater-or-equal) |
|
|
//| Coefficients of constraints are specified by matrix C (one of the|
|
|
//| parameters). One row of C corresponds to one constraint. |
|
|
//| Because transition matrix P has N*N elements, we need N*N columns|
|
|
//| to store all coefficients (they are stored row by row), and |
|
|
//| one more column to store right part - hence C has N*N+1 columns. |
|
|
//| Constraint kind is stored in the CT array. |
|
|
//| Thus, I-th linear constraint is |
|
|
//| P[0,0]*C[I,0] + P[0,1]*C[I,1] + .. + P[0,N-1]*C[I,N-1] + |
|
|
//| + P[1,0]*C[I,N] + P[1,1]*C[I,N+1] + ... + |
|
|
//| + P[N-1,N-1]*C[I,N*N-1] ?=? C[I,N*N] |
|
|
//| where ?=? can be either "=" (CT[i]=0), "<=" (CT[i]<0) or ">=" |
|
|
//| (CT[i]>0). |
|
|
//| Your constraint may involve only some subset of P (less than N*N |
|
|
//| elements). |
|
|
//| For example it can be something like |
|
|
//| P[0,0] + P[0,1] = 0.5 |
|
|
//| In this case you still should pass matrix with N*N+1 columns, |
|
|
//| but all its elements (except for C[0,0], C[0,1] and C[0,N*N-1]) |
|
|
//| will be zero. |
|
|
//| INPUT PARAMETERS: |
|
|
//| S - solver |
|
|
//| C - array[K,N*N+1] - coefficients of constraints |
|
|
//| (see above for complete description) |
|
|
//| CT - array[K] - constraint types |
|
|
//| (see above for complete description) |
|
|
//| K - number of equality/inequality constraints, K>=0: |
|
|
//| * if given, only leading K elements of C/CT are |
|
|
//| used |
|
|
//| * if not given, automatically determined from |
|
|
//| sizes of C/CT |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MCPDSetLC(CMCPDStateShell &s,CMatrixDouble &c,
|
|
int &ct[],const int k)
|
|
{
|
|
//--- function call
|
|
CMarkovCPD::MCPDSetLC(s.GetInnerObj(),c,ct,k);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function is used to set linear equality/inequality |
|
|
//| constraints on the elements of the transition matrix P. |
|
|
//| This function can be used to set one or several general linear |
|
|
//| constraints on the elements of P. Two types of constraints are |
|
|
//| supported: |
|
|
//| * equality constraints |
|
|
//| * inequality constraints (both less-or-equal and |
|
|
//| greater-or-equal) |
|
|
//| Coefficients of constraints are specified by matrix C (one of the|
|
|
//| parameters). One row of C corresponds to one constraint. |
|
|
//| Because transition matrix P has N*N elements, we need N*N columns|
|
|
//| to store all coefficients (they are stored row by row), and |
|
|
//| one more column to store right part - hence C has N*N+1 columns. |
|
|
//| Constraint kind is stored in the CT array. |
|
|
//| Thus, I-th linear constraint is |
|
|
//| P[0,0]*C[I,0] + P[0,1]*C[I,1] + .. + P[0,N-1]*C[I,N-1] + |
|
|
//| + P[1,0]*C[I,N] + P[1,1]*C[I,N+1] + ... + |
|
|
//| + P[N-1,N-1]*C[I,N*N-1] ?=? C[I,N*N] |
|
|
//| where ?=? can be either "=" (CT[i]=0), "<=" (CT[i]<0) or ">=" |
|
|
//| (CT[i]>0). |
|
|
//| Your constraint may involve only some subset of P (less than N*N |
|
|
//| elements). |
|
|
//| For example it can be something like |
|
|
//| P[0,0] + P[0,1] = 0.5 |
|
|
//| In this case you still should pass matrix with N*N+1 columns, |
|
|
//| but all its elements (except for C[0,0], C[0,1] and C[0,N*N-1]) |
|
|
//| will be zero. |
|
|
//| INPUT PARAMETERS: |
|
|
//| S - solver |
|
|
//| C - array[K,N*N+1] - coefficients of constraints |
|
|
//| (see above for complete description) |
|
|
//| CT - array[K] - constraint types |
|
|
//| (see above for complete description) |
|
|
//| K - number of equality/inequality constraints, K>=0: |
|
|
//| * if given, only leading K elements of C/CT are |
|
|
//| used |
|
|
//| * if not given, automatically determined from |
|
|
//| sizes of C/CT |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MCPDSetLC(CMCPDStateShell &s,CMatrixDouble &c,int &ct[])
|
|
{
|
|
//--- create a variable
|
|
int k;
|
|
//--- check
|
|
if((CAp::Rows(c)!=CAp::Len(ct)))
|
|
{
|
|
Print("Error while calling "+__FUNCTION__+": looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
k=CAp::Rows(c);
|
|
//--- function call
|
|
CMarkovCPD::MCPDSetLC(s.GetInnerObj(),c,ct,k);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function allows to tune amount of Tikhonov regularization |
|
|
//| being applied to your problem. |
|
|
//| By default, regularizing term is equal to r*||P-prior_P||^2, |
|
|
//| where r is a small non-zero value, P is transition matrix, |
|
|
//| prior_P is identity matrix, ||X||^2 is a sum of squared elements |
|
|
//| of X. |
|
|
//| This function allows you to change coefficient r. You can also |
|
|
//| change prior values with MCPDSetPrior() function. |
|
|
//| INPUT PARAMETERS: |
|
|
//| S - solver |
|
|
//| V - regularization coefficient, finite non-negative |
|
|
//| value. It is not recommended to specify zero |
|
|
//| value unless you are pretty sure that you want it.|
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MCPDSetTikhonovRegularizer(CMCPDStateShell &s,
|
|
const double v)
|
|
{
|
|
//--- function call
|
|
CMarkovCPD::MCPDSetTikhonovRegularizer(s.GetInnerObj(),v);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function allows to set prior values used for regularization |
|
|
//| of your problem. |
|
|
//| By default, regularizing term is equal to r*||P-prior_P||^2, |
|
|
//| where r is a small non-zero value, P is transition matrix, |
|
|
//| prior_P is identity matrix, ||X||^2 is a sum of squared elements |
|
|
//| of X. |
|
|
//| This function allows you to change prior values prior_P. You can |
|
|
//| also change r with MCPDSetTikhonovRegularizer() function. |
|
|
//| INPUT PARAMETERS: |
|
|
//| S - solver |
|
|
//| PP - array[N,N], matrix of prior values: |
|
|
//| 1. elements must be real numbers from [0,1] |
|
|
//| 2. columns must sum to 1.0. |
|
|
//| First property is checked (exception is thrown |
|
|
//| otherwise), while second one is not |
|
|
//| checked/enforced. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MCPDSetPrior(CMCPDStateShell &s,CMatrixDouble &pp)
|
|
{
|
|
//--- function call
|
|
CMarkovCPD::MCPDSetPrior(s.GetInnerObj(),pp);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function is used to change prediction weights |
|
|
//| MCPD solver scales prediction errors as follows |
|
|
//| Error(P) = ||W*(y-P*x)||^2 |
|
|
//| where |
|
|
//| x is a system state at time t |
|
|
//| y is a system state at time t+1 |
|
|
//| P is a transition matrix |
|
|
//| W is a diagonal scaling matrix |
|
|
//| By default, weights are chosen in order to minimize relative |
|
|
//| prediction error instead of absolute one. For example, if one |
|
|
//| component of state is about 0.5 in magnitude and another one is |
|
|
//| about 0.05, then algorithm will make corresponding weights equal |
|
|
//| to 2.0 and 20.0. |
|
|
//| INPUT PARAMETERS: |
|
|
//| S - solver |
|
|
//| PW - array[N], weights: |
|
|
//| * must be non-negative values (exception will be |
|
|
//| thrown otherwise) |
|
|
//| * zero values will be replaced by automatically |
|
|
//| chosen values |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MCPDSetPredictionWeights(CMCPDStateShell &s,
|
|
double &pw[])
|
|
{
|
|
//--- function call
|
|
CMarkovCPD::MCPDSetPredictionWeights(s.GetInnerObj(),pw);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function is used to start solution of the MCPD problem. |
|
|
//| After return from this function, you can use MCPDResults() to get|
|
|
//| solution and completion code. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MCPDSolve(CMCPDStateShell &s)
|
|
{
|
|
//--- function call
|
|
CMarkovCPD::MCPDSolve(s.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| MCPD results |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - algorithm state |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| P - array[N,N], transition matrix |
|
|
//| Rep - optimization report. You should check Rep. |
|
|
//| TerminationType in order to distinguish successful|
|
|
//| termination from unsuccessful one. Speaking short,|
|
|
//| positive values denote success, negative ones are |
|
|
//| failures. More information about fields of this |
|
|
//| structure can befound in the comments on |
|
|
//| MCPDReport datatype. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MCPDResults(CMCPDStateShell &s,CMatrixDouble &p,
|
|
CMCPDReportShell &rep)
|
|
{
|
|
//--- function call
|
|
CMarkovCPD::MCPDResults(s.GetInnerObj(),p,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Neural network training using modified Levenberg-Marquardt with |
|
|
//| exact Hessian calculation and regularization. Subroutine trains |
|
|
//| neural network with restarts from random positions. Algorithm is |
|
|
//| well suited for small |
|
|
//| and medium scale problems (hundreds of weights). |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - neural network with initialized geometry |
|
|
//| XY - training set |
|
|
//| NPoints - training set size |
|
|
//| Decay - weight decay constant, >=0.001 |
|
|
//| Decay term 'Decay*||Weights||^2' is added to |
|
|
//| error function. |
|
|
//| If you don't know what Decay to choose, use |
|
|
//| 0.001. |
|
|
//| Restarts - number of restarts from random position, >0. |
|
|
//| If you don't know what Restarts to choose, |
|
|
//| use 2. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Network - trained neural network. |
|
|
//| Info - return code: |
|
|
//| * -9, if internal matrix inverse subroutine |
|
|
//| failed |
|
|
//| * -2, if there is a point with class number |
|
|
//| outside of [0..NOut-1]. |
|
|
//| * -1, if wrong parameters specified |
|
|
//| (NPoints<0, Restarts<1). |
|
|
//| * 2, if task has been solved. |
|
|
//| Rep - training report |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPTrainLM(CMultilayerPerceptronShell &network,
|
|
CMatrixDouble &xy,const int npoints,
|
|
const double decay,const int restarts,
|
|
int &info,CMLPReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CMLPTrain::MLPTrainLM(network.GetInnerObj(),xy,npoints,decay,restarts,info,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Neural network training using L-BFGS algorithm with |
|
|
//| regularization. Subroutine trains neural network with restarts |
|
|
//| from random positions. Algorithm is well suited for problems of |
|
|
//| any dimensionality (memory requirements and step complexity are |
|
|
//| linear by weights number). |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - neural network with initialized geometry |
|
|
//| XY - training set |
|
|
//| NPoints - training set size |
|
|
//| Decay - weight decay constant, >=0.001 |
|
|
//| Decay term 'Decay*||Weights||^2' is added to |
|
|
//| error function. |
|
|
//| If you don't know what Decay to choose, use |
|
|
//| 0.001. |
|
|
//| Restarts - number of restarts from random position, >0. |
|
|
//| If you don't know what Restarts to choose, |
|
|
//| use 2. |
|
|
//| WStep - stopping criterion. Algorithm stops if step |
|
|
//| size is less than WStep. Recommended |
|
|
//| value - 0.01. Zero step size means stopping |
|
|
//| after MaxIts iterations. |
|
|
//| MaxIts - stopping criterion. Algorithm stops after |
|
|
//| MaxIts iterations (NOT gradient calculations).|
|
|
//| Zero MaxIts means stopping when step is |
|
|
//| sufficiently small. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Network - trained neural network. |
|
|
//| Info - return code: |
|
|
//| * -8, if both WStep=0 and MaxIts=0 |
|
|
//| * -2, if there is a point with class number |
|
|
//| outside of [0..NOut-1]. |
|
|
//| * -1, if wrong parameters specified |
|
|
//| (NPoints<0, Restarts<1). |
|
|
//| * 2, if task has been solved. |
|
|
//| Rep - training report |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPTrainLBFGS(CMultilayerPerceptronShell &network,
|
|
CMatrixDouble &xy,const int npoints,
|
|
const double decay,const int restarts,
|
|
const double wstep,int maxits,
|
|
int &info,CMLPReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CMLPTrain::MLPTrainLBFGS(network.GetInnerObj(),xy,npoints,decay,restarts,wstep,maxits,info,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Neural network training using early stopping (base algorithm - |
|
|
//| L-BFGS with regularization). |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - neural network with initialized geometry |
|
|
//| TrnXY - training set |
|
|
//| TrnSize - training set size |
|
|
//| ValXY - validation set |
|
|
//| ValSize - validation set size |
|
|
//| Decay - weight decay constant, >=0.001 |
|
|
//| Decay term 'Decay*||Weights||^2' is added to |
|
|
//| error function. |
|
|
//| If you don't know what Decay to choose, use |
|
|
//| 0.001. |
|
|
//| Restarts - number of restarts from random position, >0. |
|
|
//| If you don't know what Restarts to choose, |
|
|
//| use 2. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Network - trained neural network. |
|
|
//| Info - return code: |
|
|
//| * -2, if there is a point with class number |
|
|
//| outside of [0..NOut-1]. |
|
|
//| * -1, if wrong parameters specified |
|
|
//| (NPoints<0, Restarts<1, ...). |
|
|
//| * 2, task has been solved, stopping |
|
|
//| criterion met - sufficiently small |
|
|
//| step size. Not expected (we use EARLY |
|
|
//| stopping) but possible and not an error|
|
|
//| * 6, task has been solved, stopping |
|
|
//| criterion met - increasing of |
|
|
//| validation set error. |
|
|
//| Rep - training report |
|
|
//| NOTE: |
|
|
//| Algorithm stops if validation set error increases for a long |
|
|
//| enough or step size is small enought (there are task where |
|
|
//| validation set may decrease for eternity). In any case solution |
|
|
//| returned corresponds to the minimum of validation set error. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPTrainES(CMultilayerPerceptronShell &network,
|
|
CMatrixDouble &trnxy,const int trnsize,
|
|
CMatrixDouble &valxy,const int valsize,
|
|
const double decay,const int restarts,
|
|
int &info,CMLPReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CMLPTrain::MLPTrainES(network.GetInnerObj(),trnxy,trnsize,valxy,valsize,decay,restarts,info,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Cross-validation estimate of generalization error. |
|
|
//| Base algorithm - L-BFGS. |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - neural network with initialized geometry. |
|
|
//| Network is not changed during |
|
|
//| cross-validation - it is used only as a |
|
|
//| representative of its architecture. |
|
|
//| XY - training set. |
|
|
//| SSize - training set size |
|
|
//| Decay - weight decay, same as in MLPTrainLBFGS |
|
|
//| Restarts - number of restarts, >0. |
|
|
//| restarts are counted for each partition |
|
|
//| separately, so total number of restarts will |
|
|
//| be Restarts*FoldsCount. |
|
|
//| WStep - stopping criterion, same as in MLPTrainLBFGS |
|
|
//| MaxIts - stopping criterion, same as in MLPTrainLBFGS |
|
|
//| FoldsCount - number of folds in k-fold cross-validation, |
|
|
//| 2<=FoldsCount<=SSize. |
|
|
//| recommended value: 10. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - return code, same as in MLPTrainLBFGS |
|
|
//| Rep - report, same as in MLPTrainLM/MLPTrainLBFGS |
|
|
//| CVRep - generalization error estimates |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPKFoldCVLBFGS(CMultilayerPerceptronShell &network,
|
|
CMatrixDouble &xy,const int npoints,
|
|
const double decay,const int restarts,
|
|
const double wstep,const int maxits,
|
|
const int foldscount,int &info,
|
|
CMLPReportShell &rep,CMLPCVReportShell &cvrep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CMLPTrain::MLPKFoldCVLBFGS(network.GetInnerObj(),xy,npoints,decay,restarts,wstep,maxits,foldscount,info,rep.GetInnerObj(),cvrep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Cross-validation estimate of generalization error. |
|
|
//| Base algorithm - Levenberg-Marquardt. |
|
|
//| INPUT PARAMETERS: |
|
|
//| Network - neural network with initialized geometry. |
|
|
//| Network is not changed during |
|
|
//| cross-validation - it is used only as a |
|
|
//| representative of its architecture. |
|
|
//| XY - training set. |
|
|
//| SSize - training set size |
|
|
//| Decay - weight decay, same as in MLPTrainLBFGS |
|
|
//| Restarts - number of restarts, >0. |
|
|
//| restarts are counted for each partition |
|
|
//| separately, so total number of restarts will |
|
|
//| be Restarts*FoldsCount. |
|
|
//| FoldsCount - number of folds in k-fold cross-validation, |
|
|
//| 2<=FoldsCount<=SSize. |
|
|
//| recommended value: 10. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - return code, same as in MLPTrainLBFGS |
|
|
//| Rep - report, same as in MLPTrainLM/MLPTrainLBFGS |
|
|
//| CVRep - generalization error estimates |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPKFoldCVLM(CMultilayerPerceptronShell &network,
|
|
CMatrixDouble &xy,const int npoints,
|
|
const double decay,const int restarts,
|
|
const int foldscount,int &info,
|
|
CMLPReportShell &rep,CMLPCVReportShell &cvrep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CMLPTrain::MLPKFoldCVLM(network.GetInnerObj(),xy,npoints,decay,restarts,foldscount,info,rep.GetInnerObj(),cvrep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Like MLPCreate0, but for ensembles. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPECreate0(const int nin,const int nout,const int ensemblesize,
|
|
CMLPEnsembleShell &ensemble)
|
|
{
|
|
//--- function call
|
|
CMLPE::MLPECreate0(nin,nout,ensemblesize,ensemble.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Like MLPCreate1, but for ensembles. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPECreate1(const int nin,int nhid,const int nout,
|
|
const int ensemblesize,
|
|
CMLPEnsembleShell &ensemble)
|
|
{
|
|
//--- function call
|
|
CMLPE::MLPECreate1(nin,nhid,nout,ensemblesize,ensemble.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Like MLPCreate2, but for ensembles. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPECreate2(const int nin,const int nhid1,const int nhid2,
|
|
const int nout,const int ensemblesize,
|
|
CMLPEnsembleShell &ensemble)
|
|
{
|
|
//--- function call
|
|
CMLPE::MLPECreate2(nin,nhid1,nhid2,nout,ensemblesize,ensemble.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Like MLPCreateB0, but for ensembles. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPECreateB0(const int nin,const int nout,const double b,
|
|
const double d,const int ensemblesize,
|
|
CMLPEnsembleShell &ensemble)
|
|
{
|
|
//--- function call
|
|
CMLPE::MLPECreateB0(nin,nout,b,d,ensemblesize,ensemble.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Like MLPCreateB1, but for ensembles. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPECreateB1(const int nin,int nhid,const int nout,
|
|
const double b,const double d,const int ensemblesize,
|
|
CMLPEnsembleShell &ensemble)
|
|
{
|
|
//--- function call
|
|
CMLPE::MLPECreateB1(nin,nhid,nout,b,d,ensemblesize,ensemble.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Like MLPCreateB2, but for ensembles. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPECreateB2(const int nin,const int nhid1,const int nhid2,
|
|
const int nout,const double b,const double d,
|
|
const int ensemblesize,CMLPEnsembleShell &ensemble)
|
|
{
|
|
//--- function call
|
|
CMLPE::MLPECreateB2(nin,nhid1,nhid2,nout,b,d,ensemblesize,ensemble.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Like MLPCreateR0, but for ensembles. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPECreateR0(const int nin,const int nout,const double a,
|
|
const double b,const int ensemblesize,
|
|
CMLPEnsembleShell &ensemble)
|
|
{
|
|
//--- function call
|
|
CMLPE::MLPECreateR0(nin,nout,a,b,ensemblesize,ensemble.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Like MLPCreateR1, but for ensembles. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPECreateR1(const int nin,int nhid,const int nout,
|
|
const double a,const double b,const int ensemblesize,
|
|
CMLPEnsembleShell &ensemble)
|
|
{
|
|
//--- function call
|
|
CMLPE::MLPECreateR1(nin,nhid,nout,a,b,ensemblesize,ensemble.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Like MLPCreateR2, but for ensembles. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPECreateR2(const int nin,const int nhid1,const int nhid2,
|
|
const int nout,const double a,const double b,
|
|
const int ensemblesize,CMLPEnsembleShell &ensemble)
|
|
{
|
|
//--- function call
|
|
CMLPE::MLPECreateR2(nin,nhid1,nhid2,nout,a,b,ensemblesize,ensemble.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Like MLPCreateC0, but for ensembles. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPECreateC0(const int nin,const int nout,
|
|
const int ensemblesize,CMLPEnsembleShell &ensemble)
|
|
{
|
|
//--- function call
|
|
CMLPE::MLPECreateC0(nin,nout,ensemblesize,ensemble.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Like MLPCreateC1, but for ensembles. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPECreateC1(const int nin,int nhid,const int nout,
|
|
const int ensemblesize,CMLPEnsembleShell &ensemble)
|
|
{
|
|
//--- function call
|
|
CMLPE::MLPECreateC1(nin,nhid,nout,ensemblesize,ensemble.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Like MLPCreateC2, but for ensembles. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPECreateC2(const int nin,const int nhid1,const int nhid2,
|
|
const int nout,const int ensemblesize,
|
|
CMLPEnsembleShell &ensemble)
|
|
{
|
|
//--- function call
|
|
CMLPE::MLPECreateC2(nin,nhid1,nhid2,nout,ensemblesize,ensemble.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Creates ensemble from network. Only network geometry is copied. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPECreateFromNetwork(CMultilayerPerceptronShell &network,
|
|
const int ensemblesize,
|
|
CMLPEnsembleShell &ensemble)
|
|
{
|
|
//--- function call
|
|
CMLPE::MLPECreateFromNetwork(network.GetInnerObj(),ensemblesize,ensemble.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Randomization of MLP ensemble |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPERandomize(CMLPEnsembleShell &ensemble)
|
|
{
|
|
//--- function call
|
|
CMLPE::MLPERandomize(ensemble.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Return ensemble properties (number of inputs and outputs). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPEProperties(CMLPEnsembleShell &ensemble,
|
|
int &nin,int &nout)
|
|
{
|
|
//--- initialization
|
|
nin=0;
|
|
nout=0;
|
|
//--- function call
|
|
CMLPE::MLPEProperties(ensemble.GetInnerObj(),nin,nout);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Return normalization type (whether ensemble is SOFTMAX-normalized|
|
|
//| or not). |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::MLPEIsSoftMax(CMLPEnsembleShell &ensemble)
|
|
{
|
|
//--- return result
|
|
return(CMLPE::MLPEIsSoftMax(ensemble.GetInnerObj()));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Procesing |
|
|
//| INPUT PARAMETERS: |
|
|
//| Ensemble- neural networks ensemble |
|
|
//| X - input vector, array[0..NIn-1]. |
|
|
//| Y - (possibly) preallocated buffer; if size of Y is |
|
|
//| less than NOut, it will be reallocated. If it is |
|
|
//| large enough, it is NOT reallocated, so we can |
|
|
//| save some time on reallocation. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Y - result. Regression estimate when solving |
|
|
//| regression task, vector of posterior |
|
|
//| probabilities for classification task. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPEProcess(CMLPEnsembleShell &ensemble,
|
|
double &x[],double &y[])
|
|
{
|
|
//--- function call
|
|
CMLPE::MLPEProcess(ensemble.GetInnerObj(),x,y);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 'interactive' variant of MLPEProcess for languages like Python |
|
|
//| which support constructs like "Y = MLPEProcess(LM,X)" and |
|
|
//| interactive mode of the interpreter |
|
|
//| This function allocates new array on each call, so it is |
|
|
//| significantly slower than its 'non-interactive' counterpart, but |
|
|
//| it is more convenient when you call it from command line. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPEProcessI(CMLPEnsembleShell &ensemble,
|
|
double &x[],double &y[])
|
|
{
|
|
//--- function call
|
|
CMLPE::MLPEProcessI(ensemble.GetInnerObj(),x,y);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Relative classification error on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| Ensemble- ensemble |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| percent of incorrectly classified cases. |
|
|
//| Works both for classifier betwork and for regression networks|
|
|
//| which are used as classifiers. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::MLPERelClsError(CMLPEnsembleShell &ensemble,
|
|
CMatrixDouble &xy,const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CMLPE::MLPERelClsError(ensemble.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Average cross-entropy (in bits per element) on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| Ensemble- ensemble |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| CrossEntropy/(NPoints*LN(2)). |
|
|
//| Zero if ensemble solves regression task. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::MLPEAvgCE(CMLPEnsembleShell &ensemble,
|
|
CMatrixDouble &xy,const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CMLPE::MLPEAvgCE(ensemble.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| RMS error on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| Ensemble- ensemble |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| root mean square error. |
|
|
//| Its meaning for regression task is obvious. As for |
|
|
//| classification task RMS error means error when estimating |
|
|
//| posterior probabilities. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::MLPERMSError(CMLPEnsembleShell &ensemble,
|
|
CMatrixDouble &xy,const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CMLPE::MLPERMSError(ensemble.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Average error on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| Ensemble- ensemble |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| Its meaning for regression task is obvious. As for |
|
|
//| classification task it means average error when estimating |
|
|
//| posterior probabilities. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::MLPEAvgError(CMLPEnsembleShell &ensemble,
|
|
CMatrixDouble &xy,const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CMLPE::MLPEAvgError(ensemble.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Average relative error on the test set |
|
|
//| INPUT PARAMETERS: |
|
|
//| Ensemble- ensemble |
|
|
//| XY - test set |
|
|
//| NPoints - test set size |
|
|
//| RESULT: |
|
|
//| Its meaning for regression task is obvious. As for |
|
|
//| classification task it means average relative error when |
|
|
//| estimating posterior probabilities. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::MLPEAvgRelError(CMLPEnsembleShell &ensemble,
|
|
CMatrixDouble &xy,const int npoints)
|
|
{
|
|
//--- return result
|
|
return(CMLPE::MLPEAvgRelError(ensemble.GetInnerObj(),xy,npoints));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Training neural networks ensemble using bootstrap aggregating |
|
|
//| (bagging). |
|
|
//| Modified Levenberg-Marquardt algorithm is used as base training |
|
|
//| method. |
|
|
//| INPUT PARAMETERS: |
|
|
//| Ensemble - model with initialized geometry |
|
|
//| XY - training set |
|
|
//| NPoints - training set size |
|
|
//| Decay - weight decay coefficient, >=0.001 |
|
|
//| Restarts - restarts, >0. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Ensemble - trained model |
|
|
//| Info - return code: |
|
|
//| * -2, if there is a point with class number |
|
|
//| outside of [0..NClasses-1]. |
|
|
//| * -1, if incorrect parameters was passed |
|
|
//| (NPoints<0, Restarts<1). |
|
|
//| * 2, if task has been solved. |
|
|
//| Rep - training report. |
|
|
//| OOBErrors - out-of-bag generalization error estimate |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPEBaggingLM(CMLPEnsembleShell &ensemble,CMatrixDouble &xy,
|
|
const int npoints,const double decay,
|
|
const int restarts,int &info,
|
|
CMLPReportShell &rep,CMLPCVReportShell &ooberrors)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CMLPE::MLPEBaggingLM(ensemble.GetInnerObj(),xy,npoints,decay,restarts,info,rep.GetInnerObj(),ooberrors.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Training neural networks ensemble using bootstrap aggregating |
|
|
//| (bagging). L-BFGS algorithm is used as base training method. |
|
|
//| INPUT PARAMETERS: |
|
|
//| Ensemble - model with initialized geometry |
|
|
//| XY - training set |
|
|
//| NPoints - training set size |
|
|
//| Decay - weight decay coefficient, >=0.001 |
|
|
//| Restarts - restarts, >0. |
|
|
//| WStep - stopping criterion, same as in MLPTrainLBFGS |
|
|
//| MaxIts - stopping criterion, same as in MLPTrainLBFGS |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Ensemble - trained model |
|
|
//| Info - return code: |
|
|
//| * -8, if both WStep=0 and MaxIts=0 |
|
|
//| * -2, if there is a point with class number |
|
|
//| outside of [0..NClasses-1]. |
|
|
//| * -1, if incorrect parameters was passed |
|
|
//| (NPoints<0, Restarts<1). |
|
|
//| * 2, if task has been solved. |
|
|
//| Rep - training report. |
|
|
//| OOBErrors - out-of-bag generalization error estimate |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPEBaggingLBFGS(CMLPEnsembleShell &ensemble,CMatrixDouble &xy,
|
|
const int npoints,const double decay,
|
|
const int restarts,const double wstep,
|
|
const int maxits,int &info,
|
|
CMLPReportShell &rep,
|
|
CMLPCVReportShell &ooberrors)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CMLPE::MLPEBaggingLBFGS(ensemble.GetInnerObj(),xy,npoints,decay,restarts,wstep,maxits,info,rep.GetInnerObj(),ooberrors.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Training neural networks ensemble using early stopping. |
|
|
//| INPUT PARAMETERS: |
|
|
//| Ensemble - model with initialized geometry |
|
|
//| XY - training set |
|
|
//| NPoints - training set size |
|
|
//| Decay - weight decay coefficient, >=0.001 |
|
|
//| Restarts - restarts, >0. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Ensemble - trained model |
|
|
//| Info - return code: |
|
|
//| * -2, if there is a point with class number |
|
|
//| outside of [0..NClasses-1]. |
|
|
//| * -1, if incorrect parameters was passed |
|
|
//| (NPoints<0, Restarts<1). |
|
|
//| * 6, if task has been solved. |
|
|
//| Rep - training report. |
|
|
//| OOBErrors - out-of-bag generalization error estimate |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MLPETrainES(CMLPEnsembleShell &ensemble,CMatrixDouble &xy,
|
|
const int npoints,const double decay,
|
|
const int restarts,int &info,
|
|
CMLPReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CMLPE::MLPETrainES(ensemble.GetInnerObj(),xy,npoints,decay,restarts,info,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Principal components analysis |
|
|
//| Subroutine builds orthogonal basis where first axis corresponds |
|
|
//| to direction with maximum variance, second axis maximizes |
|
|
//| variance in subspace orthogonal to first axis and so on. |
|
|
//| It should be noted that, unlike LDA, PCA does not use class |
|
|
//| labels. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - dataset, array[0..NPoints-1,0..NVars-1]. |
|
|
//| matrix contains ONLY INDEPENDENT VARIABLES. |
|
|
//| NPoints - dataset size, NPoints>=0 |
|
|
//| NVars - number of independent variables, NVars>=1 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - return code: |
|
|
//| * -4, if SVD subroutine haven't converged |
|
|
//| * -1, if wrong parameters has been passed |
|
|
//| (NPoints<0, NVars<1) |
|
|
//| * 1, if task is solved |
|
|
//| S2 - array[0..NVars-1]. variance values |
|
|
//| corresponding to basis vectors. |
|
|
//| V - array[0..NVars-1,0..NVars-1] |
|
|
//| matrix, whose columns store basis vectors. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PCABuildBasis(CMatrixDouble &x,const int npoints,
|
|
const int nvars,int &info,double &s2[],
|
|
CMatrixDouble &v)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CPCAnalysis::PCABuildBasis(x,npoints,nvars,info,s2,v);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Cash-Karp adaptive ODE solver. |
|
|
//| This subroutine solves ODE Y'=f(Y,x) with initial conditions |
|
|
//| Y(xs)=Ys (here Y may be single variable or vector of N variables)|
|
|
//| INPUT PARAMETERS: |
|
|
//| Y - initial conditions, array[0..N-1]. |
|
|
//| contains values of Y[] at X[0] |
|
|
//| N - system size |
|
|
//| X - points at which Y should be tabulated, |
|
|
//| array[0..M-1] integrations starts at X[0], ends |
|
|
//| at X[M-1], intermediate values at X[i] are |
|
|
//| returned too. |
|
|
//| SHOULD BE ORDERED BY ASCENDING OR BY DESCENDING!!|
|
|
//| M - number of intermediate points + first point + |
|
|
//| last point: |
|
|
//| * M>2 means that you need both Y(X[M-1]) and M-2 |
|
|
//| values at intermediate points |
|
|
//| * M=2 means that you want just to integrate from |
|
|
//| X[0] to X[1] and don't interested in |
|
|
//| intermediate values. |
|
|
//| * M=1 means that you don't want to integrate :) |
|
|
//| it is degenerate case, but it will be handled |
|
|
//| correctly. |
|
|
//| * M<1 means error |
|
|
//| Eps - tolerance (absolute/relative error on each step |
|
|
//| will be less than Eps). When passing: |
|
|
//| * Eps>0, it means desired ABSOLUTE error |
|
|
//| * Eps<0, it means desired RELATIVE error. |
|
|
//| Relative errors are calculated with respect to |
|
|
//| maximum values of Y seen so far. Be careful to |
|
|
//| use this criterion when starting from Y[] that |
|
|
//| are close to zero. |
|
|
//| H - initial step lenth, it will be adjusted |
|
|
//| automatically after the first step. If H=0, step |
|
|
//| will be selected automatically (usualy it will |
|
|
//| be equal to 0.001 of min(x[i]-x[j])). |
|
|
//| OUTPUT PARAMETERS |
|
|
//| State - structure which stores algorithm state between |
|
|
//| subsequent calls of OdeSolverIteration. Used |
|
|
//| for reverse communication. This structure should |
|
|
//| be passed to the OdeSolverIteration subroutine. |
|
|
//| SEE ALSO |
|
|
//| AutoGKSmoothW, AutoGKSingular, AutoGKIteration, AutoGKResults|
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::ODESolverRKCK(double &y[],const int n,double &x[],
|
|
const int m,const double eps,const double h,
|
|
CODESolverStateShell &state)
|
|
{
|
|
//--- function call
|
|
CODESolver::ODESolverRKCK(y,n,x,m,eps,h,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Cash-Karp adaptive ODE solver. |
|
|
//| This subroutine solves ODE Y'=f(Y,x) with initial conditions |
|
|
//| Y(xs)=Ys (here Y may be single variable or vector of N variables)|
|
|
//| INPUT PARAMETERS: |
|
|
//| Y - initial conditions, array[0..N-1]. |
|
|
//| contains values of Y[] at X[0] |
|
|
//| N - system size |
|
|
//| X - points at which Y should be tabulated, |
|
|
//| array[0..M-1] integrations starts at X[0], ends |
|
|
//| at X[M-1], intermediate values at X[i] are |
|
|
//| returned too. |
|
|
//| SHOULD BE ORDERED BY ASCENDING OR BY DESCENDING!!|
|
|
//| M - number of intermediate points + first point + |
|
|
//| last point: |
|
|
//| * M>2 means that you need both Y(X[M-1]) and M-2 |
|
|
//| values at intermediate points |
|
|
//| * M=2 means that you want just to integrate from |
|
|
//| X[0] to X[1] and don't interested in |
|
|
//| intermediate values. |
|
|
//| * M=1 means that you don't want to integrate :) |
|
|
//| it is degenerate case, but it will be handled |
|
|
//| correctly. |
|
|
//| * M<1 means error |
|
|
//| Eps - tolerance (absolute/relative error on each step |
|
|
//| will be less than Eps). When passing: |
|
|
//| * Eps>0, it means desired ABSOLUTE error |
|
|
//| * Eps<0, it means desired RELATIVE error. |
|
|
//| Relative errors are calculated with respect to |
|
|
//| maximum values of Y seen so far. Be careful to |
|
|
//| use this criterion when starting from Y[] that |
|
|
//| are close to zero. |
|
|
//| H - initial step lenth, it will be adjusted |
|
|
//| automatically after the first step. If H=0, step |
|
|
//| will be selected automatically (usualy it will |
|
|
//| be equal to 0.001 of min(x[i]-x[j])). |
|
|
//| OUTPUT PARAMETERS |
|
|
//| State - structure which stores algorithm state between |
|
|
//| subsequent calls of OdeSolverIteration. Used |
|
|
//| for reverse communication. This structure should |
|
|
//| be passed to the OdeSolverIteration subroutine. |
|
|
//| SEE ALSO |
|
|
//| AutoGKSmoothW, AutoGKSingular, AutoGKIteration, AutoGKResults|
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::ODESolverRKCK(double &y[],double &x[],const double eps,
|
|
const double h,CODESolverStateShell &state)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
int m;
|
|
//--- initialization
|
|
n=CAp::Len(y);
|
|
m=CAp::Len(x);
|
|
//--- function call
|
|
CODESolver::ODESolverRKCK(y,n,x,m,eps,h,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function provides reverse communication interface |
|
|
//| Reverse communication interface is not documented or recommended |
|
|
//| to use. |
|
|
//| See below for functions which provide better documented API |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::ODESolverIteration(CODESolverStateShell &state)
|
|
{
|
|
//--- return result
|
|
return(CODESolver::ODESolverIteration(state.GetInnerObj()));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function is used to launcn iterations of ODE solver |
|
|
//| It accepts following parameters: |
|
|
//| diff - callback which calculates dy/dx for given y and x|
|
|
//| obj - optional object which is passed to diff; can be |
|
|
//| NULL |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::ODESolverSolve(CODESolverStateShell &state,
|
|
CNDimensional_ODE_RP &diff,
|
|
CObject &obj)
|
|
{
|
|
//--- cycle
|
|
while(CAlglib::ODESolverIteration(state))
|
|
{
|
|
//--- check
|
|
if(state.GetNeedDY())
|
|
{
|
|
diff.ODE_RP(state.GetInnerObj().m_y,state.GetInnerObj().m_x,state.GetInnerObj().m_dy,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
Print("ALGLIB: unexpected error in 'odesolversolve'");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| ODE solver results |
|
|
//| Called after OdeSolverIteration returned False. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - algorithm state (used by OdeSolverIteration). |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| M - number of tabulated values, M>=1 |
|
|
//| XTbl - array[0..M-1], values of X |
|
|
//| YTbl - array[0..M-1,0..N-1], values of Y in X[i] |
|
|
//| Rep - solver report: |
|
|
//| * Rep.TerminationType completetion code: |
|
|
//| * -2 X is not ordered by |
|
|
//| ascending/descending or there are |
|
|
//| non-distinct X[], i.e. X[i]=X[i+1] |
|
|
//| * -1 incorrect parameters were specified |
|
|
//| * 1 task has been solved |
|
|
//| * Rep.NFEV contains number of function |
|
|
//| calculations |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::ODESolverResults(CODESolverStateShell &state,int &m,
|
|
double &xtbl[],CMatrixDouble &ytbl,
|
|
CODESolverReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
m=0;
|
|
//--- function call
|
|
CODESolver::ODESolverResults(state.GetInnerObj(),m,xtbl,ytbl,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 1-dimensional complex FFT. |
|
|
//| Array size N may be arbitrary number (composite or prime). |
|
|
//| Composite N's are handled with cache-oblivious variation of a |
|
|
//| Cooley-Tukey algorithm. Small prime-factors are transformed using|
|
|
//| hard coded codelets (similar to FFTW codelets, but without |
|
|
//| low-level optimization), large prime-factors are handled with |
|
|
//| Bluestein's algorithm. |
|
|
//| Fastests transforms are for smooth N's (prime factors are 2, 3, |
|
|
//| 5 only), most fast for powers of 2. When N have prime factors |
|
|
//| larger than these, but orders of magnitude smaller than N, |
|
|
//| computations will be about 4 times slower than for nearby highly |
|
|
//| composite N's. When N itself is prime, speed will be 6 times |
|
|
//| lower. |
|
|
//| Algorithm has O(N*logN) complexity for any N (composite or |
|
|
//| prime). |
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..N-1] - complex function to be transformed |
|
|
//| N - problem size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| A - DFT of a input array, array[0..N-1] |
|
|
//| A_out[j] = SUM(A_in[k]*exp(-2*pi*sqrt(-1)*j*k/N), |
|
|
//| k = 0..N-1) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::FFTC1D(complex &a[],const int n)
|
|
{
|
|
//--- function call
|
|
CFastFourierTransform::FFTC1D(a,n);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 1-dimensional complex FFT. |
|
|
//| Array size N may be arbitrary number (composite or prime). |
|
|
//| Composite N's are handled with cache-oblivious variation of a |
|
|
//| Cooley-Tukey algorithm. Small prime-factors are transformed using|
|
|
//| hard coded codelets (similar to FFTW codelets, but without |
|
|
//| low-level optimization), large prime-factors are handled with |
|
|
//| Bluestein's algorithm. |
|
|
//| Fastests transforms are for smooth N's (prime factors are 2, 3, |
|
|
//| 5 only), most fast for powers of 2. When N have prime factors |
|
|
//| larger than these, but orders of magnitude smaller than N, |
|
|
//| computations will be about 4 times slower than for nearby highly |
|
|
//| composite N's. When N itself is prime, speed will be 6 times |
|
|
//| lower. |
|
|
//| Algorithm has O(N*logN) complexity for any N (composite or |
|
|
//| prime). |
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..N-1] - complex function to be transformed |
|
|
//| N - problem size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| A - DFT of a input array, array[0..N-1] |
|
|
//| A_out[j] = SUM(A_in[k]*exp(-2*pi*sqrt(-1)*j*k/N), |
|
|
//| k = 0..N-1) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::FFTC1D(complex &a[])
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(a);
|
|
//--- function call
|
|
CFastFourierTransform::FFTC1D(a,n);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 1-dimensional complex inverse FFT. |
|
|
//| Array size N may be arbitrary number (composite or prime). |
|
|
//| Algorithm has O(N*logN) complexity for any N (composite or prime)|
|
|
//| See FFTC1D() description for more information about algorithm |
|
|
//| performance. |
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..N-1] - complex array to be transformed |
|
|
//| N - problem size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| A - inverse DFT of a input array, array[0..N-1] |
|
|
//| A_out[j] = SUM(A_in[k]/N*exp(+2*pi*sqrt(-1)*j*k/N), |
|
|
//| k = 0..N-1) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::FFTC1DInv(complex &a[],const int n)
|
|
{
|
|
//--- function call
|
|
CFastFourierTransform::FFTC1DInv(a,n);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 1-dimensional complex inverse FFT. |
|
|
//| Array size N may be arbitrary number (composite or prime). |
|
|
//| Algorithm has O(N*logN) complexity for any N (composite or prime)|
|
|
//| See FFTC1D() description for more information about algorithm |
|
|
//| performance. |
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..N-1] - complex array to be transformed |
|
|
//| N - problem size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| A - inverse DFT of a input array, array[0..N-1] |
|
|
//| A_out[j] = SUM(A_in[k]/N*exp(+2*pi*sqrt(-1)*j*k/N), |
|
|
//| k = 0..N-1) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::FFTC1DInv(complex &a[])
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(a);
|
|
//--- function call
|
|
CFastFourierTransform::FFTC1DInv(a,n);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 1-dimensional real FFT. |
|
|
//| Algorithm has O(N*logN) complexity for any N (composite or |
|
|
//| prime). |
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..N-1] - real function to be transformed |
|
|
//| N - problem size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| F - DFT of a input array, array[0..N-1] |
|
|
//| F[j] = SUM(A[k]*exp(-2*pi*sqrt(-1)*j*k/N), |
|
|
//| k = 0..N-1) |
|
|
//| NOTE: |
|
|
//| F[] satisfies symmetry property F[k] = conj(F[N-k]), so just |
|
|
//| one half of array is usually needed. But for convinience |
|
|
//| subroutine returns full complex array (with frequencies above |
|
|
//| N/2), so its result may be used by other FFT-related subroutines.|
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::FFTR1D(double &a[],const int n,complex &f[])
|
|
{
|
|
//--- function call
|
|
CFastFourierTransform::FFTR1D(a,n,f);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 1-dimensional real FFT. |
|
|
//| Algorithm has O(N*logN) complexity for any N (composite or |
|
|
//| prime). |
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..N-1] - real function to be transformed |
|
|
//| N - problem size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| F - DFT of a input array, array[0..N-1] |
|
|
//| F[j] = SUM(A[k]*exp(-2*pi*sqrt(-1)*j*k/N), |
|
|
//| k = 0..N-1) |
|
|
//| NOTE: |
|
|
//| F[] satisfies symmetry property F[k] = conj(F[N-k]), so just |
|
|
//| one half of array is usually needed. But for convinience |
|
|
//| subroutine returns full complex array (with frequencies above |
|
|
//| N/2), so its result may be used by other FFT-related subroutines.|
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::FFTR1D(double &a[],complex &f[])
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(a);
|
|
//--- function call
|
|
CFastFourierTransform::FFTR1D(a,n,f);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 1-dimensional real inverse FFT. |
|
|
//| Algorithm has O(N*logN) complexity for any N (composite or |
|
|
//| prime). |
|
|
//| INPUT PARAMETERS |
|
|
//| F - array[0..floor(N/2)] - frequencies from forward real |
|
|
//| FFT |
|
|
//| N - problem size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| A - inverse DFT of a input array, array[0..N-1] |
|
|
//| NOTE: |
|
|
//| F[] should satisfy symmetry property F[k] = conj(F[N-k]), |
|
|
//| so just one half of frequencies array is needed - elements from 0|
|
|
//| to floor(N/2). F[0] is ALWAYS real. If N is even F[floor(N/2)] is|
|
|
//| real too. If N is odd, then F[floor(N/2)] has no special |
|
|
//| properties. |
|
|
//| Relying on properties noted above, FFTR1DInv subroutine uses only|
|
|
//| elements from 0th to floor(N/2)-th. It ignores imaginary part of |
|
|
//| F[0], and in case N is even it ignores imaginary part of |
|
|
//| F[floor(N/2)] too. |
|
|
//| When you call this function using full arguments list - |
|
|
//| "FFTR1DInv(F,N,A)" |
|
|
//| - you can pass either either frequencies array with N elements or|
|
|
//| reduced array with roughly N/2 elements - subroutine will |
|
|
//| successfully transform both. |
|
|
//| If you call this function using reduced arguments list - |
|
|
//| "FFTR1DInv(F,A)" - you must pass FULL array with N elements |
|
|
//| (although higher N/2 are still not used) because array size is |
|
|
//| used to automatically determine FFT length |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::FFTR1DInv(complex &f[],const int n,double &a[])
|
|
{
|
|
//--- function call
|
|
CFastFourierTransform::FFTR1DInv(f,n,a);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 1-dimensional real inverse FFT. |
|
|
//| Algorithm has O(N*logN) complexity for any N (composite or |
|
|
//| prime). |
|
|
//| INPUT PARAMETERS |
|
|
//| F - array[0..floor(N/2)] - frequencies from forward real |
|
|
//| FFT |
|
|
//| N - problem size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| A - inverse DFT of a input array, array[0..N-1] |
|
|
//| NOTE: |
|
|
//| F[] should satisfy symmetry property F[k] = conj(F[N-k]), |
|
|
//| so just one half of frequencies array is needed - elements from 0|
|
|
//| to floor(N/2). F[0] is ALWAYS real. If N is even F[floor(N/2)] is|
|
|
//| real too. If N is odd, then F[floor(N/2)] has no special |
|
|
//| properties. |
|
|
//| Relying on properties noted above, FFTR1DInv subroutine uses only|
|
|
//| elements from 0th to floor(N/2)-th. It ignores imaginary part of |
|
|
//| F[0], and in case N is even it ignores imaginary part of |
|
|
//| F[floor(N/2)] too. |
|
|
//| When you call this function using full arguments list - |
|
|
//| "FFTR1DInv(F,N,A)" |
|
|
//| - you can pass either either frequencies array with N elements or|
|
|
//| reduced array with roughly N/2 elements - subroutine will |
|
|
//| successfully transform both. |
|
|
//| If you call this function using reduced arguments list - |
|
|
//| "FFTR1DInv(F,A)" - you must pass FULL array with N elements |
|
|
//| (although higher N/2 are still not used) because array size is |
|
|
//| used to automatically determine FFT length |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::FFTR1DInv(complex &f[],double &a[])
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(f);
|
|
//--- function call
|
|
CFastFourierTransform::FFTR1DInv(f,n,a);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 1-dimensional complex convolution. |
|
|
//| For given A/B returns conv(A,B) (non-circular). Subroutine can |
|
|
//| automatically choose between three implementations: |
|
|
//| straightforward O(M*N) formula for very small N (or M), |
|
|
//| significantly larger than min(M,N), but O(M*N) algorithm is too |
|
|
//| slow, and general FFT-based formula for cases where two previois |
|
|
//| algorithms are too slow. |
|
|
//| Algorithm has max(M,N)*log(max(M,N)) complexity for any M/N. |
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..M-1] - complex function to be transformed |
|
|
//| M - problem size |
|
|
//| B - array[0..N-1] - complex function to be transformed |
|
|
//| N - problem size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| R - convolution: A*B. array[0..N+M-2]. |
|
|
//| NOTE: |
|
|
//| It is assumed that A is zero at T<0, B is zero too. If one or|
|
|
//| both functions have non-zero values at negative T's, you can |
|
|
//| still use this subroutine - just shift its result |
|
|
//| correspondingly. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::ConvC1D(complex &a[],const int m,complex &b[],
|
|
const int n,complex &r[])
|
|
{
|
|
//--- function call
|
|
CConv::ConvC1D(a,m,b,n,r);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 1-dimensional complex non-circular deconvolution (inverse of |
|
|
//| ConvC1D()). |
|
|
//| Algorithm has M*log(M)) complexity for any M (composite or prime)|
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..M-1] - convolved signal, A = conv(R, B) |
|
|
//| M - convolved signal length |
|
|
//| B - array[0..N-1] - response |
|
|
//| N - response length, N<=M |
|
|
//| OUTPUT PARAMETERS |
|
|
//| R - deconvolved signal. array[0..M-N]. |
|
|
//| NOTE: |
|
|
//| deconvolution is unstable process and may result in division |
|
|
//| by zero (if your response function is degenerate, i.e. has zero |
|
|
//| Fourier coefficient). |
|
|
//| NOTE: |
|
|
//| It is assumed that A is zero at T<0, B is zero too. If one |
|
|
//| or both functions have non-zero values at negative T's, you can |
|
|
//| still use this subroutine - just shift its result correspondingly|
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::ConvC1DInv(complex &a[],const int m,complex &b[],
|
|
const int n,complex &r[])
|
|
{
|
|
//--- function call
|
|
CConv::ConvC1DInv(a,m,b,n,r);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 1-dimensional circular complex convolution. |
|
|
//| For given S/R returns conv(S,R) (circular). Algorithm has |
|
|
//| linearithmic complexity for any M/N. |
|
|
//| IMPORTANT: normal convolution is commutative, i.e. it is |
|
|
//| symmetric - conv(A,B)=conv(B,A). Cyclic convolution IS NOT. One |
|
|
//| function - S - is a signal, periodic function, and another - R - |
|
|
//| is a response, non-periodic function with limited length. |
|
|
//| INPUT PARAMETERS |
|
|
//| S - array[0..M-1] - complex periodic signal |
|
|
//| M - problem size |
|
|
//| B - array[0..N-1] - complex non-periodic response |
|
|
//| N - problem size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| R - convolution: A*B. array[0..M-1]. |
|
|
//| NOTE: |
|
|
//| It is assumed that B is zero at T<0. If it has non-zero |
|
|
//| values at negative T's, you can still use this subroutine - just |
|
|
//| shift its result correspondingly. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::ConvC1DCircular(complex &s[],const int m,complex &r[],
|
|
const int n,complex &c[])
|
|
{
|
|
//--- function call
|
|
CConv::ConvC1DCircular(s,m,r,n,c);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 1-dimensional circular complex deconvolution (inverse of |
|
|
//| ConvC1DCircular()). |
|
|
//| Algorithm has M*log(M)) complexity for any M (composite or prime)|
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..M-1] - convolved periodic signal, |
|
|
//| A = conv(R, B) |
|
|
//| M - convolved signal length |
|
|
//| B - array[0..N-1] - non-periodic response |
|
|
//| N - response length |
|
|
//| OUTPUT PARAMETERS |
|
|
//| R - deconvolved signal. array[0..M-1]. |
|
|
//| NOTE: |
|
|
//| deconvolution is unstable process and may result in division |
|
|
//| by zero (if your response function is degenerate, i.e. has zero |
|
|
//| Fourier coefficient). |
|
|
//| NOTE: |
|
|
//| It is assumed that B is zero at T<0. If it has non-zero |
|
|
//| values at negative T's, you can still use this subroutine - just |
|
|
//| shift its result correspondingly. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::ConvC1DCircularInv(complex &a[],const int m,complex &b[],
|
|
const int n,complex &r[])
|
|
{
|
|
//--- function call
|
|
CConv::ConvC1DCircularInv(a,m,b,n,r);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 1-dimensional real convolution. |
|
|
//| Analogous to ConvC1D(), see ConvC1D() comments for more details. |
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..M-1] - real function to be transformed |
|
|
//| M - problem size |
|
|
//| B - array[0..N-1] - real function to be transformed |
|
|
//| N - problem size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| R - convolution: A*B. array[0..N+M-2]. |
|
|
//| NOTE: |
|
|
//| It is assumed that A is zero at T<0, B is zero too. If one |
|
|
//| or both functions have non-zero values at negative T's, you can |
|
|
//| still use this subroutine - just shift its result correspondingly|
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::ConvR1D(double &a[],const int m,double &b[],
|
|
const int n,double &r[])
|
|
{
|
|
//--- function call
|
|
CConv::ConvR1D(a,m,b,n,r);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 1-dimensional real deconvolution (inverse of ConvC1D()). |
|
|
//| Algorithm has M*log(M)) complexity for any M (composite or prime)|
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..M-1] - convolved signal, A = conv(R, B) |
|
|
//| M - convolved signal length |
|
|
//| B - array[0..N-1] - response |
|
|
//| N - response length, N<=M |
|
|
//| OUTPUT PARAMETERS |
|
|
//| R - deconvolved signal. array[0..M-N]. |
|
|
//| NOTE: |
|
|
//| deconvolution is unstable process and may result in division |
|
|
//| by zero (if your response function is degenerate, i.e. has zero |
|
|
//| Fourier coefficient). |
|
|
//| NOTE: |
|
|
//| It is assumed that A is zero at T<0, B is zero too. If one or|
|
|
//| both functions have non-zero values at negative T's, you can |
|
|
//| still use this subroutine - just shift its result correspondingly|
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::ConvR1DInv(double &a[],const int m,double &b[],
|
|
const int n,double &r[])
|
|
{
|
|
//--- function call
|
|
CConv::ConvR1DInv(a,m,b,n,r);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 1-dimensional circular real convolution. |
|
|
//| Analogous to ConvC1DCircular(), see ConvC1DCircular() comments |
|
|
//| for more details. |
|
|
//| INPUT PARAMETERS |
|
|
//| S - array[0..M-1] - real signal |
|
|
//| M - problem size |
|
|
//| B - array[0..N-1] - real response |
|
|
//| N - problem size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| R - convolution: A*B. array[0..M-1]. |
|
|
//| NOTE: |
|
|
//| It is assumed that B is zero at T<0. If it has non-zero |
|
|
//| values at negative T's, you can still use this subroutine - just |
|
|
//| shift its result correspondingly. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::ConvR1DCircular(double &s[],const int m,double &r[],
|
|
const int n,double &c[])
|
|
{
|
|
//--- function call
|
|
CConv::ConvR1DCircular(s,m,r,n,c);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 1-dimensional complex deconvolution (inverse of ConvC1D()). |
|
|
//| Algorithm has M*log(M)) complexity for any M (composite or prime)|
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..M-1] - convolved signal, A = conv(R, B) |
|
|
//| M - convolved signal length |
|
|
//| B - array[0..N-1] - response |
|
|
//| N - response length |
|
|
//| OUTPUT PARAMETERS |
|
|
//| R - deconvolved signal. array[0..M-N]. |
|
|
//| NOTE: |
|
|
//| deconvolution is unstable process and may result in division |
|
|
//| by zero (if your response function is degenerate, i.e. has zero |
|
|
//| Fourier coefficient). |
|
|
//| NOTE: |
|
|
//| It is assumed that B is zero at T<0. If it has non-zero |
|
|
//| values at negative T's, you can still use this subroutine - just |
|
|
//| shift its result correspondingly. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::ConvR1DCircularInv(double &a[],const int m,double &b[],
|
|
const int n,double &r[])
|
|
{
|
|
//--- function call
|
|
CConv::ConvR1DCircularInv(a,m,b,n,r);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 1-dimensional complex cross-correlation. |
|
|
//| For given Pattern/Signal returns corr(Pattern,Signal) |
|
|
//| (non-circular). |
|
|
//| Correlation is calculated using reduction to convolution. |
|
|
//| Algorithm with max(N,N)*log(max(N,N)) complexity is used (see |
|
|
//| ConvC1D() for more info about performance). |
|
|
//| IMPORTANT: |
|
|
//| for historical reasons subroutine accepts its parameters in |
|
|
//| reversed order: CorrC1D(Signal, Pattern) = Pattern x Signal |
|
|
//| (using traditional definition of cross-correlation, denoting |
|
|
//| cross-correlation as "x"). |
|
|
//| INPUT PARAMETERS |
|
|
//| Signal - array[0..N-1] - complex function to be |
|
|
//| transformed, signal containing pattern |
|
|
//| N - problem size |
|
|
//| Pattern - array[0..M-1] - complex function to be |
|
|
//| transformed, pattern to search withing signal |
|
|
//| M - problem size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| R - cross-correlation, array[0..N+M-2]: |
|
|
//| * positive lags are stored in R[0..N-1], |
|
|
//| R[i] = sum(conj(pattern[j])*signal[i+j] |
|
|
//| * negative lags are stored in R[N..N+M-2], |
|
|
//| R[N+M-1-i] = sum(conj(pattern[j])*signal[-i+j] |
|
|
//| NOTE: |
|
|
//| It is assumed that pattern domain is [0..M-1]. If Pattern is |
|
|
//| non-zero on [-K..M-1], you can still use this subroutine, just |
|
|
//| shift result by K. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CorrC1D(complex &signal[],const int n,complex &pattern[],
|
|
const int m,complex &r[])
|
|
{
|
|
//--- function call
|
|
CCorr::CorrC1D(signal,n,pattern,m,r);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 1-dimensional circular complex cross-correlation. |
|
|
//| For given Pattern/Signal returns corr(Pattern,Signal) (circular).|
|
|
//| Algorithm has linearithmic complexity for any M/N. |
|
|
//| IMPORTANT: |
|
|
//| for historical reasons subroutine accepts its parameters in |
|
|
//| reversed order: CorrC1DCircular(Signal, Pattern) = Pattern x |
|
|
//| Signal (using traditional definition of cross-correlation, |
|
|
//| denoting cross-correlation as "x"). |
|
|
//| INPUT PARAMETERS |
|
|
//| Signal - array[0..N-1] - complex function to be |
|
|
//| transformed, periodic signal containing pattern |
|
|
//| N - problem size |
|
|
//| Pattern - array[0..M-1] - complex function to be |
|
|
//| transformed, non-periodic pattern to search |
|
|
//| withing signal |
|
|
//| M - problem size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| R - convolution: A*B. array[0..M-1]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CorrC1DCircular(complex &signal[],const int m,
|
|
complex &pattern[],const int n,
|
|
complex &c[])
|
|
{
|
|
//--- function call
|
|
CCorr::CorrC1DCircular(signal,m,pattern,n,c);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 1-dimensional real cross-correlation. |
|
|
//| For given Pattern/Signal returns corr(Pattern,Signal) |
|
|
//| (non-circular). |
|
|
//| Correlation is calculated using reduction to convolution. |
|
|
//| Algorithm with max(N,N)*log(max(N,N)) complexity is used (see |
|
|
//| ConvC1D() for more info about performance). |
|
|
//| IMPORTANT: |
|
|
//| for historical reasons subroutine accepts its parameters in |
|
|
//| reversed order: CorrR1D(Signal, Pattern) = Pattern x Signal |
|
|
//| (using traditional definition of cross-correlation, denoting|
|
|
//| cross-correlation as "x"). |
|
|
//| INPUT PARAMETERS |
|
|
//| Signal - array[0..N-1] - real function to be transformed, |
|
|
//| signal containing pattern |
|
|
//| N - problem size |
|
|
//| Pattern - array[0..M-1] - real function to be transformed, |
|
|
//| pattern to search withing signal |
|
|
//| M - problem size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| R - cross-correlation, array[0..N+M-2]: |
|
|
//| * positive lags are stored in R[0..N-1], |
|
|
//| R[i] = sum(pattern[j]*signal[i+j] |
|
|
//| * negative lags are stored in R[N..N+M-2], |
|
|
//| R[N+M-1-i] = sum(pattern[j]*signal[-i+j] |
|
|
//| NOTE: |
|
|
//| It is assumed that pattern domain is [0..M-1]. If Pattern is |
|
|
//| non-zero on [-K..M-1], you can still use this subroutine, just |
|
|
//| shift result by K. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CorrR1D(double &signal[],const int n,double &pattern[],
|
|
const int m,double &r[])
|
|
{
|
|
//--- function call
|
|
CCorr::CorrR1D(signal,n,pattern,m,r);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 1-dimensional circular real cross-correlation. |
|
|
//| For given Pattern/Signal returns corr(Pattern,Signal) (circular).|
|
|
//| Algorithm has linearithmic complexity for any M/N. |
|
|
//| IMPORTANT: |
|
|
//| for historical reasons subroutine accepts its parameters in |
|
|
//| reversed order: CorrR1DCircular(Signal, Pattern) = Pattern x |
|
|
//| Signal (using traditional definition of cross-correlation, |
|
|
//| denoting cross-correlation as "x"). |
|
|
//| INPUT PARAMETERS |
|
|
//| Signal - array[0..N-1] - real function to be transformed, |
|
|
//| periodic signal containing pattern |
|
|
//| N - problem size |
|
|
//| Pattern - array[0..M-1] - real function to be transformed, |
|
|
//| non-periodic pattern to search withing signal |
|
|
//| M - problem size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| R - convolution: A*B. array[0..M-1]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CorrR1DCircular(double &signal[],const int m,
|
|
double &pattern[],const int n,
|
|
double &c[])
|
|
{
|
|
//--- function call
|
|
CCorr::CorrR1DCircular(signal,m,pattern,n,c);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 1-dimensional Fast Hartley Transform. |
|
|
//| Algorithm has O(N*logN) complexity for any N (composite or prime)|
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..N-1] - real function to be transformed |
|
|
//| N - problem size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| A - FHT of a input array, array[0..N-1], |
|
|
//| A_out[k]=sum(A_in[j]*(cos(2*pi*j*k/N)+sin(2*pi*j*k/N)),|
|
|
//| j=0..N-1) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::FHTR1D(double &a[],const int n)
|
|
{
|
|
//--- function call
|
|
CFastHartleyTransform::FHTR1D(a,n);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 1-dimensional inverse FHT. |
|
|
//| Algorithm has O(N*logN) complexity for any N (composite or prime)|
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..N-1] - complex array to be transformed |
|
|
//| N - problem size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| A - inverse FHT of a input array, array[0..N-1] |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::FHTR1DInv(double &a[],const int n)
|
|
{
|
|
//--- function call
|
|
CFastHartleyTransform::FHTR1DInv(a,n);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Computation of nodes and weights for a Gauss quadrature formula |
|
|
//| The algorithm generates the N-point Gauss quadrature formula |
|
|
//| with weight function given by coefficients alpha and beta of a |
|
|
//| recurrence relation which generates a system of orthogonal |
|
|
//| polynomials: |
|
|
//| P-1(x) = 0 |
|
|
//| P0(x) = 1 |
|
|
//| Pn+1(x) = (x-alpha(n))*Pn(x) - beta(n)*Pn-1(x) |
|
|
//| and zeroth moment Mu0 |
|
|
//| Mu0 = integral(W(x)dx,a,b) |
|
|
//| INPUT PARAMETERS: |
|
|
//| Alpha ? array[0..N-1], alpha coefficients |
|
|
//| Beta ? array[0..N-1], beta coefficients |
|
|
//| Zero-indexed element is not used and may be |
|
|
//| arbitrary. Beta[I]>0. |
|
|
//| Mu0 ? zeroth moment of the weight function. |
|
|
//| N ? number of nodes of the quadrature formula, N>=1 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - error code: |
|
|
//| * -3 internal eigenproblem solver hasn't |
|
|
//| converged |
|
|
//| * -2 Beta[i]<=0 |
|
|
//| * -1 incorrect N was passed |
|
|
//| * 1 OK |
|
|
//| X - array[0..N-1] - array of quadrature nodes, |
|
|
//| in ascending order. |
|
|
//| W - array[0..N-1] - array of quadrature weights. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::GQGenerateRec(double &alpha[],double &beta[],
|
|
const double mu0,const int n,
|
|
int &info,double &x[],double &w[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CGaussQ::GQGenerateRec(alpha,beta,mu0,n,info,x,w);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Computation of nodes and weights for a Gauss-Lobatto quadrature |
|
|
//| formula |
|
|
//| The algorithm generates the N-point Gauss-Lobatto quadrature |
|
|
//| formula with weight function given by coefficients alpha and beta|
|
|
//| of a recurrence which generates a system of orthogonal |
|
|
//| polynomials. |
|
|
//| P-1(x) = 0 |
|
|
//| P0(x) = 1 |
|
|
//| Pn+1(x) = (x-alpha(n))*Pn(x) - beta(n)*Pn-1(x) |
|
|
//| and zeroth moment Mu0 |
|
|
//| Mu0 = integral(W(x)dx,a,b) |
|
|
//| INPUT PARAMETERS: |
|
|
//| Alpha ? array[0..N-2], alpha coefficients |
|
|
//| Beta ? array[0..N-2], beta coefficients. |
|
|
//| Zero-indexed element is not used, may be |
|
|
//| arbitrary. Beta[I]>0 |
|
|
//| Mu0 ? zeroth moment of the weighting function. |
|
|
//| A ? left boundary of the integration interval. |
|
|
//| B ? right boundary of the integration interval. |
|
|
//| N ? number of nodes of the quadrature formula, N>=3 |
|
|
//| (including the left and right boundary nodes). |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - error code: |
|
|
//| * -3 internal eigenproblem solver hasn't |
|
|
//| converged |
|
|
//| * -2 Beta[i]<=0 |
|
|
//| * -1 incorrect N was passed |
|
|
//| * 1 OK |
|
|
//| X - array[0..N-1] - array of quadrature nodes, |
|
|
//| in ascending order. |
|
|
//| W - array[0..N-1] - array of quadrature weights. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::GQGenerateGaussLobattoRec(double &alpha[],double &beta[],
|
|
const double mu0,const double a,
|
|
const double b,const int n,
|
|
int &info,double &x[],double &w[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CGaussQ::GQGenerateGaussLobattoRec(alpha,beta,mu0,a,b,n,info,x,w);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Computation of nodes and weights for a Gauss-Radau quadrature |
|
|
//| formula |
|
|
//| The algorithm generates the N-point Gauss-Radau quadrature |
|
|
//| formula with weight function given by the coefficients alpha and |
|
|
//| beta of a recurrence which generates a system of orthogonal |
|
|
//| polynomials. |
|
|
//| P-1(x) = 0 |
|
|
//| P0(x) = 1 |
|
|
//| Pn+1(x) = (x-alpha(n))*Pn(x) - beta(n)*Pn-1(x) |
|
|
//| and zeroth moment Mu0 |
|
|
//| Mu0 = integral(W(x)dx,a,b) |
|
|
//| INPUT PARAMETERS: |
|
|
//| Alpha ? array[0..N-2], alpha coefficients. |
|
|
//| Beta ? array[0..N-1], beta coefficients |
|
|
//| Zero-indexed element is not used. |
|
|
//| Beta[I]>0 |
|
|
//| Mu0 ? zeroth moment of the weighting function. |
|
|
//| A ? left boundary of the integration interval. |
|
|
//| N ? number of nodes of the quadrature formula, N>=2 |
|
|
//| (including the left boundary node). |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - error code: |
|
|
//| * -3 internal eigenproblem solver hasn't |
|
|
//| converged |
|
|
//| * -2 Beta[i]<=0 |
|
|
//| * -1 incorrect N was passed |
|
|
//| * 1 OK |
|
|
//| X - array[0..N-1] - array of quadrature nodes, |
|
|
//| in ascending order. |
|
|
//| W - array[0..N-1] - array of quadrature weights. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::GQGenerateGaussRadauRec(double &alpha[],double &beta[],
|
|
const double mu0,const double a,
|
|
const int n,int &info,
|
|
double &x[],double &w[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CGaussQ::GQGenerateGaussRadauRec(alpha,beta,mu0,a,n,info,x,w);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Returns nodes/weights for Gauss-Legendre quadrature on [-1,1] |
|
|
//| with N nodes. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - number of nodes, >=1 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - error code: |
|
|
//| * -4 an error was detected when |
|
|
//| calculating weights/nodes. N is too |
|
|
//| large to obtain weights/nodes with |
|
|
//| high enough accuracy. Try to use |
|
|
//| multiple precision version. |
|
|
//| * -3 internal eigenproblem solver hasn't |
|
|
//| converged |
|
|
//| * -1 incorrect N was passed |
|
|
//| * +1 OK |
|
|
//| X - array[0..N-1] - array of quadrature nodes, |
|
|
//| in ascending order. |
|
|
//| W - array[0..N-1] - array of quadrature weights. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::GQGenerateGaussLegendre(const int n,int &info,
|
|
double &x[],double &w[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CGaussQ::GQGenerateGaussLegendre(n,info,x,w);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Returns nodes/weights for Gauss-Jacobi quadrature on [-1,1] |
|
|
//| with weight function W(x)=Power(1-x,Alpha)*Power(1+x,Beta). |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - number of nodes, >=1 |
|
|
//| Alpha - power-law coefficient, Alpha>-1 |
|
|
//| Beta - power-law coefficient, Beta>-1 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - error code: |
|
|
//| * -4 an error was detected when |
|
|
//| calculating weights/nodes. Alpha or |
|
|
//| Beta are too close to -1 to obtain |
|
|
//| weights/nodes with high enough |
|
|
//| accuracy, or, may be, N is too large.|
|
|
//| Try to use multiple precision version|
|
|
//| * -3 internal eigenproblem solver hasn't |
|
|
//| converged |
|
|
//| * -1 incorrect N/Alpha/Beta was passed |
|
|
//| * +1 OK |
|
|
//| X - array[0..N-1] - array of quadrature nodes, |
|
|
//| in ascending order. |
|
|
//| W - array[0..N-1] - array of quadrature weights. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::GQGenerateGaussJacobi(const int n,const double alpha,
|
|
const double beta,int &info,
|
|
double &x[],double &w[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CGaussQ::GQGenerateGaussJacobi(n,alpha,beta,info,x,w);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Returns nodes/weights for Gauss-Laguerre quadrature on [0,+inf) |
|
|
//| with weight function W(x)=Power(x,Alpha)*Exp(-x) |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - number of nodes, >=1 |
|
|
//| Alpha - power-law coefficient, Alpha>-1 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - error code: |
|
|
//| * -4 an error was detected when |
|
|
//| calculating weights/nodes. Alpha is |
|
|
//| too close to -1 to obtain |
|
|
//| weights/nodes with high enough |
|
|
//| accuracy or, may be, N is too large.|
|
|
//| Try to use multiple precision |
|
|
//| version. |
|
|
//| * -3 internal eigenproblem solver hasn't |
|
|
//| converged |
|
|
//| * -1 incorrect N/Alpha was passed |
|
|
//| * +1 OK |
|
|
//| X - array[0..N-1] - array of quadrature nodes, |
|
|
//| in ascending order. |
|
|
//| W - array[0..N-1] - array of quadrature weights. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::GQGenerateGaussLaguerre(const int n,const double alpha,
|
|
int &info,double &x[],double &w[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CGaussQ::GQGenerateGaussLaguerre(n,alpha,info,x,w);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Returns nodes/weights for Gauss-Hermite quadrature on |
|
|
//| (-inf,+inf) with weight function W(x)=Exp(-x*x) |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - number of nodes, >=1 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - error code: |
|
|
//| * -4 an error was detected when |
|
|
//| calculating weights/nodes. May be, N |
|
|
//| is too large. Try to use multiple |
|
|
//| precision version. |
|
|
//| * -3 internal eigenproblem solver hasn't |
|
|
//| converged |
|
|
//| * -1 incorrect N/Alpha was passed |
|
|
//| * +1 OK |
|
|
//| X - array[0..N-1] - array of quadrature nodes, |
|
|
//| in ascending order. |
|
|
//| W - array[0..N-1] - array of quadrature weights. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::GQGenerateGaussHermite(const int n,int &info,
|
|
double &x[],double &w[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CGaussQ::GQGenerateGaussHermite(n,info,x,w);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Computation of nodes and weights of a Gauss-Kronrod quadrature |
|
|
//| formula |
|
|
//| The algorithm generates the N-point Gauss-Kronrod quadrature |
|
|
//| formula with weight function given by coefficients alpha and beta|
|
|
//| of a recurrence relation which generates a system of orthogonal |
|
|
//| polynomials: |
|
|
//| P-1(x) = 0 |
|
|
//| P0(x) = 1 |
|
|
//| Pn+1(x) = (x-alpha(n))*Pn(x) - beta(n)*Pn-1(x) |
|
|
//| and zero moment Mu0 |
|
|
//| Mu0 = integral(W(x)dx,a,b) |
|
|
//| INPUT PARAMETERS: |
|
|
//| Alpha ? alpha coefficients, array[0..floor(3*K/2)]. |
|
|
//| Beta ? beta coefficients, array[0..ceil(3*K/2)]. |
|
|
//| Beta[0] is not used and may be arbitrary. |
|
|
//| Beta[I]>0. |
|
|
//| Mu0 ? zeroth moment of the weight function. |
|
|
//| N ? number of nodes of the Gauss-Kronrod |
|
|
//| quadrature formula, |
|
|
//| N >= 3, |
|
|
//| N = 2*K+1. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - error code: |
|
|
//| * -5 no real and positive Gauss-Kronrod |
|
|
//| formula can be created for such a |
|
|
//| weight function with a given number |
|
|
//| of nodes. |
|
|
//| * -4 N is too large, task may be ill |
|
|
//| conditioned - x[i]=x[i+1] found. |
|
|
//| * -3 internal eigenproblem solver hasn't |
|
|
//| converged |
|
|
//| * -2 Beta[i]<=0 |
|
|
//| * -1 incorrect N was passed |
|
|
//| * +1 OK |
|
|
//| X - array[0..N-1] - array of quadrature nodes, |
|
|
//| in ascending order. |
|
|
//| WKronrod - array[0..N-1] - Kronrod weights |
|
|
//| WGauss - array[0..N-1] - Gauss weights (interleaved |
|
|
//| with zeros corresponding to extended Kronrod |
|
|
//| nodes). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::GKQGenerateRec(double &alpha[],double &beta[],
|
|
const double mu0,const int n,
|
|
int &info,double &x[],
|
|
double &wkronrod[],double &wgauss[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CGaussKronrodQ::GKQGenerateRec(alpha,beta,mu0,n,info,x,wkronrod,wgauss);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Returns Gauss and Gauss-Kronrod nodes/weights for Gauss-Legendre |
|
|
//| quadrature with N points. |
|
|
//| GKQLegendreCalc (calculation) or GKQLegendreTbl (precomputed |
|
|
//| table) is used depending on machine precision and number of |
|
|
//| nodes. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - number of Kronrod nodes, must be odd number, |
|
|
//| >=3. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - error code: |
|
|
//| * -4 an error was detected when |
|
|
//| calculating weights/nodes. N is too |
|
|
//| obtain large to weights/nodes with |
|
|
//| high enough accuracy. Try to use |
|
|
//| multiple precision version. |
|
|
//| * -3 internal eigenproblem solver hasn't |
|
|
//| converged |
|
|
//| * -1 incorrect N was passed |
|
|
//| * +1 OK |
|
|
//| X - array[0..N-1] - array of quadrature nodes, |
|
|
//| ordered in ascending order. |
|
|
//| WKronrod - array[0..N-1] - Kronrod weights |
|
|
//| WGauss - array[0..N-1] - Gauss weights (interleaved |
|
|
//| with zeros corresponding to extended Kronrod |
|
|
//| nodes). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::GKQGenerateGaussLegendre(const int n,int &info,
|
|
double &x[],double &wkronrod[],
|
|
double &wgauss[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CGaussKronrodQ::GKQGenerateGaussLegendre(n,info,x,wkronrod,wgauss);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Returns Gauss and Gauss-Kronrod nodes/weights for Gauss-Jacobi |
|
|
//| quadrature on [-1,1] with weight function |
|
|
//| W(x)=Power(1-x,Alpha)*Power(1+x,Beta). |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - number of Kronrod nodes, must be odd number, |
|
|
//| >=3. |
|
|
//| Alpha - power-law coefficient, Alpha>-1 |
|
|
//| Beta - power-law coefficient, Beta>-1 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - error code: |
|
|
//| * -5 no real and positive Gauss-Kronrod |
|
|
//| formula can be created for such a |
|
|
//| weight function with a given number |
|
|
//| of nodes. |
|
|
//| * -4 an error was detected when |
|
|
//| calculating weights/nodes. Alpha or |
|
|
//| Beta are too close to -1 to obtain |
|
|
//| weights/nodes with high enough |
|
|
//| accuracy, or, may be, N is too large.|
|
|
//| Try to use multiple precision version|
|
|
//| * -3 internal eigenproblem solver hasn't |
|
|
//| converged |
|
|
//| * -1 incorrect N was passed |
|
|
//| * +1 OK |
|
|
//| * +2 OK, but quadrature rule have exterior|
|
|
//| nodes, x[0]<-1 or x[n-1]>+1 |
|
|
//| X - array[0..N-1] - array of quadrature nodes, |
|
|
//| ordered in ascending order. |
|
|
//| WKronrod - array[0..N-1] - Kronrod weights |
|
|
//| WGauss - array[0..N-1] - Gauss weights (interleaved |
|
|
//| with zeros corresponding to extended Kronrod |
|
|
//| nodes). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::GKQGenerateGaussJacobi(const int n,const double alpha,
|
|
const double beta,int &info,
|
|
double &x[],double &wkronrod[],
|
|
double &wgauss[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CGaussKronrodQ::GKQGenerateGaussJacobi(n,alpha,beta,info,x,wkronrod,wgauss);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Returns Gauss and Gauss-Kronrod nodes for quadrature with N |
|
|
//| points. |
|
|
//| Reduction to tridiagonal eigenproblem is used. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - number of Kronrod nodes, must be odd number, |
|
|
//| >=3. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - error code: |
|
|
//| * -4 an error was detected when |
|
|
//| calculating weights/nodes. N is too |
|
|
//| large to obtain weights/nodes with |
|
|
//| high enough accuracy. |
|
|
//| Try to use multiple precision |
|
|
//| version. |
|
|
//| * -3 internal eigenproblem solver hasn't |
|
|
//| converged |
|
|
//| * -1 incorrect N was passed |
|
|
//| * +1 OK |
|
|
//| X - array[0..N-1] - array of quadrature nodes, |
|
|
//| ordered in ascending order. |
|
|
//| WKronrod - array[0..N-1] - Kronrod weights |
|
|
//| WGauss - array[0..N-1] - Gauss weights (interleaved |
|
|
//| with zeros corresponding to extended Kronrod |
|
|
//| nodes). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::GKQLegendreCalc(const int n,int &info,double &x[],
|
|
double &wkronrod[],double &wgauss[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CGaussKronrodQ::GKQLegendreCalc(n,info,x,wkronrod,wgauss);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Returns Gauss and Gauss-Kronrod nodes for quadrature with N |
|
|
//| points using pre-calculated table. Nodes/weights were computed |
|
|
//| with accuracy up to 1.0E-32 (if MPFR version of ALGLIB is used). |
|
|
//| In standard double precision accuracy reduces to something about |
|
|
//| 2.0E-16 (depending on your compiler's handling of long floating |
|
|
//| point constants). |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - number of Kronrod nodes. |
|
|
//| N can be 15, 21, 31, 41, 51, 61. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| X - array[0..N-1] - array of quadrature nodes, |
|
|
//| ordered in ascending order. |
|
|
//| WKronrod - array[0..N-1] - Kronrod weights |
|
|
//| WGauss - array[0..N-1] - Gauss weights (interleaved |
|
|
//| with zeros corresponding to extended Kronrod |
|
|
//| nodes). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::GKQLegendreTbl(const int n,double &x[],double &wkronrod[],
|
|
double &wgauss[],double &eps)
|
|
{
|
|
//--- initialization
|
|
eps=0;
|
|
//--- function call
|
|
CGaussKronrodQ::GKQLegendreTbl(n,x,wkronrod,wgauss,eps);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Integration of a smooth function F(x) on a finite interval [a,b].|
|
|
//| Fast-convergent algorithm based on a Gauss-Kronrod formula is |
|
|
//| used. Result is calculated with accuracy close to the machine |
|
|
//| precision. |
|
|
//| Algorithm works well only with smooth integrands. It may be used |
|
|
//| with continuous non-smooth integrands, but with less performance.|
|
|
//| It should never be used with integrands which have integrable |
|
|
//| singularities at lower or upper limits - algorithm may crash. |
|
|
//| Use AutoGKSingular in such cases. |
|
|
//| INPUT PARAMETERS: |
|
|
//| A, B - interval boundaries (A<B, A=B or A>B) |
|
|
//| OUTPUT PARAMETERS |
|
|
//| State - structure which stores algorithm state |
|
|
//| SEE ALSO |
|
|
//| AutoGKSmoothW, AutoGKSingular, AutoGKResults. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::AutoGKSmooth(const double a,const double b,
|
|
CAutoGKStateShell &state)
|
|
{
|
|
//--- function call
|
|
CAutoGK::AutoGKSmooth(a,b,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Integration of a smooth function F(x) on a finite interval [a,b].|
|
|
//| This subroutine is same as AutoGKSmooth(), but it guarantees that|
|
|
//| interval [a,b] is partitioned into subintervals which have width |
|
|
//| at most XWidth. |
|
|
//| Subroutine can be used when integrating nearly-constant function |
|
|
//| with narrow "bumps" (about XWidth wide). If "bumps" are too |
|
|
//| narrow, AutoGKSmooth subroutine can overlook them. |
|
|
//| INPUT PARAMETERS: |
|
|
//| A, B - interval boundaries (A<B, A=B or A>B) |
|
|
//| OUTPUT PARAMETERS |
|
|
//| State - structure which stores algorithm state |
|
|
//| SEE ALSO |
|
|
//| AutoGKSmooth, AutoGKSingular, AutoGKResults. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::AutoGKSmoothW(const double a,const double b,
|
|
double xwidth,CAutoGKStateShell &state)
|
|
{
|
|
//--- function call
|
|
CAutoGK::AutoGKSmoothW(a,b,xwidth,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Integration on a finite interval [A,B]. |
|
|
//| Integrand have integrable singularities at A/B. |
|
|
//| F(X) must diverge as "(x-A)^alpha" at A, as "(B-x)^beta" at B, |
|
|
//| with known alpha/beta (alpha>-1, beta>-1). If alpha/beta are not |
|
|
//| known, estimates from below can be used (but these estimates |
|
|
//| should be greater than -1 too). |
|
|
//| One of alpha/beta variables (or even both alpha/beta) may be |
|
|
//| equal to 0, which means than function F(x) is non-singular at |
|
|
//| A/B. Anyway (singular at bounds or not), function F(x) is |
|
|
//| supposed to be continuous on (A,B). |
|
|
//| Fast-convergent algorithm based on a Gauss-Kronrod formula is |
|
|
//| used. Result is calculated with accuracy close to the machine |
|
|
//| precision. |
|
|
//| INPUT PARAMETERS: |
|
|
//| A, B - interval boundaries (A<B, A=B or A>B) |
|
|
//| Alpha - power-law coefficient of the F(x) at A, |
|
|
//| Alpha>-1 |
|
|
//| Beta - power-law coefficient of the F(x) at B, |
|
|
//| Beta>-1 |
|
|
//| OUTPUT PARAMETERS |
|
|
//| State - structure which stores algorithm state |
|
|
//| SEE ALSO |
|
|
//| AutoGKSmooth, AutoGKSmoothW, AutoGKResults. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::AutoGKSingular(const double a,const double b,const double alpha,
|
|
const double beta,CAutoGKStateShell &state)
|
|
{
|
|
//--- function call
|
|
CAutoGK::AutoGKSingular(a,b,alpha,beta,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function provides reverse communication interface |
|
|
//| Reverse communication interface is not documented or recommended |
|
|
//| to use. |
|
|
//| See below for functions which provide better documented API |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::AutoGKIteration(CAutoGKStateShell &state)
|
|
{
|
|
//--- return result
|
|
return(CAutoGK::AutoGKIteration(state.GetInnerObj()));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function is used to launcn iterations of ODE solver |
|
|
//| It accepts following parameters: |
|
|
//| diff - callback which calculates dy/dx for given y and x|
|
|
//| obj - optional object which is passed to diff; can be |
|
|
//| NULL |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::AutoGKIntegrate(CAutoGKStateShell &state,
|
|
CIntegrator1_Func &func,
|
|
CObject &obj)
|
|
{
|
|
//--- cycle
|
|
while(CAlglib::AutoGKIteration(state))
|
|
{
|
|
//--- check
|
|
if(state.GetNeedF())
|
|
{
|
|
func.Int_Func(state.GetInnerObj().m_x,state.GetInnerObj().m_xminusa,state.GetInnerObj().m_bminusx,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
Print("ALGLIB: unexpected error in 'autogksolve'");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Adaptive integration results |
|
|
//| Called after AutoGKIteration returned False. |
|
|
//| Input parameters: |
|
|
//| State - algorithm state (used by AutoGKIteration). |
|
|
//| Output parameters: |
|
|
//| V - integral(f(x)dx,a,b) |
|
|
//| Rep - optimization report (see AutoGKReport |
|
|
//| description) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::AutoGKResults(CAutoGKStateShell &state,double &v,
|
|
CAutoGKReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
v=0;
|
|
//--- function call
|
|
CAutoGK::AutoGKResults(state.GetInnerObj(),v,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| IDW interpolation |
|
|
//| INPUT PARAMETERS: |
|
|
//| Z - IDW interpolant built with one of model building |
|
|
//| subroutines. |
|
|
//| X - array[0..NX-1], interpolation point |
|
|
//| Result: |
|
|
//| IDW interpolant Z(X) |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::IDWCalc(CIDWInterpolantShell &z,double &x[])
|
|
{
|
|
//--- return result
|
|
return(CIDWInt::IDWCalc(z.GetInnerObj(),x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| IDW interpolant using modified Shepard method for uniform point |
|
|
//| distributions. |
|
|
//| INPUT PARAMETERS: |
|
|
//| XY - X and Y values, array[0..N-1,0..NX]. |
|
|
//| First NX columns contain X-values, last column |
|
|
//| contain Y-values. |
|
|
//| N - number of nodes, N>0. |
|
|
//| NX - space dimension, NX>=1. |
|
|
//| D - nodal function type, either: |
|
|
//| * 0 constant model. Just for demonstration only,|
|
|
//| worst model ever. |
|
|
//| * 1 linear model, least squares fitting. Simpe |
|
|
//| model for datasets too small for quadratic |
|
|
//| models |
|
|
//| * 2 quadratic model, least squares fitting. |
|
|
//| Best model available (if your dataset is |
|
|
//| large enough). |
|
|
//| * -1 "fast" linear model, use with caution!!! It |
|
|
//| is significantly faster than linear/quadratic|
|
|
//| and better than constant model. But it is |
|
|
//| less robust (especially in the presence of |
|
|
//| noise). |
|
|
//| NQ - number of points used to calculate nodal functions |
|
|
//| (ignored for constant models). NQ should be LARGER |
|
|
//| than: |
|
|
//| * max(1.5*(1+NX),2^NX+1) for linear model, |
|
|
//| * max(3/4*(NX+2)*(NX+1),2^NX+1) for quadratic model. |
|
|
//| Values less than this threshold will be silently |
|
|
//| increased. |
|
|
//| NW - number of points used to calculate weights and to |
|
|
//| interpolate. Required: >=2^NX+1, values less than |
|
|
//| this threshold will be silently increased. |
|
|
//| Recommended value: about 2*NQ |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Z - IDW interpolant. |
|
|
//| NOTES: |
|
|
//| * best results are obtained with quadratic models, worst - with|
|
|
//| constant models |
|
|
//| * when N is large, NQ and NW must be significantly smaller than|
|
|
//| N both to obtain optimal performance and to obtain optimal |
|
|
//| accuracy. In 2 or 3-dimensional tasks NQ=15 and NW=25 are |
|
|
//| good values to start with. |
|
|
//| * NQ and NW may be greater than N. In such cases they will be |
|
|
//| automatically decreased. |
|
|
//| * this subroutine is always succeeds (as long as correct |
|
|
//| parameters are passed). |
|
|
//| * see 'Multivariate Interpolation of Large Sets of Scattered |
|
|
//| Data' by Robert J. Renka for more information on this |
|
|
//| algorithm. |
|
|
//| * this subroutine assumes that point distribution is uniform at|
|
|
//| the small scales. If it isn't - for example, points are |
|
|
//| concentrated along "lines", but "lines" distribution is |
|
|
//| uniform at the larger scale - then you should use |
|
|
//| IDWBuildModifiedShepardR() |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::IDWBuildModifiedShepard(CMatrixDouble &xy,const int n,
|
|
const int nx,const int d,
|
|
const int nq,const int nw,
|
|
CIDWInterpolantShell &z)
|
|
{
|
|
//--- function call
|
|
CIDWInt::IDWBuildModifiedShepard(xy,n,nx,d,nq,nw,z.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| IDW interpolant using modified Shepard method for non-uniform |
|
|
//| datasets. |
|
|
//| This type of model uses constant nodal functions and interpolates|
|
|
//| using all nodes which are closer than user-specified radius R. It|
|
|
//| may be used when points distribution is non-uniform at the small |
|
|
//| scale, but it is at the distances as large as R. |
|
|
//| INPUT PARAMETERS: |
|
|
//| XY - X and Y values, array[0..N-1,0..NX]. |
|
|
//| First NX columns contain X-values, last column |
|
|
//| contain Y-values. |
|
|
//| N - number of nodes, N>0. |
|
|
//| NX - space dimension, NX>=1. |
|
|
//| R - radius, R>0 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Z - IDW interpolant. |
|
|
//| NOTES: |
|
|
//| * if there is less than IDWKMin points within R-ball, algorithm |
|
|
//| selects IDWKMin closest ones, so that continuity properties of |
|
|
//| interpolant are preserved even far from points. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::IDWBuildModifiedShepardR(CMatrixDouble &xy,const int n,
|
|
const int nx,const double r,
|
|
CIDWInterpolantShell &z)
|
|
{
|
|
//--- function call
|
|
CIDWInt::IDWBuildModifiedShepardR(xy,n,nx,r,z.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| IDW model for noisy data. |
|
|
//| This subroutine may be used to handle noisy data, i.e. data with |
|
|
//| noise in OUTPUT values. It differs from IDWBuildModifiedShepard()|
|
|
//| in the following aspects: |
|
|
//| * nodal functions are not constrained to pass through nodes: |
|
|
//| Qi(xi)<>yi, i.e. we have fitting instead of interpolation. |
|
|
//| * weights which are used during least squares fitting stage are |
|
|
//| all equal to 1.0 (independently of distance) |
|
|
//| * "fast"-linear or constant nodal functions are not supported |
|
|
//| (either not robust enough or too rigid) |
|
|
//| This problem require far more complex tuning than interpolation |
|
|
//| problems. |
|
|
//| Below you can find some recommendations regarding this problem: |
|
|
//| * focus on tuning NQ; it controls noise reduction. As for NW, you|
|
|
//| can just make it equal to 2*NQ. |
|
|
//| * you can use cross-validation to determine optimal NQ. |
|
|
//| * optimal NQ is a result of complex tradeoff between noise level |
|
|
//| (more noise = larger NQ required) and underlying function |
|
|
//| complexity (given fixed N, larger NQ means smoothing of compex |
|
|
//| features in the data). For example, NQ=N will reduce noise to |
|
|
//| the minimum level possible, but you will end up with just |
|
|
//| constant/linear/quadratic (depending on D) least squares |
|
|
//| model for the whole dataset. |
|
|
//| INPUT PARAMETERS: |
|
|
//| XY - X and Y values, array[0..N-1,0..NX]. |
|
|
//| First NX columns contain X-values, last column |
|
|
//| contain Y-values. |
|
|
//| N - number of nodes, N>0. |
|
|
//| NX - space dimension, NX>=1. |
|
|
//| D - nodal function degree, either: |
|
|
//| * 1 linear model, least squares fitting. Simpe |
|
|
//| model for datasets too small for quadratic |
|
|
//| models (or for very noisy problems). |
|
|
//| * 2 quadratic model, least squares fitting. Best |
|
|
//| model available (if your dataset is large |
|
|
//| enough). |
|
|
//| NQ - number of points used to calculate nodal functions. |
|
|
//| NQ should be significantly larger than 1.5 times the |
|
|
//| number of coefficients in a nodal function to |
|
|
//| overcome effects of noise: |
|
|
//| * larger than 1.5*(1+NX) for linear model, |
|
|
//| * larger than 3/4*(NX+2)*(NX+1) for quadratic model. |
|
|
//| Values less than this threshold will be silently |
|
|
//| increased. |
|
|
//| NW - number of points used to calculate weights and to |
|
|
//| interpolate. Required: >=2^NX+1, values less than |
|
|
//| this threshold will be silently increased. |
|
|
//| Recommended value: about 2*NQ or larger |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Z - IDW inte rpolant. |
|
|
//| NOTES: |
|
|
//| * best results are obtained with quadratic models, linear |
|
|
//| models are not recommended to use unless you are pretty sure |
|
|
//| that it is what you want |
|
|
//| * this subroutine is always succeeds (as long as correct |
|
|
//| parameters are passed). |
|
|
//| * see 'Multivariate Interpolation of Large Sets of Scattered |
|
|
//| Data' by Robert J. Renka for more information on this |
|
|
//| algorithm. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::IDWBuildNoisy(CMatrixDouble &xy,const int n,const int nx,
|
|
const int d,const int nq,const int nw,
|
|
CIDWInterpolantShell &z)
|
|
{
|
|
//--- function call
|
|
CIDWInt::IDWBuildNoisy(xy,n,nx,d,nq,nw,z.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Rational interpolation using barycentric formula |
|
|
//| F(t)=SUM(i=0,n-1,w[i]*f[i]/(t-x[i])) / SUM(i=0,n-1,w[i]/(t-x[i]))|
|
|
//| Input parameters: |
|
|
//| B - barycentric interpolant built with one of model |
|
|
//| building subroutines. |
|
|
//| T - interpolation point |
|
|
//| Result: |
|
|
//| barycentric interpolant F(t) |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::BarycentricCalc(CBarycentricInterpolantShell &b,
|
|
const double t)
|
|
{
|
|
//--- return result
|
|
return(CRatInt::BarycentricCalc(b.GetInnerObj(),t));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Differentiation of barycentric interpolant: first derivative. |
|
|
//| Algorithm used in this subroutine is very robust and should not |
|
|
//| fail until provided with values too close to MaxRealNumber |
|
|
//| (usually MaxRealNumber/N or greater will overflow). |
|
|
//| INPUT PARAMETERS: |
|
|
//| B - barycentric interpolant built with one of model |
|
|
//| building subroutines. |
|
|
//| T - interpolation point |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| F - barycentric interpolant at T |
|
|
//| DF - first derivative |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::BarycentricDiff1(CBarycentricInterpolantShell &b,
|
|
const double t,double &f,double &df)
|
|
{
|
|
//--- initialization
|
|
f=0;
|
|
df=0;
|
|
//--- function call
|
|
CRatInt::BarycentricDiff1(b.GetInnerObj(),t,f,df);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Differentiation of barycentric interpolant: first/second |
|
|
//| derivatives. |
|
|
//| INPUT PARAMETERS: |
|
|
//| B - barycentric interpolant built with one of model |
|
|
//| building subroutines. |
|
|
//| T - interpolation point |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| F - barycentric interpolant at T |
|
|
//| DF - first derivative |
|
|
//| D2F - second derivative |
|
|
//| NOTE: this algorithm may fail due to overflow/underflor if used |
|
|
//| on data whose values are close to MaxRealNumber or MinRealNumber.|
|
|
//| Use more robust BarycentricDiff1() subroutine in such cases. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::BarycentricDiff2(CBarycentricInterpolantShell &b,
|
|
const double t,double &f,double &df,
|
|
double &d2f)
|
|
{
|
|
//--- initialization
|
|
f=0;
|
|
df=0;
|
|
d2f=0;
|
|
//--- function call
|
|
CRatInt::BarycentricDiff2(b.GetInnerObj(),t,f,df,d2f);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine performs linear transformation of the argument. |
|
|
//| INPUT PARAMETERS: |
|
|
//| B - rational interpolant in barycentric form |
|
|
//| CA, CB - transformation coefficients: x = CA*t + CB |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| B - transformed interpolant with X replaced by T |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::BarycentricLinTransX(CBarycentricInterpolantShell &b,
|
|
const double ca,const double cb)
|
|
{
|
|
//--- function call
|
|
CRatInt::BarycentricLinTransX(b.GetInnerObj(),ca,cb);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine performs linear transformation of the barycentric|
|
|
//| interpolant. |
|
|
//| INPUT PARAMETERS: |
|
|
//| B - rational interpolant in barycentric form |
|
|
//| CA, CB - transformation coefficients: B2(x) = CA*B(x) + CB|
|
|
//| OUTPUT PARAMETERS: |
|
|
//| B - transformed interpolant |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::BarycentricLinTransY(CBarycentricInterpolantShell &b,
|
|
const double ca,const double cb)
|
|
{
|
|
//--- function call
|
|
CRatInt::BarycentricLinTransY(b.GetInnerObj(),ca,cb);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Extracts X/Y/W arrays from rational interpolant |
|
|
//| INPUT PARAMETERS: |
|
|
//| B - barycentric interpolant |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| N - nodes count, N>0 |
|
|
//| X - interpolation nodes, array[0..N-1] |
|
|
//| F - function values, array[0..N-1] |
|
|
//| W - barycentric weights, array[0..N-1] |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::BarycentricUnpack(CBarycentricInterpolantShell &b,
|
|
int &n,double &x[],double &y[],
|
|
double &w[])
|
|
{
|
|
//--- initialization
|
|
n=0;
|
|
//--- function call
|
|
CRatInt::BarycentricUnpack(b.GetInnerObj(),n,x,y,w);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Rational interpolant from X/Y/W arrays |
|
|
//| F(t)=SUM(i=0,n-1,w[i]*f[i]/(t-x[i])) / SUM(i=0,n-1,w[i]/(t-x[i]))|
|
|
//| INPUT PARAMETERS: |
|
|
//| X - interpolation nodes, array[0..N-1] |
|
|
//| F - function values, array[0..N-1] |
|
|
//| W - barycentric weights, array[0..N-1] |
|
|
//| N - nodes count, N>0 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| B - barycentric interpolant built from (X, Y, W) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::BarycentricBuildXYW(double &x[],double &y[],double &w[],
|
|
const int n,CBarycentricInterpolantShell &b)
|
|
{
|
|
//--- function call
|
|
CRatInt::BarycentricBuildXYW(x,y,w,n,b.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Rational interpolant without poles |
|
|
//| The subroutine constructs the rational interpolating function |
|
|
//| without real poles (see 'Barycentric rational interpolation with |
|
|
//| no poles and high rates of approximation', Michael S. Floater. |
|
|
//| and Kai Hormann, for more information on this subject). |
|
|
//| Input parameters: |
|
|
//| X - interpolation nodes, array[0..N-1]. |
|
|
//| Y - function values, array[0..N-1]. |
|
|
//| N - number of nodes, N>0. |
|
|
//| D - order of the interpolation scheme, 0 <= D <= N-1. |
|
|
//| D<0 will cause an error. |
|
|
//| D>=N it will be replaced with D=N-1. |
|
|
//| if you don't know what D to choose, use small value |
|
|
//| about 3-5. |
|
|
//| Output parameters: |
|
|
//| B - barycentric interpolant. |
|
|
//| Note: |
|
|
//| this algorithm always succeeds and calculates the weights |
|
|
//| with close to machine precision. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::BarycentricBuildFloaterHormann(double &x[],double &y[],
|
|
const int n,const int d,
|
|
CBarycentricInterpolantShell &b)
|
|
{
|
|
//--- function call
|
|
CRatInt::BarycentricBuildFloaterHormann(x,y,n,d,b.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Conversion from barycentric representation to Chebyshev basis. |
|
|
//| This function has O(N^2) complexity. |
|
|
//| INPUT PARAMETERS: |
|
|
//| P - polynomial in barycentric form |
|
|
//| A,B - base interval for Chebyshev polynomials (see below) |
|
|
//| A<>B |
|
|
//| OUTPUT PARAMETERS |
|
|
//| T - coefficients of Chebyshev representation; |
|
|
//| P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N-1 }, |
|
|
//| where Ti - I-th Chebyshev polynomial. |
|
|
//| NOTES: |
|
|
//| barycentric interpolant passed as P may be either polynomial |
|
|
//| obtained from polynomial interpolation/ fitting or rational |
|
|
//| function which is NOT polynomial. We can't distinguish |
|
|
//| between these two cases, and this algorithm just tries to |
|
|
//| work assuming that P IS a polynomial. If not, algorithm will |
|
|
//| return results, but they won't have any meaning. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PolynomialBar2Cheb(CBarycentricInterpolantShell &p,
|
|
const double a,const double b,
|
|
double &t[])
|
|
{
|
|
//--- function call
|
|
CPolInt::PolynomialBar2Cheb(p.GetInnerObj(),a,b,t);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Conversion from Chebyshev basis to barycentric representation. |
|
|
//| This function has O(N^2) complexity. |
|
|
//| INPUT PARAMETERS: |
|
|
//| T - coefficients of Chebyshev representation; |
|
|
//| P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N }, |
|
|
//| where Ti - I-th Chebyshev polynomial. |
|
|
//| N - number of coefficients: |
|
|
//| * if given, only leading N elements of T are used |
|
|
//| * if not given, automatically determined from size |
|
|
//| of T |
|
|
//| A,B - base interval for Chebyshev polynomials (see above) |
|
|
//| A<B |
|
|
//| OUTPUT PARAMETERS |
|
|
//| P - polynomial in barycentric form |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PolynomialCheb2Bar(double &t[],const int n,const double a,
|
|
const double b,
|
|
CBarycentricInterpolantShell &p)
|
|
{
|
|
//--- function call
|
|
CPolInt::PolynomialCheb2Bar(t,n,a,b,p.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Conversion from Chebyshev basis to barycentric representation. |
|
|
//| This function has O(N^2) complexity. |
|
|
//| INPUT PARAMETERS: |
|
|
//| T - coefficients of Chebyshev representation; |
|
|
//| P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N }, |
|
|
//| where Ti - I-th Chebyshev polynomial. |
|
|
//| N - number of coefficients: |
|
|
//| * if given, only leading N elements of T are used |
|
|
//| * if not given, automatically determined from size |
|
|
//| of T |
|
|
//| A,B - base interval for Chebyshev polynomials (see above) |
|
|
//| A<B |
|
|
//| OUTPUT PARAMETERS |
|
|
//| P - polynomial in barycentric form |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PolynomialCheb2Bar(double &t[],const double a,
|
|
const double b,
|
|
CBarycentricInterpolantShell &p)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(t);
|
|
//--- function call
|
|
CPolInt::PolynomialCheb2Bar(t,n,a,b,p.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Conversion from barycentric representation to power basis. |
|
|
//| This function has O(N^2) complexity. |
|
|
//| INPUT PARAMETERS: |
|
|
//| P - polynomial in barycentric form |
|
|
//| C - offset (see below); 0.0 is used as default value. |
|
|
//| S - scale (see below); 1.0 is used as default value. |
|
|
//| S<>0. |
|
|
//| OUTPUT PARAMETERS |
|
|
//| A - coefficients, |
|
|
//| P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 } |
|
|
//| N - number of coefficients (polynomial degree plus 1) |
|
|
//| NOTES: |
|
|
//| 1. this function accepts offset and scale, which can be set to |
|
|
//| improve numerical properties of polynomial. For example, if |
|
|
//| P was obtained as result of interpolation on [-1,+1], you can|
|
|
//| set C=0 and S=1 and represent P as sum of 1, x, x^2, x^3 and |
|
|
//| so on. In most cases you it is exactly what you need. |
|
|
//| However, if your interpolation model was built on [999,1001],|
|
|
//| you will see significant growth of numerical errors when |
|
|
//| using {1, x, x^2, x^3} as basis. Representing P as sum of 1, |
|
|
//| (x-1000), (x-1000)^2, (x-1000)^3 will be better option. Such |
|
|
//| representation can be obtained by using 1000.0 as offset |
|
|
//| C and 1.0 as scale S. |
|
|
//| 2. power basis is ill-conditioned and tricks described above |
|
|
//| can't solve this problem completely. This function will |
|
|
//| return coefficients in any case, but for N>8 they will become|
|
|
//| unreliable. However, N's less than 5 are pretty safe. |
|
|
//| 3. barycentric interpolant passed as P may be either polynomial |
|
|
//| obtained from polynomial interpolation/ fitting or rational |
|
|
//| function which is NOT polynomial. We can't distinguish |
|
|
//| between these two cases, and this algorithm just tries to |
|
|
//| work assuming that P IS a polynomial. If not, algorithm will |
|
|
//| return results, but they won't have any meaning. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PolynomialBar2Pow(CBarycentricInterpolantShell &p,
|
|
const double c,const double s,
|
|
double &a[])
|
|
{
|
|
//--- function call
|
|
CPolInt::PolynomialBar2Pow(p.GetInnerObj(),c,s,a);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Conversion from barycentric representation to power basis. |
|
|
//| This function has O(N^2) complexity. |
|
|
//| INPUT PARAMETERS: |
|
|
//| P - polynomial in barycentric form |
|
|
//| C - offset (see below); 0.0 is used as default value. |
|
|
//| S - scale (see below); 1.0 is used as default value. |
|
|
//| S<>0. |
|
|
//| OUTPUT PARAMETERS |
|
|
//| A - coefficients, |
|
|
//| P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 } |
|
|
//| N - number of coefficients (polynomial degree plus 1) |
|
|
//| NOTES: |
|
|
//| 1. this function accepts offset and scale, which can be set to |
|
|
//| improve numerical properties of polynomial. For example, if |
|
|
//| P was obtained as result of interpolation on [-1,+1], you can|
|
|
//| set C=0 and S=1 and represent P as sum of 1, x, x^2, x^3 and |
|
|
//| so on. In most cases you it is exactly what you need. |
|
|
//| However, if your interpolation model was built on [999,1001],|
|
|
//| you will see significant growth of numerical errors when |
|
|
//| using {1, x, x^2, x^3} as basis. Representing P as sum of 1, |
|
|
//| (x-1000), (x-1000)^2, (x-1000)^3 will be better option. Such |
|
|
//| representation can be obtained by using 1000.0 as offset |
|
|
//| C and 1.0 as scale S. |
|
|
//| 2. power basis is ill-conditioned and tricks described above |
|
|
//| can't solve this problem completely. This function will |
|
|
//| return coefficients in any case, but for N>8 they will become|
|
|
//| unreliable. However, N's less than 5 are pretty safe. |
|
|
//| 3. barycentric interpolant passed as P may be either polynomial |
|
|
//| obtained from polynomial interpolation/ fitting or rational |
|
|
//| function which is NOT polynomial. We can't distinguish |
|
|
//| between these two cases, and this algorithm just tries to |
|
|
//| work assuming that P IS a polynomial. If not, algorithm will |
|
|
//| return results, but they won't have any meaning. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PolynomialBar2Pow(CBarycentricInterpolantShell &p,
|
|
double &a[])
|
|
{
|
|
//--- create variables
|
|
double c;
|
|
double s;
|
|
//--- initialization
|
|
c=0;
|
|
s=1;
|
|
//--- function call
|
|
CPolInt::PolynomialBar2Pow(p.GetInnerObj(),c,s,a);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Conversion from power basis to barycentric representation. |
|
|
//| This function has O(N^2) complexity. |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - coefficients, P(x)=sum { A[i]*((X-C)/S)^i, i=0..N-1 }|
|
|
//| N - number of coefficients (polynomial degree plus 1) |
|
|
//| * if given, only leading N elements of A are used |
|
|
//| * if not given, automatically determined from size |
|
|
//| of A |
|
|
//| C - offset (see below); 0.0 is used as default value. |
|
|
//| S - scale (see below); 1.0 is used as default value. |
|
|
//| S<>0. |
|
|
//| OUTPUT PARAMETERS |
|
|
//| P - polynomial in barycentric form |
|
|
//| NOTES: |
|
|
//| 1. this function accepts offset and scale, which can be set to |
|
|
//| improve numerical properties of polynomial. For example, if |
|
|
//| you interpolate on [-1,+1], you can set C=0 and S=1 and |
|
|
//| convert from sum of 1, x, x^2, x^3 and so on. In most cases |
|
|
//| you it is exactly what you need. |
|
|
//| However, if your interpolation model was built on [999,1001],|
|
|
//| you will see significant growth of numerical errors when |
|
|
//| using {1, x, x^2, x^3} as input basis. Converting from sum |
|
|
//| of 1, (x-1000), (x-1000)^2, (x-1000)^3 will be better option |
|
|
//| (you have to specify 1000.0 as offset C and 1.0 as scale S). |
|
|
//| 2. power basis is ill-conditioned and tricks described above |
|
|
//| can't solve this problem completely. This function will |
|
|
//| return barycentric model in any case, but for N>8 accuracy |
|
|
//| well degrade. However, N's less than 5 are pretty safe. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PolynomialPow2Bar(double &a[],const int n,const double c,
|
|
const double s,CBarycentricInterpolantShell &p)
|
|
{
|
|
//--- function call
|
|
CPolInt::PolynomialPow2Bar(a,n,c,s,p.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Conversion from power basis to barycentric representation. |
|
|
//| This function has O(N^2) complexity. |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - coefficients, P(x)=sum { A[i]*((X-C)/S)^i, i=0..N-1 }|
|
|
//| N - number of coefficients (polynomial degree plus 1) |
|
|
//| * if given, only leading N elements of A are used |
|
|
//| * if not given, automatically determined from size |
|
|
//| of A |
|
|
//| C - offset (see below); 0.0 is used as default value. |
|
|
//| S - scale (see below); 1.0 is used as default value. |
|
|
//| S<>0. |
|
|
//| OUTPUT PARAMETERS |
|
|
//| P - polynomial in barycentric form |
|
|
//| NOTES: |
|
|
//| 1. this function accepts offset and scale, which can be set to |
|
|
//| improve numerical properties of polynomial. For example, if |
|
|
//| you interpolate on [-1,+1], you can set C=0 and S=1 and |
|
|
//| convert from sum of 1, x, x^2, x^3 and so on. In most cases |
|
|
//| you it is exactly what you need. |
|
|
//| However, if your interpolation model was built on [999,1001],|
|
|
//| you will see significant growth of numerical errors when |
|
|
//| using {1, x, x^2, x^3} as input basis. Converting from sum |
|
|
//| of 1, (x-1000), (x-1000)^2, (x-1000)^3 will be better option |
|
|
//| (you have to specify 1000.0 as offset C and 1.0 as scale S). |
|
|
//| 2. power basis is ill-conditioned and tricks described above |
|
|
//| can't solve this problem completely. This function will |
|
|
//| return barycentric model in any case, but for N>8 accuracy |
|
|
//| well degrade. However, N's less than 5 are pretty safe. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PolynomialPow2Bar(double &a[],CBarycentricInterpolantShell &p)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
double c;
|
|
double s;
|
|
//--- initialization
|
|
n=CAp::Len(a);
|
|
c=0;
|
|
s=1;
|
|
//--- function call
|
|
CPolInt::PolynomialPow2Bar(a,n,c,s,p.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Lagrange intepolant: generation of the model on the general grid.|
|
|
//| This function has O(N^2) complexity. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - abscissas, array[0..N-1] |
|
|
//| Y - function values, array[0..N-1] |
|
|
//| N - number of points, N>=1 |
|
|
//| OUTPUT PARAMETERS |
|
|
//| P - barycentric model which represents Lagrange |
|
|
//| interpolant (see ratint unit info and |
|
|
//| BarycentricCalc() description for more information). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PolynomialBuild(double &x[],double &y[],const int n,
|
|
CBarycentricInterpolantShell &p)
|
|
{
|
|
//--- function call
|
|
CPolInt::PolynomialBuild(x,y,n,p.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Lagrange intepolant: generation of the model on the general grid.|
|
|
//| This function has O(N^2) complexity. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - abscissas, array[0..N-1] |
|
|
//| Y - function values, array[0..N-1] |
|
|
//| N - number of points, N>=1 |
|
|
//| OUTPUT PARAMETERS |
|
|
//| P - barycentric model which represents Lagrange |
|
|
//| interpolant (see ratint unit info and |
|
|
//| BarycentricCalc() description for more information). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PolynomialBuild(double &x[],double &y[],
|
|
CBarycentricInterpolantShell &p)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- check
|
|
if((CAp::Len(x)!=CAp::Len(y)))
|
|
{
|
|
Print("Error while calling 'polynomialbuild': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CPolInt::PolynomialBuild(x,y,n,p.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Lagrange intepolant: generation of the model on equidistant grid.|
|
|
//| This function has O(N) complexity. |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - left boundary of [A,B] |
|
|
//| B - right boundary of [A,B] |
|
|
//| Y - function values at the nodes, array[0..N-1] |
|
|
//| N - number of points, N>=1 |
|
|
//| for N=1 a constant model is constructed. |
|
|
//| OUTPUT PARAMETERS |
|
|
//| P - barycentric model which represents Lagrange |
|
|
//| interpolant (see ratint unit info and |
|
|
//| BarycentricCalc() description for more information). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PolynomialBuildEqDist(const double a,const double b,
|
|
double &y[],const int n,
|
|
CBarycentricInterpolantShell &p)
|
|
{
|
|
//--- function call
|
|
CPolInt::PolynomialBuildEqDist(a,b,y,n,p.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Lagrange intepolant: generation of the model on equidistant grid.|
|
|
//| This function has O(N) complexity. |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - left boundary of [A,B] |
|
|
//| B - right boundary of [A,B] |
|
|
//| Y - function values at the nodes, array[0..N-1] |
|
|
//| N - number of points, N>=1 |
|
|
//| for N=1 a constant model is constructed. |
|
|
//| OUTPUT PARAMETERS |
|
|
//| P - barycentric model which represents Lagrange |
|
|
//| interpolant (see ratint unit info and |
|
|
//| BarycentricCalc() description for more information). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PolynomialBuildEqDist(const double a,const double b,
|
|
double &y[],
|
|
CBarycentricInterpolantShell &p)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(y);
|
|
//--- function call
|
|
CPolInt::PolynomialBuildEqDist(a,b,y,n,p.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Lagrange intepolant on Chebyshev grid (first kind). |
|
|
//| This function has O(N) complexity. |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - left boundary of [A,B] |
|
|
//| B - right boundary of [A,B] |
|
|
//| Y - function values at the nodes, array[0..N-1], |
|
|
//| Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n)))|
|
|
//| N - number of points, N>=1 |
|
|
//| for N=1 a constant model is constructed. |
|
|
//| OUTPUT PARAMETERS |
|
|
//| P - barycentric model which represents Lagrange |
|
|
//| interpolant (see ratint unit info and |
|
|
//| BarycentricCalc() description for more information). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PolynomialBuildCheb1(const double a,const double b,
|
|
double &y[],const int n,
|
|
CBarycentricInterpolantShell &p)
|
|
{
|
|
//--- function call
|
|
CPolInt::PolynomialBuildCheb1(a,b,y,n,p.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Lagrange intepolant on Chebyshev grid (first kind). |
|
|
//| This function has O(N) complexity. |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - left boundary of [A,B] |
|
|
//| B - right boundary of [A,B] |
|
|
//| Y - function values at the nodes, array[0..N-1], |
|
|
//| Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n)))|
|
|
//| N - number of points, N>=1 |
|
|
//| for N=1 a constant model is constructed. |
|
|
//| OUTPUT PARAMETERS |
|
|
//| P - barycentric model which represents Lagrange |
|
|
//| interpolant (see ratint unit info and |
|
|
//| BarycentricCalc() description for more information). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PolynomialBuildCheb1(const double a,const double b,
|
|
double &y[],
|
|
CBarycentricInterpolantShell &p)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(y);
|
|
//--- function call
|
|
CPolInt::PolynomialBuildCheb1(a,b,y,n,p.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Lagrange intepolant on Chebyshev grid (second kind). |
|
|
//| This function has O(N) complexity. |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - left boundary of [A,B] |
|
|
//| B - right boundary of [A,B] |
|
|
//| Y - function values at the nodes, array[0..N-1], |
|
|
//| Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1))) |
|
|
//| N - number of points, N>=1 |
|
|
//| for N=1 a constant model is constructed. |
|
|
//| OUTPUT PARAMETERS |
|
|
//| P - barycentric model which represents Lagrange |
|
|
//| interpolant (see ratint unit info and |
|
|
//| BarycentricCalc() description for more information). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PolynomialBuildCheb2(const double a,const double b,
|
|
double &y[],const int n,
|
|
CBarycentricInterpolantShell &p)
|
|
{
|
|
//--- function call
|
|
CPolInt::PolynomialBuildCheb2(a,b,y,n,p.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Lagrange intepolant on Chebyshev grid (second kind). |
|
|
//| This function has O(N) complexity. |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - left boundary of [A,B] |
|
|
//| B - right boundary of [A,B] |
|
|
//| Y - function values at the nodes, array[0..N-1], |
|
|
//| Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1))) |
|
|
//| N - number of points, N>=1 |
|
|
//| for N=1 a constant model is constructed. |
|
|
//| OUTPUT PARAMETERS |
|
|
//| P - barycentric model which represents Lagrange |
|
|
//| interpolant (see ratint unit info and |
|
|
//| BarycentricCalc() description for more information). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PolynomialBuildCheb2(const double a,const double b,
|
|
double &y[],
|
|
CBarycentricInterpolantShell &p)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(y);
|
|
//--- function call
|
|
CPolInt::PolynomialBuildCheb2(a,b,y,n,p.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Fast equidistant polynomial interpolation function with O(N) |
|
|
//| complexity |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - left boundary of [A,B] |
|
|
//| B - right boundary of [A,B] |
|
|
//| F - function values, array[0..N-1] |
|
|
//| N - number of points on equidistant grid, N>=1 |
|
|
//| for N=1 a constant model is constructed. |
|
|
//| T - position where P(x) is calculated |
|
|
//| RESULT |
|
|
//| value of the Lagrange interpolant at T |
|
|
//| IMPORTANT |
|
|
//| this function provides fast interface which is not |
|
|
//| overflow-safe nor it is very precise. |
|
|
//| the best option is to use PolynomialBuildEqDist() or |
|
|
//| BarycentricCalc() subroutines unless you are pretty sure that|
|
|
//| your data will not result in overflow. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::PolynomialCalcEqDist(const double a,const double b,
|
|
double &f[],const int n,
|
|
const double t)
|
|
{
|
|
//--- return result
|
|
return(CPolInt::PolynomialCalcEqDist(a,b,f,n,t));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Fast equidistant polynomial interpolation function with O(N) |
|
|
//| complexity |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - left boundary of [A,B] |
|
|
//| B - right boundary of [A,B] |
|
|
//| F - function values, array[0..N-1] |
|
|
//| N - number of points on equidistant grid, N>=1 |
|
|
//| for N=1 a constant model is constructed. |
|
|
//| T - position where P(x) is calculated |
|
|
//| RESULT |
|
|
//| value of the Lagrange interpolant at T |
|
|
//| IMPORTANT |
|
|
//| this function provides fast interface which is not |
|
|
//| overflow-safe nor it is very precise. |
|
|
//| the best option is to use PolynomialBuildEqDist() or |
|
|
//| BarycentricCalc() subroutines unless you are pretty sure that|
|
|
//| your data will not result in overflow. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::PolynomialCalcEqDist(const double a,const double b,
|
|
double &f[],const double t)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(f);
|
|
//--- return result
|
|
return(CPolInt::PolynomialCalcEqDist(a,b,f,n,t));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Fast polynomial interpolation function on Chebyshev points (first|
|
|
//| kind) with O(N) complexity. |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - left boundary of [A,B] |
|
|
//| B - right boundary of [A,B] |
|
|
//| F - function values, array[0..N-1] |
|
|
//| N - number of points on Chebyshev grid (first kind), |
|
|
//| X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n)) |
|
|
//| for N=1 a constant model is constructed. |
|
|
//| T - position where P(x) is calculated |
|
|
//| RESULT |
|
|
//| value of the Lagrange interpolant at T |
|
|
//| IMPORTANT |
|
|
//| this function provides fast interface which is not |
|
|
//| overflow-safe nor it is very precise |
|
|
//| the best option is to use PolIntBuildCheb1() or |
|
|
//| BarycentricCalc() subroutines unless you are pretty sure that|
|
|
//| your data will not result in overflow. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::PolynomialCalcCheb1(const double a,const double b,
|
|
double &f[],const int n,
|
|
const double t)
|
|
{
|
|
//--- return result
|
|
return(CPolInt::PolynomialCalcCheb1(a,b,f,n,t));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Fast polynomial interpolation function on Chebyshev points (first|
|
|
//| kind) with O(N) complexity. |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - left boundary of [A,B] |
|
|
//| B - right boundary of [A,B] |
|
|
//| F - function values, array[0..N-1] |
|
|
//| N - number of points on Chebyshev grid (first kind), |
|
|
//| X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n)) |
|
|
//| for N=1 a constant model is constructed. |
|
|
//| T - position where P(x) is calculated |
|
|
//| RESULT |
|
|
//| value of the Lagrange interpolant at T |
|
|
//| IMPORTANT |
|
|
//| this function provides fast interface which is not |
|
|
//| overflow-safe nor it is very precise |
|
|
//| the best option is to use PolIntBuildCheb1() or |
|
|
//| BarycentricCalc() subroutines unless you are pretty sure that|
|
|
//| your data will not result in overflow. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::PolynomialCalcCheb1(const double a,const double b,
|
|
double &f[],const double t)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(f);
|
|
//--- return result
|
|
return(CPolInt::PolynomialCalcCheb1(a,b,f,n,t));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Fast polynomial interpolation function on Chebyshev points |
|
|
//| (second kind) with O(N) complexity. |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - left boundary of [A,B] |
|
|
//| B - right boundary of [A,B] |
|
|
//| F - function values, array[0..N-1] |
|
|
//| N - number of points on Chebyshev grid (second kind), |
|
|
//| X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1)) |
|
|
//| for N=1 a constant model is constructed. |
|
|
//| T - position where P(x) is calculated |
|
|
//| RESULT |
|
|
//| value of the Lagrange interpolant at T |
|
|
//| IMPORTANT |
|
|
//| this function provides fast interface which is not |
|
|
//| overflow-safe nor it is very precise. |
|
|
//| the best option is to use PolIntBuildCheb2() or |
|
|
//| BarycentricCalc() subroutines unless you are pretty sure that|
|
|
//| your data will not result in overflow. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::PolynomialCalcCheb2(const double a,const double b,
|
|
double &f[],const int n,
|
|
const double t)
|
|
{
|
|
//--- return result
|
|
return(CPolInt::PolynomialCalcCheb2(a,b,f,n,t));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Fast polynomial interpolation function on Chebyshev points |
|
|
//| (second kind) with O(N) complexity. |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - left boundary of [A,B] |
|
|
//| B - right boundary of [A,B] |
|
|
//| F - function values, array[0..N-1] |
|
|
//| N - number of points on Chebyshev grid (second kind), |
|
|
//| X[i] = 0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1)) |
|
|
//| for N=1 a constant model is constructed. |
|
|
//| T - position where P(x) is calculated |
|
|
//| RESULT |
|
|
//| value of the Lagrange interpolant at T |
|
|
//| IMPORTANT |
|
|
//| this function provides fast interface which is not |
|
|
//| overflow-safe nor it is very precise. |
|
|
//| the best option is to use PolIntBuildCheb2() or |
|
|
//| BarycentricCalc() subroutines unless you are pretty sure that|
|
|
//| your data will not result in overflow. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::PolynomialCalcCheb2(const double a,const double b,
|
|
double &f[],const double t)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(f);
|
|
//--- return result
|
|
return(CPolInt::PolynomialCalcCheb2(a,b,f,n,t));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine builds linear spline interpolant |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - spline nodes, array[0..N-1] |
|
|
//| Y - function values, array[0..N-1] |
|
|
//| N - points count (optional): |
|
|
//| * N>=2 |
|
|
//| * if given, only first N points are used to build |
|
|
//| spline |
|
|
//| * if not given, automatically detected from X/Y |
|
|
//| sizes (len(X) must be equal to len(Y)) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| C - spline interpolant |
|
|
//| ORDER OF POINTS |
|
|
//| Subroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DBuildLinear(double &x[],double &y[],const int n,
|
|
CSpline1DInterpolantShell &c)
|
|
{
|
|
//--- function call
|
|
CSpline1D::Spline1DBuildLinear(x,y,n,c.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine builds linear spline interpolant |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - spline nodes, array[0..N-1] |
|
|
//| Y - function values, array[0..N-1] |
|
|
//| N - points count (optional): |
|
|
//| * N>=2 |
|
|
//| * if given, only first N points are used to build |
|
|
//| spline |
|
|
//| * if not given, automatically detected from X/Y |
|
|
//| sizes (len(X) must be equal to len(Y)) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| C - spline interpolant |
|
|
//| ORDER OF POINTS |
|
|
//| Subroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DBuildLinear(double &x[],double &y[],
|
|
CSpline1DInterpolantShell &c)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- check
|
|
if((CAp::Len(x)!=CAp::Len(y)))
|
|
{
|
|
Print("Error while calling 'spline1dbuildlinear': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CSpline1D::Spline1DBuildLinear(x,y,n,c.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine builds cubic spline interpolant. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - spline nodes, array[0..N-1]. |
|
|
//| Y - function values, array[0..N-1]. |
|
|
//| OPTIONAL PARAMETERS: |
|
|
//| N - points count: |
|
|
//| * N>=2 |
|
|
//| * if given, only first N points are used to |
|
|
//| build spline |
|
|
//| * if not given, automatically detected from |
|
|
//| X/Y sizes (len(X) must be equal to len(Y)) |
|
|
//| BoundLType - boundary condition type for the left boundary|
|
|
//| BoundL - left boundary condition (first or second |
|
|
//| derivative, depending on the BoundLType) |
|
|
//| BoundRType - boundary condition type for the right |
|
|
//| boundary |
|
|
//| BoundR - right boundary condition (first or second |
|
|
//| derivative, depending on the BoundRType) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| C - spline interpolant |
|
|
//| ORDER OF POINTS |
|
|
//| Subroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. |
|
|
//| SETTING BOUNDARY VALUES: |
|
|
//| The BoundLType/BoundRType parameters can have the following |
|
|
//| values: |
|
|
//| * -1, which corresonds to the periodic (cyclic) boundary |
|
|
//| conditions. In this case: |
|
|
//| * both BoundLType and BoundRType must be equal to -1. |
|
|
//| * BoundL/BoundR are ignored |
|
|
//| * Y[last] is ignored (it is assumed to be equal to |
|
|
//| Y[first]). |
|
|
//| * 0, which corresponds to the parabolically terminated |
|
|
//| spline (BoundL and/or BoundR are ignored). |
|
|
//| * 1, which corresponds to the first derivative boundary |
|
|
//| condition |
|
|
//| * 2, which corresponds to the second derivative boundary |
|
|
//| condition |
|
|
//| * by default, BoundType=0 is used |
|
|
//| PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: |
|
|
//| Problems with periodic boundary conditions have |
|
|
//| Y[first_point]=Y[last_point]. However, this subroutine doesn't |
|
|
//| require you to specify equal values for the first and last |
|
|
//| points - it automatically forces them to be equal by copying |
|
|
//| Y[first_point] (corresponds to the leftmost, minimal X[]) to |
|
|
//| Y[last_point]. However it is recommended to pass consistent |
|
|
//| values of Y[], i.e. to make Y[first_point]=Y[last_point]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DBuildCubic(double &x[],double &y[],const int n,
|
|
const int boundltype,const double boundl,
|
|
const int boundrtype,const double boundr,
|
|
CSpline1DInterpolantShell &c)
|
|
{
|
|
//--- function call
|
|
CSpline1D::Spline1DBuildCubic(x,y,n,boundltype,boundl,boundrtype,boundr,c.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine builds cubic spline interpolant. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - spline nodes, array[0..N-1]. |
|
|
//| Y - function values, array[0..N-1]. |
|
|
//| OPTIONAL PARAMETERS: |
|
|
//| N - points count: |
|
|
//| * N>=2 |
|
|
//| * if given, only first N points are used to |
|
|
//| build spline |
|
|
//| * if not given, automatically detected from |
|
|
//| X/Y sizes (len(X) must be equal to len(Y)) |
|
|
//| BoundLType - boundary condition type for the left boundary|
|
|
//| BoundL - left boundary condition (first or second |
|
|
//| derivative, depending on the BoundLType) |
|
|
//| BoundRType - boundary condition type for the right |
|
|
//| boundary |
|
|
//| BoundR - right boundary condition (first or second |
|
|
//| derivative, depending on the BoundRType) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| C - spline interpolant |
|
|
//| ORDER OF POINTS |
|
|
//| Subroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. |
|
|
//| SETTING BOUNDARY VALUES: |
|
|
//| The BoundLType/BoundRType parameters can have the following |
|
|
//| values: |
|
|
//| * -1, which corresonds to the periodic (cyclic) boundary |
|
|
//| conditions. In this case: |
|
|
//| * both BoundLType and BoundRType must be equal to -1. |
|
|
//| * BoundL/BoundR are ignored |
|
|
//| * Y[last] is ignored (it is assumed to be equal to |
|
|
//| Y[first]). |
|
|
//| * 0, which corresponds to the parabolically terminated |
|
|
//| spline (BoundL and/or BoundR are ignored). |
|
|
//| * 1, which corresponds to the first derivative boundary |
|
|
//| condition |
|
|
//| * 2, which corresponds to the second derivative boundary |
|
|
//| condition |
|
|
//| * by default, BoundType=0 is used |
|
|
//| PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: |
|
|
//| Problems with periodic boundary conditions have |
|
|
//| Y[first_point]=Y[last_point]. However, this subroutine doesn't |
|
|
//| require you to specify equal values for the first and last |
|
|
//| points - it automatically forces them to be equal by copying |
|
|
//| Y[first_point] (corresponds to the leftmost, minimal X[]) to |
|
|
//| Y[last_point]. However it is recommended to pass consistent |
|
|
//| values of Y[], i.e. to make Y[first_point]=Y[last_point]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DBuildCubic(double &x[],double &y[],
|
|
CSpline1DInterpolantShell &c)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
int boundltype;
|
|
double boundl;
|
|
int boundrtype;
|
|
double boundr;
|
|
//--- check
|
|
if((CAp::Len(x)!=CAp::Len(y)))
|
|
{
|
|
Print("Error while calling 'spline1dbuildcubic': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
boundltype=0;
|
|
boundl=0;
|
|
boundrtype=0;
|
|
boundr=0;
|
|
//--- function call
|
|
CSpline1D::Spline1DBuildCubic(x,y,n,boundltype,boundl,boundrtype,boundr,c.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function solves following problem: given table y[] of |
|
|
//| function values at nodes x[], it calculates and returns table of |
|
|
//| function derivatives d[] (calculated at the same nodes x[]). |
|
|
//| This function yields same result as Spline1DBuildCubic() call |
|
|
//| followed by sequence of Spline1DDiff() calls, but it can be |
|
|
//| several times faster when called for ordered X[] and X2[]. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - spline nodes |
|
|
//| Y - function values |
|
|
//| OPTIONAL PARAMETERS: |
|
|
//| N - points count: |
|
|
//| * N>=2 |
|
|
//| * if given, only first N points are used |
|
|
//| * if not given, automatically detected from |
|
|
//| X/Y sizes (len(X) must be equal to len(Y)) |
|
|
//| BoundLType - boundary condition type for the left boundary|
|
|
//| BoundL - left boundary condition (first or second |
|
|
//| derivative, depending on the BoundLType) |
|
|
//| BoundRType - boundary condition type for the right |
|
|
//| boundary |
|
|
//| BoundR - right boundary condition (first or second |
|
|
//| derivative, depending on the BoundRType) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| D - derivative values at X[] |
|
|
//| ORDER OF POINTS |
|
|
//| Subroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. Derivative values are correctly reordered on |
|
|
//| return, so D[I] is always equal to S'(X[I]) independently of |
|
|
//| points order. |
|
|
//| SETTING BOUNDARY VALUES: |
|
|
//| The BoundLType/BoundRType parameters can have the following |
|
|
//| values: |
|
|
//| * -1, which corresonds to the periodic (cyclic) boundary |
|
|
//| conditions. In this case: |
|
|
//| * both BoundLType and BoundRType must be equal to -1. |
|
|
//| * BoundL/BoundR are ignored |
|
|
//| * Y[last] is ignored (it is assumed to be equal to |
|
|
//| Y[first]). |
|
|
//| * 0, which corresponds to the parabolically terminated |
|
|
//| spline (BoundL and/or BoundR are ignored). |
|
|
//| * 1, which corresponds to the first derivative boundary |
|
|
//| condition |
|
|
//| * 2, which corresponds to the second derivative boundary |
|
|
//| condition |
|
|
//| * by default, BoundType=0 is used |
|
|
//| PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: |
|
|
//| Problems with periodic boundary conditions have |
|
|
//| Y[first_point]=Y[last_point]. However, this subroutine doesn't |
|
|
//| require you to specify equal values for the first and last |
|
|
//| points - it automatically forces them to be equal by copying |
|
|
//| Y[first_point] (corresponds to the leftmost, minimal X[]) to |
|
|
//| Y[last_point]. However it is recommended to pass consistent |
|
|
//| values of Y[], i.e. to make Y[first_point]=Y[last_point]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DGridDiffCubic(double &x[],double &y[],
|
|
const int n,const int boundltype,
|
|
const double boundl,const int boundrtype,
|
|
const double boundr,double &d[])
|
|
{
|
|
//--- function call
|
|
CSpline1D::Spline1DGridDiffCubic(x,y,n,boundltype,boundl,boundrtype,boundr,d);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function solves following problem: given table y[] of |
|
|
//| function values at nodes x[], it calculates and returns table of |
|
|
//| function derivatives d[] (calculated at the same nodes x[]). |
|
|
//| This function yields same result as Spline1DBuildCubic() call |
|
|
//| followed by sequence of Spline1DDiff() calls, but it can be |
|
|
//| several times faster when called for ordered X[] and X2[]. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - spline nodes |
|
|
//| Y - function values |
|
|
//| OPTIONAL PARAMETERS: |
|
|
//| N - points count: |
|
|
//| * N>=2 |
|
|
//| * if given, only first N points are used |
|
|
//| * if not given, automatically detected from |
|
|
//| X/Y sizes (len(X) must be equal to len(Y)) |
|
|
//| BoundLType - boundary condition type for the left boundary|
|
|
//| BoundL - left boundary condition (first or second |
|
|
//| derivative, depending on the BoundLType) |
|
|
//| BoundRType - boundary condition type for the right |
|
|
//| boundary |
|
|
//| BoundR - right boundary condition (first or second |
|
|
//| derivative, depending on the BoundRType) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| D - derivative values at X[] |
|
|
//| ORDER OF POINTS |
|
|
//| Subroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. Derivative values are correctly reordered on |
|
|
//| return, so D[I] is always equal to S'(X[I]) independently of |
|
|
//| points order. |
|
|
//| SETTING BOUNDARY VALUES: |
|
|
//| The BoundLType/BoundRType parameters can have the following |
|
|
//| values: |
|
|
//| * -1, which corresonds to the periodic (cyclic) boundary |
|
|
//| conditions. In this case: |
|
|
//| * both BoundLType and BoundRType must be equal to -1. |
|
|
//| * BoundL/BoundR are ignored |
|
|
//| * Y[last] is ignored (it is assumed to be equal to |
|
|
//| Y[first]). |
|
|
//| * 0, which corresponds to the parabolically terminated |
|
|
//| spline (BoundL and/or BoundR are ignored). |
|
|
//| * 1, which corresponds to the first derivative boundary |
|
|
//| condition |
|
|
//| * 2, which corresponds to the second derivative boundary |
|
|
//| condition |
|
|
//| * by default, BoundType=0 is used |
|
|
//| PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: |
|
|
//| Problems with periodic boundary conditions have |
|
|
//| Y[first_point]=Y[last_point]. However, this subroutine doesn't |
|
|
//| require you to specify equal values for the first and last |
|
|
//| points - it automatically forces them to be equal by copying |
|
|
//| Y[first_point] (corresponds to the leftmost, minimal X[]) to |
|
|
//| Y[last_point]. However it is recommended to pass consistent |
|
|
//| values of Y[], i.e. to make Y[first_point]=Y[last_point]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DGridDiffCubic(double &x[],double &y[],
|
|
double &d[])
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
int boundltype;
|
|
double boundl;
|
|
int boundrtype;
|
|
double boundr;
|
|
//--- check
|
|
if((CAp::Len(x)!=CAp::Len(y)))
|
|
{
|
|
Print("Error while calling 'spline1dgriddiffcubic': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
boundltype=0;
|
|
boundl=0;
|
|
boundrtype=0;
|
|
boundr=0;
|
|
//--- function call
|
|
CSpline1D::Spline1DGridDiffCubic(x,y,n,boundltype,boundl,boundrtype,boundr,d);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function solves following problem: given table y[] of |
|
|
//| function values at nodes x[], it calculates and returns tables of|
|
|
//| first and second function derivatives d1[] and d2[] (calculated |
|
|
//| at the same nodes x[]). |
|
|
//| This function yields same result as Spline1DBuildCubic() call |
|
|
//| followed by sequence of Spline1DDiff() calls, but it can be |
|
|
//| several times faster when called for ordered X[] and X2[]. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - spline nodes |
|
|
//| Y - function values |
|
|
//| OPTIONAL PARAMETERS: |
|
|
//| N - points count: |
|
|
//| * N>=2 |
|
|
//| * if given, only first N points are used |
|
|
//| * if not given, automatically detected from |
|
|
//| X/Y sizes (len(X) must be equal to len(Y)) |
|
|
//| BoundLType - boundary condition type for the left boundary|
|
|
//| BoundL - left boundary condition (first or second |
|
|
//| derivative, depending on the BoundLType) |
|
|
//| BoundRType - boundary condition type for the right |
|
|
//| boundary |
|
|
//| BoundR - right boundary condition (first or second |
|
|
//| derivative, depending on the BoundRType) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| D1 - S' values at X[] |
|
|
//| D2 - S'' values at X[] |
|
|
//| ORDER OF POINTS |
|
|
//| Subroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. Derivative values are correctly reordered on |
|
|
//| return, so D[I] is always equal to S'(X[I]) independently of |
|
|
//| points order. |
|
|
//| SETTING BOUNDARY VALUES: |
|
|
//| The BoundLType/BoundRType parameters can have the following |
|
|
//| values: |
|
|
//| * -1, which corresonds to the periodic (cyclic) boundary |
|
|
//| conditions. In this case: |
|
|
//| * both BoundLType and BoundRType must be equal to -1. |
|
|
//| * BoundL/BoundR are ignored |
|
|
//| * Y[last] is ignored (it is assumed to be equal to |
|
|
//| Y[first]). |
|
|
//| * 0, which corresponds to the parabolically terminated |
|
|
//| spline (BoundL and/or BoundR are ignored). |
|
|
//| * 1, which corresponds to the first derivative boundary |
|
|
//| condition |
|
|
//| * 2, which corresponds to the second derivative boundary |
|
|
//| condition |
|
|
//| * by default, BoundType=0 is used |
|
|
//| PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: |
|
|
//| Problems with periodic boundary conditions have |
|
|
//| Y[first_point]=Y[last_point]. |
|
|
//| However, this subroutine doesn't require you to specify equal |
|
|
//| values for the first and last points - it automatically forces |
|
|
//| them to be equal by copying Y[first_point] (corresponds to the |
|
|
//| leftmost, minimal X[]) to Y[last_point]. However it is |
|
|
//| recommended to pass consistent values of Y[], i.e. to make |
|
|
//| Y[first_point]=Y[last_point]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DGridDiff2Cubic(double &x[],double &y[],
|
|
const int n,const int boundltype,
|
|
const double boundl,const int boundrtype,
|
|
const double boundr,double &d1[],
|
|
double &d2[])
|
|
{
|
|
//--- function call
|
|
CSpline1D::Spline1DGridDiff2Cubic(x,y,n,boundltype,boundl,boundrtype,boundr,d1,d2);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function solves following problem: given table y[] of |
|
|
//| function values at nodes x[], it calculates and returns tables of|
|
|
//| first and second function derivatives d1[] and d2[] (calculated |
|
|
//| at the same nodes x[]). |
|
|
//| This function yields same result as Spline1DBuildCubic() call |
|
|
//| followed by sequence of Spline1DDiff() calls, but it can be |
|
|
//| several times faster when called for ordered X[] and X2[]. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - spline nodes |
|
|
//| Y - function values |
|
|
//| OPTIONAL PARAMETERS: |
|
|
//| N - points count: |
|
|
//| * N>=2 |
|
|
//| * if given, only first N points are used |
|
|
//| * if not given, automatically detected from |
|
|
//| X/Y sizes (len(X) must be equal to len(Y)) |
|
|
//| BoundLType - boundary condition type for the left boundary|
|
|
//| BoundL - left boundary condition (first or second |
|
|
//| derivative, depending on the BoundLType) |
|
|
//| BoundRType - boundary condition type for the right |
|
|
//| boundary |
|
|
//| BoundR - right boundary condition (first or second |
|
|
//| derivative, depending on the BoundRType) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| D1 - S' values at X[] |
|
|
//| D2 - S'' values at X[] |
|
|
//| ORDER OF POINTS |
|
|
//| Subroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. Derivative values are correctly reordered on |
|
|
//| return, so D[I] is always equal to S'(X[I]) independently of |
|
|
//| points order. |
|
|
//| SETTING BOUNDARY VALUES: |
|
|
//| The BoundLType/BoundRType parameters can have the following |
|
|
//| values: |
|
|
//| * -1, which corresonds to the periodic (cyclic) boundary |
|
|
//| conditions. In this case: |
|
|
//| * both BoundLType and BoundRType must be equal to -1. |
|
|
//| * BoundL/BoundR are ignored |
|
|
//| * Y[last] is ignored (it is assumed to be equal to |
|
|
//| Y[first]). |
|
|
//| * 0, which corresponds to the parabolically terminated |
|
|
//| spline (BoundL and/or BoundR are ignored). |
|
|
//| * 1, which corresponds to the first derivative boundary |
|
|
//| condition |
|
|
//| * 2, which corresponds to the second derivative boundary |
|
|
//| condition |
|
|
//| * by default, BoundType=0 is used |
|
|
//| PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: |
|
|
//| Problems with periodic boundary conditions have |
|
|
//| Y[first_point]=Y[last_point]. |
|
|
//| However, this subroutine doesn't require you to specify equal |
|
|
//| values for the first and last points - it automatically forces |
|
|
//| them to be equal by copying Y[first_point] (corresponds to the |
|
|
//| leftmost, minimal X[]) to Y[last_point]. However it is |
|
|
//| recommended to pass consistent values of Y[], i.e. to make |
|
|
//| Y[first_point]=Y[last_point]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DGridDiff2Cubic(double &x[],double &y[],
|
|
double &d1[],double &d2[])
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
int boundltype;
|
|
double boundl;
|
|
int boundrtype;
|
|
double boundr;
|
|
//--- check
|
|
if((CAp::Len(x)!=CAp::Len(y)))
|
|
{
|
|
Print("Error while calling 'spline1dgriddiff2cubic': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
boundltype=0;
|
|
boundl=0;
|
|
boundrtype=0;
|
|
boundr=0;
|
|
//--- function call
|
|
CSpline1D::Spline1DGridDiff2Cubic(x,y,n,boundltype,boundl,boundrtype,boundr,d1,d2);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function solves following problem: given table y[] of |
|
|
//| function values at old nodes x[] and new nodes x2[], it |
|
|
//| calculates and returns table of function values y2[] (calculated |
|
|
//| at x2[]). |
|
|
//| This function yields same result as Spline1DBuildCubic() call |
|
|
//| followed by sequence of Spline1DDiff() calls, but it can be |
|
|
//| several times faster when called for ordered X[] and X2[]. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - old spline nodes |
|
|
//| Y - function values |
|
|
//| X2 - new spline nodes |
|
|
//| OPTIONAL PARAMETERS: |
|
|
//| N - points count: |
|
|
//| * N>=2 |
|
|
//| * if given, only first N points from X/Y are |
|
|
//| used |
|
|
//| * if not given, automatically detected from |
|
|
//| X/Y sizes (len(X) must be equal to len(Y)) |
|
|
//| BoundLType - boundary condition type for the left boundary|
|
|
//| BoundL - left boundary condition (first or second |
|
|
//| derivative, depending on the BoundLType) |
|
|
//| BoundRType - boundary condition type for the right |
|
|
//| boundary |
|
|
//| BoundR - right boundary condition (first or second |
|
|
//| derivative, depending on the BoundRType) |
|
|
//| N2 - new points count: |
|
|
//| * N2>=2 |
|
|
//| * if given, only first N2 points from X2 are |
|
|
//| used |
|
|
//| * if not given, automatically detected from |
|
|
//| X2 size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| F2 - function values at X2[] |
|
|
//| ORDER OF POINTS |
|
|
//| Subroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. Function values are correctly reordered on |
|
|
//| return, so F2[I] is always equal to S(X2[I]) independently of |
|
|
//| points order. |
|
|
//| SETTING BOUNDARY VALUES: |
|
|
//| The BoundLType/BoundRType parameters can have the following |
|
|
//| values: |
|
|
//| * -1, which corresonds to the periodic (cyclic) boundary |
|
|
//| conditions. In this case: |
|
|
//| * both BoundLType and BoundRType must be equal to -1. |
|
|
//| * BoundL/BoundR are ignored |
|
|
//| * Y[last] is ignored (it is assumed to be equal to |
|
|
//| Y[first]). |
|
|
//| * 0, which corresponds to the parabolically terminated |
|
|
//| spline (BoundL and/or BoundR are ignored). |
|
|
//| * 1, which corresponds to the first derivative boundary |
|
|
//| condition |
|
|
//| * 2, which corresponds to the second derivative boundary |
|
|
//| condition |
|
|
//| * by default, BoundType=0 is used |
|
|
//| PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: |
|
|
//| Problems with periodic boundary conditions have |
|
|
//| Y[first_point]=Y[last_point]. However, this subroutine doesn't |
|
|
//| require you to specify equal values for the first and last |
|
|
//| points - it automatically forces them to be equal by copying |
|
|
//| Y[first_point] (corresponds to the leftmost, minimal X[]) to |
|
|
//| Y[last_point]. However it is recommended to pass consistent |
|
|
//| values of Y[], i.e. to make Y[first_point]=Y[last_point]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DConvCubic(double &x[],double &y[],const int n,
|
|
const int boundltype,const double boundl,
|
|
const int boundrtype,const double boundr,
|
|
double &x2[],int n2,double &y2[])
|
|
{
|
|
//--- function call
|
|
CSpline1D::Spline1DConvCubic(x,y,n,boundltype,boundl,boundrtype,boundr,x2,n2,y2);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function solves following problem: given table y[] of |
|
|
//| function values at old nodes x[] and new nodes x2[], it |
|
|
//| calculates and returns table of function values y2[] (calculated |
|
|
//| at x2[]). |
|
|
//| This function yields same result as Spline1DBuildCubic() call |
|
|
//| followed by sequence of Spline1DDiff() calls, but it can be |
|
|
//| several times faster when called for ordered X[] and X2[]. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - old spline nodes |
|
|
//| Y - function values |
|
|
//| X2 - new spline nodes |
|
|
//| OPTIONAL PARAMETERS: |
|
|
//| N - points count: |
|
|
//| * N>=2 |
|
|
//| * if given, only first N points from X/Y are |
|
|
//| used |
|
|
//| * if not given, automatically detected from |
|
|
//| X/Y sizes (len(X) must be equal to len(Y)) |
|
|
//| BoundLType - boundary condition type for the left boundary|
|
|
//| BoundL - left boundary condition (first or second |
|
|
//| derivative, depending on the BoundLType) |
|
|
//| BoundRType - boundary condition type for the right |
|
|
//| boundary |
|
|
//| BoundR - right boundary condition (first or second |
|
|
//| derivative, depending on the BoundRType) |
|
|
//| N2 - new points count: |
|
|
//| * N2>=2 |
|
|
//| * if given, only first N2 points from X2 are |
|
|
//| used |
|
|
//| * if not given, automatically detected from |
|
|
//| X2 size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| F2 - function values at X2[] |
|
|
//| ORDER OF POINTS |
|
|
//| Subroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. Function values are correctly reordered on |
|
|
//| return, so F2[I] is always equal to S(X2[I]) independently of |
|
|
//| points order. |
|
|
//| SETTING BOUNDARY VALUES: |
|
|
//| The BoundLType/BoundRType parameters can have the following |
|
|
//| values: |
|
|
//| * -1, which corresonds to the periodic (cyclic) boundary |
|
|
//| conditions. In this case: |
|
|
//| * both BoundLType and BoundRType must be equal to -1. |
|
|
//| * BoundL/BoundR are ignored |
|
|
//| * Y[last] is ignored (it is assumed to be equal to |
|
|
//| Y[first]). |
|
|
//| * 0, which corresponds to the parabolically terminated |
|
|
//| spline (BoundL and/or BoundR are ignored). |
|
|
//| * 1, which corresponds to the first derivative boundary |
|
|
//| condition |
|
|
//| * 2, which corresponds to the second derivative boundary |
|
|
//| condition |
|
|
//| * by default, BoundType=0 is used |
|
|
//| PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: |
|
|
//| Problems with periodic boundary conditions have |
|
|
//| Y[first_point]=Y[last_point]. However, this subroutine doesn't |
|
|
//| require you to specify equal values for the first and last |
|
|
//| points - it automatically forces them to be equal by copying |
|
|
//| Y[first_point] (corresponds to the leftmost, minimal X[]) to |
|
|
//| Y[last_point]. However it is recommended to pass consistent |
|
|
//| values of Y[], i.e. to make Y[first_point]=Y[last_point]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DConvCubic(double &x[],double &y[],
|
|
double &x2[],double &y2[])
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
int boundltype;
|
|
double boundl;
|
|
int boundrtype;
|
|
double boundr;
|
|
int n2;
|
|
//--- check
|
|
if((CAp::Len(x)!=CAp::Len(y)))
|
|
{
|
|
Print("Error while calling 'spline1dconvcubic': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
boundltype=0;
|
|
boundl=0;
|
|
boundrtype=0;
|
|
boundr=0;
|
|
n2=CAp::Len(x2);
|
|
//--- function call
|
|
CSpline1D::Spline1DConvCubic(x,y,n,boundltype,boundl,boundrtype,boundr,x2,n2,y2);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function solves following problem: given table y[] of |
|
|
//| function values at old nodes x[] and new nodes x2[], it |
|
|
//| calculates and returns table of function values y2[] and |
|
|
//| derivatives d2[] (calculated at x2[]). |
|
|
//| This function yields same result as Spline1DBuildCubic() call |
|
|
//| followed by sequence of Spline1DDiff() calls, but it can be |
|
|
//| several times faster when called for ordered X[] and X2[]. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - old spline nodes |
|
|
//| Y - function values |
|
|
//| X2 - new spline nodes |
|
|
//| OPTIONAL PARAMETERS: |
|
|
//| N - points count: |
|
|
//| * N>=2 |
|
|
//| * if given, only first N points from X/Y are |
|
|
//| used |
|
|
//| * if not given, automatically detected from |
|
|
//| X/Y sizes (len(X) must be equal to len(Y)) |
|
|
//| BoundLType - boundary condition type for the left boundary|
|
|
//| BoundL - left boundary condition (first or second |
|
|
//| derivative, depending on the BoundLType) |
|
|
//| BoundRType - boundary condition type for the right |
|
|
//| boundary |
|
|
//| BoundR - right boundary condition (first or second |
|
|
//| derivative, depending on the BoundRType) |
|
|
//| N2 - new points count: |
|
|
//| * N2>=2 |
|
|
//| * if given, only first N2 points from X2 are |
|
|
//| used |
|
|
//| * if not given, automatically detected from |
|
|
//| X2 size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| F2 - function values at X2[] |
|
|
//| D2 - first derivatives at X2[] |
|
|
//| ORDER OF POINTS |
|
|
//| Subroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. Function values are correctly reordered on |
|
|
//| return, so F2[I] is always equal to S(X2[I]) independently of |
|
|
//| points order. |
|
|
//| SETTING BOUNDARY VALUES: |
|
|
//| The BoundLType/BoundRType parameters can have the following |
|
|
//| values: |
|
|
//| * -1, which corresonds to the periodic (cyclic) boundary |
|
|
//| conditions. In this case: |
|
|
//| * both BoundLType and BoundRType must be equal to -1. |
|
|
//| * BoundL/BoundR are ignored |
|
|
//| * Y[last] is ignored (it is assumed to be equal to |
|
|
//| Y[first]). |
|
|
//| * 0, which corresponds to the parabolically terminated |
|
|
//| spline (BoundL and/or BoundR are ignored). |
|
|
//| * 1, which corresponds to the first derivative boundary |
|
|
//| condition |
|
|
//| * 2, which corresponds to the second derivative boundary |
|
|
//| condition |
|
|
//| * by default, BoundType=0 is used |
|
|
//| PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: |
|
|
//| Problems with periodic boundary conditions have |
|
|
//| Y[first_point]=Y[last_point]. However, this subroutine doesn't |
|
|
//| require you to specify equal values for the first and last |
|
|
//| points - it automatically forces them to be equal by copying |
|
|
//| Y[first_point] (corresponds to the leftmost, minimal X[]) to |
|
|
//| Y[last_point]. However it is recommended to pass consistent |
|
|
//| values of Y[], i.e. to make Y[first_point]=Y[last_point]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DConvDiffCubic(double &x[],double &y[],
|
|
const int n,const int boundltype,
|
|
const double boundl,const int boundrtype,
|
|
const double boundr,double &x2[],
|
|
int n2,double &y2[],double &d2[])
|
|
{
|
|
//--- function call
|
|
CSpline1D::Spline1DConvDiffCubic(x,y,n,boundltype,boundl,boundrtype,boundr,x2,n2,y2,d2);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function solves following problem: given table y[] of |
|
|
//| function values at old nodes x[] and new nodes x2[], it |
|
|
//| calculates and returns table of function values y2[] and |
|
|
//| derivatives d2[] (calculated at x2[]). |
|
|
//| This function yields same result as Spline1DBuildCubic() call |
|
|
//| followed by sequence of Spline1DDiff() calls, but it can be |
|
|
//| several times faster when called for ordered X[] and X2[]. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - old spline nodes |
|
|
//| Y - function values |
|
|
//| X2 - new spline nodes |
|
|
//| OPTIONAL PARAMETERS: |
|
|
//| N - points count: |
|
|
//| * N>=2 |
|
|
//| * if given, only first N points from X/Y are |
|
|
//| used |
|
|
//| * if not given, automatically detected from |
|
|
//| X/Y sizes (len(X) must be equal to len(Y)) |
|
|
//| BoundLType - boundary condition type for the left boundary|
|
|
//| BoundL - left boundary condition (first or second |
|
|
//| derivative, depending on the BoundLType) |
|
|
//| BoundRType - boundary condition type for the right |
|
|
//| boundary |
|
|
//| BoundR - right boundary condition (first or second |
|
|
//| derivative, depending on the BoundRType) |
|
|
//| N2 - new points count: |
|
|
//| * N2>=2 |
|
|
//| * if given, only first N2 points from X2 are |
|
|
//| used |
|
|
//| * if not given, automatically detected from |
|
|
//| X2 size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| F2 - function values at X2[] |
|
|
//| D2 - first derivatives at X2[] |
|
|
//| ORDER OF POINTS |
|
|
//| Subroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. Function values are correctly reordered on |
|
|
//| return, so F2[I] is always equal to S(X2[I]) independently of |
|
|
//| points order. |
|
|
//| SETTING BOUNDARY VALUES: |
|
|
//| The BoundLType/BoundRType parameters can have the following |
|
|
//| values: |
|
|
//| * -1, which corresonds to the periodic (cyclic) boundary |
|
|
//| conditions. In this case: |
|
|
//| * both BoundLType and BoundRType must be equal to -1. |
|
|
//| * BoundL/BoundR are ignored |
|
|
//| * Y[last] is ignored (it is assumed to be equal to |
|
|
//| Y[first]). |
|
|
//| * 0, which corresponds to the parabolically terminated |
|
|
//| spline (BoundL and/or BoundR are ignored). |
|
|
//| * 1, which corresponds to the first derivative boundary |
|
|
//| condition |
|
|
//| * 2, which corresponds to the second derivative boundary |
|
|
//| condition |
|
|
//| * by default, BoundType=0 is used |
|
|
//| PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: |
|
|
//| Problems with periodic boundary conditions have |
|
|
//| Y[first_point]=Y[last_point]. However, this subroutine doesn't |
|
|
//| require you to specify equal values for the first and last |
|
|
//| points - it automatically forces them to be equal by copying |
|
|
//| Y[first_point] (corresponds to the leftmost, minimal X[]) to |
|
|
//| Y[last_point]. However it is recommended to pass consistent |
|
|
//| values of Y[], i.e. to make Y[first_point]=Y[last_point]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DConvDiffCubic(double &x[],double &y[],
|
|
double &x2[],double &y2[],
|
|
double &d2[])
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
int boundltype;
|
|
double boundl;
|
|
int boundrtype;
|
|
double boundr;
|
|
int n2;
|
|
//--- check
|
|
if((CAp::Len(x)!=CAp::Len(y)))
|
|
{
|
|
Print("Error while calling 'spline1dconvdiffcubic': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
boundltype=0;
|
|
boundl=0;
|
|
boundrtype=0;
|
|
boundr=0;
|
|
n2=CAp::Len(x2);
|
|
//--- function call
|
|
CSpline1D::Spline1DConvDiffCubic(x,y,n,boundltype,boundl,boundrtype,boundr,x2,n2,y2,d2);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function solves following problem: given table y[] of |
|
|
//| function values at old nodes x[] and new nodes x2[], it |
|
|
//| calculates and returns table of function values y2[], first and |
|
|
//| second derivatives d2[] and dd2[] (calculated at x2[]). |
|
|
//| This function yields same result as Spline1DBuildCubic() call |
|
|
//| followed by sequence of Spline1DDiff() calls, but it can be |
|
|
//| several times faster when called for ordered X[] and X2[]. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - old spline nodes |
|
|
//| Y - function values |
|
|
//| X2 - new spline nodes |
|
|
//| OPTIONAL PARAMETERS: |
|
|
//| N - points count: |
|
|
//| * N>=2 |
|
|
//| * if given, only first N points from X/Y are |
|
|
//| used |
|
|
//| * if not given, automatically detected from |
|
|
//| X/Y sizes (len(X) must be equal to len(Y)) |
|
|
//| BoundLType - boundary condition type for the left boundary|
|
|
//| BoundL - left boundary condition (first or second |
|
|
//| derivative, depending on the BoundLType) |
|
|
//| BoundRType - boundary condition type for the right |
|
|
//| boundary |
|
|
//| BoundR - right boundary condition (first or second |
|
|
//| derivative, depending on the BoundRType) |
|
|
//| N2 - new points count: |
|
|
//| * N2>=2 |
|
|
//| * if given, only first N2 points from X2 are |
|
|
//| used |
|
|
//| * if not given, automatically detected from |
|
|
//| X2 size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| F2 - function values at X2[] |
|
|
//| D2 - first derivatives at X2[] |
|
|
//| DD2 - second derivatives at X2[] |
|
|
//| ORDER OF POINTS |
|
|
//| Subroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. Function values are correctly reordered on |
|
|
//| return, so F2[I] is always equal to S(X2[I]) independently of |
|
|
//| points order. |
|
|
//| SETTING BOUNDARY VALUES: |
|
|
//| The BoundLType/BoundRType parameters can have the following |
|
|
//| values: |
|
|
//| * -1, which corresonds to the periodic (cyclic) boundary |
|
|
//| conditions. In this case: |
|
|
//| * both BoundLType and BoundRType must be equal to -1. |
|
|
//| * BoundL/BoundR are ignored |
|
|
//| * Y[last] is ignored (it is assumed to be equal to |
|
|
//| Y[first]). |
|
|
//| * 0, which corresponds to the parabolically terminated |
|
|
//| spline (BoundL and/or BoundR are ignored). |
|
|
//| * 1, which corresponds to the first derivative boundary |
|
|
//| condition |
|
|
//| * 2, which corresponds to the second derivative boundary |
|
|
//| condition |
|
|
//| * by default, BoundType=0 is used |
|
|
//| PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: |
|
|
//| Problems with periodic boundary conditions have |
|
|
//| Y[first_point]=Y[last_point]. However, this subroutine doesn't |
|
|
//| require you to specify equal values for the first and last |
|
|
//| points - it automatically forces them to be equal by copying |
|
|
//| Y[first_point] (corresponds to the leftmost, minimal X[]) to |
|
|
//| Y[last_point]. However it is recommended to pass consistent |
|
|
//| values of Y[], i.e. to make Y[first_point]=Y[last_point]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DConvDiff2Cubic(double &x[],double &y[],
|
|
const int n,const int boundltype,
|
|
const double boundl,const int boundrtype,
|
|
const double boundr,double &x2[],
|
|
const int n2,double &y2[],
|
|
double &d2[],double &dd2[])
|
|
{
|
|
//--- function call
|
|
CSpline1D::Spline1DConvDiff2Cubic(x,y,n,boundltype,boundl,boundrtype,boundr,x2,n2,y2,d2,dd2);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function solves following problem: given table y[] of |
|
|
//| function values at old nodes x[] and new nodes x2[], it |
|
|
//| calculates and returns table of function values y2[], first and |
|
|
//| second derivatives d2[] and dd2[] (calculated at x2[]). |
|
|
//| This function yields same result as Spline1DBuildCubic() call |
|
|
//| followed by sequence of Spline1DDiff() calls, but it can be |
|
|
//| several times faster when called for ordered X[] and X2[]. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - old spline nodes |
|
|
//| Y - function values |
|
|
//| X2 - new spline nodes |
|
|
//| OPTIONAL PARAMETERS: |
|
|
//| N - points count: |
|
|
//| * N>=2 |
|
|
//| * if given, only first N points from X/Y are |
|
|
//| used |
|
|
//| * if not given, automatically detected from |
|
|
//| X/Y sizes (len(X) must be equal to len(Y)) |
|
|
//| BoundLType - boundary condition type for the left boundary|
|
|
//| BoundL - left boundary condition (first or second |
|
|
//| derivative, depending on the BoundLType) |
|
|
//| BoundRType - boundary condition type for the right |
|
|
//| boundary |
|
|
//| BoundR - right boundary condition (first or second |
|
|
//| derivative, depending on the BoundRType) |
|
|
//| N2 - new points count: |
|
|
//| * N2>=2 |
|
|
//| * if given, only first N2 points from X2 are |
|
|
//| used |
|
|
//| * if not given, automatically detected from |
|
|
//| X2 size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| F2 - function values at X2[] |
|
|
//| D2 - first derivatives at X2[] |
|
|
//| DD2 - second derivatives at X2[] |
|
|
//| ORDER OF POINTS |
|
|
//| Subroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. Function values are correctly reordered on |
|
|
//| return, so F2[I] is always equal to S(X2[I]) independently of |
|
|
//| points order. |
|
|
//| SETTING BOUNDARY VALUES: |
|
|
//| The BoundLType/BoundRType parameters can have the following |
|
|
//| values: |
|
|
//| * -1, which corresonds to the periodic (cyclic) boundary |
|
|
//| conditions. In this case: |
|
|
//| * both BoundLType and BoundRType must be equal to -1. |
|
|
//| * BoundL/BoundR are ignored |
|
|
//| * Y[last] is ignored (it is assumed to be equal to |
|
|
//| Y[first]). |
|
|
//| * 0, which corresponds to the parabolically terminated |
|
|
//| spline (BoundL and/or BoundR are ignored). |
|
|
//| * 1, which corresponds to the first derivative boundary |
|
|
//| condition |
|
|
//| * 2, which corresponds to the second derivative boundary |
|
|
//| condition |
|
|
//| * by default, BoundType=0 is used |
|
|
//| PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: |
|
|
//| Problems with periodic boundary conditions have |
|
|
//| Y[first_point]=Y[last_point]. However, this subroutine doesn't |
|
|
//| require you to specify equal values for the first and last |
|
|
//| points - it automatically forces them to be equal by copying |
|
|
//| Y[first_point] (corresponds to the leftmost, minimal X[]) to |
|
|
//| Y[last_point]. However it is recommended to pass consistent |
|
|
//| values of Y[], i.e. to make Y[first_point]=Y[last_point]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DConvDiff2Cubic(double &x[],double &y[],
|
|
double &x2[],double &y2[],
|
|
double &d2[],double &dd2[])
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
int boundltype;
|
|
double boundl;
|
|
int boundrtype;
|
|
double boundr;
|
|
int n2;
|
|
//--- check
|
|
if((CAp::Len(x)!=CAp::Len(y)))
|
|
{
|
|
Print("Error while calling 'spline1dconvdiff2cubic': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
boundltype=0;
|
|
boundl=0;
|
|
boundrtype=0;
|
|
boundr=0;
|
|
n2=CAp::Len(x2);
|
|
//--- function call
|
|
CSpline1D::Spline1DConvDiff2Cubic(x,y,n,boundltype,boundl,boundrtype,boundr,x2,n2,y2,d2,dd2);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine builds Catmull-Rom spline interpolant. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - spline nodes, array[0..N-1]. |
|
|
//| Y - function values, array[0..N-1]. |
|
|
//| OPTIONAL PARAMETERS: |
|
|
//| N - points count: |
|
|
//| * N>=2 |
|
|
//| * if given, only first N points are used to |
|
|
//| build spline |
|
|
//| * if not given, automatically detected from |
|
|
//| X/Y sizes (len(X) must be equal to len(Y)) |
|
|
//| BoundType - boundary condition type: |
|
|
//| * -1 for periodic boundary condition |
|
|
//| * 0 for parabolically terminated spline |
|
|
//| (default) |
|
|
//| Tension - tension parameter: |
|
|
//| * tension=0 corresponds to classic |
|
|
//| Catmull-Rom spline (default) |
|
|
//| * 0<tension<1 corresponds to more general |
|
|
//| form - cardinal spline |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| C - spline interpolant |
|
|
//| ORDER OF POINTS |
|
|
//| Subroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. |
|
|
//| PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: |
|
|
//| Problems with periodic boundary conditions have |
|
|
//| Y[first_point]=Y[last_point]. However, this subroutine doesn't |
|
|
//| require you to specify equal values for the first and last |
|
|
//| points - it automatically forces them to be equal by copying |
|
|
//| Y[first_point] (corresponds to the leftmost, minimal X[]) to |
|
|
//| Y[last_point]. However it is recommended to pass consistent |
|
|
//| values of Y[], i.e. to make Y[first_point]=Y[last_point]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DBuildCatmullRom(double &x[],double &y[],
|
|
const int n,const int boundtype,
|
|
const double tension,
|
|
CSpline1DInterpolantShell &c)
|
|
{
|
|
//--- function call
|
|
CSpline1D::Spline1DBuildCatmullRom(x,y,n,boundtype,tension,c.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine builds Catmull-Rom spline interpolant. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - spline nodes, array[0..N-1]. |
|
|
//| Y - function values, array[0..N-1]. |
|
|
//| OPTIONAL PARAMETERS: |
|
|
//| N - points count: |
|
|
//| * N>=2 |
|
|
//| * if given, only first N points are used to |
|
|
//| build spline |
|
|
//| * if not given, automatically detected from |
|
|
//| X/Y sizes (len(X) must be equal to len(Y)) |
|
|
//| BoundType - boundary condition type: |
|
|
//| * -1 for periodic boundary condition |
|
|
//| * 0 for parabolically terminated spline |
|
|
//| (default) |
|
|
//| Tension - tension parameter: |
|
|
//| * tension=0 corresponds to classic |
|
|
//| Catmull-Rom spline (default) |
|
|
//| * 0<tension<1 corresponds to more general |
|
|
//| form - cardinal spline |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| C - spline interpolant |
|
|
//| ORDER OF POINTS |
|
|
//| Subroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. |
|
|
//| PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS: |
|
|
//| Problems with periodic boundary conditions have |
|
|
//| Y[first_point]=Y[last_point]. However, this subroutine doesn't |
|
|
//| require you to specify equal values for the first and last |
|
|
//| points - it automatically forces them to be equal by copying |
|
|
//| Y[first_point] (corresponds to the leftmost, minimal X[]) to |
|
|
//| Y[last_point]. However it is recommended to pass consistent |
|
|
//| values of Y[], i.e. to make Y[first_point]=Y[last_point]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DBuildCatmullRom(double &x[],double &y[],
|
|
CSpline1DInterpolantShell &c)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
int boundtype;
|
|
double tension;
|
|
//--- check
|
|
if((CAp::Len(x)!=CAp::Len(y)))
|
|
{
|
|
Print("Error while calling 'spline1dbuildcatmullrom': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
boundtype=0;
|
|
tension=0;
|
|
//--- function call
|
|
CSpline1D::Spline1DBuildCatmullRom(x,y,n,boundtype,tension,c.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine builds Hermite spline interpolant. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - spline nodes, array[0..N-1] |
|
|
//| Y - function values, array[0..N-1] |
|
|
//| D - derivatives, array[0..N-1] |
|
|
//| N - points count (optional): |
|
|
//| * N>=2 |
|
|
//| * if given, only first N points are used to |
|
|
//| build spline |
|
|
//| * if not given, automatically detected from |
|
|
//| X/Y sizes (len(X) must be equal to len(Y)) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| C - spline interpolant. |
|
|
//| ORDER OF POINTS |
|
|
//| Subroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DBuildHermite(double &x[],double &y[],double &d[],
|
|
const int n,CSpline1DInterpolantShell &c)
|
|
{
|
|
//--- function call
|
|
CSpline1D::Spline1DBuildHermite(x,y,d,n,c.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine builds Hermite spline interpolant. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - spline nodes, array[0..N-1] |
|
|
//| Y - function values, array[0..N-1] |
|
|
//| D - derivatives, array[0..N-1] |
|
|
//| N - points count (optional): |
|
|
//| * N>=2 |
|
|
//| * if given, only first N points are used to |
|
|
//| build spline |
|
|
//| * if not given, automatically detected from |
|
|
//| X/Y sizes (len(X) must be equal to len(Y)) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| C - spline interpolant. |
|
|
//| ORDER OF POINTS |
|
|
//| Subroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DBuildHermite(double &x[],double &y[],double &d[],
|
|
CSpline1DInterpolantShell &c)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- check
|
|
if((CAp::Len(x)!=CAp::Len(y)) || (CAp::Len(x)!=CAp::Len(d)))
|
|
{
|
|
Print("Error while calling 'spline1dbuildhermite': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CSpline1D::Spline1DBuildHermite(x,y,d,n,c.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine builds Akima spline interpolant |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - spline nodes, array[0..N-1] |
|
|
//| Y - function values, array[0..N-1] |
|
|
//| N - points count (optional): |
|
|
//| * N>=5 |
|
|
//| * if given, only first N points are used to |
|
|
//| build spline |
|
|
//| * if not given, automatically detected from |
|
|
//| X/Y sizes (len(X) must be equal to len(Y)) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| C - spline interpolant |
|
|
//| ORDER OF POINTS |
|
|
//| Subroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DBuildAkima(double &x[],double &y[],const int n,
|
|
CSpline1DInterpolantShell &c)
|
|
{
|
|
//--- function call
|
|
CSpline1D::Spline1DBuildAkima(x,y,n,c.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine builds Akima spline interpolant |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - spline nodes, array[0..N-1] |
|
|
//| Y - function values, array[0..N-1] |
|
|
//| N - points count (optional): |
|
|
//| * N>=5 |
|
|
//| * if given, only first N points are used to |
|
|
//| build spline |
|
|
//| * if not given, automatically detected from |
|
|
//| X/Y sizes (len(X) must be equal to len(Y)) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| C - spline interpolant |
|
|
//| ORDER OF POINTS |
|
|
//| Subroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DBuildAkima(double &x[],double &y[],
|
|
CSpline1DInterpolantShell &c)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- check
|
|
if((CAp::Len(x)!=CAp::Len(y)))
|
|
{
|
|
Print("Error while calling 'spline1dbuildakima': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CSpline1D::Spline1DBuildAkima(x,y,n,c.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine calculates the value of the spline at the given |
|
|
//| point X. |
|
|
//| INPUT PARAMETERS: |
|
|
//| C - spline interpolant |
|
|
//| X - point |
|
|
//| Result: |
|
|
//| S(x) |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::Spline1DCalc(CSpline1DInterpolantShell &c,const double x)
|
|
{
|
|
//--- return result
|
|
return(CSpline1D::Spline1DCalc(c.GetInnerObj(),x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine differentiates the spline. |
|
|
//| INPUT PARAMETERS: |
|
|
//| C - spline interpolant. |
|
|
//| X - point |
|
|
//| Result: |
|
|
//| S - S(x) |
|
|
//| DS - S'(x) |
|
|
//| D2S - S''(x) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DDiff(CSpline1DInterpolantShell &c,const double x,
|
|
double &s,double &ds,double &d2s)
|
|
{
|
|
//--- initialization
|
|
s=0;
|
|
ds=0;
|
|
d2s=0;
|
|
//--- function call
|
|
CSpline1D::Spline1DDiff(c.GetInnerObj(),x,s,ds,d2s);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine unpacks the spline into the coefficients table. |
|
|
//| INPUT PARAMETERS: |
|
|
//| C - spline interpolant. |
|
|
//| X - point |
|
|
//| Result: |
|
|
//| Tbl - coefficients table, unpacked format, array[0..N-2, |
|
|
//| 0..5]. |
|
|
//| For I = 0...N-2: |
|
|
//| Tbl[I,0] = X[i] |
|
|
//| Tbl[I,1] = X[i+1] |
|
|
//| Tbl[I,2] = C0 |
|
|
//| Tbl[I,3] = C1 |
|
|
//| Tbl[I,4] = C2 |
|
|
//| Tbl[I,5] = C3 |
|
|
//| On [x[i], x[i+1]] spline is equals to: |
|
|
//| S(x) = C0 + C1*t + C2*t^2 + C3*t^3 |
|
|
//| t = x-x[i] |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DUnpack(CSpline1DInterpolantShell &c,int &n,
|
|
CMatrixDouble &tbl)
|
|
{
|
|
//--- initialization
|
|
n=0;
|
|
//--- function call
|
|
CSpline1D::Spline1DUnpack(c.GetInnerObj(),n,tbl);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine performs linear transformation of the spline |
|
|
//| argument. |
|
|
//| INPUT PARAMETERS: |
|
|
//| C - spline interpolant. |
|
|
//| A, B- transformation coefficients: x = A*t + B |
|
|
//| Result: |
|
|
//| C - transformed spline |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DLinTransX(CSpline1DInterpolantShell &c,
|
|
const double a,const double b)
|
|
{
|
|
//--- function call
|
|
CSpline1D::Spline1DLinTransX(c.GetInnerObj(),a,b);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine performs linear transformation of the spline. |
|
|
//| INPUT PARAMETERS: |
|
|
//| C - spline interpolant. |
|
|
//| A,B- transformation coefficients: S2(x)=A*S(x) + B |
|
|
//| Result: |
|
|
//| C - transformed spline |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DLinTransY(CSpline1DInterpolantShell &c,
|
|
const double a,const double b)
|
|
{
|
|
//--- function call
|
|
CSpline1D::Spline1DLinTransY(c.GetInnerObj(),a,b);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine integrates the spline. |
|
|
//| INPUT PARAMETERS: |
|
|
//| C - spline interpolant. |
|
|
//| X - right bound of the integration interval [a, x], |
|
|
//| here 'a' denotes min(x[]) |
|
|
//| Result: |
|
|
//| integral(S(t)dt,a,x) |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::Spline1DIntegrate(CSpline1DInterpolantShell &c,
|
|
const double x)
|
|
{
|
|
//--- return result
|
|
return(CSpline1D::Spline1DIntegrate(c.GetInnerObj(),x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Fitting by polynomials in barycentric form. This function |
|
|
//| provides simple unterface for unconstrained unweighted fitting. |
|
|
//| See PolynomialFitWC() if you need constrained fitting. |
|
|
//| Task is linear, so linear least squares solver is used. |
|
|
//| Complexity of this computational scheme is O(N*M^2), mostly |
|
|
//| dominated by least squares solver |
|
|
//| SEE ALSO: |
|
|
//| PolynomialFitWC() |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - points, array[0..N-1]. |
|
|
//| Y - function values, array[0..N-1]. |
|
|
//| N - number of points, N>0 |
|
|
//| * if given, only leading N elements of X/Y are used |
|
|
//| * if not given, automatically determined from sizes |
|
|
//| of X/Y |
|
|
//| M - number of basis functions (= polynomial_degree + 1), |
|
|
//| M>=1 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info- same format as in LSFitLinearW() subroutine: |
|
|
//| * Info>0 task is solved |
|
|
//| * Info<=0 an error occured: |
|
|
//| -4 means inconvergence of internal SVD |
|
|
//| P - interpolant in barycentric form. |
|
|
//| Rep - report, same format as in LSFitLinearW() subroutine. |
|
|
//| Following fields are set: |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the |
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE CALCULATED |
|
|
//| NOTES: |
|
|
//| you can convert P from barycentric form to the power or |
|
|
//| Chebyshev basis with PolynomialBar2Pow() or |
|
|
//| PolynomialBar2Cheb() functions from POLINT subpackage. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PolynomialFit(double &x[],double &y[],const int n,
|
|
const int m,int &info,CBarycentricInterpolantShell &p,
|
|
CPolynomialFitReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CLSFit::PolynomialFit(x,y,n,m,info,p.GetInnerObj(),rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Fitting by polynomials in barycentric form. This function |
|
|
//| provides simple unterface for unconstrained unweighted fitting. |
|
|
//| See PolynomialFitWC() if you need constrained fitting. |
|
|
//| Task is linear, so linear least squares solver is used. |
|
|
//| Complexity of this computational scheme is O(N*M^2), mostly |
|
|
//| dominated by least squares solver |
|
|
//| SEE ALSO: |
|
|
//| PolynomialFitWC() |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - points, array[0..N-1]. |
|
|
//| Y - function values, array[0..N-1]. |
|
|
//| N - number of points, N>0 |
|
|
//| * if given, only leading N elements of X/Y are used |
|
|
//| * if not given, automatically determined from sizes |
|
|
//| of X/Y |
|
|
//| M - number of basis functions (= polynomial_degree + 1), |
|
|
//| M>=1 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info- same format as in LSFitLinearW() subroutine: |
|
|
//| * Info>0 task is solved |
|
|
//| * Info<=0 an error occured: |
|
|
//| -4 means inconvergence of internal SVD |
|
|
//| P - interpolant in barycentric form. |
|
|
//| Rep - report, same format as in LSFitLinearW() subroutine. |
|
|
//| Following fields are set: |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the |
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE CALCULATED |
|
|
//| NOTES: |
|
|
//| you can convert P from barycentric form to the power or |
|
|
//| Chebyshev basis with PolynomialBar2Pow() or |
|
|
//| PolynomialBar2Cheb() functions from POLINT subpackage. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PolynomialFit(double &x[],double &y[],const int m,
|
|
int &info,CBarycentricInterpolantShell &p,
|
|
CPolynomialFitReportShell &rep)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- check
|
|
if((CAp::Len(x)!=CAp::Len(y)))
|
|
{
|
|
Print("Error while calling 'polynomialfit': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
info=0;
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CLSFit::PolynomialFit(x,y,n,m,info,p.GetInnerObj(),rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Weighted fitting by polynomials in barycentric form, with |
|
|
//| constraints on function values or first derivatives. |
|
|
//| Small regularizing term is used when solving constrained tasks |
|
|
//| (to improve stability). |
|
|
//| Task is linear, so linear least squares solver is used. |
|
|
//| Complexity of this computational scheme is O(N*M^2), mostly |
|
|
//| dominated by least squares solver |
|
|
//| SEE ALSO: |
|
|
//| PolynomialFit() |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - points, array[0..N-1]. |
|
|
//| Y - function values, array[0..N-1]. |
|
|
//| W - weights, array[0..N-1] |
|
|
//| Each summand in square sum of approximation |
|
|
//| deviations from given values is multiplied by the |
|
|
//| square of corresponding weight. Fill it by 1's if you|
|
|
//| don't want to solve weighted task. |
|
|
//| N - number of points, N>0. |
|
|
//| * if given, only leading N elements of X/Y/W are used|
|
|
//| * if not given, automatically determined from sizes |
|
|
//| of X/Y/W |
|
|
//| XC - points where polynomial values/derivatives are |
|
|
//| constrained, array[0..K-1]. |
|
|
//| YC - values of constraints, array[0..K-1] |
|
|
//| DC - array[0..K-1], types of constraints: |
|
|
//| * DC[i]=0 means that P(XC[i])=YC[i] |
|
|
//| * DC[i]=1 means that P'(XC[i])=YC[i] |
|
|
//| SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS |
|
|
//| K - number of constraints, 0<=K<M. |
|
|
//| K=0 means no constraints (XC/YC/DC are not used in |
|
|
//| such cases) |
|
|
//| M - number of basis functions (= polynomial_degree + 1), |
|
|
//| M>=1 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info- same format as in LSFitLinearW() subroutine: |
|
|
//| * Info>0 task is solved |
|
|
//| * Info<=0 an error occured: |
|
|
//| -4 means inconvergence of internal SVD |
|
|
//| -3 means inconsistent constraints |
|
|
//| P - interpolant in barycentric form. |
|
|
//| Rep - report, same format as in LSFitLinearW() subroutine. |
|
|
//| Following fields are set: |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the |
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE CALCULATED |
|
|
//| IMPORTANT: |
|
|
//| this subroitine doesn't calculate task's condition number |
|
|
//| for K<>0. |
|
|
//| NOTES: |
|
|
//| you can convert P from barycentric form to the power or |
|
|
//| Chebyshev basis with PolynomialBar2Pow() or |
|
|
//| PolynomialBar2Cheb() functions from POLINT subpackage. |
|
|
//| SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: |
|
|
//| Setting constraints can lead to undesired results, like |
|
|
//| ill-conditioned behavior, or inconsistency being detected. |
|
|
//| From the other side, it allows us to improve quality of the fit. |
|
|
//| Here we summarize our experience with constrained regression |
|
|
//| splines: |
|
|
//| * even simple constraints can be inconsistent, see Wikipedia |
|
|
//| article on this subject: |
|
|
//| http://en.wikipedia.org/wiki/Birkhoff_interpolation |
|
|
//| * the greater is M (given fixed constraints), the more chances |
|
|
//| that constraints will be consistent |
|
|
//| * in the general case, consistency of constraints is NOT |
|
|
//| GUARANTEED. |
|
|
//| * in the one special cases, however, we can guarantee |
|
|
//| consistency. This case is: M>1 and constraints on the |
|
|
//| function values (NOT DERIVATIVES) |
|
|
//| Our final recommendation is to use constraints WHEN AND ONLY when|
|
|
//| you can't solve your task without them. Anything beyond special |
|
|
//| cases given above is not guaranteed and may result in |
|
|
//| inconsistency. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PolynomialFitWC(double &x[],double &y[],double &w[],
|
|
const int n,double &xc[],double &yc[],
|
|
int &dc[],const int k,const int m,
|
|
int &info,CBarycentricInterpolantShell &p,
|
|
CPolynomialFitReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CLSFit::PolynomialFitWC(x,y,w,n,xc,yc,dc,k,m,info,p.GetInnerObj(),rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Weighted fitting by polynomials in barycentric form, with |
|
|
//| constraints on function values or first derivatives. |
|
|
//| Small regularizing term is used when solving constrained tasks |
|
|
//| (to improve stability). |
|
|
//| Task is linear, so linear least squares solver is used. |
|
|
//| Complexity of this computational scheme is O(N*M^2), mostly |
|
|
//| dominated by least squares solver |
|
|
//| SEE ALSO: |
|
|
//| PolynomialFit() |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - points, array[0..N-1]. |
|
|
//| Y - function values, array[0..N-1]. |
|
|
//| W - weights, array[0..N-1] |
|
|
//| Each summand in square sum of approximation |
|
|
//| deviations from given values is multiplied by the |
|
|
//| square of corresponding weight. Fill it by 1's if you|
|
|
//| don't want to solve weighted task. |
|
|
//| N - number of points, N>0. |
|
|
//| * if given, only leading N elements of X/Y/W are used|
|
|
//| * if not given, automatically determined from sizes |
|
|
//| of X/Y/W |
|
|
//| XC - points where polynomial values/derivatives are |
|
|
//| constrained, array[0..K-1]. |
|
|
//| YC - values of constraints, array[0..K-1] |
|
|
//| DC - array[0..K-1], types of constraints: |
|
|
//| * DC[i]=0 means that P(XC[i])=YC[i] |
|
|
//| * DC[i]=1 means that P'(XC[i])=YC[i] |
|
|
//| SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS |
|
|
//| K - number of constraints, 0<=K<M. |
|
|
//| K=0 means no constraints (XC/YC/DC are not used in |
|
|
//| such cases) |
|
|
//| M - number of basis functions (= polynomial_degree + 1), |
|
|
//| M>=1 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info- same format as in LSFitLinearW() subroutine: |
|
|
//| * Info>0 task is solved |
|
|
//| * Info<=0 an error occured: |
|
|
//| -4 means inconvergence of internal SVD |
|
|
//| -3 means inconsistent constraints |
|
|
//| P - interpolant in barycentric form. |
|
|
//| Rep - report, same format as in LSFitLinearW() subroutine. |
|
|
//| Following fields are set: |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the |
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE CALCULATED |
|
|
//| IMPORTANT: |
|
|
//| this subroitine doesn't calculate task's condition number |
|
|
//| for K<>0. |
|
|
//| NOTES: |
|
|
//| you can convert P from barycentric form to the power or |
|
|
//| Chebyshev basis with PolynomialBar2Pow() or |
|
|
//| PolynomialBar2Cheb() functions from POLINT subpackage. |
|
|
//| SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: |
|
|
//| Setting constraints can lead to undesired results, like |
|
|
//| ill-conditioned behavior, or inconsistency being detected. |
|
|
//| From the other side, it allows us to improve quality of the fit. |
|
|
//| Here we summarize our experience with constrained regression |
|
|
//| splines: |
|
|
//| * even simple constraints can be inconsistent, see Wikipedia |
|
|
//| article on this subject: |
|
|
//| http://en.wikipedia.org/wiki/Birkhoff_interpolation |
|
|
//| * the greater is M (given fixed constraints), the more chances |
|
|
//| that constraints will be consistent |
|
|
//| * in the general case, consistency of constraints is NOT |
|
|
//| GUARANTEED. |
|
|
//| * in the one special cases, however, we can guarantee |
|
|
//| consistency. This case is: M>1 and constraints on the |
|
|
//| function values (NOT DERIVATIVES) |
|
|
//| Our final recommendation is to use constraints WHEN AND ONLY when|
|
|
//| you can't solve your task without them. Anything beyond special |
|
|
//| cases given above is not guaranteed and may result in |
|
|
//| inconsistency. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PolynomialFitWC(double &x[],double &y[],double &w[],
|
|
double &xc[],double &yc[],int &dc[],
|
|
const int m,int &info,CBarycentricInterpolantShell &p,
|
|
CPolynomialFitReportShell &rep)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
int k;
|
|
//--- check
|
|
if((CAp::Len(x)!=CAp::Len(y)) || (CAp::Len(x)!=CAp::Len(w)))
|
|
{
|
|
Print("Error while calling 'polynomialfitwc': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- check
|
|
if((CAp::Len(xc)!=CAp::Len(yc)) || (CAp::Len(xc)!=CAp::Len(dc)))
|
|
{
|
|
Print("Error while calling 'polynomialfitwc': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
info=0;
|
|
n=CAp::Len(x);
|
|
k=CAp::Len(xc);
|
|
//--- function call
|
|
CLSFit::PolynomialFitWC(x,y,w,n,xc,yc,dc,k,m,info,p.GetInnerObj(),rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Weghted rational least squares fitting using Floater-Hormann |
|
|
//| rational functions with optimal D chosen from [0,9], with |
|
|
//| constraints and individual weights. |
|
|
//| Equidistant grid with M node on [min(x),max(x)] is used to build |
|
|
//| basis functions. Different values of D are tried, optimal D |
|
|
//| (least WEIGHTED root mean square error) is chosen. Task is |
|
|
//| linear, so linear least squares solver is used. Complexity of |
|
|
//| this computational scheme is O(N*M^2) (mostly dominated by the |
|
|
//| least squares solver). |
|
|
//| SEE ALSO |
|
|
//| * BarycentricFitFloaterHormann(), "lightweight" fitting without |
|
|
//| invididual weights and constraints. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - points, array[0..N-1]. |
|
|
//| Y - function values, array[0..N-1]. |
|
|
//| W - weights, array[0..N-1] |
|
|
//| Each summand in square sum of approximation |
|
|
//| deviations from given values is multiplied by the |
|
|
//| square of corresponding weight. Fill it by 1's if |
|
|
//| you don't want to solve weighted task. |
|
|
//| N - number of points, N>0. |
|
|
//| XC - points where function values/derivatives are |
|
|
//| constrained, array[0..K-1]. |
|
|
//| YC - values of constraints, array[0..K-1] |
|
|
//| DC - array[0..K-1], types of constraints: |
|
|
//| * DC[i]=0 means that S(XC[i])=YC[i] |
|
|
//| * DC[i]=1 means that S'(XC[i])=YC[i] |
|
|
//| SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS |
|
|
//| K - number of constraints, 0<=K<M. |
|
|
//| K=0 means no constraints (XC/YC/DC are not used in |
|
|
//| such cases) |
|
|
//| M - number of basis functions ( = number_of_nodes), |
|
|
//| M>=2. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info- same format as in LSFitLinearWC() subroutine. |
|
|
//| * Info>0 task is solved |
|
|
//| * Info<=0 an error occured: |
|
|
//| -4 means inconvergence of internal SVD |
|
|
//| -3 means inconsistent constraints |
|
|
//| -1 means another errors in parameters |
|
|
//| passed (N<=0, for example) |
|
|
//| B - barycentric interpolant. |
|
|
//| Rep - report, same format as in LSFitLinearWC() subroutine.|
|
|
//| Following fields are set: |
|
|
//| * DBest best value of the D parameter |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the |
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE CALCULATED |
|
|
//| IMPORTANT: |
|
|
//| this subroutine doesn't calculate task's condition number |
|
|
//| for K<>0. |
|
|
//| SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: |
|
|
//| Setting constraints can lead to undesired results, like |
|
|
//| ill-conditioned behavior, or inconsistency being detected. From |
|
|
//| the other side, it allows us to improve quality of the fit. Here |
|
|
//| we summarize our experience with constrained barycentric |
|
|
//| interpolants: |
|
|
//| * excessive constraints can be inconsistent. Floater-Hormann |
|
|
//| basis functions aren't as flexible as splines (although they |
|
|
//| are very smooth). |
|
|
//| * the more evenly constraints are spread across [min(x),max(x)], |
|
|
//| the more chances that they will be consistent |
|
|
//| * the greater is M (given fixed constraints), the more chances |
|
|
//| that constraints will be consistent |
|
|
//| * in the general case, consistency of constraints IS NOT |
|
|
//| GUARANTEED. |
|
|
//| * in the several special cases, however, we CAN guarantee |
|
|
//| consistency. |
|
|
//| * one of this cases is constraints on the function VALUES at the |
|
|
//| interval boundaries. Note that consustency of the constraints |
|
|
//| on the function DERIVATIVES is NOT guaranteed (you can use in |
|
|
//| such cases cubic splines which are more flexible). |
|
|
//| * another special case is ONE constraint on the function value |
|
|
//| (OR, but not AND, derivative) anywhere in the interval |
|
|
//| Our final recommendation is to use constraints WHEN AND ONLY |
|
|
//| WHEN you can't solve your task without them. Anything beyond |
|
|
//| special cases given above is not guaranteed and may result in |
|
|
//| inconsistency. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::BarycentricFitFloaterHormannWC(double &x[],double &y[],
|
|
double &w[],const int n,
|
|
double &xc[],double &yc[],
|
|
int &dc[],const int k,
|
|
const int m,int &info,
|
|
CBarycentricInterpolantShell &b,
|
|
CBarycentricFitReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CLSFit::BarycentricFitFloaterHormannWC(x,y,w,n,xc,yc,dc,k,m,info,b.GetInnerObj(),rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Rational least squares fitting using Floater-Hormann rational |
|
|
//| functions with optimal D chosen from [0,9]. |
|
|
//| Equidistant grid with M node on [min(x),max(x)] is used to build |
|
|
//| basis functions. Different values of D are tried, optimal D |
|
|
//| (least root mean square error) is chosen. Task is linear, so |
|
|
//| linear least squares solver is used. Complexity of this |
|
|
//| computational scheme is O(N*M^2) (mostly dominated by the least |
|
|
//| squares solver). |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - points, array[0..N-1]. |
|
|
//| Y - function values, array[0..N-1]. |
|
|
//| N - number of points, N>0. |
|
|
//| M - number of basis functions ( = number_of_nodes), M>=2.|
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info- same format as in LSFitLinearWC() subroutine. |
|
|
//| * Info>0 task is solved |
|
|
//| * Info<=0 an error occured: |
|
|
//| -4 means inconvergence of internal SVD |
|
|
//| -3 means inconsistent constraints |
|
|
//| B - barycentric interpolant. |
|
|
//| Rep - report, same format as in LSFitLinearWC() subroutine.|
|
|
//| Following fields are set: |
|
|
//| * DBest best value of the D parameter |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the |
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE CALCULATED |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::BarycentricFitFloaterHormann(double &x[],double &y[],
|
|
const int n,const int m,
|
|
int &info,CBarycentricInterpolantShell &b,
|
|
CBarycentricFitReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CLSFit::BarycentricFitFloaterHormann(x,y,n,m,info,b.GetInnerObj(),rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Rational least squares fitting using Floater-Hormann rational |
|
|
//| functions with optimal D chosen from [0,9]. |
|
|
//| Equidistant grid with M node on [min(x),max(x)] is used to build |
|
|
//| basis functions. Different values of D are tried, optimal D |
|
|
//| (least root mean square error) is chosen. Task is linear, so |
|
|
//| linear least squares solver is used. Complexity of this |
|
|
//| computational scheme is O(N*M^2) (mostly dominated by the least |
|
|
//| squares solver). |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - points, array[0..N-1]. |
|
|
//| Y - function values, array[0..N-1]. |
|
|
//| N - number of points, N>0. |
|
|
//| M - number of basis functions ( = number_of_nodes), M>=2.|
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info- same format as in LSFitLinearWC() subroutine. |
|
|
//| * Info>0 task is solved |
|
|
//| * Info<=0 an error occured: |
|
|
//| -4 means inconvergence of internal SVD |
|
|
//| -3 means inconsistent constraints |
|
|
//| B - barycentric interpolant. |
|
|
//| Rep - report, same format as in LSFitLinearWC() subroutine.|
|
|
//| Following fields are set: |
|
|
//| * DBest best value of the D parameter |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the |
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE CALCULATED |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DFitPenalized(double &x[],double &y[],const int n,
|
|
const int m,const double rho,int &info,
|
|
CSpline1DInterpolantShell &s,
|
|
CSpline1DFitReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CLSFit::Spline1DFitPenalized(x,y,n,m,rho,info,s.GetInnerObj(),rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Rational least squares fitting using Floater-Hormann rational |
|
|
//| functions with optimal D chosen from [0,9]. |
|
|
//| Equidistant grid with M node on [min(x),max(x)] is used to build |
|
|
//| basis functions. Different values of D are tried, optimal D |
|
|
//| (least root mean square error) is chosen. Task is linear, so |
|
|
//| linear least squares solver is used. Complexity of this |
|
|
//| computational scheme is O(N*M^2) (mostly dominated by the least |
|
|
//| squares solver). |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - points, array[0..N-1]. |
|
|
//| Y - function values, array[0..N-1]. |
|
|
//| N - number of points, N>0. |
|
|
//| M - number of basis functions ( = number_of_nodes), M>=2.|
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info- same format as in LSFitLinearWC() subroutine. |
|
|
//| * Info>0 task is solved |
|
|
//| * Info<=0 an error occured: |
|
|
//| -4 means inconvergence of internal SVD |
|
|
//| -3 means inconsistent constraints |
|
|
//| B - barycentric interpolant. |
|
|
//| Rep - report, same format as in LSFitLinearWC() subroutine.|
|
|
//| Following fields are set: |
|
|
//| * DBest best value of the D parameter |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the |
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE CALCULATED |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DFitPenalized(double &x[],double &y[],const int m,
|
|
const double rho,int &info,
|
|
CSpline1DInterpolantShell &s,
|
|
CSpline1DFitReportShell &rep)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- check
|
|
if((CAp::Len(x)!=CAp::Len(y)))
|
|
{
|
|
Print("Error while calling 'spline1dfitpenalized': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
info=0;
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CLSFit::Spline1DFitPenalized(x,y,n,m,rho,info,s.GetInnerObj(),rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Weighted fitting by penalized cubic spline. |
|
|
//| Equidistant grid with M nodes on [min(x,xc),max(x,xc)] is used to|
|
|
//| build basis functions. Basis functions are cubic splines with |
|
|
//| natural boundary conditions. Problem is regularized by adding |
|
|
//| non-linearity penalty to the usual least squares penalty |
|
|
//| function: |
|
|
//| S(x) = arg min { LS + P }, where |
|
|
//| LS = SUM { w[i]^2*(y[i] - S(x[i]))^2 } - least squares |
|
|
//| penalty |
|
|
//| P = C*10^rho*integral{ S''(x)^2*dx } - non-linearity |
|
|
//| penalty |
|
|
//| rho - tunable constant given by user |
|
|
//| C - automatically determined scale parameter, |
|
|
//| makes penalty invariant with respect to scaling of X, |
|
|
//| Y, W. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - points, array[0..N-1]. |
|
|
//| Y - function values, array[0..N-1]. |
|
|
//| W - weights, array[0..N-1] |
|
|
//| Each summand in square sum of approximation |
|
|
//| deviations from given values is multiplied by the |
|
|
//| square of corresponding weight. Fill it by 1's if |
|
|
//| you don't want to solve weighted problem. |
|
|
//| N - number of points (optional): |
|
|
//| * N>0 |
|
|
//| * if given, only first N elements of X/Y/W are |
|
|
//| processed |
|
|
//| * if not given, automatically determined from X/Y/W |
|
|
//| sizes |
|
|
//| M - number of basis functions ( = number_of_nodes), M>=4.|
|
|
//| Rho - regularization constant passed by user. It penalizes |
|
|
//| nonlinearity in the regression spline. It is |
|
|
//| logarithmically scaled, i.e. actual value of |
|
|
//| regularization constant is calculated as 10^Rho. It |
|
|
//| is automatically scaled so that: |
|
|
//| * Rho=2.0 corresponds to moderate amount of |
|
|
//| nonlinearity |
|
|
//| * generally, it should be somewhere in the |
|
|
//| [-8.0,+8.0] |
|
|
//| If you do not want to penalize nonlineary, |
|
|
//| pass small Rho. Values as low as -15 should work. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info- same format as in LSFitLinearWC() subroutine. |
|
|
//| * Info>0 task is solved |
|
|
//| * Info<=0 an error occured: |
|
|
//| -4 means inconvergence of internal SVD |
|
|
//| or Cholesky decomposition; problem |
|
|
//| may be too ill-conditioned (very |
|
|
//| rare) |
|
|
//| S - spline interpolant. |
|
|
//| Rep - Following fields are set: |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the |
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE CALCULATED |
|
|
//| IMPORTANT: |
|
|
//| this subroitine doesn't calculate task's condition number |
|
|
//| for K<>0. |
|
|
//| NOTE 1: additional nodes are added to the spline outside of the |
|
|
//| fitting interval to force linearity when x<min(x,xc) or |
|
|
//| x>max(x,xc). It is done for consistency - we penalize |
|
|
//| non-linearity at [min(x,xc),max(x,xc)], so it is natural to |
|
|
//| force linearity outside of this interval. |
|
|
//| NOTE 2: function automatically sorts points, so caller may pass |
|
|
//| unsorted array. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DFitPenalizedW(double &x[],double &y[],
|
|
double &w[],const int n,
|
|
const int m,const double rho,
|
|
int &info,CSpline1DInterpolantShell &s,
|
|
CSpline1DFitReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CLSFit::Spline1DFitPenalizedW(x,y,w,n,m,rho,info,s.GetInnerObj(),rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Weighted fitting by penalized cubic spline. |
|
|
//| Equidistant grid with M nodes on [min(x,xc),max(x,xc)] is used to|
|
|
//| build basis functions. Basis functions are cubic splines with |
|
|
//| natural boundary conditions. Problem is regularized by adding |
|
|
//| non-linearity penalty to the usual least squares penalty |
|
|
//| function: |
|
|
//| S(x) = arg min { LS + P }, where |
|
|
//| LS = SUM { w[i]^2*(y[i] - S(x[i]))^2 } - least squares |
|
|
//| penalty |
|
|
//| P = C*10^rho*integral{ S''(x)^2*dx } - non-linearity |
|
|
//| penalty |
|
|
//| rho - tunable constant given by user |
|
|
//| C - automatically determined scale parameter, |
|
|
//| makes penalty invariant with respect to scaling of X, |
|
|
//| Y, W. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - points, array[0..N-1]. |
|
|
//| Y - function values, array[0..N-1]. |
|
|
//| W - weights, array[0..N-1] |
|
|
//| Each summand in square sum of approximation |
|
|
//| deviations from given values is multiplied by the |
|
|
//| square of corresponding weight. Fill it by 1's if |
|
|
//| you don't want to solve weighted problem. |
|
|
//| N - number of points (optional): |
|
|
//| * N>0 |
|
|
//| * if given, only first N elements of X/Y/W are |
|
|
//| processed |
|
|
//| * if not given, automatically determined from X/Y/W |
|
|
//| sizes |
|
|
//| M - number of basis functions ( = number_of_nodes), M>=4.|
|
|
//| Rho - regularization constant passed by user. It penalizes |
|
|
//| nonlinearity in the regression spline. It is |
|
|
//| logarithmically scaled, i.e. actual value of |
|
|
//| regularization constant is calculated as 10^Rho. It |
|
|
//| is automatically scaled so that: |
|
|
//| * Rho=2.0 corresponds to moderate amount of |
|
|
//| nonlinearity |
|
|
//| * generally, it should be somewhere in the |
|
|
//| [-8.0,+8.0] |
|
|
//| If you do not want to penalize nonlineary, |
|
|
//| pass small Rho. Values as low as -15 should work. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info- same format as in LSFitLinearWC() subroutine. |
|
|
//| * Info>0 task is solved |
|
|
//| * Info<=0 an error occured: |
|
|
//| -4 means inconvergence of internal SVD |
|
|
//| or Cholesky decomposition; problem |
|
|
//| may be too ill-conditioned (very |
|
|
//| rare) |
|
|
//| S - spline interpolant. |
|
|
//| Rep - Following fields are set: |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the |
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE CALCULATED |
|
|
//| IMPORTANT: |
|
|
//| this subroitine doesn't calculate task's condition number |
|
|
//| for K<>0. |
|
|
//| NOTE 1: additional nodes are added to the spline outside of the |
|
|
//| fitting interval to force linearity when x<min(x,xc) or |
|
|
//| x>max(x,xc). It is done for consistency - we penalize |
|
|
//| non-linearity at [min(x,xc),max(x,xc)], so it is natural to |
|
|
//| force linearity outside of this interval. |
|
|
//| NOTE 2: function automatically sorts points, so caller may pass |
|
|
//| unsorted array. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DFitPenalizedW(double &x[],double &y[],
|
|
double &w[],const int m,
|
|
const double rho,int &info,
|
|
CSpline1DInterpolantShell &s,
|
|
CSpline1DFitReportShell &rep)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- check
|
|
if((CAp::Len(x)!=CAp::Len(y)) || (CAp::Len(x)!=CAp::Len(w)))
|
|
{
|
|
Print("Error while calling 'spline1dfitpenalizedw': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
info=0;
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CLSFit::Spline1DFitPenalizedW(x,y,w,n,m,rho,info,s.GetInnerObj(),rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Weighted fitting by cubic spline, with constraints on function |
|
|
//| values or derivatives. |
|
|
//| Equidistant grid with M-2 nodes on [min(x,xc),max(x,xc)] is used |
|
|
//| to build basis functions. Basis functions are cubic splines with |
|
|
//| continuous second derivatives and non-fixed first derivatives at |
|
|
//| interval ends. Small regularizing term is used when solving |
|
|
//| constrained tasks (to improve stability). |
|
|
//| Task is linear, so linear least squares solver is used. |
|
|
//| Complexity of this computational scheme is O(N*M^2), mostly |
|
|
//| dominated by least squares solver |
|
|
//| SEE ALSO |
|
|
//| Spline1DFitHermiteWC() - fitting by Hermite splines (more |
|
|
//| flexible, less smooth) |
|
|
//| Spline1DFitCubic() - "lightweight" fitting by cubic |
|
|
//| splines, without invididual |
|
|
//| weights and constraints |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - points, array[0..N-1]. |
|
|
//| Y - function values, array[0..N-1]. |
|
|
//| W - weights, array[0..N-1] |
|
|
//| Each summand in square sum of approximation |
|
|
//| deviations from given values is multiplied by the |
|
|
//| square of corresponding weight. Fill it by 1's if you|
|
|
//| don't want to solve weighted task. |
|
|
//| N - number of points (optional): |
|
|
//| * N>0 |
|
|
//| * if given, only first N elements of X/Y/W are |
|
|
//| processed |
|
|
//| * if not given, automatically determined from X/Y/W |
|
|
//| sizes |
|
|
//| XC - points where spline values/derivatives are |
|
|
//| constrained, array[0..K-1]. |
|
|
//| YC - values of constraints, array[0..K-1] |
|
|
//| DC - array[0..K-1], types of constraints: |
|
|
//| * DC[i]=0 means that S(XC[i])=YC[i] |
|
|
//| * DC[i]=1 means that S'(XC[i])=YC[i] |
|
|
//| SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS |
|
|
//| K - number of constraints (optional): |
|
|
//| * 0<=K<M. |
|
|
//| * K=0 means no constraints (XC/YC/DC are not used) |
|
|
//| * if given, only first K elements of XC/YC/DC are |
|
|
//| used |
|
|
//| * if not given, automatically determined from |
|
|
//| XC/YC/DC |
|
|
//| M - number of basis functions ( = number_of_nodes+2), |
|
|
//| M>=4. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info- same format as in LSFitLinearWC() subroutine. |
|
|
//| * Info>0 task is solved |
|
|
//| * Info<=0 an error occured: |
|
|
//| -4 means inconvergence of internal SVD |
|
|
//| -3 means inconsistent constraints |
|
|
//| S - spline interpolant. |
|
|
//| Rep - report, same format as in LSFitLinearWC() subroutine.|
|
|
//| Following fields are set: |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the |
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE CALCULATED |
|
|
//| IMPORTANT: |
|
|
//| this subroitine doesn't calculate task's condition number |
|
|
//| for K<>0. |
|
|
//| ORDER OF POINTS |
|
|
//| Subroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. |
|
|
//| SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: |
|
|
//| Setting constraints can lead to undesired results, like |
|
|
//| ill-conditioned behavior, or inconsistency being detected. From |
|
|
//| the other side, it allows us to improve quality of the fit. |
|
|
//| Here we summarize our experience with constrained regression |
|
|
//| splines: |
|
|
//| * excessive constraints can be inconsistent. Splines are |
|
|
//| piecewise cubic functions, and it is easy to create an |
|
|
//| example, where large number of constraints concentrated in |
|
|
//| small area will result in inconsistency. Just because spline |
|
|
//| is not flexible enough to satisfy all of them. And same |
|
|
//| constraints spread across the [min(x),max(x)] will be |
|
|
//| perfectly consistent. |
|
|
//| * the more evenly constraints are spread across [min(x),max(x)], |
|
|
//| the more chances that they will be consistent |
|
|
//| * the greater is M (given fixed constraints), the more chances |
|
|
//| that constraints will be consistent |
|
|
//| * in the general case, consistency of constraints IS NOT |
|
|
//| GUARANTEED. |
|
|
//| * in the several special cases, however, we CAN guarantee |
|
|
//| consistency. |
|
|
//| * one of this cases is constraints on the function values |
|
|
//| AND/OR its derivatives at the interval boundaries. |
|
|
//| * another special case is ONE constraint on the function value |
|
|
//| (OR, but not AND, derivative) anywhere in the interval |
|
|
//| Our final recommendation is to use constraints WHEN AND ONLY WHEN|
|
|
//| you can't solve your task without them. Anything beyond special |
|
|
//| cases given above is not guaranteed and may result in |
|
|
//| inconsistency. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DFitCubicWC(double &x[],double &y[],double &w[],
|
|
const int n,double &xc[],double &yc[],
|
|
int &dc[],const int k,const int m,
|
|
int &info,CSpline1DInterpolantShell &s,
|
|
CSpline1DFitReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CLSFit::Spline1DFitCubicWC(x,y,w,n,xc,yc,dc,k,m,info,s.GetInnerObj(),rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Weighted fitting by cubic spline, with constraints on function |
|
|
//| values or derivatives. |
|
|
//| Equidistant grid with M-2 nodes on [min(x,xc),max(x,xc)] is used |
|
|
//| to build basis functions. Basis functions are cubic splines with |
|
|
//| continuous second derivatives and non-fixed first derivatives at |
|
|
//| interval ends. Small regularizing term is used when solving |
|
|
//| constrained tasks (to improve stability). |
|
|
//| Task is linear, so linear least squares solver is used. |
|
|
//| Complexity of this computational scheme is O(N*M^2), mostly |
|
|
//| dominated by least squares solver |
|
|
//| SEE ALSO |
|
|
//| Spline1DFitHermiteWC() - fitting by Hermite splines (more |
|
|
//| flexible, less smooth) |
|
|
//| Spline1DFitCubic() - "lightweight" fitting by cubic |
|
|
//| splines, without invididual |
|
|
//| weights and constraints |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - points, array[0..N-1]. |
|
|
//| Y - function values, array[0..N-1]. |
|
|
//| W - weights, array[0..N-1] |
|
|
//| Each summand in square sum of approximation |
|
|
//| deviations from given values is multiplied by the |
|
|
//| square of corresponding weight. Fill it by 1's if you|
|
|
//| don't want to solve weighted task. |
|
|
//| N - number of points (optional): |
|
|
//| * N>0 |
|
|
//| * if given, only first N elements of X/Y/W are |
|
|
//| processed |
|
|
//| * if not given, automatically determined from X/Y/W |
|
|
//| sizes |
|
|
//| XC - points where spline values/derivatives are |
|
|
//| constrained, array[0..K-1]. |
|
|
//| YC - values of constraints, array[0..K-1] |
|
|
//| DC - array[0..K-1], types of constraints: |
|
|
//| * DC[i]=0 means that S(XC[i])=YC[i] |
|
|
//| * DC[i]=1 means that S'(XC[i])=YC[i] |
|
|
//| SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS |
|
|
//| K - number of constraints (optional): |
|
|
//| * 0<=K<M. |
|
|
//| * K=0 means no constraints (XC/YC/DC are not used) |
|
|
//| * if given, only first K elements of XC/YC/DC are |
|
|
//| used |
|
|
//| * if not given, automatically determined from |
|
|
//| XC/YC/DC |
|
|
//| M - number of basis functions ( = number_of_nodes+2), |
|
|
//| M>=4. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info- same format as in LSFitLinearWC() subroutine. |
|
|
//| * Info>0 task is solved |
|
|
//| * Info<=0 an error occured: |
|
|
//| -4 means inconvergence of internal SVD |
|
|
//| -3 means inconsistent constraints |
|
|
//| S - spline interpolant. |
|
|
//| Rep - report, same format as in LSFitLinearWC() subroutine.|
|
|
//| Following fields are set: |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the |
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE CALCULATED |
|
|
//| IMPORTANT: |
|
|
//| this subroitine doesn't calculate task's condition number |
|
|
//| for K<>0. |
|
|
//| ORDER OF POINTS |
|
|
//| Subroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. |
|
|
//| SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: |
|
|
//| Setting constraints can lead to undesired results, like |
|
|
//| ill-conditioned behavior, or inconsistency being detected. From |
|
|
//| the other side, it allows us to improve quality of the fit. |
|
|
//| Here we summarize our experience with constrained regression |
|
|
//| splines: |
|
|
//| * excessive constraints can be inconsistent. Splines are |
|
|
//| piecewise cubic functions, and it is easy to create an |
|
|
//| example, where large number of constraints concentrated in |
|
|
//| small area will result in inconsistency. Just because spline |
|
|
//| is not flexible enough to satisfy all of them. And same |
|
|
//| constraints spread across the [min(x),max(x)] will be |
|
|
//| perfectly consistent. |
|
|
//| * the more evenly constraints are spread across [min(x),max(x)], |
|
|
//| the more chances that they will be consistent |
|
|
//| * the greater is M (given fixed constraints), the more chances |
|
|
//| that constraints will be consistent |
|
|
//| * in the general case, consistency of constraints IS NOT |
|
|
//| GUARANTEED. |
|
|
//| * in the several special cases, however, we CAN guarantee |
|
|
//| consistency. |
|
|
//| * one of this cases is constraints on the function values |
|
|
//| AND/OR its derivatives at the interval boundaries. |
|
|
//| * another special case is ONE constraint on the function value |
|
|
//| (OR, but not AND, derivative) anywhere in the interval |
|
|
//| Our final recommendation is to use constraints WHEN AND ONLY WHEN|
|
|
//| you can't solve your task without them. Anything beyond special |
|
|
//| cases given above is not guaranteed and may result in |
|
|
//| inconsistency. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DFitCubicWC(double &x[],double &y[],double &w[],
|
|
double &xc[],double &yc[],int &dc[],
|
|
const int m,int &info,CSpline1DInterpolantShell &s,
|
|
CSpline1DFitReportShell &rep)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
int k;
|
|
//--- check
|
|
if((CAp::Len(x)!=CAp::Len(y)) || (CAp::Len(x)!=CAp::Len(w)))
|
|
{
|
|
Print("Error while calling 'spline1dfitcubicwc': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- check
|
|
if((CAp::Len(xc)!=CAp::Len(yc)) || (CAp::Len(xc)!=CAp::Len(dc)))
|
|
{
|
|
Print("Error while calling 'spline1dfitcubicwc': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
info=0;
|
|
n=CAp::Len(x);
|
|
k=CAp::Len(xc);
|
|
//--- function call
|
|
CLSFit::Spline1DFitCubicWC(x,y,w,n,xc,yc,dc,k,m,info,s.GetInnerObj(),rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Weighted fitting by Hermite spline, with constraints on function |
|
|
//| values or first derivatives. |
|
|
//| Equidistant grid with M nodes on [min(x,xc),max(x,xc)] is used to|
|
|
//| build basis functions. Basis functions are Hermite splines. Small|
|
|
//| regularizing term is used when solving constrained tasks (to |
|
|
//| improve stability). |
|
|
//| Task is linear, so linear least squares solver is used. |
|
|
//| Complexity of this computational scheme is O(N*M^2), mostly |
|
|
//| dominated by least squares solver |
|
|
//| SEE ALSO |
|
|
//| Spline1DFitCubicWC() - fitting by Cubic splines (less |
|
|
//| flexible, more smooth) |
|
|
//| Spline1DFitHermite() - "lightweight" Hermite fitting, |
|
|
//| without invididual weights and |
|
|
//| constraints |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - points, array[0..N-1]. |
|
|
//| Y - function values, array[0..N-1]. |
|
|
//| W - weights, array[0..N-1] |
|
|
//| Each summand in square sum of approximation |
|
|
//| deviations from given values is multiplied by the |
|
|
//| square of corresponding weight. Fill it by 1's if |
|
|
//| you don't want to solve weighted task. |
|
|
//| N - number of points (optional): |
|
|
//| * N>0 |
|
|
//| * if given, only first N elements of X/Y/W are |
|
|
//| processed |
|
|
//| * if not given, automatically determined from X/Y/W |
|
|
//| sizes |
|
|
//| XC - points where spline values/derivatives are |
|
|
//| constrained, array[0..K-1]. |
|
|
//| YC - values of constraints, array[0..K-1] |
|
|
//| DC - array[0..K-1], types of constraints: |
|
|
//| * DC[i]=0 means that S(XC[i])=YC[i] |
|
|
//| * DC[i]=1 means that S'(XC[i])=YC[i] |
|
|
//| SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS |
|
|
//| K - number of constraints (optional): |
|
|
//| * 0<=K<M. |
|
|
//| * K=0 means no constraints (XC/YC/DC are not used) |
|
|
//| * if given, only first K elements of XC/YC/DC are |
|
|
//| used |
|
|
//| * if not given, automatically determined from |
|
|
//| XC/YC/DC |
|
|
//| M - number of basis functions (= 2 * number of nodes), |
|
|
//| M>=4, |
|
|
//| M IS EVEN! |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info- same format as in LSFitLinearW() subroutine: |
|
|
//| * Info>0 task is solved |
|
|
//| * Info<=0 an error occured: |
|
|
//| -4 means inconvergence of internal SVD |
|
|
//| -3 means inconsistent constraints |
|
|
//| -2 means odd M was passed (which is not |
|
|
//| supported) |
|
|
//| -1 means another errors in parameters |
|
|
//| passed (N<=0, for example) |
|
|
//| S - spline interpolant. |
|
|
//| Rep - report, same format as in LSFitLinearW() subroutine. |
|
|
//| Following fields are set: |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the |
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE CALCULATED |
|
|
//| IMPORTANT: |
|
|
//| this subroitine doesn't calculate task's condition number |
|
|
//| for K<>0. |
|
|
//| IMPORTANT: |
|
|
//| this subroitine supports only even M's |
|
|
//| ORDER OF POINTS |
|
|
//| ubroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. |
|
|
//| SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: |
|
|
//| Setting constraints can lead to undesired results, like |
|
|
//| ill-conditioned behavior, or inconsistency being detected. From |
|
|
//| the other side, it allows us to improve quality of the fit. Here |
|
|
//| we summarize our experience with constrained regression splines:|
|
|
//| * excessive constraints can be inconsistent. Splines are |
|
|
//| piecewise cubic functions, and it is easy to create an example,|
|
|
//| where large number of constraints concentrated in small area |
|
|
//| will result in inconsistency. Just because spline is not |
|
|
//| flexible enough to satisfy all of them. And same constraints |
|
|
//| spread across the [min(x),max(x)] will be perfectly consistent.|
|
|
//| * the more evenly constraints are spread across [min(x),max(x)], |
|
|
//| the more chances that they will be consistent |
|
|
//| * the greater is M (given fixed constraints), the more chances |
|
|
//| that constraints will be consistent |
|
|
//| * in the general case, consistency of constraints is NOT |
|
|
//| GUARANTEED. |
|
|
//| * in the several special cases, however, we can guarantee |
|
|
//| consistency. |
|
|
//| * one of this cases is M>=4 and constraints on the function |
|
|
//| value (AND/OR its derivative) at the interval boundaries. |
|
|
//| * another special case is M>=4 and ONE constraint on the |
|
|
//| function value (OR, BUT NOT AND, derivative) anywhere in |
|
|
//| [min(x),max(x)] |
|
|
//| Our final recommendation is to use constraints WHEN AND ONLY when|
|
|
//| you can't solve your task without them. Anything beyond special |
|
|
//| cases given above is not guaranteed and may result in |
|
|
//| inconsistency. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DFitHermiteWC(double &x[],double &y[],double &w[],
|
|
const int n,double &xc[],double &yc[],
|
|
int &dc[],const int k,const int m,
|
|
int &info,CSpline1DInterpolantShell &s,
|
|
CSpline1DFitReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CLSFit::Spline1DFitHermiteWC(x,y,w,n,xc,yc,dc,k,m,info,s.GetInnerObj(),rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Weighted fitting by Hermite spline, with constraints on function |
|
|
//| values or first derivatives. |
|
|
//| Equidistant grid with M nodes on [min(x,xc),max(x,xc)] is used to|
|
|
//| build basis functions. Basis functions are Hermite splines. Small|
|
|
//| regularizing term is used when solving constrained tasks (to |
|
|
//| improve stability). |
|
|
//| Task is linear, so linear least squares solver is used. |
|
|
//| Complexity of this computational scheme is O(N*M^2), mostly |
|
|
//| dominated by least squares solver |
|
|
//| SEE ALSO |
|
|
//| Spline1DFitCubicWC() - fitting by Cubic splines (less |
|
|
//| flexible, more smooth) |
|
|
//| Spline1DFitHermite() - "lightweight" Hermite fitting, |
|
|
//| without invididual weights and |
|
|
//| constraints |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - points, array[0..N-1]. |
|
|
//| Y - function values, array[0..N-1]. |
|
|
//| W - weights, array[0..N-1] |
|
|
//| Each summand in square sum of approximation |
|
|
//| deviations from given values is multiplied by the |
|
|
//| square of corresponding weight. Fill it by 1's if |
|
|
//| you don't want to solve weighted task. |
|
|
//| N - number of points (optional): |
|
|
//| * N>0 |
|
|
//| * if given, only first N elements of X/Y/W are |
|
|
//| processed |
|
|
//| * if not given, automatically determined from X/Y/W |
|
|
//| sizes |
|
|
//| XC - points where spline values/derivatives are |
|
|
//| constrained, array[0..K-1]. |
|
|
//| YC - values of constraints, array[0..K-1] |
|
|
//| DC - array[0..K-1], types of constraints: |
|
|
//| * DC[i]=0 means that S(XC[i])=YC[i] |
|
|
//| * DC[i]=1 means that S'(XC[i])=YC[i] |
|
|
//| SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS |
|
|
//| K - number of constraints (optional): |
|
|
//| * 0<=K<M. |
|
|
//| * K=0 means no constraints (XC/YC/DC are not used) |
|
|
//| * if given, only first K elements of XC/YC/DC are |
|
|
//| used |
|
|
//| * if not given, automatically determined from |
|
|
//| XC/YC/DC |
|
|
//| M - number of basis functions (= 2 * number of nodes), |
|
|
//| M>=4, |
|
|
//| M IS EVEN! |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info- same format as in LSFitLinearW() subroutine: |
|
|
//| * Info>0 task is solved |
|
|
//| * Info<=0 an error occured: |
|
|
//| -4 means inconvergence of internal SVD |
|
|
//| -3 means inconsistent constraints |
|
|
//| -2 means odd M was passed (which is not |
|
|
//| supported) |
|
|
//| -1 means another errors in parameters |
|
|
//| passed (N<=0, for example) |
|
|
//| S - spline interpolant. |
|
|
//| Rep - report, same format as in LSFitLinearW() subroutine. |
|
|
//| Following fields are set: |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the |
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE CALCULATED |
|
|
//| IMPORTANT: |
|
|
//| this subroitine doesn't calculate task's condition number |
|
|
//| for K<>0. |
|
|
//| IMPORTANT: |
|
|
//| this subroitine supports only even M's |
|
|
//| ORDER OF POINTS |
|
|
//| ubroutine automatically sorts points, so caller may pass |
|
|
//| unsorted array. |
|
|
//| SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES: |
|
|
//| Setting constraints can lead to undesired results, like |
|
|
//| ill-conditioned behavior, or inconsistency being detected. From |
|
|
//| the other side, it allows us to improve quality of the fit. Here |
|
|
//| we summarize our experience with constrained regression splines:|
|
|
//| * excessive constraints can be inconsistent. Splines are |
|
|
//| piecewise cubic functions, and it is easy to create an example,|
|
|
//| where large number of constraints concentrated in small area |
|
|
//| will result in inconsistency. Just because spline is not |
|
|
//| flexible enough to satisfy all of them. And same constraints |
|
|
//| spread across the [min(x),max(x)] will be perfectly consistent.|
|
|
//| * the more evenly constraints are spread across [min(x),max(x)], |
|
|
//| the more chances that they will be consistent |
|
|
//| * the greater is M (given fixed constraints), the more chances |
|
|
//| that constraints will be consistent |
|
|
//| * in the general case, consistency of constraints is NOT |
|
|
//| GUARANTEED. |
|
|
//| * in the several special cases, however, we can guarantee |
|
|
//| consistency. |
|
|
//| * one of this cases is M>=4 and constraints on the function |
|
|
//| value (AND/OR its derivative) at the interval boundaries. |
|
|
//| * another special case is M>=4 and ONE constraint on the |
|
|
//| function value (OR, BUT NOT AND, derivative) anywhere in |
|
|
//| [min(x),max(x)] |
|
|
//| Our final recommendation is to use constraints WHEN AND ONLY when|
|
|
//| you can't solve your task without them. Anything beyond special |
|
|
//| cases given above is not guaranteed and may result in |
|
|
//| inconsistency. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DFitHermiteWC(double &x[],double &y[],double &w[],
|
|
double &xc[],double &yc[],int &dc[],
|
|
const int m,int &info,
|
|
CSpline1DInterpolantShell &s,
|
|
CSpline1DFitReportShell &rep)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
int k;
|
|
//--- check
|
|
if((CAp::Len(x)!=CAp::Len(y)) || (CAp::Len(x)!=CAp::Len(w)))
|
|
{
|
|
Print("Error while calling 'spline1dfithermitewc': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- check
|
|
if((CAp::Len(xc)!=CAp::Len(yc)) || (CAp::Len(xc)!=CAp::Len(dc)))
|
|
{
|
|
Print("Error while calling 'spline1dfithermitewc': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
info=0;
|
|
n=CAp::Len(x);
|
|
k=CAp::Len(xc);
|
|
//--- function call
|
|
CLSFit::Spline1DFitHermiteWC(x,y,w,n,xc,yc,dc,k,m,info,s.GetInnerObj(),rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Least squares fitting by cubic spline. |
|
|
//| This subroutine is "lightweight" alternative for more complex |
|
|
//| and feature - rich Spline1DFitCubicWC(). See Spline1DFitCubicWC()|
|
|
//| for more information about subroutine parameters (we don't |
|
|
//| duplicate it here because of length) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DFitCubic(double &x[],double &y[],const int n,
|
|
const int m,int &info,
|
|
CSpline1DInterpolantShell &s,
|
|
CSpline1DFitReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CLSFit::Spline1DFitCubic(x,y,n,m,info,s.GetInnerObj(),rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Least squares fitting by cubic spline. |
|
|
//| This subroutine is "lightweight" alternative for more complex |
|
|
//| and feature - rich Spline1DFitCubicWC(). See Spline1DFitCubicWC()|
|
|
//| for more information about subroutine parameters (we don't |
|
|
//| duplicate it here because of length) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DFitCubic(double &x[],double &y[],const int m,
|
|
int &info,CSpline1DInterpolantShell &s,
|
|
CSpline1DFitReportShell &rep)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- check
|
|
if((CAp::Len(x)!=CAp::Len(y)))
|
|
{
|
|
Print("Error while calling 'spline1dfitcubic': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
info=0;
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CLSFit::Spline1DFitCubic(x,y,n,m,info,s.GetInnerObj(),rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Least squares fitting by Hermite spline. |
|
|
//| This subroutine is "lightweight" alternative for more complex |
|
|
//| and feature - rich Spline1DFitHermiteWC(). See |
|
|
//| Spline1DFitHermiteWC() description for more information about |
|
|
//| subroutine parameters (we don't duplicate it here because of |
|
|
//| length). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DFitHermite(double &x[],double &y[],const int n,
|
|
const int m,int &info,
|
|
CSpline1DInterpolantShell &s,
|
|
CSpline1DFitReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CLSFit::Spline1DFitHermite(x,y,n,m,info,s.GetInnerObj(),rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Least squares fitting by Hermite spline. |
|
|
//| This subroutine is "lightweight" alternative for more complex |
|
|
//| and feature - rich Spline1DFitHermiteWC(). See |
|
|
//| Spline1DFitHermiteWC() description for more information about |
|
|
//| subroutine parameters (we don't duplicate it here because of |
|
|
//| length). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline1DFitHermite(double &x[],double &y[],const int m,
|
|
int &info,CSpline1DInterpolantShell &s,
|
|
CSpline1DFitReportShell &rep)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- check
|
|
if((CAp::Len(x)!=CAp::Len(y)))
|
|
{
|
|
Print("Error while calling 'spline1dfithermite': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
info=0;
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CLSFit::Spline1DFitHermite(x,y,n,m,info,s.GetInnerObj(),rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Weighted linear least squares fitting. |
|
|
//| QR decomposition is used to reduce task to MxM, then triangular |
|
|
//| solver or SVD-based solver is used depending on condition number |
|
|
//| of the system. It allows to maximize speed and retain decent |
|
|
//| accuracy. |
|
|
//| INPUT PARAMETERS: |
|
|
//| Y - array[0..N-1] Function values in N points. |
|
|
//| W - array[0..N-1] Weights corresponding to function |
|
|
//| values. Each summand in square sum of |
|
|
//| approximation deviations from given values is |
|
|
//| multiplied by the square of corresponding weight.|
|
|
//| FMatrix - a table of basis functions values, |
|
|
//| array[0..N-1, 0..M-1]. FMatrix[I, J] - value of |
|
|
//| J-th basis function in I-th point. |
|
|
//| N - number of points used. N>=1. |
|
|
//| M - number of basis functions, M>=1. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - error code: |
|
|
//| * -4 internal SVD decomposition subroutine |
|
|
//| failed (very rare and for degenerate |
|
|
//| systems only) |
|
|
//| * -1 incorrect N/M were specified |
|
|
//| * 1 task is solved |
|
|
//| C - decomposition coefficients, array[0..M-1] |
|
|
//| Rep - fitting report. Following fields are set: |
|
|
//| * Rep.TaskRCond reciprocal of condition |
|
|
//| number |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the|
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE |
|
|
//| CALCULATED |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitLinearW(double &y[],double &w[],CMatrixDouble &fmatrix,
|
|
const int n,const int m,int &info,
|
|
double &c[],CLSFitReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CLSFit::LSFitLinearW(y,w,fmatrix,n,m,info,c,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Weighted linear least squares fitting. |
|
|
//| QR decomposition is used to reduce task to MxM, then triangular |
|
|
//| solver or SVD-based solver is used depending on condition number |
|
|
//| of the system. It allows to maximize speed and retain decent |
|
|
//| accuracy. |
|
|
//| INPUT PARAMETERS: |
|
|
//| Y - array[0..N-1] Function values in N points. |
|
|
//| W - array[0..N-1] Weights corresponding to function |
|
|
//| values. Each summand in square sum of |
|
|
//| approximation deviations from given values is |
|
|
//| multiplied by the square of corresponding weight.|
|
|
//| FMatrix - a table of basis functions values, |
|
|
//| array[0..N-1, 0..M-1]. FMatrix[I, J] - value of |
|
|
//| J-th basis function in I-th point. |
|
|
//| N - number of points used. N>=1. |
|
|
//| M - number of basis functions, M>=1. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - error code: |
|
|
//| * -4 internal SVD decomposition subroutine |
|
|
//| failed (very rare and for degenerate |
|
|
//| systems only) |
|
|
//| * -1 incorrect N/M were specified |
|
|
//| * 1 task is solved |
|
|
//| C - decomposition coefficients, array[0..M-1] |
|
|
//| Rep - fitting report. Following fields are set: |
|
|
//| * Rep.TaskRCond reciprocal of condition |
|
|
//| number |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the|
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE |
|
|
//| CALCULATED |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitLinearW(double &y[],double &w[],CMatrixDouble &fmatrix,
|
|
int &info,double &c[],CLSFitReportShell &rep)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
int m;
|
|
//--- check
|
|
if((CAp::Len(y)!=CAp::Len(w)) || (CAp::Len(y)!=CAp::Rows(fmatrix)))
|
|
{
|
|
Print("Error while calling 'lsfitlinearw': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
info=0;
|
|
n=CAp::Len(y);
|
|
m=CAp::Cols(fmatrix);
|
|
//--- function call
|
|
CLSFit::LSFitLinearW(y,w,fmatrix,n,m,info,c,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Weighted constained linear least squares fitting. |
|
|
//| This is variation of LSFitLinearW(), which searchs for |
|
|
//| min|A*x=b| given that K additional constaints C*x=bc are |
|
|
//| satisfied. It reduces original task to modified one: min|B*y-d| |
|
|
//| WITHOUT constraints, then LSFitLinearW() is called. |
|
|
//| INPUT PARAMETERS: |
|
|
//| Y - array[0..N-1] Function values in N points. |
|
|
//| W - array[0..N-1] Weights corresponding to function |
|
|
//| values. Each summand in square sum of |
|
|
//| approximation deviations from given values is |
|
|
//| multiplied by the square of corresponding |
|
|
//| weight. |
|
|
//| FMatrix - a table of basis functions values, |
|
|
//| array[0..N-1, 0..M-1]. FMatrix[I,J] - value of |
|
|
//| J-th basis function in I-th point. |
|
|
//| CMatrix - a table of constaints, array[0..K-1,0..M]. |
|
|
//| I-th row of CMatrix corresponds to I-th linear |
|
|
//| constraint: CMatrix[I,0]*C[0] + ... + |
|
|
//| + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M] |
|
|
//| N - number of points used. N>=1. |
|
|
//| M - number of basis functions, M>=1. |
|
|
//| K - number of constraints, 0 <= K < M |
|
|
//| K=0 corresponds to absence of constraints. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - error code: |
|
|
//| * -4 internal SVD decomposition subroutine |
|
|
//| failed (very rare and for degenerate |
|
|
//| systems only) |
|
|
//| * -3 either too many constraints (M or more), |
|
|
//| degenerate constraints (some constraints |
|
|
//| are repetead twice) or inconsistent |
|
|
//| constraints were specified. |
|
|
//| * 1 task is solved |
|
|
//| C - decomposition coefficients, array[0..M-1] |
|
|
//| Rep - fitting report. Following fields are set: |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the|
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE |
|
|
//| CALCULATED |
|
|
//| IMPORTANT: |
|
|
//| this subroitine doesn't calculate task's condition number |
|
|
//| for K<>0. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitLinearWC(double &y[],double &w[],CMatrixDouble &fmatrix,
|
|
CMatrixDouble &cmatrix,const int n,
|
|
const int m,const int k,int &info,
|
|
double &c[],CLSFitReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CLSFit::LSFitLinearWC(y,w,fmatrix,cmatrix,n,m,k,info,c,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Weighted constained linear least squares fitting. |
|
|
//| This is variation of LSFitLinearW(), which searchs for |
|
|
//| min|A*x=b| given that K additional constaints C*x=bc are |
|
|
//| satisfied. It reduces original task to modified one: min|B*y-d| |
|
|
//| WITHOUT constraints, then LSFitLinearW() is called. |
|
|
//| INPUT PARAMETERS: |
|
|
//| Y - array[0..N-1] Function values in N points. |
|
|
//| W - array[0..N-1] Weights corresponding to function |
|
|
//| values. Each summand in square sum of |
|
|
//| approximation deviations from given values is |
|
|
//| multiplied by the square of corresponding |
|
|
//| weight. |
|
|
//| FMatrix - a table of basis functions values, |
|
|
//| array[0..N-1, 0..M-1]. FMatrix[I,J] - value of |
|
|
//| J-th basis function in I-th point. |
|
|
//| CMatrix - a table of constaints, array[0..K-1,0..M]. |
|
|
//| I-th row of CMatrix corresponds to I-th linear |
|
|
//| constraint: CMatrix[I,0]*C[0] + ... + |
|
|
//| + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M] |
|
|
//| N - number of points used. N>=1. |
|
|
//| M - number of basis functions, M>=1. |
|
|
//| K - number of constraints, 0 <= K < M |
|
|
//| K=0 corresponds to absence of constraints. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - error code: |
|
|
//| * -4 internal SVD decomposition subroutine |
|
|
//| failed (very rare and for degenerate |
|
|
//| systems only) |
|
|
//| * -3 either too many constraints (M or more), |
|
|
//| degenerate constraints (some constraints |
|
|
//| are repetead twice) or inconsistent |
|
|
//| constraints were specified. |
|
|
//| * 1 task is solved |
|
|
//| C - decomposition coefficients, array[0..M-1] |
|
|
//| Rep - fitting report. Following fields are set: |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the|
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE |
|
|
//| CALCULATED |
|
|
//| IMPORTANT: |
|
|
//| this subroitine doesn't calculate task's condition number |
|
|
//| for K<>0. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitLinearWC(double &y[],double &w[],CMatrixDouble &fmatrix,
|
|
CMatrixDouble &cmatrix,int &info,
|
|
double &c[],CLSFitReportShell &rep)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
int m;
|
|
int k;
|
|
//--- check
|
|
if((CAp::Len(y)!=CAp::Len(w)) || (CAp::Len(y)!=CAp::Rows(fmatrix)))
|
|
{
|
|
Print("Error while calling 'lsfitlinearwc': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- check
|
|
if((CAp::Cols(fmatrix)!=CAp::Cols(cmatrix)-1))
|
|
{
|
|
Print("Error while calling 'lsfitlinearwc': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
info=0;
|
|
n=CAp::Len(y);
|
|
m=CAp::Cols(fmatrix);
|
|
k=CAp::Rows(cmatrix);
|
|
//--- function call
|
|
CLSFit::LSFitLinearWC(y,w,fmatrix,cmatrix,n,m,k,info,c,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Linear least squares fitting. |
|
|
//| QR decomposition is used to reduce task to MxM, then triangular |
|
|
//| solver or SVD-based solver is used depending on condition number |
|
|
//| of the system. It allows to maximize speed and retain decent |
|
|
//| accuracy. |
|
|
//| INPUT PARAMETERS: |
|
|
//| Y - array[0..N-1] Function values in N points. |
|
|
//| FMatrix - a table of basis functions values, |
|
|
//| array[0..N-1, 0..M-1]. |
|
|
//| FMatrix[I, J] - value of J-th basis function in |
|
|
//| I-th point. |
|
|
//| N - number of points used. N>=1. |
|
|
//| M - number of basis functions, M>=1. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - error code: |
|
|
//| * -4 internal SVD decomposition subroutine |
|
|
//| failed (very rare and for degenerate |
|
|
//| systems only) |
|
|
//| * 1 task is solved |
|
|
//| C - decomposition coefficients, array[0..M-1] |
|
|
//| Rep - fitting report. Following fields are set: |
|
|
//| * Rep.TaskRCond reciprocal of condition |
|
|
//| number |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the|
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE |
|
|
//| CALCULATED |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitLinear(double &y[],CMatrixDouble &fmatrix,
|
|
const int n,const int m,int &info,
|
|
double &c[],CLSFitReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CLSFit::LSFitLinear(y,fmatrix,n,m,info,c,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Linear least squares fitting. |
|
|
//| QR decomposition is used to reduce task to MxM, then triangular |
|
|
//| solver or SVD-based solver is used depending on condition number |
|
|
//| of the system. It allows to maximize speed and retain decent |
|
|
//| accuracy. |
|
|
//| INPUT PARAMETERS: |
|
|
//| Y - array[0..N-1] Function values in N points. |
|
|
//| FMatrix - a table of basis functions values, |
|
|
//| array[0..N-1, 0..M-1]. |
|
|
//| FMatrix[I, J] - value of J-th basis function in |
|
|
//| I-th point. |
|
|
//| N - number of points used. N>=1. |
|
|
//| M - number of basis functions, M>=1. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - error code: |
|
|
//| * -4 internal SVD decomposition subroutine |
|
|
//| failed (very rare and for degenerate |
|
|
//| systems only) |
|
|
//| * 1 task is solved |
|
|
//| C - decomposition coefficients, array[0..M-1] |
|
|
//| Rep - fitting report. Following fields are set: |
|
|
//| * Rep.TaskRCond reciprocal of condition |
|
|
//| number |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the|
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE |
|
|
//| CALCULATED |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitLinear(double &y[],CMatrixDouble &fmatrix,
|
|
int &info,double &c[],CLSFitReportShell &rep)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
int m;
|
|
//--- check
|
|
if((CAp::Len(y)!=CAp::Rows(fmatrix)))
|
|
{
|
|
Print("Error while calling 'lsfitlinear': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
info=0;
|
|
n=CAp::Len(y);
|
|
m=CAp::Cols(fmatrix);
|
|
//--- function call
|
|
CLSFit::LSFitLinear(y,fmatrix,n,m,info,c,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Constained linear least squares fitting. |
|
|
//| This is variation of LSFitLinear(), which searchs for min|A*x=b| |
|
|
//| given that K additional constaints C*x=bc are satisfied. It |
|
|
//| reduces original task to modified one: min|B*y-d| WITHOUT |
|
|
//| constraints, then LSFitLinear() is called. |
|
|
//| INPUT PARAMETERS: |
|
|
//| Y - array[0..N-1] Function values in N points. |
|
|
//| FMatrix - a table of basis functions values, |
|
|
//| array[0..N-1, 0..M-1]. FMatrix[I,J] - value of |
|
|
//| J-th basis function in I-th point. |
|
|
//| CMatrix - a table of constaints, array[0..K-1,0..M]. |
|
|
//| I-th row of CMatrix corresponds to I-th linear |
|
|
//| constraint: CMatrix[I,0]*C[0] + ... + |
|
|
//| + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M] |
|
|
//| N - number of points used. N>=1. |
|
|
//| M - number of basis functions, M>=1. |
|
|
//| K - number of constraints, 0 <= K < M |
|
|
//| K=0 corresponds to absence of constraints. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - error code: |
|
|
//| * -4 internal SVD decomposition subroutine |
|
|
//| failed (very rare and for degenerate |
|
|
//| systems only) |
|
|
//| * -3 either too many constraints (M or more), |
|
|
//| degenerate constraints (some constraints |
|
|
//| are repetead twice) or inconsistent |
|
|
//| constraints were specified. |
|
|
//| * 1 task is solved |
|
|
//| C - decomposition coefficients, array[0..M-1] |
|
|
//| Rep - fitting report. Following fields are set: |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the|
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE |
|
|
//| CALCULATED |
|
|
//| IMPORTANT: |
|
|
//| this subroitine doesn't calculate task's condition number |
|
|
//| for K<>0. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitLinearC(double &y[],CMatrixDouble &fmatrix,
|
|
CMatrixDouble &cmatrix,const int n,
|
|
const int m,const int k,int &info,
|
|
double &c[],CLSFitReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CLSFit::LSFitLinearC(y,fmatrix,cmatrix,n,m,k,info,c,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Constained linear least squares fitting. |
|
|
//| This is variation of LSFitLinear(), which searchs for min|A*x=b| |
|
|
//| given that K additional constaints C*x=bc are satisfied. It |
|
|
//| reduces original task to modified one: min|B*y-d| WITHOUT |
|
|
//| constraints, then LSFitLinear() is called. |
|
|
//| INPUT PARAMETERS: |
|
|
//| Y - array[0..N-1] Function values in N points. |
|
|
//| FMatrix - a table of basis functions values, |
|
|
//| array[0..N-1, 0..M-1]. FMatrix[I,J] - value of |
|
|
//| J-th basis function in I-th point. |
|
|
//| CMatrix - a table of constaints, array[0..K-1,0..M]. |
|
|
//| I-th row of CMatrix corresponds to I-th linear |
|
|
//| constraint: CMatrix[I,0]*C[0] + ... + |
|
|
//| + CMatrix[I,M-1]*C[M-1] = CMatrix[I,M] |
|
|
//| N - number of points used. N>=1. |
|
|
//| M - number of basis functions, M>=1. |
|
|
//| K - number of constraints, 0 <= K < M |
|
|
//| K=0 corresponds to absence of constraints. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - error code: |
|
|
//| * -4 internal SVD decomposition subroutine |
|
|
//| failed (very rare and for degenerate |
|
|
//| systems only) |
|
|
//| * -3 either too many constraints (M or more), |
|
|
//| degenerate constraints (some constraints |
|
|
//| are repetead twice) or inconsistent |
|
|
//| constraints were specified. |
|
|
//| * 1 task is solved |
|
|
//| C - decomposition coefficients, array[0..M-1] |
|
|
//| Rep - fitting report. Following fields are set: |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the|
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE |
|
|
//| CALCULATED |
|
|
//| IMPORTANT: |
|
|
//| this subroitine doesn't calculate task's condition number |
|
|
//| for K<>0. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitLinearC(double &y[],CMatrixDouble &fmatrix,
|
|
CMatrixDouble &cmatrix,int &info,
|
|
double &c[],CLSFitReportShell &rep)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
int m;
|
|
int k;
|
|
//--- check
|
|
if((CAp::Len(y)!=CAp::Rows(fmatrix)))
|
|
{
|
|
Print("Error while calling 'lsfitlinearc': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- check
|
|
if((CAp::Cols(fmatrix)!=CAp::Cols(cmatrix)-1))
|
|
{
|
|
Print("Error while calling 'lsfitlinearc': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
info=0;
|
|
n=CAp::Len(y);
|
|
m=CAp::Cols(fmatrix);
|
|
k=CAp::Rows(cmatrix);
|
|
//--- function call
|
|
CLSFit::LSFitLinearC(y,fmatrix,cmatrix,n,m,k,info,c,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Weighted nonlinear least squares fitting using function values |
|
|
//| only. |
|
|
//| Combination of numerical differentiation and secant updates is |
|
|
//| used to obtain function Jacobian. |
|
|
//| Nonlinear task min(F(c)) is solved, where |
|
|
//| F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + |
|
|
//| + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2, |
|
|
//| * N is a number of points, |
|
|
//| * M is a dimension of a space points belong to, |
|
|
//| * K is a dimension of a space of parameters being fitted, |
|
|
//| * w is an N-dimensional vector of weight coefficients, |
|
|
//| * x is a set of N points, each of them is an M-dimensional |
|
|
//| vector, |
|
|
//| * c is a K-dimensional vector of parameters being fitted |
|
|
//| This subroutine uses only f(c,x[i]). |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[0..N-1,0..M-1], points (one row = one |
|
|
//| point) |
|
|
//| Y - array[0..N-1], function values. |
|
|
//| W - weights, array[0..N-1] |
|
|
//| C - array[0..K-1], initial approximation to the |
|
|
//| solution, |
|
|
//| N - number of points, N>1 |
|
|
//| M - dimension of space |
|
|
//| K - number of parameters being fitted |
|
|
//| DiffStep- numerical differentiation step; |
|
|
//| should not be very small or large; |
|
|
//| large = loss of accuracy |
|
|
//| small = growth of round-off errors |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitCreateWF(CMatrixDouble &x,double &y[],double &w[],
|
|
double &c[],const int n,const int m,
|
|
const int k,const double diffstep,
|
|
CLSFitStateShell &state)
|
|
{
|
|
//--- function call
|
|
CLSFit::LSFitCreateWF(x,y,w,c,n,m,k,diffstep,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Weighted nonlinear least squares fitting using function values |
|
|
//| only. |
|
|
//| Combination of numerical differentiation and secant updates is |
|
|
//| used to obtain function Jacobian. |
|
|
//| Nonlinear task min(F(c)) is solved, where |
|
|
//| F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + |
|
|
//| + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2, |
|
|
//| * N is a number of points, |
|
|
//| * M is a dimension of a space points belong to, |
|
|
//| * K is a dimension of a space of parameters being fitted, |
|
|
//| * w is an N-dimensional vector of weight coefficients, |
|
|
//| * x is a set of N points, each of them is an M-dimensional |
|
|
//| vector, |
|
|
//| * c is a K-dimensional vector of parameters being fitted |
|
|
//| This subroutine uses only f(c,x[i]). |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[0..N-1,0..M-1], points (one row = one |
|
|
//| point) |
|
|
//| Y - array[0..N-1], function values. |
|
|
//| W - weights, array[0..N-1] |
|
|
//| C - array[0..K-1], initial approximation to the |
|
|
//| solution, |
|
|
//| N - number of points, N>1 |
|
|
//| M - dimension of space |
|
|
//| K - number of parameters being fitted |
|
|
//| DiffStep- numerical differentiation step; |
|
|
//| should not be very small or large; |
|
|
//| large = loss of accuracy |
|
|
//| small = growth of round-off errors |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitCreateWF(CMatrixDouble &x,double &y[],double &w[],
|
|
double &c[],const double diffstep,
|
|
CLSFitStateShell &state)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
int m;
|
|
int k;
|
|
//--- check
|
|
if((CAp::Rows(x)!=CAp::Len(y)) || (CAp::Rows(x)!=CAp::Len(w)))
|
|
{
|
|
Print("Error while calling 'lsfitcreatewf': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
n=CAp::Rows(x);
|
|
m=CAp::Cols(x);
|
|
k=CAp::Len(c);
|
|
//--- function call
|
|
CLSFit::LSFitCreateWF(x,y,w,c,n,m,k,diffstep,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Nonlinear least squares fitting using function values only. |
|
|
//| Combination of numerical differentiation and secant updates is |
|
|
//| used to obtain function Jacobian. |
|
|
//| Nonlinear task min(F(c)) is solved, where |
|
|
//| F(c) = (f(c,x[0])-y[0])^2 + ... + (f(c,x[n-1])-y[n-1])^2, |
|
|
//| * N is a number of points, |
|
|
//| * M is a dimension of a space points belong to, |
|
|
//| * K is a dimension of a space of parameters being fitted, |
|
|
//| * w is an N-dimensional vector of weight coefficients, |
|
|
//| * x is a set of N points, each of them is an M-dimensional |
|
|
//| vector, |
|
|
//| * c is a K-dimensional vector of parameters being fitted |
|
|
//| This subroutine uses only f(c,x[i]). |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[0..N-1,0..M-1], points (one row = one |
|
|
//| point) |
|
|
//| Y - array[0..N-1], function values. |
|
|
//| C - array[0..K-1], initial approximation to the |
|
|
//| solution, |
|
|
//| N - number of points, N>1 |
|
|
//| M - dimension of space |
|
|
//| K - number of parameters being fitted |
|
|
//| DiffStep- numerical differentiation step; |
|
|
//| should not be very small or large; |
|
|
//| large = loss of accuracy |
|
|
//| small = growth of round-off errors |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitCreateF(CMatrixDouble &x,double &y[],double &c[],
|
|
const int n,const int m,const int k,
|
|
const double diffstep,CLSFitStateShell &state)
|
|
{
|
|
//--- function call
|
|
CLSFit::LSFitCreateF(x,y,c,n,m,k,diffstep,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Nonlinear least squares fitting using function values only. |
|
|
//| Combination of numerical differentiation and secant updates is |
|
|
//| used to obtain function Jacobian. |
|
|
//| Nonlinear task min(F(c)) is solved, where |
|
|
//| F(c) = (f(c,x[0])-y[0])^2 + ... + (f(c,x[n-1])-y[n-1])^2, |
|
|
//| * N is a number of points, |
|
|
//| * M is a dimension of a space points belong to, |
|
|
//| * K is a dimension of a space of parameters being fitted, |
|
|
//| * w is an N-dimensional vector of weight coefficients, |
|
|
//| * x is a set of N points, each of them is an M-dimensional |
|
|
//| vector, |
|
|
//| * c is a K-dimensional vector of parameters being fitted |
|
|
//| This subroutine uses only f(c,x[i]). |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[0..N-1,0..M-1], points (one row = one |
|
|
//| point) |
|
|
//| Y - array[0..N-1], function values. |
|
|
//| C - array[0..K-1], initial approximation to the |
|
|
//| solution, |
|
|
//| N - number of points, N>1 |
|
|
//| M - dimension of space |
|
|
//| K - number of parameters being fitted |
|
|
//| DiffStep- numerical differentiation step; |
|
|
//| should not be very small or large; |
|
|
//| large = loss of accuracy |
|
|
//| small = growth of round-off errors |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitCreateF(CMatrixDouble &x,double &y[],double &c[],
|
|
const double diffstep,CLSFitStateShell &state)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
int m;
|
|
int k;
|
|
//--- check
|
|
if((CAp::Rows(x)!=CAp::Len(y)))
|
|
{
|
|
Print("Error while calling 'lsfitcreatef': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
n=CAp::Rows(x);
|
|
m=CAp::Cols(x);
|
|
k=CAp::Len(c);
|
|
//--- function call
|
|
CLSFit::LSFitCreateF(x,y,c,n,m,k,diffstep,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Weighted nonlinear least squares fitting using gradient only. |
|
|
//| Nonlinear task min(F(c)) is solved, where |
|
|
//| F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + |
|
|
//| + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2, |
|
|
//| * N is a number of points, |
|
|
//| * M is a dimension of a space points belong to, |
|
|
//| * K is a dimension of a space of parameters being fitted, |
|
|
//| * w is an N-dimensional vector of weight coefficients, |
|
|
//| * x is a set of N points, each of them is an M-dimensional |
|
|
//| vector, |
|
|
//| * c is a K-dimensional vector of parameters being fitted |
|
|
//| This subroutine uses only f(c,x[i]) and its gradient. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[0..N-1,0..M-1], points (one row = one |
|
|
//| point) |
|
|
//| Y - array[0..N-1], function values. |
|
|
//| W - weights, array[0..N-1] |
|
|
//| C - array[0..K-1], initial approximation to the |
|
|
//| solution, |
|
|
//| N - number of points, N>1 |
|
|
//| M - dimension of space |
|
|
//| K - number of parameters being fitted |
|
|
//| CheapFG - boolean flag, which is: |
|
|
//| * True if both function and gradient calculation |
|
|
//| complexity are less than O(M^2). An |
|
|
//| improved algorithm can be used which |
|
|
//| corresponds to FGJ scheme from MINLM unit.|
|
|
//| * False otherwise. |
|
|
//| Standard Jacibian-bases |
|
|
//| Levenberg-Marquardt algo will be used (FJ |
|
|
//| scheme). |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| See also: |
|
|
//| LSFitResults |
|
|
//| LSFitCreateFG (fitting without weights) |
|
|
//| LSFitCreateWFGH (fitting using Hessian) |
|
|
//| LSFitCreateFGH (fitting using Hessian, without weights) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitCreateWFG(CMatrixDouble &x,double &y[],double &w[],
|
|
double &c[],const int n,const int m,
|
|
const int k,const bool cheapfg,
|
|
CLSFitStateShell &state)
|
|
{
|
|
//--- function call
|
|
CLSFit::LSFitCreateWFG(x,y,w,c,n,m,k,cheapfg,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Weighted nonlinear least squares fitting using gradient only. |
|
|
//| Nonlinear task min(F(c)) is solved, where |
|
|
//| F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + |
|
|
//| + (w[n-1]*(f(c,x[n-1])-y[n-1]))^2, |
|
|
//| * N is a number of points, |
|
|
//| * M is a dimension of a space points belong to, |
|
|
//| * K is a dimension of a space of parameters being fitted, |
|
|
//| * w is an N-dimensional vector of weight coefficients, |
|
|
//| * x is a set of N points, each of them is an M-dimensional |
|
|
//| vector, |
|
|
//| * c is a K-dimensional vector of parameters being fitted |
|
|
//| This subroutine uses only f(c,x[i]) and its gradient. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[0..N-1,0..M-1], points (one row = one |
|
|
//| point) |
|
|
//| Y - array[0..N-1], function values. |
|
|
//| W - weights, array[0..N-1] |
|
|
//| C - array[0..K-1], initial approximation to the |
|
|
//| solution, |
|
|
//| N - number of points, N>1 |
|
|
//| M - dimension of space |
|
|
//| K - number of parameters being fitted |
|
|
//| CheapFG - boolean flag, which is: |
|
|
//| * True if both function and gradient calculation |
|
|
//| complexity are less than O(M^2). An |
|
|
//| improved algorithm can be used which |
|
|
//| corresponds to FGJ scheme from MINLM unit.|
|
|
//| * False otherwise. |
|
|
//| Standard Jacibian-bases |
|
|
//| Levenberg-Marquardt algo will be used (FJ |
|
|
//| scheme). |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| See also: |
|
|
//| LSFitResults |
|
|
//| LSFitCreateFG (fitting without weights) |
|
|
//| LSFitCreateWFGH (fitting using Hessian) |
|
|
//| LSFitCreateFGH (fitting using Hessian, without weights) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitCreateWFG(CMatrixDouble &x,double &y[],double &w[],
|
|
double &c[],const bool cheapfg,
|
|
CLSFitStateShell &state)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
int m;
|
|
int k;
|
|
//--- check
|
|
if((CAp::Rows(x)!=CAp::Len(y)) || (CAp::Rows(x)!=CAp::Len(w)))
|
|
{
|
|
Print("Error while calling 'lsfitcreatewfg': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
n=CAp::Rows(x);
|
|
m=CAp::Cols(x);
|
|
k=CAp::Len(c);
|
|
//--- function call
|
|
CLSFit::LSFitCreateWFG(x,y,w,c,n,m,k,cheapfg,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Nonlinear least squares fitting using gradient only, without |
|
|
//| individual weights. |
|
|
//| Nonlinear task min(F(c)) is solved, where |
|
|
//| F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2,|
|
|
//| * N is a number of points, |
|
|
//| * M is a dimension of a space points belong to, |
|
|
//| * K is a dimension of a space of parameters being fitted, |
|
|
//| * x is a set of N points, each of them is an M-dimensional |
|
|
//| vector, |
|
|
//| * c is a K-dimensional vector of parameters being fitted |
|
|
//| This subroutine uses only f(c,x[i]) and its gradient. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[0..N-1,0..M-1], points (one row = one |
|
|
//| point) |
|
|
//| Y - array[0..N-1], function values. |
|
|
//| C - array[0..K-1], initial approximation to the |
|
|
//| solution, |
|
|
//| N - number of points, N>1 |
|
|
//| M - dimension of space |
|
|
//| K - number of parameters being fitted |
|
|
//| CheapFG - boolean flag, which is: |
|
|
//| * True if both function and gradient calculation|
|
|
//| complexity are less than O(M^2). An |
|
|
//| improved algorithm can be used which |
|
|
//| corresponds to FGJ scheme from MINLM |
|
|
//| unit. |
|
|
//| * False otherwise. |
|
|
//| Standard Jacibian-bases |
|
|
//| Levenberg-Marquardt algo will be used |
|
|
//| (FJ scheme). |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitCreateFG(CMatrixDouble &x,double &y[],double &c[],
|
|
const int n,const int m,const int k,
|
|
const bool cheapfg,CLSFitStateShell &state)
|
|
{
|
|
//--- function call
|
|
CLSFit::LSFitCreateFG(x,y,c,n,m,k,cheapfg,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Nonlinear least squares fitting using gradient only, without |
|
|
//| individual weights. |
|
|
//| Nonlinear task min(F(c)) is solved, where |
|
|
//| F(c) = ((f(c,x[0])-y[0]))^2 + ... + ((f(c,x[n-1])-y[n-1]))^2,|
|
|
//| * N is a number of points, |
|
|
//| * M is a dimension of a space points belong to, |
|
|
//| * K is a dimension of a space of parameters being fitted, |
|
|
//| * x is a set of N points, each of them is an M-dimensional |
|
|
//| vector, |
|
|
//| * c is a K-dimensional vector of parameters being fitted |
|
|
//| This subroutine uses only f(c,x[i]) and its gradient. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[0..N-1,0..M-1], points (one row = one |
|
|
//| point) |
|
|
//| Y - array[0..N-1], function values. |
|
|
//| C - array[0..K-1], initial approximation to the |
|
|
//| solution, |
|
|
//| N - number of points, N>1 |
|
|
//| M - dimension of space |
|
|
//| K - number of parameters being fitted |
|
|
//| CheapFG - boolean flag, which is: |
|
|
//| * True if both function and gradient calculation|
|
|
//| complexity are less than O(M^2). An |
|
|
//| improved algorithm can be used which |
|
|
//| corresponds to FGJ scheme from MINLM |
|
|
//| unit. |
|
|
//| * False otherwise. |
|
|
//| Standard Jacibian-bases |
|
|
//| Levenberg-Marquardt algo will be used |
|
|
//| (FJ scheme). |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitCreateFG(CMatrixDouble &x,double &y[],double &c[],
|
|
const bool cheapfg,CLSFitStateShell &state)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
int m;
|
|
int k;
|
|
//--- check
|
|
if((CAp::Rows(x)!=CAp::Len(y)))
|
|
{
|
|
Print("Error while calling 'lsfitcreatefg': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
n=CAp::Rows(x);
|
|
m=CAp::Cols(x);
|
|
k=CAp::Len(c);
|
|
//--- function call
|
|
CLSFit::LSFitCreateFG(x,y,c,n,m,k,cheapfg,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Weighted nonlinear least squares fitting using gradient/Hessian. |
|
|
//| Nonlinear task min(F(c)) is solved, where |
|
|
//| F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + |
|
|
//| (w[n-1]*(f(c,x[n-1])-y[n-1]))^2, |
|
|
//| * N is a number of points, |
|
|
//| * M is a dimension of a space points belong to, |
|
|
//| * K is a dimension of a space of parameters being fitted, |
|
|
//| * w is an N-dimensional vector of weight coefficients, |
|
|
//| * x is a set of N points, each of them is an M-dimensional |
|
|
//| vector, |
|
|
//| * c is a K-dimensional vector of parameters being fitted |
|
|
//| This subroutine uses f(c,x[i]), its gradient and its Hessian. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[0..N-1,0..M-1], points (one row = one |
|
|
//| point) |
|
|
//| Y - array[0..N-1], function values. |
|
|
//| W - weights, array[0..N-1] |
|
|
//| C - array[0..K-1], initial approximation to the |
|
|
//| solution, |
|
|
//| N - number of points, N>1 |
|
|
//| M - dimension of space |
|
|
//| K - number of parameters being fitted |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitCreateWFGH(CMatrixDouble &x,double &y[],double &w[],
|
|
double &c[],const int n,const int m,
|
|
const int k,CLSFitStateShell &state)
|
|
{
|
|
//--- function call
|
|
CLSFit::LSFitCreateWFGH(x,y,w,c,n,m,k,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Weighted nonlinear least squares fitting using gradient/Hessian. |
|
|
//| Nonlinear task min(F(c)) is solved, where |
|
|
//| F(c) = (w[0]*(f(c,x[0])-y[0]))^2 + ... + |
|
|
//| (w[n-1]*(f(c,x[n-1])-y[n-1]))^2, |
|
|
//| * N is a number of points, |
|
|
//| * M is a dimension of a space points belong to, |
|
|
//| * K is a dimension of a space of parameters being fitted, |
|
|
//| * w is an N-dimensional vector of weight coefficients, |
|
|
//| * x is a set of N points, each of them is an M-dimensional |
|
|
//| vector, |
|
|
//| * c is a K-dimensional vector of parameters being fitted |
|
|
//| This subroutine uses f(c,x[i]), its gradient and its Hessian. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[0..N-1,0..M-1], points (one row = one |
|
|
//| point) |
|
|
//| Y - array[0..N-1], function values. |
|
|
//| W - weights, array[0..N-1] |
|
|
//| C - array[0..K-1], initial approximation to the |
|
|
//| solution, |
|
|
//| N - number of points, N>1 |
|
|
//| M - dimension of space |
|
|
//| K - number of parameters being fitted |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitCreateWFGH(CMatrixDouble &x,double &y[],double &w[],
|
|
double &c[],CLSFitStateShell &state)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
int m;
|
|
int k;
|
|
//--- check
|
|
if((CAp::Rows(x)!=CAp::Len(y)) || (CAp::Rows(x)!=CAp::Len(w)))
|
|
{
|
|
Print("Error while calling 'lsfitcreatewfgh': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
n=CAp::Rows(x);
|
|
m=CAp::Cols(x);
|
|
k=CAp::Len(c);
|
|
//--- function call
|
|
CLSFit::LSFitCreateWFGH(x,y,w,c,n,m,k,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Nonlinear least squares fitting using gradient/Hessian, without |
|
|
//| individial weights. |
|
|
//| Nonlinear task min(F(c)) is solved, where |
|
|
//| F(c) = ((f(c,x[0])-y[0]))^2 + ... + |
|
|
//| ((f(c,x[n-1])-y[n-1]))^2, |
|
|
//| * N is a number of points, |
|
|
//| * M is a dimension of a space points belong to, |
|
|
//| * K is a dimension of a space of parameters being fitted, |
|
|
//| * x is a set of N points, each of them is an M-dimensional |
|
|
//| vector, |
|
|
//| * c is a K-dimensional vector of parameters being fitted |
|
|
//| This subroutine uses f(c,x[i]), its gradient and its Hessian. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[0..N-1,0..M-1], points (one row = one |
|
|
//| point) |
|
|
//| Y - array[0..N-1], function values. |
|
|
//| C - array[0..K-1], initial approximation to the |
|
|
//| solution, |
|
|
//| N - number of points, N>1 |
|
|
//| M - dimension of space |
|
|
//| K - number of parameters being fitted |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitCreateFGH(CMatrixDouble &x,double &y[],double &c[],
|
|
const int n,const int m,const int k,
|
|
CLSFitStateShell &state)
|
|
{
|
|
//--- function call
|
|
CLSFit::LSFitCreateFGH(x,y,c,n,m,k,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Nonlinear least squares fitting using gradient/Hessian, without |
|
|
//| individial weights. |
|
|
//| Nonlinear task min(F(c)) is solved, where |
|
|
//| F(c) = ((f(c,x[0])-y[0]))^2 + ... + |
|
|
//| ((f(c,x[n-1])-y[n-1]))^2, |
|
|
//| * N is a number of points, |
|
|
//| * M is a dimension of a space points belong to, |
|
|
//| * K is a dimension of a space of parameters being fitted, |
|
|
//| * x is a set of N points, each of them is an M-dimensional |
|
|
//| vector, |
|
|
//| * c is a K-dimensional vector of parameters being fitted |
|
|
//| This subroutine uses f(c,x[i]), its gradient and its Hessian. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[0..N-1,0..M-1], points (one row = one |
|
|
//| point) |
|
|
//| Y - array[0..N-1], function values. |
|
|
//| C - array[0..K-1], initial approximation to the |
|
|
//| solution, |
|
|
//| N - number of points, N>1 |
|
|
//| M - dimension of space |
|
|
//| K - number of parameters being fitted |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitCreateFGH(CMatrixDouble &x,double &y[],double &c[],
|
|
CLSFitStateShell &state)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
int m;
|
|
int k;
|
|
//--- check
|
|
if((CAp::Rows(x)!=CAp::Len(y)))
|
|
{
|
|
Print("Error while calling 'lsfitcreatefgh': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
n=CAp::Rows(x);
|
|
m=CAp::Cols(x);
|
|
k=CAp::Len(c);
|
|
//--- function call
|
|
CLSFit::LSFitCreateFGH(x,y,c,n,m,k,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Stopping conditions for nonlinear least squares fitting. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| EpsF - stopping criterion. Algorithm stops if |
|
|
//| |F(k+1)-F(k)| <= EpsF*max{|F(k)|, |F(k+1)|, 1} |
|
|
//| EpsX - >=0 |
|
|
//| The subroutine finishes its work if on k+1-th |
|
|
//| iteration the condition |v|<=EpsX is fulfilled, |
|
|
//| where: |
|
|
//| * |.| means Euclidian norm |
|
|
//| * v - scaled step vector, v[i]=dx[i]/s[i] |
|
|
//| * dx - ste pvector, dx=X(k+1)-X(k) |
|
|
//| * s - scaling coefficients set by LSFitSetScale()|
|
|
//| MaxIts - maximum number of iterations. If MaxIts=0, the |
|
|
//| number of iterations is unlimited. Only |
|
|
//| Levenberg-Marquardt iterations are counted |
|
|
//| (L-BFGS/CG iterations are NOT counted because |
|
|
//| their cost is very low compared to that of LM). |
|
|
//| NOTE |
|
|
//| Passing EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to|
|
|
//| automatic stopping criterion selection (according to the scheme |
|
|
//| used by MINLM unit). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitSetCond(CLSFitStateShell &state,const double epsf,
|
|
const double epsx,const int maxits)
|
|
{
|
|
//--- function call
|
|
CLSFit::LSFitSetCond(state.GetInnerObj(),epsf,epsx,maxits);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets maximum step length |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| StpMax - maximum step length, >=0. Set StpMax to 0.0, if |
|
|
//| you don't want to limit step length. |
|
|
//| Use this subroutine when you optimize target function which |
|
|
//| contains exp() or other fast growing functions, and optimization |
|
|
//| algorithm makes too large steps which leads to overflow. This |
|
|
//| function allows us to reject steps that are too large (and |
|
|
//| therefore expose us to the possible overflow) without actually |
|
|
//| calculating function value at the x+stp*d. |
|
|
//| NOTE: non-zero StpMax leads to moderate performance degradation |
|
|
//| because intermediate step of preconditioned L-BFGS optimization |
|
|
//| is incompatible with limits on step size. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitSetStpMax(CLSFitStateShell &state,const double stpmax)
|
|
{
|
|
//--- function call
|
|
CLSFit::LSFitSetStpMax(state.GetInnerObj(),stpmax);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function turns on/off reporting. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NeedXRep- whether iteration reports are needed or not |
|
|
//| When reports are needed, State.C (current parameters) and State. |
|
|
//| F (current value of fitting function) are reported. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitSetXRep(CLSFitStateShell &state,const bool needxrep)
|
|
{
|
|
//--- function call
|
|
CLSFit::LSFitSetXRep(state.GetInnerObj(),needxrep);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets scaling coefficients for underlying optimizer.|
|
|
//| ALGLIB optimizers use scaling matrices to test stopping |
|
|
//| conditions (step size and gradient are scaled before comparison |
|
|
//| with tolerances). Scale of the I-th variable is a translation |
|
|
//| invariant measure of: |
|
|
//| a) "how large" the variable is |
|
|
//| b) how large the step should be to make significant changes in |
|
|
//| the function |
|
|
//| Generally, scale is NOT considered to be a form of |
|
|
//| preconditioner. But LM optimizer is unique in that it uses |
|
|
//| scaling matrix both in the stopping condition tests and as |
|
|
//| Marquardt damping factor. |
|
|
//| Proper scaling is very important for the algorithm performance. |
|
|
//| It is less important for the quality of results, but still has |
|
|
//| some influence (it is easier to converge when variables are |
|
|
//| properly scaled, so premature stopping is possible when very |
|
|
//| badly scalled variables are combined with relaxed stopping |
|
|
//| conditions). |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure stores algorithm state |
|
|
//| S - array[N], non-zero scaling coefficients |
|
|
//| S[i] may be negative, sign doesn't matter. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitSetScale(CLSFitStateShell &state,double &s[])
|
|
{
|
|
//--- function call
|
|
CLSFit::LSFitSetScale(state.GetInnerObj(),s);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets boundary constraints for underlying optimizer |
|
|
//| Boundary constraints are inactive by default (after initial |
|
|
//| creation). They are preserved until explicitly turned off with |
|
|
//| another SetBC() call. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure stores algorithm state |
|
|
//| BndL - lower bounds, array[K]. |
|
|
//| If some (all) variables are unbounded, you may |
|
|
//| specify very small number or -INF (latter is |
|
|
//| recommended because it will allow solver to use |
|
|
//| better algorithm). |
|
|
//| BndU - upper bounds, array[K]. |
|
|
//| If some (all) variables are unbounded, you may |
|
|
//| specify very large number or +INF (latter is |
|
|
//| recommended because it will allow solver to use |
|
|
//| better algorithm). |
|
|
//| NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case |
|
|
//| I-th variable will be "frozen" at X[i]=BndL[i]=BndU[i]. |
|
|
//| NOTE 2: unlike other constrained optimization algorithms, this |
|
|
//| solver has following useful properties: |
|
|
//| * bound constraints are always satisfied exactly |
|
|
//| * function is evaluated only INSIDE area specified by bound |
|
|
//| constraints |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitSetBC(CLSFitStateShell &state,double &bndl[],
|
|
double &bndu[])
|
|
{
|
|
//--- function call
|
|
CLSFit::LSFitSetBC(state.GetInnerObj(),bndl,bndu);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function provides reverse communication interface |
|
|
//| Reverse communication interface is not documented or recommended |
|
|
//| to use. |
|
|
//| See below for functions which provide better documented API |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::LSFitIteration(CLSFitStateShell &state)
|
|
{
|
|
//--- return result
|
|
return(CLSFit::LSFitIteration(state.GetInnerObj()));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This family of functions is used to launcn iterations of |
|
|
//| nonlinear fitter |
|
|
//| These functions accept following parameters: |
|
|
//| func - callback which calculates function (or merit |
|
|
//| function) value func at given point x |
|
|
//| grad - callback which calculates function (or merit |
|
|
//| function) value func and gradient grad at given |
|
|
//| point x |
|
|
//| hess - callback which calculates function (or merit |
|
|
//| function) value func, gradient grad and Hessian |
|
|
//| hess at given point x |
|
|
//| rep - optional callback which is called after each |
|
|
//| iteration can be null |
|
|
//| obj - optional object which is passed to |
|
|
//| func/grad/hess/jac/rep can be null |
|
|
//| NOTES: |
|
|
//| 1. this algorithm is somewhat unusual because it works with |
|
|
//| parameterized function f(C,X), where X is a function argument |
|
|
//| (we have many points which are characterized by different |
|
|
//| argument values), and C is a parameter to fit. |
|
|
//| For example, if we want to do linear fit by |
|
|
//| f(c0,c1,x)=c0*x+c1, then x will be argument, and {c0,c1} will |
|
|
//| be parameters. |
|
|
//| It is important to understand that this algorithm finds |
|
|
//| minimum in the space of function PARAMETERS (not arguments), |
|
|
//| so it needs derivatives of f() with respect to C, not X. |
|
|
//| In the example above it will need f=c0*x+c1 and |
|
|
//| {df/dc0,df/dc1}={x,1} instead of {df/dx}={c0}. |
|
|
//| 2. Callback functions accept C as the first parameter, and X as |
|
|
//| the second |
|
|
//| 3. If state was created with LSFitCreateFG(), algorithm needs |
|
|
//| just function and its gradient, but if state wascreated with |
|
|
//| LSFitCreateFGH(), algorithm will need function, gradient and |
|
|
//| Hessian. |
|
|
//| According to the said above, there ase several versions of |
|
|
//| this function, which accept different sets of callbacks. |
|
|
//| This flexibility opens way to subtle errors - you may create |
|
|
//| state with LSFitCreateFGH() (optimization using Hessian), but |
|
|
//| call function which does not accept Hessian. So when algorithm|
|
|
//| will request Hessian, there will be no callback to call. In |
|
|
//| this case exception will be thrown. |
|
|
//| Be careful to avoid such errors because there is no way to |
|
|
//| find them at compile time - you can see them at runtime only. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitFit(CLSFitStateShell &state,CNDimensional_PFunc &func,
|
|
CNDimensional_Rep &rep,bool rep_status,CObject &obj)
|
|
{
|
|
//--- cycle
|
|
while(CAlglib::LSFitIteration(state))
|
|
{
|
|
//--- check
|
|
if(state.GetNeedF())
|
|
{
|
|
func.PFunc(state.GetInnerObj().m_c,state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetInnerObj().m_xupdated)
|
|
{
|
|
//--- check
|
|
if(rep_status)
|
|
rep.Rep(state.GetInnerObj().m_c,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
Print("ALGLIB: error in 'lsfitfit' (some derivatives were not provided?)");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This family of functions is used to launcn iterations of |
|
|
//| nonlinear fitter |
|
|
//| These functions accept following parameters: |
|
|
//| func - callback which calculates function (or merit |
|
|
//| function) value func at given point x |
|
|
//| grad - callback which calculates function (or merit |
|
|
//| function) value func and gradient grad at given |
|
|
//| point x |
|
|
//| hess - callback which calculates function (or merit |
|
|
//| function) value func, gradient grad and Hessian |
|
|
//| hess at given point x |
|
|
//| rep - optional callback which is called after each |
|
|
//| iteration can be null |
|
|
//| obj - optional object which is passed to |
|
|
//| func/grad/hess/jac/rep can be null |
|
|
//| NOTES: |
|
|
//| 1. this algorithm is somewhat unusual because it works with |
|
|
//| parameterized function f(C,X), where X is a function argument |
|
|
//| (we have many points which are characterized by different |
|
|
//| argument values), and C is a parameter to fit. |
|
|
//| For example, if we want to do linear fit by |
|
|
//| f(c0,c1,x)=c0*x+c1, then x will be argument, and {c0,c1} will |
|
|
//| be parameters. |
|
|
//| It is important to understand that this algorithm finds |
|
|
//| minimum in the space of function PARAMETERS (not arguments), |
|
|
//| so it needs derivatives of f() with respect to C, not X. |
|
|
//| In the example above it will need f=c0*x+c1 and |
|
|
//| {df/dc0,df/dc1}={x,1} instead of {df/dx}={c0}. |
|
|
//| 2. Callback functions accept C as the first parameter, and X as |
|
|
//| the second |
|
|
//| 3. If state was created with LSFitCreateFG(), algorithm needs |
|
|
//| just function and its gradient, but if state wascreated with |
|
|
//| LSFitCreateFGH(), algorithm will need function, gradient and |
|
|
//| Hessian. |
|
|
//| According to the said above, there ase several versions of |
|
|
//| this function, which accept different sets of callbacks. |
|
|
//| This flexibility opens way to subtle errors - you may create |
|
|
//| state with LSFitCreateFGH() (optimization using Hessian), but |
|
|
//| call function which does not accept Hessian. So when algorithm|
|
|
//| will request Hessian, there will be no callback to call. In |
|
|
//| this case exception will be thrown. |
|
|
//| Be careful to avoid such errors because there is no way to |
|
|
//| find them at compile time - you can see them at runtime only. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitFit(CLSFitStateShell &state,CNDimensional_PFunc &func,
|
|
CNDimensional_PGrad &grad,CNDimensional_Rep &rep,
|
|
bool rep_status,CObject &obj)
|
|
{
|
|
//--- cycle
|
|
while(CAlglib::LSFitIteration(state))
|
|
{
|
|
//--- check
|
|
if(state.GetNeedF())
|
|
{
|
|
func.PFunc(state.GetInnerObj().m_c,state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetNeedFG())
|
|
{
|
|
grad.PGrad(state.GetInnerObj().m_c,state.GetInnerObj().m_x,state.GetInnerObj().m_f,state.GetInnerObj().m_g,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetInnerObj().m_xupdated)
|
|
{
|
|
//--- check
|
|
if(rep_status)
|
|
rep.Rep(state.GetInnerObj().m_c,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
Print("ALGLIB: error in 'lsfitfit' (some derivatives were not provided?)");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This family of functions is used to launcn iterations of |
|
|
//| nonlinear fitter |
|
|
//| These functions accept following parameters: |
|
|
//| func - callback which calculates function (or merit |
|
|
//| function) value func at given point x |
|
|
//| grad - callback which calculates function (or merit |
|
|
//| function) value func and gradient grad at given |
|
|
//| point x |
|
|
//| hess - callback which calculates function (or merit |
|
|
//| function) value func, gradient grad and Hessian |
|
|
//| hess at given point x |
|
|
//| rep - optional callback which is called after each |
|
|
//| iteration can be null |
|
|
//| obj - optional object which is passed to |
|
|
//| func/grad/hess/jac/rep can be null |
|
|
//| NOTES: |
|
|
//| 1. this algorithm is somewhat unusual because it works with |
|
|
//| parameterized function f(C,X), where X is a function argument |
|
|
//| (we have many points which are characterized by different |
|
|
//| argument values), and C is a parameter to fit. |
|
|
//| For example, if we want to do linear fit by |
|
|
//| f(c0,c1,x)=c0*x+c1, then x will be argument, and {c0,c1} will |
|
|
//| be parameters. |
|
|
//| It is important to understand that this algorithm finds |
|
|
//| minimum in the space of function PARAMETERS (not arguments), |
|
|
//| so it needs derivatives of f() with respect to C, not X. |
|
|
//| In the example above it will need f=c0*x+c1 and |
|
|
//| {df/dc0,df/dc1}={x,1} instead of {df/dx}={c0}. |
|
|
//| 2. Callback functions accept C as the first parameter, and X as |
|
|
//| the second |
|
|
//| 3. If state was created with LSFitCreateFG(), algorithm needs |
|
|
//| just function and its gradient, but if state wascreated with |
|
|
//| LSFitCreateFGH(), algorithm will need function, gradient and |
|
|
//| Hessian. |
|
|
//| According to the said above, there ase several versions of |
|
|
//| this function, which accept different sets of callbacks. |
|
|
//| This flexibility opens way to subtle errors - you may create |
|
|
//| state with LSFitCreateFGH() (optimization using Hessian), but |
|
|
//| call function which does not accept Hessian. So when algorithm|
|
|
//| will request Hessian, there will be no callback to call. In |
|
|
//| this case exception will be thrown. |
|
|
//| Be careful to avoid such errors because there is no way to |
|
|
//| find them at compile time - you can see them at runtime only. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitFit(CLSFitStateShell &state,CNDimensional_PFunc &func,
|
|
CNDimensional_PGrad &grad,CNDimensional_PHess &hess,
|
|
CNDimensional_Rep &rep,bool rep_status,CObject &obj)
|
|
{
|
|
//--- cycle
|
|
while(CAlglib::LSFitIteration(state))
|
|
{
|
|
//--- check
|
|
if(state.GetNeedF())
|
|
{
|
|
func.PFunc(state.GetInnerObj().m_c,state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetNeedFG())
|
|
{
|
|
grad.PGrad(state.GetInnerObj().m_c,state.GetInnerObj().m_x,state.GetInnerObj().m_f,state.GetInnerObj().m_g,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetNeedFGH())
|
|
{
|
|
hess.PHess(state.GetInnerObj().m_c,state.GetInnerObj().m_x,state.GetInnerObj().m_f,state.GetInnerObj().m_g,state.GetInnerObj().m_h,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetInnerObj().m_xupdated)
|
|
{
|
|
//--- check
|
|
if(rep_status)
|
|
rep.Rep(state.GetInnerObj().m_c,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
Print("ALGLIB: error in 'lsfitfit' (some derivatives were not provided?)");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Nonlinear least squares fitting results. |
|
|
//| Called after return from LSFitFit(). |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - algorithm state |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - completetion code: |
|
|
//| * 1 relative function improvement is no |
|
|
//| more than EpsF. |
|
|
//| * 2 relative step is no more than EpsX. |
|
|
//| * 4 gradient norm is no more than EpsG |
|
|
//| * 5 MaxIts steps was taken |
|
|
//| * 7 stopping conditions are too |
|
|
//| stringent, further improvement is |
|
|
//| impossible |
|
|
//| C - array[0..K-1], solution |
|
|
//| Rep - optimization report. Following fields are set: |
|
|
//| * Rep.TerminationType completetion code: |
|
|
//| * RMSError rms error on the (X,Y). |
|
|
//| * AvgError average error on the (X,Y). |
|
|
//| * AvgRelError average relative error on the|
|
|
//| non-zero Y |
|
|
//| * MaxError maximum error |
|
|
//| NON-WEIGHTED ERRORS ARE |
|
|
//| CALCULATED |
|
|
//| * WRMSError weighted rms error on the |
|
|
//| (X,Y). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LSFitResults(CLSFitStateShell &state,int &info,
|
|
double &c[],CLSFitReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CLSFit::LSFitResults(state.GetInnerObj(),info,c,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function builds non-periodic 2-dimensional parametric |
|
|
//| spline which starts at (X[0],Y[0]) and ends at (X[N-1],Y[N-1]). |
|
|
//| INPUT PARAMETERS: |
|
|
//| XY - points, array[0..N-1,0..1]. |
|
|
//| XY[I,0:1] corresponds to the Ith point. |
|
|
//| Order of points is important! |
|
|
//| N - points count, N>=5 for Akima splines, N>=2 for other |
|
|
//| types of splines. |
|
|
//| ST - spline type: |
|
|
//| * 0 Akima spline |
|
|
//| * 1 parabolically terminated Catmull-Rom spline |
|
|
//| (Tension=0) |
|
|
//| * 2 parabolically terminated cubic spline |
|
|
//| PT - parameterization type: |
|
|
//| * 0 uniform |
|
|
//| * 1 chord length |
|
|
//| * 2 centripetal |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| P - parametric spline interpolant |
|
|
//| NOTES: |
|
|
//| * this function assumes that there all consequent points are |
|
|
//| distinct. I.e. (x0,y0)<>(x1,y1), (x1,y1)<>(x2,y2), |
|
|
//| (x2,y2)<>(x3,y3) and so on. However, non-consequent points may |
|
|
//| coincide, i.e. we can have (x0,y0) = (x2,y2). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PSpline2Build(CMatrixDouble &xy,const int n,const int st,
|
|
const int pt,CPSpline2InterpolantShell &p)
|
|
{
|
|
//--- function call
|
|
CPSpline::PSpline2Build(xy,n,st,pt,p.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function builds non-periodic 3-dimensional parametric spline|
|
|
//| which starts at (X[0],Y[0],Z[0]) and ends at |
|
|
//| (X[N-1],Y[N-1],Z[N-1]). |
|
|
//| Same as PSpline2Build() function, but for 3D, so we won't |
|
|
//| duplicate its description here. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PSpline3Build(CMatrixDouble &xy,const int n,const int st,
|
|
const int pt,CPSpline3InterpolantShell &p)
|
|
{
|
|
//--- function call
|
|
CPSpline::PSpline3Build(xy,n,st,pt,p.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function builds periodic 2-dimensional parametric spline |
|
|
//| which starts at (X[0],Y[0]), goes through all points to |
|
|
//| (X[N-1],Y[N-1]) and then back to (X[0],Y[0]). |
|
|
//| INPUT PARAMETERS: |
|
|
//| XY - points, array[0..N-1,0..1]. |
|
|
//| XY[I,0:1] corresponds to the Ith point. |
|
|
//| XY[N-1,0:1] must be different from XY[0,0:1]. |
|
|
//| Order of points is important! |
|
|
//| N - points count, N>=3 for other types of splines. |
|
|
//| ST - spline type: |
|
|
//| * 1 Catmull-Rom spline (Tension=0) with cyclic |
|
|
//| boundary conditions |
|
|
//| * 2 cubic spline with cyclic boundary conditions |
|
|
//| PT - parameterization type: |
|
|
//| * 0 uniform |
|
|
//| * 1 chord length |
|
|
//| * 2 centripetal |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| P - parametric spline interpolant |
|
|
//| NOTES: |
|
|
//| * this function assumes that there all consequent points are |
|
|
//| distinct. I.e. (x0,y0)<>(x1,y1), (x1,y1)<>(x2,y2), |
|
|
//| (x2,y2)<>(x3,y3) and so on. However, non-consequent points may |
|
|
//| coincide, i.e. we can have (x0,y0) = (x2,y2). |
|
|
//| * last point of sequence is NOT equal to the first point. You |
|
|
//| shouldn't make curve "explicitly periodic" by making them |
|
|
//| equal. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PSpline2BuildPeriodic(CMatrixDouble &xy,const int n,
|
|
const int st,const int pt,
|
|
CPSpline2InterpolantShell &p)
|
|
{
|
|
//--- function call
|
|
CPSpline::PSpline2BuildPeriodic(xy,n,st,pt,p.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function builds periodic 3-dimensional parametric spline |
|
|
//| which starts at (X[0],Y[0],Z[0]), goes through all points to |
|
|
//| (X[N-1],Y[N-1],Z[N-1]) and then back to (X[0],Y[0],Z[0]). |
|
|
//| Same as PSpline2Build() function, but for 3D, so we won't |
|
|
//| duplicate its description here. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PSpline3BuildPeriodic(CMatrixDouble &xy,const int n,
|
|
const int st,const int pt,
|
|
CPSpline3InterpolantShell &p)
|
|
{
|
|
//--- function call
|
|
CPSpline::PSpline3BuildPeriodic(xy,n,st,pt,p.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function returns vector of parameter values correspoding to |
|
|
//| points. |
|
|
//| I.e. for P created from (X[0],Y[0])...(X[N-1],Y[N-1]) and |
|
|
//| U=TValues(P) we have |
|
|
//| (X[0],Y[0]) = PSpline2Calc(P,U[0]), |
|
|
//| (X[1],Y[1]) = PSpline2Calc(P,U[1]), |
|
|
//| (X[2],Y[2]) = PSpline2Calc(P,U[2]), |
|
|
//| ... |
|
|
//| INPUT PARAMETERS: |
|
|
//| P - parametric spline interpolant |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| N - array size |
|
|
//| T - array[0..N-1] |
|
|
//| NOTES: |
|
|
//| * for non-periodic splines U[0]=0, U[0]<U[1]<...<U[N-1], U[N-1]=1|
|
|
//| * for periodic splines U[0]=0, U[0]<U[1]<...<U[N-1], U[N-1]<1|
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PSpline2ParameterValues(CPSpline2InterpolantShell &p,
|
|
int &n,double &t[])
|
|
{
|
|
//--- initialization
|
|
n=0;
|
|
//--- function call
|
|
CPSpline::PSpline2ParameterValues(p.GetInnerObj(),n,t);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function returns vector of parameter values correspoding to |
|
|
//| points. |
|
|
//| Same as PSpline2ParameterValues(), but for 3D. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PSpline3ParameterValues(CPSpline3InterpolantShell &p,
|
|
int &n,double &t[])
|
|
{
|
|
//--- initialization
|
|
n=0;
|
|
//--- function call
|
|
CPSpline::PSpline3ParameterValues(p.GetInnerObj(),n,t);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function calculates the value of the parametric spline for a|
|
|
//| given value of parameter T |
|
|
//| INPUT PARAMETERS: |
|
|
//| P - parametric spline interpolant |
|
|
//| T - point: |
|
|
//| * T in [0,1] corresponds to interval spanned by |
|
|
//| points |
|
|
//| * for non-periodic splines T<0 (or T>1) correspond to|
|
|
//| parts of the curve before the first (after the |
|
|
//| last) point |
|
|
//| * for periodic splines T<0 (or T>1) are projected |
|
|
//| into [0,1] by making T=T-floor(T). |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| X - X-position |
|
|
//| Y - Y-position |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PSpline2Calc(CPSpline2InterpolantShell &p,const double t,
|
|
double &x,double &y)
|
|
{
|
|
//--- initialization
|
|
x=0;
|
|
y=0;
|
|
//--- function call
|
|
CPSpline::PSpline2Calc(p.GetInnerObj(),t,x,y);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function calculates the value of the parametric spline for a|
|
|
//| given value of parameter T. |
|
|
//| INPUT PARAMETERS: |
|
|
//| P - parametric spline interpolant |
|
|
//| T - point: |
|
|
//| * T in [0,1] corresponds to interval spanned by |
|
|
//| points |
|
|
//| * for non-periodic splines T<0 (or T>1) correspond |
|
|
//| to parts of the curve before the first (after the |
|
|
//| last) point |
|
|
//| * for periodic splines T<0 (or T>1) are projected |
|
|
//| into [0,1] by making T=T-floor(T). |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| X - X-position |
|
|
//| Y - Y-position |
|
|
//| Z - Z-position |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PSpline3Calc(CPSpline3InterpolantShell &p,const double t,
|
|
double &x,double &y,double &z)
|
|
{
|
|
//--- initialization
|
|
x=0;
|
|
y=0;
|
|
z=0;
|
|
//--- function call
|
|
CPSpline::PSpline3Calc(p.GetInnerObj(),t,x,y,z);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function calculates tangent vector for a given value of |
|
|
//| parameter T |
|
|
//| INPUT PARAMETERS: |
|
|
//| P - parametric spline interpolant |
|
|
//| T - point: |
|
|
//| * T in [0,1] corresponds to interval spanned by |
|
|
//| points |
|
|
//| * for non-periodic splines T<0 (or T>1) correspond to|
|
|
//| parts of the curve before the first (after the |
|
|
//| last) point |
|
|
//| * for periodic splines T<0 (or T>1) are projected |
|
|
//| into [0,1] by making T=T-floor(T). |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| X - X-component of tangent vector (normalized) |
|
|
//| Y - Y-component of tangent vector (normalized) |
|
|
//| NOTE: |
|
|
//| X^2+Y^2 is either 1 (for non-zero tangent vector) or 0. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PSpline2Tangent(CPSpline2InterpolantShell &p,const double t,
|
|
double &x,double &y)
|
|
{
|
|
//--- initialization
|
|
x=0;
|
|
y=0;
|
|
//--- function call
|
|
CPSpline::PSpline2Tangent(p.GetInnerObj(),t,x,y);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function calculates tangent vector for a given value of |
|
|
//| parameter T |
|
|
//| INPUT PARAMETERS: |
|
|
//| P - parametric spline interpolant |
|
|
//| T - point: |
|
|
//| * T in [0,1] corresponds to interval spanned by |
|
|
//| points |
|
|
//| * for non-periodic splines T<0 (or T>1) correspond to|
|
|
//| parts of the curve before the first (after the |
|
|
//| last) point |
|
|
//| * for periodic splines T<0 (or T>1) are projected |
|
|
//| into [0,1] by making T=T-floor(T). |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| X - X-component of tangent vector (normalized) |
|
|
//| Y - Y-component of tangent vector (normalized) |
|
|
//| Z - Z-component of tangent vector (normalized) |
|
|
//| NOTE: |
|
|
//| X^2+Y^2+Z^2 is either 1 (for non-zero tangent vector) or 0. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PSpline3Tangent(CPSpline3InterpolantShell &p,const double t,
|
|
double &x,double &y,double &z)
|
|
{
|
|
//--- initialization
|
|
x=0;
|
|
y=0;
|
|
z=0;
|
|
//--- function call
|
|
CPSpline::PSpline3Tangent(p.GetInnerObj(),t,x,y,z);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function calculates derivative, i.e. it returns |
|
|
//| (dX/dT,dY/dT). |
|
|
//| INPUT PARAMETERS: |
|
|
//| P - parametric spline interpolant |
|
|
//| T - point: |
|
|
//| * T in [0,1] corresponds to interval spanned by |
|
|
//| points |
|
|
//| * for non-periodic splines T<0 (or T>1) correspond to|
|
|
//| parts of the curve before the first (after the |
|
|
//| last) point |
|
|
//| * for periodic splines T<0 (or T>1) are projected |
|
|
//| into [0,1] by making T=T-floor(T). |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| X - X-value |
|
|
//| DX - X-derivative |
|
|
//| Y - Y-value |
|
|
//| DY - Y-derivative |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PSpline2Diff(CPSpline2InterpolantShell &p,const double t,
|
|
double &x,double &dx,double &y,double &dy)
|
|
{
|
|
//--- initialization
|
|
x=0;
|
|
dx=0;
|
|
y=0;
|
|
dy=0;
|
|
//--- function call
|
|
CPSpline::PSpline2Diff(p.GetInnerObj(),t,x,dx,y,dy);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function calculates derivative, i.e. it returns |
|
|
//| (dX/dT,dY/dT,dZ/dT). |
|
|
//| INPUT PARAMETERS: |
|
|
//| P - parametric spline interpolant |
|
|
//| T - point: |
|
|
//| * T in [0,1] corresponds to interval spanned by |
|
|
//| points |
|
|
//| * for non-periodic splines T<0 (or T>1) correspond to|
|
|
//| parts of the curve before the first (after the |
|
|
//| last) point |
|
|
//| * for periodic splines T<0 (or T>1) are projected |
|
|
//| into [0,1] by making T=T-floor(T). |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| X - X-value |
|
|
//| DX - X-derivative |
|
|
//| Y - Y-value |
|
|
//| DY - Y-derivative |
|
|
//| Z - Z-value |
|
|
//| DZ - Z-derivative |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PSpline3Diff(CPSpline3InterpolantShell &p,const double t,
|
|
double &x,double &dx,double &y,double &dy
|
|
,double &z,double &dz)
|
|
{
|
|
//--- initialization
|
|
x=0;
|
|
dx=0;
|
|
y=0;
|
|
dy=0;
|
|
z=0;
|
|
dz=0;
|
|
//--- function call
|
|
CPSpline::PSpline3Diff(p.GetInnerObj(),t,x,dx,y,dy,z,dz);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function calculates first and second derivative with respect|
|
|
//| to T. |
|
|
//| INPUT PARAMETERS: |
|
|
//| P - parametric spline interpolant |
|
|
//| T - point: |
|
|
//| * T in [0,1] corresponds to interval spanned by |
|
|
//| points |
|
|
//| * for non-periodic splines T<0 (or T>1) correspond to|
|
|
//| parts of the curve before the first (after the |
|
|
//| last) point |
|
|
//| * for periodic splines T<0 (or T>1) are projected |
|
|
//| into [0,1] by making T=T-floor(T). |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| X - X-value |
|
|
//| DX - derivative |
|
|
//| D2X - second derivative |
|
|
//| Y - Y-value |
|
|
//| DY - derivative |
|
|
//| D2Y - second derivative |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PSpline2Diff2(CPSpline2InterpolantShell &p,const double t,
|
|
double &x,double &dx,double &d2x,double &y,
|
|
double &dy,double &d2y)
|
|
{
|
|
//--- initialization
|
|
x=0;
|
|
dx=0;
|
|
d2x=0;
|
|
y=0;
|
|
dy=0;
|
|
d2y=0;
|
|
//--- function call
|
|
CPSpline::PSpline2Diff2(p.GetInnerObj(),t,x,dx,d2x,y,dy,d2y);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function calculates first and second derivative with respect|
|
|
//| to T. |
|
|
//| INPUT PARAMETERS: |
|
|
//| P - parametric spline interpolant |
|
|
//| T - point: |
|
|
//| * T in [0,1] corresponds to interval spanned by |
|
|
//| points |
|
|
//| * for non-periodic splines T<0 (or T>1) correspond to|
|
|
//| parts of the curve before the first (after the |
|
|
//| last) point |
|
|
//| * for periodic splines T<0 (or T>1) are projected |
|
|
//| into [0,1] by making T=T-floor(T). |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| X - X-value |
|
|
//| DX - derivative |
|
|
//| D2X - second derivative |
|
|
//| Y - Y-value |
|
|
//| DY - derivative |
|
|
//| D2Y - second derivative |
|
|
//| Z - Z-value |
|
|
//| DZ - derivative |
|
|
//| D2Z - second derivative |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PSpline3Diff2(CPSpline3InterpolantShell &p,const double t,
|
|
double &x,double &dx,double &d2x,double &y,
|
|
double &dy,double &d2y,double &z,
|
|
double &dz,double &d2z)
|
|
{
|
|
//--- initialization
|
|
x=0;
|
|
dx=0;
|
|
d2x=0;
|
|
y=0;
|
|
dy=0;
|
|
d2y=0;
|
|
z=0;
|
|
dz=0;
|
|
d2z=0;
|
|
//--- function call
|
|
CPSpline::PSpline3Diff2(p.GetInnerObj(),t,x,dx,d2x,y,dy,d2y,z,dz,d2z);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function calculates arc length, i.e. length of curve between|
|
|
//| t=a and t=b. |
|
|
//| INPUT PARAMETERS: |
|
|
//| P - parametric spline interpolant |
|
|
//| A,B - parameter values corresponding to arc ends: |
|
|
//| * B>A will result in positive length returned |
|
|
//| * B<A will result in negative length returned |
|
|
//| RESULT: |
|
|
//| length of arc starting at T=A and ending at T=B. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::PSpline2ArcLength(CPSpline2InterpolantShell &p,
|
|
const double a,const double b)
|
|
{
|
|
//--- return result
|
|
return(CPSpline::PSpline2ArcLength(p.GetInnerObj(),a,b));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function calculates arc length, i.e. length of curve between|
|
|
//| t=a and t=b. |
|
|
//| INPUT PARAMETERS: |
|
|
//| P - parametric spline interpolant |
|
|
//| A,B - parameter values corresponding to arc ends: |
|
|
//| * B>A will result in positive length returned |
|
|
//| * B<A will result in negative length returned |
|
|
//| RESULT: |
|
|
//| length of arc starting at T=A and ending at T=B. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::PSpline3ArcLength(CPSpline3InterpolantShell &p,
|
|
const double a,const double b)
|
|
{
|
|
//--- return result
|
|
return(CPSpline::PSpline3ArcLength(p.GetInnerObj(),a,b));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine builds bilinear spline coefficients table. |
|
|
//| Input parameters: |
|
|
//| X - spline abscissas, array[0..N-1] |
|
|
//| Y - spline ordinates, array[0..M-1] |
|
|
//| F - function values, array[0..M-1,0..N-1] |
|
|
//| M,N - grid size, M>=2, N>=2 |
|
|
//| Output parameters: |
|
|
//| C - spline interpolant |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline2DBuildBilinear(double &x[],double &y[],
|
|
CMatrixDouble &f,const int m,
|
|
const int n,CSpline2DInterpolantShell &c)
|
|
{
|
|
//--- function call
|
|
CSpline2D::Spline2DBuildBilinear(x,y,f,m,n,c.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine builds bicubic spline coefficients table. |
|
|
//| Input parameters: |
|
|
//| X - spline abscissas, array[0..N-1] |
|
|
//| Y - spline ordinates, array[0..M-1] |
|
|
//| F - function values, array[0..M-1,0..N-1] |
|
|
//| M,N - grid size, M>=2, N>=2 |
|
|
//| Output parameters: |
|
|
//| C - spline interpolant |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline2DBuildBicubic(double &x[],double &y[],CMatrixDouble &f,
|
|
const int m,const int n,
|
|
CSpline2DInterpolantShell &c)
|
|
{
|
|
//--- function call
|
|
CSpline2D::Spline2DBuildBicubic(x,y,f,m,n,c.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine calculates the value of the bilinear or bicubic |
|
|
//| spline at the given point X. |
|
|
//| Input parameters: |
|
|
//| C - coefficients table. |
|
|
//| Built by BuildBilinearSpline or BuildBicubicSpline. |
|
|
//| X, Y- point |
|
|
//| Result: |
|
|
//| S(x,y) |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::Spline2DCalc(CSpline2DInterpolantShell &c,
|
|
const double x,const double y)
|
|
{
|
|
//--- return result
|
|
return(CSpline2D::Spline2DCalc(c.GetInnerObj(),x,y));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine calculates the value of the bilinear or bicubic |
|
|
//| spline at the given point X and its derivatives. |
|
|
//| Input parameters: |
|
|
//| C - spline interpolant. |
|
|
//| X, Y- point |
|
|
//| Output parameters: |
|
|
//| F - S(x,y) |
|
|
//| FX - dS(x,y)/dX |
|
|
//| FY - dS(x,y)/dY |
|
|
//| FXY - d2S(x,y)/dXdY |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline2DDiff(CSpline2DInterpolantShell &c,const double x,
|
|
const double y,double &f,double &fx,
|
|
double &fy,double &fxy)
|
|
{
|
|
//--- initialization
|
|
f=0;
|
|
fx=0;
|
|
fy=0;
|
|
fxy=0;
|
|
//--- function call
|
|
CSpline2D::Spline2DDiff(c.GetInnerObj(),x,y,f,fx,fy,fxy);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine unpacks two-dimensional spline into the |
|
|
//| coefficients table |
|
|
//| Input parameters: |
|
|
//| C - spline interpolant. |
|
|
//| Result: |
|
|
//| M, N- grid size (x-axis and y-axis) |
|
|
//| Tbl - coefficients table, unpacked format, |
|
|
//| [0..(N-1)*(M-1)-1, 0..19]. |
|
|
//| For I = 0...M-2, J=0..N-2: |
|
|
//| K = I*(N-1)+J |
|
|
//| Tbl[K,0] = X[j] |
|
|
//| Tbl[K,1] = X[j+1] |
|
|
//| Tbl[K,2] = Y[i] |
|
|
//| Tbl[K,3] = Y[i+1] |
|
|
//| Tbl[K,4] = C00 |
|
|
//| Tbl[K,5] = C01 |
|
|
//| Tbl[K,6] = C02 |
|
|
//| Tbl[K,7] = C03 |
|
|
//| Tbl[K,8] = C10 |
|
|
//| Tbl[K,9] = C11 |
|
|
//| ... |
|
|
//| Tbl[K,19] = C33 |
|
|
//| On each grid square spline is equals to: |
|
|
//| S(x) = SUM(c[i,j]*(x^i)*(y^j), i=0..3, j=0..3) |
|
|
//| t = x-x[j] |
|
|
//| u = y-y[i] |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline2DUnpack(CSpline2DInterpolantShell &c,int &m,
|
|
int &n,CMatrixDouble &tbl)
|
|
{
|
|
//--- initialization
|
|
m=0;
|
|
n=0;
|
|
//--- function call
|
|
CSpline2D::Spline2DUnpack(c.GetInnerObj(),m,n,tbl);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine performs linear transformation of the spline |
|
|
//| argument. |
|
|
//| Input parameters: |
|
|
//| C - spline interpolant |
|
|
//| AX, BX - transformation coefficients: x = A*t + B |
|
|
//| AY, BY - transformation coefficients: y = A*u + B |
|
|
//| Result: |
|
|
//| C - transformed spline |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline2DLinTransXY(CSpline2DInterpolantShell &c,
|
|
const double ax,const double bx,
|
|
const double ay,const double by)
|
|
{
|
|
//--- function call
|
|
CSpline2D::Spline2DLinTransXY(c.GetInnerObj(),ax,bx,ay,by);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine performs linear transformation of the spline. |
|
|
//| Input parameters: |
|
|
//| C - spline interpolant. |
|
|
//| A, B- transformation coefficients: S2(x,y) = A*S(x,y) + B |
|
|
//| Output parameters: |
|
|
//| C - transformed spline |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline2DLinTransF(CSpline2DInterpolantShell &c,
|
|
const double a,const double b)
|
|
{
|
|
//--- function call
|
|
CSpline2D::Spline2DLinTransF(c.GetInnerObj(),a,b);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Bicubic spline resampling |
|
|
//| Input parameters: |
|
|
//| A - function values at the old grid, |
|
|
//| array[0..OldHeight-1, 0..OldWidth-1] |
|
|
//| OldHeight - old grid height, OldHeight>1 |
|
|
//| OldWidth - old grid width, OldWidth>1 |
|
|
//| NewHeight - new grid height, NewHeight>1 |
|
|
//| NewWidth - new grid width, NewWidth>1 |
|
|
//| Output parameters: |
|
|
//| B - function values at the new grid, |
|
|
//| array[0..NewHeight-1, 0..NewWidth-1] |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline2DResampleBicubic(CMatrixDouble &a,const int oldheight,
|
|
const int oldwidth,CMatrixDouble &b,
|
|
const int newheight,const int newwidth)
|
|
{
|
|
//--- function call
|
|
CSpline2D::Spline2DResampleBicubic(a,oldheight,oldwidth,b,newheight,newwidth);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Bilinear spline resampling |
|
|
//| Input parameters: |
|
|
//| A - function values at the old grid, |
|
|
//| array[0..OldHeight-1, 0..OldWidth-1] |
|
|
//| OldHeight - old grid height, OldHeight>1 |
|
|
//| OldWidth - old grid width, OldWidth>1 |
|
|
//| NewHeight - new grid height, NewHeight>1 |
|
|
//| NewWidth - new grid width, NewWidth>1 |
|
|
//| Output parameters: |
|
|
//| B - function values at the new grid, |
|
|
//| array[0..NewHeight-1, 0..NewWidth-1] |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Spline2DResampleBilinear(CMatrixDouble &a,const int oldheight,
|
|
const int oldwidth,CMatrixDouble &b,
|
|
const int newheight,const int newwidth)
|
|
{
|
|
//--- function call
|
|
CSpline2D::Spline2DResampleBilinear(a,oldheight,oldwidth,b,newheight,newwidth);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Cache-oblivous complex "copy-and-transpose" |
|
|
//| Input parameters: |
|
|
//| M - number of rows |
|
|
//| N - number of columns |
|
|
//| A - source matrix, MxN submatrix is copied and transposed|
|
|
//| IA - submatrix offset (row index) |
|
|
//| JA - submatrix offset (column index) |
|
|
//| A - destination matrix |
|
|
//| IB - submatrix offset (row index) |
|
|
//| JB - submatrix offset (column index) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixTranspose(const int m,const int n,CMatrixComplex &a,
|
|
const int ia,const int ja,CMatrixComplex &b,
|
|
const int ib,const int jb)
|
|
{
|
|
//--- function call
|
|
CAblas::CMatrixTranspose(m,n,a,ia,ja,b,ib,jb);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Cache-oblivous real "copy-and-transpose" |
|
|
//| Input parameters: |
|
|
//| M - number of rows |
|
|
//| N - number of columns |
|
|
//| A - source matrix, MxN submatrix is copied and transposed|
|
|
//| IA - submatrix offset (row index) |
|
|
//| JA - submatrix offset (column index) |
|
|
//| A - destination matrix |
|
|
//| IB - submatrix offset (row index) |
|
|
//| JB - submatrix offset (column index) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixTranspose(const int m,const int n,CMatrixDouble &a,
|
|
const int ia,const int ja,CMatrixDouble &b,
|
|
const int ib,const int jb)
|
|
{
|
|
//--- function call
|
|
CAblas::RMatrixTranspose(m,n,a,ia,ja,b,ib,jb);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Copy |
|
|
//| Input parameters: |
|
|
//| M - number of rows |
|
|
//| N - number of columns |
|
|
//| A - source matrix, MxN submatrix is copied and transposed|
|
|
//| IA - submatrix offset (row index) |
|
|
//| JA - submatrix offset (column index) |
|
|
//| B - destination matrix |
|
|
//| IB - submatrix offset (row index) |
|
|
//| JB - submatrix offset (column index) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixCopy(const int m,const int n,CMatrixComplex &a,
|
|
const int ia,const int ja,CMatrixComplex &b,
|
|
const int ib,const int jb)
|
|
{
|
|
//--- function call
|
|
CAblas::CMatrixCopy(m,n,a,ia,ja,b,ib,jb);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Copy |
|
|
//| Input parameters: |
|
|
//| M - number of rows |
|
|
//| N - number of columns |
|
|
//| A - source matrix, MxN submatrix is copied and transposed|
|
|
//| IA - submatrix offset (row index) |
|
|
//| JA - submatrix offset (column index) |
|
|
//| B - destination matrix |
|
|
//| IB - submatrix offset (row index) |
|
|
//| JB - submatrix offset (column index) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixCopy(const int m,const int n,CMatrixDouble &a,
|
|
const int ia,const int ja,CMatrixDouble &b,
|
|
const int ib,const int jb)
|
|
{
|
|
//--- function call
|
|
CAblas::RMatrixCopy(m,n,a,ia,ja,b,ib,jb);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Rank-1 correction: A := A + u*v' |
|
|
//| INPUT PARAMETERS: |
|
|
//| M - number of rows |
|
|
//| N - number of columns |
|
|
//| A - target matrix, MxN submatrix is updated |
|
|
//| IA - submatrix offset (row index) |
|
|
//| JA - submatrix offset (column index) |
|
|
//| U - vector #1 |
|
|
//| IU - subvector offset |
|
|
//| V - vector #2 |
|
|
//| IV - subvector offset |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixRank1(const int m,const int n,CMatrixComplex &a,
|
|
const int ia,const int ja,complex &u[],
|
|
const int iu,complex &v[],const int iv)
|
|
{
|
|
//--- function call
|
|
CAblas::CMatrixRank1(m,n,a,ia,ja,u,iu,v,iv);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Rank-1 correction: A := A + u*v' |
|
|
//| INPUT PARAMETERS: |
|
|
//| M - number of rows |
|
|
//| N - number of columns |
|
|
//| A - target matrix, MxN submatrix is updated |
|
|
//| IA - submatrix offset (row index) |
|
|
//| JA - submatrix offset (column index) |
|
|
//| U - vector #1 |
|
|
//| IU - subvector offset |
|
|
//| V - vector #2 |
|
|
//| IV - subvector offset |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixRank1(const int m,const int n,CMatrixDouble &a,
|
|
const int ia,const int ja,double &u[],
|
|
const int iu,double &v[],const int iv)
|
|
{
|
|
//--- function call
|
|
CAblas::RMatrixRank1(m,n,a,ia,ja,u,iu,v,iv);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Matrix-vector product: y := op(A)*x |
|
|
//| INPUT PARAMETERS: |
|
|
//| M - number of rows of op(A) |
|
|
//| M>=0 |
|
|
//| N - number of columns of op(A) |
|
|
//| N>=0 |
|
|
//| A - target matrix |
|
|
//| IA - submatrix offset (row index) |
|
|
//| JA - submatrix offset (column index) |
|
|
//| OpA - operation type: |
|
|
//| * OpA=0 => op(A) = A |
|
|
//| * OpA=1 => op(A) = A^T |
|
|
//| * OpA=2 => op(A) = A^H |
|
|
//| X - input vector |
|
|
//| IX - subvector offset |
|
|
//| IY - subvector offset |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Y - vector which stores result |
|
|
//| if M=0, then subroutine does nothing. |
|
|
//| if N=0, Y is filled by zeros. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixMVect(const int m,const int n,CMatrixComplex &a,
|
|
const int ia,const int ja,const int opa,
|
|
complex &x[],const int ix,complex &y[],
|
|
const int iy)
|
|
{
|
|
//--- function call
|
|
CAblas::CMatrixMVect(m,n,a,ia,ja,opa,x,ix,y,iy);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Matrix-vector product: y := op(A)*x |
|
|
//| INPUT PARAMETERS: |
|
|
//| M - number of rows of op(A) |
|
|
//| N - number of columns of op(A) |
|
|
//| A - target matrix |
|
|
//| IA - submatrix offset (row index) |
|
|
//| JA - submatrix offset (column index) |
|
|
//| OpA - operation type: |
|
|
//| * OpA=0 => op(A) = A |
|
|
//| * OpA=1 => op(A) = A^T |
|
|
//| X - input vector |
|
|
//| IX - subvector offset |
|
|
//| IY - subvector offset |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Y - vector which stores result |
|
|
//| if M=0, then subroutine does nothing. |
|
|
//| if N=0, Y is filled by zeros. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixMVect(const int m,const int n,CMatrixDouble &a,
|
|
const int ia,const int ja,const int opa,
|
|
double &x[],const int ix,double &y[],
|
|
const int iy)
|
|
{
|
|
//--- function call
|
|
CAblas::RMatrixMVect(m,n,a,ia,ja,opa,x,ix,y,iy);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine calculates X*op(A^-1) where: |
|
|
//| * X is MxN general matrix |
|
|
//| * A is NxN upper/lower triangular/unitriangular matrix |
|
|
//| * "op" may be identity transformation, transposition, conjugate |
|
|
//| transposition |
|
|
//| Multiplication result replaces X. |
|
|
//| Cache-oblivious algorithm is used. |
|
|
//| INPUT PARAMETERS |
|
|
//| N - matrix size, N>=0 |
|
|
//| M - matrix size, N>=0 |
|
|
//| A - matrix, actial matrix is stored in |
|
|
//| A[I1:I1+N-1,J1:J1+N-1] |
|
|
//| I1 - submatrix offset |
|
|
//| J1 - submatrix offset |
|
|
//| IsUpper - whether matrix is upper triangular |
|
|
//| IsUnit - whether matrix is unitriangular |
|
|
//| OpType - transformation type: |
|
|
//| * 0 - no transformation |
|
|
//| * 1 - transposition |
|
|
//| * 2 - conjugate transposition |
|
|
//| C - matrix, actial matrix is stored in |
|
|
//| C[I2:I2+M-1,J2:J2+N-1] |
|
|
//| I2 - submatrix offset |
|
|
//| J2 - submatrix offset |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixRightTrsM(const int m,const int n,CMatrixComplex &a,
|
|
const int i1,const int j1,const bool isupper,
|
|
const bool isunit,const int optype,
|
|
CMatrixComplex &x,const int i2,const int j2)
|
|
{
|
|
//--- function call
|
|
CAblas::CMatrixRightTrsM(m,n,a,i1,j1,isupper,isunit,optype,x,i2,j2);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine calculates op(A^-1)*X where: |
|
|
//| * X is MxN general matrix |
|
|
//| * A is MxM upper/lower triangular/unitriangular matrix |
|
|
//| * "op" may be identity transformation, transposition, conjugate |
|
|
//| transposition |
|
|
//| Multiplication result replaces X. |
|
|
//| Cache-oblivious algorithm is used. |
|
|
//| INPUT PARAMETERS |
|
|
//| N - matrix size, N>=0 |
|
|
//| M - matrix size, N>=0 |
|
|
//| A - matrix, actial matrix is stored in |
|
|
//| A[I1:I1+M-1,J1:J1+M-1] |
|
|
//| I1 - submatrix offset |
|
|
//| J1 - submatrix offset |
|
|
//| IsUpper - whether matrix is upper triangular |
|
|
//| IsUnit - whether matrix is unitriangular |
|
|
//| OpType - transformation type: |
|
|
//| * 0 - no transformation |
|
|
//| * 1 - transposition |
|
|
//| * 2 - conjugate transposition |
|
|
//| C - matrix, actial matrix is stored in |
|
|
//| C[I2:I2+M-1,J2:J2+N-1] |
|
|
//| I2 - submatrix offset |
|
|
//| J2 - submatrix offset |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixLeftTrsM(const int m,const int n,CMatrixComplex &a,
|
|
const int i1,const int j1,const bool isupper,
|
|
const bool isunit,const int optype,
|
|
CMatrixComplex &x,const int i2,const int j2)
|
|
{
|
|
//--- function call
|
|
CAblas::CMatrixLeftTrsM(m,n,a,i1,j1,isupper,isunit,optype,x,i2,j2);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Same as CMatrixRightTRSM, but for real matrices |
|
|
//| OpType may be only 0 or 1. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixRightTrsM(const int m,const int n,CMatrixDouble &a,
|
|
const int i1,const int j1,const bool isupper,
|
|
const bool isunit,const int optype,
|
|
CMatrixDouble &x,const int i2,const int j2)
|
|
{
|
|
//--- function call
|
|
CAblas::RMatrixRightTrsM(m,n,a,i1,j1,isupper,isunit,optype,x,i2,j2);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Same as CMatrixLeftTRSM, but for real matrices |
|
|
//| OpType may be only 0 or 1. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixLeftTrsM(const int m,const int n,CMatrixDouble &a,
|
|
const int i1,const int j1,const bool isupper,
|
|
const bool isunit,const int optype,
|
|
CMatrixDouble &x,const int i2,const int j2)
|
|
{
|
|
//--- function call
|
|
CAblas::RMatrixLeftTrsM(m,n,a,i1,j1,isupper,isunit,optype,x,i2,j2);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine calculates C=alpha*A*A^H+beta*C or |
|
|
//| C=alpha*A^H*A+beta*C where: |
|
|
//| * C is NxN Hermitian matrix given by its upper/lower triangle |
|
|
//| * A is NxK matrix when A*A^H is calculated, KxN matrix otherwise |
|
|
//| Additional info: |
|
|
//| * cache-oblivious algorithm is used. |
|
|
//| * multiplication result replaces C. If Beta=0, C elements are not|
|
|
//| used in calculations (not multiplied by zero - just not |
|
|
//| referenced) |
|
|
//| * if Alpha=0, A is not used (not multiplied by zero - just not |
|
|
//| referenced) |
|
|
//| * if both Beta and Alpha are zero, C is filled by zeros. |
|
|
//| INPUT PARAMETERS |
|
|
//| N - matrix size, N>=0 |
|
|
//| K - matrix size, K>=0 |
|
|
//| Alpha - coefficient |
|
|
//| A - matrix |
|
|
//| IA - submatrix offset |
|
|
//| JA - submatrix offset |
|
|
//| OpTypeA - multiplication type: |
|
|
//| * 0 - A*A^H is calculated |
|
|
//| * 2 - A^H*A is calculated |
|
|
//| Beta - coefficient |
|
|
//| C - matrix |
|
|
//| IC - submatrix offset |
|
|
//| JC - submatrix offset |
|
|
//| IsUpper - whether C is upper triangular or lower triangular|
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixSyrk(const int n,const int k,const double alpha,
|
|
CMatrixComplex &a,const int ia,const int ja,
|
|
const int optypea,const double beta,CMatrixComplex &c,
|
|
const int ic,const int jc,const bool isupper)
|
|
{
|
|
//--- function call
|
|
CAblas::CMatrixSyrk(n,k,alpha,a,ia,ja,optypea,beta,c,ic,jc,isupper);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Same as CMatrixSYRK, but for real matrices |
|
|
//| OpType may be only 0 or 1. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixSyrk(const int n,const int k,const double alpha,
|
|
CMatrixDouble &a,const int ia,const int ja,
|
|
const int optypea,const double beta,
|
|
CMatrixDouble &c,const int ic,
|
|
const int jc,const bool isupper)
|
|
{
|
|
//--- function call
|
|
CAblas::RMatrixSyrk(n,k,alpha,a,ia,ja,optypea,beta,c,ic,jc,isupper);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine calculates C = alpha*op1(A)*op2(B) +beta*C where:|
|
|
//| * C is MxN general matrix |
|
|
//| * op1(A) is MxK matrix |
|
|
//| * op2(B) is KxN matrix |
|
|
//| * "op" may be identity transformation, transposition, conjugate |
|
|
//| transposition |
|
|
//| Additional info: |
|
|
//| * cache-oblivious algorithm is used. |
|
|
//| * multiplication result replaces C. If Beta=0, C elements are not|
|
|
//| used in calculations (not multiplied by zero - just not |
|
|
//| referenced) |
|
|
//| * if Alpha=0, A is not used (not multiplied by zero - just not |
|
|
//| referenced) |
|
|
//| * if both Beta and Alpha are zero, C is filled by zeros. |
|
|
//| INPUT PARAMETERS |
|
|
//| N - matrix size, N>0 |
|
|
//| M - matrix size, N>0 |
|
|
//| K - matrix size, K>0 |
|
|
//| Alpha - coefficient |
|
|
//| A - matrix |
|
|
//| IA - submatrix offset |
|
|
//| JA - submatrix offset |
|
|
//| OpTypeA - transformation type: |
|
|
//| * 0 - no transformation |
|
|
//| * 1 - transposition |
|
|
//| * 2 - conjugate transposition |
|
|
//| B - matrix |
|
|
//| IB - submatrix offset |
|
|
//| JB - submatrix offset |
|
|
//| OpTypeB - transformation type: |
|
|
//| * 0 - no transformation |
|
|
//| * 1 - transposition |
|
|
//| * 2 - conjugate transposition |
|
|
//| Beta - coefficient |
|
|
//| C - matrix |
|
|
//| IC - submatrix offset |
|
|
//| JC - submatrix offset |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixGemm(const int m,const int n,const int k,
|
|
complex &alpha,CMatrixComplex &a,
|
|
const int ia,const int ja,const int optypea,
|
|
CMatrixComplex &b,const int ib,const int jb,
|
|
const int optypeb,complex &beta,CMatrixComplex &c,
|
|
const int ic,const int jc)
|
|
{
|
|
//--- function call
|
|
CAblas::CMatrixGemm(m,n,k,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Same as CMatrixGEMM, but for real numbers. |
|
|
//| OpType may be only 0 or 1. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixGemm(const int m,const int n,const int k,
|
|
const double alpha,CMatrixDouble &a,
|
|
const int ia,const int ja,const int optypea,
|
|
CMatrixDouble &b,const int ib,const int jb,
|
|
const int optypeb,const double beta,
|
|
CMatrixDouble &c,const int ic,const int jc)
|
|
{
|
|
//--- function call
|
|
CAblas::RMatrixGemm(m,n,k,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| QR decomposition of a rectangular matrix of size MxN |
|
|
//| Input parameters: |
|
|
//| A - matrix A whose indexes range within [0..M-1, 0..N-1].|
|
|
//| M - number of rows in matrix A. |
|
|
//| N - number of columns in matrix A. |
|
|
//| Output parameters: |
|
|
//| A - matrices Q and R in compact form (see below). |
|
|
//| Tau - array of scalar factors which are used to form |
|
|
//| matrix Q. Array whose index ranges within |
|
|
//| [0.. Min(M-1,N-1)]. |
|
|
//| Matrix A is represented as A = QR, where Q is an orthogonal |
|
|
//| matrix of size MxM, R - upper triangular (or upper trapezoid) |
|
|
//| matrix of size M x N. |
|
|
//| The elements of matrix R are located on and above the main |
|
|
//| diagonal of matrix A. The elements which are located in Tau |
|
|
//| array and below the main diagonal of matrix A are used to form |
|
|
//| matrix Q as follows: |
|
|
//| Matrix Q is represented as a product of elementary reflections |
|
|
//| Q = H(0)*H(2)*...*H(k-1), |
|
|
//| where k = min(m,n), and each H(i) is in the form |
|
|
//| H(i) = 1 - tau * v * (v^T) |
|
|
//| where tau is a scalar stored in Tau[I]; v - real vector, |
|
|
//| so that v(0:i-1) = 0, v(i) = 1, v(i+1:m-1) stored in |
|
|
//| A(i+1:m-1,i). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixQR(CMatrixDouble &a,const int m,const int n,
|
|
double &tau[])
|
|
{
|
|
//--- function call
|
|
COrtFac::RMatrixQR(a,m,n,tau);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| LQ decomposition of a rectangular matrix of size MxN |
|
|
//| Input parameters: |
|
|
//| A - matrix A whose indexes range within [0..M-1, 0..N-1].|
|
|
//| M - number of rows in matrix A. |
|
|
//| N - number of columns in matrix A. |
|
|
//| Output parameters: |
|
|
//| A - matrices L and Q in compact form (see below) |
|
|
//| Tau - array of scalar factors which are used to form |
|
|
//| matrix Q. Array whose index ranges within |
|
|
//| [0..Min(M,N)-1]. |
|
|
//| Matrix A is represented as A = LQ, where Q is an orthogonal |
|
|
//| matrix of size MxM, L - lower triangular (or lower trapezoid) |
|
|
//| matrix of size M x N. |
|
|
//| The elements of matrix L are located on and below the main |
|
|
//| diagonal of matrix A. The elements which are located in Tau |
|
|
//| array and above the main diagonal of matrix A are used to form |
|
|
//| matrix Q as follows: |
|
|
//| Matrix Q is represented as a product of elementary reflections |
|
|
//| Q = H(k-1)*H(k-2)*...*H(1)*H(0), |
|
|
//| where k = min(m,n), and each H(i) is of the form |
|
|
//| H(i) = 1 - tau * v * (v^T) |
|
|
//| where tau is a scalar stored in Tau[I]; v - real vector, so that |
|
|
//| v(0:i-1)=0, v(i) = 1, v(i+1:n-1) stored in A(i,i+1:n-1). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixLQ(CMatrixDouble &a,const int m,const int n,
|
|
double &tau[])
|
|
{
|
|
//--- function call
|
|
COrtFac::RMatrixLQ(a,m,n,tau);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| QR decomposition of a rectangular complex matrix of size MxN |
|
|
//| Input parameters: |
|
|
//| A - matrix A whose indexes range within [0..M-1, 0..N-1] |
|
|
//| M - number of rows in matrix A. |
|
|
//| N - number of columns in matrix A. |
|
|
//| Output parameters: |
|
|
//| A - matrices Q and R in compact form |
|
|
//| Tau - array of scalar factors which are used to form |
|
|
//| matrix Q. Array whose indexes range within |
|
|
//| [0.. Min(M,N)-1] |
|
|
//| Matrix A is represented as A = QR, where Q is an orthogonal |
|
|
//| matrix of size MxM, R - upper triangular (or upper trapezoid) |
|
|
//| matrix of size MxN. |
|
|
//| -- LAPACK routine (version 3.0) -- |
|
|
//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., |
|
|
//| Courant Institute, Argonne National Lab, and Rice University|
|
|
//| September 30, 1994 |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixQR(CMatrixComplex &a,const int m,const int n,
|
|
complex &tau[])
|
|
{
|
|
//--- function call
|
|
COrtFac::CMatrixQR(a,m,n,tau);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| LQ decomposition of a rectangular complex matrix of size MxN |
|
|
//| Input parameters: |
|
|
//| A - matrix A whose indexes range within [0..M-1, 0..N-1] |
|
|
//| M - number of rows in matrix A. |
|
|
//| N - number of columns in matrix A. |
|
|
//| Output parameters: |
|
|
//| A - matrices Q and L in compact form |
|
|
//| Tau - array of scalar factors which are used to form |
|
|
//| matrix Q. Array whose indexes range within |
|
|
//| [0.. Min(M,N)-1] |
|
|
//| Matrix A is represented as A = LQ, where Q is an orthogonal |
|
|
//| matrix of size MxM, L - lower triangular (or lower trapezoid) |
|
|
//| matrix of size MxN. |
|
|
//| -- LAPACK routine (version 3.0) -- |
|
|
//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., |
|
|
//| Courant Institute, Argonne National Lab, and Rice University|
|
|
//| September 30, 1994 |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixLQ(CMatrixComplex &a,const int m,const int n,
|
|
complex &tau[])
|
|
{
|
|
//--- function call
|
|
COrtFac::CMatrixLQ(a,m,n,tau);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Partial unpacking of matrix Q from the QR decomposition of a |
|
|
//| matrix A |
|
|
//| Input parameters: |
|
|
//| A - matrices Q and R in compact form. |
|
|
//| Output of RMatrixQR subroutine. |
|
|
//| M - number of rows in given matrix A. M>=0. |
|
|
//| N - number of columns in given matrix A. N>=0. |
|
|
//| Tau - scalar factors which are used to form Q. |
|
|
//| Output of the RMatrixQR subroutine. |
|
|
//| QColumns - required number of columns of matrix Q. |
|
|
//| M>=QColumns>=0. |
|
|
//| Output parameters: |
|
|
//| Q - first QColumns columns of matrix Q. |
|
|
//| Array whose indexes range within |
|
|
//| [0..M-1, 0..QColumns-1]. |
|
|
//| If QColumns=0, the array remains unchanged. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixQRUnpackQ(CMatrixDouble &a,const int m,const int n,
|
|
double &tau[],const int qcolumns,
|
|
CMatrixDouble &q)
|
|
{
|
|
//--- function call
|
|
COrtFac::RMatrixQRUnpackQ(a,m,n,tau,qcolumns,q);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Unpacking of matrix R from the QR decomposition of a matrix A |
|
|
//| Input parameters: |
|
|
//| A - matrices Q and R in compact form. |
|
|
//| Output of RMatrixQR subroutine. |
|
|
//| M - number of rows in given matrix A. M>=0. |
|
|
//| N - number of columns in given matrix A. N>=0. |
|
|
//| Output parameters: |
|
|
//| R - matrix R, array[0..M-1, 0..N-1]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixQRUnpackR(CMatrixDouble &a,const int m,
|
|
const int n,CMatrixDouble &r)
|
|
{
|
|
//--- function call
|
|
COrtFac::RMatrixQRUnpackR(a,m,n,r);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Partial unpacking of matrix Q from LQ decomposition of a complex |
|
|
//| matrix A. |
|
|
//| Input parameters: |
|
|
//| A - matrices Q and R in compact form. |
|
|
//| Output of CMatrixLQ subroutine. |
|
|
//| M - number of rows in matrix A. M>=0. |
|
|
//| N - number of columns in matrix A. N>=0. |
|
|
//| Tau - scalar factors which are used to form Q. |
|
|
//| Output of CMatrixLQ subroutine . |
|
|
//| QRows - required number of rows in matrix Q. |
|
|
//| N>=QColumns>=0. |
|
|
//| Output parameters: |
|
|
//| Q - first QRows rows of matrix Q. |
|
|
//| Array whose index ranges within [0..QRows-1, |
|
|
//| 0..N-1]. |
|
|
//| If QRows=0, array isn't changed. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixLQUnpackQ(CMatrixDouble &a,const int m,const int n,
|
|
double &tau[],const int qrows,
|
|
CMatrixDouble &q)
|
|
{
|
|
//--- function call
|
|
COrtFac::RMatrixLQUnpackQ(a,m,n,tau,qrows,q);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Unpacking of matrix L from the LQ decomposition of a matrix A |
|
|
//| Input parameters: |
|
|
//| A -matrices Q and L in compact form. |
|
|
//| Output of RMatrixLQ subroutine. |
|
|
//| M -number of rows in given matrix A. M>=0. |
|
|
//| N -number of columns in given matrix A. N>=0. |
|
|
//| Output parameters: |
|
|
//| L -matrix L, array[0..M-1,0..N-1]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixLQUnpackL(CMatrixDouble &a,const int m,
|
|
const int n,CMatrixDouble &l)
|
|
{
|
|
//--- function call
|
|
COrtFac::RMatrixLQUnpackL(a,m,n,l);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Partial unpacking of matrix Q from QR decomposition of a complex |
|
|
//| matrix A. |
|
|
//| Input parameters: |
|
|
//| A - matrices Q and R in compact form. |
|
|
//| Output of CMatrixQR subroutine . |
|
|
//| M - number of rows in matrix A. M>=0. |
|
|
//| N - number of columns in matrix A. N>=0. |
|
|
//| Tau - scalar factors which are used to form Q. |
|
|
//| Output of CMatrixQR subroutine . |
|
|
//| QColumns - required number of columns in matrix Q. |
|
|
//| M>=QColumns>=0. |
|
|
//| Output parameters: |
|
|
//| Q - first QColumns columns of matrix Q. |
|
|
//| Array whose index ranges within [0..M-1, |
|
|
//| 0..QColumns-1]. |
|
|
//| If QColumns=0, array isn't changed. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixQRUnpackQ(CMatrixComplex &a,const int m,
|
|
const int n,complex &tau[],
|
|
const int qcolumns,CMatrixComplex &q)
|
|
{
|
|
//--- function call
|
|
COrtFac::CMatrixQRUnpackQ(a,m,n,tau,qcolumns,q);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Unpacking of matrix R from the QR decomposition of a matrix A |
|
|
//| Input parameters: |
|
|
//| A - matrices Q and R in compact form. |
|
|
//| Output of CMatrixQR subroutine. |
|
|
//| M - number of rows in given matrix A. M>=0. |
|
|
//| N - number of columns in given matrix A. N>=0. |
|
|
//| Output parameters: |
|
|
//| R - matrix R, array[0..M-1, 0..N-1]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixQRUnpackR(CMatrixComplex &a,const int m,
|
|
const int n,CMatrixComplex &r)
|
|
{
|
|
//--- function call
|
|
COrtFac::CMatrixQRUnpackR(a,m,n,r);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Partial unpacking of matrix Q from LQ decomposition of a complex |
|
|
//| matrix A. |
|
|
//| Input parameters: |
|
|
//| A - matrices Q and R in compact form. |
|
|
//| Output of CMatrixLQ subroutine. |
|
|
//| M - number of rows in matrix A. M>=0. |
|
|
//| N - number of columns in matrix A. N>=0. |
|
|
//| Tau - scalar factors which are used to form Q. |
|
|
//| Output of CMatrixLQ subroutine . |
|
|
//| QRows - required number of rows in matrix Q. |
|
|
//| N>=QColumns>=0. |
|
|
//| Output parameters: |
|
|
//| Q - first QRows rows of matrix Q. |
|
|
//| Array whose index ranges within [0..QRows-1, |
|
|
//| 0..N-1]. |
|
|
//| If QRows=0, array isn't changed. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixLQUnpackQ(CMatrixComplex &a,const int m,
|
|
const int n,complex &tau[],
|
|
const int qrows,CMatrixComplex &q)
|
|
{
|
|
//--- function call
|
|
COrtFac::CMatrixLQUnpackQ(a,m,n,tau,qrows,q);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Unpacking of matrix L from the LQ decomposition of a matrix A |
|
|
//| Input parameters: |
|
|
//| A - matrices Q and L in compact form. |
|
|
//| Output of CMatrixLQ subroutine. |
|
|
//| M - number of rows in given matrix A. M>=0. |
|
|
//| N - number of columns in given matrix A. N>=0. |
|
|
//| Output parameters: |
|
|
//| L - matrix L, array[0..M-1, 0..N-1]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixLQUnpackL(CMatrixComplex &a,const int m,
|
|
const int n,CMatrixComplex &l)
|
|
{
|
|
//--- function call
|
|
COrtFac::CMatrixLQUnpackL(a,m,n,l);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Reduction of a rectangular matrix to bidiagonal form |
|
|
//| The algorithm reduces the rectangular matrix A to bidiagonal |
|
|
//| form by orthogonal transformations P and Q: A = Q*B*P. |
|
|
//| Input parameters: |
|
|
//| A - source matrix. array[0..M-1, 0..N-1] |
|
|
//| M - number of rows in matrix A. |
|
|
//| N - number of columns in matrix A. |
|
|
//| Output parameters: |
|
|
//| A - matrices Q, B, P in compact form (see below). |
|
|
//| TauQ - scalar factors which are used to form matrix Q. |
|
|
//| TauP - scalar factors which are used to form matrix P. |
|
|
//| The main diagonal and one of the secondary diagonals of matrix A |
|
|
//| are replaced with bidiagonal matrix B. Other elements contain |
|
|
//| elementary reflections which form MxM matrix Q and NxN matrix P, |
|
|
//| respectively. |
|
|
//| If M>=N, B is the upper bidiagonal MxN matrix and is stored in |
|
|
//| the corresponding elements of matrix A. Matrix Q is represented |
|
|
//| as a product of elementary reflections Q = H(0)*H(1)*...*H(n-1), |
|
|
//| where H(i) = 1-tau*v*v'. Here tau is a scalar which is stored in |
|
|
//| TauQ[i], and vector v has the following structure: v(0:i-1)=0, |
|
|
//| v(i)=1, v(i+1:m-1) is stored in elements A(i+1:m-1,i).Matrix P is|
|
|
//| as follows: P = G(0)*G(1)*...*G(n-2), where G(i) = 1 - tau*u*u'. |
|
|
//| Tau is stored in TauP[i], u(0:i)=0, u(i+1)=1, u(i+2:n-1) is |
|
|
//| stored in elements A(i,i+2:n-1). |
|
|
//| If M<N, B is the lower bidiagonal MxN matrix and is stored in the|
|
|
//| corresponding elements of matrix A. Q = H(0)*H(1)*...*H(m-2), |
|
|
//| where H(i) = 1 - tau*v*v', tau is stored in TauQ, v(0:i)=0, |
|
|
//| v(i+1)=1, v(i+2:m-1) is stored in elements A(i+2:m-1,i). |
|
|
//| P = G(0)*G(1)*...*G(m-1), G(i) = 1-tau*u*u', tau is stored in |
|
|
//| TauP, u(0:i-1)=0, u(i)=1, u(i+1:n-1) is stored in A(i,i+1:n-1). |
|
|
//| EXAMPLE: |
|
|
//| m=6, n=5 (m > n): m=5, n=6 (m < n): |
|
|
//| ( d e u1 u1 u1 ) ( d u1 u1 u1 u1 u1 ) |
|
|
//| ( v1 d e u2 u2 ) ( e d u2 u2 u2 u2 ) |
|
|
//| ( v1 v2 d e u3 ) ( v1 e d u3 u3 u3 ) |
|
|
//| ( v1 v2 v3 d e ) ( v1 v2 e d u4 u4 ) |
|
|
//| ( v1 v2 v3 v4 d ) ( v1 v2 v3 e d u5 ) |
|
|
//| ( v1 v2 v3 v4 v5 ) |
|
|
//| Here vi and ui are vectors which form H(i) and G(i), and d and |
|
|
//| e - are the diagonal and off-diagonal elements of matrix B. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixBD(CMatrixDouble &a,const int m,const int n,
|
|
double &tauq[],double &taup[])
|
|
{
|
|
//--- function call
|
|
COrtFac::RMatrixBD(a,m,n,tauq,taup);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Unpacking matrix Q which reduces a matrix to bidiagonal form. |
|
|
//| Input parameters: |
|
|
//| QP - matrices Q and P in compact form. |
|
|
//| Output of ToBidiagonal subroutine. |
|
|
//| M - number of rows in matrix A. |
|
|
//| N - number of columns in matrix A. |
|
|
//| TAUQ - scalar factors which are used to form Q. |
|
|
//| Output of ToBidiagonal subroutine. |
|
|
//| QColumns - required number of columns in matrix Q. |
|
|
//| M>=QColumns>=0. |
|
|
//| Output parameters: |
|
|
//| Q - first QColumns columns of matrix Q. |
|
|
//| Array[0..M-1, 0..QColumns-1] |
|
|
//| If QColumns=0, the array is not modified. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixBDUnpackQ(CMatrixDouble &qp,const int m,
|
|
const int n,double &tauq[],
|
|
const int qcolumns,CMatrixDouble &q)
|
|
{
|
|
//--- function call
|
|
COrtFac::RMatrixBDUnpackQ(qp,m,n,tauq,qcolumns,q);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Multiplication by matrix Q which reduces matrix A to bidiagonal |
|
|
//| form. |
|
|
//| The algorithm allows pre- or post-multiply by Q or Q'. |
|
|
//| Input parameters: |
|
|
//| QP - matrices Q and P in compact form. |
|
|
//| Output of ToBidiagonal subroutine. |
|
|
//| M - number of rows in matrix A. |
|
|
//| N - number of columns in matrix A. |
|
|
//| TAUQ - scalar factors which are used to form Q. |
|
|
//| Output of ToBidiagonal subroutine. |
|
|
//| Z - multiplied matrix. |
|
|
//| array[0..ZRows-1,0..ZColumns-1] |
|
|
//| ZRows - number of rows in matrix Z. If FromTheRight= |
|
|
//| =False, ZRows=M, otherwise ZRows can be |
|
|
//| arbitrary. |
|
|
//| ZColumns - number of columns in matrix Z. If |
|
|
//| FromTheRight=True, ZColumns=M, otherwise |
|
|
//| ZColumns can be arbitrary. |
|
|
//| FromTheRight - pre- or post-multiply. |
|
|
//| DoTranspose - multiply by Q or Q'. |
|
|
//| Output parameters: |
|
|
//| Z - product of Z and Q. |
|
|
//| Array[0..ZRows-1,0..ZColumns-1] |
|
|
//| If ZRows=0 or ZColumns=0, the array is not |
|
|
//| modified. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixBDMultiplyByQ(CMatrixDouble &qp,const int m,
|
|
const int n,double &tauq[],
|
|
CMatrixDouble &z,const int zrows,
|
|
const int zcolumns,const bool fromtheright,
|
|
const bool dotranspose)
|
|
{
|
|
//--- function call
|
|
COrtFac::RMatrixBDMultiplyByQ(qp,m,n,tauq,z,zrows,zcolumns,fromtheright,dotranspose);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Unpacking matrix P which reduces matrix A to bidiagonal form. |
|
|
//| The subroutine returns transposed matrix P. |
|
|
//| Input parameters: |
|
|
//| QP - matrices Q and P in compact form. |
|
|
//| Output of ToBidiagonal subroutine. |
|
|
//| M - number of rows in matrix A. |
|
|
//| N - number of columns in matrix A. |
|
|
//| TAUP - scalar factors which are used to form P. |
|
|
//| Output of ToBidiagonal subroutine. |
|
|
//| PTRows - required number of rows of matrix P^T. |
|
|
//| N >= PTRows >= 0. |
|
|
//| Output parameters: |
|
|
//| PT - first PTRows columns of matrix P^T |
|
|
//| Array[0..PTRows-1, 0..N-1] |
|
|
//| If PTRows=0, the array is not modified. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixBDUnpackPT(CMatrixDouble &qp,const int m,
|
|
const int n,double &taup[],
|
|
const int ptrows,CMatrixDouble &pt)
|
|
{
|
|
//--- function call
|
|
COrtFac::RMatrixBDUnpackPT(qp,m,n,taup,ptrows,pt);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Multiplication by matrix P which reduces matrix A to bidiagonal |
|
|
//| form. |
|
|
//| The algorithm allows pre- or post-multiply by P or P'. |
|
|
//| Input parameters: |
|
|
//| QP - matrices Q and P in compact form. |
|
|
//| Output of RMatrixBD subroutine. |
|
|
//| M - number of rows in matrix A. |
|
|
//| N - number of columns in matrix A. |
|
|
//| TAUP - scalar factors which are used to form P. |
|
|
//| Output of RMatrixBD subroutine. |
|
|
//| Z - multiplied matrix. |
|
|
//| Array whose indexes range within |
|
|
//| [0..ZRows-1,0..ZColumns-1]. |
|
|
//| ZRows - number of rows in matrix Z. If |
|
|
//| FromTheRight=False, ZRows=N, otherwise ZRows |
|
|
//| can be arbitrary. |
|
|
//| ZColumns - number of columns in matrix Z. If |
|
|
//| FromTheRight=True, ZColumns=N, otherwise |
|
|
//| ZColumns can be arbitrary. |
|
|
//| FromTheRight - pre- or post-multiply. |
|
|
//| DoTranspose - multiply by P or P'. |
|
|
//| Output parameters: |
|
|
//| Z - product of Z and P. |
|
|
//| Array whose indexes range within |
|
|
//| [0..ZRows-1,0..ZColumns-1]. If ZRows=0 or |
|
|
//| ZColumns=0, the array is not modified. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixBDMultiplyByP(CMatrixDouble &qp,const int m,
|
|
const int n,double &taup[],
|
|
CMatrixDouble &z,const int zrows,
|
|
const int zcolumns,const bool fromtheright,
|
|
const bool dotranspose)
|
|
{
|
|
//--- function call
|
|
COrtFac::RMatrixBDMultiplyByP(qp,m,n,taup,z,zrows,zcolumns,fromtheright,dotranspose);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Unpacking of the main and secondary diagonals of bidiagonal |
|
|
//| decomposition of matrix A. |
|
|
//| Input parameters: |
|
|
//| B - output of RMatrixBD subroutine. |
|
|
//| M - number of rows in matrix B. |
|
|
//| N - number of columns in matrix B. |
|
|
//| Output parameters: |
|
|
//| IsUpper - True, if the matrix is upper bidiagonal. |
|
|
//| otherwise IsUpper is False. |
|
|
//| D - the main diagonal. |
|
|
//| Array whose index ranges within [0..Min(M,N)-1]. |
|
|
//| E - the secondary diagonal (upper or lower, depending|
|
|
//| on the value of IsUpper). |
|
|
//| Array index ranges within [0..Min(M,N)-1], the |
|
|
//| last element is not used. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixBDUnpackDiagonals(CMatrixDouble &b,const int m,
|
|
const int n,bool &isupper,
|
|
double &d[],double &e[])
|
|
{
|
|
//--- initialization
|
|
isupper=false;
|
|
//--- function call
|
|
COrtFac::RMatrixBDUnpackDiagonals(b,m,n,isupper,d,e);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Reduction of a square matrix to upper Hessenberg form: |
|
|
//| Q'*A*Q = H, where Q is an orthogonal matrix, H - Hessenberg |
|
|
//| matrix. |
|
|
//| Input parameters: |
|
|
//| A - matrix A with elements [0..N-1, 0..N-1] |
|
|
//| N - size of matrix A. |
|
|
//| Output parameters: |
|
|
//| A - matrices Q and P in compact form (see below). |
|
|
//| Tau - array of scalar factors which are used to form |
|
|
//| matrix Q. |
|
|
//| Array whose index ranges within [0..N-2] |
|
|
//| Matrix H is located on the main diagonal, on the lower secondary |
|
|
//| diagonal and above the main diagonal of matrix A. The elements |
|
|
//| which are used to form matrix Q are situated in array Tau and |
|
|
//| below the lower secondary diagonal of matrix A as follows: |
|
|
//| Matrix Q is represented as a product of elementary reflections |
|
|
//| Q = H(0)*H(2)*...*H(n-2), |
|
|
//| where each H(i) is given by |
|
|
//| H(i) = 1 - tau * v * (v^T) |
|
|
//| where tau is a scalar stored in Tau[I]; v - is a real vector, |
|
|
//| so that v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) stored in |
|
|
//| A(i+2:n-1,i). |
|
|
//| -- LAPACK routine (version 3.0) -- |
|
|
//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., |
|
|
//| Courant Institute, Argonne National Lab, and Rice University|
|
|
//| October 31, 1992 |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixHessenberg(CMatrixDouble &a,const int n,
|
|
double &tau[])
|
|
{
|
|
//--- function call
|
|
COrtFac::RMatrixHessenberg(a,n,tau);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Unpacking matrix Q which reduces matrix A to upper Hessenberg |
|
|
//| form |
|
|
//| Input parameters: |
|
|
//| A - output of RMatrixHessenberg subroutine. |
|
|
//| N - size of matrix A. |
|
|
//| Tau - scalar factors which are used to form Q. |
|
|
//| Output of RMatrixHessenberg subroutine. |
|
|
//| Output parameters: |
|
|
//| Q - matrix Q. |
|
|
//| Array whose indexes range within [0..N-1, 0..N-1]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixHessenbergUnpackQ(CMatrixDouble &a,const int n,
|
|
double &tau[],CMatrixDouble &q)
|
|
{
|
|
//--- function call
|
|
COrtFac::RMatrixHessenbergUnpackQ(a,n,tau,q);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Unpacking matrix H (the result of matrix A reduction to upper |
|
|
//| Hessenberg form) |
|
|
//| Input parameters: |
|
|
//| A - output of RMatrixHessenberg subroutine. |
|
|
//| N - size of matrix A. |
|
|
//| Output parameters: |
|
|
//| H - matrix H. Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixHessenbergUnpackH(CMatrixDouble &a,const int n,
|
|
CMatrixDouble &h)
|
|
{
|
|
//--- function call
|
|
COrtFac::RMatrixHessenbergUnpackH(a,n,h);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Reduction of a symmetric matrix which is given by its higher or |
|
|
//| lower triangular part to a tridiagonal matrix using orthogonal |
|
|
//| similarity transformation: Q'*A*Q=T. |
|
|
//| Input parameters: |
|
|
//| A - matrix to be transformed |
|
|
//| array with elements [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| IsUpper - storage format. If IsUpper = True, then matrix A |
|
|
//| is given by its upper triangle, and the lower |
|
|
//| triangle is not used and not modified by the |
|
|
//| algorithm, and vice versa if IsUpper = False. |
|
|
//| Output parameters: |
|
|
//| A - matrices T and Q in compact form (see lower) |
|
|
//| Tau - array of factors which are forming matrices H(i) |
|
|
//| array with elements [0..N-2]. |
|
|
//| D - main diagonal of symmetric matrix T. |
|
|
//| array with elements [0..N-1]. |
|
|
//| E - secondary diagonal of symmetric matrix T. |
|
|
//| array with elements [0..N-2]. |
|
|
//| If IsUpper=True, the matrix Q is represented as a product of |
|
|
//| elementary reflectors |
|
|
//| Q = H(n-2) . . . H(2) H(0). |
|
|
//| Each H(i) has the form |
|
|
//| H(i) = I - tau * v * v' |
|
|
//| where tau is a real scalar, and v is a real vector with |
|
|
//| v(i+1:n-1) = 0, v(i) = 1, v(0:i-1) is stored on exit in |
|
|
//| A(0:i-1,i+1), and tau in TAU(i). |
|
|
//| If IsUpper=False, the matrix Q is represented as a product of |
|
|
//| elementary reflectors |
|
|
//| Q = H(0) H(2) . . . H(n-2). |
|
|
//| Each H(i) has the form |
|
|
//| H(i) = I - tau * v * v' |
|
|
//| where tau is a real scalar, and v is a real vector with |
|
|
//| v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) is stored on exit in |
|
|
//| A(i+2:n-1,i), and tau in TAU(i). |
|
|
//| The contents of A on exit are illustrated by the following |
|
|
//| examples with n = 5: |
|
|
//| if UPLO = 'U': if UPLO = 'L': |
|
|
//| ( d e v1 v2 v3 ) ( d ) |
|
|
//| ( d e v2 v3 ) ( e d ) |
|
|
//| ( d e v3 ) ( v0 e d ) |
|
|
//| ( d e ) ( v0 v1 e d ) |
|
|
//| ( d ) ( v0 v1 v2 e d ) |
|
|
//| where d and e denote diagonal and off-diagonal elements of T, |
|
|
//| and vi denotes an element of the vector defining H(i). |
|
|
//| -- LAPACK routine (version 3.0) -- |
|
|
//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., |
|
|
//| Courant Institute, Argonne National Lab, and Rice University|
|
|
//| October 31, 1992 |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SMatrixTD(CMatrixDouble &a,const int n,const bool isupper,
|
|
double &tau[],double &d[],double &e[])
|
|
{
|
|
//--- function call
|
|
COrtFac::SMatrixTD(a,n,isupper,tau,d,e);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Unpacking matrix Q which reduces symmetric matrix to a |
|
|
//| tridiagonal form. |
|
|
//| Input parameters: |
|
|
//| A - the result of a SMatrixTD subroutine |
|
|
//| N - size of matrix A. |
|
|
//| IsUpper - storage format (a parameter of SMatrixTD |
|
|
//| subroutine) |
|
|
//| Tau - the result of a SMatrixTD subroutine |
|
|
//| Output parameters: |
|
|
//| Q - transformation matrix. |
|
|
//| array with elements [0..N-1, 0..N-1]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SMatrixTDUnpackQ(CMatrixDouble &a,const int n,
|
|
const bool isupper,double &tau[],
|
|
CMatrixDouble &q)
|
|
{
|
|
//--- function call
|
|
COrtFac::SMatrixTDUnpackQ(a,n,isupper,tau,q);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Reduction of a Hermitian matrix which is given by its higher or |
|
|
//| lower triangular part to a real tridiagonal matrix using unitary |
|
|
//| similarity transformation: Q'*A*Q = T. |
|
|
//| Input parameters: |
|
|
//| A - matrix to be transformed |
|
|
//| array with elements [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| IsUpper - storage format. If IsUpper = True, then matrix A |
|
|
//| is given by its upper triangle, and the lower |
|
|
//| triangle is not used and not modified by the |
|
|
//| algorithm, and vice versa if IsUpper = False. |
|
|
//| Output parameters: |
|
|
//| A - matrices T and Q in compact form (see lower) |
|
|
//| Tau - array of factors which are forming matrices H(i) |
|
|
//| array with elements [0..N-2]. |
|
|
//| D - main diagonal of real symmetric matrix T. |
|
|
//| array with elements [0..N-1]. |
|
|
//| E - secondary diagonal of real symmetric matrix T. |
|
|
//| array with elements [0..N-2]. |
|
|
//| If IsUpper=True, the matrix Q is represented as a product of |
|
|
//| elementary reflectors |
|
|
//| Q = H(n-2) . . . H(2) H(0). |
|
|
//| Each H(i) has the form |
|
|
//| H(i) = I - tau * v * v' |
|
|
//| where tau is a complex scalar, and v is a complex vector with |
|
|
//| v(i+1:n-1) = 0, v(i) = 1, v(0:i-1) is stored on exit in |
|
|
//| A(0:i-1,i+1), and tau in TAU(i). |
|
|
//| If IsUpper=False, the matrix Q is represented as a product of |
|
|
//| elementary reflectors |
|
|
//| Q = H(0) H(2) . . . H(n-2). |
|
|
//| Each H(i) has the form |
|
|
//| H(i) = I - tau * v * v' |
|
|
//| where tau is a complex scalar, and v is a complex vector with |
|
|
//| v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) is stored on exit in |
|
|
//| A(i+2:n-1,i), and tau in TAU(i). |
|
|
//| The contents of A on exit are illustrated by the following |
|
|
//| examples with n = 5: |
|
|
//| if UPLO = 'U': if UPLO = 'L': |
|
|
//| ( d e v1 v2 v3 ) ( d ) |
|
|
//| ( d e v2 v3 ) ( e d ) |
|
|
//| ( d e v3 ) ( v0 e d ) |
|
|
//| ( d e ) ( v0 v1 e d ) |
|
|
//| ( d ) ( v0 v1 v2 e d ) |
|
|
//| where d and e denote diagonal and off-diagonal elements of T, and|
|
|
//| vi denotes an element of the vector defining H(i). |
|
|
//| -- LAPACK routine (version 3.0) -- |
|
|
//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., |
|
|
//| Courant Institute, Argonne National Lab, and Rice University|
|
|
//| October 31, 1992 |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::HMatrixTD(CMatrixComplex &a,const int n,const bool isupper,
|
|
complex &tau[],double &d[],double &e[])
|
|
{
|
|
//--- function call
|
|
COrtFac::HMatrixTD(a,n,isupper,tau,d,e);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Unpacking matrix Q which reduces a Hermitian matrix to a real |
|
|
//| tridiagonal form. |
|
|
//| Input parameters: |
|
|
//| A - the result of a HMatrixTD subroutine |
|
|
//| N - size of matrix A. |
|
|
//| IsUpper - storage format (a parameter of HMatrixTD |
|
|
//| subroutine) |
|
|
//| Tau - the result of a HMatrixTD subroutine |
|
|
//| Output parameters: |
|
|
//| Q - transformation matrix. |
|
|
//| array with elements [0..N-1, 0..N-1]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::HMatrixTDUnpackQ(CMatrixComplex &a,const int n,
|
|
const bool isupper,complex &tau[],
|
|
CMatrixComplex &q)
|
|
{
|
|
//--- function call
|
|
COrtFac::HMatrixTDUnpackQ(a,n,isupper,tau,q);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Finding the eigenvalues and eigenvectors of a symmetric matrix |
|
|
//| The algorithm finds eigen pairs of a symmetric matrix by reducing|
|
|
//| it to tridiagonal form and using the QL/QR algorithm. |
|
|
//| Input parameters: |
|
|
//| A - symmetric matrix which is given by its upper or |
|
|
//| lower triangular part. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| ZNeeded - flag controlling whether the eigenvectors are |
|
|
//| needed or not. |
|
|
//| If ZNeeded is equal to: |
|
|
//| * 0, the eigenvectors are not returned; |
|
|
//| * 1, the eigenvectors are returned. |
|
|
//| IsUpper - storage format. |
|
|
//| Output parameters: |
|
|
//| D - eigenvalues in ascending order. |
|
|
//| Array whose index ranges within [0..N-1]. |
|
|
//| Z - if ZNeeded is equal to: |
|
|
//| * 0, Z hasn?t changed; |
|
|
//| * 1, Z contains the eigenvectors. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| The eigenvectors are stored in the matrix |
|
|
//| columns. |
|
|
//| Result: |
|
|
//| True, if the algorithm has converged. |
|
|
//| False, if the algorithm hasn't converged (rare case). |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::SMatrixEVD(CMatrixDouble &a,const int n,int zneeded,
|
|
const bool isupper,double &d[],
|
|
CMatrixDouble &z)
|
|
{
|
|
//--- return result
|
|
return(CEigenVDetect::SMatrixEVD(a,n,zneeded,isupper,d,z));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Subroutine for finding the eigenvalues (and eigenvectors) of a |
|
|
//| symmetric matrix in a given half open interval (A, B] by using a |
|
|
//| bisection and inverse iteration |
|
|
//| Input parameters: |
|
|
//| A - symmetric matrix which is given by its upper or |
|
|
//| lower triangular part. Array [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| ZNeeded - flag controlling whether the eigenvectors are |
|
|
//| needed or not. |
|
|
//| If ZNeeded is equal to: |
|
|
//| * 0, the eigenvectors are not returned; |
|
|
//| * 1, the eigenvectors are returned. |
|
|
//| IsUpperA - storage format of matrix A. |
|
|
//| B1, B2 - half open interval (B1, B2] to search |
|
|
//| eigenvalues in. |
|
|
//| Output parameters: |
|
|
//| M - number of eigenvalues found in a given |
|
|
//| half-interval (M>=0). |
|
|
//| W - array of the eigenvalues found. |
|
|
//| Array whose index ranges within [0..M-1]. |
|
|
//| Z - if ZNeeded is equal to: |
|
|
//| * 0, Z hasn?t changed; |
|
|
//| * 1, Z contains eigenvectors. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..M-1]. |
|
|
//| The eigenvectors are stored in the matrix |
|
|
//| columns. |
|
|
//| Result: |
|
|
//| True, if successful. M contains the number of eigenvalues in |
|
|
//| the given half-interval (could be equal to 0), W contains the|
|
|
//| eigenvalues, Z contains the eigenvectors (if needed). |
|
|
//| False, if the bisection method subroutine wasn't able to find|
|
|
//| the eigenvalues in the given interval or if the inverse |
|
|
//| iteration subroutine wasn't able to find all the |
|
|
//| corresponding eigenvectors. In that case, the eigenvalues |
|
|
//| and eigenvectors are not returned, M is equal to 0. |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::SMatrixEVDR(CMatrixDouble &a,const int n,int zneeded,
|
|
const bool isupper,double b1,double b2,
|
|
int &m,double &w[],CMatrixDouble &z)
|
|
{
|
|
//--- initialization
|
|
m=0;
|
|
//--- return result
|
|
return(CEigenVDetect::SMatrixEVDR(a,n,zneeded,isupper,b1,b2,m,w,z));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Subroutine for finding the eigenvalues and eigenvectors of a |
|
|
//| symmetric matrix with given indexes by using bisection and |
|
|
//| inverse iteration methods. |
|
|
//| Input parameters: |
|
|
//| A - symmetric matrix which is given by its upper or |
|
|
//| lower triangular part. Array whose indexes range |
|
|
//| within [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| ZNeeded - flag controlling whether the eigenvectors are |
|
|
//| needed or not. |
|
|
//| If ZNeeded is equal to: |
|
|
//| * 0, the eigenvectors are not returned; |
|
|
//| * 1, the eigenvectors are returned. |
|
|
//| IsUpperA - storage format of matrix A. |
|
|
//| I1, I2 - index interval for searching (from I1 to I2). |
|
|
//| 0 <= I1 <= I2 <= N-1. |
|
|
//| Output parameters: |
|
|
//| W - array of the eigenvalues found. |
|
|
//| Array whose index ranges within [0..I2-I1]. |
|
|
//| Z - if ZNeeded is equal to: |
|
|
//| * 0, Z hasn?t changed; |
|
|
//| * 1, Z contains eigenvectors. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..I2-I1]. |
|
|
//| In that case, the eigenvectors are stored in the |
|
|
//| matrix columns. |
|
|
//| Result: |
|
|
//| True, if successful. W contains the eigenvalues, Z contains |
|
|
//| the eigenvectors (if needed). |
|
|
//| False, if the bisection method subroutine wasn't able to find|
|
|
//| the eigenvalues in the given interval or if the inverse |
|
|
//| iteration subroutine wasn't able to find all the |
|
|
//| corresponding eigenvectors. In that case, the eigenvalues |
|
|
//| and eigenvectors are not returned. |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::SMatrixEVDI(CMatrixDouble &a,const int n,int zneeded,
|
|
const bool isupper,const int i1,
|
|
const int i2,double &w[],CMatrixDouble &z)
|
|
{
|
|
//--- return result
|
|
return(CEigenVDetect::SMatrixEVDI(a,n,zneeded,isupper,i1,i2,w,z));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Finding the eigenvalues and eigenvectors of a Hermitian matrix |
|
|
//| The algorithm finds eigen pairs of a Hermitian matrix by reducing|
|
|
//| it to real tridiagonal form and using the QL/QR algorithm. |
|
|
//| Input parameters: |
|
|
//| A - Hermitian matrix which is given by its upper or |
|
|
//| lower triangular part. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| IsUpper - storage format. |
|
|
//| ZNeeded - flag controlling whether the eigenvectors are |
|
|
//| needed or not. If ZNeeded is equal to: |
|
|
//| * 0, the eigenvectors are not returned; |
|
|
//| * 1, the eigenvectors are returned. |
|
|
//| Output parameters: |
|
|
//| D - eigenvalues in ascending order. |
|
|
//| Array whose index ranges within [0..N-1]. |
|
|
//| Z - if ZNeeded is equal to: |
|
|
//| * 0, Z hasn?t changed; |
|
|
//| * 1, Z contains the eigenvectors. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| The eigenvectors are stored in the matrix |
|
|
//| columns. |
|
|
//| Result: |
|
|
//| True, if the algorithm has converged. |
|
|
//| False, if the algorithm hasn't converged (rare case). |
|
|
//| Note: |
|
|
//| eigenvectors of Hermitian matrix are defined up to |
|
|
//| multiplication by a complex number L, such that |L|=1. |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::HMatrixEVD(CMatrixComplex &a,const int n,const int zneeded,
|
|
const bool isupper,double &d[],CMatrixComplex &z)
|
|
{
|
|
//--- return result
|
|
return(CEigenVDetect::HMatrixEVD(a,n,zneeded,isupper,d,z));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Subroutine for finding the eigenvalues (and eigenvectors) of a |
|
|
//| Hermitian matrix in a given half-interval (A, B] by using a |
|
|
//| bisection and inverse iteration |
|
|
//| Input parameters: |
|
|
//| A - Hermitian matrix which is given by its upper or |
|
|
//| lower triangular part. Array whose indexes range |
|
|
//| within [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| ZNeeded - flag controlling whether the eigenvectors are |
|
|
//| needed or not. If ZNeeded is equal to: |
|
|
//| * 0, the eigenvectors are not returned; |
|
|
//| * 1, the eigenvectors are returned. |
|
|
//| IsUpperA - storage format of matrix A. |
|
|
//| B1, B2 - half-interval (B1, B2] to search eigenvalues in. |
|
|
//| Output parameters: |
|
|
//| M - number of eigenvalues found in a given |
|
|
//| half-interval, M>=0 |
|
|
//| W - array of the eigenvalues found. |
|
|
//| Array whose index ranges within [0..M-1]. |
|
|
//| Z - if ZNeeded is equal to: |
|
|
//| * 0, Z hasn?t changed; |
|
|
//| * 1, Z contains eigenvectors. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..M-1]. |
|
|
//| The eigenvectors are stored in the matrix |
|
|
//| columns. |
|
|
//| Result: |
|
|
//| True, if successful. M contains the number of eigenvalues |
|
|
//| in the given half-interval (could be equal to 0), W contains |
|
|
//| the eigenvalues, Z contains the eigenvectors (if needed). |
|
|
//| False, if the bisection method subroutine wasn't able to find|
|
|
//| the eigenvalues in the given interval or if the inverse |
|
|
//| iteration subroutine wasn't able to find all the |
|
|
//| corresponding eigenvectors. In that case, the eigenvalues and|
|
|
//| eigenvectors are not returned, M is equal to 0. |
|
|
//| Note: |
|
|
//| eigen vectors of Hermitian matrix are defined up to |
|
|
//| multiplication by a complex number L, such as |L|=1. |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::HMatrixEVDR(CMatrixComplex &a,const int n,const int zneeded,
|
|
const bool isupper,double b1,double b2,
|
|
int &m,double &w[],CMatrixComplex &z)
|
|
{
|
|
//--- initialization
|
|
m=0;
|
|
//--- return result
|
|
return(CEigenVDetect::HMatrixEVDR(a,n,zneeded,isupper,b1,b2,m,w,z));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Subroutine for finding the eigenvalues and eigenvectors of a |
|
|
//| Hermitian matrix with given indexes by using bisection and |
|
|
//| inverse iteration methods |
|
|
//| Input parameters: |
|
|
//| A - Hermitian matrix which is given by its upper or |
|
|
//| lower triangular part. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| ZNeeded - flag controlling whether the eigenvectors are |
|
|
//| needed or not. If ZNeeded is equal to: |
|
|
//| * 0, the eigenvectors are not returned; |
|
|
//| * 1, the eigenvectors are returned. |
|
|
//| IsUpperA - storage format of matrix A. |
|
|
//| I1, I2 - index interval for searching (from I1 to I2). |
|
|
//| 0 <= I1 <= I2 <= N-1. |
|
|
//| Output parameters: |
|
|
//| W - array of the eigenvalues found. |
|
|
//| Array whose index ranges within [0..I2-I1]. |
|
|
//| Z - if ZNeeded is equal to: |
|
|
//| * 0, Z hasn?t changed; |
|
|
//| * 1, Z contains eigenvectors. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..I2-I1]. |
|
|
//| In that case, the eigenvectors are stored in |
|
|
//| the matrix columns. |
|
|
//| Result: |
|
|
//| True, if successful. W contains the eigenvalues, Z contains |
|
|
//| the eigenvectors (if needed). |
|
|
//| False, if the bisection method subroutine wasn't able to find|
|
|
//| the eigenvalues in the given interval or if the inverse |
|
|
//| corresponding eigenvectors. iteration subroutine wasn't able |
|
|
//| to find all the corresponding eigenvectors. In that case, |
|
|
//| the eigenvalues and eigenvectors are not returned. |
|
|
//| Note: |
|
|
//| eigen vectors of Hermitian matrix are defined up to |
|
|
//| multiplication by a complex number L, such as |L|=1. |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::HMatrixEVDI(CMatrixComplex &a,const int n,const int zneeded,
|
|
const bool isupper,const int i1,const int i2,
|
|
double &w[],CMatrixComplex &z)
|
|
{
|
|
//--- return result
|
|
return(CEigenVDetect::HMatrixEVDI(a,n,zneeded,isupper,i1,i2,w,z));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Finding the eigenvalues and eigenvectors of a tridiagonal |
|
|
//| symmetric matrix |
|
|
//| The algorithm finds the eigen pairs of a tridiagonal symmetric |
|
|
//| matrix by using an QL/QR algorithm with implicit shifts. |
|
|
//| Input parameters: |
|
|
//| D - the main diagonal of a tridiagonal matrix. |
|
|
//| Array whose index ranges within [0..N-1]. |
|
|
//| E - the secondary diagonal of a tridiagonal matrix. |
|
|
//| Array whose index ranges within [0..N-2]. |
|
|
//| N - size of matrix A. |
|
|
//| ZNeeded - flag controlling whether the eigenvectors are |
|
|
//| needed or not. |
|
|
//| If ZNeeded is equal to: |
|
|
//| * 0, the eigenvectors are not needed; |
|
|
//| * 1, the eigenvectors of a tridiagonal matrix |
|
|
//| are multiplied by the square matrix Z. It is |
|
|
//| used if the tridiagonal matrix is obtained by |
|
|
//| the similarity transformation of a symmetric |
|
|
//| matrix; |
|
|
//| * 2, the eigenvectors of a tridiagonal matrix |
|
|
//| replace the square matrix Z; |
|
|
//| * 3, matrix Z contains the first row of the |
|
|
//| eigenvectors matrix. |
|
|
//| Z - if ZNeeded=1, Z contains the square matrix by |
|
|
//| which the eigenvectors are multiplied. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| Output parameters: |
|
|
//| D - eigenvalues in ascending order. |
|
|
//| Array whose index ranges within [0..N-1]. |
|
|
//| Z - if ZNeeded is equal to: |
|
|
//| * 0, Z hasn?t changed; |
|
|
//| * 1, Z contains the product of a given matrix |
|
|
//| (from the left) and the eigenvectors matrix |
|
|
//| (from the right); |
|
|
//| * 2, Z contains the eigenvectors. |
|
|
//| * 3, Z contains the first row of the |
|
|
//| eigenvectors matrix. |
|
|
//| If ZNeeded<3, Z is the array whose indexes range |
|
|
//| within [0..N-1, 0..N-1]. |
|
|
//| In that case, the eigenvectors are stored in the |
|
|
//| matrix columns. |
|
|
//| If ZNeeded=3, Z is the array whose indexes range |
|
|
//| within [0..0, 0..N-1]. |
|
|
//| Result: |
|
|
//| True, if the algorithm has converged. |
|
|
//| False, if the algorithm hasn't converged. |
|
|
//| -- LAPACK routine (version 3.0) -- |
|
|
//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., |
|
|
//| Courant Institute, Argonne National Lab, and Rice University|
|
|
//| September 30, 1994 |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::SMatrixTdEVD(double &d[],double &e[],const int n,
|
|
const int zneeded,CMatrixDouble &z)
|
|
{
|
|
//--- return result
|
|
return(CEigenVDetect::SMatrixTdEVD(d,e,n,zneeded,z));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Subroutine for finding the tridiagonal matrix eigenvalues/vectors|
|
|
//| in a given half-interval (A, B] by using bisection and inverse |
|
|
//| iteration. |
|
|
//| Input parameters: |
|
|
//| D - the main diagonal of a tridiagonal matrix. |
|
|
//| Array whose index ranges within [0..N-1]. |
|
|
//| E - the secondary diagonal of a tridiagonal matrix. |
|
|
//| Array whose index ranges within [0..N-2]. |
|
|
//| N - size of matrix, N>=0. |
|
|
//| ZNeeded - flag controlling whether the eigenvectors are |
|
|
//| needed or not. If ZNeeded is equal to: |
|
|
//| * 0, the eigenvectors are not needed; |
|
|
//| * 1, the eigenvectors of a tridiagonal matrix |
|
|
//| are multiplied by the square matrix Z. It is |
|
|
//| used if the tridiagonal matrix is obtained by |
|
|
//| the similarity transformation of a symmetric |
|
|
//| matrix. |
|
|
//| * 2, the eigenvectors of a tridiagonal matrix |
|
|
//| replace matrix Z. |
|
|
//| A, B - half-interval (A, B] to search eigenvalues in. |
|
|
//| Z - if ZNeeded is equal to: |
|
|
//| * 0, Z isn't used and remains unchanged; |
|
|
//| * 1, Z contains the square matrix (array whose |
|
|
//| indexes range within [0..N-1, 0..N-1]) which |
|
|
//| reduces the given symmetric matrix to |
|
|
//| tridiagonal form; |
|
|
//| * 2, Z isn't used (but changed on the exit). |
|
|
//| Output parameters: |
|
|
//| D - array of the eigenvalues found. |
|
|
//| Array whose index ranges within [0..M-1]. |
|
|
//| M - number of eigenvalues found in the given |
|
|
//| half-interval (M>=0). |
|
|
//| Z - if ZNeeded is equal to: |
|
|
//| * 0, doesn't contain any information; |
|
|
//| * 1, contains the product of a given NxN matrix |
|
|
//| Z (from the left) and NxM matrix of the |
|
|
//| eigenvectors found (from the right). Array |
|
|
//| whose indexes range within [0..N-1, 0..M-1]. |
|
|
//| * 2, contains the matrix of the eigenvectors |
|
|
//| found. Array whose indexes range within |
|
|
//| [0..N-1, 0..M-1]. |
|
|
//| Result: |
|
|
//| True, if successful. In that case, M contains the number of |
|
|
//| eigenvalues in the given half-interval (could be equal to 0),|
|
|
//| D contains the eigenvalues, Z contains the eigenvectors (if |
|
|
//| needed). It should be noted that the subroutine changes the |
|
|
//| size of arrays D and Z. |
|
|
//| False, if the bisection method subroutine wasn't able to find|
|
|
//| the eigenvalues in the given interval or if the inverse |
|
|
//| iteration subroutine wasn't able to find all the |
|
|
//| corresponding eigenvectors. In that case, the eigenvalues and|
|
|
//| eigenvectors are not returned, M is equal to 0. |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::SMatrixTdEVDR(double &d[],double &e[],const int n,
|
|
const int zneeded,const double a,
|
|
const double b,int &m,CMatrixDouble &z)
|
|
{
|
|
//--- initialization
|
|
m=0;
|
|
//--- return result
|
|
return(CEigenVDetect::SMatrixTdEVDR(d,e,n,zneeded,a,b,m,z));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Subroutine for finding tridiagonal matrix eigenvalues/vectors |
|
|
//| with given indexes (in ascending order) by using the bisection |
|
|
//| and inverse iteraion. |
|
|
//| Input parameters: |
|
|
//| D - the main diagonal of a tridiagonal matrix. |
|
|
//| Array whose index ranges within [0..N-1]. |
|
|
//| E - the secondary diagonal of a tridiagonal matrix. |
|
|
//| Array whose index ranges within [0..N-2]. |
|
|
//| N - size of matrix. N>=0. |
|
|
//| ZNeeded - flag controlling whether the eigenvectors are |
|
|
//| needed or not. If ZNeeded is equal to: |
|
|
//| * 0, the eigenvectors are not needed; |
|
|
//| * 1, the eigenvectors of a tridiagonal matrix |
|
|
//| are multiplied by the square matrix Z. It is |
|
|
//| used if the tridiagonal matrix is obtained by |
|
|
//| the similarity transformation of a symmetric |
|
|
//| matrix. |
|
|
//| * 2, the eigenvectors of a tridiagonal matrix |
|
|
//| replace matrix Z. |
|
|
//| I1, I2 - index interval for searching (from I1 to I2). |
|
|
//| 0 <= I1 <= I2 <= N-1. |
|
|
//| Z - if ZNeeded is equal to: |
|
|
//| * 0, Z isn't used and remains unchanged; |
|
|
//| * 1, Z contains the square matrix (array whose |
|
|
//| indexes range within [0..N-1, 0..N-1]) which |
|
|
//| reduces the given symmetric matrix to |
|
|
//| tridiagonal form; |
|
|
//| * 2, Z isn't used (but changed on the exit). |
|
|
//| Output parameters: |
|
|
//| D - array of the eigenvalues found. |
|
|
//| Array whose index ranges within [0..I2-I1]. |
|
|
//| Z - if ZNeeded is equal to: |
|
|
//| * 0, doesn't contain any information; |
|
|
//| * 1, contains the product of a given NxN matrix |
|
|
//| Z (from the left) and Nx(I2-I1) matrix of the |
|
|
//| eigenvectors found (from the right). Array |
|
|
//| whose indexes range within [0..N-1, 0..I2-I1].|
|
|
//| * 2, contains the matrix of the eigenvalues |
|
|
//| found. Array whose indexes range within |
|
|
//| [0..N-1, 0..I2-I1]. |
|
|
//| Result: |
|
|
//| True, if successful. In that case, D contains the |
|
|
//| eigenvalues, Z contains the eigenvectors (if needed). |
|
|
//| It should be noted that the subroutine changes the size of |
|
|
//| arrays D and Z. |
|
|
//| False, if the bisection method subroutine wasn't able to find|
|
|
//| the eigenvalues in the given interval or if the inverse |
|
|
//| iteration subroutine wasn't able to find all the |
|
|
//| corresponding eigenvectors. In that case, the eigenvalues and|
|
|
//| eigenvectors are not returned. |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::SMatrixTdEVDI(double &d[],double &e[],const int n,
|
|
const int zneeded,const int i1,
|
|
const int i2,CMatrixDouble &z)
|
|
{
|
|
//--- return result
|
|
return(CEigenVDetect::SMatrixTdEVDI(d,e,n,zneeded,i1,i2,z));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Finding eigenvalues and eigenvectors of a general matrix |
|
|
//| The algorithm finds eigenvalues and eigenvectors of a general |
|
|
//| matrix by using the QR algorithm with multiple shifts. The |
|
|
//| algorithm can find eigenvalues and both left and right |
|
|
//| eigenvectors. |
|
|
//| The right eigenvector is a vector x such that A*x = w*x, and the |
|
|
//| left eigenvector is a vector y such that y'*A = w*y' (here y' |
|
|
//| implies a complex conjugate transposition of vector y). |
|
|
//| Input parameters: |
|
|
//| A - matrix. Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| VNeeded - flag controlling whether eigenvectors are needed |
|
|
//| or not. If VNeeded is equal to: |
|
|
//| * 0, eigenvectors are not returned; |
|
|
//| * 1, right eigenvectors are returned; |
|
|
//| * 2, left eigenvectors are returned; |
|
|
//| * 3, both left and right eigenvectors are |
|
|
//| returned. |
|
|
//| Output parameters: |
|
|
//| WR - real parts of eigenvalues. |
|
|
//| Array whose index ranges within [0..N-1]. |
|
|
//| WR - imaginary parts of eigenvalues. |
|
|
//| Array whose index ranges within [0..N-1]. |
|
|
//| VL, VR - arrays of left and right eigenvectors (if they |
|
|
//| are needed). If WI[i]=0, the respective |
|
|
//| eigenvalue is a real number, and it corresponds |
|
|
//| to the column number I of matrices VL/VR. If |
|
|
//| WI[i]>0, we have a pair of complex conjugate |
|
|
//| numbers with positive and negative imaginary |
|
|
//| parts: the first eigenvalue WR[i] + |
|
|
//| + sqrt(-1)*WI[i]; the second eigenvalue |
|
|
//| WR[i+1] + sqrt(-1)*WI[i+1]; |
|
|
//| WI[i]>0 |
|
|
//| WI[i+1] = -WI[i] < 0 |
|
|
//| In that case, the eigenvector corresponding to |
|
|
//| the first eigenvalue is located in i and i+1 |
|
|
//| columns of matrices VL/VR (the column number i |
|
|
//| contains the real part, and the column number |
|
|
//| i+1 contains the imaginary part), and the vector |
|
|
//| corresponding to the second eigenvalue is a |
|
|
//| complex conjugate to the first vector. |
|
|
//| Arrays whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| Result: |
|
|
//| True, if the algorithm has converged. |
|
|
//| False, if the algorithm has not converged. |
|
|
//| Note 1: |
|
|
//| Some users may ask the following question: what if WI[N-1]>0?|
|
|
//| WI[N] must contain an eigenvalue which is complex conjugate |
|
|
//| to the N-th eigenvalue, but the array has only size N? |
|
|
//| The answer is as follows: such a situation cannot occur |
|
|
//| because the algorithm finds a pairs of eigenvalues, |
|
|
//| therefore, if WI[i]>0, I is strictly less than N-1. |
|
|
//| Note 2: |
|
|
//| The algorithm performance depends on the value of the |
|
|
//| internal parameter NS of the InternalSchurDecomposition |
|
|
//| subroutine which defines the number of shifts in the QR |
|
|
//| algorithm (similarly to the block width in block-matrix |
|
|
//| algorithms of linear algebra). If you require maximum |
|
|
//| performance on your machine, it is recommended to adjust |
|
|
//| this parameter manually. |
|
|
//| See also the InternalTREVC subroutine. |
|
|
//| The algorithm is based on the LAPACK 3.0 library. |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::RMatrixEVD(CMatrixDouble &a,const int n,const int vneeded,
|
|
double &wr[],double &wi[],CMatrixDouble &vl,
|
|
CMatrixDouble &vr)
|
|
{
|
|
bool result=CEigenVDetect::RMatrixEVD(a,n,vneeded,wr,wi,vl,vr);
|
|
//--- return result
|
|
return(result);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Generation of a random uniformly distributed (Haar) orthogonal |
|
|
//| matrix |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - matrix size, N>=1 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| A - orthogonal NxN matrix, array[0..N-1,0..N-1] |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixRndOrthogonal(const int n,CMatrixDouble &a)
|
|
{
|
|
//--- function call
|
|
CMatGen::RMatrixRndOrthogonal(n,a);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Generation of random NxN matrix with given condition number and |
|
|
//| norm2(A)=1 |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - matrix size |
|
|
//| C - condition number (in 2-norm) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| A - random matrix with norm2(A)=1 and cond(A)=C |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixRndCond(const int n,const double c,
|
|
CMatrixDouble &a)
|
|
{
|
|
//--- function call
|
|
CMatGen::RMatrixRndCond(n,c,a);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Generation of a random Haar distributed orthogonal complex matrix|
|
|
//| INPUT PARAMETERS: |
|
|
//| N - matrix size, N>=1 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| A - orthogonal NxN matrix, array[0..N-1,0..N-1] |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixRndOrthogonal(const int n,CMatrixComplex &a)
|
|
{
|
|
//--- function call
|
|
CMatGen::CMatrixRndOrthogonal(n,a);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Generation of random NxN complex matrix with given condition |
|
|
//| number C and norm2(A)=1 |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - matrix size |
|
|
//| C - condition number (in 2-norm) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| A - random matrix with norm2(A)=1 and cond(A)=C |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixRndCond(const int n,const double c,
|
|
CMatrixComplex &a)
|
|
{
|
|
//--- function call
|
|
CMatGen::CMatrixRndCond(n,c,a);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Generation of random NxN symmetric matrix with given condition |
|
|
//| number and norm2(A)=1 |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - matrix size |
|
|
//| C - condition number (in 2-norm) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| A - random matrix with norm2(A)=1 and cond(A)=C |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SMatrixRndCond(const int n,const double c,
|
|
CMatrixDouble &a)
|
|
{
|
|
//--- function call
|
|
CMatGen::SMatrixRndCond(n,c,a);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Generation of random NxN symmetric positive definite matrix with |
|
|
//| given condition number and norm2(A)=1 |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - matrix size |
|
|
//| C - condition number (in 2-norm) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| A - random SPD matrix with norm2(A)=1 and cond(A)=C |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SPDMatrixRndCond(const int n,const double c,
|
|
CMatrixDouble &a)
|
|
{
|
|
//--- function call
|
|
CMatGen::SPDMatrixRndCond(n,c,a);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Generation of random NxN Hermitian matrix with given condition |
|
|
//| number and norm2(A)=1 |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - matrix size |
|
|
//| C - condition number (in 2-norm) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| A - random matrix with norm2(A)=1 and cond(A)=C |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::HMatrixRndCond(const int n,const double c,
|
|
CMatrixComplex &a)
|
|
{
|
|
//--- function call
|
|
CMatGen::HMatrixRndCond(n,c,a);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Generation of random NxN Hermitian positive definite matrix with |
|
|
//| given condition number and norm2(A)=1 |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - matrix size |
|
|
//| C - condition number (in 2-norm) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| A - random HPD matrix with norm2(A)=1 and cond(A)=C |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::HPDMatrixRndCond(const int n,const double c,
|
|
CMatrixComplex &a)
|
|
{
|
|
//--- function call
|
|
CMatGen::HPDMatrixRndCond(n,c,a);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Multiplication of MxN matrix by NxN random Haar distributed |
|
|
//| orthogonal matrix |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - matrix, array[0..M-1, 0..N-1] |
|
|
//| M, N- matrix size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| A - A*Q, where Q is random NxN orthogonal matrix |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixRndOrthogonalFromTheRight(CMatrixDouble &a,
|
|
const int m,const int n)
|
|
{
|
|
//--- function call
|
|
CMatGen::RMatrixRndOrthogonalFromTheRight(a,m,n);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Multiplication of MxN matrix by MxM random Haar distributed |
|
|
//| orthogonal matrix |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - matrix, array[0..M-1, 0..N-1] |
|
|
//| M, N- matrix size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| A - Q*A, where Q is random MxM orthogonal matrix |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixRndOrthogonalFromTheLeft(CMatrixDouble &a,
|
|
const int m,const int n)
|
|
{
|
|
//--- function call
|
|
CMatGen::RMatrixRndOrthogonalFromTheLeft(a,m,n);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Multiplication of MxN complex matrix by NxN random Haar |
|
|
//| distributed complex orthogonal matrix |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - matrix, array[0..M-1, 0..N-1] |
|
|
//| M, N- matrix size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| A - A*Q, where Q is random NxN orthogonal matrix |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixRndOrthogonalFromTheRight(CMatrixComplex &a,
|
|
const int m,const int n)
|
|
{
|
|
//--- function call
|
|
CMatGen::CMatrixRndOrthogonalFromTheRight(a,m,n);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Multiplication of MxN complex matrix by MxM random Haar |
|
|
//| distributed complex orthogonal matrix |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - matrix, array[0..M-1, 0..N-1] |
|
|
//| M, N- matrix size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| A - Q*A, where Q is random MxM orthogonal matrix |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixRndOrthogonalFromTheLeft(CMatrixComplex &a,
|
|
const int m,const int n)
|
|
{
|
|
//--- function call
|
|
CMatGen::CMatrixRndOrthogonalFromTheLeft(a,m,n);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Symmetric multiplication of NxN matrix by random Haar |
|
|
//| distributed orthogonal matrix |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - matrix, array[0..N-1, 0..N-1] |
|
|
//| N - matrix size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| A - Q'*A*Q, where Q is random NxN orthogonal matrix |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SMatrixRndMultiply(CMatrixDouble &a,const int n)
|
|
{
|
|
//--- function call
|
|
CMatGen::SMatrixRndMultiply(a,n);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Hermitian multiplication of NxN matrix by random Haar distributed|
|
|
//| complex orthogonal matrix |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - matrix, array[0..N-1, 0..N-1] |
|
|
//| N - matrix size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| A - Q^H*A*Q, where Q is random NxN orthogonal matrix |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::HMatrixRndMultiply(CMatrixComplex &a,const int n)
|
|
{
|
|
//--- function call
|
|
CMatGen::HMatrixRndMultiply(a,n);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| LU decomposition of a general real matrix with row pivoting |
|
|
//| A is represented as A = P*L*U, where: |
|
|
//| * L is lower unitriangular matrix |
|
|
//| * U is upper triangular matrix |
|
|
//| * P = P0*P1*...*PK, K=min(M,N)-1, |
|
|
//| Pi - permutation matrix for I and Pivots[I] |
|
|
//| This is cache-oblivous implementation of LU decomposition. |
|
|
//| It is optimized for square matrices. As for rectangular matrices:|
|
|
//| * best case - M>>N |
|
|
//| * worst case - N>>M, small M, large N, matrix does not fit in CPU|
|
|
//| cache |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - array[0..M-1, 0..N-1]. |
|
|
//| M - number of rows in matrix A. |
|
|
//| N - number of columns in matrix A. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| A - matrices L and U in compact form: |
|
|
//| * L is stored under main diagonal |
|
|
//| * U is stored on and above main diagonal |
|
|
//| Pivots - permutation matrix in compact form. |
|
|
//| array[0..Min(M-1,N-1)]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixLU(CMatrixDouble &a,const int m,const int n,
|
|
int &pivots[])
|
|
{
|
|
//--- function call
|
|
CTrFac::RMatrixLU(a,m,n,pivots);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| LU decomposition of a general complex matrix with row pivoting |
|
|
//| A is represented as A = P*L*U, where: |
|
|
//| * L is lower unitriangular matrix |
|
|
//| * U is upper triangular matrix |
|
|
//| * P = P0*P1*...*PK, K=min(M,N)-1, |
|
|
//| Pi - permutation matrix for I and Pivots[I] |
|
|
//| This is cache-oblivous implementation of LU decomposition. It is |
|
|
//| optimized for square matrices. As for rectangular matrices: |
|
|
//| * best case - M>>N |
|
|
//| * worst case - N>>M, small M, large N, matrix does not fit in CPU|
|
|
//| cache |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - array[0..M-1, 0..N-1]. |
|
|
//| M - number of rows in matrix A. |
|
|
//| N - number of columns in matrix A. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| A - matrices L and U in compact form: |
|
|
//| * L is stored under main diagonal |
|
|
//| * U is stored on and above main diagonal |
|
|
//| Pivots - permutation matrix in compact form. |
|
|
//| array[0..Min(M-1,N-1)]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixLU(CMatrixComplex &a,const int m,const int n,
|
|
int &pivots[])
|
|
{
|
|
//--- function call
|
|
CTrFac::CMatrixLU(a,m,n,pivots);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Cache-oblivious Cholesky decomposition |
|
|
//| The algorithm computes Cholesky decomposition of a Hermitian |
|
|
//| positive - definite matrix. The result of an algorithm is a |
|
|
//| representation of A as A=U'*U or A=L*L' (here X' detones |
|
|
//| conj(X^T)). |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - upper or lower triangle of a factorized matrix. |
|
|
//| array with elements [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| IsUpper - if IsUpper=True, then A contains an upper |
|
|
//| triangle of a symmetric matrix, otherwise A |
|
|
//| contains a lower one. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| A - the result of factorization. If IsUpper=True, |
|
|
//| then the upper triangle contains matrix U, so |
|
|
//| that A = U'*U, and the elements below the main |
|
|
//| diagonal are not modified. Similarly, if |
|
|
//| IsUpper = False. |
|
|
//| RESULT: |
|
|
//| If the matrix is positive-definite, the function returns |
|
|
//| True. Otherwise, the function returns False. Contents of A is|
|
|
//| not determined in such case. |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::HPDMatrixCholesky(CMatrixComplex &a,const int n,
|
|
const bool isupper)
|
|
{
|
|
//--- return result
|
|
return(CTrFac::HPDMatrixCholesky(a,n,isupper));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Cache-oblivious Cholesky decomposition |
|
|
//| The algorithm computes Cholesky decomposition of a symmetric |
|
|
//| positive - definite matrix. The result of an algorithm is a |
|
|
//| representation of A as A=U^T*U or A=L*L^T |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - upper or lower triangle of a factorized matrix. |
|
|
//| array with elements [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| IsUpper - if IsUpper=True, then A contains an upper |
|
|
//| triangle of a symmetric matrix, otherwise A |
|
|
//| contains a lower one. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| A - the result of factorization. If IsUpper=True, |
|
|
//| then the upper triangle contains matrix U, so |
|
|
//| that A = U^T*U, and the elements below the main |
|
|
//| diagonal are not modified. Similarly, if |
|
|
//| IsUpper = False. |
|
|
//| RESULT: |
|
|
//| If the matrix is positive-definite, the function returns |
|
|
//| True. Otherwise, the function returns False. Contents of A is|
|
|
//| not determined in such case. |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::SPDMatrixCholesky(CMatrixDouble &a,const int n,
|
|
const bool isupper)
|
|
{
|
|
//--- return result
|
|
return(CTrFac::SPDMatrixCholesky(a,n,isupper));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Estimate of a matrix condition number (1-norm) |
|
|
//| The algorithm calculates a lower bound of the condition number. |
|
|
//| In this case, the algorithm does not return a lower bound of the |
|
|
//| condition number, but an inverse number (to avoid an overflow in |
|
|
//| case of a singular matrix). |
|
|
//| Input parameters: |
|
|
//| A - matrix. Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| Result: 1/LowerBound(cond(A)) |
|
|
//| NOTE: |
|
|
//| if k(A) is very large, then matrix is assumed degenerate, |
|
|
//| k(A)=INF, 0.0 is returned in such cases. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::RMatrixRCond1(CMatrixDouble &a,const int n)
|
|
{
|
|
//--- return result
|
|
return(CRCond::RMatrixRCond1(a,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Estimate of a matrix condition number (infinity-norm). |
|
|
//| The algorithm calculates a lower bound of the condition number. |
|
|
//| In this case, the algorithm does not return a lower bound of the |
|
|
//| condition number, but an inverse number (to avoid an overflow in |
|
|
//| case of a singular matrix). |
|
|
//| Input parameters: |
|
|
//| A - matrix. Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| Result: 1/LowerBound(cond(A)) |
|
|
//| NOTE: |
|
|
//| if k(A) is very large, then matrix is assumed degenerate, |
|
|
//| k(A)=INF, 0.0 is returned in such cases. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::RMatrixRCondInf(CMatrixDouble &a,const int n)
|
|
{
|
|
//--- return result
|
|
return(CRCond::RMatrixRCondInf(a,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Condition number estimate of a symmetric positive definite |
|
|
//| matrix. |
|
|
//| The algorithm calculates a lower bound of the condition number. |
|
|
//| In this case, the algorithm does not return a lower bound of the |
|
|
//| condition number, but an inverse number (to avoid an overflow in |
|
|
//| case of a singular matrix). |
|
|
//| It should be noted that 1-norm and inf-norm of condition numbers |
|
|
//| of symmetric matrices are equal, so the algorithm doesn't take |
|
|
//| into account the differences between these types of norms. |
|
|
//| Input parameters: |
|
|
//| A - symmetric positive definite matrix which is given|
|
|
//| by its upper or lower triangle depending on the |
|
|
//| value of IsUpper. Array with elements |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| IsUpper - storage format. |
|
|
//| Result: |
|
|
//| 1/LowerBound(cond(A)), if matrix A is positive definite, |
|
|
//| -1, if matrix A is not positive definite, and its condition |
|
|
//| number could not be found by this algorithm. |
|
|
//| NOTE: |
|
|
//| if k(A) is very large, then matrix is assumed degenerate, |
|
|
//| k(A)=INF, 0.0 is returned in such cases. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::SPDMatrixRCond(CMatrixDouble &a,const int n,
|
|
const bool isupper)
|
|
{
|
|
//--- return result
|
|
return(CRCond::SPDMatrixRCond(a,n,isupper));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Triangular matrix: estimate of a condition number (1-norm) |
|
|
//| The algorithm calculates a lower bound of the condition number. |
|
|
//| In this case, the algorithm does not return a lower bound of the |
|
|
//| condition number, but an inverse number (to avoid an overflow in |
|
|
//| case of a singular matrix). |
|
|
//| Input parameters: |
|
|
//| A - matrix. Array[0..N-1, 0..N-1]. |
|
|
//| N - size of A. |
|
|
//| IsUpper - True, if the matrix is upper triangular. |
|
|
//| IsUnit - True, if the matrix has a unit diagonal. |
|
|
//| Result: 1/LowerBound(cond(A)) |
|
|
//| NOTE: |
|
|
//| if k(A) is very large, then matrix is assumed degenerate, |
|
|
//| k(A)=INF, 0.0 is returned in such cases. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::RMatrixTrRCond1(CMatrixDouble &a,const int n,
|
|
const bool isupper,const bool isunit)
|
|
{
|
|
//--- return result
|
|
return(CRCond::RMatrixTrRCond1(a,n,isupper,isunit));
|
|
}
|
|
//+-------------------------------------------------------------------+
|
|
//| Triangular matrix: estimate of a matrix condition number |
|
|
//| (infinity-norm). |
|
|
//| The algorithm calculates a lower bound of the condition number. In|
|
|
//| this case, the algorithm does not return a lower bound of the |
|
|
//| condition number, but an inverse number (to avoid an overflow in |
|
|
//| case of a singular matrix). |
|
|
//| Input parameters: |
|
|
//| A - matrix. Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| IsUpper - True, if the matrix is upper triangular. |
|
|
//| IsUnit - True, if the matrix has a unit diagonal. |
|
|
//| Result: 1/LowerBound(cond(A)) |
|
|
//| NOTE: |
|
|
//| if k(A) is very large, then matrix is assumed degenerate, |
|
|
//| k(A)=INF, 0.0 is returned in such cases. |
|
|
//+-------------------------------------------------------------------+
|
|
static double CAlglib::RMatrixTrRCondInf(CMatrixDouble &a,const int n,
|
|
const bool isupper,const bool isunit)
|
|
{
|
|
//--- return result
|
|
return(CRCond::RMatrixTrRCondInf(a,n,isupper,isunit));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Condition number estimate of a Hermitian positive definite |
|
|
//| matrix. |
|
|
//| The algorithm calculates a lower bound of the condition number. |
|
|
//| In this case, the algorithm does not return a lower bound of the |
|
|
//| condition number, but an inverse number (to avoid an overflow in |
|
|
//| case of a singular matrix). |
|
|
//| It should be noted that 1-norm and inf-norm of condition numbers |
|
|
//| of symmetric matrices are equal, so the algorithm doesn't take |
|
|
//| into account the differences between these types of norms. |
|
|
//| Input parameters: |
|
|
//| A - Hermitian positive definite matrix which is given|
|
|
//| by its upper or lower triangle depending on the |
|
|
//| value of IsUpper. Array with elements |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| IsUpper - storage format. |
|
|
//| Result: |
|
|
//| 1/LowerBound(cond(A)), if matrix A is positive definite, |
|
|
//| -1, if matrix A is not positive definite, and its condition |
|
|
//| number could not be found by this algorithm. |
|
|
//| NOTE: |
|
|
//| if k(A) is very large, then matrix is assumed degenerate, |
|
|
//| k(A)=INF, 0.0 is returned in such cases. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::HPDMatrixRCond(CMatrixComplex &a,const int n,
|
|
const bool isupper)
|
|
{
|
|
//--- return result
|
|
return(CRCond::HPDMatrixRCond(a,n,isupper));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Estimate of a matrix condition number (1-norm) |
|
|
//| The algorithm calculates a lower bound of the condition number. |
|
|
//| In this case, the algorithm does not return a lower bound of the |
|
|
//| condition number, but an inverse number (to avoid an overflow in |
|
|
//| case of a singular matrix). |
|
|
//| Input parameters: |
|
|
//| A - matrix. Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| Result: 1/LowerBound(cond(A)) |
|
|
//| NOTE: |
|
|
//| if k(A) is very large, then matrix is assumed degenerate, |
|
|
//| k(A)=INF, 0.0 is returned in such cases. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::CMatrixRCond1(CMatrixComplex &a,const int n)
|
|
{
|
|
//--- return result
|
|
return(CRCond::CMatrixRCond1(a,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Estimate of a matrix condition number (infinity-norm). |
|
|
//| The algorithm calculates a lower bound of the condition number. |
|
|
//| In this case, the algorithm does not return a lower bound of the |
|
|
//| condition number, but an inverse number (to avoid an overflow in |
|
|
//| case of a singular matrix). |
|
|
//| Input parameters: |
|
|
//| A - matrix. Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| Result: 1/LowerBound(cond(A)) |
|
|
//| NOTE: |
|
|
//| if k(A) is very large, then matrix is assumed degenerate, |
|
|
//| k(A)=INF, 0.0 is returned in such cases. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::CMatrixRCondInf(CMatrixComplex &a,const int n)
|
|
{
|
|
//--- return result
|
|
return(CRCond::CMatrixRCondInf(a,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Estimate of the condition number of a matrix given by its LU |
|
|
//| decomposition (1-norm) |
|
|
//| The algorithm calculates a lower bound of the condition number. |
|
|
//| In this case, the algorithm does not return a lower bound of the |
|
|
//| condition number, but an inverse number (to avoid an overflow in |
|
|
//| case of a singular matrix). |
|
|
//| Input parameters: |
|
|
//| LUA - LU decomposition of a matrix in compact form.|
|
|
//| Output of the RMatrixLU subroutine. |
|
|
//| N - size of matrix A. |
|
|
//| Result: 1/LowerBound(cond(A)) |
|
|
//| NOTE: |
|
|
//| if k(A) is very large, then matrix is assumed degenerate, |
|
|
//| k(A)=INF, 0.0 is returned in such cases. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::RMatrixLURCond1(CMatrixDouble &lua,const int n)
|
|
{
|
|
//--- return result
|
|
return(CRCond::RMatrixLURCond1(lua,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Estimate of the condition number of a matrix given by its LU |
|
|
//| decomposition (infinity norm). |
|
|
//| The algorithm calculates a lower bound of the condition number. |
|
|
//| In this case, the algorithm does not return a lower bound of the |
|
|
//| condition number, but an inverse number (to avoid an overflow in |
|
|
//| case of a singular matrix). |
|
|
//| Input parameters: |
|
|
//| LUA - LU decomposition of a matrix in compact form. |
|
|
//| Output of the RMatrixLU subroutine. |
|
|
//| N - size of matrix A. |
|
|
//| Result: 1/LowerBound(cond(A)) |
|
|
//| NOTE: |
|
|
//| if k(A) is very large, then matrix is assumed degenerate, |
|
|
//| k(A)=INF, 0.0 is returned in such cases. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::RMatrixLURCondInf(CMatrixDouble &lua,const int n)
|
|
{
|
|
//--- return result
|
|
return(CRCond::RMatrixLURCondInf(lua,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Condition number estimate of a symmetric positive definite matrix|
|
|
//| given by Cholesky decomposition. |
|
|
//| The algorithm calculates a lower bound of the condition number. |
|
|
//| In this case, the algorithm does not return a lower bound of the |
|
|
//| condition number, but an inverse number (to avoid an overflow in |
|
|
//| case of a singular matrix). |
|
|
//| It should be noted that 1-norm and inf-norm condition numbers of |
|
|
//| symmetric matrices are equal, so the algorithm doesn't take into |
|
|
//| account the differences between these types of norms. |
|
|
//| Input parameters: |
|
|
//| CD - Cholesky decomposition of matrix A, |
|
|
//| output of SMatrixCholesky subroutine. |
|
|
//| N - size of matrix A. |
|
|
//| Result: 1/LowerBound(cond(A)) |
|
|
//| NOTE: |
|
|
//| if k(A) is very large, then matrix is assumed degenerate, |
|
|
//| k(A)=INF, 0.0 is returned in such cases. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::SPDMatrixCholeskyRCond(CMatrixDouble &a,const int n,
|
|
const bool isupper)
|
|
{
|
|
//--- return result
|
|
return(CRCond::SPDMatrixCholeskyRCond(a,n,isupper));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Condition number estimate of a Hermitian positive definite matrix|
|
|
//| given by Cholesky decomposition. |
|
|
//| The algorithm calculates a lower bound of the condition number. |
|
|
//| In this case, the algorithm does not return a lower bound of the |
|
|
//| condition number, but an inverse number (to avoid an overflow in |
|
|
//| case of a singular matrix). |
|
|
//| It should be noted that 1-norm and inf-norm condition numbers of |
|
|
//| symmetric matrices are equal, so the algorithm doesn't take into |
|
|
//| account the differences between these types of norms. |
|
|
//| Input parameters: |
|
|
//| CD - Cholesky decomposition of matrix A, |
|
|
//| output of SMatrixCholesky subroutine. |
|
|
//| N - size of matrix A. |
|
|
//| Result: 1/LowerBound(cond(A)) |
|
|
//| NOTE: |
|
|
//| if k(A) is very large, then matrix is assumed degenerate, |
|
|
//| k(A)=INF, 0.0 is returned in such cases. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::HPDMatrixCholeskyRCond(CMatrixComplex &a,const int n,
|
|
const bool isupper)
|
|
{
|
|
//--- return result
|
|
return(CRCond::HPDMatrixCholeskyRCond(a,n,isupper));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Estimate of the condition number of a matrix given by its LU |
|
|
//| decomposition (1-norm) |
|
|
//| The algorithm calculates a lower bound of the condition number. |
|
|
//| In this case, the algorithm does not return a lower bound of the |
|
|
//| condition number, but an inverse number (to avoid an overflow in |
|
|
//| case of a singular matrix). |
|
|
//| Input parameters: |
|
|
//| LUA - LU decomposition of a matrix in compact form.|
|
|
//| Output of the CMatrixLU subroutine. |
|
|
//| N - size of matrix A. |
|
|
//| Result: 1/LowerBound(cond(A)) |
|
|
//| NOTE: |
|
|
//| if k(A) is very large, then matrix is assumed degenerate, |
|
|
//| k(A)=INF, 0.0 is returned in such cases. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::CMatrixLURCond1(CMatrixComplex &lua,const int n)
|
|
{
|
|
//--- return result
|
|
return(CRCond::CMatrixLURCond1(lua,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Estimate of the condition number of a matrix given by its LU |
|
|
//| decomposition (infinity norm). |
|
|
//| The algorithm calculates a lower bound of the condition number. |
|
|
//| In this case, the algorithm does not return a lower bound of the |
|
|
//| condition number, but an inverse number (to avoid an overflow in |
|
|
//| case of a singular matrix). |
|
|
//| Input parameters: |
|
|
//| LUA - LU decomposition of a matrix in compact form. |
|
|
//| Output of the CMatrixLU subroutine. |
|
|
//| N - size of matrix A. |
|
|
//| Result: 1/LowerBound(cond(A)) |
|
|
//| NOTE: |
|
|
//| if k(A) is very large, then matrix is assumed degenerate, |
|
|
//| k(A)=INF, 0.0 is returned in such cases. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::CMatrixLURCondInf(CMatrixComplex &lua,const int n)
|
|
{
|
|
//--- return result
|
|
return(CRCond::CMatrixLURCondInf(lua,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Triangular matrix: estimate of a condition number (1-norm) |
|
|
//| The algorithm calculates a lower bound of the condition number. |
|
|
//| In this case, the algorithm does not return a lower bound of the |
|
|
//| condition number, but an inverse number (to avoid an overflow in |
|
|
//| case of a singular matrix). |
|
|
//| Input parameters: |
|
|
//| A - matrix. Array[0..N-1, 0..N-1]. |
|
|
//| N - size of A. |
|
|
//| IsUpper - True, if the matrix is upper triangular. |
|
|
//| IsUnit - True, if the matrix has a unit diagonal. |
|
|
//| Result: 1/LowerBound(cond(A)) |
|
|
//| NOTE: |
|
|
//| if k(A) is very large, then matrix is assumed degenerate, |
|
|
//| k(A)=INF, 0.0 is returned in such cases. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::CMatrixTrRCond1(CMatrixComplex &a,const int n,
|
|
const bool isupper,const bool isunit)
|
|
{
|
|
//--- return result
|
|
return(CRCond::CMatrixTrRCond1(a,n,isupper,isunit));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Triangular matrix: estimate of a matrix condition number |
|
|
//| (infinity-norm). |
|
|
//| The algorithm calculates a lower bound of the condition number. |
|
|
//| In this case, the algorithm does not return a lower bound of the |
|
|
//| condition number, but an inverse number (to avoid an overflow in |
|
|
//| case of a singular matrix). |
|
|
//| Input parameters: |
|
|
//| A - matrix. Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| IsUpper - True, if the matrix is upper triangular. |
|
|
//| IsUnit - True, if the matrix has a unit diagonal. |
|
|
//| Result: 1/LowerBound(cond(A)) |
|
|
//| NOTE: |
|
|
//| if k(A) is very large, then matrix is assumed degenerate, |
|
|
//| k(A)=INF, 0.0 is returned in such cases. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::CMatrixTrRCondInf(CMatrixComplex &a,const int n,
|
|
const bool isupper,const bool isunit)
|
|
{
|
|
//--- return result
|
|
return(CRCond::CMatrixTrRCondInf(a,n,isupper,isunit));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inversion of a matrix given by its LU decomposition. |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - LU decomposition of the matrix |
|
|
//| (output of RMatrixLU subroutine). |
|
|
//| Pivots - table of permutations |
|
|
//| (the output of RMatrixLU subroutine). |
|
|
//| N - size of matrix A (optional) : |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, size is automatically determined |
|
|
//| from matrix size (A must be square matrix) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - return code: |
|
|
//| * -3 A is singular, or VERY close to singular.|
|
|
//| it is filled by zeros in such cases. |
|
|
//| * 1 task is solved (but matrix A may be |
|
|
//| ill-conditioned, check R1/RInf parameters|
|
|
//| for condition numbers). |
|
|
//| Rep - solver report, see below for more info |
|
|
//| A - inverse of matrix A. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| SOLVER REPORT |
|
|
//| Subroutine sets following fields of the Rep structure: |
|
|
//| * R1 reciprocal of condition number: 1/cond(A), 1-norm. |
|
|
//| * RInf reciprocal of condition number: 1/cond(A), inf-norm. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixLUInverse(CMatrixDouble &a,int &pivots[],
|
|
const int n,int &info,
|
|
CMatInvReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CMatInv::RMatrixLUInverse(a,pivots,n,info,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inversion of a matrix given by its LU decomposition. |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - LU decomposition of the matrix |
|
|
//| (output of RMatrixLU subroutine). |
|
|
//| Pivots - table of permutations |
|
|
//| (the output of RMatrixLU subroutine). |
|
|
//| N - size of matrix A (optional) : |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, size is automatically determined |
|
|
//| from matrix size (A must be square matrix) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - return code: |
|
|
//| * -3 A is singular, or VERY close to singular.|
|
|
//| it is filled by zeros in such cases. |
|
|
//| * 1 task is solved (but matrix A may be |
|
|
//| ill-conditioned, check R1/RInf parameters|
|
|
//| for condition numbers). |
|
|
//| Rep - solver report, see below for more info |
|
|
//| A - inverse of matrix A. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| SOLVER REPORT |
|
|
//| Subroutine sets following fields of the Rep structure: |
|
|
//| * R1 reciprocal of condition number: 1/cond(A), 1-norm. |
|
|
//| * RInf reciprocal of condition number: 1/cond(A), inf-norm. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixLUInverse(CMatrixDouble &a,int &pivots[],
|
|
int &info,CMatInvReportShell &rep)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- check
|
|
if((CAp::Cols(a)!=CAp::Rows(a)) || (CAp::Cols(a)!=CAp::Len(pivots)))
|
|
{
|
|
Print(__FUNCTION__+": looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
info=0;
|
|
n=CAp::Cols(a);
|
|
//--- function call
|
|
CMatInv::RMatrixLUInverse(a,pivots,n,info,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inversion of a general matrix. |
|
|
//| Input parameters: |
|
|
//| A - matrix. |
|
|
//| N - size of matrix A (optional) : |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, size is automatically determined |
|
|
//| from matrix size (A must be square matrix) |
|
|
//| Output parameters: |
|
|
//| Info - return code, same as in RMatrixLUInverse |
|
|
//| Rep - solver report, same as in RMatrixLUInverse |
|
|
//| A - inverse of matrix A, same as in RMatrixLUInverse |
|
|
//| Result: |
|
|
//| True, if the matrix is not singular. |
|
|
//| False, if the matrix is singular. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixInverse(CMatrixDouble &a,const int n,int &info,
|
|
CMatInvReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CMatInv::RMatrixInverse(a,n,info,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inversion of a general matrix. |
|
|
//| Input parameters: |
|
|
//| A - matrix. |
|
|
//| N - size of matrix A (optional) : |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, size is automatically determined |
|
|
//| from matrix size (A must be square matrix) |
|
|
//| Output parameters: |
|
|
//| Info - return code, same as in RMatrixLUInverse |
|
|
//| Rep - solver report, same as in RMatrixLUInverse |
|
|
//| A - inverse of matrix A, same as in RMatrixLUInverse |
|
|
//| Result: |
|
|
//| True, if the matrix is not singular. |
|
|
//| False, if the matrix is singular. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixInverse(CMatrixDouble &a,int &info,
|
|
CMatInvReportShell &rep)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- check
|
|
if((CAp::Cols(a)!=CAp::Rows(a)))
|
|
{
|
|
Print(__FUNCTION__+": looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
info=0;
|
|
n=CAp::Cols(a);
|
|
//--- function call
|
|
CMatInv::RMatrixInverse(a,n,info,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inversion of a matrix given by its LU decomposition. |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - LU decomposition of the matrix |
|
|
//| (output of CMatrixLU subroutine). |
|
|
//| Pivots - table of permutations |
|
|
//| (the output of CMatrixLU subroutine). |
|
|
//| N - size of matrix A (optional) : |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, size is automatically determined |
|
|
//| from matrix size (A must be square matrix) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - return code, same as in RMatrixLUInverse |
|
|
//| Rep - solver report, same as in RMatrixLUInverse |
|
|
//| A - inverse of matrix A, same as in RMatrixLUInverse |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixLUInverse(CMatrixComplex &a,int &pivots[],
|
|
const int n,int &info,
|
|
CMatInvReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CMatInv::CMatrixLUInverse(a,pivots,n,info,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inversion of a matrix given by its LU decomposition. |
|
|
//| INPUT PARAMETERS: |
|
|
//| A - LU decomposition of the matrix |
|
|
//| (output of CMatrixLU subroutine). |
|
|
//| Pivots - table of permutations |
|
|
//| (the output of CMatrixLU subroutine). |
|
|
//| N - size of matrix A (optional) : |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, size is automatically determined |
|
|
//| from matrix size (A must be square matrix) |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| Info - return code, same as in RMatrixLUInverse |
|
|
//| Rep - solver report, same as in RMatrixLUInverse |
|
|
//| A - inverse of matrix A, same as in RMatrixLUInverse |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixLUInverse(CMatrixComplex &a,int &pivots[],
|
|
int &info,CMatInvReportShell &rep)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- check
|
|
if((CAp::Cols(a)!=CAp::Rows(a)) || (CAp::Cols(a)!=CAp::Len(pivots)))
|
|
{
|
|
Print(__FUNCTION__+": looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
info=0;
|
|
n=CAp::Cols(a);
|
|
//--- function call
|
|
CMatInv::CMatrixLUInverse(a,pivots,n,info,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inversion of a general matrix. |
|
|
//| Input parameters: |
|
|
//| A - matrix |
|
|
//| N - size of matrix A (optional) : |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, size is automatically determined |
|
|
//| from matrix size (A must be square matrix) |
|
|
//| Output parameters: |
|
|
//| Info - return code, same as in RMatrixLUInverse |
|
|
//| Rep - solver report, same as in RMatrixLUInverse |
|
|
//| A - inverse of matrix A, same as in RMatrixLUInverse |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixInverse(CMatrixComplex &a,const int n,int &info,
|
|
CMatInvReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CMatInv::CMatrixInverse(a,n,info,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inversion of a general matrix. |
|
|
//| Input parameters: |
|
|
//| A - matrix |
|
|
//| N - size of matrix A (optional) : |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, size is automatically determined |
|
|
//| from matrix size (A must be square matrix) |
|
|
//| Output parameters: |
|
|
//| Info - return code, same as in RMatrixLUInverse |
|
|
//| Rep - solver report, same as in RMatrixLUInverse |
|
|
//| A - inverse of matrix A, same as in RMatrixLUInverse |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixInverse(CMatrixComplex &a,int &info,
|
|
CMatInvReportShell &rep)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- check
|
|
if((CAp::Cols(a)!=CAp::Rows(a)))
|
|
{
|
|
Print(__FUNCTION__+": looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
info=0;
|
|
n=CAp::Cols(a);
|
|
//--- function call
|
|
CMatInv::CMatrixInverse(a,n,info,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inversion of a symmetric positive definite matrix which is given |
|
|
//| by Cholesky decomposition. |
|
|
//| Input parameters: |
|
|
//| A - Cholesky decomposition of the matrix to be |
|
|
//| inverted: A=U?*U or A = L*L'. |
|
|
//| Output of SPDMatrixCholesky subroutine. |
|
|
//| N - size of matrix A (optional) : |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, size is automatically determined |
|
|
//| from matrix size (A must be square matrix) |
|
|
//| IsUpper - storage type (optional): |
|
|
//| * if True, symmetric matrix A is given by its |
|
|
//| upper triangle, and the lower triangle isn?t |
|
|
//| used/changed by function |
|
|
//| * if False, symmetric matrix A is given by its |
|
|
//| lower triangle, and the upper triangle isn?t |
|
|
//| used/changed by function |
|
|
//| * if not given, lower half is used. |
|
|
//| Output parameters: |
|
|
//| Info - return code, same as in RMatrixLUInverse |
|
|
//| Rep - solver report, same as in RMatrixLUInverse |
|
|
//| A - inverse of matrix A, same as in RMatrixLUInverse |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SPDMatrixCholeskyInverse(CMatrixDouble &a,const int n,
|
|
const bool isupper,int &info,
|
|
CMatInvReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CMatInv::SPDMatrixCholeskyInverse(a,n,isupper,info,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inversion of a symmetric positive definite matrix which is given |
|
|
//| by Cholesky decomposition. |
|
|
//| Input parameters: |
|
|
//| A - Cholesky decomposition of the matrix to be |
|
|
//| inverted: A=U?*U or A = L*L'. |
|
|
//| Output of SPDMatrixCholesky subroutine. |
|
|
//| N - size of matrix A (optional) : |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, size is automatically determined |
|
|
//| from matrix size (A must be square matrix) |
|
|
//| IsUpper - storage type (optional): |
|
|
//| * if True, symmetric matrix A is given by its |
|
|
//| upper triangle, and the lower triangle isn?t |
|
|
//| used/changed by function |
|
|
//| * if False, symmetric matrix A is given by its |
|
|
//| lower triangle, and the upper triangle isn?t |
|
|
//| used/changed by function |
|
|
//| * if not given, lower half is used. |
|
|
//| Output parameters: |
|
|
//| Info - return code, same as in RMatrixLUInverse |
|
|
//| Rep - solver report, same as in RMatrixLUInverse |
|
|
//| A - inverse of matrix A, same as in RMatrixLUInverse |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SPDMatrixCholeskyInverse(CMatrixDouble &a,int &info,
|
|
CMatInvReportShell &rep)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
bool isupper;
|
|
//--- check
|
|
if((CAp::Cols(a)!=CAp::Rows(a)))
|
|
{
|
|
Print(__FUNCTION__+": looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
info=0;
|
|
n=CAp::Cols(a);
|
|
//--- initialization
|
|
isupper=false;
|
|
//--- function call
|
|
CMatInv::SPDMatrixCholeskyInverse(a,n,isupper,info,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inversion of a symmetric positive definite matrix. |
|
|
//| Given an upper or lower triangle of a symmetric positive definite|
|
|
//| matrix, the algorithm generates matrix A^-1 and saves the upper |
|
|
//| or lower triangle depending on the input. |
|
|
//| Input parameters: |
|
|
//| A - matrix to be inverted (upper or lower triangle). |
|
|
//| Array with elements [0..N-1,0..N-1]. |
|
|
//| N - size of matrix A (optional) : |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, size is automatically determined |
|
|
//| from matrix size (A must be square matrix) |
|
|
//| IsUpper - storage type (optional): |
|
|
//| * if True, symmetric matrix A is given by its |
|
|
//| upper triangle, and the lower triangle isn?t |
|
|
//| used/changed by function |
|
|
//| * if False, symmetric matrix A is given by its |
|
|
//| lower triangle, and the upper triangle isn?t |
|
|
//| used/changed by function |
|
|
//| * if not given, both lower and upper triangles |
|
|
//| must be filled. |
|
|
//| Output parameters: |
|
|
//| Info - return code, same as in RMatrixLUInverse |
|
|
//| Rep - solver report, same as in RMatrixLUInverse |
|
|
//| A - inverse of matrix A, same as in RMatrixLUInverse |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SPDMatrixInverse(CMatrixDouble &a,const int n,
|
|
const bool isupper,int &info,
|
|
CMatInvReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CMatInv::SPDMatrixInverse(a,n,isupper,info,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inversion of a symmetric positive definite matrix. |
|
|
//| Given an upper or lower triangle of a symmetric positive definite|
|
|
//| matrix, the algorithm generates matrix A^-1 and saves the upper |
|
|
//| or lower triangle depending on the input. |
|
|
//| Input parameters: |
|
|
//| A - matrix to be inverted (upper or lower triangle). |
|
|
//| Array with elements [0..N-1,0..N-1]. |
|
|
//| N - size of matrix A (optional) : |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, size is automatically determined |
|
|
//| from matrix size (A must be square matrix) |
|
|
//| IsUpper - storage type (optional): |
|
|
//| * if True, symmetric matrix A is given by its |
|
|
//| upper triangle, and the lower triangle isn?t |
|
|
//| used/changed by function |
|
|
//| * if False, symmetric matrix A is given by its |
|
|
//| lower triangle, and the upper triangle isn?t |
|
|
//| used/changed by function |
|
|
//| * if not given, both lower and upper triangles |
|
|
//| must be filled. |
|
|
//| Output parameters: |
|
|
//| Info - return code, same as in RMatrixLUInverse |
|
|
//| Rep - solver report, same as in RMatrixLUInverse |
|
|
//| A - inverse of matrix A, same as in RMatrixLUInverse |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SPDMatrixInverse(CMatrixDouble &a,int &info,
|
|
CMatInvReportShell &rep)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
bool isupper;
|
|
//--- check
|
|
if((CAp::Cols(a)!=CAp::Rows(a)))
|
|
{
|
|
Print(__FUNCTION__+": looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- check
|
|
if(!CAp::IsSymmetric(a))
|
|
{
|
|
Print(__FUNCTION__+": 'a' parameter is not symmetric matrix");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
info=0;
|
|
n=CAp::Cols(a);
|
|
isupper=false;
|
|
//--- function call
|
|
CMatInv::SPDMatrixInverse(a,n,isupper,info,rep.GetInnerObj());
|
|
//--- check
|
|
if(!CAp::ForceSymmetric(a))
|
|
{
|
|
Print(__FUNCTION__+": Internal error while forcing symmetricity of 'a' parameter");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inversion of a Hermitian positive definite matrix which is given |
|
|
//| by Cholesky decomposition. |
|
|
//| Input parameters: |
|
|
//| A - Cholesky decomposition of the matrix to be |
|
|
//| inverted: A=U?*U or A = L*L'. |
|
|
//| Output of HPDMatrixCholesky subroutine. |
|
|
//| N - size of matrix A (optional) : |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, size is automatically determined |
|
|
//| from matrix size (A must be square matrix) |
|
|
//| IsUpper - storage type (optional): |
|
|
//| * if True, symmetric matrix A is given by its |
|
|
//| upper triangle, and the lower triangle isn?t |
|
|
//| used/changed by function |
|
|
//| * if False, symmetric matrix A is given by its |
|
|
//| lower triangle, and the upper triangle isn?t |
|
|
//| used/changed by function |
|
|
//| * if not given, lower half is used. |
|
|
//| Output parameters: |
|
|
//| Info - return code, same as in RMatrixLUInverse |
|
|
//| Rep - solver report, same as in RMatrixLUInverse |
|
|
//| A - inverse of matrix A, same as in RMatrixLUInverse |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::HPDMatrixCholeskyInverse(CMatrixComplex &a,const int n,
|
|
const bool isupper,int &info,
|
|
CMatInvReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CMatInv::HPDMatrixCholeskyInverse(a,n,isupper,info,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inversion of a Hermitian positive definite matrix which is given |
|
|
//| by Cholesky decomposition. |
|
|
//| Input parameters: |
|
|
//| A - Cholesky decomposition of the matrix to be |
|
|
//| inverted: A=U?*U or A = L*L'. |
|
|
//| Output of HPDMatrixCholesky subroutine. |
|
|
//| N - size of matrix A (optional) : |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, size is automatically determined |
|
|
//| from matrix size (A must be square matrix) |
|
|
//| IsUpper - storage type (optional): |
|
|
//| * if True, symmetric matrix A is given by its |
|
|
//| upper triangle, and the lower triangle isn?t |
|
|
//| used/changed by function |
|
|
//| * if False, symmetric matrix A is given by its |
|
|
//| lower triangle, and the upper triangle isn?t |
|
|
//| used/changed by function |
|
|
//| * if not given, lower half is used. |
|
|
//| Output parameters: |
|
|
//| Info - return code, same as in RMatrixLUInverse |
|
|
//| Rep - solver report, same as in RMatrixLUInverse |
|
|
//| A - inverse of matrix A, same as in RMatrixLUInverse |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::HPDMatrixCholeskyInverse(CMatrixComplex &a,int &info,
|
|
CMatInvReportShell &rep)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
bool isupper;
|
|
//--- check
|
|
if((CAp::Cols(a)!=CAp::Rows(a)))
|
|
{
|
|
Print(__FUNCTION__+": looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
info=0;
|
|
n=CAp::Cols(a);
|
|
isupper=false;
|
|
//--- function call
|
|
CMatInv::HPDMatrixCholeskyInverse(a,n,isupper,info,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inversion of a Hermitian positive definite matrix. |
|
|
//| Given an upper or lower triangle of a Hermitian positive definite|
|
|
//| matrix, the algorithm generates matrix A^-1 and saves the upper |
|
|
//| or lower triangle depending on the input. |
|
|
//| Input parameters: |
|
|
//| A - matrix to be inverted (upper or lower triangle). |
|
|
//| Array with elements [0..N-1,0..N-1]. |
|
|
//| N - size of matrix A (optional) : |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, size is automatically determined |
|
|
//| from matrix size (A must be square matrix) |
|
|
//| IsUpper - storage type (optional): |
|
|
//| * if True, symmetric matrix A is given by its |
|
|
//| upper triangle, and the lower triangle isn?t |
|
|
//| used/changed by function |
|
|
//| * if False, symmetric matrix A is given by its |
|
|
//| lower triangle, and the upper triangle isn?t |
|
|
//| used/changed by function |
|
|
//| * if not given, both lower and upper triangles |
|
|
//| must be filled. |
|
|
//| Output parameters: |
|
|
//| Info - return code, same as in RMatrixLUInverse |
|
|
//| Rep - solver report, same as in RMatrixLUInverse |
|
|
//| A - inverse of matrix A, same as in RMatrixLUInverse |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::HPDMatrixInverse(CMatrixComplex &a,const int n,
|
|
const bool isupper,int &info,
|
|
CMatInvReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CMatInv::HPDMatrixInverse(a,n,isupper,info,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inversion of a Hermitian positive definite matrix. |
|
|
//| Given an upper or lower triangle of a Hermitian positive definite|
|
|
//| matrix, the algorithm generates matrix A^-1 and saves the upper |
|
|
//| or lower triangle depending on the input. |
|
|
//| Input parameters: |
|
|
//| A - matrix to be inverted (upper or lower triangle). |
|
|
//| Array with elements [0..N-1,0..N-1]. |
|
|
//| N - size of matrix A (optional) : |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, size is automatically determined |
|
|
//| from matrix size (A must be square matrix) |
|
|
//| IsUpper - storage type (optional): |
|
|
//| * if True, symmetric matrix A is given by its |
|
|
//| upper triangle, and the lower triangle isn?t |
|
|
//| used/changed by function |
|
|
//| * if False, symmetric matrix A is given by its |
|
|
//| lower triangle, and the upper triangle isn?t |
|
|
//| used/changed by function |
|
|
//| * if not given, both lower and upper triangles |
|
|
//| must be filled. |
|
|
//| Output parameters: |
|
|
//| Info - return code, same as in RMatrixLUInverse |
|
|
//| Rep - solver report, same as in RMatrixLUInverse |
|
|
//| A - inverse of matrix A, same as in RMatrixLUInverse |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::HPDMatrixInverse(CMatrixComplex &a,int &info,
|
|
CMatInvReportShell &rep)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
bool isupper;
|
|
//--- check
|
|
if((CAp::Cols(a)!=CAp::Rows(a)))
|
|
{
|
|
Print(__FUNCTION__+": looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- check
|
|
if(!CAp::IsHermitian(a))
|
|
{
|
|
Print(__FUNCTION__+": 'a' parameter is not Hermitian matrix");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
info=0;
|
|
n=CAp::Cols(a);
|
|
isupper=false;
|
|
//--- function call
|
|
CMatInv::HPDMatrixInverse(a,n,isupper,info,rep.GetInnerObj());
|
|
//--- check
|
|
if(!CAp::ForceHermitian(a))
|
|
{
|
|
Print(__FUNCTION__+": Internal error while forcing Hermitian properties of 'a' parameter");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Triangular matrix inverse (real) |
|
|
//| The subroutine inverts the following types of matrices: |
|
|
//| * upper triangular |
|
|
//| * upper triangular with unit diagonal |
|
|
//| * lower triangular |
|
|
//| * lower triangular with unit diagonal |
|
|
//| In case of an upper (lower) triangular matrix, the inverse matrix|
|
|
//| will also be upper (lower) triangular, and after the end of the |
|
|
//| algorithm, the inverse matrix replaces the source matrix. The |
|
|
//| elements below (above) the main diagonal are not changed by the |
|
|
//| algorithm. |
|
|
//| If the matrix has a unit diagonal, the inverse matrix also has a |
|
|
//| unit diagonal, and the diagonal elements are not passed to the |
|
|
//| algorithm. |
|
|
//| Input parameters: |
|
|
//| A - matrix, array[0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A (optional) : |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, size is automatically determined |
|
|
//| from matrix size (A must be square matrix) |
|
|
//| IsUpper - True, if the matrix is upper triangular. |
|
|
//| IsUnit - diagonal type (optional): |
|
|
//| * if True, matrix has unit diagonal (a[i,i] are |
|
|
//| NOT used) |
|
|
//| * if False, matrix diagonal is arbitrary |
|
|
//| * if not given, False is assumed |
|
|
//| Output parameters: |
|
|
//| Info - same as for RMatrixLUInverse |
|
|
//| Rep - same as for RMatrixLUInverse |
|
|
//| A - same as for RMatrixLUInverse. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixTrInverse(CMatrixDouble &a,const int n,
|
|
const bool isupper,const bool isunit,
|
|
int &info,CMatInvReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CMatInv::RMatrixTrInverse(a,n,isupper,isunit,info,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Triangular matrix inverse (real) |
|
|
//| The subroutine inverts the following types of matrices: |
|
|
//| * upper triangular |
|
|
//| * upper triangular with unit diagonal |
|
|
//| * lower triangular |
|
|
//| * lower triangular with unit diagonal |
|
|
//| In case of an upper (lower) triangular matrix, the inverse matrix|
|
|
//| will also be upper (lower) triangular, and after the end of the |
|
|
//| algorithm, the inverse matrix replaces the source matrix. The |
|
|
//| elements below (above) the main diagonal are not changed by the |
|
|
//| algorithm. |
|
|
//| If the matrix has a unit diagonal, the inverse matrix also has a |
|
|
//| unit diagonal, and the diagonal elements are not passed to the |
|
|
//| algorithm. |
|
|
//| Input parameters: |
|
|
//| A - matrix, array[0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A (optional) : |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, size is automatically determined |
|
|
//| from matrix size (A must be square matrix) |
|
|
//| IsUpper - True, if the matrix is upper triangular. |
|
|
//| IsUnit - diagonal type (optional): |
|
|
//| * if True, matrix has unit diagonal (a[i,i] are |
|
|
//| NOT used) |
|
|
//| * if False, matrix diagonal is arbitrary |
|
|
//| * if not given, False is assumed |
|
|
//| Output parameters: |
|
|
//| Info - same as for RMatrixLUInverse |
|
|
//| Rep - same as for RMatrixLUInverse |
|
|
//| A - same as for RMatrixLUInverse. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixTrInverse(CMatrixDouble &a,const bool isupper,
|
|
int &info,CMatInvReportShell &rep)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
bool isunit;
|
|
//--- check
|
|
if((CAp::Cols(a)!=CAp::Rows(a)))
|
|
{
|
|
Print(__FUNCTION__+": looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
info=0;
|
|
n=CAp::Cols(a);
|
|
isunit=false;
|
|
//--- function call
|
|
CMatInv::RMatrixTrInverse(a,n,isupper,isunit,info,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Triangular matrix inverse (complex) |
|
|
//| The subroutine inverts the following types of matrices: |
|
|
//| * upper triangular |
|
|
//| * upper triangular with unit diagonal |
|
|
//| * lower triangular |
|
|
//| * lower triangular with unit diagonal |
|
|
//| In case of an upper (lower) triangular matrix, the inverse matrix|
|
|
//| will also be upper (lower) triangular, and after the end of the |
|
|
//| algorithm, the inverse matrix replaces the source matrix. The |
|
|
//| elements below (above) the main diagonal are not changed by the |
|
|
//| algorithm. |
|
|
//| If the matrix has a unit diagonal, the inverse matrix also has a |
|
|
//| unit diagonal, and the diagonal elements are not passed to the |
|
|
//| algorithm. |
|
|
//| Input parameters: |
|
|
//| A - matrix, array[0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A (optional) : |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, size is automatically determined |
|
|
//| from matrix size (A must be square matrix) |
|
|
//| IsUpper - True, if the matrix is upper triangular. |
|
|
//| IsUnit - diagonal type (optional): |
|
|
//| * if True, matrix has unit diagonal (a[i,i] are |
|
|
//| NOT used) |
|
|
//| * if False, matrix diagonal is arbitrary |
|
|
//| * if not given, False is assumed |
|
|
//| Output parameters: |
|
|
//| Info - same as for RMatrixLUInverse |
|
|
//| Rep - same as for RMatrixLUInverse |
|
|
//| A - same as for RMatrixLUInverse. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixTrInverse(CMatrixComplex &a,const int n,
|
|
const bool isupper,const bool isunit,
|
|
int &info,CMatInvReportShell &rep)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CMatInv::CMatrixTrInverse(a,n,isupper,isunit,info,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Triangular matrix inverse (complex) |
|
|
//| The subroutine inverts the following types of matrices: |
|
|
//| * upper triangular |
|
|
//| * upper triangular with unit diagonal |
|
|
//| * lower triangular |
|
|
//| * lower triangular with unit diagonal |
|
|
//| In case of an upper (lower) triangular matrix, the inverse matrix|
|
|
//| will also be upper (lower) triangular, and after the end of the |
|
|
//| algorithm, the inverse matrix replaces the source matrix. The |
|
|
//| elements below (above) the main diagonal are not changed by the |
|
|
//| algorithm. |
|
|
//| If the matrix has a unit diagonal, the inverse matrix also has a |
|
|
//| unit diagonal, and the diagonal elements are not passed to the |
|
|
//| algorithm. |
|
|
//| Input parameters: |
|
|
//| A - matrix, array[0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A (optional) : |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, size is automatically determined |
|
|
//| from matrix size (A must be square matrix) |
|
|
//| IsUpper - True, if the matrix is upper triangular. |
|
|
//| IsUnit - diagonal type (optional): |
|
|
//| * if True, matrix has unit diagonal (a[i,i] are |
|
|
//| NOT used) |
|
|
//| * if False, matrix diagonal is arbitrary |
|
|
//| * if not given, False is assumed |
|
|
//| Output parameters: |
|
|
//| Info - same as for RMatrixLUInverse |
|
|
//| Rep - same as for RMatrixLUInverse |
|
|
//| A - same as for RMatrixLUInverse. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixTrInverse(CMatrixComplex &a,const bool isupper,
|
|
int &info,CMatInvReportShell &rep)
|
|
{
|
|
//--- create variables
|
|
int n;
|
|
bool isunit;
|
|
//--- check
|
|
if((CAp::Cols(a)!=CAp::Rows(a)))
|
|
{
|
|
Print(__FUNCTION__+": looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
info=0;
|
|
n=CAp::Cols(a);
|
|
isunit=false;
|
|
//--- function call
|
|
CMatInv::CMatrixTrInverse(a,n,isupper,isunit,info,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Singular value decomposition of a bidiagonal matrix (extended |
|
|
//| algorithm) |
|
|
//| The algorithm performs the singular value decomposition of a |
|
|
//| bidiagonal matrix B (upper or lower) representing it as |
|
|
//| B = Q*S*P^T, where Q and P - orthogonal matrices, S - diagonal |
|
|
//| matrix with non-negative elements on the main diagonal, in |
|
|
//| descending order. |
|
|
//| The algorithm finds singular values. In addition, the algorithm |
|
|
//| can calculate matrices Q and P (more precisely, not the matrices,|
|
|
//| but their product with given matrices U and VT - U*Q and |
|
|
//| (P^T)*VT)). Of course, matrices U and VT can be of any type, |
|
|
//| including identity. Furthermore, the algorithm can calculate Q'*C|
|
|
//| (this product is calculated more effectively than U*Q, because |
|
|
//| this calculation operates with rows instead of matrix columns). |
|
|
//| The feature of the algorithm is its ability to find all singular |
|
|
//| values including those which are arbitrarily close to 0 with |
|
|
//| relative accuracy close to machine precision. If the parameter |
|
|
//| IsFractionalAccuracyRequired is set to True, all singular values |
|
|
//| will have high relative accuracy close to machine precision. If |
|
|
//| the parameter is set to False, only the biggest singular value |
|
|
//| will have relative accuracy close to machine precision. The |
|
|
//| absolute error of other singular values is equal to the absolute |
|
|
//| error of the biggest singular value. |
|
|
//| Input parameters: |
|
|
//| D - main diagonal of matrix B. |
|
|
//| Array whose index ranges within [0..N-1]. |
|
|
//| E - superdiagonal (or subdiagonal) of matrix B. |
|
|
//| Array whose index ranges within [0..N-2]. |
|
|
//| N - size of matrix B. |
|
|
//| IsUpper - True, if the matrix is upper bidiagonal. |
|
|
//| IsFractionalAccuracyRequired - |
|
|
//| accuracy to search singular values with. |
|
|
//| U - matrix to be multiplied by Q. |
|
|
//| Array whose indexes range within |
|
|
//| [0..NRU-1, 0..N-1]. |
|
|
//| The matrix can be bigger, in that case only the |
|
|
//| submatrix [0..NRU-1, 0..N-1] will be multiplied |
|
|
//| by Q. |
|
|
//| NRU - number of rows in matrix U. |
|
|
//| C - matrix to be multiplied by Q'. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..NCC-1]. |
|
|
//| The matrix can be bigger, in that case only the |
|
|
//| submatrix [0..N-1, 0..NCC-1] will be multiplied |
|
|
//| by Q'. |
|
|
//| NCC - number of columns in matrix C. |
|
|
//| VT - matrix to be multiplied by P^T. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..NCVT-1]. |
|
|
//| The matrix can be bigger, in that case only the |
|
|
//| submatrix [0..N-1, 0..NCVT-1] will be multiplied |
|
|
//| by P^T. |
|
|
//| NCVT - number of columns in matrix VT. |
|
|
//| Output parameters: |
|
|
//| D - singular values of matrix B in descending order. |
|
|
//| U - if NRU>0, contains matrix U*Q. |
|
|
//| VT - if NCVT>0, contains matrix (P^T)*VT. |
|
|
//| C - if NCC>0, contains matrix Q'*C. |
|
|
//| Result: |
|
|
//| True, if the algorithm has converged. |
|
|
//| False, if the algorithm hasn't converged (rare case). |
|
|
//| Additional information: |
|
|
//| The type of convergence is controlled by the internal |
|
|
//| parameter TOL. If the parameter is greater than 0, the |
|
|
//| singular values will have relative accuracy TOL. If TOL<0, |
|
|
//| the singular values will have absolute accuracy |
|
|
//| ABS(TOL)*norm(B). By default, |TOL| falls within the range of|
|
|
//| 10*Epsilon and 100*Epsilon, where Epsilon is the machine |
|
|
//| precision. It is not recommended to use TOL less than |
|
|
//| 10*Epsilon since this will considerably slow down the |
|
|
//| algorithm and may not lead to error decreasing. |
|
|
//| History: |
|
|
//| * 31 March, 2007. |
|
|
//| changed MAXITR from 6 to 12. |
|
|
//| -- LAPACK routine (version 3.0) -- |
|
|
//| Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., |
|
|
//| Courant Institute, Argonne National Lab, and Rice University|
|
|
//| October 31, 1999. |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::RMatrixBdSVD(double &d[],double &e[],const int n,
|
|
const bool isupper,
|
|
bool isfractionalaccuracyrequired,
|
|
CMatrixDouble &u,const int nru,
|
|
CMatrixDouble &c,const int ncc,
|
|
CMatrixDouble &vt,const int ncvt)
|
|
{
|
|
//--- return result
|
|
return(CBdSingValueDecompose::RMatrixBdSVD(d,e,n,isupper,isfractionalaccuracyrequired,u,nru,c,ncc,vt,ncvt));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Singular value decomposition of a rectangular matrix. |
|
|
//| The algorithm calculates the singular value decomposition of a |
|
|
//| matrix of size MxN: A = U * S * V^T |
|
|
//| The algorithm finds the singular values and, optionally, matrices|
|
|
//| U and V^T. The algorithm can find both first min(M,N) columns of |
|
|
//| matrix U and rows of matrix V^T (singular vectors), and matrices |
|
|
//| U and V^T wholly (of sizes MxM and NxN respectively). |
|
|
//| Take into account that the subroutine does not return matrix V |
|
|
//| but V^T. |
|
|
//| Input parameters: |
|
|
//| A - matrix to be decomposed. |
|
|
//| Array whose indexes range within |
|
|
//| [0..M-1, 0..N-1]. |
|
|
//| M - number of rows in matrix A. |
|
|
//| N - number of columns in matrix A. |
|
|
//| UNeeded - 0, 1 or 2. See the description of the |
|
|
//| parameter U. |
|
|
//| VTNeeded - 0, 1 or 2. See the description of the |
|
|
//| parameter VT. |
|
|
//| AdditionalMemory - |
|
|
//| If the parameter: |
|
|
//| * equals 0, the algorithm doesn?t use |
|
|
//| additional memory (lower requirements, |
|
|
//| lower performance). |
|
|
//| * equals 1, the algorithm uses additional |
|
|
//| memory of size min(M,N)*min(M,N) of real |
|
|
//| numbers. It often speeds up the algorithm.|
|
|
//| * equals 2, the algorithm uses additional |
|
|
//| memory of size M*min(M,N) of real numbers.|
|
|
//| It allows to get a maximum performance. |
|
|
//| The recommended value of the parameter is 2. |
|
|
//| Output parameters: |
|
|
//| W - contains singular values in descending order.|
|
|
//| U - if UNeeded=0, U isn't changed, the left |
|
|
//| singular vectors are not calculated. |
|
|
//| if Uneeded=1, U contains left singular |
|
|
//| vectors (first min(M,N) columns of matrix U).|
|
|
//| Array whose indexes range within |
|
|
//| [0..M-1, 0..Min(M,N)-1]. if UNeeded=2, U |
|
|
//| contains matrix U wholly. Array whose indexes|
|
|
//| range within [0..M-1, 0..M-1]. |
|
|
//| VT - if VTNeeded=0, VT isn?t changed, the right |
|
|
//| singular vectors are not calculated. |
|
|
//| if VTNeeded=1, VT contains right singular |
|
|
//| vectors (first min(M,N) rows of matrix V^T). |
|
|
//| Array whose indexes range within |
|
|
//| [0..min(M,N)-1, 0..N-1]. if VTNeeded=2, VT |
|
|
//| contains matrix V^T wholly. Array whose |
|
|
//| indexes range within [0..N-1, 0..N-1]. |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::RMatrixSVD(CMatrixDouble &a,const int m,const int n,
|
|
const int uneeded,const int vtneeded,
|
|
const int additionalmemory,double &w[],
|
|
CMatrixDouble &u,CMatrixDouble &vt)
|
|
{
|
|
//--- return result
|
|
return(CSingValueDecompose::RMatrixSVD(a,m,n,uneeded,vtneeded,additionalmemory,w,u,vt));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Determinant calculation of the matrix given by its LU |
|
|
//| decomposition. |
|
|
//| Input parameters: |
|
|
//| A - LU decomposition of the matrix (output of |
|
|
//| RMatrixLU subroutine). |
|
|
//| Pivots - table of permutations which were made during |
|
|
//| the LU decomposition. |
|
|
//| Output of RMatrixLU subroutine. |
|
|
//| N - (optional) size of matrix A: |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, automatically determined from |
|
|
//| matrix size (A must be square matrix) |
|
|
//| Result: matrix determinant. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::RMatrixLUDet(CMatrixDouble &a,int &pivots[],const int n)
|
|
{
|
|
//--- return result
|
|
return(CMatDet::RMatrixLUDet(a,pivots,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Determinant calculation of the matrix given by its LU |
|
|
//| decomposition. |
|
|
//| Input parameters: |
|
|
//| A - LU decomposition of the matrix (output of |
|
|
//| RMatrixLU subroutine). |
|
|
//| Pivots - table of permutations which were made during |
|
|
//| the LU decomposition. |
|
|
//| Output of RMatrixLU subroutine. |
|
|
//| N - (optional) size of matrix A: |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, automatically determined from |
|
|
//| matrix size (A must be square matrix) |
|
|
//| Result: matrix determinant. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::RMatrixLUDet(CMatrixDouble &a,int &pivots[])
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- check
|
|
if((CAp::Rows(a)!=CAp::Cols(a)) || (CAp::Rows(a)!=CAp::Len(pivots)))
|
|
{
|
|
Print(__FUNCTION__+": looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return(EMPTY_VALUE);
|
|
}
|
|
//--- initialization
|
|
n=CAp::Rows(a);
|
|
//--- return result
|
|
return(CMatDet::RMatrixLUDet(a,pivots,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Calculation of the determinant of a general matrix |
|
|
//| Input parameters: |
|
|
//| A - matrix, array[0..N-1, 0..N-1] |
|
|
//| N - (optional) size of matrix A: |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, automatically determined from |
|
|
//| matrix size (A must be square matrix) |
|
|
//| Result: determinant of matrix A. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::RMatrixDet(CMatrixDouble &a,const int n)
|
|
{
|
|
//--- return result
|
|
return(CMatDet::RMatrixDet(a,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Calculation of the determinant of a general matrix |
|
|
//| Input parameters: |
|
|
//| A - matrix, array[0..N-1, 0..N-1] |
|
|
//| N - (optional) size of matrix A: |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, automatically determined from |
|
|
//| matrix size (A must be square matrix) |
|
|
//| Result: determinant of matrix A. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::RMatrixDet(CMatrixDouble &a)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- check
|
|
if((CAp::Rows(a)!=CAp::Cols(a)))
|
|
{
|
|
Print(__FUNCTION__+": looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return(EMPTY_VALUE);
|
|
}
|
|
//--- initialization
|
|
n=CAp::Rows(a);
|
|
//--- return result
|
|
return(CMatDet::RMatrixDet(a,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Determinant calculation of the matrix given by its LU |
|
|
//| decomposition. |
|
|
//| Input parameters: |
|
|
//| A - LU decomposition of the matrix (output of |
|
|
//| RMatrixLU subroutine). |
|
|
//| Pivots - table of permutations which were made during |
|
|
//| the LU decomposition. |
|
|
//| Output of RMatrixLU subroutine. |
|
|
//| N - (optional) size of matrix A: |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, automatically determined from |
|
|
//| matrix size (A must be square matrix) |
|
|
//| Result: matrix determinant. |
|
|
//+------------------------------------------------------------------+
|
|
static complex CAlglib::CMatrixLUDet(CMatrixComplex &a,int &pivots[],
|
|
const int n)
|
|
{
|
|
//--- return result
|
|
return(CMatDet::CMatrixLUDet(a,pivots,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Determinant calculation of the matrix given by its LU |
|
|
//| decomposition. |
|
|
//| Input parameters: |
|
|
//| A - LU decomposition of the matrix (output of |
|
|
//| RMatrixLU subroutine). |
|
|
//| Pivots - table of permutations which were made during |
|
|
//| the LU decomposition. |
|
|
//| Output of RMatrixLU subroutine. |
|
|
//| N - (optional) size of matrix A: |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, automatically determined from |
|
|
//| matrix size (A must be square matrix) |
|
|
//| Result: matrix determinant. |
|
|
//+------------------------------------------------------------------+
|
|
static complex CAlglib::CMatrixLUDet(CMatrixComplex &a,int &pivots[])
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- check
|
|
if((CAp::Rows(a)!=CAp::Cols(a)) || (CAp::Rows(a)!=CAp::Len(pivots)))
|
|
{
|
|
Print(__FUNCTION__+": looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return(EMPTY_VALUE);
|
|
}
|
|
//--- initialization
|
|
n=CAp::Rows(a);
|
|
//--- return result
|
|
return(CMatDet::CMatrixLUDet(a,pivots,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Calculation of the determinant of a general matrix |
|
|
//| Input parameters: |
|
|
//| A - matrix, array[0..N-1, 0..N-1] |
|
|
//| N - (optional) size of matrix A: |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, automatically determined from |
|
|
//| matrix size (A must be square matrix) |
|
|
//| Result: determinant of matrix A. |
|
|
//+------------------------------------------------------------------+
|
|
static complex CAlglib::CMatrixDet(CMatrixComplex &a,const int n)
|
|
{
|
|
//--- return result
|
|
return(CMatDet::CMatrixDet(a,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Calculation of the determinant of a general matrix |
|
|
//| Input parameters: |
|
|
//| A - matrix, array[0..N-1, 0..N-1] |
|
|
//| N - (optional) size of matrix A: |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, automatically determined from |
|
|
//| matrix size (A must be square matrix) |
|
|
//| Result: determinant of matrix A. |
|
|
//+------------------------------------------------------------------+
|
|
static complex CAlglib::CMatrixDet(CMatrixComplex &a)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- check
|
|
if((CAp::Rows(a)!=CAp::Cols(a)))
|
|
{
|
|
Print(__FUNCTION__+": looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return(EMPTY_VALUE);
|
|
}
|
|
//--- initialization
|
|
n=CAp::Rows(a);
|
|
//--- return result
|
|
return(CMatDet::CMatrixDet(a,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Determinant calculation of the matrix given by the Cholesky |
|
|
//| decomposition. |
|
|
//| Input parameters: |
|
|
//| A - Cholesky decomposition, |
|
|
//| output of SMatrixCholesky subroutine. |
|
|
//| N - (optional) size of matrix A: |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, automatically determined from |
|
|
//| matrix size (A must be square matrix) |
|
|
//| As the determinant is equal to the product of squares of diagonal|
|
|
//| elements, it?s not necessary to specify which triangle - lower |
|
|
//| or upper - the matrix is stored in. |
|
|
//| Result: |
|
|
//| matrix determinant. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::SPDMatrixCholeskyDet(CMatrixDouble &a,const int n)
|
|
{
|
|
//--- return result
|
|
return(CMatDet::SPDMatrixCholeskyDet(a,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Determinant calculation of the matrix given by the Cholesky |
|
|
//| decomposition. |
|
|
//| Input parameters: |
|
|
//| A - Cholesky decomposition, |
|
|
//| output of SMatrixCholesky subroutine. |
|
|
//| N - (optional) size of matrix A: |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, automatically determined from |
|
|
//| matrix size (A must be square matrix) |
|
|
//| As the determinant is equal to the product of squares of diagonal|
|
|
//| elements, it?s not necessary to specify which triangle - lower |
|
|
//| or upper - the matrix is stored in. |
|
|
//| Result: |
|
|
//| matrix determinant. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::SPDMatrixCholeskyDet(CMatrixDouble &a)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- check
|
|
if((CAp::Rows(a)!=CAp::Cols(a)))
|
|
{
|
|
Print(__FUNCTION__+": looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return(EMPTY_VALUE);
|
|
}
|
|
//--- initialization
|
|
n=CAp::Rows(a);
|
|
//--- return result
|
|
return(CMatDet::SPDMatrixCholeskyDet(a,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Determinant calculation of the symmetric positive definite |
|
|
//| matrix. |
|
|
//| Input parameters: |
|
|
//| A - matrix. Array with elements [0..N-1, 0..N-1]. |
|
|
//| N - (optional) size of matrix A: |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, automatically determined from |
|
|
//| matrix size (A must be square matrix) |
|
|
//| IsUpper - (optional) storage type: |
|
|
//| * if True, symmetric matrix A is given by its |
|
|
//| upper triangle, and the lower triangle isn?t |
|
|
//| used/changed by function |
|
|
//| * if False, symmetric matrix A is given by its |
|
|
//| lower triangle, and the upper triangle isn?t |
|
|
//| used/changed by function |
|
|
//| * if not given, both lower and upper triangles |
|
|
//| must be filled. |
|
|
//| Result: |
|
|
//| determinant of matrix A. |
|
|
//| If matrix A is not positive definite, exception is thrown. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::SPDMatrixDet(CMatrixDouble &a,const int n,
|
|
const bool isupper)
|
|
{
|
|
//--- return result
|
|
return(CMatDet::SPDMatrixDet(a,n,isupper));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Determinant calculation of the symmetric positive definite |
|
|
//| matrix. |
|
|
//| Input parameters: |
|
|
//| A - matrix. Array with elements [0..N-1, 0..N-1]. |
|
|
//| N - (optional) size of matrix A: |
|
|
//| * if given, only principal NxN submatrix is |
|
|
//| processed and overwritten. other elements are |
|
|
//| unchanged. |
|
|
//| * if not given, automatically determined from |
|
|
//| matrix size (A must be square matrix) |
|
|
//| IsUpper - (optional) storage type: |
|
|
//| * if True, symmetric matrix A is given by its |
|
|
//| upper triangle, and the lower triangle isn?t |
|
|
//| used/changed by function |
|
|
//| * if False, symmetric matrix A is given by its |
|
|
//| lower triangle, and the upper triangle isn?t |
|
|
//| used/changed by function |
|
|
//| * if not given, both lower and upper triangles |
|
|
//| must be filled. |
|
|
//| Result: |
|
|
//| determinant of matrix A. |
|
|
//| If matrix A is not positive definite, exception is thrown. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::SPDMatrixDet(CMatrixDouble &a)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
bool isupper;
|
|
//--- check
|
|
if((CAp::Rows(a)!=CAp::Cols(a)))
|
|
{
|
|
Print(__FUNCTION__+": looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return(EMPTY_VALUE);
|
|
}
|
|
//--- check
|
|
if(!CAp::IsSymmetric(a))
|
|
{
|
|
Print(__FUNCTION__+": 'a' parameter is not symmetric matrix");
|
|
CAp::exception_happened=true;
|
|
return(EMPTY_VALUE);
|
|
}
|
|
//--- initialization
|
|
n=CAp::Rows(a);
|
|
isupper=false;
|
|
//--- return result
|
|
return(CMatDet::SPDMatrixDet(a,n,isupper));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Algorithm for solving the following generalized symmetric |
|
|
//| positive-definite eigenproblem: |
|
|
//| A*x = lambda*B*x (1) or |
|
|
//| A*B*x = lambda*x (2) or |
|
|
//| B*A*x = lambda*x (3). |
|
|
//| where A is a symmetric matrix, B - symmetric positive-definite |
|
|
//| matrix. The problem is solved by reducing it to an ordinary |
|
|
//| symmetric eigenvalue problem. |
|
|
//| Input parameters: |
|
|
//| A - symmetric matrix which is given by its upper |
|
|
//| or lower triangular part. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| N - size of matrices A and B. |
|
|
//| IsUpperA - storage format of matrix A. |
|
|
//| B - symmetric positive-definite matrix which is |
|
|
//| given by its upper or lower triangular part. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| IsUpperB - storage format of matrix B. |
|
|
//| ZNeeded - if ZNeeded is equal to: |
|
|
//| * 0, the eigenvectors are not returned; |
|
|
//| * 1, the eigenvectors are returned. |
|
|
//| ProblemType - if ProblemType is equal to: |
|
|
//| * 1, the following problem is solved: |
|
|
//| A*x = lambda*B*x; |
|
|
//| * 2, the following problem is solved: |
|
|
//| A*B*x = lambda*x; |
|
|
//| * 3, the following problem is solved: |
|
|
//| B*A*x = lambda*x. |
|
|
//| Output parameters: |
|
|
//| D - eigenvalues in ascending order. |
|
|
//| Array whose index ranges within [0..N-1]. |
|
|
//| Z - if ZNeeded is equal to: |
|
|
//| * 0, Z hasn?t changed; |
|
|
//| * 1, Z contains eigenvectors. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| The eigenvectors are stored in matrix |
|
|
//| columns. It should be noted that the |
|
|
//| eigenvectors in such problems do not form an |
|
|
//| orthogonal system. |
|
|
//| Result: |
|
|
//| True, if the problem was solved successfully. |
|
|
//| False, if the error occurred during the Cholesky |
|
|
//| decomposition of matrix B (the matrix isn?t |
|
|
//| positive-definite) or during the work of the iterative |
|
|
//| algorithm for solving the symmetric eigenproblem. |
|
|
//| See also the GeneralizedSymmetricDefiniteEVDReduce subroutine. |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::SMatrixGEVD(CMatrixDouble &a,const int n,const bool isuppera,
|
|
CMatrixDouble &b,const bool isupperb,
|
|
const int zneeded,const int problemtype,
|
|
double &d[],CMatrixDouble &z)
|
|
{
|
|
//--- return result
|
|
return(CSpdGEVD::SMatrixGEVD(a,n,isuppera,b,isupperb,zneeded,problemtype,d,z));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Algorithm for reduction of the following generalized symmetric |
|
|
//| positive- definite eigenvalue problem: |
|
|
//| A*x = lambda*B*x (1) or |
|
|
//| A*B*x = lambda*x (2) or |
|
|
//| B*A*x = lambda*x (3) |
|
|
//| to the symmetric eigenvalues problem C*y = lambda*y (eigenvalues |
|
|
//| of this and the given problems are the same, and the eigenvectors|
|
|
//| of the given problem could be obtained by multiplying the |
|
|
//| obtained eigenvectors by the transformation matrix x = R*y). |
|
|
//| Here A is a symmetric matrix, B - symmetric positive-definite |
|
|
//| matrix. |
|
|
//| Input parameters: |
|
|
//| A - symmetric matrix which is given by its upper |
|
|
//| or lower triangular part. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| N - size of matrices A and B. |
|
|
//| IsUpperA - storage format of matrix A. |
|
|
//| B - symmetric positive-definite matrix which is |
|
|
//| given by its upper or lower triangular part. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| IsUpperB - storage format of matrix B. |
|
|
//| ProblemType - if ProblemType is equal to: |
|
|
//| * 1, the following problem is solved: |
|
|
//| A*x = lambda*B*x; |
|
|
//| * 2, the following problem is solved: |
|
|
//| A*B*x = lambda*x; |
|
|
//| * 3, the following problem is solved: |
|
|
//| B*A*x = lambda*x. |
|
|
//| Output parameters: |
|
|
//| A - symmetric matrix which is given by its upper |
|
|
//| or lower triangle depending on IsUpperA. |
|
|
//| Contains matrix C. Array whose indexes range |
|
|
//| within [0..N-1, 0..N-1]. |
|
|
//| R - upper triangular or low triangular |
|
|
//| transformation matrix which is used to obtain|
|
|
//| the eigenvectors of a given problem as the |
|
|
//| product of eigenvectors of C (from the right)|
|
|
//| and matrix R (from the left). If the matrix |
|
|
//| is upper triangular, the elements below the |
|
|
//| main diagonal are equal to 0 (and vice versa)|
|
|
//| Thus, we can perform the multiplication |
|
|
//| without taking into account the internal |
|
|
//| structure (which is an easier though less |
|
|
//| effective way). Array whose indexes range |
|
|
//| within [0..N-1, 0..N-1]. |
|
|
//| IsUpperR - type of matrix R (upper or lower triangular).|
|
|
//| Result: |
|
|
//| True, if the problem was reduced successfully. |
|
|
//| False, if the error occurred during the Cholesky |
|
|
//| decomposition of matrix B (the matrix is not |
|
|
//| positive-definite). |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::SMatrixGEVDReduce(CMatrixDouble &a,const int n,
|
|
const bool isuppera,CMatrixDouble &b,
|
|
const bool isupperb,const int problemtype,
|
|
CMatrixDouble &r,bool &isupperr)
|
|
{
|
|
//--- initialization
|
|
isupperr=false;
|
|
//--- return result
|
|
return(CSpdGEVD::SMatrixGEVDReduce(a,n,isuppera,b,isupperb,problemtype,r,isupperr));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inverse matrix update by the Sherman-Morrison formula |
|
|
//| The algorithm updates matrix A^-1 when adding a number to an |
|
|
//| element of matrix A. |
|
|
//| Input parameters: |
|
|
//| InvA - inverse of matrix A. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| UpdRow - row where the element to be updated is stored. |
|
|
//| UpdColumn - column where the element to be updated is stored.|
|
|
//| UpdVal - a number to be added to the element. |
|
|
//| Output parameters: |
|
|
//| InvA - inverse of modified matrix A. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixInvUpdateSimple(CMatrixDouble &inva,const int n,
|
|
const int updrow,const int updcolumn,
|
|
const double updval)
|
|
{
|
|
//--- get result
|
|
CInverseUpdate::RMatrixInvUpdateSimple(inva,n,updrow,updcolumn,updval);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inverse matrix update by the Sherman-Morrison formula |
|
|
//| The algorithm updates matrix A^-1 when adding a vector to a row |
|
|
//| of matrix A. |
|
|
//| Input parameters: |
|
|
//| InvA - inverse of matrix A. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| UpdRow - the row of A whose vector V was added. |
|
|
//| 0 <= Row <= N-1 |
|
|
//| V - the vector to be added to a row. |
|
|
//| Array whose index ranges within [0..N-1]. |
|
|
//| Output parameters: |
|
|
//| InvA - inverse of modified matrix A. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixInvUpdateRow(CMatrixDouble &inva,const int n,
|
|
const int updrow,double &v[])
|
|
{
|
|
//--- get result
|
|
CInverseUpdate::RMatrixInvUpdateRow(inva,n,updrow,v);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inverse matrix update by the Sherman-Morrison formula |
|
|
//| The algorithm updates matrix A^-1 when adding a vector to a |
|
|
//| column of matrix A. |
|
|
//| Input parameters: |
|
|
//| InvA - inverse of matrix A. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| UpdColumn - the column of A whose vector U was added. |
|
|
//| 0 <= UpdColumn <= N-1 |
|
|
//| U - the vector to be added to a column. |
|
|
//| Array whose index ranges within [0..N-1]. |
|
|
//| Output parameters: |
|
|
//| InvA - inverse of modified matrix A. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixInvUpdateColumn(CMatrixDouble &inva,const int n,
|
|
const int updcolumn,double &u[])
|
|
{
|
|
//--- get result
|
|
CInverseUpdate::RMatrixInvUpdateColumn(inva,n,updcolumn,u);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inverse matrix update by the Sherman-Morrison formula |
|
|
//| The algorithm computes the inverse of matrix A+u*v? by using the |
|
|
//| given matrix A^-1 and the vectors u and v. |
|
|
//| Input parameters: |
|
|
//| InvA - inverse of matrix A. |
|
|
//| Array whose indexes range within |
|
|
//| [0..N-1, 0..N-1]. |
|
|
//| N - size of matrix A. |
|
|
//| U - the vector modifying the matrix. |
|
|
//| Array whose index ranges within [0..N-1]. |
|
|
//| V - the vector modifying the matrix. |
|
|
//| Array whose index ranges within [0..N-1]. |
|
|
//| Output parameters: |
|
|
//| InvA - inverse of matrix A + u*v'. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixInvUpdateUV(CMatrixDouble &inva,const int n,
|
|
double &u[],double &v[])
|
|
{
|
|
//--- get result
|
|
CInverseUpdate::RMatrixInvUpdateUV(inva,n,u,v);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Subroutine performing the Schur decomposition of a general matrix|
|
|
//| by using the QR algorithm with multiple shifts. |
|
|
//| The source matrix A is represented as S'*A*S = T, where S is an |
|
|
//| orthogonal matrix (Schur vectors), T - upper quasi-triangular |
|
|
//| matrix (with blocks of sizes 1x1 and 2x2 on the main diagonal). |
|
|
//| Input parameters: |
|
|
//| A - matrix to be decomposed. |
|
|
//| Array whose indexes range within [0..N-1, 0..N-1]. |
|
|
//| N - size of A, N>=0. |
|
|
//| Output parameters: |
|
|
//| A - contains matrix T. |
|
|
//| Array whose indexes range within [0..N-1, 0..N-1]. |
|
|
//| S - contains Schur vectors. |
|
|
//| Array whose indexes range within [0..N-1, 0..N-1]. |
|
|
//| Note 1: |
|
|
//| The block structure of matrix T can be easily recognized: |
|
|
//| since all the elements below the blocks are zeros, the |
|
|
//| elements a[i+1,i] which are equal to 0 show the block border.|
|
|
//| Note 2: |
|
|
//| The algorithm performance depends on the value of the |
|
|
//| internal parameter NS of the InternalSchurDecomposition |
|
|
//| subroutine which defines the number of shifts in the QR |
|
|
//| algorithm (similarly to the block width in block-matrix |
|
|
//| algorithms in linear algebra). If you require maximum |
|
|
//| performance on your machine, it is recommended to adjust |
|
|
//| this parameter manually. |
|
|
//| Result: |
|
|
//| True, |
|
|
//| if the algorithm has converged and parameters A and S |
|
|
//| contain the result. |
|
|
//| False, |
|
|
//| if the algorithm has not converged. |
|
|
//| Algorithm implemented on the basis of the DHSEQR subroutine |
|
|
//| (LAPACK 3.0 library). |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::RMatrixSchur(CMatrixDouble &a,const int n,CMatrixDouble &s)
|
|
{
|
|
//--- return result
|
|
return(CSchur::RMatrixSchur(a,n,s));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| NONLINEAR CONJUGATE GRADIENT METHOD |
|
|
//| DESCRIPTION: |
|
|
//| The subroutine minimizes function F(x) of N arguments by using |
|
|
//| one of the nonlinear conjugate gradient methods. |
|
|
//| These CG methods are globally convergent (even on non-convex |
|
|
//| functions) as long as grad(f) is Lipschitz continuous in a some |
|
|
//| neighborhood of the L = { x : f(x)<=f(x0) }. |
|
|
//| REQUIREMENTS: |
|
|
//| Algorithm will request following information during its |
|
|
//| operation: |
|
|
//| * function value F and its gradient G (simultaneously) at given |
|
|
//| point X |
|
|
//| USAGE: |
|
|
//| 1. User initializes algorithm state with MinCGCreate() call |
|
|
//| 2. User tunes solver parameters with MinCGSetCond(), |
|
|
//| MinCGSetStpMax() and other functions |
|
|
//| 3. User calls MinCGOptimize() function which takes algorithm |
|
|
//| state and pointer (delegate, etc.) to callback function which |
|
|
//| calculates F/G. |
|
|
//| 4. User calls MinCGResults() to get solution |
|
|
//| 5. Optionally, user may call MinCGRestartFrom() to solve another |
|
|
//| problem with same N but another starting point and/or another |
|
|
//| function. MinCGRestartFrom() allows to reuse already |
|
|
//| initialized structure. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - problem dimension, N>0: |
|
|
//| * if given, only leading N elements of X are used|
|
|
//| * if not given, automatically determined from |
|
|
//| size of X |
|
|
//| X - starting point, array[0..N-1]. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinCGCreate(const int n,double &x[],CMinCGStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinCG::MinCGCreate(n,x,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| NONLINEAR CONJUGATE GRADIENT METHOD |
|
|
//| DESCRIPTION: |
|
|
//| The subroutine minimizes function F(x) of N arguments by using |
|
|
//| one of the nonlinear conjugate gradient methods. |
|
|
//| These CG methods are globally convergent (even on non-convex |
|
|
//| functions) as long as grad(f) is Lipschitz continuous in a some |
|
|
//| neighborhood of the L = { x : f(x)<=f(x0) }. |
|
|
//| REQUIREMENTS: |
|
|
//| Algorithm will request following information during its |
|
|
//| operation: |
|
|
//| * function value F and its gradient G (simultaneously) at given |
|
|
//| point X |
|
|
//| USAGE: |
|
|
//| 1. User initializes algorithm state with MinCGCreate() call |
|
|
//| 2. User tunes solver parameters with MinCGSetCond(), |
|
|
//| MinCGSetStpMax() and other functions |
|
|
//| 3. User calls MinCGOptimize() function which takes algorithm |
|
|
//| state and pointer (delegate, etc.) to callback function which |
|
|
//| calculates F/G. |
|
|
//| 4. User calls MinCGResults() to get solution |
|
|
//| 5. Optionally, user may call MinCGRestartFrom() to solve another |
|
|
//| problem with same N but another starting point and/or another |
|
|
//| function. MinCGRestartFrom() allows to reuse already |
|
|
//| initialized structure. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - problem dimension, N>0: |
|
|
//| * if given, only leading N elements of X are used|
|
|
//| * if not given, automatically determined from |
|
|
//| size of X |
|
|
//| X - starting point, array[0..N-1]. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinCGCreate(double &x[],CMinCGStateShell &state)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CMinCG::MinCGCreate(n,x,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| The subroutine is finite difference variant of MinCGCreate(). |
|
|
//| It uses finite differences in order to differentiate target |
|
|
//| function. |
|
|
//| Description below contains information which is specific to this |
|
|
//| function only. We recommend to read comments on MinCGCreate() in |
|
|
//| order to get more information about creation of CG optimizer. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - problem dimension, N>0: |
|
|
//| * if given, only leading N elements of X are |
|
|
//| used |
|
|
//| * if not given, automatically determined from |
|
|
//| size of X |
|
|
//| X - starting point, array[0..N-1]. |
|
|
//| DiffStep- differentiation step, >0 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NOTES: |
|
|
//| 1. algorithm uses 4-point central formula for differentiation. |
|
|
//| 2. differentiation step along I-th axis is equal to |
|
|
//| DiffStep*S[I] where S[] is scaling vector which can be set by |
|
|
//| MinCGSetScale() call. |
|
|
//| 3. we recommend you to use moderate values of differentiation |
|
|
//| step. Too large step will result in too large truncation |
|
|
//| errors, while too small step will result in too large |
|
|
//| numerical errors. 1.0E-6 can be good value to start with. |
|
|
//| 4. Numerical differentiation is very inefficient - one gradient |
|
|
//| calculation needs 4*N function evaluations. This function will|
|
|
//| work for any N - either small (1...10), moderate (10...100) or|
|
|
//| large (100...). However, performance penalty will be too |
|
|
//| severe for any N's except for small ones. |
|
|
//| We should also say that code which relies on numerical |
|
|
//| differentiation is less robust and precise. L-BFGS needs |
|
|
//| exact gradient values. Imprecise gradient may slow down |
|
|
//| convergence, especially on highly nonlinear problems. |
|
|
//| Thus we recommend to use this function for fast prototyping |
|
|
//| on small- dimensional problems only, and to implement |
|
|
//| analytical gradient as soon as possible. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinCGCreateF(const int n,double &x[],double diffstep,
|
|
CMinCGStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinCG::MinCGCreateF(n,x,diffstep,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| The subroutine is finite difference variant of MinCGCreate(). |
|
|
//| It uses finite differences in order to differentiate target |
|
|
//| function. |
|
|
//| Description below contains information which is specific to this |
|
|
//| function only. We recommend to read comments on MinCGCreate() in |
|
|
//| order to get more information about creation of CG optimizer. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - problem dimension, N>0: |
|
|
//| * if given, only leading N elements of X are |
|
|
//| used |
|
|
//| * if not given, automatically determined from |
|
|
//| size of X |
|
|
//| X - starting point, array[0..N-1]. |
|
|
//| DiffStep- differentiation step, >0 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NOTES: |
|
|
//| 1. algorithm uses 4-point central formula for differentiation. |
|
|
//| 2. differentiation step along I-th axis is equal to |
|
|
//| DiffStep*S[I] where S[] is scaling vector which can be set by |
|
|
//| MinCGSetScale() call. |
|
|
//| 3. we recommend you to use moderate values of differentiation |
|
|
//| step. Too large step will result in too large truncation |
|
|
//| errors, while too small step will result in too large |
|
|
//| numerical errors. 1.0E-6 can be good value to start with. |
|
|
//| 4. Numerical differentiation is very inefficient - one gradient |
|
|
//| calculation needs 4*N function evaluations. This function will|
|
|
//| work for any N - either small (1...10), moderate (10...100) or|
|
|
//| large (100...). However, performance penalty will be too |
|
|
//| severe for any N's except for small ones. |
|
|
//| We should also say that code which relies on numerical |
|
|
//| differentiation is less robust and precise. L-BFGS needs |
|
|
//| exact gradient values. Imprecise gradient may slow down |
|
|
//| convergence, especially on highly nonlinear problems. |
|
|
//| Thus we recommend to use this function for fast prototyping |
|
|
//| on small- dimensional problems only, and to implement |
|
|
//| analytical gradient as soon as possible. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinCGCreateF(double &x[],double diffstep,
|
|
CMinCGStateShell &state)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CMinCG::MinCGCreateF(n,x,diffstep,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets stopping conditions for CG optimization |
|
|
//| algorithm. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| EpsG - >=0 |
|
|
//| The subroutine finishes its work if the condition|
|
|
//| |v|<EpsG is satisfied, where: |
|
|
//| * |.| means Euclidian norm |
|
|
//| * v - scaled gradient vector, v[i]=g[i]*s[i] |
|
|
//| * g - gradient |
|
|
//| * s - scaling coefficients set by MinCGSetScale()|
|
|
//| EpsF - >=0 |
|
|
//| The subroutine finishes its work if on k+1-th |
|
|
//| iteration the condition |F(k+1)-F(k)| <= |
|
|
//| <= EpsF*max{|F(k)|,|F(k+1)|,1} is satisfied. |
|
|
//| EpsX - >=0 |
|
|
//| The subroutine finishes its work if on k+1-th |
|
|
//| iteration the condition |v|<=EpsX is fulfilled, |
|
|
//| where: |
|
|
//| * |.| means Euclidian norm |
|
|
//| * v - scaled step vector, v[i]=dx[i]/s[i] |
|
|
//| * dx - ste pvector, dx=X(k+1)-X(k) |
|
|
//| * s - scaling coefficients set by MinCGSetScale()|
|
|
//| MaxIts - maximum number of iterations. If MaxIts=0, the |
|
|
//| number of iterations is unlimited. |
|
|
//| Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will|
|
|
//| lead to automatic stopping criterion selection (small EpsX). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinCGSetCond(CMinCGStateShell &state,double epsg,
|
|
double epsf,double epsx,int maxits)
|
|
{
|
|
//--- function call
|
|
CMinCG::MinCGSetCond(state.GetInnerObj(),epsg,epsf,epsx,maxits);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets scaling coefficients for CG optimizer. |
|
|
//| ALGLIB optimizers use scaling matrices to test stopping |
|
|
//| conditions (step size and gradient are scaled before comparison |
|
|
//| with tolerances). Scale of the I-th variable is a translation |
|
|
//| invariant measure of: |
|
|
//| a) "how large" the variable is |
|
|
//| b) how large the step should be to make significant changes in |
|
|
//| the function |
|
|
//| Scaling is also used by finite difference variant of CG |
|
|
//| optimizer - step along I-th axis is equal to DiffStep*S[I]. |
|
|
//| In most optimizers (and in the CG too) scaling is NOT a form of |
|
|
//| preconditioning. It just affects stopping conditions. You should |
|
|
//| set preconditioner by separate call to one of the |
|
|
//| MinCGSetPrec...() functions. |
|
|
//| There is special preconditioning mode, however, which uses |
|
|
//| scaling coefficients to form diagonal preconditioning matrix. |
|
|
//| You can turn this mode on, if you want. But you should understand|
|
|
//| that scaling is not the same thing as preconditioning - these are|
|
|
//| two different, although related forms of tuning solver. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure stores algorithm state |
|
|
//| S - array[N], non-zero scaling coefficients |
|
|
//| S[i] may be negative, sign doesn't matter. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinCGSetScale(CMinCGStateShell &state,double &s[])
|
|
{
|
|
//--- function call
|
|
CMinCG::MinCGSetScale(state.GetInnerObj(),s);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function turns on/off reporting. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NeedXRep- whether iteration reports are needed or not |
|
|
//| If NeedXRep is True, algorithm will call rep() callback function |
|
|
//| if it is provided to MinCGOptimize(). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinCGSetXRep(CMinCGStateShell &state,bool needxrep)
|
|
{
|
|
//--- function call
|
|
CMinCG::MinCGSetXRep(state.GetInnerObj(),needxrep);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets CG algorithm. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| CGType - algorithm type: |
|
|
//| * -1 automatic selection of the best |
|
|
//| algorithm |
|
|
//| * 0 DY (Dai and Yuan) algorithm |
|
|
//| * 1 Hybrid DY-HS algorithm |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinCGSetCGType(CMinCGStateShell &state,int cgtype)
|
|
{
|
|
//--- function call
|
|
CMinCG::MinCGSetCGType(state.GetInnerObj(),cgtype);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets maximum step length |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| StpMax - maximum step length, >=0. Set StpMax to 0.0, if |
|
|
//| you don't want to limit step length. |
|
|
//| Use this subroutine when you optimize target function which |
|
|
//| contains exp() or other fast growing functions, and optimization |
|
|
//| algorithm makes too large steps which leads to overflow. This |
|
|
//| function allows us to reject steps that are too large (and |
|
|
//| therefore expose us to the possible overflow) without actually |
|
|
//| calculating function value at the x+stp*d. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinCGSetStpMax(CMinCGStateShell &state,double stpmax)
|
|
{
|
|
//--- function call
|
|
CMinCG::MinCGSetStpMax(state.GetInnerObj(),stpmax);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function allows to suggest initial step length to the CG |
|
|
//| algorithm. |
|
|
//| Suggested step length is used as starting point for the line |
|
|
//| search. It can be useful when you have badly scaled problem, i.e.|
|
|
//| when ||grad|| (which is used as initial estimate for the first |
|
|
//| step) is many orders of magnitude different from the desired |
|
|
//| step. |
|
|
//| Line search may fail on such problems without good estimate of |
|
|
//| initial step length. Imagine, for example, problem with |
|
|
//| ||grad||=10^50 and desired step equal to 0.1 Line search |
|
|
//| function will use 10^50 as initial step, then it will decrease |
|
|
//| step length by 2 (up to 20 attempts) and will get 10^44, which is|
|
|
//| still too large. |
|
|
//| This function allows us to tell than line search should be |
|
|
//| started from some moderate step length, like 1.0, so algorithm |
|
|
//| will be able to detect desired step length in a several searches.|
|
|
//| Default behavior (when no step is suggested) is to use |
|
|
//| preconditioner, if it is available, to generate initial estimate |
|
|
//| of step length. |
|
|
//| This function influences only first iteration of algorithm. It |
|
|
//| should be called between MinCGCreate/MinCGRestartFrom() call and |
|
|
//| MinCGOptimize call. Suggested step is ignored if you have |
|
|
//| preconditioner. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure used to store algorithm state. |
|
|
//| Stp - initial estimate of the step length. |
|
|
//| Can be zero (no estimate). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinCGSuggestStep(CMinCGStateShell &state,double stp)
|
|
{
|
|
//--- function call
|
|
CMinCG::MinCGSuggestStep(state.GetInnerObj(),stp);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Modification of the preconditioner: preconditioning is turned |
|
|
//| off. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NOTE: you can change preconditioner "on the fly", during |
|
|
//| algorithm iterations. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinCGSetPrecDefault(CMinCGStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinCG::MinCGSetPrecDefault(state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Modification of the preconditioner: diagonal of approximate |
|
|
//| Hessian is used. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| D - diagonal of the approximate Hessian, |
|
|
//| array[0..N-1], (if larger, only leading N |
|
|
//| elements are used). |
|
|
//| NOTE: you can change preconditioner "on the fly", during |
|
|
//| algorithm iterations. |
|
|
//| NOTE 2: D[i] should be positive. Exception will be thrown |
|
|
//| otherwise. |
|
|
//| NOTE 3: you should pass diagonal of approximate Hessian - NOT |
|
|
//| ITS INVERSE. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinCGSetPrecDiag(CMinCGStateShell &state,double &d[])
|
|
{
|
|
//--- function call
|
|
CMinCG::MinCGSetPrecDiag(state.GetInnerObj(),d);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Modification of the preconditioner: scale-based diagonal |
|
|
//| preconditioning. |
|
|
//| This preconditioning mode can be useful when you don't have |
|
|
//| approximate diagonal of Hessian, but you know that your variables|
|
|
//| are badly scaled (for example, one variable is in [1,10], and |
|
|
//| another in [1000,100000]), and most part of the ill-conditioning |
|
|
//| comes from different scales of vars. |
|
|
//| In this case simple scale-based preconditioner, |
|
|
//| with H[i] = 1/(s[i]^2), can greatly improve convergence. |
|
|
//| IMPRTANT: you should set scale of your variables with |
|
|
//| MinCGSetScale() call (before or after MinCGSetPrecScale() call). |
|
|
//| Without knowledge of the scale of your variables scale-based |
|
|
//| preconditioner will be just unit matrix. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NOTE: you can change preconditioner "on the fly", during |
|
|
//| algorithm iterations. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinCGSetPrecScale(CMinCGStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinCG::MinCGSetPrecScale(state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function provides reverse communication interface |
|
|
//| Reverse communication interface is not documented or recommended |
|
|
//| to use. |
|
|
//| See below for functions which provide better documented API |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::MinCGIteration(CMinCGStateShell &state)
|
|
{
|
|
//--- return result
|
|
return(CMinCG::MinCGIteration(state.GetInnerObj()));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This family of functions is used to launcn iterations of |
|
|
//| nonlinear optimizer |
|
|
//| These functions accept following parameters: |
|
|
//| func - callback which calculates function (or merit |
|
|
//| function) value func at given point x |
|
|
//| grad - callback which calculates function (or merit |
|
|
//| function) value func and gradient grad at given |
|
|
//| point x |
|
|
//| rep - optional callback which is called after each |
|
|
//| iteration can be null |
|
|
//| obj - optional object which is passed to |
|
|
//| func/grad/hess/jac/rep can be null |
|
|
//| NOTES: |
|
|
//| 1. This function has two different implementations: one which |
|
|
//| uses exact (analytical) user-supplied gradient, and one which|
|
|
//| uses function value only and numerically differentiates |
|
|
//| function in order to obtain gradient. |
|
|
//| Depending on the specific function used to create optimizer |
|
|
//| object (either MinCGCreate() for analytical gradient or |
|
|
//| MinCGCreateF() for numerical differentiation) you should |
|
|
//| choose appropriate variant of MinCGOptimize() - one which |
|
|
//| accepts function AND gradient or one which accepts function |
|
|
//| ONLY. |
|
|
//| Be careful to choose variant of MinCGOptimize() which |
|
|
//| corresponds to your optimization scheme! Table below lists |
|
|
//| different combinations of callback (function/gradient) passed |
|
|
//| to MinCGOptimize() and specific function used to create |
|
|
//| optimizer. |
|
|
//| | USER PASSED TO MinCGOptimize() |
|
|
//| CREATED WITH | function only | function and gradient |
|
|
//| ------------------------------------------------------------ |
|
|
//| MinCGCreateF() | work FAIL |
|
|
//| MinCGCreate() | FAIL work |
|
|
//| Here "FAIL" denotes inappropriate combinations of optimizer |
|
|
//| creation function and MinCGOptimize() version. Attemps to use |
|
|
//| such combination (for example, to create optimizer with |
|
|
//| MinCGCreateF() and to pass gradient information to |
|
|
//| MinCGOptimize()) will lead to exception being thrown. Either |
|
|
//| you did not pass gradient when it WAS needed or you passed |
|
|
//| gradient when it was NOT needed. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinCGOptimize(CMinCGStateShell &state,CNDimensional_Func &func,
|
|
CNDimensional_Rep &rep,bool rep_status,CObject &obj)
|
|
{
|
|
//--- cycle
|
|
while(CAlglib::MinCGIteration(state))
|
|
{
|
|
//--- check
|
|
if(state.GetNeedF())
|
|
{
|
|
func.Func(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetInnerObj().m_xupdated)
|
|
{
|
|
//--- check
|
|
if(rep_status)
|
|
rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
Print("ALGLIB: error in 'mincgoptimize' (some derivatives were not provided?)");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This family of functions is used to launcn iterations of |
|
|
//| nonlinear optimizer |
|
|
//| These functions accept following parameters: |
|
|
//| func - callback which calculates function (or merit |
|
|
//| function) value func at given point x |
|
|
//| grad - callback which calculates function (or merit |
|
|
//| function) value func and gradient grad at given |
|
|
//| point x |
|
|
//| rep - optional callback which is called after each |
|
|
//| iteration can be null |
|
|
//| obj - optional object which is passed to |
|
|
//| func/grad/hess/jac/rep can be null |
|
|
//| NOTES: |
|
|
//| 1. This function has two different implementations: one which |
|
|
//| uses exact (analytical) user-supplied gradient, and one which|
|
|
//| uses function value only and numerically differentiates |
|
|
//| function in order to obtain gradient. |
|
|
//| Depending on the specific function used to create optimizer |
|
|
//| object (either MinCGCreate() for analytical gradient or |
|
|
//| MinCGCreateF() for numerical differentiation) you should |
|
|
//| choose appropriate variant of MinCGOptimize() - one which |
|
|
//| accepts function AND gradient or one which accepts function |
|
|
//| ONLY. |
|
|
//| Be careful to choose variant of MinCGOptimize() which |
|
|
//| corresponds to your optimization scheme! Table below lists |
|
|
//| different combinations of callback (function/gradient) passed |
|
|
//| to MinCGOptimize() and specific function used to create |
|
|
//| optimizer. |
|
|
//| | USER PASSED TO MinCGOptimize() |
|
|
//| CREATED WITH | function only | function and gradient |
|
|
//| ------------------------------------------------------------ |
|
|
//| MinCGCreateF() | work FAIL |
|
|
//| MinCGCreate() | FAIL work |
|
|
//| Here "FAIL" denotes inappropriate combinations of optimizer |
|
|
//| creation function and MinCGOptimize() version. Attemps to use |
|
|
//| such combination (for example, to create optimizer with |
|
|
//| MinCGCreateF() and to pass gradient information to |
|
|
//| MinCGOptimize()) will lead to exception being thrown. Either |
|
|
//| you did not pass gradient when it WAS needed or you passed |
|
|
//| gradient when it was NOT needed. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinCGOptimize(CMinCGStateShell &state,CNDimensional_Grad &grad,
|
|
CNDimensional_Rep &rep,bool rep_status,CObject &obj)
|
|
{
|
|
//--- cycle
|
|
while(CAlglib::MinCGIteration(state))
|
|
{
|
|
//--- check
|
|
if(state.GetNeedFG())
|
|
{
|
|
grad.Grad(state.GetInnerObj().m_x,state.GetInnerObj().m_f,state.GetInnerObj().m_g,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetInnerObj().m_xupdated)
|
|
{
|
|
//--- check
|
|
if(rep_status)
|
|
rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
Print("ALGLIB: error in 'mincgoptimize' (some derivatives were not provided?)");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Conjugate gradient results |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - algorithm state |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| X - array[0..N-1], solution |
|
|
//| Rep - optimization report: |
|
|
//| * Rep.TerminationType completetion code: |
|
|
//| * 1 relative function improvement is no |
|
|
//| more than EpsF. |
|
|
//| * 2 relative step is no more than EpsX. |
|
|
//| * 4 gradient norm is no more than EpsG |
|
|
//| * 5 MaxIts steps was taken |
|
|
//| * 7 stopping conditions are too |
|
|
//| stringent, further improvement is |
|
|
//| impossible, we return best X found |
|
|
//| so far |
|
|
//| * 8 terminated by user |
|
|
//| * Rep.IterationsCount contains iterations count |
|
|
//| * NFEV countains number of function calculations |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinCGResults(CMinCGStateShell &state,double &x[],
|
|
CMinCGReportShell &rep)
|
|
{
|
|
//--- function call
|
|
CMinCG::MinCGResults(state.GetInnerObj(),x,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Conjugate gradient results |
|
|
//| Buffered implementation of MinCGResults(), which uses |
|
|
//| pre-allocated buffer to store X[]. If buffer size is too small, |
|
|
//| it resizes buffer.It is intended to be used in the inner cycles |
|
|
//| of performance critical algorithms where array reallocation |
|
|
//| penalty is too large to be ignored. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinCGResultsBuf(CMinCGStateShell &state,double &x[],
|
|
CMinCGReportShell &rep)
|
|
{
|
|
//--- function call
|
|
CMinCG::MinCGResultsBuf(state.GetInnerObj(),x,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine restarts CG algorithm from new point. All |
|
|
//| optimization parameters are left unchanged. |
|
|
//| This function allows to solve multiple optimization problems |
|
|
//| (which must have same number of dimensions) without object |
|
|
//| reallocation penalty. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure used to store algorithm state. |
|
|
//| X - new starting point. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinCGRestartFrom(CMinCGStateShell &state,double &x[])
|
|
{
|
|
//--- function call
|
|
CMinCG::MinCGRestartFrom(state.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| BOUND CONSTRAINED OPTIMIZATION |
|
|
//| WITH ADDITIONAL LINEAR EQUALITY AND INEQUALITY CONSTRAINTS|
|
|
//| DESCRIPTION: |
|
|
//| The subroutine minimizes function F(x) of N arguments subject to |
|
|
//| any combination of: |
|
|
//| * bound constraints |
|
|
//| * linear inequality constraints |
|
|
//| * linear equality constraints |
|
|
//| REQUIREMENTS: |
|
|
//| * user must provide function value and gradient |
|
|
//| * starting point X0 must be feasible or |
|
|
//| not too far away from the feasible set |
|
|
//| * grad(f) must be Lipschitz continuous on a level set: |
|
|
//| L = { x : f(x)<=f(x0) } |
|
|
//| * function must be defined everywhere on the feasible set F |
|
|
//| USAGE: |
|
|
//| Constrained optimization if far more complex than the |
|
|
//| unconstrained one. Here we give very brief outline of the BLEIC |
|
|
//| optimizer. We strongly recommend you to read examples in the |
|
|
//| ALGLIB Reference Manual and to read ALGLIB User Guide on |
|
|
//| optimization, which is available at |
|
|
//| http://www.alglib.net/optimization/ |
|
|
//| 1. User initializes algorithm state with MinBLEICCreate() call |
|
|
//| 2. USer adds boundary and/or linear constraints by calling |
|
|
//| MinBLEICSetBC() and MinBLEICSetLC() functions. |
|
|
//| 3. User sets stopping conditions for underlying unconstrained |
|
|
//| solver with MinBLEICSetInnerCond() call. |
|
|
//| This function controls accuracy of underlying optimization |
|
|
//| algorithm. |
|
|
//| 4. User sets stopping conditions for outer iteration by calling |
|
|
//| MinBLEICSetOuterCond() function. |
|
|
//| This function controls handling of boundary and inequality |
|
|
//| constraints. |
|
|
//| 5. Additionally, user may set limit on number of internal |
|
|
//| iterations by MinBLEICSetMaxIts() call. |
|
|
//| This function allows to prevent algorithm from looping |
|
|
//| forever. |
|
|
//| 6. User calls MinBLEICOptimize() function which takes algorithm |
|
|
//| state and pointer (delegate, etc.) to callback function |
|
|
//| which calculates F/G. |
|
|
//| 7. User calls MinBLEICResults() to get solution |
|
|
//| 8. Optionally user may call MinBLEICRestartFrom() to solve |
|
|
//| another problem with same N but another starting point. |
|
|
//| MinBLEICRestartFrom() allows to reuse already initialized |
|
|
//| structure. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - problem dimension, N>0: |
|
|
//| * if given, only leading N elements of X are |
|
|
//| used |
|
|
//| * if not given, automatically determined from |
|
|
//| size ofX |
|
|
//| X - starting point, array[N]: |
|
|
//| * it is better to set X to a feasible point |
|
|
//| * but X can be infeasible, in which case |
|
|
//| algorithm will try to find feasible point |
|
|
//| first, using X as initial approximation. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure stores algorithm state |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICCreate(const int n,double &x[],CMinBLEICStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinBLEIC::MinBLEICCreate(n,x,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| BOUND CONSTRAINED OPTIMIZATION |
|
|
//| WITH ADDITIONAL LINEAR EQUALITY AND INEQUALITY CONSTRAINTS|
|
|
//| DESCRIPTION: |
|
|
//| The subroutine minimizes function F(x) of N arguments subject to |
|
|
//| any combination of: |
|
|
//| * bound constraints |
|
|
//| * linear inequality constraints |
|
|
//| * linear equality constraints |
|
|
//| REQUIREMENTS: |
|
|
//| * user must provide function value and gradient |
|
|
//| * starting point X0 must be feasible or |
|
|
//| not too far away from the feasible set |
|
|
//| * grad(f) must be Lipschitz continuous on a level set: |
|
|
//| L = { x : f(x)<=f(x0) } |
|
|
//| * function must be defined everywhere on the feasible set F |
|
|
//| USAGE: |
|
|
//| Constrained optimization if far more complex than the |
|
|
//| unconstrained one. Here we give very brief outline of the BLEIC |
|
|
//| optimizer. We strongly recommend you to read examples in the |
|
|
//| ALGLIB Reference Manual and to read ALGLIB User Guide on |
|
|
//| optimization, which is available at |
|
|
//| http://www.alglib.net/optimization/ |
|
|
//| 1. User initializes algorithm state with MinBLEICCreate() call |
|
|
//| 2. USer adds boundary and/or linear constraints by calling |
|
|
//| MinBLEICSetBC() and MinBLEICSetLC() functions. |
|
|
//| 3. User sets stopping conditions for underlying unconstrained |
|
|
//| solver with MinBLEICSetInnerCond() call. |
|
|
//| This function controls accuracy of underlying optimization |
|
|
//| algorithm. |
|
|
//| 4. User sets stopping conditions for outer iteration by calling |
|
|
//| MinBLEICSetOuterCond() function. |
|
|
//| This function controls handling of boundary and inequality |
|
|
//| constraints. |
|
|
//| 5. Additionally, user may set limit on number of internal |
|
|
//| iterations by MinBLEICSetMaxIts() call. |
|
|
//| This function allows to prevent algorithm from looping |
|
|
//| forever. |
|
|
//| 6. User calls MinBLEICOptimize() function which takes algorithm |
|
|
//| state and pointer (delegate, etc.) to callback function |
|
|
//| which calculates F/G. |
|
|
//| 7. User calls MinBLEICResults() to get solution |
|
|
//| 8. Optionally user may call MinBLEICRestartFrom() to solve |
|
|
//| another problem with same N but another starting point. |
|
|
//| MinBLEICRestartFrom() allows to reuse already initialized |
|
|
//| structure. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - problem dimension, N>0: |
|
|
//| * if given, only leading N elements of X are |
|
|
//| used |
|
|
//| * if not given, automatically determined from |
|
|
//| size ofX |
|
|
//| X - starting point, array[N]: |
|
|
//| * it is better to set X to a feasible point |
|
|
//| * but X can be infeasible, in which case |
|
|
//| algorithm will try to find feasible point |
|
|
//| first, using X as initial approximation. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure stores algorithm state |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICCreate(double &x[],CMinBLEICStateShell &state)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CMinBLEIC::MinBLEICCreate(n,x,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| The subroutine is finite difference variant of MinBLEICCreate(). |
|
|
//| It uses finite differences in order to differentiate target |
|
|
//| function. |
|
|
//| Description below contains information which is specific to this |
|
|
//| function only. We recommend to read comments on MinBLEICCreate() |
|
|
//| in order to get more information about creation of BLEIC |
|
|
//| optimizer. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - problem dimension, N>0: |
|
|
//| * if given, only leading N elements of X are used|
|
|
//| * if not given, automatically determined from |
|
|
//| size of X |
|
|
//| X - starting point, array[0..N-1]. |
|
|
//| DiffStep- differentiation step, >0 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NOTES: |
|
|
//| 1. algorithm uses 4-point central formula for differentiation. |
|
|
//| 2. differentiation step along I-th axis is equal to DiffStep*S[I]|
|
|
//| where S[] is scaling vector which can be set by |
|
|
//| MinBLEICSetScale() call. |
|
|
//| 3. we recommend you to use moderate values of differentiation |
|
|
//| step. Too large step will result in too large truncation |
|
|
//| errors, while too small step will result in too large |
|
|
//| numerical errors. 1.0E-6 can be good value to start with. |
|
|
//| 4. Numerical differentiation is very inefficient - one gradient |
|
|
//| calculation needs 4*N function evaluations. This function will|
|
|
//| work for any N - either small (1...10), moderate (10...100) or|
|
|
//| large (100...). However, performance penalty will be too |
|
|
//| severe for any N's except for small ones. |
|
|
//| We should also say that code which relies on numerical |
|
|
//| differentiation is less robust and precise. CG needs exact |
|
|
//| gradient values. Imprecise gradient may slow down convergence,|
|
|
//| especially on highly nonlinear problems. |
|
|
//| Thus we recommend to use this function for fast prototyping on|
|
|
//| small - dimensional problems only, and to implement analytical|
|
|
//| gradient as soon as possible. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICCreateF(const int n,double &x[],double diffstep,
|
|
CMinBLEICStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinBLEIC::MinBLEICCreateF(n,x,diffstep,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| The subroutine is finite difference variant of MinBLEICCreate(). |
|
|
//| It uses finite differences in order to differentiate target |
|
|
//| function. |
|
|
//| Description below contains information which is specific to this |
|
|
//| function only. We recommend to read comments on MinBLEICCreate() |
|
|
//| in order to get more information about creation of BLEIC |
|
|
//| optimizer. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - problem dimension, N>0: |
|
|
//| * if given, only leading N elements of X are used|
|
|
//| * if not given, automatically determined from |
|
|
//| size of X |
|
|
//| X - starting point, array[0..N-1]. |
|
|
//| DiffStep- differentiation step, >0 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NOTES: |
|
|
//| 1. algorithm uses 4-point central formula for differentiation. |
|
|
//| 2. differentiation step along I-th axis is equal to DiffStep*S[I]|
|
|
//| where S[] is scaling vector which can be set by |
|
|
//| MinBLEICSetScale() call. |
|
|
//| 3. we recommend you to use moderate values of differentiation |
|
|
//| step. Too large step will result in too large truncation |
|
|
//| errors, while too small step will result in too large |
|
|
//| numerical errors. 1.0E-6 can be good value to start with. |
|
|
//| 4. Numerical differentiation is very inefficient - one gradient |
|
|
//| calculation needs 4*N function evaluations. This function will|
|
|
//| work for any N - either small (1...10), moderate (10...100) or|
|
|
//| large (100...). However, performance penalty will be too |
|
|
//| severe for any N's except for small ones. |
|
|
//| We should also say that code which relies on numerical |
|
|
//| differentiation is less robust and precise. CG needs exact |
|
|
//| gradient values. Imprecise gradient may slow down convergence,|
|
|
//| especially on highly nonlinear problems. |
|
|
//| Thus we recommend to use this function for fast prototyping on|
|
|
//| small - dimensional problems only, and to implement analytical|
|
|
//| gradient as soon as possible. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICCreateF(double &x[],double diffstep,
|
|
CMinBLEICStateShell &state)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CMinBLEIC::MinBLEICCreateF(n,x,diffstep,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets boundary constraints for BLEIC optimizer. |
|
|
//| Boundary constraints are inactive by default (after initial |
|
|
//| creation). They are preserved after algorithm restart with |
|
|
//| MinBLEICRestartFrom(). |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure stores algorithm state |
|
|
//| BndL - lower bounds, array[N]. |
|
|
//| If some (all) variables are unbounded, you may |
|
|
//| specify very small number or -INF. |
|
|
//| BndU - upper bounds, array[N]. |
|
|
//| If some (all) variables are unbounded, you may |
|
|
//| specify very large number or +INF. |
|
|
//| NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case |
|
|
//| I-th variable will be "frozen" at X[i]=BndL[i]=BndU[i]. |
|
|
//| NOTE 2: this solver has following useful properties: |
|
|
//| * bound constraints are always satisfied exactly |
|
|
//| * function is evaluated only INSIDE area specified by bound |
|
|
//| constraints, even when numerical differentiation is used |
|
|
//| (algorithm adjusts nodes according to boundary constraints) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICSetBC(CMinBLEICStateShell &state,double &bndl[],
|
|
double &bndu[])
|
|
{
|
|
//--- function call
|
|
CMinBLEIC::MinBLEICSetBC(state.GetInnerObj(),bndl,bndu);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets linear constraints for BLEIC optimizer. |
|
|
//| Linear constraints are inactive by default (after initial |
|
|
//| creation). They are preserved after algorithm restart with |
|
|
//| MinBLEICRestartFrom(). |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure previously allocated with |
|
|
//| MinBLEICCreate call. |
|
|
//| C - linear constraints, array[K,N+1]. |
|
|
//| Each row of C represents one constraint, either |
|
|
//| equality or inequality (see below): |
|
|
//| * first N elements correspond to coefficients, |
|
|
//| * last element corresponds to the right part. |
|
|
//| All elements of C (including right part) must be |
|
|
//| finite. |
|
|
//| CT - type of constraints, array[K]: |
|
|
//| * if CT[i]>0, then I-th constraint is |
|
|
//| C[i,*]*x >= C[i,n+1] |
|
|
//| * if CT[i]=0, then I-th constraint is |
|
|
//| C[i,*]*x = C[i,n+1] |
|
|
//| * if CT[i]<0, then I-th constraint is |
|
|
//| C[i,*]*x <= C[i,n+1] |
|
|
//| K - number of equality/inequality constraints, K>=0: |
|
|
//| * if given, only leading K elements of C/CT are |
|
|
//| used |
|
|
//| * if not given, automatically determined from |
|
|
//| sizes of C/CT |
|
|
//| NOTE 1: linear (non-bound) constraints are satisfied only |
|
|
//| approximately: |
|
|
//| * there always exists some minor violation (about Epsilon in |
|
|
//| magnitude) due to rounding errors |
|
|
//| * numerical differentiation, if used, may lead to function |
|
|
//| evaluations outside of the feasible area, because algorithm |
|
|
//| does NOT change numerical differentiation formula according to |
|
|
//| linear constraints. |
|
|
//| If you want constraints to be satisfied exactly, try to |
|
|
//| reformulate your problem in such manner that all constraints will|
|
|
//| become boundary ones (this kind of constraints is always |
|
|
//| satisfied exactly, both in the final solution and in all |
|
|
//| intermediate points). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICSetLC(CMinBLEICStateShell &state,CMatrixDouble &c,
|
|
int &ct[],const int k)
|
|
{
|
|
//--- function call
|
|
CMinBLEIC::MinBLEICSetLC(state.GetInnerObj(),c,ct,k);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets linear constraints for BLEIC optimizer. |
|
|
//| Linear constraints are inactive by default (after initial |
|
|
//| creation). They are preserved after algorithm restart with |
|
|
//| MinBLEICRestartFrom(). |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure previously allocated with |
|
|
//| MinBLEICCreate call. |
|
|
//| C - linear constraints, array[K,N+1]. |
|
|
//| Each row of C represents one constraint, either |
|
|
//| equality or inequality (see below): |
|
|
//| * first N elements correspond to coefficients, |
|
|
//| * last element corresponds to the right part. |
|
|
//| All elements of C (including right part) must be |
|
|
//| finite. |
|
|
//| CT - type of constraints, array[K]: |
|
|
//| * if CT[i]>0, then I-th constraint is |
|
|
//| C[i,*]*x >= C[i,n+1] |
|
|
//| * if CT[i]=0, then I-th constraint is |
|
|
//| C[i,*]*x = C[i,n+1] |
|
|
//| * if CT[i]<0, then I-th constraint is |
|
|
//| C[i,*]*x <= C[i,n+1] |
|
|
//| K - number of equality/inequality constraints, K>=0: |
|
|
//| * if given, only leading K elements of C/CT are |
|
|
//| used |
|
|
//| * if not given, automatically determined from |
|
|
//| sizes of C/CT |
|
|
//| NOTE 1: linear (non-bound) constraints are satisfied only |
|
|
//| approximately: |
|
|
//| * there always exists some minor violation (about Epsilon in |
|
|
//| magnitude) due to rounding errors |
|
|
//| * numerical differentiation, if used, may lead to function |
|
|
//| evaluations outside of the feasible area, because algorithm |
|
|
//| does NOT change numerical differentiation formula according to |
|
|
//| linear constraints. |
|
|
//| If you want constraints to be satisfied exactly, try to |
|
|
//| reformulate your problem in such manner that all constraints will|
|
|
//| become boundary ones (this kind of constraints is always |
|
|
//| satisfied exactly, both in the final solution and in all |
|
|
//| intermediate points). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICSetLC(CMinBLEICStateShell &state,CMatrixDouble &c,
|
|
int &ct[])
|
|
{
|
|
//--- create a variable
|
|
int k;
|
|
//--- check
|
|
if(CAp::Rows(c)!=CAp::Len(ct))
|
|
{
|
|
Print(__FUNCTION__+": looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
k=CAp::Rows(c);
|
|
//--- function call
|
|
CMinBLEIC::MinBLEICSetLC(state.GetInnerObj(),c,ct,k);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets stopping conditions for the underlying |
|
|
//| nonlinear CG optimizer. It controls overall accuracy of solution.|
|
|
//| These conditions should be strict enough in order for algorithm |
|
|
//| to converge. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| EpsG - >=0 |
|
|
//| The subroutine finishes its work if the condition|
|
|
//| |v|<EpsG is satisfied, where: |
|
|
//| * |.| means Euclidian norm |
|
|
//| * v - scaled gradient vector, v[i]=g[i]*s[i] |
|
|
//| * g - gradient |
|
|
//| * s - scaling coefficients set by |
|
|
//| MinBLEICSetScale() |
|
|
//| EpsF - >=0 |
|
|
//| The subroutine finishes its work if on k+1-th |
|
|
//| iteration the condition |F(k+1)-F(k)| <= |
|
|
//| <= EpsF*max{|F(k)|,|F(k+1)|,1} is satisfied. |
|
|
//| EpsX - >=0 |
|
|
//| The subroutine finishes its work if on k+1-th |
|
|
//| iteration the condition |v|<=EpsX is fulfilled, |
|
|
//| where: |
|
|
//| * |.| means Euclidian norm |
|
|
//| * v - scaled step vector, v[i]=dx[i]/s[i] |
|
|
//| * dx - ste pvector, dx=X(k+1)-X(k) |
|
|
//| * s - scaling coefficients set by |
|
|
//| MinBLEICSetScale() |
|
|
//| Passing EpsG=0, EpsF=0 and EpsX=0 (simultaneously) will lead to |
|
|
//| automatic stopping criterion selection. |
|
|
//| These conditions are used to terminate inner iterations. However,|
|
|
//| you need to tune termination conditions for outer iterations too.|
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICSetInnerCond(CMinBLEICStateShell &state,
|
|
const double epsg,
|
|
const double epsf,
|
|
const double epsx)
|
|
{
|
|
//--- function call
|
|
CMinBLEIC::MinBLEICSetInnerCond(state.GetInnerObj(),epsg,epsf,epsx);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets stopping conditions for outer iteration of |
|
|
//| BLEIC algo. |
|
|
//| These conditions control accuracy of constraint handling and |
|
|
//| amount of infeasibility allowed in the solution. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| EpsX - >0, stopping condition on outer iteration step |
|
|
//| length |
|
|
//| EpsI - >0, stopping condition on infeasibility |
|
|
//| Both EpsX and EpsI must be non-zero. |
|
|
//| MEANING OF EpsX |
|
|
//| EpsX is a stopping condition for outer iterations. Algorithm will|
|
|
//| stop when solution of the current modified subproblem will be |
|
|
//| within EpsX (using 2-norm) of the previous solution. |
|
|
//| MEANING OF EpsI |
|
|
//| EpsI controls feasibility properties - algorithm won't stop until|
|
|
//| all inequality constraints will be satisfied with error (distance|
|
|
//| from current point to the feasible area) at most EpsI. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICSetOuterCond(CMinBLEICStateShell &state,
|
|
const double epsx,const double epsi)
|
|
{
|
|
//--- function call
|
|
CMinBLEIC::MinBLEICSetOuterCond(state.GetInnerObj(),epsx,epsi);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets scaling coefficients for BLEIC optimizer. |
|
|
//| ALGLIB optimizers use scaling matrices to test stopping |
|
|
//| conditions (step size and gradient are scaled before comparison |
|
|
//| with tolerances). Scale of the I-th variable is a translation |
|
|
//| invariant measure of: |
|
|
//| a) "how large" the variable is |
|
|
//| b) how large the step should be to make significant changes in |
|
|
//| the function |
|
|
//| Scaling is also used by finite difference variant of the |
|
|
//| optimizer - step along I-th axis is equal to DiffStep*S[I]. |
|
|
//| In most optimizers (and in the BLEIC too) scaling is NOT a form |
|
|
//| of preconditioning. It just affects stopping conditions. You |
|
|
//| should set preconditioner by separate call to one of the |
|
|
//| MinBLEICSetPrec...() functions. |
|
|
//| There is a special preconditioning mode, however, which uses |
|
|
//| scaling coefficients to form diagonal preconditioning matrix. |
|
|
//| You can turn this mode on, if you want. But you should understand|
|
|
//| that scaling is not the same thing as preconditioning - these are|
|
|
//| two different, although related forms of tuning solver. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure stores algorithm state |
|
|
//| S - array[N], non-zero scaling coefficients |
|
|
//| S[i] may be negative, sign doesn't matter. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICSetScale(CMinBLEICStateShell &state,double &s[])
|
|
{
|
|
//--- function call
|
|
CMinBLEIC::MinBLEICSetScale(state.GetInnerObj(),s);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Modification of the preconditioner: preconditioning is turned |
|
|
//| off. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICSetPrecDefault(CMinBLEICStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinBLEIC::MinBLEICSetPrecDefault(state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Modification of the preconditioner: diagonal of approximate |
|
|
//| Hessian is used. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| D - diagonal of the approximate Hessian, |
|
|
//| array[0..N-1], (if larger, only leading N |
|
|
//| elements are used). |
|
|
//| NOTE 1: D[i] should be positive. Exception will be thrown |
|
|
//| otherwise. |
|
|
//| NOTE 2: you should pass diagonal of approximate Hessian - NOT |
|
|
//| ITS INVERSE. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICSetPrecDiag(CMinBLEICStateShell &state,
|
|
double &d[])
|
|
{
|
|
//--- function call
|
|
CMinBLEIC::MinBLEICSetPrecDiag(state.GetInnerObj(),d);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Modification of the preconditioner: scale-based diagonal |
|
|
//| preconditioning. |
|
|
//| This preconditioning mode can be useful when you don't have |
|
|
//| approximate diagonal of Hessian, but you know that your variables|
|
|
//| are badly scaled (for example, one variable is in [1,10], and |
|
|
//| another in [1000,100000]), and most part of the ill-conditioning |
|
|
//| comes from different scales of vars. |
|
|
//| In this case simple scale-based preconditioner, with H[i] = |
|
|
//| = 1/(s[i]^2), can greatly improve convergence. |
|
|
//| IMPRTANT: you should set scale of your variables with |
|
|
//| MinBLEICSetScale() call (before or after MinBLEICSetPrecScale() |
|
|
//| call). Without knowledge of the scale of your variables |
|
|
//| scale-based preconditioner will be just unit matrix. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICSetPrecScale(CMinBLEICStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinBLEIC::MinBLEICSetPrecScale(state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function allows to stop algorithm after specified number of |
|
|
//| inner iterations. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| MaxIts - maximum number of inner iterations. |
|
|
//| If MaxIts=0, the number of iterations is |
|
|
//| unlimited. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICSetMaxIts(CMinBLEICStateShell &state,
|
|
const int maxits)
|
|
{
|
|
//--- function call
|
|
CMinBLEIC::MinBLEICSetMaxIts(state.GetInnerObj(),maxits);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function turns on/off reporting. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NeedXRep- whether iteration reports are needed or not |
|
|
//| If NeedXRep is True, algorithm will call rep() callback function |
|
|
//| if it is provided to MinBLEICOptimize(). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICSetXRep(CMinBLEICStateShell &state,bool needxrep)
|
|
{
|
|
//--- function call
|
|
CMinBLEIC::MinBLEICSetXRep(state.GetInnerObj(),needxrep);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets maximum step length |
|
|
//| IMPORTANT: this feature is hard to combine with preconditioning. |
|
|
//| You can't set upper limit on step length, when you solve |
|
|
//| optimization problem with linear (non-boundary) constraints AND |
|
|
//| preconditioner turned on. |
|
|
//| When non-boundary constraints are present, you have to either a) |
|
|
//| use preconditioner, or b) use upper limit on step length. YOU |
|
|
//| CAN'T USE BOTH! In this case algorithm will terminate with |
|
|
//| appropriate error code. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| StpMax - maximum step length, >=0. Set StpMax to 0.0, if |
|
|
//| you don't want to limit step length. |
|
|
//| Use this subroutine when you optimize target function which |
|
|
//| contains exp() or other fast growing functions, and optimization |
|
|
//| algorithm makes too large steps which lead to overflow. This |
|
|
//| function allows us to reject steps that are too large (and |
|
|
//| therefore expose us to the possible overflow) without actually |
|
|
//| calculating function value at the x+stp*d. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICSetStpMax(CMinBLEICStateShell &state,double stpmax)
|
|
{
|
|
//--- function call
|
|
CMinBLEIC::MinBLEICSetStpMax(state.GetInnerObj(),stpmax);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function provides reverse communication interface |
|
|
//| Reverse communication interface is not documented or recommended |
|
|
//| to use. |
|
|
//| See below for functions which provide better documented API |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::MinBLEICIteration(CMinBLEICStateShell &state)
|
|
{
|
|
//--- return result
|
|
return(CMinBLEIC::MinBLEICIteration(state.GetInnerObj()));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This family of functions is used to launcn iterations of |
|
|
//| nonlinear optimizer |
|
|
//| These functions accept following parameters: |
|
|
//| func - callback which calculates function (or merit |
|
|
//| function) value func at given point x |
|
|
//| grad - callback which calculates function (or merit |
|
|
//| function) value func and gradient grad at given |
|
|
//| point x |
|
|
//| rep - optional callback which is called after each |
|
|
//| iteration can be null |
|
|
//| obj - optional object which is passed to |
|
|
//| func/grad/hess/jac/rep can be null |
|
|
//| NOTES: |
|
|
//| 1. This function has two different implementations: one which |
|
|
//| uses exact (analytical) user-supplied gradient, and one which |
|
|
//| uses function value only and numerically differentiates |
|
|
//| function in order to obtain gradient. |
|
|
//| Depending on the specific function used to create optimizer |
|
|
//| object (either MinBLEICCreate() for analytical gradient or |
|
|
//| MinBLEICCreateF() for numerical differentiation) you should |
|
|
//| choose appropriate variant of MinBLEICOptimize() - one which |
|
|
//| accepts function AND gradient or one which accepts function |
|
|
//| ONLY. |
|
|
//| Be careful to choose variant of MinBLEICOptimize() which |
|
|
//| corresponds to your optimization scheme! Table below lists |
|
|
//| different combinations of callback (function/gradient) passed |
|
|
//| to MinBLEICOptimize() and specific function used to create |
|
|
//| optimizer. |
|
|
//| | USER PASSED TO MinBLEICOptimize() |
|
|
//| CREATED WITH | function only | function and gradient |
|
|
//| ------------------------------------------------------------ |
|
|
//| MinBLEICCreateF() | work FAIL |
|
|
//| MinBLEICCreate() | FAIL work |
|
|
//| Here "FAIL" denotes inappropriate combinations of optimizer |
|
|
//| creation function and MinBLEICOptimize() version. Attemps to |
|
|
//| use such combination (for example, to create optimizer with |
|
|
//| MinBLEICCreateF() and to pass gradient information to |
|
|
//| MinCGOptimize()) will lead to exception being thrown. Either |
|
|
//| you did not pass gradient when it WAS needed or you passed |
|
|
//| gradient when it was NOT needed. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICOptimize(CMinBLEICStateShell &state,CNDimensional_Func &func,
|
|
CNDimensional_Rep &rep,bool rep_status,CObject &obj)
|
|
{
|
|
//--- cycle
|
|
while(CAlglib::MinBLEICIteration(state))
|
|
{
|
|
//--- check
|
|
if(state.GetNeedF())
|
|
{
|
|
func.Func(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetInnerObj().m_xupdated)
|
|
{
|
|
//--- check
|
|
if(rep_status)
|
|
rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
Print("ALGLIB: error in 'minbleicoptimize' (some derivatives were not provided?)");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This family of functions is used to launcn iterations of |
|
|
//| nonlinear optimizer |
|
|
//| These functions accept following parameters: |
|
|
//| func - callback which calculates function (or merit |
|
|
//| function) value func at given point x |
|
|
//| grad - callback which calculates function (or merit |
|
|
//| function) value func and gradient grad at given |
|
|
//| point x |
|
|
//| rep - optional callback which is called after each |
|
|
//| iteration can be null |
|
|
//| obj - optional object which is passed to |
|
|
//| func/grad/hess/jac/rep can be null |
|
|
//| NOTES: |
|
|
//| 1. This function has two different implementations: one which |
|
|
//| uses exact (analytical) user-supplied gradient, and one which |
|
|
//| uses function value only and numerically differentiates |
|
|
//| function in order to obtain gradient. |
|
|
//| Depending on the specific function used to create optimizer |
|
|
//| object (either MinBLEICCreate() for analytical gradient or |
|
|
//| MinBLEICCreateF() for numerical differentiation) you should |
|
|
//| choose appropriate variant of MinBLEICOptimize() - one which |
|
|
//| accepts function AND gradient or one which accepts function |
|
|
//| ONLY. |
|
|
//| Be careful to choose variant of MinBLEICOptimize() which |
|
|
//| corresponds to your optimization scheme! Table below lists |
|
|
//| different combinations of callback (function/gradient) passed |
|
|
//| to MinBLEICOptimize() and specific function used to create |
|
|
//| optimizer. |
|
|
//| | USER PASSED TO MinBLEICOptimize() |
|
|
//| CREATED WITH | function only | function and gradient |
|
|
//| ------------------------------------------------------------ |
|
|
//| MinBLEICCreateF() | work FAIL |
|
|
//| MinBLEICCreate() | FAIL work |
|
|
//| Here "FAIL" denotes inappropriate combinations of optimizer |
|
|
//| creation function and MinBLEICOptimize() version. Attemps to |
|
|
//| use such combination (for example, to create optimizer with |
|
|
//| MinBLEICCreateF() and to pass gradient information to |
|
|
//| MinCGOptimize()) will lead to exception being thrown. Either |
|
|
//| you did not pass gradient when it WAS needed or you passed |
|
|
//| gradient when it was NOT needed. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICOptimize(CMinBLEICStateShell &state,CNDimensional_Grad &grad,
|
|
CNDimensional_Rep &rep,bool rep_status,CObject &obj)
|
|
{
|
|
//--- cycle
|
|
while(CAlglib::MinBLEICIteration(state))
|
|
{
|
|
//--- check
|
|
if(state.GetNeedFG())
|
|
{
|
|
grad.Grad(state.GetInnerObj().m_x,state.GetInnerObj().m_f,state.GetInnerObj().m_g,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetInnerObj().m_xupdated)
|
|
{
|
|
//--- check
|
|
if(rep_status)
|
|
rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
Print("ALGLIB: error in 'minbleicoptimize' (some derivatives were not provided?)");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| BLEIC results |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - algorithm state |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| X - array[0..N-1], solution |
|
|
//| Rep - optimization report. You should check Rep. |
|
|
//| TerminationType in order to distinguish |
|
|
//| successful termination from unsuccessful one. |
|
|
//| More information about fields of this structure |
|
|
//| can be found in the comments on MinBLEICReport |
|
|
//| datatype. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICResults(CMinBLEICStateShell &state,double &x[],
|
|
CMinBLEICReportShell &rep)
|
|
{
|
|
//--- function call
|
|
CMinBLEIC::MinBLEICResults(state.GetInnerObj(),x,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| BLEIC results |
|
|
//| Buffered implementation of MinBLEICResults() which uses |
|
|
//| pre-allocated buffer to store X[]. If buffer size is too small, |
|
|
//| it resizes buffer. It is intended to be used in the inner cycles |
|
|
//| of performance critical algorithms where array reallocation |
|
|
//| penalty is too large to be ignored. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICResultsBuf(CMinBLEICStateShell &state,double &x[],
|
|
CMinBLEICReportShell &rep)
|
|
{
|
|
//--- function call
|
|
CMinBLEIC::MinBLEICResultsBuf(state.GetInnerObj(),x,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine restarts algorithm from new point. |
|
|
//| All optimization parameters (including constraints) are left |
|
|
//| unchanged. |
|
|
//| This function allows to solve multiple optimization problems |
|
|
//| (which must have same number of dimensions) without object |
|
|
//| reallocation penalty. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure previously allocated with |
|
|
//| MinBLEICCreate call. |
|
|
//| X - new starting point. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICRestartFrom(CMinBLEICStateShell &state,
|
|
double &x[])
|
|
{
|
|
//--- function call
|
|
CMinBLEIC::MinBLEICRestartFrom(state.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| LIMITED MEMORY BFGS METHOD FOR LARGE SCALE OPTIMIZATION |
|
|
//| DESCRIPTION: |
|
|
//| The subroutine minimizes function F(x) of N arguments by using a |
|
|
//| quasi - Newton method (LBFGS scheme) which is optimized to use a |
|
|
//| minimum amount of memory. |
|
|
//| The subroutine generates the approximation of an inverse Hessian |
|
|
//| matrix by using information about the last M steps of the |
|
|
//| algorithm (instead of N). It lessens a required amount of memory |
|
|
//| from a value of order N^2 to a value of order 2*N*M. |
|
|
//| REQUIREMENTS: |
|
|
//| Algorithm will request following information during its |
|
|
//| operation: |
|
|
//| * function value F and its gradient G (simultaneously) at given |
|
|
//| point X |
|
|
//| USAGE: |
|
|
//| 1. User initializes algorithm state with MinLBFGSCreate() call |
|
|
//| 2. User tunes solver parameters with MinLBFGSSetCond() |
|
|
//| MinLBFGSSetStpMax() and other functions |
|
|
//| 3. User calls MinLBFGSOptimize() function which takes algorithm |
|
|
//| state and pointer (delegate, etc.) to callback function which |
|
|
//| calculates F/G. |
|
|
//| 4. User calls MinLBFGSResults() to get solution |
|
|
//| 5. Optionally user may call MinLBFGSRestartFrom() to solve |
|
|
//| another problem with same N/M but another starting point |
|
|
//| and/or another function. MinLBFGSRestartFrom() allows to reuse|
|
|
//| already initialized structure. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - problem dimension. N>0 |
|
|
//| M - number of corrections in the BFGS scheme of |
|
|
//| Hessian approximation update. Recommended value: |
|
|
//| 3<=M<=7. The smaller value causes worse |
|
|
//| convergence, the bigger will not cause a |
|
|
//| considerably better convergence, but will cause |
|
|
//| a fall in the performance. M<=N. |
|
|
//| X - initial solution approximation, array[0..N-1]. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NOTES: |
|
|
//| 1. you may tune stopping conditions with MinLBFGSSetCond() |
|
|
//| function |
|
|
//| 2. if target function contains exp() or other fast growing |
|
|
//| functions, and optimization algorithm makes too large steps |
|
|
//| which leads to overflow, use MinLBFGSSetStpMax() function to |
|
|
//| bound algorithm's steps. However, L-BFGS rarely needs such a |
|
|
//| tuning. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLBFGSCreate(const int n,const int m,double &x[],
|
|
CMinLBFGSStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinLBFGS::MinLBFGSCreate(n,m,x,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| LIMITED MEMORY BFGS METHOD FOR LARGE SCALE OPTIMIZATION |
|
|
//| DESCRIPTION: |
|
|
//| The subroutine minimizes function F(x) of N arguments by using a |
|
|
//| quasi - Newton method (LBFGS scheme) which is optimized to use a |
|
|
//| minimum amount of memory. |
|
|
//| The subroutine generates the approximation of an inverse Hessian |
|
|
//| matrix by using information about the last M steps of the |
|
|
//| algorithm (instead of N). It lessens a required amount of memory |
|
|
//| from a value of order N^2 to a value of order 2*N*M. |
|
|
//| REQUIREMENTS: |
|
|
//| Algorithm will request following information during its |
|
|
//| operation: |
|
|
//| * function value F and its gradient G (simultaneously) at given |
|
|
//| point X |
|
|
//| USAGE: |
|
|
//| 1. User initializes algorithm state with MinLBFGSCreate() call |
|
|
//| 2. User tunes solver parameters with MinLBFGSSetCond() |
|
|
//| MinLBFGSSetStpMax() and other functions |
|
|
//| 3. User calls MinLBFGSOptimize() function which takes algorithm |
|
|
//| state and pointer (delegate, etc.) to callback function which |
|
|
//| calculates F/G. |
|
|
//| 4. User calls MinLBFGSResults() to get solution |
|
|
//| 5. Optionally user may call MinLBFGSRestartFrom() to solve |
|
|
//| another problem with same N/M but another starting point |
|
|
//| and/or another function. MinLBFGSRestartFrom() allows to reuse|
|
|
//| already initialized structure. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - problem dimension. N>0 |
|
|
//| M - number of corrections in the BFGS scheme of |
|
|
//| Hessian approximation update. Recommended value: |
|
|
//| 3<=M<=7. The smaller value causes worse |
|
|
//| convergence, the bigger will not cause a |
|
|
//| considerably better convergence, but will cause |
|
|
//| a fall in the performance. M<=N. |
|
|
//| X - initial solution approximation, array[0..N-1]. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NOTES: |
|
|
//| 1. you may tune stopping conditions with MinLBFGSSetCond() |
|
|
//| function |
|
|
//| 2. if target function contains exp() or other fast growing |
|
|
//| functions, and optimization algorithm makes too large steps |
|
|
//| which leads to overflow, use MinLBFGSSetStpMax() function to |
|
|
//| bound algorithm's steps. However, L-BFGS rarely needs such a |
|
|
//| tuning. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLBFGSCreate(const int m,double &x[],CMinLBFGSStateShell &state)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CMinLBFGS::MinLBFGSCreate(n,m,x,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| The subroutine is finite difference variant of MinLBFGSCreate(). |
|
|
//| It uses finite differences in order to differentiate target |
|
|
//| function. |
|
|
//| Description below contains information which is specific to this |
|
|
//| function only. We recommend to read comments on MinLBFGSCreate() |
|
|
//| in order to get more information about creation of LBFGS |
|
|
//| optimizer. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - problem dimension, N>0: |
|
|
//| * if given, only leading N elements of X are used|
|
|
//| * if not given, automatically determined from |
|
|
//| size of X |
|
|
//| M - number of corrections in the BFGS scheme of |
|
|
//| Hessian approximation update. Recommended value: |
|
|
//| 3<=M<=7. The smaller value causes worse |
|
|
//| convergence, the bigger will not cause a |
|
|
//| considerably better convergence, but will cause a|
|
|
//| fall in the performance. M<=N. |
|
|
//| X - starting point, array[0..N-1]. |
|
|
//| DiffStep- differentiation step, >0 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NOTES: |
|
|
//| 1. algorithm uses 4-point central formula for differentiation. |
|
|
//| 2. differentiation step along I-th axis is equal to DiffStep*S[I]|
|
|
//| where S[] is scaling vector which can be set by |
|
|
//| MinLBFGSSetScale() call. |
|
|
//| 3. we recommend you to use moderate values of differentiation |
|
|
//| step. Too large step will result in too large truncation |
|
|
//| errors, while too small step will result in too large |
|
|
//| numerical errors. 1.0E-6 can be good value to start with. |
|
|
//| 4. Numerical differentiation is very inefficient - one gradient |
|
|
//| calculation needs 4*N function evaluations. This function will|
|
|
//| work for any N - either small (1...10), moderate (10...100) or|
|
|
//| large (100...). However, performance penalty will be too |
|
|
//| severe for any N's except for small ones. |
|
|
//| We should also say that code which relies on numerical |
|
|
//| differentiation is less robust and precise. LBFGS needs exact |
|
|
//| gradient values. Imprecise gradient may slow down convergence,|
|
|
//| especially on highly nonlinear problems. |
|
|
//| Thus we recommend to use this function for fast prototyping on|
|
|
//| small- dimensional problems only, and to implement analytical |
|
|
//| gradient as soon as possible. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLBFGSCreateF(const int n,const int m,double &x[],
|
|
const double diffstep,CMinLBFGSStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinLBFGS::MinLBFGSCreateF(n,m,x,diffstep,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| The subroutine is finite difference variant of MinLBFGSCreate(). |
|
|
//| It uses finite differences in order to differentiate target |
|
|
//| function. |
|
|
//| Description below contains information which is specific to this |
|
|
//| function only. We recommend to read comments on MinLBFGSCreate() |
|
|
//| in order to get more information about creation of LBFGS |
|
|
//| optimizer. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - problem dimension, N>0: |
|
|
//| * if given, only leading N elements of X are used|
|
|
//| * if not given, automatically determined from |
|
|
//| size of X |
|
|
//| M - number of corrections in the BFGS scheme of |
|
|
//| Hessian approximation update. Recommended value: |
|
|
//| 3<=M<=7. The smaller value causes worse |
|
|
//| convergence, the bigger will not cause a |
|
|
//| considerably better convergence, but will cause a|
|
|
//| fall in the performance. M<=N. |
|
|
//| X - starting point, array[0..N-1]. |
|
|
//| DiffStep- differentiation step, >0 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NOTES: |
|
|
//| 1. algorithm uses 4-point central formula for differentiation. |
|
|
//| 2. differentiation step along I-th axis is equal to DiffStep*S[I]|
|
|
//| where S[] is scaling vector which can be set by |
|
|
//| MinLBFGSSetScale() call. |
|
|
//| 3. we recommend you to use moderate values of differentiation |
|
|
//| step. Too large step will result in too large truncation |
|
|
//| errors, while too small step will result in too large |
|
|
//| numerical errors. 1.0E-6 can be good value to start with. |
|
|
//| 4. Numerical differentiation is very inefficient - one gradient |
|
|
//| calculation needs 4*N function evaluations. This function will|
|
|
//| work for any N - either small (1...10), moderate (10...100) or|
|
|
//| large (100...). However, performance penalty will be too |
|
|
//| severe for any N's except for small ones. |
|
|
//| We should also say that code which relies on numerical |
|
|
//| differentiation is less robust and precise. LBFGS needs exact |
|
|
//| gradient values. Imprecise gradient may slow down convergence,|
|
|
//| especially on highly nonlinear problems. |
|
|
//| Thus we recommend to use this function for fast prototyping on|
|
|
//| small- dimensional problems only, and to implement analytical |
|
|
//| gradient as soon as possible. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLBFGSCreateF(const int m,double &x[],const double diffstep,
|
|
CMinLBFGSStateShell &state)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CMinLBFGS::MinLBFGSCreateF(n,m,x,diffstep,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets stopping conditions for L-BFGS optimization |
|
|
//| algorithm. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| EpsG - >=0 |
|
|
//| The subroutine finishes its work if the condition|
|
|
//| |v|<EpsG is satisfied, where: |
|
|
//| * |.| means Euclidian norm |
|
|
//| * v - scaled gradient vector, v[i]=g[i]*s[i] |
|
|
//| * g - gradient |
|
|
//| * s - scaling coefficients set by |
|
|
//| MinLBFGSSetScale() |
|
|
//| EpsF - >=0 |
|
|
//| The subroutine finishes its work if on k+1-th |
|
|
//| iteration the condition |F(k+1)-F(k)| <= |
|
|
//| <= EpsF*max{|F(k)|,|F(k+1)|,1} is satisfied. |
|
|
//| EpsX - >=0 |
|
|
//| The subroutine finishes its work if on k+1-th |
|
|
//| iteration the condition |v|<=EpsX is fulfilled, |
|
|
//| where: |
|
|
//| * |.| means Euclidian norm |
|
|
//| * v - scaled step vector, v[i]=dx[i]/s[i] |
|
|
//| * dx - ste pvector, dx=X(k+1)-X(k) |
|
|
//| * s - scaling coefficients set by |
|
|
//| MinLBFGSSetScale() |
|
|
//| MaxIts - maximum number of iterations. If MaxIts=0, the |
|
|
//| number of iterations is unlimited. |
|
|
//| Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will|
|
|
//| lead to automatic stopping criterion selection (small EpsX). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLBFGSSetCond(CMinLBFGSStateShell &state,const double epsg,
|
|
const double epsf,const double epsx,
|
|
const int maxits)
|
|
{
|
|
//--- function call
|
|
CMinLBFGS::MinLBFGSSetCond(state.GetInnerObj(),epsg,epsf,epsx,maxits);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function turns on/off reporting. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NeedXRep- whether iteration reports are needed or not |
|
|
//| If NeedXRep is True, algorithm will call rep() callback function |
|
|
//| if it is provided to MinLBFGSOptimize(). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLBFGSSetXRep(CMinLBFGSStateShell &state,const bool needxrep)
|
|
{
|
|
//--- function call
|
|
CMinLBFGS::MinLBFGSSetXRep(state.GetInnerObj(),needxrep);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets maximum step length |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| StpMax - maximum step length, >=0. Set StpMax to 0.0 |
|
|
//| (default), if you don't want to limit step |
|
|
//| length. |
|
|
//| Use this subroutine when you optimize target function which |
|
|
//| contains exp() or other fast growing functions, and optimization |
|
|
//| algorithm makes too large steps which leads to overflow. This |
|
|
//| function allows us to reject steps that are too large (and |
|
|
//| therefore expose us to the possible overflow) without actually |
|
|
//| calculating function value at the x+stp*d. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLBFGSSetStpMax(CMinLBFGSStateShell &state,const double stpmax)
|
|
{
|
|
//--- function call
|
|
CMinLBFGS::MinLBFGSSetStpMax(state.GetInnerObj(),stpmax);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets scaling coefficients for LBFGS optimizer. |
|
|
//| ALGLIB optimizers use scaling matrices to test stopping |
|
|
//| conditions (step size and gradient are scaled before comparison |
|
|
//| with tolerances). Scale of the I-th variable is a translation |
|
|
//| invariant measure of: |
|
|
//| a) "how large" the variable is |
|
|
//| b) how large the step should be to make significant changes in |
|
|
//| the function |
|
|
//| Scaling is also used by finite difference variant of the |
|
|
//| optimizer - step along I-th axis is equal to DiffStep*S[I]. |
|
|
//| In most optimizers (and in the LBFGS too) scaling is NOT a form |
|
|
//| of preconditioning. It just affects stopping conditions. You |
|
|
//| should set preconditioner by separate call to one of the |
|
|
//| MinLBFGSSetPrec...() functions. |
|
|
//| There is special preconditioning mode, however, which uses |
|
|
//| scaling coefficients to form diagonal preconditioning matrix. |
|
|
//| You can turn this mode on, if you want. But you should |
|
|
//| understand that scaling is not the same thing as |
|
|
//| preconditioning - these are two different, although related |
|
|
//| forms of tuning solver. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure stores algorithm state |
|
|
//| S - array[N], non-zero scaling coefficients |
|
|
//| S[i] may be negative, sign doesn't matter. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLBFGSSetScale(CMinLBFGSStateShell &state,double &s[])
|
|
{
|
|
//--- function call
|
|
CMinLBFGS::MinLBFGSSetScale(state.GetInnerObj(),s);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Modification of the preconditioner: default preconditioner |
|
|
//| (simple scaling, same for all elements of X) is used. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NOTE: you can change preconditioner "on the fly", during |
|
|
//| algorithm iterations. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLBFGSSetPrecDefault(CMinLBFGSStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinLBFGS::MinLBFGSSetPrecDefault(state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Modification of the preconditioner: Cholesky factorization of |
|
|
//| approximate Hessian is used. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| P - triangular preconditioner, Cholesky factorization|
|
|
//| of the approximate Hessian. array[0..N-1,0..N-1],|
|
|
//| (if larger, only leading N elements are used). |
|
|
//| IsUpper - whether upper or lower triangle of P is given |
|
|
//| (other triangle is not referenced) |
|
|
//| After call to this function preconditioner is changed to P (P is |
|
|
//| copied into the internal buffer). |
|
|
//| NOTE: you can change preconditioner "on the fly", during |
|
|
//| algorithm iterations. |
|
|
//| NOTE 2: P should be nonsingular. Exception will be thrown |
|
|
//| otherwise. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLBFGSSetPrecCholesky(CMinLBFGSStateShell &state,
|
|
CMatrixDouble &p,const bool isupper)
|
|
{
|
|
//--- function call
|
|
CMinLBFGS::MinLBFGSSetPrecCholesky(state.GetInnerObj(),p,isupper);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Modification of the preconditioner: diagonal of approximate |
|
|
//| Hessian is used. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| D - diagonal of the approximate Hessian, |
|
|
//| array[0..N-1], (if larger, only leading N |
|
|
//| elements are used). |
|
|
//| NOTE: you can change preconditioner "on the fly", during |
|
|
//| algorithm iterations. |
|
|
//| NOTE 2: D[i] should be positive. Exception will be thrown |
|
|
//| otherwise. |
|
|
//| NOTE 3: you should pass diagonal of approximate Hessian - NOT |
|
|
//| ITS INVERSE. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLBFGSSetPrecDiag(CMinLBFGSStateShell &state,double &d[])
|
|
{
|
|
//--- function call
|
|
CMinLBFGS::MinLBFGSSetPrecDiag(state.GetInnerObj(),d);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Modification of the preconditioner: scale-based diagonal |
|
|
//| preconditioning. |
|
|
//| This preconditioning mode can be useful when you don't have |
|
|
//| approximate diagonal of Hessian, but you know that your variables|
|
|
//| are badly scaled (for example, one variable is in [1,10], and |
|
|
//| another in [1000,100000]), and most part of the ill-conditioning |
|
|
//| comes from different scales of vars. |
|
|
//| In this case simple scale-based preconditioner, with H[i] = |
|
|
//| = 1/(s[i]^2), can greatly improve convergence. |
|
|
//| IMPRTANT: you should set scale of your variables with |
|
|
//| MinLBFGSSetScale() call (before or after MinLBFGSSetPrecScale() |
|
|
//| call). Without knowledge of the scale of your variables |
|
|
//| scale-based preconditioner will be just unit matrix. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLBFGSSetPrecScale(CMinLBFGSStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinLBFGS::MinLBFGSSetPrecScale(state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function provides reverse communication interface |
|
|
//| Reverse communication interface is not documented or recommended |
|
|
//| to use. |
|
|
//| See below for functions which provide better documented API |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::MinLBFGSIteration(CMinLBFGSStateShell &state)
|
|
{
|
|
//--- return result
|
|
return(CMinLBFGS::MinLBFGSIteration(state.GetInnerObj()));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This family of functions is used to launcn iterations of |
|
|
//| nonlinear optimizer |
|
|
//| These functions accept following parameters: |
|
|
//| func - callback which calculates function (or merit |
|
|
//| function) value func at given point x |
|
|
//| grad - callback which calculates function (or merit |
|
|
//| function) value func and gradient grad at given |
|
|
//| point x |
|
|
//| rep - optional callback which is called after each |
|
|
//| iteration can be null |
|
|
//| obj - optional object which is passed to |
|
|
//| func/grad/hess/jac/rep can be null |
|
|
//| NOTES: |
|
|
//| 1. This function has two different implementations: one which |
|
|
//| uses exact (analytical) user-supplied gradient, and one which |
|
|
//| uses function value only and numerically differentiates |
|
|
//| function in order to obtain gradient. |
|
|
//| Depending on the specific function used to create optimizer |
|
|
//| object (either MinLBFGSCreate() for analytical gradient or |
|
|
//| MinLBFGSCreateF() for numerical differentiation) you should |
|
|
//| choose appropriate variant of MinLBFGSOptimize() - one which |
|
|
//| accepts function AND gradient or one which accepts function |
|
|
//| ONLY. |
|
|
//| Be careful to choose variant of MinLBFGSOptimize() which |
|
|
//| corresponds to your optimization scheme! Table below lists |
|
|
//| different combinations of callback (function/gradient) passed |
|
|
//| to MinLBFGSOptimize() and specific function used to create |
|
|
//| optimizer. |
|
|
//| | USER PASSED TO MinLBFGSOptimize() |
|
|
//| CREATED WITH | function only | function and gradient |
|
|
//| ------------------------------------------------------------ |
|
|
//| MinLBFGSCreateF() | work FAIL |
|
|
//| MinLBFGSCreate() | FAIL work |
|
|
//| Here "FAIL" denotes inappropriate combinations of optimizer |
|
|
//| creation function and MinLBFGSOptimize() version. Attemps to |
|
|
//| use such combination (for example, to create optimizer with |
|
|
//| MinLBFGSCreateF() and to pass gradient information to |
|
|
//| MinCGOptimize()) will lead to exception being thrown. Either |
|
|
//| you did not pass gradient when it WAS needed or you passed |
|
|
//| gradient when it was NOT needed. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLBFGSOptimize(CMinLBFGSStateShell &state,CNDimensional_Func &func,
|
|
CNDimensional_Rep &rep,bool rep_status,CObject &obj)
|
|
{
|
|
//--- cycle
|
|
while(CAlglib::MinLBFGSIteration(state))
|
|
{
|
|
//--- check
|
|
if(state.GetNeedF())
|
|
{
|
|
func.Func(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetInnerObj().m_xupdated)
|
|
{
|
|
//--- check
|
|
if(rep_status)
|
|
rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
Print("ALGLIB: error in 'minlbfgsoptimize' (some derivatives were not provided?)");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This family of functions is used to launcn iterations of |
|
|
//| nonlinear optimizer |
|
|
//| These functions accept following parameters: |
|
|
//| func - callback which calculates function (or merit |
|
|
//| function) value func at given point x |
|
|
//| grad - callback which calculates function (or merit |
|
|
//| function) value func and gradient grad at given |
|
|
//| point x |
|
|
//| rep - optional callback which is called after each |
|
|
//| iteration can be null |
|
|
//| obj - optional object which is passed to |
|
|
//| func/grad/hess/jac/rep can be null |
|
|
//| NOTES: |
|
|
//| 1. This function has two different implementations: one which |
|
|
//| uses exact (analytical) user-supplied gradient, and one which |
|
|
//| uses function value only and numerically differentiates |
|
|
//| function in order to obtain gradient. |
|
|
//| Depending on the specific function used to create optimizer |
|
|
//| object (either MinLBFGSCreate() for analytical gradient or |
|
|
//| MinLBFGSCreateF() for numerical differentiation) you should |
|
|
//| choose appropriate variant of MinLBFGSOptimize() - one which |
|
|
//| accepts function AND gradient or one which accepts function |
|
|
//| ONLY. |
|
|
//| Be careful to choose variant of MinLBFGSOptimize() which |
|
|
//| corresponds to your optimization scheme! Table below lists |
|
|
//| different combinations of callback (function/gradient) passed |
|
|
//| to MinLBFGSOptimize() and specific function used to create |
|
|
//| optimizer. |
|
|
//| | USER PASSED TO MinLBFGSOptimize() |
|
|
//| CREATED WITH | function only | function and gradient |
|
|
//| ------------------------------------------------------------ |
|
|
//| MinLBFGSCreateF() | work FAIL |
|
|
//| MinLBFGSCreate() | FAIL work |
|
|
//| Here "FAIL" denotes inappropriate combinations of optimizer |
|
|
//| creation function and MinLBFGSOptimize() version. Attemps to |
|
|
//| use such combination (for example, to create optimizer with |
|
|
//| MinLBFGSCreateF() and to pass gradient information to |
|
|
//| MinCGOptimize()) will lead to exception being thrown. Either |
|
|
//| you did not pass gradient when it WAS needed or you passed |
|
|
//| gradient when it was NOT needed. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLBFGSOptimize(CMinLBFGSStateShell &state,CNDimensional_Grad &grad,
|
|
CNDimensional_Rep &rep,bool rep_status,CObject &obj)
|
|
{
|
|
//--- cycle
|
|
while(CAlglib::MinLBFGSIteration(state))
|
|
{
|
|
//--- check
|
|
if(state.GetNeedFG())
|
|
{
|
|
grad.Grad(state.GetInnerObj().m_x,state.GetInnerObj().m_f,state.GetInnerObj().m_g,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetInnerObj().m_xupdated)
|
|
{
|
|
//--- check
|
|
if(rep_status)
|
|
rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
Print("ALGLIB: error in 'minlbfgsoptimize' (some derivatives were not provided?)");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| L-BFGS algorithm results |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - algorithm state |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| X - array[0..N-1], solution |
|
|
//| Rep - optimization report: |
|
|
//| * Rep.TerminationType completetion code: |
|
|
//| * -2 rounding errors prevent further |
|
|
//| improvement. X contains best point |
|
|
//| found. |
|
|
//| * -1 incorrect parameters were specified |
|
|
//| * 1 relative function improvement is no |
|
|
//| more than EpsF. |
|
|
//| * 2 relative step is no more than EpsX. |
|
|
//| * 4 gradient norm is no more than EpsG |
|
|
//| * 5 MaxIts steps was taken |
|
|
//| * 7 stopping conditions are too |
|
|
//| stringent, further improvement is |
|
|
//| impossible |
|
|
//| * Rep.IterationsCount contains iterations count |
|
|
//| * NFEV countains number of function calculations |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLBFGSResults(CMinLBFGSStateShell &state,double &x[],
|
|
CMinLBFGSReportShell &rep)
|
|
{
|
|
//--- function call
|
|
CMinLBFGS::MinLBFGSResults(state.GetInnerObj(),x,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| L-BFGS algorithm results |
|
|
//| Buffered implementation of MinLBFGSResults which uses |
|
|
//| pre-allocated buffer to store X[]. If buffer size is too small, |
|
|
//| it resizes buffer. It is intended to be used in the inner cycles |
|
|
//| of performance critical algorithms where array reallocation |
|
|
//| penalty is too large to be ignored. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLBFGSresultsbuf(CMinLBFGSStateShell &state,double &x[],
|
|
CMinLBFGSReportShell &rep)
|
|
{
|
|
//--- function call
|
|
CMinLBFGS::MinLBFGSresultsbuf(state.GetInnerObj(),x,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine restarts LBFGS algorithm from new point. All |
|
|
//| optimization parameters are left unchanged. |
|
|
//| This function allows to solve multiple optimization problems |
|
|
//| (which must have same number of dimensions) without object |
|
|
//| reallocation penalty. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure used to store algorithm state |
|
|
//| X - new starting point. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLBFGSRestartFrom(CMinLBFGSStateShell &state,double &x[])
|
|
{
|
|
//--- function call
|
|
CMinLBFGS::MinLBFGSRestartFrom(state.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| CONSTRAINED QUADRATIC PROGRAMMING |
|
|
//| The subroutine creates QP optimizer. After initial creation, it |
|
|
//| contains default optimization problem with zero quadratic and |
|
|
//| linear terms and no constraints. You should set quadratic/linear |
|
|
//| terms with calls to functions provided by MinQP subpackage. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - problem size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - optimizer with zero quadratic/linear terms |
|
|
//| and no constraints |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinQPCreate(const int n,CMinQPStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinQP::MinQPCreate(n,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets linear term for QP solver. |
|
|
//| By default, linear term is zero. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| B - linear term, array[N]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinQPSetLinearTerm(CMinQPStateShell &state,double &b[])
|
|
{
|
|
//--- function call
|
|
CMinQP::MinQPSetLinearTerm(state.GetInnerObj(),b);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets quadratic term for QP solver. |
|
|
//| By default quadratic term is zero. |
|
|
//| IMPORTANT: this solver minimizes following function: |
|
|
//| f(x) = 0.5*x'*A*x + b'*x. |
|
|
//| Note that quadratic term has 0.5 before it. So if you want to |
|
|
//| minimize |
|
|
//| f(x) = x^2 + x |
|
|
//| you should rewrite your problem as follows: |
|
|
//| f(x) = 0.5*(2*x^2) + x |
|
|
//| and your matrix A will be equal to [[2.0]], not to [[1.0]] |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| A - matrix, array[N,N] |
|
|
//| IsUpper - (optional) storage type: |
|
|
//| * if True, symmetric matrix A is given by its |
|
|
//| upper triangle, and the lower triangle isn?t |
|
|
//| used |
|
|
//| * if False, symmetric matrix A is given by its |
|
|
//| lower triangle, and the upper triangle isn?t |
|
|
//| used |
|
|
//| * if not given, both lower and upper triangles |
|
|
//| must be filled. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinQPSetQuadraticTerm(CMinQPStateShell &state,CMatrixDouble &a,
|
|
const bool isupper)
|
|
{
|
|
//--- function call
|
|
CMinQP::MinQPSetQuadraticTerm(state.GetInnerObj(),a,isupper);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets quadratic term for QP solver. |
|
|
//| By default quadratic term is zero. |
|
|
//| IMPORTANT: this solver minimizes following function: |
|
|
//| f(x) = 0.5*x'*A*x + b'*x. |
|
|
//| Note that quadratic term has 0.5 before it. So if you want to |
|
|
//| minimize |
|
|
//| f(x) = x^2 + x |
|
|
//| you should rewrite your problem as follows: |
|
|
//| f(x) = 0.5*(2*x^2) + x |
|
|
//| and your matrix A will be equal to [[2.0]], not to [[1.0]] |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| A - matrix, array[N,N] |
|
|
//| IsUpper - (optional) storage type: |
|
|
//| * if True, symmetric matrix A is given by its |
|
|
//| upper triangle, and the lower triangle isn?t |
|
|
//| used |
|
|
//| * if False, symmetric matrix A is given by its |
|
|
//| lower triangle, and the upper triangle isn?t |
|
|
//| used |
|
|
//| * if not given, both lower and upper triangles |
|
|
//| must be filled. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinQPSetQuadraticTerm(CMinQPStateShell &state,CMatrixDouble &a)
|
|
{
|
|
//--- create a variable
|
|
bool isupper;
|
|
//--- check
|
|
if(!CAp::IsSymmetric(a))
|
|
{
|
|
Print(__FUNCTION__+": 'a' parameter is not symmetric matrix");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
isupper=false;
|
|
//--- function call
|
|
CMinQP::MinQPSetQuadraticTerm(state.GetInnerObj(),a,isupper);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets starting point for QP solver. It is useful to |
|
|
//| have good initial approximation to the solution, because it will |
|
|
//| increase speed of convergence and identification of active |
|
|
//| constraints. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| X - starting point, array[N]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinQPSetStartingPoint(CMinQPStateShell &state,double &x[])
|
|
{
|
|
//--- function call
|
|
CMinQP::MinQPSetStartingPoint(state.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets origin for QP solver. By default, following |
|
|
//| QP program is solved: |
|
|
//| min(0.5*x'*A*x+b'*x) |
|
|
//| This function allows to solve different problem: |
|
|
//| min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin)) |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| XOrigin - origin, array[N]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinQPSetOrigin(CMinQPStateShell &state,double &xorigin[])
|
|
{
|
|
//--- function call
|
|
CMinQP::MinQPSetOrigin(state.GetInnerObj(),xorigin);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function tells solver to use Cholesky-based algorithm. |
|
|
//| Cholesky-based algorithm can be used when: |
|
|
//| * problem is convex |
|
|
//| * there is no constraints or only boundary constraints are |
|
|
//| present |
|
|
//| This algorithm has O(N^3) complexity for unconstrained problem |
|
|
//| and is up to several times slower on bound constrained problems |
|
|
//| (these additional iterations are needed to identify active |
|
|
//| constraints). |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinQPSetAlgoCholesky(CMinQPStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinQP::MinQPSetAlgoCholesky(state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets boundary constraints for QP solver |
|
|
//| Boundary constraints are inactive by default (after initial |
|
|
//| creation). After being set, they are preserved until explicitly |
|
|
//| turned off with another SetBC() call. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure stores algorithm state |
|
|
//| BndL - lower bounds, array[N]. |
|
|
//| If some (all) variables are unbounded, you may |
|
|
//| specify very small number or -INF (latter is |
|
|
//| recommended because it will allow solver to use |
|
|
//| better algorithm). |
|
|
//| BndU - upper bounds, array[N]. |
|
|
//| If some (all) variables are unbounded, you may |
|
|
//| specify very large number or +INF (latter is |
|
|
//| recommended because it will allow solver to use |
|
|
//| better algorithm). |
|
|
//| NOTE: it is possible to specify BndL[i]=BndU[i]. In this case |
|
|
//| I-th variable will be "frozen" at X[i]=BndL[i]=BndU[i]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinQPSetBC(CMinQPStateShell &state,double &bndl[],
|
|
double &bndu[])
|
|
{
|
|
//--- function call
|
|
CMinQP::MinQPSetBC(state.GetInnerObj(),bndl,bndu);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function solves quadratic programming problem. |
|
|
//| You should call it after setting solver options with |
|
|
//| MinQPSet...() calls. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - algorithm state |
|
|
//| You should use MinQPResults() function to access results after |
|
|
//| calls to this function. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinQPOptimize(CMinQPStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinQP::MinQPOptimize(state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| QP solver results |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - algorithm state |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| X - array[0..N-1], solution |
|
|
//| Rep - optimization report. You should check Rep. |
|
|
//| TerminationType, which contains completion code, |
|
|
//| and you may check another fields which contain |
|
|
//| another information about algorithm functioning. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinQPResults(CMinQPStateShell &state,double &x[],
|
|
CMinQPReportShell &rep)
|
|
{
|
|
//--- function call
|
|
CMinQP::MinQPResults(state.GetInnerObj(),x,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| QP results |
|
|
//| Buffered implementation of MinQPResults() which uses |
|
|
//| pre-allocated buffer to store X[]. If buffer size is too small, |
|
|
//| it resizes buffer. It is intended to be used in the inner cycles |
|
|
//| of performance critical algorithms where array reallocation |
|
|
//| penalty is too large to be ignored. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinQPResultsBuf(CMinQPStateShell &state,double &x[],
|
|
CMinQPReportShell &rep)
|
|
{
|
|
//--- function call
|
|
CMinQP::MinQPResultsBuf(state.GetInnerObj(),x,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| IMPROVED LEVENBERG-MARQUARDT METHOD FOR |
|
|
//| NON-LINEAR LEAST SQUARES OPTIMIZATION |
|
|
//| DESCRIPTION: |
|
|
//| This function is used to find minimum of function which is |
|
|
//| represented as sum of squares: |
|
|
//| F(x) = f[0]^2(x[0],...,x[n-1]) + ... + |
|
|
//| + f[m-1]^2(x[0],...,x[n-1]) |
|
|
//| using value of function vector f[] and Jacobian of f[]. |
|
|
//| REQUIREMENTS: |
|
|
//| This algorithm will request following information during its |
|
|
//| operation: |
|
|
//| * function vector f[] at given point X |
|
|
//| * function vector f[] and Jacobian of f[] (simultaneously) at |
|
|
//| given point |
|
|
//| There are several overloaded versions of MinLMOptimize() |
|
|
//| function which correspond to different LM-like optimization |
|
|
//| algorithms provided by this unit. You should choose version which|
|
|
//| accepts fvec() and jac() callbacks. First one is used to |
|
|
//| calculate f[] at given point, second one calculates f[] and |
|
|
//| Jacobian df[i]/dx[j]. |
|
|
//| You can try to initialize MinLMState structure with VJ function |
|
|
//| and then use incorrect version of MinLMOptimize() (for example,|
|
|
//| version which works with general form function and does not |
|
|
//| provide Jacobian), but it will lead to exception being thrown |
|
|
//| after first attempt to calculate Jacobian. |
|
|
//| USAGE: |
|
|
//| 1. User initializes algorithm state with MinLMCreateVJ() call |
|
|
//| 2. User tunes solver parameters with MinLMSetCond(), |
|
|
//| MinLMSetStpMax() and other functions |
|
|
//| 3. User calls MinLMOptimize() function which takes algorithm |
|
|
//| state and callback functions. |
|
|
//| 4. User calls MinLMResults() to get solution |
|
|
//| 5. Optionally, user may call MinLMRestartFrom() to solve another |
|
|
//| problem with same N/M but another starting point and/or |
|
|
//| another function. MinLMRestartFrom() allows to reuse already |
|
|
//| initialized structure. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - dimension, N>1 |
|
|
//| * if given, only leading N elements of X are |
|
|
//| used |
|
|
//| * if not given, automatically determined from |
|
|
//| size of X |
|
|
//| M - number of functions f[i] |
|
|
//| X - initial solution, array[0..N-1] |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NOTES: |
|
|
//| 1. you may tune stopping conditions with MinLMSetCond() function |
|
|
//| 2. if target function contains exp() or other fast growing |
|
|
//| functions, and optimization algorithm makes too large steps |
|
|
//| which leads to overflow, use MinLMSetStpMax() function to |
|
|
//| bound algorithm's steps. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMCreateVJ(const int n,const int m,double &x[],
|
|
CMinLMStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinLM::MinLMCreateVJ(n,m,x,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| IMPROVED LEVENBERG-MARQUARDT METHOD FOR |
|
|
//| NON-LINEAR LEAST SQUARES OPTIMIZATION |
|
|
//| DESCRIPTION: |
|
|
//| This function is used to find minimum of function which is |
|
|
//| represented as sum of squares: |
|
|
//| F(x) = f[0]^2(x[0],...,x[n-1]) + ... + |
|
|
//| + f[m-1]^2(x[0],...,x[n-1]) |
|
|
//| using value of function vector f[] and Jacobian of f[]. |
|
|
//| REQUIREMENTS: |
|
|
//| This algorithm will request following information during its |
|
|
//| operation: |
|
|
//| * function vector f[] at given point X |
|
|
//| * function vector f[] and Jacobian of f[] (simultaneously) at |
|
|
//| given point |
|
|
//| There are several overloaded versions of MinLMOptimize() |
|
|
//| function which correspond to different LM-like optimization |
|
|
//| algorithms provided by this unit. You should choose version which|
|
|
//| accepts fvec() and jac() callbacks. First one is used to |
|
|
//| calculate f[] at given point, second one calculates f[] and |
|
|
//| Jacobian df[i]/dx[j]. |
|
|
//| You can try to initialize MinLMState structure with VJ function |
|
|
//| and then use incorrect version of MinLMOptimize() (for example,|
|
|
//| version which works with general form function and does not |
|
|
//| provide Jacobian), but it will lead to exception being thrown |
|
|
//| after first attempt to calculate Jacobian. |
|
|
//| USAGE: |
|
|
//| 1. User initializes algorithm state with MinLMCreateVJ() call |
|
|
//| 2. User tunes solver parameters with MinLMSetCond(), |
|
|
//| MinLMSetStpMax() and other functions |
|
|
//| 3. User calls MinLMOptimize() function which takes algorithm |
|
|
//| state and callback functions. |
|
|
//| 4. User calls MinLMResults() to get solution |
|
|
//| 5. Optionally, user may call MinLMRestartFrom() to solve another |
|
|
//| problem with same N/M but another starting point and/or |
|
|
//| another function. MinLMRestartFrom() allows to reuse already |
|
|
//| initialized structure. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - dimension, N>1 |
|
|
//| * if given, only leading N elements of X are |
|
|
//| used |
|
|
//| * if not given, automatically determined from |
|
|
//| size of X |
|
|
//| M - number of functions f[i] |
|
|
//| X - initial solution, array[0..N-1] |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NOTES: |
|
|
//| 1. you may tune stopping conditions with MinLMSetCond() function |
|
|
//| 2. if target function contains exp() or other fast growing |
|
|
//| functions, and optimization algorithm makes too large steps |
|
|
//| which leads to overflow, use MinLMSetStpMax() function to |
|
|
//| bound algorithm's steps. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMCreateVJ(const int m,double &x[],CMinLMStateShell &state)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CMinLM::MinLMCreateVJ(n,m,x,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| IMPROVED LEVENBERG-MARQUARDT METHOD FOR |
|
|
//| NON-LINEAR LEAST SQUARES OPTIMIZATION |
|
|
//| DESCRIPTION: |
|
|
//| This function is used to find minimum of function which is |
|
|
//| represented as sum of squares: |
|
|
//| F(x) = f[0]^2(x[0],...,x[n-1]) + ... + |
|
|
//| + f[m-1]^2(x[0],...,x[n-1]) |
|
|
//| using value of function vector f[] only. Finite differences are |
|
|
//| used to calculate Jacobian. |
|
|
//| REQUIREMENTS: |
|
|
//| This algorithm will request following information during its |
|
|
//| operation: |
|
|
//| * function vector f[] at given point X |
|
|
//| There are several overloaded versions of MinLMOptimize() function|
|
|
//| which correspond to different LM-like optimization algorithms |
|
|
//| provided by this unit. You should choose version which accepts |
|
|
//| fvec() callback. |
|
|
//| You can try to initialize MinLMState structure with VJ function |
|
|
//| and then use incorrect version of MinLMOptimize() (for example, |
|
|
//| version which works with general form function and does not |
|
|
//| accept function vector), but it will lead to exception being |
|
|
//| thrown after first attempt to calculate Jacobian. |
|
|
//| USAGE: |
|
|
//| 1. User initializes algorithm state with MinLMCreateV() call |
|
|
//| 2. User tunes solver parameters with MinLMSetCond(), |
|
|
//| MinLMSetStpMax() and other functions |
|
|
//| 3. User calls MinLMOptimize() function which takes algorithm |
|
|
//| state and callback functions. |
|
|
//| 4. User calls MinLMResults() to get solution |
|
|
//| 5. Optionally, user may call MinLMRestartFrom() to solve another |
|
|
//| problem with same N/M but another starting point and/or |
|
|
//| another function. MinLMRestartFrom() allows to reuse already |
|
|
//| initialized structure. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - dimension, N>1 |
|
|
//| * if given, only leading N elements of X are |
|
|
//| used |
|
|
//| * if not given, automatically determined from |
|
|
//| size of X |
|
|
//| M - number of functions f[i] |
|
|
//| X - initial solution, array[0..N-1] |
|
|
//| DiffStep- differentiation step, >0 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| See also MinLMIteration, MinLMResults. |
|
|
//| NOTES: |
|
|
//| 1. you may tune stopping conditions with MinLMSetCond() function |
|
|
//| 2. if target function contains exp() or other fast growing |
|
|
//| functions, and optimization algorithm makes too large steps |
|
|
//| which leads to overflow, use MinLMSetStpMax() function to |
|
|
//| bound algorithm's steps. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMCreateV(const int n,const int m,double &x[],
|
|
double diffstep,CMinLMStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinLM::MinLMCreateV(n,m,x,diffstep,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| IMPROVED LEVENBERG-MARQUARDT METHOD FOR |
|
|
//| NON-LINEAR LEAST SQUARES OPTIMIZATION |
|
|
//| DESCRIPTION: |
|
|
//| This function is used to find minimum of function which is |
|
|
//| represented as sum of squares: |
|
|
//| F(x) = f[0]^2(x[0],...,x[n-1]) + ... + |
|
|
//| + f[m-1]^2(x[0],...,x[n-1]) |
|
|
//| using value of function vector f[] only. Finite differences are |
|
|
//| used to calculate Jacobian. |
|
|
//| REQUIREMENTS: |
|
|
//| This algorithm will request following information during its |
|
|
//| operation: |
|
|
//| * function vector f[] at given point X |
|
|
//| There are several overloaded versions of MinLMOptimize() function|
|
|
//| which correspond to different LM-like optimization algorithms |
|
|
//| provided by this unit. You should choose version which accepts |
|
|
//| fvec() callback. |
|
|
//| You can try to initialize MinLMState structure with VJ function |
|
|
//| and then use incorrect version of MinLMOptimize() (for example, |
|
|
//| version which works with general form function and does not |
|
|
//| accept function vector), but it will lead to exception being |
|
|
//| thrown after first attempt to calculate Jacobian. |
|
|
//| USAGE: |
|
|
//| 1. User initializes algorithm state with MinLMCreateV() call |
|
|
//| 2. User tunes solver parameters with MinLMSetCond(), |
|
|
//| MinLMSetStpMax() and other functions |
|
|
//| 3. User calls MinLMOptimize() function which takes algorithm |
|
|
//| state and callback functions. |
|
|
//| 4. User calls MinLMResults() to get solution |
|
|
//| 5. Optionally, user may call MinLMRestartFrom() to solve another |
|
|
//| problem with same N/M but another starting point and/or |
|
|
//| another function. MinLMRestartFrom() allows to reuse already |
|
|
//| initialized structure. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - dimension, N>1 |
|
|
//| * if given, only leading N elements of X are |
|
|
//| used |
|
|
//| * if not given, automatically determined from |
|
|
//| size of X |
|
|
//| M - number of functions f[i] |
|
|
//| X - initial solution, array[0..N-1] |
|
|
//| DiffStep- differentiation step, >0 |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| See also MinLMIteration, MinLMResults. |
|
|
//| NOTES: |
|
|
//| 1. you may tune stopping conditions with MinLMSetCond() function |
|
|
//| 2. if target function contains exp() or other fast growing |
|
|
//| functions, and optimization algorithm makes too large steps |
|
|
//| which leads to overflow, use MinLMSetStpMax() function to |
|
|
//| bound algorithm's steps. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMCreateV(const int m,double &x[],const double diffstep,
|
|
CMinLMStateShell &state)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CMinLM::MinLMCreateV(n,m,x,diffstep,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| LEVENBERG-MARQUARDT-LIKE METHOD FOR NON-LINEAR OPTIMIZATION |
|
|
//| DESCRIPTION: |
|
|
//| This function is used to find minimum of general form (not |
|
|
//| "sum-of-squares") function |
|
|
//| F = F(x[0], ..., x[n-1]) |
|
|
//| using its gradient and Hessian. Levenberg-Marquardt modification |
|
|
//| with L-BFGS pre-optimization and internal pre-conditioned L-BFGS |
|
|
//| optimization after each Levenberg-Marquardt step is used. |
|
|
//| REQUIREMENTS: |
|
|
//| This algorithm will request following information during its |
|
|
//| operation: |
|
|
//| * function value F at given point X |
|
|
//| * F and gradient G (simultaneously) at given point X |
|
|
//| * F, G and Hessian H (simultaneously) at given point X |
|
|
//| There are several overloaded versions of MinLMOptimize() |
|
|
//| function which correspond to different LM-like optimization |
|
|
//| algorithms provided by this unit. You should choose version which|
|
|
//| accepts func(), grad() and hess() function pointers. First |
|
|
//| pointer is used to calculate F at given point, second one |
|
|
//| calculates F(x) and grad F(x), third one calculates F(x), grad |
|
|
//| F(x), hess F(x). |
|
|
//| You can try to initialize MinLMState structure with FGH-function |
|
|
//| and then use incorrect version of MinLMOptimize() (for example, |
|
|
//| version which does not provide Hessian matrix), but it will lead |
|
|
//| to exception being thrown after first attempt to calculate |
|
|
//| Hessian. |
|
|
//| USAGE: |
|
|
//| 1. User initializes algorithm state with MinLMCreateFGH() call |
|
|
//| 2. User tunes solver parameters with MinLMSetCond(), |
|
|
//| MinLMSetStpMax() and other functions |
|
|
//| 3. User calls MinLMOptimize() function which takes algorithm |
|
|
//| state and pointers (delegates, etc.) to callback functions. |
|
|
//| 4. User calls MinLMResults() to get solution |
|
|
//| 5. Optionally, user may call MinLMRestartFrom() to solve another |
|
|
//| problem with same N but another starting point and/or another |
|
|
//| function. MinLMRestartFrom() allows to reuse already |
|
|
//| initialized structure. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - dimension, N>1 |
|
|
//| * if given, only leading N elements of X are |
|
|
//| used |
|
|
//| * if not given, automatically determined from |
|
|
//| size of X |
|
|
//| X - initial solution, array[0..N-1] |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NOTES: |
|
|
//| 1. you may tune stopping conditions with MinLMSetCond() function |
|
|
//| 2. if target function contains exp() or other fast growing |
|
|
//| functions, and optimization algorithm makes too large steps |
|
|
//| which leads to overflow, use MinLMSetStpMax() function to |
|
|
//| bound algorithm's steps. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMCreateFGH(const int n,double &x[],CMinLMStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinLM::MinLMCreateFGH(n,x,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| LEVENBERG-MARQUARDT-LIKE METHOD FOR NON-LINEAR OPTIMIZATION |
|
|
//| DESCRIPTION: |
|
|
//| This function is used to find minimum of general form (not |
|
|
//| "sum-of-squares") function |
|
|
//| F = F(x[0], ..., x[n-1]) |
|
|
//| using its gradient and Hessian. Levenberg-Marquardt modification |
|
|
//| with L-BFGS pre-optimization and internal pre-conditioned L-BFGS |
|
|
//| optimization after each Levenberg-Marquardt step is used. |
|
|
//| REQUIREMENTS: |
|
|
//| This algorithm will request following information during its |
|
|
//| operation: |
|
|
//| * function value F at given point X |
|
|
//| * F and gradient G (simultaneously) at given point X |
|
|
//| * F, G and Hessian H (simultaneously) at given point X |
|
|
//| There are several overloaded versions of MinLMOptimize() |
|
|
//| function which correspond to different LM-like optimization |
|
|
//| algorithms provided by this unit. You should choose version which|
|
|
//| accepts func(), grad() and hess() function pointers. First |
|
|
//| pointer is used to calculate F at given point, second one |
|
|
//| calculates F(x) and grad F(x), third one calculates F(x), grad |
|
|
//| F(x), hess F(x). |
|
|
//| You can try to initialize MinLMState structure with FGH-function |
|
|
//| and then use incorrect version of MinLMOptimize() (for example, |
|
|
//| version which does not provide Hessian matrix), but it will lead |
|
|
//| to exception being thrown after first attempt to calculate |
|
|
//| Hessian. |
|
|
//| USAGE: |
|
|
//| 1. User initializes algorithm state with MinLMCreateFGH() call |
|
|
//| 2. User tunes solver parameters with MinLMSetCond(), |
|
|
//| MinLMSetStpMax() and other functions |
|
|
//| 3. User calls MinLMOptimize() function which takes algorithm |
|
|
//| state and pointers (delegates, etc.) to callback functions. |
|
|
//| 4. User calls MinLMResults() to get solution |
|
|
//| 5. Optionally, user may call MinLMRestartFrom() to solve another |
|
|
//| problem with same N but another starting point and/or another |
|
|
//| function. MinLMRestartFrom() allows to reuse already |
|
|
//| initialized structure. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - dimension, N>1 |
|
|
//| * if given, only leading N elements of X are |
|
|
//| used |
|
|
//| * if not given, automatically determined from |
|
|
//| size of X |
|
|
//| X - initial solution, array[0..N-1] |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NOTES: |
|
|
//| 1. you may tune stopping conditions with MinLMSetCond() function |
|
|
//| 2. if target function contains exp() or other fast growing |
|
|
//| functions, and optimization algorithm makes too large steps |
|
|
//| which leads to overflow, use MinLMSetStpMax() function to |
|
|
//| bound algorithm's steps. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMCreateFGH(double &x[],CMinLMStateShell &state)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CMinLM::MinLMCreateFGH(n,x,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets stopping conditions for Levenberg-Marquardt |
|
|
//| optimization algorithm. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| EpsG - >=0 |
|
|
//| The subroutine finishes its work if the |
|
|
//| condition |v|<EpsG is satisfied, where: |
|
|
//| * |.| means Euclidian norm |
|
|
//| * v - scaled gradient vector, v[i]=g[i]*s[i] |
|
|
//| * g - gradient |
|
|
//| * s - scaling coefficients set by MinLMSetScale()|
|
|
//| EpsF - >=0 |
|
|
//| The subroutine finishes its work if on k+1-th |
|
|
//| iteration the condition |F(k+1)-F(k)| <= |
|
|
//| <= EpsF*max{|F(k)|,|F(k+1)|,1} is satisfied. |
|
|
//| EpsX - >=0 |
|
|
//| The subroutine finishes its work if on k+1-th |
|
|
//| iteration the condition |v|<=EpsX is fulfilled, |
|
|
//| where: |
|
|
//| * |.| means Euclidian norm |
|
|
//| * v - scaled step vector, v[i]=dx[i]/s[i] |
|
|
//| * dx - ste pvector, dx=X(k+1)-X(k) |
|
|
//| * s - scaling coefficients set by MinLMSetScale()|
|
|
//| MaxIts - maximum number of iterations. If MaxIts=0, the |
|
|
//| number of iterations is unlimited. Only |
|
|
//| Levenberg-Marquardt iterations are counted |
|
|
//| (L-BFGS/CG iterations are NOT counted because |
|
|
//| their cost is very low compared to that of LM). |
|
|
//| Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will|
|
|
//| lead to automatic stopping criterion selection (small EpsX). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMSetCond(CMinLMStateShell &state,const double epsg,
|
|
const double epsf,const double epsx,
|
|
const int maxits)
|
|
{
|
|
//--- function call
|
|
CMinLM::MinLMSetCond(state.GetInnerObj(),epsg,epsf,epsx,maxits);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function turns on/off reporting. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NeedXRep- whether iteration reports are needed or not |
|
|
//| If NeedXRep is True, algorithm will call rep() callback function |
|
|
//| if it is provided to MinLMOptimize(). Both Levenberg-Marquardt |
|
|
//| and internal L-BFGS iterations are reported. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMSetXRep(CMinLMStateShell &state,const bool needxrep)
|
|
{
|
|
//--- function call
|
|
CMinLM::MinLMSetXRep(state.GetInnerObj(),needxrep);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets maximum step length |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| StpMax - maximum step length, >=0. Set StpMax to 0.0, if |
|
|
//| you don't want to limit step length. |
|
|
//| Use this subroutine when you optimize target function which |
|
|
//| contains exp() or other fast growing functions, and optimization |
|
|
//| algorithm makes too large steps which leads to overflow. This |
|
|
//| function allows us to reject steps that are too large (and |
|
|
//| therefore expose us to the possible overflow) without actually |
|
|
//| calculating function value at the x+stp*d. |
|
|
//| NOTE: non-zero StpMax leads to moderate performance degradation |
|
|
//| because intermediate step of preconditioned L-BFGS optimization |
|
|
//| is incompatible with limits on step size. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMSetStpMax(CMinLMStateShell &state,const double stpmax)
|
|
{
|
|
//--- function call
|
|
CMinLM::MinLMSetStpMax(state.GetInnerObj(),stpmax);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets scaling coefficients for LM optimizer. |
|
|
//| ALGLIB optimizers use scaling matrices to test stopping |
|
|
//| conditions (step size and gradient are scaled before comparison |
|
|
//| with tolerances). Scale of the I-th variable is a translation |
|
|
//| invariant measure of: |
|
|
//| a) "how large" the variable is |
|
|
//| b) how large the step should be to make significant changes in |
|
|
//| the function |
|
|
//| Generally, scale is NOT considered to be a form of |
|
|
//| preconditioner. But LM optimizer is unique in that it uses |
|
|
//| scaling matrix both in the stopping condition tests and as |
|
|
//| Marquardt damping factor. |
|
|
//| Proper scaling is very important for the algorithm performance. |
|
|
//| It is less important for the quality of results, but still has |
|
|
//| some influence (it is easier to converge when variables are |
|
|
//| properly scaled, so premature stopping is possible when very |
|
|
//| badly scalled variables are combined with relaxed stopping |
|
|
//| conditions). |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure stores algorithm state |
|
|
//| S - array[N], non-zero scaling coefficients |
|
|
//| S[i] may be negative, sign doesn't matter. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMSetScale(CMinLMStateShell &state,double &s[])
|
|
{
|
|
//--- function call
|
|
CMinLM::MinLMSetScale(state.GetInnerObj(),s);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets boundary constraints for LM optimizer |
|
|
//| Boundary constraints are inactive by default (after initial |
|
|
//| creation). They are preserved until explicitly turned off with |
|
|
//| another SetBC() call. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure stores algorithm state |
|
|
//| BndL - lower bounds, array[N]. |
|
|
//| If some (all) variables are unbounded, you may |
|
|
//| specify very small number or -INF (latter is |
|
|
//| recommended because it will allow solver to use |
|
|
//| better algorithm). |
|
|
//| BndU - upper bounds, array[N]. |
|
|
//| If some (all) variables are unbounded, you may |
|
|
//| specify very large number or +INF (latter is |
|
|
//| recommended because it will allow solver to use |
|
|
//| better algorithm). |
|
|
//| NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case |
|
|
//| I-th variable will be "frozen" at X[i]=BndL[i]=BndU[i]. |
|
|
//| NOTE 2: this solver has following useful properties: |
|
|
//| * bound constraints are always satisfied exactly |
|
|
//| * function is evaluated only INSIDE area specified by bound |
|
|
//| constraints or at its boundary |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMSetBC(CMinLMStateShell &state,double &bndl[],
|
|
double &bndu[])
|
|
{
|
|
//--- function call
|
|
CMinLM::MinLMSetBC(state.GetInnerObj(),bndl,bndu);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function is used to change acceleration settings |
|
|
//| You can choose between three acceleration strategies: |
|
|
//| * AccType=0, no acceleration. |
|
|
//| * AccType=1, secant updates are used to update quadratic model |
|
|
//| after each iteration. After fixed number of iterations (or |
|
|
//| after model breakdown) we recalculate quadratic model using |
|
|
//| analytic Jacobian or finite differences. Number of secant-based|
|
|
//| iterations depends on optimization settings: about 3 |
|
|
//| iterations - when we have analytic Jacobian, up to 2*N |
|
|
//| iterations - when we use finite differences to calculate |
|
|
//| Jacobian. |
|
|
//| AccType=1 is recommended when Jacobian calculation cost is |
|
|
//| prohibitive high (several Mx1 function vector calculations |
|
|
//| followed by several NxN Cholesky factorizations are faster than |
|
|
//| calculation of one M*N Jacobian). It should also be used when we|
|
|
//| have no Jacobian, because finite difference approximation takes |
|
|
//| too much time to compute. |
|
|
//| Table below list optimization protocols (XYZ protocol corresponds|
|
|
//| to MinLMCreateXYZ) and acceleration types they support (and use |
|
|
//| by default). |
|
|
//| ACCELERATION TYPES SUPPORTED BY OPTIMIZATION PROTOCOLS: |
|
|
//| protocol 0 1 comment |
|
|
//| V + + |
|
|
//| VJ + + |
|
|
//| FGH + |
|
|
//| DAFAULT VALUES: |
|
|
//| protocol 0 1 comment |
|
|
//| V x without acceleration it is so slooooooooow |
|
|
//| VJ x |
|
|
//| FGH x |
|
|
//| NOTE: this function should be called before optimization. |
|
|
//| Attempt to call it during algorithm iterations may result in |
|
|
//| unexpected behavior. |
|
|
//| NOTE: attempt to call this function with unsupported |
|
|
//| protocol/acceleration combination will result in exception being |
|
|
//| thrown. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMSetAccType(CMinLMStateShell &state,const int acctype)
|
|
{
|
|
//--- function call
|
|
CMinLM::MinLMSetAccType(state.GetInnerObj(),acctype);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function provides reverse communication interface |
|
|
//| Reverse communication interface is not documented or recommended |
|
|
//| to use. |
|
|
//| See below for functions which provide better documented API |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::MinLMIteration(CMinLMStateShell &state)
|
|
{
|
|
//--- return result
|
|
return(CMinLM::MinLMIteration(state.GetInnerObj()));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This family of functions is used to launcn iterations of |
|
|
//| nonlinear optimizer |
|
|
//| These functions accept following parameters: |
|
|
//| func - callback which calculates function (or merit |
|
|
//| function) value func at given point x |
|
|
//| grad - callback which calculates function (or merit |
|
|
//| function) value func and gradient grad at given |
|
|
//| point x |
|
|
//| hess - callback which calculates function (or merit |
|
|
//| function) value func, gradient grad and Hessian |
|
|
//| hess at given point x |
|
|
//| fvec - callback which calculates function vector fi[] |
|
|
//| at given point x |
|
|
//| jac - callback which calculates function vector fi[] |
|
|
//| and Jacobian jac at given point x |
|
|
//| rep - optional callback which is called after each |
|
|
//| iteration can be null |
|
|
//| obj - optional object which is passed to |
|
|
//| func/grad/hess/jac/rep can be null |
|
|
//| NOTES: |
|
|
//| 1. Depending on function used to create state structure, this |
|
|
//| algorithm may accept Jacobian and/or Hessian and/or gradient. |
|
|
//| According to the said above, there ase several versions of |
|
|
//| this function, which accept different sets of callbacks. |
|
|
//| This flexibility opens way to subtle errors - you may create |
|
|
//| state with MinLMCreateFGH() (optimization using Hessian), but |
|
|
//| call function which does not accept Hessian. So when |
|
|
//| algorithm will request Hessian, there will be no callback to |
|
|
//| call. In this case exception will be thrown. |
|
|
//| Be careful to avoid such errors because there is no way to |
|
|
//| find them at compile time - you can see them at runtime only. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMOptimize(CMinLMStateShell &state,CNDimensional_FVec &fvec,
|
|
CNDimensional_Rep &rep,bool rep_status,CObject &obj)
|
|
{
|
|
//--- cycle
|
|
while(CAlglib::MinLMIteration(state))
|
|
{
|
|
if(state.GetNeedFI())
|
|
{
|
|
fvec.FVec(state.GetInnerObj().m_x,state.GetInnerObj().m_fi,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetInnerObj().m_xupdated)
|
|
{
|
|
//--- check
|
|
if(rep_status)
|
|
rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
Print("ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This family of functions is used to launcn iterations of |
|
|
//| nonlinear optimizer |
|
|
//| These functions accept following parameters: |
|
|
//| func - callback which calculates function (or merit |
|
|
//| function) value func at given point x |
|
|
//| grad - callback which calculates function (or merit |
|
|
//| function) value func and gradient grad at given |
|
|
//| point x |
|
|
//| hess - callback which calculates function (or merit |
|
|
//| function) value func, gradient grad and Hessian |
|
|
//| hess at given point x |
|
|
//| fvec - callback which calculates function vector fi[] |
|
|
//| at given point x |
|
|
//| jac - callback which calculates function vector fi[] |
|
|
//| and Jacobian jac at given point x |
|
|
//| rep - optional callback which is called after each |
|
|
//| iteration can be null |
|
|
//| obj - optional object which is passed to |
|
|
//| func/grad/hess/jac/rep can be null |
|
|
//| NOTES: |
|
|
//| 1. Depending on function used to create state structure, this |
|
|
//| algorithm may accept Jacobian and/or Hessian and/or gradient. |
|
|
//| According to the said above, there ase several versions of |
|
|
//| this function, which accept different sets of callbacks. |
|
|
//| This flexibility opens way to subtle errors - you may create |
|
|
//| state with MinLMCreateFGH() (optimization using Hessian), but |
|
|
//| call function which does not accept Hessian. So when |
|
|
//| algorithm will request Hessian, there will be no callback to |
|
|
//| call. In this case exception will be thrown. |
|
|
//| Be careful to avoid such errors because there is no way to |
|
|
//| find them at compile time - you can see them at runtime only. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMOptimize(CMinLMStateShell &state,CNDimensional_FVec &fvec,
|
|
CNDimensional_Jac &jac,CNDimensional_Rep &rep,
|
|
bool rep_status,CObject &obj)
|
|
{
|
|
//--- cycle
|
|
while(CAlglib::MinLMIteration(state))
|
|
{
|
|
//--- check
|
|
if(state.GetNeedFI())
|
|
{
|
|
fvec.FVec(state.GetInnerObj().m_x,state.GetInnerObj().m_fi,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetNeedFIJ())
|
|
{
|
|
jac.Jac(state.GetInnerObj().m_x,state.GetInnerObj().m_fi,state.GetInnerObj().m_j,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetInnerObj().m_xupdated)
|
|
{
|
|
//--- check
|
|
if(rep_status)
|
|
rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
Print("ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This family of functions is used to launcn iterations of |
|
|
//| nonlinear optimizer |
|
|
//| These functions accept following parameters: |
|
|
//| func - callback which calculates function (or merit |
|
|
//| function) value func at given point x |
|
|
//| grad - callback which calculates function (or merit |
|
|
//| function) value func and gradient grad at given |
|
|
//| point x |
|
|
//| hess - callback which calculates function (or merit |
|
|
//| function) value func, gradient grad and Hessian |
|
|
//| hess at given point x |
|
|
//| fvec - callback which calculates function vector fi[] |
|
|
//| at given point x |
|
|
//| jac - callback which calculates function vector fi[] |
|
|
//| and Jacobian jac at given point x |
|
|
//| rep - optional callback which is called after each |
|
|
//| iteration can be null |
|
|
//| obj - optional object which is passed to |
|
|
//| func/grad/hess/jac/rep can be null |
|
|
//| NOTES: |
|
|
//| 1. Depending on function used to create state structure, this |
|
|
//| algorithm may accept Jacobian and/or Hessian and/or gradient. |
|
|
//| According to the said above, there ase several versions of |
|
|
//| this function, which accept different sets of callbacks. |
|
|
//| This flexibility opens way to subtle errors - you may create |
|
|
//| state with MinLMCreateFGH() (optimization using Hessian), but |
|
|
//| call function which does not accept Hessian. So when |
|
|
//| algorithm will request Hessian, there will be no callback to |
|
|
//| call. In this case exception will be thrown. |
|
|
//| Be careful to avoid such errors because there is no way to |
|
|
//| find them at compile time - you can see them at runtime only. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMOptimize(CMinLMStateShell &state,CNDimensional_Func &func,
|
|
CNDimensional_Grad &grad,CNDimensional_Hess &hess,
|
|
CNDimensional_Rep &rep,bool rep_status,CObject &obj)
|
|
{
|
|
//--- cycle
|
|
while(CAlglib::MinLMIteration(state))
|
|
{
|
|
//--- check
|
|
if(state.GetNeedF())
|
|
{
|
|
func.Func(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetNeedFG())
|
|
{
|
|
grad.Grad(state.GetInnerObj().m_x,state.GetInnerObj().m_f,state.GetInnerObj().m_g,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetNeedFGH())
|
|
{
|
|
hess.Hess(state.GetInnerObj().m_x,state.GetInnerObj().m_f,state.GetInnerObj().m_g,state.GetInnerObj().m_h,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetInnerObj().m_xupdated)
|
|
{
|
|
//--- check
|
|
if(rep_status)
|
|
rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
Print("ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This family of functions is used to launcn iterations of |
|
|
//| nonlinear optimizer |
|
|
//| These functions accept following parameters: |
|
|
//| func - callback which calculates function (or merit |
|
|
//| function) value func at given point x |
|
|
//| grad - callback which calculates function (or merit |
|
|
//| function) value func and gradient grad at given |
|
|
//| point x |
|
|
//| hess - callback which calculates function (or merit |
|
|
//| function) value func, gradient grad and Hessian |
|
|
//| hess at given point x |
|
|
//| fvec - callback which calculates function vector fi[] |
|
|
//| at given point x |
|
|
//| jac - callback which calculates function vector fi[] |
|
|
//| and Jacobian jac at given point x |
|
|
//| rep - optional callback which is called after each |
|
|
//| iteration can be null |
|
|
//| obj - optional object which is passed to |
|
|
//| func/grad/hess/jac/rep can be null |
|
|
//| NOTES: |
|
|
//| 1. Depending on function used to create state structure, this |
|
|
//| algorithm may accept Jacobian and/or Hessian and/or gradient. |
|
|
//| According to the said above, there ase several versions of |
|
|
//| this function, which accept different sets of callbacks. |
|
|
//| This flexibility opens way to subtle errors - you may create |
|
|
//| state with MinLMCreateFGH() (optimization using Hessian), but |
|
|
//| call function which does not accept Hessian. So when |
|
|
//| algorithm will request Hessian, there will be no callback to |
|
|
//| call. In this case exception will be thrown. |
|
|
//| Be careful to avoid such errors because there is no way to |
|
|
//| find them at compile time - you can see them at runtime only. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMOptimize(CMinLMStateShell &state,CNDimensional_Func &func,
|
|
CNDimensional_Jac &jac,CNDimensional_Rep &rep,
|
|
bool rep_status,CObject &obj)
|
|
{
|
|
//--- cycle
|
|
while(CAlglib::MinLMIteration(state))
|
|
{
|
|
//--- check
|
|
if(state.GetNeedF())
|
|
{
|
|
func.Func(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetNeedFIJ())
|
|
{
|
|
jac.Jac(state.GetInnerObj().m_x,state.GetInnerObj().m_fi,state.GetInnerObj().m_j,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetInnerObj().m_xupdated)
|
|
{
|
|
//--- check
|
|
if(rep_status)
|
|
rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
Print("ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This family of functions is used to launcn iterations of |
|
|
//| nonlinear optimizer |
|
|
//| These functions accept following parameters: |
|
|
//| func - callback which calculates function (or merit |
|
|
//| function) value func at given point x |
|
|
//| grad - callback which calculates function (or merit |
|
|
//| function) value func and gradient grad at given |
|
|
//| point x |
|
|
//| hess - callback which calculates function (or merit |
|
|
//| function) value func, gradient grad and Hessian |
|
|
//| hess at given point x |
|
|
//| fvec - callback which calculates function vector fi[] |
|
|
//| at given point x |
|
|
//| jac - callback which calculates function vector fi[] |
|
|
//| and Jacobian jac at given point x |
|
|
//| rep - optional callback which is called after each |
|
|
//| iteration can be null |
|
|
//| obj - optional object which is passed to |
|
|
//| func/grad/hess/jac/rep can be null |
|
|
//| NOTES: |
|
|
//| 1. Depending on function used to create state structure, this |
|
|
//| algorithm may accept Jacobian and/or Hessian and/or gradient. |
|
|
//| According to the said above, there ase several versions of |
|
|
//| this function, which accept different sets of callbacks. |
|
|
//| This flexibility opens way to subtle errors - you may create |
|
|
//| state with MinLMCreateFGH() (optimization using Hessian), but |
|
|
//| call function which does not accept Hessian. So when |
|
|
//| algorithm will request Hessian, there will be no callback to |
|
|
//| call. In this case exception will be thrown. |
|
|
//| Be careful to avoid such errors because there is no way to |
|
|
//| find them at compile time - you can see them at runtime only. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMOptimize(CMinLMStateShell &state,CNDimensional_Func &func,
|
|
CNDimensional_Grad &grad,CNDimensional_Jac &jac,
|
|
CNDimensional_Rep &rep,bool rep_status,CObject &obj)
|
|
{
|
|
//--- cycle
|
|
while(CAlglib::MinLMIteration(state))
|
|
{
|
|
//--- check
|
|
if(state.GetNeedF())
|
|
{
|
|
func.Func(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetNeedFG())
|
|
{
|
|
grad.Grad(state.GetInnerObj().m_x,state.GetInnerObj().m_f,state.GetInnerObj().m_g,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetNeedFIJ())
|
|
{
|
|
jac.Jac(state.GetInnerObj().m_x,state.GetInnerObj().m_fi,state.GetInnerObj().m_j,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetInnerObj().m_xupdated)
|
|
{
|
|
//--- check
|
|
if(rep_status)
|
|
rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
Print("ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Levenberg-Marquardt algorithm results |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - algorithm state |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| X - array[0..N-1], solution |
|
|
//| Rep - optimization report; |
|
|
//| see comments for this structure for more info. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMResults(CMinLMStateShell &state,double &x[],
|
|
CMinLMReportShell &rep)
|
|
{
|
|
//--- function call
|
|
CMinLM::MinLMResults(state.GetInnerObj(),x,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Levenberg-Marquardt algorithm results |
|
|
//| Buffered implementation of MinLMResults(), which uses |
|
|
//| pre-allocated buffer to store X[]. If buffer size is too small, |
|
|
//| it resizes buffer. It is intended to be used in the inner cycles |
|
|
//| of performance critical algorithms where array reallocation |
|
|
//| penalty is too large to be ignored. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMResultsBuf(CMinLMStateShell &state,double &x[],
|
|
CMinLMReportShell &rep)
|
|
{
|
|
//--- function call
|
|
CMinLM::MinLMResultsBuf(state.GetInnerObj(),x,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine restarts LM algorithm from new point. All |
|
|
//| optimization parameters are left unchanged. |
|
|
//| This function allows to solve multiple optimization problems |
|
|
//| (which must have same number of dimensions) without object |
|
|
//| reallocation penalty. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure used for reverse communication |
|
|
//| previously allocated with MinLMCreateXXX call. |
|
|
//| X - new starting point. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMRestartFrom(CMinLMStateShell &state,double &x[])
|
|
{
|
|
//--- function call
|
|
CMinLM::MinLMRestartFrom(state.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This is obsolete function. |
|
|
//| Since ALGLIB 3.3 it is equivalent to MinLMCreateVJ(). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMCreateVGJ(const int n,const int m,double &x[],
|
|
CMinLMStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinLM::MinLMCreateVGJ(n,m,x,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This is obsolete function. |
|
|
//| Since ALGLIB 3.3 it is equivalent to MinLMCreateVJ(). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMCreateVGJ(const int m,double &x[],CMinLMStateShell &state)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CMinLM::MinLMCreateVGJ(n,m,x,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This is obsolete function. |
|
|
//| Since ALGLIB 3.3 it is equivalent to MinLMCreateFJ(). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMCreateFGJ(const int n,const int m,double &x[],
|
|
CMinLMStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinLM::MinLMCreateFGJ(n,m,x,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This is obsolete function. |
|
|
//| Since ALGLIB 3.3 it is equivalent to MinLMCreateFJ(). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMCreateFGJ(const int m,double &x[],CMinLMStateShell &state)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CMinLM::MinLMCreateFGJ(n,m,x,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function is considered obsolete since ALGLIB 3.1.0 and is |
|
|
//| present for backward compatibility only. We recommend to use |
|
|
//| MinLMCreateVJ, which provides similar, but more consistent and |
|
|
//| feature-rich interface. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMCreateFJ(const int n,const int m,double &x[],
|
|
CMinLMStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinLM::MinLMCreateFJ(n,m,x,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function is considered obsolete since ALGLIB 3.1.0 and is |
|
|
//| present for backward compatibility only. We recommend to use |
|
|
//| MinLMCreateVJ, which provides similar, but more consistent and |
|
|
//| feature-rich interface. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLMCreateFJ(const int m,double &x[],CMinLMStateShell &state)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CMinLM::MinLMCreateFJ(n,m,x,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Obsolete function, use MinLBFGSSetPrecDefault() instead. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLBFGSSetDefaultPreconditioner(CMinLBFGSStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinComp::MinLBFGSSetDefaultPreconditioner(state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Obsolete function, use MinLBFGSSetCholeskyPreconditioner() |
|
|
//| instead. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinLBFGSSetCholeskyPreconditioner(CMinLBFGSStateShell &state,
|
|
CMatrixDouble &p,bool isupper)
|
|
{
|
|
//--- function call
|
|
CMinComp::MinLBFGSSetCholeskyPreconditioner(state.GetInnerObj(),p,isupper);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This is obsolete function which was used by previous version of |
|
|
//| the BLEIC optimizer. It does nothing in the current version of |
|
|
//| BLEIC. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICSetBarrierWidth(CMinBLEICStateShell &state,
|
|
const double mu)
|
|
{
|
|
//--- function call
|
|
CMinComp::MinBLEICSetBarrierWidth(state.GetInnerObj(),mu);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This is obsolete function which was used by previous version of |
|
|
//| the BLEIC optimizer. It does nothing in the current version of |
|
|
//| BLEIC. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinBLEICSetBarrierDecay(CMinBLEICStateShell &state,
|
|
const double mudecay)
|
|
{
|
|
//--- function call
|
|
CMinComp::MinBLEICSetBarrierDecay(state.GetInnerObj(),mudecay);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Obsolete optimization algorithm. |
|
|
//| Was replaced by MinBLEIC subpackage. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinASACreate(const int n,double &x[],double &bndl[],
|
|
double &bndu[],CMinASAStateShell &state)
|
|
{
|
|
//--- function call
|
|
CMinComp::MinASACreate(n,x,bndl,bndu,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Obsolete optimization algorithm. |
|
|
//| Was replaced by MinBLEIC subpackage. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinASACreate(double &x[],double &bndl[],double &bndu[],
|
|
CMinASAStateShell &state)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- check
|
|
if((CAp::Len(x)!=CAp::Len(bndl)) || (CAp::Len(x)!=CAp::Len(bndu)))
|
|
{
|
|
Print("Error while calling 'minasacreate': looks like one of arguments has wrong size");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CMinComp::MinASACreate(n,x,bndl,bndu,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Obsolete optimization algorithm. |
|
|
//| Was replaced by MinBLEIC subpackage. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinASASetCond(CMinASAStateShell &state,const double epsg,
|
|
const double epsf,const double epsx,const int maxits)
|
|
{
|
|
//--- function call
|
|
CMinComp::MinASASetCond(state.GetInnerObj(),epsg,epsf,epsx,maxits);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Obsolete optimization algorithm. |
|
|
//| Was replaced by MinBLEIC subpackage. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinASASetXRep(CMinASAStateShell &state,const bool needxrep)
|
|
{
|
|
//--- function call
|
|
CMinComp::MinASASetXRep(state.GetInnerObj(),needxrep);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Obsolete optimization algorithm. |
|
|
//| Was replaced by MinBLEIC subpackage. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinASASetAlgorithm(CMinASAStateShell &state,const int algotype)
|
|
{
|
|
//--- function call
|
|
CMinComp::MinASASetAlgorithm(state.GetInnerObj(),algotype);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Obsolete optimization algorithm. |
|
|
//| Was replaced by MinBLEIC subpackage. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinASASetStpMax(CMinASAStateShell &state,const double stpmax)
|
|
{
|
|
//--- function call
|
|
CMinComp::MinASASetStpMax(state.GetInnerObj(),stpmax);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function provides reverse communication interface |
|
|
//| Reverse communication interface is not documented or recommended |
|
|
//| to use. |
|
|
//| See below for functions which provide better documented API |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::MinASAIteration(CMinASAStateShell &state)
|
|
{
|
|
//--- return result
|
|
return(CMinComp::MinASAIteration(state.GetInnerObj()));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This family of functions is used to launcn iterations of |
|
|
//| nonlinear optimizer |
|
|
//| These functions accept following parameters: |
|
|
//| grad - callback which calculates function (or merit |
|
|
//| function) value func and gradient grad at given |
|
|
//| point x |
|
|
//| rep - optional callback which is called after each |
|
|
//| iteration can be null |
|
|
//| obj - optional object which is passed to |
|
|
//| func/grad/hess/jac/rep can be null |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinASAOptimize(CMinASAStateShell &state,CNDimensional_Grad &grad,
|
|
CNDimensional_Rep &rep,bool rep_status,CObject &obj)
|
|
{
|
|
//--- cycle
|
|
while(CAlglib::MinASAIteration(state))
|
|
{
|
|
//--- check
|
|
if(state.GetNeedFG())
|
|
{
|
|
grad.Grad(state.GetInnerObj().m_x,state.GetInnerObj().m_f,state.GetInnerObj().m_g,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetInnerObj().m_xupdated)
|
|
{
|
|
//--- check
|
|
if(rep_status)
|
|
rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
Print("ALGLIB: error in 'minasaoptimize' (some derivatives were not provided?)");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Obsolete optimization algorithm. |
|
|
//| Was replaced by MinBLEIC subpackage. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinASAResults(CMinASAStateShell &state,double &x[],
|
|
CMinASAReportShell &rep)
|
|
{
|
|
//--- function call
|
|
CMinComp::MinASAResults(state.GetInnerObj(),x,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Obsolete optimization algorithm. |
|
|
//| Was replaced by MinBLEIC subpackage. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinASAResultsBuf(CMinASAStateShell &state,double &x[],
|
|
CMinASAReportShell &rep)
|
|
{
|
|
//--- function call
|
|
CMinComp::MinASAResultsBuf(state.GetInnerObj(),x,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Obsolete optimization algorithm. |
|
|
//| Was replaced by MinBLEIC subpackage. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MinASARestartFrom(CMinASAStateShell &state,double &x[],
|
|
double &bndl[],double &bndu[])
|
|
{
|
|
//--- function call
|
|
CMinComp::MinASARestartFrom(state.GetInnerObj(),x,bndl,bndu);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Dense solver. |
|
|
//| This subroutine solves a system A*x=b, where A is NxN |
|
|
//| non-denegerate real matrix, x and b are vectors. |
|
|
//| Algorithm features: |
|
|
//| * automatic detection of degenerate cases |
|
|
//| * condition number estimation |
|
|
//| * iterative refinement |
|
|
//| * O(N^3) complexity |
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..N-1,0..N-1], system matrix |
|
|
//| N - size of A |
|
|
//| B - array[0..N-1], right part |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Info - return code: |
|
|
//| * -3 A is singular, or VERY close to singular.|
|
|
//| X is filled by zeros in such cases. |
|
|
//| * -1 N<=0 was passed |
|
|
//| * 1 task is solved (but matrix A may be |
|
|
//| ill-conditioned, check R1/RInf parameters|
|
|
//| for condition numbers). |
|
|
//| Rep - solver report, see below for more info |
|
|
//| X - array[0..N-1], it contains: |
|
|
//| * solution of A*x=b if A is non-singular |
|
|
//| (well-conditioned or ill-conditioned, but not |
|
|
//| very close to singular) |
|
|
//| * zeros, if A is singular or VERY close to |
|
|
//| singular (in this case Info=-3). |
|
|
//| SOLVER REPORT |
|
|
//| Subroutine sets following fields of the Rep structure: |
|
|
//| * R1 reciprocal of condition number: 1/cond(A), 1-norm. |
|
|
//| * RInf reciprocal of condition number: 1/cond(A), inf-norm. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixSolve(CMatrixDouble &a,const int n,double &b[],
|
|
int &info,CDenseSolverReportShell &rep,
|
|
double &x[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDenseSolver::RMatrixSolve(a,n,b,info,rep.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Dense solver. |
|
|
//| Similar to RMatrixSolve() but solves task with multiple right |
|
|
//| parts (where b and x are NxM matrices). |
|
|
//| Algorithm features: |
|
|
//| * automatic detection of degenerate cases |
|
|
//| * condition number estimation |
|
|
//| * optional iterative refinement |
|
|
//| * O(N^3+M*N^2) complexity |
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..N-1,0..N-1], system matrix |
|
|
//| N - size of A |
|
|
//| B - array[0..N-1,0..M-1], right part |
|
|
//| M - right part size |
|
|
//| RFS - iterative refinement switch: |
|
|
//| * True - refinement is used. |
|
|
//| Less performance, more precision. |
|
|
//| * False - refinement is not used. |
|
|
//| More performance, less precision. |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Info - same as in RMatrixSolve |
|
|
//| Rep - same as in RMatrixSolve |
|
|
//| X - same as in RMatrixSolve |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixSolveM(CMatrixDouble &a,const int n,CMatrixDouble &b,
|
|
const int m,const bool rfs,int &info,
|
|
CDenseSolverReportShell &rep,CMatrixDouble &x)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDenseSolver::RMatrixSolveM(a,n,b,m,rfs,info,rep.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Dense solver. |
|
|
//| This subroutine solves a system A*X=B, where A is NxN |
|
|
//| non-denegerate real matrix given by its LU decomposition, X and |
|
|
//| B are NxM real matrices. |
|
|
//| Algorithm features: |
|
|
//| * automatic detection of degenerate cases |
|
|
//| * O(N^2) complexity |
|
|
//| * condition number estimation |
|
|
//| No iterative refinement is provided because exact form of |
|
|
//| original matrix is not known to subroutine. Use RMatrixSolve or |
|
|
//| RMatrixMixedSolve if you need iterative refinement. |
|
|
//| INPUT PARAMETERS |
|
|
//| LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU|
|
|
//| result |
|
|
//| P - array[0..N-1], pivots array, RMatrixLU result |
|
|
//| N - size of A |
|
|
//| B - array[0..N-1], right part |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Info - same as in RMatrixSolve |
|
|
//| Rep - same as in RMatrixSolve |
|
|
//| X - same as in RMatrixSolve |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixLUSolve(CMatrixDouble &lua,int &p[],const int n,
|
|
double &b[],int &info,
|
|
CDenseSolverReportShell &rep,double &x[])
|
|
{//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDenseSolver::RMatrixLUSolve(lua,p,n,b,info,rep.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Dense solver. |
|
|
//| Similar to RMatrixLUSolve() but solves task with multiple right |
|
|
//| parts (where b and x are NxM matrices). |
|
|
//| Algorithm features: |
|
|
//| * automatic detection of degenerate cases |
|
|
//| * O(M*N^2) complexity |
|
|
//| * condition number estimation |
|
|
//| No iterative refinement is provided because exact form of |
|
|
//| original matrix is not known to subroutine. Use RMatrixSolve or |
|
|
//| RMatrixMixedSolve if you need iterative refinement. |
|
|
//| INPUT PARAMETERS |
|
|
//| LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU|
|
|
//| result |
|
|
//| P - array[0..N-1], pivots array, RMatrixLU result |
|
|
//| N - size of A |
|
|
//| B - array[0..N-1,0..M-1], right part |
|
|
//| M - right part size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Info - same as in RMatrixSolve |
|
|
//| Rep - same as in RMatrixSolve |
|
|
//| X - same as in RMatrixSolve |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixLUSolveM(CMatrixDouble &lua,int &p[],const int n,
|
|
CMatrixDouble &b,const int m,int &info,
|
|
CDenseSolverReportShell &rep,CMatrixDouble &x)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDenseSolver::RMatrixLUSolveM(lua,p,n,b,m,info,rep.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Dense solver. |
|
|
//| This subroutine solves a system A*x=b, where BOTH ORIGINAL A AND |
|
|
//| ITS LU DECOMPOSITION ARE KNOWN. You can use it if for some |
|
|
//| reasons you have both A and its LU decomposition. |
|
|
//| Algorithm features: |
|
|
//| * automatic detection of degenerate cases |
|
|
//| * condition number estimation |
|
|
//| * iterative refinement |
|
|
//| * O(N^2) complexity |
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..N-1,0..N-1], system matrix |
|
|
//| LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU|
|
|
//| result |
|
|
//| P - array[0..N-1], pivots array, RMatrixLU result |
|
|
//| N - size of A |
|
|
//| B - array[0..N-1], right part |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Info - same as in RMatrixSolveM |
|
|
//| Rep - same as in RMatrixSolveM |
|
|
//| X - same as in RMatrixSolveM |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixMixedSolve(CMatrixDouble &a,CMatrixDouble &lua,
|
|
int &p[],const int n,double &b[],
|
|
int &info,CDenseSolverReportShell &rep,
|
|
double &x[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDenseSolver::RMatrixMixedSolve(a,lua,p,n,b,info,rep.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Dense solver. |
|
|
//| Similar to RMatrixMixedSolve() but solves task with multiple |
|
|
//| right parts (where b and x are NxM matrices). |
|
|
//| Algorithm features: |
|
|
//| * automatic detection of degenerate cases |
|
|
//| * condition number estimation |
|
|
//| * iterative refinement |
|
|
//| * O(M*N^2) complexity |
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..N-1,0..N-1], system matrix |
|
|
//| LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU|
|
|
//| result |
|
|
//| P - array[0..N-1], pivots array, RMatrixLU result |
|
|
//| N - size of A |
|
|
//| B - array[0..N-1,0..M-1], right part |
|
|
//| M - right part size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Info - same as in RMatrixSolveM |
|
|
//| Rep - same as in RMatrixSolveM |
|
|
//| X - same as in RMatrixSolveM |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixMixedSolveM(CMatrixDouble &a,CMatrixDouble &lua,
|
|
int &p[],const int n,CMatrixDouble &b,
|
|
const int m,int &info,
|
|
CDenseSolverReportShell &rep,
|
|
CMatrixDouble &x)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDenseSolver::RMatrixMixedSolveM(a,lua,p,n,b,m,info,rep.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Dense solver. Same as RMatrixSolveM(), but for complex matrices. |
|
|
//| Algorithm features: |
|
|
//| * automatic detection of degenerate cases |
|
|
//| * condition number estimation |
|
|
//| * iterative refinement |
|
|
//| * O(N^3+M*N^2) complexity |
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..N-1,0..N-1], system matrix |
|
|
//| N - size of A |
|
|
//| B - array[0..N-1,0..M-1], right part |
|
|
//| M - right part size |
|
|
//| RFS - iterative refinement switch: |
|
|
//| * True - refinement is used. |
|
|
//| Less performance, more precision. |
|
|
//| * False - refinement is not used. |
|
|
//| More performance, less precision. |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Info - same as in RMatrixSolve |
|
|
//| Rep - same as in RMatrixSolve |
|
|
//| X - same as in RMatrixSolve |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixSolveM(CMatrixComplex &a,const int n,CMatrixComplex &b,
|
|
const int m,const bool rfs,int &info,
|
|
CDenseSolverReportShell &rep,
|
|
CMatrixComplex &x)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDenseSolver::CMatrixSolveM(a,n,b,m,rfs,info,rep.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Dense solver. Same as RMatrixSolve(), but for complex matrices. |
|
|
//| Algorithm features: |
|
|
//| * automatic detection of degenerate cases |
|
|
//| * condition number estimation |
|
|
//| * iterative refinement |
|
|
//| * O(N^3) complexity |
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..N-1,0..N-1], system matrix |
|
|
//| N - size of A |
|
|
//| B - array[0..N-1], right part |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Info - same as in RMatrixSolve |
|
|
//| Rep - same as in RMatrixSolve |
|
|
//| X - same as in RMatrixSolve |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixSolve(CMatrixComplex &a,const int n,complex &b[],
|
|
int &info,CDenseSolverReportShell &rep,
|
|
complex &x[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDenseSolver::CMatrixSolve(a,n,b,info,rep.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Dense solver. Same as RMatrixLUSolveM(), but for complex |
|
|
//| matrices. |
|
|
//| Algorithm features: |
|
|
//| * automatic detection of degenerate cases |
|
|
//| * O(M*N^2) complexity |
|
|
//| * condition number estimation |
|
|
//| No iterative refinement is provided because exact form of |
|
|
//| original matrix is not known to subroutine. Use CMatrixSolve or |
|
|
//| CMatrixMixedSolve if you need iterative refinement. |
|
|
//| INPUT PARAMETERS |
|
|
//| LUA - array[0..N-1,0..N-1], LU decomposition, RMatrixLU|
|
|
//| result |
|
|
//| P - array[0..N-1], pivots array, RMatrixLU result |
|
|
//| N - size of A |
|
|
//| B - array[0..N-1,0..M-1], right part |
|
|
//| M - right part size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Info - same as in RMatrixSolve |
|
|
//| Rep - same as in RMatrixSolve |
|
|
//| X - same as in RMatrixSolve |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixLUSolveM(CMatrixComplex &lua,int &p[],const int n,
|
|
CMatrixComplex &b,const int m,int &info,
|
|
CDenseSolverReportShell &rep,CMatrixComplex &x)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDenseSolver::CMatrixLUSolveM(lua,p,n,b,m,info,rep.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Dense solver. Same as RMatrixLUSolve(), but for complex matrices.|
|
|
//| Algorithm features: |
|
|
//| * automatic detection of degenerate cases |
|
|
//| * O(N^2) complexity |
|
|
//| * condition number estimation |
|
|
//| No iterative refinement is provided because exact form of |
|
|
//| original matrix is not known to subroutine. Use CMatrixSolve or |
|
|
//| CMatrixMixedSolve if you need iterative refinement. |
|
|
//| INPUT PARAMETERS |
|
|
//| LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU|
|
|
//| result |
|
|
//| P - array[0..N-1], pivots array, CMatrixLU result |
|
|
//| N - size of A |
|
|
//| B - array[0..N-1], right part |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Info - same as in RMatrixSolve |
|
|
//| Rep - same as in RMatrixSolve |
|
|
//| X - same as in RMatrixSolve |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixLUSolve(CMatrixComplex &lua,int &p[],const int n,
|
|
complex &b[],int &info,CDenseSolverReportShell &rep,
|
|
complex &x[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDenseSolver::CMatrixLUSolve(lua,p,n,b,info,rep.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Dense solver. Same as RMatrixMixedSolveM(), but for complex |
|
|
//| matrices. |
|
|
//| Algorithm features: |
|
|
//| * automatic detection of degenerate cases |
|
|
//| * condition number estimation |
|
|
//| * iterative refinement |
|
|
//| * O(M*N^2) complexity |
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..N-1,0..N-1], system matrix |
|
|
//| LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU|
|
|
//| result |
|
|
//| P - array[0..N-1], pivots array, CMatrixLU result |
|
|
//| N - size of A |
|
|
//| B - array[0..N-1,0..M-1], right part |
|
|
//| M - right part size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Info - same as in RMatrixSolveM |
|
|
//| Rep - same as in RMatrixSolveM |
|
|
//| X - same as in RMatrixSolveM |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixMixedSolveM(CMatrixComplex &a,CMatrixComplex &lua,
|
|
int &p[],const int n,CMatrixComplex &b,
|
|
const int m,int &info,
|
|
CDenseSolverReportShell &rep,
|
|
CMatrixComplex &x)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDenseSolver::CMatrixMixedSolveM(a,lua,p,n,b,m,info,rep.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Dense solver. Same as RMatrixMixedSolve(), but for complex |
|
|
//| matrices. |
|
|
//| Algorithm features: |
|
|
//| * automatic detection of degenerate cases |
|
|
//| * condition number estimation |
|
|
//| * iterative refinement |
|
|
//| * O(N^2) complexity |
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..N-1,0..N-1], system matrix |
|
|
//| LUA - array[0..N-1,0..N-1], LU decomposition, CMatrixLU|
|
|
//| result |
|
|
//| P - array[0..N-1], pivots array, CMatrixLU result |
|
|
//| N - size of A |
|
|
//| B - array[0..N-1], right part |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Info - same as in RMatrixSolveM |
|
|
//| Rep - same as in RMatrixSolveM |
|
|
//| X - same as in RMatrixSolveM |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CMatrixMixedSolve(CMatrixComplex &a,CMatrixComplex &lua,
|
|
int &p[],const int n,complex &b[],
|
|
int &info,CDenseSolverReportShell &rep,
|
|
complex &x[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDenseSolver::CMatrixMixedSolve(a,lua,p,n,b,info,rep.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Dense solver. Same as RMatrixSolveM(), but for symmetric positive|
|
|
//| definite matrices. |
|
|
//| Algorithm features: |
|
|
//| * automatic detection of degenerate cases |
|
|
//| * condition number estimation |
|
|
//| * O(N^3+M*N^2) complexity |
|
|
//| * matrix is represented by its upper or lower triangle |
|
|
//| No iterative refinement is provided because such partial |
|
|
//| representation of matrix does not allow efficient calculation of |
|
|
//| extra-precise matrix-vector products for large matrices. Use |
|
|
//| RMatrixSolve or RMatrixMixedSolve if you need iterative |
|
|
//| refinement. |
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..N-1,0..N-1], system matrix |
|
|
//| N - size of A |
|
|
//| IsUpper - what half of A is provided |
|
|
//| B - array[0..N-1,0..M-1], right part |
|
|
//| M - right part size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Info - same as in RMatrixSolve. |
|
|
//| Returns -3 for non-SPD matrices. |
|
|
//| Rep - same as in RMatrixSolve |
|
|
//| X - same as in RMatrixSolve |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SPDMatrixSolveM(CMatrixDouble &a,const int n,const bool isupper,
|
|
CMatrixDouble &b,const int m,int &info,
|
|
CDenseSolverReportShell &rep,CMatrixDouble &x)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDenseSolver::SPDMatrixSolveM(a,n,isupper,b,m,info,rep.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Dense solver. Same as RMatrixSolve(), but for SPD matrices. |
|
|
//| Algorithm features: |
|
|
//| * automatic detection of degenerate cases |
|
|
//| * condition number estimation |
|
|
//| * O(N^3) complexity |
|
|
//| * matrix is represented by its upper or lower triangle |
|
|
//| No iterative refinement is provided because such partial |
|
|
//| representation of matrix does not allow efficient calculation of |
|
|
//| extra-precise matrix-vector products for large matrices. Use |
|
|
//| RMatrixSolve or RMatrixMixedSolve if you need iterative |
|
|
//| refinement. |
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..N-1,0..N-1], system matrix |
|
|
//| N - size of A |
|
|
//| IsUpper - what half of A is provided |
|
|
//| B - array[0..N-1], right part |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Info - same as in RMatrixSolve |
|
|
//| Returns -3 for non-SPD matrices. |
|
|
//| Rep - same as in RMatrixSolve |
|
|
//| X - same as in RMatrixSolve |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SPDMatrixSolve(CMatrixDouble &a,const int n,const bool isupper,
|
|
double &b[],int &info,CDenseSolverReportShell &rep,
|
|
double &x[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDenseSolver::SPDMatrixSolve(a,n,isupper,b,info,rep.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Dense solver. Same as RMatrixLUSolveM(), but for SPD matrices |
|
|
//| represented by their Cholesky decomposition. |
|
|
//| Algorithm features: |
|
|
//| * automatic detection of degenerate cases |
|
|
//| * O(M*N^2) complexity |
|
|
//| * condition number estimation |
|
|
//| * matrix is represented by its upper or lower triangle |
|
|
//| No iterative refinement is provided because such partial |
|
|
//| representation of matrix does not allow efficient calculation of |
|
|
//| extra-precise matrix-vector products for large matrices. Use |
|
|
//| RMatrixSolve or RMatrixMixedSolve if you need iterative |
|
|
//| refinement. |
|
|
//| INPUT PARAMETERS |
|
|
//| CHA - array[0..N-1,0..N-1], Cholesky decomposition, |
|
|
//| SPDMatrixCholesky result |
|
|
//| N - size of CHA |
|
|
//| IsUpper - what half of CHA is provided |
|
|
//| B - array[0..N-1,0..M-1], right part |
|
|
//| M - right part size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Info - same as in RMatrixSolve |
|
|
//| Rep - same as in RMatrixSolve |
|
|
//| X - same as in RMatrixSolve |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SPDMatrixCholeskySolveM(CMatrixDouble &cha,const int n,
|
|
const bool isupper,CMatrixDouble &b,
|
|
const int m,int &info,
|
|
CDenseSolverReportShell &rep,
|
|
CMatrixDouble &x)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDenseSolver::SPDMatrixCholeskySolveM(cha,n,isupper,b,m,info,rep.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Dense solver. Same as RMatrixLUSolve(), but for SPD matrices |
|
|
//| represented by their Cholesky decomposition. |
|
|
//| Algorithm features: |
|
|
//| * automatic detection of degenerate cases |
|
|
//| * O(N^2) complexity |
|
|
//| * condition number estimation |
|
|
//| * matrix is represented by its upper or lower triangle |
|
|
//| No iterative refinement is provided because such partial |
|
|
//| representation of matrix does not allow efficient calculation of |
|
|
//| extra-precise matrix-vector products for large matrices. Use |
|
|
//| RMatrixSolve or RMatrixMixedSolve if you need iterative |
|
|
//| refinement. |
|
|
//| INPUT PARAMETERS |
|
|
//| CHA - array[0..N-1,0..N-1], Cholesky decomposition, |
|
|
//| SPDMatrixCholesky result |
|
|
//| N - size of A |
|
|
//| IsUpper - what half of CHA is provided |
|
|
//| B - array[0..N-1], right part |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Info - same as in RMatrixSolve |
|
|
//| Rep - same as in RMatrixSolve |
|
|
//| X - same as in RMatrixSolve |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SPDMatrixCholeskySolve(CMatrixDouble &cha,const int n,
|
|
const bool isupper,double &b[],
|
|
int &info,CDenseSolverReportShell &rep,
|
|
double &x[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDenseSolver::SPDMatrixCholeskySolve(cha,n,isupper,b,info,rep.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Dense solver. Same as RMatrixSolveM(), but for Hermitian positive|
|
|
//| definite matrices. |
|
|
//| Algorithm features: |
|
|
//| * automatic detection of degenerate cases |
|
|
//| * condition number estimation |
|
|
//| * O(N^3+M*N^2) complexity |
|
|
//| * matrix is represented by its upper or lower triangle |
|
|
//| No iterative refinement is provided because such partial |
|
|
//| representation of matrix does not allow efficient calculation of |
|
|
//| extra-precise matrix-vector products for large matrices. Use |
|
|
//| RMatrixSolve or RMatrixMixedSolve if you need iterative |
|
|
//| refinement. |
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..N-1,0..N-1], system matrix |
|
|
//| N - size of A |
|
|
//| IsUpper - what half of A is provided |
|
|
//| B - array[0..N-1,0..M-1], right part |
|
|
//| M - right part size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Info - same as in RMatrixSolve. |
|
|
//| Returns -3 for non-HPD matrices. |
|
|
//| Rep - same as in RMatrixSolve |
|
|
//| X - same as in RMatrixSolve |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::HPDMatrixSolveM(CMatrixComplex &a,const int n,const bool isupper,
|
|
CMatrixComplex &b,const int m,int &info,
|
|
CDenseSolverReportShell &rep,CMatrixComplex &x)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDenseSolver::HPDMatrixSolveM(a,n,isupper,b,m,info,rep.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Dense solver. Same as RMatrixSolve(), but for Hermitian positive |
|
|
//| definite matrices. |
|
|
//| Algorithm features: |
|
|
//| * automatic detection of degenerate cases |
|
|
//| * condition number estimation |
|
|
//| * O(N^3) complexity |
|
|
//| * matrix is represented by its upper or lower triangle |
|
|
//| No iterative refinement is provided because such partial |
|
|
//| representation of matrix does not allow efficient calculation of |
|
|
//| extra-precise matrix-vector products for large matrices. Use |
|
|
//| RMatrixSolve or RMatrixMixedSolve if you need iterative |
|
|
//| refinement. |
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..N-1,0..N-1], system matrix |
|
|
//| N - size of A |
|
|
//| IsUpper - what half of A is provided |
|
|
//| B - array[0..N-1], right part |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Info - same as in RMatrixSolve |
|
|
//| Returns -3 for non-HPD matrices. |
|
|
//| Rep - same as in RMatrixSolve |
|
|
//| X - same as in RMatrixSolve |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::HPDMatrixSolve(CMatrixComplex &a,const int n,
|
|
const bool isupper,complex &b[],
|
|
int &info,CDenseSolverReportShell &rep,
|
|
complex &x[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDenseSolver::HPDMatrixSolve(a,n,isupper,b,info,rep.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Dense solver. Same as RMatrixLUSolveM(), but for HPD matrices |
|
|
//| represented by their Cholesky decomposition. |
|
|
//| Algorithm features: |
|
|
//| * automatic detection of degenerate cases |
|
|
//| * O(M*N^2) complexity |
|
|
//| * condition number estimation |
|
|
//| * matrix is represented by its upper or lower triangle |
|
|
//| No iterative refinement is provided because such partial |
|
|
//| representation of matrix does not allow efficient calculation of |
|
|
//| extra-precise matrix-vector products for large matrices. Use |
|
|
//| RMatrixSolve or RMatrixMixedSolve if you need iterative |
|
|
//| refinement. |
|
|
//| INPUT PARAMETERS |
|
|
//| CHA - array[0..N-1,0..N-1], Cholesky decomposition, |
|
|
//| HPDMatrixCholesky result |
|
|
//| N - size of CHA |
|
|
//| IsUpper - what half of CHA is provided |
|
|
//| B - array[0..N-1,0..M-1], right part |
|
|
//| M - right part size |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Info - same as in RMatrixSolve |
|
|
//| Rep - same as in RMatrixSolve |
|
|
//| X - same as in RMatrixSolve |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::HPDMatrixCholeskySolveM(CMatrixComplex &cha,const int n,
|
|
const bool isupper,CMatrixComplex &b,
|
|
const int m,int &info,
|
|
CDenseSolverReportShell &rep,
|
|
CMatrixComplex &x)
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDenseSolver::HPDMatrixCholeskySolveM(cha,n,isupper,b,m,info,rep.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Dense solver. Same as RMatrixLUSolve(), but for HPD matrices |
|
|
//| represented by their Cholesky decomposition. |
|
|
//| Algorithm features: |
|
|
//| * automatic detection of degenerate cases |
|
|
//| * O(N^2) complexity |
|
|
//| * condition number estimation |
|
|
//| * matrix is represented by its upper or lower triangle |
|
|
//| No iterative refinement is provided because such partial |
|
|
//| representation of matrix does not allow efficient calculation of |
|
|
//| extra-precise matrix-vector products for large matrices. Use |
|
|
//| RMatrixSolve or RMatrixMixedSolve if you need iterative |
|
|
//| refinement. |
|
|
//| INPUT PARAMETERS |
|
|
//| CHA - array[0..N-1,0..N-1], Cholesky decomposition, |
|
|
//| SPDMatrixCholesky result |
|
|
//| N - size of A |
|
|
//| IsUpper - what half of CHA is provided |
|
|
//| B - array[0..N-1], right part |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Info - same as in RMatrixSolve |
|
|
//| Rep - same as in RMatrixSolve |
|
|
//| X - same as in RMatrixSolve |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::HPDMatrixCholeskySolve(CMatrixComplex &cha,const int n,
|
|
const bool isupper,complex &b[],
|
|
int &info,CDenseSolverReportShell &rep,
|
|
complex &x[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDenseSolver::HPDMatrixCholeskySolve(cha,n,isupper,b,info,rep.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Dense solver. |
|
|
//| This subroutine finds solution of the linear system A*X=B with |
|
|
//| non-square, possibly degenerate A. System is solved in the least |
|
|
//| squares sense, and general least squares solution X = X0 + CX*y |
|
|
//| which minimizes |A*X-B| is returned. If A is non-degenerate, |
|
|
//| solution in the usual sense is returned |
|
|
//| Algorithm features: |
|
|
//| * automatic detection of degenerate cases |
|
|
//| * iterative refinement |
|
|
//| * O(N^3) complexity |
|
|
//| INPUT PARAMETERS |
|
|
//| A - array[0..NRows-1,0..NCols-1], system matrix |
|
|
//| NRows - vertical size of A |
|
|
//| NCols - horizontal size of A |
|
|
//| B - array[0..NCols-1], right part |
|
|
//| Threshold- a number in [0,1]. Singular values beyond |
|
|
//| Threshold are considered zero. Set it to 0.0, |
|
|
//| if you don't understand what it means, so the |
|
|
//| solver will choose good value on its own. |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Info - return code: |
|
|
//| * -4 SVD subroutine failed |
|
|
//| * -1 if NRows<=0 or NCols<=0 or Threshold<0 |
|
|
//| was passed |
|
|
//| * 1 if task is solved |
|
|
//| Rep - solver report, see below for more info |
|
|
//| X - array[0..N-1,0..M-1], it contains: |
|
|
//| * solution of A*X=B if A is non-singular |
|
|
//| (well-conditioned or ill-conditioned, but not |
|
|
//| very close to singular) |
|
|
//| * zeros, if A is singular or VERY close to |
|
|
//| singular (in this case Info=-3). |
|
|
//| SOLVER REPORT |
|
|
//| Subroutine sets following fields of the Rep structure: |
|
|
//| * R2 reciprocal of condition number: 1/cond(A), 2-norm. |
|
|
//| * N = NCols |
|
|
//| * K dim(Null(A)) |
|
|
//| * CX array[0..N-1,0..K-1], kernel of A. |
|
|
//| Columns of CX store such vectors that A*CX[i]=0. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::RMatrixSolveLS(CMatrixDouble &a,const int nrows,
|
|
const int ncols,double &b[],
|
|
const double threshold,int &info,
|
|
CDenseSolverLSReportShell &rep,
|
|
double &x[])
|
|
{
|
|
//--- initialization
|
|
info=0;
|
|
//--- function call
|
|
CDenseSolver::RMatrixSolveLS(a,nrows,ncols,b,threshold,info,rep.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| LEVENBERG-MARQUARDT-LIKE NONLINEAR SOLVER |
|
|
//| DESCRIPTION: |
|
|
//| This algorithm solves system of nonlinear equations |
|
|
//| F[0](x[0], ..., x[n-1]) = 0 |
|
|
//| F[1](x[0], ..., x[n-1]) = 0 |
|
|
//| ... |
|
|
//| F[M-1](x[0], ..., x[n-1]) = 0 |
|
|
//| with M/N do not necessarily coincide. Algorithm converges |
|
|
//| quadratically under following conditions: |
|
|
//| * the solution set XS is nonempty |
|
|
//| * for some xs in XS there exist such neighbourhood N(xs) |
|
|
//| that: |
|
|
//| * vector function F(x) and its Jacobian J(x) are |
|
|
//| continuously differentiable on N |
|
|
//| * ||F(x)|| provides local error bound on N, i.e. there |
|
|
//| exists such c1, that ||F(x)||>c1*distance(x,XS) |
|
|
//| Note that these conditions are much more weaker than usual |
|
|
//| non-singularity conditions. For example, algorithm will converge |
|
|
//| for any affine function F (whether its Jacobian singular or not).|
|
|
//| REQUIREMENTS: |
|
|
//| Algorithm will request following information during its |
|
|
//| operation: |
|
|
//| * function vector F[] and Jacobian matrix at given point X |
|
|
//| * value of merit function f(x)=F[0]^2(x)+...+F[M-1]^2(x) at given|
|
|
//| point X |
|
|
//| USAGE: |
|
|
//| 1. User initializes algorithm state with NLEQCreateLM() call |
|
|
//| 2. User tunes solver parameters with NLEQSetCond(), |
|
|
//| NLEQSetStpMax() and other functions |
|
|
//| 3. User calls NLEQSolve() function which takes algorithm state |
|
|
//| and pointers (delegates, etc.) to callback functions which |
|
|
//| calculate merit function value and Jacobian. |
|
|
//| 4. User calls NLEQResults() to get solution |
|
|
//| 5. Optionally, user may call NLEQRestartFrom() to solve another |
|
|
//| problem with same parameters (N/M) but another starting point |
|
|
//| and/or another function vector. NLEQRestartFrom() allows to |
|
|
//| reuse already initialized structure. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - space dimension, N>1: |
|
|
//| * if provided, only leading N elements of X are |
|
|
//| used |
|
|
//| * if not provided, determined automatically from |
|
|
//| size of X |
|
|
//| M - system size |
|
|
//| X - starting point |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NOTES: |
|
|
//| 1. you may tune stopping conditions with NLEQSetCond() function |
|
|
//| 2. if target function contains exp() or other fast growing |
|
|
//| functions, and optimization algorithm makes too large steps |
|
|
//| which leads to overflow, use NLEQSetStpMax() function to bound|
|
|
//| algorithm's steps. |
|
|
//| 3. this algorithm is a slightly modified implementation of the |
|
|
//| method described in 'Levenberg-Marquardt method for |
|
|
//| constrained nonlinear equations with strong local convergence |
|
|
//| properties' by Christian Kanzow Nobuo Yamashita and Masao |
|
|
//| Fukushima and further developed in 'On the convergence of a |
|
|
//| New Levenberg-Marquardt Method' by Jin-yan Fan and Ya-Xiang |
|
|
//| Yuan. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::NlEqCreateLM(const int n,const int m,double &x[],
|
|
CNlEqStateShell &state)
|
|
{
|
|
//--- function call
|
|
CNlEq::NlEqCreateLM(n,m,x,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| LEVENBERG-MARQUARDT-LIKE NONLINEAR SOLVER |
|
|
//| DESCRIPTION: |
|
|
//| This algorithm solves system of nonlinear equations |
|
|
//| F[0](x[0], ..., x[n-1]) = 0 |
|
|
//| F[1](x[0], ..., x[n-1]) = 0 |
|
|
//| ... |
|
|
//| F[M-1](x[0], ..., x[n-1]) = 0 |
|
|
//| with M/N do not necessarily coincide. Algorithm converges |
|
|
//| quadratically under following conditions: |
|
|
//| * the solution set XS is nonempty |
|
|
//| * for some xs in XS there exist such neighbourhood N(xs) |
|
|
//| that: |
|
|
//| * vector function F(x) and its Jacobian J(x) are |
|
|
//| continuously differentiable on N |
|
|
//| * ||F(x)|| provides local error bound on N, i.e. there |
|
|
//| exists such c1, that ||F(x)||>c1*distance(x,XS) |
|
|
//| Note that these conditions are much more weaker than usual |
|
|
//| non-singularity conditions. For example, algorithm will converge |
|
|
//| for any affine function F (whether its Jacobian singular or not).|
|
|
//| REQUIREMENTS: |
|
|
//| Algorithm will request following information during its |
|
|
//| operation: |
|
|
//| * function vector F[] and Jacobian matrix at given point X |
|
|
//| * value of merit function f(x)=F[0]^2(x)+...+F[M-1]^2(x) at given|
|
|
//| point X |
|
|
//| USAGE: |
|
|
//| 1. User initializes algorithm state with NLEQCreateLM() call |
|
|
//| 2. User tunes solver parameters with NLEQSetCond(), |
|
|
//| NLEQSetStpMax() and other functions |
|
|
//| 3. User calls NLEQSolve() function which takes algorithm state |
|
|
//| and pointers (delegates, etc.) to callback functions which |
|
|
//| calculate merit function value and Jacobian. |
|
|
//| 4. User calls NLEQResults() to get solution |
|
|
//| 5. Optionally, user may call NLEQRestartFrom() to solve another |
|
|
//| problem with same parameters (N/M) but another starting point |
|
|
//| and/or another function vector. NLEQRestartFrom() allows to |
|
|
//| reuse already initialized structure. |
|
|
//| INPUT PARAMETERS: |
|
|
//| N - space dimension, N>1: |
|
|
//| * if provided, only leading N elements of X are |
|
|
//| used |
|
|
//| * if not provided, determined automatically from |
|
|
//| size of X |
|
|
//| M - system size |
|
|
//| X - starting point |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NOTES: |
|
|
//| 1. you may tune stopping conditions with NLEQSetCond() function |
|
|
//| 2. if target function contains exp() or other fast growing |
|
|
//| functions, and optimization algorithm makes too large steps |
|
|
//| which leads to overflow, use NLEQSetStpMax() function to bound|
|
|
//| algorithm's steps. |
|
|
//| 3. this algorithm is a slightly modified implementation of the |
|
|
//| method described in 'Levenberg-Marquardt method for |
|
|
//| constrained nonlinear equations with strong local convergence |
|
|
//| properties' by Christian Kanzow Nobuo Yamashita and Masao |
|
|
//| Fukushima and further developed in 'On the convergence of a |
|
|
//| New Levenberg-Marquardt Method' by Jin-yan Fan and Ya-Xiang |
|
|
//| Yuan. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::NlEqCreateLM(const int m,double &x[],CNlEqStateShell &state)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CNlEq::NlEqCreateLM(n,m,x,state.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets stopping conditions for the nonlinear solver |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| EpsF - >=0 |
|
|
//| The subroutine finishes its work if on k+1-th |
|
|
//| iteration the condition ||F||<=EpsF is satisfied |
|
|
//| MaxIts - maximum number of iterations. If MaxIts=0, the |
|
|
//| number of iterations is unlimited. |
|
|
//| Passing EpsF=0 and MaxIts=0 simultaneously will lead to |
|
|
//| automatic stopping criterion selection (small EpsF). |
|
|
//| NOTES: |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::NlEqSetCond(CNlEqStateShell &state,const double epsf,
|
|
const int maxits)
|
|
{
|
|
//--- function call
|
|
CNlEq::NlEqSetCond(state.GetInnerObj(),epsf,maxits);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function turns on/off reporting. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| NeedXRep- whether iteration reports are needed or not |
|
|
//| If NeedXRep is True, algorithm will call rep() callback function |
|
|
//| if it is provided to NLEQSolve(). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::NlEqSetXRep(CNlEqStateShell &state,const bool needxrep)
|
|
{
|
|
//--- function call
|
|
CNlEq::NlEqSetXRep(state.GetInnerObj(),needxrep);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function sets maximum step length |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure which stores algorithm state |
|
|
//| StpMax - maximum step length, >=0. Set StpMax to 0.0, if |
|
|
//| you don't want to limit step length. |
|
|
//| Use this subroutine when target function contains exp() or other |
|
|
//| fast growing functions, and algorithm makes too large steps which|
|
|
//| lead to overflow. This function allows us to reject steps that |
|
|
//| are too large (and therefore expose us to the possible overflow) |
|
|
//| without actually calculating function value at the x+stp*d. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::NlEqSetStpMax(CNlEqStateShell &state,const double stpmax)
|
|
{
|
|
//--- function call
|
|
CNlEq::NlEqSetStpMax(state.GetInnerObj(),stpmax);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This function provides reverse communication interface |
|
|
//| Reverse communication interface is not documented or recommended |
|
|
//| to use. |
|
|
//| See below for functions which provide better documented API |
|
|
//+------------------------------------------------------------------+
|
|
static bool CAlglib::NlEqIteration(CNlEqStateShell &state)
|
|
{
|
|
//--- return result
|
|
return(CNlEq::NlEqIteration(state.GetInnerObj()));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This family of functions is used to launcn iterations of |
|
|
//| nonlinear solver |
|
|
//| These functions accept following parameters: |
|
|
//| func - callback which calculates function (or merit |
|
|
//| function) value func at given point x |
|
|
//| jac - callback which calculates function vector fi[] |
|
|
//| and Jacobian jac at given point x |
|
|
//| rep - optional callback which is called after each |
|
|
//| iteration can be null |
|
|
//| obj - optional object which is passed to |
|
|
//| func/grad/hess/jac/rep can be null |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::NlEqSolve(CNlEqStateShell &state,CNDimensional_Func &func,
|
|
CNDimensional_Jac &jac,CNDimensional_Rep &rep,
|
|
bool rep_status,CObject &obj)
|
|
{
|
|
//--- cycle
|
|
while(CAlglib::NlEqIteration(state))
|
|
{
|
|
//--- check
|
|
if(state.GetNeedF())
|
|
{
|
|
func.Func(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetNeedFIJ())
|
|
{
|
|
jac.Jac(state.GetInnerObj().m_x,state.GetInnerObj().m_fi,state.GetInnerObj().m_j,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
//--- check
|
|
if(state.GetInnerObj().m_xupdated)
|
|
{
|
|
//--- check
|
|
if(rep_status)
|
|
rep.Rep(state.GetInnerObj().m_x,state.GetInnerObj().m_f,obj);
|
|
//--- next iteration
|
|
continue;
|
|
}
|
|
Print("ALGLIB: error in 'nleqsolve' (some derivatives were not provided?)");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| NLEQ solver results |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - algorithm state. |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| X - array[0..N-1], solution |
|
|
//| Rep - optimization report: |
|
|
//| * Rep.TerminationType completetion code: |
|
|
//| * -4 ERROR: algorithm has converged to the|
|
|
//| stationary point Xf which is local |
|
|
//| minimum of f=F[0]^2+...+F[m-1]^2, |
|
|
//| but is not solution of nonlinear |
|
|
//| system. |
|
|
//| * 1 sqrt(f)<=EpsF. |
|
|
//| * 5 MaxIts steps was taken |
|
|
//| * 7 stopping conditions are too |
|
|
//| stringent, further improvement is |
|
|
//| impossible |
|
|
//| * Rep.IterationsCount contains iterations count |
|
|
//| * NFEV countains number of function calculations |
|
|
//| * ActiveConstraints contains number of active |
|
|
//| constraints |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::NlEqResults(CNlEqStateShell &state,double &x[],
|
|
CNlEqReportShell &rep)
|
|
{
|
|
//--- function call
|
|
CNlEq::NlEqResults(state.GetInnerObj(),x,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| NLEQ solver results |
|
|
//| Buffered implementation of NLEQResults(), which uses |
|
|
//| pre-allocated buffer to store X[]. If buffer size is too small, |
|
|
//| it resizes buffer. It is intended to be used in the inner cycles |
|
|
//| of performance critical algorithms where array reallocation |
|
|
//| penalty is too large to be ignored. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::NlEqResultsBuf(CNlEqStateShell &state,double &x[],
|
|
CNlEqReportShell &rep)
|
|
{
|
|
//--- function call
|
|
CNlEq::NlEqResultsBuf(state.GetInnerObj(),x,rep.GetInnerObj());
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| This subroutine restarts CG algorithm from new point. All |
|
|
//| optimization parameters are left unchanged. |
|
|
//| This function allows to solve multiple optimization problems |
|
|
//| (which must have same number of dimensions) without object |
|
|
//| reallocation penalty. |
|
|
//| INPUT PARAMETERS: |
|
|
//| State - structure used for reverse communication |
|
|
//| previously allocated with MinCGCreate call. |
|
|
//| X - new starting point. |
|
|
//| BndL - new lower bounds |
|
|
//| BndU - new upper bounds |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::NlEqRestartFrom(CNlEqStateShell &state,double &x[])
|
|
{
|
|
//--- function call
|
|
CNlEq::NlEqRestartFrom(state.GetInnerObj(),x);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Gamma function |
|
|
//| Input parameters: |
|
|
//| X - argument |
|
|
//| Domain: |
|
|
//| 0 < X < 171.6 |
|
|
//| -170 < X < 0, X is not an integer. |
|
|
//| Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE -170,-33 20000 2.3e-15 3.3e-16 |
|
|
//| IEEE -33, 33 20000 9.4e-16 2.2e-16 |
|
|
//| IEEE 33, 171.6 20000 2.3e-15 3.2e-16 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::GammaFunction(const double x)
|
|
{
|
|
//--- return result
|
|
return(CGammaFunc::GammaFunc(x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Natural logarithm of gamma function |
|
|
//| Input parameters: |
|
|
//| X - argument |
|
|
//| Result: |
|
|
//| logarithm of the absolute value of the Gamma(X). |
|
|
//| Output parameters: |
|
|
//| SgnGam - sign(Gamma(X)) |
|
|
//| Domain: |
|
|
//| 0 < X < 2.55e305 |
|
|
//| -2.55e305 < X < 0, X is not an integer. |
|
|
//| ACCURACY: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0, 3 28000 5.4e-16 1.1e-16 |
|
|
//| IEEE 2.718, 2.556e305 40000 3.5e-16 8.3e-17 |
|
|
//| The error criterion was relative when the function magnitude |
|
|
//| was greater than one but absolute when it was less than one. |
|
|
//| The following test used the relative error criterion, though |
|
|
//| at certain points the relative error could be much higher than |
|
|
//| indicated. |
|
|
//| IEEE -200, -4 10000 4.8e-16 1.3e-16 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::LnGamma(const double x,double &sgngam)
|
|
{
|
|
//--- initialization
|
|
sgngam=0;
|
|
//--- return result
|
|
return(CGammaFunc::LnGamma(x,sgngam));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Error function |
|
|
//| The integral is |
|
|
//| x |
|
|
//| - |
|
|
//| 2 | | 2 |
|
|
//| erf(x) = -------- | exp( - t ) dt. |
|
|
//| sqrt(pi) | | |
|
|
//| - |
|
|
//| 0 |
|
|
//| For 0 <= |x| < 1, erf(x) = x * P4(x**2)/Q5(x**2); otherwise |
|
|
//| erf(x) = 1 - erfc(x). |
|
|
//| ACCURACY: |
|
|
//| Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0,1 30000 3.7e-16 1.0e-16 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::ErrorFunction(const double x)
|
|
{
|
|
//--- return result
|
|
return(CNormalDistr::ErrorFunction(x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Complementary error function |
|
|
//| 1 - erf(x) = |
|
|
//| inf. |
|
|
//| - |
|
|
//| 2 | | 2 |
|
|
//| erfc(x) = -------- | exp( - t ) dt |
|
|
//| sqrt(pi) | | |
|
|
//| - |
|
|
//| x |
|
|
//| For small x, erfc(x) = 1 - erf(x); otherwise rational |
|
|
//| approximations are computed. |
|
|
//| ACCURACY: |
|
|
//| Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0,26.6417 30000 5.7e-14 1.5e-14 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::ErrorFunctionC(const double x)
|
|
{
|
|
//--- return result
|
|
return(CNormalDistr::ErrorFunctionC(x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Normal distribution function |
|
|
//| Returns the area under the Gaussian probability density |
|
|
//| function, integrated from minus infinity to x: |
|
|
//| x |
|
|
//| - |
|
|
//| 1 | | 2 |
|
|
//| ndtr(x) = --------- | exp( - t /2 ) dt |
|
|
//| sqrt(2pi) | | |
|
|
//| - |
|
|
//| -inf. |
|
|
//| = ( 1 + erf(z) ) / 2 |
|
|
//| = erfc(z) / 2 |
|
|
//| where z = x/sqrt(2). Computation is via the functions |
|
|
//| erf and erfc. |
|
|
//| ACCURACY: |
|
|
//| Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE -13,0 30000 3.4e-14 6.7e-15 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::NormalDistribution(const double x)
|
|
{
|
|
//--- return result
|
|
return(CNormalDistr::NormalDistribution(x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inverse of the error function |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::InvErF(double e)
|
|
{
|
|
//--- return result
|
|
return(CNormalDistr::InvErF(e));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inverse of Normal distribution function |
|
|
//| Returns the argument, x, for which the area under the |
|
|
//| Gaussian probability density function (integrated from |
|
|
//| minus infinity to x) is equal to y. |
|
|
//| For small arguments 0 < y < exp(-2), the program computes |
|
|
//| z = sqrt( -2.0 * log(y) ); then the approximation is |
|
|
//| x = z - log(z)/z - (1/z) P(1/z) / Q(1/z). |
|
|
//| There are two rational functions P/Q, one for 0 < y < exp(-32) |
|
|
//| and the other for y up to exp(-2). For larger arguments, |
|
|
//| w = y - 0.5, and x/sqrt(2pi) = w + w**3 R(w**2)/S(w**2)). |
|
|
//| ACCURACY: |
|
|
//| Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0.125, 1 20000 7.2e-16 1.3e-16 |
|
|
//| IEEE 3e-308, 0.135 50000 4.6e-16 9.8e-17 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::InvNormalDistribution(const double y0)
|
|
{
|
|
//--- return result
|
|
return(CNormalDistr::InvNormalDistribution(y0));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Incomplete gamma integral |
|
|
//| The function is defined by |
|
|
//| x |
|
|
//| - |
|
|
//| 1 | | -t a-1 |
|
|
//| igam(a,x) = ----- | e t dt. |
|
|
//| - | | |
|
|
//| | (a) - |
|
|
//| 0 |
|
|
//| In this implementation both arguments must be positive. |
|
|
//| The integral is evaluated by either a power series or |
|
|
//| continued fraction expansion, depending on the relative |
|
|
//| values of a and x. |
|
|
//| ACCURACY: |
|
|
//| Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0,30 200000 3.6e-14 2.9e-15 |
|
|
//| IEEE 0,100 300000 9.9e-14 1.5e-14 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::IncompleteGamma(const double a,const double x)
|
|
{
|
|
//--- return result
|
|
return(CIncGammaF::IncompleteGamma(a,x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Complemented incomplete gamma integral |
|
|
//| The function is defined by |
|
|
//| igamc(a,x) = 1 - igam(a,x) |
|
|
//| inf. |
|
|
//| - |
|
|
//| 1 | | -t a-1 |
|
|
//| = ----- | e t dt. |
|
|
//| - | | |
|
|
//| | (a) - |
|
|
//| x |
|
|
//| In this implementation both arguments must be positive. |
|
|
//| The integral is evaluated by either a power series or |
|
|
//| continued fraction expansion, depending on the relative |
|
|
//| values of a and x. |
|
|
//| ACCURACY: |
|
|
//| Tested at random a, x. |
|
|
//| a x Relative error: |
|
|
//| arithmetic domain domain # trials peak rms |
|
|
//| IEEE 0.5,100 0,100 200000 1.9e-14 1.7e-15|
|
|
//| IEEE 0.01,0.5 0,100 200000 1.4e-13 1.6e-15|
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::IncompleteGammaC(const double a,const double x)
|
|
{
|
|
//--- return result
|
|
return(CIncGammaF::IncompleteGammaC(a,x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inverse of complemented imcomplete gamma integral |
|
|
//| Given p, the function finds x such that |
|
|
//| igamc( a, x ) = p. |
|
|
//| Starting with the approximate value |
|
|
//| 3 |
|
|
//| x = a t |
|
|
//| where |
|
|
//| t = 1 - d - ndtri(p) sqrt(d) |
|
|
//| and |
|
|
//| d = 1/9a, |
|
|
//| the routine performs up to 10 Newton iterations to find the |
|
|
//| root of igamc(a,x) - p = 0. |
|
|
//| ACCURACY: |
|
|
//| Tested at random a, p in the intervals indicated. |
|
|
//| a p Relative error: |
|
|
//| arithmetic domain domain # trials peak rms |
|
|
//| IEEE 0.5,100 0,0.5 100000 1.0e-14 1.7e-15|
|
|
//| IEEE 0.01,0.5 0,0.5 100000 9.0e-14 3.4e-15|
|
|
//| IEEE 0.5,10000 0,0.5 20000 2.3e-13 3.8e-14|
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::InvIncompleteGammaC(const double a,const double y0)
|
|
{
|
|
//--- return result
|
|
return(CIncGammaF::InvIncompleteGammaC(a,y0));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Airy function |
|
|
//| Solution of the differential equation |
|
|
//| y"(x) = xy. |
|
|
//| The function returns the two independent solutions Ai, Bi |
|
|
//| and their first derivatives Ai'(x), Bi'(x). |
|
|
//| Evaluation is by power series summation for small x, |
|
|
//| by rational minimax approximations for large x. |
|
|
//| ACCURACY: |
|
|
//| Error criterion is absolute when function <= 1, relative |
|
|
//| when function > 1, except * denotes relative error criterion. |
|
|
//| For large negative x, the absolute error increases as x^1.5. |
|
|
//| For large positive x, the relative error increases as x^1.5. |
|
|
//| Arithmetic domain function # trials peak rms |
|
|
//| IEEE -10, 0 Ai 10000 1.6e-15 2.7e-16 |
|
|
//| IEEE 0, 10 Ai 10000 2.3e-14* 1.8e-15*|
|
|
//| IEEE -10, 0 Ai' 10000 4.6e-15 7.6e-16 |
|
|
//| IEEE 0, 10 Ai' 10000 1.8e-14* 1.5e-15*|
|
|
//| IEEE -10, 10 Bi 30000 4.2e-15 5.3e-16 |
|
|
//| IEEE -10, 10 Bi' 30000 4.9e-15 7.3e-16 |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::Airy(const double x,double &ai,double &aip,double &bi,
|
|
double &bip)
|
|
{
|
|
//--- create variables
|
|
ai=0;
|
|
aip=0;
|
|
bi=0;
|
|
bip=0;
|
|
//--- function call
|
|
CAiryF::Airy(x,ai,aip,bi,bip);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Bessel function of order zero |
|
|
//| Returns Bessel function of order zero of the argument. |
|
|
//| The domain is divided into the intervals [0, 5] and |
|
|
//| (5, infinity). In the first interval the following rational |
|
|
//| approximation is used: |
|
|
//| 2 2 |
|
|
//| (w - r ) (w - r ) P (w) / Q (w) |
|
|
//| 1 2 3 8 |
|
|
//| 2 |
|
|
//| where w = x and the two r's are zeros of the function. |
|
|
//| In the second interval, the Hankel asymptotic expansion |
|
|
//| is employed with two rational functions of degree 6/6 |
|
|
//| and 7/7. |
|
|
//| ACCURACY: |
|
|
//| Absolute error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0, 30 60000 4.2e-16 1.1e-16 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::BesselJ0(const double x)
|
|
{
|
|
//--- return result
|
|
return(CBessel::BesselJ0(x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Bessel function of order one |
|
|
//| Returns Bessel function of order one of the argument. |
|
|
//| The domain is divided into the intervals [0, 8] and |
|
|
//| (8, infinity). In the first interval a 24 term Chebyshev |
|
|
//| expansion is used. In the second, the asymptotic |
|
|
//| trigonometric representation is employed using two |
|
|
//| rational functions of degree 5/5. |
|
|
//| ACCURACY: |
|
|
//| Absolute error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0, 30 30000 2.6e-16 1.1e-16 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::BesselJ1(const double x)
|
|
{
|
|
//--- return result
|
|
return(CBessel::BesselJ1(x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Bessel function of integer order |
|
|
//| Returns Bessel function of order n, where n is a |
|
|
//| (possibly negative) integer. |
|
|
//| The ratio of jn(x) to j0(x) is computed by backward |
|
|
//| recurrence. First the ratio jn/jn-1 is found by a |
|
|
//| continued fraction expansion. Then the recurrence |
|
|
//| relating successive orders is applied until j0 or j1 is |
|
|
//| reached. |
|
|
//| If n = 0 or 1 the routine for j0 or j1 is called |
|
|
//| directly. |
|
|
//| ACCURACY: |
|
|
//| Absolute error: |
|
|
//| arithmetic range # trials peak rms |
|
|
//| IEEE 0, 30 5000 4.4e-16 7.9e-17 |
|
|
//| Not suitable for large n or x. Use jv() (fractional order) |
|
|
//| instead. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::BesselJN(const int n,const double x)
|
|
{
|
|
//--- return result
|
|
return(CBessel::BesselJN(n,x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Bessel function of the second kind, order zero |
|
|
//| Returns Bessel function of the second kind, of order |
|
|
//| zero, of the argument. |
|
|
//| The domain is divided into the intervals [0, 5] and |
|
|
//| (5, infinity). In the first interval a rational approximation |
|
|
//| R(x) is employed to compute |
|
|
//| y0(x) = R(x) + 2 * log(x) * j0(x) / PI. |
|
|
//| Thus a call to j0() is required. |
|
|
//| In the second interval, the Hankel asymptotic expansion |
|
|
//| is employed with two rational functions of degree 6/6 |
|
|
//| and 7/7. |
|
|
//| ACCURACY: |
|
|
//| Absolute error, when y0(x) < 1; else relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0, 30 30000 1.3e-15 1.6e-16 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::BesselY0(const double x)
|
|
{
|
|
//--- return result
|
|
return(CBessel::BesselY0(x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Bessel function of second kind of order one |
|
|
//| Returns Bessel function of the second kind of order one |
|
|
//| of the argument. |
|
|
//| The domain is divided into the intervals [0, 8] and |
|
|
//| (8, infinity). In the first interval a 25 term Chebyshev |
|
|
//| expansion is used, and a call to j1() is required. |
|
|
//| In the second, the asymptotic trigonometric representation |
|
|
//| is employed using two rational functions of degree 5/5. |
|
|
//| ACCURACY: |
|
|
//| Absolute error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0, 30 30000 1.0e-15 1.3e-16 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::BesselY1(const double x)
|
|
{
|
|
//--- return result
|
|
return(CBessel::BesselY1(x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Bessel function of second kind of integer order |
|
|
//| Returns Bessel function of order n, where n is a |
|
|
//| (possibly negative) integer. |
|
|
//| The function is evaluated by forward recurrence on |
|
|
//| n, starting with values computed by the routines |
|
|
//| y0() and y1(). |
|
|
//| If n = 0 or 1 the routine for y0 or y1 is called |
|
|
//| directly. |
|
|
//| ACCURACY: |
|
|
//| Absolute error, except relative |
|
|
//| when y > 1: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0, 30 30000 3.4e-15 4.3e-16 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::BesselYN(const int n,const double x)
|
|
{
|
|
//--- return result
|
|
return(CBessel::BesselYN(n,x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Modified Bessel function of order zero |
|
|
//| Returns modified Bessel function of order zero of the |
|
|
//| argument. |
|
|
//| The function is defined as i0(x) = j0( ix ). |
|
|
//| The range is partitioned into the two intervals [0,8] and |
|
|
//| (8, infinity). Chebyshev polynomial expansions are employed |
|
|
//| in each interval. |
|
|
//| ACCURACY: |
|
|
//| Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0,30 30000 5.8e-16 1.4e-16 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::BesselI0(const double x)
|
|
{
|
|
//--- return result
|
|
return(CBessel::BesselI0(x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Modified Bessel function of order one |
|
|
//| Returns modified Bessel function of order one of the |
|
|
//| argument. |
|
|
//| The function is defined as i1(x) = -i j1( ix ). |
|
|
//| The range is partitioned into the two intervals [0,8] and |
|
|
//| (8, infinity). Chebyshev polynomial expansions are employed |
|
|
//| in each interval. |
|
|
//| ACCURACY: |
|
|
//| Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0, 30 30000 1.9e-15 2.1e-16 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::BesselI1(const double x)
|
|
{
|
|
//--- return result
|
|
return(CBessel::BesselI1(x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Modified Bessel function, second kind, order zero |
|
|
//| Returns modified Bessel function of the second kind |
|
|
//| of order zero of the argument. |
|
|
//| The range is partitioned into the two intervals [0,8] and |
|
|
//| (8, infinity). Chebyshev polynomial expansions are employed |
|
|
//| in each interval. |
|
|
//| ACCURACY: |
|
|
//| Tested at 2000 random points between 0 and 8. Peak absolute |
|
|
//| error (relative when K0 > 1) was 1.46e-14; rms, 4.26e-15. |
|
|
//| Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0, 30 30000 1.2e-15 1.6e-16 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::BesselK0(const double x)
|
|
{
|
|
//--- return result
|
|
return(CBessel::BesselK0(x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Modified Bessel function, second kind, order one |
|
|
//| Computes the modified Bessel function of the second kind |
|
|
//| of order one of the argument. |
|
|
//| The range is partitioned into the two intervals [0,2] and |
|
|
//| (2, infinity). Chebyshev polynomial expansions are employed |
|
|
//| in each interval. |
|
|
//| ACCURACY: |
|
|
//| Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0, 30 30000 1.2e-15 1.6e-16 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::BesselK1(const double x)
|
|
{
|
|
//--- return result
|
|
return(CBessel::BesselK1(x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Modified Bessel function, second kind, integer order |
|
|
//| Returns modified Bessel function of the second kind |
|
|
//| of order n of the argument. |
|
|
//| The range is partitioned into the two intervals [0,9.55] and |
|
|
//| (9.55, infinity). An ascending power series is used in the |
|
|
//| low range, and an asymptotic expansion in the high range. |
|
|
//| ACCURACY: |
|
|
//| Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0,30 90000 1.8e-8 3.0e-10 |
|
|
//| Error is high only near the crossover point x = 9.55 |
|
|
//| between the two expansions used. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::BesselKN(const int nn,const double x)
|
|
{
|
|
//--- return result
|
|
return(CBessel::BesselKN(nn,x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Beta function |
|
|
//| - - |
|
|
//| | (a) | (b) |
|
|
//| beta( a, b ) = -----------. |
|
|
//| - |
|
|
//| | (a+b) |
|
|
//| For large arguments the logarithm of the function is |
|
|
//| evaluated using lgam(), then exponentiated. |
|
|
//| ACCURACY: |
|
|
//| Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0,30 30000 8.1e-14 1.1e-14 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::Beta(const double a,const double b)
|
|
{
|
|
//--- return result
|
|
return(CBetaF::Beta(a,b));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Incomplete beta integral |
|
|
//| Returns incomplete beta integral of the arguments, evaluated |
|
|
//| from zero to x. The function is defined as |
|
|
//| x |
|
|
//| - - |
|
|
//| | (a+b) | | a-1 b-1 |
|
|
//| ----------- | t (1-t) dt. |
|
|
//| - - | | |
|
|
//| | (a) | (b) - |
|
|
//| 0 |
|
|
//| The domain of definition is 0 <= x <= 1. In this |
|
|
//| implementation a and b are restricted to positive values. |
|
|
//| The integral from x to 1 may be obtained by the symmetry |
|
|
//| relation |
|
|
//| 1 - incbet( a, b, x ) = incbet( b, a, 1-x ). |
|
|
//| The integral is evaluated by a continued fraction expansion |
|
|
//| or, when b*x is small, by a power series. |
|
|
//| ACCURACY: |
|
|
//| Tested at uniformly distributed random points (a,b,x) with a and |
|
|
//| b in "domain" and x between 0 and 1. |
|
|
//| Relative error |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0,5 10000 6.9e-15 4.5e-16 |
|
|
//| IEEE 0,85 250000 2.2e-13 1.7e-14 |
|
|
//| IEEE 0,1000 30000 5.3e-12 6.3e-13 |
|
|
//| IEEE 0,10000 250000 9.3e-11 7.1e-12 |
|
|
//| IEEE 0,100000 10000 8.7e-10 4.8e-11 |
|
|
//| Outputs smaller than the IEEE gradual underflow threshold |
|
|
//| were excluded from these statistics. |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::IncompleteBeta(const double a,const double b,const double x)
|
|
{
|
|
//--- return result
|
|
return(CIncBetaF::IncompleteBeta(a,b,x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inverse of imcomplete beta integral |
|
|
//| Given y, the function finds x such that |
|
|
//| incbet( a, b, x ) = y . |
|
|
//| The routine performs interval halving or Newton iterations to |
|
|
//| find the root of incbet(a,b,x) - y = 0. |
|
|
//| ACCURACY: |
|
|
//| Relative error: |
|
|
//| x a,b |
|
|
//| arithmetic domain domain # trials peak rms |
|
|
//| IEEE 0,1 .5,10000 50000 5.8e-12 1.3e-13 |
|
|
//| IEEE 0,1 .25,100 100000 1.8e-13 3.9e-15 |
|
|
//| IEEE 0,1 0,5 50000 1.1e-12 5.5e-15 |
|
|
//| With a and b constrained to half-integer or integer values: |
|
|
//| IEEE 0,1 .5,10000 50000 5.8e-12 1.1e-13 |
|
|
//| IEEE 0,1 .5,100 100000 1.7e-14 7.9e-16 |
|
|
//| With a = .5, b constrained to half-integer or integer values: |
|
|
//| IEEE 0,1 .5,10000 10000 8.3e-11 1.0e-11 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::InvIncompleteBeta(const double a,const double b,double y)
|
|
{
|
|
//--- return result
|
|
return(CIncBetaF::InvIncompleteBeta(a,b,y));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Binomial distribution |
|
|
//| Returns the sum of the terms 0 through k of the Binomial |
|
|
//| probability density: |
|
|
//| k |
|
|
//| -- ( n ) j n-j |
|
|
//| > ( ) p (1-p) |
|
|
//| -- ( j ) |
|
|
//| j=0 |
|
|
//| The terms are not summed directly; instead the incomplete |
|
|
//| beta integral is employed, according to the formula |
|
|
//| y = bdtr( k, n, p ) = incbet( n-k, k+1, 1-p ). |
|
|
//| The arguments must be positive, with p ranging from 0 to 1. |
|
|
//| ACCURACY: |
|
|
//| Tested at random points (a,b,p), with p between 0 and 1. |
|
|
//| a,b Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| For p between 0.001 and 1: |
|
|
//| IEEE 0,100 100000 4.3e-15 2.6e-16 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::BinomialDistribution(const int k,const int n,const double p)
|
|
{
|
|
//--- return result
|
|
return(CBinomialDistr::BinomialDistribution(k,n,p));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Complemented binomial distribution |
|
|
//| Returns the sum of the terms k+1 through n of the Binomial |
|
|
//| probability density: |
|
|
//| n |
|
|
//| -- ( n ) j n-j |
|
|
//| > ( ) p (1-p) |
|
|
//| -- ( j ) |
|
|
//| j=k+1 |
|
|
//| The terms are not summed directly; instead the incomplete |
|
|
//| beta integral is employed, according to the formula |
|
|
//| y = bdtrc( k, n, p ) = incbet( k+1, n-k, p ). |
|
|
//| The arguments must be positive, with p ranging from 0 to 1. |
|
|
//| ACCURACY: |
|
|
//| Tested at random points (a,b,p). |
|
|
//| a,b Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| For p between 0.001 and 1: |
|
|
//| IEEE 0,100 100000 6.7e-15 8.2e-16 |
|
|
//| For p between 0 and .001: |
|
|
//| IEEE 0,100 100000 1.5e-13 2.7e-15 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::BinomialComplDistribution(const int k,const int n,const double p)
|
|
{
|
|
//--- return result
|
|
return(CBinomialDistr::BinomialComplDistribution(k,n,p));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inverse binomial distribution |
|
|
//| Finds the event probability p such that the sum of the |
|
|
//| terms 0 through k of the Binomial probability density |
|
|
//| is equal to the given cumulative probability y. |
|
|
//| This is accomplished using the inverse beta integral |
|
|
//| function and the relation |
|
|
//| 1 - p = incbi( n-k, k+1, y ). |
|
|
//| ACCURACY: |
|
|
//| Tested at random points (a,b,p). |
|
|
//| a,b Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| For p between 0.001 and 1: |
|
|
//| IEEE 0,100 100000 2.3e-14 6.4e-16 |
|
|
//| IEEE 0,10000 100000 6.6e-12 1.2e-13 |
|
|
//| For p between 10^-6 and 0.001: |
|
|
//| IEEE 0,100 100000 2.0e-12 1.3e-14 |
|
|
//| IEEE 0,10000 100000 1.5e-12 3.2e-14 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::InvBinomialDistribution(const int k,const int n,const double y)
|
|
{
|
|
//--- return result
|
|
return(CBinomialDistr::InvBinomialDistribution(k,n,y));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Calculation of the value of the Chebyshev polynomials of the |
|
|
//| first and second kinds. |
|
|
//| Parameters: |
|
|
//| r - polynomial kind, either 1 or 2. |
|
|
//| n - degree, n>=0 |
|
|
//| x - argument, -1 <= x <= 1 |
|
|
//| Result: |
|
|
//| the value of the Chebyshev polynomial at x |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::ChebyshevCalculate(int r,const int n,const double x)
|
|
{
|
|
//--- return result
|
|
return(CChebyshev::ChebyshevCalculate(r,n,x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Summation of Chebyshev polynomials using Clenshaw?s recurrence |
|
|
//| formula. |
|
|
//| This routine calculates |
|
|
//| c[0]*T0(x) + c[1]*T1(x) + ... + c[N]*TN(x) |
|
|
//| or |
|
|
//| c[0]*U0(x) + c[1]*U1(x) + ... + c[N]*UN(x) |
|
|
//| depending on the R. |
|
|
//| Parameters: |
|
|
//| r - polynomial kind, either 1 or 2. |
|
|
//| n - degree, n>=0 |
|
|
//| x - argument |
|
|
//| Result: |
|
|
//| the value of the Chebyshev polynomial at x |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::ChebyshevSum(double &c[],const int r,const int n,const double x)
|
|
{
|
|
//--- return result
|
|
return(CChebyshev::ChebyshevSum(c,r,n,x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Representation of Tn as C[0] + C[1]*X + ... + C[N]*X^N |
|
|
//| Input parameters: |
|
|
//| N - polynomial degree, n>=0 |
|
|
//| Output parameters: |
|
|
//| C - coefficients |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::ChebyshevCoefficients(const int n,double &c[])
|
|
{
|
|
//--- function call
|
|
CChebyshev::ChebyshevCoefficients(n,c);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Conversion of a series of Chebyshev polynomials to a power |
|
|
//| series. |
|
|
//| Represents A[0]*T0(x) + A[1]*T1(x) + ... + A[N]*Tn(x) as |
|
|
//| B[0] + B[1]*X + ... + B[N]*X^N. |
|
|
//| Input parameters: |
|
|
//| A - Chebyshev series coefficients |
|
|
//| N - degree, N>=0 |
|
|
//| Output parameters |
|
|
//| B - power series coefficients |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::FromChebyshev(double &a[],const int n,double &b[])
|
|
{
|
|
//--- function call
|
|
CChebyshev::FromChebyshev(a,n,b);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Chi-square distribution |
|
|
//| Returns the area under the left hand tail (from 0 to x) |
|
|
//| of the Chi square probability density function with |
|
|
//| v degrees of freedom. |
|
|
//| x |
|
|
//| - |
|
|
//| 1 | | v/2-1 -t/2 |
|
|
//| P( x | v ) = ----------- | t e dt |
|
|
//| v/2 - | | |
|
|
//| 2 | (v/2) - |
|
|
//| 0 |
|
|
//| where x is the Chi-square variable. |
|
|
//| The incomplete gamma integral is used, according to the |
|
|
//| formula |
|
|
//| y = chdtr( v, x ) = igam( v/2.0, x/2.0 ). |
|
|
//| The arguments must both be positive. |
|
|
//| ACCURACY: |
|
|
//| See incomplete gamma function |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::ChiSquareDistribution(const double v,const double x)
|
|
{
|
|
//--- return result
|
|
return(CChiSquareDistr::ChiSquareDistribution(v,x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Complemented Chi-square distribution |
|
|
//| Returns the area under the right hand tail (from x to |
|
|
//| infinity) of the Chi square probability density function |
|
|
//| with v degrees of freedom: |
|
|
//| inf. |
|
|
//| - |
|
|
//| 1 | | v/2-1 -t/2 |
|
|
//| P( x | v ) = ----------- | t e dt |
|
|
//| v/2 - | | |
|
|
//| 2 | (v/2) - |
|
|
//| x |
|
|
//| where x is the Chi-square variable. |
|
|
//| The incomplete gamma integral is used, according to the |
|
|
//| formula |
|
|
//| y = chdtr( v, x ) = igamc( v/2.0, x/2.0 ). |
|
|
//| The arguments must both be positive. |
|
|
//| ACCURACY: |
|
|
//| See incomplete gamma function |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::ChiSquareComplDistribution(const double v,const double x)
|
|
{
|
|
//--- return result
|
|
return(CChiSquareDistr::ChiSquareComplDistribution(v,x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inverse of complemented Chi-square distribution |
|
|
//| Finds the Chi-square argument x such that the integral |
|
|
//| from x to infinity of the Chi-square density is equal |
|
|
//| to the given cumulative probability y. |
|
|
//| This is accomplished using the inverse gamma integral |
|
|
//| function and the relation |
|
|
//| x/2 = igami( df/2, y ); |
|
|
//| ACCURACY: |
|
|
//| See inverse incomplete gamma function |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::InvChiSquareDistribution(const double v,const double y)
|
|
{
|
|
//--- return result
|
|
return(CChiSquareDistr::InvChiSquareDistribution(v,y));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Dawson's Integral |
|
|
//| Approximates the integral |
|
|
//| x |
|
|
//| - |
|
|
//| 2 | | 2 |
|
|
//| dawsn(x) = exp( -x ) | exp( t ) dt |
|
|
//| | | |
|
|
//| - |
|
|
//| 0 |
|
|
//| Three different rational approximations are employed, for |
|
|
//| the intervals 0 to 3.25; 3.25 to 6.25; and 6.25 up. |
|
|
//| ACCURACY: |
|
|
//| Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0,10 10000 6.9e-16 1.0e-16 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::DawsonIntegral(const double x)
|
|
{
|
|
//--- return result
|
|
return(CDawson::DawsonIntegral(x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Complete elliptic integral of the first kind |
|
|
//| Approximates the integral |
|
|
//| pi/2 |
|
|
//| - |
|
|
//| | | |
|
|
//| | dt |
|
|
//| K(m) = | ------------------ |
|
|
//| | 2 |
|
|
//| | | sqrt( 1 - m sin t ) |
|
|
//| - |
|
|
//| 0 |
|
|
//| using the approximation |
|
|
//| P(x) - log x Q(x). |
|
|
//| ACCURACY: |
|
|
//| Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0,1 30000 2.5e-16 6.8e-17 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::EllipticIntegralK(const double m)
|
|
{
|
|
//--- return result
|
|
return(CElliptic::EllipticIntegralK(m));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Complete elliptic integral of the first kind |
|
|
//| Approximates the integral |
|
|
//| pi/2 |
|
|
//| - |
|
|
//| | | |
|
|
//| | dt |
|
|
//| K(m) = | ------------------ |
|
|
//| | 2 |
|
|
//| | | sqrt( 1 - m sin t ) |
|
|
//| - |
|
|
//| 0 |
|
|
//| where m = 1 - m1, using the approximation |
|
|
//| P(x) - log x Q(x). |
|
|
//| The argument m1 is used rather than m so that the logarithmic |
|
|
//| singularity at m = 1 will be shifted to the origin; this |
|
|
//| preserves maximum accuracy. |
|
|
//| K(0) = pi/2. |
|
|
//| ACCURACY: |
|
|
//| Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0,1 30000 2.5e-16 6.8e-17 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::EllipticIntegralKhighPrecision(const double m1)
|
|
{
|
|
//--- return result
|
|
return(CElliptic::EllipticIntegralKhighPrecision(m1));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Incomplete elliptic integral of the first kind F(phi|m) |
|
|
//| Approximates the integral |
|
|
//| phi |
|
|
//| - |
|
|
//| | | |
|
|
//| | dt |
|
|
//| F(phi_\m) = | ------------------ |
|
|
//| | 2 |
|
|
//| | | sqrt( 1 - m sin t ) |
|
|
//| - |
|
|
//| 0 |
|
|
//| of amplitude phi and modulus m, using the arithmetic - |
|
|
//| geometric mean algorithm. |
|
|
//| ACCURACY: |
|
|
//| Tested at random points with m in [0, 1] and phi as indicated. |
|
|
//| Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE -10,10 200000 7.4e-16 1.0e-16 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::IncompleteEllipticIntegralK(const double phi,const double m)
|
|
{
|
|
//--- return result
|
|
return(CElliptic::IncompleteEllipticIntegralK(phi,m));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Complete elliptic integral of the second kind |
|
|
//| Approximates the integral |
|
|
//| pi/2 |
|
|
//| - |
|
|
//| | | 2 |
|
|
//| E(m) = | sqrt( 1 - m sin t ) dt |
|
|
//| | | |
|
|
//| - |
|
|
//| 0 |
|
|
//| using the approximation |
|
|
//| P(x) - x log x Q(x). |
|
|
//| ACCURACY: |
|
|
//| Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0, 1 10000 2.1e-16 7.3e-17 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::EllipticIntegralE(const double m)
|
|
{
|
|
//--- return result
|
|
return(CElliptic::EllipticIntegralE(m));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Incomplete elliptic integral of the second kind |
|
|
//| Approximates the integral |
|
|
//| phi |
|
|
//| - |
|
|
//| | | |
|
|
//| | 2 |
|
|
//| E(phi_\m) = | sqrt( 1 - m sin t ) dt |
|
|
//| | |
|
|
//| | | |
|
|
//| - |
|
|
//| 0 |
|
|
//| of amplitude phi and modulus m, using the arithmetic - |
|
|
//| geometric mean algorithm. |
|
|
//| ACCURACY: |
|
|
//| Tested at random arguments with phi in [-10, 10] and m in |
|
|
//| [0, 1]. |
|
|
//| Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE -10,10 150000 3.3e-15 1.4e-16 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::IncompleteEllipticIntegralE(const double phi,const double m)
|
|
{
|
|
//--- return result
|
|
return(CElliptic::IncompleteEllipticIntegralE(phi,m));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Exponential integral Ei(x) |
|
|
//| x |
|
|
//| - t |
|
|
//| | | e |
|
|
//| Ei(x) = -|- --- dt . |
|
|
//| | | t |
|
|
//| - |
|
|
//| -inf |
|
|
//| Not defined for x <= 0. |
|
|
//| See also expn.c. |
|
|
//| ACCURACY: |
|
|
//| Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0,100 50000 8.6e-16 1.3e-16 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::ExponentialIntegralEi(const double x)
|
|
{
|
|
//--- return result
|
|
return(CExpIntegrals::ExponentialIntegralEi(x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Exponential integral En(x) |
|
|
//| Evaluates the exponential integral |
|
|
//| inf. |
|
|
//| - |
|
|
//| | | -xt |
|
|
//| | e |
|
|
//| E (x) = | ---- dt. |
|
|
//| n | n |
|
|
//| | | t |
|
|
//| - |
|
|
//| 1 |
|
|
//| Both n and x must be nonnegative. |
|
|
//| The routine employs either a power series, a continued |
|
|
//| fraction, or an asymptotic formula depending on the |
|
|
//| relative values of n and x. |
|
|
//| ACCURACY: |
|
|
//| Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0, 30 10000 1.7e-15 3.6e-16 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::ExponentialIntegralEn(const double x,const int n)
|
|
{
|
|
//--- return result
|
|
return(CExpIntegrals::ExponentialIntegralEn(x,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| F distribution |
|
|
//| Returns the area from zero to x under the F density |
|
|
//| function (also known as Snedcor's density or the |
|
|
//| variance ratio density). This is the density |
|
|
//| of x = (u1/df1)/(u2/df2), where u1 and u2 are random |
|
|
//| variables having Chi square distributions with df1 |
|
|
//| and df2 degrees of freedom, respectively. |
|
|
//| The incomplete beta integral is used, according to the |
|
|
//| formula |
|
|
//| P(x) = incbet( df1/2, df2/2, (df1*x/(df2 + df1*x) ). |
|
|
//| The arguments a and b are greater than zero, and x is |
|
|
//| nonnegative. |
|
|
//| ACCURACY: |
|
|
//| Tested at random points (a,b,x). |
|
|
//| x a,b Relative error: |
|
|
//| arithmetic domain domain # trials peak rms |
|
|
//| IEEE 0,1 0,100 100000 9.8e-15 1.7e-15 |
|
|
//| IEEE 1,5 0,100 100000 6.5e-15 3.5e-16 |
|
|
//| IEEE 0,1 1,10000 100000 2.2e-11 3.3e-12 |
|
|
//| IEEE 1,5 1,10000 100000 1.1e-11 1.7e-13 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::FDistribution(const int a,const int b,const double x)
|
|
{
|
|
//--- return result
|
|
return(CFDistr::FDistribution(a,b,x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Complemented F distribution |
|
|
//| Returns the area from x to infinity under the F density |
|
|
//| function (also known as Snedcor's density or the |
|
|
//| variance ratio density). |
|
|
//| inf. |
|
|
//| - |
|
|
//| 1 | | a-1 b-1 |
|
|
//| 1-P(x) = ------ | t (1-t) dt |
|
|
//| B(a,b) | | |
|
|
//| - |
|
|
//| x |
|
|
//| The incomplete beta integral is used, according to the |
|
|
//| formula |
|
|
//| P(x) = incbet( df2/2, df1/2, (df2/(df2 + df1*x) ). |
|
|
//| ACCURACY: |
|
|
//| Tested at random points (a,b,x) in the indicated intervals. |
|
|
//| x a,b Relative error: |
|
|
//| arithmetic domain domain # trials peak rms |
|
|
//| IEEE 0,1 1,100 100000 3.7e-14 5.9e-16 |
|
|
//| IEEE 1,5 1,100 100000 8.0e-15 1.6e-15 |
|
|
//| IEEE 0,1 1,10000 100000 1.8e-11 3.5e-13 |
|
|
//| IEEE 1,5 1,10000 100000 2.0e-11 3.0e-12 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::FComplDistribution(const int a,const int b,const double x)
|
|
{
|
|
//--- return result
|
|
return(CFDistr::FComplDistribution(a,b,x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inverse of complemented F distribution |
|
|
//| Finds the F density argument x such that the integral |
|
|
//| from x to infinity of the F density is equal to the |
|
|
//| given probability p. |
|
|
//| This is accomplished using the inverse beta integral |
|
|
//| function and the relations |
|
|
//| z = incbi( df2/2, df1/2, p ) |
|
|
//| x = df2 (1-z) / (df1 z). |
|
|
//| Note: the following relations hold for the inverse of |
|
|
//| the uncomplemented F distribution: |
|
|
//| z = incbi( df1/2, df2/2, p ) |
|
|
//| x = df2 z / (df1 (1-z)). |
|
|
//| ACCURACY: |
|
|
//| Tested at random points (a,b,p). |
|
|
//| a,b Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| For p between .001 and 1: |
|
|
//| IEEE 1,100 100000 8.3e-15 4.7e-16 |
|
|
//| IEEE 1,10000 100000 2.1e-11 1.4e-13 |
|
|
//| For p between 10^-6 and 10^-3: |
|
|
//| IEEE 1,100 50000 1.3e-12 8.4e-15 |
|
|
//| IEEE 1,10000 50000 3.0e-12 4.8e-14 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::InvFDistribution(const int a,const int b,const double y)
|
|
{
|
|
//--- return result
|
|
return(CFDistr::InvFDistribution(a,b,y));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Fresnel integral |
|
|
//| Evaluates the Fresnel integrals |
|
|
//| x |
|
|
//| - |
|
|
//| | | |
|
|
//| C(x) = | cos(pi/2 t**2) dt, |
|
|
//| | | |
|
|
//| - |
|
|
//| 0 |
|
|
//| x |
|
|
//| - |
|
|
//| | | |
|
|
//| S(x) = | sin(pi/2 t**2) dt. |
|
|
//| | | |
|
|
//| - |
|
|
//| 0 |
|
|
//| The integrals are evaluated by a power series for x < 1. |
|
|
//| For x >= 1 auxiliary functions f(x) and g(x) are employed |
|
|
//| such that |
|
|
//| C(x) = 0.5 + f(x) sin( pi/2 x**2 ) - g(x) cos( pi/2 x**2 ) |
|
|
//| S(x) = 0.5 - f(x) cos( pi/2 x**2 ) - g(x) sin( pi/2 x**2 ) |
|
|
//| ACCURACY: |
|
|
//| Relative error. |
|
|
//| Arithmetic function domain # trials peak rms |
|
|
//| IEEE S(x) 0, 10 10000 2.0e-15 3.2e-16|
|
|
//| IEEE C(x) 0, 10 10000 1.8e-15 3.3e-16|
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::FresnelIntegral(const double x,double &c,double &s)
|
|
{
|
|
//--- function call
|
|
CFresnel::FresnelIntegral(x,c,s);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Calculation of the value of the Hermite polynomial. |
|
|
//| Parameters: |
|
|
//| n - degree, n>=0 |
|
|
//| x - argument |
|
|
//| Result: |
|
|
//| the value of the Hermite polynomial Hn at x |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::HermiteCalculate(const int n,const double x)
|
|
{
|
|
//--- return result
|
|
return(CHermite::HermiteCalculate(n,x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Summation of Hermite polynomials using Clenshaw?s recurrence |
|
|
//| formula. |
|
|
//| This routine calculates |
|
|
//| c[0]*H0(x) + c[1]*H1(x) + ... + c[N]*HN(x) |
|
|
//| Parameters: |
|
|
//| n - degree, n>=0 |
|
|
//| x - argument |
|
|
//| Result: |
|
|
//| the value of the Hermite polynomial at x |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::HermiteSum(double &c[],const int n,const double x)
|
|
{
|
|
//--- return result
|
|
return(CHermite::HermiteSum(c,n,x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Representation of Hn as C[0] + C[1]*X + ... + C[N]*X^N |
|
|
//| Input parameters: |
|
|
//| N - polynomial degree, n>=0 |
|
|
//| Output parameters: |
|
|
//| C - coefficients |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::HermiteCoefficients(const int n,double &c[])
|
|
{
|
|
//--- function call
|
|
CHermite::HermiteCoefficients(n,c);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Jacobian Elliptic Functions |
|
|
//| Evaluates the Jacobian elliptic functions sn(u|m), cn(u|m), |
|
|
//| and dn(u|m) of parameter m between 0 and 1, and real |
|
|
//| argument u. |
|
|
//| These functions are periodic, with quarter-period on the |
|
|
//| real axis equal to the complete elliptic integral |
|
|
//| ellpk(1.0-m). |
|
|
//| Relation to incomplete elliptic integral: |
|
|
//| If u = ellik(phi,m), then sn(u|m) = sin(phi), |
|
|
//| and cn(u|m) = cos(phi). Phi is called the amplitude of u. |
|
|
//| Computation is by means of the arithmetic-geometric mean |
|
|
//| algorithm, except when m is within 1e-9 of 0 or 1. In the |
|
|
//| latter case with m close to 1, the approximation applies |
|
|
//| only for phi < pi/2. |
|
|
//| ACCURACY: |
|
|
//| Tested at random points with u between 0 and 10, m between |
|
|
//| 0 and 1. |
|
|
//| Absolute error (* = relative error): |
|
|
//| arithmetic function # trials peak rms |
|
|
//| IEEE phi 10000 9.2e-16* 1.4e-16* |
|
|
//| IEEE sn 50000 4.1e-15 4.6e-16 |
|
|
//| IEEE cn 40000 3.6e-15 4.4e-16 |
|
|
//| IEEE dn 10000 1.3e-12 1.8e-14 |
|
|
//| Peak error observed in consistency check using addition |
|
|
//| theorem for sn(u+v) was 4e-16 (absolute). Also tested by |
|
|
//| the above relation to the incomplete elliptic integral. |
|
|
//| Accuracy deteriorates when u is large. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::JacobianEllipticFunctions(const double u,const double m,
|
|
double &sn,double &cn,
|
|
double &dn,double &ph)
|
|
{
|
|
//--- create variables
|
|
sn=0;
|
|
cn=0;
|
|
dn=0;
|
|
ph=0;
|
|
//--- function call
|
|
CJacobianElliptic::JacobianEllipticFunctions(u,m,sn,cn,dn,ph);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Calculation of the value of the Laguerre polynomial. |
|
|
//| Parameters: |
|
|
//| n - degree, n>=0 |
|
|
//| x - argument |
|
|
//| Result: |
|
|
//| the value of the Laguerre polynomial Ln at x |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::LaguerreCalculate(const int n,const double x)
|
|
{
|
|
//--- return result
|
|
return(CLaguerre::LaguerreCalculate(n,x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Summation of Laguerre polynomials using Clenshaw?s recurrence |
|
|
//| formula. |
|
|
//| This routine calculates c[0]*L0(x) + c[1]*L1(x) + ... + |
|
|
//| + c[N]*LN(x) |
|
|
//| Parameters: |
|
|
//| n - degree, n>=0 |
|
|
//| x - argument |
|
|
//| Result: |
|
|
//| the value of the Laguerre polynomial at x |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::LaguerreSum(double &c[],const int n,const double x)
|
|
{
|
|
//--- return result
|
|
return(CLaguerre::LaguerreSum(c,n,x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Representation of Ln as C[0] + C[1]*X + ... + C[N]*X^N |
|
|
//| Input parameters: |
|
|
//| N - polynomial degree, n>=0 |
|
|
//| Output parameters: |
|
|
//| C - coefficients |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LaguerreCoefficients(const int n,double &c[])
|
|
{
|
|
//--- function call
|
|
CLaguerre::LaguerreCoefficients(n,c);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Calculation of the value of the Legendre polynomial Pn. |
|
|
//| Parameters: |
|
|
//| n - degree, n>=0 |
|
|
//| x - argument |
|
|
//| Result: |
|
|
//| the value of the Legendre polynomial Pn at x |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::LegendreCalculate(const int n,const double x)
|
|
{
|
|
//--- return result
|
|
return(CLegendre::LegendreCalculate(n,x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Summation of Legendre polynomials using Clenshaw?s recurrence |
|
|
//| formula. |
|
|
//| This routine calculates |
|
|
//| c[0]*P0(x) + c[1]*P1(x) + ... + c[N]*PN(x) |
|
|
//| Parameters: |
|
|
//| n - degree, n>=0 |
|
|
//| x - argument |
|
|
//| Result: |
|
|
//| the value of the Legendre polynomial at x |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::LegendreSum(double &c[],const int n,const double x)
|
|
{
|
|
//--- return result
|
|
return(CLegendre::LegendreSum(c,n,x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Representation of Pn as C[0] + C[1]*X + ... + C[N]*X^N |
|
|
//| Input parameters: |
|
|
//| N - polynomial degree, n>=0 |
|
|
//| Output parameters: |
|
|
//| C - coefficients |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::LegendreCoefficients(const int n,double &c[])
|
|
{
|
|
//--- function call
|
|
CLegendre::LegendreCoefficients(n,c);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Poisson distribution |
|
|
//| Returns the sum of the first k+1 terms of the Poisson |
|
|
//| distribution: |
|
|
//| k j |
|
|
//| -- -m m |
|
|
//| > e -- |
|
|
//| -- j! |
|
|
//| j=0 |
|
|
//| The terms are not summed directly; instead the incomplete |
|
|
//| gamma integral is employed, according to the relation |
|
|
//| y = pdtr( k, m ) = igamc( k+1, m ). |
|
|
//| The arguments must both be positive. |
|
|
//| ACCURACY: |
|
|
//| See incomplete gamma function |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::PoissonDistribution(const int k,const double m)
|
|
{
|
|
//--- return result
|
|
return(CPoissonDistr::PoissonDistribution(k,m));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Complemented Poisson distribution |
|
|
//| Returns the sum of the terms k+1 to infinity of the Poisson |
|
|
//| distribution: |
|
|
//| inf. j |
|
|
//| -- -m m |
|
|
//| > e -- |
|
|
//| -- j! |
|
|
//| j=k+1 |
|
|
//| The terms are not summed directly; instead the incomplete |
|
|
//| gamma integral is employed, according to the formula |
|
|
//| y = pdtrc( k, m ) = igam( k+1, m ). |
|
|
//| The arguments must both be positive. |
|
|
//| ACCURACY: |
|
|
//| See incomplete gamma function |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::PoissonComplDistribution(const int k,const double m)
|
|
{
|
|
//--- return result
|
|
return(CPoissonDistr::PoissonComplDistribution(k,m));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Inverse Poisson distribution |
|
|
//| Finds the Poisson variable x such that the integral |
|
|
//| from 0 to x of the Poisson density is equal to the |
|
|
//| given probability y. |
|
|
//| This is accomplished using the inverse gamma integral |
|
|
//| function and the relation |
|
|
//| m = igami( k+1, y ). |
|
|
//| ACCURACY: |
|
|
//| See inverse incomplete gamma function |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::InvPoissonDistribution(const int k,const double y)
|
|
{
|
|
//--- return result
|
|
return(CPoissonDistr::InvPoissonDistribution(k,y));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Psi (digamma) function |
|
|
//| d - |
|
|
//| psi(x) = -- ln | (x) |
|
|
//| dx |
|
|
//| is the logarithmic derivative of the gamma function. |
|
|
//| For integer x, |
|
|
//| n-1 |
|
|
//| - |
|
|
//| psi(n) = -EUL + > 1/k. |
|
|
//| - |
|
|
//| k=1 |
|
|
//| This formula is used for 0 < n <= 10. If x is negative, it |
|
|
//| is transformed to a positive argument by the reflection |
|
|
//| formula psi(1-x) = psi(x) + pi cot(pi x). |
|
|
//| For general positive x, the argument is made greater than 10 |
|
|
//| using the recurrence psi(x+1) = psi(x) + 1/x. |
|
|
//| Then the following asymptotic expansion is applied: |
|
|
//| inf. B |
|
|
//| - 2k |
|
|
//| psi(x) = log(x) - 1/2x - > ------- |
|
|
//| - 2k |
|
|
//| k=1 2k x |
|
|
//| where the B2k are Bernoulli numbers. |
|
|
//| ACCURACY: |
|
|
//| Relative error (except absolute when |psi| < 1): |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE 0,30 30000 1.3e-15 1.4e-16 |
|
|
//| IEEE -30,0 40000 1.5e-15 2.2e-16 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::Psi(const double x)
|
|
{
|
|
//--- return result
|
|
return(CPsiF::Psi(x));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Student's t distribution |
|
|
//| Computes the integral from minus infinity to t of the Student |
|
|
//| t distribution with integer k > 0 degrees of freedom: |
|
|
//| t |
|
|
//| - |
|
|
//| | | |
|
|
//| - | 2 -(k+1)/2 |
|
|
//| | ( (k+1)/2 ) | ( x ) |
|
|
//| ---------------------- | ( 1 + --- ) dx |
|
|
//| - | ( k ) |
|
|
//| sqrt( k pi ) | ( k/2 ) | |
|
|
//| | | |
|
|
//| - |
|
|
//| -inf. |
|
|
//| Relation to incomplete beta integral: |
|
|
//| 1 - stdtr(k,t) = 0.5 * incbet( k/2, 1/2, z ) |
|
|
//| where |
|
|
//| z = k/(k + t**2). |
|
|
//| For t < -2, this is the method of computation. For higher t, |
|
|
//| a direct method is derived from integration by parts. |
|
|
//| Since the function is symmetric about t=0, the area under the |
|
|
//| right tail of the density is found by calling the function |
|
|
//| with -t instead of t. |
|
|
//| ACCURACY: |
|
|
//| Tested at random 1 <= k <= 25. The "domain" refers to t. |
|
|
//| Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE -100,-2 50000 5.9e-15 1.4e-15 |
|
|
//| IEEE -2,100 500000 2.7e-15 4.9e-17 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::StudenttDistribution(const int k,const double t)
|
|
{
|
|
//--- return result
|
|
return(CStudenttDistr::StudenttDistribution(k,t));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Functional inverse of Student's t distribution |
|
|
//| Given probability p, finds the argument t such that stdtr(k,t) |
|
|
//| is equal to p. |
|
|
//| ACCURACY: |
|
|
//| Tested at random 1 <= k <= 100. The "domain" refers to p: |
|
|
//| Relative error: |
|
|
//| arithmetic domain # trials peak rms |
|
|
//| IEEE .001,.999 25000 5.7e-15 8.0e-16 |
|
|
//| IEEE 10^-6,.001 25000 2.0e-12 2.9e-14 |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::InvStudenttDistribution(const int k,const double p)
|
|
{
|
|
//--- return result
|
|
return(CStudenttDistr::InvStudenttDistribution(k,p));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Sine and cosine integrals |
|
|
//| Evaluates the integrals |
|
|
//| x |
|
|
//| - |
|
|
//| | cos t - 1 |
|
|
//| Ci(x) = eul + ln x + | --------- dt, |
|
|
//| | t |
|
|
//| - |
|
|
//| 0 |
|
|
//| x |
|
|
//| - |
|
|
//| | sin t |
|
|
//| Si(x) = | ----- dt |
|
|
//| | t |
|
|
//| - |
|
|
//| 0 |
|
|
//| where eul = 0.57721566490153286061 is Euler's constant. |
|
|
//| The integrals are approximated by rational functions. |
|
|
//| For x > 8 auxiliary functions f(x) and g(x) are employed |
|
|
//| such that |
|
|
//| Ci(x) = f(x) sin(x) - g(x) cos(x) |
|
|
//| Si(x) = pi/2 - f(x) cos(x) - g(x) sin(x) |
|
|
//| ACCURACY: |
|
|
//| Test interval = [0,50]. |
|
|
//| Absolute error, except relative when > 1: |
|
|
//| arithmetic function # trials peak rms |
|
|
//| IEEE Si 30000 4.4e-16 7.3e-17 |
|
|
//| IEEE Ci 30000 6.9e-16 5.1e-17 |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SineCosineIntegrals(const double x,double &si,double &ci)
|
|
{
|
|
//--- initialization
|
|
si=0;
|
|
ci=0;
|
|
//--- function call
|
|
CTrigIntegrals::SineCosineIntegrals(x,si,ci);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Hyperbolic sine and cosine integrals |
|
|
//| Approximates the integrals |
|
|
//| x |
|
|
//| - |
|
|
//| | | cosh t - 1 |
|
|
//| Chi(x) = eul + ln x + | ----------- dt, |
|
|
//| | | t |
|
|
//| - |
|
|
//| 0 |
|
|
//| x |
|
|
//| - |
|
|
//| | | sinh t |
|
|
//| Shi(x) = | ------ dt |
|
|
//| | | t |
|
|
//| - |
|
|
//| 0 |
|
|
//| where eul = 0.57721566490153286061 is Euler's constant. |
|
|
//| The integrals are evaluated by power series for x < 8 |
|
|
//| and by Chebyshev expansions for x between 8 and 88. |
|
|
//| For large x, both functions approach exp(x)/2x. |
|
|
//| Arguments greater than 88 in magnitude return MAXNUM. |
|
|
//| ACCURACY: |
|
|
//| Test interval 0 to 88. |
|
|
//| Relative error: |
|
|
//| arithmetic function # trials peak rms |
|
|
//| IEEE Shi 30000 6.9e-16 1.6e-16 |
|
|
//| Absolute error, except relative when |Chi| > 1: |
|
|
//| IEEE Chi 30000 8.4e-16 1.4e-16 |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::HyperbolicSineCosineIntegrals(const double x,double &shi,double &chi)
|
|
{
|
|
//--- initialization
|
|
shi=0;
|
|
chi=0;
|
|
//--- function call
|
|
CTrigIntegrals::HyperbolicSineCosineIntegrals(x,shi,chi);
|
|
//--- exit the function
|
|
return;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Calculation of the distribution moments: mean, variance, |
|
|
//| skewness, kurtosis. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - sample |
|
|
//| N - N>=0, sample size: |
|
|
//| * if given, only leading N elements of X are |
|
|
//| processed |
|
|
//| * if not given, automatically determined from |
|
|
//| size of X |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Mean - mean. |
|
|
//| Variance- variance. |
|
|
//| Skewness- skewness (if variance<>0; zero otherwise). |
|
|
//| Kurtosis- kurtosis (if variance<>0; zero otherwise). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SampleMoments(const double &x[],const int n,double &mean,
|
|
double &variance,double &skewness,
|
|
double &kurtosis)
|
|
{
|
|
//--- initialization
|
|
mean=0;
|
|
variance=0;
|
|
skewness=0;
|
|
kurtosis=0;
|
|
//--- function call
|
|
CBaseStat::SampleMoments(x,n,mean,variance,skewness,kurtosis);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Calculation of the distribution moments: mean, variance, |
|
|
//| skewness, kurtosis. |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - sample |
|
|
//| N - N>=0, sample size: |
|
|
//| * if given, only leading N elements of X are |
|
|
//| processed |
|
|
//| * if not given, automatically determined from |
|
|
//| size of X |
|
|
//| OUTPUT PARAMETERS |
|
|
//| Mean - mean. |
|
|
//| Variance- variance. |
|
|
//| Skewness- skewness (if variance<>0; zero otherwise). |
|
|
//| Kurtosis- kurtosis (if variance<>0; zero otherwise). |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SampleMoments(const double &x[],double &mean,
|
|
double &variance,double &skewness,
|
|
double &kurtosis)
|
|
{
|
|
//--- create a variable
|
|
int n;
|
|
//--- initialization
|
|
mean=0;
|
|
variance=0;
|
|
skewness=0;
|
|
kurtosis=0;
|
|
//--- get lenght
|
|
n=CAp::Len(x);
|
|
//--- function call
|
|
CBaseStat::SampleMoments(x,n,mean,variance,skewness,kurtosis);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| ADev |
|
|
//| Input parameters: |
|
|
//| X - sample |
|
|
//| N - N>=0, sample size: |
|
|
//| * if given, only leading N elements of X are |
|
|
//| processed |
|
|
//| * if not given, automatically determined from size |
|
|
//| of X |
|
|
//| Output parameters: |
|
|
//| ADev- ADev |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SampleAdev(const double &x[],const int n,double &adev)
|
|
{
|
|
//--- initialization
|
|
adev=0;
|
|
//--- function call
|
|
CBaseStat::SampleAdev(x,n,adev);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| ADev |
|
|
//| Input parameters: |
|
|
//| X - sample |
|
|
//| N - N>=0, sample size: |
|
|
//| * if given, only leading N elements of X are |
|
|
//| processed |
|
|
//| * if not given, automatically determined from size |
|
|
//| of X |
|
|
//| Output parameters: |
|
|
//| ADev- ADev |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SampleAdev(const double &x[],double &adev)
|
|
{
|
|
//--- create a variable
|
|
int n=CAp::Len(x);
|
|
//--- initialization
|
|
adev=0;
|
|
//--- function call
|
|
CBaseStat::SampleAdev(x,n,adev);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Median calculation. |
|
|
//| Input parameters: |
|
|
//| X - sample (array indexes: [0..N-1]) |
|
|
//| N - N>=0, sample size: |
|
|
//| * if given, only leading N elements of X are |
|
|
//| processed |
|
|
//| * if not given, automatically determined from size |
|
|
//| of X |
|
|
//| Output parameters: |
|
|
//| Median |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SampleMedian(const double &x[],const int n,double &median)
|
|
{
|
|
//--- initialization
|
|
median=0;
|
|
//--- function call
|
|
CBaseStat::SampleMedian(x,n,median);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Median calculation. |
|
|
//| Input parameters: |
|
|
//| X - sample (array indexes: [0..N-1]) |
|
|
//| N - N>=0, sample size: |
|
|
//| * if given, only leading N elements of X are |
|
|
//| processed |
|
|
//| * if not given, automatically determined from size |
|
|
//| of X |
|
|
//| Output parameters: |
|
|
//| Median |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SampleMedian(const double &x[],double &median)
|
|
{
|
|
//--- create a variable
|
|
int n=CAp::Len(x);
|
|
//--- initialization
|
|
median=0;
|
|
//--- function call
|
|
CBaseStat::SampleMedian(x,n,median);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Percentile calculation. |
|
|
//| Input parameters: |
|
|
//| X - sample (array indexes: [0..N-1]) |
|
|
//| N - N>=0, sample size: |
|
|
//| * if given, only leading N elements of X are |
|
|
//| processed |
|
|
//| * if not given, automatically determined from size |
|
|
//| of X |
|
|
//| P - percentile (0<=P<=1) |
|
|
//| Output parameters: |
|
|
//| V - percentile |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SamplePercentile(const double &x[],const int n,
|
|
const double p,double &v)
|
|
{
|
|
//--- initialization
|
|
v=0;
|
|
//--- function call
|
|
CBaseStat::SamplePercentile(x,n,p,v);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Percentile calculation. |
|
|
//| Input parameters: |
|
|
//| X - sample (array indexes: [0..N-1]) |
|
|
//| N - N>=0, sample size: |
|
|
//| * if given, only leading N elements of X are |
|
|
//| processed |
|
|
//| * if not given, automatically determined from size |
|
|
//| of X |
|
|
//| P - percentile (0<=P<=1) |
|
|
//| Output parameters: |
|
|
//| V - percentile |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SamplePercentile(const double &x[],const double p,
|
|
double &v)
|
|
{
|
|
//--- create a variable
|
|
int n=CAp::Len(x);
|
|
//--- initialization
|
|
v=0;
|
|
//--- function call
|
|
CBaseStat::SamplePercentile(x,n,p,v);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 2-sample covariance |
|
|
//| Input parameters: |
|
|
//| X - sample 1 (array indexes: [0..N-1]) |
|
|
//| Y - sample 2 (array indexes: [0..N-1]) |
|
|
//| N - N>=0, sample size: |
|
|
//| * if given, only N leading elements of X/Y are |
|
|
//| processed |
|
|
//| * if not given, automatically determined from |
|
|
//| input sizes |
|
|
//| Result: |
|
|
//| covariance (zero for N=0 or N=1) |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::Cov2(const double &x[],const double &y[],const int n)
|
|
{
|
|
//--- return result
|
|
return(CBaseStat::Cov2(x,y,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| 2-sample covariance |
|
|
//| Input parameters: |
|
|
//| X - sample 1 (array indexes: [0..N-1]) |
|
|
//| Y - sample 2 (array indexes: [0..N-1]) |
|
|
//| N - N>=0, sample size: |
|
|
//| * if given, only N leading elements of X/Y are |
|
|
//| processed |
|
|
//| * if not given, automatically determined from |
|
|
//| input sizes |
|
|
//| Result: |
|
|
//| covariance (zero for N=0 or N=1) |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::Cov2(const double &x[],const double &y[])
|
|
{
|
|
//--- check
|
|
if(CAp::Len(x)!=CAp::Len(y))
|
|
{
|
|
Print(__FUNCTION__+": arrays size are not equal");
|
|
CAp::exception_happened=true;
|
|
return(EMPTY_VALUE);
|
|
}
|
|
//--- create a variable
|
|
int n=CAp::Len(x);
|
|
//--- return result
|
|
return(CBaseStat::Cov2(x,y,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Pearson product-moment correlation coefficient |
|
|
//| Input parameters: |
|
|
//| X - sample 1 (array indexes: [0..N-1]) |
|
|
//| Y - sample 2 (array indexes: [0..N-1]) |
|
|
//| N - N>=0, sample size: |
|
|
//| * if given, only N leading elements of X/Y are |
|
|
//| processed |
|
|
//| * if not given, automatically determined from |
|
|
//| input sizes |
|
|
//| Result: |
|
|
//| Pearson product-moment correlation coefficient |
|
|
//| (zero for N=0 or N=1) |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::PearsonCorr2(const double &x[],const double &y[],
|
|
const int n)
|
|
{
|
|
//--- return result
|
|
return(CBaseStat::PearsonCorr2(x,y,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Pearson product-moment correlation coefficient |
|
|
//| Input parameters: |
|
|
//| X - sample 1 (array indexes: [0..N-1]) |
|
|
//| Y - sample 2 (array indexes: [0..N-1]) |
|
|
//| N - N>=0, sample size: |
|
|
//| * if given, only N leading elements of X/Y are |
|
|
//| processed |
|
|
//| * if not given, automatically determined from |
|
|
//| input sizes |
|
|
//| Result: |
|
|
//| Pearson product-moment correlation coefficient |
|
|
//| (zero for N=0 or N=1) |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::PearsonCorr2(const double &x[],const double &y[])
|
|
{
|
|
//--- check
|
|
if(CAp::Len(x)!=CAp::Len(y))
|
|
{
|
|
Print(__FUNCTION__+": arrays size are not equal");
|
|
CAp::exception_happened=true;
|
|
return(EMPTY_VALUE);
|
|
}
|
|
//--- create a variable
|
|
int n=CAp::Len(x);
|
|
//--- return result
|
|
return(CBaseStat::PearsonCorr2(x,y,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Spearman's rank correlation coefficient |
|
|
//| Input parameters: |
|
|
//| X - sample 1 (array indexes: [0..N-1]) |
|
|
//| Y - sample 2 (array indexes: [0..N-1]) |
|
|
//| N - N>=0, sample size: |
|
|
//| * if given, only N leading elements of X/Y are |
|
|
//| processed |
|
|
//| * if not given, automatically determined from |
|
|
//| input sizes |
|
|
//| Result: |
|
|
//| Spearman's rank correlation coefficient |
|
|
//| (zero for N=0 or N=1) |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::SpearmanCorr2(const double &x[],const double &y[],
|
|
const int n)
|
|
{
|
|
//--- return result
|
|
return(CBaseStat::SpearmanCorr2(x,y,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Spearman's rank correlation coefficient |
|
|
//| Input parameters: |
|
|
//| X - sample 1 (array indexes: [0..N-1]) |
|
|
//| Y - sample 2 (array indexes: [0..N-1]) |
|
|
//| N - N>=0, sample size: |
|
|
//| * if given, only N leading elements of X/Y are |
|
|
//| processed |
|
|
//| * if not given, automatically determined from |
|
|
//| input sizes |
|
|
//| Result: |
|
|
//| Spearman's rank correlation coefficient |
|
|
//| (zero for N=0 or N=1) |
|
|
//+------------------------------------------------------------------+
|
|
static double CAlglib::SpearmanCorr2(const double &x[],const double &y[])
|
|
{
|
|
//--- check
|
|
if(CAp::Len(x)!=CAp::Len(y))
|
|
{
|
|
Print(__FUNCTION__+": arrays size are not equal");
|
|
CAp::exception_happened=true;
|
|
return(EMPTY_VALUE);
|
|
}
|
|
//--- create a variable
|
|
int n=CAp::Len(x);
|
|
//--- return result
|
|
return(CBaseStat::SpearmanCorr2(x,y,n));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Covariance matrix |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[N,M], sample matrix: |
|
|
//| * J-th column corresponds to J-th variable |
|
|
//| * I-th row corresponds to I-th observation |
|
|
//| N - N>=0, number of observations: |
|
|
//| * if given, only leading N rows of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| M - M>0, number of variables: |
|
|
//| * if given, only leading M columns of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| C - array[M,M], covariance matrix (zero if N=0 or N=1) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CovM(const CMatrixDouble &x,const int n,const int m,
|
|
CMatrixDouble &c)
|
|
{
|
|
//--- function call
|
|
CBaseStat::CovM(x,n,m,c);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Covariance matrix |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[N,M], sample matrix: |
|
|
//| * J-th column corresponds to J-th variable |
|
|
//| * I-th row corresponds to I-th observation |
|
|
//| N - N>=0, number of observations: |
|
|
//| * if given, only leading N rows of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| M - M>0, number of variables: |
|
|
//| * if given, only leading M columns of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| C - array[M,M], covariance matrix (zero if N=0 or N=1) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CovM(const CMatrixDouble &x,CMatrixDouble &c)
|
|
{
|
|
//--- create variables
|
|
int n=CAp::Rows(x);
|
|
int m=CAp::Cols(x);
|
|
//--- function call
|
|
CBaseStat::CovM(x,n,m,c);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Pearson product-moment correlation matrix |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[N,M], sample matrix: |
|
|
//| * J-th column corresponds to J-th variable |
|
|
//| * I-th row corresponds to I-th observation |
|
|
//| N - N>=0, number of observations: |
|
|
//| * if given, only leading N rows of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| M - M>0, number of variables: |
|
|
//| * if given, only leading M columns of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| C - array[M,M], correlation matrix (zero if N=0 or N=1) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PearsonCorrM(const CMatrixDouble &x,const int n,
|
|
const int m,CMatrixDouble &c)
|
|
{
|
|
//--- function call
|
|
CBaseStat::PearsonCorrM(x,n,m,c);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Pearson product-moment correlation matrix |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[N,M], sample matrix: |
|
|
//| * J-th column corresponds to J-th variable |
|
|
//| * I-th row corresponds to I-th observation |
|
|
//| N - N>=0, number of observations: |
|
|
//| * if given, only leading N rows of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| M - M>0, number of variables: |
|
|
//| * if given, only leading M columns of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| C - array[M,M], correlation matrix (zero if N=0 or N=1) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PearsonCorrM(CMatrixDouble &x,CMatrixDouble &c)
|
|
{
|
|
//--- create variables
|
|
int n=CAp::Rows(x);
|
|
int m=CAp::Cols(x);
|
|
//--- function call
|
|
CBaseStat::PearsonCorrM(x,n,m,c);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Spearman's rank correlation matrix |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[N,M], sample matrix: |
|
|
//| * J-th column corresponds to J-th variable |
|
|
//| * I-th row corresponds to I-th observation |
|
|
//| N - N>=0, number of observations: |
|
|
//| * if given, only leading N rows of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| M - M>0, number of variables: |
|
|
//| * if given, only leading M columns of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| C - array[M,M], correlation matrix (zero if N=0 or N=1) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SpearmanCorrM(const CMatrixDouble &x,const int n,
|
|
const int m,CMatrixDouble &c)
|
|
{
|
|
//--- function call
|
|
CBaseStat::SpearmanCorrM(x,n,m,c);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Spearman's rank correlation matrix |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[N,M], sample matrix: |
|
|
//| * J-th column corresponds to J-th variable |
|
|
//| * I-th row corresponds to I-th observation |
|
|
//| N - N>=0, number of observations: |
|
|
//| * if given, only leading N rows of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| M - M>0, number of variables: |
|
|
//| * if given, only leading M columns of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| C - array[M,M], correlation matrix (zero if N=0 or N=1) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SpearmanCorrM(const CMatrixDouble &x,CMatrixDouble &c)
|
|
{
|
|
//--- create variables
|
|
int n=CAp::Rows(x);
|
|
int m=CAp::Cols(x);
|
|
//--- function call
|
|
CBaseStat::SpearmanCorrM(x,n,m,c);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Cross-covariance matrix |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[N,M1], sample matrix: |
|
|
//| * J-th column corresponds to J-th variable |
|
|
//| * I-th row corresponds to I-th observation |
|
|
//| Y - array[N,M2], sample matrix: |
|
|
//| * J-th column corresponds to J-th variable |
|
|
//| * I-th row corresponds to I-th observation |
|
|
//| N - N>=0, number of observations: |
|
|
//| * if given, only leading N rows of X/Y are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| sizes |
|
|
//| M1 - M1>0, number of variables in X: |
|
|
//| * if given, only leading M1 columns of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| M2 - M2>0, number of variables in Y: |
|
|
//| * if given, only leading M1 columns of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| C - array[M1,M2], cross-covariance matrix (zero if N=0 or|
|
|
//| N=1) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CovM2(const CMatrixDouble &x,const CMatrixDouble &y,
|
|
const int n,const int m1,const int m2,
|
|
CMatrixDouble &c)
|
|
{
|
|
//--- function call
|
|
CBaseStat::CovM2(x,y,n,m1,m2,c);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Cross-covariance matrix |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[N,M1], sample matrix: |
|
|
//| * J-th column corresponds to J-th variable |
|
|
//| * I-th row corresponds to I-th observation |
|
|
//| Y - array[N,M2], sample matrix: |
|
|
//| * J-th column corresponds to J-th variable |
|
|
//| * I-th row corresponds to I-th observation |
|
|
//| N - N>=0, number of observations: |
|
|
//| * if given, only leading N rows of X/Y are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| sizes |
|
|
//| M1 - M1>0, number of variables in X: |
|
|
//| * if given, only leading M1 columns of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| M2 - M2>0, number of variables in Y: |
|
|
//| * if given, only leading M1 columns of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| C - array[M1,M2], cross-covariance matrix (zero if N=0 or|
|
|
//| N=1) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::CovM2(const CMatrixDouble &x,const CMatrixDouble &y,
|
|
CMatrixDouble &c)
|
|
{
|
|
//--- create variables
|
|
int n=CAp::Rows(x);
|
|
int m1=CAp::Cols(x);
|
|
int m2=CAp::Cols(y);
|
|
//--- check
|
|
if(CAp::Rows(x)!=CAp::Rows(y))
|
|
{
|
|
Print(__FUNCTION__+": rows size are not equal");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- function call
|
|
CBaseStat::CovM2(x,y,n,m1,m2,c);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Pearson product-moment cross-correlation matrix |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[N,M1], sample matrix: |
|
|
//| * J-th column corresponds to J-th variable |
|
|
//| * I-th row corresponds to I-th observation |
|
|
//| Y - array[N,M2], sample matrix: |
|
|
//| * J-th column corresponds to J-th variable |
|
|
//| * I-th row corresponds to I-th observation |
|
|
//| N - N>=0, number of observations: |
|
|
//| * if given, only leading N rows of X/Y are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| sizes |
|
|
//| M1 - M1>0, number of variables in X: |
|
|
//| * if given, only leading M1 columns of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| M2 - M2>0, number of variables in Y: |
|
|
//| * if given, only leading M1 columns of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| C - array[M1,M2], cross-correlation matrix (zero if N=0 |
|
|
//| or N=1) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PearsonCorrM2(const CMatrixDouble &x,const CMatrixDouble &y,
|
|
const int n,const int m1,const int m2,
|
|
CMatrixDouble &c)
|
|
{
|
|
//--- function call
|
|
CBaseStat::PearsonCorrM2(x,y,n,m1,m2,c);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Pearson product-moment cross-correlation matrix |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[N,M1], sample matrix: |
|
|
//| * J-th column corresponds to J-th variable |
|
|
//| * I-th row corresponds to I-th observation |
|
|
//| Y - array[N,M2], sample matrix: |
|
|
//| * J-th column corresponds to J-th variable |
|
|
//| * I-th row corresponds to I-th observation |
|
|
//| N - N>=0, number of observations: |
|
|
//| * if given, only leading N rows of X/Y are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| sizes |
|
|
//| M1 - M1>0, number of variables in X: |
|
|
//| * if given, only leading M1 columns of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| M2 - M2>0, number of variables in Y: |
|
|
//| * if given, only leading M1 columns of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| C - array[M1,M2], cross-correlation matrix (zero if N=0 |
|
|
//| or N=1) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PearsonCorrM2(const CMatrixDouble &x,const CMatrixDouble &y,
|
|
CMatrixDouble &c)
|
|
{
|
|
//--- create variables
|
|
int n=CAp::Rows(x);
|
|
int m1=CAp::Cols(x);
|
|
int m2=CAp::Cols(y);
|
|
//--- check
|
|
if(CAp::Rows(x)!=CAp::Rows(y))
|
|
{
|
|
Print(__FUNCTION__+": rows size are not equal");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- function call
|
|
CBaseStat::PearsonCorrM2(x,y,n,m1,m2,c);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Spearman's rank cross-correlation matrix |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[N,M1], sample matrix: |
|
|
//| * J-th column corresponds to J-th variable |
|
|
//| * I-th row corresponds to I-th observation |
|
|
//| Y - array[N,M2], sample matrix: |
|
|
//| * J-th column corresponds to J-th variable |
|
|
//| * I-th row corresponds to I-th observation |
|
|
//| N - N>=0, number of observations: |
|
|
//| * if given, only leading N rows of X/Y are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| sizes |
|
|
//| M1 - M1>0, number of variables in X: |
|
|
//| * if given, only leading M1 columns of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| M2 - M2>0, number of variables in Y: |
|
|
//| * if given, only leading M1 columns of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| C - array[M1,M2], cross-correlation matrix (zero if N=0 |
|
|
//| or N=1) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SpearmanCorrM2(const CMatrixDouble &x,const CMatrixDouble &y,
|
|
const int n,const int m1,const int m2,
|
|
CMatrixDouble &c)
|
|
{
|
|
//--- function call
|
|
CBaseStat::SpearmanCorrM2(x,y,n,m1,m2,c);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Spearman's rank cross-correlation matrix |
|
|
//| INPUT PARAMETERS: |
|
|
//| X - array[N,M1], sample matrix: |
|
|
//| * J-th column corresponds to J-th variable |
|
|
//| * I-th row corresponds to I-th observation |
|
|
//| Y - array[N,M2], sample matrix: |
|
|
//| * J-th column corresponds to J-th variable |
|
|
//| * I-th row corresponds to I-th observation |
|
|
//| N - N>=0, number of observations: |
|
|
//| * if given, only leading N rows of X/Y are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| sizes |
|
|
//| M1 - M1>0, number of variables in X: |
|
|
//| * if given, only leading M1 columns of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| M2 - M2>0, number of variables in Y: |
|
|
//| * if given, only leading M1 columns of X are used |
|
|
//| * if not given, automatically determined from input |
|
|
//| size |
|
|
//| OUTPUT PARAMETERS: |
|
|
//| C - array[M1,M2], cross-correlation matrix (zero if N=0 |
|
|
//| or N=1) |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SpearmanCorrM2(const CMatrixDouble &x,const CMatrixDouble &y,
|
|
CMatrixDouble &c)
|
|
{
|
|
//--- create variables
|
|
int n=CAp::Rows(x);
|
|
int m1=CAp::Cols(x);
|
|
int m2=CAp::Cols(y);
|
|
//--- check
|
|
if(CAp::Rows(x)!=CAp::Rows(y))
|
|
{
|
|
Print(__FUNCTION__+": rows size are not equal");
|
|
CAp::exception_happened=true;
|
|
return;
|
|
}
|
|
//--- function call
|
|
CBaseStat::SpearmanCorrM2(x,y,n,m1,m2,c);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Pearson's correlation coefficient significance test |
|
|
//| This test checks hypotheses about whether X and Y are samples of|
|
|
//| two continuous distributions having zero correlation or whether |
|
|
//| their correlation is non-zero. |
|
|
//| The following tests are performed: |
|
|
//| * two-tailed test (null hypothesis - X and Y have zero |
|
|
//| correlation) |
|
|
//| * left-tailed test (null hypothesis - the correlation |
|
|
//| coefficient is greater than or equal to 0) |
|
|
//| * right-tailed test (null hypothesis - the correlation |
|
|
//| coefficient is less than or equal to 0). |
|
|
//| Requirements: |
|
|
//| * the number of elements in each sample is not less than 5 |
|
|
//| * normality of distributions of X and Y. |
|
|
//| Input parameters: |
|
|
//| R - Pearson's correlation coefficient for X and Y |
|
|
//| N - number of elements in samples, N>=5. |
|
|
//| Output parameters: |
|
|
//| BothTails - p-value for two-tailed test. |
|
|
//| If BothTails is less than the given |
|
|
//| significance level the null hypothesis is |
|
|
//| rejected. |
|
|
//| LeftTail - p-value for left-tailed test. |
|
|
//| If LeftTail is less than the given |
|
|
//| significance level, the null hypothesis is |
|
|
//| rejected. |
|
|
//| RightTail - p-value for right-tailed test. |
|
|
//| If RightTail is less than the given |
|
|
//| significance level the null hypothesis is |
|
|
//| rejected. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::PearsonCorrelationSignificance(const double r,const int n,
|
|
double &bothTails,double &leftTail,
|
|
double &rightTail)
|
|
{
|
|
//--- function call
|
|
CCorrTests::PearsonCorrSignific(r,n,bothTails,leftTail,rightTail);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Spearman's rank correlation coefficient significance test |
|
|
//| This test checks hypotheses about whether X and Y are samples of |
|
|
//| two continuous distributions having zero correlation or whether |
|
|
//| their correlation is non-zero. |
|
|
//| The following tests are performed: |
|
|
//| * two-tailed test (null hypothesis - X and Y have zero |
|
|
//| correlation) |
|
|
//| * left-tailed test (null hypothesis - the correlation |
|
|
//| coefficient is greater than or equal to 0) |
|
|
//| * right-tailed test (null hypothesis - the correlation |
|
|
//| coefficient is less than or equal to 0). |
|
|
//| Requirements: |
|
|
//| * the number of elements in each sample is not less than 5. |
|
|
//| The test is non-parametric and doesn't require distributions X |
|
|
//| and Y to be normal. |
|
|
//| Input parameters: |
|
|
//| R - Spearman's rank correlation coefficient for X and Y |
|
|
//| N - number of elements in samples, N>=5. |
|
|
//| Output parameters: |
|
|
//| BothTails - p-value for two-tailed test. |
|
|
//| If BothTails is less than the given |
|
|
//| significance level the null hypothesis is |
|
|
//| rejected. |
|
|
//| LeftTail - p-value for left-tailed test. |
|
|
//| If LeftTail is less than the given |
|
|
//| significance level, the null hypothesis is |
|
|
//| rejected. |
|
|
//| RightTail - p-value for right-tailed test. |
|
|
//| If RightTail is less than the given |
|
|
//| significance level the null hypothesis is |
|
|
//| rejected. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::SpearmanRankCorrelationSignificance(const double r,
|
|
const int n,
|
|
double &bothTails,
|
|
double &leftTail,
|
|
double &rightTail)
|
|
{
|
|
//--- function call
|
|
CCorrTests::SpearmanRankCorrSignific(r,n,bothTails,leftTail,rightTail);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Jarque-Bera test |
|
|
//| This test checks hypotheses about the fact that a given sample X |
|
|
//| is a sample of normal random variable. |
|
|
//| Requirements: |
|
|
//| * the number of elements in the sample is not less than 5. |
|
|
//| Input parameters: |
|
|
//| X - sample. Array whose index goes from 0 to N-1. |
|
|
//| N - size of the sample. N>=5 |
|
|
//| Output parameters: |
|
|
//| BothTails - p-value for two-tailed test. |
|
|
//| If BothTails is less than the given |
|
|
//| significance level the null hypothesis is |
|
|
//| rejected. |
|
|
//| LeftTail - p-value for left-tailed test. |
|
|
//| If LeftTail is less than the given |
|
|
//| significance level, the null hypothesis is |
|
|
//| rejected. |
|
|
//| RightTail - p-value for right-tailed test. |
|
|
//| If RightTail is less than the given |
|
|
//| significance level the null hypothesis is |
|
|
//| rejected. |
|
|
//| Accuracy of the approximation used (5<=N<=1951): |
|
|
//| p-value relative error (5<=N<=1951) |
|
|
//| [1, 0.1] < 1% |
|
|
//| [0.1, 0.01] < 2% |
|
|
//| [0.01, 0.001] < 6% |
|
|
//| [0.001, 0] wasn't measured |
|
|
//| For N>1951 accuracy wasn't measured but it shouldn't be sharply |
|
|
//| different from table values. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::JarqueBeraTest(const double &x[],const int n,double &p)
|
|
{
|
|
//--- create a variable
|
|
p=0;
|
|
//--- function call
|
|
CJarqueBera::JarqueBeraTest(x,n,p);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Mann-Whitney U-test |
|
|
//| This test checks hypotheses about whether X and Y are samples of |
|
|
//| two continuous distributions of the same shape and same median or|
|
|
//| whether their medians are different. |
|
|
//| The following tests are performed: |
|
|
//| * two-tailed test (null hypothesis - the medians are equal) |
|
|
//| * left-tailed test (null hypothesis - the median of the first|
|
|
//| sample is greater than or equal to the median of the second|
|
|
//| sample) |
|
|
//| * right-tailed test (null hypothesis - the median of the |
|
|
//| first sample is less than or equal to the median of the |
|
|
//| second sample). |
|
|
//| Requirements: |
|
|
//| * the samples are independent |
|
|
//| * X and Y are continuous distributions (or discrete |
|
|
//| distributions well- approximating continuous distributions)|
|
|
//| * distributions of X and Y have the same shape. The only |
|
|
//| possible difference is their position (i.e. the value of |
|
|
//| the median) |
|
|
//| * the number of elements in each sample is not less than 5 |
|
|
//| * the scale of measurement should be ordinal, interval or |
|
|
//| ratio (i.e. the test could not be applied to nominal |
|
|
//| variables). |
|
|
//| The test is non-parametric and doesn't require distributions to |
|
|
//| be normal. |
|
|
//| Input parameters: |
|
|
//| X - sample 1. Array whose index goes from 0 to N-1. |
|
|
//| N - size of the sample. N>=5 |
|
|
//| Y - sample 2. Array whose index goes from 0 to M-1. |
|
|
//| M - size of the sample. M>=5 |
|
|
//| Output parameters: |
|
|
//| BothTails - p-value for two-tailed test. |
|
|
//| If BothTails is less than the given |
|
|
//| significance level the null hypothesis is |
|
|
//| rejected. |
|
|
//| LeftTail - p-value for left-tailed test. |
|
|
//| If LeftTail is less than the given |
|
|
//| significance level, the null hypothesis is |
|
|
//| rejected. |
|
|
//| RightTail - p-value for right-tailed test. |
|
|
//| If RightTail is less than the given |
|
|
//| significance level the null hypothesis is |
|
|
//| rejected. |
|
|
//| To calculate p-values, special approximation is used. This |
|
|
//| method lets us calculate p-values with satisfactory accuracy in |
|
|
//| interval [0.0001, 1]. There is no approximation outside the |
|
|
//| [0.0001, 1] interval. Therefore, if the significance level |
|
|
//| outlies this interval, the test returns 0.0001. |
|
|
//| Relative precision of approximation of p-value: |
|
|
//| N M Max.err. Rms.err. |
|
|
//| 5..10 N..10 1.4e-02 6.0e-04 |
|
|
//| 5..10 N..100 2.2e-02 5.3e-06 |
|
|
//| 10..15 N..15 1.0e-02 3.2e-04 |
|
|
//| 10..15 N..100 1.0e-02 2.2e-05 |
|
|
//| 15..100 N..100 6.1e-03 2.7e-06 |
|
|
//| For N,M>100 accuracy checks weren't put into practice, but taking|
|
|
//| into account characteristics of asymptotic approximation used, |
|
|
//| precision should not be sharply different from the values for |
|
|
//| interval [5, 100]. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::MannWhitneyUTest(const double &x[],const int n,
|
|
const double &y[],const int m,
|
|
double &bothTails,double &leftTail,
|
|
double &rightTail)
|
|
{
|
|
//--- function call
|
|
CMannWhitneyU::CMannWhitneyUTest(x,n,y,m,bothTails,leftTail,rightTail);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Sign test |
|
|
//| This test checks three hypotheses about the median of the given |
|
|
//| sample. |
|
|
//| The following tests are performed: |
|
|
//| * two-tailed test (null hypothesis - the median is equal to |
|
|
//| the given value) |
|
|
//| * left-tailed test (null hypothesis - the median is greater |
|
|
//| than or equal to the given value) |
|
|
//| * right-tailed test (null hypothesis - the median is less |
|
|
//| than or equal to the given value) |
|
|
//| Requirements: |
|
|
//| * the scale of measurement should be ordinal, interval or |
|
|
//| ratio (i.e. the test could not be applied to nominal |
|
|
//| variables). |
|
|
//| The test is non-parametric and doesn't require distribution X to |
|
|
//| be normal |
|
|
//| Input parameters: |
|
|
//| X - sample. Array whose index goes from 0 to N-1. |
|
|
//| N - size of the sample. |
|
|
//| Median - assumed median value. |
|
|
//| Output parameters: |
|
|
//| BothTails - p-value for two-tailed test. |
|
|
//| If BothTails is less than the given |
|
|
//| significance level the null hypothesis is |
|
|
//| rejected. |
|
|
//| LeftTail - p-value for left-tailed test. |
|
|
//| If LeftTail is less than the given |
|
|
//| significance level, the null hypothesis is |
|
|
//| rejected. |
|
|
//| RightTail - p-value for right-tailed test. |
|
|
//| If RightTail is less than the given |
|
|
//| significance levelthe null hypothesis is |
|
|
//| rejected. |
|
|
//| While calculating p-values high-precision binomial distribution |
|
|
//| approximation is used, so significance levels have about 15 exact|
|
|
//| digits. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::OneSampleSignTest(const double &x[],const int n,
|
|
const double median,double &bothTails,
|
|
double &leftTail,double &rightTail)
|
|
{
|
|
//--- function call
|
|
CSignTest::OneSampleSignTest(x,n,median,bothTails,leftTail,rightTail);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| One-sample t-test |
|
|
//| This test checks three hypotheses about the mean of the given |
|
|
//| sample. The following tests are performed: |
|
|
//| * two-tailed test (null hypothesis - the mean is equal to the|
|
|
//| given value) |
|
|
//| * left-tailed test (null hypothesis - the mean is greater |
|
|
//| than or equal to the given value) |
|
|
//| * right-tailed test (null hypothesis - the mean is less than |
|
|
//| or equal to the given value). |
|
|
//| The test is based on the assumption that a given sample has a |
|
|
//| normal distribution and an unknown dispersion. If the |
|
|
//| distribution sharply differs from normal, the test will work |
|
|
//| incorrectly. |
|
|
//| Input parameters: |
|
|
//| X - sample. Array whose index goes from 0 to N-1. |
|
|
//| N - size of sample. |
|
|
//| Mean - assumed value of the mean. |
|
|
//| Output parameters: |
|
|
//| BothTails - p-value for two-tailed test. |
|
|
//| If BothTails is less than the given |
|
|
//| significance level the null hypothesis is |
|
|
//| rejected. |
|
|
//| LeftTail - p-value for left-tailed test. |
|
|
//| If LeftTail is less than the given |
|
|
//| significance level, the null hypothesis is |
|
|
//| rejected. |
|
|
//| RightTail - p-value for right-tailed test. |
|
|
//| If RightTail is less than the given |
|
|
//| significance level the null hypothesis is |
|
|
//| rejected. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::StudentTest1(const double &x[],const int n,const double mean,
|
|
double &bothTails,double &leftTail,
|
|
double &rightTail)
|
|
{
|
|
//--- function call
|
|
CStudentTests::StudentTest1(x,n,mean,bothTails,leftTail,rightTail);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Two-sample pooled test |
|
|
//| This test checks three hypotheses about the mean of the given |
|
|
//| samples. The following tests are performed: |
|
|
//| * two-tailed test (null hypothesis - the means are equal) |
|
|
//| * left-tailed test (null hypothesis - the mean of the first |
|
|
//| sample is greater than or equal to the mean of the second |
|
|
//| sample) |
|
|
//| * right-tailed test (null hypothesis - the mean of the first |
|
|
//| sample is less than or equal to the mean of the second |
|
|
//| sample). |
|
|
//| Test is based on the following assumptions: |
|
|
//| * given samples have normal distributions |
|
|
//| * dispersions are equal |
|
|
//| * samples are independent. |
|
|
//| Input parameters: |
|
|
//| X - sample 1. Array whose index goes from 0 to N-1. |
|
|
//| N - size of sample. |
|
|
//| Y - sample 2. Array whose index goes from 0 to M-1. |
|
|
//| M - size of sample. |
|
|
//| Output parameters: |
|
|
//| BothTails - p-value for two-tailed test. |
|
|
//| If BothTails is less than the given |
|
|
//| significance level the null hypothesis is |
|
|
//| rejected. |
|
|
//| LeftTail - p-value for left-tailed test. |
|
|
//| If LeftTail is less than the given |
|
|
//| significance level, the null hypothesis is |
|
|
//| rejected. |
|
|
//| RightTail - p-value for right-tailed test. |
|
|
//| If RightTail is less than the given |
|
|
//| significance level the null hypothesis is |
|
|
//| rejected. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::StudentTest2(const double &x[],const int n,const double &y[],
|
|
const int m,double &bothTails,
|
|
double &leftTail,double &rightTail)
|
|
{
|
|
//--- function call
|
|
CStudentTests::StudentTest2(x,n,y,m,bothTails,leftTail,rightTail);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Two-sample unpooled test |
|
|
//| This test checks three hypotheses about the mean of the given |
|
|
//| samples. The following tests are performed: |
|
|
//| * two-tailed test (null hypothesis - the means are equal) |
|
|
//| * left-tailed test (null hypothesis - the mean of the first |
|
|
//| sample is greater than or equal to the mean of the second |
|
|
//| sample) |
|
|
//| * right-tailed test (null hypothesis - the mean of the first |
|
|
//| sample is less than or equal to the mean of the second |
|
|
//| sample). |
|
|
//| Test is based on the following assumptions: |
|
|
//| * given samples have normal distributions |
|
|
//| * samples are independent. |
|
|
//| Dispersion equality is not required |
|
|
//| Input parameters: |
|
|
//| X - sample 1. Array whose index goes from 0 to N-1. |
|
|
//| N - size of the sample. |
|
|
//| Y - sample 2. Array whose index goes from 0 to M-1. |
|
|
//| M - size of the sample. |
|
|
//| Output parameters: |
|
|
//| BothTails - p-value for two-tailed test. |
|
|
//| If BothTails is less than the given |
|
|
//| significance level the null hypothesis is |
|
|
//| rejected. |
|
|
//| LeftTail - p-value for left-tailed test. |
|
|
//| If LeftTail is less than the given |
|
|
//| significance level, the null hypothesis is |
|
|
//| rejected. |
|
|
//| RightTail - p-value for right-tailed test. |
|
|
//| If RightTail is less than the given |
|
|
//| significance level the null hypothesis is |
|
|
//| rejected. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::UnequalVarianceTest(const double &x[],const int n,
|
|
const double &y[],const int m,
|
|
double &bothTails,double &leftTail,
|
|
double &rightTail)
|
|
{
|
|
//--- function call
|
|
CStudentTests::UnequalVarianceTest(x,n,y,m,bothTails,leftTail,rightTail);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Two-sample F-test |
|
|
//| This test checks three hypotheses about dispersions of the given |
|
|
//| samples. The following tests are performed: |
|
|
//| * two-tailed test (null hypothesis - the dispersions are |
|
|
//| equal) |
|
|
//| * left-tailed test (null hypothesis - the dispersion of the |
|
|
//| first sample is greater than or equal to the dispersion of |
|
|
//| the second sample). |
|
|
//| * right-tailed test (null hypothesis - the dispersion of the |
|
|
//| first sample is less than or equal to the dispersion of |
|
|
//| the second sample) |
|
|
//| The test is based on the following assumptions: |
|
|
//| * the given samples have normal distributions |
|
|
//| * the samples are independent. |
|
|
//| Input parameters: |
|
|
//| X - sample 1. Array whose index goes from 0 to N-1. |
|
|
//| N - sample size. |
|
|
//| Y - sample 2. Array whose index goes from 0 to M-1. |
|
|
//| M - sample size. |
|
|
//| Output parameters: |
|
|
//| BothTails - p-value for two-tailed test. |
|
|
//| If BothTails is less than the given |
|
|
//| significance level the null hypothesis is |
|
|
//| rejected. |
|
|
//| LeftTail - p-value for left-tailed test. |
|
|
//| If LeftTail is less than the given |
|
|
//| significance level, the null hypothesis is |
|
|
//| rejected. |
|
|
//| RightTail - p-value for right-tailed test. |
|
|
//| If RightTail is less than the given |
|
|
//| significance level the null hypothesis is |
|
|
//| rejected. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::FTest(const double &x[],const int n,const double &y[],
|
|
const int m,double &bothTails,double &leftTail,
|
|
double &rightTail)
|
|
{
|
|
//--- function call
|
|
CVarianceTests::FTest(x,n,y,m,bothTails,leftTail,rightTail);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| One-sample chi-square test |
|
|
//| This test checks three hypotheses about the dispersion of the |
|
|
//| given sample The following tests are performed: |
|
|
//| * two-tailed test (null hypothesis - the dispersion equals |
|
|
//| the given number) |
|
|
//| * left-tailed test (null hypothesis - the dispersion is |
|
|
//| greater than or equal to the given number) |
|
|
//| * right-tailed test (null hypothesis - dispersion is less |
|
|
//| than or equal to the given number). |
|
|
//| Test is based on the following assumptions: |
|
|
//| * the given sample has a normal distribution. |
|
|
//| Input parameters: |
|
|
//| X - sample 1. Array whose index goes from 0 to |
|
|
//| N-1. |
|
|
//| N - size of the sample. |
|
|
//| Variance - dispersion value to compare with. |
|
|
//| Output parameters: |
|
|
//| BothTails - p-value for two-tailed test. |
|
|
//| If BothTails is less than the given |
|
|
//| significance level the null hypothesis is |
|
|
//| rejected. |
|
|
//| LeftTail - p-value for left-tailed test. |
|
|
//| If LeftTail is less than the given |
|
|
//| significance level, the null hypothesis is |
|
|
//| rejected. |
|
|
//| RightTail - p-value for right-tailed test. |
|
|
//| If RightTail is less than the given |
|
|
//| significance level the null hypothesis is |
|
|
//| rejected. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::OneSampleVarianceTest(double &x[],int n,double variance,
|
|
double &bothTails,double &leftTail,
|
|
double &rightTail)
|
|
{
|
|
//--- function call
|
|
CVarianceTests::OneSampleVarianceTest(x,n,variance,bothTails,leftTail,rightTail);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Wilcoxon signed-rank test |
|
|
//| This test checks three hypotheses about the median of the given |
|
|
//| sample. The following tests are performed: |
|
|
//| * two-tailed test (null hypothesis - the median is equal to |
|
|
//| the given value) |
|
|
//| * left-tailed test (null hypothesis - the median is greater |
|
|
//| than or equal to the given value) |
|
|
//| * right-tailed test (null hypothesis - the median is less |
|
|
//| than or equal to the given value) |
|
|
//| Requirements: |
|
|
//| * the scale of measurement should be ordinal, interval or |
|
|
//| ratio (i.e. the test could not be applied to nominal |
|
|
//| variables). |
|
|
//| * the distribution should be continuous and symmetric |
|
|
//| relative to its median. |
|
|
//| * number of distinct values in the X array should be greater |
|
|
//| than 4 |
|
|
//| The test is non-parametric and doesn't require distribution X to |
|
|
//| be normal |
|
|
//| Input parameters: |
|
|
//| X - sample. Array whose index goes from 0 to N-1. |
|
|
//| N - size of the sample. |
|
|
//| Median - assumed median value. |
|
|
//| Output parameters: |
|
|
//| BothTails - p-value for two-tailed test. |
|
|
//| If BothTails is less than the given |
|
|
//| significance level the null hypothesis is |
|
|
//| rejected. |
|
|
//| LeftTail - p-value for left-tailed test. |
|
|
//| If LeftTail is less than the given |
|
|
//| significance level, the null hypothesis is |
|
|
//| rejected. |
|
|
//| RightTail - p-value for right-tailed test. |
|
|
//| If RightTail is less than the given |
|
|
//| significance level the null hypothesis is |
|
|
//| rejected. |
|
|
//| To calculate p-values, special approximation is used. This method|
|
|
//| lets us calculate p-values with two decimal places in interval |
|
|
//| [0.0001, 1]. |
|
|
//| "Two decimal places" does not sound very impressive, but in |
|
|
//| practice the relative error of less than 1% is enough to make a |
|
|
//| decision. |
|
|
//| There is no approximation outside the [0.0001, 1] interval. |
|
|
//| Therefore, if the significance level outlies this interval, the |
|
|
//| test returns 0.0001. |
|
|
//+------------------------------------------------------------------+
|
|
static void CAlglib::WilcoxonSignedRankTest(const double &x[],const int n,
|
|
const double e,double &bothTails,
|
|
double &leftTail,double &rightTail)
|
|
{
|
|
//--- function call
|
|
CWilcoxonSignedRank::WilcoxonSignedRankTest(x,n,e,bothTails,leftTail,rightTail);
|
|
}
|
|
//+------------------------------------------------------------------+
|