Пример #1
0
        /// <summary>
        /// Trains the specified game.
        /// </summary>
        /// <param name="game">The game.</param>
        /// <param name="players">The players.</param>
        /// <param name="priors">The priors.</param>
        /// <returns>
        /// The <see cref="Results" />.
        /// </returns>
        public override Results Train(Game game, IList <string> players, Marginals priors)
        {
            var twoPlayer = game as TwoPlayerGame;

            if (twoPlayer == null)
            {
                throw new InvalidOperationException("Multi-player/team games not supported");
            }

            var skills = players.Select(ia => priors.Skills[ia]).ToArray();

            this.skill1Prior.ObservedValue = skills[0];
            this.skill2Prior.ObservedValue = skills[1];
            this.outcome.ObservedValue     = (int)twoPlayer.Outcome;

            this.drawMarginPrior.ObservedValue = priors.DrawMargin;

            return(new Results
            {
                Posteriors =
                    new Posteriors(
                        players,
                        new Gaussian[] {
                    this.engine.Infer <Gaussian>(this.player1skill),
                    this.engine.Infer <Gaussian>(this.player2skill)
                },
                        this.engine.Infer <Gaussian>(this.drawMargin))
            });
        }
Пример #2
0
        /// <summary>
        /// Trains the specified game.
        /// </summary>
        /// <param name="game">The game.</param>
        /// <param name="players">The players.</param>
        /// <param name="priors">The priors.</param>
        /// <returns>
        /// The <see cref="Results" />.
        /// </returns>
        /// <exception cref="System.NotSupportedException">Multi-team games not supported</exception>
        public override Results Train(Game game, IList<string> players, Marginals priors)
        {
            var teamGame = game as TeamGame;
            if (teamGame == null)
            {
                throw new NotSupportedException("Multi-team games not supported");
            }

            this.numberOfPlayers.ObservedValue = teamGame.Players.Count;
            this.skillPriors.ObservedValue = teamGame.Players.Select(ia => priors.Skills[ia]).ToArray();
            this.drawMarginPrior.ObservedValue = priors.DrawMargin;

            this.team1Count.ObservedValue = teamGame.TeamCounts[0];
            this.team2Count.ObservedValue = teamGame.TeamCounts[1];

            this.team1Players.ObservedValue = teamGame.Teams[0].PlayerScores.Keys.Select(players.IndexOf).ToArray();
            this.team2Players.ObservedValue = teamGame.Teams[1].PlayerScores.Keys.Select(players.IndexOf).ToArray();

            this.outcome.ObservedValue = (int)teamGame.Outcome;

            return new Results
                       {
                           Posteriors =
                               new Posteriors(
                               players,
                               this.engine.Infer<Gaussian[]>(this.skills),
                               this.engine.Infer<Gaussian>(this.drawMargin))
                       };
        }
Пример #3
0
        /// <summary>
        /// Predicts the outcome (ranking) of a game.
        /// </summary>
        /// <param name="game">The game.</param>
        /// <param name="posteriors">The posteriors.</param>
        /// <returns>
        /// The <see cref="TwoPlayerPrediction" />.
        /// </returns>
        /// <exception cref="System.InvalidOperationException">Multi-player/team games not supported</exception>
        public override Prediction PredictOutcome(Game game, Marginals posteriors)
        {
            var twoPlayer = game as TwoPlayerGame;

            if (twoPlayer == null)
            {
                return(null);
            }

            var skills = game.Players.Select(p => posteriors.Skills[p]).ToArray();

            this.skill1Prior.ObservedValue = skills[0];
            this.skill2Prior.ObservedValue = skills[1];

            var outcomePosterior = this.engine.Infer <Bernoulli>(this.outcome);

            return(new TwoPlayerPrediction
            {
                Actual = twoPlayer.Outcome,
                Predicted =
                    outcomePosterior.GetProbTrue() > 0.5 ? MatchOutcome.Player1Win : MatchOutcome.Player2Win,
                LogProbOfTruth =
                    twoPlayer.Outcome == MatchOutcome.Draw
                                   ? double.NaN
                                   : outcomePosterior.GetLogProb(twoPlayer.Outcome == MatchOutcome.Player1Win),
                IncludeDraws = false
            });
        }
