package uk.ac.ox.krr.logmap2.mappings;

import java.util.LinkedList;

import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import uk.ac.ox.krr.logmap2.oaei.oracle.OracleManager;

import uk.ac.ox.krr.logmap2.Parameters;
import uk.ac.ox.krr.logmap2.SIAssessment.DataPropertyMappingAssessment;
import uk.ac.ox.krr.logmap2.SIAssessment.ObjectPropertyMappingAssessment;
import uk.ac.ox.krr.logmap2.SIAssessment.InstanceMatchingAssessment;
//import uk.ac.ox.krr.logmap2.backknowlede.ManageBackgroundKnowledge;
import uk.ac.ox.krr.logmap2.indexing.IndexManager;
import uk.ac.ox.krr.logmap2.indexing.OntologyProcessing;
import uk.ac.ox.krr.logmap2.indexing.entities.ClassIndex;
import uk.ac.ox.krr.logmap2.io.LogOutput;
import uk.ac.ox.krr.logmap2.mappings.objects.MappingObjectIdentifiers;
import uk.ac.ox.krr.logmap2.mappings.objects.MappingObjectStr;
import uk.ac.ox.krr.logmap2.utilities.Lib;
import uk.ac.ox.krr.logmap2.statistics.*;
import uk.ac.ox.krr.logmap2.utilities.Utilities;

/**
 * 
 * This class extracts the anchors by intersecting the lexical inverted files
 * associated with the respective ontologies. It will also manage the discovery of
 * further mappings
 *
 * @author Ernesto Jimenez-Ruiz
 * Created: Dec 13, 2011
 *
 */
public class CandidateMappingManager extends MappingManager {

	
	private OntologyProcessing onto_process1;
	private OntologyProcessing onto_process2;
	
	private Set<Set<String>> if_exact_intersection;
	private Set<Set<String>> if_stemming_intersection;
	private Set<Set<String>> if_weak_intersection;

	private Set<Set<String>> if_exact_intersection4data_prop;
	
	private Set<Set<String>> if_exact_intersection4obj_prop;
	
	private Set<Set<String>> if_exact_intersection4individuals;	
	private Set<String> if_weak_intersection4individuals;
	private Set<String> if_roleassertions_intersection4individuals;
	
	private Set<MappingObjectIdentifiers> input_mappings = new HashSet<MappingObjectIdentifiers>();
	
	private int IF_VALIDATED=0;
	private int IF_EXACT=1;
	private int IF_STEMMING=2;
	private int IF_WEAK=3;
	
	
	//Statistics: which mappings should be required to ask to the user
	/*private int include=0;
	private int exclude=0;
	private int ask=0;
	
	private int include_good=0;
	private int exclude_good=0;
	private int ask_good=0;*/
	
	/**
	 * 
	 * @param index
	 * @param onto_process1
	 * @param onto_process2
	 */
	public CandidateMappingManager(
			IndexManager index, 
			OntologyProcessing onto_process1, 
			OntologyProcessing onto_process2){
		
		this.index=index;
		this.onto_process1=onto_process1;
		this.onto_process2=onto_process2;
		
	}
	
	
	
	public void clearIntersectedInvertedFilesExact(){
		if_exact_intersection.clear();
		
	}

	
	public void clearIntersectedInvertedFilesStemmingAndWeak(){
		if_stemming_intersection.clear();
		if_weak_intersection.clear();
	}
	
	
	public void clearIntersectedInvertedFiles4Properties(){
		if_exact_intersection4data_prop.clear();
		if_exact_intersection4obj_prop.clear();
		
	}
	
	
	
