Add log-asymmetric-triangular (ltriangle3) distribution - #204
Open
joethorley wants to merge 1 commit into
Open
joethorley wants to merge 1 commit into
joethorley wants to merge 1 commit into
Conversation
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
marked this pull request as ready for review
September 9, 2026 16:49
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Builds on #169. Adds
ltriangle3, a log-triangular distribution with a skewness parameter, following theltrianglewiring.Parameterization
If
log(Y)has a triangular distribution with modelocationlog, half-widthscalelogand skewnessskewin [-1, 1], the support is[locationlog - (1 - skew) scalelog, locationlog + (1 + skew) scalelog]. The total width is2 scalelogregardless of skew,skew = 0isltriangle, positive values lengthen the upper limb andskew = +/-1is a right triangle with the mode at a support limit.skewis estimated directly with L-BFGS-B bounds at -1 and 1 (bound = TRUEindist_data), so right-triangular fits are flagged byssd_at_boundary()and excluded byssd_fit_dists()unlessat_boundary_ok = TRUE.Changes
R/ltriangle3.R:ssd_pltriangle3()/qltriangle3/rltriangle3/eltriangle3,sltriangle3()starting values,bltriangle3()bounds, and thetriangle3_ssd/ltriangle3_ssdhelpers used bypdist()and model averaging.src/TMB/ll_ltriangle3.hpp: negative log-likelihood with the same soft-log barrier asll_ltriangle.hpp, applied per limb; registered inssdtools_TMBExports.cpp. Verified against the analytic density in R.dist_datarow (bcanz FALSE, tails FALSE, npars 3, valid TRUE, bound TRUE);ssd_pmulti/qmulti/rmultiandparams.Rextended.tests/testthat/test-ltriangle3.R:test_dist, skew = 0 equalsltriangle, 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
skew = +/-1with 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 useat_boundary_ok = TRUE.ltriangle(1e-2) because the optimizer stops within a looser neighbourhood of a kinked optimum.🤖 Generated with Claude Code