Skip to content

pdokoupil/LTP

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.

PyPI CI License: MIT Paper

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 position p updates state with weight exp(-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 weights w; 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.

About

LTP (Long-Term Proportionality) — fair sequential group recommendation: balances long-term fairness across recommendation sessions so no group member is consistently overlooked, while preserving group utility. Pure-NumPy, pip-installable Python library. Group recommender systems · KAIS 2026.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages