mirror of
				https://github.com/furyfire/trueskill.git
				synced 2025-11-04 10:12:28 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			136 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			136 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
namespace Moserware\Skills\TrueSkill;
 | 
						|
 | 
						|
require_once(dirname(__FILE__) . '/../Numerics/GaussianDistribution.php');
 | 
						|
 | 
						|
use Moserware\Numerics\GaussianDistribution;
 | 
						|
 | 
						|
class TruncatedGaussianCorrectionFunctions
 | 
						|
{
 | 
						|
    // These functions from the bottom of page 4 of the TrueSkill paper.
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// The "V" function where the team performance difference is greater than the draw margin.
 | 
						|
    /// </summary>
 | 
						|
    /// <remarks>In the reference F# implementation, this is referred to as "the additive
 | 
						|
    /// correction of a single-sided truncated Gaussian with unit variance."</remarks>
 | 
						|
    /// <param name="teamPerformanceDifference"></param>
 | 
						|
    /// <param name="drawMargin">In the paper, it's referred to as just "ε".</param>
 | 
						|
    /// <returns></returns>
 | 
						|
    public static function vExceedsMarginScaled($teamPerformanceDifference, $drawMargin, $c)
 | 
						|
    {
 | 
						|
        return self::vExceedsMargin($teamPerformanceDifference/$c, $drawMargin/$c);
 | 
						|
    }
 | 
						|
 | 
						|
    public static function vExceedsMargin($teamPerformanceDifference, $drawMargin)
 | 
						|
    {
 | 
						|
        $denominator = GaussianDistribution::cumulativeTo($teamPerformanceDifference - $drawMargin);
 | 
						|
 | 
						|
        if ($denominator < 2.222758749e-162)
 | 
						|
        {
 | 
						|
            return -$teamPerformanceDifference + $drawMargin;
 | 
						|
        }
 | 
						|
 | 
						|
        return GaussianDistribution::at($teamPerformanceDifference - $drawMargin)/$denominator;
 | 
						|
    }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// The "W" function where the team performance difference is greater than the draw margin.
 | 
						|
    /// </summary>
 | 
						|
    /// <remarks>In the reference F# implementation, this is referred to as "the multiplicative
 | 
						|
    /// correction of a single-sided truncated Gaussian with unit variance."</remarks>
 | 
						|
    /// <param name="teamPerformanceDifference"></param>
 | 
						|
    /// <param name="drawMargin"></param>
 | 
						|
    /// <param name="c"></param>
 | 
						|
    /// <returns></returns>
 | 
						|
    public static function wExceedsMarginScaled($teamPerformanceDifference, $drawMargin, $c)
 | 
						|
    {
 | 
						|
        return self::wExceedsMargin($teamPerformanceDifference/$c, $drawMargin/$c);
 | 
						|
    }
 | 
						|
 | 
						|
    public static function wExceedsMargin($teamPerformanceDifference, $drawMargin)
 | 
						|
    {
 | 
						|
        $denominator = GaussianDistribution::cumulativeTo($teamPerformanceDifference - $drawMargin);
 | 
						|
 | 
						|
        if ($denominator < 2.222758749e-162)
 | 
						|
        {
 | 
						|
            if ($teamPerformanceDifference < 0.0)
 | 
						|
            {
 | 
						|
                return 1.0;
 | 
						|
            }
 | 
						|
            return 0.0;
 | 
						|
        }
 | 
						|
 | 
						|
        $vWin = self::vExceedsMargin($teamPerformanceDifference, $drawMargin);
 | 
						|
        return $vWin*($vWin + $teamPerformanceDifference - $drawMargin);
 | 
						|
    }
 | 
						|
 | 
						|
    // the additive correction of a double-sided truncated Gaussian with unit variance
 | 
						|
    public static function vWithinMarginScaled($teamPerformanceDifference, $drawMargin, $c)
 | 
						|
    {
 | 
						|
        return self::vWithinMargin($teamPerformanceDifference/$c, $drawMargin/$c);
 | 
						|
    }
 | 
						|
    
 | 
						|
    // from F#:
 | 
						|
    public static function vWithinMargin($teamPerformanceDifference, $drawMargin)
 | 
						|
    {
 | 
						|
        $teamPerformanceDifferenceAbsoluteValue = abs($teamPerformanceDifference);
 | 
						|
        $denominator =
 | 
						|
            GaussianDistribution::cumulativeTo($drawMargin - $teamPerformanceDifferenceAbsoluteValue) -
 | 
						|
            GaussianDistribution::cumulativeTo(-$drawMargin - $teamPerformanceDifferenceAbsoluteValue);
 | 
						|
 | 
						|
        if ($denominator < 2.222758749e-162)
 | 
						|
        {
 | 
						|
            if ($teamPerformanceDifference < 0.0)
 | 
						|
            {
 | 
						|
                return -$teamPerformanceDifference - $drawMargin;
 | 
						|
            }
 | 
						|
 | 
						|
            return -$teamPerformanceDifference + $drawMargin;
 | 
						|
        }
 | 
						|
 | 
						|
        $numerator = GaussianDistribution::at(-$drawMargin - $teamPerformanceDifferenceAbsoluteValue) -
 | 
						|
                     GaussianDistribution::at($drawMargin - $teamPerformanceDifferenceAbsoluteValue);
 | 
						|
 | 
						|
        if ($teamPerformanceDifference < 0.0)
 | 
						|
        {
 | 
						|
            return -$numerator/$denominator;
 | 
						|
        }
 | 
						|
 | 
						|
        return $numerator/$denominator;
 | 
						|
    }
 | 
						|
 | 
						|
    // the multiplicative correction of a double-sided truncated Gaussian with unit variance
 | 
						|
    public static function wWithinMarginScaled($teamPerformanceDifference, $drawMargin, $c)
 | 
						|
    {
 | 
						|
        return self::wWithinMargin($teamPerformanceDifference/$c, $drawMargin/$c);
 | 
						|
    }
 | 
						|
 | 
						|
    // From F#:
 | 
						|
    public static function wWithinMargin($teamPerformanceDifference, $drawMargin)
 | 
						|
    {
 | 
						|
        $teamPerformanceDifferenceAbsoluteValue = abs($teamPerformanceDifference);
 | 
						|
        $denominator = GaussianDistribution::cumulativeTo($drawMargin - $teamPerformanceDifferenceAbsoluteValue)
 | 
						|
                       -
 | 
						|
                       GaussianDistribution::cumulativeTo(-$drawMargin - $teamPerformanceDifferenceAbsoluteValue);
 | 
						|
 | 
						|
        if ($denominator < 2.222758749e-162)
 | 
						|
        {
 | 
						|
            return 1.0;
 | 
						|
        }
 | 
						|
 | 
						|
        $vt = self::vWithinMargin($teamPerformanceDifferenceAbsoluteValue, $drawMargin);
 | 
						|
 | 
						|
        return $vt*$vt +
 | 
						|
               (
 | 
						|
                   ($drawMargin - $teamPerformanceDifferenceAbsoluteValue)
 | 
						|
                   *
 | 
						|
                   GaussianDistribution::at(
 | 
						|
                       $drawMargin - $teamPerformanceDifferenceAbsoluteValue)
 | 
						|
                   - (-$drawMargin - $teamPerformanceDifferenceAbsoluteValue)
 | 
						|
                     *
 | 
						|
                     GaussianDistribution::at(-$drawMargin - $teamPerformanceDifferenceAbsoluteValue))/$denominator;
 | 
						|
    }
 | 
						|
}
 | 
						|
?>
 |