mirror of
				https://github.com/furyfire/trueskill.git
				synced 2025-11-04 10:12:28 +01:00 
			
		
		
		
	Initial version of Moserware.Skills TrueSkill calculator to go along with my Computing Your Skill blog post
This commit is contained in:
		
							
								
								
									
										192
									
								
								Skills/TrueSkill/Layers/IteratedTeamDifferencesInnerLayer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								Skills/TrueSkill/Layers/IteratedTeamDifferencesInnerLayer.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,192 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using Moserware.Numerics;
 | 
			
		||||
using Moserware.Skills.FactorGraphs;
 | 
			
		||||
using Moserware.Skills.TrueSkill.Factors;
 | 
			
		||||
 | 
			
		||||
namespace Moserware.Skills.TrueSkill.Layers
 | 
			
		||||
{
 | 
			
		||||
    // The whole purpose of this is to do a loop on the bottom
 | 
			
		||||
    internal class IteratedTeamDifferencesInnerLayer<TPlayer> :
 | 
			
		||||
        TrueSkillFactorGraphLayer
 | 
			
		||||
            <TPlayer, Variable<GaussianDistribution>, GaussianWeightedSumFactor, Variable<GaussianDistribution>>
 | 
			
		||||
    {
 | 
			
		||||
        private readonly TeamDifferencesComparisonLayer<TPlayer> _TeamDifferencesComparisonLayer;
 | 
			
		||||
 | 
			
		||||
        private readonly TeamPerformancesToTeamPerformanceDifferencesLayer<TPlayer>
 | 
			
		||||
            _TeamPerformancesToTeamPerformanceDifferencesLayer;
 | 
			
		||||
 | 
			
		||||
        public IteratedTeamDifferencesInnerLayer(TrueSkillFactorGraph<TPlayer> parentGraph,
 | 
			
		||||
                                                 TeamPerformancesToTeamPerformanceDifferencesLayer<TPlayer>
 | 
			
		||||
                                                     teamPerformancesToPerformanceDifferences,
 | 
			
		||||
                                                 TeamDifferencesComparisonLayer<TPlayer> teamDifferencesComparisonLayer)
 | 
			
		||||
            : base(parentGraph)
 | 
			
		||||
        {
 | 
			
		||||
            _TeamPerformancesToTeamPerformanceDifferencesLayer = teamPerformancesToPerformanceDifferences;
 | 
			
		||||
            _TeamDifferencesComparisonLayer = teamDifferencesComparisonLayer;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<Factor<GaussianDistribution>> UntypedFactors
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return
 | 
			
		||||
                    _TeamPerformancesToTeamPerformanceDifferencesLayer.UntypedFactors.Concat(
 | 
			
		||||
                        _TeamDifferencesComparisonLayer.UntypedFactors);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void BuildLayer()
 | 
			
		||||
        {
 | 
			
		||||
            _TeamPerformancesToTeamPerformanceDifferencesLayer.SetRawInputVariablesGroups(InputVariablesGroups);
 | 
			
		||||
            _TeamPerformancesToTeamPerformanceDifferencesLayer.BuildLayer();
 | 
			
		||||
 | 
			
		||||
            _TeamDifferencesComparisonLayer.SetRawInputVariablesGroups(
 | 
			
		||||
                _TeamPerformancesToTeamPerformanceDifferencesLayer.GetRawOutputVariablesGroups());
 | 
			
		||||
            _TeamDifferencesComparisonLayer.BuildLayer();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override Schedule<GaussianDistribution> CreatePriorSchedule()
 | 
			
		||||
        {
 | 
			
		||||
            Schedule<GaussianDistribution> loop = null;
 | 
			
		||||
 | 
			
		||||
            switch (InputVariablesGroups.Count)
 | 
			
		||||
            {
 | 
			
		||||
                case 0:
 | 
			
		||||
                case 1:
 | 
			
		||||
                    throw new InvalidOperationException();
 | 
			
		||||
                case 2:
 | 
			
		||||
                    loop = CreateTwoTeamInnerPriorLoopSchedule();
 | 
			
		||||
                    break;
 | 
			
		||||
                default:
 | 
			
		||||
                    loop = CreateMultipleTeamInnerPriorLoopSchedule();
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // When dealing with differences, there are always (n-1) differences, so add in the 1
 | 
			
		||||
            int totalTeamDifferences = _TeamPerformancesToTeamPerformanceDifferencesLayer.LocalFactors.Count;
 | 
			
		||||
            int totalTeams = totalTeamDifferences + 1;
 | 
			
		||||
 | 
			
		||||
            var innerSchedule = new ScheduleSequence<GaussianDistribution>(
 | 
			
		||||
                "inner schedule",
 | 
			
		||||
                new[]
 | 
			
		||||
                    {
 | 
			
		||||
                        loop,
 | 
			
		||||
                        new ScheduleStep<GaussianDistribution>(
 | 
			
		||||
                            "teamPerformanceToPerformanceDifferenceFactors[0] @ 1",
 | 
			
		||||
                            _TeamPerformancesToTeamPerformanceDifferencesLayer.LocalFactors[0], 1),
 | 
			
		||||
                        new ScheduleStep<GaussianDistribution>(
 | 
			
		||||
                            String.Format("teamPerformanceToPerformanceDifferenceFactors[teamTeamDifferences = {0} - 1] @ 2",
 | 
			
		||||
                                          totalTeamDifferences),
 | 
			
		||||
                            _TeamPerformancesToTeamPerformanceDifferencesLayer.LocalFactors[totalTeamDifferences - 1], 2)
 | 
			
		||||
                    }
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
            return innerSchedule;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Schedule<GaussianDistribution> CreateTwoTeamInnerPriorLoopSchedule()
 | 
			
		||||
        {
 | 
			
		||||
            return ScheduleSequence(
 | 
			
		||||
                new[]
 | 
			
		||||
                    {
 | 
			
		||||
                        new ScheduleStep<GaussianDistribution>(
 | 
			
		||||
                            "send team perf to perf differences",
 | 
			
		||||
                            _TeamPerformancesToTeamPerformanceDifferencesLayer.LocalFactors[0],
 | 
			
		||||
                            0),
 | 
			
		||||
                        new ScheduleStep<GaussianDistribution>(
 | 
			
		||||
                            "send to greater than or within factor",
 | 
			
		||||
                            _TeamDifferencesComparisonLayer.LocalFactors[0],
 | 
			
		||||
                            0)
 | 
			
		||||
                    },
 | 
			
		||||
                "loop of just two teams inner sequence");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Schedule<GaussianDistribution> CreateMultipleTeamInnerPriorLoopSchedule()
 | 
			
		||||
        {
 | 
			
		||||
            int totalTeamDifferences = _TeamPerformancesToTeamPerformanceDifferencesLayer.LocalFactors.Count;
 | 
			
		||||
 | 
			
		||||
            var forwardScheduleList = new List<Schedule<GaussianDistribution>>();
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < totalTeamDifferences - 1; i++)
 | 
			
		||||
            {
 | 
			
		||||
                Schedule<GaussianDistribution> currentForwardSchedulePiece =
 | 
			
		||||
                    ScheduleSequence(
 | 
			
		||||
                        new Schedule<GaussianDistribution>[]
 | 
			
		||||
                            {
 | 
			
		||||
                                new ScheduleStep<GaussianDistribution>(
 | 
			
		||||
                                    String.Format("team perf to perf diff {0}",
 | 
			
		||||
                                                  i),
 | 
			
		||||
                                    _TeamPerformancesToTeamPerformanceDifferencesLayer.LocalFactors[i], 0),
 | 
			
		||||
                                new ScheduleStep<GaussianDistribution>(
 | 
			
		||||
                                    String.Format("greater than or within result factor {0}",
 | 
			
		||||
                                                  i),
 | 
			
		||||
                                    _TeamDifferencesComparisonLayer.LocalFactors[i],
 | 
			
		||||
                                    0),
 | 
			
		||||
                                new ScheduleStep<GaussianDistribution>(
 | 
			
		||||
                                    String.Format("team perf to perf diff factors [{0}], 2",
 | 
			
		||||
                                                  i),
 | 
			
		||||
                                    _TeamPerformancesToTeamPerformanceDifferencesLayer.LocalFactors[i], 2)
 | 
			
		||||
                            }, "current forward schedule piece {0}", i);
 | 
			
		||||
 | 
			
		||||
                forwardScheduleList.Add(currentForwardSchedulePiece);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var forwardSchedule =
 | 
			
		||||
                new ScheduleSequence<GaussianDistribution>(
 | 
			
		||||
                    "forward schedule",
 | 
			
		||||
                    forwardScheduleList);
 | 
			
		||||
 | 
			
		||||
            var backwardScheduleList = new List<Schedule<GaussianDistribution>>();
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < totalTeamDifferences - 1; i++)
 | 
			
		||||
            {
 | 
			
		||||
                var currentBackwardSchedulePiece = new ScheduleSequence<GaussianDistribution>(
 | 
			
		||||
                    "current backward schedule piece",
 | 
			
		||||
                    new Schedule<GaussianDistribution>[]
 | 
			
		||||
                        {
 | 
			
		||||
                            new ScheduleStep<GaussianDistribution>(
 | 
			
		||||
                                String.Format("teamPerformanceToPerformanceDifferenceFactors[totalTeamDifferences - 1 - {0}] @ 0",
 | 
			
		||||
                                              i),
 | 
			
		||||
                                _TeamPerformancesToTeamPerformanceDifferencesLayer.LocalFactors[
 | 
			
		||||
                                    totalTeamDifferences - 1 - i], 0),
 | 
			
		||||
                            new ScheduleStep<GaussianDistribution>(
 | 
			
		||||
                                String.Format("greaterThanOrWithinResultFactors[totalTeamDifferences - 1 - {0}] @ 0",
 | 
			
		||||
                                              i),
 | 
			
		||||
                                _TeamDifferencesComparisonLayer.LocalFactors[totalTeamDifferences - 1 - i], 0),
 | 
			
		||||
                            new ScheduleStep<GaussianDistribution>(
 | 
			
		||||
                                String.Format("teamPerformanceToPerformanceDifferenceFactors[totalTeamDifferences - 1 - {0}] @ 1",
 | 
			
		||||
                                              i),
 | 
			
		||||
                                _TeamPerformancesToTeamPerformanceDifferencesLayer.LocalFactors[
 | 
			
		||||
                                    totalTeamDifferences - 1 - i], 1)
 | 
			
		||||
                        }
 | 
			
		||||
                    );
 | 
			
		||||
                backwardScheduleList.Add(currentBackwardSchedulePiece);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var backwardSchedule =
 | 
			
		||||
                new ScheduleSequence<GaussianDistribution>(
 | 
			
		||||
                    "backward schedule",
 | 
			
		||||
                    backwardScheduleList);
 | 
			
		||||
 | 
			
		||||
            var forwardBackwardScheduleToLoop =
 | 
			
		||||
                new ScheduleSequence<GaussianDistribution>(
 | 
			
		||||
                    "forward Backward Schedule To Loop",
 | 
			
		||||
                    new Schedule<GaussianDistribution>[]
 | 
			
		||||
                        {
 | 
			
		||||
                            forwardSchedule, backwardSchedule
 | 
			
		||||
                        });
 | 
			
		||||
 | 
			
		||||
            const double initialMaxDelta = 0.0001;
 | 
			
		||||
 | 
			
		||||
            var loop = new ScheduleLoop<GaussianDistribution>(
 | 
			
		||||
                String.Format("loop with max delta of {0}",
 | 
			
		||||
                              initialMaxDelta),
 | 
			
		||||
                forwardBackwardScheduleToLoop,
 | 
			
		||||
                initialMaxDelta);
 | 
			
		||||
 | 
			
		||||
            return loop;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,68 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using Moserware.Numerics;
 | 
			
		||||
using Moserware.Skills.FactorGraphs;
 | 
			
		||||
using Moserware.Skills.TrueSkill.Factors;
 | 
			
		||||
 | 
			
		||||
namespace Moserware.Skills.TrueSkill.Layers
 | 
			
		||||
{
 | 
			
		||||
    internal class PlayerPerformancesToTeamPerformancesLayer<TPlayer> :
 | 
			
		||||
        TrueSkillFactorGraphLayer
 | 
			
		||||
            <TPlayer, KeyedVariable<TPlayer, GaussianDistribution>, GaussianWeightedSumFactor,
 | 
			
		||||
            Variable<GaussianDistribution>>
 | 
			
		||||
    {
 | 
			
		||||
        public PlayerPerformancesToTeamPerformancesLayer(TrueSkillFactorGraph<TPlayer> parentGraph)
 | 
			
		||||
            : base(parentGraph)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void BuildLayer()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (var currentTeam in InputVariablesGroups)
 | 
			
		||||
            {
 | 
			
		||||
                Variable<GaussianDistribution> teamPerformance = CreateOutputVariable(currentTeam);
 | 
			
		||||
                AddLayerFactor(CreatePlayerToTeamSumFactor(currentTeam, teamPerformance));
 | 
			
		||||
 | 
			
		||||
                // REVIEW: Does it make sense to have groups of one?
 | 
			
		||||
                OutputVariablesGroups.Add(new[] {teamPerformance});
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override Schedule<GaussianDistribution> CreatePriorSchedule()
 | 
			
		||||
        {
 | 
			
		||||
            return ScheduleSequence(
 | 
			
		||||
                from weightedSumFactor in LocalFactors
 | 
			
		||||
                select new ScheduleStep<GaussianDistribution>("Perf to Team Perf Step", weightedSumFactor, 0),
 | 
			
		||||
                "all player perf to team perf schedule");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected GaussianWeightedSumFactor CreatePlayerToTeamSumFactor(
 | 
			
		||||
            IList<KeyedVariable<TPlayer, GaussianDistribution>> teamMembers, Variable<GaussianDistribution> sumVariable)
 | 
			
		||||
        {
 | 
			
		||||
            return new GaussianWeightedSumFactor(sumVariable, teamMembers.ToArray(),
 | 
			
		||||
                                                 teamMembers.Select(v => PartialPlay.GetPartialPlayPercentage(v.Key)).
 | 
			
		||||
                                                     ToArray());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override Schedule<GaussianDistribution> CreatePosteriorSchedule()
 | 
			
		||||
        {
 | 
			
		||||
            return ScheduleSequence(from currentFactor in LocalFactors
 | 
			
		||||
                                    from currentIteration in
 | 
			
		||||
                                        Enumerable.Range(1, currentFactor.NumberOfMessages - 1)
 | 
			
		||||
                                    select new ScheduleStep<GaussianDistribution>(
 | 
			
		||||
                                        "team sum perf @" + currentIteration,
 | 
			
		||||
                                        currentFactor,
 | 
			
		||||
                                        currentIteration),
 | 
			
		||||
                                    "all of the team's sum iterations");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Variable<GaussianDistribution> CreateOutputVariable(
 | 
			
		||||
            IList<KeyedVariable<TPlayer, GaussianDistribution>> team)
 | 
			
		||||
        {
 | 
			
		||||
            string teamMemberNames = String.Join(", ", team.Select(teamMember => teamMember.Key.ToString()).ToArray());
 | 
			
		||||
 | 
			
		||||
            return ParentFactorGraph.VariableFactory.CreateBasicVariable("Team[{0}]'s performance", teamMemberNames);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										63
									
								
								Skills/TrueSkill/Layers/PlayerPriorValuesToSkillsLayer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								Skills/TrueSkill/Layers/PlayerPriorValuesToSkillsLayer.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using Moserware.Numerics;
 | 
			
		||||
using Moserware.Skills.FactorGraphs;
 | 
			
		||||
using Moserware.Skills.TrueSkill.Factors;
 | 
			
		||||
 | 
			
		||||
namespace Moserware.Skills.TrueSkill.Layers
 | 
			
		||||
{
 | 
			
		||||
    // We intentionally have no Posterior schedule since the only purpose here is to 
 | 
			
		||||
    internal class PlayerPriorValuesToSkillsLayer<TPlayer> :
 | 
			
		||||
        TrueSkillFactorGraphLayer
 | 
			
		||||
            <TPlayer, DefaultVariable<GaussianDistribution>, GaussianPriorFactor,
 | 
			
		||||
            KeyedVariable<TPlayer, GaussianDistribution>>
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IEnumerable<IDictionary<TPlayer, Rating>> _Teams;
 | 
			
		||||
 | 
			
		||||
        public PlayerPriorValuesToSkillsLayer(TrueSkillFactorGraph<TPlayer> parentGraph,
 | 
			
		||||
                                              IEnumerable<IDictionary<TPlayer, Rating>> teams)
 | 
			
		||||
            : base(parentGraph)
 | 
			
		||||
        {
 | 
			
		||||
            _Teams = teams;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void BuildLayer()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (var currentTeam in _Teams)
 | 
			
		||||
            {
 | 
			
		||||
                var currentTeamSkills = new List<KeyedVariable<TPlayer, GaussianDistribution>>();
 | 
			
		||||
 | 
			
		||||
                foreach (var currentTeamPlayer in currentTeam)
 | 
			
		||||
                {
 | 
			
		||||
                    KeyedVariable<TPlayer, GaussianDistribution> playerSkill =
 | 
			
		||||
                        CreateSkillOutputVariable(currentTeamPlayer.Key);
 | 
			
		||||
                    AddLayerFactor(CreatePriorFactor(currentTeamPlayer.Key, currentTeamPlayer.Value, playerSkill));
 | 
			
		||||
                    currentTeamSkills.Add(playerSkill);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                OutputVariablesGroups.Add(currentTeamSkills);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override Schedule<GaussianDistribution> CreatePriorSchedule()
 | 
			
		||||
        {
 | 
			
		||||
            return ScheduleSequence(
 | 
			
		||||
                from prior in LocalFactors
 | 
			
		||||
                select new ScheduleStep<GaussianDistribution>("Prior to Skill Step", prior, 0),
 | 
			
		||||
                "All priors");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private GaussianPriorFactor CreatePriorFactor(TPlayer player, Rating priorRating,
 | 
			
		||||
                                                      Variable<GaussianDistribution> skillsVariable)
 | 
			
		||||
        {
 | 
			
		||||
            return new GaussianPriorFactor(priorRating.Mean,
 | 
			
		||||
                                           Square(priorRating.StandardDeviation) +
 | 
			
		||||
                                           Square(ParentFactorGraph.GameInfo.DynamicsFactor), skillsVariable);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private KeyedVariable<TPlayer, GaussianDistribution> CreateSkillOutputVariable(TPlayer key)
 | 
			
		||||
        {
 | 
			
		||||
            return ParentFactorGraph.VariableFactory.CreateKeyedVariable(key, "{0}'s skill", key);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										64
									
								
								Skills/TrueSkill/Layers/PlayerSkillsToPerformancesLayer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								Skills/TrueSkill/Layers/PlayerSkillsToPerformancesLayer.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using Moserware.Numerics;
 | 
			
		||||
using Moserware.Skills.FactorGraphs;
 | 
			
		||||
using Moserware.Skills.TrueSkill.Factors;
 | 
			
		||||
 | 
			
		||||
namespace Moserware.Skills.TrueSkill.Layers
 | 
			
		||||
{
 | 
			
		||||
    internal class PlayerSkillsToPerformancesLayer<TPlayer> :
 | 
			
		||||
        TrueSkillFactorGraphLayer
 | 
			
		||||
            <TPlayer, KeyedVariable<TPlayer, GaussianDistribution>, GaussianLikelihoodFactor,
 | 
			
		||||
            KeyedVariable<TPlayer, GaussianDistribution>>
 | 
			
		||||
    {
 | 
			
		||||
        public PlayerSkillsToPerformancesLayer(TrueSkillFactorGraph<TPlayer> parentGraph)
 | 
			
		||||
            : base(parentGraph)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void BuildLayer()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (var currentTeam in InputVariablesGroups)
 | 
			
		||||
            {
 | 
			
		||||
                var currentTeamPlayerPerformances = new List<KeyedVariable<TPlayer, GaussianDistribution>>();
 | 
			
		||||
 | 
			
		||||
                foreach (var playerSkillVariable in currentTeam)
 | 
			
		||||
                {
 | 
			
		||||
                    KeyedVariable<TPlayer, GaussianDistribution> playerPerformance =
 | 
			
		||||
                        CreateOutputVariable(playerSkillVariable.Key);
 | 
			
		||||
                    AddLayerFactor(CreateLikelihood(playerSkillVariable, playerPerformance));
 | 
			
		||||
                    currentTeamPlayerPerformances.Add(playerPerformance);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                OutputVariablesGroups.Add(currentTeamPlayerPerformances);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private GaussianLikelihoodFactor CreateLikelihood(KeyedVariable<TPlayer, GaussianDistribution> playerSkill,
 | 
			
		||||
                                                          KeyedVariable<TPlayer, GaussianDistribution> playerPerformance)
 | 
			
		||||
        {
 | 
			
		||||
            return new GaussianLikelihoodFactor(Square(ParentFactorGraph.GameInfo.Beta), playerPerformance, playerSkill);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private KeyedVariable<TPlayer, GaussianDistribution> CreateOutputVariable(TPlayer key)
 | 
			
		||||
        {
 | 
			
		||||
            return ParentFactorGraph.VariableFactory.CreateKeyedVariable(key, "{0}'s performance", key);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override Schedule<GaussianDistribution> CreatePriorSchedule()
 | 
			
		||||
        {
 | 
			
		||||
            return ScheduleSequence(
 | 
			
		||||
                from likelihood in LocalFactors
 | 
			
		||||
                select new ScheduleStep<GaussianDistribution>("Skill to Perf step", likelihood, 0),
 | 
			
		||||
                "All skill to performance sending");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override Schedule<GaussianDistribution> CreatePosteriorSchedule()
 | 
			
		||||
        {
 | 
			
		||||
            return ScheduleSequence(
 | 
			
		||||
                from likelihood in LocalFactors
 | 
			
		||||
                select new ScheduleStep<GaussianDistribution>("name", likelihood, 1),
 | 
			
		||||
                "All skill to performance sending");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								Skills/TrueSkill/Layers/TeamDifferencesComparisonLayer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								Skills/TrueSkill/Layers/TeamDifferencesComparisonLayer.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
using Moserware.Numerics;
 | 
			
		||||
using Moserware.Skills.FactorGraphs;
 | 
			
		||||
using Moserware.Skills.TrueSkill.Factors;
 | 
			
		||||
 | 
			
		||||
namespace Moserware.Skills.TrueSkill.Layers
 | 
			
		||||
{
 | 
			
		||||
    internal class TeamDifferencesComparisonLayer<TPlayer> :
 | 
			
		||||
        TrueSkillFactorGraphLayer
 | 
			
		||||
            <TPlayer, Variable<GaussianDistribution>, GaussianFactor, DefaultVariable<GaussianDistribution>>
 | 
			
		||||
    {
 | 
			
		||||
        private readonly double _Epsilon;
 | 
			
		||||
        private readonly int[] _TeamRanks;
 | 
			
		||||
 | 
			
		||||
        public TeamDifferencesComparisonLayer(TrueSkillFactorGraph<TPlayer> parentGraph, int[] teamRanks)
 | 
			
		||||
            : base(parentGraph)
 | 
			
		||||
        {
 | 
			
		||||
            _TeamRanks = teamRanks;
 | 
			
		||||
            GameInfo gameInfo = ParentFactorGraph.GameInfo;
 | 
			
		||||
            _Epsilon = DrawMargin.GetDrawMarginFromDrawProbability(gameInfo.DrawProbability, gameInfo.Beta);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void BuildLayer()
 | 
			
		||||
        {
 | 
			
		||||
            for (int i = 0; i < InputVariablesGroups.Count; i++)
 | 
			
		||||
            {
 | 
			
		||||
                bool isDraw = (_TeamRanks[i] == _TeamRanks[i + 1]);
 | 
			
		||||
                Variable<GaussianDistribution> teamDifference = InputVariablesGroups[i][0];
 | 
			
		||||
 | 
			
		||||
                GaussianFactor factor =
 | 
			
		||||
                    isDraw
 | 
			
		||||
                        ? (GaussianFactor) new GaussianWithinFactor(_Epsilon, teamDifference)
 | 
			
		||||
                        : new GaussianGreaterThanFactor(_Epsilon, teamDifference);
 | 
			
		||||
 | 
			
		||||
                AddLayerFactor(factor);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,43 @@
 | 
			
		||||
using Moserware.Numerics;
 | 
			
		||||
using Moserware.Skills.FactorGraphs;
 | 
			
		||||
using Moserware.Skills.TrueSkill.Factors;
 | 
			
		||||
 | 
			
		||||
namespace Moserware.Skills.TrueSkill.Layers
 | 
			
		||||
{
 | 
			
		||||
    internal class TeamPerformancesToTeamPerformanceDifferencesLayer<TPlayer> :
 | 
			
		||||
        TrueSkillFactorGraphLayer
 | 
			
		||||
            <TPlayer, Variable<GaussianDistribution>, GaussianWeightedSumFactor, Variable<GaussianDistribution>>
 | 
			
		||||
    {
 | 
			
		||||
        public TeamPerformancesToTeamPerformanceDifferencesLayer(TrueSkillFactorGraph<TPlayer> parentGraph)
 | 
			
		||||
            : base(parentGraph)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void BuildLayer()
 | 
			
		||||
        {
 | 
			
		||||
            for (int i = 0; i < InputVariablesGroups.Count - 1; i++)
 | 
			
		||||
            {
 | 
			
		||||
                Variable<GaussianDistribution> strongerTeam = InputVariablesGroups[i][0];
 | 
			
		||||
                Variable<GaussianDistribution> weakerTeam = InputVariablesGroups[i + 1][0];
 | 
			
		||||
 | 
			
		||||
                Variable<GaussianDistribution> currentDifference = CreateOutputVariable();
 | 
			
		||||
                AddLayerFactor(CreateTeamPerformanceToDifferenceFactor(strongerTeam, weakerTeam, currentDifference));
 | 
			
		||||
 | 
			
		||||
                // REVIEW: Does it make sense to have groups of one?
 | 
			
		||||
                OutputVariablesGroups.Add(new[] {currentDifference});
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private GaussianWeightedSumFactor CreateTeamPerformanceToDifferenceFactor(
 | 
			
		||||
            Variable<GaussianDistribution> strongerTeam, Variable<GaussianDistribution> weakerTeam,
 | 
			
		||||
            Variable<GaussianDistribution> output)
 | 
			
		||||
        {
 | 
			
		||||
            return new GaussianWeightedSumFactor(output, new[] {strongerTeam, weakerTeam}, new[] {1.0, -1.0});
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Variable<GaussianDistribution> CreateOutputVariable()
 | 
			
		||||
        {
 | 
			
		||||
            return ParentFactorGraph.VariableFactory.CreateBasicVariable("Team performance difference");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								Skills/TrueSkill/Layers/TrueSkillFactorGraphLayer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								Skills/TrueSkill/Layers/TrueSkillFactorGraphLayer.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
using Moserware.Numerics;
 | 
			
		||||
using Moserware.Skills.FactorGraphs;
 | 
			
		||||
 | 
			
		||||
namespace Moserware.Skills.TrueSkill.Layers
 | 
			
		||||
{
 | 
			
		||||
    internal abstract class TrueSkillFactorGraphLayer<TPlayer, TInputVariable, TFactor, TOutputVariable>
 | 
			
		||||
        :
 | 
			
		||||
            FactorGraphLayer
 | 
			
		||||
                <TrueSkillFactorGraph<TPlayer>, GaussianDistribution, Variable<GaussianDistribution>, TInputVariable,
 | 
			
		||||
                TFactor, TOutputVariable>
 | 
			
		||||
        where TInputVariable : Variable<GaussianDistribution>
 | 
			
		||||
        where TFactor : Factor<GaussianDistribution>
 | 
			
		||||
        where TOutputVariable : Variable<GaussianDistribution>
 | 
			
		||||
    {
 | 
			
		||||
        public TrueSkillFactorGraphLayer(TrueSkillFactorGraph<TPlayer> parentGraph)
 | 
			
		||||
            : base(parentGraph)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user