Subversion Repositories eFlore/Applications.cel

Rev

Rev 2388 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2388 jpm 1
<?php
2
/**
3
 * PHPExcel
4
 *
5
 * Copyright (c) 2006 - 2013 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 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel)
24
 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt	LGPL
25
 * @version    ##VERSION##, ##DATE##
26
 */
27
 
28
 
29
require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php';
30
require_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 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel)
39
 */
40
class 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