//
// $Source: /cvsroot/gambit/gambit/sources/tools/lcp/nfglcp.cc,v $
// $Date: 2006/02/08 21:12:04 $
// $Revision: 1.16 $
//
// DESCRIPTION:
// Compute Nash equilibria via Lemke-Howson algorithm
//
// 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 <unistd.h>
#include <iostream>
#include "libgambit/libgambit.h"
#include "lhtab.h"
extern int g_numDecimals;
void PrintProfile(std::ostream &p_stream,
const std::string &p_label,
const Gambit::MixedStrategyProfile<double> &p_profile)
{
p_stream << p_label;
for (int i = 1; i <= p_profile.Length(); i++) {
p_stream << "," << p_profile[i];
}
p_stream << std::endl;
}
void PrintProfile(std::ostream &p_stream,
const std::string &p_label,
const Gambit::MixedStrategyProfile<Gambit::Rational> &p_profile)
{
p_stream << p_label;
for (int i = 1; i <= p_profile.Length(); i++) {
p_stream.setf(std::ios::fixed);
p_stream << "," << std::setprecision(g_numDecimals) << p_profile[i];
}
p_stream << std::endl;
}
template <class T> Gambit::Matrix<T> Make_A1(const Gambit::StrategySupport &,
const T &);
template <class T> Gambit::Vector<T> Make_b1(const Gambit::StrategySupport &,
const T &);
template <class T> Gambit::Matrix<T> Make_A2(const Gambit::StrategySupport &,
const T &);
template <class T> Gambit::Vector<T> Make_b2(const Gambit::StrategySupport &,
const T &);
template <class T> class nfgLcp {
private:
int m_stopAfter, m_maxDepth;
int AddBfs(LHTableau<T> &, Gambit::List<BFS<T> > &);
void AddSolutions(const Gambit::StrategySupport &,
const Gambit::List<BFS<T> > &, const T &);
void AllLemke(const Gambit::StrategySupport &, int, LHTableau<T> &B, Gambit::List<BFS<T> > &,
int depth);
public:
nfgLcp(void);
virtual ~nfgLcp() { }
int StopAfter(void) const { return m_stopAfter; }
void SetStopAfter(int p_stopAfter) { m_stopAfter = p_stopAfter; }
int MaxDepth(void) const { return m_maxDepth; }
void SetMaxDepth(int p_maxDepth) { m_maxDepth = p_maxDepth; }
void Solve(const Gambit::StrategySupport &);
};
//---------------------------------------------------------------------------
// nfgLcp: member functions
//---------------------------------------------------------------------------
template <class T>
void nfgLcp<T>::Solve(const Gambit::StrategySupport &p_support)
{
BFS<T> cbfs((T) 0);
if (p_support.GetGame()->NumPlayers() != 2) {
return;
}
Gambit::List<BFS<T> > bfsList;
try {
Gambit::Matrix<T> A1 = Make_A1(p_support, (T) 0);
Gambit::Vector<T> b1 = Make_b1(p_support, (T) 0);
Gambit::Matrix<T> A2 = Make_A2(p_support, (T) 0);
Gambit::Vector<T> b2 = Make_b2(p_support, (T) 0);
LHTableau<T> B(A1,A2,b1,b2);
if (m_stopAfter != 1) {
AllLemke(p_support,0,B,bfsList,m_maxDepth);
}
else {
B.LemkePath(1);
AddBfs(B, bfsList);
}
return AddSolutions(p_support, bfsList, B.Epsilon());
}
catch (...) {
// for now, we won't give *any* solutions -- but we should list
// any solutions found!
throw;
}
// any other exceptions will propagate out.
}
template <class T> int nfgLcp<T>::AddBfs(LHTableau<T> &p_tableau,
Gambit::List<BFS<T> > &p_list)
{
BFS<T> cbfs((T) 0);
cbfs = p_tableau.GetBFS();
if ((m_stopAfter > 0 && p_list.Length() > m_stopAfter) ||
p_list.Contains(cbfs)) {
return 0;
}
p_list.Append(cbfs);
return 1;
}
//
// AllLemke finds all accessible Nash equilibria by recursively
// calling itself. List maintains the list of basic variables
// for the equilibria that have already been found.
// From each new accessible equilibrium, it follows
// all possible paths, adding any new equilibria to the List.
//
template <class T> void nfgLcp<T>::AllLemke(const Gambit::StrategySupport &p_support,
int j, LHTableau<T> &B,
Gambit::List<BFS<T> > &p_list,
int depth)
{
if (m_maxDepth != 0 && depth > m_maxDepth) {
return;
}
if (!AddBfs(B, p_list)) {
return;
}
for (int i = B.MinCol();
i <= B.MaxCol() &&
(m_stopAfter==0 || (p_list.Length()-1) < m_stopAfter);
i++) {
if (i != j) {
LHTableau<T> Bcopy(B);
Bcopy.LemkePath(i);
AllLemke(p_support,i,Bcopy, p_list, depth+1);
}
}
return;
}
template <class T>
void nfgLcp<T>::AddSolutions(const Gambit::StrategySupport &p_support,
const Gambit::List<BFS<T> > &p_list,
const T &epsilon)
{
int i,j;
int n1 = p_support.NumStrategies(1);
int n2 = p_support.NumStrategies(2);
for (i = 1; i <= p_list.Length(); i++) {
Gambit::MixedStrategyProfile<T> profile(p_support);
T sum = (T) 0;
for (j = 1; j <= n1; j++)
if (p_list[i].IsDefined(j)) sum += p_list[i](j);
if (sum == (T) 0) continue;
for (j = 1; j <= n1; j++) {
if (p_list[i].IsDefined(j)) {
profile[p_support.GetStrategy(1, j)] = p_list[i](j) / sum;
}
else {
profile[p_support.GetStrategy(1, j)] = (T) 0;
}
}
sum = (T) 0;
for (j = 1; j <= n2; j++)
if (p_list[i].IsDefined(n1 + j))
sum += p_list[i](n1 + j);
if (sum == (T) 0) continue;
for (j = 1; j <= n2; j++) {
if (p_list[i].IsDefined(n1 + j)) {
profile[p_support.GetStrategy(2, j)] = p_list[i](n1 + j) / sum;
}
else {
profile[p_support.GetStrategy(2, j)] = (T) 0;
}
}
PrintProfile(std::cout, "NE", profile);
}
}
//-------------------------------------------------------------------------
// nfgLcp<T>: Member functions
//-------------------------------------------------------------------------
template <class T>
nfgLcp<T>::nfgLcp(void)
: m_stopAfter(0), m_maxDepth(0)
{ }
template <class T>
void SolveStrategic(const Gambit::Game &p_game)
{
nfgLcp<T> algorithm;
algorithm.Solve(p_game);
}
template void SolveStrategic<double>(const Gambit::Game &);
template void SolveStrategic<Gambit::Rational>(const Gambit::Game &);
syntax highlighted by Code2HTML, v. 0.9.1