pub fn power_law_fit(
data: &[f64],
xmin: Option<f64>,
force_continuous: bool,
) -> Result<PowerLawFit<'_>>Expand description
Fits a power-law distribution to a sample, with the maximum likelihood method of Clauset, Shalizi and Newman.
data holds the samples (e.g. the degrees of the vertices of a graph),
not a histogram or a distribution function. For a given xmin, the
exponent alpha that maximizes the likelihood of the samples >= xmin
is returned. The threshold is:
None: estimated, choosing thexminfor which the Kolmogorov–Smirnov distance between the fitted law and the sample is the smallest (slower, as every distinct value is tried);Some(x): fixed tox; samples belowxare ignored.xmust be positive for a continuous law and at least 1 for a discrete one (soSome(1.0)uses all the positive integer samples);Some(0.0)is rejected by igraph.
A discrete power law is fitted if all samples are integers, unless
force_continuous is true; a continuous one otherwise.
Degenerate samples give degenerate or failed fits. For a discrete law
with no sample reaching the given xmin, igraph returns alpha = inf
and a NaN log-likelihood (check alpha.is_finite() when xmin is
chosen by hand); the continuous fit fails with
ErrorKind::InvalidValue instead, and
a single sample makes both fail.
See also Graph::degree (the usual sample to
fit), and the generators of scale-free graphs
Graph::barabasi_game and
Graph::static_power_law_game.
Reference: A. Clauset, C. R. Shalizi and M. E. J. Newman, Power-law distributions in empirical data, SIAM Review 51(4):661–703, 2009.
Binds igraph_power_law_fit.
Time complexity: O(n log n) in the continuous case with a fixed xmin;
the discrete case is dominated by an L-BFGS optimization; estimating
xmin multiplies the cost by the number of distinct samples.
§Errors
ErrorKind::InvalidValue for invalid
data (e.g. no samples, NaN or infinite samples, an xmin below 1 for
discrete or not positive for continuous samples, discrete samples or
xmin of 2^62 or more), and other kinds for numerical failures of the
fitting procedure.
Integer samples of 2^62 (about 4.6e18) or more are only accepted with
force_continuous = true: for huge discrete samples plfit’s L-BFGS
optimization fails, and igraph 1.0.1 then reads the error message from a
stack buffer that no longer exists. The bound matches the one of
PowerLawFit::p_value, so every discrete fit can be tested.
§Examples
Continuous samples drawn by inverse transform sampling from a power law
with alpha = 2.5 and xmin = 1:
use igraph::{misc, prelude::*};
rng::seed(7)?;
let sample: Vec<f64> =
(0..5000).map(|_| (1.0 - rng::uniform01()).powf(-1.0 / 1.5)).collect();
let fit = misc::power_law_fit(&sample, Some(1.0), false)?;
assert!(fit.continuous);
assert!((fit.alpha - 2.5).abs() < 0.1);
assert_eq!(fit.xmin, 1.0);The degrees of a Barabási–Albert graph (igraph’s
examples/simple/igraph_power_law_fit.c, with the same seed and output):
use igraph::{games::BarabasiOptions, misc, prelude::*};
rng::seed(42)?;
let options = BarabasiOptions {
m: 2,
algorithm: BarabasiAlgorithm::Bag,
..Default::default()
};
let g = Graph::barabasi_game(10_000, &options)?;
let degrees: Vec<f64> = g
.degree(.., NeighborMode::All, Loops::None)?
.into_iter()
.map(|d| d as f64)
.collect();
let fit = misc::power_law_fit(°rees, None, false)?;
assert!(!fit.continuous); // integer samples: a discrete law
assert_eq!(fit.xmin, 7.0);
assert!((fit.alpha - 3.04393).abs() < 1e-5);