/*
 * Testing.java
 *
 * Created on 7 maart 2006, 13:21
 *
 * To change this template, choose Tools | Options and locate the template under
 * the Source Creation and Management node. Right-click the template and choose
 * Open. You can then make changes to the template in the Source Editor.
 */

package DOPParser;

/**
 *
 * @author gideon
 */
import java.util.*;
import java.io.*;
import java.text.*;

public class Testing {
    
    public int nrUnknownWordSentences = 0;
    public int nrUnparseableSentences = 0;
    public static HashMap<String, Integer> labelFrequencies1 = new HashMap<String, Integer>();
    public static HashMap<String, Integer> labelFrequencies2 = new HashMap<String, Integer>();
    public static HashMap<String, Integer> matchingLabelsPerCategory = new HashMap<String, Integer>();
    
    /** Creates a new instance of Testing */
    public Testing(String testFileNameUnlabeled, String testFileNameLabeled, Grammar myGrammar) throws Exception {
  
        //print parses to file; this creates BufferedWriter out_latex and out_parses
    	Printer myPrinter = new Printer();
        
        String uOrL = "U";
        if (Main.DO_LABELED_PRECISION_AND_RECALL) uOrL = "L";
            
        if(!Main.DO_RIGHT_BRANCHING_TEST) System.out.println("**************************************************************************");
        BufferedReader buffUnlabeled = new BufferedReader(new FileReader(testFileNameUnlabeled));
        BufferedReader buffLabeled = new BufferedReader(new FileReader(testFileNameLabeled));

        String mySentence, myParsedSentence;
        int myCounter = 0;
        int nrParsedSentences = 0;
        int nrSingleWordSentences = 0;
        int nrTooManyWordSentences = 0;


        int nrMatchingConstituents=0, nrConstituentsOfComputedParse=0, nrConstituentsOfGivenParse=0;
        int nrTotalMatchingConstituents=0, nrTotalConstituentsOfComputedParse=0, nrTotalConstituentsOfGivenParse=0;        
        double LP = 0d;
        double LR = 0d;
        double totalLP = 0d;
        double totalLR = 0d;
        int nrExactMatch = 0;

        ArrayList<String> parsesWSJFormat = new ArrayList<String> ();
        ArrayList<String> unlabeledSentencesCorrespondingWithParses = new ArrayList<String> ();
        ArrayList<String> matchingLabels = new ArrayList<String> ();
        parseTree computedParse;
        parseTree givenParse = null;
        HashMap<String, GenericPair<String, parseTree>> myTreeBank = new HashMap<String, GenericPair<String, parseTree>>();

        while ((mySentence = buffUnlabeled.readLine()) !=null){
        	//always convert to lowercase
        	mySentence = mySentence.toLowerCase();
            myCounter++;
            int nrWords =0;

            System.out.println("Test Sentence " + myCounter + ": " + mySentence);
            myPrinter.printLineToStandardFile("Test Sentence " + myCounter + ": " + mySentence);
            
            //cut of the . at the end
            mySentence = mySentence.substring(0, mySentence.length()-2);
            nrWords = mySentence.split(" ").length;

            //skip sentences with only a single word
            if (nrWords == 1) {
                System.out.println("Test Sentence " + myCounter + " contains only a single word and is skipped");
                myPrinter.printLineToStandardFile("Test Sentence " + myCounter + " contains only a single word and is skipped");
                
                
                //read from parsed testfile
                myParsedSentence = buffLabeled.readLine();
                nrSingleWordSentences++;
                continue;
            }
            /*
            //skip sentences with more than 12 words
            if (nrWords > 12) {
                System.out.println("Test Sentence " + myCounter + " contains more than 12 words and is skipped");
                //read from parsed testfile
                myParsedSentence = buffParses1.readLine();
                nrTooManyWordSentences++;
                continue;
            }
            */
            if (!Main.DO_RIGHT_BRANCHING_TEST) {
                computedParse = goParse(mySentence, myGrammar);
                if (computedParse == null) {
                    System.out.println("Test Sentence " + myCounter + " is not parseable");
                    myPrinter.printLineToStandardFile("Test Sentence " + myCounter + " is not parseable");
                    
                    //read from parsed testfile
                    myParsedSentence = buffLabeled.readLine();
                    //write given parse in any case
                    if (Main.BRACKET_FORMAT_WSJ_STYLE) {
                        //XXX TEMP because in some files every sentence starts with TOP
                        //myParsedSentence = myParsedSentence.substring(5, mySentence.length()-1);
                        givenParse = Grammar.ExtractParseFromWSJText(myParsedSentence, false);
                    }
                    else givenParse = Grammar.ExtractParseFromOVISText(myParsedSentence);
                    givenParse.calculateNodeDepthAndLabelNodes();
                    givenParse.calculateNodeSpans();
                    givenParse.printToLatex(false, true, " given  ");
                    //nrUnknownWordSentences++;   //XXX dit weet je niet zeker
                    continue;
                }   //if (computedParse == null)
                else {
                	if (Main.CALCULATE_LIKELIHOOD || Main.CALCULATE_PERPLEXITY) {
                        GenericPair<String, parseTree> myPair = new GenericPair<String, parseTree>(computedParse.printWSJFormat(), computedParse);
                        myTreeBank.put(mySentence + "#" + Math.random(), myPair);
                        }
                }
            }
            nrParsedSentences++;

            //read from parsed testfile
            if (!Main.DO_PARSING_NO_EVALUATION) {
                myParsedSentence = buffLabeled.readLine();
                //System.out.println("Test Sentence =" + myParsedSentence);
                if (Main.BRACKET_FORMAT_WSJ_STYLE) {
                    givenParse = Grammar.ExtractParseFromWSJText(myParsedSentence, false);
                }
                else givenParse = Grammar.ExtractParseFromOVISText(myParsedSentence);
                givenParse.calculateNodeDepthAndLabelNodes();
                givenParse.calculateNodeSpans();
            }     

            myPrinter.printStuff(computedParse, givenParse, "computed", " given  ");


            //boolean blnWithUnderScore = false;
            //parseTreeOVISFormat.add(computedParse.printOVISFormat(blnWithUnderScore));

            if (Main.DO_PARSING_NO_EVALUATION) {
                
                parsesWSJFormat.add(computedParse.printWSJFormat());
                unlabeledSentencesCorrespondingWithParses.add(mySentence);
            }

            
            //compare them with PARSEVAL
            //PARSEVAL returns the number of matching constituents between the two trees
            //does not take into account TOP or preterminals
            //nrMatchingConstituents = doPARSEVAL(computedParse, givenParse);
            //XXX don't count multiple duplicate brackets
            if (!Main.DO_PARSING_NO_EVALUATION) {
                if (!Main.DO_RIGHT_BRANCHING_TEST ) {
                    if (Main.DO_LABELED_PRECISION_AND_RECALL) nrMatchingConstituents = doPARSEVAL(computedParse, givenParse);
                    else nrMatchingConstituents = doUPARSEVAL(computedParse, givenParse);
                    
                    if (Main.DO_LABEL_ASSOCIATION) matchingLabels.addAll(doLabelAssociation(computedParse, givenParse));
                }
                else {
                    if (!Main.SWITCH_LEFT_BRANCHING) nrMatchingConstituents = doRightBranchingUPARSEVAL(givenParse, nrWords);
                    else nrMatchingConstituents = doLeftBranchingUPARSEVAL(givenParse, nrWords);
                }

                nrTotalMatchingConstituents += nrMatchingConstituents;

                //Labeled Precision (LP) = nrMatchingConstituents/(nrConstituents in givenParse)
                //Labeled Recall (LR) = nrMatchingConstituents/(nrConstituents in computedParse) 
                //exclude terminals, preterminals and TOP: there are supposed to be mySentence.length preterminal nodes
                //and idem Terminal nodes is this correct?

                //XXX don't count multiple, do count TOP
                //nrConstituentsOfComputedParse = computedParse.getNodes().size() - 2*nrWords -1;
                //nrConstituentsOfGivenParse = givenParse.getNodes().size() - 2*nrWords -1;
                if (!Main.DO_RIGHT_BRANCHING_TEST ) {
                    nrConstituentsOfComputedParse = Utils.computeUniqueBrackets(computedParse.getNodes());
                }
                else nrConstituentsOfComputedParse = nrWords-1;

                nrTotalConstituentsOfComputedParse += nrConstituentsOfComputedParse;

                nrConstituentsOfGivenParse = Utils.computeUniqueBrackets(givenParse.getNodes());

                nrTotalConstituentsOfGivenParse += nrConstituentsOfGivenParse;

                System.out.println("nrMatchingConstituents=" + nrMatchingConstituents + "; nrConstituentsOfGivenParse=" + nrConstituentsOfGivenParse + "; nrConstituentsOfComputedParse=" + nrConstituentsOfComputedParse);
                myPrinter.printLineToStandardFile("nrMatchingConstituents=" + nrMatchingConstituents + "; nrConstituentsOfGivenParse=" + nrConstituentsOfGivenParse + "; nrConstituentsOfComputedParse=" + nrConstituentsOfComputedParse);
                
                //if nrConstituentsOfGivenParse = 0, or nrConstituentsOfComputedParse=0, then don't include
                LP = ((double) nrMatchingConstituents)/((double) nrConstituentsOfGivenParse);
                LR = ((double) nrMatchingConstituents)/((double) nrConstituentsOfComputedParse);
                totalLP = totalLP + LP;
                totalLR = totalLR + LR;

                if (LP==1. && LR==1.) nrExactMatch++;

                System.out.println("Test Sentence " + myCounter + ": " + uOrL + "P=" + LP + "; " + uOrL + "R=" + LR);
                myPrinter.printLineToStandardFile("Test Sentence " + myCounter + ": " + uOrL + "P=" + LP + "; " + uOrL + "R=" + LR);
                
            }   //if (!Main.DO_ONLY_PARSING) 
        }   //while ((mySentence = buffUnlabeled.readLine()) !=null)
        
        System.out.println(" ");
        System.out.println(nrParsedSentences + " out of " + myCounter + " sentences were processed.");
        //nrUnparseableSentences
        System.out.println(nrSingleWordSentences + " sentences contained only a single word.");
        System.out.println(nrTooManyWordSentences + " sentences contained more than 12 words.");
        System.out.println(nrUnknownWordSentences + " sentences contained unknown words.");
        System.out.println(nrUnparseableSentences + " sentences could not be parsed.");
        //System.out.println("Average UP=" + totalLP/((double) nrParsedSentences) );
        //System.out.println("Average UR=" + totalLR/((double) nrParsedSentences) );

        if (Main.DO_LABEL_ASSOCIATION) {
            doLabelAssociation(matchingLabels);
        }
        
        if (!Main.DO_PARSING_NO_EVALUATION) {
            
            System.out.println("total # MatchingConstituents=" + nrTotalMatchingConstituents);
            System.out.println("total # ConstituentsOfComputedParse=" + nrTotalConstituentsOfComputedParse);
            System.out.println("total # ConstituentsOfGivenParse=" + nrTotalConstituentsOfGivenParse);

            System.out.println("Average " + uOrL + "P=" + ( (double) nrTotalMatchingConstituents/ nrTotalConstituentsOfComputedParse) );
            System.out.println("Average " + uOrL + "R=" + ( (double) nrTotalMatchingConstituents/ nrTotalConstituentsOfGivenParse ) );
            System.out.println("Exact Match=" + nrExactMatch);

            //Write output to file   
            myPrinter.printLineToStandardFile("");
            myPrinter.printLineToStandardFile("total # MatchingConstituents=" + nrTotalMatchingConstituents);
            myPrinter.printLineToStandardFile("total # ConstituentsOfComputedParse=" + nrTotalConstituentsOfComputedParse);
            myPrinter.printLineToStandardFile("total # ConstituentsOfGivenParse=" + nrTotalConstituentsOfGivenParse);
            myPrinter.printLineToStandardFile("");
            myPrinter.printLineToStandardFile("Average " + uOrL + "P=" + ( (double) nrTotalMatchingConstituents/ nrTotalConstituentsOfComputedParse) );
            myPrinter.printLineToStandardFile("Average " + uOrL + "R=" + ( (double) nrTotalMatchingConstituents/ nrTotalConstituentsOfGivenParse ) );
            myPrinter.printLineToStandardFile("Exact Match=" + nrExactMatch);
            //myPrinter.printLineToFile.write("**************************************");

            //print parameters
            myPrinter.printLineToStandardFile("");
            if (Main.DOGOODMANDOP) myPrinter.printLineToStandardFile("DOP PARSER USED");
            else myPrinter.printLineToStandardFile("DOP PARSER NOT USED");
            myPrinter.printLineToStandardFile("BRANCHING_FACTOR=" + Main.BRANCHING_FACTOR);
            myPrinter.printLineToStandardFile("BEAM_WIDTH=" + Main.BEAM_WIDTH);
            myPrinter.printLineToStandardFile("READOFF_GRAMMAR_FROM_TREEBANK=" + Main.READOFF_GRAMMAR_FROM_TREEBANK);
            if (Main.READOFF_GRAMMAR_FROM_TREEBANK) myPrinter.printLineToStandardFile("GRAMMAR/TREEBANK FILE =" + Main.TREEBANK_FILE);
            else myPrinter.printLineToStandardFile("INPUT FILE =" + Main.GRAMMAR_FILE);
            myPrinter.printLineToStandardFile("UNLABELED TESTFILE=" + Main.TESTSET_UNLABELLED);
            myPrinter.printLineToStandardFile("GOLD STANDARD TESTFILE=" + Main.TESTSET_GOLD_STANDARD);
         }

        if (Main.CALCULATE_PERPLEXITY) {
            
        	calculatePerplexity(myTreeBank);
    		
    		
        }   

        
        if (Main.DO_PARSING_NO_EVALUATION) {

            BufferedWriter out = new BufferedWriter(new FileWriter("CHILDES_parses.txt"));
            for (String myLabeledSentence : parsesWSJFormat) {
                out.write(myLabeledSentence);
                out.newLine();
            }
            out.flush();
            out.close();
            
            BufferedWriter out2 = new BufferedWriter(new FileWriter("CHILDES_unlabeled.txt"));
            for (String myUnlabeledSentence : unlabeledSentencesCorrespondingWithParses) {
                out2.write(myUnlabeledSentence);
                out2.newLine();
            }
            out2.flush();
            out2.close();
            
        }

        myPrinter.flushAndClose();
        
        
    }

