<?php
/*
* FunctionFit
*
* This class perform linear least squres fitting to a linear
* combination of user defined functions in the form
* y=a0+a1*F1(X)+ ... + an*Fn(X)
*
* Copyright (C) 2013 José Gómez López
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
require_once('LinearFit.php');
/**
* FunctionFit
*
* @author José Gómez López <jose.gomez.lopez@gmail.com>
*
* This class perform linear least squres fitting to a linear
* combination of user defined functions in the form
* y=a0+a1*F1(X)+ ... + an*Fn(X)
* It uses LinearFit class the independent variable vector is transformated
* in an array which elements are its function values
**/
class FunctionFit extends LinearFit
{
private $X;
private $Y;
private $Func;
private $Size;
private $Vars;
private $nY;
/**
* Initialize data
*
* Initialize internal data and prepare for next calculation
**/
protected function init()
{
$this->X=array();
$this->Y=array();
$this->Func=array();
$this->Conf=array();
$this->Size=0;
$this->Vars=0;
$this->nY=0;
} // End of init()
/**
* Constructor
*
* Create a new object
**/
public function __construct ()
{
$this->init();
} // End of function __construct
/**
* Set Functions
*
* sets foron array set for fitting
* @param array $aFunction array of functions
**/
public function SetFunctions($aFunction)
{
if (count($this->Func) > 0)
{
$this->Coeffs=array();
$this->Conf=array();
parent::init();
}
$this->Func=$aFunction;
if ($this->Size>0)
{
for ($i=0; $i<count($this->Func); $i++)
{
for ($j=0; $j<count($this->X); $j++)
{
$adX[$j][$i]=call_user_func($this->Func[$i],$this->X[$j]);
}
}
parent::SetData($adX, $this->Y);
}
}
/**
* Add New data
*
* Add new data to the fitting process
* @param array double $adX vector with values for each variable
* @param double $dY value corresponding to $adX
**/
public function AddData ($adX, $dY)
{
if ($this->Size>0 && $this->Vars>0 && $this->Vars != count($adX))
{
throw new Exception('# of variables of stored data and input vector is different');
}
else
{
$this->Size++;
$this->Vars=count($adX);
if (is_array($dY))
{
if ($this->nY==0)
{
$this->nY=count($dY);
}
if (count($dY) != $this->nY )
{
throw new Exception('Number of Y elements is wrong');
}
}
else
{
if ($this->nY==0)
{
$this->nY=1;
}
if ($this->nY != 1)
{
throw new Exception('Y must be an array');
}
}
$this->Y[]=$dY;
$this->X[]=$adX;
if (count($this->Func)>0)
{
for ($i=0; $i<count($this->Func); $i++)
{
$adXr[$i]=call_user_func($this->Func[$i],$adX);
}
parent::AddData($adXr,$dY);
}
} // End of if
} // End of AddData
/**
* Set New data
*
* Set new data destroying previous data
* @param array double $adX matrix with a set of X values
* @param array double $adY vector of values corresponding to each row of $adX
**/
public function SetData($adX, $adY)
{
if (count($adX) != count($adY))
{
throw new Exception('The size of both arrays should be the same');
}
else
{
$this->Size=count($adX);
if (is_array($adX[0]))
{
$this->Vars=count($adX[0]);
}
else
{
$this->Vars=1;
}
$this->Y=$adY;
$this->X=$adX;
if ( is_array($adY[0]) )
{
$this->nY=count($adY[0]);
}
else
{
$this->nY=1;
}
if (count($this->Func)>0)
{
if (count($this->X)>0)
{
for ($i=0; $i<count($this->Func); $i++)
{
for ($j=0; $j<count($adX); $j++)
{
$adXr[$j][$i]=call_user_func($this->Func[$i],$adX[$j]);
}
}
parent::SetData($adXr, $this->Y);
}
}
} // End of if
} // End of setData
/**
* Get values from an input
*
* Get the values of an input using the calculated coefficients
* @param array double $adX input to get the values
**/
public function GetValues($adXo)
{
if (count($this->Func)>0)
{
if (!is_array($adXo))
{
$adXin=array($adXo);
}
else
{
$adXin=$adXo;
}
for ($i=0; $i<count($this->Func); $i++)
{
for ($j=0; $j<count($adXin); $j++)
{
$adXr[$j][$i]=call_user_func($this->Func[$i],$adXin[$j]);
}
}
if (!is_array($adXo))
{
return parent::GetValues($adXr)[0];
}
else
{
return parent::GetValues($adXr);
}
}
}
} // End of class FunctionFit
?>
|