how do I compute the z-score of a array of numbers using PHP? I need to compute the z-score and then find the percentile (CDF)! what PHP functions can I use? thanks!
The following code will give a good approximation of the CDF (Abramowitz & Stegun (1964))
function normal_pdf($x) {
return exp(-$x * $x / 4) / sqrt(2 * M_PI);
}
function normal_cdf($x) {
$b = array(0.2316419, 0.319381530, -0.356563782, 1.781477937, -1.821255978, 1.330274429);
$t = 1 / (1 + $b[0] * $x);
$result = 0;
for ($i = 1; $i < 6; $i++) {
$result += $b[$i] * pow($t, $i);
}
return 1 - normal_pdf($x) * $result;
}
This assumes a standard normal distribution. Recall that to standardize, use z = (x - mean) / (standard deviation)
/* Mean */
function mean($input_array)
{
$total = 0;
foreach ($input_array as $value)
{
$total += $value;
}
return ($total / count($input_array));
}
/* Standard Deviation */
function std($arr)
{
if (!count($arr))
return 0;
$mean = mean($arr);
$sos = 0; // Sum of squares
for ($i = 0; $i < count($arr); $i++)
{
$sos += ($arr[$i] - $mean) * ($arr[$i] - $mean);
}
return sqrt($sos / (count($arr) - 1));
}
/* Z Scores */
function z($var, $arr)
{
return ($var -mean($arr)) / std($arr);
}
There are a few functions in the PHP statistics extension that could help you — You probably want stats_standard_deviation for a start.
$control=array(15,7);
$treatment=array(46,8);
$confidence=number_format(cumnormdist(zscore($control, $treatment))*100,0);
function cr($t)
{
return $t[1]/$t[0];
}
function zscore($c, $t)
{
$z = cr($t)-cr($c);
$s = (cr($t)*(1-cr($t)))/$t[0] + (cr($c)*(1-cr($c)))/$c[0];
return $z/sqrt($s);
}
function cumnormdist($x)
{
$b1 = 0.319381530;
$b2 = -0.356563782;
$b3 = 1.781477937;
$b4 = -1.821255978;
$b5 = 1.330274429;
$p = 0.2316419;
$c = 0.39894228;
if($x >= 0.0) {
$t = 1.0 / ( 1.0 + $p * $x );
return (1.0 - $c * exp( -$x * $x / 2.0 ) * $t *
( $t *( $t * ( $t * ( $t * $b5 + $b4 ) + $b3 ) + $b2 ) + $b1 ));
}
else {
$t = 1.0 / ( 1.0 - $p * $x );
return ( $c * exp( -$x * $x / 2.0 ) * $t *
( $t *( $t * ( $t * ( $t * $b5 + $b4 ) + $b3 ) + $b2 ) + $b1 ));
}
}
Related
Expected output :
my current code only output the pattern but it can't have more comb:
$n = 5;
$n1 = 4;
for ($i = 0; $i <= $n; $i++) {
for ($j = 0; $j <= $n1; $j++) {
if (($i == 0 || $i == 5) && ($j > 0 and $j < 3)) {
if (($i == 0 && $j == 1) || ($i == $n && $j != 2)) {
printf(" ");
}
printf("$i");
} elseif (($j == 0 || $j == 3) && ($i != 0 and $i != 5)) {
if ($j == 0 && $i != 1 && $i != 4) {
printf("");
} elseif (($j == 3 && $i != 1 && $i != 4)) {
printf(" ");
} elseif ($j == 0) {
printf(" ");
}
printf("$i");
} else {
printf(" ");
}
}
echo "<be>";
`
this is the output the only problem is how do i multiply the comb.
Just for fun I wrote it in JS, but probably pretty straightforward to convert to PHP (String.repeat => str_repeat, [].push => array_push, [].slice => array_slice, etc)
const arr = [];
const output = (x=1, y=1) => {
for (let k = 0; k < 5; k++) {
arr.push([' '.repeat(5-k), k, ' '.repeat(k), k, ' '.repeat(5-k)].join(''))
}
for (let k = 5; k <= 10; k++) {
arr.push([' '.repeat(k-5), 10-k, ' '.repeat(10-k), 10-k, ' '.repeat(k-5)].join(''))
}
arr.forEach((row, index) => {
arr[index] = row + row.substring(1).repeat(x - 1);
});
const orig = [...arr.slice(1)]
for (let i = 1; i < y; i++) {
arr.push(...orig);
}
console.log(arr.join('\n'))
}
output(2,3)
The simplest way is to create an array, where 1 = '*' and 0 = ' '.
This is the algorithm in PHP 7 that I have done to create the pattern.
Note: I have made changes to optimize the code
<?php
$max = 6;
// Arg
$arg1 = 2;
$arg2 = 2;
// Change to pair size when is non
if ($max % 2 != 0) {
++$max;
}
// Matrix with zero values
$t = \array_fill(0, $max * $arg1 - $arg1 + 1, \array_fill(0, $max * $arg2 - $arg2 + 1, 0));
// Lower: start left position
$lower = $max / 2 - 1;
// Upper: start right postion
$upper = $lower + 1;
// Set pattern in matrix
for ($i = 0, $n = $max - 1; $i <= $n; $i++, $lower--, $upper++) {
for ($a1 = 0; $a1 < $arg1; $a1++) {
for ($a2 = 0; $a2 < $arg2; $a2++) {
$y = $i + $max * $a1 - $a1;
$p = $max * $a2 - $a2;
// Set pixel pattern
$t[$y][$lower + $p] = $t[$y][$upper + $p] = 1;
}
}
// Restart lower?
if ($lower == 0) {
$lower = $max;
}
// Restart upper?
if ($upper == $n) {
$upper = -1;
}
}
echo '<pre>', \PHP_EOL;
foreach ($t as $r) {
foreach ($r as $v) {
if ($v) {
echo '*';
} else {
echo ' ';
}
}
echo \PHP_EOL;
}
echo '</pre>';
?>
Output:
** **
* * * *
* * *
* * *
* * * *
** **
* * * *
* * *
* * *
* * * *
** **
I need to use this table to get the probability from a given z value:
https://statistics.laerd.com/statistical-guides/img/normal-table-large.png
I'm sure there should be a better way to get those values on php but don't know how to calculate them.
Any help would be very appreciated.
Cumulative distribution function of the standard normal distribution with precision calculation:
function cumulativeNormalDensity($x, $mean = 0, $stddev = 1, $precision = 48) {
$result = 0;
$x -= $mean;
$x /= $stddev;
for ($i = 0, $k = 1; $i < $precision; $i++) {
$n = $i * 2 + 1;
$k *= $n;
$p = pow($x, $n) / $k;
if (is_nan($p) || is_infinite($p)) break;
$result += $p;
}
$result *= 1 / sqrt(2 * pi()) * exp(-pow($x, 2) / 2);
$result += 0.5;
return max(0, $result);
}
Table, I believe, is CDF of the normal distribution. I coded it using expression for
error function approximation.
Code is untested!
function sgn( $x ) {
if ( $x < 0 )
return -1;
return 1;
}
function erf( $x ) {
$e = exp(-$x*$x);
$e2 = exp(-$x*$x*2);
$q = sqrt(pi())/2 + 31*$e/200 - 341*$e2/8000;
return 2*sgn($x)*sqrt(1-$e)*$q/sqrt(pi());
}
function CDF( $x ) {
return (1 + erf($x / sqrt(2))) / 2;
}
print_r(CDF(0));
print_r(CDF(0.1));
....
UPDATE
Here is quick (untested!) code to compute erf() with up to 4 terms
function erf( $x ) {
$e = exp(-$x*$x);
$t = 1.0 - $e;
$s = 1. + $t*(-1./12. + $t*(-7./480. + $t*( -5./896. +$t * (-787./276480.))));
return 2.*sgn($x)*sqrt($t)*$s/sqrt(pi());
}
Hey guys :) I want to ask for some solution. Now, I have dictionary words.txt, here some example:
happy
laugh
sad
And I have the slang string:
hppy
I want to search & match that slang string to my dictionary wich means it will return "happy" because those string refer to "happy" in dictionary.
Recently I've been using similar_text() but doesn't confident about its validity. Can you guys recommend better solution for my problem? Thank you :)
And here i put my codes:
function searchwords($tweet){
//echo $tweet;
$find = false;
$handle = #fopen("words.txt", "r");
if ($handle)
{
while (!feof($handle))
{
$buffer = fgets($handle);
similar_text(trim($tweet),trim($buffer),$percent);
if ($percent == 100){ // this exact match
$find = true;
}else if ($percent >= 90){ //there is the possibility of errors
$find = true;
}
}
fclose($handle);
}
if ($find == true){
unset($tweet);
}else{
return $tweet;
}
}
As answered here
I've found that to calculate a similarity percentage between strings,
the Levenshtein and Jaro Winkler algorithms work well for
spelling mistakes and small changes between strings, while the Smith
Waterman Gotoh algorithm works well for strings where significant
chunks of the text would be the same but with "noise" around the
edges. This answer to a similar question shows more detail on
this.
I included the php examples of using each of these three examples to return a similarity percentage between two strings:
Levenshtein
echo levenshtein("LEGENDARY","BARNEY STINSON");
Jaro Winkler
class StringCompareJaroWinkler
{
public function compare($str1, $str2)
{
return $this->JaroWinkler($str1, $str2, $PREFIXSCALE = 0.1 );
}
private function getCommonCharacters( $string1, $string2, $allowedDistance ){
$str1_len = mb_strlen($string1);
$str2_len = mb_strlen($string2);
$temp_string2 = $string2;
$commonCharacters='';
for( $i=0; $i < $str1_len; $i++){
$noMatch = True;
// compare if char does match inside given allowedDistance
// and if it does add it to commonCharacters
for( $j= max( 0, $i-$allowedDistance ); $noMatch && $j < min( $i + $allowedDistance + 1, $str2_len ); $j++){
if( $temp_string2[$j] == $string1[$i] ){
$noMatch = False;
$commonCharacters .= $string1[$i];
$temp_string2[$j] = '';
}
}
}
return $commonCharacters;
}
private function Jaro( $string1, $string2 ){
$str1_len = mb_strlen( $string1 );
$str2_len = mb_strlen( $string2 );
// theoretical distance
$distance = (int) floor(min( $str1_len, $str2_len ) / 2.0);
// get common characters
$commons1 = $this->getCommonCharacters( $string1, $string2, $distance );
$commons2 = $this->getCommonCharacters( $string2, $string1, $distance );
if( ($commons1_len = mb_strlen( $commons1 )) == 0) return 0;
if( ($commons2_len = mb_strlen( $commons2 )) == 0) return 0;
// calculate transpositions
$transpositions = 0;
$upperBound = min( $commons1_len, $commons2_len );
for( $i = 0; $i < $upperBound; $i++){
if( $commons1[$i] != $commons2[$i] ) $transpositions++;
}
$transpositions /= 2.0;
// return the Jaro distance
return ($commons1_len/($str1_len) + $commons2_len/($str2_len) + ($commons1_len - $transpositions)/($commons1_len)) / 3.0;
}
private function getPrefixLength( $string1, $string2, $MINPREFIXLENGTH = 4 ){
$n = min( array( $MINPREFIXLENGTH, mb_strlen($string1), mb_strlen($string2) ) );
for($i = 0; $i < $n; $i++){
if( $string1[$i] != $string2[$i] ){
// return index of first occurrence of different characters
return $i;
}
}
// first n characters are the same
return $n;
}
private function JaroWinkler($string1, $string2, $PREFIXSCALE = 0.1 ){
$JaroDistance = $this->Jaro( $string1, $string2 );
$prefixLength = $this->getPrefixLength( $string1, $string2 );
return $JaroDistance + $prefixLength * $PREFIXSCALE * (1.0 - $JaroDistance);
}
}
$jw = new StringCompareJaroWinkler();
echo $jw->compare("LEGENDARY","BARNEY STINSON");
Smith Waterman Gotoh
class SmithWatermanGotoh
{
private $gapValue;
private $substitution;
/**
* Constructs a new Smith Waterman metric.
*
* #param gapValue
* a non-positive gap penalty
* #param substitution
* a substitution function
*/
public function __construct($gapValue=-0.5,
$substitution=null)
{
if($gapValue > 0.0) throw new Exception("gapValue must be <= 0");
//if(empty($substitution)) throw new Exception("substitution is required");
if (empty($substitution)) $this->substitution = new SmithWatermanMatchMismatch(1.0, -2.0);
else $this->substitution = $substitution;
$this->gapValue = $gapValue;
}
public function compare($a, $b)
{
if (empty($a) && empty($b)) {
return 1.0;
}
if (empty($a) || empty($b)) {
return 0.0;
}
$maxDistance = min(mb_strlen($a), mb_strlen($b))
* max($this->substitution->max(), $this->gapValue);
return $this->smithWatermanGotoh($a, $b) / $maxDistance;
}
private function smithWatermanGotoh($s, $t)
{
$v0 = [];
$v1 = [];
$t_len = mb_strlen($t);
$max = $v0[0] = max(0, $this->gapValue, $this->substitution->compare($s, 0, $t, 0));
for ($j = 1; $j < $t_len; $j++) {
$v0[$j] = max(0, $v0[$j - 1] + $this->gapValue,
$this->substitution->compare($s, 0, $t, $j));
$max = max($max, $v0[$j]);
}
// Find max
for ($i = 1; $i < mb_strlen($s); $i++) {
$v1[0] = max(0, $v0[0] + $this->gapValue, $this->substitution->compare($s, $i, $t, 0));
$max = max($max, $v1[0]);
for ($j = 1; $j < $t_len; $j++) {
$v1[$j] = max(0, $v0[$j] + $this->gapValue, $v1[$j - 1] + $this->gapValue,
$v0[$j - 1] + $this->substitution->compare($s, $i, $t, $j));
$max = max($max, $v1[$j]);
}
for ($j = 0; $j < $t_len; $j++) {
$v0[$j] = $v1[$j];
}
}
return $max;
}
}
class SmithWatermanMatchMismatch
{
private $matchValue;
private $mismatchValue;
/**
* Constructs a new match-mismatch substitution function. When two
* characters are equal a score of <code>matchValue</code> is assigned. In
* case of a mismatch a score of <code>mismatchValue</code>. The
* <code>matchValue</code> must be strictly greater then
* <code>mismatchValue</code>
*
* #param matchValue
* value when characters are equal
* #param mismatchValue
* value when characters are not equal
*/
public function __construct($matchValue, $mismatchValue) {
if($matchValue <= $mismatchValue) throw new Exception("matchValue must be > matchValue");
$this->matchValue = $matchValue;
$this->mismatchValue = $mismatchValue;
}
public function compare($a, $aIndex, $b, $bIndex) {
return ($a[$aIndex] === $b[$bIndex] ? $this->matchValue
: $this->mismatchValue);
}
public function max() {
return $this->matchValue;
}
public function min() {
return $this->mismatchValue;
}
}
$o = new SmithWatermanGotoh();
echo $o->compare("LEGENDARY","BARNEY STINSON");
Hopefully it'll serve your purpose. But there are some things to keep in mind while working with similar_text().
matching percentage can differ depending on the order of parameters. ie: similar_text($a, $b, $percent) and similar_text($b, $a, $percent) here in both cases $percent may not be same.
Note that this function is case sensitive: so while passing $a and $b pass both either in uppercase or lowercase.
for more info check this page
What's an elegant code for finding common alphabets among two strings without including the space in PHP?
Also return a similarity index i.e. count the number of common characters and return that as a percentage over the total number of characters.
Suppose i have one string "LEGENDARY ", whereas other as "BARNEY STINSON" so i need to find common letters b/w both without including space.
Also my code should return a similarity index i.e. count the number of common characters and return that as a percentage over the total number of characters.
For these two strings, the common characters are "ARNEY" so the score is 5/22 ~= 22%. Any help on this?
I've found that to calculate a similarity percentage between strings, the Levenshtein and Jaro Winkler algorithms work well for spelling mistakes and small changes between strings, while the Smith Waterman Gotoh algorithm works well for strings where significant chunks of the text would be the same but with "noise" around the edges. This answer to a similar question shows more detail on this.
Here are php examples of using each of these three examples to return a similarity percentage between two strings:
Levenshtein
echo levenshtein("LEGENDARY","BARNEY STINSON");
Jaro Winkler
class StringCompareJaroWinkler
{
public function compare($str1, $str2)
{
return $this->JaroWinkler($str1, $str2, $PREFIXSCALE = 0.1 );
}
private function getCommonCharacters( $string1, $string2, $allowedDistance ){
$str1_len = mb_strlen($string1);
$str2_len = mb_strlen($string2);
$temp_string2 = $string2;
$commonCharacters='';
for( $i=0; $i < $str1_len; $i++){
$noMatch = True;
// compare if char does match inside given allowedDistance
// and if it does add it to commonCharacters
for( $j= max( 0, $i-$allowedDistance ); $noMatch && $j < min( $i + $allowedDistance + 1, $str2_len ); $j++){
if( $temp_string2[$j] == $string1[$i] ){
$noMatch = False;
$commonCharacters .= $string1[$i];
$temp_string2[$j] = '';
}
}
}
return $commonCharacters;
}
private function Jaro( $string1, $string2 ){
$str1_len = mb_strlen( $string1 );
$str2_len = mb_strlen( $string2 );
// theoretical distance
$distance = (int) floor(min( $str1_len, $str2_len ) / 2.0);
// get common characters
$commons1 = $this->getCommonCharacters( $string1, $string2, $distance );
$commons2 = $this->getCommonCharacters( $string2, $string1, $distance );
if( ($commons1_len = mb_strlen( $commons1 )) == 0) return 0;
if( ($commons2_len = mb_strlen( $commons2 )) == 0) return 0;
// calculate transpositions
$transpositions = 0;
$upperBound = min( $commons1_len, $commons2_len );
for( $i = 0; $i < $upperBound; $i++){
if( $commons1[$i] != $commons2[$i] ) $transpositions++;
}
$transpositions /= 2.0;
// return the Jaro distance
return ($commons1_len/($str1_len) + $commons2_len/($str2_len) + ($commons1_len - $transpositions)/($commons1_len)) / 3.0;
}
private function getPrefixLength( $string1, $string2, $MINPREFIXLENGTH = 4 ){
$n = min( array( $MINPREFIXLENGTH, mb_strlen($string1), mb_strlen($string2) ) );
for($i = 0; $i < $n; $i++){
if( $string1[$i] != $string2[$i] ){
// return index of first occurrence of different characters
return $i;
}
}
// first n characters are the same
return $n;
}
private function JaroWinkler($string1, $string2, $PREFIXSCALE = 0.1 ){
$JaroDistance = $this->Jaro( $string1, $string2 );
$prefixLength = $this->getPrefixLength( $string1, $string2 );
return $JaroDistance + $prefixLength * $PREFIXSCALE * (1.0 - $JaroDistance);
}
}
$jw = new StringCompareJaroWinkler();
echo $jw->compare("LEGENDARY","BARNEY STINSON");
Smith Waterman Gotoh
class SmithWatermanGotoh
{
private $gapValue;
private $substitution;
/**
* Constructs a new Smith Waterman metric.
*
* #param gapValue
* a non-positive gap penalty
* #param substitution
* a substitution function
*/
public function __construct($gapValue=-0.5,
$substitution=null)
{
if($gapValue > 0.0) throw new Exception("gapValue must be <= 0");
//if(empty($substitution)) throw new Exception("substitution is required");
if (empty($substitution)) $this->substitution = new SmithWatermanMatchMismatch(1.0, -2.0);
else $this->substitution = $substitution;
$this->gapValue = $gapValue;
}
public function compare($a, $b)
{
if (empty($a) && empty($b)) {
return 1.0;
}
if (empty($a) || empty($b)) {
return 0.0;
}
$maxDistance = min(mb_strlen($a), mb_strlen($b))
* max($this->substitution->max(), $this->gapValue);
return $this->smithWatermanGotoh($a, $b) / $maxDistance;
}
private function smithWatermanGotoh($s, $t)
{
$v0 = [];
$v1 = [];
$t_len = mb_strlen($t);
$max = $v0[0] = max(0, $this->gapValue, $this->substitution->compare($s, 0, $t, 0));
for ($j = 1; $j < $t_len; $j++) {
$v0[$j] = max(0, $v0[$j - 1] + $this->gapValue,
$this->substitution->compare($s, 0, $t, $j));
$max = max($max, $v0[$j]);
}
// Find max
for ($i = 1; $i < mb_strlen($s); $i++) {
$v1[0] = max(0, $v0[0] + $this->gapValue, $this->substitution->compare($s, $i, $t, 0));
$max = max($max, $v1[0]);
for ($j = 1; $j < $t_len; $j++) {
$v1[$j] = max(0, $v0[$j] + $this->gapValue, $v1[$j - 1] + $this->gapValue,
$v0[$j - 1] + $this->substitution->compare($s, $i, $t, $j));
$max = max($max, $v1[$j]);
}
for ($j = 0; $j < $t_len; $j++) {
$v0[$j] = $v1[$j];
}
}
return $max;
}
}
class SmithWatermanMatchMismatch
{
private $matchValue;
private $mismatchValue;
/**
* Constructs a new match-mismatch substitution function. When two
* characters are equal a score of <code>matchValue</code> is assigned. In
* case of a mismatch a score of <code>mismatchValue</code>. The
* <code>matchValue</code> must be strictly greater then
* <code>mismatchValue</code>
*
* #param matchValue
* value when characters are equal
* #param mismatchValue
* value when characters are not equal
*/
public function __construct($matchValue, $mismatchValue) {
if($matchValue <= $mismatchValue) throw new Exception("matchValue must be > matchValue");
$this->matchValue = $matchValue;
$this->mismatchValue = $mismatchValue;
}
public function compare($a, $aIndex, $b, $bIndex) {
return ($a[$aIndex] === $b[$bIndex] ? $this->matchValue
: $this->mismatchValue);
}
public function max() {
return $this->matchValue;
}
public function min() {
return $this->mismatchValue;
}
}
$o = new SmithWatermanGotoh();
echo $o->compare("LEGENDARY","BARNEY STINSON");
see similar_text(). And if you want to exclude spaces simple str_replace(' ', '', $string); prior.
echo similar_text ( 'LEGENDARY' , 'BARNEYSTINSON', $percent); // outputs 3
echo $percent; // outputs 27.272727272727
Here's another way using only unique characters
<?php
function unique_chars($string) {
return count_chars(strtolower(str_replace(' ', '', $string)), 3);
}
function compare_strings($a, $b) {
$index = similar_text(unique_chars($a), unique_chars($b), $percent);
return array('index' => $index, 'percent' => $percent);
}
print_r( compare_strings('LEGENDARY', 'BARNEY STINSON') );
// outputs:
?>
Array
(
[index] => 5
[percent] => 55.555555555556
)
i need smith-waterman in php, do you know if there is already an implementation?
I need this algo for proxmity searches ( Function that returns affinity between texts? )
I will try to make it if there aren't any.
thanks
I reverse engineered the SimMetrics java code for SmithWatermanGotoh - I found that SmithWatermanGotoh is more efficient than SmithWaterman with very similar results:
class SmithWatermanGotoh
{
private $gapValue;
private $substitution;
/**
* Constructs a new Smith Waterman metric.
*
* #param gapValue
* a non-positive gap penalty
* #param substitution
* a substitution function
*/
public function __construct($gapValue=-0.5,
$substitution=null)
{
if($gapValue > 0.0) throw new Exception("gapValue must be <= 0");
//if(empty($substitution)) throw new Exception("substitution is required");
if (empty($substitution)) $this->substitution = new SmithWatermanMatchMismatch(1.0, -2.0);
else $this->substitution = $substitution;
$this->gapValue = $gapValue;
}
public function compare($a, $b)
{
if (empty($a) && empty($b)) {
return 1.0;
}
if (empty($a) || empty($b)) {
return 0.0;
}
$maxDistance = min(mb_strlen($a), mb_strlen($b))
* max($this->substitution->max(), $this->gapValue);
return $this->smithWatermanGotoh($a, $b) / $maxDistance;
}
private function smithWatermanGotoh($s, $t)
{
$v0 = [];
$v1 = [];
$t_len = mb_strlen($t);
$max = $v0[0] = max(0, $this->gapValue, $this->substitution->compare($s, 0, $t, 0));
for ($j = 1; $j < $t_len; $j++) {
$v0[$j] = max(0, $v0[$j - 1] + $this->gapValue,
$this->substitution->compare($s, 0, $t, $j));
$max = max($max, $v0[$j]);
}
// Find max
for ($i = 1; $i < mb_strlen($s); $i++) {
$v1[0] = max(0, $v0[0] + $this->gapValue, $this->substitution->compare($s, $i, $t, 0));
$max = max($max, $v1[0]);
for ($j = 1; $j < $t_len; $j++) {
$v1[$j] = max(0, $v0[$j] + $this->gapValue, $v1[$j - 1] + $this->gapValue,
$v0[$j - 1] + $this->substitution->compare($s, $i, $t, $j));
$max = max($max, $v1[$j]);
}
for ($j = 0; $j < $t_len; $j++) {
$v0[$j] = $v1[$j];
}
}
return $max;
}
}
class SmithWatermanMatchMismatch
{
private $matchValue;
private $mismatchValue;
/**
* Constructs a new match-mismatch substitution function. When two
* characters are equal a score of <code>matchValue</code> is assigned. In
* case of a mismatch a score of <code>mismatchValue</code>. The
* <code>matchValue</code> must be strictly greater then
* <code>mismatchValue</code>
*
* #param matchValue
* value when characters are equal
* #param mismatchValue
* value when characters are not equal
*/
public function __construct($matchValue, $mismatchValue) {
if($matchValue <= $mismatchValue) throw new Exception("matchValue must be > matchValue");
$this->matchValue = $matchValue;
$this->mismatchValue = $mismatchValue;
}
public function compare($a, $aIndex, $b, $bIndex) {
return ($a[$aIndex] === $b[$bIndex] ? $this->matchValue
: $this->mismatchValue);
}
public function max() {
return $this->matchValue;
}
public function min() {
return $this->mismatchValue;
}
}
$str1 = "COELACANTH";
$str2 = "PELICAN";
$o = new SmithWatermanGotoh();
echo $o->compare($str1, $str2);
There is this "BioStor" project that has an implementation of the Smith-Waterman algorithm in PHP.