    public Testing(String parseFile1, String parseFile2) throws IOException {
        compareParses(parseFile1, parseFile2);
    }
    
    
	private void calculatePerplexity(HashMap<String, GenericPair<String, parseTree>> myTreeBank) throws IOException {
		//Grammar.calculateLikelihood(myTreeBank, myGrammar);
		double logLikelihood=0d, totalLogLikelihood = 0d;
		//TreeMap<Double, String> labeledSentencesSortedByLikelihood = new TreeMap<Double, String>();
		//TreeMap<Double, String> unlabeledSentencesSortedByLikelihood = new TreeMap<Double, String>();
		TreeMap<Double, ArrayList<String>> sentencesSortedByLikelihood = new TreeMap<Double, ArrayList<String>>();
		HashMap<Integer, Double> totalLogLikelihoodPerSentenceLength = new HashMap<Integer, Double>();
		HashMap<Integer, Integer> totalNrSentencesOfLength = new HashMap<Integer, Integer>();
		//NonTerminal myNodeNonTerminal=null, ChildNonTerminal1=null, ChildNonTerminal2=null;
		//Constituent Child1;
		parseTree cnfParseTree = null;
		int sentenceLength;
		
		//unlabeled sentence, #words, loglik, normalized loglik in csv
		for (String myUnlabeledSentence : myTreeBank.keySet()) {
		    //System.out.println (myUnlabeledSentence.split("#")[0]);

		    cnfParseTree = myTreeBank.get(myUnlabeledSentence).getSecond();
		    logLikelihood -= Math.log(cnfParseTree.getProbability())/Math.log(2.);  
		    totalLogLikelihood +=logLikelihood;
		    
		    //store the total probability for trees of different lengths
		    sentenceLength = myUnlabeledSentence.split(" ").length -1; //because unlabeled sentence includes " ."
		    
		    if (totalLogLikelihoodPerSentenceLength.get(sentenceLength) ==null) {
		        totalLogLikelihoodPerSentenceLength.put(sentenceLength, logLikelihood);
		        totalNrSentencesOfLength.put(sentenceLength, 1);
		    }
		    else {
		        totalLogLikelihoodPerSentenceLength.put(sentenceLength, totalLogLikelihoodPerSentenceLength.get(sentenceLength) + logLikelihood);
		        totalNrSentencesOfLength.put(sentenceLength, totalNrSentencesOfLength.get(sentenceLength)+1);
		    }
		}
		System.out.println ("totalLogLikelihood=" + totalLogLikelihood);
		
		
		double normalizedLikelihood = 0d;
		double averageLikelihood = 0d;
		String labeledSentence = null;
		parseTree myParse = null;
		String latexSentence = null;
		//System.out.println("# sentences=" + bankOfParses.size());
		
		for (String myUnlabeledSentence : myTreeBank.keySet()) {
		    sentenceLength = myUnlabeledSentence.split(" ").length-1;
		    averageLikelihood = totalLogLikelihoodPerSentenceLength.get(sentenceLength)/((double) totalNrSentencesOfLength.get(sentenceLength));
		       
		    cnfParseTree = myTreeBank.get(myUnlabeledSentence).getSecond(); 
		    normalizedLikelihood = -Math.log(cnfParseTree.getProbability())/Math.log(2.) -averageLikelihood;
		    
		    labeledSentence = myTreeBank.get(myUnlabeledSentence).getFirst();
		    myParse = myTreeBank.get(myUnlabeledSentence).getSecond();
		    latexSentence = myParse.printToLatex(false, false, "");
		    
		    if (sentencesSortedByLikelihood.get(normalizedLikelihood)==null) {
		        //create new HashSet for sentences with exactly identical probabilities
		        ArrayList<String> sentencesWithSameLikelihood = new ArrayList<String>();
		        
		        //.split("#")[0], because random number added at end, so it takes duplicates
		        sentencesWithSameLikelihood.add(myUnlabeledSentence.split("#")[0] + "#" + labeledSentence  + "#" + latexSentence);
		        sentencesSortedByLikelihood.put(normalizedLikelihood, sentencesWithSameLikelihood);
		    }
		    else {
		        //add pair to HashSet of identical probabilities, which already exists
		        sentencesSortedByLikelihood.get(normalizedLikelihood).add(myUnlabeledSentence.split("#")[0] + "#" + labeledSentence+ "#" + labeledSentence);
		    }        
		}
		
		
		//so sentencesSortedByLikelihood is Treemap with key=likelihood, value is pair of unlabeled and corresp labeled sentences
		//print a sorted list of unlabeled sentences, and labeled sentences
		BufferedWriter out_likelihood = new BufferedWriter(new FileWriter(Main.OUTPUT_DIR + "/" + "likelihood.csv"));
		//BufferedWriter out_labeled = new BufferedWriter(new FileWriter(Main.OUTPUT_DIR + "/" + "labeled.txt"));
		
		 for (Double myLikelihood : sentencesSortedByLikelihood.keySet()) {
		     for (String pairOfSentences : sentencesSortedByLikelihood.get(myLikelihood)) {
		        sentenceLength = pairOfSentences.split("#")[0].split(" ").length-1;
		        averageLikelihood = totalLogLikelihoodPerSentenceLength.get(sentenceLength)/((double) totalNrSentencesOfLength.get(sentenceLength));
		    
		        out_likelihood.write(pairOfSentences.split("#")[0] + ", " + pairOfSentences.split("#")[1] + ", " + pairOfSentences.split("#")[2] + ", " + (myLikelihood + averageLikelihood) );
		        out_likelihood.newLine();
		        
		        //out_labeled.write(pairOfSentences.split("#")[1] );
		        //out_labeled.newLine();
		     }
		 }
		 //out_labeled.flush();
		 //out_labeled.close();
		 out_likelihood.flush();
		 out_likelihood.close();
	}
    
    
    
