| """Main experiment runner for QIMAD vs. baseline comparison.""" |
| import os |
|
|
| import numpy as np |
| import pandas as pd |
|
|
| from baselines import get_optimizer |
| from benchmarks import get_benchmark_function |
| from qimad_optimizer import QIMAD |
| from utils import load_config, plot_convergence, print_summary, save_results_to_csv |
|
|
|
|
| def _run_qimad(obj_func, dim, bounds, qimad_cfg, num_iterations, convergence_threshold, run_seed): |
| topologies = qimad_cfg.get('topology', ['complete']) |
| agents_list = qimad_cfg.get('num_agents', [8]) |
| skip_keys = {'name', 'num_agents', 'dimensions', 'topology'} |
| base_params = {k: v for k, v in qimad_cfg.items() if k not in skip_keys} |
|
|
| rows = [] |
| for topology in topologies: |
| for num_agents in agents_list: |
| opt = QIMAD( |
| objective_function=obj_func, |
| num_agents=num_agents, |
| dim=dim, |
| topology_type=topology, |
| seed=run_seed, |
| bounds=bounds, |
| **base_params, |
| ) |
| df = opt.optimize(num_iterations, convergence_threshold) |
| df['optimizer'] = 'QIMAD' |
| df['topology'] = topology |
| df['num_agents'] = num_agents |
| rows.append(df) |
| return rows |
|
|
|
|
| def _run_baselines(obj_func, dim, bounds, optimizers_cfg, num_iterations, convergence_threshold): |
| rows = [] |
| for name in ('SGD', 'Adam', 'PSO'): |
| if name not in optimizers_cfg: |
| continue |
| cfg = dict(optimizers_cfg[name]) |
| cfg.pop('name', None) |
|
|
| if name == 'PSO': |
| particles_val = cfg.pop('num_particles', [8]) |
| cfg.pop('dimensions', None) |
| num_p = particles_val[0] if isinstance(particles_val, list) else int(particles_val) |
| cfg['num_particles'] = num_p |
| n_agents = num_p |
| else: |
| n_agents = 1 |
|
|
| opt = get_optimizer(name, obj_func, dim, bounds, {name: cfg}) |
| df = opt.optimize(num_iterations, convergence_threshold) |
| df['optimizer'] = name |
| df['topology'] = 'N/A' |
| df['num_agents'] = n_agents |
| rows.append(df) |
| return rows |
|
|
|
|
| def main(config_path='config.yaml'): |
| cfg = load_config(config_path) |
| exp = cfg['experiment'] |
| seed = exp.get('random_seed', 42) |
| num_runs = exp.get('num_runs_per_experiment', 1) |
| num_iters = exp.get('num_iterations', 150) |
| conv_thr = exp.get('convergence_threshold', 1e-4) |
| out_dir = exp.get('output_dir', 'results') |
| plots_dir = exp.get('plots_dir', 'plots') |
|
|
| qimad_cfg = cfg['optimizers'].get('QIMAD', {}) |
| dimensions_list = qimad_cfg.get('dimensions', [10]) |
|
|
| all_results = [] |
|
|
| for func_name, func_params in cfg['objective_functions'].items(): |
| bounds = func_params.get('bounds', [-10.0, 10.0]) |
|
|
| for dim in dimensions_list: |
| obj_func = get_benchmark_function(func_name, dim, cfg['objective_functions']) |
|
|
| for run in range(num_runs): |
| run_seed = seed + run |
| np.random.seed(run_seed) |
|
|
| rows = _run_qimad(obj_func, dim, bounds, qimad_cfg, |
| num_iters, conv_thr, run_seed) |
| rows += _run_baselines(obj_func, dim, bounds, cfg['optimizers'], |
| num_iters, conv_thr) |
|
|
| for df in rows: |
| df['function'] = func_name |
| df['dimensions'] = dim |
| df['run'] = run |
|
|
| all_results.extend(rows) |
| print(f" Done: {func_name} D={dim} run={run}") |
|
|
| if not all_results: |
| print("No results generated.") |
| return pd.DataFrame() |
|
|
| results_df = pd.concat(all_results, ignore_index=True) |
| save_results_to_csv(results_df, out_dir) |
| plot_convergence(results_df, os.path.join(out_dir, plots_dir)) |
| print_summary(results_df) |
| return results_df |
|
|
|
|
| if __name__ == '__main__': |
| main() |
|
|