MathUtils.class.php

Go to the documentation of this file.
00001 <?php
00002 /***************************************************************************
00003  *   Copyright (C) 2009 by Denis M. Gabaidulin                             *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU Lesser General Public License as        *
00007  *   published by the Free Software Foundation; either version 3 of the    *
00008  *   License, or (at your option) any later version.                       *
00009  *                                                                         *
00010  ***************************************************************************/
00011 
00015     final class MathUtils extends StaticFactory
00016     {
00020         public static function fisherYatesShuffle(&$elts)
00021         {
00022             $num = count($elts);
00023             
00024             for ($i = $num - 1; $i > 0; --$i) {
00025                 $j = mt_rand(0, $i);
00026                 
00027                 $tmp        = $elts[$i];
00028                 $elts[$i]   = $elts[$j];
00029                 $elts[$j]   = $tmp;
00030             }
00031         }
00032         
00033         public static function makeCartesianProduct(
00034             $arrays, $generateHash = false
00035         )
00036         {
00037             $result = array();
00038             
00039             $size = (sizeof($arrays) > 0) ? 1 : 0;
00040             
00041             foreach ($arrays as $array)
00042                 $size *= sizeof($array);
00043             
00044             $keys = array_keys($arrays);
00045             
00046             foreach ($keys as $key)
00047                 $tmpArrays[] = $arrays[$key];
00048             
00049             for ($i = 0; $i < $size; $i++) {
00050                 $result[$i] = array();
00051                 
00052                 for ($j = 0; $j < sizeof($tmpArrays); $j++) {
00053                     $result[$i][$keys[$j]] = current($tmpArrays[$j]);
00054                 }
00055                 
00056                 if ($generateHash)
00057                     $result[$i]['hash'] = md5(implode('_', $result[$i]));
00058                 
00059                 for ($j = (sizeof($tmpArrays) - 1); $j >= 0; $j--) {
00060                     if (next($tmpArrays[$j])) {
00061                         break;
00062                     } else
00063                         reset($tmpArrays[$j]);
00064                 }
00065             }
00066             
00067             return $result;
00068         }
00069         
00070         public static function applyFunctorToCartesianProduct(
00071             $arrays, TupleFunctor $functor
00072         )
00073         {
00074             $result = array();
00075             
00076             $size = (sizeof($arrays) > 0) ? 1 : 0;
00077             
00078             foreach ($arrays as $array)
00079                 $size *= sizeof($array);
00080             
00081             $keys = array_keys($arrays);
00082             
00083             foreach ($keys as $key)
00084                 $tmpArrays[] = $arrays[$key];
00085             
00086             for ($i = 0; $i < $size; $i++) {
00087                 $result[$i] = array();
00088                 
00089                 for ($j = 0; $j < sizeof($tmpArrays); $j++) {
00090                     $result[$i][$keys[$j]] = current($tmpArrays[$j]);
00091                 }
00092                 
00093                 $functor->apply($result[$i]);
00094                 
00095                 unset($result[$i]);
00096                 
00097                 for ($j = (sizeof($tmpArrays) - 1); $j >= 0; $j--) {
00098                     if (next($tmpArrays[$j])) {
00099                         break;
00100                     } else
00101                         reset($tmpArrays[$j]);
00102                 }
00103             }
00104         }
00105         
00106         public static function randFloat($min, $max)
00107         {
00108             return ($min + lcg_value() * (abs($max - $min)));
00109         }
00110         
00111         public static function alignByBase($value, $base, $ceil = false)
00112         {
00113             $function = $ceil ? 'ceil' : 'floor';
00114             
00115             return $function($value / $base) * $base;
00116         }
00117 
00123         public static function randomNormalStd()
00124         {
00125             do {
00126                 $x = rand() / getrandmax() * 2 - 1;
00127                 $y = rand() / getrandmax() * 2 - 1;
00128 
00129                 $r = ($x * $x) + ($y * $y);
00130 
00131             } while (($r > 1) || ($x + $y == 0));
00132 
00133             $z = $x * sqrt(-2 * log($r) / $r);
00134 
00135             return $z;
00136         }
00137         
00138         public static function getStandardDeviation(array $list)
00139         {
00140             return self::getStandardDeviationP($list, count($list) - 1);
00141         }
00142         
00143         public static function getStandardDeviationP(array $list, $size = null)
00144         {
00145             $tempSum = 0;
00146             
00147             if (!$size)
00148                 $size = count($list);
00149             
00150             Assert::isPositiveInteger($size);
00151             
00152             $averageValue = self::getAverage($list, $size);
00153             
00154             for ($i = 0; $i < $size; $i++)
00155                 $tempSum += pow($list[$i] - $averageValue, 2);
00156         
00157             return sqrt($tempSum / $size);
00158         }
00159         
00160         public static function getAbsoluteDeviation(array $list)
00161         {
00162             $value = 0;
00163             
00164             $averageValue = self::getAverage($list);
00165             
00166             foreach ($list as $elt)
00167                 $value += abs($elt - $averageValue);
00168             
00169             return $value / count($list);
00170         }
00171         
00172         public static function getMeanDeviation($elt, $averageValue)
00173         {
00174             return $elt - $averageValue;
00175         }
00176         
00177         public static function getAverage(array $list, $size = null)
00178         {
00179             if (!$size)
00180                 $size = count($list);
00181             
00182             Assert::isPositiveInteger($size);
00183             
00184             $tempSum = 0;
00185             
00186             for ($i = 0; $i < $size; $i++)
00187                 $tempSum += $list[$i];
00188             
00189             return $tempSum / $size;
00190         }
00191         
00192         public static function getCovariance(array $list1, array $list2)
00193         {
00194             $list1Size = count($list1);
00195             $list2Size = count($list2);
00196             
00197             Assert::isEqual($list1Size, $list2Size, 'Array sizes should be equals!');
00198             
00199             $list1AverageValue = self::getAverage($list1);
00200             $list2AverageValue = self::getAverage($list2);
00201             
00202             $tempSum = 0;
00203             
00204             for ($i = 0; $i < $list1Size; $i++) {
00205                 $elt1Dev = self::getMeanDeviation($list1[$i], $list1AverageValue);
00206                 $elt2Dev = self::getMeanDeviation($list2[$i], $list2AverageValue);
00207                 
00208                 $tempSum += $elt1Dev * $elt2Dev;
00209             }
00210             
00211             return $tempSum / ($list1Size - 1);
00212         }
00213         
00214         public static function getPearsonProductMomentCorrelation(array $list1, array $list2)
00215         {
00216             return
00217                 self::getCovariance($list1, $list2)
00218                 / (
00219                     self::getStandardDeviation($list1)
00220                     * self::getStandardDeviation($list2)
00221                 );
00222         }
00223         
00224         public static function getMmult(array $list1, array $list2)
00225         {
00226             $list1Size = count($list1);
00227             $list2Size = count($list2);
00228             
00229             $result = array();
00230             
00231             for ($i = 0; $i < $list1Size; $i++) {
00232                 for ($j = 0; $j < $list2Size; $j++) {
00233                     $x = 0;
00234                     
00235                     for ($k = 0; $k < $list2Size; $k++) {
00236                         if (isset($list1[$i][$k]))
00237                             $l1 = $list1[$i][$k];
00238                         else
00239                             $l1 = 0;
00240                         
00241                         if (isset($list2[$k][$j]))
00242                             $l2 = $list2[$k][$j];
00243                         else
00244                             $l2 = 0;
00245                         
00246                         $x += $l1 * $l2;
00247                     }
00248                     
00249                     $result[$i][$j] = $x;
00250                 }
00251             }
00252             
00253             return $result;
00254         }
00255     }
00256 ?>