    public HashMap<String, String> doLabelAssociation(ArrayList<String> matchingLabels)  throws IOException {
        //put matchingLabels into HashMap, with matchingPair as the key, and frequency count as value
            HashMap<String, Integer> uniqueLabelPairs = new HashMap<String, Integer>();
            for (String myPair : matchingLabels) {
                if (uniqueLabelPairs.get(myPair) ==null) {
                    uniqueLabelPairs.put(myPair, 1);
                }
                else {
                    uniqueLabelPairs.put(myPair, uniqueLabelPairs.get(myPair) +1);
                }
            }
            //create list of best associations for every label of induced grammar
            HashMap<String, String> bestAssociations = new HashMap<String, String>();
            HashMap<String, Integer> bestAssociationFrequencies = new HashMap<String, Integer>();
            String inducedLabel = null;
            for (String myUniquePair : uniqueLabelPairs.keySet()) {
                inducedLabel = myUniquePair.split("#")[0];
                if (bestAssociations.get(inducedLabel) == null) {
                    //inducedLabel not associated yet, so put it with first
                    bestAssociations.put(inducedLabel, myUniquePair.split("#")[1]);
                    bestAssociationFrequencies.put(inducedLabel, uniqueLabelPairs.get(myUniquePair));
                }
                else {
                    //replace it by other association if that has higher freqency
                    if (uniqueLabelPairs.get(myUniquePair) > bestAssociationFrequencies.get(inducedLabel) ) {
                        bestAssociations.put(inducedLabel, myUniquePair.split("#")[1]);
                        bestAssociationFrequencies.put(inducedLabel, uniqueLabelPairs.get(myUniquePair));
                    }
                }
            }
            
            
            
            //print proportion of labels explained by best associations
            int totalMatchingLabels = 0;
            for (String myLabel : bestAssociationFrequencies.keySet()) {
                totalMatchingLabels += bestAssociationFrequencies.get(myLabel);
            }
            System.out.println("The proportion of matching label pairs explained by the most frequent associations =" + ((double) totalMatchingLabels/(double) matchingLabels.size()));
            //output list of best associations 
             BufferedWriter out = new BufferedWriter(new FileWriter("labelAssociations.csv"));
            for (String myLabel : bestAssociations.keySet()) {
                out.write(myLabel + "," + bestAssociations.get(myLabel));
                out.newLine();
            }
            out.flush();
            out.close();
            
            return bestAssociations;
}
    
    
    public void compareParses(String parseFile1, String parseFile2) throws IOException {
       //parseTree1="Viterbi_parses.txt", parseTree2="Viterbi_Treebank_parses.txt"=GoldStandard 
        
    	//print parses to file; this creates BufferedWriter out_latex and out_parses
        Printer myPrinter = new Printer();
        
        NumberFormat numberFormatter;
        numberFormatter = NumberFormat.getNumberInstance();

        String mySentence, myParsedSentence;
        int myCounter = 0;

        int nrMatchingConstituents=0, nrConstituentsOfComputedParse=0, nrConstituentsOfGivenParse=0;
        int nrTotalMatchingConstituents=0, nrTotalConstituentsOfComputedParse=0, nrTotalConstituentsOfGivenParse=0;        
        double LP = 0d;
        double LR = 0d;
        double totalLP = 0d;
        double totalLR = 0d;
        int nrExactMatch = 0;

        ArrayList<String> allUnlabeledSentences = new ArrayList<String> ();
        ArrayList<String> matchingLabels = new ArrayList<String> ();
        ArrayList<String> tempTreebankSpansForTest = new ArrayList<String> ();
        parseTree parseTree1;
        parseTree parseTree2;

        ArrayList<parseTree> treesForRelabeling = new ArrayList<parseTree>();
        TreeMap<String, parseTree> treesOfFile1 = new TreeMap<String, parseTree>();
        TreeMap<String, parseTree> treesOfFile2 = new TreeMap<String, parseTree>();

        BufferedReader buffParses1 = new BufferedReader(new FileReader(parseFile1));
        BufferedReader buffParses2 = new BufferedReader(new FileReader(parseFile2));

        //XXX temp
        BufferedReader buffUnlabeled = new BufferedReader(new FileReader("Input_for_evaluation/Viterbi_unlabeled.txt"));
        
        //read from parseFile1
        while ((mySentence = buffParses1.readLine()) !=null) {
            myCounter++;
            int nrWords =0;

            //System.out.println("mySentence:" + mySentence + "@");
            //System.out.println("Viterbi_Treebank_parses Test Sentence =" + mySentence);
            
            if (Main.BRACKET_FORMAT_WSJ_STYLE) {
                boolean blnPrintChars = false;
                
                parseTree1 = Grammar.ExtractParseFromWSJText(mySentence, blnPrintChars);
            }
            else parseTree1 = Grammar.ExtractParseFromOVISText(mySentence);
            if (Main.PRINT_LABEL_FREQUENCIES || Main.PRINT_PARSEVAL_PER_CATEGORY) parseTree1.calculateLabelFrequencies(labelFrequencies1);
            
            parseTree1.calculateNodeDepthAndLabelNodes();
            parseTree1.calculateNodeSpans();

            //put parseTree into TreeMap, alphabetically indexed by unlabeled sentence
            StringBuffer unLabeledSentence = new StringBuffer();
            for (Node myNode : parseTree1.getNodes()) {
               if (myNode.getType()==Main.TERMINAL) {  //TERMINALS
                   if (myNode.getName().startsWith("_")) unLabeledSentence.append(myNode.getName().substring(1).toLowerCase()).append(' ');
                   else unLabeledSentence.append(myNode.getName());//       .append(' ')    
               }
            }
        
          //temp xxx
            
           /// unLabeledSentence = new StringBuffer();
           // String[] tempSolution = buffUnlabeled.readLine().split(" ");
           // for (int m=0; m< tempSolution.length-1; m++) {
           //     unLabeledSentence.append(tempSolution[m] + "  ");
           // }
            
            
            treesOfFile1.put(unLabeledSentence.toString(), parseTree1);
            treesForRelabeling.add(parseTree1);
            allUnlabeledSentences.add(unLabeledSentence.toString());
            //System.out.println("LabeledSentence of parseTree1: " + mySentence);
            System.out.println("unLabeledSentence of parseTree1: >" + unLabeledSentence.toString() + "<");
            
            //read from parseFile2
            myParsedSentence = buffParses2.readLine();
            //System.out.println("Viterbi_parses.txt Test Sentence =" + myParsedSentence);
            if (Main.BRACKET_FORMAT_WSJ_STYLE) {
                boolean blnPrintChars = false;
                parseTree2 = Grammar.ExtractParseFromWSJText(myParsedSentence, blnPrintChars);
            }
            else 
            parseTree2 = Grammar.ExtractParseFromOVISText(myParsedSentence);
            
            //YOU MUST make the parse BINARY before you compare!!!
            //if (Main.FIND_TREEBANK_PARSES_FOR_UNLABELED_VITERBI) parseTree2.transformToCNF();
            parseTree2.calculateNodeDepthAndLabelNodes();
            parseTree2.calculateNodeSpans();
            if (Main.PRINT_LABEL_FREQUENCIES || Main.PRINT_PARSEVAL_PER_CATEGORY) parseTree2.calculateLabelFrequencies(labelFrequencies2); 
            
            //put parseTree into TreeMap, alphabetically indexed by unlabeled sentence
            unLabeledSentence = new StringBuffer();
            StringBuffer tempSentenceSpanForTest = new StringBuffer();
            for (Node myNode : parseTree2.getNodes()) {
               if (myNode.getType()==Main.TERMINAL) {  //TERMINALS
                   if (myNode.getName().startsWith("_")) unLabeledSentence.append(myNode.getName().substring(1).toLowerCase()).append(' ');
                   else unLabeledSentence.append(myNode.getName()).append(' ');//            
               }
               if (myNode.getType()==Main.NONTERMINAL) {  //TERMINALS
                    tempSentenceSpanForTest.append("" + myNode.getLeftSpan() + "-" + myNode.getRightSpan()).append(", ");           
               }
            }
        
          
            treesOfFile2.put(unLabeledSentence.toString(), parseTree2);
            tempTreebankSpansForTest.add(tempSentenceSpanForTest.toString());
            
            //System.out.println("LabeledSentence of parseTree2: " + myParsedSentence);
            System.out.println("unLabeledSentence of parseTree2: >" + unLabeledSentence.toString() + "<");
        }

        myCounter =0;
        String uOrL = "U";
        if (Main.DO_LABELED_PRECISION_AND_RECALL) uOrL = "L";
            
        //for (String unlabeledSentence : treesOfFile1.keySet()) { WRONG!! there are duplicate unlabeled sentences
        for (String unlabeledSentence : allUnlabeledSentences) {
            myCounter++;
            parseTree1 = treesOfFile1.get(unlabeledSentence);
            parseTree2 = treesOfFile2.get(unlabeledSentence);
            
            System.out.println("Test Sentence " + myCounter + ": " + unlabeledSentence);
            myPrinter.printLineToStandardFile("Test Sentence " + myCounter + ": " + unlabeledSentence);
            
            if (parseTree2==null) System.out.println("Nullpointer: " + unlabeledSentence);
            //parseTree1="Viterbi_parses.txt", parseTree2="Viterbi_Treebank_parses.txt"=GoldStandard
            myPrinter.printStuff(parseTree1, parseTree2,  "  Stolcke  ", " treebank ");

            //compare them with PARSEVAL
            //PARSEVAL returns the number of matching constituents between the two trees
            if (Main.DO_LABELED_PRECISION_AND_RECALL) nrMatchingConstituents = doPARSEVAL(parseTree1, parseTree2);
            else nrMatchingConstituents = doUPARSEVAL(parseTree1, parseTree2);
            nrTotalMatchingConstituents += nrMatchingConstituents;

            if (Main.DO_LABEL_ASSOCIATION || Main.FIND_PARSES_CORRESPONDING_WITH_UNLABELED_FROM_TREEBANK ) matchingLabels.addAll(doLabelAssociation(parseTree1, parseTree2));
            
            //parseTree1="Viterbi_parses.txt", parseTree2="Viterbi_Treebank_parses.txt"=GoldStandard
            nrConstituentsOfComputedParse = Utils.computeUniqueBrackets(parseTree1.getNodes());
            nrTotalConstituentsOfComputedParse += nrConstituentsOfComputedParse;

            nrConstituentsOfGivenParse = Utils.computeUniqueBrackets(parseTree2.getNodes());
            nrTotalConstituentsOfGivenParse += nrConstituentsOfGivenParse;

            System.out.println("nrMatchingConstituents=" + nrMatchingConstituents + "; nrConstituentsOfGivenParse=" + nrConstituentsOfGivenParse + "; nrConstituentsOfComputedParse=" + nrConstituentsOfComputedParse);
            myPrinter.printLineToStandardFile("nrMatchingConstituents=" + nrMatchingConstituents + "; nrConstituentsOfGivenParse=" + nrConstituentsOfGivenParse + "; nrConstituentsOfComputedParse=" + nrConstituentsOfComputedParse);
            
            //if nrConstituentsOfGivenParse = 0, or nrConstituentsOfComputedParse=0, then don't include
            
            LP = ((double) nrMatchingConstituents)/((double) nrConstituentsOfGivenParse);
            LR = ((double) nrMatchingConstituents)/((double) nrConstituentsOfComputedParse);
            totalLP = totalLP + LP;
            totalLR = totalLR + LR;

            if (LP==1. && LR==1.) nrExactMatch++;
            
            System.out.println("Test Sentence " + myCounter + ": " + uOrL + "P=" + LP + "; " + uOrL + "R=" + LR);
            myPrinter.printLineToStandardFile("Test Sentence " + myCounter + ": " + uOrL + "P=" + LP + "; " + uOrL + "R=" + LR);
            
        }   
        
        System.out.println(" ");
        System.out.println(myCounter + " sentences were processed.");

        System.out.println("total # MatchingConstituents=" + nrTotalMatchingConstituents);
        System.out.println("total # ConstituentsOfComputedParse=" + nrTotalConstituentsOfComputedParse);
        System.out.println("total # ConstituentsOfGivenParse=" + nrTotalConstituentsOfGivenParse);

        System.out.println("Average " + uOrL + "P=" + ( (double) nrTotalMatchingConstituents/ nrTotalConstituentsOfComputedParse) );
        System.out.println("Average " + uOrL + "R=" + ( (double) nrTotalMatchingConstituents/ nrTotalConstituentsOfGivenParse ) );
        System.out.println("Exact Match=" + nrExactMatch);

        if (Main.PRINT_LABEL_FREQUENCIES) {
        	BufferedWriter out_labelfreq1= new BufferedWriter(new FileWriter(Main.OUTPUT_DIR + "/labelFrequencies1.csv"));
        	BufferedWriter out_labelfreq2= new BufferedWriter(new FileWriter(Main.OUTPUT_DIR + "/labelFrequencies2.csv"));
        	
            //print labelFrequencies1
            //System.out.println("");
            //System.out.println("labelFrequencies1");
            int totalNrLabels = 0;
            for (String myLabel : labelFrequencies1.keySet()) {
                totalNrLabels += labelFrequencies1.get(myLabel).intValue();
            }

            for (String myLabel : labelFrequencies1.keySet()) {
            	out_labelfreq1.write(myLabel + ";" + numberFormatter.format(((double) 100.*labelFrequencies1.get(myLabel).intValue())/((double) totalNrLabels )));
            	out_labelfreq1.newLine();
                //System.out.println(myLabel + ";" + numberFormatter.format(((double) 100.*labelFrequencies1.get(myLabel).intValue())/((double) totalNrLabels ))) ;
            }

            //print labelFrequencies2
            //System.out.println("");
            //System.out.println("labelFrequencies2");
            totalNrLabels = 0;
            for (String myLabel : labelFrequencies2.keySet()) {
                totalNrLabels += labelFrequencies2.get(myLabel).intValue();
            }

            for (String myLabel : labelFrequencies2.keySet()) {
            	out_labelfreq2.write(myLabel + ";" + numberFormatter.format(((double) 100.*labelFrequencies2.get(myLabel).intValue())/((double) totalNrLabels )));
            	out_labelfreq2.newLine();
                //System.out.println(myLabel + ";" + numberFormatter.format(((double) 100.*labelFrequencies2.get(myLabel).intValue())/((double) totalNrLabels ))) ;
            }
            
            out_labelfreq1.flush();
            out_labelfreq1.close();
            out_labelfreq2.flush();
            out_labelfreq2.close();
        }
        
        if (Main.PRINT_PARSEVAL_PER_CATEGORY) {
           
            System.out.println("");
            System.out.println("LP/LR per category");
            //print matching labels per category
            
            for (String myLabel : matchingLabelsPerCategory.keySet()) {
                System.out.println(myLabel);
                if (myLabel.equals("TOP")) System.out.println(myLabel + ";" + numberFormatter.format((100.*(double) matchingLabelsPerCategory.get(myLabel).intValue())/((double) labelFrequencies1.get(myLabel).intValue())) + ";" + numberFormatter.format((100.*(double) matchingLabelsPerCategory.get(myLabel).intValue())/((double) labelFrequencies2.get(myLabel).intValue())));
                //else System.out.println(myLabel + ";" + numberFormatter.format((100.*(double) matchingLabelsPerCategory.get(myLabel).intValue())/((double) labelFrequencies1.get(myLabel).intValue())) + ";" + numberFormatter.format((100.*(double) matchingLabelsPerCategory.get(myLabel).intValue())/((double) labelFrequencies2.get(myLabel.toLowerCase()).intValue())));
                //else {
                //    if (!(matchingLabelsPerCategory.get(myLabel)==null))
                
                //    System.out.println(myLabel + ";" + numberFormatter.format((100.*(double) matchingLabelsPerCategory.get(myLabel).intValue())/((double) labelFrequencies1.get(myLabel).intValue())) + ";" + numberFormatter.format((100.*(double) matchingLabelsPerCategory.get(myLabel).intValue())/((double) labelFrequencies2.get(myLabel).intValue())));
                //}
            }
             
        }
        
        HashMap<String, String> bestAssociations = null;
        if (Main.DO_LABEL_ASSOCIATION || Main.FIND_PARSES_CORRESPONDING_WITH_UNLABELED_FROM_TREEBANK) {
            //treesForRelabeling contains the parses that you want to relabel
            relabelViterbiParses(matchingLabels, treesForRelabeling);
        }  
         
        
        //Write output to file

        myPrinter.flushAndClose();
        
        //TEMP TEST XXX
        BufferedWriter out_spans=null;
        
        out_spans = new BufferedWriter(new FileWriter("treebank_Spans.txt"));
        for (String mySentenceSpan : tempTreebankSpansForTest) {
            out_spans.write(mySentenceSpan);
            out_spans.newLine();
        }
        out_spans.flush();
        out_spans.close();
    }
    