Пример #4
0
        /// <summary>
        /// Trains the specified game.
        /// </summary>
        /// <param name="game">The game.</param>
        /// <param name="players">The players.</param>
        /// <param name="priors">The priors.</param>
        /// <returns>
        /// The <see cref="Results" />.
        /// </returns>
        public override Results Train(Game game, IList <string> players, Marginals priors)
        {
            var multiPlayerGame = game as MultiPlayerGame;

            if (multiPlayerGame == null)
            {
                throw new InvalidOperationException("Incorrect game type");
            }

            this.numberOfPlayers.ObservedValue = players.Count;
            this.skillPriors.ObservedValue     = players.Select(ia => priors.Skills[ia]).ToArray();
            this.drawMarginPrior.ObservedValue = priors.DrawMargin;

            this.playersPerGame.ObservedValue = multiPlayerGame.Players.Count;

            // order the indices of the players by descending order of score
            this.playerIndices.ObservedValue = multiPlayerGame.PlayersInDescendingScoreOrder.Select(players.IndexOf).ToArray();

            this.scores.ObservedValue = multiPlayerGame.Scores.OrderByDescending(x => x).ToArray();

            return(new Results
            {
                Posteriors =
                    new Posteriors(
                        players,
                        this.engine.Infer <Gaussian[]>(this.skills),
                        this.engine.Infer <Gaussian>(this.drawMargin))
            });
        }
Пример #5
0
        /// <summary>
        /// Samples from the model.
        /// </summary>
        /// <param name="truth">The truth.</param>
        /// <param name="players">The players.</param>
        /// <param name="performanceVariance">The performance variance.</param>
        /// <param name="drawMargin">The draw margin.</param>
        /// <returns>
        /// The <see cref="Game" />.
        /// </returns>
        public static Game Sample(Marginals truth, IList <string> players, double performanceVariance, double drawMargin)
        {
            double perf1 = new Gaussian(truth.Skills[players[0]].GetMean(), performanceVariance).Sample();
            double perf2 = new Gaussian(truth.Skills[players[1]].GetMean(), performanceVariance).Sample();

            double       diff    = perf1 - perf2;
            MatchOutcome outcome = diff < drawMargin ? MatchOutcome.Draw : (diff > 0 ? MatchOutcome.Player1Win : MatchOutcome.Player2Win);

            return(TwoPlayerGame.CreateGame(Guid.NewGuid().ToString(), players[0], players[1], outcome));
        }
Пример #6
0
        /// <summary>
        /// Runs the specified model.
        /// </summary>
        /// <param name="games">The games.</param>
        /// <param name="count">The count.</param>
        /// <param name="verbose">if set to <c>true</c> [verbose].</param>
        public override void Run(IEnumerable <Game> games, int count, bool verbose)
        {
            this.PlayerPosteriors = this.Priors.Skills.ToDictionary(ia => ia.Key, ia => new List <Gaussian> {
                ia.Value
            });
            this.DrawMargins = new List <Gaussian> {
                this.Priors.DrawMargin
            };
            this.Predictions = new List <Prediction>();

            using (new CodeTimer(this.Name))
            {
                foreach (var game in games)
                {
                    var priors = new Marginals {
                        DrawMargin = this.DrawMargins.Last()
                    };

                    foreach (var player in game.Players)
                    {
                        if (!this.PlayerPosteriors.ContainsKey(player))
                        {
                            this.PlayerPosteriors[player] = new List <Gaussian> {
                                this.SkillPrior
                            };
                        }

                        priors.Skills[player] = this.PlayerPosteriors[player].Last();
                    }

                    // Predict outcome of game
                    var prediction = PredictModel?.PredictOutcome(game, priors);
                    if (prediction != null)
                    {
                        this.Predictions.Add(prediction);
                    }

                    // Train model using this game
                    this.LastResults = this.TrainModel.Train(game, game.Players, priors);

                    foreach (var player in game.Players)
                    {
                        this.PlayerPosteriors[player].Add(this.LastResults.Posteriors.Skills[player]);
                    }

                    this.DrawMargins.Add(this.LastResults.Posteriors.DrawMargin);

                    if (verbose)
                    {
                        var post = this.LastResults.Posteriors.Skills.Select(ia => $"{ia.Key}: {ia.Value}").ToArray();
                        Console.WriteLine(@"Game {0}, Posteriors: {1}", game.Id, string.Join(", ", post));
                    }
                }
            }
        }
