[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/phpexcel/PHPExcel/Shared/trend/ -> polynomialBestFitClass.php (source)

   1  <?php
   2  
   3  require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php';
   4  require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/Matrix.php';
   5  
   6  /**
   7   * PHPExcel_Polynomial_Best_Fit
   8   *
   9   * Copyright (c) 2006 - 2015 PHPExcel
  10   *
  11   * This library is free software; you can redistribute it and/or
  12   * modify it under the terms of the GNU Lesser General Public
  13   * License as published by the Free Software Foundation; either
  14   * version 2.1 of the License, or (at your option) any later version.
  15   *
  16   * This library is distributed in the hope that it will be useful,
  17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  19   * Lesser General Public License for more details.
  20   *
  21   * You should have received a copy of the GNU Lesser General Public
  22   * License along with this library; if not, write to the Free Software
  23   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  24   *
  25   * @category   PHPExcel
  26   * @package    PHPExcel_Shared_Trend
  27   * @copyright  Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  28   * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
  29   * @version    ##VERSION##, ##DATE##
  30   */
  31  class PHPExcel_Polynomial_Best_Fit extends PHPExcel_Best_Fit
  32  {
  33      /**
  34       * Algorithm type to use for best-fit
  35       * (Name of this trend class)
  36       *
  37       * @var    string
  38       **/
  39      protected $bestFitType = 'polynomial';
  40  
  41      /**
  42       * Polynomial order
  43       *
  44       * @protected
  45       * @var    int
  46       **/
  47      protected $order = 0;
  48  
  49  
  50      /**
  51       * Return the order of this polynomial
  52       *
  53       * @return     int
  54       **/
  55      public function getOrder()
  56      {
  57          return $this->order;
  58      }
  59  
  60  
  61      /**
  62       * Return the Y-Value for a specified value of X
  63       *
  64       * @param     float        $xValue            X-Value
  65       * @return     float                        Y-Value
  66       **/
  67      public function getValueOfYForX($xValue)
  68      {
  69          $retVal = $this->getIntersect();
  70          $slope = $this->getSlope();
  71          foreach ($slope as $key => $value) {
  72              if ($value != 0.0) {
  73                  $retVal += $value * pow($xValue, $key + 1);
  74              }
  75          }
  76          return $retVal;
  77      }
  78  
  79  
  80      /**
  81       * Return the X-Value for a specified value of Y
  82       *
  83       * @param     float        $yValue            Y-Value
  84       * @return     float                        X-Value
  85       **/
  86      public function getValueOfXForY($yValue)
  87      {
  88          return ($yValue - $this->getIntersect()) / $this->getSlope();
  89      }
  90  
  91  
  92      /**
  93       * Return the Equation of the best-fit line
  94       *
  95       * @param     int        $dp        Number of places of decimal precision to display
  96       * @return     string
  97       **/
  98      public function getEquation($dp = 0)
  99      {
 100          $slope = $this->getSlope($dp);
 101          $intersect = $this->getIntersect($dp);
 102  
 103          $equation = 'Y = ' . $intersect;
 104          foreach ($slope as $key => $value) {
 105              if ($value != 0.0) {
 106                  $equation .= ' + ' . $value . ' * X';
 107                  if ($key > 0) {
 108                      $equation .= '^' . ($key + 1);
 109                  }
 110              }
 111          }
 112          return $equation;
 113      }
 114  
 115  
 116      /**
 117       * Return the Slope of the line
 118       *
 119       * @param     int        $dp        Number of places of decimal precision to display
 120       * @return     string
 121       **/
 122      public function getSlope($dp = 0)
 123      {
 124          if ($dp != 0) {
 125              $coefficients = array();
 126              foreach ($this->_slope as $coefficient) {
 127                  $coefficients[] = round($coefficient, $dp);
 128              }
 129              return $coefficients;
 130          }
 131          return $this->_slope;
 132      }
 133  
 134  
 135      public function getCoefficients($dp = 0)
 136      {
 137          return array_merge(array($this->getIntersect($dp)), $this->getSlope($dp));
 138      }
 139  
 140  
 141      /**
 142       * Execute the regression and calculate the goodness of fit for a set of X and Y data values
 143       *
 144       * @param    int            $order        Order of Polynomial for this regression
 145       * @param    float[]        $yValues    The set of Y-values for this regression
 146       * @param    float[]        $xValues    The set of X-values for this regression
 147       * @param    boolean        $const
 148       */
 149      private function polynomialRegression($order, $yValues, $xValues, $const)
 150      {
 151          // calculate sums
 152          $x_sum = array_sum($xValues);
 153          $y_sum = array_sum($yValues);
 154          $xx_sum = $xy_sum = 0;
 155          for ($i = 0; $i < $this->valueCount; ++$i) {
 156              $xy_sum += $xValues[$i] * $yValues[$i];
 157              $xx_sum += $xValues[$i] * $xValues[$i];
 158              $yy_sum += $yValues[$i] * $yValues[$i];
 159          }
 160          /*
 161           *    This routine uses logic from the PHP port of polyfit version 0.1
 162           *    written by Michael Bommarito and Paul Meagher
 163           *
 164           *    The function fits a polynomial function of order $order through
 165           *    a series of x-y data points using least squares.
 166           *
 167           */
 168          for ($i = 0; $i < $this->valueCount; ++$i) {
 169              for ($j = 0; $j <= $order; ++$j) {
 170                  $A[$i][$j] = pow($xValues[$i], $j);
 171              }
 172          }
 173          for ($i=0; $i < $this->valueCount; ++$i) {
 174              $B[$i] = array($yValues[$i]);
 175          }
 176          $matrixA = new Matrix($A);
 177          $matrixB = new Matrix($B);
 178          $C = $matrixA->solve($matrixB);
 179  
 180          $coefficients = array();
 181          for ($i = 0; $i < $C->m; ++$i) {
 182              $r = $C->get($i, 0);
 183              if (abs($r) <= pow(10, -9)) {
 184                  $r = 0;
 185              }
 186              $coefficients[] = $r;
 187          }
 188  
 189          $this->intersect = array_shift($coefficients);
 190          $this->_slope = $coefficients;
 191  
 192          $this->calculateGoodnessOfFit($x_sum, $y_sum, $xx_sum, $yy_sum, $xy_sum);
 193          foreach ($this->xValues as $xKey => $xValue) {
 194              $this->yBestFitValues[$xKey] = $this->getValueOfYForX($xValue);
 195          }
 196      }
 197  
 198  
 199      /**
 200       * Define the regression and calculate the goodness of fit for a set of X and Y data values
 201       *
 202       * @param    int            $order        Order of Polynomial for this regression
 203       * @param    float[]        $yValues    The set of Y-values for this regression
 204       * @param    float[]        $xValues    The set of X-values for this regression
 205       * @param    boolean        $const
 206       */
 207      public function __construct($order, $yValues, $xValues = array(), $const = true)
 208      {
 209          if (parent::__construct($yValues, $xValues) !== false) {
 210              if ($order < $this->valueCount) {
 211                  $this->bestFitType .= '_'.$order;
 212                  $this->order = $order;
 213                  $this->polynomialRegression($order, $yValues, $xValues, $const);
 214                  if (($this->getGoodnessOfFit() < 0.0) || ($this->getGoodnessOfFit() > 1.0)) {
 215                      $this->_error = true;
 216                  }
 217              } else {
 218                  $this->_error = true;
 219              }
 220          }
 221      }
 222  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1