	/**
	 * Intersects exact and stemming IFs, extract IF weak and intersects them
	 */
	public void intersectInvertedFiles(){
		
		//INTERSECTION
		
		//DATA PROP IF
		if_exact_intersection4data_prop = onto_process1.getInvertedFileExactMatching4DataProp().keySet();
		if_exact_intersection4data_prop.retainAll(onto_process2.getInvertedFileExactMatching4DataProp().keySet());
		onto_process2.getInvertedFileExactMatching4DataProp().keySet().retainAll(if_exact_intersection4data_prop);
		
		//OBJ PROP IF
		if_exact_intersection4obj_prop = onto_process1.getInvertedFileExactMatching4ObjProp().keySet();
		if_exact_intersection4obj_prop.retainAll(onto_process2.getInvertedFileExactMatching4ObjProp().keySet());
		onto_process2.getInvertedFileExactMatching4ObjProp().keySet().retainAll(if_exact_intersection4obj_prop);
		
		
		//INDIVIDUALS IF exact
		if_exact_intersection4individuals = onto_process1.getInvertedFileMatching4Individuals().keySet();
		if_exact_intersection4individuals.retainAll(onto_process2.getInvertedFileMatching4Individuals().keySet());
		onto_process2.getInvertedFileMatching4Individuals().keySet().retainAll(if_exact_intersection4individuals);
		
		
		//INDIVIDUALS IF weak
		if_weak_intersection4individuals = onto_process1.getInvertedFileWeakMatching4Individuals().keySet();
		if_weak_intersection4individuals.retainAll(onto_process2.getInvertedFileWeakMatching4Individuals().keySet());
		onto_process2.getInvertedFileWeakMatching4Individuals().keySet().retainAll(if_weak_intersection4individuals);
		
		
		//INDIVIDUALS IF role assertions
		if_roleassertions_intersection4individuals = onto_process1.getInvertedFileRoleAssertions().keySet();
		if_roleassertions_intersection4individuals.retainAll(onto_process2.getInvertedFileRoleAssertions().keySet());
		onto_process2.getInvertedFileRoleAssertions().keySet().retainAll(if_roleassertions_intersection4individuals);
				
		
		
		
		
		
		
		
		
		
		Map<Set<String>,Set<Integer>> if_difference1;
		Map<Set<String>,Set<Integer>> if_difference2;
		
		
		//INT EXACT
		
		LogOutput.print("IF Exact 1: " + onto_process1.getInvertedFileExactMatching().size());
		LogOutput.print("IF Exact 2: " + onto_process2.getInvertedFileExactMatching().size());
		//We perform intersection an we only keep in inverted file the intersected elements
		if_exact_intersection = onto_process1.getInvertedFileExactMatching().keySet();
		if_exact_intersection.retainAll(onto_process2.getInvertedFileExactMatching().keySet());
		onto_process2.getInvertedFileExactMatching().keySet().retainAll(if_exact_intersection);
		
		LogOutput.print("Intersection IF Exact: " + if_exact_intersection.size());
		
		
		
		//WEAK STEMMING
		LogOutput.print("IF Stemming 1: " + onto_process1.getInvertedFileWeakLabelsStemming().size());
		LogOutput.print("IF Stemming 2: " + onto_process2.getInvertedFileWeakLabelsStemming().size());
		
		if_stemming_intersection = new HashSet<Set<String>>(onto_process1.getInvertedFileWeakLabelsStemming().keySet());
		if_stemming_intersection.retainAll(onto_process2.getInvertedFileWeakLabelsStemming().keySet());
		
		
		LogOutput.print("Intersection IF Stemming: " + if_stemming_intersection.size());
		
		
		//NOT MATCHED IN IF STEMMING -> TO WEAK ENTRIES
		if_difference1  = new HashMap<Set<String>,Set<Integer>>(onto_process1.getInvertedFileWeakLabelsStemming());
		//Reduce IF
		onto_process1.getInvertedFileWeakLabelsStemming().keySet().retainAll(if_stemming_intersection);
		if_difference1.keySet().removeAll(if_stemming_intersection);
		onto_process1.addEntries2InvertedFileWeakLabels(if_difference1);
		if_difference1.clear();
		LogOutput.print("Entries in Weak IF from Setemming: " + onto_process1.getInvertedFileWeakLabels().size());
		
		
		if_difference2  = new HashMap<Set<String>,Set<Integer>>(onto_process2.getInvertedFileWeakLabelsStemming());
		//Reduce IF
		onto_process2.getInvertedFileWeakLabelsStemming().keySet().retainAll(if_stemming_intersection);
		if_difference2.keySet().removeAll(if_stemming_intersection);
		onto_process2.addEntries2InvertedFileWeakLabels(if_difference2);
		if_difference2.clear();
		LogOutput.print("Entries in Weak IF from Setemming: " + onto_process2.getInvertedFileWeakLabels().size());
		
		
		//Extract weak mappings
		//onto_process1.setFullInvertedFileWeakLabels();
		//onto_process2.setFullInvertedFileWeakLabels();
		onto_process1.setInvertedFileWeakLabels();
		onto_process2.setInvertedFileWeakLabels();
		
		LogOutput.print("IF Weak 1: " + onto_process1.getInvertedFileWeakLabels().size());
		LogOutput.print("IF Weak 2: " + onto_process2.getInvertedFileWeakLabels().size());
		
		
		//We perform intersection an we only keep in inverted file the intersected elements
		if_weak_intersection = onto_process1.getInvertedFileWeakLabels().keySet();
		if_weak_intersection.retainAll(onto_process2.getInvertedFileWeakLabels().keySet());
		onto_process2.getInvertedFileWeakLabels().keySet().retainAll(if_weak_intersection);
		
		LogOutput.print("Intersection IF Weak: " + if_weak_intersection.size());
		
		
		
		
		
	}
	
	
	
	
	/**
	 * This method extract all (weak) mappings. This set will only be used for scope purposes  
	 */
	public void extractAllWeakMappings() {
		
		//if (true)
		//return;
		
		for (Set<String> set_str : if_exact_intersection){			
			for (int ide1 : onto_process1.getInvertedFileExactMatching().get(set_str)){
				for (int ide2 : onto_process2.getInvertedFileExactMatching().get(set_str)){
					addEquivMapping2ListOfWeakAnchors(ide1, ide2);
				}
			}
		}
		
		if (Parameters.use_stemming) {
			for (Set<String> set_str : if_stemming_intersection){
				for (int ide1 : onto_process1.getInvertedFileWeakLabelsStemming().get(set_str)){
					for (int ide2 : onto_process2.getInvertedFileWeakLabelsStemming().get(set_str)){
						addEquivMapping2ListOfWeakAnchors(ide1, ide2);
					}
				}
			}
		}
		
		for (Set<String> set_str : if_weak_intersection)
			for (int ide1 : onto_process1.getInvertedFileWeakLabels().get(set_str)) 
				for (int ide2 : onto_process2.getInvertedFileWeakLabels().get(set_str))
					addEquivMapping2ListOfWeakAnchors(ide1, ide2);
		
		
		
		
		
		//Count all weak anchors
		int weak_anchors=0;
		for (int ide1 : allWeakMappings1N.keySet()){
			weak_anchors+=allWeakMappings1N.get(ide1).size();
		}
		LogOutput.print("WEAK ANCHORS: " + weak_anchors);
		
		
		
		
	}
	
	
	
	
	public void extractCandidatesSubsetFromWeakMappings(){
		
		extractSubsetFromWeakMapping();
		extractSubsetFromWeakMappingFrequency();
		
		//Clear structures
		//Clear weak
		onto_process1.clearInvertedFileWeak();
		onto_process2.clearInvertedFileWeak();
		if_weak_intersection.clear();
		
		
		
	}
	
	

