Process.java

package hierarchicalinterpolation.control; 
 
import fuzzy.FuzzyNumber; 
import fuzzy.IncompatibleFuzzyNumberTypeException; 
import fuzzy.TrapezoidalFuzzyNumber; 
import fuzzy.TriangularFuzzyNumber; 
import hierarchicalinterpolation.model.Observation; 
import hierarchicalinterpolation.model.Rule; 
import hierarchicalinterpolation.model.RuleBase; 
import hierarchicalinterpolation.model.RuleComparator; 
import huang.PrintfFormat; 
 
import java.io.FileReader; 
import java.util.ArrayList; 
import java.util.Collections; 
import java.util.List; 
 
/** 
 * Created by IntelliJ IDEA. 
 * User: rrd09 
 * Date: 28/07/11 
 * Time: 14:17 
 * To change this template use File | Settings | File Templates. 
 */ 
public class Process { 
 
    private boolean verbose = true; 
 
    @Deprecated 
    public static float getDelta(FuzzyNumber aStar, FuzzyNumber a1, FuzzyNumber a2) { 
        return Math.abs((a1.getRepresentativeValue() - aStar.getRepresentativeValue()) / (a1.getRepresentativeValue() - a2.getRepresentativeValue())); 
    } 
 
    public static float[][] getNormalisedTermWeights(Observation observation, Rule[] rules, int missingIndex) { 
        float[][] termWeights = calculateTermWeights(observation, rules, missingIndex); 
        float wSum = 0; 
        for (int i = 0; i < observation.getNumberOfAntecedents(); i++) { 
            if (i != missingIndex) { 
                wSum = 0; 
                for (int j = 0; j < rules.length; j++) { 
                    wSum += termWeights[j][i]; 
                } 
                for (int j = 0; j < rules.length; j++) { 
                    termWeights[j][i] = termWeights[j][i] / wSum; 
                    //System.out.println("A*" + i + "NormlisedtermWeights " + ":" + termWeights[j][i]); 
                } 
            } 
        } 
        if (missingIndex < observation.getNumberOfAntecedents()) { 
            wSum = 0; 
            for (int j = 0; j < rules.length; j++) { 
                wSum += termWeights[j][observation.getNumberOfAntecedents()]; 
            } 
            for (int j = 0; j < rules.length; j++) { 
                termWeights[j][observation.getNumberOfAntecedents()] = termWeights[j][observation.getNumberOfAntecedents()] / wSum; 
                //System.out.println("B*" + "NormlisedtermWeights to B" + j + ":" + termWeights[j][observation.getNumberOfAntecedents()]); 
            } 
        } 
        //System.out.println("Normalised Weights:"); 
        //printArrays(termWeights); 
        return termWeights; 
    } 
 
    public static float[][] calculateTermWeights(Observation observation, Rule[] rules, int missingIndex) { 
        //termWeights is a N*(K+1) matrix of N rules, and K antecedents + 1 consequence 
        float[][] termWeights = new float[rules.length][observation.getAntecedents().length + 1]; 
        for (int i = 0; i < rules.length; i++) { 
            for (int j = 0; j < rules[i].getAntecedents().length; j++) { 
                if (j != missingIndex) { 
                    // System.out.println("rules" + i + "Antecedent" + j + rules[i].getAntecedent(j).toStringInt() + " vs " + "observation.Antecedent" + j + observation.getAntecedent(j).toStringInt()); 
                    float distance = rules[i].getAntecedent(j).absDistanceTo(observation.getAntecedent(j)); 
                    termWeights[i][j] = 1f / distance; 
                    //System.out.println("A*" + j + "termWeights to R" + i + j + ":" + termWeights[i][j]); 
                } 
            } 
            if (missingIndex < observation.getNumberOfAntecedents()) { 
                termWeights[i][observation.getNumberOfAntecedents()] = 1f / rules[i].getConsequence().absDistanceTo(observation.getConsequence()); 
                //System.out.println("B*" + "termWeights to B" + i + ":" + termWeights[i][observation.getNumberOfAntecedents()]); 
            } 
        } 
        //System.out.println("Raw Term Weights:"); 
        //printArrays(termWeights); 
        return termWeights; 
    } 
 
    public static Rule getIntermediateFuzzyRule(Rule[] rules, float[][] normalisedWeights, int missingIndex) 
            throws IllegalAccessException, InstantiationException { 
        float[] points; 
        Rule intermediateFuzzyRule = new Rule(rules[0]); 
        for (int i = 0; i < rules[0].getNumberOfAntecedents(); i++) { 
            if (i != missingIndex) { 
                points = new float[rules[0].getAntecedent(i).getPoints().length]; 
                for (int j = 0; j < rules.length; j++) { 
                    for (int k = 0; k < points.length; k++) { 
                        points[k] = points[k] + normalisedWeights[j][i] * rules[j].getAntecedent(i).getPoint(k); 
                    } 
                } 
                FuzzyNumber intermediateFuzzyTerm = rules[0].getAntecedent(i).getClass().newInstance(); 
                intermediateFuzzyTerm.setPoints(points); 
                intermediateFuzzyRule.setAntecedent(i, intermediateFuzzyTerm); 
                System.out.println("intermediate A''" + i + ":" + intermediateFuzzyRule.getAntecedent(i)); 
            } 
        } 
        if (missingIndex < rules[0].getNumberOfAntecedents()) { 
            points = new float[rules[0].getConsequence().getPoints().length]; 
            for (int j = 0; j < rules.length; j++) { 
                for (int k = 0; k < points.length; k++) { 
                    points[k] = points[k] + normalisedWeights[j][rules[0].getNumberOfAntecedents()] * 
                            rules[j].getConsequence().getPoint(k); 
                } 
            } 
            FuzzyNumber intermediateConsequence = rules[0].getConsequence().getClass().newInstance(); 
            intermediateConsequence.setPoints(points); 
            intermediateFuzzyRule.setConsequence(intermediateConsequence); 
            System.out.println("intermediate B''" + intermediateFuzzyRule.getConsequence()); 
        } 
        return intermediateFuzzyRule; 
    } 
 
