All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.metacsp.fuzzyAllenInterval.FuzzyAllenIntervalNetworkSolver Maven / Gradle / Ivy

There is a newer version: 1.3.5
Show newest version
/*******************************************************************************
 * Copyright (c) 2010-2013 Federico Pecora 
 * 
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 ******************************************************************************/
package org.metacsp.fuzzyAllenInterval;

import java.util.Collections;
import java.util.HashMap;
import java.util.Vector;

import org.metacsp.framework.Constraint;
import org.metacsp.framework.ConstraintNetwork;
import org.metacsp.framework.ConstraintSolver;
import org.metacsp.framework.Domain;
import org.metacsp.framework.ValueChoiceFunction;
import org.metacsp.framework.Variable;
import org.metacsp.multi.fuzzyActivity.FuzzyActivity;
import org.metacsp.time.qualitative.SimpleAllenInterval;
import org.metacsp.time.qualitative.SimpleInterval;


/**
 * This {@link ConstraintSolver} implements a fuzzified version of Allen's path consistency 
 * algorithm, as well as search procedure to extract the optimal solution of a fuzzy temporal
 * CSP.
 * 
 * @author Masoumeh Mansouri
 *
 */
public class FuzzyAllenIntervalNetworkSolver extends ConstraintSolver {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1499386815980553133L;
	private int IDs = 0;
	private double globalPossibilityDegree = 0.0;
	private Vector subs = new Vector();
	private int numVars = 0;
	private Vector subVariables = new Vector();
	private boolean isSubGraph = false;
	private HashMap varIndex = new HashMap();
	private Constraint[] crispCons = null;
	
	/**
	 * Creates a new {@link FuzzyAllenIntervalNetworkSolver}.
	 */
	public FuzzyAllenIntervalNetworkSolver() {
		super(new Class[]{FuzzyAllenIntervalConstraint.class}, SimpleAllenInterval.class);
		this.setOptions(OPTIONS.AUTO_PROPAGATE);
	}

	@Override
	protected boolean addConstraintsSub(Constraint[] c) {
		return true;
	}

	@Override
	protected Variable[] createVariablesSub(int num) {
		SimpleAllenInterval[] ret = new SimpleAllenInterval[num];
		for (int i = 0; i < num; i++) {
			ret[i] = new SimpleAllenInterval(this, IDs++);
		}
		return ret;
	}
	
	/**
	 * Get the upper bound of the possibility degree of this solver's {@link ConstraintNetwork}. 
	 * @return The upper bound of the possibility degree of this solver's {@link ConstraintNetwork}.
	 */
	public double getPosibilityDegree() {
		return globalPossibilityDegree;
	}
	
	@Override
	public boolean propagate() {
		isSubGraph = false;
		Vector>> frelations = createFuzzyCompleteNetwork(this.getConstraints());
		frelations = simplify(frelations);
		
		//revise frelations w/ PC
		frelations = fuzzyPathConsistency(frelations);
		//update global possibility degree
		updateGlobalPossibilityDegree(frelations);
		return true;
	}

//	private HashMap movaghati(FuzzyAllenIntervalConstraint.Type type) { 
//		HashMap fr = new HashMap();
//		for (FuzzyAllenIntervalConstraint.Type t : FuzzyAllenIntervalConstraint.Type.values()) fr.put(t, 0.0);
//			for(int t = 0; t <  FuzzyAllenIntervalConstraint.freksa_neighbor[type.ordinal()].length; t++){
//				if (fr.get(FuzzyAllenIntervalConstraint.lookupTypeByInt(t)) != null) {
//					fr.put(FuzzyAllenIntervalConstraint.lookupTypeByInt(t), Math.max(fr.get(FuzzyAllenIntervalConstraint.lookupTypeByInt(t)), FuzzyAllenIntervalConstraint.getPossibilityDegree(FuzzyAllenIntervalConstraint.freksa_neighbor[type.ordinal()][t])));
//				}
//				else {
//					fr.put(FuzzyAllenIntervalConstraint.lookupTypeByInt(t), FuzzyAllenIntervalConstraint.getPossibilityDegree(FuzzyAllenIntervalConstraint.freksa_neighbor[type.ordinal()][t]));
//				}
//			}
//		return fr;
//	}
    
//	private String getFRelationsString(Vector>> frelations) {
//		String ret = "";
//		for(int i = 0; i < frelations.size(); i++){
//			for(int j = 0; j < frelations.size(); j++)
//			{
//				if(i == j) continue;
//				ret += (i + " --> " +  j + " :");
//				ret += (frelations.get(i).get(j) + "\n");
//			}
//		}
//		return ret;
//	}
	
