---
title: "Vine copula models and structures"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Vine copula models and structures}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
library(rvinecopulib)
set.seed(301)
```

A vine copula decomposes a multivariate dependence model into a sequence of
bivariate copulas. The structure determines which conditioned and conditioning
variables belong to each edge; one `bicop_dist` object supplies the model for
that edge.

## Read an R-vine structure

Consider the triangular array

```
4 4 4 4
3 3 3
2 2
1
```

It represents these pair copulas:

| Tree | Edge | Conditioned pair | Conditioning set |
|---:|---:|---|---|
| 1 | 1 | 1, 4 | — |
| 1 | 2 | 2, 4 | — |
| 1 | 3 | 3, 4 | — |
| 2 | 1 | 1, 3 | 4 |
| 2 | 2 | 2, 3 | 4 |
| 3 | 1 | 1, 2 | 3, 4 |

In R, the structure can be constructed from its order and off-diagonal rows:

```{r structure}
structure <- rvine_structure(
  order = 1:4,
  struct_array = list(c(4, 4, 4), c(3, 3), 2)
)
structure
as_rvine_matrix(structure)
```

The square R-vine matrix contains the same information with zeros filling the
unused triangle. `as_rvine_structure()` converts it back to the compressed
representation.

`cvine_structure()` and `dvine_structure()` construct the two common
order-determined special cases. Random valid structures are available through
`rvine_structure_sim()`.

```{r special-structures}
cvine_structure(c(4, 1, 3, 2))
dvine_structure(c(4, 1, 3, 2))
rvine_structure_sim(4)
```

See `?rvine_structure` for the complete validity and proximity conditions.

## Construct a vine copula from components

For a three-dimensional model, the first tree has two pair copulas and the
second has one. The nested list follows `pair_copulas[[tree]][[edge]]`.

```{r construct-model}
pair_copulas <- list(
  list(
    bicop_dist("gaussian", parameters = 0.6),
    bicop_dist("clayton", parameters = 1.5)
  ),
  list(bicop_dist("frank", parameters = 2))
)
model <- vinecop_dist(
  pair_copulas,
  structure = dvine_structure(1:3)
)
model
summary(model)
```

The model can immediately be evaluated and simulated:

```{r use-model}
u <- rvinecop(5, model)
dvinecop(u, model)
pvinecop(u[1:2, ], model, n_mc = 1000)
```

## Fit and select a model

With no structure supplied, `vinecop()` selects trees sequentially using the
Dissmann algorithm and fits a pair copula on every selected edge.

```{r fit-model}
n <- 150
z <- rnorm(n)
x <- cbind(
  z + rnorm(n, sd = 0.7),
  0.6 * z + rnorm(n),
  -0.4 * z + rnorm(n),
  rnorm(n)
)
u <- pseudo_obs(x)

fit <- vinecop(u, family_set = "onepar", selcrit = "bic")
fit
summary(fit)
```

The most important pair-copula controls (`family_set`, `par_method`,
`nonpar_method`, `mult`, `selcrit`, `weights`, `presel`, and
`allow_rotations`) have the same meaning as in `bicop()`. The [bivariate
copula guide](bivariate-copulas.html) describes the available families,
rotations, and estimation methods.

## Inspect the selected trees

Getters work on both manually constructed and fitted models. Tree and edge
indices are one-based in the R interface.

```{r inspect}
get_structure(fit)
get_matrix(fit)
get_pair_copula(fit, tree = 1, edge = 1)
get_family(fit, tree = 1, edge = 1)
get_parameters(fit, tree = 1, edge = 1)
get_ktau(fit, tree = 1, edge = 1)
get_all_families(fit)
```

`summary(fit)` returns the edge table invisibly, which is convenient for
programmatic inspection.

## Control structure selection

The edge weight used to build each tree is selected by `tree_crit`:

- `"tau"` for absolute Kendall's tau;
- `"rho"` for absolute Spearman's rho;
- `"hoeffd"` for Hoeffding's D;
- `"mcor"` for maximum correlation;
- `"cxi"` for symmetrized Chatterjee's xi;
- `"joe"` for a Gaussian-copula mutual-information criterion;
- a custom function of `data` and `weights`.

`tree_algorithm = "mst_prim"` and `"mst_kruskal"` select a maximum spanning
tree. `"random_weighted"` and `"random_unweighted"` draw random spanning
trees, which can be useful in ensemble or exploratory workflows.

```{r structure-controls, eval=FALSE}
custom_strength <- function(data, weights) {
  if (length(weights)) {
    abs(weighted.mean(data[, 1] * data[, 2], weights))
  } else {
    abs(mean(data[, 1] * data[, 2]))
  }
}

custom_fit <- vinecop(u, tree_crit = custom_strength)
random_fit <- vinecop(u, tree_algorithm = "random_weighted")
```

Custom criteria run on the calling thread. Pair-copula fitting may still use
multiple `cores`.

## Fix all or part of a structure

Supply a full structure to keep it fixed while selecting pair-copula families.
A truncated structure fixes its existing trees and asks `vinecop()` to select
the remaining trees up to `trunc_lvl`.

```{r fixed-structure}
fixed_structure_fit <- vinecop(
  u,
  structure = dvine_structure(1:4),
  family_set = c("gaussian", "clayton")
)

first_tree <- rvine_structure(order = 1:4, struct_array = list(rep(4, 3)))
partial_fit <- vinecop(
  u,
  structure = first_tree,
  family_set = "onepar"
)
```

## Truncation and thresholding

`trunc_lvl` limits the number of fitted trees. Pair copulas above that level are
independence copulas. `threshold` replaces edges whose selection strength is
below the threshold by independence copulas.

```{r sparse-models}
truncated <- vinecop(u, family_set = "onepar", trunc_lvl = 1)
thresholded <- vinecop(u, family_set = "onepar", threshold = 0.1)
truncate_model(fit, trunc_lvl = 1)
```

Set `trunc_lvl = NA` or `threshold = NA` to select the value automatically with
mBICV. The fitted threshold and truncation level are visible in the model
summary.

## Refit an existing model

Pass a fitted model through `vinecop_object` to update parameters while keeping
its structure and families fixed. This is useful for rolling windows or
bootstrap samples.

```{r refit}
refitted <- vinecop(u, vinecop_object = fit)
stopifnot(identical(get_all_families(refitted), get_all_families(fit)))
```

For a manually constructed distribution, use `vinecop()` to select from data
or construct a new `vinecop_dist()` after changing its components.

## Related documentation

- [Bivariate copula models](bivariate-copulas.html) provides the details of
  the pair-copula building blocks.
- [Discrete, mixed, and zero-inflated data](discrete-data.html) explains the
  copula-scale representation required when some variables have atoms.
- [Conditional simulation and Rosenblatt
  transforms](conditional-simulation.html) describes conditioning-aware
  structures and sampling orders.
- [Scores, Hessians, and varying parameters](likelihood-inference.html)
  explains edge parameter ordering and stepwise versus full derivatives.
- The [`vinecop()` reference](../reference/vinecop.html) lists all fitting and
  selection arguments; the [structure reference](../reference/rvine_structure.html)
  gives the formal matrix validity conditions.