    public void relabelViterbiParses(ArrayList<String> matchingLabels, ArrayList<parseTree> treesOfFile1)  throws IOException {
        
        HashMap<String, String> bestAssociations = doLabelAssociation(matchingLabels);  //also writes labelAssociations to file
        //replace all induced labels in parseTree by their associations directly in Viterbi Parse
        //and store the output in relabeled_parses.txt

        //String inducedParseViterbiFile = "Viterbi_parses.txt";
        //parseTree viterbiParseTree = null; 
        //BufferedReader buffViterbiParses = new BufferedReader(new FileReader(inducedParseViterbiFile));
       //write unlabeled text to file
        BufferedWriter    out = new BufferedWriter(new FileWriter("Input_for_evaluation/relabeled_parses.txt"));
        ArrayList<String> relabeledViterbiParses = new ArrayList<String> ();
        String mySentence;
        
        /*
        //read from inducedParseViterbiFile
        while ((mySentence = buffViterbiParses.readLine()) !=null) {

            if (Main.DO_WSJ_PARSE) {
                boolean blnPrintChars = false;
                viterbiParseTree = Grammar.ExtractParseFromWSJText(mySentence, blnPrintChars);
            }
            else viterbiParseTree = Grammar.ExtractParseFromOVISText(mySentence);
            viterbiParseTree.calculateNodeDepthAndLabelNodes();
            viterbiParseTree.calculateNodeSpans();
         */
            //put parseTree into TreeMap, alphabetically indexed by unlabeled sentence
            
        for (parseTree viterbiParseTree : treesOfFile1) {
            for (Node myNode : viterbiParseTree.getNodes()) {

               if (myNode.getType()==Main.NONTERMINAL) {  
                   //replace name of node by new label, according to bestAssociations
                   //replace name only if bestAssociations exists, otherwise leave it the same
                   if (!(bestAssociations.get(myNode.getName().toUpperCase())==null)) {
                       myNode.setName(bestAssociations.get(myNode.getName().toUpperCase()));
                   }

               }
            }

            //write parseTree in WSJ or OVIS format
            //append it to ArrayList of relabeled Viterbi Parses XXX
            boolean blnWithUnderScore = false;
            if (Main.BRACKET_FORMAT_WSJ_STYLE)
                relabeledViterbiParses.add(viterbiParseTree.printWSJFormat());
            else relabeledViterbiParses.add(viterbiParseTree.printOVISFormat(blnWithUnderScore));
        }   //while ((mySentence = buffViterbiParses.readLine())

        //write relabeled Viterbi Parse to file
         for (String myRelabeledViterbiParse : relabeledViterbiParses) {
                out.write(myRelabeledViterbiParse);
                out.newLine();
            }
        out.flush();
        out.close();
            
  }

