/*******************************************************************************
* 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.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
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 sensitivity test implementation uses statistics to analyse the model. It
* should be used with a IWeightModifier that uses several (>10) random
* modifications for each node. After each modification to the node weights the
* value for each alternative of the whole tree is evaluated.
*
* @author Jan Zarnikov
*
*/
public class VarianceSensitivityTest implements ISensitivityTest {
private TreeNode root;
private IAggregator aggregator;
private List<Alternative> alternatives;
private Map<String, DescriptiveStatistics> statisticsMap = new HashMap<String, DescriptiveStatistics>();
public VarianceSensitivityTest(TreeNode root, IAggregator aggregator, List<Alternative> alternatives) {
super();
this.root = root;
this.aggregator = aggregator;
this.alternatives = alternatives;
}
public void afterIteration(ResultNode node) {
for(Alternative a : alternatives) {
double value = aggregator.getAggregatedValue(root, a);
statisticsMap.get(a.getName()).addValue(value);
}
}
public void afterNode(ResultNode node) {
VarianceResult result = new VarianceResult();
for(Alternative a : alternatives) {
String alternativeName = a.getName();
double variance = statisticsMap.get(alternativeName).getVariance();
double average = statisticsMap.get(alternativeName).getMean();
result.addAlternativeResult(a, variance, average);
}
node.setSensitivityAnalysisResult(result);
}
public void beforeIteration(ResultNode node) {
}
public void beforeNode(ResultNode node) {
for(Alternative a : alternatives) {
statisticsMap.put(a.getName(), new DescriptiveStatistics());
}
}
private static class VarianceResult implements ISensitivityAnalysisResult {
private static final DecimalFormat format = new DecimalFormat("#0.00");
private Map<Alternative, Double> variances = new HashMap<Alternative, Double>();
private Map<Alternative, Double> averages = new HashMap<Alternative, Double>();
private static final double THRESHOLD = 0.3;
public String toString() {
return "Variance: " + format.format(getHighestVarianceCoefficient());
}
public boolean isSensitive() {
return getHighestVarianceCoefficient() > THRESHOLD;
}
public void addAlternativeResult(Alternative a, double variance, double average) {
variances.put(a, variance);
averages.put(a, average);
}
private double getVarianceCoefficient(Alternative a) {
double variance = variances.get(a);
double average = averages.get(a);
if(average != 0) {
return Math.sqrt(variance)/average;
} else {
return 0;
}
}
public double getHighestVarianceCoefficient() {
double highest = 0;
for(Alternative a : variances.keySet()) {
double v = getVarianceCoefficient(a);
if(v > highest) {
highest = v;
}
}
return highest;
}
public double getSensitivityCoefficient() {
return getHighestVarianceCoefficient();
}
public double getSensitivityThreashold() {
return THRESHOLD;
}
}
}