    @Deprecated 
    public static FuzzyNumber getIntermediateFuzzyTerm(FuzzyNumber a1, FuzzyNumber a2, float delta) 
            throws IncompatibleFuzzyNumberTypeException { 
        float[] points = new float[a1.getPoints().length]; 
        for (int i = 0; i < points.length; i++) { 
            points[i] = (1 - delta) * a1.getPoints()[i] + delta * a2.getPoints()[i]; 
        } 
        if (a1 instanceof TriangularFuzzyNumber) { 
            return new TriangularFuzzyNumber(points); 
        } else if (a1 instanceof TrapezoidalFuzzyNumber) { 
            return new TrapezoidalFuzzyNumber(points); 
        } else { 
            throw new IncompatibleFuzzyNumberTypeException(); 
        } 
    } 
 
    public static float getConsequenceScaleRate(float scaleRatio, float sB, float sT, FuzzyNumber fuzzyNumber) throws Exception { 
        /*if (fuzzyNumber instanceof TriangularFuzzyNumber) { 
            //TODO: Copy back the triangular function, check again later 
            return 0; 
        } else if (fuzzyNumber instanceof TrapezoidalFuzzyNumber) {*/ 
        float rB = ((TrapezoidalFuzzyNumber) fuzzyNumber).getTopBottomSupportRatio(); 
        if ((sT >= sB) && (sB >= 0)) { 
            //original equation is : sT = sB * (scaleRatio - scaleRatio * rB + rB) / rB 
            //which was transformed from ((sT / sB) * rB - rB) / (1 - rB) = scaleRatio 
            //where scaleRatio is calculated according the A' and A* 
            return sB * scaleRatio / rB - sB * scaleRatio + sB; 
        } else if ((sB >= sT) && (sT >= 0)) { 
            return sB * scaleRatio; 
        } else { 
            throw new Exception("Unsupported Scale Rate"); 
        } 
        /*} 
        return 0;*/ 
    } 
 
    public static float getScaleRate(FuzzyNumber aDash, FuzzyNumber aStar) throws Exception { 
        if (aDash instanceof TriangularFuzzyNumber) { 
            return (aStar.getPoints()[2] - aStar.getPoints()[0]) / 
                    (aDash.getPoints()[2] - aDash.getPoints()[0]); 
        } else if (aDash instanceof TrapezoidalFuzzyNumber) { 
            if ((((TrapezoidalFuzzyNumber) aStar).getTopBottomSupportRatio() >= 
                    ((TrapezoidalFuzzyNumber) aDash).getTopBottomSupportRatio()) && 
                    (((TrapezoidalFuzzyNumber) aDash).getTopBottomSupportRatio() >= 0)) { 
                return ((aStar.getPoints()[2] - aStar.getPoints()[1]) / (aStar.getPoints()[3] - aStar.getPoints()[0]) - 
                        (aDash.getPoints()[2] - aDash.getPoints()[1]) / (aDash.getPoints()[3] - aDash.getPoints()[0])) / 
                        (1 - (aDash.getPoints()[2] - aDash.getPoints()[1]) / (aDash.getPoints()[3] - aDash.getPoints()[0])); 
            } else if ((((TrapezoidalFuzzyNumber) aDash).getTopBottomSupportRatio() >= 
                    ((TrapezoidalFuzzyNumber) aStar).getTopBottomSupportRatio()) && 
                    (((TrapezoidalFuzzyNumber) aStar).getTopBottomSupportRatio() >= 0)) { 
                return ((aStar.getPoints()[2] - aStar.getPoints()[1]) / (aStar.getPoints()[3] - aStar.getPoints()[0]) - 
                        (aDash.getPoints()[2] - aDash.getPoints()[1]) / (aDash.getPoints()[3] - aDash.getPoints()[0])) / 
                        ((aDash.getPoints()[2] - aDash.getPoints()[1]) / (aDash.getPoints()[3] - aDash.getPoints()[0])); 
            } else { 
                throw new Exception("Unsupported Scale Rate"); 
            } 
        } 
        return 0; 
    } 
 
    public static float getMoveRatio(FuzzyNumber aDashScaled, FuzzyNumber aStar) throws Exception { 
        float moveRatio = 0; 
        if (aDashScaled instanceof TriangularFuzzyNumber) { 
            if (aStar.getPoints()[0] >= aDashScaled.getPoints()[0]) { 
                moveRatio = (aStar.getPoints()[0] - aDashScaled.getPoints()[0]) * 3 / 
                        (aDashScaled.getPoints()[1] - aDashScaled.getPoints()[0]); 
                if ((moveRatio < 0) || (moveRatio > 1)) 
                    throw new Exception("Move Ratio (" + moveRatio + ") cannot exceed [0,1]"); 
            } else { 
                moveRatio = (aStar.getPoints()[0] - aDashScaled.getPoints()[0]) * 3 / 
                        (aDashScaled.getPoints()[2] - aDashScaled.getPoints()[1]); 
                if ((moveRatio > 0) || (moveRatio < -1)) 
                    throw new Exception("Move Ratio (" + moveRatio + ") cannot exceed [-1,0]"); 
            } 
        } else if (aDashScaled instanceof TrapezoidalFuzzyNumber) { 
            if (aStar.getPoints()[0] >= aDashScaled.getPoints()[0]) { 
                moveRatio = (aStar.getPoints()[0] - aDashScaled.getPoints()[0]) * 3 / 
                        (aDashScaled.getPoints()[1] - aDashScaled.getPoints()[0]); 
                if ((moveRatio < 0) || (moveRatio > 1)) 
                    throw new Exception("Move Ratio (" + moveRatio + ") cannot exceed [0,1]"); 
            } else { 
                moveRatio = (aStar.getPoints()[0] - aDashScaled.getPoints()[0]) * 3 / 
                        (aDashScaled.getPoints()[3] - aDashScaled.getPoints()[2]); 
                if ((moveRatio > 0) || (moveRatio < -1)) 
                    throw new Exception("Move Ratio (" + moveRatio + ") cannot exceed [-1,0]"); 
            } 
        } 
        return moveRatio; 
    } 
 
