# Introduction to Evolutionary Algorithms

**Genetic algorithms are a very interesting approach to solving problems that cannot be easily solved in polynomial time, such as classically NP-Hard problems, and anything else that would take far too long to exhaustively process.** When used on their own, they are typically applied to combinatorial problems; however, genetic algorithms are often used in tandem with other methods, acting as a quick way to find a somewhat optimal starting place for another algorithm to work off of.

The premise of a genetic algorithm (to be further known as a **GA**) is quite simple given that you are familiar with the process of natural selection. A GA contains four overall steps: **initialization, selection, genetic operators, and termination**. These steps each correspond, roughly, to a particular facet of natural selection, and provide easy ways to modularize implementations of this algorithm-type. **Simply put, in a GA, fitter members will survive and proliferate, while unfit members will die off and not contribute to the gene pool of further generations, much like in natural selection.**

#### Background

**In the scope of this article, we will generally define the problem as such: we wish to find the best combination of elements that maximizes some fitness function, and we will accept a final solution once we have either ran the algorithm for some maximum number of iterations, or we have reached some fitness threshold.** This scenario is clearly not the only way to use a GA, but it does encompass many common applications. These terms may not be entirely clear at the moment, but this overall scenario will prove useful when diving into individual components.

#### Initialization

In order to begin our algorithm, we must first create an initial **population** of solutions. The population will contain an arbitrary number of possible solutions to the problem, oftentimes called **members**. It will often be created randomly (**within the constraints** of the problem) or, if some prior knowledge of the task is known, roughly centered around what is believed to be ideal. It is important that the population encompasses a wide range of solutions, because it essentially represents a gene pool; ergo, if we wish to explore many different possibilities over the course of the algorithm, **we should aim to have many different genes present.**

**Selection**

Once a population is created, members of the population must now be **evaluated according to a fitness function**. A fitness function is a function that takes in the characteristics of a member, and outputs a numerical representation of how viable of a solution it is. Creating the fitness function can often be very difficult, and it is important to find a good function that accurately represents the data; **it is very problem-specific**. Now, we calculate the fitness of all members, and select a portion of the top-scoring members.

#### Genetic Operators

This step really includes two sub-steps: **crossover and mutation**. After selecting the top members (typically top 2, but this number can vary), these members are now used to create the next generation in the algorithm. Using the characteristics of the selected parents, new children are created that are a mixture of the parents’ qualities. Doing this can often be difficult depending on the type of data, but typically in combinatorial problems, it is possible to mix combinations and output valid combinations from these inputs. Now, we must introduce **new genetic material** into the generation. **If we do not do this crucial step, we will become stuck in local extrema very quickly, and will not obtain optimal results**. This step is mutation, and we do this, quite simply, by changing a small portion of the children such that they no longer perfectly mirror subsets of the parents’ genes. Mutation typically occurs probabilistically, in that the chance of a child receiving a mutation as well as the severity of the mutation are governed by a probability distribution.

#### Termination

**Eventually, the algorithm must end**. There are two cases in which this usually occurs: either the algorithm has reached some **maximum runtime**, or the algorithm has reached some **threshold of performance**.

#### General flow

This flow chart describes the flow of the overall algorithm.

#### Things to Note

**Genetic algorithms excel in their speed.** They are a very fast way to arrive at a solution that may not be the overall best solution, but a very good solution nonetheless. **Therefore, it is important to know when to use them**.

**Additionally, genetic algorithms will suffer under large population sizes or overly-complex fitness functions.** Therefore, if you encounter problems, it may be useful to sample member of the population instead of evaluating all members. There are many similar optimizations that can be done as well.