Debt Payment Optimization
Project description
DPO: Debt-Paying Optimizer
DPO is a population-based metaheuristic optimizer designed for Neural Architecture Search (NAS) and generalized to solve continuous, combinatoric, and hybrid optimization problems.
It combines deliberate acceptance of worse candidates (debt accumulation) with aggressive repayment and overshoot to escape local optima while converging toward strong global solutions.
Highlights
- Unified engine for NAS, HPO, resource allocation, TSP/pathfinding, and custom problems.
- Preset-driven workflows via
DPO_Presetsfor fast setup. - Works with custom
Problemimplementations for domain-specific constraints. - Supports both
DPO_NAS(low-level) andDPO_Universal(recommended high-level).
Benchmark Snapshot (Feb 2026)
The latest comprehensive benchmark run (495 total runs across NASBench201, HPOBench, and HPOLib) produced the following overall summary:
| Method | Mean Rank (↓ better) | #1 Wins | Mean AUC |
|---|---|---|---|
| JADE | 2.27 | 7 | 0.8919 |
| DE | 3.33 | 2 | 0.8228 |
| FA | 3.60 | 5 | 0.8070 |
| GWO | 4.53 | 0 | 0.9077 |
| ACO | 4.80 | 0 | 0.8266 |
| DPO | 6.07 | 1 | 0.9459 |
| PSO | 6.73 | 0 | 0.8531 |
| GA | 6.80 | 0 | 0.9360 |
| ABC | 7.60 | 0 | 0.7658 |
| WOA | 9.33 | 0 | 0.9269 |
| SA | 10.93 | 0 | 0.7772 |
Interpretation:
- DPO is highly competitive on convergence quality (
AUC) and stability during search. - On this specific benchmark mix, JADE/FA/DE lead final-score rank averages.
- This indicates DPO currently favors fast/robust trajectory quality over best final score on some datasets.
Repro command used:
python -m dpo.benchmarks.hpo_comprehensive_benchmark --seeds 3 --population 40 --iterations 60
Generated artifacts:
- JSON:
hpo_benchmark_results/results.json - Plots:
hpo_benchmark_results/*.png
Installation
pip install -e .
Optional extras:
pip install -e .[dev]
pip install -e .[docs]
pip install -e .[gpu]
Quick Start
1) One-line NAS optimization
from dpo import dpo
result = dpo(preset="nas")
print(result["best_fitness"])
print(result.get("best_accuracy"))
2) Recommended explicit universal interface
from dpo.core.universal import DPO_Universal, DPO_Presets
config = DPO_Presets.NAS_Config(population_size=40, max_iterations=80)
optimizer = DPO_Universal(config=config)
result = optimizer.optimize()
best_solution = optimizer.get_best_solution()
print(result["best_fitness"], result.get("best_accuracy"))
print(best_solution)
How to Use DPO in Detail
Core API Layers
Layer A: DPO_Universal (best default)
Use this for almost all projects.
from dpo.core.universal import DPO_Universal, DPO_Presets
config = DPO_Presets.Pathfinding_Config(population_size=50, max_iterations=100)
optimizer = DPO_Universal(problem=my_problem, config=config)
result = optimizer.optimize()
Layer B: DPO_NAS (low-level / manual control)
Use this when you need direct control over evaluator, constraints, or internals.
from dpo.core.optimizer import DPO_NAS
from dpo.core.config import DPO_Config
config = DPO_Config.balanced()
optimizer = DPO_NAS(config=config)
result = optimizer.optimize()
Layer C: convenience helpers
Kept for easy onboarding:
dpo(...)dpo_optimize(...)dpo_solve_tsp(...)dpo_solve_nas(...)
Problem Types
1) Continuous optimization (HPO, calibration, scalar black-box)
from dpo import dpo_optimize
def objective(params):
x = params["x"]
y = params["y"]
fitness = (x - 2.0) ** 2 + (y + 1.5) ** 2
return fitness, {
"accuracy": 1.0 / (1.0 + fitness),
"latency_ms": abs(x) + abs(y),
"memory_mb": 1.0,
"flops_m": 1.0,
}
result = dpo_optimize(
objective=objective,
bounds=[(-5.0, 5.0), (-5.0, 5.0)],
names=["x", "y"],
preset="continuous",
max_iterations=80,
)
print(result["best_solution"])
2) Combinatoric optimization (TSP, routing, scheduling)
import numpy as np
from dpo import dpo_solve_tsp
rng = np.random.default_rng(7)
n = 20
coords = rng.uniform(0.0, 100.0, (n, 2))
dist = np.linalg.norm(coords[:, None, :] - coords[None, :, :], axis=2)
result = dpo_solve_tsp(
distance_matrix=dist,
preset="balanced",
max_iterations=120,
population_size=60,
)
print(result["best_fitness"])
3) NAS with custom estimator
from dpo import dpo_solve_nas
class MyEstimator:
def estimate(self, arch_dict, **kwargs):
acc = 0.80 # replace with real evaluation
return 1.0 - acc, {
"accuracy": acc,
"latency_ms": 50.0,
"memory_mb": 20.0,
"flops_m": 180.0,
}
result = dpo_solve_nas(
estimator=MyEstimator(),
constraints={"latency": 100.0, "memory": 50.0, "flops": 300.0},
preset="nas",
)
print(result["best_fitness"], result.get("best_accuracy"))
4) Custom Problem class (full extensibility)
import numpy as np
from dpo.core.problem import Problem
from dpo.core.solution import NumericSolution
from dpo.core.universal import DPO_Universal
class SphereProblem(Problem):
def evaluate(self, solution, **kwargs):
params = solution.to_dict()
x, y = params["x"], params["y"]
fitness = x * x + y * y
return fitness, {
"accuracy": 1.0 / (1.0 + fitness),
"latency_ms": abs(x) + abs(y),
"memory_mb": 1.0,
"flops_m": 1.0,
}
def create_solution(self, **kwargs):
values = np.random.uniform(-5.0, 5.0, size=2)
return NumericSolution(values, [(-5.0, 5.0), (-5.0, 5.0)], ["x", "y"])
problem = SphereProblem()
result = DPO_Universal(problem=problem, preset="balanced").optimize()
print(result["best_fitness"])
Output Contract
Common result keys:
best_fitness: best objective value (lower is better).best_solution: best solution as dict-like structure.best_accuracy: optional metric when provided by evaluator/problem.best_metrics: metrics dictionary for the best solution.history: convergence and run history.elapsed_time: optimization wall time in seconds.total_evaluations: function evaluations performed.
Presets and Tuning
Use problem-tailored presets:
DPO_Presets.NAS_Config(...)DPO_Presets.ResourceAllocation_Config(...)DPO_Presets.Pathfinding_Config(...)DPO_Presets.HyperparameterTuning_Config(...)DPO_Presets.Scheduling_Config(...)
For low-dimensional continuous problems, start with:
from dpo.core.config import DPO_Config
config = DPO_Config.continuous_analytic()
Examples
See runnable scripts in dpo/examples/:
example_nas.pyexample_hpo.pyexample_tsp.pyexample_pathfinding.pyexample_resource_allocation.pyexample_hybrid.py
Migration Notes
Legacy modules dpo/api.py and dpo/api_universal.py have been removed to simplify the API surface.
Use either:
from dpo import dpo, dpo_optimize, dpo_solve_tsp, dpo_solve_nas, orfrom dpo.core.universal import DPO_Universal, DPO_Presets(recommended for long-term projects).
Documentation
Full docs are available in docs/:
docs/index.mddocs/installation.mddocs/quickstart.mddocs/api_reference.mddocs/examples.mddocs/methodology.md
PyPI README Visibility
This project is configured to publish this README.md as the PyPI project description via pyproject.toml ([project].readme).
To publish/update on PyPI:
python -m pip install --upgrade build twine
python -m build
python -m twine check dist/*
python -m twine upload dist/*
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dpo-2.0.0.tar.gz.
File metadata
- Download URL: dpo-2.0.0.tar.gz
- Upload date:
- Size: 172.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
89225c2878c9d039983b8d1e26df5d220074c5733664ef26f2cf54e663319766
|
|
| MD5 |
bf38bed04d4da95e6252cd9561c57e27
|
|
| BLAKE2b-256 |
01e47599928b5c492b900b5c07e0b9a0c5f001b8db3e193ec69ffa6b1eaab7a5
|
File details
Details for the file dpo-2.0.0-py3-none-any.whl.
File metadata
- Download URL: dpo-2.0.0-py3-none-any.whl
- Upload date:
- Size: 196.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
896ceddedf4dffb5fddb901d6253d9b6dfc6c38e6bdc23eb8db90403cb97e6e2
|
|
| MD5 |
9e77f115968acc63feafb59df0d648ec
|
|
| BLAKE2b-256 |
a20ceb606b2c49ce003ad26fb5bff43adc4a3e7bb7b67cb5898406d9f7594cf9
|