    public static float getBottomScaleRate(FuzzyNumber aDash, FuzzyNumber aStar) { 
        return (aStar.getPoints()[3] - aStar.getPoints()[0]) / 
                (aDash.getPoints()[3] - aDash.getPoints()[0]); 
    } 
 
    public static float getTopScaleRate(FuzzyNumber aDash, FuzzyNumber aStar) { 
        return (aStar.getPoints()[2] - aStar.getPoints()[1]) / 
                (aDash.getPoints()[2] - aDash.getPoints()[1]); 
    } 
 
    public static Rule shift(Rule intermediateRule, Observation observation, int missingIndex) { 
        Rule shiftedIntermediateRule = new Rule(intermediateRule); 
        float delta = 0, deltaSum = 0; 
        if (missingIndex >= intermediateRule.getNumberOfAntecedents()) { 
            //forward 
            for (int i = 0; i < intermediateRule.getNumberOfAntecedents(); i++) { 
                float distance = observation.getAntecedent(i).distanceTo(intermediateRule.getAntecedent(i)); 
                delta = distance / 
                        (intermediateRule.getMaxAntecedentRanges()[i] - intermediateRule.getMinAntecedentRanges()[i]); 
                shiftedIntermediateRule.setAntecedent(i, intermediateRule.getAntecedent(i).adds(delta * 
                        (intermediateRule.getMaxAntecedentRanges()[i] - intermediateRule.getMinAntecedentRanges()[i]))); 
                deltaSum += delta; 
                System.out.println("Delta A" + i + " " + delta); 
            } 
            delta = deltaSum / intermediateRule.getNumberOfAntecedents(); 
            System.out.println("Delta B " + delta); 
            shiftedIntermediateRule.setConsequence(intermediateRule.getConsequence().adds( 
                    delta * (intermediateRule.getMaxConsequenceRange() - intermediateRule.getMinConsequenceRange()))); 
            System.out.println("(f)shifted B'" + ":" + shiftedIntermediateRule.getConsequence() + " " + shiftedIntermediateRule.getConsequence().getRepresentativeValue()); 
        } else { 
            for (int i = 0; i < intermediateRule.getNumberOfAntecedents(); i++) { 
                if (i != missingIndex) { 
                    delta = observation.getAntecedent(i).distanceTo(intermediateRule.getAntecedent(i)) / 
                            (intermediateRule.getMaxAntecedentRanges()[i] - intermediateRule.getMinAntecedentRanges()[i]); 
                    shiftedIntermediateRule.setAntecedent(i, intermediateRule.getAntecedent(i).adds(delta * 
                            (intermediateRule.getMaxAntecedentRanges()[i] - intermediateRule.getMinAntecedentRanges()[i]))); 
                    System.out.println("shifted A'" + i + ":" + shiftedIntermediateRule.getAntecedent(i)); 
                    deltaSum += delta; 
                    System.out.println("Delta A" + i + " " + delta); 
                } 
            } 
            delta = observation.getConsequence().distanceTo(intermediateRule.getConsequence()) / 
                    (intermediateRule.getMaxConsequenceRange() - intermediateRule.getMinConsequenceRange()); 
            System.out.println("Delta B "  + delta); 
            shiftedIntermediateRule.setConsequence(intermediateRule.getConsequence().adds(delta * 
                    (intermediateRule.getMaxConsequenceRange() - intermediateRule.getMinConsequenceRange()))); 
            System.out.println("(b)shifted B'" + ":" + shiftedIntermediateRule.getConsequence() + " " + shiftedIntermediateRule.getConsequence().getRepresentativeValue()); 
 
            delta = delta * intermediateRule.getNumberOfAntecedents() - deltaSum; 
            System.out.println("Delta A" + missingIndex + " " + delta); 
            shiftedIntermediateRule.setAntecedent(missingIndex, intermediateRule.getAntecedent(missingIndex).adds( 
                    delta * (intermediateRule.getMaxAntecedentRanges()[missingIndex] - 
                            intermediateRule.getMinAntecedentRanges()[missingIndex]))); 
            System.out.println("shifted A'" + missingIndex + ":" + shiftedIntermediateRule.getAntecedent(missingIndex)); 
        } 
        return shiftedIntermediateRule; 
    } 
 
    public static TriangularFuzzyNumber scale(TriangularFuzzyNumber fuzzyNumber, float scaleRate) throws Exception { 
        if (scaleRate < 0) throw new Exception("Scale Rate (" + scaleRate + ") cannot be less than 0"); 
        double newLeftShoulder = (fuzzyNumber.getLeftShoulder() * (1 + 2 * scaleRate) + 
                fuzzyNumber.getCentroid() * (1 - scaleRate) + 
                fuzzyNumber.getRightShoulder() * (1 - scaleRate)) / 3; 
        double newCentroid = (fuzzyNumber.getLeftShoulder() * (1 - scaleRate) + 
                fuzzyNumber.getCentroid() * (1 + 2 * scaleRate) + 
                fuzzyNumber.getRightShoulder() * (1 - scaleRate)) / 3; 
        double newRightShoulder = (fuzzyNumber.getLeftShoulder() * (1 - scaleRate) + 
                fuzzyNumber.getCentroid() * (1 - scaleRate) + 
                fuzzyNumber.getRightShoulder() * (1 + 2 * scaleRate)) / 3; 
        return new TriangularFuzzyNumber(newLeftShoulder, newCentroid, newRightShoulder); 
    } 
 