Пример #7
0
        /// <summary>
        /// Samples from the model.
        /// </summary>
        /// <param name="truth">The truth.</param>
        /// <param name="players">The players.</param>
        /// <param name="performanceVariance">The performance variance.</param>
        /// <returns>The <see cref="Game"/>.</returns>
        public static TwoPlayerGame Sample(Marginals truth, IList <string> players, double performanceVariance)
        {
            double perf1 = new Gaussian(truth.Skills[players[0]].GetMean(), performanceVariance).Sample();
            double perf2 = new Gaussian(truth.Skills[players[1]].GetMean(), performanceVariance).Sample();

            return(TwoPlayerGame.CreateGame(
                       Guid.NewGuid().ToString(),
                       players[0],
                       players[1],
                       perf1 > perf2 ? MatchOutcome.Player1Win : MatchOutcome.Player2Win));
        }
Пример #8
0
 /// <summary>
 /// Predicts the outcome of a game.
 /// </summary>
 /// <param name="game">The game.</param>
 /// <param name="posteriors">The posteriors.</param>
 /// <returns>
 /// The <see cref="TwoPlayerPrediction" />.
 /// </returns>
 /// <exception cref="System.InvalidOperationException">Multi-player/team games not supported</exception>
 public TwoPlayerPrediction PredictOutcome(TwoPlayerGame game, Marginals posteriors)
 {
     return(new TwoPlayerPrediction
     {
         Actual = game.Outcome,
         Predicted =
             this.Parameters.IncludeDraws
                            ? (MatchOutcome)this.OutcomeDistribution.Sample()
                            : (Rand.Int(2) == 0 ? MatchOutcome.Player1Win : MatchOutcome.Player2Win),
         IncludeDraws = this.Parameters.IncludeDraws
     });
 }
Пример #9
0
 /// <summary>
 /// Predicts the outcome of a game.
 /// </summary>
 /// <param name="game">The game.</param>
 /// <param name="posteriors">The posteriors.</param>
 /// <returns>
 /// The <see cref="TwoTeamPrediction" />.
 /// </returns>
 public TwoTeamPrediction PredictOutcome(TeamGame game, Marginals posteriors)
 {
     return(new TwoTeamPrediction
     {
         Actual = game.Outcome,
         Predicted =
             this.Parameters.IncludeDraws
                 ? (TeamMatchOutcome)this.OutcomeDistribution.Sample()
                 : (Rand.Int(2) == 0 ? TeamMatchOutcome.Team1Win : TeamMatchOutcome.Team2Win),
         IncludeDraws = this.Parameters.IncludeDraws
     });
 }
Пример #10
0
        /// <summary>
        /// Trains the specified games.
        /// </summary>
        /// <param name="games">The games.</param>
        /// <param name="players">The players.</param>
        /// <param name="priors">The priors.</param>
        /// <returns>The <see cref="IList{Results}"/>.</returns>
        public IList <Results> Train(IList <Game> games, IList <string> players, Marginals priors)
        {
            var results = new List <Results> {
                new Results {
                    Posteriors = priors
                }
            };

            foreach (var game in games)
            {
                results.Add(this.Train(game, players, results.Last().Posteriors));
            }

            return(results);
        }
