View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  package org.hipparchus.samples;
23  
24  import java.awt.BasicStroke;
25  import java.awt.Color;
26  import java.awt.Component;
27  import java.awt.Font;
28  import java.awt.GridBagConstraints;
29  import java.awt.GridBagLayout;
30  import java.awt.Insets;
31  import java.util.ArrayList;
32  import java.util.List;
33  
34  import javax.swing.BorderFactory;
35  import javax.swing.BoxLayout;
36  import javax.swing.JComponent;
37  import javax.swing.JLabel;
38  import javax.swing.JPanel;
39  import javax.swing.JScrollPane;
40  
41  import org.hipparchus.distribution.RealDistribution;
42  import org.hipparchus.distribution.continuous.BetaDistribution;
43  import org.hipparchus.distribution.continuous.CauchyDistribution;
44  import org.hipparchus.distribution.continuous.ChiSquaredDistribution;
45  import org.hipparchus.distribution.continuous.ExponentialDistribution;
46  import org.hipparchus.distribution.continuous.FDistribution;
47  import org.hipparchus.distribution.continuous.GammaDistribution;
48  import org.hipparchus.distribution.continuous.LevyDistribution;
49  import org.hipparchus.distribution.continuous.LogNormalDistribution;
50  import org.hipparchus.distribution.continuous.NormalDistribution;
51  import org.hipparchus.distribution.continuous.ParetoDistribution;
52  import org.hipparchus.distribution.continuous.TDistribution;
53  import org.hipparchus.distribution.continuous.WeibullDistribution;
54  import org.hipparchus.exception.MathRuntimeException;
55  import org.hipparchus.samples.ExampleUtils.ExampleFrame;
56  import org.hipparchus.util.FastMath;
57  
58  import com.xeiam.xchart.Chart;
59  import com.xeiam.xchart.ChartBuilder;
60  import com.xeiam.xchart.Series;
61  import com.xeiam.xchart.SeriesMarker;
62  import com.xeiam.xchart.StyleManager.ChartType;
63  import com.xeiam.xchart.StyleManager.LegendPosition;
64  import com.xeiam.xchart.XChartPanel;
65  
66  /**
67   * Displays pdf/cdf for real distributions.
68   */
69  public class RealDistributionComparison {
70  
71      /** Arial font. */
72      private static final String ARIAL = "Arial";
73  
74      /** Mu 0, sigma 1. */
75      private static final String MU_0_SIGMA_02 = "μ=0,σ\u00B2=0.2";
76  
77      /** Mu 0, sigma 1. */
78      private static final String MU_0_SIGMA_1 = "μ=0,σ\u00B2=1";
79  
80      /** Mu 0, sigma 1. */
81      private static final String MU_0_SIGMA_5 = "μ=0,σ\u00B2=5";
82  
83      /** Mu 0, sigma 1. */
84      private static final String MU_M2_SIGMA_05 = "μ=-2,σ\u00B2=0.5";
85  
86      /** Empty constructor.
87       * @since 3.0
88       */
89      private RealDistributionComparison() {
90          // nothing to do
91      }
92  
93      /** Add a PDF series.
94       * @param chart chart to which series must be added
95       * @param distribution integer distribution to draw
96       * @param desc description
97       * @param lowerBound lower bound
98       * @param upperBound upper bound
99       */
100     public static void addPDFSeries(Chart chart, RealDistribution distribution, String desc, int lowerBound, int upperBound) {
101         // generates Log data
102         List<Number> xData = new ArrayList<Number>();
103         List<Number> yData = new ArrayList<Number>();
104         int samples = 100;
105         double stepSize = (upperBound - lowerBound) / (double) samples;
106         for (double x = lowerBound; x <= upperBound; x += stepSize) {
107             try {
108                 double density = distribution.density(x);
109                 if (! Double.isInfinite(density) && ! Double.isNaN(density)) {
110                     xData.add(x);
111                     yData.add(density);
112                 }
113             } catch (MathRuntimeException e) {
114                 // ignore
115                 // some distributions may reject certain values depending on the parameter settings
116             }
117         }
118 
119         Series series = chart.addSeries(desc, xData, yData);
120         series.setMarker(SeriesMarker.NONE);
121         series.setLineStyle(new BasicStroke(1.2f));
122     }
123 
124     /** Add a CDF series.
125      * @param chart chart to which series must be added
126      * @param distribution integer distribution to draw
127      * @param desc description
128      * @param lowerBound lower bound
129      * @param upperBound upper bound
130      */
131     public static void addCDFSeries(Chart chart, RealDistribution distribution, String desc, int lowerBound, int upperBound) {
132         // generates Log data
133         List<Number> xData = new ArrayList<Number>();
134         List<Number> yData = new ArrayList<Number>();
135         int samples = 100;
136         double stepSize = (upperBound - lowerBound) / (double) samples;
137         for (double x = lowerBound; x <= upperBound; x += stepSize) {
138           double density = distribution.cumulativeProbability(x);
139           if (! Double.isInfinite(density) && ! Double.isNaN(density)) {
140               xData.add(x);
141               yData.add(density);
142           }
143         }
144 
145         Series series = chart.addSeries(desc, xData, yData);
146         series.setMarker(SeriesMarker.NONE);
147         series.setLineStyle(new BasicStroke(1.2f));
148     }
149 
150     /** Create a chart.
151      * @param title chart title
152      * @param minX minimum abscissa
153      * @param maxX maximum abscissa
154      * @param position position of the legend
155      * @return created chart
156      */
157     public static Chart createChart(String title, int minX, int maxX, LegendPosition position) {
158         Chart chart = new ChartBuilder().width(235).height(200).build();
159 
160         // Customize Chart
161         chart.setChartTitle(title);
162         chart.getStyleManager().setChartTitleVisible(true);
163         chart.getStyleManager().setChartTitleFont(new Font(ARIAL, Font.PLAIN, 10));
164         chart.getStyleManager().setLegendPosition(position);
165         chart.getStyleManager().setLegendVisible(true);
166         chart.getStyleManager().setLegendFont(new Font(ARIAL, Font.PLAIN, 10));
167         chart.getStyleManager().setLegendPadding(6);
168         chart.getStyleManager().setLegendSeriesLineLength(6);
169         chart.getStyleManager().setAxisTickLabelsFont(new Font(ARIAL, Font.PLAIN, 9));
170 
171         chart.getStyleManager().setXAxisMin(minX);
172         chart.getStyleManager().setXAxisMax(maxX);
173         chart.getStyleManager().setChartBackgroundColor(Color.white);
174         chart.getStyleManager().setChartPadding(4);
175 
176         chart.getStyleManager().setChartType(ChartType.Line);
177         return chart;
178     }
179 
180     /** Create a component.
181      * @param distributionName name of the distribution
182      * @param minX minimum abscissa
183      * @param maxX maximum abscissa
184      * @param seriesText descriptions of the series
185      * @param series series
186      * @return create component
187      */
188     public static JComponent createComponent(String distributionName, int minX, int maxX, String[] seriesText, RealDistribution... series) {
189         JComponent container = new JPanel();
190         container.setLayout(new BoxLayout(container, BoxLayout.PAGE_AXIS));
191 
192         container.add(new JLabel(distributionName));
193 
194         Chart chart = createChart("PDF", minX, maxX, LegendPosition.InsideNE);
195         int i = 0;
196         for (RealDistribution d : series) {
197             addPDFSeries(chart, d, seriesText[i++], minX, maxX);
198         }
199         container.add(new XChartPanel(chart));
200 
201         chart = createChart("CDF", minX, maxX, LegendPosition.InsideSE);
202         i = 0;
203         for (RealDistribution d : series) {
204             addCDFSeries(chart, d, seriesText[i++], minX, maxX);
205         }
206         container.add(new XChartPanel(chart));
207 
208         container.setBorder(BorderFactory.createLineBorder(Color.black, 1));
209         return container;
210     }
211 
212     /** Main frame for displaying distributions. */
213     @SuppressWarnings("serial")
214     public static class Display extends ExampleFrame {
215 
216         /** Container. */
217         private JComponent container;
218 
219         /** Simple constructor.
220          */
221         public Display() {
222             setTitle("Hipparchus: Real distributions overview");
223             setSize(1320, 920);
224 
225             container = new JPanel();
226             container.setLayout(new GridBagLayout());
227 
228             GridBagConstraints c = new GridBagConstraints();
229             c.fill = GridBagConstraints.VERTICAL;
230             c.gridx = 0;
231             c.gridy = 0;
232             c.insets = new Insets(2, 2, 2, 2);
233 
234             JComponent comp = null;
235 
236             comp = createComponent("Normal", -5, 5,
237                                    new String[] { MU_0_SIGMA_02, MU_0_SIGMA_1, MU_0_SIGMA_5, MU_M2_SIGMA_05 },
238                                    new NormalDistribution(0, FastMath.sqrt(0.2)),
239                                    new NormalDistribution(),
240                                    new NormalDistribution(0, FastMath.sqrt(5)),
241                                    new NormalDistribution(-2, FastMath.sqrt(0.5)));
242             container.add(comp, c);
243 
244             c.gridx++;
245             comp = createComponent("Beta", 0, 1,
246                                    new String[] { "α=β=0.5", "α=5,β=1", "α=1,β=3", "α=2,β=2", "α=2,β=5" },
247                                    new BetaDistribution(0.5, 0.5),
248                                    new BetaDistribution(5, 1),
249                                    new BetaDistribution(1, 3),
250                                    new BetaDistribution(2, 2),
251                                    new BetaDistribution(2, 5));
252             container.add(comp, c);
253 
254             c.gridx++;
255             comp = createComponent("Cauchy", -5, 5,
256                                    new String[] { "x=0,γ=0.5", "x=0,γ=1", "x=0,γ=2", "x=-2,γ=1" },
257                                    new CauchyDistribution(0, 0.5),
258                                    new CauchyDistribution(0, 1),
259                                    new CauchyDistribution(0, 2),
260                                    new CauchyDistribution(-2, 1));
261             container.add(comp, c);
262 
263             c.gridx++;
264             comp = createComponent("ChiSquared", 0, 5,
265                                    new String[] { "k=1", "k=2", "k=3", "k=4", "k=6" },
266                                    new ChiSquaredDistribution(1),
267                                    new ChiSquaredDistribution(2),
268                                    new ChiSquaredDistribution(3),
269                                    new ChiSquaredDistribution(4),
270                                    new ChiSquaredDistribution(6));
271             container.add(comp, c);
272 
273             c.gridy++;
274             c.gridx = 0;
275             comp = createComponent("Exponential", 0, 5,
276                                    new String[] { "λ=0.5", "λ=1", "λ=1.5", "λ=2.5" },
277                                    new ExponentialDistribution(0.5),
278                                    new ExponentialDistribution(1),
279                                    new ExponentialDistribution(1.5),
280                                    new ExponentialDistribution(2.5));
281             container.add(comp, c);
282 
283             c.gridx++;
284             comp = createComponent("Fisher-Snedecor", 0, 5,
285                                    new String[] { "d1=1,d2=1", "d1=2,d2=1", "d1=5,d2=2", "d1=100,d2=1", "d1=100,d2=100" },
286                                    new FDistribution(1, 1),
287                                    new FDistribution(2, 1),
288                                    new FDistribution(5, 2),
289                                    new FDistribution(100, 1),
290                                    new FDistribution(100, 100));
291             container.add(comp, c);
292 
293             c.gridx++;
294             comp = createComponent("Gamma", 0, 20,
295                                    new String[] { "k=1,θ=2", "k=2,θ=2", "k=3,θ=2", "k=5,θ=1", "k=9,θ=0.5" },
296                                    new GammaDistribution(1, 2),
297                                    new GammaDistribution(2, 2),
298                                    new GammaDistribution(3, 2),
299                                    new GammaDistribution(5, 1),
300                                    new GammaDistribution(9, 0.5));
301             container.add(comp, c);
302 
303             c.gridx++;
304             comp = createComponent("Levy", 0, 3,
305                                    new String[] { "c=0.5", "c=1", "c=2", "c=4", "c=8" },
306                                    new LevyDistribution(0, 0.5),
307                                    new LevyDistribution(0, 1),
308                                    new LevyDistribution(0, 2),
309                                    new LevyDistribution(0, 4),
310                                    new LevyDistribution(0, 8));
311             container.add(comp, c);
312 
313             c.gridy++;
314             c.gridx = 0;
315             comp = createComponent("Log-Normal", 0, 3,
316                                    new String[] { "μ=0,σ\u00B2=10", "μ=0,σ\u00B2=1.5", MU_0_SIGMA_1, "μ=0,σ\u00B2=0.5", "μ=0,σ\u00B2=0.25", "μ=0,σ\u00B2=0.125" },
317                                    new LogNormalDistribution(0, 10),
318                                    new LogNormalDistribution(0, 1.5),
319                                    new LogNormalDistribution(0, 1),
320                                    new LogNormalDistribution(0, 0.5),
321                                    new LogNormalDistribution(0, 0.25),
322                                    new LogNormalDistribution(0, 0.125));
323             container.add(comp, c);
324 
325             c.gridx++;
326             comp = createComponent("Pareto", 0, 5,
327                                    new String[] { "x=1,α=1", "x=1,α=2", "x=1,α=3", "x=1,α=10" },
328                                    new ParetoDistribution(1, 1),
329                                    new ParetoDistribution(1, 2),
330                                    new ParetoDistribution(1, 3),
331                                    new ParetoDistribution(1, 10));
332             container.add(comp, c);
333 
334             c.gridx++;
335             comp = createComponent("Student-T", -5, 5,
336                                    new String[] { "df=1", "df=2", "df=5", "df=10000" },
337                                    new TDistribution(1),
338                                    new TDistribution(2),
339                                    new TDistribution(5),
340                                    new TDistribution(10000));
341             container.add(comp, c);
342 
343             c.gridx++;
344             comp = createComponent("Weibull", 0, 3,
345                                    new String[] { "λ=0.5,k=1", "λ=1,k=1", "λ=1.5,k=1", "λ=5,k=1" },
346                                    new WeibullDistribution(0.5, 1),
347                                    new WeibullDistribution(1, 1),
348                                    new WeibullDistribution(1.5, 1),
349                                    new WeibullDistribution(5, 1));
350             container.add(comp, c);
351 
352             JScrollPane scrollPane = new JScrollPane(container);
353             add(scrollPane);
354 
355         }
356 
357         /** {@inheritDoc} */
358         @Override
359         public Component getMainPanel() {
360             return container;
361         }
362 
363     }
364 
365     /** Program entry point.
366      * @param args program arguments (unused here)
367      */
368     public static void main(String[] args) {
369         ExampleUtils.showExampleFrame(new Display());
370     }
371 
372 }