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      /** Empty constructor.
75       * @since 3.0
76       */
77      private RealDistributionComparison() {
78          // nothing to do
79      }
80  
81      /** Add a PDF series.
82       * @param chart chart to which series must be added
83       * @param distribution integer distribution to draw
84       * @param desc description
85       * @param lowerBound lower bound
86       * @param upperBound upper bound
87       */
88      public static void addPDFSeries(Chart chart, RealDistribution distribution, String desc, int lowerBound, int upperBound) {
89          // generates Log data
90          List<Number> xData = new ArrayList<Number>();
91          List<Number> yData = new ArrayList<Number>();
92          int samples = 100;
93          double stepSize = (upperBound - lowerBound) / (double) samples;
94          for (double x = lowerBound; x <= upperBound; x += stepSize) {
95              try {
96                  double density = distribution.density(x);
97                  if (! Double.isInfinite(density) && ! Double.isNaN(density)) {
98                      xData.add(x);
99                      yData.add(density);
100                 }
101             } catch (MathRuntimeException e) {
102                 // ignore
103                 // some distributions may reject certain values depending on the parameter settings
104             }
105         }
106 
107         Series series = chart.addSeries(desc, xData, yData);
108         series.setMarker(SeriesMarker.NONE);
109         series.setLineStyle(new BasicStroke(1.2f));
110     }
111 
112     /** Add a CDF series.
113      * @param chart chart to which series must be added
114      * @param distribution integer distribution to draw
115      * @param desc description
116      * @param lowerBound lower bound
117      * @param upperBound upper bound
118      */
119     public static void addCDFSeries(Chart chart, RealDistribution distribution, String desc, int lowerBound, int upperBound) {
120         // generates Log data
121         List<Number> xData = new ArrayList<Number>();
122         List<Number> yData = new ArrayList<Number>();
123         int samples = 100;
124         double stepSize = (upperBound - lowerBound) / (double) samples;
125         for (double x = lowerBound; x <= upperBound; x += stepSize) {
126           double density = distribution.cumulativeProbability(x);
127           if (! Double.isInfinite(density) && ! Double.isNaN(density)) {
128               xData.add(x);
129               yData.add(density);
130           }
131         }
132 
133         Series series = chart.addSeries(desc, xData, yData);
134         series.setMarker(SeriesMarker.NONE);
135         series.setLineStyle(new BasicStroke(1.2f));
136     }
137 
138     /** Create a chart.
139      * @param title chart title
140      * @param minX minimum abscissa
141      * @param maxX maximum abscissa
142      * @param position position of the legend
143      * @return created chart
144      */
145     public static Chart createChart(String title, int minX, int maxX, LegendPosition position) {
146         Chart chart = new ChartBuilder().width(235).height(200).build();
147 
148         // Customize Chart
149         chart.setChartTitle(title);
150         chart.getStyleManager().setChartTitleVisible(true);
151         chart.getStyleManager().setChartTitleFont(new Font(ARIAL, Font.PLAIN, 10));
152         chart.getStyleManager().setLegendPosition(position);
153         chart.getStyleManager().setLegendVisible(true);
154         chart.getStyleManager().setLegendFont(new Font(ARIAL, Font.PLAIN, 10));
155         chart.getStyleManager().setLegendPadding(6);
156         chart.getStyleManager().setLegendSeriesLineLength(6);
157         chart.getStyleManager().setAxisTickLabelsFont(new Font(ARIAL, Font.PLAIN, 9));
158 
159         chart.getStyleManager().setXAxisMin(minX);
160         chart.getStyleManager().setXAxisMax(maxX);
161         chart.getStyleManager().setChartBackgroundColor(Color.white);
162         chart.getStyleManager().setChartPadding(4);
163 
164         chart.getStyleManager().setChartType(ChartType.Line);
165         return chart;
166     }
167 
168     /** Create a component.
169      * @param distributionName name of the distribution
170      * @param minX minimum abscissa
171      * @param maxX maximum abscissa
172      * @param seriesText descriptions of the series
173      * @param series series
174      * @return create component
175      */
176     public static JComponent createComponent(String distributionName, int minX, int maxX, String[] seriesText, RealDistribution... series) {
177         JComponent container = new JPanel();
178         container.setLayout(new BoxLayout(container, BoxLayout.PAGE_AXIS));
179 
180         container.add(new JLabel(distributionName));
181 
182         Chart chart = createChart("PDF", minX, maxX, LegendPosition.InsideNE);
183         int i = 0;
184         for (RealDistribution d : series) {
185             addPDFSeries(chart, d, seriesText[i++], minX, maxX);
186         }
187         container.add(new XChartPanel(chart));
188 
189         chart = createChart("CDF", minX, maxX, LegendPosition.InsideSE);
190         i = 0;
191         for (RealDistribution d : series) {
192             addCDFSeries(chart, d, seriesText[i++], minX, maxX);
193         }
194         container.add(new XChartPanel(chart));
195 
196         container.setBorder(BorderFactory.createLineBorder(Color.black, 1));
197         return container;
198     }
199 
200     /** Main frame for displaying distributions. */
201     @SuppressWarnings("serial")
202     public static class Display extends ExampleFrame {
203 
204         /** Container. */
205         private JComponent container;
206 
207         /** Simple constructor.
208          */
209         public Display() {
210             setTitle("Hipparchus: Real distributions overview");
211             setSize(1320, 920);
212 
213             container = new JPanel();
214             container.setLayout(new GridBagLayout());
215 
216             GridBagConstraints c = new GridBagConstraints();
217             c.fill = GridBagConstraints.VERTICAL;
218             c.gridx = 0;
219             c.gridy = 0;
220             c.insets = new Insets(2, 2, 2, 2);
221 
222             JComponent comp = null;
223 
224             comp = createComponent("Normal", -5, 5,
225                                    new String[] { "μ=0,σ\u00B2=0.2", "μ=0,σ\u00B2=1", "μ=0,σ\u00B2=5", "μ=-2,σ\u00B2=0.5" },
226                                    new NormalDistribution(0, FastMath.sqrt(0.2)),
227                                    new NormalDistribution(),
228                                    new NormalDistribution(0, FastMath.sqrt(5)),
229                                    new NormalDistribution(-2, FastMath.sqrt(0.5)));
230             container.add(comp, c);
231 
232             c.gridx++;
233             comp = createComponent("Beta", 0, 1,
234                                    new String[] { "α=β=0.5", "α=5,β=1", "α=1,β=3", "α=2,β=2", "α=2,β=5" },
235                                    new BetaDistribution(0.5, 0.5),
236                                    new BetaDistribution(5, 1),
237                                    new BetaDistribution(1, 3),
238                                    new BetaDistribution(2, 2),
239                                    new BetaDistribution(2, 5));
240             container.add(comp, c);
241 
242             c.gridx++;
243             comp = createComponent("Cauchy", -5, 5,
244                                    new String[] { "x=0,γ=0.5", "x=0,γ=1", "x=0,γ=2", "x=-2,γ=1" },
245                                    new CauchyDistribution(0, 0.5),
246                                    new CauchyDistribution(0, 1),
247                                    new CauchyDistribution(0, 2),
248                                    new CauchyDistribution(-2, 1));
249             container.add(comp, c);
250 
251             c.gridx++;
252             comp = createComponent("ChiSquared", 0, 5,
253                                    new String[] { "k=1", "k=2", "k=3", "k=4", "k=6" },
254                                    new ChiSquaredDistribution(1),
255                                    new ChiSquaredDistribution(2),
256                                    new ChiSquaredDistribution(3),
257                                    new ChiSquaredDistribution(4),
258                                    new ChiSquaredDistribution(6));
259             container.add(comp, c);
260 
261             c.gridy++;
262             c.gridx = 0;
263             comp = createComponent("Exponential", 0, 5,
264                                    new String[] { "λ=0.5", "λ=1", "λ=1.5", "λ=2.5" },
265                                    new ExponentialDistribution(0.5),
266                                    new ExponentialDistribution(1),
267                                    new ExponentialDistribution(1.5),
268                                    new ExponentialDistribution(2.5));
269             container.add(comp, c);
270 
271             c.gridx++;
272             comp = createComponent("Fisher-Snedecor", 0, 5,
273                                    new String[] { "d1=1,d2=1", "d1=2,d2=1", "d1=5,d2=2", "d1=100,d2=1", "d1=100,d2=100" },
274                                    new FDistribution(1, 1),
275                                    new FDistribution(2, 1),
276                                    new FDistribution(5, 2),
277                                    new FDistribution(100, 1),
278                                    new FDistribution(100, 100));
279             container.add(comp, c);
280 
281             c.gridx++;
282             comp = createComponent("Gamma", 0, 20,
283                                    new String[] { "k=1,θ=2", "k=2,θ=2", "k=3,θ=2", "k=5,θ=1", "k=9,θ=0.5" },
284                                    new GammaDistribution(1, 2),
285                                    new GammaDistribution(2, 2),
286                                    new GammaDistribution(3, 2),
287                                    new GammaDistribution(5, 1),
288                                    new GammaDistribution(9, 0.5));
289             container.add(comp, c);
290 
291             c.gridx++;
292             comp = createComponent("Levy", 0, 3,
293                                    new String[] { "c=0.5", "c=1", "c=2", "c=4", "c=8" },
294                                    new LevyDistribution(0, 0.5),
295                                    new LevyDistribution(0, 1),
296                                    new LevyDistribution(0, 2),
297                                    new LevyDistribution(0, 4),
298                                    new LevyDistribution(0, 8));
299             container.add(comp, c);
300 
301             c.gridy++;
302             c.gridx = 0;
303             comp = createComponent("Log-Normal", 0, 3,
304                                    new String[] { "μ=0,σ\u00B2=10", "μ=0,σ\u00B2=1.5", "μ=0,σ\u00B2=1", "μ=0,σ\u00B2=0.5", "μ=0,σ\u00B2=0.25", "μ=0,σ\u00B2=0.125" },
305                                    new LogNormalDistribution(0, 10),
306                                    new LogNormalDistribution(0, 1.5),
307                                    new LogNormalDistribution(0, 1),
308                                    new LogNormalDistribution(0, 0.5),
309                                    new LogNormalDistribution(0, 0.25),
310                                    new LogNormalDistribution(0, 0.125));
311             container.add(comp, c);
312 
313             c.gridx++;
314             comp = createComponent("Pareto", 0, 5,
315                                    new String[] { "x=1,α=1", "x=1,α=2", "x=1,α=3", "x=1,α=10" },
316                                    new ParetoDistribution(1, 1),
317                                    new ParetoDistribution(1, 2),
318                                    new ParetoDistribution(1, 3),
319                                    new ParetoDistribution(1, 10));
320             container.add(comp, c);
321 
322             c.gridx++;
323             comp = createComponent("Student-T", -5, 5,
324                                    new String[] { "df=1", "df=2", "df=5", "df=10000" },
325                                    new TDistribution(1),
326                                    new TDistribution(2),
327                                    new TDistribution(5),
328                                    new TDistribution(10000));
329             container.add(comp, c);
330 
331             c.gridx++;
332             comp = createComponent("Weibull", 0, 3,
333                                    new String[] { "λ=0.5,k=1", "λ=1,k=1", "λ=1.5,k=1", "λ=5,k=1" },
334                                    new WeibullDistribution(0.5, 1),
335                                    new WeibullDistribution(1, 1),
336                                    new WeibullDistribution(1.5, 1),
337                                    new WeibullDistribution(5, 1));
338             container.add(comp, c);
339 
340             JScrollPane scrollPane = new JScrollPane(container);
341             add(scrollPane);
342 
343         }
344 
345         /** {@inheritDoc} */
346         @Override
347         public Component getMainPanel() {
348             return container;
349         }
350 
351     }
352 
353     /** Program entry point.
354      * @param args program arguments (unused here)
355      */
356     public static void main(String[] args) {
357         ExampleUtils.showExampleFrame(new Display());
358     }
359 
360 }