Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
c0659c6
Document test architecture redesign plan
lrnv Aug 26, 2026
e67450c
Require Julia 1.11 and refine API test plan
lrnv Aug 26, 2026
db35586
Record public API visibility decisions
lrnv Aug 26, 2026
165f131
Define the supported public API surface
lrnv Aug 26, 2026
309e362
Move the legacy test suite under test old
lrnv Aug 26, 2026
3c4d615
Keep Aqua in the active test suite
lrnv Aug 26, 2026
c6cb800
Plan the public API contract test migration
lrnv Aug 26, 2026
ca90744
Add public copula contract test harness
lrnv Aug 26, 2026
e61d44c
Test standalone public APIs and dispatch paths
lrnv Aug 26, 2026
b528dc5
Add generator and tail component contracts
lrnv Aug 26, 2026
66c6676
Complete the public SklarDist parameter API
lrnv Aug 26, 2026
8338987
Complete copula parameter introspection
lrnv Aug 26, 2026
ce07c56
Correct contract fixtures and dimensional semantics
lrnv Aug 26, 2026
c925c10
Replace the monolithic generic test matrix
lrnv Aug 26, 2026
aa12e1a
Enhance tests for copula functionality and mathematical coherence
lrnv Aug 26, 2026
2e1828d
Honor public univariate and generator contracts
lrnv Aug 26, 2026
396fd33
Co-locate public contract tests and fix their harness
lrnv Aug 26, 2026
1306e23
Restore the remaining test redesign roadmap
lrnv Aug 26, 2026
1e9f56d
Complete canonical constructors for public copulas
lrnv Aug 26, 2026
709faf1
Make the public API contract exhaustive
lrnv Aug 26, 2026
b27b974
Complete the public API contract audit
lrnv Aug 27, 2026
0475a6b
Document and enforce the test architecture
lrnv Aug 27, 2026
e926076
Prune redundant legacy test coverage
lrnv Aug 27, 2026
76653ec
move parameter dof
lrnv Aug 27, 2026
fbef349
Define the mathematical test reference strategy
lrnv Aug 27, 2026
b420cca
Add comprehensive tests for specialized copulas and oracles
lrnv Aug 27, 2026
5434642
few corrections
lrnv Aug 27, 2026
96d4d31
typo
lrnv Aug 27, 2026
5515a3a
Fix constructor and copula contracts
lrnv Aug 27, 2026
4d771d6
Consolidate mathematical coherence tests
lrnv Aug 27, 2026
a982658
Fix contract paths exposed by CI
lrnv Aug 27, 2026
694154c
Fix API contracts exposed by CI
lrnv Aug 27, 2026
7ecc082
Fix discrete spectral method load order
lrnv Aug 27, 2026
db00920
Fix BB constructors and trace copula contracts
lrnv Aug 27, 2026
1ec0688
Deduplicate dependence contract execution
lrnv Aug 27, 2026
73881ef
Fix contracts and paths exposed by CI
lrnv Aug 27, 2026
587d6ef
Fix Tawn fitting capability signature
lrnv Aug 27, 2026
3c1166b
Add shared univariate component contracts
lrnv Aug 27, 2026
971f4a5
Build exhaustive dispatch path registry
lrnv Aug 27, 2026
5aac7f5
Migrate family and extension regressions
lrnv Aug 27, 2026
58a7fe6
Document test proof obligations
lrnv Aug 27, 2026
c6b5946
Organize tests by proof obligation
lrnv Aug 27, 2026
6cf1bc6
Complete test proof obligations
lrnv Aug 28, 2026
a49e01f
Cover optional plotting extension
lrnv Aug 28, 2026
6748b1a
Document non-generic equivalence oracles
lrnv Aug 28, 2026
b70dde6
Fix failures exposed by test obligations
lrnv Aug 28, 2026
b0a7f02
Close remaining public-tail coverage gaps
lrnv Aug 28, 2026
6396885
Record remaining proof-obligation gaps
lrnv Aug 28, 2026
ada5705
Complete deterministic path oracles
lrnv Aug 28, 2026
ee2bd34
Close major proof-obligation gaps
lrnv Aug 28, 2026
464a454
Enhance testing for copula methods and improve proof obligations
lrnv Aug 28, 2026
8162105
Complete dimension-aware route proofs
lrnv Aug 28, 2026
2d3584c
Complete public adapter and dispatch proofs
lrnv Aug 28, 2026
30b3a16
Fix and streamline test proof oracles
lrnv Aug 28, 2026
fedbf53
Clarify and streamline test reporting
lrnv Aug 28, 2026
af2aac6
Track public behavior and internal test branches
lrnv Aug 28, 2026
e76f50c
correction TOML
lrnv Aug 28, 2026
16d05a1
Fix test oracles and cut expensive duplicate routes
lrnv Aug 28, 2026
03435df
Instrument and streamline test execution
lrnv Aug 29, 2026
7498495
Reduce test harness specialization
lrnv Aug 29, 2026
50443aa
Shard exhaustive test obligations
lrnv Aug 29, 2026
1cab3af
remove sharding
lrnv Aug 29, 2026
01f809e
Complete exhaustive test proof ledgers
lrnv Aug 29, 2026
f4c1ff8
Fix exhaustive test proof failures
lrnv Aug 29, 2026
1fdc894
Keep t-EV fitting inside dimensional bounds
lrnv Aug 29, 2026
0a6e1d2
Close remaining test routing gaps
lrnv Aug 29, 2026
3e538c3
Prune superseded family regressions
lrnv Aug 29, 2026
a5236c9
Classify cross-family tests by proof obligation
lrnv Aug 29, 2026
7adeaa1
Enhance test coverage and correctness for copula models
lrnv Aug 29, 2026
091a05b
up
lrnv Aug 29, 2026
991f90a
Stabilize numerical correctness oracles
lrnv Aug 29, 2026
099cefe
Enhance test coverage for copula models by adding new tests for error…
lrnv Aug 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ concurrency:

