//
// $Source: /cvsroot/gambit/gambit/sources/tools/enumpoly/sfg.cc,v $
// $Date: 2006/08/17 02:35:36 $
// $Revision: 1.15 $
//
// DESCRIPTION:
// Implementation of sequence form 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 "sfg.h"
#include "sfstrat.h"
#include "gnarray.imp"
#include "libgambit/libgambit.h"
//----------------------------------------------------
// Sfg: Constructors, Destructors, Operators
//----------------------------------------------------
Sfg::Sfg(const Gambit::BehavSupport &S)
: EF(S.GetGame()), efsupp(S), seq(EF->NumPlayers()), isetFlag(S.GetGame()->NumInfosets()),
isetRow(S.GetGame()->NumInfosets()), infosets(EF->NumPlayers())
{
int i;
Gambit::Array<Gambit::GameInfoset> zero(EF->NumPlayers());
Gambit::Array<int> one(EF->NumPlayers());
Gambit::BehavSupport support(EF);
for(i=1;i<=EF->NumPlayers();i++) {
seq[i]=1;
zero[i]=0;
one[i]=1;
}
isetFlag = 0;
isetRow = 0;
GetSequenceDims(EF->GetRoot());
isetFlag = 0;
gIndexOdometer index(seq);
SF = new gNArray<Gambit::Array<Gambit::Rational> *>(seq);
while (index.Turn()) {
(*SF)[index.CurrentIndices()] = new Gambit::Array<Gambit::Rational>(EF->NumPlayers());
for(i=1;i<=EF->NumPlayers();i++)
(*(*SF)[index.CurrentIndices()])[i]=(Gambit::Rational)0;
}
E = new Gambit::Array<Gambit::RectArray<Gambit::Rational> *> (EF->NumPlayers());
for(i=1;i<=EF->NumPlayers();i++) {
(*E)[i] = new Gambit::RectArray<Gambit::Rational>(infosets[i].Length()+1,seq[i]);
for(int j = (*(*E)[i]).MinRow();j<=(*(*E)[i]).MaxRow();j++)
for(int k = (*(*E)[i]).MinCol();k<=(*(*E)[i]).MaxCol();k++)
(*(*E)[i])(j,k)=(Gambit::Rational)0;
(*(*E)[i])(1,1)=(Gambit::Rational)1;
}
sequences = new Gambit::Array<SFSequenceSet *>(EF->NumPlayers());
for(i=1;i<=EF->NumPlayers();i++)
(*sequences)[i] = new SFSequenceSet(EF->GetPlayer(i));
Gambit::Array<Sequence *> parent(EF->NumPlayers());
for(i=1;i<=EF->NumPlayers();i++)
parent[i] = (((*sequences)[i])->GetSFSequenceSet())[1];
MakeSequenceForm(EF->GetRoot(),(Gambit::Rational)1,one,zero,parent);
}
Sfg::~Sfg()
{
gIndexOdometer index(seq);
while (index.Turn())
delete (*SF)[index.CurrentIndices()];
delete SF;
int i;
for(i=1;i<=EF->NumPlayers();i++)
delete (*E)[i];
delete E;
for(i=1;i<=EF->NumPlayers();i++)
delete (*sequences)[i];
delete sequences;
}
void Sfg::
MakeSequenceForm(const Gambit::GameNode &n, Gambit::Rational prob,Gambit::Array<int>seq,
Gambit::Array<Gambit::GameInfoset> iset, Gambit::Array<Sequence *> parent)
{
int i,pl;
if (n->GetOutcome()) {
for(pl = 1;pl<=seq.Length();pl++)
(*(*SF)[seq])[pl] += prob * n->GetOutcome()->GetPayoff<Gambit::Rational>(pl);
}
if(n->GetInfoset()) {
if(n->GetPlayer()->IsChance()) {
for(i=1;i<=n->NumChildren();i++)
MakeSequenceForm(n->GetChild(i),
prob * n->GetInfoset()->GetActionProb<Gambit::Rational>(i), seq,iset,parent);
}
else {
int pl = n->GetPlayer()->GetNumber();
iset[pl]=n->GetInfoset();
int isetnum = iset[pl]->GetNumber();
Gambit::Array<int> snew(seq);
snew[pl]=1;
for(i=1;i<isetnum;i++)
if(isetRow(pl,i))
snew[pl]+=efsupp.NumActions(pl,i);
(*(*E)[pl])(isetRow(pl,isetnum),seq[pl]) = (Gambit::Rational)1;
Sequence *myparent(parent[pl]);
bool flag = false;
if(!isetFlag(pl,isetnum)) { // on first visit to iset, create new sequences
isetFlag(pl,isetnum)=1;
flag =true;
}
for(i=1;i<=n->NumChildren();i++) {
if(efsupp.Contains(n->GetInfoset()->GetAction(i))) {
snew[pl]+=1;
if(flag) {
Sequence* child;
child = new Sequence(n->GetPlayer(),
n->GetInfoset()->GetAction(i),
myparent,snew[pl]);
parent[pl]=child;
((*sequences)[pl])->AddSequence(child);
}
(*(*E)[pl])(isetRow(pl,isetnum),snew[pl]) = -(Gambit::Rational)1;
MakeSequenceForm(n->GetChild(i),prob,snew,iset,parent);
}
}
}
}
}
void Sfg::
GetSequenceDims(const Gambit::GameNode &n)
{
int i;
if(n->GetInfoset()) {
if(n->GetPlayer()->IsChance()) {
for(i=1;i<=n->NumChildren();i++)
GetSequenceDims(n->GetChild(i));
}
else {
int pl = n->GetPlayer()->GetNumber();
int isetnum = n->GetInfoset()->GetNumber();
bool flag = false;
if(!isetFlag(pl,isetnum)) { // on first visit to iset, create new sequences
infosets[pl].Append(n->GetInfoset());
isetFlag(pl,isetnum)=1;
isetRow(pl,isetnum)=infosets[pl].Length()+1;
flag =true;
}
for(i=1;i<=n->NumChildren();i++) {
if(efsupp.Contains(n->GetInfoset()->GetAction(i))) {
if(flag) {
seq[pl]++;
}
GetSequenceDims(n->GetChild(i));
}
}
}
}
}
int Sfg::TotalNumSequences() const
{
int tot=0;
for(int i=1;i<=seq.Length();i++)
tot+=seq[i];
return tot;
}
int Sfg::NumPlayerInfosets() const
{
int tot=0;
for(int i=1;i<=infosets.Length();i++)
tot+=infosets[i].Length();
return tot;
}
int Sfg::InfosetRowNumber(int pl, int j) const
{
if(j==1) return 0;
int isetnum = (*sequences)[pl]->Find(j)->GetInfoset()->GetNumber();
return isetRow(pl,isetnum);
}
int Sfg::ActionNumber(int pl, int j) const
{
if(j==1) return 0;
return efsupp.GetIndex(GetAction(pl,j));
}
Gambit::GameInfoset Sfg::GetInfoset(int pl, int j) const
{
if(j==1) return 0;
return (*sequences)[pl]->Find(j)->GetInfoset();
}
Gambit::GameAction Sfg::GetAction(int pl, int j) const
{
if(j==1) return 0;
return (*sequences)[pl]->Find(j)->GetAction();
}
Gambit::MixedBehavProfile<double> Sfg::ToBehav(const Gambit::PVector<double> &x) const
{
Gambit::MixedBehavProfile<double> b(efsupp);
b = (Gambit::Rational) 0;
Sequence *sij;
const Sequence *parent;
Gambit::Rational value;
int i,j;
for(i=1;i<=EF->NumPlayers();i++)
for(j=2;j<=seq[i];j++) {
sij = ((*sequences)[i]->GetSFSequenceSet())[j];
int sn = sij->GetNumber();
parent = sij->Parent();
// gout << "\ni,j,sn,iset,act: " << i << " " << j << " " << sn << " ";
// gout << sij->GetInfoset()->GetNumber() << " " << sij->GetAction()->GetNumber();
if(x(i, parent->GetNumber())>(double)0)
value = (x(i,sn)/x(i,parent->GetNumber()));
else
value = 0;
b(i,sij->GetInfoset()->GetNumber(),efsupp.GetIndex(sij->GetAction()))= value;
}
return b;
}
Gambit::Rational Sfg::Payoff(const Gambit::Array<int> & index,int pl) const
{
return Payoffs(index)[pl];
}
template class gNArray<Gambit::Array<Gambit::Rational> *>;
syntax highlighted by Code2HTML, v. 0.9.1