Skip to main content

pytrees-rs

pytrees-rs learns anytime optimal decision trees. It is written mostly in Rust and comes with a Python wrapper that follows the scikit-learn API.

An optimal tree is the one with the lowest training error among all trees of a given depth. Finding it can take a long time, so the optimal searches can run as anytime searches: they return a good tree quickly and keep improving it until it is proven optimal or the time limit is reached. status_ tells you which.

Estimator Features What it learns
DL85Classifier binary Optimal trees (DL8.5), for the misclassification error or your own
ConTreeClassifier continuous Optimal trees without binarising the data (ConTree)
LGDTClassifier binary Trees grown top-down, each test chosen with a depth-2 lookahead (LGDT)
DL85Cluster binary Clusterings whose clusters are the leaves of an optimal tree

The estimators behave like any scikit-learn estimator: they can be cloned, pickled and used in Pipeline, GridSearchCV or cross_val_score. The fitted tree is in tree_, with scikit-learn's layout, and a row goes left when x[feature] <= threshold.

Installation

pip install pytrees-rs

Wheels are provided for Linux, macOS and Windows, for Python 3.10 and later. To build from source you need a Rust toolchain (1.77 or later):

git clone https://github.com/haroldks/pytrees-rs.git
cd pytrees-rs
pip install .

Quick start

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from pytrees import ConTreeClassifier

X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)

clf = ConTreeClassifier(max_depth=3, min_sup=5).fit(X_train, y_train)
print(clf.status_)              # "optimal", or "time_limit" if it ran out of time
print(clf.train_error_)         # training misclassifications
print(clf.score(X_test, y_test))
print(clf.to_dot())             # the tree in Graphviz format

DL8.5 and LGDT need binary features (0 or 1). A Binarizer or KBinsDiscretizer with one-hot output in a Pipeline takes care of that:

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import KBinsDiscretizer
from pytrees import DL85Classifier

model = make_pipeline(
    KBinsDiscretizer(n_bins=4, encode="onehot-dense"),
    DL85Classifier(max_depth=3, min_sup=5, max_time=60),
)
model.fit(X_train, y_train)

fit_anytime works like fit, but calls you back each time the search finds a better tree:

from pytrees import DL85Classifier
from pytrees.rules import DiscrepancyRule

X_bin = KBinsDiscretizer(n_bins=4, encode="onehot-dense").fit_transform(X)
clf = DL85Classifier(
    max_depth=5,
    heuristic="information_gain",
    discrepancy=DiscrepancyRule(),   # limited discrepancy search
    max_time=120,
)
clf.fit_anytime(X_bin, y, callback=lambda error, seconds, status: print(seconds, error, status))

ConTreeClassifier has the same method, and use_lds=True makes its plain fit anytime too.

Custom error functions

DL8.5 finds the tree that minimises the sum of its leaf errors, and the error of a leaf does not have to be the number of misclassified rows. Pass your own as error_function: it receives the class counts of a leaf (or its row indices, with error_function_input="indices") and returns the error and the predicted class. Class-dependent costs, sample weights and clustering objectives (DL85Cluster works this way) all fit. ConTreeClassifier takes an error_function the same way:

import numpy as np

y_bin = (y == 2).astype(int)   # is it Iris virginica?
costs = np.array([1.0, 5.0])   # missing a virginica costs five times more

def cost_sensitive(class_counts):
    counts = np.asarray(class_counts, dtype=float)
    per_prediction = [(costs * counts).sum() - costs[k] * counts[k] for k in range(len(counts))]
    best = int(np.argmin(per_prediction))
    return per_prediction[best], best

clf = DL85Classifier(max_depth=3, error_function=cost_sensitive).fit(X_bin, y_bin)

Documentation

  • User guide: installation, every estimator and its parameters, the anytime search rules, custom error functions and the command line tools.
  • Rust API: the dtrees-rs and contree-rs crates.

Repository layout

The Python package is built from a Cargo workspace:

Path Contents
crates/dtrees The dtrees-rs library: DL8.5, LGDT and the search rules, over binary features
crates/contree The contree-rs library: ConTree and its anytime variant, over continuous features
crates/dtrees-cli, crates/contree-cli Command line front ends
crates/pytrees-py The Python bindings (pytrees._native)
python/pytrees The Python package and its scikit-learn estimators
doc The documentation site (mdBook)

To work on it:

cargo test --workspace                     # Rust tests
pip install maturin && maturin develop     # build the Python package in place
pytest python/tests                        # Python tests

Publications

The algorithms in this repository come from the following papers. If you use them in your work, please cite the relevant one.

  • H. Kiossou, P. Schaus, S. Nijssen and V. R. Houndji. Time Constrained DL8.5 Using Limited Discrepancy Search. ECML PKDD 2022, LNCS 13717, pp. 443-459. doi:10.1007/978-3-031-26419-1_27 (DL85Classifier with DiscrepancyRule)
  • H. Kiossou, P. Schaus, S. Nijssen and G. Aglin. Efficient Lookahead Decision Trees. IDA 2024, pp. 133-144. doi:10.1007/978-3-031-58553-1_11 (LGDTClassifier)
  • H. Kiossou and P. Schaus. A Generic Complete Anytime Beam Search for Optimal Decision Tree. IDA 2026. doi:10.1007/978-3-032-23833-7_8, arXiv:2508.06064 (the search rules of DL85Classifier: CA-DL8.5)
  • H. Kiossou, P. Schaus and S. Nijssen. Anytime Optimal Decision Tree Learning with Continuous Features. ECML PKDD 2026. arXiv:2601.14765 (ConTreeClassifier with use_lds=True)

