Skip to content

Add log-asymmetric-triangular (ltriangle3) distribution - #204

Open
joethorley wants to merge 1 commit into
add-triangle-distributionfrom
joethorley/ltriangle3
Open

joethorley wants to merge 1 commit into
add-triangle-distributionfrom
joethorley/ltriangle3

Conversation

@joethorley

Copy link
Copy Markdown
Member

Builds on #169. Adds ltriangle3, a log-triangular distribution with a skewness parameter, following the ltriangle wiring.

Parameterization

If log(Y) has a triangular distribution with mode locationlog, half-width scalelog and skewness skew in [-1, 1], the support is [locationlog - (1 - skew) scalelog, locationlog + (1 + skew) scalelog]. The total width is 2 scalelog regardless of skew, skew = 0 is ltriangle, positive values lengthen the upper limb and skew = +/-1 is a right triangle with the mode at a support limit.

skew is estimated directly with L-BFGS-B bounds at -1 and 1 (bound = TRUE in dist_data), so right-triangular fits are flagged by ssd_at_boundary() and excluded by ssd_fit_dists() unless at_boundary_ok = TRUE.

Changes

  • R/ltriangle3.R: ssd_pltriangle3()/qltriangle3/rltriangle3/eltriangle3, sltriangle3() starting values, bltriangle3() bounds, and the triangle3_ssd / ltriangle3_ssd helpers used by pdist() and model averaging.
  • src/TMB/ll_ltriangle3.hpp: negative log-likelihood with the same soft-log barrier as ll_ltriangle.hpp, applied per limb; registered in ssdtools_TMBExports.cpp. Verified against the analytic density in R.
  • dist_data row (bcanz FALSE, tails FALSE, npars 3, valid TRUE, bound TRUE); ssd_pmulti/qmulti/rmulti and params.R extended.
  • tests/testthat/test-ltriangle3.R: test_dist, skew = 0 equals ltriangle, support limits and quantile inversion for skew in {-1, -0.5, 0, 0.5, 1}, skew recovery from simulated data, right-triangular boundary flagging, censored and outlier cases, scale invariance, model averaging support limits. Affected snapshots regenerated.
  • distributions.Rmd: new section with pdf/cdf and a figure.

Findings worth knowing

  • Right-triangular optima are common. Across the 61 ssddata datasets, about 10 have their maximum likelihood fit at skew = +/-1 with the mode at the smallest or largest observation (boron is one). This is a property of the triangular likelihood (the density is positive at the support edge only for a right triangle), not of the implementation, and is why the boron tests use at_boundary_ok = TRUE.
  • Starting values matter. The log-likelihood has a kink at every observation. A moment-based start (support just beyond the data, mode from the mean) reached a lower objective than the symmetric start on 27 datasets and a higher one on 16, with the large gains on the largest datasets, so it is the default. On a few datasets L-BFGS-B still stops at a kink short of the optimum.
  • Skew bound margins were tested (skew within +/-(1 - d) for d in 0, 0.001, 0.01, 0.02, 0.05). Exact bounds of +/-1 gave the best convergence record (0 line-search failures on ssddata versus 1 to 12 for the inset margins), so they are kept.
  • Scale-invariance tolerances in the tests are looser than for ltriangle (1e-2) because the optimizer stops within a looser neighbourhood of a kinked optimum.

🤖 Generated with Claude Code

Extend the log-triangular distribution with a skewness parameter `skew`
in [-1, 1]. On the log scale the support is
[locationlog - (1 - skew) scalelog, locationlog + (1 + skew) scalelog],
so skew = 0 recovers ltriangle and skew = +/-1 is a right triangle with
the mode at a support limit. The skew is estimated directly with
L-BFGS-B bounds so right-triangular fits are flagged by
ssd_at_boundary().

Starting values place the support just beyond the data and set the mode
from the mean, which reaches a lower objective than the symmetric start
on most ssddata datasets.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@joethorley
joethorley marked this pull request as ready for review September 9, 2026 16:49

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant