Changelog

0.8.0

Breaking API changes in pyvinecopulib

  • Reorganize the public API into the core / families / utils / sklearn subpackages (#207).

    • Top-level classes (Bicop, Vinecop, RVineStructure, CVineStructure, DVineStructure, FitControlsBicop, FitControlsVinecop, BicopFamily) and to_pseudo_obs are kept at the top level indefinitely.

    • Family constants / groups (indep, gaussian, …, parametric, …, itau), Kde1d, wdm, sobol, ghalton, simulate_uniform, benchmark, pairs_copula_data still resolve at the top level but emit a DeprecationWarning on access pointing at the canonical subpackage path. Aliases are scheduled for removal in the next major release.

    • repr and pickle now use canonical module paths (Bicop.__module__ == "pyvinecopulib.core", Kde1d.__module__ == "pyvinecopulib.utils", etc.); pickles from releases up to 0.7.x still load via the deprecated aliases.

  • pyvinecopulib.sklearn estimators take a single backend= keyword (#218).

    • VineDensity(controls=..., structure=..., seed=...)VineDensity(backend=VinecopBackend(controls=..., structure=...), random_state=...). Same shape change for VineRegressor / VineForestDensity / VineForestRegressor. No string shortcuts; pass a VinecopBackend or TorchVinecopBackend instance.

    • seed-style kwargs renamed to random_state across the forests and on sample / cdf / cdf. Legacy seed / seeds kwargs removed without a deprecation alias.

    • VineRegressor gains a real normalize_weights=True __init__ parameter; the previous post-init _normalize_weights attribute is gone.

  • from_data now dispatches on controls=FitControlsTorchBicop(...) (#217). Callers who passed grid_size, mult, or grid_type as keyword arguments must move them onto the dataclass. cache_integrals, device, and dtype remain direct kwargs on from_data.

  • TorchBicop.sample(num_sample, seed, is_sobol) renamed to TorchBicop.simulate(n, qrng=False, seeds=[]) for parity with pv.Bicop.simulate (#216).

  • Remove TorchBicop’s log_pdf method. The vine pdf cascade now accumulates a product of per-edge pdf (rather than a log-sum-exp), so the pair-level log-density convenience method is no longer needed; it was never part of the BicopLike contract. Use TorchBicop.pdf(u).log() if you need a log density.

New features in pyvinecopulib

  • Add backend-neutral pair-copula / vine contracts to pyvinecopulib.core: the generic, runtime_checkable protocols BicopLike / VinecopLike and BicopBase, their canonical array-backend-agnostic (NumPy / PyTorch, via array_api_compat) partial implementation. BicopLike mirrors the C++ Bicop evaluation surface exactly (pdf / cdf / hfunc1 / hfunc2 / hinv1 / hinv2, with an optional trailing x conditioning matrix; no dtype / device, since an nn.Module-backed pair has no intrinsic precision/placement), so the C++ Bicop / Vinecop satisfy BicopLike / VinecopLike structurally (isinstance is True); the x conditioning matrix appears symmetrically on both (per-pair on BicopLike, per-call on VinecopLike). a custom pair need only implement pdf / hfunc1 / hfunc2 and inherits hinv1 / hinv2 (bisection), simulate (inverse Rosenblatt of the pair, via a _simulate_uniform RNG hook), loglik (sum(log pdf), differentiable on autograd backends), plot (density contour / surface), and a structural __repr__ from BicopBase. simulate is part of the BicopLike contract (symmetric with VinecopLike; the C++ Bicop provides it). TorchBicop now subclasses BicopBase[torch.Tensor]. These are the extension point for custom (e.g. neural, conditional) pair copulas, and pyvinecopulib.core imports without PyTorch.

  • Extract the vine evaluation cascades onto an array-agnostic VinecopBase in pyvinecopulib.core (NumPy / PyTorch): pdf / cdf / rosenblatt / inverse_rosenblatt / simulate, plus loglik / plot / __repr__ / dim / get_pair_copula and the public fit engine. Conditioning is threaded per edge through a pluggable ConditioningContext (SimplifiedContext default — external covariates only; NonSimplifiedContext also gathers the edge’s conditioning-set values u_D): fit(structure, u, fit_edge, *, context=, x=) builds a non-simplified / conditional vine, assembling each pair’s x_e in the fixed C1 column order (u_D in ascending conditioning-tree index, then external covariates x). A backend hosting arbitrary (e.g. scikit-style, conditional) pair copulas subclasses VinecopBase directly. TorchVinecop subclasses VinecopBase[torch.Tensor], stays an nn.Module vine of TorchBicop pairs (GPU / autograd / state_dict honour the whole object), keeps the batched TLL fast path (falling back when a pair lacks the grid internals), and inherits loglik / plot. Behavior-preserving: the pdf cascade is a product of per-edge densities and the torch↔Vinecop (1e-10) / batched↔non-batched (1e-12) parity are unchanged.

  • Fuse the batched TLL evaluation lookups (torch): with cache_integrals=True, the per-tree-level batched pdf / hfunc1 / hfunc2 (and hfunc1 / hfunc2 for the Rosenblatt cascade) now share a single bilinear cell search + weight computation via interpolate_batched_many over a stacked (N, K, m, m) cache, instead of recomputing the same cell index / weights 3× (pdf cascade) or 2× (Rosenblatt) per level. Bit-for-bit identical to the separate lookups (the batched↔per-pair 1e-15 and torch↔C++ 1e-10 parity gates are unchanged). On CUDA the batched fast path this optimizes runs ~6–18× faster than the non-batched cascade (pdf / rosenblatt, d = 10–20, n = 2000–10000; e.g. pdf at d = 20, n = 10000: ~388 → 22 ms) and up to ~16–18× faster than single-threaded C++; this fusion trims the redundant per-level cell searches on that path (benchmark: scripts/bench_torch_vinecop.py).

  • Add pyvinecopulib.sklearn with scikit-learn-compatible VineDensity and VineRegressor estimators following the BaseEstimator / DensityMixin / RegressorMixin protocols, with mixed continuous/discrete input handling (DataFrame or ndarray) (#211).

  • Add VineForestDensity and VineForestRegressor: ensembles of vine estimators sampled either uniformly (Joe’s algorithm) or via Wilson’s Kendall’s-τ-weighted random walk, pruned by a model-confidence-set survivor test on a held-out split (#213).

  • Add the pyvinecopulib.torch subpackage: pure-PyTorch TorchBicop / TorchVinecop evaluators (nn.Module subclasses) for GPU placement, autograd, and nn.Module pipeline composition. The torch cascade matches the C++ TLL fit to machine precision (#216).

  • Add a sklearn-side backend layer (pyvinecopulib.sklearn.backends): VinecopBackend (default, C++) and TorchVinecopBackend (opt-in PyTorch) route the same estimator class through either backend; both produce fitted vines that satisfy the canonical pyvinecopulib.core.VinecopLike protocol (#218).

  • Add from_structure, simulate, and cdf (quasi-MC) so the torch evaluators mirror their pv.Vinecop counterparts (#216).

  • from_data now selects an R-vine structure automatically when structure=None, mirroring pv.Vinecop.from_data, while a supplied structure still fixes the skeleton and fits only the pair copulas. With the API gap closed, the two pyvinecopulib.sklearn backends collapse onto a single shared base: VinecopBackend and TorchVinecopBackend now differ only in the divergent members, the name / supports_discrete / supports_cdf / supports_simulate capability flags are gone (the continuous-only guard lives on from_data), and resolve_backend only defaults None. pyvinecopulib.torch no longer re-exports InterpolationGrid2D (it stays an internal detail of TorchBicop) (#241).

  • Port vine structure selection into the array-agnostic VinecopBase, so TorchVinecop.from_data(structure=None) selects the R-vine natively in torch instead of round-tripping through Vinecop. VinecopBase.select(u, fit_edge, *, trunc_lvl=, tree_criterion=, threshold=, tree_algorithm=, seeds=, to_numpy=) is the array-agnostic (NumPy / PyTorch) Dissmann / Wilson selector, an exact port of Vinecop’s: it builds each tree’s candidate graph under the proximity condition (same enumeration order), weights edges by 1 - |tau| (Kendall’s tau via wdm), keeps a spanning tree, fits the pair copulas to propagate h-functions, finalizes the chosen edges into an RVineStructure with the same peel and diagonal policy, and returns (structure, pair_copulas) — the selection-time pairs reoriented onto their finalized slots, so (like Vinecop) no re-fit happens. The fixed-structure fit engine is exposed as fit (renamed from the unreleased sequential_fit), so VinecopBase now mirrors Vinecop’s select / fit by name — both differ only in being functional (they return the structure / fitted pairs rather than mutating the vine in place, since VinecopBase leaves pair storage to the subclass). Given identical pair fits, the selected matrix encoding, the reused pairs, and the resulting density are identical to from_data’s (bit-for-bit on the NumPy path; to TLL-fit precision, ~1e-13, on the torch path). Two scoped C++ primitives support it: RVineStructure.from_trees(d, trees) (reuses upstream’s RVineTrees peel — the exact finalization Vinecop uses) and an internal boost-based spanning-tree helper (prim / kruskal / Wilson). The BicopLike contract gains a flip() method (return the argument-swapped copula) used to reorient reused pairs: flip() is now bound (returns a flipped copy), flip() transposes its interpolation grid, and BicopBase ships a raising default (custom pairs only need it to be hosted in selection). The structure_controls field on FitControlsTorchVinecop (a nested FitControlsVinecop, added in the unreleased #241) is replaced by native fields trunc_lvl / tree_criterion / threshold / tree_algorithm / seeds; both sklearn backends now steer selection through these same-named fields, dropping the last backend-specific indirection. Structure selection is continuous-only and TLL-only on the torch path; automatic truncation / thresholding (aic / bic / mbicv) is not ported (trunc_lvl is a fixed cap) (#244).

  • Flip torch defaults based on a bicop + vine benchmark sweep: cache_integrals=True everywhere (80–300× faster cdf / hfunc / hinv on cpu, 2–80× on cuda), batched resolves device-aware via _default_batched() (True on cuda, False on cpu) (#219).

  • Add a tutorial-style docs/concepts.rst introducing Sklar’s theorem, pair-copula construction, R-vines, and the TLL family in a ~5-minute read (#218).

  • Use Sphinx autosummary on the four subpackage landing pages so module docstrings, classes, and free functions get their own indexed pages (#214).

  • Add a custom tree_criterion for vine structure selection: set FitControlsVinecop(tree_criterion="custom") and supply tree_criterion_function, a callable f(data, weights) -> float mapping a two-column array of pair pseudo-observations (and observation weights) to a scalar edge weight (its absolute value is used). The callable round-trips through pickle when it is picklable (e.g. a module-level function); calls acquire the GIL, so they serialise under num_threads > 1 (vinecopulib#674).

  • Add per-row-parameter overloads of pdf / cdf / hfunc1 / hfunc2 / hinv1 / hinv2 / loglik: pass an (n, p) array of parameters (one row per observation, p family parameters each) plus an optional num_threads to evaluate the copula with a different parameter set per row in a single (optionally threaded) call, instead of reusing the object’s stored parameters. Parametric families only (vinecopulib#675).

  • Expose the vine gradient/diagnostics surface on Vinecop: pdf_full (density plus, with keep_all=True, the per-edge densities and h-functions, returned as a dict of [tree][edge] nested arrays; the left-limit hfunc*_sub entries are only populated for models with discrete variables), scores (observation-wise score matrix), hessian (average Hessian), hessian_full (per-observation Hessians), and scores_cov (score covariance). Scores and Hessians are computed analytically (models with discrete variables fall back to finite differences); models with nonparametric pair copulas raise RuntimeError. Mirrors the R additions in rvinecopulib#320 (vinecopulib#679, vinecopulib#683).

  • Port the closed-form TLL conditional-quantile inversion (vinecopulib#691) to the torch backend: InterpolationGrid2D.inverse_integrate_1d inverts the piecewise-quadratic conditional cdf exactly, replacing the vectorized ITP root-finder in hinv1 / hinv2 (cache_integrals=False) and in the inverse-cache construction. The no-cache h-inverse now matches the C++ Bicop.hinv* to machine precision (~1e-15, was root-finder-limited) and is ~60–120× faster on cpu (1.4 ms vs 171 ms for 10k points; see scripts/bench_torch_bicop_fit.py --mode hinv); the internal _util.solve_itp helper is removed (a reference copy lives in the benchmark script).

  • Add binary CBOR model persistence: to_file / to_file / to_file and the matching from_file factories select CBOR automatically when the filename ends in .cbor; all other filenames keep reading / writing JSON text. to_json / from_json (and pickling, which serializes via JSON strings) are unchanged (vinecopulib#684).

  • Add gradient (the observation-average of scores, mirroring how hessian averages hessian_full) and scores_full (the scores together with the per-edge derivative caches behind them, returned as a dict of [tree][edge] nested arrays with a keep_all option mirroring pdf_full; caches are only populated on the analytic path) (vinecopulib#683).

  • Add analytic derivatives of the bivariate copula density and h-functions to Bicop: pdf_deriv, pdf_deriv2, hfunc1_deriv, hfunc1_deriv2, hfunc2_deriv, hfunc2_deriv2, logpdf_deriv, and logpdf_deriv2, each taking a deriv selector string ("par1", "par2", …, "u1", "u2"; "par" is short for "par1"; second-order selectors concatenate two components in any order, a single component meaning twice, e.g. "par1u1" or "u1""u1u1"). Closed forms are used for the families in families.analytic_derivs (currently every parametric family); rotations are handled internally, so derivatives are always w.r.t. the natural parameters and arguments of the rotated copula. Like pdf and friends, each method accepts optional per-row parameters (an (n, p) array) and num_threads. For tll, the argument gradients pdf_deriv / logpdf_deriv w.r.t. "u1" / "u2" return the exact slope of the interpolation grid; parameter selectors, second-order, and h-function derivatives raise (vinecopulib#683, vinecopulib#687, vinecopulib#694).

  • Add the families.analytic_derivs group: families with closed-form density / h-function derivatives (vinecopulib#683, vinecopulib#687).

  • Add tail dependence and Blomqvist’s beta to Bicop: the read-only taildep property (a 2×2 matrix collecting the tail dependence coefficients in the four corners of the unit square; NaN for tll) and beta property (Blomqvist’s β = 4·C(0.5, 0.5) − 1, all families), plus parameters_to_taildep / parameters_to_beta for evaluation at arbitrary parameters, analogous to parameters_to_tau (vinecopulib#682).

  • Add RVineStructure.from_struct_array(order, struct_array, natural_order=False, check=True) (build a structure from an order vector and a [tree][edge] nested-list structure array) and RVineStructure.get_struct_array(natural_order=False) / Vinecop.get_struct_array(natural_order=False) (the full structure array as a nested list, complementing the per-entry struct_array(tree, edge)), on top of the TriangularArray conversions added in vinecopulib#680.

Build / packaging

  • Migrate to uv + scikit-build-core for the editable / wheel build pipeline, with [build-system].requires mirroring the dev [dependency-groups] so --no-build-isolation works out of the box (#209).

  • Replace mypy with ty (Astral’s type checker, alpha) and enable strict checks against a Python 3.10 baseline; only pyvinecopulib.pyvinecopulib_ext is allowed as an unresolved import (#210).

  • Add bandit security linting to make check and pre-commit (scanning src/pyvinecopulib + scripts). The previously-unused [tool.bandit] config silently excluded everything ("lib" matched pyvinecopulib); the config is fixed and the surfaced findings resolved.

  • Refactor the build / docs / examples pipeline into a thin Makefile over uv run and rework scripts/regenerate_notebooks.py (#205).

  • Add a pyvinecopulib[sklearn] extra (scikit-learn>=1.4, pandas>=2.0, joblib>=1.3, scipy>=1.10) and a pyvinecopulib[torch] extra (torch>=2.0) (#211, #216).

  • Treat pyvinecopulib-originated DeprecationWarnings as errors under pytest so internal call sites stay on the canonical import paths (#207).

  • Install --extra torch in the notebook-test and regenerate-notebooks CI jobs so examples/10_torch_backend.ipynb executes under nbmake (#216).

  • Fix osx / musllinux wheel builds: feed libclang the compiler’s implicit system include dirs (plus -ferror-limit=0 and the macOS SDK sysroot) so the C++ stdlib / intrinsic headers resolve, and abort docstr.hpp generation only on fatal libclang diagnostics (intrinsic-header errors are benign and no longer silently drop symbols).

  • Fix Windows wheel builds against the VS 2026 / MSVC 14.51 STL: rewrite __builtin_verbose_trap to __builtin_trap() during docstr.hpp generation. The newer STL emits this Clang-18 builtin from core allocator / string / call_once headers, which the pinned PyPI libclang (≤18) can’t resolve; because those headers reach nearly every translation unit, the broken parse crashed symbol extraction. Also narrow a numpy-scalar union in the Kde1d plot helper so make check (ty) passes (#224).

  • Migrate macOS CI to macos-15 and re-add macos-15-intel (MACOSX_DEPLOYMENT_TARGET=10.13 for nanobind’s aligned new/delete); wheel matrix is now 5 platforms × 3 ABI (15 wheels).

  • Fix the source build against Eigen 5.x (e.g. conda-forge eigen>=5): its CMake package exposes the include path only through the Eigen3::Eigen target and no longer sets the legacy EIGEN3_INCLUDE_DIR, leaving docstr.hpp generation (and the compile) unable to find <Eigen/Dense>. Derive EIGEN3_INCLUDE_DIR from the target’s INTERFACE_INCLUDE_DIRECTORIES when unset.

  • Build the Read the Docs site from source instead of the published PyPI wheel: enable the lib/ submodules, install header-only Boost / Eigen via apt (Ubuntu’s libboost-dev / libeigen3-dev clear vinecopulib’s >=1.56 / 3.4 floors), and pip install .[doc,examples,sklearn,torch]. The wheel-install shortcut only rendered the last release’s API, so RTD’s dev build failed once dev moved ahead of PyPI (missing numpydoc, then the entire core abstraction layer plus the sklearn / torch subpackages conf.py documents).

  • Make the Sphinx docs cross-reference-clean and enforce it going forward: enable nitpicky so make docs (-W, run by the verify_docs_build CI job) fails on any unresolved reference. The bulk of previously-dead links are fixed by giving the autosummary class template’s Attributes block a :toctree: (so each property gets a page for numpydoc’s member-summary links to resolve); backticked class names are rewritten to fully-qualified targets in process_cross_references so they link from any page; intersphinx mappings (numpy / torch / python) resolve external types; nanobind’s numpy.ndarray[dtype=…] signature annotations are collapsed to numpy.ndarray; and private-method references are reworded to plain literals. A short nitpick_ignore_regex covers the few irreducible refs (upstream-C++ getter-name mismatches, BicopFamily value aliases, scikit-learn-generated methods).

Bug fixes in pyvinecopulib

  • Port the integrate_2d marginal-renormalisation fix to the torch backend (InterpolationGrid2D.integrate_2d and integrate_2d_batched) so cdf enforces C(1, u_2) = u_2 exactly, matching the post-vinecopulib#667 C++ CDF to machine precision on the on-the-fly path (vinecopulib#667).

  • Declare BicopFamily enum members as class attributes in the generated type stubs so the documented pv.BicopFamily.clayton access pattern passes static type checking (ty / pyright / mypy), not only the module-level constants (#223).

Dependency changes

  • numpy>=2.0 is now a project-wide requirement (was >=1.14); VineRegressor needs np.quantile(weights=...) from NumPy 2.0 (#211).

  • [sklearn] extra adds pandas>=2.0 (used by VineBase.expand_factors for DataFrame inputs) (#211).

Changes in vinecopulib

NEW FEATURES

  • Early exit in vine selection when the structure is already a tree, avoiding redundant work in select (vinecopulib#661).

  • Per-family parameter / rotation / tail-dependence documentation on the BicopFamily enum members, surfaced through the Python families subpackage (#214, vinecopulib#668).

  • Numpydoc-compliant //! comments on every property getter / setter in the Python-binding surface, surfaced through the pyvinecopulib autosummary pages (#214, vinecopulib#670).

  • Allow a custom tree_criterion function for vine structure selection (vinecopulib#674).

  • Per-row parameter evaluation for parametric bivariate copulas: Bicop::pdf / cdf / hfunc1 / hfunc2 / hinv1 / hinv2 / loglik gain an overload taking an n×p parameter matrix (one set per observation) plus an optional thread count, backed by an eval-core refactor to a single parameter-aware leaf per family (vinecopulib#675).

  • Improve start parameters when fitting pair copulas on discrete data (vinecopulib#677).

  • TriangularArray<T> owns its conversions: to_json(), a JSON constructor, and to_list() (nested rows), used by the pyvinecopulib bindings for the structure-array and per-edge outputs (vinecopulib#680).

  • Analytic derivatives of the bivariate copula density and h-functions with respect to parameters and arguments for all parametric families, making Vinecop scores and Hessians analytic (exact and faster); models with nonparametric pair copulas are now rejected by scores / hessian (vinecopulib#683, vinecopulib#687). The TLL family additionally gains the exact argument gradient of its density (vinecopulib#694).

  • Rename the Vinecop Hessian API: hessian_avghessian (average) and hessianhessian_full (per-observation), mirrored by the Python bindings (vinecopulib#679).

PERFORMANCE

  • Speed up the bicop evaluation engine: vectorized closed-form pdf / h-function / CDF leaves and derivative-cascade allocation hygiene. Evaluations may shift by ≤ 1e-12 and fitted parameters by ≤ 1e-8 (vinecopulib#681).

  • Speed up Vinecop evaluation and structure selection: no per-edge copula copies in inverse_rosenblatt, in-place data collapsing, parallel allocation-free Monte-Carlo cdf, and selection fast paths. pdf_full no longer duplicates continuous h-functions into the hfunc*_sub buffers (they are now empty for models without discrete variables) (vinecopulib#692).

  • Speed up TLL fitting and evaluation: fused conditional-cdf interpolation and closed-form inversion of the conditional cdf. TLL hinv1 / hinv2 (hence simulate / inverse_rosenblatt on TLL vines) may shift by ≤ 1e-9 (vinecopulib#691).

  • Speed up tools_stats: SIMD qnorm, leaner bivariate normal / t kernels, faster pseudo-observations and quasi-random fills. Gaussian / Student evaluations may shift at the ≤ 1e-12 level (vinecopulib#690).

  • Faster shared Eigen / thread / integration primitives; the relaxed integration tolerance (1e-12 → 1e-9) may shift Kendall’s τ of the integrated families (BB6 / BB7 / BB8, Tawn) by up to ~1e-7 (vinecopulib#689).

  • Compute the Student t score’s df-only terms once per call, speeding up Vinecop scores / Hessians and Student t maximum-likelihood fits (vinecopulib#693).

BUG FIXES

  • Fix an out-of-bounds read in the mixed discrete/continuous h-inverse (hinv2 for {d, c} copulas with a numeric inverse: Frank, BB1/6/7/8, Tawn) (vinecopulib#675).

  • Add a missing thread-related include (vinecopulib#676).

  • Fix integrade_2d numerical handling on the bivariate-copula CDF path (vinecopulib#667).

  • Fix a typo in pdf_d_d and tighten the threshold under which the analytical derivative is preferred over the finite-difference fallback (vinecopulib#664).

  • Drop an unused fit-controls option (vinecopulib#662).

  • Fix Doxygen typos surfaced by the libclang extractor (vinecopulib#665).

  • Bump CI off the deprecated macos-13 runner (vinecopulib#663).

Changes in kde1d

  • Numpydoc-compliant //! getter-return docstrings on Kde1d, surfaced through pyvinecopulib.utils.Kde1d (#214, kde1d#26).

  • Capitalize method first words, add a fit-summary, and fix the quantile description (kde1d#27).

0.7.6

This release was only used to pull the latest changes from vinecopulib’s dev branch, which includes some bug fixes.

0.7.5

New features in pyvinecopulib

  • Add support for 1d data with the Kde1d Python bindings (#189, #198)

  • Add support for weighted dependence measures wdm (#194)

  • Add an argument to control the nonparametric grid size in both Kde1d and Bicop (#191, #192)

  • Release GIL for C++-only operations (#193)

  • Add support for Python 3.14 (#200)

Bug fixes in pyvinecopulib

  • Improve repo health (#188)

  • Improve pickling by making the state a dict instead of tuple for all classes (#190)

0.7.4

This release was yanked due to an issue with the wheel upload. Please use 0.7.5 instead.

0.7.3

Breaking API changes in pyvinecopulib

  • Rename the mst_algorithm argument in FitControlsVinecop to tree_algorithm to match the underlying C++ API (#178).

    • The accepted values are now "mst_prim", "mst_kruskal" instead of "prim" and "kruskal".

  • Drop support for Python 3.8. Add support for Python 3.13 (#181).

New features in pyvinecopulib

  • Add support for random spanning trees in structure selection via tree_algorithm="random_weighted" and "random_unweighted" using Wilson’s algorithm, enabling uniform or weight-proportional tree sampling (#178).

  • Upgrade to nanobind v0.2.7, which removes the need for casting hacks and improves compatibility (#180).

  • Introduce a format() method and improve __str__ output for the Vinecop class (#144, #185).

  • Add PEP 561-compatible stub files and full static type annotations across the package. Enable mypy checks in CI (#144).

  • Add .[dev] and .[examples] extras in pyproject.toml for installing development and example dependencies (#181, #182, #183).

  • Replace flake8 with ruff for linting and add code formatting checks (#182).

  • Execute and test Jupyter notebooks in CI, including Graphviz rendering (#181).

Bug fixes in pyvinecopulib

  • Fix non-deterministic structure selection in multithreaded environments by decoupling criterion computation from edge insertion (#178, vinecopulib#640).

  • Refactor unit test environment setup and cleanup; remove stale directories in tests (#183).

  • Fix documentation rendering and improve docstrings across the package (#144, #185).

Changes in vinecopulib version 0.7.3

These changes originate from the release 0.7.3 of vinecopulib, the C++ library which powers pyvinecopulib.

BREAKING API CHANGES

  • The mst_algorithm option to FitControlsVinecop has been renamed to tree_algorithm to allow for alternative spanning tree algorithms (#637).

  • tree_algorithm’s default value is now "mst_prim" instead of "prim", and "mst_kruskal" replaces "kruskal" (#637).

  • The CMake option VINECOPULIB_BUILD_SHARED_LIBS has been changed to VINECOPULIB_PRECOMPILED to better reflect its purpose (#641).

NEW FEATURES

  • Allow for random spanning trees as alternatives to the MST-based structure selection using tree_algorithm in FitControlsVinecop with "random_weighted" or "random_unweighted" (#637).

BUG FIXES

  • Decouple edge insertion from criterion computation in VinecopSelector to fix randomness issues in structure selection when using multiple threads (#640)

Changes in vinecopulib version 0.7.2

These changes originate from the release 0.7.2 of vinecopulib, the C++ library which powers pyvinecopulib.

BUG FIXES

  • More build system updates by @jschueller (#633)

  • Fix deprecation warning in json header (#634)

  • Fix TLL speed issues related to FFT (#635)

0.7.1

New features in pyvinecopulib

Bug fixes in pyvinecopulib

  • Upgrade nanobind to allow for single row matrices (fix #169 and #170)

Changes in vinecopulib version 0.7.1

These changes originate from the latest release of vinecopulib, the C++ library which powers pyvinecopulib.

NEW FEATURES

BUG FIXES

  • Restrict parameter range for fitting Tawn copulas; fix handling of their shape/argument order (#620).

  • Compute and save loglik/nobs in Vinecop::fit() (#623)

  • Disable unwanted compiler output related to BOOST_CONCEPT checks (#624)

0.7.0

This version introduces a switch to nanobind as a backend (#160): i.e., the C++ bindings, now use nanobind instead of pybind11. It allows for considerable performance improvements (~8x speedup in our latest benchmarks) and smaller binaries.

Breaking API changes in pyvinecopulib

  • Removal of the overloaded constructors:

    • For all classes, only one constructor is now available. The reason is that the overloaded constructors were un-Pythonic, error-prone, and could not be properly documented with Sphinx. They have been replaced by a single constructor for each class, along with factory from_xzy methods.

    • For the {py:class}~pyvinecopulib.core.Bicop`` class:

      • {py:meth}~pyvinecopulib.core.Bicop.from_family``: Instantiate from a family, rotation, parameters, and variable types.

      • {py:meth}~pyvinecopulib.core.Bicop.from_data``: Instantiate from data, as well as optional controls and variable types.

      • {py:meth}~pyvinecopulib.core.Bicop.from_file``: Instantiate from a file.

      • {py:meth}~pyvinecopulib.core.Bicop.from_json``: Instantiate from a JSON-like string.

    • For the {py:class}~pyvinecopulib.core.Vinecop`` class:

      • {py:meth}~pyvinecopulib.core.Vinecop.from_dimension``: Instantiate an empty vine copula of a given dimension.

      • {py:meth}~pyvinecopulib.core.Vinecop.from_data: Instantiate from data, as well as an optional `{py:class}`~pyvinecopulib.core.FitControlsVinecop, an {py:class}~pyvinecopulib.core.RVineStructure`` or matrix, and variable types.

      • {py:meth}~pyvinecopulib.core.Vinecop.from_structure: Instantiate from an `{py:class}`~pyvinecopulib.core.RVineStructure or matrix, as well as optional pair-copulas and variable types.

      • {py:meth}~pyvinecopulib.core.Vinecop.from_file``: Instantiate from a file.

      • {py:meth}~pyvinecopulib.core.Vinecop.from_json``: Instantiate from a JSON-like string.

    • For the {py:class}~pyvinecopulib.core.RVineStructure`` class:

      • {py:meth}~pyvinecopulib.core.RVineStructure.from_dimension``: Instantiate a default structure of a given dimension and truncation level.

      • {py:meth}~pyvinecopulib.core.RVineStructure.from_order``: Instantiate from an order vector.

      • {py:meth}~pyvinecopulib.core.RVineStructure.from_matrix``: Instantiate from a matrix.

      • {py:meth}~pyvinecopulib.core.RVineStructure.from_file``: Instantiate from a file.

      • {py:meth}~pyvinecopulib.core.RVineStructure.from_json``: Instantiate from a JSON-like string.

New features in pyvinecopulib

  • Expose more structure methods to python (#157)

  • Switch to nanobind as a backend (#160)

  • New IO methods for Bicop and Vinecop classes to use JSON-like strings (#160)

  • Extensive documentation revamp (#160)

  • Adding a benchmark example (#160)

  • Convertion of all examples to Jupyter notebooks (#160)

Bug fixes in pyvinecopulib

  • Install and test source distribution (#164)

Changes in vinecopulib

These changes originate from the underlying C++ library, vinecopulib, which powers pyvinecopulib.

New features

  • Use analytical derivatives in discrete pdf/hfuncs (#572)

  • Allow for alternative for "prim" vs "kruskal" in MST-based model selection (#577)

  • Improve the dependencies install script to use it in other projects (#576)

  • Add tawn copula (#579)

  • Improve doc (#580, #585, #607)

  • Allow for the discrete Rosenblatt transform (#581)

  • Add Vinecop::fit() (#584)

  • Improve Bicop::str() (#588) and Vinecop::str() (#589)

  • Properly handle discrete variables for the TLL family (#597)

  • Weighted pseudo-observations (#602)

  • Cross-platform random numbers and add seeds options to to_pseudo_obs (#603)

  • Improve performance by

    • aligning with the R defaults (e.g., BOOST_NO_AUTO_PTR, BOOST_ALLOW_DEPRECATED_HEADERS, BOOST_MATH_PROMOTE_DOUBLE_POLICY=false, std::string nonparametric_method = "constant" for the TLL instead of "quadratic", -O3 -march=native compiler flags) and add benchmarking example (#592, #611, #613),

    • using Eigen element-wise operations instead of boost whenever possible (#598, #612),

    • using binary search in the TLL for get_indices (#613).

Bug fixes

  • Improve stability in BB7 PDF (#573)

  • Revamped CI/CD pipeline, tests discoverable by CTest, boost version on windows ((66cf8b0))

  • Fix ASAN issues (#583)

  • Fix interface includes and other CMake issue (#586, #599, #601, #608), by @jschueller