    public parseTree goParse(String fullSentence, Grammar myGrammar) {
        //String[] mySentence = {"ik_", "wil_", "van_", "voorschoten_", "naar_", "den_", "haag_", "centraal_", "station_"};
        
        String[] mySentence = fullSentence.split(" ");
        //check for unknown words
        boolean blnUnknownWord = false;
        for ( String myWord : mySentence) {
            if (myGrammar != null) {
                if (myGrammar.Terminals != null) {
                    if (myWord != null) {
                       if (myGrammar.Terminals.get(myWord) != null) {
		          System.out.println(myGrammar.Terminals.get(myWord));
                       } else
		          System.out.println("null");
                    } else
		        System.out.println("myWord null");
                } else
		    System.out.println("terminals null");
            } else
	        System.out.println("grammar null");

            if (myGrammar.Terminals.get(myWord) == null){
                blnUnknownWord = true;
                System.out.println("The sentence contains the unknown word #" + myWord + "#");
                nrUnknownWordSentences++;
                break;
            }
        }
        if(blnUnknownWord) return null;
        
        //System.out.println("Starting a new parse...");
        CYKParser myParser = new CYKParser(myGrammar,  mySentence);
        
        parseTree viterbiParse = myParser.readoutViterbiParse();
        if (viterbiParse==null) {
        //was: if (myParser.readoutViterbiParse()==null) {
            nrUnparseableSentences++;   
            return null;
        }
        //System.out.println("Starting readout...");        
        return viterbiParse;  //returns null if unparseable

    }
    
