/*  Monte-Carlo simulation code for statistical physics
    Copyright (C) 2001-2004  Sylvain Reynal
    
    Département de Physique
    Ecole Nationale Supérieure de l'Electronique et de ses Applications (ENSEA)
    6, avenue du Ponceau,    
    F-95014 CERGY CEDEX

    et
    
    Laboratoire de Physique Théorique et Modélisation (LPTM)
    Université de Cergy-Pontoise - Site de Neuville
    F-95031 CERGY CEDEX
    
	
    Tel : 00 +33 130 736 245
    Fax : 00 +33 130 736 667
    e-mail : reynal@ensea.fr
    web page : http://www.ensea.fr/staff/reynal/
*/

package fr.ensea.montecarlo.canonical;

import java.io.*;
import java.awt.Color;
import java.text.*;

import fr.ensea.Localizer;
import fr.ensea.montecarlo.data.*;
import fr.ensea.montecarlo.model.*;
import fr.ensea.montecarlo.canonical.*;
import fr.ensea.montecarlo.misc.*;


/**
 * Algorithme de Metropolis. Class abstraite pour des modèles de spins quelconques.
 */
public abstract class AbstractMetropolis extends Montecarlo  {

	protected long attemptedMoves; // nombre de mises-à-jour tentées
	protected long acceptedMoves; // nombre de mises-à-jour acceptées

	protected NumberFormat nfPercent;

	/**
	 * Initialise un nouvel algorithm de Metropolis
	 * @param energySamples liste pour les mesures de l'énergie
	 * @param magnetizationSamples liste pour les mesures de l'aimantation
	 * @param kT la température par défaut
	 */
	public AbstractMetropolis(SamplesBag bag, double kT) {
		super(bag, kT);
		nfPercent = NumberFormat.getPercentInstance();
		nfPercent.setGroupingUsed(false);
		nfPercent.setMaximumFractionDigits(0);
	}

	/**
	 * Modifie la température courante et remet les compteurs à zéro.
	 */
	public synchronized void setTemperature(double kT){
		this.kT = kT;
		reinitCounters();
	}
	
	/**
	 * Génère un nouveau nombre aléatoire distribué uniformément dans l'intervalle [0,1), et le retourne.
	 */
	public double createRandomNumber(){
		return Math.random();
	}

	/**
	 * Réalise un sweep de l'ensemble du réseau
	 */
	public abstract void sweep();

	///////////////////////////////////////////////////////////
	/// Statistiques
	///////////////////////////////////////////////////////////

	/**
	 * Retourne le taux de mise-à-jour réussies en pourcents.
	 */
	public double getAcceptanceRate(){
		if (attemptedMoves==0) return 0;
		return (double)acceptedMoves/(double)attemptedMoves;
	}

	/**
	 * Réinitialise les compteurs de mises-à-jours acceptées
	 */
	public synchronized void reinitCounters(){
		this.acceptedMoves = this.attemptedMoves = 0;
	}
	
	public String getCountersRateJLabel(){
		return Localizer.get("AcceptedMoves")+"="+nfPercent.format(getAcceptanceRate());
	}		
	
	
	/////////////////////////////////////////////////////////////////////////////////
	// TEST
	/////////////////////////////////////////////////////////////////////////////////

	/**
	 * Retourne un message d'information
	 */
	public String toString(){
		String s = "Algorithm de Metropolis :\n";
		s += "\ttaux de mises-à-jour réussies = " + Double.toString(getAcceptanceRate()) + "%";
		return s;
	}

	/////////////////////////////////////////////////////////////////////////////////
	// TEST
	/////////////////////////////////////////////////////////////////////////////////

}