	public void createAnchors() {
		createAnchors(false);
	}
	
	
	
	@Override
	public void createAnchors(boolean are_input_mapping_validated) {
		
		try {
			
			//From input mappings (e.g. composed mappings given as input)
			createCandidatesFromInputMappings(are_input_mapping_validated);
			
			//Inverted file intersection
			createCandidatesFromExactIF();
			
			
			//Dataprop and ObjectProp. Currently is at the end of the process
			
			
			
			//Clear
			//Clear Exact IF
			onto_process1.clearInvertedFilesExact();
			onto_process2.clearInvertedFilesExact();
			
			clearIntersectedInvertedFilesExact();
			//clearIntersectedInvertedFiles4Properties();
			
			
		}
		catch (Exception e){
			System.err.println("Error extracting anchors: " + e.getMessage());
			e.printStackTrace();
		}
		
	}
	
	
	
	/*public void createCandidatesFromBackgroundKnowledge() throws Exception{
		
		
		Map<String, Set<String>> map = ManageBackgroundKnowledge.createComposedMappingsMouse2Uberon2NCI();
		
		int mouse_id = -1;
		int nci_id = -1;
		
		for (String mouse_iri : map.keySet()){
			
			mouse_id = onto_process1.getIdentifier4ConceptName(Utilities.getEntityLabelFromURI(mouse_iri));
			
			for (String nci_iri : map.get(mouse_iri)){
			
				nci_id = onto_process2.getIdentifier4ConceptName(Utilities.getEntityLabelFromURI(nci_iri));
				
				if (mouse_id>=0 && nci_id>=0){
					
					//We will see
					//evaluateCandidateMapping(mouse_id, nci_id, IF_EXACT);
					
					//We do not need to filter by isub in exact cases
					//With scope, no ambiguous or best confidence
					addSubMapping2ListOfAnchors(mouse_id, nci_id);
					addSubMapping2ListOfAnchors(nci_id, mouse_id);
					
					//we add confidences
					addIsub2Structure(mouse_id, nci_id, 1.0);
					addIsub2Structure(nci_id, mouse_id, 1.0);
					
					addIsubAverage2Structure(mouse_id, nci_id, 1.0);
					addIsubAverage2Structure(nci_id, mouse_id, 1.0);
					
					addScopeAll2Structure(mouse_id, nci_id, 1.0);
					addScopeAll2Structure(nci_id, mouse_id, 1.0); //we add both sides
					
				}
				
			}
			
		}
		
		
		
		
		map.clear();
		ManageBackgroundKnowledge.clearStructures();
		
	}*/
	
	
	
	/**
	 * We will increase the number of anchors and create the set of mappings 2 ask
	 */
	public void createCandidates() {
		
		try {
			//Inverted file intersection
			LogOutput.print("assessAnchors2Review()");
			assessAnchors2Review(); //Mappings from IF exact to assess
			
			//Stemmming extraction
			LogOutput.print("createCandidates4StemmingLikeAnchors()");
			createCandidates4StemmingLikeAnchors();
			//clear
			onto_process1.clearInvertedFileStemming();
			onto_process2.clearInvertedFileStemming();
			if_stemming_intersection.clear();
			
			
			
			//Deprecated EXPANSION from LogMap 1
			//createAnchorsExpansion(); //Not good results (does not improves what extracted by weak mappings)
			
			//Extracts/assess weak mappings
			LogOutput.print("createCandidates4WeakAnchors()");
			createCandidates4WeakAnchors();
			
			//We remove the set of week candidate mappings: already in correspondent sets
			//clearWeakCandidateAnchors();
			weakCandidateMappings1N.clear();
			
			
			//Clear intersected IF
			//clearIntersectedInvertedFilesStemmingAndWeak();
			
			//Characterise/reduce mappings to ask. Some of them will automatically be included within anchors and others will be discarded
			LogOutput.print("createMappings2AskUser()");
			createMappings2AskUser();
			
			
			
			
			
		}
		catch (Exception e){
			System.err.println("Error extracting anchors: " + e.getMessage());
			e.printStackTrace();
		}
		
	}

	
	