    /* this method returns the number of matching constituents between the two trees
     *LP and LR are not calculated here
     */
    public int doPARSEVAL(parseTree parseTree1, parseTree parseTree2) {
        //int nrMatchingConstituents = 0;
        HashSet<String> listOfUniqueBrackets = new HashSet<String>();
        //iterate over nodes of both trees
        for(Node nodeOfTree1 : parseTree1.getNodes()) {
            //skip terminals, skip TOP XXX also skip preterminals???
            //if (nodeOfTree1.getType()==Main.NONTERMINAL && nodeOfTree1.getChildNodes().size()>1 ) { FOUT: dat excludeert TOP node!!!
            if (nodeOfTree1.getType()==Main.NONTERMINAL && (nodeOfTree1.getRightSpan()- nodeOfTree1.getLeftSpan())>1 ) { 
                for(Node nodeOfTree2 : parseTree2.getNodes()) {
                    //may be unnecessary
                    if (nodeOfTree2.getType()==Main.NONTERMINAL && (nodeOfTree2.getRightSpan()- nodeOfTree2.getLeftSpan())>1 ) { 
                        //compare labels (case-insensitive)
                        if (nodeOfTree1.getName().toLowerCase().equals(nodeOfTree2.getName().toLowerCase())){
                            //check spans
                            if ((nodeOfTree1.getLeftSpan()==nodeOfTree2.getLeftSpan()) && (nodeOfTree1.getRightSpan()==nodeOfTree2.getRightSpan())) {
                                listOfUniqueBrackets.add(nodeOfTree1.getLeftSpan() + "_" + nodeOfTree1.getRightSpan());
                                if (Main.PRINT_PARSEVAL_PER_CATEGORY) {
                                    if (matchingLabelsPerCategory.get(nodeOfTree1.getName())==null) {
                                        matchingLabelsPerCategory.put(nodeOfTree1.getName(), 1);
                                    }
                                    else matchingLabelsPerCategory.put(nodeOfTree1.getName(), matchingLabelsPerCategory.get(nodeOfTree1.getName()).intValue() +1);
                                }
                                break; //breaks out of fpr-loop, so the match will be counted only once!!! not true, if 
                                //The computed parse tree is:  [.{TOP (0-3)} [.{A (0-3)} 
                                //The  given   parse tree is:  [.{TOP (0-3)} [.{a (0-3)}
                                
                            }
                        }
                    }
                }
            }
        }
        return listOfUniqueBrackets.size(); 
    }
    
