//  -*- C++  -*-
//
//======================================================================
//  File:          ptable.h
//  Author:        Thomas G. Dietterich
//  Description:   Declares classes for probability tables
//                 
//  Copyright (c) 1995 by Thomas G. Dietterich.  All Rights Reserved.
//       may be reproduced by any non-commercial purpose.
//======================================================================
//

#ifndef PTABLE_H
#define PTABLE_H

#include <iostream.h>
#include "list.h"
#include "vector.h"
#include "clrandom.h"

// we use a 32-bit word of bits to represent sets of variables.
// Hence, we can only handle a total of 32 variables
typedef unsigned long int  Mask;

class variableSet
{
public:
  // constructors
  variableSet(Mask b = 0): bits(b) {};
  variableSet(list<int> & varList);
  variableSet(const variableSet & other): bits(other.bits) {};

  // binary operators
  variableSet operator | (const variableSet & other) {
    return variableSet(bits | other.bits);
  }
  variableSet operator & (const variableSet & other) {
    return variableSet(bits & other.bits);
  }
  variableSet operator ~ () {
    return variableSet(~bits);
  }
  variableSet operator - (const variableSet & other) {
    // set difference
    return variableSet(bits & (~other.bits));
  }
  int operator == (const variableSet & other) {
    return bits == other.bits;
  }
  int operator != (const variableSet & other) {
    return bits != other.bits;
  }

  int isEmpty() {
    return bits == 0;
  }

  int size ();
  list<int> * variableList();

  // data fields
  Mask  bits;

  // friends
  friend istream & operator >>(istream & str, variableSet & vs);
  friend ostream & operator <<(ostream & str, variableSet & vs);
};

istream & operator >> (istream & str, variableSet & vs);
ostream & operator << (ostream & str, variableSet & vs);


Mask compressUnderMask(Mask item, Mask mask);
Mask expandUnderMask(Mask item, Mask mask);

class probabilityTable
{
public:
  // constructor
  probabilityTable(int n=0): vars(0), values((1<<n), 1.0) {};
  probabilityTable(variableSet v): vars(v), values((1<<v.size()), 1.0) {};

  variableSet vars;
  vector<float> values;

  // conformal product  (returns new table)
  probabilityTable * operator * (probabilityTable & other);
  // conformal quotient (returns new table)
  probabilityTable * operator / (probabilityTable & other);
  // in place conformal product (destructive)
  probabilityTable * operator *= (probabilityTable & other);
  // in place accumulation
  void operator += (probabilityTable & other);
  // marginalize  (destructive)
  void sumOver (variableSet vs);
  // sum of all elements
  double sum ();
  // print in readable format
  void maxOver(variableSet vs);
  // compute the max marginal (destructive)
  void maximize(variableSet vs);
  // sharpen probabilities to 0/1
  void print(ostream & str);
  // duplicate the table
  probabilityTable * duplicate();
  // project to remove one of the values (destructive)
  void project(int var, int value);  
  // normalize so that the sum of the entries for the indicated
  // variables is 1  (destructive)
  void normalize(variableSet vs);
  // assignment
  probabilityTable & operator = (probabilityTable & other);
  // initialization
  void fill(float & value) {
    values.fill(value);
  }
  // fill with random values, normalized so that for each combination
  // of vars - var, the two entries for var sum to 1.
  void randomize(clrandom & rng, int var);

};  

istream & operator >> (istream & str, probabilityTable & table);
ostream & operator << (ostream & str, probabilityTable & table);

#endif
