// // $Source: /cvsroot/gambit/gambit/sources/libgambit/mixed.imp,v $ // $Date: 2006/02/28 19:06:35 $ // $Revision: 1.19 $ // // DESCRIPTION: // Implementation of mixed strategy profile classes // // This file is part of Gambit // Copyright (c) 2002, The Gambit Project // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // #include "game.h" #include "mixed.h" namespace Gambit { //======================================================================== // MixedStrategyProfile: Lifecycle //======================================================================== template MixedStrategyProfile::MixedStrategyProfile(const StrategySupport &p_support) : Vector(p_support.MixedProfileLength()), support(p_support) { SetCentroid(); } template MixedStrategyProfile::MixedStrategyProfile(const MixedBehavProfile &p_profile) : Vector(p_profile.GetGame()->MixedProfileLength()), support(p_profile.GetGame()) { Game efg = p_profile.GetGame(); for (int pl = 1; pl <= support.GetGame()->NumPlayers(); pl++) { for (int st = 1; st <= support.GetGame()->GetPlayer(pl)->NumStrategies(); st++) { T prob = (T) 1; for (int iset = 1; iset <= efg->GetPlayer(pl)->NumInfosets(); iset++) { if (efg->m_players[pl]->m_strategies[st]->m_behav[iset] > 0) prob *= p_profile(pl, iset, efg->m_players[pl]->m_strategies[st]->m_behav[iset]); } (*this)[support.GetGame()->GetPlayer(pl)->GetStrategy(st)] = prob; } } } //======================================================================== // MixedStrategyProfile: General data access //======================================================================== template void MixedStrategyProfile::SetCentroid(void) { for (GamePlayerIterator player = support.Players(); !player.AtEnd(); player++) { T center = ((T) 1) / ((T) support.NumStrategies(player->GetNumber())); for (SupportStrategyIterator strategy = support.Strategies(player); !strategy.AtEnd(); strategy++) { (*this)[strategy] = center; } } } template MixedStrategyProfile MixedStrategyProfile::ToFullSupport(void) const { MixedStrategyProfile full(support.GetGame()); static_cast &>(full) = (T) 0; for (int pl = 1; pl <= support.GetGame()->NumPlayers(); pl++) { GamePlayer player = support.GetGame()->GetPlayer(pl); for (int st = 1; st <= player->NumStrategies(); st++) { if (support.Contains(player->GetStrategy(st))) { full[player->GetStrategy(st)] = (*this)[player->GetStrategy(st)]; } } } return full; } //======================================================================== // MixedStrategyProfile: Computation of interesting quantities //======================================================================== template T MixedStrategyProfile::GetPayoff(int pl, int index, int current) const { if (current > support.GetGame()->NumPlayers()) { GameOutcomeRep *outcome = support.GetGame()->m_results[index]; if (outcome) { return outcome->GetPayoff(pl); } else { return (T) 0; } } T sum = (T) 0; for (int j = 1; j <= support.NumStrategies(current); j++) { GameStrategyRep *s = support.GetStrategy(current, j); if ((*this)[s] != (T) 0) { sum += ((*this)[s] * GetPayoff(pl, index + s->m_offset, current + 1)); } } return sum; } template T MixedStrategyProfile::GetPayoff(int pl) const { if (support.GetGame()->IsTree()) { return MixedBehavProfile(*this).GetPayoff(pl); } else { return GetPayoff(pl, 1, 1); } } template void MixedStrategyProfile::GetPayoffDeriv(int pl, int const_pl, int cur_pl, long index, const T &prob, T &value) const { if (cur_pl == const_pl) { cur_pl++; } if (cur_pl > support.GetGame()->NumPlayers()) { GameOutcomeRep *outcome = support.GetGame()->m_results[index]; if (outcome) { value += prob * outcome->GetPayoff(pl); } } else { for (int j = 1; j <= support.NumStrategies(cur_pl); j++) { GameStrategyRep *s = support.GetStrategy(cur_pl, j); if ((*this)[s] > (T) 0) GetPayoffDeriv(pl, const_pl, cur_pl + 1, index + s->m_offset, prob * (*this)[s], value); } } } template T MixedStrategyProfile::GetPayoffDeriv(int pl, const GameStrategy &strategy) const { if (support.GetGame()->IsTree()) { MixedStrategyProfile foo(*this); int player1 = strategy->GetPlayer()->GetNumber(); for (int st = 1; st <= support.NumStrategies(player1); st++) { foo[support.GetStrategy(player1, st)] = (T) 0; } foo[strategy] = (T) 1; return foo.GetPayoff(pl); } else { T value = (T) 0; GetPayoffDeriv(pl, strategy->GetPlayer()->GetNumber(), 1, strategy->m_offset + 1, (T) 1, value); return value; } } template void MixedStrategyProfile::GetPayoffDeriv(int pl, int const_pl1, int const_pl2, int cur_pl, long index, const T &prob, T &value) const { while (cur_pl == const_pl1 || cur_pl == const_pl2) { cur_pl++; } if (cur_pl > support.GetGame()->NumPlayers()) { GameOutcomeRep *outcome = support.GetGame()->m_results[index]; if (outcome) { value += prob * outcome->GetPayoff(pl); } } else { for (int j = 1; j <= support.NumStrategies(cur_pl); j++ ) { GameStrategyRep *s = support.GetStrategy(cur_pl, j); if ((*this)[s] > (T) 0) { GetPayoffDeriv(pl, const_pl1, const_pl2, cur_pl + 1, index + s->m_offset, prob * (*this)[s], value); } } } } template T MixedStrategyProfile::GetPayoffDeriv(int pl, const GameStrategy &strategy1, const GameStrategy &strategy2) const { GamePlayerRep *player1 = strategy1->GetPlayer(); GamePlayerRep *player2 = strategy2->GetPlayer(); if (player1 == player2) return (T) 0; if (support.GetGame()->IsTree()) { MixedStrategyProfile foo(*this); for (SupportStrategyIterator strategy = support.Strategies(player1); !strategy.AtEnd(); strategy++) { foo[strategy] = (T) 0; } foo[strategy1] = (T) 1; for (SupportStrategyIterator strategy = support.Strategies(player2); !strategy.AtEnd(); strategy++) { foo[strategy] = (T) 0; } foo[strategy2] = (T) 1; return foo.GetPayoff(pl); } else { T value = (T) 0; GetPayoffDeriv(pl, player1->GetNumber(), player2->GetNumber(), 1, strategy1->m_offset + strategy2->m_offset + 1, (T) 1, value); return value; } } template T MixedStrategyProfile::GetLiapValue(void) const { static const T BIG1 = (T) 100; static const T BIG2 = (T) 100; T liapValue = (T) 0; for (GamePlayerIterator player = support.Players(); !player.AtEnd(); player++) { // values of the player's strategies Array values(support.NumStrategies(player->GetNumber())); T avg = (T) 0, sum = (T) 0; for (SupportStrategyIterator strategy = support.Strategies(player); !strategy.AtEnd(); strategy++) { const T &prob = (*this)[strategy]; values[support.GetIndex(strategy)] = GetStrategyValue(strategy); avg += prob * values[support.GetIndex(strategy)]; sum += prob; if (prob < (T) 0) { liapValue += BIG1*prob*prob; // penalty for negative probabilities } } for (int st = 1; st <= values.Length(); st++) { T regret = values[st] - avg; if (regret > (T) 0) { liapValue += regret*regret; // penalty if not best response } } // penalty if sum does not equal to one liapValue += BIG2*(sum - (T) 1.0)*(sum - (T) 1.0); } return liapValue; } } // end namespace Gambit