    /* this method returns the number of matching constituents between the two trees
     *LP and LR are not calculated here
     */
    /* this method returns the number of matching constituents between the two trees
     *LP and LR are not calculated here
     */
    public int doUPARSEVAL(parseTree parseTree1, parseTree parseTree2) {
        int nrMatchingConstituents = 0;
        HashSet<String> listOfUniqueBrackets = new HashSet<String>();
        //iterate over nodes of both trees
        for(Node nodeOfTree1 : parseTree1.getNodes()) {
            //skip terminals, skip TOP XXX also skip preterminals???
            //if (nodeOfTree1.getType()==Main.NONTERMINAL && nodeOfTree1.getChildNodes().size()>1 ) { WRONG: that excludes TOP!!!
            if (nodeOfTree1.getType()==Main.NONTERMINAL && (nodeOfTree1.getRightSpan()- nodeOfTree1.getLeftSpan())>1 ) {
                for(Node nodeOfTree2 : parseTree2.getNodes()) {
                    //may be unnecessary
                    if (nodeOfTree2.getType()==Main.NONTERMINAL && (nodeOfTree2.getRightSpan()- nodeOfTree2.getLeftSpan())>1 ) { 
                        //check spans
                        if ((nodeOfTree1.getLeftSpan()==nodeOfTree2.getLeftSpan()) && (nodeOfTree1.getRightSpan()==nodeOfTree2.getRightSpan())) {
                            listOfUniqueBrackets.add(nodeOfTree1.getLeftSpan() + "_" + nodeOfTree1.getRightSpan());
                            //nrMatchingConstituents++;
                            break;
                        }
                    }
                }
            }
        }
        return listOfUniqueBrackets.size(); //nrMatchingConstituents;
    }
    
