> For the complete documentation index, see [llms.txt](https://finch-1.gitbook.io/version0.0.1/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://finch-1.gitbook.io/version0.0.1/examples/game-of-life.md).

# Game of Life

### Overview

Conway's Game of Life is a cellular automaton where cells in a grid evolve over discrete time steps based on a set of rules. This example uses genetic algorithms to find initial grid configurations that result in a high number of live cells in the subsequent generation.

### Code Breakdown

Let's break down the code into chunks and explain each part:

#### 1. Imports and Setup

```python
import numpy as np
from Finch.generic import Environment, Individual
from Finch.layers.universal_layers import Populate, SortByFitness, CapPopulation
from Finch.selectors import RandomSelection, RankBasedSelection
from Finch.layers.array_layers import ArrayPool, ParentNPoint, SwapMutation
import matplotlib.pyplot as plt

# Define the grid size
GRID_SIZE = 50
```

This section imports necessary modules from Finch 3.5 and other libraries. We define the grid size for our Game of Life simulation.

#### 2. Game of Life Rules

```python
def apply_rules(grid):
    new_grid = grid.copy()
    for i in range(GRID_SIZE):
        for j in range(GRID_SIZE):
            total = int((grid[i, (j-1)%GRID_SIZE] + grid[i, (j+1)%GRID_SIZE] +
                         grid[(i-1)%GRID_SIZE, j] + grid[(i+1)%GRID_SIZE, j] +
                         grid[(i-1)%GRID_SIZE, (j-1)%GRID_SIZE] + grid[(i-1)%GRID_SIZE, (j+1)%GRID_SIZE] +
                         grid[(i+1)%GRID_SIZE, (j-1)%GRID_SIZE] + grid[(i+1)%GRID_SIZE, (j+1)%GRID_SIZE]))
            if grid[i, j] == 1:
                if (total < 2) or (total > 3):
                    new_grid[i, j] = 0
            else:
                if total == 3:
                    new_grid[i, j] = 1
    return new_grid
```

This function implements the rules of Conway's Game of Life. It takes a grid as input and returns the next generation of the grid based on the classic rules.

#### 3. Fitness Function

```python
def fitness_function(individual):
    grid = individual.item.reshape((GRID_SIZE, GRID_SIZE))
    next_gen = apply_rules(grid)
    return np.sum(next_gen)  # Return the number of live cells in the next generation
```

The fitness function evaluates how "good" a particular grid configuration is. In this case, we're measuring fitness by the number of live cells in the next generation.

#### 4. Gene Pool Setup

```python
pool = ArrayPool(gene_array=np.array([0, 1]), fitness_function=fitness_function, length=GRID_SIZE**2)
```

We create an `ArrayPool` that will generate individuals with binary genes (0 or 1) representing dead or alive cells. The length is set to `GRID_SIZE**2` to represent the entire grid as a flattened array.

#### 5. Defining Evolutionary Layers

```python
layers = [
    Populate(population=100, gene_pool=pool),
    SwapMutation(selection_function=RandomSelection(amount_to_select=10).select),
    ParentNPoint(selection_function=RankBasedSelection(amount_to_select=2, factor=1).select, families=8, children=2, n_points=3),
    SortByFitness(),
    CapPopulation(max_population=100)
]
```

This section defines the layers of our genetic algorithm:

1. `Populate`: Creates an initial population of 100 individuals.
2. `SwapMutation`: Introduces variations by swapping cell states.
3. `ParentNPoint`: Performs crossover between parents to create new children.
4. `SortByFitness`: Sorts the population based on fitness.
5. `CapPopulation`: Maintains a constant population size.

#### 6. Setting Up the Environment

```python
env = Environment(layers=layers, verbose_every=10)
env.compile()
```

We create an `Environment` with our defined layers and compile it.

#### 7. Evolution

```python
env.evolve(generations=5000)
```

This line starts the evolution process, running for 5000 generations.

#### 8. Visualizing the Result

```python
best = env.best_ever
best_grid = best.item.reshape((GRID_SIZE, GRID_SIZE))

plt.imshow(apply_rules(best_grid), cmap='binary')
plt.title("Best Game of Life Grid")
plt.show()
```

After evolution, we retrieve the best individual, reshape it into a grid, and visualize the next generation of this best grid using matplotlib.

### Running the Example

To run this example:

1. Ensure you have Finch 3.5 and its dependencies installed.
2. Copy the provided code into a Python file (e.g., `game_of_life_evolution.py`).
3. Execute the script: `python game_of_life_evolution.py`

The script will evolve grid configurations and display the best result at the end.

### Customization

You can experiment with different parameters:

* Adjust the `GRID_SIZE` for larger or smaller grids.
* Modify the number of generations or population size.
* Try different genetic operators or selection strategies.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://finch-1.gitbook.io/version0.0.1/examples/game-of-life.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
