package infosapient.resolution;
/*
* Copyright (c) 2001, Workplace Performance Tools, All Rights Reserved.
*
* LICENSE TO USE THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THE COMMON PUBLIC LICENSE 0.5
* ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES
* RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
* The license may be viewed at:
* http://www.opensource.org/licenses/cpl.html
*/
import infosapient.system.FSEvent;
import infosapient.system.FzyKnowledgebase;
import infosapient.system.FzySet;
import infosapient.system.FzySystemComponent;
import infosapient.system.FzySystemException;
import infosapient.util.UtilityOperations;
import infosapient.opr.FzyOperator;
import infosapient.hdg.FzyHedge;
import java.util.Vector;
import java.rmi.server.ObjID;
/**
* FzyResolutionMethod implements the methods required for knowledgebase solution.
* @author: Michael McConnell
* @version $Revision: 1.1.1.1 $
*
*/
public abstract class FzyResolutionMethod extends FzySystemComponent implements java.io.Serializable, infosapient.util.XMLOutput {
static final long serialVersionUID = -2984786848240024584L;
static final String PREFIX = "infosapient.resolution.FzyRes";
//
protected int VECMAX;
private int[] edges = new int[2];
private FzyKnowledgebase theKB;
protected static final int LEFT = 0;
protected static final int RIGHT = 1;
protected int edgeCnt;
protected double domainValue;
protected double mbrValue;
protected int indexForDefuzz;
protected int i;
/**
* Return the int array representing the left and right hand side of the plateau in the membership function.
* If the right and left hand indexes are inside
* the fuzzy set, then this is a double edged plateau. (Edge count = 2)
* @param FzySet
* @return Vector the plateau locations
* @exception FzySystemException - if the membership of this set is zero, or Set index error.
*/
protected Vector _findPlateau(FzySet fset) throws FzySystemException {
Vector theLocations = new Vector();
PlateauLocation aLocation = null;
double maxH = fset.getMaxHeight();
if (maxH <= 0.0)
throw new FzySystemException(
this +" Cannot proceed. Fzy set " + fset.getName() + " has zero membership. ");
VECMAX = fset.getDomainArray().length;
int right = VECMAX - 1;
int i, j;
int d_indexR = right;
int d_indexL = 0;
int pCount = 0; // plateau count
setLeftEdge(0);
setRightEdge(right);
i = 0;
j = 1;
while (j < VECMAX) {
label1 : for (; j < VECMAX; i++, j++) {
if ((fset.getMembership(i) + fset.getMembership(j) > 0.0)
&& (Math.abs(fset.getMembership(i) - fset.getMembership(j)) == 0.0)) {
// found left side of plateau
d_indexL = i;
for (; j < VECMAX; j++) {
if ((fset.getMembership(d_indexL) != fset.getMembership(j)) || (j >= right)) {
// found right side of plateau
d_indexR = j;
aLocation =
new PlateauLocation(d_indexL, d_indexR, fset.getMembership(d_indexR));
pCount++;
if (pCount > 1) {
issueWarning(fset, fset.getMembership(d_indexR), pCount);
}
theLocations.add(aLocation);
i = j++;
break label1;
}
}
}
}
}
if (theLocations.isEmpty()) {
double domainVal = fset.domainForMembership(maxH);
d_indexL = fset.getIndexForDomain(domainVal);
theLocations.add(new PlateauLocation(d_indexL, d_indexL, maxH));
} else
java.util.Collections.sort(theLocations);
return theLocations;
}
public void applyAlfa(FzySet fset,int type)
{
int i;
VECMAX = fset.getDomainArray().length;
for(i=0;i<VECMAX;i++) {
if(!(fset.getDomain(i) > fset.getAlphaCut()))
fset.setMembership(0.0, i);
}
}
/**
* Modifies the shape of a sets surface causing a change in the membership function
* @param FzySet the input set
* @param FzyHedge the FzyHedge to be applied
* @return FzySet the fzySet with hedge applied to the membership space.
*
*/
public FzySet applyHedge(FzySet inputSet, FzyHedge hedge) {
return hedge.apply(inputSet);
}
public double domainValue(){
return domainValue;
}
public void domainValue(double sca){
domainValue = sca;
}
/**
* Find the far edge of the plateau
* @param FzySet - The (solutionset) set containing the plateau to find the edge(s)
* @return double - the domain value of the far edge.
*/
public double farEdge(FzySet fset) {
try {
findPlateau(fset);
setDomainValue(getScalarUsing(fset, getRightEdge()));
} catch (Exception e) {
notifyObservers(new FSEvent(this, "Error", e));
} finally {
return getDomainValue();
}
}
/**
* Return the int array representing the left and right hand side of the plateau in the membership function.
* If the right and left hand indexes are inside
* the fuzzy set, then this is a double edged plateau. (Edge count = 2)
* @param FzySet
* @return int[]
* @exception FzySystemException - if the membership of this set is zero, or Set index error.
*/
protected int[] findPlateau(FzySet fset) throws FzySystemException {
int i = 0;
int j = 0;
int pCount = 0;
VECMAX = fset.getDomainArray().length;
int pRight = VECMAX - 1;
double height = 0.0;
edgeCnt = 0;
setLeftEdge(0);
setRightEdge(0);
if ((height = fset.getMaxHeight()) <= 0.0)
throw new FzySystemException(
this +" Cannot proceed. Fzy set " + fset.getName() + " has zero membership. ");
for (i = 0; i < VECMAX; i++) {
if (fset.getMembership(i) < height)
fset.setMembership(0.0, i);
pCount = plateauCount(fset, height);
if (pCount > 1)
issueWarning(fset, height, pCount);
for (i = 0; i < pRight; i++) {
if (fset.getMembership(i) > 0) {
for (j = pRight; j >= 0; j--) {
if (j < i){
double maxH = fset.getMaxHeight();
double domainVal = fset.domainForMembership(maxH);
int d_index = fset.getIndexForDomain(domainVal);
setLeftEdge(d_index);
setRightEdge(d_index);
}
if (fset.getMembership(j) > 0) {
setLeftEdge(i);
setRightEdge(j);
/**
* Ok, we now have the left and right hand side of
* the plateau in the truth membership function.
* if the right and left hand indexes are inside
* the fuzzy set, then this is a double edged plateau.
*/
if ((i > 0) && (j < pRight)) {
edgeCnt = 2;
} else {
edgeCnt = 1;
}
}
}
}
}
}
return (getEdges());
}
/**
* find the left edge of the specified set.
* @param FzySet - the fuzzy set to be examined for left and right edges.
* @return double - the domain value of the near edge.
*/
public double getDomainForLeftEdge(FzySet fset) {
try {
findPlateau(fset);
} catch (Exception e) {
e.printStackTrace();
} finally {
return fset.getDomain(getLeftEdge());
}
}
/**
* Insert the method's description here.
* Creation date: (04/16/01 10:32:22 AM)
* @return double
*/
public double getDomainValue() {
return domainValue;
}
/**
* Insert the method's description here.
* Creation date: (04/16/01 10:32:22 AM)
* @return int
*/
public int getEdgeCnt() {
return edgeCnt;
}
/**
* Insert the method's description here.
* Creation date: (04/16/01 10:32:22 AM)
* @return int[]
*/
public int[] getEdges() {
return edges;
}
public FzyKnowledgebase getKB(){
return theKB;
}
/**
* Return the current left edge of set.
* Creation date: (04/16/01 10:33:09 AM)
* @return int
*/
public int getLeftEdge() {
return edges[LEFT];
}
/**
* Insert the method's description here.
* Creation date: (04/16/01 10:32:22 AM)
* @return double
*/
public double getMbrValue() {
return mbrValue;
}
/**
* Return the right edge of the fuzzy set.
* Creation date: (04/16/01 10:33:09 AM)
* @return int
*/
public int getRightEdge() {
return edges[RIGHT];
}
public double getScalarUsing(FzySet fset, int inx) throws IllegalArgumentException {
VECMAX = fset.getDomainArray().length;
if(inx < 0 || inx > VECMAX)
throw new IllegalArgumentException(" Illegal index given in FzyResolutionMethod.getScalar(): " + inx );
double range=fset.getHighDomain() - fset.getLowDomain();
double domainValue=fset.getLowDomain()+(inx * range)/(VECMAX-1);
return domainValue;
}
protected void issueWarning(FzySet fset,double height,int pCount){
notifyObservers(new FSEvent(this, "Warning", "CAUTION: Solution Fuzzy Set '"
+ fset.getName()
+ "' has "
+ Integer.toString(pCount)
+ " plateau(s) at height: "
+ Double.toString(height)
));
}
/**
*
* Calculate a solution for a monotonic space.
* returns a double representing an output scalar within the toSet.
* @param FzySet 'fromSet' -- the set the membership value is taken.
* @param FzySet 'toSet' the set to which the membership value from the first set is to be mapped.
* @param double the domain value for the 'fromSet'
* @return double the solution domain value.
*/
public double monotonicSolution(FzySet fromSet, FzySet toSet, double fromDomValue) throws FzySystemException {
return (toSet.domainForMembership(fromSet.getDOM(fromDomValue)));
}
/**
* Implements the standard Zadeh OR operator.
* @param double the membership value_1
* @param double the membership value_2
* @return double the Math.max(value_1, value_2)
*/
public double OR(double truth_1,double truth_2) {
return Math.max(truth_1, truth_2);
}
public int plateauCount(FzySet fset, double height) {
boolean inPlateau = false;
int i;
int startIDX;
int pCount = 0;
VECMAX = fset.getDomainArray().length;
// locate the start of a plateau
startIDX = -1;
for (i = 0; i < VECMAX; i++) {
if (fset.getMembership(i) != 0)
startIDX = i;
if (startIDX == -1)
return 0;
}
/**
* We found the start of the first plateau. We now say
* that we are in a plateau and we count this region.
*/
inPlateau = true;
pCount++;
/**
* Anytime we hit a zero, we have left the plateau. So
* the next nonzero we hit will be start of another plateau.
*/
for (i = startIDX; i < VECMAX; i++) {
if (fset.getMembership(i) == 0) {
inPlateau = false;
} else {
if (inPlateau == false) {
pCount++;
inPlateau = true;
}
}
return pCount;
}
return pCount;
}
public void printOn(java.io.Writer outWriter, int nTabs)throws java.io.IOException {
StringBuffer tabs = new StringBuffer(nTabs+1);
StringBuffer sb = new StringBuffer(100);
sb.append(tabs).append(" resolutionMethod ").append(getName()).append(";\n");
outWriter.write(sb.toString());
}
/**
* Resolution method factory
* Creation date: (1/26/00 12:17:44 PM)
* @return infosapient.resolution.FzyResolutionMethod
* @param name java.lang.String
* @exception java.lang.IllegalAccessException
* @exception java.lang.IllegalArgumentException If the argument is null.
* @exception java.lang.InstantiationException
* @exception java.lang.ClassNotFoundException
*/
public
static
FzyResolutionMethod
ResolutionMethodFactory(String name)
throws java.lang.IllegalAccessException,
java.lang.IllegalArgumentException,
java.lang.InstantiationException,
java.lang.ClassNotFoundException {
FzyResolutionMethod frm = null;
if (name == null) throw new IllegalArgumentException("Resolution name cannot be null.");
if (name.equalsIgnoreCase("average_maximum")) {
frm = (FzyResolutionMethod) Class.forName(PREFIX+name.toUpperCase()).newInstance();
} else
if (name.equalsIgnoreCase("average_space")) {
frm = (FzyResolutionMethod) Class.forName(PREFIX+name.toUpperCase()).newInstance();
} else
if (name.equalsIgnoreCase("average_support")) {
frm = (FzyResolutionMethod) Class.forName(PREFIX+name.toUpperCase()).newInstance();
} else
if (name.equalsIgnoreCase("bestevidence")) {
frm = (FzyResolutionMethod) Class.forName(PREFIX+name.toUpperCase()).newInstance();
} else
if (name.equalsIgnoreCase("bounded_add")) {
frm = (FzyResolutionMethod) Class.forName(PREFIX+name.toUpperCase()).newInstance();
} else
if (name.equalsIgnoreCase("bounded_mean")) {
frm = (FzyResolutionMethod) Class.forName(PREFIX+name.toUpperCase()).newInstance();
} else
if (name.equalsIgnoreCase("centroid")) {
frm = (FzyResolutionMethod) Class.forName(PREFIX+name.toUpperCase()).newInstance();
} else
if (name.equalsIgnoreCase("leastentropy")) {
frm = (FzyResolutionMethod) Class.forName(PREFIX+name.toUpperCase()).newInstance();
} else
if (name.equalsIgnoreCase("maximum")) {
frm = (FzyResolutionMethod) Class.forName(PREFIX+name.toUpperCase()).newInstance();
} else
if (name.equalsIgnoreCase("maxplateau")) {
frm = (FzyResolutionMethod) Class.forName(PREFIX+name.toUpperCase()).newInstance();
} else
if (name.equalsIgnoreCase("minmax")) {
frm = (FzyResolutionMethod) Class.forName(PREFIX+name.toUpperCase()).newInstance();
} else
throw new InstantiationException("Class not found for name: "+name);
return frm;
}
/**
* The method to be used for those who wish to defuzzify a given set. Performs certain checks for internal consistancy
* before attempting to defuzzify.
* @param FzySet the fuzzy set to defuzzify.
* @returns double the defuzzified domain value within the fuzzy set
*/
public double resolveToScalar(FzySet aSet) {
double integratedMem = aSet.integrateMbr();
if (integratedMem == 0) {
setChanged();
notifyObservers(new FSEvent(this, "Warning", getName() + " method not performed as fset membership is zero."));
return 0.0;
}else{
return resolveUsing(aSet);
}
}
/**
* The method used by subclasses of FzyResolutionMethod to defuzzify a given
* set.
* @param FzySet the fuzzy set to defuzzify.
* @returns double the defuzzified domain value within the fuzzy set
*/
protected abstract double resolveUsing(FzySet aSet);
/**
* Insert the method's description here.
* Creation date: (04/16/01 10:32:22 AM)
* @param newDomainValue double
*/
public void setDomainValue(double newDomainValue) {
domainValue = newDomainValue;
}
/**
* Insert the method's description here.
* Creation date: (04/16/01 10:32:22 AM)
* @param newEdgeCnt int
*/
public void setEdgeCnt(int newEdgeCnt) {
edgeCnt = newEdgeCnt;
}
/**
* set the found edges of a set.
* Creation date: (04/16/01 10:32:22 AM)
* @param newEdges int[]
*/
public void setEdges(int[] newEdges) {
if (newEdges.length != 2) throw new IllegalArgumentException("Length of edges array MUST be 2");
edges = newEdges;
}
public void setKB(FzyKnowledgebase akb){
theKB = akb;
setChanged();
}
/**
* Set the current left edge of set.
* Creation date: (04/16/01 10:33:09 AM)
* @return int
*/
public void setLeftEdge(int l) {
edges[LEFT] = l;
}
/**
* Insert the method's description here.
* Creation date: (04/16/01 10:32:22 AM)
* @param newMbrValue double
*/
public void setMbrValue(double newMbrValue) {
mbrValue = newMbrValue;
}
/**
* Set the current Right edge of set.
* Creation date: (04/16/01 10:33:09 AM)
* @return int
*/
public void setRightEdge(int r) {
edges[RIGHT] = r;
}
public String toString() {
if (getName() != null) return getName();
else return getClass().getName();
}
/**
* Represent this resolution method as xml tags.
* Creation date: (1/31/00 8:47:14 AM)
* @return java.lang.StringBuffer
*/
public StringBuffer toXML() {
StringBuffer xmlSB = new StringBuffer(35);
xmlSB.append("\tresolution-method=\"");
xmlSB.append(getName()+"\" \n");
return xmlSB;
}
/**
* Represent this resolution method as xml tags.
* Creation date: (1/31/00 8:47:14 AM)
* @return java.lang.StringBuffer
*/
public StringBuffer toXML(int nTabs) {
StringBuffer xmlSB = new StringBuffer(35);
for (int i = 0; i < nTabs; i++) xmlSB.append("\t");
xmlSB.append("resolution-method=\"");
xmlSB.append(getName()+"\" \n");
return xmlSB;
}
}