    public static TrapezoidalFuzzyNumber scale(TrapezoidalFuzzyNumber fuzzyNumber, float sB, float sT) throws Exception { 
 
        float a0 = fuzzyNumber.getPoints()[0]; 
        float a1 = fuzzyNumber.getPoints()[1]; 
        float a2 = fuzzyNumber.getPoints()[2]; 
        float a3 = fuzzyNumber.getPoints()[3]; 
 
        /*   if (scaleRate < 0) 
// scaleRate=-scaleRate; 
throw new Exception("Scale Rate (" + scaleRate + ") cannot be less than 0");*/ 
        float A = (2 * a0 + a1 + a2 + 2 * a3) / 6; 
        float B = 6 * (a1 + a3 - a0 - a2); 
        float C = 2 * sB * (a3 - a0); 
        float D = sT * (a2 - a1); 
 
        float newLeftShoulder = A - (C * (2 * a1 + a3 - 2 * a0 - a2) - D * (a1 + a2 - a0 - a3)) / B; 
        float newLeftCentroid = A - (C * (a0 + a3 - a1 - a2) - D * (5 * a0 + a2 - 5 * a1 - a3)) / B; 
        float newRightCentroid = A - (C * (a0 + a3 - a1 - a2) - D * (a1 + 5 * a3 - a0 - 5 * a2)) / B; 
        float newRightShoulder = A - (C * (a0 + 2 * a2 - a1 - 2 * a3) - D * (a1 + a2 - a0 - a3)) / B; 
        return new TrapezoidalFuzzyNumber(newLeftShoulder, newLeftCentroid, newRightCentroid, newRightShoulder); 
    } 
 
 
    /*public static float getMoveRatio(FuzzyNumber aDashScaled, FuzzyNumber aStar) throws Exception { 
        float moveRatio; 
        if (aDashScaled.getLeftShoulder() >= aStar.getLeftShoulder()) { 
            moveRatio = (aDashScaled.getLeftCentroid() - aStar.getLeftShoulder()) * 3 / 
                    (aStar.getLeftCentroid() - aStar.getLeftShoulder()); 
            if ((moveRatio < 0) || (moveRatio > 1)) 
                throw new Exception("Move Ratio (" + moveRatio + ") cannot exceed [0,1]"); 
        } else { 
            moveRatio = (aDashScaled.getLeftShoulder() - aStar.getLeftShoulder()) * 3 / 
                    (aStar.getRightShoulder() - aStar.getRightCentroid()); 
            if ((moveRatio > 0) || (moveRatio < -1)) 
                throw new Exception("Move Ratio (" + moveRatio + ") cannot exceed [-1,0]"); 
 
        } 
        return moveRatio; 
    }*/ 
 
    public static TrapezoidalFuzzyNumber move(TrapezoidalFuzzyNumber fuzzyNumber, float moveRatio) { 
        float moveRate = (moveRatio >= 0) ? 
                moveRatio * (fuzzyNumber.getPoints()[1] - fuzzyNumber.getPoints()[0]) / 3 : 
                moveRatio * (fuzzyNumber.getPoints()[3] - fuzzyNumber.getPoints()[2]) / 3; 
        return new TrapezoidalFuzzyNumber(fuzzyNumber.getPoints()[0] + moveRate, 
                fuzzyNumber.getPoints()[1] - 2 * moveRate, 
                fuzzyNumber.getPoints()[2] - 2 * moveRate, 
                fuzzyNumber.getPoints()[3] + moveRate); 
    } 
 
    public static TriangularFuzzyNumber move(TriangularFuzzyNumber fuzzyNumber, float moveRatio) { 
        float moveRate = (moveRatio >= 0) ? 
                moveRatio * (fuzzyNumber.getPoints()[1] - fuzzyNumber.getPoints()[0]) / 3 : 
                moveRatio * (fuzzyNumber.getPoints()[2] - fuzzyNumber.getPoints()[1]) / 3; 
        return new TriangularFuzzyNumber(fuzzyNumber.getLeftShoulder() + moveRate, 
                fuzzyNumber.getCentroid() - 2 * moveRate, 
                fuzzyNumber.getRightShoulder() + moveRate); 
    } 
 
    public static Rule getIntermediateRule(Rule[] rules, Observation observation, int missingIndex) 
            throws InstantiationException, IllegalAccessException { 
        float[][] normalisedWeights = getNormalisedTermWeights(observation, rules, missingIndex); 
        Rule intermediateRule = getIntermediateFuzzyRule(rules, normalisedWeights, missingIndex); 
        if ((missingIndex >= 0) & (missingIndex < observation.getAntecedents().length)) { 
            //backward 
            float[] points = new float[rules[0].getAntecedent(missingIndex).getPoints().length]; 
            float wSum = 0; 
            for (int i = 0; i < rules.length; i++) { 
                wSum = 0; 
                for (int j = 0; j < rules[0].getNumberOfAntecedents(); j++) { 
                    if (j != missingIndex) { 
                        wSum += normalisedWeights[i][j]; 
                    } 
                } 
                normalisedWeights[i][missingIndex] = normalisedWeights[i][rules[0].getNumberOfAntecedents()] * 
                        rules[0].getNumberOfAntecedents() - wSum; 
                for (int k = 0; k < points.length; k++) { 
                    points[k] = points[k] + normalisedWeights[i][missingIndex] * rules[i].getAntecedent(missingIndex).getPoint(k); 
                } 
            } 
            FuzzyNumber intermediateMissingAntecedent = rules[0].getAntecedent(missingIndex).getClass().newInstance(); 
            intermediateMissingAntecedent.setPoints(points); 
            intermediateRule.setAntecedent(missingIndex, intermediateMissingAntecedent); 
            System.out.println("intermediate A''" + missingIndex + "'':" + intermediateRule.getAntecedents()[missingIndex ]); 
        } else { 
            //forward 
            float[] points = new float[rules[0].getConsequence().getPoints().length]; 
            float wSum = 0; 
            for (int i = 0; i < rules.length; i++) { 
                wSum = 0; 
                for (int j = 0; j < rules[0].getNumberOfAntecedents(); j++) { 
                    wSum += normalisedWeights[i][j]; 
                } 
                normalisedWeights[i][rules[0].getNumberOfAntecedents()] = wSum / rules[0].getNumberOfAntecedents(); 
                for (int k = 0; k < points.length; k++) { 
                    points[k] = points[k] + normalisedWeights[i][rules[0].getNumberOfAntecedents()] * rules[i].getConsequence().getPoint(k); 
                } 
            } 
            FuzzyNumber intermediateConsequence = rules[0].getConsequence().getClass().newInstance(); 
            intermediateConsequence.setPoints(points); 
            intermediateRule.setConsequence(intermediateConsequence); 
            System.out.println("intermediate B'':" + intermediateRule.getConsequence()); 
 
 
            float consequenceWeightSum = 0; 
            for (int i = 0; i < rules.length; i++) { 
                float consequenceWeight = (float) (1/ Math.abs(intermediateConsequence.distanceTo(rules[i].getConsequence()) -0.092990205*15)); 
                consequenceWeightSum += consequenceWeight; 
            } 
 
            for (int i = 0; i < rules.length; i++) { 
                float consequenceWeight2 = (float) (1/ Math.abs(intermediateConsequence.distanceTo(rules[i].getConsequence()) -0.092990205*15)); 
                consequenceWeight2 = consequenceWeight2 / consequenceWeightSum; 
                System.out.print(consequenceWeight2 + "\t"); 
            } 
            System.out.println(); 
        } 
        System.out.println("Normalised Weights:"); 
        printArrays(normalisedWeights); 
        Rule shiftedIntermediateRule = shift(intermediateRule, observation, missingIndex); 
 
 
        float consequenceWeightSum = 0; 
            for (int i = 0; i < rules.length; i++) { 
                float consequenceWeight = 1/ shiftedIntermediateRule.getConsequence().absDistanceTo(rules[i].getConsequence()); 
                consequenceWeightSum += consequenceWeight; 
            } 
 
            for (int i = 0; i < rules.length; i++) { 
                float consequenceWeight2 = 1/ shiftedIntermediateRule.getConsequence().absDistanceTo(rules[i].getConsequence()); 
                consequenceWeight2 = consequenceWeight2 / consequenceWeightSum; 
                System.out.print(consequenceWeight2 + "\t"); 
            } 
            System.out.println(); 
 
        return shiftedIntermediateRule; 
    } 
 
