//
// $Source: /cvsroot/gambit/gambit/sources/tools/lp/nfglp.cc,v $
// $Date: 2006/08/15 22:57:38 $
// $Revision: 1.18 $
//
// DESCRIPTION:
// Implementation of algorithm to compute mixed strategy equilibria
// of constant sum normal form games via linear programming
//
// This file is part of Gambit
// Copyright (c) 2006, 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 "lpsolve.h"
using namespace Gambit;
extern int g_numDecimals;
//
// The routine to actually solve the LP
// This routine takes an LP of the form
// maximize c x subject to Ax>=b and x>=0,
// except the last 'nequals' constraints in A hold with equality.
// It expects the array p_primal to be the same length as the
// number of columns in A, and the routine returns the primal solution;
// similarly, the array p_dual should have the same length as the
// number of rows in A, and the routine returns the dual solution.
//
// To implement your own custom solver for this problem, simply
// replace this function.
//
template <class T> bool
SolveLP(const Matrix<T> &A, const Vector<T> &b, const Vector<T> &c,
int nequals,
Array<T> &p_primal, Array<T> &p_dual)
{
LPSolve<T> LP(A, b, c, nequals);
if (!LP.IsAborted()) {
BFS<T> cbfs((T) 0);
LP.OptBFS(cbfs);
for (int i = 1; i <= A.NumColumns(); i++) {
if (cbfs.IsDefined(i)) {
p_primal[i] = cbfs(i);
}
else {
p_primal[i] = (T) 0;
}
}
for (int i = 1; i <= A.NumRows(); i++) {
if (cbfs.IsDefined(-i)) {
p_dual[i] = cbfs(-i);
}
else {
p_dual[i] = (T) 0;
}
}
return true;
}
else {
return false;
}
}
void PrintProfile(std::ostream &p_stream,
const std::string &p_label,
const 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 MixedStrategyProfile<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;
}
//
// Convert the LP solution represented by the vectors
// (p_primal, p_dual) back to a strategy profile.
// The primal vector is the mixed strategy for player 1, and the
// dual the mixed strategy for player 2.
//
template <class T>
void PrintSolution(const StrategySupport &p_support,
const Array<T> &p_primal,
const Array<T> &p_dual)
{
int n1 = p_support.NumStrategies(1);
int n2 = p_support.NumStrategies(2);
MixedStrategyProfile<T> profile(p_support);
for (int j = 1; j <= n1; j++) {
profile[p_support.GetStrategy(1, j)] = p_primal[j];
}
for (int j = 1; j <= n2; j++) {
profile[p_support.GetStrategy(2, j)] = p_dual[j];
}
PrintProfile(std::cout, "NE", profile);
}
//
// Compute and print one equilibrium by solving a linear program based
// on the strategic game representation.
//
template <class T>
void SolveStrategic(const Game &p_game)
{
StrategySupport support(p_game);
int m = support.NumStrategies(1);
int k = support.NumStrategies(2);
Matrix<T> A(1,k+1,1,m+1);
Vector<T> b(1,k+1);
Vector<T> c(1,m+1);
PureStrategyProfile profile(support.GetGame());
T minpay = p_game->GetMinPayoff() - Rational(1);
for (int i = 1; i <= k; i++) {
profile.SetStrategy(support.GetStrategy(2, i));
for (int j = 1; j <= m; j++) {
profile.SetStrategy(support.GetStrategy(1, j));
A(i, j) = Rational(minpay) - profile.GetPayoff<Rational>(1);
}
A(i,m+1) = (T) 1;
}
for (int j = 1; j <= m; j++) {
A(k+1,j) = (T) 1;
}
A(k+1,m+1) = (T) 0;
b = (T) 0;
b[k+1] = (T) 1;
c = (T) 0;
c[m+1] = (T) 1;
Array<T> primal(A.NumColumns()), dual(A.NumRows());
if (SolveLP(A, b, c, 1, primal, dual)) {
PrintSolution(support, primal, dual);
}
}
template void SolveStrategic<double>(const Game &);
template void SolveStrategic<Rational>(const Game &);
syntax highlighted by Code2HTML, v. 0.9.1