Пример #11
0
        /// <summary>
        /// Predicts the outcome of a game.
        /// </summary>
        /// <param name="game">The game.</param>
        /// <param name="posteriors">The posteriors.</param>
        /// <returns>
        /// The <see cref="Prediction" />.
        /// </returns>
        public override Prediction PredictOutcome(Game game, Marginals posteriors)
        {
            var teamGame = game as TeamGame;
            if (teamGame == null)
            {
                // unsupported game type
                return null;
            }

            this.numberOfPlayers.ObservedValue = teamGame.Players.Count;
            this.skillPriors.ObservedValue = teamGame.Players.Select(ia => posteriors.Skills[ia]).ToArray();
            this.drawMarginPrior.ObservedValue = posteriors.DrawMargin;

            this.team1Count.ObservedValue = teamGame.TeamCounts[0];
            this.team2Count.ObservedValue = teamGame.TeamCounts[1];

            this.team1Players.ObservedValue = teamGame.Teams[0].PlayerScores.Keys.Select(teamGame.Players.IndexOf).ToArray();
            this.team2Players.ObservedValue = teamGame.Teams[1].PlayerScores.Keys.Select(teamGame.Players.IndexOf).ToArray();

            var outcomePosterior = this.engine.Infer<Discrete>(this.outcome);
            double logProbOfTruth = outcomePosterior.GetLogProb((int)teamGame.Outcome);

            // check if multimodal
            if (outcomePosterior.GetMode() == 0 &&
                Math.Abs(outcomePosterior.Evaluate(0) - outcomePosterior.Evaluate(2)) < double.Epsilon)
            {
                // Random outcome
                var randomOutcome = Rand.Int(2) == 0 ? TeamMatchOutcome.Team1Win : TeamMatchOutcome.Team2Win;
                return new TwoTeamPrediction
                           {
                               Actual = teamGame.Outcome,
                               Predicted = randomOutcome,
                               IncludeDraws = true,
                               LogProbOfTruth = logProbOfTruth
                           };
            }

            return new TwoTeamPrediction
            {
                Actual = teamGame.Outcome,
                Predicted = (TeamMatchOutcome)outcomePosterior.GetMode(),
                LogProbOfTruth = logProbOfTruth,
                IncludeDraws = true
            };
        }
Пример #12
0
        /// <summary>
        /// Predicts the outcome of a game.
        /// </summary>
        /// <param name="game">The game.</param>
        /// <param name="posteriors">The posteriors.</param>
        /// <returns>
        /// The <see cref="Prediction" />.
        /// </returns>
        public Prediction PredictOutcome(Game game, Marginals posteriors)
        {
            var twoPlayer = game as TwoPlayerGame;

            if (twoPlayer != null)
            {
                return(this.PredictOutcome(twoPlayer, posteriors));
            }

            var teamGame = game as TeamGame;

            if (teamGame != null)
            {
                return(this.PredictOutcome(teamGame, posteriors));
            }

            // Unsupported game type
            return(null);
        }
Пример #13
0
        /// <summary>
        /// Predicts the outcome of a game.
        /// </summary>
        /// <param name="game">The game.</param>
        /// <param name="posteriors">The posteriors.</param>
        /// <returns>
        /// The <see cref="Prediction" />.
        /// </returns>
        /// <exception cref="System.InvalidOperationException">Multi-player/team games not supported</exception>
        public override Prediction PredictOutcome(Game game, Marginals posteriors)
        {
            var twoPlayer = game as TwoPlayerGame;

            if (twoPlayer == null)
            {
                return(null);
            }

            var skills = game.Players.Select(p => posteriors.Skills[p]).ToArray();

            this.skill1Prior.ObservedValue     = skills[0];
            this.skill2Prior.ObservedValue     = skills[1];
            this.drawMarginPrior.ObservedValue = posteriors.DrawMargin;

            var outcomePosterior = this.engine.Infer <Discrete>(this.outcome);

            // check if multimodal
            if (outcomePosterior.GetMode() == 0 &&
                Math.Abs(outcomePosterior.Evaluate(0) - outcomePosterior.Evaluate(2)) < double.Epsilon)
            {
                // Random outcome
                var randomOutcome = Rand.Int(2) == 0 ? MatchOutcome.Player1Win : MatchOutcome.Player2Win;
                return(new TwoPlayerPrediction {
                    Actual = twoPlayer.Outcome, Predicted = randomOutcome, IncludeDraws = true
                });
            }

            return(new TwoPlayerPrediction
            {
                Actual = twoPlayer.Outcome,
                Predicted = (MatchOutcome)outcomePosterior.GetMode(),
                LogProbOfTruth = outcomePosterior.GetLogProb((int)twoPlayer.Outcome),
                IncludeDraws = true
            });
        }
