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

tyRuBa.modes.Mode Maven / Gradle / Ivy

/*
 * Created on Apr 17, 2003
 *
 */
package tyRuBa.modes;

/**
 * A Mode is an object representing an abstract approximation of
 * the number of results a query is expected to return.
 * 
 * It is represented by a range of Multiplicities.
 */
public class Mode {

	/**
	 * 1..1 
	 */
	public static final Mode DET = makeDet();

	/**
	 * 0..1
	 */
	public static final Mode SEMIDET = makeSemidet();
	
	/**
	 * 0..n
	 */
	public static final Mode NONDET = makeNondet();
	
	/**
	 * 1..n
	 */
	public static final Mode MULTI = makeMulti();
	

	// Note at all times, lo should be <= hi
	final public Multiplicity lo;
	final public Multiplicity hi;
	final private String printString;
	private int numFree = 0;
	private int numBound = 0;
	
	public Mode(Multiplicity lo, Multiplicity hi) {
		this(lo, hi, 0, 0);
	}

	public Mode(Multiplicity lo, Multiplicity hi, int numFree, int numBound) {
		this.lo = lo;
		this.hi = hi;
		this.numFree = numFree;
		this.numBound = numBound;
		if (lo.equals(Multiplicity.zero)) {
			if (hi.equals(Multiplicity.zero)) {
				printString = "FAIL";
			} else if (hi.equals(Multiplicity.one)) {
				printString = "SEMIDET";
			} else if (hi.equals(Multiplicity.many)) {
				printString = "NONDET";
			} else if (hi.equals(Multiplicity.infinite)) {
				printString = "INFINITE";
			} else {
				throw new Error("this should not happen");
			}
		} else if (lo.equals(Multiplicity.one)) {
			if (hi.equals(Multiplicity.one)) {
				printString = "DET";
			} else if (hi.equals(Multiplicity.many)) {
				printString = "MULTI";
			} else if (hi.equals(Multiplicity.infinite)) {
				printString = "INFINITE";
			} else {
				throw new Error("this should not happen");
			}
		} else {
			System.err.println("lo = " + lo + "\nhi = " + hi);
			throw new Error("this should not happen");
		}
	}
	
	public Mode withFreeBound(int numFree, int numBound)
	{
		return new Mode(lo, hi, numFree, numBound);
	}
	
	public static Mode makeFail() {
		return new Mode(Multiplicity.zero, Multiplicity.zero, 0, 0);
	}
	
	public static Mode makeSemidet() {
		return new Mode(Multiplicity.zero, Multiplicity.one, 0, 0);
	}
	
	public static Mode makeDet() {
		return new Mode(Multiplicity.one, Multiplicity.one, 0, 0);
	}
	
	public static Mode makeNondet() {
		return new Mode(Multiplicity.zero, Multiplicity.many, 0, 0);
	}
	
	public static Mode makeMulti() {
		return new Mode(Multiplicity.one, Multiplicity.many, 0, 0);
	}

	public boolean isFail() {
		return lo.equals(Multiplicity.zero) && hi.equals(Multiplicity.zero);
	}
	
	public boolean isSemiDet() {
	    return lo.equals(Multiplicity.zero) && hi.equals(Multiplicity.one);
	}
	
	public boolean isDet() {
		return lo.equals(Multiplicity.one) && hi.equals(Multiplicity.one);
	}
	
	public boolean isNondet() {
		return lo.equals(Multiplicity.zero) && hi.equals(Multiplicity.many);
	}
	
	public boolean isMulti() {
		return lo.equals(Multiplicity.one) && hi.equals(Multiplicity.many);
	}
	
	public static Mode makeConvertTo() {
		return new Mode(Multiplicity.zero, Multiplicity.one, 1, 1);
	}
	
	public static Mode convertFromString(String modeString) {
		if (modeString.equals("DET")) {
			return makeDet();
		} else if (modeString.equals("SEMIDET")) {
			return makeSemidet();
		} else if (modeString.equals("NONDET")) {
			return makeNondet();
		} else if (modeString.equals("MULTI")) {
			return makeMulti();
		} else if (modeString.equals("FAIL")) {
			return makeFail();
		} else if (modeString.equals("ERROR")) {
			return new ErrorMode("");
		} else {
			throw new Error("unknown mode " + modeString);
		}
	}

