<?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 <[email protected]> 
     * 
     * 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 
?> 
 
 |