	private boolean isInTheSubGraph(Variable varTmp) {	
		for (int i = 0; i < subs.size(); i++) {
			if(subs.get(i).getInternalVariables()[0].getID() == varTmp.getID()) return true;
		}
		return false;
	}

	private Constraint[] extractSubGraphCons(Constraint[] c) {
		
		if(!isSubGraph) return c;
 		Vector ctmp = new Vector();
		for (int i = 0; i < c.length; i++) {
			if(isInTheSubGraph(c[i].getScope()[0]) && isInTheSubGraph(c[i].getScope()[1])){
					ctmp.add(c[i]);
			}
		}
		Constraint[] ret = ctmp.toArray(new Constraint[ctmp.size()]);
		return ret;
	}

	//Return value contains possibilities of all 13 relations between all intervals 
	// -- each hashmap is the possibility degree of the relation (i,j), and
	// -- the i-th internal vector contains the relations between i and all other variables 
	private Vector>> createFuzzyCompleteNetwork(Constraint[] cns) {	
		
		if(subs != null){
			if(subs.size() > 0) 
				isSubGraph = true;
		}
		Constraint[] c = extractSubGraphCons(cns);
		
/*		if(isSubGraph){
			
			System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
			for (int i = 0; i < cns.length; i++) {
				System.out.println("cns: " + cns[i]);	
			}
			System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
			for (int i = 0; i < subs.size(); i++) {
				System.out.println("sb: " + subs.get(i));
			}
			System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
			for (int i = 0; i < c.length; i++) {
				System.out.println("c: " + c[i]);	
			}
		} //Iran
*/
		setNumVars(c);
		
		Vector>> frelations = new Vector>>();
		
		final class Coord {
			public int x, y;
			public Coord(int x, int y) { this.x = x; this.y = y; }
			public boolean equals(Object o) {
				if (!(o instanceof Coord)) return false;
				Coord oc = (Coord)o;
				return ((oc.x == x) && (oc.y == y));
			}
			public int hashCode() {
				return (x*31)^y;
			}
		}
		
		HashMap> multiple = new HashMap>();
		
		FuzzyAllenIntervalConstraint[][] tmp = new FuzzyAllenIntervalConstraint[getNumVars()][getNumVars()];
		
		int row = 0 , col = 0;
		for(int i = 0; i < c.length; i++){
			if(!isSubGraph){
				row = this.getID(c[i].getScope()[0]);
				col = this.getID(c[i].getScope()[1]);
			}
			else{
				row = (int)varIndex.get(c[i].getScope()[0].getID());
				col = (int)varIndex.get(c[i].getScope()[1].getID());
			}
			if (tmp[row][col] == null)
				tmp[row][col] = ((FuzzyAllenIntervalConstraint)c[i]);
			else {
				Coord coord = new Coord(row,col);
				Vector vec = multiple.get(coord);
				if (vec == null) {
					vec = new Vector();
					vec.add(tmp[row][col]);
					multiple.put(coord, vec);
				}
				vec.add((FuzzyAllenIntervalConstraint)c[i]);
			}
		}
		boolean isACrispCons = false;
		for(int i = 0; i < tmp.length; i++){
			Vector> con = new Vector>(); 
			for(int j = 0; j < tmp.length; j++){
				if(crispCons != null && tmp[i][j] != null){
					if(isACrispConstrint(tmp[i][j])) isACrispCons = true;
				}
				if(tmp[i][j] != null) {
					//add poss (i,j)
					/*
					System.out.println("----------------------------------");
					System.out.println("LOOKING AT " + tmpToConstraints.get(new Coords(i,j)) + ":\n" + (tmpToConstraints.get(new Coords(i,j))).getPossibilities());
					System.out.println("----------------------------------");
					*/
					Coord coord = new Coord(i,j);
					if (!multiple.containsKey(coord)) {
						if(!isACrispCons)
							con.add(tmp[i][j].getPossibilities());
						else
							con.add(tmp[i][j].makeCrispRel());
					}
					else {
						if(!isACrispCons){
							HashMap poss = multiple.get(coord).get(0).getPossibilities();
							for (int h = 1; h < multiple.get(coord).size(); h++) {
								updateRelation(poss, multiple.get(coord).get(h).getPossibilities());
							}
							con.add(poss);
						}
						else{
							HashMap poss = multiple.get(coord).get(0).makeCrispRel();
							for (int h = 1; h < multiple.get(coord).size(); h++) {
								updateRelation(poss, multiple.get(coord).get(h).makeCrispRel());
							}
							con.add(poss);
						}
					}
				}
				else if (tmp[j][i] != null) {
					//add inverse of (i,j)
					/*
					System.out.println("----------------------------------");
					System.out.println("LOOKING AT (I) " + tmpToConstraints.get(new Coords(j,i)) + ":\n" + (tmpToConstraints.get(new Coords(j,i))).getInversePossibilities());
					System.out.println("----------------------------------");
					*/
					Coord coord = new Coord(j,i);
					if(!isACrispCons){
						if (!multiple.containsKey(coord)) {
							con.add(tmp[j][i].getInversePossibilities());
						}
						else {
							HashMap poss = multiple.get(coord).get(0).getInversePossibilities();
							for (int h = 1; h < multiple.get(coord).size(); h++) {
								updateRelation(poss, multiple.get(coord).get(h).getInversePossibilities());
							}
							con.add(poss);
						}
					}
					else{
						if (!multiple.containsKey(coord)) {
							con.add(tmp[j][i].getCrispInverse());
						}
						else {
							HashMap poss = multiple.get(coord).get(0).getCrispInverse();
							for (int h = 1; h < multiple.get(coord).size(); h++) {
								updateRelation(poss, multiple.get(coord).get(h).getCrispInverse());
							}
							con.add(poss);
						}
					}
				}
				
				//if no relation exists, add [all possibilities <-- 1.0]
				else con.add(createAllFuzzyAllenRelation());
			}
			isACrispCons = false;
			frelations.add(con);
		}	
		
		return frelations;
	}
	
	private boolean isACrispConstrint(	FuzzyAllenIntervalConstraint fc) {
		// TODO Auto-generated method stub
		for (int i = 0; i < crispCons.length; i++) {
			if (((fc.getFrom().getID() == (crispCons[i].getScope()[0].getID())) && (fc.getTo().getID() == (crispCons[i].getScope()[1].getID()))))
					return true;
		}
		return false;
	}

	private HashMap createAllFuzzyAllenRelation() {
		HashMap fr = new HashMap();
		for(int t = 0; t <  FuzzyAllenIntervalConstraint.freksa_neighbor[FuzzyAllenIntervalConstraint.Type.Before.ordinal()].length; t++)
			fr.put(FuzzyAllenIntervalConstraint.lookupTypeByInt(t), 1.0);
		return fr;
	}
	
	/*
	private HashMap invertPossibilities(HashMap frelation) {
		HashMap ret = new HashMap();
		for (Type t : Type.values()) ret.put(t, 0.0);
		for (Type t : frelation.keySet()) {
			if (frelation.get(t) == 1.0) {
				//??? IS THIS CORRECT ??? --> Seems correct
				//get inverse of each relation that is 1.0 
				Type inverseRelation = FuzzyAllenIntervalConstraint.getComplement(t);
				
				//set poss of each inverse relation to 1.0
				ret.put(inverseRelation, frelation.get(t));
				
				//calculate the Freksa N of each inverse relation
				HashMap fr = new HashMap();
				for(int i = 0; i <  FuzzyAllenIntervalConstraint.freksa_neighbor[inverseRelation.ordinal()].length; i++)
					fr.put(FuzzyAllenIntervalConstraint.lookupTypeByInt(i), FuzzyAllenIntervalConstraint.getPossibilityDegree(FuzzyAllenIntervalConstraint.freksa_neighbor[inverseRelation.ordinal()][i]));
				
				//take the maximum between calculated Freksa N and previously added possibilities
				//(because this is an OR)
				for(FuzzyAllenIntervalConstraint.Type t1: fr.keySet())
					ret.put(t1, Math.max(ret.get(t1), fr.get(t1)));
			}
		}
		return ret;
	}
    */

	private Vector>> simplify(Vector>> frelations) {
		int numVars = getNumVars();
		for (int i = 0; i < numVars; i++) {
			for (int j = 0; j < numVars; j++) {
				if (i != j) {
					//Variable from = this.getVariables()[i];
					//Variable to = this.getVariables()[j];
					Variable from = getSubVariable()[i];
					Variable to = getSubVariable()[j];
					FuzzyAllenIntervalConstraint direct = (FuzzyAllenIntervalConstraint) this.getConstraintNetwork().getConstraint(from, to);
					FuzzyAllenIntervalConstraint inverse = (FuzzyAllenIntervalConstraint) this.getConstraintNetwork().getConstraint(to, from);
					if (direct != null && inverse != null) {
						//System.out.println("DOING " + direct + "\nPLUS " + inverse);
						HashMap inversePossibilities = inverse.getInversePossibilities();
						updateRelation(frelations.get(i).get(j), inversePossibilities);
					}
				}
			}
		}
		return frelations;
	}
	
	/*
	private Vector>> fuzzyArcConsistency(Vector>> frelations) {
		int numVars = this.getVariables().length;
		boolean changed = false;
		do {
			changed = false;
			for (int i = 0; i < numVars; i++) {
				for (int j = 0; j < numVars; j++) {
					if (i != j) {
						HashMap temp = (HashMap)frelations.get(i).get(j).clone();
						HashMap direct = frelations.get(i).get(j);
						HashMap inverse = invertPossibilities(frelations.get(j).get(i));
						updateRelation(direct, inverse);
						if (!compareRelation(direct, temp)) changed = true;
					}
				}
			}
		} while (changed);
		
		return frelations;
	}
	*/
	
	@SuppressWarnings("unchecked")
	private Vector>> fuzzyPathConsistency(Vector>> frelations) {
		int numVars = getNumVars();
		//need to cycle at least (numVars^2 - numVars) times
		int counter = numVars*numVars - numVars;
		boolean[][] mark = new boolean[numVars][numVars];
		
		for(int i = 0; i < numVars; i++) {
			for(int j = 0; j < numVars; j++) {
				if(i == j) mark[i][j] = false;
				else mark[i][j] = true;
			}
		}	
		
		while(counter != 0) { // while the set is not empty
			for(int i = 0; i < numVars; i++) {
				for(int j = 0; j < numVars; j++) {
					if(i == j) continue;
					if(mark[i][j]){
						mark[i][j] = false;	
						counter--; //remove from set
						for(int k = 0; k < numVars; k++) {
							if(k == i || k == j) continue;
							//process relation (k,j)
							//back up relation (k,j)
							HashMap hashMaptmp = (HashMap) frelations.get(k).get(j).clone();
							//(k,j) <-- (k,j) n (k,i) + (i,j) 
							updateRelation(frelations.get(k).get(j), generateComposition(frelations.get(k).get(i), frelations.get(i).get(j)));
							//if changed, must re-process (k,j)
							if(!compareRelation(frelations.get(k).get(j), hashMaptmp)) {
								if(!mark[k][j]) {
									mark[k][j] = true;
									counter++;
								}
							}
							//process relation (i,k)
							//back up relation (i,k)
							hashMaptmp = (HashMap)frelations.get(i).get(k).clone();
							//(i,k) <-- (i,k) n (i,j) + (j,k)
							updateRelation(frelations.get(i).get(k), generateComposition(frelations.get(i).get(j), frelations.get(j).get(k)));
							//if changed, must re-process (i,k)
							if(!compareRelation(frelations.get(i).get(k), hashMaptmp)) {
								if(!mark[i][k]) {
									mark[i][k] = true;
									counter++;
								}
							}
						}//end of k loop	
					}
				}
			}
		}
		return frelations;
	}

	private void updateGlobalPossibilityDegree(Vector>> frelations) {
		Vector max = new Vector();
		//calculate global possibility degree
		for(int i = 0; i < frelations.size(); i++){ 
			for(int j = 0; j < frelations.get(i).size(); j++){
				max.add(Collections.max(frelations.get(i).get(j).values()));
			}
		}	
		globalPossibilityDegree = Collections.min(max);
	}

	private boolean compareRelation(HashMap hashMap1,
			HashMap hashMap2) {
		for(FuzzyAllenIntervalConstraint.Type t: hashMap1.keySet())
			if(Double.compare(hashMap1.get(t), hashMap2.get(t)) != 0) return false;
		return true;
	}

	private void updateRelation(HashMap hashMap1,
			HashMap hashMap2) {
		for(FuzzyAllenIntervalConstraint.Type t: hashMap1.keySet())
			hashMap1.put(t, Math.min(hashMap1.get(t), hashMap2.get(t)));		
	}

	private HashMap generateComposition(HashMap hashMap1,
			HashMap hashMap2) {
		double tmpValue = 0;
		HashMap cmprelation =  new HashMap();
		for(FuzzyAllenIntervalConstraint.Type t: hashMap1.keySet()){
			for(FuzzyAllenIntervalConstraint.Type t2: hashMap2.keySet()){
				FuzzyAllenIntervalConstraint.Type[] tmpType = FuzzyAllenIntervalConstraint.transitionTable[t.ordinal()][t2.ordinal()];
				for(FuzzyAllenIntervalConstraint.Type t3: tmpType){
					if(cmprelation.containsKey(t3)){
						tmpValue = Math.max(cmprelation.get(t3), Math.min(hashMap1.get(t), hashMap2.get(t2)));	
						cmprelation.put(t3, tmpValue);
					}
					else{
						cmprelation.put(t3, Math.min(hashMap1.get(t), hashMap2.get(t2)));
					}
				}	
			}
		}
		return cmprelation;
	}

	@Override
	protected void removeConstraintsSub(Constraint[] c) {
		// TODO Auto-generated method stub
	}

	@Override
	protected void removeVariablesSub(Variable[] v) {
		// TODO Auto-generated method stub
	}

	/**
	 * IRAN: please comment this.
	 * @param fas
	 */
	public void setVarOfSubGraph(Vector fas) {
		this.subs = fas;  
	}

	private int getNumVars(){
		return numVars;				
	}
	
	private void setNumVars(Constraint[] c) {
		varIndex.clear();
		subVariables.clear();
		numVars = this.getVariables().length;
		for (int i = 0; i < this.getVariables().length; i++) {
			subVariables.add(this.getVariables()[i]);
		}
		if(isSubGraph){
			Vector vars = new Vector();
			for (int i = 0; i < c.length; i++) {
				if(!vars.contains(c[i].getScope()[0])){
					vars.add(c[i].getScope()[0]);
					varIndex.put(c[i].getScope()[0].getID(), vars.size() - 1);
				}
				if(!vars.contains(c[i].getScope()[1])){
					vars.add(c[i].getScope()[1]);	
					varIndex.put(c[i].getScope()[1].getID(), vars.size() - 1);
				}
			}
			numVars = vars.size();
			subVariables = vars;
		}
	}
	
	private Variable[] getSubVariable(){
		return subVariables.toArray(new Variable[subVariables.size()]);
	}

	/**
	 * Sets the given {@link FuzzyAllenIntervalConstraint}s to be considered as crisp
	 * (meaning that the desired possibility degrees of the constraint should
	 * not change, and the possibility degrees of all other relation types should be 0).
	 * @param crispCons The constraints to set as crisp.
	 */
	public void setCrispCons(Constraint[] crispCons) {
		this.crispCons  = crispCons;
	}

	@Override
	public void registerValueChoiceFunctions() {
		ValueChoiceFunction vcf = new ValueChoiceFunction(){
			@Override
			public Object getValue(Domain dom) {
				return ((SimpleInterval)dom).getIntervalName();
			}};
		Domain.registerValueChoiceFunction(SimpleInterval.class, vcf, "ID");		
	}
	
	

	

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy