/*
* Copyright 2011 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.drools.chance.degree.interval;
import org.drools.chance.degree.Degree;
import org.drools.chance.degree.simple.SimpleDegree;
/**
* Class that implements an uncertain degree, specified using an interval [low,upp].
* Thus, supports a simple form of second-order imperfection.
*
* Still experimental
*/
public class IntervalDegree implements Degree {
private static final double EPSILON = 1e-6;
private double tau;
private double phi;
public static final Degree TRUE = new IntervalDegree(1,1);
public static final Degree FALSE = new IntervalDegree(0,0);
public static final Degree UNKNOWN = new IntervalDegree(0,1);
public IntervalDegree() { }
public IntervalDegree(double low, double upp) {
this.setTau(low);
this.setPhi(1.0 - upp);
}
public SimpleDegree asSimpleDegree() {
return new SimpleDegree(getTau());
}
public double getValue() {
return getTau();
}
public void setValue(double d) {
setTau( d );
setPhi( 1.0 - d );
}
// coherent with simpleDegree, under CWA
public boolean toBoolean() {
return getTau() > 0;
}
public String toString() {
return "["+getLow()+","+getUpp()+"]";
}
/**
* @param phi the phi to set
*/
protected void setPhi(double phi) {
this.phi = phi;
}
/**
* @return the phi
*/
public double getPhi() {
return phi;
}
/**
* @param tau the tau to set
*/
protected void setTau(double tau) {
this.tau = tau;
}
/**
* @return the tau
*/
public double getTau() {
return tau;
}
public double getLow() {
return getTau();
}
public double getUpp() {
return 1.0 - getPhi();
}
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(phi);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(tau);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
IntervalDegree other = (IntervalDegree) obj;
return Math.abs(this.phi - other.phi) <= EPSILON
&&
Math.abs(this.tau - other.tau) <= EPSILON;
}
public double getConfidence() {
return phi+tau;
}
public IntervalDegree asIntervalDegree() {
return this;
}
public boolean isComparableTo(Degree o) {
IntervalDegree other = o.asIntervalDegree();
return ( (this.getUpp() < other.getLow())
||
(this.getLow() > other.getUpp()));
}
public int compareTo(Degree o) {
IntervalDegree other = o.asIntervalDegree();
if (this.getUpp() < other.getLow()) return -1;
if (this.getLow() > other.getUpp()) return 1;
if ((Math.abs(this.phi - other.phi) < EPSILON)
&&
(Math.abs(this.tau - other.tau) < EPSILON))
return 0;
return -99;
}
public Degree False() {
return FALSE;
}
public Degree True() {
return TRUE;
}
public Degree Unknown() {
return UNKNOWN;
}
public Degree sum(Degree other) {
double l = Math.min(1.0, this.getLow()+other.asIntervalDegree().getLow());
double u = Math.min(1.0, this.getUpp()+other.asIntervalDegree().getUpp());
return new IntervalDegree(l,u);
}
public Degree mul(Degree other) {
return new IntervalDegree(
this.getLow()*other.asIntervalDegree().getLow(),
this.getUpp()*other.asIntervalDegree().getUpp()
);
}
public Degree div(Degree other) {
double d1 = other.asIntervalDegree().getUpp();
double l = d1 != 0 ? Math.min(1.0, this.getLow()/d1) : 1.0;
double d2 = other.asIntervalDegree().getLow();
double u = d2 != 0 ? Math.min(1.0, this.getUpp()/d2) : 1.0;
return new IntervalDegree(l,u);
}
public Degree sub(Degree other) {
double l = Math.max(0.0, this.getLow() - other.asIntervalDegree().getUpp());
double u = Math.max(0.0, this.getUpp() - other.asIntervalDegree().getLow());
return new IntervalDegree(l,u);
}
public Degree max(Degree other) {
return new IntervalDegree(
Math.max(this.getLow(), other.asIntervalDegree().getLow()),
Math.max(this.getUpp(), other.asIntervalDegree().getUpp())
);
}
public Degree min(Degree other) {
return new IntervalDegree(
Math.min(this.getLow(),other.asIntervalDegree().getLow()),
Math.min(this.getUpp(),other.asIntervalDegree().getUpp())
);
}
public Degree fromConst(double number) {
return new IntervalDegree(number,number);
}
public Degree fromString(String val) {
val = val.replace("[","").replace("]","");
int pos = val.indexOf(",");
return new IntervalDegree( Double.parseDouble( val.substring( 0, pos - 1 ) ), Double.parseDouble( val.substring( pos + 1 ) ) );
}
public Degree fromBoolean( boolean val ) {
return fromBooleanLiteral( val );
}
public static Degree fromBooleanLiteral( boolean val ) {
return val ? TRUE : FALSE;
}
}