Repository: scipy/scipy
File: scipy/stats/_morestats.py (Python)

Code before:

    suggestion = ("Maximum likelihood estimation is known to be challenging "
                  "for the three-parameter Weibull distribution. Consider "
                  "performing a custom goodness-of-fit test using "
                  "`scipy.stats.monte_carlo_test`.")

    if np.allclose(u, np.min(x)) or m < 1:
        # The critical values provided by [7] don't seem to control the
        # Type I error rate in this case. Error out.
        message = ("Maximum likelihood estimation has converged to "
                   "a solution in which the location is equal to the minimum "
                   "of the data, the shape parameter is less than 2, or both. "
                   "The table of critical values in [7] does not "
                   "include this case. " + suggestion)
        raise ValueError(message)

    try:
        # Refine the MLE / verify that first-order necessary conditions are
        # satisfied. If so, the critical values provided in [7] seem reliable.
        with np.errstate(over='raise', invalid='raise'):
            res = optimize.root(dnllf, params[:-1])

        message = ("Solution of MLE first-order conditions failed: "
                   f"{res.message}. `anderson` cannot continue. " + suggestion)
        if not res.success:
            raise ValueError(message)

    except (FloatingPointError, ValueError) as e:
        message = ("An error occurred while fitting the Weibull distribution "
                   "to the data, so `anderson` cannot continue. " + suggestion)
        raise ValueError(message) from e

    m, u = res.x
    s = get_scale(m, u)
    return m, u, s


AndersonResult = _make_tuple_bunch('AndersonResult',
                                   ['statistic', 'critical_values',
                                    'significance_level'], ['fit_result'])


@xp_capabilities(np_only=True)
def anderson(x, dist='norm'):
    """Anderson-Darling test for data coming from a particular distribution.

    The Anderson-Darling test tests the null hypothesis that a sample is
    drawn from a population that follows a particular distribution.
    For the Anderson-Darling test, the critical values depend on
    which distribution is being tested against.  This function works
    for normal, exponential, logistic, weibull_min, or Gumbel (Extreme Value

Review comment (suggestion):
<img width="841" height="45" alt="image" src="https://github.com/user-attachments/assets/c1d2a26a-894f-426c-8947-f1809d83af1a" />


Code after:
    phi = ((mTm - 2*mn**2) / (1 - 2*an**2) if n <= 5
           else (mTm - 2*mn**2 - 2*mnm1**2) / (1 - 2*an**2 - 2*anm1**2))
    a = phi**(-0.5) * m
    if n > 5:
        a = xpx.at(a)[..., -2].set(anm1)
        a = xpx.at(a)[..., 1].set(-anm1)
    a = xpx.at(a)[..., -1].set(an)
    a = xpx.at(a)[..., -0].set(-an)
    W = _swilk_w(y, a, xp=xp)

    # Follows [4] Table 1
    if n <= 11:
        u = n
        gamma = -2.273 + 0.459*u
        mu = 0.5440 - 0.39978*u + 0.025054*u**2 - 0.0006714*u**3
        sigma = math.exp(1.3822 - 0.77857*u + 0.062767*u**2 - 0.0020322*u**3)
        gW = -xp.log(gamma - xp.log(1 - W))
    else:
        u = math.log(n)
        mu = -1.5861 - 0.31082*u - 0.083751*u**2 + 0.0038915*u**3
        sigma = math.exp(-0.4803 - 0.082676*u + 0.0030302*u**2)
        gW = xp.log(1 - W)

    z = (gW - mu) / sigma
    pvalue = special.ndtr(-z)
    return W, pvalue


# Values from [8]
_Avals_norm = array([0.561, 0.631, 0.752, 0.873, 1.035])
_Avals_expon = array([0.916, 1.062, 1.321, 1.591, 1.959])
# From Stephens, M A, "Goodness of Fit for the Extreme Value Distribution",
#             Biometrika, Vol. 64, Issue 3, Dec. 1977, pp 583-588.
_Avals_gumbel = array([0.474, 0.637, 0.757, 0.877, 1.038])
# From Stephens, M A, "Tests of Fit for the Logistic Distribution Based
#             on the Empirical Distribution Function.", Biometrika,
#             Vol. 66, Issue 3, Dec. 1979, pp 591-595.
_Avals_logistic = array([0.426, 0.563, 0.660, 0.769, 0.906, 1.010])
# From Richard A. Lockhart and Michael A. Stephens "Estimation and Tests of
#             Fit for the Three-Parameter Weibull Distribution"
#             Journal of the Royal Statistical Society.Series B(Methodological)
#             Vol. 56, No. 3 (1994), pp. 491-500, table 1. Keys are c*100
_Avals_weibull = [[0.292, 0.395, 0.467, 0.522, 0.617, 0.711, 0.836, 0.931],
                  [0.295, 0.399, 0.471, 0.527, 0.623, 0.719, 0.845, 0.941],
                  [0.298, 0.403, 0.476, 0.534, 0.631, 0.728, 0.856, 0.954],
                  [0.301, 0.408, 0.483, 0.541, 0.640, 0.738, 0.869, 0.969],
                  [0.305, 0.414, 0.490, 0.549, 0.650, 0.751, 0.885, 0.986],
                  [0.309, 0.421, 0.498, 0.559, 0.662, 0.765, 0.902, 1.007],
                  [0.314, 0.429, 0.508, 0.570, 0.676, 0.782, 0.923, 1.030],
                  [0.320, 0.438, 0.519, 0.583, 0.692, 0.802, 0.947, 1.057],
                  [0.327, 0.448, 0.532, 0.598, 0.711, 0.824, 0.974, 1.089],