    @Deprecated 
    public static Rule getIntermediateRule(Rule rule1, Rule rule2, Observation observation, int dimensionToBeInterpolated) throws IncompatibleFuzzyNumberTypeException { 
        float deltaSum = 0; 
        float delta; 
        Rule intermediateRule = new Rule(rule1); 
 
        if ((dimensionToBeInterpolated >= 0) & (dimensionToBeInterpolated < observation.getAntecedents().length)) { 
            //backward 
            for (int i = 0; i < observation.getAntecedents().length; i++) { 
                if (i != dimensionToBeInterpolated) { 
                    delta = getDelta(observation.getAntecedents()[i], 
                            rule1.getAntecedents()[i], 
                            rule2.getAntecedents()[i]); 
                    System.out.println(i + "'th dimension delta:" + delta); 
                    deltaSum = deltaSum + delta; 
                    intermediateRule.getAntecedents()[i] = 
                            getIntermediateFuzzyTerm(rule1.getAntecedents()[i], rule2.getAntecedents()[i], delta); 
                } 
            } 
            delta = getDelta(observation.getConsequence(), 
                    rule1.getConsequence(), 
                    rule2.getConsequence()); 
            System.out.println("Consequence delta:" + delta); 
            intermediateRule.setConsequence( 
                    getIntermediateFuzzyTerm(rule1.getConsequence(), rule2.getConsequence(), delta)); 
 
            delta = delta * observation.getAntecedents().length - deltaSum; 
            System.out.println(dimensionToBeInterpolated + "'th antecedent delta:" + delta); 
            intermediateRule.getAntecedents()[dimensionToBeInterpolated] = 
                    getIntermediateFuzzyTerm( 
                            rule1.getAntecedents()[dimensionToBeInterpolated], 
                            rule2.getAntecedents()[dimensionToBeInterpolated], delta); 
 
        } else { 
            //forward 
            for (int i = 0; i < observation.getAntecedents().length; i++) { 
                delta = getDelta(observation.getAntecedents()[i], 
                        rule1.getAntecedents()[i], 
                        rule2.getAntecedents()[i]); 
                System.out.println(i + "'th antecedent delta=" + delta); 
                deltaSum = deltaSum + delta; 
                intermediateRule.getAntecedents()[i] = 
                        getIntermediateFuzzyTerm(rule1.getAntecedents()[i], rule2.getAntecedents()[i], delta); 
            } 
            delta = deltaSum / observation.getAntecedents().length; 
            System.out.println("Consequent delta=" + delta); 
            intermediateRule.setConsequence( 
                    getIntermediateFuzzyTerm(rule1.getConsequence(), rule2.getConsequence(), delta)); 
        } 
        //   System.out.println("delta=" + delta); 
        for (int j = 0; j < intermediateRule.getAntecedents().length; j++) { 
            System.out.println("A" + j + "' antecedent = " + intermediateRule.getAntecedents()[j].toString()); 
        } 
 
        System.out.println(" B'= " + intermediateRule.getConsequence().toString()); 
        return intermediateRule; 
    } 
 
    public static Rule transform(Rule intermediateRule, Observation observation, int missingIndex) throws Exception { 
        if ((missingIndex >= 0) & (missingIndex < observation.getAntecedents().length)) { 
            if (intermediateRule.getAntecedent(missingIndex) instanceof TrapezoidalFuzzyNumber) { 
                return backwardInterpolation(new TrapezoidalFuzzyNumber(), 
                        intermediateRule, 
                        observation, 
                        missingIndex); 
            } else { 
                return backwardInterpolation(new TriangularFuzzyNumber(), 
                        intermediateRule, 
                        observation, 
                        missingIndex); 
            } 
        } else { 
            if (intermediateRule.getConsequence() instanceof TrapezoidalFuzzyNumber) { 
                return forwardInterpolation(new TrapezoidalFuzzyNumber(), 
                        intermediateRule, 
                        observation); 
            } else { 
                return forwardInterpolation(new TriangularFuzzyNumber(), 
                        intermediateRule, 
                        observation); 
            } 
        } 
    } 
 
    private static Rule forwardInterpolation(TriangularFuzzyNumber triangularFuzzyNumber, 
                                             Rule intermediateRule, 
                                             Observation observation) throws Exception { 
        //Rule scaledRule = new Rule(intermediateRule); 
        Rule transformedRule = new Rule(intermediateRule); 
        float s = 0, sSum = 0, m = 0, mSum = 0; 
        for (int i = 0; i < intermediateRule.getNumberOfAntecedents(); i++) { 
            s = getScaleRate(intermediateRule.getAntecedent(i), observation.getAntecedent(i)); 
            System.out.println(i + "'th dimension: " + "s=" + s); 
            intermediateRule.setAntecedent(i, scale((TriangularFuzzyNumber) intermediateRule.getAntecedent(i), s)); 
            System.out.println("scaled A" + i + "'':" + intermediateRule.getAntecedents()[i]); 
            sSum = sSum + s; 
 
            m = getMoveRatio(intermediateRule.getAntecedent(i), observation.getAntecedent(i)); 
            System.out.println(i + "'th dimension: " + "m=" + m); 
            transformedRule.setAntecedent(i, move((TriangularFuzzyNumber) intermediateRule.getAntecedent(i), m)); 
            mSum = mSum + m; 
        } 
        s = sSum / intermediateRule.getNumberOfAntecedents(); 
        m = mSum / intermediateRule.getNumberOfAntecedents(); 
        System.out.println("Consequence dimension: " + "s=" + s); 
        System.out.println("Consequence dimension: " + "m=" + m); 
        transformedRule.setConsequence(move(scale((TriangularFuzzyNumber) intermediateRule.getConsequence(), s), m)); 
        return transformedRule; 
    } 
 
    private static Rule backwardInterpolation(TriangularFuzzyNumber triangularFuzzyNumber, 
                                              Rule intermediateRule, 
                                              Observation observation, 
                                              int missingIndex) throws Exception { 
        Rule transformedRule = new Rule(intermediateRule); 
        float s = 0, sSum = 0, m = 0, mSum = 0; 
        for (int i = 0; i < observation.getAntecedents().length; i++) { 
            if (i != missingIndex) { 
                s = getScaleRate(intermediateRule.getAntecedents()[i], observation.getAntecedents()[i]); 
                System.out.println(i + "'th dimension: " + "s=" + s); 
                intermediateRule.setAntecedent(i, scale((TriangularFuzzyNumber) intermediateRule.getAntecedent(i), s)); 
                System.out.println("scaled A" + i + "'':" + intermediateRule.getAntecedents()[i]); 
                sSum = sSum + s; 
 
                m = getMoveRatio(intermediateRule.getAntecedent(i), observation.getAntecedent(i)); 
                System.out.println(i + "'th dimension: " + "m=" + m); 
                transformedRule.setAntecedent(i, move((TriangularFuzzyNumber) intermediateRule.getAntecedent(i), m)); 
                mSum = mSum + m; 
            } 
        } 
 
        s = getScaleRate(intermediateRule.getConsequence(), observation.getConsequence()); 
        intermediateRule.setConsequence(scale((TriangularFuzzyNumber) intermediateRule.getConsequence(), s)); 
        System.out.println("Consequence dimension: " + "s=" + s); 
        System.out.println("B'':" + intermediateRule.getConsequence()); 
        m = getMoveRatio(intermediateRule.getConsequence(), observation.getConsequence()); 
        transformedRule.setConsequence(move((TriangularFuzzyNumber) intermediateRule.getConsequence(), m)); 
        System.out.println("Consequence dimension: " + "m=" + m); 
 
        s = s * observation.getAntecedents().length - sSum; 
        System.out.println(missingIndex + " dimension: " + "s=" + s); 
        m = m * observation.getAntecedents().length - mSum; 
        System.out.println(missingIndex + " dimension: " + "m=" + m); 
        transformedRule.getAntecedents()[missingIndex] = scale((TriangularFuzzyNumber) intermediateRule.getAntecedents()[missingIndex], s); 
        System.out.println("scaled A" + missingIndex + "''" + transformedRule.getAntecedents()[missingIndex].toString()); 
        transformedRule.getAntecedents()[missingIndex] = move((TriangularFuzzyNumber) transformedRule.getAntecedents()[missingIndex], m); 
        System.out.println("Backward interpolation antecedent:" + missingIndex + transformedRule.getAntecedents()[missingIndex].toString()); 
        return transformedRule; 
    } 
 
