LTP
Group recommendations that are fair over time. If a member loses out this session, LTP prioritizes them next session — keeping result-level proportionality across a sequence of sessions while preserving group utility.
Group recommender systems must balance conflicting member preferences, and within
a single recommendation it's often impossible to be fair to everyone. But group
decisions usually happen over several sessions — so fairness can be balanced
across them. LTP (Long-Term Proportionality) does exactly that: it carries
per-member fairness state between sessions and selects proportionally, so no member
is consistently overlooked.
Algorithm: Patrik Dokoupil & Ladislav Peska (KAIS '26, see Citing). This implementation: Patrik Dokoupil — a standalone, packaged reimplementation.
Install
pip install ltp-rs
Quick start
Create one LTP per group; call recommend once per session — the fairness state
carries across calls.
import numpy as np
from ltp import LTP
agg = LTP(gamma=1.0, beta=0.0) # one aggregator per group
for session in range(n_sessions):
# ratings[m, i] = predicted rating of item i for group member m, this session
ratings = your_model.predict(group, session) # shape (n_members, n_items)
recommendation = agg.recommend(ratings, k=10) # -> item indices
agg.reset() # start a fresh group
Items recommended in earlier sessions are not repeated (toggle with
avoid_repeats=False).
What you can tune
gamma— memory of past sessions (1.0 = full; < 1.0 gradually forgets).beta— in-list position discount; item at positionpupdates state with weightexp(-beta·p)(0.0 = all positions equal).tie_breaking— fairness nudge when items score near-equally.member_weights— relative importance of members (the paper's user weightsw; default uniform).normalize— per-member scaling each session:None,"minmax","standard","robust","quantile".
How it works
Each session, LTP runs RLProp's mandate-allocation step over the group members (members play the role of "objectives"), but seeded with each member's accumulated gains from previous sessions, averaged by the number of sessions. A member who has been under-served carries a larger unfilled mandate and is favored until balance is restored. See the paper for the algorithm, the simulated-choice evaluation, and the fairness/utility trade-off.
python examples/quickstart.py shows cumulative per-member utility staying far more
balanced under LTP than under a per-session additive baseline.
Relation to RLProp
LTP is the sequential, group generalization of
RLProp: a single session of LTP with
gamma=1, beta=0 is exactly RLProp over the group members. This package reuses
RLProp's allocation kernel (rlprop.core.rlprop_step) and normalizers, so the two
stay numerically consistent (a test asserts the single-session equivalence).
Citing
If you use this software, please cite the paper (GitHub's "Cite this repository"
button reads CITATION.cff):
@article{dokoupil2026ltp,
author = {Dokoupil, Patrik and Peska, Ladislav},
title = {Long-term fairness in sequential group recommendations},
journal = {Knowledge and Information Systems},
volume = {68},
number = {1},
year = {2026},
doi = {10.1007/s10115-025-02642-9}
}
License
MIT — see LICENSE.
Metadata
Release files for ltp-rs 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ltp_rs-0.1.0.tar.gz | 9.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ltp_rs-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 16.1 kB
Release files / ltp_rs-0.1.0.tar.gz
| Download URL | ltp_rs-0.1.0.tar.gz |
|---|---|
| Size | 9.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
205509741fd65575f456837b60ef23c5de65d653e2dbb28663093894c87ff663
|
|
BLAKE2b-256 checksum How to use checksums |
bbbde9729cb408cc9e2efcba998fa2c912934a038d3e6c9152d1a7d29d8a6661
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.12
|
Release files / ltp_rs-0.1.0-py3-none-any.whl
| Download URL | ltp_rs-0.1.0-py3-none-any.whl |
|---|---|
| Size | 7.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3207e60b45f765e3545b162fdc558a853c236a8a9cb07a7aa979ae7ed519af65
|
|
BLAKE2b-256 checksum How to use checksums |
84c2482ec26b8a5081933917c0125f9ccd5aa524d4623277978614a94b167b76
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.12
|