void potts_NestedSampling_Algorithm_2D(float** ptrMatrix, float* Matrix, std::vector<double>& coordinates, std::vector<double>& likelyhoods, std::vector<double>& postlikelyhoods, Lattice lattice, RandomLib::Random& r, double const J, double const h, double const label_coeff, int const K, int const max, int const mcycle)
{
    int k, p, z, distance, iteration, K_iteration, oldSpin;
    double H_tot, H_in, H_fin, H_tot_constraint, H_tot_trial;

    initialise_likelyhoods(likelyhoods, K);
    initialise_likelyhoods(postlikelyhoods, K);
    initialise_coordinates(coordinates, lattice, K);

    for(int i = 0; i < K; i++)
    {
        potts_generate_random_matrix_2D(Matrix, lattice, r, max);

        H_tot = potts_total_hamiltonian_2D(ptrMatrix,lattice,J,h);

        H_tot = label_likelyhood(H_tot, label_coeff, r);

        likelyhoods.insert(likelyhoods.end(), H_tot);

        add_coordinates(Matrix, coordinates, lattice);
    }

    std::cout<<"END OF INITIALISATION"<<std::endl;
    std::cout<<"likelyhoods.size: "<<likelyhoods.size()<<std::endl;
    std::cout<<"coordinates.size: "<<coordinates.size()<<std::endl;

    bool LOOP = true;
    std::vector<double>::iterator max_likelyhood;

    while(LOOP == true)
    {
        max_likelyhood = std::max_element(likelyhoods.begin(),likelyhoods.end());
        distance = std::distance(likelyhoods.begin(), max_likelyhood);
        H_tot_constraint = likelyhoods.at(distance);
        postlikelyhoods.insert(postlikelyhoods.end(), H_tot_constraint);
        //std::cout<<"H_tot_constraint: "<<H_tot_constraint<<std::endl;

        distance = get_randomlikelyhood_coordinates(Matrix, coordinates, likelyhoods, r, lattice);
        H_tot = likelyhoods.at(distance);
        K_iteration = 0;

        for(z = 0; z < mcycle; z++)
        {
            Matrix_samplepoint_2D(lattice, r, &k, &p);

            H_in = potts_nodal_hamiltonian_2D(ptrMatrix, p, lattice, J, h);

            //flip spin
            oldSpin = Matrix[k];
            Matrix[k] = r.IntegerC(1, max);

            H_fin = potts_nodal_hamiltonian_2D(ptrMatrix, p, lattice, J, h);

            H_tot_trial = H_tot - H_in + H_fin;

            H_tot_trial = label_likelyhood(H_tot_trial, label_coeff, r);

            if (H_tot_trial < H_tot_constraint)
            {
                H_tot = H_tot_trial;
            }
            else
            {
                Matrix[k] = oldSpin;
            }

            if (z == mcycle - 1)
            {
                if (H_tot < H_tot_constraint)
                {
                    replace_maxlikelyhood_coordinates(Matrix, coordinates, likelyhoods, lattice, H_tot);
                    break;
                }
                else
                {
                    //std::cout<<"change"<<std::endl;
                    K_iteration = get_alternativelikelyhood_coordinates_random(Matrix, coordinates, likelyhoods,lattice, r, K, H_tot, K_iteration);
                    z = 0;
                    ++K_iteration;
                }
            }
            else if (K_iteration == K )
            {
                LOOP = false;
                std::cout<<"Algorithm termination condition met"<<std::endl;
                break;
            }
        }
    }
}
void potts_WangLandau_Algorithm_bean_3D(float** ptrMatrix, float* Matrix, std::vector<double>& Histogram, std::vector<double>& Histogram2, std::vector<double>& DOS, Lattice lattice, Bean bean, RandomLib::Random& r, double* ptrf, double const InitialDOS, double const end_f, double const average_frac, double const Jp, int const max, double const h, int const mcycle)
{
  int k, p, z, g, average;
  double H_tot_trial, H_in, H_fin, gE1, gE2, oldSpin;

  double H_tot = potts_total_hamiltonian_3D(ptrMatrix,lattice,Jp,h);
  
  initialiseHistogram_bean(Histogram, DOS);
  initialiseHistogram_bean(Histogram2, DOS);
  
  /*
    std::cout<<"DEBUG3: DOS size: "<<DOS.size()<< std::endl;
    std::cout<<"DEBUG3: Histogram size: "<<Histogram.size()<< std::endl;
  */
  
  while(*ptrf >= end_f)
    {
      bool LOOP = true; 
              
      std::cout<<"DEBUG Outer while loop"<<std::endl;
       
      while(LOOP == true)
	{
	  //std::cout<<"DEBUG inner while loop"<<std::endl;
	     
	  for(z = 0; z < mcycle; z++)
	    {
	      //the inner loop is necessary for the preconditioning
	      
	      //select random node on the lattice Matrix
	      Matrix_samplepoint_3D(lattice, r, &k, &p);
	      
	      H_in = potts_nodal_hamiltonian_3D(ptrMatrix, p, lattice, Jp, h);
	      
	      //flip spin
	      oldSpin = Matrix[k];
	      Matrix[k] = r.IntegerC(1, max);
	      
	      H_fin = potts_nodal_hamiltonian_3D(ptrMatrix, p, lattice, Jp, h);
	      
	      H_tot_trial = H_tot - H_in + H_fin;
	      gE1 = get_DOS_bean(DOS, bean, H_tot);
	      gE2 = get_DOS_bean(DOS, bean, H_tot_trial);
	      
	      if(gE2 <= gE1)
		{
		  H_tot = H_tot_trial;
		  update_DOS_bean(DOS, Histogram, Histogram2, bean, ptrf, H_tot, InitialDOS);
		  update_EnergyHistogram_bean(Histogram, bean, H_tot);
		}
	      else if (r.Fixed() <= exp( gE1 - gE2 ) ) 
		{
		  H_tot = H_tot_trial;
		  update_DOS_bean(DOS, Histogram, Histogram2, bean, ptrf, H_tot, InitialDOS);
		  update_EnergyHistogram_bean(Histogram, bean, H_tot);
		}
	      else
		{
		  Matrix[k] = oldSpin;
		  update_DOS_bean(DOS, Histogram, Histogram2, bean, ptrf, H_tot, InitialDOS);
		  update_EnergyHistogram_bean(Histogram, bean, H_tot);
		}
	      //std::cout<<H_tot<<std::endl;
	    }
	    
	  average = average_EnergyHistogram_bean(Histogram, DOS, InitialDOS, end_f);
	     
	  LOOP = termination_EnergyHistogram_bean(Histogram, DOS, InitialDOS, average, average_frac, end_f);
	}
       
      initialiseHistogram_bean(Histogram, DOS);
      
      evolve_update_function_sqrt(ptrf);

      //std::cout<<"UPDATED OOOOOOOOOOOOOOOOOOOOOOOOOOOO"<<std::endl;
    }
}