/******************************************************************************* * 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. * * This work originates from the Planets project, co-funded by the European Union under the Sixth Framework Programme. ******************************************************************************/ package eu.scape_project.planning.model.sensitivity; import java.text.DecimalFormat; import java.util.Iterator; import java.util.List; import java.util.SortedSet; import eu.scape_project.planning.model.Alternative; import eu.scape_project.planning.model.aggregators.IAggregator; import eu.scape_project.planning.model.beans.ResultNode; import eu.scape_project.planning.model.tree.TreeNode; /** * This senstitivity analysis test is similar to the OrderChangeTest. * * At start (with the normal importance weights) the order of the alternatives is evaluated - which * alternative is currently the best, which is second best etc. This is the "normal order". * * After each iteration the alternatives are evaluated again. Then the order of the alternatives is compared * to the "normal order". Afterwards the ratio between the number of all iterations and the number * of iterations where the order has changed is computet (e.g. a node was processed 50 times and in 15 of these * iterations the order of the alternatives has chaged - compared to the "normal order"). * * If the ratio is higher than a certain threshold then the node is considered sensitive. * * @author Jan Zarnikov * */ public class OrderChangeCountTest extends OrderChangeTest { private int orderChangeCount = 0; private int roundCount = 0; public OrderChangeCountTest(TreeNode root, IAggregator aggregator, List<Alternative> alternatives) { super(root, aggregator, alternatives); } public void afterIteration(ResultNode node) { roundCount++; SortedSet<ComparableAlternative> order = getOrder(); // unfortunately we cannot compare order and normalOrder using equals() Iterator<ComparableAlternative> normalOrderIterator = normalOrder.iterator(); if(order.size() != normalOrder.size()) { // huh?! how did this happen? someone has modified the alternatives list return; } for(ComparableAlternative ca : order) { if(!ca.equals(normalOrderIterator.next())) { orderChangeCount++; return; } } } public void afterNode(ResultNode node) { node.setSensitivityAnalysisResult(new OrderChangeCountResult(orderChangeCount, roundCount)); } public void beforeNode(ResultNode node) { orderChangeCount = 0; roundCount = 0; } public String toString() { return "Order changed " + orderChangeCount + "/" + roundCount; } private static class OrderChangeCountResult implements ISensitivityAnalysisResult { private double ratio = Double.NaN; /** * This defines a threshold from which a node is considered sensitive. */ public static final double RATIO_THRESHOLD = 0.03; private static final DecimalFormat format = new DecimalFormat("#0.00"); public OrderChangeCountResult(int orderChangeCount, int roundCount) { ratio = (double) orderChangeCount / (double) roundCount; } public String toString() { if(Double.isInfinite(ratio) || Double.isNaN(ratio)) { return "Change ratio: -"; } else { return "Change ratio: " + format.format(ratio); } } public boolean isSensitive() { if(Double.isInfinite(ratio) || Double.isNaN(ratio)) { return false; } else { return ratio > RATIO_THRESHOLD; } } public double getSensitivityCoefficient() { return (Double.isInfinite(ratio) || Double.isNaN(ratio)) ? 0 : ratio; } public double getSensitivityThreashold() { return RATIO_THRESHOLD; } } }