    private static Rule backwardInterpolation(TrapezoidalFuzzyNumber trapezoidalFuzzyNumber, 
                                              Rule intermediateRule, 
                                              Observation observation, 
                                              int missingIndex) throws Exception { 
        Rule scaledRule = new Rule(intermediateRule); 
        Rule transformedRule = new Rule(intermediateRule); 
        float sb = 0, st = 0, sbSum = 0, stSum = 0, scaleRatio = 0, scaleRatioSum = 0, m = 0, mSum = 0; 
        //backward 
        for (int i = 0; i < observation.getAntecedents().length; i++) { 
            if (i != missingIndex) { 
                sb = getBottomScaleRate(intermediateRule.getAntecedents()[i], observation.getAntecedents()[i]); 
                st = getTopScaleRate(intermediateRule.getAntecedents()[i], observation.getAntecedents()[i]); 
                scaleRatio = getScaleRate(intermediateRule.getAntecedents()[i], observation.getAntecedents()[i]); 
                System.out.println(i + "'th dimension: " + "sb=" + sb + "and " + " st=" + st); 
                System.out.println("scaleRatio A" + i + " = " + scaleRatio); 
                //intermediateRule.getAntecedents()[i] = scale(intermediateRule.getAntecedents()[i], sb, st); 
                scaledRule.getAntecedents()[i] = scale((TrapezoidalFuzzyNumber) intermediateRule.getAntecedent(i), sb, st); 
                System.out.println("A" + i + "'':" + scaledRule.getAntecedents()[i]); 
                sbSum = sbSum + sb; 
                stSum = stSum + st; 
                scaleRatioSum = scaleRatioSum + scaleRatio; 
                m = getMoveRatio(scaledRule.getAntecedents()[i], observation.getAntecedents()[i]); 
                System.out.println(i + "'th dimension: " + "m=" + m); 
                transformedRule.getAntecedents()[i] = move((TrapezoidalFuzzyNumber) scaledRule.getAntecedents()[i], m); 
                mSum = mSum + m; 
            } 
        } 
 
        sb = getBottomScaleRate(intermediateRule.getConsequence(), observation.getConsequence()); 
        st = getTopScaleRate(intermediateRule.getConsequence(), observation.getConsequence()); 
        scaleRatio = getScaleRate(intermediateRule.getConsequence(), observation.getConsequence()); 
        scaledRule.setConsequence(scale((TrapezoidalFuzzyNumber) intermediateRule.getConsequence(), sb, st)); 
        System.out.println("Consequence dimension: " + "sb=" + sb + "and " + " st=" + st); 
        System.out.println("Scaled B'':" + scaledRule.getConsequence()); 
        System.out.println("B scaleRatio " + " = " + scaleRatio); 
        m = getMoveRatio(scaledRule.getConsequence(), observation.getConsequence()); 
        transformedRule.setConsequence(move((TrapezoidalFuzzyNumber) scaledRule.getConsequence(), m)); 
        System.out.println("Consequence dimension: " + "m=" + m); 
 
        sb = sb * observation.getAntecedents().length - sbSum; 
        st = st * observation.getAntecedents().length - stSum; 
        scaleRatio = scaleRatio * observation.getAntecedents().length - scaleRatioSum; 
 
        st = getConsequenceScaleRate(scaleRatio, sb, st, intermediateRule.getAntecedents()[missingIndex]); 
 
        System.out.println(missingIndex + " dimension: " + "sb=" + sb + "and " + " st=" + st); 
        System.out.println("A" + missingIndex + "scaleRatio " + " = " + scaleRatio); 
        m = m * observation.getAntecedents().length - mSum; 
        System.out.println(missingIndex + " dimension: " + "m=" + m); 
        scaledRule.setAntecedent(missingIndex, scale((TrapezoidalFuzzyNumber) intermediateRule.getAntecedents()[missingIndex], sb, st)); 
        System.out.println("Scaled A" + missingIndex + "''" + scaledRule.getAntecedents()[missingIndex].toString()); 
        transformedRule.setAntecedent(missingIndex, move((TrapezoidalFuzzyNumber) scaledRule.getAntecedents()[missingIndex], m)); 
        System.out.println("Backward interpolation antecedent:" + "missingIndex " + transformedRule.getAntecedents()[missingIndex].toString()); 
        return transformedRule; 
    } 
 
    private static Rule forwardInterpolation(TrapezoidalFuzzyNumber trapezoidalFuzzyNumber, 
                                             Rule intermediateRule, 
                                             Observation observation) throws Exception { 
        Rule scaledRule = new Rule(intermediateRule); 
        Rule transformedRule = new Rule(intermediateRule); 
        float sb = 0, st = 0, sbSum = 0, stSum = 0, scaleRatio = 0, scaleRatioSum = 0, m = 0, mSum = 0; 
        //forward 
        for (int i = 0; i < observation.getAntecedents().length; i++) { 
            // 
            sb = getBottomScaleRate(intermediateRule.getAntecedent(i), observation.getAntecedent(i)); 
            st = getTopScaleRate(intermediateRule.getAntecedent(i), observation.getAntecedent(i)); 
            scaleRatio = getScaleRate(intermediateRule.getAntecedent(i), observation.getAntecedent(i)); 
            System.out.println(i + "'dimension:" + "sb=" + sb + "and " + " st=" + st); 
            System.out.println("scaleRatio " + i + " = " + scaleRatio); 
            scaledRule.setAntecedent(i, scale((TrapezoidalFuzzyNumber) intermediateRule.getAntecedent(i), sb, st)); 
            System.out.println("A" + i + "''" + scaledRule.getAntecedent(i).toString()); 
            sbSum = sbSum + sb; 
            stSum = stSum + st; 
            scaleRatioSum = scaleRatioSum + scaleRatio; 
 
            m = getMoveRatio(scaledRule.getAntecedent(i), observation.getAntecedent(i)); 
            System.out.println(i + "'dimension:" + "m=" + m); 
            transformedRule.setAntecedent(i, move((TrapezoidalFuzzyNumber) scaledRule.getAntecedent(i), m)); 
            System.out.println("A" + i + "*" + transformedRule.getAntecedent(i).toString()); 
            mSum = mSum + m; 
        } 
        sb = sbSum / observation.getAntecedents().length; 
        st = stSum / observation.getAntecedents().length; 
        scaleRatio = scaleRatioSum / observation.getAntecedents().length; 
 
        st = getConsequenceScaleRate(scaleRatio, sb, st, intermediateRule.getConsequence()); 
        System.out.println("Consequent dimension:" + "sb=" + sb + "and " + " st=" + st); 
        intermediateRule.setConsequence(scale((TrapezoidalFuzzyNumber) intermediateRule.getConsequence(), sb, st)); 
 
        m = mSum / observation.getAntecedents().length; 
        System.out.println("Scaled B'':" + intermediateRule.getConsequence()); 
        System.out.println("Consequent dimension: m=" + m); 
        transformedRule.setConsequence(move((TrapezoidalFuzzyNumber) intermediateRule.getConsequence(), m)); 
        return transformedRule; 
 
    } 
 
 
    /* 
 
    if ((st >= sb) && (sb >= 0)) { 
            st = (st * (a2 - a1) / (sb * (a3 - a0)) - (a2 - a1) / (a3 - a0)) / 
                    (1 - (a2 - a1) / (a3 - a0)); 
        } else if ((sb >= st) && (st >= 0)) { 
            st = (st * (a2 - a1) / (sb * (a3 - a0)) - (a2 - a1) / (a3 - a0)) / 
                    ((a2 - a1) / (a3 - a0)); 
        } else { 
            throw new Exception("Unsupported Scale Rate"); 
        } 
     */ 
 
