Skip to main content

Revealed preference analysis at scale — rationality scores, efficiency indices, and utility recovery. Rust engine, Python interface.

Project description

PrefGraph

Rationality scores for every user, at scale. Rust engine, Python interface.

PyPI Documentation License: MIT

pip install prefgraph

Quick Example

Score how consistently each user's choices align with rational utility maximization. Paste and run:

from prefgraph.datasets import load_demo
from prefgraph.engine import Engine

users = load_demo()  # 100 synthetic consumers, no download needed
engine = Engine(metrics=["garp", "ccei", "mpi", "harp", "hm"])
results = engine.analyze_arrays(users)

for r in results[:5]:
    print(r)
EngineResult: [+] GARP-consistent  ccei=1.0000  hm=15/15  (42us)
EngineResult: [-] 3 violations  ccei=0.8472  mpi=0.0231  hm=12/15  (38us)
EngineResult: [+] GARP-consistent  ccei=1.0000  hm=15/15  (35us)
...

Every score is a feature. Use them for fraud detection, user segmentation, A/B testing, churn prediction, or personalization.

Your Data

Have a pandas DataFrame? One line:

import prefgraph as rp

# Transaction logs (one row per item per time)
results = rp.analyze(df, user_col="user_id", item_col="product",
                     cost_col="price", action_col="quantity", time_col="week")

# Wide format (one row per observation, items as columns)
results = rp.analyze(df, user_col="user_id",
                     cost_cols=["price_A", "price_B"],
                     action_cols=["qty_A", "qty_B"])

# Menu/click data
results = rp.analyze(df, user_col="user_id",
                     menu_col="shown_items", choice_col="clicked")

Returns a pandas DataFrame with one row per user. Customize with metrics=["garp", "ccei", "mpi", "hm"]. Handle missing data with nan_policy="drop".

Scores

Score Field What it measures Range
Consistency is_garp Are choices rationalizable? (GARP) bool
Efficiency ccei How close to perfectly rational? (Afriat) 0-1
Exploitability mpi Value left on the table per choice (Karp cycle) 0-1
Homotheticity is_harp Do preferences scale with budget? bool
Noise fraction hm_consistent/hm_total Fraction of rationalizable choices (Houtman-Maks) 0-1
Utility recovery utility_success Can latent utility be reconstructed? (Afriat LP) bool
Per-obs efficiency vei_mean Average efficiency across observations (Varian) 0-1

Which API?

Engine Function API
Use case Score thousands of users Deep-dive one user
Speed 10,000+ users/sec (Rust) Single-user
Returns EngineResult (flat scores) GARPResult, AEIResult, etc. (matrices, cycles, graphs)
Metrics 7 (garp, ccei, mpi, harp, hm, utility, vei) 30+ algorithms
Input list[(prices, quantities)] BehaviorLog

Engine for batch scoring. Function API when you need violation details, preference graphs, or advanced tests:

from prefgraph import BehaviorLog, validate_consistency, compute_integrity_score
session = BehaviorLog(cost_vectors=prices, action_vectors=quantities)
garp = validate_consistency(session)       # GARPResult with violation cycles, matrices
ccei = compute_integrity_score(session)    # AEIResult with binary search details

4 Choice Categories

                Test (bool)     Score (0-1)     Recover (vector)  Structure (bool)
Budget          GARP, WARP      CCEI, MPI, HM   Utility, CV/EV    HARP, Separability
Discrete        SARP, RUM LP    HM (menu)        Ordinal utility   Congruence
Production      Prod GARP       Prod CCEI        Tech efficiency   Cost minimization
Intertemporal   Exp discount    —                Discount delta    Quasi-hyperbolic
Category Input format Example domain
Budget (prices T×K, quantities T×K) E-commerce, grocery, food delivery
Discrete (menus, choices) or (menus, frequencies) Surveys, A/B tests, recommendations
Production (input_p, input_q, output_p, output_q) Supply chain, manufacturing
Intertemporal (amounts, dates, chosen) Subscriptions, savings, loyalty

Performance

The Rust engine (rpt-core) handles graph algorithms and LP solving via Rayon thread pool. Python handles I/O and the user-facing API.

Users Metrics Time Throughput
1,000 5 0.1s 10,000/s
10,000 5 2s 5,000/s
100,000 5 20s 5,000/s

18-100x faster than pure Python. Memory stays bounded via streaming chunks.

Documentation

Full docs — examples, theory, API reference, application case studies.

7-dataset benchmark — 167K users, 15 tasks. RP features add 0–0.7% AUC over RFM baselines.

15 dataset loaders — Dunnhumby, Instacart, H&M, Taobao, and 11 more real-world datasets.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

prefgraph-0.5.3.tar.gz (17.8 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

prefgraph-0.5.3-cp311-cp311-macosx_11_0_universal2.whl (4.3 MB view details)

Uploaded CPython 3.11macOS 11.0+ universal2 (ARM64, x86-64)

File details

Details for the file prefgraph-0.5.3.tar.gz.

File metadata

  • Download URL: prefgraph-0.5.3.tar.gz
  • Upload date:
  • Size: 17.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.6

File hashes

Hashes for prefgraph-0.5.3.tar.gz
Algorithm Hash digest
SHA256 da351a7801ad32389a32909fb8b38ba65cd4b1acd5d610a4665e138384c3216e
MD5 7e6e14b7f746ae9aba8491ec4cfaaf90
BLAKE2b-256 84c6429b395d952fde5057441cae675fed42e79117e26eb270078c47850f7f9e

See more details on using hashes here.

File details

Details for the file prefgraph-0.5.3-cp311-cp311-macosx_11_0_universal2.whl.

File metadata

File hashes

Hashes for prefgraph-0.5.3-cp311-cp311-macosx_11_0_universal2.whl
Algorithm Hash digest
SHA256 c2f7b01a2b9b2227d3a6e34621058d46f837b2085c508289345ed59a26553a37
MD5 994e05f7296c4d2692dc7875b5917af8
BLAKE2b-256 b6c6a62da5e04d58c359cc66b9eea4678bae7404e0f9c7945063e9c0931af7bb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page