	public void processInputMappings(Set<MappingObjectStr> mappings) {
		
		for (MappingObjectStr mapping : mappings){
			
			if (mapping.isClassMapping()){
				
				int ide1 = onto_process1.getIdentifier4ConceptIRI(mapping.getIRIStrEnt1());
				int ide2 = onto_process2.getIdentifier4ConceptIRI(mapping.getIRIStrEnt2());
				
				if (ide1>=0 && ide2>=0){
					input_mappings.add(
							new MappingObjectIdentifiers(
									onto_process1.getIdentifier4ConceptIRI(mapping.getIRIStrEnt1()),
									onto_process2.getIdentifier4ConceptIRI(mapping.getIRIStrEnt2()))
							);
				}
				else
					System.err.println("Mapping with no direct correspondence to ids: " + mapping);
			}
		}	
	}

	
	
	
	/**
	 * Create candidates from input mappings (e.g. )
	 */
	private void createCandidatesFromInputMappings(boolean are_input_mapping_validated) throws Exception {
	
		//int candidates=0;
		
		for (MappingObjectIdentifiers mapping : input_mappings){

			if (onto_process1.getDangerousClasses().contains(mapping.getIdentifierOnto1()) ||
				onto_process2.getDangerousClasses().contains(mapping.getIdentifierOnto2()))
				continue;
		
			if (are_input_mapping_validated)
				evaluateCandidateMapping(mapping.getIdentifierOnto1(), mapping.getIdentifierOnto2(), IF_VALIDATED);
			else
				evaluateCandidateMapping(mapping.getIdentifierOnto1(), mapping.getIdentifierOnto2(), IF_EXACT);
			
		}
		
		
		
		
		
	}
	
	

	
	
	
	