    @Deprecated 
    private Rule[] getClosestRules(FuzzyNumber subConsequence, 
                                   ArrayList<Rule> rules) { 
        Rule[] closestRules = new Rule[2]; 
        float[] distances = new float[rules.size()]; 
        for (int i = 0; i < rules.size(); i++) { 
            distances[i] = rules.get(i).getConsequence().distanceTo(subConsequence); 
        } 
        float minDistance1 = Float.MAX_VALUE; 
        int minIndex1 = 0; 
        float minDistance2 = Float.MAX_VALUE; 
        int minIndex2 = 0; 
 
        for (int i = 0; i < rules.size(); i++) { 
            if ((Math.abs(distances[i]) < minDistance1) & (distances[i] * distances[minIndex1] < 0)) { 
                minDistance2 = minDistance1; 
                minIndex2 = minIndex1; 
                minDistance1 = Math.abs(distances[i]); 
                minIndex1 = i; 
            } else if ((Math.abs(distances[i]) < minDistance2) & (distances[i] * distances[minIndex1] < 0)) { 
                minDistance2 = Math.abs(distances[i]); 
                minIndex2 = i; 
            } 
        } 
        closestRules[0] = rules.get(minIndex1).clone(); 
        closestRules[1] = rules.get(minIndex2).clone(); 
        return closestRules; 
    } 
 
    public static Rule[] getClosestRules(RuleBase ruleBase, 
                                         Observation observation, 
                                         int numberOfClosestRules, 
                                         boolean useWeightedConsequenceDistance) { 
        sortRuleBase(ruleBase, observation, useWeightedConsequenceDistance); 
        Rule[] closestRules = new Rule[numberOfClosestRules]; 
        List<Rule> tempClosestRules = ruleBase.subList(0, numberOfClosestRules); 
        for (int i = 0; i < numberOfClosestRules; i++) { 
            closestRules[i] = tempClosestRules.get(i); 
        } 
        return closestRules; 
/* 
        closestRules[0] = ruleBase.get(0).clone(); 
        int currentRuleIndex = 1; 
        int startIndex = 1; 
        //boolean valid = true; 
        while (currentRuleIndex != numberOfClosestRules) { 
            for (int i = startIndex; i < ruleBase.size(); i++) { 
                Rule currentRule = ruleBase.get(i); 
                valid = true; 
                for (int j = 0; j < currentRule.getAntecedents().length; j++) { 
                    if (observation.getAntecedents()[j] == null) { 
                        valid = valid & (currentRule.getConsequence() 
                                .distanceTo(observation.getConsequence()) * 
                                closestRules[currentRuleIndex - 1].getConsequence() 
                                        .distanceTo(observation.getConsequence()) < 0); 
                    } else { 
                        valid = valid & 
                                (currentRule.getAntecedents()[j] 
                                        .distanceTo(observation.getAntecedents()[j]) * 
                                        closestRules[currentRuleIndex - 1].getAntecedents()[j] 
                                                .distanceTo(observation.getAntecedents()[j]) < 0); 
                    } 
                } 
                if (valid == true) { 
                    closestRules[currentRuleIndex] = ruleBase.get(i).clone(); 
                    startIndex = i; 
                    currentRuleIndex++; 
                    i = ruleBase.size(); 
                } 
                //startIndex = i; 
 
            } 
            //currentRuleIndex ++; 
        } 
        return closestRules;*/ 
    } 
 
    public static void sortRuleBase(RuleBase ruleBase, Observation observation, boolean useWeightedConsequenceDistance) { 
        Collections.sort(ruleBase, new RuleComparator(observation, useWeightedConsequenceDistance)); 
    } 
 
    public static void printRules(Rule[] rules) { 
        for (int i = 0; i < rules.length; i++) { 
            for (FuzzyNumber fuzzyNumber : rules[i].getAntecedents()) { 
                System.out.print(fuzzyNumber.toString() + "\t"); 
            } 
            System.out.println(rules[i].getConsequence().toString()); 
        } 
    } 
 
    public static void printRule(Rule rule) { 
 
        for (FuzzyNumber fuzzyNumber : rule.getAntecedents()) { 
            if (fuzzyNumber != null) { 
                System.out.print(fuzzyNumber.toString() + "\t"); 
            } else { 
                System.out.print("(null, null, null)" + "\t"); 
            } 
        } 
        if (rule.getConsequence() != null) { 
            System.out.println(rule.getConsequence().toString()); 
        } else { 
            System.out.println("(null, null, null)"); 
        } 
    } 
 
 
    public static void printRules(RuleBase ruleBase) { 
        for (int i = 0; i < ruleBase.size(); i++) { 
            for (FuzzyNumber fuzzyNumber : ruleBase.get(i).getAntecedents()) { 
                System.out.print(fuzzyNumber.toString() + "\t"); 
            } 
            System.out.println(ruleBase.get(i).getConsequence().toString()); 
        } 
        System.out.println("----------------------------"); 
    } 
 
    public static void printRulesInt(RuleBase ruleBase) { 
        for (int i = 0; i < ruleBase.size(); i++) { 
            for (FuzzyNumber fuzzyNumber : ruleBase.get(i).getAntecedents()) { 
                System.out.print(fuzzyNumber.toStringInt() + "\t"); 
            } 
            System.out.println(ruleBase.get(i).getConsequence().toStringInt()); 
        } 
    } 
 
    public static void printRulesTex(RuleBase ruleBase) { 
        for (int i = 0; i < ruleBase.size(); i++) { 
            System.out.print("C" + (i + 1) + " & "); 
            for (FuzzyNumber fuzzyNumber : ruleBase.get(i).getAntecedents()) { 
                System.out.print(fuzzyNumber.toString() + " & "); 
            } 
            System.out.println(ruleBase.get(i).getConsequence().toString() + "\\\\\\hline"); 
        } 
        System.out.println("----------------------------"); 
    } 
 
    public static void printArrays(float[][] arrays) { 
        //StringBuffer stringBuffer = new StringBuffer(); 
        for (int j = 0; j < arrays[0].length; j++) { 
            for (int i = 0; i < arrays.length; i++) { 
                System.out.format("%8.2f", arrays[i][j]); 
        } 
            System.out.print("\n"); 
        } 
        //System.out.println(stringBuffer.toString()); 
    } 
}