{"id":20284187,"url":"https://github.com/clebert/otus","last_synced_at":"2025-06-22T07:05:45.146Z","repository":{"id":56010517,"uuid":"267353103","full_name":"clebert/otus","owner":"clebert","description":"A modular JavaScript API for programming with genetic algorithms.","archived":false,"fork":false,"pushed_at":"2023-03-26T22:49:43.000Z","size":1383,"stargazers_count":3,"open_issues_count":3,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-06-21T04:43:39.900Z","etag":null,"topics":["genetic-algorithm","genetic-programming"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/clebert.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-05-27T15:13:42.000Z","updated_at":"2024-09-24T07:30:53.000Z","dependencies_parsed_at":"2025-04-11T08:52:34.072Z","dependency_job_id":"59ab594c-3bb8-4b8a-ac45-449956b77d91","html_url":"https://github.com/clebert/otus","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/clebert/otus","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clebert%2Fotus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clebert%2Fotus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clebert%2Fotus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clebert%2Fotus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/clebert","download_url":"https://codeload.github.com/clebert/otus/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clebert%2Fotus/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261250276,"owners_count":23130541,"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","genetic-programming"],"created_at":"2024-11-14T14:18:40.305Z","updated_at":"2025-06-22T07:05:40.129Z","avatar_url":"https://github.com/clebert.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Otus\n\n\u003e A modular JavaScript API for programming with\n\u003e [genetic algorithms](https://en.wikipedia.org/wiki/Genetic_algorithm).\n\n## Installation\n\n```\nnpm install otus\n```\n\n## Features\n\n- Support for three modular exchangeable\n  [genetic operators](https://en.wikipedia.org/wiki/Genetic_operator)\n  (selection, crossover, mutation)\n- A ready-to-use implementation of each of the supported genetic operators:\n  - [Fitness proportionate selection](https://en.wikipedia.org/wiki/Fitness_proportionate_selection)\n    (via [stochastic acceptance](https://arxiv.org/abs/1109.3627))\n  - [Uniform crossover](\u003chttps://en.wikipedia.org/wiki/Crossover_(genetic_algorithm)#Uniform_crossover\u003e)\n  - [Uniform mutation](\u003chttps://en.wikipedia.org/wiki/Mutation_(genetic_algorithm)\u003e)\n- [Genetic representation](https://en.wikipedia.org/wiki/Genetic_representation)\n  using plain JavaScript objects\n- Support for [elitism](https://en.wikipedia.org/wiki/Genetic_algorithm#Elitism)\n- Support for adaptive parameters\n  ([adaptive genetic algorithms](https://en.wikipedia.org/wiki/Genetic_algorithm#Adaptive_GAs))\n- Immutable/functional API\n- Built-in support for TypeScript\n- No dependencies\n\n## Terminology\n\n### [Genotype](https://en.wikipedia.org/wiki/Genotype)\n\nThe genotype defines all genes and their possible values using alleles. It is so\nto speak the blueprint for the construction of phenotypes.\n\n\u003cdetails\u003e\n  \u003csummary\u003eType definition\u003c/summary\u003e\n\n```ts\ninterface Genotype {\n  readonly [geneName: string]: Allele\u003cany\u003e;\n}\n```\n\n\u003c/details\u003e\n\n### [Allele](https://en.wikipedia.org/wiki/Allele)\n\nThe possible values of a particular gene are called alleles. An allele is a\nfunction with which the initial value of a gene is generated as well as all\nfurther values of a gene in the course of mutations.\n\n\u003cdetails\u003e\n  \u003csummary\u003eType definition\u003c/summary\u003e\n\n```ts\ntype Allele\u003cTValue\u003e = () =\u003e TValue;\n```\n\n\u003c/details\u003e\n\n### [Phenotype](https://en.wikipedia.org/wiki/Phenotype)\n\nThe phenotype represents a\n[candidate solution](https://en.wikipedia.org/wiki/Feasible_region#Candidate_solution)\nand contains all genes defined by the genotype with concrete values.\n\n\u003cdetails\u003e\n  \u003csummary\u003eType definition\u003c/summary\u003e\n\n```ts\ntype Phenotype\u003cTGenotype extends Genotype\u003e = {\n  readonly [TGeneName in keyof TGenotype]: Gene\u003cTGenotype, TGeneName\u003e;\n};\n```\n\n\u003c/details\u003e\n\n### [Gene](https://en.wikipedia.org/wiki/Gene)\n\nA gene represents a concrete property of a solution which can be mutated and\naltered.\n\n\u003cdetails\u003e\n  \u003csummary\u003eType definition\u003c/summary\u003e\n\n```ts\ntype Gene\u003c\n  TGenotype extends Genotype,\n  TGeneName extends keyof TGenotype,\n\u003e = ReturnType\u003cTGenotype[TGeneName]\u003e;\n```\n\n\u003c/details\u003e\n\n### [Selection operator](\u003chttps://en.wikipedia.org/wiki/Selection_(genetic_algorithm)\u003e)\n\nThe selection operator is used to select individual solutions from a population\nfor later breeding (using the crossover operator). The selection is usually\nbased on the fitness of each individual, which is determined by a fitness\nfunction.\n\n\u003cdetails\u003e\n  \u003csummary\u003eType definition\u003c/summary\u003e\n\n```ts\ntype SelectionOperator\u003cTGenotype extends Genotype\u003e = (\n  phenotypes: readonly Phenotype\u003cTGenotype\u003e[],\n  fitnessFunction: FitnessFunction\u003cTGenotype\u003e,\n) =\u003e Phenotype\u003cTGenotype\u003e;\n```\n\n\u003c/details\u003e\n\n### [Fitness function](https://en.wikipedia.org/wiki/Fitness_function)\n\nA fitness function is a particular type of\n[objective function](https://en.wikipedia.org/wiki/Loss_function) that is used\nto summarise, as a single figure of merit, how close a given solution is to\nachieving the set aims.\n\n\u003cdetails\u003e\n  \u003csummary\u003eType definition\u003c/summary\u003e\n\n```ts\ntype FitnessFunction\u003cTGenotype extends Genotype\u003e = (\n  phenotype: Phenotype\u003cTGenotype\u003e,\n) =\u003e number;\n```\n\n\u003c/details\u003e\n\n### [Crossover operator](\u003chttps://en.wikipedia.org/wiki/Crossover_(genetic_algorithm)\u003e)\n\nThe crossover operator is used in the process of taking two parent solutions and\nproducing a child solution from them. By recombining portions of good solutions,\nthe genetic algorithm is more likely to create a better solution.\n\n\u003cdetails\u003e\n  \u003csummary\u003eType definition\u003c/summary\u003e\n\n```ts\ntype CrossoverOperator\u003cTGenotype extends Genotype\u003e = (\n  phenotypeA: Phenotype\u003cTGenotype\u003e,\n  phenotypeB: Phenotype\u003cTGenotype\u003e,\n) =\u003e Phenotype\u003cTGenotype\u003e;\n```\n\n\u003c/details\u003e\n\n### [Mutation operator](\u003chttps://en.wikipedia.org/wiki/Mutation_(genetic_algorithm)\u003e)\n\nThe mutation operator encourages genetic diversity amongst solutions and\nattempts to prevent the genetic algorithm converging to a local minimum by\nstopping the solutions becoming too close to one another.\n\n\u003cdetails\u003e\n  \u003csummary\u003eType definition\u003c/summary\u003e\n\n```ts\ntype MutationOperator\u003cTGenotype extends Genotype\u003e = (\n  phenotype: Phenotype\u003cTGenotype\u003e,\n  genotype: TGenotype,\n) =\u003e Phenotype\u003cTGenotype\u003e;\n```\n\n\u003c/details\u003e\n\n## Usage example\n\n```js\nimport {\n  cacheFitnessFunction,\n  createFitnessProportionateSelectionOperator,\n  createFloatAllele,\n  createIntegerAllele,\n  createUniformCrossoverOperator,\n  createUniformMutationOperator,\n  geneticAlgorithm,\n  getFittestPhenotype,\n} from 'otus';\n```\n\n```js\nconst smallNumberGenotype = {\n  base: createFloatAllele(1, 10), // float between 1.0 (inclusive) and 10.0 (exclusive)\n  exponent: createIntegerAllele(2, 4), // integer between 2 (inclusive) and 4 (inclusive)\n};\n```\n\n```js\nfunction isAnswerToEverything(smallNumberPhenotype) {\n  const number = Math.pow(\n    smallNumberPhenotype.base,\n    smallNumberPhenotype.exponent,\n  );\n\n  return number === 42 ? Number.MAX_SAFE_INTEGER : 1 / Math.abs(42 - number);\n}\n```\n\n```js\nconst state = {\n  genotype: smallNumberGenotype,\n  phenotypes: [],\n  populationSize: 100,\n  elitePopulationSize: 2,\n  fitnessFunction: cacheFitnessFunction(isAnswerToEverything),\n  selectionOperator: createFitnessProportionateSelectionOperator(),\n  crossoverOperator: createUniformCrossoverOperator(0.5),\n  mutationOperator: createUniformMutationOperator(0.1),\n};\n```\n\n```js\nfor (let i = 0; i \u003c 100; i += 1) {\n  state = geneticAlgorithm(state);\n}\n```\n\n```js\nconst answerToEverythingPhenotype = getFittestPhenotype(state);\n```\n\n```js\nconsole.log(\n  `The answer to everything:`,\n  Math.pow(\n    answerToEverythingPhenotype.base,\n    answerToEverythingPhenotype.exponent,\n  ),\n  answerToEverythingPhenotype,\n);\n```\n\n```\nThe answer to everything: 42.00057578051458 { base: 3.4760425291663264, exponent: 3 }\n```\n\n## API reference\n\n### Genetic algorithm function\n\n```ts\nfunction geneticAlgorithm\u003cTGenotype extends Genotype\u003e(\n  state: GeneticAlgorithmState\u003cTGenotype\u003e,\n): GeneticAlgorithmState\u003cTGenotype\u003e;\n```\n\n```ts\ninterface GeneticAlgorithmState\u003cTGenotype extends Genotype\u003e {\n  readonly genotype: TGenotype;\n  readonly phenotypes: readonly Phenotype\u003cTGenotype\u003e[];\n  readonly populationSize: number;\n  readonly elitePopulationSize?: number;\n  readonly fitnessFunction: FitnessFunction\u003cTGenotype\u003e;\n  readonly selectionOperator: SelectionOperator\u003cTGenotype\u003e;\n  readonly crossoverOperator: CrossoverOperator\u003cTGenotype\u003e;\n  readonly mutationOperator: MutationOperator\u003cTGenotype\u003e;\n}\n```\n\n### Genetic operator factory functions\n\n```ts\nfunction createFitnessProportionateSelectionOperator\u003c\n  TGenotype extends Genotype,\n\u003e(randomFunction?: () =\u003e number): SelectionOperator\u003cTGenotype\u003e;\n```\n\n```ts\nfunction createUniformCrossoverOperator\u003cTGenotype extends Genotype\u003e(\n  probability: number,\n  randomFunction?: () =\u003e number,\n): CrossoverOperator\u003cTGenotype\u003e;\n```\n\n```ts\nfunction createUniformMutationOperator\u003cTGenotype extends Genotype\u003e(\n  probability: number,\n  randomFunction?: () =\u003e number,\n): MutationOperator\u003cTGenotype\u003e;\n```\n\n### Allele factory functions\n\n```ts\nfunction createFloatAllele(\n  min: number,\n  max: number,\n  randomFunction?: () =\u003e number,\n): Allele\u003cnumber\u003e;\n```\n\n\u003e The created allele returns a random float between min (inclusive) and max\n\u003e (exclusive).\n\n```ts\nfunction createIntegerAllele(\n  min: number,\n  max: number,\n  randomFunction?: () =\u003e number,\n): Allele\u003cnumber\u003e;\n```\n\n\u003e The created allele returns a random integer between min (inclusive) and max\n\u003e (inclusive).\n\n### Utility functions\n\n```ts\nfunction getFittestPhenotype\u003cTGenotype extends Genotype\u003e(\n  state: GeneticAlgorithmState\u003cTGenotype\u003e,\n): Phenotype\u003cTGenotype\u003e | undefined;\n```\n\n```ts\nfunction cacheFitnessFunction\u003cTGenotype extends Genotype\u003e(\n  fitnessFunction: FitnessFunction\u003cTGenotype\u003e,\n): FitnessFunction\u003cTGenotype\u003e;\n```\n\n```ts\nfunction createRandomPhenotype\u003cTGenotype extends Genotype\u003e(\n  genotype: TGenotype,\n): Phenotype\u003cTGenotype\u003e;\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclebert%2Fotus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fclebert%2Fotus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclebert%2Fotus/lists"}