{"id":31211542,"url":"https://github.com/cyberagentailab/cmaes","last_synced_at":"2025-09-21T05:32:48.287Z","repository":{"id":42371127,"uuid":"237296717","full_name":"CyberAgentAILab/cmaes","owner":"CyberAgentAILab","description":"Python library for CMA Evolution Strategy.","archived":false,"fork":false,"pushed_at":"2025-07-23T07:42:25.000Z","size":413,"stargazers_count":443,"open_issues_count":9,"forks_count":71,"subscribers_count":13,"default_branch":"main","last_synced_at":"2025-09-08T13:59:52.776Z","etag":null,"topics":["black-box-optimization","cma-es","evolution-strategies","evolution-strategy","hyperparameter-optimization","optuna"],"latest_commit_sha":null,"homepage":"https://arxiv.org/abs/2402.01373","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CyberAgentAILab.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-01-30T20:13:13.000Z","updated_at":"2025-09-05T12:39:05.000Z","dependencies_parsed_at":"2023-02-05T12:02:18.175Z","dependency_job_id":"a27955b5-69c1-498f-bcd4-a8370aa52059","html_url":"https://github.com/CyberAgentAILab/cmaes","commit_stats":{"total_commits":296,"total_committers":6,"mean_commits":"49.333333333333336","dds":"0.28378378378378377","last_synced_commit":"91bcaca06eef8193d8ee6a65b2a2bec0b5cfb114"},"previous_names":["cyberagent/cmaes"],"tags_count":20,"template":false,"template_full_name":null,"purl":"pkg:github/CyberAgentAILab/cmaes","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CyberAgentAILab%2Fcmaes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CyberAgentAILab%2Fcmaes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CyberAgentAILab%2Fcmaes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CyberAgentAILab%2Fcmaes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CyberAgentAILab","download_url":"https://codeload.github.com/CyberAgentAILab/cmaes/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CyberAgentAILab%2Fcmaes/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":276195641,"owners_count":25601156,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-21T02:00:07.055Z","response_time":72,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["black-box-optimization","cma-es","evolution-strategies","evolution-strategy","hyperparameter-optimization","optuna"],"created_at":"2025-09-21T05:31:01.982Z","updated_at":"2025-09-21T05:32:48.262Z","avatar_url":"https://github.com/CyberAgentAILab.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cmaes\n\n[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](./LICENSE) [![PyPI - Downloads](https://img.shields.io/pypi/dw/cmaes)](https://pypistats.org/packages/cmaes)\n\n:whale: [**Paper is now available on arXiv!**](https://arxiv.org/abs/2402.01373)\n\n*Simple* and *Practical* Python library for CMA-ES.\nPlease refer to the [paper](https://arxiv.org/abs/2402.01373) [Nomura and Shibata 2024] for detailed information, including the design philosophy and advanced examples.\n\n![visualize-six-hump-camel](https://user-images.githubusercontent.com/5564044/73486622-db5cff00-43e8-11ea-98fb-8246dbacab6d.gif)\n\n## Installation\n\nSupported Python versions are 3.8 or later.\n\n```\n$ pip install cmaes\n```\n\nOr you can install via [conda-forge](https://anaconda.org/conda-forge/cmaes).\n\n```\n$ conda install -c conda-forge cmaes\n```\n\n## Usage\n\nThis library provides an \"ask-and-tell\" style interface. We employ the standard version of CMA-ES [Hansen 2016].\n\n```python\nimport numpy as np\nfrom cmaes import CMA\n\ndef quadratic(x1, x2):\n    return (x1 - 3) ** 2 + (10 * (x2 + 2)) ** 2\n\nif __name__ == \"__main__\":\n    optimizer = CMA(mean=np.zeros(2), sigma=1.3)\n\n    for generation in range(50):\n        solutions = []\n        for _ in range(optimizer.population_size):\n            x = optimizer.ask()\n            value = quadratic(x[0], x[1])\n            solutions.append((x, value))\n            print(f\"#{generation} {value} (x1={x[0]}, x2 = {x[1]})\")\n        optimizer.tell(solutions)\n```\n\nYou can also use this library via [Optuna](https://github.com/optuna/optuna) [Akiba et al. 2019], an automatic hyperparameter optimization framework.\n\n```python\nimport optuna\n\ndef objective(trial: optuna.Trial):\n    x1 = trial.suggest_float(\"x1\", -4, 4)\n    x2 = trial.suggest_float(\"x2\", -4, 4)\n    return (x1 - 3) ** 2 + (10 * (x2 + 2)) ** 2\n\nif __name__ == \"__main__\":\n    sampler = optuna.samplers.CmaEsSampler()\n    study = optuna.create_study(sampler=sampler)\n    study.optimize(objective, n_trials=250)\n```\n\nFor more information, see [the documentation](https://optuna.readthedocs.io/en/stable/reference/samplers/generated/optuna.samplers.CmaEsSampler.html).\n\n## CMA-ES variants\n\n#### CatCMA with Margin [Hamano et al. 2025]\nCatCMA with Margin (CatCMAwM) is a method for mixed-variable optimization problems, simultaneously optimizing continuous, integer, and categorical variables. CatCMAwM extends CatCMA by introducing a novel integer handling mechanism, and supports arbitrary combinations of continuous, integer, and categorical variables in a unified framework.\n\n![CatCMAwM](https://github.com/user-attachments/assets/d0c866f5-1c12-4f44-a862-af47bcd7dfb1)\n\n\n\u003cdetails\u003e\n\u003csummary\u003eSource code\u003c/summary\u003e\n\n```python\nimport numpy as np\nfrom cmaes import CatCMAwM\n\n\ndef SphereIntCOM(x, z, c):\n    return sum(x * x) + sum(z * z) + len(c) - sum(c[:, 0])\n\n\ndef SphereInt(x, z):\n    return sum(x * x) + sum(z * z)\n\n\ndef SphereCOM(x, c):\n    return sum(x * x) + len(c) - sum(c[:, 0])\n\n\ndef f_cont_int_cat():\n    # [lower_bound, upper_bound] for each continuous variable\n    X = [[-5, 5], [-5, 5]]\n    # possible values for each integer variable\n    Z = [[-1, 0, 1], [-2, -1, 0, 1, 2]]\n    # number of categories for each categorical variable\n    C = [3, 3]\n\n    optimizer = CatCMAwM(x_space=X, z_space=Z, c_space=C)\n\n    for generation in range(50):\n        solutions = []\n        for _ in range(optimizer.population_size):\n            sol = optimizer.ask()\n            value = SphereIntCOM(sol.x, sol.z, sol.c)\n            solutions.append((sol, value))\n            print(f\"#{generation} {sol} evaluation: {value}\")\n        optimizer.tell(solutions)\n\n\ndef f_cont_int():\n    # [lower_bound, upper_bound] for each continuous variable\n    X = [[-np.inf, np.inf], [-np.inf, np.inf]]\n    # possible values for each integer variable\n    Z = [[-2, -1, 0, 1, 2], [-2, -1, 0, 1, 2]]\n\n    # initial distribution parameters (Optional)\n    # If you know a promising solution for X and Z, set init_mean to that value.\n    init_mean = np.ones(len(X) + len(Z))\n    init_cov = np.diag(np.ones(len(X) + len(Z)))\n    init_sigma = 1.0\n\n    optimizer = CatCMAwM(\n        x_space=X, z_space=Z, mean=init_mean, cov=init_cov, sigma=init_sigma\n    )\n\n    for generation in range(50):\n        solutions = []\n        for _ in range(optimizer.population_size):\n            sol = optimizer.ask()\n            value = SphereInt(sol.x, sol.z)\n            solutions.append((sol, value))\n            print(f\"#{generation} {sol} evaluation: {value}\")\n        optimizer.tell(solutions)\n\n\ndef f_cont_cat():\n    # [lower_bound, upper_bound] for each continuous variable\n    X = [[-5, 5], [-5, 5]]\n    # number of categories for each categorical variable\n    C = [3, 5]\n\n    # initial distribution parameters (Optional)\n    init_cat_param = np.array(\n        [\n            [0.5, 0.3, 0.2, 0.0, 0.0],  # zero-padded at the end\n            [0.2, 0.2, 0.2, 0.2, 0.2],  # each row must sum to 1\n        ]\n    )\n\n    optimizer = CatCMAwM(x_space=X, c_space=C, cat_param=init_cat_param)\n\n    for generation in range(50):\n        solutions = []\n        for _ in range(optimizer.population_size):\n            sol = optimizer.ask()\n            value = SphereCOM(sol.x, sol.c)\n            solutions.append((sol, value))\n            print(f\"#{generation} {sol} evaluation: {value}\")\n        optimizer.tell(solutions)\n\n\nif __name__ == \"__main__\":\n    f_cont_int_cat()\n    # f_cont_int()\n    # f_cont_cat()\n```\n\nThe full source code is available [here](./examples/catcma_with_margin.py).\n\n\u003c/details\u003e\n\nWe recommend using CatCMAwM for continuous+integer and continuous+categorical settings. In particular, [Hamano et al. 2025] shows that CatCMAwM outperforms CMA-ES with Margin in mixed-integer scenarios. Therefore, we suggest CatCMAwM in place of CMA-ES with Margin or CatCMA.\n\n#### CatCMA [Hamano et al. 2024a]\nCatCMA is a method for mixed-category optimization problems, which is the problem of simultaneously optimizing continuous and categorical variables. CatCMA employs the joint probability distribution of multivariate Gaussian and categorical distributions as the search distribution.\n\n![CatCMA](https://github.com/CyberAgentAILab/cmaes/assets/27720055/f91443b6-d71b-4849-bfc3-095864f7c58c)\n\n\u003cdetails\u003e\n\u003csummary\u003eSource code\u003c/summary\u003e\n\n```python\nimport numpy as np\nfrom cmaes import CatCMA\n\n\ndef sphere_com(x, c):\n    dim_co = len(x)\n    dim_ca = len(c)\n    if dim_co \u003c 2:\n        raise ValueError(\"dimension must be greater one\")\n    sphere = sum(x * x)\n    com = dim_ca - sum(c[:, 0])\n    return sphere + com\n\n\ndef rosenbrock_clo(x, c):\n    dim_co = len(x)\n    dim_ca = len(c)\n    if dim_co \u003c 2:\n        raise ValueError(\"dimension must be greater one\")\n    rosenbrock = sum(100 * (x[:-1] ** 2 - x[1:]) ** 2 + (x[:-1] - 1) ** 2)\n    clo = dim_ca - (c[:, 0].argmin() + c[:, 0].prod() * dim_ca)\n    return rosenbrock + clo\n\n\ndef mc_proximity(x, c, cat_num):\n    dim_co = len(x)\n    dim_ca = len(c)\n    if dim_co \u003c 2:\n        raise ValueError(\"dimension must be greater one\")\n    if dim_co != dim_ca:\n        raise ValueError(\n            \"number of dimensions of continuous and categorical variables \"\n            \"must be equal in mc_proximity\"\n        )\n\n    c_index = np.argmax(c, axis=1) / cat_num\n    return sum((x - c_index) ** 2) + sum(c_index)\n\n\nif __name__ == \"__main__\":\n    cont_dim = 5\n    cat_dim = 5\n    cat_num = np.array([3, 4, 5, 5, 5])\n    # cat_num = 3 * np.ones(cat_dim, dtype=np.int64)\n    optimizer = CatCMA(mean=3.0 * np.ones(cont_dim), sigma=1.0, cat_num=cat_num)\n\n    for generation in range(200):\n        solutions = []\n        for _ in range(optimizer.population_size):\n            x, c = optimizer.ask()\n            value = mc_proximity(x, c, cat_num)\n            if generation % 10 == 0:\n                print(f\"#{generation} {value}\")\n            solutions.append(((x, c), value))\n        optimizer.tell(solutions)\n\n        if optimizer.should_stop():\n            break\n```\n\nThe full source code is available [here](./examples/catcma.py).\n\n\u003c/details\u003e\n\n#### Safe CMA [Uchida et al. 2024a]\nSafe CMA-ES is a variant of CMA-ES for safe optimization. Safe optimization is formulated as a special type of constrained optimization problem aiming to solve the optimization problem with fewer evaluations of the solutions whose safety function values exceed the safety thresholds. The safe CMA-ES requires safe seeds that do not violate the safety constraints. Note that the safe CMA-ES is designed for noiseless safe optimization. This module needs `torch` and `gpytorch`.\n\n\u003cdetails\u003e\n\u003csummary\u003eSource code\u003c/summary\u003e\n\n```python\nimport numpy as np\nfrom cmaes.safe_cma import SafeCMA\n\n# objective function\ndef quadratic(x):\n    coef = 1000 ** (np.arange(dim) / float(dim - 1)) \n    return np.sum((x * coef) ** 2)\n\n# safety function\ndef safe_function(x):\n    return x[0]\n\n\"\"\"\n    example with a single safety function\n\"\"\"\nif __name__ == \"__main__\":\n    # number of dimensions\n    dim = 5\n\n    # safe seeds\n    safe_seeds_num = 10\n    safe_seeds = (np.random.rand(safe_seeds_num, dim) * 2 - 1) * 5\n    safe_seeds[:,0] = - np.abs(safe_seeds[:,0])\n\n    # evaluation of safe seeds (with a single safety function)\n    seeds_evals = np.array([ quadratic(x) for x in safe_seeds ])\n    seeds_safe_evals = np.stack([ [safe_function(x)] for x in safe_seeds ])\n    safety_threshold = np.array([0])\n\n    # optimizer (safe CMA-ES)\n    optimizer = SafeCMA(\n        sigma=1., \n        safety_threshold=safety_threshold, \n        safe_seeds=safe_seeds,\n        seeds_evals=seeds_evals,\n        seeds_safe_evals=seeds_safe_evals,\n    )\n\n    unsafe_eval_counts = 0\n    best_eval = np.inf\n\n    for generation in range(400):\n        solutions = []\n        for _ in range(optimizer.population_size):\n            # Ask a parameter\n            x = optimizer.ask()\n            value = quadratic(x)\n            safe_value = np.array([safe_function(x)])\n\n            # save best eval\n            best_eval = np.min((best_eval, value))\n            unsafe_eval_counts += (safe_value \u003e safety_threshold)\n\n            solutions.append((x, value, safe_value))\n\n        # Tell evaluation values.\n        optimizer.tell(solutions)\n\n        print(f\"#{generation} ({best_eval} {unsafe_eval_counts})\")\n        \n        if optimizer.should_stop():\n            break\n```\n\nThe full source code is available [here](./examples/safecma.py).\n\n\u003c/details\u003e\n\n\n#### Maximum a Posteriori CMA-ES [Hamano et al. 2024b]\nMAP-CMA is a method that is introduced to interpret the rank-one update in the CMA-ES from the perspective of the natural gradient.\nThe rank-one update derived from the natural gradient perspective is extensible, and an additional term, called momentum update, appears in the update of the mean vector.\nThe performance of MAP-CMA is not significantly different from that of CMA-ES, as the primary motivation for MAP-CMA comes from the theoretical understanding of CMA-ES.\n\n\u003cdetails\u003e\n\n\u003csummary\u003eSource code\u003c/summary\u003e\n\n```python\nimport numpy as np\nfrom cmaes import MAPCMA\n\n\ndef rosenbrock(x):\n    dim = len(x)\n    if dim \u003c 2:\n        raise ValueError(\"dimension must be greater one\")\n    return sum(100 * (x[:-1] ** 2 - x[1:]) ** 2 + (x[:-1] - 1) ** 2)\n\n\nif __name__ == \"__main__\":\n    dim = 20\n    optimizer = MAPCMA(mean=np.zeros(dim), sigma=0.5, momentum_r=dim)\n    print(\" evals    f(x)\")\n    print(\"======  ==========\")\n\n    evals = 0\n    while True:\n        solutions = []\n        for _ in range(optimizer.population_size):\n            x = optimizer.ask()\n            value = rosenbrock(x)\n            evals += 1\n            solutions.append((x, value))\n            if evals % 1000 == 0:\n                print(f\"{evals:5d}  {value:10.5f}\")\n        optimizer.tell(solutions)\n\n        if optimizer.should_stop():\n            break\n```\n\nThe full source code is available [here](./examples/mapcma.py).\n\n\u003c/details\u003e\n\n\n#### CMA-ES-SoP [Uchida et al. 2024b]\nCMA-ES on sets of points (CMA-ES-SoP) is a variant of CMA-ES for optimization on sets of points. In the optimization on sets of points, the search space consists of several disjoint subspaces containing multiple possible points where the objective function value can be computed. In the mixed-variable cases, some subspaces are continuous spaces. Note that the discrete subspaces with more than five dimensions require computational cost for the construction of the Voronoi diagrams.\n\n\u003cdetails\u003e\n\u003csummary\u003eSource code\u003c/summary\u003e\n\n```python\nimport numpy as np\nfrom cmaes.cma_sop import CMASoP\n\n# numbers of dimensions in each subspace\nsubspace_dim_list = [2, 3, 5]\ncont_dim = 10\n\n# numbers of points in each subspace\npoint_num_list = [10, 20, 40]\n\n# number of total dimensions\ndim = int(np.sum(subspace_dim_list) + cont_dim)\n\n# objective function\ndef quadratic(x):\n    coef = 1000 ** (np.arange(dim) / float(dim - 1))\n    return np.sum((coef * x) ** 2)\n\n# sets_of_points (on [-5, 5])\ndiscrete_subspace_num = len(subspace_dim_list)\nsets_of_points = [(\n    2 * np.random.rand(point_num_list[i], subspace_dim_list[i]) - 1) * 5\nfor i in range(discrete_subspace_num)]\n\n# add the optimal solution (for benchmark function)\nfor i in range(discrete_subspace_num):\n    sets_of_points[i][-1] = np.zeros(subspace_dim_list[i])\n    np.random.shuffle(sets_of_points[i])\n\n# optimizer (CMA-ES-SoP)\noptimizer = CMASoP(\n    sets_of_points=sets_of_points,\n    mean=np.random.rand(dim) * 4 + 1,\n    sigma=2.0,\n)\n\nbest_eval = np.inf\neval_count = 0\n\nfor generation in range(400):\n    solutions = []\n    for _ in range(optimizer.population_size):\n        # Ask a parameter\n        x, enc_x = optimizer.ask()\n        value = quadratic(enc_x)\n\n        # save best eval\n        best_eval = np.min((best_eval, value))\n        eval_count += 1\n\n        solutions.append((x, value))\n\n    # Tell evaluation values.\n    optimizer.tell(solutions)\n\n    print(f\"#{generation} ({best_eval} {eval_count})\")\n\n    if best_eval \u003c 1e-4 or optimizer.should_stop():\n        break\n```\n\nThe full source code is available [here](./examples/cma_sop.py).\n\n\u003c/details\u003e\n\n#### Learning Rate Adaptation CMA-ES [Nomura et al. 2023]\nThe performance of the CMA-ES can deteriorate when faced with *difficult* problems such as multimodal or noisy ones, if its hyperparameter values are not properly configured.\nThe Learning Rate Adaptation CMA-ES (LRA-CMA) effectively addresses this issue by autonomously adjusting the learning rate.\nConsequently, LRA-CMA eliminates the need for expensive hyperparameter tuning.\n\nLRA-CMA can be used by simply adding `lr_adapt=True` to the initialization of `CMA()`.\n\n\u003cdetails\u003e\n\n\u003csummary\u003eSource code\u003c/summary\u003e\n\n```python\nimport numpy as np\nfrom cmaes import CMA\n\n\ndef rastrigin(x):\n    dim = len(x)\n    return 10 * dim + sum(x**2 - 10 * np.cos(2 * np.pi * x))\n\n\nif __name__ == \"__main__\":\n    dim = 40\n    optimizer = CMA(mean=3*np.ones(dim), sigma=2.0, lr_adapt=True)\n\n    for generation in range(50000):\n        solutions = []\n        for _ in range(optimizer.population_size):\n            x = optimizer.ask()\n            value = rastrigin(x)\n            if generation % 500 == 0:\n                print(f\"#{generation} {value}\")\n            solutions.append((x, value))\n        optimizer.tell(solutions)\n\n        if optimizer.should_stop():\n            break\n```\n\nThe full source code is available [here](./examples/lra_cma.py).\n\n\u003c/details\u003e\n\n\n#### CMA-ES with Margin [Hamano et al. 2022]\n\nCMA-ES with Margin (CMAwM) introduces a lower bound on the marginal probability for each discrete dimension, ensuring that samples avoid being fixed to a single point.\nThis method can be applied to mixed spaces consisting of continuous (such as float) and discrete elements (including integer and binary types).\n\n|CMA|CMAwM|\n|---|---|\n|![CMA-ES](https://github.com/CyberAgentAILab/cmaes/assets/27720055/41d33c4b-b80b-42af-9f62-6d22f19dbae5)|![CMA-ESwM](https://github.com/CyberAgentAILab/cmaes/assets/27720055/9035deaa-6222-4720-a417-c31c765f3228)|\n\nThe above figures are taken from [EvoConJP/CMA-ES_with_Margin](https://github.com/EvoConJP/CMA-ES_with_Margin).\n\n\u003cdetails\u003e\n\u003csummary\u003eSource code\u003c/summary\u003e\n\n```python\nimport numpy as np\nfrom cmaes import CMAwM\n\n\ndef ellipsoid_onemax(x, n_zdim):\n    n = len(x)\n    n_rdim = n - n_zdim\n    r = 10\n    if len(x) \u003c 2:\n        raise ValueError(\"dimension must be greater one\")\n    ellipsoid = sum([(1000 ** (i / (n_rdim - 1)) * x[i]) ** 2 for i in range(n_rdim)])\n    onemax = n_zdim - (0.0 \u003c x[(n - n_zdim) :]).sum()\n    return ellipsoid + r * onemax\n\n\ndef main():\n    binary_dim, continuous_dim = 10, 10\n    dim = binary_dim + continuous_dim\n    bounds = np.concatenate(\n        [\n            np.tile([-np.inf, np.inf], (continuous_dim, 1)),\n            np.tile([0, 1], (binary_dim, 1)),\n        ]\n    )\n    steps = np.concatenate([np.zeros(continuous_dim), np.ones(binary_dim)])\n    optimizer = CMAwM(mean=np.zeros(dim), sigma=2.0, bounds=bounds, steps=steps)\n    print(\" evals    f(x)\")\n    print(\"======  ==========\")\n\n    evals = 0\n    while True:\n        solutions = []\n        for _ in range(optimizer.population_size):\n            x_for_eval, x_for_tell = optimizer.ask()\n            value = ellipsoid_onemax(x_for_eval, binary_dim)\n            evals += 1\n            solutions.append((x_for_tell, value))\n            if evals % 300 == 0:\n                print(f\"{evals:5d}  {value:10.5f}\")\n        optimizer.tell(solutions)\n\n        if optimizer.should_stop():\n            break\n\n\nif __name__ == \"__main__\":\n    main()\n```\n\nSource code is also available [here](./examples/cmaes_with_margin.py).\n\n\u003c/details\u003e\n\n\n#### Warm Starting CMA-ES [Nomura et al. 2021]\n\nWarm Starting CMA-ES (WS-CMA) is a method that transfers prior knowledge from similar tasks through the initialization of the CMA-ES.\nThis is useful especially when the evaluation budget is limited (e.g., hyperparameter optimization of machine learning algorithms).\n\n\u003cdetails\u003e\n\u003csummary\u003eSource code\u003c/summary\u003e\n\n```python\nimport numpy as np\nfrom cmaes import CMA, get_warm_start_mgd\n\ndef source_task(x1: float, x2: float) -\u003e float:\n    b = 0.4\n    return (x1 - b) ** 2 + (x2 - b) ** 2\n\ndef target_task(x1: float, x2: float) -\u003e float:\n    b = 0.6\n    return (x1 - b) ** 2 + (x2 - b) ** 2\n\nif __name__ == \"__main__\":\n    # Generate solutions from a source task\n    source_solutions = []\n    for _ in range(1000):\n        x = np.random.random(2)\n        value = source_task(x[0], x[1])\n        source_solutions.append((x, value))\n\n    # Estimate a promising distribution of the source task,\n    # then generate parameters of the multivariate gaussian distribution.\n    ws_mean, ws_sigma, ws_cov = get_warm_start_mgd(\n        source_solutions, gamma=0.1, alpha=0.1\n    )\n    optimizer = CMA(mean=ws_mean, sigma=ws_sigma, cov=ws_cov)\n\n    # Run WS-CMA-ES\n    print(\" g    f(x1,x2)     x1      x2  \")\n    print(\"===  ==========  ======  ======\")\n    while True:\n        solutions = []\n        for _ in range(optimizer.population_size):\n            x = optimizer.ask()\n            value = target_task(x[0], x[1])\n            solutions.append((x, value))\n            print(\n                f\"{optimizer.generation:3d}  {value:10.5f}\"\n                f\"  {x[0]:6.2f}  {x[1]:6.2f}\"\n            )\n        optimizer.tell(solutions)\n\n        if optimizer.should_stop():\n            break\n```\n\nThe full source code is available [here](./examples/ws_cma.py).\n\n\u003c/details\u003e\n\n\n#### Separable CMA-ES [Ros and Hansen 2008]\n\nSep-CMA-ES is an algorithm that limits the covariance matrix to a diagonal form.\nThis reduction in the number of parameters enhances scalability, making Sep-CMA-ES well-suited for high-dimensional optimization tasks.\nAdditionally, the learning rate for the covariance matrix is increased, leading to superior performance over the (full-covariance) CMA-ES on separable functions.\n\n\u003cdetails\u003e\n\u003csummary\u003eSource code\u003c/summary\u003e\n\n```python\nimport numpy as np\nfrom cmaes import SepCMA\n\ndef ellipsoid(x):\n    n = len(x)\n    if len(x) \u003c 2:\n        raise ValueError(\"dimension must be greater one\")\n    return sum([(1000 ** (i / (n - 1)) * x[i]) ** 2 for i in range(n)])\n\nif __name__ == \"__main__\":\n    dim = 40\n    optimizer = SepCMA(mean=3 * np.ones(dim), sigma=2.0)\n    print(\" evals    f(x)\")\n    print(\"======  ==========\")\n\n    evals = 0\n    while True:\n        solutions = []\n        for _ in range(optimizer.population_size):\n            x = optimizer.ask()\n            value = ellipsoid(x)\n            evals += 1\n            solutions.append((x, value))\n            if evals % 3000 == 0:\n                print(f\"{evals:5d}  {value:10.5f}\")\n        optimizer.tell(solutions)\n\n        if optimizer.should_stop():\n            break\n```\n\nFull source code is available [here](./examples/sep_cma.py).\n\n\u003c/details\u003e\n\n#### IPOP-CMA-ES [Auger and Hansen 2005]\n\nIPOP-CMA-ES is a method that involves restarting the CMA-ES with an incrementally increasing population size, as described below.\n\n\u003cdetails\u003e\n\u003csummary\u003eSource code\u003c/summary\u003e\n\n```python\nimport math\nimport numpy as np\nfrom cmaes import CMA\n\ndef ackley(x1, x2):\n    # https://www.sfu.ca/~ssurjano/ackley.html\n    return (\n        -20 * math.exp(-0.2 * math.sqrt(0.5 * (x1 ** 2 + x2 ** 2)))\n        - math.exp(0.5 * (math.cos(2 * math.pi * x1) + math.cos(2 * math.pi * x2)))\n        + math.e + 20\n    )\n\nif __name__ == \"__main__\":\n    bounds = np.array([[-32.768, 32.768], [-32.768, 32.768]])\n    lower_bounds, upper_bounds = bounds[:, 0], bounds[:, 1]\n\n    mean = lower_bounds + (np.random.rand(2) * (upper_bounds - lower_bounds))\n    sigma = 32.768 * 2 / 5  # 1/5 of the domain width\n    optimizer = CMA(mean=mean, sigma=sigma, bounds=bounds, seed=0)\n\n    for generation in range(200):\n        solutions = []\n        for _ in range(optimizer.population_size):\n            x = optimizer.ask()\n            value = ackley(x[0], x[1])\n            solutions.append((x, value))\n            print(f\"#{generation} {value} (x1={x[0]}, x2 = {x[1]})\")\n        optimizer.tell(solutions)\n\n        if optimizer.should_stop():\n            # popsize multiplied by 2 (or 3) before each restart.\n            popsize = optimizer.population_size * 2\n            mean = lower_bounds + (np.random.rand(2) * (upper_bounds - lower_bounds))\n            optimizer = CMA(mean=mean, sigma=sigma, population_size=popsize)\n            print(f\"Restart CMA-ES with popsize={popsize}\")\n```\n\nFull source code is available [here](./examples/ipop_cma.py).\n\n\u003c/details\u003e\n\n## Citation\nIf you use our library in your work, please cite our paper:\n\nMasahiro Nomura, Masashi Shibata.\u003cbr\u003e\n**cmaes : A Simple yet Practical Python Library for CMA-ES**\u003cbr\u003e\n[https://arxiv.org/abs/2402.01373](https://arxiv.org/abs/2402.01373)\n\nBibtex:\n```\n@article{nomura2024cmaes,\n  title={cmaes : A Simple yet Practical Python Library for CMA-ES},\n  author={Nomura, Masahiro and Shibata, Masashi},\n  journal={arXiv preprint arXiv:2402.01373},\n  year={2024}\n}\n```\n\n\n## Links\n\n**Projects using cmaes:**\n\n* [Optuna](https://github.com/optuna/optuna) : A hyperparameter optimization framework that supports CMA-ES using this library under the hood.\n* [Kubeflow/Katib](https://www.kubeflow.org/docs/components/katib/user-guides/katib-config/) : Kubernetes-based system for hyperparameter tuning and neural architecture search\n* (If you are using `cmaes` in your project and would like it to be listed here, please submit a GitHub issue.)\n\n**Other libraries:**\n\nWe have great respect for all libraries involved in CMA-ES.\n\n* [pycma](https://github.com/CMA-ES/pycma) : Most renowned CMA-ES implementation, created and maintained by Nikolaus Hansen.\n* [pymoo](https://github.com/msu-coinlab/pymoo) : A library for multi-objective optimization in Python.\n* [evojax](https://github.com/google/evojax) : evojax offers a JAX-port of this library.\n* [evosax](https://github.com/RobertTLange/evosax) : evosax provides a JAX-based implementation of CMA-ES and sep-CMA-ES, inspired by this library.\n\n**References:**\n\n* [Akiba et al. 2019] [T. Akiba, S. Sano, T. Yanase, T. Ohta, M. Koyama, Optuna: A Next-generation Hyperparameter Optimization Framework, KDD, 2019.](https://dl.acm.org/citation.cfm?id=3330701)\n* [Auger and Hansen 2005] [A. Auger, N. Hansen, A Restart CMA Evolution Strategy with Increasing Population Size, CEC, 2005.](http://www.cmap.polytechnique.fr/~nikolaus.hansen/cec2005ipopcmaes.pdf)\n* [Hamano et al. 2022] [R. Hamano, S. Saito, M. Nomura, S. Shirakawa, CMA-ES with Margin: Lower-Bounding Marginal Probability for Mixed-Integer Black-Box Optimization, GECCO, 2022.](https://arxiv.org/abs/2205.13482)\n* [Hamano et al. 2024a] [R. Hamano, S. Saito, M. Nomura, K. Uchida, S. Shirakawa, CatCMA : Stochastic Optimization for Mixed-Category Problems, GECCO, 2024.](https://arxiv.org/abs/2405.09962)\n* [Hamano et al. 2025] [R. Hamano, M. Nomura, S. Saito, K. Uchida, S. Shirakawa, CatCMA with Margin: Stochastic Optimization for Continuous, Integer, and Categorical Variables, GECCO, 2025.](https://arxiv.org/abs/2504.07884)\n* [Hamano et al. 2024b] [R. Hamano, S. Shirakawa, M. Nomura, Natural Gradient Interpretation of Rank-One Update in CMA-ES, PPSN, 2024.](https://arxiv.org/abs/2406.16506)\n* [Hansen 2016] [N. Hansen, The CMA Evolution Strategy: A Tutorial. arXiv:1604.00772, 2016.](https://arxiv.org/abs/1604.00772)\n* [Nomura et al. 2021] [M. Nomura, S. Watanabe, Y. Akimoto, Y. Ozaki, M. Onishi, Warm Starting CMA-ES for Hyperparameter Optimization, AAAI, 2021.](https://arxiv.org/abs/2012.06932)\n* [Nomura et al. 2023] [M. Nomura, Y. Akimoto, I. Ono, CMA-ES with Learning\nRate Adaptation: Can CMA-ES with Default Population Size Solve Multimodal\nand Noisy Problems?, GECCO, 2023.](https://arxiv.org/abs/2304.03473)\n* [Nomura and Shibata 2024] [M. Nomura, M. Shibata, cmaes : A Simple yet Practical Python Library for CMA-ES, arXiv:2402.01373, 2024.](https://arxiv.org/abs/2402.01373)\n* [Ros and Hansen 2008] [R. Ros, N. Hansen, A Simple Modification in CMA-ES Achieving Linear Time and Space Complexity, PPSN, 2008.](https://hal.inria.fr/inria-00287367/document)\n* [Uchida et al. 2024a] [K. Uchida, R. Hamano, M. Nomura, S. Saito, S. Shirakawa, CMA-ES for Safe Optimization, GECCO, 2024.](https://arxiv.org/abs/2405.10534)\n* [Uchida et al. 2024b] [K. Uchida, R. Hamano, M. Nomura, S. Saito, S. Shirakawa, CMA-ES for Discrete and Mixed-Variable Optimization on Sets of Points, PPSN, 2024.](https://arxiv.org/abs/2408.13046)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcyberagentailab%2Fcmaes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcyberagentailab%2Fcmaes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcyberagentailab%2Fcmaes/lists"}