Skip to content

Commit

Permalink
Version 0.7.1 (#172)
Browse files Browse the repository at this point in the history
* Add pickling feature (#168)

* Add pickling feature

* Small typo

* modify tests

* Make pickling safer with new FitControlsConfig

* bump version number

* upgrade nanobind (#171)

* upgrade nanobind

* unit test

* upgrade changelog

* correct unit tests

* Upgrade to vinecopulib 0.7.1 (#173)

* Remove codacy (#174)

* Update changelog
  • Loading branch information
tvatter authored Feb 9, 2025
1 parent 9a64b2e commit d3b3151
Show file tree
Hide file tree
Showing 17 changed files with 436 additions and 58 deletions.
29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,34 @@
# Changelog

## 0.7.1

## Bug fixes in `pyvinecopulib`

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

## New features in `pyvinecopulib`

* Add pickle support for all classes (#168)
* Add `allow_rotation` option to `FitControlsBicop` and `FitControlsVinecop` (#168)

## Changes in `vinecopulib` version 0.7.1

These changes originate from the latest release of [`vinecopulib`](https://github.com/vinecopulib/vinecopulib/releases/tag/v0.7.1), the C++ library which powers `pyvinecopulib`.

### NEW FEATURES

* add `allow_rotation` option to `FitControlsBicop` and `FitControlsVinecop`
to allow for the rotation of the pair copulas ([#628](https://github.com/vinecopulib/vinecopulib/pull/628)).
* add a `FitControlsConfig` struct to create flexible and yet safe constructors
for `FitControlsBicop` and `FitControlsVinecop` ([#629](https://github.com/vinecopulib/vinecopulib/pull/629)).

### BUG FIXES

* restrict parameter range for fitting Tawn copulas; fix handling of their
shape/argument order ([#620](https://github.com/vinecopulib/vinecopulib/pull/620)).
* compute and save loglik/nobs in `Vinecop::fit()` ([#623](https://github.com/vinecopulib/vinecopulib/pull/623))
* disable unwanted compiler output related to BOOST_CONCEPT checks ([#624](https://github.com/vinecopulib/vinecopulib/pull/624))

## 0.7.0

This version introduces a switch to nanobind as a backend (#160): i.e., the C++ bindings, now use [nanobind](https://nanobind.readthedocs.io/) instead of [pybind11](https://pybind11.readthedocs.io/).
Expand Down
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
[![Documentation](https://img.shields.io/website/http/vinecopulib.github.io/pyvinecopulib.svg)](https://vinecopulib.github.io/pyvinecopulib/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Build Status](https://github.com/vinecopulib/pyvinecopulib/actions/workflows/pypi.yml/badge.svg)](https://github.com/vinecopulib/pyvinecopulib/actions/workflows/pypi.yml)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/3c0056d3ca5244a5ba6a2b32f87be4cf)](https://www.codacy.com/gh/vinecopulib/pyvinecopulib?utm_source=github.com&utm_medium=referral&utm_content=vinecopulib/pyvinecopulib&utm_campaign=Badge_Grade)
[![DOI](https://zenodo.org/badge/196999069.svg)](https://zenodo.org/badge/latestdoi/196999069)

## Introduction
Expand Down Expand Up @@ -71,7 +70,7 @@ mamba install conda-forge::pyvinecopulib
The main build time prerequisites are:

* scikit-build-core (>=0.4.3),
* nanobind (>=1.3.2),
* nanobind (>=2.5.0),
* a compiler with C++17 support.

To install from source, `Eigen` and `Boost` also need to be available, and CMake will try to find suitable versions automatically.
Expand Down
4 changes: 0 additions & 4 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@ pyvinecopulib
:target: https://github.com/vinecopulib/pyvinecopulib/actions/workflows/pypi.yml
:alt: Build Status

.. image:: https://api.codacy.com/project/badge/Grade/3c0056d3ca5244a5ba6a2b32f87be4cf
:target: https://www.codacy.com/gh/vinecopulib/pyvinecopulib?utm_source=github.com&utm_medium=referral&utm_content=vinecopulib/pyvinecopulib&utm_campaign=Badge_Grade
:alt: Codacy Badge

.. image:: https://zenodo.org/badge/196999069.svg
:target: https://zenodo.org/badge/latestdoi/196999069
:alt: DOI
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[build-system]
requires = ["scikit-build-core >=0.4.3", "nanobind >=1.3.2"]
requires = ["scikit-build-core >=0.4.3", "nanobind >=2.5.0"]
build-backend = "scikit_build_core.build"

[project]
name = "pyvinecopulib"
version = "0.7.0"
version = "0.7.1"
authors = [
{ name="Thibault Vatter", email="info@vinecopulib.com" },
{ name="Thomas Nagler", email="info@vinecopulib.com" },
Expand Down
40 changes: 16 additions & 24 deletions scripts/process_changelog.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,30 +36,22 @@ def replace_commit(match):

# Example changelog
changelog_text = """
#### 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
### NEW FEATURES
* add `allow_rotation` option to `FitControlsBicop` and `FitControlsVinecop`
to allow for the rotation of the pair copulas (#628).
* add a `FitControlsConfig` struct to create flexible and yet safe constructors
for `FitControlsBicop` and `FitControlsVinecop` (#629).
### 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)
"""

# Repository URL
Expand Down
21 changes: 20 additions & 1 deletion src/include/bicop/class.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "docstr.hpp"
#include <nanobind/eigen/dense.h>
#include <nanobind/nanobind.h>
#include <nanobind/stl/tuple.h>
#include <vinecopulib.hpp>

namespace nb = nanobind;
Expand Down Expand Up @@ -208,5 +209,23 @@ Alternatives to instantiate bivariate copulas are:
nb::cast<std::string>(
nb::module_::import_("pyvinecopulib._python_helpers.bicop")
.attr("BICOP_PLOT_DOC"))
.c_str());
.c_str())
.def("__getstate__",
[](const Bicop& cop) {
return std::make_tuple(cop.get_family(),
cop.get_rotation(),
cop.get_parameters(),
cop.get_var_types());
})
.def("__setstate__",
[](Bicop& cop,
std::tuple<BicopFamily,
int,
const Eigen::MatrixXd&,
std::vector<std::string>> state) {
new (&cop) Bicop(std::get<0>(state),
std::get<1>(state),
std::get<2>(state),
std::get<3>(state));
});
}
3 changes: 0 additions & 3 deletions src/include/bicop/family.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ init_bicop_family(nb::module_& module)
``bb1``, ``bb7``, ``tawn``),
- ``ut`` contains the families that are upper-tail dependent (``gumbel``,
``joe``, ``bb1``, ``bb6``, ``bb7``, ``bb8``, ``tawn``),
- ``flip_by_rotation`` contains families that can be flipped by rotation
(``clayton``, ``gumbel``, ``frank`` , ``joe``, ``bb1``, ``bb6``, ``bb7``, ``bb8``, ``tawn``),
- ``rotationless`` contains families that don't have a rotation
because they already cover positive and negative dependence (``indep``, ``gaussian``, ``student``, ``frank``, ``tll``).
)pbdoc")
Expand Down Expand Up @@ -80,5 +78,4 @@ init_bicop_family(nb::module_& module)
module.attr("lt") = bicop_families::lt;
module.attr("ut") = bicop_families::ut;
module.attr("itau") = bicop_families::itau;
module.attr("flip_by_rotation") = bicop_families::flip_by_rotation;
}
48 changes: 47 additions & 1 deletion src/include/bicop/fit_controls.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <nanobind/eigen/dense.h>
#include <nanobind/nanobind.h>
#include <nanobind/stl/string.h>
#include <nanobind/stl/tuple.h>
#include <nanobind/stl/vector.h>
#include <vinecopulib.hpp>

Expand All @@ -28,6 +29,7 @@ init_bicop_fit_controls(nb::module_& module)
const Eigen::VectorXd&,
double,
bool,
bool,
size_t>(),
fitcontrolsbicop_doc.ctor.doc_9args,
"family_set"_a = bicop_families::all,
Expand All @@ -38,6 +40,7 @@ init_bicop_fit_controls(nb::module_& module)
"weights"_a = Eigen::VectorXd(),
"psi0"_a = 0.9,
"preselect_families"_a = true,
"allow_rotations"_a = true,
"num_threads"_a = 1)
/* .def(nb::init<std::string>(), */
// "creates default controls except for the parameteric method.",
Expand Down Expand Up @@ -78,6 +81,10 @@ init_bicop_fit_controls(nb::module_& module)
&FitControlsBicop::set_preselect_families,
"Whether to exclude families based on symmetry properties "
"of the data.")
.def_prop_rw("allow_rotations",
&FitControlsBicop::get_allow_rotations,
&FitControlsBicop::set_allow_rotations,
"Whether to allow rotations for the families.")
.def_prop_rw("num_threads",
&FitControlsBicop::get_num_threads,
&FitControlsBicop::set_num_threads,
Expand All @@ -86,5 +93,44 @@ init_bicop_fit_controls(nb::module_& module)
[](const FitControlsBicop& controls) {
return "<pyvinecopulib.FitControlsBicop>\n" + controls.str();
})
.def("str", &FitControlsBicop::str, fitcontrolsbicop_doc.str.doc);
.def("str", &FitControlsBicop::str, fitcontrolsbicop_doc.str.doc)
.def("__getstate__",
[](const FitControlsBicop& controls) {
return std::make_tuple(controls.get_family_set(),
controls.get_parametric_method(),
controls.get_nonparametric_method(),
controls.get_nonparametric_mult(),
controls.get_selection_criterion(),
controls.get_weights(),
controls.get_psi0(),
controls.get_preselect_families(),
controls.get_allow_rotations(),
controls.get_num_threads());
})
.def("__setstate__",
[](FitControlsBicop& controls,
std::tuple<std::vector<BicopFamily>,
std::string,
std::string,
double,
std::string,
const Eigen::VectorXd&,
double,
bool,
bool,
size_t> state) {
FitControlsConfig config;
config.family_set = std::get<0>(state);
config.parametric_method = std::get<1>(state);
config.nonparametric_method = std::get<2>(state);
config.nonparametric_mult = std::get<3>(state);
config.selection_criterion = std::get<4>(state);
config.weights = std::get<5>(state);
config.psi0 = std::get<6>(state);
config.preselect_families = std::get<7>(state);
config.allow_rotations = std::get<8>(state);
config.num_threads = std::get<9>(state);

new (&controls) FitControlsBicop(config);
});
}
18 changes: 17 additions & 1 deletion src/include/vinecop/class.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,5 +330,21 @@ empty vine copula of a given dimension. It can then be used to select a model fr
nb::cast<std::string>(
nb::module_::import_("pyvinecopulib._python_helpers.vinecop")
.attr("VINECOP_PLOT_DOC"))
.c_str());
.c_str())
.def("__getstate__",
[](const Vinecop& cop) {
return std::make_tuple(cop.get_rvine_structure().to_json().dump(),
cop.get_all_pair_copulas(),
cop.get_var_types());
})
.def("__setstate__",
[](Vinecop& cop,
std::tuple<std::string,
std::vector<std::vector<Bicop>>,
std::vector<std::string>> state) {
nlohmann::json json_obj = nlohmann::json::parse(std::get<0>(state));
RVineStructure structure = RVineStructure(json_obj);
new (&cop)
Vinecop(structure, std::get<1>(state), std::get<2>(state));
});
}
78 changes: 76 additions & 2 deletions src/include/vinecop/fit_controls.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <nanobind/eigen/dense.h>
#include <nanobind/nanobind.h>
#include <nanobind/stl/string.h>
#include <nanobind/stl/tuple.h>
#include <nanobind/stl/vector.h>
#include <vinecopulib.hpp>

Expand Down Expand Up @@ -36,7 +37,8 @@ init_vinecop_fit_controls(nb::module_& module)
bool,
bool,
size_t,
std::string>(),
std::string,
bool>(),
"family_set"_a = bicop_families::all,
"parametric_method"_a = "mle",
"nonparametric_method"_a = "constant",
Expand All @@ -54,6 +56,7 @@ init_vinecop_fit_controls(nb::module_& module)
"show_trace"_a = false,
"num_threads"_a = 1,
"mst_algorithm"_a = "prim",
"allow_rotations"_a = true,
fitcontrolsvinecop_doc.ctor.doc_17args)
.def_prop_rw("family_set",
&FitControlsVinecop::get_family_set,
Expand Down Expand Up @@ -120,9 +123,80 @@ init_vinecop_fit_controls(nb::module_& module)
&FitControlsVinecop::get_num_threads,
&FitControlsVinecop::set_num_threads,
"The number of threads.")
.def_prop_rw("mst_algorithm",
&FitControlsVinecop::get_mst_algorithm,
&FitControlsVinecop::set_mst_algorithm,
"The minimum spanning tree algorithm.")
.def_prop_rw("allow_rotations",
&FitControlsVinecop::get_allow_rotations,
&FitControlsVinecop::set_allow_rotations,
"Whether to allow rotations for the families.")
.def("__repr__",
[](const FitControlsVinecop& controls) {
return "<pyvinecopulib.FitControlsVinecop>\n" + controls.str();
})
.def("str", &FitControlsVinecop::str, fitcontrolsvinecop_doc.str.doc);
.def("str", &FitControlsVinecop::str, fitcontrolsvinecop_doc.str.doc)
.def("__getstate__",
[](const FitControlsVinecop& controls) {
return std::make_tuple(controls.get_family_set(),
controls.get_parametric_method(),
controls.get_nonparametric_method(),
controls.get_nonparametric_mult(),
controls.get_trunc_lvl(),
controls.get_tree_criterion(),
controls.get_threshold(),
controls.get_selection_criterion(),
controls.get_weights(),
controls.get_psi0(),
controls.get_preselect_families(),
controls.get_select_trunc_lvl(),
controls.get_select_threshold(),
controls.get_select_families(),
controls.get_show_trace(),
controls.get_num_threads(),
controls.get_mst_algorithm(),
controls.get_allow_rotations());
})
.def("__setstate__",
[](FitControlsVinecop& controls,
std::tuple<std::vector<BicopFamily>,
std::string,
std::string,
double,
size_t,
std::string,
double,
std::string,
Eigen::VectorXd,
double,
bool,
bool,
bool,
bool,
bool,
size_t,
std::string,
bool> state) {
FitControlsConfig config;
config.family_set = std::get<0>(state);
config.parametric_method = std::get<1>(state);
config.nonparametric_method = std::get<2>(state);
config.nonparametric_mult = std::get<3>(state);
config.trunc_lvl = std::get<4>(state);
config.tree_criterion = std::get<5>(state);
config.threshold = std::get<6>(state);
config.selection_criterion = std::get<7>(state);
config.weights = std::get<8>(state);
config.psi0 = std::get<9>(state);
config.preselect_families = std::get<10>(state);
config.select_trunc_lvl = std::get<11>(state);
config.select_threshold = std::get<12>(state);
config.select_families = std::get<13>(state);
config.show_trace = std::get<14>(state);
config.num_threads = std::get<15>(state);
config.mst_algorithm = std::get<16>(state);
config.allow_rotations = std::get<17>(state);

new (&controls) FitControlsVinecop(config);
});
}
Loading

0 comments on commit d3b3151

Please sign in to comment.