// // $Source: /cvsroot/gambit/gambit/sources/gui/analysis.cc,v $ // $Date: 2006/08/20 17:02:14 $ // $Revision: 1.16 $ // // DESCRIPTION: // Declaration of analysis storage classes // // This file is part of Gambit // Copyright (c) 2005, 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 #ifndef WX_PRECOMP #include #endif // WX_PRECOMP #include #include "tinyxml.h" // for XML parser for Load() #include "libgambit/libgambit.h" #include "analysis.h" #include "gamedoc.h" using namespace Gambit; //========================================================================= // class gbtAnalysisProfileList //========================================================================= // Use anonymous namespace to make these helpers private namespace { class gbtNotNashException : public Exception { public: virtual ~gbtNotNashException() { } std::string GetDescription(void) const { return "Output line does not contain a Nash equilibrium"; } }; template MixedStrategyProfile OutputToMixedProfile(gbtGameDocument *p_doc, const wxString &p_text) { MixedStrategyProfile profile(p_doc->GetGame()); wxStringTokenizer tok(p_text, wxT(",")); if (tok.GetNextToken() == wxT("NE")) { if (tok.CountTokens() == (unsigned int) profile.Length()) { for (int i = 1; i <= profile.Length(); i++) { profile[i] = ToNumber(std::string((const char *) tok.GetNextToken().mb_str())); } return profile; } } throw gbtNotNashException(); } template MixedBehavProfile OutputToBehavProfile(gbtGameDocument *p_doc, const wxString &p_text) { MixedBehavProfile profile(p_doc->GetGame()); wxStringTokenizer tok(p_text, wxT(",")); if (tok.GetNextToken() == wxT("NE")) { if (tok.CountTokens() == (unsigned int) profile.Length()) { for (int i = 1; i <= profile.Length(); i++) { profile[i] = ToNumber(std::string((const char *) tok.GetNextToken().mb_str())); } return profile; } } throw gbtNotNashException(); } } // end anonymous namespace template void gbtAnalysisProfileList::AddOutput(const wxString &p_output) { try { if (m_isBehav) { MixedBehavProfile profile(OutputToBehavProfile(m_doc, p_output)); m_behavProfiles.Append(profile); m_mixedProfiles.Append(MixedStrategyProfile(profile)); m_current = m_behavProfiles.Length(); } else { MixedStrategyProfile profile(OutputToMixedProfile(m_doc, p_output)); m_mixedProfiles.Append(profile); if (m_doc->IsTree()) { m_behavProfiles.Append(MixedBehavProfile(profile)); } m_current = m_mixedProfiles.Length(); } } catch (gbtNotNashException &) { } } template void gbtAnalysisProfileList::BuildNfg(void) { for (int i = 1; i <= m_behavProfiles.Length(); i++) { m_mixedProfiles.Append(MixedStrategyProfile(m_behavProfiles[i])); } } template int gbtAnalysisProfileList::NumProfiles(void) const { if (m_doc->IsTree()) { return m_behavProfiles.Length(); } else { return m_mixedProfiles.Length(); } } template void gbtAnalysisProfileList::Clear(void) { m_behavProfiles = List >(); m_mixedProfiles = List >(); m_current = 0; } //------------------------------------------------------------------------- // gbtAnalysisProfileList: Saving and loading profile lists //------------------------------------------------------------------------- // Use anonymous namespace to make these helpers private namespace { template MixedStrategyProfile TextToMixedProfile(gbtGameDocument *p_doc, const wxString &p_text) { MixedStrategyProfile profile(p_doc->GetGame()); wxStringTokenizer tok(p_text, wxT(",")); for (int i = 1; i <= profile.Length(); i++) { profile[i] = ToNumber(std::string((const char *) tok.GetNextToken().mb_str())); } return profile; } template MixedBehavProfile TextToBehavProfile(gbtGameDocument *p_doc, const wxString &p_text) { MixedBehavProfile profile(p_doc->GetGame()); wxStringTokenizer tok(p_text, wxT(",")); for (int i = 1; i <= profile.Length(); i++) { profile[i] = ToNumber(std::string((const char *) tok.GetNextToken().mb_str())); } return profile; } } // end anonymous namespace // // Load a profile list from XML. Pass a node pointing to an // entry in the workbook file // template void gbtAnalysisProfileList::Load(TiXmlNode *p_analysis) { Clear(); TiXmlNode *description = p_analysis->FirstChild("description"); if (description) { m_description = wxString(description->FirstChild()->Value(), *wxConvCurrent); } for (TiXmlNode *node = p_analysis->FirstChild("profile"); node; node = node->NextSiblingElement()) { const char *type = node->ToElement()->Attribute("type"); if (!strcmp(type, "behav")) { MixedBehavProfile profile = TextToBehavProfile(m_doc, wxString(node->FirstChild()->Value(), *wxConvCurrent)); m_behavProfiles.Append(profile); m_isBehav = true; m_current = m_behavProfiles.Length(); } else { MixedStrategyProfile profile = TextToMixedProfile(m_doc, wxString(node->FirstChild()->Value(), *wxConvCurrent)); m_mixedProfiles.Append(profile); m_isBehav = false; m_current = m_mixedProfiles.Length(); } } } template std::string gbtAnalysisProfileList::GetPayoff(int pl, int p_index) const { int index = (p_index == -1) ? m_current : p_index; try { if (m_doc->IsTree()) { return ToText(m_behavProfiles[index].GetPayoff(pl), m_doc->GetStyle().NumDecimals()); } else { return ToText(m_mixedProfiles[index].GetPayoff(pl), m_doc->GetStyle().NumDecimals()); } } catch (IndexException &) { return ""; } } template std::string gbtAnalysisProfileList::GetRealizProb(const GameNode &p_node, int p_index) const { int index = (p_index == -1) ? m_current : p_index; try { return ToText(m_behavProfiles[index].GetRealizProb(p_node), m_doc->GetStyle().NumDecimals()); } catch (IndexException &) { return ""; } } template std::string gbtAnalysisProfileList::GetBeliefProb(const GameNode &p_node, int p_index) const { int index = (p_index == -1) ? m_current : p_index; if (!p_node->GetPlayer()) return ""; try { if (m_behavProfiles[index].GetInfosetProb(p_node->GetInfoset()) > Rational(0)) { return ToText(m_behavProfiles[index].GetBeliefProb(p_node), m_doc->GetStyle().NumDecimals()); } else { // We don't compute assessments yet! return "*"; } } catch (IndexException &) { return ""; } } template std::string gbtAnalysisProfileList::GetNodeValue(const GameNode &p_node, int p_player, int p_index) const { int index = (p_index == -1) ? m_current : p_index; try { return ToText(m_behavProfiles[index].GetNodeValue(p_node)[p_player], m_doc->GetStyle().NumDecimals()); } catch (IndexException &) { return ""; } } template std::string gbtAnalysisProfileList::GetInfosetProb(const GameNode &p_node, int p_index) const { int index = (p_index == -1) ? m_current : p_index; if (!p_node->GetPlayer()) return ""; try { return ToText(m_behavProfiles[index].GetInfosetProb(p_node->GetInfoset()), m_doc->GetStyle().NumDecimals()); } catch (IndexException &) { return ""; } } template std::string gbtAnalysisProfileList::GetInfosetValue(const GameNode &p_node, int p_index) const { int index = (p_index == -1) ? m_current : p_index; if (!p_node->GetPlayer() || p_node->GetPlayer()->IsChance()) return ""; try { if (m_behavProfiles[index].GetInfosetProb(p_node->GetInfoset()) > Rational(0)) { return ToText(m_behavProfiles[index].GetInfosetValue(p_node->GetInfoset()), m_doc->GetStyle().NumDecimals()); } else { // In the absence of beliefs, this is not well-defined in general return "*"; } } catch (IndexException &) { return ""; } } template std::string gbtAnalysisProfileList::GetActionProb(const GameNode &p_node, int p_act, int p_index) const { int index = (p_index == -1) ? m_current : p_index; if (p_node->GetPlayer() && p_node->GetPlayer()->IsChance()) { GameInfoset infoset = p_node->GetInfoset(); return infoset->GetActionProb(p_act); } if (!p_node->GetPlayer()) return ""; try { const MixedBehavProfile &profile = m_behavProfiles[index]; if (!profile.IsDefinedAt(p_node->GetInfoset())) { return "*"; } return ToText(profile.GetActionProb(p_node->GetInfoset()->GetAction(p_act)), m_doc->GetStyle().NumDecimals()); } catch (IndexException &) { return ""; } } template std::string gbtAnalysisProfileList::GetActionProb(int p_action, int p_index) const { int index = (p_index == -1) ? m_current : p_index; try { const MixedBehavProfile &profile = m_behavProfiles[index]; if (!profile.IsDefinedAt(profile.GetGame()->GetAction(p_action)->GetInfoset())) { return "*"; } return ToText(profile[p_action], m_doc->GetStyle().NumDecimals()); } catch (IndexException &) { return ""; } } template std::string gbtAnalysisProfileList::GetActionValue(const GameNode &p_node, int p_act, int p_index) const { int index = (p_index == -1) ? m_current : p_index; if (!p_node->GetPlayer() || p_node->GetPlayer()->IsChance()) return ""; try { if (m_behavProfiles[index].GetInfosetProb(p_node->GetInfoset()) > Rational(0)) { return ToText(m_behavProfiles[index].GetActionValue(p_node->GetInfoset()->GetAction(p_act)), m_doc->GetStyle().NumDecimals()); } else { // In the absence of beliefs, this is not well-defined return "*"; } } catch (IndexException &) { return ""; } } template std::string gbtAnalysisProfileList::GetStrategyProb(int p_strategy, int p_index) const { int index = (p_index == -1) ? m_current : p_index; try { const MixedStrategyProfile &profile = m_mixedProfiles[index]; return ToText(profile[p_strategy], m_doc->GetStyle().NumDecimals()); } catch (IndexException &) { return ""; } } template std::string gbtAnalysisProfileList::GetStrategyValue(int p_strategy, int p_index) const { int index = (p_index == -1) ? m_current : p_index; try { const MixedStrategyProfile &profile = m_mixedProfiles[index]; GameStrategy strategy = profile.GetGame()->GetStrategy(p_strategy); return ToText(profile.GetStrategyValue(strategy), m_doc->GetStyle().NumDecimals()); } catch (IndexException &) { return ""; } } template void gbtAnalysisProfileList::Save(std::ostream &p_file) const { p_file << "\n"; p_file << "\n"; p_file << (const char *) m_description.mb_str() << "\n"; p_file << "\n"; if (m_doc->IsTree()) { for (int j = 1; j <= NumProfiles(); j++) { const MixedBehavProfile &behav = m_behavProfiles[j]; p_file << "\n"; for (int k = 1; k <= behav.Length(); k++) { p_file << behav[k]; if (k < behav.Length()) { p_file << ","; } else { p_file << "\n"; } } p_file << "\n"; } } else { for (int j = 1; j <= NumProfiles(); j++) { const MixedStrategyProfile &mixed = m_mixedProfiles[j]; p_file << "\n"; for (int k = 1; k <= mixed.Length(); k++) { p_file << mixed[k]; if (k < mixed.Length()) { p_file << ","; } else { p_file << "\n"; } } p_file << "\n"; } } p_file << "\n"; } // Explicit instantiations template class gbtAnalysisProfileList; template class gbtAnalysisProfileList;