They build on:

  • G. Aglin, S. Nijssen and P. Schaus. Learning Optimal Decision Trees Using Caching Branch-and-Bound Search. AAAI 2020. (DL8.5; the original implementation is pydl8.5.)
  • E. Demirović, A. Lukina, E. Hebrard, J. Chan, J. Bailey, C. Leckie, K. Ramamohanarao and P. J. Stuckey. MurTree: Optimal Decision Trees via Dynamic Programming and Search. JMLR 23, 2022. (The depth-2 solver.)
  • C. E. Briţa, J. G. M. van der Linden and E. Demirović. Optimal Classification Trees for Continuous Feature Data Using Dynamic Programming with Branch-and-Bound. AAAI 2025. (ConTree; the original implementation is ConSol-Lab/contree.)

License

MIT; see LICENSE.

Metadata

Release files for pytrees-rs 2.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pytrees-rs 2.2.0
File Size Uploaded Provenance Actions
pytrees_rs-2.2.0.tar.gz 1.2 MB With provenance Details for pytrees_rs-2.2.0.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for pytrees-rs 2.2.0
File Actions
pytrees_rs-2.2.0-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details for pytrees_rs-2.2.0-cp310-abi3-win_amd64.whl
pytrees_rs-2.2.0-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-64 Details for pytrees_rs-2.2.0-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
pytrees_rs-2.2.0-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl CPython 3.10 abi3 Linux glibc 2.17+ ARM64 Details for pytrees_rs-2.2.0-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
pytrees_rs-2.2.0-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details for pytrees_rs-2.2.0-cp310-abi3-macosx_11_0_arm64.whl
pytrees_rs-2.2.0-cp310-abi3-macosx_10_12_x86_64.whl CPython 3.10 abi3 macOS 10.12+ x86-64 Details for pytrees_rs-2.2.0-cp310-abi3-macosx_10_12_x86_64.whl

Total release size: 3.5 MB

Release files / pytrees_rs-2.2.0.tar.gz

Download URL pytrees_rs-2.2.0.tar.gz
Size 1.2 MB
Tags Source
SHA-256 checksum
How to use checksums
4246459315cf97b800eb1d949d5ffae59130c22085e8173ad2c9748e5abf658e
BLAKE2b-256 checksum
How to use checksums
6b4b4b884281e12d992c1e648848db26e687f3bba5b085fd1cbe32c2dc150a8c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.

Transparency log

Release files / pytrees_rs-2.2.0-cp310-abi3-win_amd64.whl

Download URL pytrees_rs-2.2.0-cp310-abi3-win_amd64.whl
Size 397.7 kB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
dae49da3afb6fb66f7ddc28788e7913e20ceb3934b9455f3f02b377d562a5f00
BLAKE2b-256 checksum
How to use checksums
d9df6e3d95a4be2cfa5f2e6b8ac62ba5cac205b77d42beb5e83fb6558938feec
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.

Transparency log

Release files / pytrees_rs-2.2.0-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl

Download URL pytrees_rs-2.2.0-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Size 515.8 kB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
346c6a343c03e5686d5ed4630be0148991442a8dee2c258bd8b27868f08afb7d
BLAKE2b-256 checksum
How to use checksums
bf24d5b8e4f953e560049738a5d2df681553fbf681bcf0caee877cc1acfea86e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.

Transparency log

Release files / pytrees_rs-2.2.0-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl

Download URL pytrees_rs-2.2.0-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Size 491.7 kB
Tags CPython 3.10 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
9bd1374dae7eb8deed5092b68627c89f703b149cc88e8230e26693a06c790cdc
BLAKE2b-256 checksum
How to use checksums
ac031726cf3d54c4b9fe7c51dec35182619f1831c55e3da465df1d73d8509344
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.

Transparency log

Release files / pytrees_rs-2.2.0-cp310-abi3-macosx_11_0_arm64.whl

Download URL pytrees_rs-2.2.0-cp310-abi3-macosx_11_0_arm64.whl
Size 469.9 kB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
484718bada5b6c958adab2d3c839cb08d7dcc607e82f3b067819f2001b72360f
BLAKE2b-256 checksum
How to use checksums
935839dc162f032a075b3e0bb8d883648eb1fc80925b7c3b9f64fb414a846e26
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.

Transparency log

Release files / pytrees_rs-2.2.0-cp310-abi3-macosx_10_12_x86_64.whl

Download URL pytrees_rs-2.2.0-cp310-abi3-macosx_10_12_x86_64.whl
Size 498.9 kB
Tags CPython 3.10 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
c9a76af183c742603d74adfa8f8f4069e8fd32e06c0bb9591509b7ceebd35670
BLAKE2b-256 checksum
How to use checksums
0495a8d6563f4fc1eddeff15fa54cf5fe5725bc7781884c9f8f54f81a3b9f442
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.

Transparency log

Security for pytrees-rs 2.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 6 files in this release have been uploaded with provenance metadata.

Select from 6 files

Attestation for pytrees_rs-2.2.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page