{"id":21295684,"url":"https://github.com/tjkessler/pygenetics","last_synced_at":"2025-07-11T17:30:31.117Z","repository":{"id":62580562,"uuid":"135760706","full_name":"tjkessler/pygenetics","owner":"tjkessler","description":"Genetic algorithm framework for tuning arbitrary functions","archived":false,"fork":false,"pushed_at":"2023-08-02T21:20:21.000Z","size":3368,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-10-10T18:13:59.291Z","etag":null,"topics":["genetic-algorithm","hyperparameter-optimization","hyperparameter-search","hyperparameter-tuning","optimization-algorithms","python"],"latest_commit_sha":null,"homepage":"","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/tjkessler.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}},"created_at":"2018-06-01T20:31:01.000Z","updated_at":"2023-11-11T18:51:06.000Z","dependencies_parsed_at":"2022-11-03T20:49:27.597Z","dependency_job_id":null,"html_url":"https://github.com/tjkessler/pygenetics","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tjkessler%2Fpygenetics","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tjkessler%2Fpygenetics/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tjkessler%2Fpygenetics/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tjkessler%2Fpygenetics/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tjkessler","download_url":"https://codeload.github.com/tjkessler/pygenetics/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225280891,"owners_count":17449246,"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","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":["genetic-algorithm","hyperparameter-optimization","hyperparameter-search","hyperparameter-tuning","optimization-algorithms","python"],"created_at":"2024-11-21T14:06:46.778Z","updated_at":"2024-11-21T14:06:47.917Z","avatar_url":"https://github.com/tjkessler.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PyGenetics: Genetic Algorithm for Tuning Function Parameters\n\n[![GitHub version](https://badge.fury.io/gh/tjkessler%2FPyGenetics.svg)](https://badge.fury.io/gh/tjkessler%2FPyGenetics)\n[![PyPI version](https://badge.fury.io/py/pygenetics.svg)](https://badge.fury.io/py/pygenetics)\n[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/TJKessler/PyGenetics/master/LICENSE.txt)\n\nPyGenetics is an open source Python package used to tune parameters for user-supplied functions. Inspired by [genetic algorithms](https://www.researchgate.net/profile/Darrell_Whitley2/publication/2425017_A_Genetic_Algorithm_Tutorial/links/563214a108ae506cea68fd96/A-Genetic-Algorithm-Tutorial.pdf), PyGenetics is able to optimize variables in a multidimensional search space to minimize a \"cost\" (e.g. an error value returned by the user-supplied function).\n\n\u003cp align=\"center\"\u003e\n  \u003cimg align=\"center\" src=\"docs/img/demo.gif\" width=\"75%\" height=\"75%\"\u003e\n\u003c/p\u003e\n\n# Installation:\n\n### Method 1: pip\n```\npip install pygenetics\n```\n\nTo update your version of PyGenetics to the latest version, use:\n```\npip install --upgrade pygenetics\n```\n\n### Method 2: From source\nDownload the PyGenetics repository, navigate to the download location on the command line/terminal, and execute:\n```\npip install .\n```\n\nThere are currently no additional dependencies for PyGenetics.\n\n# Usage:\n\nTo start using PyGenetics, you need a couple items:\n- a cost function (objective function) to optimize\n- parameters used by the cost function\n\nFor example, let's define a cost function to minimize the sum of three integers:\n\n```python\ndef minimize_integers(integers):\n\n    return sum(integers)\n\n```\n\nYour cost function must accept a **list** from PyGenetics. The list values represent the current solution, i.e. parameter values, being evaluated by a population member\n\nNow that we have our cost function, let's import the Population object from PyGenetics, initialize the population, and add our parameters/genes:\n\n```python\nfrom pygenetics import Population\n\ndef minimize_integers(integers):\n\n    return sum(integers)\n\npop = Population(10, minimize_integers)\npop.add_param(0, 10)\npop.add_param(0, 10)\npop.add_param(0, 10)\n```\n\nHere we initialize the population with 10 population members, supply our cost function and add our parameters/genes. Parameters are added with minimum/maximum values for its search space. By default, parameter mutations (searching a neighboring solution) will not exceed the specified parameter bounds [min_val, max_val]; if this limitation is not desired, supply the \"restrict=False\" argument:\n\n```python\npop.add_param(0, 10, restrict=False)\n```\n\nOnce we have created our population and added our parameters/genes, we then need to \"initialize\" the population's members:\n\n```python\nfrom pygenetics import Population\n\ndef minimize_integers(integers):\n\n    return sum(integers)\n\npop = Population(10, minimize_integers)\npop.add_param(0, 10)\npop.add_param(0, 10)\npop.add_param(0, 10)\npop.initialize()\n```\n\nInitializing the population's members (in this example, 10 members) deploys them to random solutions/chromosomes (a random parameter/gene set is created), and their fitness is evaluated (in this example, lowest sum is better).\n\nWe then compute a pre-determined number of generations, each derived from the previous generation's members:\n\n```python\nfrom pygenetics import Population\n\ndef minimize_integers(integers):\n\n    return sum(integers)\n\npop = Population(10, minimize_integers)\npop.add_param(0, 10)\npop.add_param(0, 10)\npop.add_param(0, 10)\npop.initialize()\nfor _ in range(10):\n    pop.next_generation()\n```\n\nComputing the next generation consists of:\n\n- **1.** Select a chromosome (parameter/gene set) from the population based on fitness (a higher fitness score results in a higher chance of being chosen)\n\n- **2a.** Perform crossover with probability _p\u003csub\u003ec\u003c/sub\u003e_ (default of 0.5, 50%); if crossover is not performed, perform step (2b)\n\n    - Select a different chromosome per method in (1)\n    - Select a crossover point between 1 and L-1 (random index in chromosomes' genes) with uniform probability\n    - Recombine chromosomes to form two offspring\n    - Perform mutation on each gene with probability _p\u003csub\u003em\u003c/sub\u003e_ (default of 0.01, 1%)\n    - Place both offspring in the next generation\n    \n- **2b.** Crossover not performed, perform mutation on each gene of the chromosome with probability _p\u003csub\u003em\u003c/sub\u003e_ (default of 0.01, 1%), place chromosome in the next generation\n\n- **3.** If the next generation is not full (less than total population size), continue from step (1)\n\nBoth _p\u003csub\u003ec\u003c/sub\u003e_ and _p\u003csub\u003em\u003c/sub\u003e_ can be adjusted when the next generation is created:\n\n```python\npop.next_generation(p_crossover=0.75, p_mutation=0.05)\n```\n\nWe can access the populations's average fitness score, average objective function return value, best fitness score, best objective function return value and best parameters at any time:\n\n```python\nprint(pop.average_fitness)\nprint(pop.average_ret_val)\nprint(pop.best_fitness)\nprint(pop.best_ret_val)\nprint(pop.best_params)\n```\n\nPyGenetics can utilize multiple CPU cores for concurrent processing:\n\n```python\npop = Population(10, minimize_integers, num_processes=8)\n```\n\nTying everything together, we have:\n\n```python\nfrom pygenetics import Population\n\ndef minimize_integers(integers):\n\n    return sum(integers)\n\npop = Population(10, minimize_integers)\npop.add_param(0, 10)\npop.add_param(0, 10)\npop.add_param(0, 10)\npop.initialize()\nfor _ in range(10):\n    pop.next_generation()\n    print('Average fitness: {}'.format(pop.average_fitness))\n    print('Average obj. fn. return value: {}'.format(pop.average_ret_val))\n    print('Best fitness score: {}'.format(pop.best_fitness))\n    print('Best obj. fn. return value: {}'.format(pop.best_ret_val))\n    print('Best parameters: {}\\n'.format(pop.best_params))\n```\n\nRunning this script produces:\n\n```\nAverage fitness: 0.11519380797455661\nAverage obj. fn. return value: 9.545454545454545\nBest fitness score: 0.25\nBest obj. fn. return value: 3\nBest parameters: [1, 0, 2]\n\nAverage fitness: 0.16551587301587303\nAverage obj. fn. return value: 5.6\nBest fitness score: 0.25\nBest obj. fn. return value: 3\nBest parameters: [1, 0, 2]\n\nAverage fitness: 0.1694047619047619\nAverage obj. fn. return value: 5.5\nBest fitness score: 0.25\nBest obj. fn. return value: 3\nBest parameters: [1, 0, 2]\n\nAverage fitness: 0.18857142857142856\nAverage obj. fn. return value: 4.9\nBest fitness score: 0.25\nBest obj. fn. return value: 3\nBest parameters: [1, 2, 0]\n\nAverage fitness: 0.19935064935064933\nAverage obj. fn. return value: 5.0\nBest fitness score: 0.5\nBest obj. fn. return value: 1\nBest parameters: [1, 0, 0]\n\nAverage fitness: 0.2946969696969697\nAverage obj. fn. return value: 3.1818181818181817\nBest fitness score: 0.5\nBest obj. fn. return value: 1\nBest parameters: [1, 0, 0]\n\nAverage fitness: 0.29416666666666663\nAverage obj. fn. return value: 3.2\nBest fitness score: 0.5\nBest obj. fn. return value: 1\nBest parameters: [1, 0, 0]\n\nAverage fitness: 0.25844155844155847\nAverage obj. fn. return value: 3.5454545454545454\nBest fitness score: 0.5\nBest obj. fn. return value: 1\nBest parameters: [1, 0, 0]\n\nAverage fitness: 0.3538961038961039\nAverage obj. fn. return value: 2.727272727272727\nBest fitness score: 0.5\nBest obj. fn. return value: 1\nBest parameters: [1, 0, 0]\n\nAverage fitness: 0.4772727272727273\nAverage obj. fn. return value: 1.1818181818181819\nBest fitness score: 0.5\nBest obj. fn. return value: 1\nBest parameters: [1, 0, 0]\n```\n\nTo run this script yourself, head over to our [examples](https://github.com/tjkessler/PyGenetics/tree/master/examples) directory.\n\n# Contributing, Reporting Issues and Other Support:\n\nTo contribute to PyGenetics, make a pull request. Contributions should include tests for new features added, as well as extensive documentation.\n\nTo report problems with the software or feature requests, file an issue. When reporting problems, include information such as error messages, your OS/environment and Python version.\n\nFor additional support/questions, contact Travis Kessler (travis.j.kessler@gmail.com).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftjkessler%2Fpygenetics","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftjkessler%2Fpygenetics","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftjkessler%2Fpygenetics/lists"}