1 | package de.uka.ipd.sdq.simucomframework; |
2 | |
3 | import java.util.Vector; |
4 | |
5 | import javax.measure.Measure; |
6 | import javax.measure.quantity.Duration; |
7 | import javax.measure.quantity.Quantity; |
8 | import javax.measure.unit.SI; |
9 | |
10 | import org.apache.log4j.Logger; |
11 | |
12 | import de.uka.ipd.sdq.probespec.framework.calculator.Calculator; |
13 | import de.uka.ipd.sdq.probespec.framework.calculator.ICalculatorListener; |
14 | import de.uka.ipd.sdq.simucomframework.model.SimuComModel; |
15 | import de.uka.ipd.sdq.simulation.abstractsimengine.SimCondition; |
16 | import de.uka.ipd.sdq.statistics.IBatchAlgorithm; |
17 | import de.uka.ipd.sdq.statistics.estimation.ConfidenceInterval; |
18 | import de.uka.ipd.sdq.statistics.estimation.IConfidenceEstimator; |
19 | |
20 | /** |
21 | * Provides a stop condition which determines when to stop based on the |
22 | * confidence interval around a point estimation (e.g. mean). |
23 | * |
24 | * @author Philipp Merkle |
25 | * |
26 | */ |
27 | public class ConfidenceStopCondition implements SimCondition, ICalculatorListener { |
28 | |
29 | private static final Logger logger = Logger.getLogger(ConfidenceStopCondition.class); |
30 | |
31 | private SimuComModel model; |
32 | |
33 | private String usageScenarioName; |
34 | |
35 | /** mean of the observations and the corresponding confidence interval */ |
36 | private ConfidenceInterval confidence; |
37 | |
38 | private boolean confidenceReached = false; |
39 | |
40 | private IBatchAlgorithm batchAlgorithm; |
41 | |
42 | private IConfidenceEstimator estimator; |
43 | |
44 | private double confidenceLevel; |
45 | |
46 | private double halfWidth; |
47 | |
48 | private int minBatches; |
49 | |
50 | /** |
51 | * |
52 | * @param model |
53 | * @param batchAlgorithm |
54 | * @param confidenceLevel |
55 | * the confidence level. Use values between 0 and 1. |
56 | * @param halfWidth |
57 | * the relative half width of the target confidence interval. Use |
58 | * values between 0 and 1. |
59 | */ |
60 | protected ConfidenceStopCondition(SimuComModel model, |
61 | IBatchAlgorithm batchAlgorithm, IConfidenceEstimator estimator, |
62 | double confidenceLevel, double halfWidth) { |
63 | this.model = model; |
64 | this.batchAlgorithm = batchAlgorithm; |
65 | this.estimator = estimator; |
66 | this.confidenceLevel = confidenceLevel; |
67 | this.halfWidth = halfWidth; |
68 | |
69 | if (model.getConfiguration() |
70 | .getConfidenceModelElementName() == null){ |
71 | throw new RuntimeException("SimuCom tried to set up a ConfidenceStopCondition, but no usage scenario name was given to measure the confidence for."); |
72 | } |
73 | this.usageScenarioName = model.getConfiguration() |
74 | .getConfidenceModelElementName(); |
75 | |
76 | initialize(); |
77 | } |
78 | |
79 | private void initialize() { |
80 | Calculator c = obtainUsageScenarioResponseTimeCalculator(usageScenarioName); |
81 | c.addCalculatorListener(this); |
82 | minBatches = 0; |
83 | } |
84 | |
85 | @Override |
86 | public boolean check() { |
87 | return confidenceReached; |
88 | } |
89 | |
90 | public void calculated(Vector<Measure<?, ? extends Quantity>> resultTuple) { |
91 | Measure<Double, Duration> responseTimeMeasure = (Measure<Double, Duration>) resultTuple.get(0); |
92 | double responseTime = responseTimeMeasure.doubleValue(SI.SECOND); |
93 | |
94 | batchAlgorithm.offerSample(responseTime); |
95 | if (batchAlgorithm.hasValidBatches() |
96 | && batchAlgorithm.getBatchMeans().size() >= minBatches) { |
97 | // estimate actual confidence interval |
98 | ConfidenceInterval ci = estimator.estimateConfidence( |
99 | batchAlgorithm.getBatchMeans(), confidenceLevel); |
100 | |
101 | if (ci != null){ |
102 | // construct target confidence interval |
103 | ConfidenceInterval targetCI = new ConfidenceInterval(ci |
104 | .getMean(), halfWidth, confidenceLevel); |
105 | |
106 | if (targetCI.contains(ci)) { |
107 | logger.info("Requested confidence reached."); |
108 | confidenceReached = true; |
109 | this.confidence = ci; |
110 | |
111 | // request another batch in order to proceed with improving |
112 | // confidence interval's half-width until the simulation |
113 | // actually stops. |
114 | minBatches = batchAlgorithm.getBatchMeans().size() + 1; |
115 | } else { |
116 | logger.info("Requested confidence not yet reached."); |
117 | |
118 | // request another batch in order to reduce the confidence |
119 | // interval's half-width |
120 | minBatches = batchAlgorithm.getBatchMeans().size() + 1; |
121 | } |
122 | logger.info("Current confidence interval: Mean " + ci.getMean() |
123 | + ", " + confidenceLevel * 100 |
124 | + "% Confidence Interval " + "[" + ci.getLowerBound() |
125 | + "," + ci.getUpperBound() + "]"); |
126 | } |
127 | } |
128 | } |
129 | |
130 | public ConfidenceInterval getConfidence() { |
131 | return confidence; |
132 | } |
133 | |
134 | /** |
135 | * Returns the calculator for the specified usage scenario's response time. |
136 | * |
137 | * @param usageScenarioName |
138 | * the name of the usage scenario |
139 | * @return |
140 | */ |
141 | private Calculator obtainUsageScenarioResponseTimeCalculator( |
142 | String usageScenarioName) { |
143 | String calculatorId = usageScenarioName; |
144 | return this.model.getProbeSpecContext().getCalculatorRegistry().getCalculatorForId(calculatorId); |
145 | } |
146 | |
147 | } |