Example #1
0
ExplicitEquation::FitError ExplicitEquation::Fit(DataSource &series, double &r2) {
	r2 = 0;
	if (series.IsExplicit() || series.IsParam())
		return InadequateDataSource;
	
	if (series.GetCount() < coeff.GetCount())
		return SmallDataSource;
	
	ptrdiff_t numUnknowns = coeff.GetCount();
	
	VectorXd x(numUnknowns);
	for (int i = 0; i < numUnknowns; ++i)
		x(i) = coeff[i];
	
	Equation_functor functor;	
	functor.series = &series;
	functor.fSource = this;
	functor.unknowns = numUnknowns;
	functor.datasetLen = series.GetCount();
	
	NumericalDiff<Equation_functor> numDiff(functor);
	LevenbergMarquardt<NumericalDiff<Equation_functor> > lm(numDiff);
// 	ftol is a nonnegative input variable that measures the relative error desired in the sum of squares 
	lm.parameters.ftol = 1.E4*NumTraits<double>::epsilon();
//  xtol is a nonnegative input variable that measures the relative error desired in the approximate solution
	lm.parameters.xtol = 1.E4*NumTraits<double>::epsilon();
	lm.parameters.maxfev = maxFitFunctionEvaluations;
	int ret = lm.minimize(x);
	if (ret == LevenbergMarquardtSpace::ImproperInputParameters)
		return ExplicitEquation::ImproperInputParameters;
	if (ret == LevenbergMarquardtSpace::TooManyFunctionEvaluation)
		return TooManyFunctionEvaluation;

	double mean = series.AvgY();
	double sse = 0, sst = 0;
	for (int64 i = 0; i < series.GetCount(); ++i) {
		double y = series.y(i);
		if (!IsNull(y)) {
			double res = y - f(series.x(i));
			sse += res*res;
			double d = y - mean;
			sst += d*d;
		}
	}
	r2 = 1 - sse/sst;

	return NoError;
}
Example #2
0
ExplicitEquation::FitError SplineEquation::Fit(DataSource &data, double &r2)
{	
	Vector<Pointf> seriesRaw;
	for (int64 i = 0; i < data.GetCount(); ++i) {		// Remove Nulls	
		if (!IsNull(data.x(i)) && !IsNull(data.y(i)))
			seriesRaw << Pointf(data.x(i), data.y(i));
	}

	if(seriesRaw.IsEmpty())
        return InadequateDataSource;
        	
	PointfLess less;
	Sort(seriesRaw, less);								// Sort
	
	Vector<Pointf> series;
	for (int i = 1; i < seriesRaw.GetCount(); ++i) {	// Remove points with duplicate x
		if (seriesRaw[i].x != seriesRaw[i - 1].x)
			series << seriesRaw[i];	
	}

	r2 = 0;
	
    int n = int(series.GetCount()) - 1;
    
    Buffer<double> h(n);
    for(int i = 0; i < n; ++i)
        h[i] = (series[i+1].x - series[i].x);

    Buffer<double> alpha(n);
    for(int i = 1; i < n; ++i)
        alpha[i] = (3.*(series[i+1].y - series[i].y)/h[i] - 3*(series[i].y - series[i-1].y)/h[i-1]);

    Buffer<double> c(n+1), l(n+1), mu(n+1), z(n+1);
    l[0] = 1;
    mu[0] = 0;
    z[0] = 0;

    for(int i = 1; i < n; ++i) {
        l[i] = 2.*(series[i+1].x - series[i-1].x) - h[i-1]*mu[i-1];
        mu[i] = h[i]/l[i];
        z[i] = (alpha[i] - h[i-1]*z[i-1])/l[i];
    }

    l[n] = 1.;
    z[n] = 0;
    c[n] = 0;

	Buffer<double> b(n), d(n);
    for(int i = n-1; i >= 0; --i) {
        c[i] = z[i] - mu[i] * c[i+1];
        b[i] = (series[i+1].y - series[i].y)/h[i] - h[i]*(c[i+1] + 2*c[i])/3.;
        d[i] = (c[i+1] - c[i])/3./h[i];
    }

	ncoeff = n;
    coeff.Alloc(ncoeff);
    for(int i = 0; i < n; ++i) {
        coeff[i].x = series[i].x;
        coeff[i].a = series[i].y;
        coeff[i].b = b[i];
        coeff[i].c = c[i];
        coeff[i].d = d[i];
    }
    return NoError;
}