"""
Hybrid optimization example with both continuous and discrete decisions.
"""

from dpo.core.problem import HybridProblem
from dpo.core.universal import DPO_Presets, DPO_Universal


def run_hybrid_example():
    def objective(params):
        lr = params.get("num_0", 1e-3)
        reg = params.get("num_1", 1e-4)
        model_family = params.get("disc_0", "mlp")

        family_bias = {
            "mlp": 0.02,
            "cnn": 0.01,
            "transformer": 0.015,
        }.get(model_family, 0.02)

        fitness = (lr - 0.002) ** 2 * 1000 + (reg - 0.0002) ** 2 * 20000 + family_bias

        return float(fitness), {
            "accuracy": float(1.0 / (1.0 + fitness)),
            "latency_ms": float(30.0 + 1000.0 * reg),
            "memory_mb": float(12.0 + (5.0 if model_family == "transformer" else 2.0)),
            "flops_m": float(80.0 + (40.0 if model_family == "cnn" else 20.0)),
        }

    problem = HybridProblem(
        objective_fn=objective,
        numeric_bounds=[(1e-5, 1e-2), (1e-6, 1e-3)],
        discrete_options={"model_family": ["mlp", "cnn", "transformer"]},
    )

    config = DPO_Presets.HyperparameterTuning_Config(population_size=28, max_iterations=35)
    config.verbose = False

    optimizer = DPO_Universal(problem=problem, config=config)
    result = optimizer.optimize()

    print("Hybrid Example")
    print("-" * 40)
    print(f"Best fitness : {result['best_fitness']:.6f}")
    metrics = result.get('best_metrics', {})
    if metrics:
        for k, v in metrics.items():
            if isinstance(v, float):
                print(f"  {k}: {v:.6f}")
    best_sol = result.get('best_solution', {})
    if best_sol:
        for k, v in best_sol.items():
            print(f"  {k}: {v}")
    print(f"Time         : {result.get('elapsed_time', 0):.2f}s")
    return result


if __name__ == "__main__":
    run_hybrid_example()