	/**
	 * Processes the intersected 'exact' inverted files and extract anchors.
	 * When ambiguity filter by isub and scope
	 */
	private void createCandidatesFromExactIF() throws Exception {
	
		int candidates=0;
		
		
		/*We need to remove ambiguity*/		
		for (Set<String> set_str : if_exact_intersection){
			
			if (set_str.isEmpty()){
				LogOutput.print("EMPTY SET IN EXACT IF: " + onto_process1.getInvertedFileExactMatching().get(set_str).size() + " - " +  + onto_process2.getInvertedFileExactMatching().get(set_str).size());
				continue;
			}
			
			
			for (int ide1 : onto_process1.getInvertedFileExactMatching().get(set_str)){
				
				if (onto_process1.getDangerousClasses().contains(ide1))
					continue;
			
				for (int ide2 : onto_process2.getInvertedFileExactMatching().get(set_str)){
					
					if (onto_process2.getDangerousClasses().contains(ide2))
						continue;
					
					//Decides if mappings should be considered
					//Checks ambiguity and scope
					evaluateCandidateMapping(ide1, ide2, IF_EXACT);
					candidates++;
					
				}
			}
		}
		
		
		//printStatisticsMappingEvaluation();
		//LogOutput.print("Candidates EXACT: " + candidates);
		
		
		
		
	}
	
	
	/**
	 * Evaluates mapping confidence and decides if mappings should be included or must be treated later (e.g.
	 * ambiguity cases and mappings without scope)
	 * @param ide1
	 * @param ide2
	 * @param origin
	 */
	private void evaluateCandidateMapping(int ide1, int ide2, int origin){
		
		
		if (origin==IF_VALIDATED){
			evaluateCandidateMappingIFValidated(ide1, ide2);
		}		
		else if (origin==IF_EXACT){
			evaluateCandidateMappingIFExact(ide1, ide2);
		}
		else if (origin==IF_STEMMING){
			evaluateCandidateMappingIFStemming(ide1, ide2);
		}
		else if (origin==IF_WEAK){
			evaluateCandidateMappingIFWeak(ide1, ide2);
		}
		
	}
	
	
	/**
	 * Evaluation of mappings coming from a validated input
	 * @param ide1
	 * @param ide2
	 */
	private void evaluateCandidateMappingIFValidated(int ide1, int ide2){
		
		
		//Already considered
		if (isMappingAlreadyConsidered(ide1, ide2))
			return;
		
		//Statistics All
		StatisticsManager.addStatisticsMappingsAll(ide1, ide2);
		
		//We extract and store
		extractISUB4Mapping(ide1, ide2);
		extractISUBAverage4Mapping(ide1, ide2);
						
		extractScopeAll4Mapping(ide1, ide2);
		
		getConfidence4Mapping(ide1, ide2); //isub+scope

		
		//We do not need to filter by isub in exact cases
		//With scope, no ambiguous or best confidence
		addSubMapping2ListOfAnchors(ide1, ide2);
		addSubMapping2ListOfAnchors(ide2, ide1);
		
		
	}
	
	
	/**
	 * Evaluation of mappings coming from exact IF
	 * @param ide1
	 * @param ide2
	 */
	private void evaluateCandidateMappingIFExact(int ide1, int ide2){
		
		
		double scoreScope;
		double scoreISUB;
		double scoreISUB_avg;
		
		double conf;
		
		
		//Already considered
		if (isMappingAlreadyConsidered(ide1, ide2))
			return;
		
		//Statistics Mall
		StatisticsManager.addStatisticsMappingsAll(ide1, ide2);
		
		
		
		//We extract and store
		scoreISUB = extractISUB4Mapping(ide1, ide2);
		scoreISUB_avg = extractISUBAverage4Mapping(ide1, ide2);
						
		scoreScope = extractScopeAll4Mapping(ide1, ide2);
		
		conf = getConfidence4Mapping(ide1, ide2); //isub+scope
		
		
		if (scoreISUB<Parameters.good_isub_anchors || scoreISUB_avg<0.35 || scoreScope<=Parameters.bad_score_scope){
			addSubMapping2Mappings2Review(ide1, ide2);//only one side, at this stage we consider in this set equivalent mappings
			return;
		}
		
		
		int ide1a;
		int ide2a;
		
		double conf1;
		double conf2;
		
		
		boolean ambiguous=false;
		
		
		//SCOPE and ISUB>=0.95
		//Ambiguity: cases with scope that are already in exact mappings
		//At this stage we will only allow mappings 1:1
		if (isEntityAlreadyMapped(ide1) && isEntityAlreadyMapped(ide2)){
			//compare cases (3 cases)
			///ide1-ide2a
			//ide1a-ide2
			//ide1=ide2
			
			ide2a = getTargetEntity4Index(ide1);
			ide1a = getTargetEntity4Index(ide2);
			conf1 = getConfidence4Mapping(ide1, ide2a);
			conf2 = getConfidence4Mapping(ide1a, ide2);

			//substitute only if better than both two
			if (conf > conf1 && conf > conf2){

				moveMapping2ReviewList(ide1, ide2a);
				moveMapping2ReviewList(ide1a, ide2);
				
				//we add mapping to list in the end			
			}			
			else{ //Ambiguous
				ambiguous=true;
			}
			
		}
		else if (isEntityAlreadyMapped(ide1)){
		
			//If better confidence then substitute (add loser to ambiguity)
			ide2a = getTargetEntity4Index(ide1);
			conf1 = getConfidence4Mapping(ide1, ide2a);
			
			if (conf>conf1){				
				moveMapping2ReviewList(ide1, ide2a);									
			}
			else { //Ambiguous
				ambiguous=true;	
			}
			
			
		}
		else if (isEntityAlreadyMapped(ide2)){
			
			//If better confidence then substitute (add loser to ambiguity)
			ide1a = getTargetEntity4Index(ide2);
			conf1 = getConfidence4Mapping(ide1a, ide2);
			
			if (conf>conf1){				
				moveMapping2ReviewList(ide1a, ide2);				
			}
			else { //Ambiguous
				ambiguous=true;				
			}
		}
		
		
		if (ambiguous){
			addSubMapping2Mappings2Review(ide1, ide2);
			return;
		}
		
		
		
		//We do not need to filter by isub in exact cases
		//With scope, no ambiguous or best confidence
		addSubMapping2ListOfAnchors(ide1, ide2);
		addSubMapping2ListOfAnchors(ide2, ide1);
		
	}
	
	
	

	
	
	
	

	
	
	
	/**
	 * Mappings coming from exact IF. We evaluate wrt fixed mappings
	 */
	private void assessAnchors2Review(){
		
		
		//Mappings to review and 
		/*for (int ide1 : weakenedDandG_Mappings1N.keySet()){
			
			for (int ide2 : weakenedDandG_Mappings1N.get(ide1)){
				
				if (!isMappingInferred(ide1, ide2)){
					
					//Add in exact
					addSubMapping2ListOfAnchors(ide1, ide2);
					
				}
			}
		}
		
		//We remove those mappings that are already inferred
		weakenedDandG_Mappings1N.clear();*/
		
		
		//Deleted with D&G
		//We try to recover some of them (we give the another chance)
		//Preliminary tests: it seem there is not impact on that
		//Note that we may check them again as a weak mapping
		/*for (int ide1 : getDircardedAnchors().keySet()){
			for (int ide2 : getDircardedAnchors().get(ide1)){
				
				if (isId1SmallerThanId2(ide1, ide2)){
					addSubMapping2Mappings2Review(ide1, ide2);
				}
				else{
					addSubMapping2Mappings2Review(ide2, ide1);
				}		
			}
		}*/
		
		
		
		for (int ide1 : mappings2Review.keySet()){
			for (int ide2 : mappings2Review.get(ide1)){
				
				if (!isId1SmallerThanId2(ide1, ide2))
					continue; //JUST IN CASE
				
				evaluateAnchor2Review(ide1, ide2);
				
			}
		}
		
		mappings2Review.clear();
		
		
		
	}
	
	
	
