Package eu.scape_project.planning.criteria.bean

Source Code of eu.scape_project.planning.criteria.bean.ImportanceAnalysis

/*******************************************************************************
* Copyright 2006 - 2012 Vienna University of Technology,
* Department of Software Technology and Interactive Systems, IFS
*
* 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 eu.scape_project.planning.criteria.bean;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import eu.scape_project.planning.model.TargetValueObject;
import eu.scape_project.planning.model.kbrowser.CriteriaLeaf;
import eu.scape_project.planning.model.kbrowser.VPlanLeaf;
import eu.scape_project.planning.model.measurement.Measure;
import eu.scape_project.planning.model.transform.NumericTransformer;
import eu.scape_project.planning.model.transform.OrdinalTransformer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ImportanceAnalysis implements Serializable {
    private static final long serialVersionUID = -814054847584527659L;
    private static final Logger log = LoggerFactory.getLogger(ImportanceAnalysis.class);

    private List<VPlanLeaf> planLeaves = new ArrayList<VPlanLeaf>();
    private List<VPlanLeaf> mappedPlanLeaves = new ArrayList<VPlanLeaf>();

    private List<PlanInfo> selectedPlans;
    private long nrRelevantPlans;

    private List<ImportanceAnalysisProperty> tableRows;
    private int tableRowsCount = 0;

    public ImportanceAnalysis(final Collection<Measure> measures, final List<VPlanLeaf> planLeaves,
        final List<PlanInfo> selectedPlans) {
        this.planLeaves = planLeaves;
        filterMappedLeaves();

        this.nrRelevantPlans = selectedPlans.size();
        this.selectedPlans = selectedPlans;

        buildTable(measures);
    }

    /**
     * Method responsible for filtering mapped leaves out of all given leaves.
     */
    private void filterMappedLeaves() {
        // Filter mapped PlanLeaves
        mappedPlanLeaves = new ArrayList<VPlanLeaf>(planLeaves.size());
        for (VPlanLeaf pl : planLeaves) {
            if (pl.isMapped()) {
                mappedPlanLeaves.add(pl);
            }
        }
    }

    private void buildTable(Collection<Measure> measures) {
        tableRows = new ArrayList<ImportanceAnalysisProperty>(measures.size());

        for (Measure measure : measures) {
            evaluateCriterion(measure);
        }

        tableRowsCount = tableRows.size();
    }

    private void evaluateCriterion(Measure measure) {
        List<VPlanLeaf> criterionPlanLeaves = getCriterionPlanLeaves(measure);

        if (criterionPlanLeaves.size() > 0) {
            CriteriaLeaf criteriaLeaf = new CriteriaLeaf(nrRelevantPlans);
            criteriaLeaf.setPlanLeaves(criterionPlanLeaves);

            ImportanceAnalysisProperty importanceAnalysisProperty = new ImportanceAnalysisProperty();
            importanceAnalysisProperty.setCategory(measure.getAttribute().getCategory().getName());
            importanceAnalysisProperty.setAttribute(measure.getAttribute().getName());
            importanceAnalysisProperty.setMeasure(measure.getName());

            importanceAnalysisProperty.setIf1(criteriaLeaf.getImportanceFactorIF1());
            importanceAnalysisProperty.setIf2(criteriaLeaf.getImportanceFactorIF2());
            importanceAnalysisProperty.setIf3(criteriaLeaf.getImportanceFactorIF3());
            importanceAnalysisProperty.setIf4(criteriaLeaf.getImportanceFactorIF4());
            importanceAnalysisProperty.setIf5(criteriaLeaf.getImportanceFactorIF5());
            importanceAnalysisProperty.setIf6(criteriaLeaf.getImportanceFactorIF6());
            importanceAnalysisProperty.setIf7(criteriaLeaf.getImportanceFactorIF7());
            importanceAnalysisProperty.setIf8(criteriaLeaf.getImportanceFactorIF8());
            importanceAnalysisProperty.setIf9(criteriaLeaf.getImportanceFactorIF9());
            importanceAnalysisProperty.setIf10(criteriaLeaf.getImportanceFactorIF10());
            importanceAnalysisProperty.setIf11(criteriaLeaf.getImportanceFactorIF11());
            importanceAnalysisProperty.setIf12(criteriaLeaf.getImportanceFactorIF12());
            importanceAnalysisProperty.setIf13(criteriaLeaf.getImportanceFactorIF13());
            importanceAnalysisProperty.setIf14(criteriaLeaf.getImportanceFactorIF14());
            importanceAnalysisProperty.setIf15(criteriaLeaf.getImportanceFactorIF15());
            importanceAnalysisProperty.setIf16(criteriaLeaf.getImportanceFactorIF16());
            importanceAnalysisProperty.setIf17(criteriaLeaf.getImportanceFactorIF17());
            importanceAnalysisProperty.setIf18(criteriaLeaf.getImportanceFactorIF18());

            importanceAnalysisProperty.setIf19(calculateImportanceFactorIF19(selectedPlans, criteriaLeaf));

            tableRows.add(importanceAnalysisProperty);
        }
    }

    /**
     * calculates importance factor "robustness" - the extend to which the
     * measured value of a criterion can change, without impact on the winning
     * alternative - CriteriaLeaf is an entity bean and part of plato-model for
     * the calculations we need PlanInfo and I don't want to pollute plato-model
     * (further) with kbrowser related classes. for this reason the calculation
     * is done here.
     *
     * @param selectedPlans
     * @param criteriaLeaf
     * @return
     */
    private double calculateImportanceFactorIF19(List<PlanInfo> selectedPlans, CriteriaLeaf criteriaLeaf) {
        double sum = 0.0;
        for (VPlanLeaf pLeaf : criteriaLeaf.getPlanLeaves()) {
            String prefix = "IF19 - " + pLeaf.getMeasure().getUri() + ": ";
            double leafFactor = 0.0;
            PlanInfo planInfo = null;
            // retrieve the PlanInfo for this plan
            for (PlanInfo p : selectedPlans) {
                if (p.getId() == pLeaf.getPlanId()) {
                    planInfo = p;
                    break;
                }
            }
            Set<String> competitors = new HashSet<String>(planInfo.getOverallResults().getResults().keySet());
            competitors.remove(planInfo.getWinningAlternative());
            if (competitors.isEmpty()) {
                // sum += leafFactor;
                log.info(prefix + "No competitors left beside " + planInfo.getWinningAlternative() + " in plan: "
                    + planInfo.getId());
                continue;
            }

            double winnerOverallResult = planInfo.getWinningResult();

            // determine result of the nearest non-winning alternative
            String sndAlternative = "";
            double sndOverallResult = Double.MIN_VALUE;
            for (String a : competitors) {
                double result = planInfo.getOverallResults().getResults().get(a);
                if (result > sndOverallResult) {
                    sndOverallResult = result;
                    sndAlternative = a;
                }
            }
            double overallDiffToNext = winnerOverallResult - sndOverallResult;
            // map this difference back as target result for this criterion
            double overallDiffToNextAsTargetValue = overallDiffToNext / pLeaf.getTotalWeight();

            // get the transformed, but not weighted, result of the winning
            // alternative for this criterion
            double winnerTargetValue = pLeaf.getAlternativeResultsAsMap().get(planInfo.getWinningAlternative());

            // calculate the minimal target value, which would cause a change of
            // the winning alternative
            double minTargetValue = winnerTargetValue - overallDiffToNextAsTargetValue;

            // this will be negative, if the difference between 1st and 2nd is
            // too big,
            // and depending on the transformer setting, the minimal possible
            // value could be > 0
            String intermediaryResults = "; overallDiffToNext = " + overallDiffToNext + " = as target value = "
                + overallDiffToNextAsTargetValue + "; minTargetValue = " + minTargetValue
                + "; pLeaf.getPotentialMinimum() = " + pLeaf.getPotentialMinimum();
            if (minTargetValue > pLeaf.getPotentialMinimum()) {
                log.info(prefix + "1st " + planInfo.getWinningAlternative() + ", 2nd : " + sndAlternative
                    + " in plan: " + planInfo.getId());
                // this criterion could be a game changer - map it back to the
                // measurement scale
                if (pLeaf.getTransformer() instanceof NumericTransformer) {
                    NumericTransformer numTransformer = (NumericTransformer) pLeaf.getTransformer();
                    // For numeric values: The percentage that we can change the
                    // value on the (overally!) winning candidate
                    // without the output range changing so much as to make the
                    // winning candidate lose its winning rank

                    // TODO: CHECK: Do we have a problem here? the values of an
                    // alternative are first transformed, then aggregated
                    // therefore we have to transform this winning value also
                    // back ...
                    double winnerMeasuredValue = numTransformer.transformBack(winnerTargetValue);
                    double minMeasuredValue = numTransformer.transformBack(minTargetValue);

                    // TODO: what if the measured value was 0.0?
                    if (winnerMeasuredValue != 0.0) {
                        leafFactor = (winnerMeasuredValue - minMeasuredValue) / winnerMeasuredValue;
                        if (!numTransformer.hasIncreasingOrder()) {
                            leafFactor *= -1.0;
                        }
                    }
                    log.info(prefix + " - numeric = " + leafFactor + intermediaryResults + ";  winnerMeasuredValue = "
                        + winnerMeasuredValue + "; minMeasuredValue = " + minMeasuredValue + "; plan id "
                        + planInfo.getId());
                } else {
                    // it's an ordinal transformer
                    // For ordinals: Percentage of possible alternative values
                    // for the (overally!) winning candidate
                    // that would make the winning candidate lose its winning
                    // rank.
                    // E.g: “good, bad, ugly” > value is good; bad doesn’t
                    // change rank; ugly changes rank: robustness = 1/2 = 0.5
                    int numPossible = 0;
                    Collection<TargetValueObject> targetValueObjects = ((OrdinalTransformer) pLeaf.getTransformer())
                        .getMapping().values();
                    for (TargetValueObject value : targetValueObjects) {
                        if (value.getValue() >= minTargetValue) {
                            numPossible++;
                        }
                    }
                    leafFactor = (double) numPossible / (double) (targetValueObjects.size());
                    log.info(prefix + " - ordinal = " + leafFactor + intermediaryResults + ";  numPossible = "
                        + numPossible + "; numTotal = " + targetValueObjects.size() + "; plan id " + planInfo.getId());
                }

            } else {
                // it's not possible to reduce the value of the winner to this
                // amount
                log.info(prefix + "1st " + planInfo.getWinningAlternative() + ", 2nd : " + sndAlternative
                    + intermediaryResults + " in plan: " + planInfo.getId());
                // leafFactor = 0.0
            }
            sum += leafFactor;
        }
        // TODO: CHECK: How to aggregate - just average values?
        return sum / (double) criteriaLeaf.getPlanLeaves().size();
    }

    /**
     * Method responsible for filtering all leaves which match the given
     * criterion (Property [+ Metric]). Validity check of the input parameters
     * (e.g. property + metric must be measurable) is done in calling code!!
     *
     * @param cMeasurableProperty
     *            property to filter.
     * @param cMetric
     *            metric to filter.
     */
    public List<VPlanLeaf> getCriterionPlanLeaves(Measure measure) {
        List<VPlanLeaf> measurePlanLeaves = new ArrayList<VPlanLeaf>();

        // filter PlanLeaves
        for (VPlanLeaf l : mappedPlanLeaves) {
            // property and metric must match
            if (l.getMeasure().getUri().equals(measure.getUri())) {
                measurePlanLeaves.add(l);
            }
        }

        return measurePlanLeaves;
    }

    /**
     * Exports the current importance table to a csv file.
     */
    public void exportTableToCsv() {

    }

    /**
     * Calculates the average potential output range based on the CPL
     * occurrence.
     *
     * @param criterionPlanLeaves
     *            corresponding plan leaves.
     * @return average potential output range based on the CPL occurrence, if
     *         calculation is possible. If calculation is not possible -1 is
     *         returned.
     */
    /*
     * public double
     * getCPLAvgPotentialOutputRangeOccurrenceBased(List<VPlanLeaf>
     * criterionPlanLeaves) { int appropriateLeaves = 0; double porSum = 0;
     *
     * for (VPlanLeaf l : criterionPlanLeaves) { double por =
     * l.getPotentialOutputRange();
     *
     * // only leaves for which the por can be calculated can be used if (por !=
     * -1) { porSum = porSum + por; appropriateLeaves++; } }
     *
     * if (appropriateLeaves == 0) { return -1; }
     *
     * double avgPor = porSum / appropriateLeaves; return avgPor; }
     */

    /**
     * Calculates the average actual output range based on the CPL occurrence.
     *
     * @param criterionPlanLeaves
     *            corresponding plan leaves.
     * @return average actual output range based on the CPL occurrence, if
     *         calculation is possible. If calculation is not possible -1 is
     *         returned.
     */
    /*
     * public double getCPLAvgActualOutputRangeOccurrenceBased(List<VPlanLeaf>
     * criterionPlanLeaves) { int appropriateLeaves = 0; double aorSum = 0;
     *
     * for (VPlanLeaf l : criterionPlanLeaves) { double aor =
     * l.getActualOutputRange();
     *
     * // only leaves for which the aor can be calculated can be used if (aor !=
     * -1) { aorSum = aorSum + aor; appropriateLeaves++; } }
     *
     * if (appropriateLeaves == 0) { return -1; }
     *
     * double avgAor = aorSum / appropriateLeaves; return avgAor; }
     */

    public void setTableRows(List<ImportanceAnalysisProperty> tableRows) {
        this.tableRows = tableRows;
    }

    public List<ImportanceAnalysisProperty> getTableRows() {
        return tableRows;
    }

    public void setTableRowsCount(int tableRowsCount) {
        this.tableRowsCount = tableRowsCount;
    }

    public int getTableRowsCount() {
        return tableRowsCount;
    }

    /* ----------------- Init ----------------- */

    public String init() {
        log.debug("init finally called");
        return "success";
    }
}
TOP

Related Classes of eu.scape_project.planning.criteria.bean.ImportanceAnalysis

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.