{"id":23888435,"url":"https://github.com/usmanmehmood55/genetic_algorithm","last_synced_at":"2025-06-30T20:05:27.817Z","repository":{"id":153232794,"uuid":"563951574","full_name":"usmanmehmood55/genetic_algorithm","owner":"usmanmehmood55","description":"Genetic Algorithms(GAs) are adaptive heuristic search algorithms based on the premise of natural selection and genetics. ","archived":false,"fork":false,"pushed_at":"2023-09-22T21:50:54.000Z","size":432,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-23T04:41:43.388Z","etag":null,"topics":["algorithm","c","genetic-algorithm","optimization-algorithms"],"latest_commit_sha":null,"homepage":"","language":"C","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/usmanmehmood55.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}},"created_at":"2022-11-09T17:17:40.000Z","updated_at":"2023-12-16T21:33:31.000Z","dependencies_parsed_at":"2025-01-04T20:04:12.145Z","dependency_job_id":null,"html_url":"https://github.com/usmanmehmood55/genetic_algorithm","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/usmanmehmood55/genetic_algorithm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usmanmehmood55%2Fgenetic_algorithm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usmanmehmood55%2Fgenetic_algorithm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usmanmehmood55%2Fgenetic_algorithm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usmanmehmood55%2Fgenetic_algorithm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/usmanmehmood55","download_url":"https://codeload.github.com/usmanmehmood55/genetic_algorithm/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usmanmehmood55%2Fgenetic_algorithm/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262842921,"owners_count":23373166,"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":["algorithm","c","genetic-algorithm","optimization-algorithms"],"created_at":"2025-01-04T09:00:24.832Z","updated_at":"2025-06-30T20:05:27.730Z","avatar_url":"https://github.com/usmanmehmood55.png","language":"C","readme":"# Genetic Algorithm\n\nThis project is an implementation of a genetic algorithm in C. The application was\ninitially based on this [article by Geeks for Geeks](https://www.geeksforgeeks.org/genetic-algorithms/),\nbut has now been developed and changed enough to be more than a mere port from\ntheir C++ implementation into C. The subsequent paragraph however is straight from\nthe above mentioned article.\n\n[![Build and Test](https://github.com/usmanmehmood55/genetic_algorithm/actions/workflows/build_and_test.yml/badge.svg)](https://github.com/usmanmehmood55/genetic_algorithm/actions/workflows/build_and_test.yml)\n[![codecov](https://codecov.io/gh/usmanmehmood55/genetic_algorithm/graph/badge.svg?token=OXCFJ9W6EN)](https://codecov.io/gh/usmanmehmood55/genetic_algorithm)\n\n- [Genetic Algorithm](#genetic-algorithm)\n  - [What is a Genetic Algorithm](#what-is-a-genetic-algorithm)\n  - [My Implementation](#my-implementation)\n    - [Genome Initializations](#genome-initializations)\n    - [Genome Mating](#genome-mating)\n    - [Fitness Calculation](#fitness-calculation)\n    - [Survival of the Fittest](#survival-of-the-fittest)\n    - [Generational Evolution and Convergence](#generational-evolution-and-convergence)\n  - [Notes](#notes)\n  - [Sample Output](#sample-output)\n  - [Setup](#setup)\n  - [Project Files](#project-files)\n\n## What is a Genetic Algorithm\n\nGenetic Algorithms(GAs) are adaptive heuristic search algorithms that belong to the\nlarger part of evolutionary algorithms. Genetic algorithms are based on the ideas\nof natural selection and genetics. These are intelligent exploitation of random\nsearch provided with historical data to direct the search into the region of better\nperformance in solution space. They are commonly used to generate high-quality\nsolutions for optimization problems and search problems.\n\nGenetic algorithms simulate the process of natural selection which means those\nspecies who can adapt to changes in their environment are able to survive and\nreproduce and go to next generation. In simple words, they simulate “survival of\nthe fittest” among individual of consecutive generation for solving a problem. Each\ngeneration consist of a population of individuals and each individual represents\na point in search space and possible solution. Each individual is represented as\na string of character/integer/float/bits. This string is analogous to the Chromosome.\n\n## My Implementation\n\nThis image explains my implementation of the algorithm. The code specific\ndocumentation is hosted on the [project's page](https://usmanmehmood55.github.io/genetic_algorithm/genetic__algorithm__utils_8h.html).\n\n![genetic algorithm flowchart](genetic_algorithm.png)\n\nA singular gene, is represented as a character.\n\n```c\ntypedef char gene_t;\n```\n\nA genome being a collection of genes, is represented as this structure. It\ncontains the pointer to an array of genes, the quantity of those genes being\nthe length of the genome, and a placeholder to store the fitness of that genome\nfor ease of access.\n\n```c\ntypedef struct genome_t\n{\n    gene_t   * genes;\n    uint16_t   length;\n    int        fitness;\n} genome_t;\n```\n\nThe application expects a string argument that it takes as its target, and the\nnumber of offspring to generate. The string must only contain the characters\npresent in the gene pool, which is is defined in\n[`genetic_algorithm_utils.h`](genetic_algorithm_utils/genetic_algorithm_utils.h).\n\n```c\n#define GENE_POOL \"!@#$^\u0026*()_-=+,.;:'/\\\\\\\"{}[]\u003c\u003e? 1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n```\n\n### Genome Initializations\n\nAfter initializing the target genome, two new parent genomes, and `n` number of\noffspring genomes are initialized. Their genes are selected randomly from the gene\npool. This is done in the `genome_init()` function.\n\n```c\ngenome_t parents[2];\nparents[0] = genome_init(target.length);\nparents[1] = genome_init(target.length);\n\ngenome_t offsprings[offspring_count];\nfor (uint16_t i = 0U; i \u003c offspring_count; i++)\n{\n    offsprings[i] = genome_init(target.length);\n}\n```\n\n### Genome Mating\n\nThe algorithm starts by mating the two parent genomes to create all the offspring\ngenomes.\n\n```c\nfor (uint16_t i = 0U; i \u003c offspring_count; i++)\n{\n    genomes_mate(\u0026target, \u0026parents[0], \u0026parents[1], \u0026offsprings[i]);\n}\n```\n\nMating involves two steps.\n\n1. Joining the parents over a random crossover point\n2. Performing a slight mutation\n\nTake these two parents, of size 7:\n\n```\n+-----------+---+---+---+---+---+---+---+\n| index     | 0 | 1 | 2 | 3 | 4 | 5 | 6 |\n|-----------|---|---|---|---|---|---|---|\n| parent 1  | a | b | c | d | e | f | g |\n| parent 2  | h | i | j | k | l | m | n |\n+-----------+---+---+---+---+---+---+---+\n```\n\nIf the random crossover point is 3, the resulting offspring will look like this\n\n```\n+-----------+---+---+---+---+---+---+---+\n| index     | 0 | 1 | 2 | 3 | 4 | 5 | 6 |\n|-----------|---|---|---|---|---|---|---|\n| parent 1  | a | b | c | d |   |   |   |\n| parent 2  |   |   |   |   | l | m | n |\n|-----------|---|---|---|---|---|---|---|\n| offspring | a | b | c | d | l | m | n |\n+-----------+---+---+---+---+---+---+---+\n```\n\nHowever to prevent parent 1 from always contributing to the first `n` genes and\nparent 2 to the remaining `n-length`, their sequence is randomly (should be 50/50)\nselected so with the same crossover point at 3, this can also happen\n\n```\n+-----------+---+---+---+---+---+---+---+\n| index     | 0 | 1 | 2 | 3 | 4 | 5 | 6 |\n|-----------|---|---|---|---|---|---|---|\n| parent 1  |   |   |   |   | e | f | g |\n| parent 2  | h | i | j | k |   |   |   |\n|-----------|---|---|---|---|---|---|---|\n| offspring | h | i | j | k | e | f | g |\n+-----------+---+---+---+---+---+---+---+\n```\n\nAfter joining, a mutation can (at a 50/50 chance) be performed at a random index\non the offspring. This is done to prevent the evolution from being stuck in a local\nmaxima.\n\n```\n+-----------+---+---+---+---+---+---+---+\n| index     | 0 | 1 | 2 | 3 | 4 | 5 | 6 |\n|-----------|---|---|---|---|---|---|---|\n| offspring | a | b | c | d | l | m | n |\n| mutation  |   | X |   |   |   |   |   |\n|-----------|---|---|---|---|---|---|---|\n| mutated   | a | X | c | d | l | m | n |\n+-----------+---+---+---+---+---+---+---+\n```\n\n### Fitness Calculation\n\nThe fitness of a genome is being calculated based on these parameters.\n\n1. ~~How many genes in this are also present in the target, regardless of the order.~~\n2. ~~How many genes in this are NOT present in the target.~~\n3. How many genes match the target exactly in order.\n\nNaturally, a heavy bias is given to genes that match with the target in order.\n\nIdeally a genome that EXACTLY matches the target should have a fitness score of 0\nand the less it matches, the more negative its fitness should become.\n\nCurrently the fitness calculation is anything but optimized, but I want to keep it\nthat way for ease of understanding and debugging. It is done inside the `genome_mate()`\nfunction when an offspring is created.\n\n```c\np_offspring-\u003efitness = genome_calculate_fitness(p_target-\u003egenes, p_offspring-\u003egenes, length);\n```\n\n### Survival of the Fittest\n\nAfter creating an `n` number of offspring, they are sorted by ascending fitness.\nThis is done using the `genomes_sort_by_fitness()` function which performs a bubble\nsort.\n\nThe two fittest offspring are then declared as the new parents, by copying them to\nthe parent genomes using the `genome_copy()` function which performs a deep copy\nto preserve the references of the original parents.\n\n```c\ngenome_copy(\u0026parents[0], \u0026offsprings[0]);\ngenome_copy(\u0026parents[1], \u0026offsprings[1]);\n```\n\n### Generational Evolution and Convergence\n\nAs the algorithm iterates, the genomes closer to the target keep getting selected\nto be parents and the resulting offspring keep getting closer to the target with\nslight mutations every time to help them converge.\n\nConvergence is achieved when the healthiest parent has a fitness score of 0, i.e.,\nit matches the target exactly. There is also an upper bound to number of iterations\nin case the algorithm never converges.\n\n```c\nif ((parents[0].fitness == 0) || (iterations == UINT64_MAX))\n{\n    (void)printf(\"\\rConvergence Achieved!\\n\");\n    break;\n}\n```\n\n## Notes\n\nSome observations that can be made about this algorithm:\n\n- Bigger the target, the more iterations it takes to converge\n- If a target is too big, it fails to converge (within reasonable limits)\n- Larger the offspring count, the less iterations it takes to converge\n- Larger the offspring count, the longer a single iteration lasts\n- If the offspring count is too small, it fails to converge\n\nIt is also noticeable that in some cases having a smaller offspring count leads to\nconvergence quicker due to more iterations, than having a large offspring count\nleading to less in number, but more time consuming iterations.\n\n## Sample Output\n\n```bash\ngenetic_algorithm\u003e ./build/genetic_algorithm.exe \"Hi, my name is Usman. :)\" 1000\n\n(-23) : \"BkGd0 +gh4,KSpX2lTuJfIO\"\n(-21) : \"BkGd0 +gh4,KS UKf_j?nEH\"\n(-20) : \"BkGd0 +gh4,KS Usf_j?nEH\"\n(-19) : \"B,Gd0 +gh4,KS Usf_j?nEH\"\n(-17) : \"B, d0 +gh4,KS Usm_j?nEH\"\n(-16) : \"B, d0 +gh4 KS Usm_j?nEH\"\n(-16) : \"B, d0 +gh4 KS Usm_j?nEH\"\n(-15) : \"B, m0 +gh4 KS Usm_j?nEH\"\n(-14) : \"B, m0 +gh4 KS Usmaj?nEH\"\n(-13) : \"B, m0 +gh4 KS Usmaj.nEH\"\n(-12) : \"B, m0 +ah4 KY Usmaj.nEH\"\n(-11) : \"B, m0 +ah4 Ks Usmaj.nEH\"\n(-10) : \"B, m0 nah4 Ks Usmaj.nEH\"\n( -9) : \"HB, m0 nah4 Ks Usmaj.nEH\"\n( -8) : \"HB, m0 nahe Ks Usmaj.nEH\"\n( -7) : \"HB, m4 nahe is Usmaj.nEH\"\n( -7) : \"HB, m0 nahe is Usmaj.nBH\"\n( -6) : \"Hi, m0 nahe is Usma'.nEH\"\n( -5) : \"Hi, my nahe is Usma'.nEH\"\n( -4) : \"Hi, my nahe is Usma'.n:H\"\n( -3) : \"Hi, my nahe is Usma'. :H\"\n( -2) : \"Hi, my nahe is Usman. :H\"\n( -1) : \"Hi, my name is Usman. :H\"\n( -1) : \"Hi, my name is Usman. :H\"\n( -1) : \"Hi, my name is Usman. :H\"\n(  0) : \"Hi, my name is Usman. :)\"\n\nConvergence Achieved!\nIterations:      25\nTime taken:      56 milliseconds\nIteration time:  2.240000 msec per iter\n```\n\n## Setup\n\nFollowing tools are required to compile\n\n- [CMake](https://cmake.org/)\n- [Ninja](https://ninja-build.org/)\n- [GCC](https://gcc.gnu.org/)\n\nIn the repository directory, use CMake and Ninja to build\n\n```bash\ncmake -GNinja -Bbuild\nninja -C build\n```\n\nTo make a `Debug` build without optimizations,\n\n```bash\ncmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Debug\nninja -C build\n```\n\nTo make a `Test` build with unit tests and coverage data, first\ninitialize the [c_asserts](https://github.com/usmanmehmood55/c_asserts/) submodule.\n\n```bash\ngit submodule update --init --recursive\n```\n\nAnd then perform the build\n\n```bash\ncmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Test\nninja -C build\n```\n\nTo run the application\n\n```bash\n./build/genetic_algorithm.exe \"Your test string\" 1000\n```\n\n## Project Files\n\nThe source files (excluding supporting files) are organized like this:\n\n- [`app_init`](app_init) contains the parser for CLI args passed to the application.\n- [`c_asserts`](c_asserts) is a submodule that provides a basic testing framework\n- [`genetic_algorithm_utils`](genetic_algorithm_utils) contains all the functions\n  used for operations in the algorithm\n- [`test`](test) contains a test application which covers genetic_algorithm_utils\n- [`main.c`](main.c) contains the actual algorithm\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fusmanmehmood55%2Fgenetic_algorithm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fusmanmehmood55%2Fgenetic_algorithm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fusmanmehmood55%2Fgenetic_algorithm/lists"}