php/Math   
Recreational Mathematics   
   home  |  library  |  contact
 Math Notes
 Math Programming [25]
 Regression [3]
 Data Mining [17]
 Notation [6]
 Linear Algebra [9]
 Stats & Prob [15]
 Math Cognition [5]
 Space & Physics [6]
 Formulas [5]
 Fun & Games [2]
 Haskell [1]
 Bayes Theory [1]
 Site News [0]
 Math Projects [5]
 Polynomials [1]
 Calculus [9]
 Number Theory [3]
 Optimization [2]
 Financial [1]

 Math Links
 PHP/ir
 Andrew Gelman
 Chance Wiki
 Daniel Lemire
 KD Knuggets
 Social Stats
 MySQL Performance
 Hunch.net
 Matthew Hurst
 JMLR
 JSS
 Hal Daume III
 Math Notes >> Permanent Link

Elementwise operations [Regression
Posted on January 28, 2012 @ 06:33:46 AM by Paul Meagher

In my last post, I discussed how basic arithmetic operations might be vectorized using PHP. I wasn't very satisfied with the implemention. One issue was that I was duplicating alot of code and felt that the vectorization code could be reused across vectorized arithmetic operations better. Another issue was that I didn't study how matlab/octave elementwise operations worked in detail so didn't know what the allowable argument types were (scalar, vector, matrix) and what combination of argument types was allowed on both sides of the arithmetic operation. I'm happy to report that I've addressed both of these issues in the new implementation. While I could probably add more error handling, I think the code below could be used to easily vectorize many operations in PHP such as exp, sin, cos, pow, etc...

<?php
/**
* elementwise_operations.php
*
* Functions that mimic matlab/octave's elementwise operations (e.g., .+, .-, .*, ./):
*
*  .+  =  madd  =  element-by-element addition
*  .-  =  msub  =  element-by-element subtraction
*  .*  =  mmul  =  element-by-element multiplication
*  ./  =  mdiv  =  element-by-element division
*/

/**
* Determines whether a variable is a scalar, vector, or matrix
*/
function get_type($var) {  
  if (
is_numeric($var)) {
    return 
"scalar";
  } elseif (
is_array($var)) {
    if (
is_array($var[0])) 
      return 
"matrix";
    else 
      return 
"vector";
  } else 
    return 
false;
}

/**
* Function that vectorizes the elementary operations.
*/
function vectorize($a$b$op) {
  
  
$atype get_type($a);  
  
$btype get_type($b);

  if ((
$atype != false) AND ($btype != false))
    
$arguments $atype."-".$btype;
  else 
    die(
"Argument is not a scalar, vector or matrix.");
  
  switch (
$arguments) {
    
    case 
"scalar-scalar"
      return 
$op($a$b);
      break;

    case 
"vector-scalar"
      
$asize count($a);
      
$b     array_fill(0$asize$b);
      return 
array_map($op$a$b);      
      break;

    case 
"vector-vector":
      
$asize count($a);
      
$bsize count($b);      
      if (
$asize == $bsize
        return 
array_map($op$a$b);              
      else 
        die(
"Nonconformant arguments.");
      break; 
      
    case 
"matrix-scalar":        
      
$nrows count($a);
      
$ncols count($a[0]);      
      for(
$i=0$i<$nrows$i++) {
        
$bvec  array_fill(0$ncols$b);        
        
$c[$i] = array_map($op$a[$i], $bvec);           
      }  
      return 
$c;
      break;
      
    case 
"matrix-matrix":        
      
$arows count($a);
      
$acols count($a[0]); 
      
$brows count($b);
      
$bcols count($b[0]);       
      if ((
$arows == $brows) AND ($acols == $bcols)) {
        for(
$i=0$i<$arows$i++) 
          
$c[$i] = array_map($op$a[$i], $b[$i]);   
        return 
$c;                        
      } else 
        die(
"Nonconformant arguments.");      
      break;             
  }    
  
}


// Elementary arithmetic operations.

function _add($addend1$addend2) {
  return (
$addend1 $addend2);
}

function 
_sub($minuend$subtrahend) {
  return (
$minuend $subtrahend);
}

function 
_mul($factor1$factor2) {
  return (
$factor1 $factor2);
}

function 
_div($numerator$divisor) {
  return (
$numerator $divisor);
}


// Elementwise operators.

function madd($m$addend) {
  return 
vectorize($m$addend"_add");
}

function 
msub($m$subtrahend) {
  return 
vectorize($m$subtrahend"_sub");
}

function 
mmul($m$factor) {
  return 
vectorize($m$factor"_mul");
}

function 
mdiv($m$divisor) {
  return 
vectorize($m$divisor"_div");
}


// Test elementwise addition.

$s 5;
$v = array(123);
$m = array(array(123), array(456));

// scalar-scalar case
$ans madd($s$s);
print_r($ans);
echo 
"<br />";

// vector-scalar case
$ans madd($v$s);
print_r($ans);
echo 
"<br />";

// vector-vector case
$ans madd($v$v);
print_r($ans);
echo 
"<br />";

// matrix-scalar case
$ans madd($m$s);
print_r($ans);
echo 
"<br />";

// matrix-matrix case
$ans madd($m$m);
print_r($ans);

// What the output looks like:

// 10
// Array ( [0] => 6 [1] => 7 [2] => 8 )
// Array ( [0] => 2 [1] => 4 [2] => 6 )
// Array ( [0] => Array ( [0] => 6 [1] => 7 [2] => 8 ) [1] => Array ( [0] => 9 [1] => 10 [2] => 11 ) )
// Array ( [0] => Array ( [0] => 2 [1] => 4 [2] => 6 ) [1] => Array ( [0] => 8 [1] => 10 [2] => 12 ) ) 

?>
  

Permalink 

No comments entered ...

 Archive 
 

php/Math Project
© 2011. All rights reserved.