	private void evaluateAnchor2Review(int ide1, int ide2){
		
		
		//if (isMappingInAnchors(ide1, ide2))
		//	return;
		
		if (isMappingInConflictWithFixedMappings(ide1, ide2)){
			addSubMapping2ConflictiveAnchors(ide1, ide2);
			addSubMapping2ConflictiveAnchors(ide2, ide1);
			return;
		}
		
		if (isMappingDangerousEquiv(ide1, ide2)){
			addEquivMapping2HardDiscardedAnchors(ide1, ide2);
			isHardMappingInGS(ide1, ide2, 1);// tmp method
			return;
		}
		
		//Already extracted
		//double scoreISUB = extractISUB4Mapping(ide1, ide2);
		//double scoreISUB_avg = extractISUBAverage4Mapping(ide1, ide2);
		
		//Scope with only anchors: for future check
		extractScopeAnchors4Mapping(ide1, ide2);
		
		double scoreScope = extractScopeAll4Mapping(ide1, ide2);
		
		
		//Discard if no scope and ambiguity
		if (scoreScope<=Parameters.bad_score_scope && (isEntityAlreadyMapped(ide1) || isEntityAlreadyMapped(ide2))){// && scoreISUB_avg<0.9
			
			addEquivMapping2HardDiscardedAnchors(ide1, ide2); //No scope and ambiguous
			isHardMappingInGS(ide1, ide2, 2);//TODO tmp method
			return;
		}
		
		//Minimum ISUB... as before....
		//Only ambiguity -> ask
		//No scope ->ask
		
		
		//Always ask otherwise
		addMapping2ListOfAnchors2AskLogMap(ide1, ide2);
		
		
		
	}
	
	
	
	
	

	
	
	
	/**
	 * Created candidates for anchors using a stemmed lexicon.
	 */
	private void createCandidates4StemmingLikeAnchors() throws Exception{
		
		int candidates=0;
		int ambiguity, size1, size2;
		
		//System.out.println(if_stemming_intersection.size());
		//System.out.println(onto_process1.getInvertedFileWeakLabelsStemming().values().size());
		//System.out.println(onto_process2.getInvertedFileWeakLabelsStemming().values().size());
		
		
		for (Set<String> set_str : if_stemming_intersection){
			
			
			if (set_str.isEmpty()){
				LogOutput.print("EMPTY SET IN STEMMING IF: " + onto_process1.getInvertedFileWeakLabelsStemming().get(set_str).size() + " - " +  + onto_process2.getInvertedFileWeakLabelsStemming().get(set_str).size());
				continue;
			}
			
			size1=onto_process1.getInvertedFileWeakLabelsStemming().get(set_str).size();
			size2=onto_process2.getInvertedFileWeakLabelsStemming().get(set_str).size();
			
			
			
			//Only Low amabiguity
			ambiguity=size1*size2;
			if (ambiguity>=7 || size1>=4 || size2>=4){//Max cases 3*2  (for FMA-NCI-SNOMED)
			//if (ambiguity>=13 && size1>=5 && size2>=5){//Max cases 3*2 (Mosue?)
				
				if (ambiguity>20)
					LogOutput.print("High ambiguity stemming: "+ ambiguity);
				
				continue;
			}
			
			
			//System.out.println(onto_process1.getInvertedFileWeakLabelsStemming().get(set_str).size());
			//System.out.println(onto_process2.getInvertedFileWeakLabelsStemming().get(set_str).size());
			//System.out.println();
			
			for (int ide1 : onto_process1.getInvertedFileWeakLabelsStemming().get(set_str)){							
				
				if (onto_process1.getDangerousClasses().contains(ide1))
					continue;
				
				for (int ide2 : onto_process2.getInvertedFileWeakLabelsStemming().get(set_str)){
					
					if (onto_process2.getDangerousClasses().contains(ide2))
						continue;
					
					//Decides if mappings should be considered
					//Checks ambiguity and scope
					evaluateCandidateMapping(ide1, ide2, IF_STEMMING);
					candidates++;
				}
			}
			
		}
		
		
		//printStatisticsMappingEvaluation();
		LogOutput.print("Candidates STEMING: " + candidates);
		
	
		
	}
	
	
	
	
	/**
	 * Evaluation of mappings coming from stemming IF
	 * 
	 * @param ide1
	 * @param ide2
	 */
	private void evaluateCandidateMappingIFStemming(int ide1, int ide2){
		
		double scoreScope;
		double scoreISUB;
		double confidence;
		
		//Already in list or discarded
		if (isMappingAlreadyConsidered(ide1, ide2))
			return;
		
		//Statistics Mall
		StatisticsManager.addStatisticsMappingsAll(ide1, ide2);
		
		
		if (isMappingInConflictWithFixedMappings(ide1, ide2)){
			addSubMapping2ConflictiveAnchors(ide1, ide2);
			addSubMapping2ConflictiveAnchors(ide2, ide1);
			return;
		}
		
		
		
		
		if (isMappingDangerousEquiv(ide1, ide2)){
			addEquivMapping2HardDiscardedAnchors(ide1, ide2);
			isHardMappingInGS(ide1, ide2, 1);// tmp method
			return;
		}
		
		//Ambiguity->discard! with current anchors
		if (isEntityAlreadyMapped(ide1) || isEntityAlreadyMapped(ide2)){
			addEquivMapping2HardDiscardedAnchors(ide1, ide2);
			isHardMappingInGS(ide1, ide2, 2);// tmp method
			return;
		}
		
		//Scope with only anchors: for future check
		extractScopeAnchors4Mapping(ide1, ide2);
		
		scoreScope = extractScopeAll4Mapping(ide1, ide2);
		//We extract and store
		scoreISUB = extractISUB4Mapping(ide1, ide2);
		//if (scoreISUB<0.75)
		//			return; //do not consider...
		
		confidence = getConfidence4Mapping(ide1, ide2);
		
		if (scoreScope<=Parameters.bad_score_scope || scoreISUB<Parameters.good_isub_candidates) {
			
			//For mouse anatomy
			if (scoreISUB>0.70 && confidence>0.45){
				addEquivMapping2DiscardedAnchors(ide1, ide2);
			}
			else{
				addEquivMapping2HardDiscardedAnchors(ide1, ide2);
				isHardMappingInGS(ide1, ide2, 3);// tmp method
				//if (.isMappingInGoldStandard(ide1, ide2))
				//	System.out.println();
			}
			return;
		}
		
		
	
		addMapping2ListOfAnchors2AskLogMap(ide1, ide2);
		
		
		
		
	}
	
	
	/**
	 * Evaluation of mappings coming from expansion
	 * 
	 * @param ide1
	 * @param ide2
	 * @deprecated Not used
	 */
	private boolean evaluateCandidateMappingExpansion(int ide1, int ide2){
		
		double scoreISUB;

		
		//Already in list or discarded
		if (isMappingAlreadyConsidered(ide1, ide2))
			return false;
		
		
		scoreISUB = extractISUB4Mapping(ide1, ide2);
		if (scoreISUB<0.95)//do not consider
			return false;
		
		
		//Cases Isub > 0.95
		
		if (isMappingInConflictWithFixedMappings(ide1, ide2)){
			addSubMapping2ConflictiveAnchors(ide1, ide2);
			addSubMapping2ConflictiveAnchors(ide2, ide1);
			return false;
		}
		
		if (isMappingDangerousEquiv(ide1, ide2)){
			addEquivMapping2HardDiscardedAnchors(ide1, ide2);
			return false;
		}
		
		//Ambiguity->discard!
		if (isEntityAlreadyMapped(ide1) || isEntityAlreadyMapped(ide2) || scoreISUB<0.98){
			//addEquivMapping2HardDiscardedAnchors(ide1, ide2); //to avoid many discards
			return false;
		}
		
		//>0.98
		addMapping2ListOfAnchors2AskLogMap(ide1, ide2);
		return true;
		
		
		
		
	}
	
	

	
	/**
	 * Creation of candidate mappings from weak anchors. called from main LogMap method
	 * 
	 */
	private void createCandidates4WeakAnchors(){
	
		
		//Now the set weakCandidateMappings1N is pre-extracted
		//extractSubsetFromWeakMapping();
		//extractSubsetFromWeakMappingFrequency();
		
		int candidates=0;
		
		//for (int ide1 : weakMappings1N.keySet()){
		for (int ide1 : weakCandidateMappings1N.keySet()){
			
			if (onto_process1.getDangerousClasses().contains(ide1))
				continue;
			
			//for (int ide2 : weakMappings1N.get(ide1)){
			for (int ide2 : weakCandidateMappings1N.get(ide1)){
				
				if (onto_process2.getDangerousClasses().contains(ide2))
					continue;
				
				if (!isId1SmallerThanId2(ide1, ide2))
					continue;
				
				
				
				evaluateCandidateMappingIFWeak(ide1, ide2);
				
				
				
				candidates++;
				
			}
			
		}
		
		//printStatisticsMappingEvaluation();
	//	LogOutput.print("Candidates WEAK: " + candidates);
		
		
		
	}
	
	
	