jobs:
test:
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }}
name: Julia ${{ matrix.version }} - ${{ github.event_name }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
version:
- 'lts'
- '1.11'
- '1'
os:
- ubuntu-latest
Expand All @@ -48,13 +48,22 @@ jobs:
- uses: julia-actions/cache@v3
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-runtest@v1
env:
COPULAS_TEST_TIMINGS: ${{ github.workspace }}/test-timings.toml
with:
force_latest_compatible_version: ${{ matrix.version == 'lts' && 'false' || 'auto' }}
coverage: ${{ matrix.version == 'lts' }}
force_latest_compatible_version: ${{ matrix.version == '1.11' && 'false' || 'auto' }}
coverage: ${{ matrix.version == '1.11' }}
- uses: actions/upload-artifact@v7
if: always()
with:
name: test-timings-julia-${{ matrix.version }}
path: test-timings.toml
if-no-files-found: warn
- uses: julia-actions/julia-processcoverage@v1
if: matrix.version == 'lts'
if: matrix.version == '1.11'
- uses: codecov/codecov-action@v7
if: matrix.version == 'lts'
if: matrix.version == '1.11'
with:
files: lcov.info
name: julia-${{ matrix.version }}
token: ${{ secrets.CODECOV_TOKEN }}
6 changes: 4 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,10 @@ StableRNGs = "1"
Statistics = "1"
StatsBase = "0.33, 0.34"
StatsFuns = "0.9, 1.3, 2"
TOML = "1.0.3"
TaylorSeries = "0.20, 0.21, 0.22"
Test = "1"
julia = "1"
julia = "1.11"

[extras]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
Expand All @@ -76,6 +77,7 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76"

[targets]
test = ["Test", "InteractiveUtils", "LinearAlgebra", "HypothesisTests", "Aqua", "StableRNGs", "StatsBase", "DelimitedFiles", "ExpectationMaximization"]
test = ["Test", "InteractiveUtils", "LinearAlgebra", "HypothesisTests", "Aqua", "StableRNGs", "StatsBase", "DelimitedFiles", "ExpectationMaximization", "Plots", "RecipesBase", "TOML"]
29 changes: 27 additions & 2 deletions docs/src/api/public.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,32 @@ CurrentModule = Copulas

# Public API

This page lists all public docstrings exposed by the package.
This page lists all public docstrings exposed by the package.

## Behavioural contract

The public API consists of documented symbols declared with `export` or
`public`, together with the documented methods that Copulas.jl adds to adopted
interfaces such as Distributions.jl and StatsBase.jl. These behaviours follow
semantic versioning; implementation hooks described in the developer guide do
not.

| Area | Public operations | Guaranteed behaviour |
|:--|:--|:--|
| Construction | `Family{d}(parameters...)`, `Family(d, parameters...)` | Both forms select dimension `d`, validate their inputs and construct equivalent models. A family may document an additional dimension-inferred form. |
| Distribution | `length`, `eltype`, `params`, `cdf`, `logcdf`, `rand` | Every copula is a multivariate distribution with uniform margins and support in the unit hypercube. Vector and matrix sampling preserve dimension and numeric type. |
| Density | `pdf`, `logpdf`, `loglikelihood` | Available for absolutely continuous components. Singular and mixed copulas follow their documented generalized-density semantics and need not possess a Lebesgue density. |
| Marginalization | `subsetdims` | Preserves the requested coordinates and their order. One coordinate yields its univariate marginal. |
| Conditioning | `condition` | Produces the conditional univariate distortion or lower-dimensional distribution, with generalized quantiles where atoms occur. |
| Transforms | `rosenblatt`, `inverse_rosenblatt` | Vector and matrix forms are supported. Round-trip bijectivity is guaranteed only for continuous models without atoms. |
| Dependence | `τ`, `ρ`, `β`, `γ`, `ι`, `λₗ`, `λᵤ`, their documented inverses, `StatsBase.corkendall`, `StatsBase.corspearman` | Results have the documented scalar or pairwise-matrix shape, bounds and symmetry. Closed forms and numerical fallbacks have the same contract. |
| Fitting | `fit`, `CopulaModel` and the StatsBase model interface | Documented family/method pairs return valid fitted models. `CopulaModel` exposes observations, coefficients, covariance when computed, information criteria, residuals and prediction. |
| Composition | `SklarDist` | Distribution operations, marginalization, conditioning and Rosenblatt transforms are expressed on the marginal scales. |
| Utilities | `pseudos`, `measure`, `Nataf` | Rank pseudo-observations, copula rectangle probability, and Nataf correlation correction respectively. |

The mathematical primitives documented for public generators and extreme-value
tails are also stable. Concrete internal wrappers, caches, samplers and fallback
selection are deliberately outside this contract.

```@autodocs
Modules = [Copulas]
Expand All @@ -16,4 +41,4 @@ Private = false
```@bibliography
Pages = [@__FILE__]
Canonical = false
```
```
7 changes: 1 addition & 6 deletions docs/src/bestiary/archimedean.md
Original file line number Diff line number Diff line change
Expand Up @@ -357,12 +357,7 @@ WilliamsonGenerator
EmpiricalGenerator
```

### `TiltedGenerator`
```@docs; canonical=false
TiltedGenerator
```

### `FrailtyGenerator`
### `FrailtyGenerator`
```@docs; canonical=false
FrailtyGenerator
```
Expand Down
12 changes: 4 additions & 8 deletions docs/src/bestiary/miscellaneous.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,11 @@ WCopula
SurvivalCopula
```

### `SubsetCopula`
### Subsetting

```@docs; canonical = false
Copulas.subsetdims
```

```@docs; canonical = false
Copulas.SubsetCopula
```
```@docs; canonical = false
Copulas.subsetdims
```

## Others

Expand Down
2 changes: 1 addition & 1 deletion docs/src/examples/liouville.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ The bivariate CDF uses a one-dimensional radial/Beta expectation. In higher dime

## Conditioning and Rosenblatt transforms

Conditioning preserves the Liouville structure. If the generator has a frailty, Copulas.jl conditions that frailty directly: its posterior is tilted by `v^sum(α[J]) * exp(-sJ*v)`, which works uniformly for integer and non-integer parameters. For generators without a frailty, integer orders reuse `TiltedGenerator` and fractional orders use the exact conditional-radial representation. The public interface is unchanged:
Conditioning preserves the Liouville structure. If the generator has a frailty, Copulas.jl conditions that frailty directly: its posterior is tilted by `v^sum(α[J]) * exp(-sJ*v)`, which works uniformly for integer and non-integer parameters. Generators without a frailty use exact order-reduction or conditional-radial representations internally. The public interface is unchanged:

```@example liouville
conditional_23_given_1 = condition(C, 1, 0.4)
Expand Down
38 changes: 17 additions & 21 deletions docs/src/manual/conditioning_and_subsetting.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ On the original scale for a compound distribution `X = SklarDist(C, (X_1,…,X_D
F_{X_i\mid X_J}(x\mid \mathbf x_J) = H_{i\mid J}\big(F_i(x)\mid \mathbf u_J\big).
```

The copula of the conditional vector $U_I | U_J = u_J$ is a genuine copula denoted $C_{I|J}(·|u_J)$, which is the copula of $H_{I|J}$. In our implementation, this is materialized by the a `ConditionalCopula(C, J, u_J)` and used internally by `condition`. The `condition` function can be used as follows:
The copula of the conditional vector $U_I | U_J = u_J$ is a genuine copula denoted $C_{I|J}(·|u_J)$, which is the copula of $H_{I|J}$. The public entry point is `condition`:

- `condition(C::Copula, js, u_js)` returns the conditional distribution on the uniform scale for `I = setdiff(1:D, js)`. If `length(I) == 1`, the result is a univariate distribution supported on $[0,1]$, subclass of `Distortion`, and otherwise it is a `SklarDist(::ConditionalCopula, NTuple{d,<:Distortion})`.
- `condition(X::SklarDist, js, x_js)` returns the conditional distribution on the original scale by pushing forward each distortion through the corresponding marginal.
- For known parametric families, there are fast paths implemented mostly as subclass to `Distortions` or `ConditionalCopula`, but this should be completely transparent to the user.
- `condition(C::Copula, js, u_js)` returns the conditional distribution on the uniform scale for `I = setdiff(1:D, js)`. If `length(I) == 1`, the result is a univariate distribution supported on $[0,1]`; otherwise it is a multivariate distribution implementing the usual `Distributions.jl` interface.
- `condition(X::SklarDist, js, x_js)` returns the conditional distribution on the original scale by pushing forward each distortion through the corresponding marginal.
- Known parametric families may use specialized representations, but their concrete types are implementation details and do not change this contract.

!!! tip "Missing fast-paths?"
If you find a conditional that should admit a faster closed-form or semi-analytic path but currently falls back to the generic construction, please open an issue, we’ll happily implement it :)
Expand Down Expand Up @@ -99,9 +99,9 @@ H = condition(ClaytonCopula(4, 4.2), (2, 3), (0.25, 0.8))
plot(H)
```

### Relation to the conditional copula
### Relation to the conditional copula

The conditional copula $C_{I|J}(·|u_J)$ is the copula of the conditional distribution $H_{I|J}(·|u_J)$. In the implementation it is represented by `ConditionalCopula(C, js, u_js)` and is used as the copula of the conditional joint when `|I| > 1`. When `condition` returns a `SklarDist` (i.e., when `|I| > 1`), you can access this copula directly via the `.C` field of the returned object:
The conditional copula $C_{I|J}(·|u_J)$ is the copula of the conditional distribution $H_{I|J}(·|u_J)$. A multivariate result currently follows the `SklarDist` interface, so its copula and margins can be inspected as follows. Code should nevertheless rely on the public distribution interface rather than on a particular internal wrapper type:

```@example cond1
H.C # the copula
Expand All @@ -114,13 +114,10 @@ H.m # the marginals

### Implementation

```@docs; canonical=false
condition
Distortion
DistortionFromCop
DistortedDist
ConditionalCopula
```
```@docs; canonical=false
condition
Distortion
```


### See also
Expand All @@ -140,7 +137,7 @@ There are two entry points:
- `subsetdims(X::SklarDist, dims)` returns a `SklarDist` with copula `subsetdims(C, dims)`
and marginals `(m[i] for i in dims)`.

Internally, we materialize subsetting with a small wrapper type `SubsetCopula{p}(C, dims)` which delegates `cdf`, `pdf`, and sampling to the base copula by saturating non-selected coordinates at 1. For many families we provide specialized constructors that return the natural reduced-parameter form instead of a wrapper (e.g., elliptical copulas return the appropriate submatrix, Archimedean keeps the same generator with reduced dimension, etc.). It can be used as follows:
The concrete representation is family-dependent. Some families return a natural reduced-parameter form, while the generic path uses an internal delegating representation. Both implement the same public copula interface:

```@example subset1
using Copulas, Distributions
Expand All @@ -155,9 +152,9 @@ X13 = subsetdims(X, (1,3)) # keeps marginals (Normal(), LogNormal()) and reduce
length(X13.C), length(X13.m)
```

The resulting object depends on the copula familly, since some fast paths are given. If no specialization exists, a `SubsetCopula` wrapper is returned. It’s fully usable and equivalent from an API perspective; specialized forms simply yield better performance and clearer display.
Subsetting and conditioning commute in the obvious way: conditioning on coordinates `J` and then extracting a subset of the remaining coordinates is equivalent to subsetting the base copula first and then conditioning on the corresponding indices. In code, if `S = subsetdims(C, dims)`, conditioning on indices `js` within `S` is implemented by mapping `js` to indices in the base copula and delegating to `ConditionalCopula(C, ·, ·)`; the resulting conditional copula of `S` is either the base conditional copula (when all remaining coordinates are kept) or a further `SubsetCopula` of it.
The exact result type is not part of the contract. Specialized forms may provide better performance or clearer display, while every result remains usable through the same copula API.

Subsetting and conditioning commute in the obvious way: conditioning on coordinates `J` and then extracting a subset of the remaining coordinates is equivalent to subsetting the base copula first and then conditioning on the corresponding indices.

### Examples

Expand All @@ -179,10 +176,9 @@ typeof(S13), S13 isa SurvivalCopula

### Implementation

```@docs; canonical=false
Copulas.subsetdims
Copulas.SubsetCopula
```
```@docs; canonical=false
Copulas.subsetdims
```

## Rosenblatt transformations

Expand Down
Loading
Loading