	public Mode add(Mode other) {
		if (other == null) {
			return this;
		} else if (other instanceof ErrorMode) {
			return other.add(this);
		} else {
			return new Mode(this.lo.max(other.lo), this.hi.add(other.hi),
				this.numFree + other.numFree, this.numBound + other.numBound);
		}
	}

	public Mode multiply(Mode other) {
		if (other instanceof ErrorMode) {
			return other;
		} else {
			return new Mode(this.lo.multiply(other.lo), this.hi.multiply(other.hi),
				this.numFree + other.numFree, this.numBound + other.numBound);
		}
	}

	public String toString() {
		return printString;
	}
	
	public double getPercentFree() {
		if (numFree == 0) {
			return 0;
		} else {
			return ((double) numFree) / (numFree + numBound);
		}
	}

	public boolean equals(Object other) {
		if (other instanceof Mode) {
			Mode om = (Mode) other;
			return this.hi.equals(om.hi) && this.lo.equals(om.lo);
		} else {
			return false;
		}
	}
	
	public int hashCode() {
		return hi.hashCode() + 13*lo.hashCode();
	}

	/** return -1 if this expected to return less results than other
	 *  return 0 if this expected to return same nr of results than other
	 *  return 1 if this expected to return more results than other*/
	public int compareTo(Mode other) {
		int result = this.hi.compareTo(other.hi);
		if (result == 0) {
			result = this.lo.compareTo(other.lo);
			if (result == 0) {
				double thisPercentFree = getPercentFree();
				double otherPercentFree = other.getPercentFree();
				if (thisPercentFree < otherPercentFree) {
					return -1; // less free means expectation of less results returned!
				} else if (thisPercentFree > otherPercentFree) {
					return 1; // more free means expectation of more results returned!
				} else {
					return 0;
				}
			}
		}
		return result;
	}
	
	public boolean isBetterThan(Mode other) {
		return this.compareTo(other) < 0; // It is better to return less results.
	}

	public boolean compatibleWith(Mode declared) {
		return declared.hi.compareTo(this.hi) >= 0;
	}

	public Mode first() {
		if (this instanceof ErrorMode) {
			return this;
		} else {
			return new Mode(lo.min(Multiplicity.one), hi.min(Multiplicity.one),
				numFree, numBound);
		}
	}
	
	public Mode negate() {
		if (isFail()) {
			return new Mode(Multiplicity.one, Multiplicity.one, numFree, numBound);
		} else if (this instanceof ErrorMode) {
			return this;
		} else if (isDet() || isMulti()) {
			return new Mode(Multiplicity.zero, Multiplicity.zero, numFree, numBound);
		} else {
			return new Mode(Multiplicity.zero, Multiplicity.one, numFree, numBound);
		}
	}

	public Mode unique() {
		if (isDet() || isFail()) {
			return new Mode(lo, hi, numFree, numBound);
		} else if (this instanceof ErrorMode) {
			return this;
		} else {
			return new Mode(Multiplicity.zero, Multiplicity.one, numFree, numBound);
		}
	}

	public Mode restrictedBy(Mode upperBound) {
		if (this.hi.compareTo(upperBound.hi) > 0)
			return new Mode(this.lo, upperBound.hi, numFree, numBound);
		else
			return this;
	}

	public Mode findAll() {
		return new Mode(Multiplicity.one, Multiplicity.one, numFree, numBound);
	}
	
	/**
	 * What's the mode if in actuality more parameters are bound than in the 
	 * declaration?
	 */
	public Mode moreBound() {
		return new Mode(Multiplicity.zero, hi, numFree, numBound);
	}

	public void setPercentFree(BindingList bindings) {
		for (int i = 0; i < bindings.size(); i++) {
			if (bindings.get(i).isBound()) {
				numBound++;
			} else {
				numFree++;
			}
		}
	}

	public Mode noOverlapWith(Mode other) {
		if (other == null) {
			return this;
		} else {
			return new Mode(lo.min(other.lo), hi.max(other.hi));
		}
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy