/**********************************************************

This software is part of J.-S. Caux's ABACUS library.

Copyright (c) J.-S. Caux.

-----------------------------------------------------------

File:  ABACUS_Young.h

Purpose:  Declares Young tableau class.

***********************************************************/

#ifndef ABACUS_YOUNG_H
#define ABACUS_YOUNG_H

#include "ABACUS_Vect.h"

namespace ABACUS {

  const int YOUNG_TABLEAU_ID_OPTION = 0;
  const long long int TABLEAU_ID_UPPER_LIMIT = 10000000LL;

  //***********************************************************************

  class Young_Tableau {

  public:
    int Nrows;
    int Ncols;
    int* Row_L;
    int* Col_L;
    long long int id;     // identification number
    long long int maxid;
    long long int* map;
    bool map_computed;
    long long int idnr_reached;
    int nboxes_reached;

  private:
    int dimchoose;
    long long int* choose_table;

  public:
    Young_Tableau ();    // empty constructor, does nothing
    Young_Tableau (int Nr, int Nc);  // constructs empty tableau
    Young_Tableau (int Nr, int Nc, long long int idnr);  // constructs the tableau corresponding to identification number idnr
    Young_Tableau (const Young_Tableau& RefTableau);  // copy constructor
    Young_Tableau (int Nr, int Nc, const Young_Tableau& RefTableau);
    Young_Tableau& operator= (const Young_Tableau& RefTableau);  // assignment
    ~Young_Tableau ();  // destructor

  public:
    Young_Tableau& Compute_Map (long long int idnr_to_reach);  // fills the map vector
    Young_Tableau& Distribute_boxes (int nboxes_to_dist, int level);
    Young_Tableau& Set_to_id (long long int idnr); // sets the tableau to the one corresponding to idnr
    Young_Tableau& Set_to_id (long long int idnr, int option); // sets the tableau to the one corresponding to idnr according to rule option
    Young_Tableau& Set_Row_L (Vect<int>& Row_Lengths);  // set row lengths
    Young_Tableau& Set_Col_L_given_Row_L ();   // sets the Col_L array self-consistently
    Young_Tableau& Set_Row_L_given_Col_L ();   // sets the Col_L array self-consistently
    long long int Compute_Descendent_id (int option, Vect<int>& Desc_Row_L, int Nrows_Desc, int Ncols_Desc,
					 const Young_Tableau& RefTableau);
    Young_Tableau& Compute_id();       // computes the id number of tableau
    Young_Tableau& Compute_id(int option);       // computes the id number of tableau according to rule option
    Young_Tableau& Print();            // couts the tableau

    bool Lower_Row (int i);
    bool Raise_Row (int i);
    bool Lower_Col (int i);
    bool Raise_Col (int i);
    bool Raise_Lowest_Nonzero_Row(); // adds a box to the lowest nonzero length Row, recomputes id, returns true if tableau has changed
    bool Raise_Next_to_Lowest_Nonzero_Row(); // same thing, but for Row under lowest nonzero length one.
    bool Move_Box_from_Col_to_Col (int ifrom, int ito);

    Vect<Young_Tableau> Descendents (int fixed_Nboxes);
    Vect<Young_Tableau> Descendents_Boosted_State (int fixed_Nboxes);

    int Add_Boxes_From_Lowest (int Nboxes);  // tries to add Nboxes to Tableau, returns number of boxes added.
  };

  std::ostream& operator<< (std::ostream& s, const Young_Tableau& tableau);

  inline int Nr_Nonzero_Rows (const Vect<Young_Tableau>& Tableau_ref)
  {
    // This function checks the number of rows containing at least one box
    // in the whole vector of Young tableaux given as argument.
    // The usefulness is to force descent of states in which only a few
    // excitations have started dispersing.

    int nr_nonzero_rows = 0;
    for (int i = 0; i < Tableau_ref.size(); ++i)
      for (int alpha = 0; alpha < Tableau_ref[i].Nrows; ++alpha)
	if (Tableau_ref[i].Row_L[alpha] > 0) nr_nonzero_rows++;

    return(nr_nonzero_rows);
  }

  //***********************************************************************

  class Tableau_Map {

  public:
    Vect<long long int> map;
    long long int idnr_reached;
    int nboxes_reached;

  public:
    Tableau_Map (int Nrows, int Ncols);
    void Distribute_id (int nboxes_to_dist, int level, Young_Tableau& RefTableau);

  };



} // namespace ABACUS

#endif