	private void evaluateCandidateMappingIFWeak(int ide1, int ide2){

		
		
		
		double scoreScopeAnc;
		double scoreScope;
		double scoreISUB;
		double confidence;
		
		//Only if the mapping is already in list of anchors or in list to ask logmap
		if (isMappingAlreadyInList(ide1, ide2) || isMappingInAnchors2AskLogMap(ide1, ide2) || isMappingInConflictiveSet(ide1, ide2)){
			return;
		}
		
		//Already in list or discarded (but not weak yujiao, we give another chance)
		//Probably not necessary anymore
		if (isMappingAlreadyConsidered(ide1, ide2) && !hasWeakMappingSim(ide1, ide2))
			return;
		
		if (!isMappingAlreadyConsidered(ide1, ide2)){
			
			//Statistics Mall
			StatisticsManager.addStatisticsMappingsAll(ide1, ide2);
			
		}
		
		
		
		
		if (isMappingInConflictWithFixedMappings(ide1, ide2)){
			addSubMapping2ConflictiveAnchors(ide1, ide2);
			addSubMapping2ConflictiveAnchors(ide2, ide1);
			return;
		}
		
		
		
		//Do not consider?
		if (isMappingDangerousEquiv(ide1, ide2)){
			addEquivMapping2HardDiscardedAnchors(ide1, ide2);
			isHardMappingInGS(ide1, ide2, 1);// tmp method
			return;
		}
		
		//Ambiguity->discard! with anchors then no consider
		if (isEntityAlreadyMapped(ide1) || isEntityAlreadyMapped(ide2)){ //no anchor
			addEquivMapping2HardDiscardedAnchors(ide1, ide2);
			isHardMappingInGS(ide1, ide2, 2);// tmp method
			return;
		}
		
		
		
		
		
		
		scoreScope = extractScopeAll4Mapping(ide1, ide2);
		//We extract and store
		scoreISUB = extractISUB4Mapping(ide1, ide2);
		
		confidence = getConfidence4Mapping(ide1, ide2);
		
		//Scope with only anchors: for future check
		scoreScopeAnc = extractScopeAnchors4Mapping(ide1, ide2);
		
		
		if (!hasWeakMappingSim(ide1, ide2)){
		
			if (scoreISUB<Parameters.good_isub_candidates && scoreScope<=Parameters.bad_score_scope){
				//Must be hard discarded always
				addEquivMapping2HardDiscardedAnchors(ide1, ide2);
				//isHardMappingInGS(ide1, ide2, 3);//TODO tmp method
				return;
			}
			
			
			if (scoreISUB<Parameters.good_isub_candidates) {
				//if (scoreISUB<0.70 && scoreScope<=0.01)
				//	return;
				
				//For mouse anatomy
				if (scoreISUB>0.83 && confidence>0.45){
					addEquivMapping2DiscardedAnchors(ide1, ide2);
				}
				else{
					//Must be hard discarded always
					addEquivMapping2HardDiscardedAnchors(ide1, ide2);
					//isHardMappingInGS(ide1, ide2, 3);// tmp method
				}
				
				return;
			}
			
			addMapping2ListOfAnchors2AskLogMap(ide1, ide2);
		}
		else{
			
						
			if (scoreISUB>=Parameters.good_isub_candidates && scoreScope>Parameters.bad_score_scope){

				//System.out.println("1");
				
				addMapping2ListOfAnchors2AskLogMap(ide1, ide2);
				return;
			}
			
			if (getSimWeak4Mapping2(ide1, ide2)>=Parameters.good_sim_coocurrence && scoreScope>Parameters.bad_score_scope){
				addMapping2ListOfAnchors2AskLogMap(ide1, ide2);
				//LogOutput.print("Mapping " + ide1 + "=" + ide2 + ", sim: " + getSimWeak4Mapping2(ide1, ide2) + ", scope: " + scoreScope);
				//LogOutput.print("\tASK");
				
				//System.out.println("2");
				
				
				return;
			}
			
			
			if (scoreISUB<0.65){
				//Always
				addEquivMapping2HardDiscardedAnchors(ide1, ide2);
				
				/*if (index.getIRIStr4ConceptIndex(ide1).equals("http://bioontology.org/projects/ontologies/fma/fmaOwlDlComponent_2_0#Stromal_cell")
						|| index.getIRIStr4ConceptIndex(ide2).equals("http://ncicb.nci.nih.gov/xml/owl/EVS/Thesaurus.owl#Stromal_Neoplasm")){
						System.out.println("3");
						System.out.println(index.getIRIStr4ConceptIndex(ide1) + " " + index.getIRIStr4ConceptIndex(ide2) + "  WEAK");
				}*/
				
				
				return;
			}
			
			
			//if (confidence>0.40 && getSimWeak4Mapping2(ide1, ide2)>=0.05 && scoreScope>0.0){
			//if (scoreISUB>0.83 && confidence>0.45 && scoreScope>0.0){ //Best results 112/167
			if (scoreISUB>0.89 || (scoreISUB > 0.80 && confidence>Parameters.good_confidence && scoreScope>Parameters.bad_score_scope) || (confidence>0.80)){
			//if (getSimWeak4Mapping(ide1, ide2)>=0.05){
				
				//System.out.println("4");
				
				addEquivMapping2DiscardedAnchors(ide1, ide2);