Пример #14
0
 /// <summary>
 /// Predicts the outcome of a game.
 /// </summary>
 /// <param name="game">The game.</param>
 /// <param name="posteriors">The posteriors.</param>
 /// <returns>
 /// The <see cref="Prediction" />.
 /// </returns>
 public abstract Prediction PredictOutcome(Game game, Marginals posteriors);
Пример #15
0
 /// <summary>
 /// Trains the specified game.
 /// </summary>
 /// <param name="game">The game.</param>
 /// <param name="players">The players.</param>
 /// <param name="priors">The priors.</param>
 /// <returns>The <see cref="Results"/>.</returns>
 public abstract Results Train(Game game, IList <string> players, Marginals priors);
Пример #16
0
 /// <summary>
 /// Trains the specified game.
 /// </summary>
 /// <param name="game">The game.</param>
 /// <param name="players">The players.</param>
 /// <param name="priors">The priors.</param>
 /// <returns>
 /// The <see cref="Results" />.
 /// </returns>
 public Results Train(Game game, IList <string> players, Marginals priors)
 {
     return(new Results {
         Posteriors = priors
     });
 }
Пример #17
0
 /// <summary>
 /// Trains the specified games.
 /// </summary>
 /// <param name="games">The games.</param>
 /// <param name="players">The players.</param>
 /// <param name="priors">The priors.</param>
 /// <returns>
 /// The <see cref="IList{Results}" />.
 /// </returns>
 public IList <Results> Train(IList <Game> games, IList <string> players, Marginals priors)
 {
     return(games.Select(ia => new Results {
         Posteriors = priors
     }).ToList());
 }
Пример #18
0
 /// <summary>
 /// Predicts the outcome of a game.
 /// </summary>
 /// <param name="game">The game.</param>
 /// <param name="posteriors">The posteriors.</param>
 /// <returns>
 /// The <see cref="Prediction" />.
 /// </returns>
 public override Prediction PredictOutcome(Game game, Marginals posteriors)
 {
     // Not supported for this class
     return(null);
 }
Пример #19
0
        /// <summary>
        /// Samples the specified inputs.
        /// </summary>
        /// <param name="performanceVariance">The performance variance.</param>
        /// <param name="playerIndices">The player indices.</param>
        /// <param name="truth">The truth.</param>
        /// <param name="startIndex">The start index.</param>
        /// <returns>
        /// The <see cref="GameCollection" />.
        /// </returns>
        public static GameCollection Sample(double performanceVariance, int[][] playerIndices, Marginals truth, int startIndex = 0)
        {
            // var random = new Random(0);
            var players = truth.Skills.Keys.ToArray();
            var games   = new GameCollection(ia => ia.Id);
            int count   = playerIndices.Length;

            for (int i = 0; i < count; i++)
            {
                // Because this model relies on the fact that the game scores are provided in descending order,
                // we need to randomise the player order
                var randomIndices = playerIndices[i].OrderBy(ia => Guid.NewGuid()).ToArray();

                // Skills
                var skills = playerIndices[i].Select(ia => truth.Skills[players[ia]].Point).ToArray();

                // Sample peformances to get scores
                var scores = skills.Select(ia => new Gaussian(ia, performanceVariance).Sample()).ToArray();

                var game = new MultiPlayerGame {
                    Id = (startIndex + i + 1).ToString("D")
                };

                for (int j = 0; j < playerIndices[i].Length; j++)
                {
                    // game.Teams.Add(new Team { Players = new[] { players[randomIndices[j]] }, Score = (int)scores[j] });
                    game.Players.Add(players[randomIndices[j]]);
                    game.Scores.Add((int)scores[j]);
                }

                games.Add(game);
            }

            return(games);
        }