source: sourcecode/application/libraries/PHPExcel/Shared/trend/polynomialBestFitClass.php @ 1

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