QFlex distribution

Release:

 • 4.6 •  5.0 •  5.1 •  5.2 •  5.3 •  5.4 •   •  6.0 •  6.1 •  6.2 •  6.3 •  6.4 •  6.5 •  6.6 •  7.0 •  7.1

Provided by a downloadable add-in library (not a built-in distribution). Fitting requires the Analytica Optimizer edition.

QFlex( a, K, gamma, lb, ub )

The QFlex distribution ("Quantile Flexibility") is a flexible, quantile-parameterized distribution capable of fitting a wide variety of continuous shapes directly to a set of assessed quantiles — for example a 10-50-90 judgment, or a larger set of assessed percentiles. Use it when standard parametric distributions such as the Normal, LogNormal, or Beta are too restrictive to match what you have assessed, and you want a single smooth distribution that passes through (or near) your elicited quantiles while remaining a valid probability distribution.

You obtain the coefficient vector «a» by fitting it to your assessed quantiles with QFlexFit (see How to use the library below). QFlex then draws a sampled, uncertain value from the fitted distribution, much as you would use a built-in distribution like Normal or LogNormal. Define a Chance variable as QFlex(...).

Reference
Bickel, J. Eric, Connor Colombe, and Benjamin D. Leibowicz. The QFlex Distribution. The University of Texas at Austin. (Under review for publication, June 2026.)
The QFlex distribution and the methods implemented in this library are described in this paper. Because the paper is currently in review, the citation details may change.

QFlex is not a built-in Analytica distribution. It is provided as a downloadable library (see Download and installation). Because the coefficient fit is solved as a quadratic program (QP), the Analytica Optimizer edition is required to fit a QFlex distribution to your data.

Parameters

  • «a»: The QFlex coefficient vector, indexed by «K». You normally obtain this from QFlexFit.
  • «K»: The coefficient Index. Its length is the maximum number of terms. Use, e.g., K := 1..10. (A 1-term QFlex is not a valid distribution, so use at least 2; more terms give a more flexible fit.)
  • «gamma»: (Optional, default 0.5): The centering parameter. Use the same «gamma» that you used when fitting «a». See QFlexEstimateGamma.
  • «lb», «ub»: (Optional): The support bounds. Omit both for an unbounded distribution; supply «lb» only for a lower-bounded [«lb», ∞) distribution; supply both for a bounded [«lb», «ub»] distribution.

About the QFlex distribution

Internally, QFlex builds the distribution's quantile function (the inverse CDF) as a weighted sum of simple, individually valid building blocks: powers of a right-tail exponential, a left-tail (reflected) exponential, and a centered-uniform term. Because every building block is itself a valid, strictly increasing quantile function, a QFlex fit can be kept monotone — a genuine probability distribution — by construction, through simple conditions on its coefficients. This is its main practical advantage over some other flexible quantile-parameterized families such as the Keelin (MetaLog) distribution, which can require more complex constraints to ensure monotonicity. (Note that the Keelin distribution in Analytica automatically enforces these).

Consider QFlex when:

  • You have more assessed (or empirical) quantiles than a standard 2-3 parameter distribution can honor, and you want the distribution to match them rather than only approximate their mean and spread.
  • You want a smooth, valid continuous distribution (with an analytic CDF and PDF) rather than a discrete or purely empirical one.
  • You need control over skewness and tail behavior, or want to shape the left tail, right tail, and center somewhat independently.
  • Your quantity is unbounded, lower-bounded, or bounded — QFlex supports all three.

The number of terms (the length of «K») controls flexibility: more terms can match more assessed quantiles and more complex shapes. With «K» terms you can interpolate up to «K» probability-quantile pairs; with more assessed pairs than terms, the fit is a constrained least-squares fit. You do not need to work through the paper's mathematics to use the library — the functions encapsulate the fitting and the analytic details for practical model building.

Since the Keelin (MetaLog) distribution and QFlex are both highly flexible with largely the same underpinning motivations, the question of when to use one or the other arises. In general, the MetaLog distribution exhibits a greater degree of flexibility, and is more apt to capture distributional variation (and a comparable number of terms), whereas QFlex tends towards a strong unimodal bias and is less likely to display wiggle that may (or may not) actually be present. Both distributions exhibit strong matching to classic Pearson distributions, with QFlex showing a somewhat stronger bias to shapes within the Pearson space. In Analytica, for now, QFlex requires the Optimizer edition whereas MetaLog is available in all editions. For those who have to implement their own code in a different platform, QFlex is easier to implement than MetaLog 2.0.

