dpss (Dynamic Programming Subset Sum) is an ultra-fast algorithm library and transaction reconciliation engine.
It solves the many-to-many transaction matching problem (also known as the Subset Sum Matching Problem) using an optimized dynamic programming approach.
Unlike standard matching tools that only handle 1-to-1 relationships, dpss can find combinations like 3 invoices that perfectly match 2 payments, even with allowed variance (tolerance) for things like transaction fees or currency rounding.
- Reconciliation Engine: Direct support for transaction objects (ID, Amount, Date, Description).
- Tolerance Matching: Match transactions even if amounts differ slightly (e.g., due to bank fees).
- Extremely Fast: Uses a sparse hash-set-based DP table and runs in parallel via Rayon.
- Cross-Platform: Available as a Rust Crate, a Python Package, a CLI tool, and a WebAssembly app.
Bank statements and internal ledgers often diverge. A single payment on the bank side might map to multiple entries in the ledger, or vice versa. dpss finds exactly these many-to-many correspondences, surfacing what remains unmatched so you know exactly where the discrepancy lies.
This specific challenge in automated banking was recently formalized as a combinatorial optimization task by J.P. Morgan AI Research (ECAI 2025). dpss provides an out-of-the-box open-source engine to solve exactly this.
There are five ways to use this program:
- Web UIπ (The easiest way!)
- Pythonπ
- CLIπ₯οΈ
- Rustπ¦
- Agent Skills / MCPπ€
You can run the reconciliation engine directly in your browser without uploading data to any server.
- Reconciliation Engine Web UI: Upload two CSV files (Keys and Targets) and instantly get a matched groups report.
- Subset Sum Solver Web UI: Raw array-based subset sum matching.
pip install dpssThe fastest way to match Pandas DataFrames or lists of dictionaries.
import dpss
# 1. Define your data
keys = [
dpss.Transaction("k1", 10300), # e.g., $103.00
dpss.Transaction("k2", 19800),
dpss.Transaction("k3", 50000),
]
targets = [
dpss.Transaction("t1", 10000),
dpss.Transaction("t2", 20000),
dpss.Transaction("t3", 50000),
]
# 2. Run Reconciliation
# max_key_group=5, max_target_group=5, tolerance=500 (allow up to $5.00 diff)
result = dpss.reconcile(keys, targets, 5, 5, 500)
print(f"Matched amount: {result.summary.matched_amount}")
for group in result.matched:
print(f"Match: {[k.id for k in group.keys]} == {[t.id for t in group.targets]} (Diff: {group.difference})")
# Output:
# Matched amount: 80100
# Match: ['k1'] == ['t1'] (Diff: 300)
# Match: ['k2'] == ['t2'] (Diff: -200)
# Match: ['k3'] == ['t3'] (Diff: 0)# Find subsets that sum to a target
print(dpss.find_subset([1, -2, 3, 4, 5], 2, 3))
# [[4, -2], [3, -2, 1]]Download the binary from the Releases page.
Given two CSV files with headers id,amount,date,description:
subset_sum reconcile keys.csv targets.csv --tolerance 5Find matching subsets from two text files containing raw numbers.
subset_sum sequence-matcher arr1.txt arr2.txt 10 10Add it to your Cargo.toml:
[dependencies]
dpss = { version = "0.23.3", package = "subset_sum" }use dpss::reconciliation::{reconcile, Transaction, ReconciliationConfig};
fn main() {
let keys = vec![
Transaction { id: "k1".into(), amount: 100, date: None, description: None },
Transaction { id: "k2".into(), amount: 200, date: None, description: None },
];
let targets = vec![
Transaction { id: "t1".into(), amount: 300, date: None, description: None },
];
let config = ReconciliationConfig {
max_key_group_size: 5,
max_target_group_size: 5,
tolerance: 0,
n_candidates: 10,
};
let result = reconcile(keys, targets, config).unwrap();
println!("Matched groups: {}", result.matched.len());
}dpss includes a Model Context Protocol (MCP) server and specialized Agent Skills, allowing AI assistants like Claude Code and Gemini CLI to autonomously reconcile your data safely and deterministically.
- See
python_mcp/README.mdfor MCP server setup instructions. - We provide an official agent skill instruction set in
.agents/skills/dpss-reconcile/SKILL.md.