   public ArrayList<String> doLabelAssociation(parseTree parseTree1, parseTree parseTree2) {
        //not HashSet, because same labels may occur on different spans
        ArrayList<String> matchingPairs = new ArrayList<String>();
        
        //iterate over nodes of both trees
        for(Node nodeOfTree1 : parseTree1.getNodes()) {
            //skip terminals and preterminals, skip TOP, or other nodes with span equal to entire sentence
            if (nodeOfTree1.getType()==Main.NONTERMINAL && nodeOfTree1.getChildNodes().size()>1 && !nodeOfTree1.getName().equals("TOP")) { 
                for(Node nodeOfTree2 : parseTree2.getNodes()) {
                    //may be unnecessary
                    if (nodeOfTree2.getType()==Main.NONTERMINAL && nodeOfTree2.getChildNodes().size()>1 && !nodeOfTree2.getName().equals("TOP")) { 
                        //check spans
                        if ((nodeOfTree1.getLeftSpan()==nodeOfTree2.getLeftSpan()) && (nodeOfTree1.getRightSpan()==nodeOfTree2.getRightSpan())) {
                            matchingPairs.add(nodeOfTree1.getName().toUpperCase() + "#" + nodeOfTree2.getName().toUpperCase());
                            //no break, because multiplicity counts;
                        }
                    }
                }
            }
        }
        return matchingPairs;
    }
    
    /* this method returns the number of matching constituents between the two trees
     *LP and LR are not calculated here
     */
    public int doRightBranchingUPARSEVAL(parseTree parseTree1, int nrWordsInSentence) {
        int nrMatchingConstituents = 0;
        HashSet<String> listOfUniqueBrackets = new HashSet<String>();
        //iterate over nodes of both trees
        for(Node nodeOfTree1 : parseTree1.getNodes()) {
            //skip terminals
            if (nodeOfTree1.getType()==Main.NONTERMINAL && nodeOfTree1.getChildNodes().size()>1 ) { 
                //check spans Right spans are (0,3), (1,3) ... (nrWords-1,nrWords)
                for (int myLeftSpan = 0; myLeftSpan <= nrWordsInSentence-2; myLeftSpan++) {
                    if ((nodeOfTree1.getLeftSpan()==myLeftSpan) && (nodeOfTree1.getRightSpan()==(nrWordsInSentence))) {
                        listOfUniqueBrackets.add(nodeOfTree1.getLeftSpan() + "_" + nodeOfTree1.getRightSpan());
                        //nrMatchingConstituents++;
                        break;
                    }
                }     
            }
        }
        return listOfUniqueBrackets.size(); //nrMatchingConstituents;
    }
    
    /* this method returns the number of matching constituents between the two trees
     *LP and LR are not calculated here
     */
    public int doLeftBranchingUPARSEVAL(parseTree parseTree1, int nrWordsInSentence) {
        int nrMatchingConstituents = 0;
        HashSet<String> listOfUniqueBrackets = new HashSet<String>();
        //iterate over nodes of both trees
        for(Node nodeOfTree1 : parseTree1.getNodes()) {
            //skip terminals
            if (nodeOfTree1.getType()==Main.NONTERMINAL && nodeOfTree1.getChildNodes().size()>1 ) { 
                //check spans: Left spans are (0,2), (0,3) ... (0,nrWords)
                for (int myRightSpan = 2; myRightSpan <= nrWordsInSentence; myRightSpan++) {
                    if ((nodeOfTree1.getLeftSpan()==0) && (nodeOfTree1.getRightSpan()==myRightSpan)) {
                        listOfUniqueBrackets.add(nodeOfTree1.getLeftSpan() + "_" + nodeOfTree1.getRightSpan());
                        //nrMatchingConstituents++;
                        break;
                    }
                }     
            }
        }
        return listOfUniqueBrackets.size(); //nrMatchingConstituents;
    }
    
    /*
    public int doUPARSEVAL(parseTree parseTree1, parseTree parseTree2) {
        int nrMatchingConstituents = 0;
        //iterate over nodes of both trees
        for(Node nodeOfTree1 : parseTree1.getNodes()) {
            //skip terminals, skip TOP XXX also skip preterminals???
            if (nodeOfTree1.getType()==Main.NONTERMINAL && nodeOfTree1.getChildNodes().size()>1 && !nodeOfTree1.getName().equals("TOP")) { 
                for(Node nodeOfTree2 : parseTree2.getNodes()) {
                    //may be unnecessary
                    if (nodeOfTree2.getType()==Main.NONTERMINAL && nodeOfTree2.getChildNodes().size()>1 && !nodeOfTree2.getName().equals("TOP")) { 
                        //check spans
                        if ((nodeOfTree1.getLeftSpan()==nodeOfTree2.getLeftSpan()) && (nodeOfTree1.getRightSpan()==nodeOfTree2.getRightSpan())) {
                            nrMatchingConstituents++;
                            break;
                        }
                    }
                }
            }
        }
        return nrMatchingConstituents;
    }
    */
    /* this method returns true if the parses are identical (according to PARSEVAL measure)
     
    public boolean identicalParses(parseTree parseTree1, parseTree parseTree2) {
        
        //iterate over nodes of both trees
        boolean existsIdenticalNode;
        for(Node nodeOfTree1 : parseTree1.getNodes()) {
            existsIdenticalNode = false;
            for(Node nodeOfTree2 : parseTree2.getNodes()) {
                if (nodeOfTree1.getName().equals(nodeOfTree2.getName())){
                    //check spans
                    if ((nodeOfTree1.getLeftSpan()==nodeOfTree2.getLeftSpan()) && (nodeOfTree1.getRightSpan()==nodeOfTree2.getRightSpan())) {
                        existsIdenticalNode = true;
                        break;
                    }   
                }
            }
            if(!existsIdenticalNode) return false;
        }
        return true;
    }
     **/
}