Download and installation

QFlex is distributed as an Analytica library plus a demonstration model, both plain .ana files:

  • Library: QFlex distribution library.anaDownload
  • Demo model: Demo of QFlex distribution.anaDownload

To use the library in your own model, open your model and choose File → Add Library..., select QFlex distribution library.ana, and link it. The library's functions then become available in your model. The demo model already includes the library and shows the full workflow.

Requirements

  • Analytica Optimizer edition. The fitting function QFlexFit solves a quadratic program, which requires Optimizer. (Once you have a fitted coefficient vector, the remaining functions — QFlex, CumQFlex, CumQFlexInv, and DensQFlex — are ordinary evaluations and do not themselves require Optimizer; but in normal use you fit with QFlexFit, so Optimizer is required.)
  • Analytica 7.x or later is recommended.

How to use the library

The workflow has three steps:

  1. Compute the centering parameter «gamma». Use QFlexEstimateGamma( p, q, I ) on your assessed probability-quantile pairs, or specify a «gamma» yourself if you have a preferred value. Keep that «gamma» and pass the same value to the later functions.
  2. Fit the coefficient vector «a». Use QFlexFit( p, q, I, K, gamma, numTerms ) with your probabilities «p», quantiles «q», the assessment index «I», and the coefficient index «K». (This step requires the Optimizer edition.)
  3. Use the fitted distribution. Call QFlex( a, K, gamma, lb, ub ) to construct the uncertain quantity, or use CumQFlexInv, CumQFlex, and DensQFlex for the inverse CDF, CDF, and density at specific points. Use the same «gamma» and «K» that you used when fitting.

Because «gamma» is an explicit parameter to the QFlex functions, it is best to compute or choose «gamma» once and then pass that same value consistently to the fitting and evaluation functions.

Examples

Fit to assessed quantiles

Suppose you have assessed ten quantiles of an uncertain quantity. Define an index of the assessed probabilities, the assessed quantile values, and a coefficient index:

Index Quantile_probability := [0.01, 0.05, 0.1, 0.25, 0.5, 0.75, 0.9, 0.95, 0.99, 0.999]
Variable Assessed_quantiles := Table( Quantile_probability )( ... )   (your ten assessed quantile values)
Index K_terms := 1..10

Then carry out the three steps:

Variable Gamma_to_use := QFlexEstimateGamma( Quantile_probability, Assessed_quantiles, Quantile_probability )
Variable QFlex_coefficients := QFlexFit( Quantile_probability, Assessed_quantiles, Quantile_probability, K_terms, Gamma_to_use )
Chance Fitted_distribution := QFlex( QFlex_coefficients, K_terms, Gamma_to_use )

Now Fitted_distribution is an uncertain quantity you can use anywhere in your model. You can also read the fitted distribution analytically at specific points:

CumQFlexInv( 0.9, QFlex_coefficients, K_terms, Gamma_to_use )   the fitted 90th percentile
CumQFlex( x, QFlex_coefficients, K_terms, Gamma_to_use )   the CDF, P(X ≤ x)
DensQFlex( x, QFlex_coefficients, K_terms, Gamma_to_use )   the density (PDF) at x

Bounded and semi-bounded fits

To fit a distribution known to be non-negative (for example, a cost or a physical quantity), pass a lower bound to the construction and evaluation functions:

QFlex( QFlex_coefficients, K_terms, Gamma_to_use, lb: 0 )   lower-bounded at 0
QFlex( QFlex_coefficients, K_terms, Gamma_to_use, lb: 0, ub: 100 )   bounded on [0, 100]

Use the same «lb» and «ub» consistently across QFlex, CumQFlex, CumQFlexInv, and DensQFlex so they all describe the same distribution.

Fitting the distribution to your data

These two functions are used before constructing the distribution, to estimate the centering parameter and fit the coefficients.

QFlexEstimateGamma( p, q, I )

Estimates the QFlex centering parameter «gamma» from assessed probability-quantile pairs («p», «q») indexed by «I». It estimates Q(0.1), Q(0.5), and Q(0.9) from your assessed quantiles by interpolation, computes the Kelly skewness index SI, and returns gamma = 0.5 × (1 − SI), clipped to the open interval (0, 1).

  • «p»: The assessed probabilities, each in (0, 1), indexed by «I».
  • «q»: The corresponding assessed quantile values, indexed by «I».
  • «I»: The Index over the assessments.

