//package hu.birot.OTKit.runableExamples;


//import otBuildingBlocks.*;
import hu.birot.OTKit.dataType.*;
import hu.birot.OTKit.grammarExamples.*;
import hu.birot.OTKit.performance.*;

import java.util.*;


/**
 * Play around with string grammars.
 * @see hu.birot.OTKit.grammarExamples.StringGrammar
 * @author <a href="http://www.birot.hu">Tamas Biro</a>
 *
 */
public class StringGrammarExperiments {

	public static void main(String[] args) {		
 
		// Parameters of Simulated Annealing:
		//         ... feel free to play with them!
		
        int K_max      = 18;
        int K_step     = 1;		// standard value is 1
        int K_min      = -10;	// not used in practice, because nr_unmoved used below
        
        double t_max   = 3;	    // standard value is 3
        double t_min   = 0;	    // standard value is 0
        double t_step  = 0.1;
        
		int nr_unmoved = 80;

		int nr_run = 1000;   // number of outputs

		// Underlying form:
		
		int[] arrayuf = {0,0,0,0}; // the length of this array must be == L below.

		// Grammar:

		int K = 4 ; // size of the alphabet
		int L = 4 ; // length of the string in string grammar

		StringGrammar G = new StringGrammar(K,L, "ot"); // in principle you do not need to change this.
		// G.hierarchy.type = "ot"; // do not change, unless you also change the SA method to HG below.

		// Hierarchy:
		
		G.hierarchy.setKvalue("No0", 14);
		G.hierarchy.setKvalue("Assimilate", 13);
		G.hierarchy.setKvalue("Faithfulness", 12);
		G.hierarchy.setKvalue("Ni1", 11);
		G.hierarchy.setKvalue("Ni0", 10);
		G.hierarchy.setKvalue("Ni2",  9);
		G.hierarchy.setKvalue("Ni3",  8);
		G.hierarchy.setKvalue("Nf0",  7);
		G.hierarchy.setKvalue("Nf1",  6);
		G.hierarchy.setKvalue("Nf2",  5);
		G.hierarchy.setKvalue("Nf3",  4);
		G.hierarchy.setKvalue("No3",  3);
		G.hierarchy.setKvalue("No2",  2);
		G.hierarchy.setKvalue("No1",  1);
		G.hierarchy.setKvalue("Dissimilate", 0);

		// Up till here: 	setting up the experiment.
		// Make sure everything is as you would like it to be.
		// From here onwards: running the experiment.
		// You do not need to change anything, unless
		//   - you would like to print out the tableau, etc.
		//   - you would like to change the method from SA-OT with not_moved
		//-----------------------------------------------
		
		//-----------------------------------------------
		// Initialize Grammar, create underlying form:
		
		G.hierarchy.kvalue2rank();
		G.hierarchy.sortByRank();
		final Form uf = G.StrForm(arrayuf);


		//-----------------------------------------------------------------
		// Print out the parameters of the simulation for your information

        System.out.println("SA-OT with nr_unmoved");
        System.out.println(    " K_max = "      + K_max +
                               " | K_min = "      + K_min +
                               " | K_step = "     + K_step +
                               " | t_max = "      + t_max +
                               " | t_min = "      + t_min +
                               " | t_step = "     + t_step +
                               " | nr_unmoved = " + nr_unmoved);
        System.out.println("Underlying form = " + uf);

        // Print out the tableau 
        // Change | into & if you need it for LaTeX.
        // Or change | into >> if you want a hierarchy.

        System.out.print("    || ");
        for(int j=G.hierarchy.sortedByRank().length-1; j>-1; j--) {
        	System.out.print(G.hierarchy.sortedByRank()[j].name()+" | ");
        }
        System.out.println();
                   
        // (remove comments if you want it to be printed out)
        /*
        for(Candidate cand : G.gen.allCandidates(uf)) {
        	System.out.print(cand.sf+" || ");
            for(int j=G.hierarchy.sortedByRank().length-1; j>-1; j--) {
            	System.out.print(G.hierarchy.sortedByRank()[j].value(cand)+" | ");
            }
            System.out.println();
        }
        */

		  System.out.println("nr of runs  = "+ nr_run);

		  
		// ------------------------------------------
		// Run Simulated Annealing:
			
		  // Create a HashMap to collect frequencies.
		HashMap<Form,Double> collector = new HashMap<Form,Double>();
			
		Form sf, sf1;
		for (double i = 0.0; i < nr_run; i++) {
				Temperature t = RandomWalks.randomWalk(
					G.gen.randomCandidate(uf,i/nr_run), 
					G.topology, 
					G.hierarchy, 
					RulesOfMovingExamples.simulatedAnnealing(), 
					CoolingScheduleExamples.saotNM(
						K_max, K_step,
						t_max, t_min, t_step,
						nr_unmoved)
					);
				sf1 = t.output.sf;
				sf = G.StrFormSet(sf1, 0, StringGrammar.StrFormGet(sf1, 0)); 				
				if (collector.containsKey(sf)) {
					collector.put(sf, collector.get(sf)+1);
				}
				else {
					collector.put(sf, 1.0);
				}
		}
			
		// -----------------------------------
		// Output:
			
		for (Form key : collector.keySet()) {
			System.out.println(	key +	" : " +
					(collector.get(key) / nr_run) );
		}
			
	}
		
}


