Skip to main content

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_Presets for fast setup.
  • Works with custom Problem implementations for domain-specific constraints.
  • Supports both DPO_NAS (low-level) and DPO_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.py
  • example_hpo.py
  • example_tsp.py
  • example_pathfinding.py
  • example_resource_allocation.py
  • example_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, or
  • from dpo.core.universal import DPO_Universal, DPO_Presets (recommended for long-term projects).

Documentation

Full docs are available in docs/:

  • docs/index.md
  • docs/installation.md
  • docs/quickstart.md
  • docs/api_reference.md
  • docs/examples.md
  • docs/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

dpo-2.0.0.tar.gz (172.1 kB view details)

Uploaded Source

Built Distribution

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

dpo-2.0.0-py3-none-any.whl (196.8 kB view details)

Uploaded Python 3

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

Hashes for dpo-2.0.0.tar.gz
Algorithm Hash digest
SHA256 89225c2878c9d039983b8d1e26df5d220074c5733664ef26f2cf54e663319766
MD5 bf38bed04d4da95e6252cd9561c57e27
BLAKE2b-256 01e47599928b5c492b900b5c07e0b9a0c5f001b8db3e193ec69ffa6b1eaab7a5

See more details on using hashes here.

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

Hashes for dpo-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 896ceddedf4dffb5fddb901d6253d9b6dfc6c38e6bdc23eb8db90403cb97e6e2
MD5 9e77f115968acc63feafb59df0d648ec
BLAKE2b-256 a20ceb606b2c49ce003ad26fb5bff43adc4a3e7bb7b67cb5898406d9f7594cf9

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