Returns gamma = 0.5 for a symmetric assessment with no skew (0.45 in the exactly symmetric case, matching the paper's convention), a value greater than 0.5 for right-skewed assessments, and less than 0.5 for left-skewed ones. If fewer than three points are supplied, it returns 0.5.

Why «gamma» matters: it centers the centered-uniform basis terms. Choosing «gamma» from the assessed skewness (rather than always 0.5) keeps the fit well-conditioned — important especially when your assessed probabilities are symmetric about 0.5.

QFlexFit( p, q, I, K, gamma, numTerms )

Fits the QFlex coefficient vector «a» (indexed by «K») to your assessed pairs («p», «q») by constrained least squares: it minimizes squared quantile error subject to the monotonicity constraints (tail-coefficient nonnegativity and the tail-center magnitude bound) from the paper, so the fitted distribution is valid by construction. Requires the Analytica Optimizer edition (the fit is a QP).

  • «p», «q»: The assessed probabilities and quantiles, indexed by «I».
  • «I»: The Index over the assessments.
  • «K»: The coefficient Index; its length sets the maximum number of terms.
  • «gamma»: (Optional): The centering parameter. If omitted, QFlexFit estimates it internally via QFlexEstimateGamma. Best practice: compute «gamma» once with QFlexEstimateGamma and pass it explicitly, so the same value is used for both fitting and evaluation.
  • «numTerms»: (Optional): How many terms (≤ IndexLength(K)) to actually fit. If omitted, all of «K» is used. If «numTerms» is less than the length of «K», the result is still indexed by «K» and is Null in the positions beyond «numTerms».

Returns the coefficient vector «a» indexed by «K» (with Null in any unused positions). Pass this vector, with the same «K» and «gamma», to QFlex, CumQFlex, CumQFlexInv, or DensQFlex.

Analytic distribution functions

These functions evaluate the fitted distribution analytically at a point (or an array of points), without sampling. They all take the fitted coefficient vector «a» indexed by «K», the centering parameter «gamma», and the same optional bounds «lb»/«ub» described under QFlex.

CumQFlexInv( p, a, K, gamma, lb, ub )

The analytic inverse cumulative (quantile) function: returns the value «x» such that P(X ≤ «x») = «p». Evaluate it at a probability «p» (or an array of probabilities) to read quantiles off the fitted distribution. This is the closed-form construction; QFlex simply calls it with a uniform random «p».

  • «p»: A probability in [0, 1] (or an array of them).
  • «a», «K», «gamma», «lb», «ub»: As for QFlex.

Example: CumQFlexInv( 0.9, QFlex_coefficients, K_terms, Gamma_to_use ) returns the fitted 90th percentile.

CumQFlex( x, a, K, gamma, lb, ub )

The analytic cumulative distribution function: returns P(X ≤ «x») for a value «x». It is computed by numerically inverting the quantile function (bisection), giving the analytic CDF at a point, independent of sampling.

  • «x»: The value (or array of values) at which to evaluate the CDF.
  • «a», «K», «gamma», «lb», «ub»: As for QFlex.

Example: CumQFlex( 0, QFlex_coefficients, K_terms, Gamma_to_use )

DensQFlex( x, a, K, gamma, lb, ub )

The analytic probability density function f(«x»): returns the density at a value «x», using the quantile-density relationship (no sampling required). This is convenient for plotting a smooth PDF curve over a grid of «x» values.

  • «x»: The value (or array of values) at which to evaluate the density.
  • «a», «K», «gamma», «lb», «ub»: As for QFlex.

Example: DensQFlex( Plot_x, QFlex_coefficients, K_terms, Gamma_to_use )

Note on bounds: An upper bound must be supplied together with a lower bound. Specifying «ub» without «lb» is not supported, and the analytic CDF/PDF return Null in that case. For an upper-bounded quantity, use the bounded [«lb», «ub»] form.

The demo model

The demo model Demo of QFlex distribution.ana provides an interactive playground:

  • Editable assessed quantiles for several example data sets (a symmetric logistic, a right-skewed lognormal, a heavy-tailed Student-t, and two bimodal shapes), selectable individually.
  • A number-of-terms control to explore how flexibility changes the fit.
  • Live graphs of the fitted inverse CDF, CDF, and PDF, built from CumQFlexInv, CumQFlex, and DensQFlex.
  • A QA-tests module with analytically tractable checks (for example, the coefficient vector «a» = [0, 1, 1] reproduces the standard logistic quantile), useful as worked sanity checks.

See Also

Comments


You are not allowed to post comments.