//
// $Source: /cvsroot/gambit/gambit/sources/tools/logit/logbehav.h,v $
// $Date: 2006/10/30 21:07:40 $
// $Revision: 1.5 $
//
// DESCRIPTION:
// Declaration of behavior strategy 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.
//

#ifndef LOGBEHAV_H
#define LOGBEHAV_H

using namespace Gambit;

///
/// This is a modified behavior profile class used in the tracing procedure.
/// It assumes that all probabilities are positive; therefore, the log
/// of the probability is well-defined.  Because of this, the realization
/// probability for any node can be computed by taking the sum of the log
/// probabilities of the actions leading up to it, and then exponentiating
/// the sum.
///
/// This means that beliefs can be computed accurately even for information
/// sets for which the information set realization probability is going
/// to zero.  In computing beliefs, for each information set, we find the
/// member reached with maximum probability.  Observe that it must be that
/// this node's realization probability divided by the information set's
/// realization probability must be bounded away from zero.  Beliefs are
/// then computed by subtracting the other nodes' log-realization probability
/// from this "leading" node's log-realization probability, and then
/// exponentiating the result.
///
/// This procedure is significant for this application because it is
/// necessary to accurately compute beliefs for information sets whose
/// realization probabilities are going to zero, so as to be able to
/// get a good approximation to the limiting sequential equilibrium.
///
template <class T> class LogBehavProfile : private DVector<T>  {
protected:
  BehavSupport m_support;
  DVector<T> m_logProbs;

  mutable bool m_cacheValid;

  // structures for storing cached data: nodes
  mutable Vector<T> m_realizProbs, m_logRealizProbs;
  mutable Vector<T> m_beliefs;
  mutable Matrix<T> m_nodeValues;

  // structures for storing cached data: information sets
  mutable PVector<T> m_infosetValues;

  // structures for storing cached data: actions
  mutable DVector<T> m_actionValues;   // aka conditional payoffs
  mutable DVector<T> m_gripe;

  const T &ActionValue(const GameAction &act) const 
    { return m_actionValues(act->GetInfoset()->GetPlayer()->GetNumber(),
			    act->GetInfoset()->GetNumber(),
			    act->GetNumber()); }
  T &ActionValue(const GameAction &act)
    { return m_actionValues(act->GetInfoset()->GetPlayer()->GetNumber(),
			    act->GetInfoset()->GetNumber(),
			    act->GetNumber()); }
  
  /// @name Auxiliary functions for computation of interesting values
  //@{
  void GetPayoff(GameNodeRep *, const T &, int, T &) const;
  
  void ComputeSolutionDataPass2(const GameNode &node) const;
  void ComputeSolutionDataPass1(const GameNode &node) const;
  void ComputeSolutionData(void) const;
  //@}

public:
  /// @name Lifecycle
  //@{
  LogBehavProfile(const BehavSupport &);
  LogBehavProfile(const LogBehavProfile<T> &);
  ~LogBehavProfile() { }

  LogBehavProfile<T> &operator=(const LogBehavProfile<T> &);
  LogBehavProfile<T> &operator=(const Vector<T> &p)
    { Invalidate(); Vector<T>::operator=(p); return *this;}
  LogBehavProfile<T> &operator=(const T &x)  
    { Invalidate(); DVector<T>::operator=(x); return *this; }

  //@}
  
  /// @name Operator overloading
  //@{
  bool operator==(const LogBehavProfile<T> &) const;
  bool operator!=(const LogBehavProfile<T> &x) const 
  { return !(*this == x); }

  bool operator==(const DVector<T> &x) const
  { return DVector<T>::operator==(x); }
  bool operator!=(const DVector<T> &x) const
  { return DVector<T>::operator!=(x); }

  const T &GetProb(const GameAction &p_action) const
    { return (*this)(p_action->GetInfoset()->GetPlayer()->GetNumber(),
		     p_action->GetInfoset()->GetNumber(),
		     m_support.GetIndex(p_action)); }
  const T &GetProb(int a) const
    { return Array<T>::operator[](a); }

  const T &GetLogProb(int a) const
    { return m_logProbs[a]; }
  T GetLogProb(const GameAction &p_action) const
    { if (p_action->GetInfoset()->GetPlayer()->GetNumber() == 0) {
	GameInfoset infoset = p_action->GetInfoset();
	return log(infoset->GetActionProb<T>(p_action->GetNumber()));
      }
      else {
	return m_logProbs(p_action->GetInfoset()->GetPlayer()->GetNumber(),
			  p_action->GetInfoset()->GetNumber(),
			  m_support.GetIndex(p_action)); 
      }
    }
  const T &GetLogProb(int a, int b, int c) const
    { return m_logProbs(a, b, c); }
  const T &GetProb(int a, int b, int c) const
    { return DVector<T>::operator()(a, b, c); }

  void SetLogProb(int a, const T &p_value)
    { Invalidate();  
      m_logProbs[a] = p_value;
      Array<T>::operator[](a) = exp(p_value);
    }

  void SetProb(int a, const T &p_value)
  { Invalidate();
    Array<T>::operator[](a) = p_value;
    m_logProbs[a] = log(p_value);
  }
  
  LogBehavProfile<T> &operator+=(const LogBehavProfile<T> &x)
    { Invalidate();  DVector<T>::operator+=(x);  return *this; }
  LogBehavProfile<T> &operator+=(const DVector<T> &x)
    { Invalidate();  DVector<T>::operator+=(x);  return *this; }
  LogBehavProfile<T> &operator-=(const LogBehavProfile<T> &x)
    { Invalidate();  DVector<T>::operator-=(x);  return *this; }
  LogBehavProfile<T> &operator*=(const T &x)
    { Invalidate();  DVector<T>::operator*=(x);  return *this; }
  //@}

  /// @name Initialization, validation
  //@{
  /// Force recomputation of stored quantities
  void Invalidate(void) const { m_cacheValid = false; }
  /// Set the profile to the centroid
  void Centroid(void);
  //@}

  /// @name General data access
  //@{
  int Length(void) const { return Array<T>::Length(); }
  Game GetGame(void) const { return m_support.GetGame(); }
  const BehavSupport &GetSupport(void) const { return m_support; }
  //@}

  /// @name Computation of interesting quantities
  //@{
  T GetPayoff(int p_player) const;
  T GetLiapValue(bool p_definedOnly = false) const;

  const T &GetRealizProb(const GameNode &node) const;
  const T &GetBeliefProb(const GameNode &node) const;
  Vector<T> GetNodeValue(const GameNode &node) const;
  T GetInfosetProb(const GameInfoset &iset) const;
  const T &GetInfosetValue(const GameInfoset &iset) const;
  T GetActionProb(const GameAction &act) const;
  T GetLogActionProb(const GameAction &) const;
  const T &GetActionValue(const GameAction &act) const;
  const T &GetRegret(const GameAction &act) const;

  T DiffActionValue(const GameAction &action, 
		    const GameAction &oppAction) const;
  T DiffRealizProb(const GameNode &node, 
		   const GameAction &oppAction) const;
  T DiffNodeValue(const GameNode &node, const GamePlayer &player,
		  const GameAction &oppAction) const;

  //@}
};

#endif // LOGBEHAV_H


syntax highlighted by Code2HTML, v. 0.9.1