## Acknowledgements
I extend my heartfelt gratitude to Professor Dr. Denver Lewellen for his guidance and support throughout the duration of this thesis report. His expertise and mentorship have been instrumental in shaping the direction of this research. I would also like to acknowledge the Brooklyn College Anthropology Department for providing the platform and resources necessary for the development of this report.
## Abstract
This report explores the application of genetic algorithms in representing behavioral patterns within cultural anthropology. The study involves the development of interactive visualizations aimed at solving the Knapsack Problem through various genetic algorithm adaptations, including simulations of diverse societal mating structures and mate selection strategies. Furthermore, the research encompasses the creation of interactive simulations to elucidate how behavioral strategies, such as Aggressive and Non-aggressive approaches, impact reproductive fitness through the lens of Game Theory. These simulations visualize the distribution of "simulated alleles" across successive generations, shedding light on the evolutionary dynamics of behavioral traits within populations.
## Introduction
### Intention
The purpose of this simulation is to explore the applications of genetic algorithms in the context of biological anthropology. Specifically, we aim to identify solutions and conditions that can be used to establish relationships that provide insights into possible explanations of anthropological behaviors.
### Background information on genetic algorithms
Tracing back to the earliest computer scientists like Turing and von Neumann, who envisioned imbuing computer programs with intelligence, replication, and adaptive learning akin to natural systems[^gen_ch1], the exploration of evolutionary systems for optimization began in the 1950s and 1960s, inspired by natural genetic variation and selection[^gen_ch1]. One of the earliest strategies to solve computer problems can be traced to John Holland in 1975, who aimed to study adaptation in nature and import natural adaptation mechanisms into computer systems[^gen_ch1]. Holland's genetic algorithm involves natural selection, crossover, mutation, and inversion operations on a population of chromosomes, which can be represented as sequences of 1s and 0s[^gen_ch1]. Today, Holland's work forms the backbone of genetic algorithms, which are used to inspire solutions for optimization problems, machine learning, and neural networks[^gen_ch1].
[^gen_ch1]: [An Introduction to Genetic Algorithms](https://mitpress.mit.edu/books/introduction-genetic-algorithms) by Melanie Mitchell, Chapter 1: Introduction, pp. 1-10.
## Methods: Simulating Evolutionary Behavior Dynamics
To begin, the report will present an example solution for the Knapsack method, using an introductory exercise to illustrate the methodology of the genetic evolution framework employed. Following this, we will proceed with a behavioral analysis of individuals who choose to either cooperate or act non-cooperatively, examining the impact of these behaviors on their fitness across generations. This analysis serves as an analogy to survival strategies of individuals in a civilization from a behavioral anthropological perspective, highlighting interactions in various settings and their resultant effects on population dynamics.
## Biological and Computing Terminology
*General Interpretation of methods. To understand the termonologies we have to first examine how the methods work.*
### Workflow Selection Cycle (of a single generation).
After creation an initial population of chromosomes. We run the selection and populations updates (outlined in red) process until we complete the cycles of generatiosn to be runned.

### Parameters
| Term | Definition |
|--|--|
| Selection method | Selection method used to select the pairs. Usually each pair of parents produce a pair of children. |
| Mutation Strategy | Strategy used to mutate.
| Mutation Rate| Rate in which to apply mutation strategy per mutation term (depends on mutation strategy, usually the indenpendent chromosome)|
| Crossover Strategy| Strategy used to apply Crossover. |
| Crossover Rate| Rate in which to apply crossover method per crossover term (depends on mutation strategy, issually the indenpendent chromosome)|
### Definitions
Here a quick illustration with the labeled terms:


|Term | Definition |
|--|--|
|Individual | The solution (the combination of items) are defined as an individual.
| Population | The Pool of individuals in a generation
| Offspring | Refers of the individuals prepared for the next generation.
| Generation | The snapshot of population at that cycle.
| Mutation | The rate at which an individual item might change
### Definitions for the Variables
|Term | Definition |
|--|--|
| Initial Population | Initial Population of the `genes` that define the solution of the problem |
| Mutation Probability | The rate at which an offspring might
## The Knapsack Problem

> Image extracted from Wikipedia: https://commons.wikimedia.org/wiki/File:Knapsack_Problem_Illustration.svg
- The Simulator is available at: https://nenewang-genetic-algorithms-exploration-2-streamlitapp-89mw45.streamlit.app/knapsack
- This Problem is useful to start illustrating how genetic algorithms work.
- The Knapsack Problem is a combinatorial optimization problem that seeks to maximize the value of items in a knapsack without exceeding its weight capacity.
- Here I will post some hypothesis and results of the simulations that can be explored here.
- This problem can be seen at Rosetta, classical problem.
- We can think of each individual as a solution candidate. A combination of items:

### Dataset
The initital definitions of the items weights and utility had been extracted from: [Rosetta Code - Knacksack Prooblem 0-1](https://rosettacode.org/wiki/Knapsack_problem/0-1#)
### Question Driven Experiments
The following will posses a structure as follows:
- Question
- Parameters/Settings
- Data Analysis
- Hypothesis and testings
- Interpretation
### Selection Methods
Selection Algorithms are used to choose the "parents" for next's generations offsprings. A parent can be chosen multiple times.
Here we can see some pseudocode for common Selection Algorithms.
#### Tournament Selection
Idea: Select the parents from multiple competitions between random individuals.
Algorithm Pseudocode
```
1. Selects K individuals from the population at random to create a `tournament`.
2. Select the best individuals and put them in the 'parent' pool
3. Repeat `1` and `2` until `n` times (population count in this simulation).
4. Selected parents are then used as input for crossover, mutation to create next generation's offspring
```

Read more: ^[tournament Selection: https://www.geeksforgeeks.org/tournament-selection-ga]^[Wikipedia Tournament Selection: https://en.wikipedia.org/wiki/Tournament_selection#:~:text=Tournament%20selection%20is%20a%20method,at%20random%20from%20the%20population]
Implements `selTournament` method^[[deap selTorunament](http://deap.gel.ulaval.ca/doc/default/api/tools.html#deap.tools.selTournament): http://deap.gel.ulaval.ca/doc/default/api/tools.html#deap.tools.selTournament].
#### Roulette Selection
Idea: The probability of selection is proportional to it's fitness
Algorithm Pseudocode
```
1. create roulette proportional to fitness =>roulette
2. parent.add(roulette.random())
3. Repeat 1, 2 until `n` times is reached
4. Selected parents are used to derive offspring.
```

> For purposes of understanding you can imagine a roulette where fitnesses are proportional with the likelyhood of being selected.
#### Best K
Picks the best K as the parents (blueprints) to create offsprings.
Pseudocode
```
1. Sort population by fitness, Descending
2. Use top k as parents.
```
Read More^[[Baedung - Roulette Selection](https://www.baeldung.com/cs/genetic-algorithms-roulette-selection):
https://www.baeldung.com/cs/genetic-algorithms-roulette-selection]
### Testing Performance
To evaluate performance, we will compile results by exhaustively testing all combinations of the following parameters:
[Source code can be found here.](https://github.com/NeneWang/genetic-algorithms-exploration-2/blob/master/streamlit/computing_reports.py)
```py
# Population sizes to be tested, ranging from 50 to 800 in steps of 250.
populations = [x for x in range(50, 800, 250)]
# Number of generations to be tested, ranging from 50 to 200 in steps of 50.
generations = [x for x in range(50, 200, 50)]
# Crossover probabilities to be tested, ranging from 0.1 to 0.4 in steps of 0.1.
crossover_probabilities = [x/10 for x in range(1, 5)]
# Mutation probabilities to be tested, ranging from 0.1 to 0.4 in steps of 0.1.
mutation_probabilities = [x/10 for x in range(1, 5)]
# Selection methods to be tested, including Tournament Selection, Roulette Wheel Selection, and Best Selection.
selection_methods = [
tools.selTournament,
tools.selRoulette,
tools.selBest
]
# 'k' parameter values for selection methods, ranging from 1 to 4.
k = [x for x in range(1, 5)]
```
> We limit numerical variables into separated values in a range of selected samples to reduce the time complexity of computing all variables.
> Populations: 50, 300, 550... 800
> Generations: 50 100, 150, 200
The compiled results can be seen [here](https://github.com/NeneWang/genetic-algorithms-exploration-2/blob/master/streamlit/reports/knapsack_full_experiments.csv).

#### Correlations

Pairplots.

Correlations as numbers.
Some relevant moderate correations and it's likely descriptions:
- Max Found at Generations (Generation where the maximum generation is found)
- Initital Population (-0.48): Likely meaning when there is a larger intiial Population then the maximum can be found earlier.
- Max Generation (0.23): Likely when the max allowed generation is larger, then a max found generations can be found later (at later generations).
- Mutation Probability
- end max fitness (moderately possitive 0.21)
- end mean fitness (weak moderate correlation -0.13)
Some results correlations: These are correlations between results type of variables:
- End mean fitness of the population and the end max fitness (0.92 highly correlation). Makes sense as the likelihood of th emax fitness to be larger increases as the general population fitness increases.
- End mean
Some surprising lack of correlations:
- k_value: There seems to be no clear correlations for k_values. However we have to take into account that k_value only works for tournament and Roulette Selections.
**Hypothesis**: K Values have a stronger impact on the results for Tournament and Roulette Selections
**Null Hypothesis** : K Values don't have a correlation with the end result for Tournament and Roulette Selections.

> Computed with 'Tournament' and 'Roulette' selection only.
It seems that there is no significant change in the output when k_value changes.
#### Selection Method and speed at finding the maximum fitness.
- Motivation: Understand the difference between Selection Methods on it's impact of finding results.

T-Tests Tournament and Roulette Selections:
```python=
output_variables = ['max_found_at_generation', 'end_mean_fitness_population', 'end_max_fitness','end_max_fitness']
ttest_ind(df_full_knapsack[df_full_knapsack['selection_strategy_name'] == 'Tournament'][output_variables],
df_full_knapsack[df_full_knapsack['selection_strategy_name'] == 'Roulette'][output_variables])
```
>Ttest_indResult(statistic=array([-0.24105878, 0.49789979, 0.26877548, 0.26877548]), pvalue=array([0.80955253, 0.61864987, 0.78815067, 0.78815067]))
T-Tests Tournament and Best Selections:
```python=
ttest_ind(df_full_knapsack[df_full_knapsack['selection_strategy_name'] == 'Tournament'][output_variables],
df_full_knapsack[df_full_knapsack['selection_strategy_name'] == 'Best'][output_variables])
```
> Ttest_indResult(statistic=array([-0.78275557, 0.346537 , 0.29468014, 0.29468014]), pvalue=array([0.43393182, 0.72900258, 0.76829142, 0.76829142]))
T-Tests Roulette and Best Selections:
```python=
ttest_ind(df_full_knapsack[df_full_knapsack['selection_strategy_name'] == 'Roulette'][output_variables],
df_full_knapsack[df_full_knapsack['selection_strategy_name'] == 'Best'][output_variables])
```
> Ttest_indResult(statistic=array([-0.53668376, -0.14779815, 0.03241924, 0.03241924]), pvalue=array([0.59158988, 0.88252798, 0.97414335, 0.97414335]))
Non have a low enough P Value to further investigate. This could be because I am attempting this computations solely with the same random seed.
#### What are the parameters that resulted in the most fit individuals found?

> Distribution of end_max_fitness: It looks like the larger fitnesses are found the most.

What happens if we reduce the max generations allowed. Will we found the parameters that are able to find the max fitnesses more efficiently? (less generations)
Filtering where max fitness is larger than 1020.
```python
selected_max_df = df_full_knapsack[df_full_knapsack['end_max_fitness'] >= 1020]
```

> We can see that the more generations we allow to be processed. The more parameters combinations are able to find where max fitness are larger than 1020.
There doesn't seem to be the case where one selection strategy is superior than another one. As we can see that the stacks are fairly distributed on each generation.
#### Relation of Mutation rate and the speed of fitness improvement.

> If you look closely on max_generation 10, 11, 12 It seems that is likelier for larger crossover probabilities to find solutions where max fitness is>1020

> In some generations, e.g. 24, 25 we can see the pattern where larger mutation probabilities evidently results in finding max fitness where > 1020.

Where the count is > 1020, we compute the linear regression of mutation and max found at generation.
```python
linregress(selected_max_df['mutation_probability'], selected_max_df['max_found_at_generation'])
```
- **Null Hypothesis:** There is no linear relationship between `Mutation Probability` and `Max Found at Generation`
- **Alternative Hypothesis:** There is a linear relationship between `Mutation Probability` and `Max Found at Generation`
> LinregressResult(slope=-10.263877170580605, intercept=22.522917234960566, rvalue=-0.05144740085141358, pvalue=0.059445531776354574, stderr=5.440741640008741)
We can see that the pvalue is larger by an approximated of +1%. Which is an weak evidnece against the null hypothesis.
#### Relation between initial population size and end mean/max fitness
**End Max Fitness**
End max fitness is the maximum fitness found at the last generation.

Motivation: While this is just a preliminary simple model, this result could be argued to repeat the pattern and common theory seen in anthropology. This principle can be observed in natural populations where larger gene pools allow for better adaptation and survival ^[[Population genetic diversity and fitness in multiple environments](https://bmcecolevol.biomedcentral.com/articles/10.1186/1471-2148-10-205) https://bmcecolevol.biomedcentral.com/articles/10.1186/1471-2148-10-205]. Similarly, in our analysis, a larger initial population size increases the chances of discovering individuals with optimal fitness, mirroring the dynamics seen in natural evolutionary processes.
- Null Hypothesis: There is no relation between initial population and max end fitness
- Alternative Hypothesis: There is a relationship between max end fitness and the amount of first population.
> sns.scatterplot(data=df_full_knapsack, x='initial_population', y='end_mean_fitness_population', hue='selection_strategy_name')

```
linregress(df_full_knapsack['initial_population'], df_full_knapsack['end_mean_fitness_population'])
```
> LinregressResult(slope=0.0572676325757576, intercept=985.2328901164421, rvalue=0.5170708190600998, pvalue=9.302278745284642e-119, stderr=0.002281830899062215)
This result suggests that there is a strong evidence against the null hypothesis. Confirming the significance of the relationship. Which slope in this case is about 0.05 (small)
**End Mean Fitness**
End mean fitness is the value attributed to the mean fitness calculated from the population of solutions in the last generation.

> sns.scatterplot(data=df_full_knapsack, x='initial_population', y='end_max_fitness', hue='selection_strategy_name')

From the plot we can see a more evident relationship between the initial population and the end max fitness.
- Null Hypothesis: There isn't a linear relationship between the initial population and the end mean fitness.
- Alternative Hypothesis: There is a linear relationship between the initial population and the end mean population
> LinregressResult(slope=0.057576388888888906, intercept=1002.3497685185185, rvalue=0.5190784869886601, pvalue=7.965403256212276e-120, stderr=0.002282013484407436)
This result
## Introduction to Game Theory
Game Theory is a branch of applied mathematics where players make decisions that affect each other’s outcomes^[Britannica - Game Theory: https://www.britannica.com/science/game-theory]. This framework provides a foundation for creating simulations with multiple individuals, using rules from common game theory dilemmas like the Prisoner's Dilemma. By evaluating these agents, we can gain insights into behavioral patterns and how the viability of these patterns, as depicted in compensation tables, influences population tendencies as inherited traits. This Section explores the intersection of game theory, behavioral analysis, and evolutionary dynamics to understand how strategic interactions shape the evolution of behaviors within populations.

> Image extracted from: https://www.britannica.com/science/game-theory/Two-person-constant-sum-games
The Prisoner's Dilemma is a classic problem in game theory. Two prisoners, A and B, are isolated and must decide whether to confess to a crime without knowing the other's decision. The outcomes are:
1. If both confess, they each get five years in jail.
2. If neither confesses, they each get one year in jail.
3. If one confesses and the other remains silent, the confessor goes free while the silent one gets 20 years in jail.
### Using the Simulator
The following simualtions can be tested online here:
If the website is down, the simulator can be installed locally following the instructions here: https://nenewang-genetic-algorithms-exploration-2-streamlitapp-89mw45.streamlit.app/genetic_population_sim

If the website is down. The code and setup can be found here: https://github.com/NeneWang/genetic-algorithms-exploration-2
## Simulating Behavioural Evolution Using Game Theory
- Taking from the example of the Knapsack Problem.
- The simulation will attempt to measure the impact effects of Aggressive and Non-aggressive behaviours
- My initial inspiration and resources are from Youtube visualizations such as [^simulating_evolution]
[^simulating_evolution]: [Simulating the Evolution of Aggression - Primer](https://www.youtube.com/watch?v=YNMkADpvO4w&t=248s&ab_channel=Primer)
## BE1. Base Case: Tribal Hunters
**Motivation:** Investigating the Evolutionary Perspective of Collaboration
In this simulation, we will explore the dynamics of collaboration among hunters from different tribes. Each hunter has the option to either collaborate or act aggressively during hunting expeditions. The outcomes of these interactions will determine the resources obtained by each hunter.
**Scenario:**
- **Hunters' Behavior:**
- Collaborative: Hunters work together, sharing the resources obtained equally.
- Aggressive: Hunters compete for resources, potentially resulting in conflict.
**Table Representation:**
| Hunter 1 | Hunter 2 | Result |
|-------------|-------------|----------------------------------|
| Collaborative | Collaborative | Both hunters share resources equally |
| Collaborative | Aggressive | Collaborative hunter shares, Aggressive hunter keeps all resources |
| Aggressive | Collaborative | Aggressive hunter keeps all resources, Collaborative hunter shares |
| Aggressive | Aggressive | Conflict; both hunters leave with a single unit of food each |
**Simulation Constraints:**
- The offspring count of an individual aligns with the corresponding results shown in the table, representing the amount of resources the hunter is able to fetch as well.
- In cases where both hunters act aggressively, a conflict arises, resulting in both hunters obtaining a single unit of food each.
| | Collaborate | Agressive
--|--|--
**Collaborate** | 2, 2 | 0, 3
**Aggressive** | 3, 0 | 1, 1
Configuration Settings:
```json
"be1.tribal_hunters": {
"lore": "BE1 Base Case Tribal Hunters",
"both_coop": 2,
"mixed_coop": 0,
"mixed_defect": 3,
"defect_winner": 1,
"POPULATION_SIZE": 100,
"INITIAL_COOPERATIE_RATE": .5,
"P_CROSSOVER": 0.0,
"P_MUTATION": 0.0,
"RANDOMIZE_SEED": False,
"encounterEval": "prisonDilemmaEval"
},
```

> Cooperative and Agressive populations distribution across generations.
It appears that choosing to be aggressive always results in the hunter having offspring, regardless of the other hunter's choice. This highlights an interesting aspect of the scenario where the aggressive strategy may seem more advantageous from an individual hunter's perspective, as it ensures offspring regardless of the outcome of the interaction.
### BE1B. Does the initial population of cooperative members affect the result?
Motivation: The results in the previous experiment, shows that population with the aggressive trait will dominate the population by the end of the 50th generation. Does a different initial distribution of the population change this result?
```json
"be1b.tribal_hunters": {
"lore": "BE1 Base Case Tribal Hunters",
"both_coop": 2,
"mixed_coop": 0,
"mixed_defect": 3,
"both_defect_winner": 1,
"POPULATION_SIZE": 100,
"INITIAL_COOPERATIE_RATE": .9,
"P_CROSSOVER": 0.0,
"P_MUTATION": 0.0,
"RANDOMIZE_SEED": False,
"encounterEval": "prisonDilemmaEval"
},
```
> Notice Initial Cooperative rate to be set as 90%
|Control Results |Experimental Results |
|----------------|---------------------|
| 
> We can see that maximum population becomes 2500% larger by having a 90% initially cooperative members instead of 50%.
**Hypothesis**: Max resources available at the economy only increases when a collaborative member appears on the interaction. Once Collaborative members disappear from the genetic pool. They max resource is locked.
### BE1C. What if collaborating is much more rewarding?
| | Collaborate | Agressive
--|--|--
**Collaborate** | 4, 4 | 0, 3
**Aggressive** | 3, 0 | 1, 1
> 100% larger compensation for collaborating (control: 2)
```json
"be1c.tribal_hunters": {
"lore": "BE1 variant. With a more rewarding setting for coolaboration.",
"both_coop": 4,
"mixed_coop": 0,
"mixed_defect": 3,
"both_defect_winner": 1,
"POPULATION_SIZE": 100,
"INITIAL_COOPERATIE_RATE": .5,
"P_CROSSOVER": 0.0,
"P_MUTATION": 0.0,
"RANDOMIZE_SEED": False,
"encounterEval": "prisonDilemmaEval"
},
```
|Control Results |Experimental Results |
|----------------|---------------------|
| 
> Similar to the experiment above, increasing rewards seems to only to extend the max population/resources on the economy.
## BE2. Making aggressiveness nuclear.
Motivation: So far we had been allowing the case where both hunters are aggressive to allow resources to be split as 1 and 1. This allows the strategy to always be aggressive to be sustainable. What if aggressive causes an disagreements that ends up with no resources to any of the hunters?
| | Collaborate | Agressive
--|--|--
**Collaborate** | 2, 2 | 0, 3
**Aggressive** | 3, 0 | 0, 0
```json
"be2.tribal_hunters": {
"lore": "BE2 Making aggressiveness nuclear",
"both_coop": 2,
"mixed_coop": 0,
"mixed_defect": 3,
"both_defect_winner": 0,
"POPULATION_SIZE": 100,
"INITIAL_COOPERATIE_RATE": .5,
"P_CROSSOVER": 0.0,
"P_MUTATION": 0.0,
"RANDOMIZE_SEED": False,
"encounterEval": "prisonDilemmaEval"
},
```
|BE1 (Control) |BE2 (No Split) |
|----------------|---------------------|
| 
- We can see here that once all members with coollaborative tendencies are extint, the population collapses.
- In comparison to BE1 (Control) this is the case as aggressive and aggressive pairings results in no offsprings for neither.
### BE2b. Making it more appealing to collaborate.
Motivation: It seems that there isn't a combination in which cooperation becomes a sustainable strategy for the population. The intention is to increase cooperativeness results.
What if the rewards are 4, 5 or 6 as a result of collaboration? Does it make any difference?
```json
"be2b.tribal_hunters": {
"lore": "BE2 variant | Where being cooperative is many times more rewarding.",
"both_coop": 10,
"mixed_coop": 0,
"mixed_defect": 3,
"both_defect_winner": 0,
"POPULATION_SIZE": 10,
"INITIAL_COOPERATIE_RATE": .5,
"POPULATION_LIMIT": 800000,
"P_CROSSOVER": 0.0,
"P_MUTATION": 0.0,
"RANDOMIZE_SEED": False,
"encounterEval": "prisonDilemmaEval",
"select": selLiteralToFitness
},
```
> In this example we are starting with a lower population size, as the increase of population can quickly take over computer resources..
|Collaboration 4 | Collaboration 5 | Collaboration 6 | Collaboration 10
|--|--|--|--|
|  | | | 
It seems that increasing the reward for collaborating does increase the maximum population reached. But doesn't result in a sustainable long term strategy.
## BE3. Limiting Population with Limit Offspring
| | Collaborate | Agressive
--|--|--
**Collaborate** | 2, 2 | 0, 3
**Aggressive** | 3, 0 | 1, 1
We will prioritize in this cases. Those scored higher
A pseudocode as follows:
```python=
1. IndividualsWithScore = Run individuals against each other(Individuals)
2. RankedIndividualsWithScore = Sort by Score(individualsWithScore)
3. OffspringNextGeneration = LimitPopulation(RankedIndividualsWithScore, returnOnlyfirst=POPULATION_LIMIT)
```
> In other words, those with a higher result will end up with priority to occupy a limited amount of coupons for offsprings.
- What happens if there is so many populations allowed? How should we solve this?
```json
"be3.limiting_population": {
"lore": "BE2 variant | Where being cooperative is many times more rewarding.",
"both_coop": 4,
"mixed_coop": 0,
"mixed_defect": 3,
"both_defect_winner": 1,
"POPULATION_SIZE": 1000,
"INITIAL_COOPERATIE_RATE": .5,
"POPULATION_LIMIT": 100000,
"P_CROSSOVER": 0.0,
"P_MUTATION": 0.0,
"RANDOMIZE_SEED": False,
"encounterEval": "prisonDilemmaEval",
```
|BE1 |BE3 Introducing Limitations |
|----------------|---------------------|
| 
Let's try also with an environment that encourages cooperation more:
```json
"be3.limiting_population": {
"lore": "BE2 variant | Where we create an limit to the max amount of individuals in the population.",
"both_coop": 2,
"mixed_coop": 0,
"mixed_defect": 3,
"both_defect_winner": 1,
"POPULATION_SIZE": 100,
"INITIAL_COOPERATIE_RATE": .5,
"POPULATION_LIMIT": 150,
"P_CROSSOVER": 0.0,
"P_MUTATION": 0.0,
"RANDOMIZE_SEED": False,
"encounterEval": "prisonDilemmaEval",
"select": selLiteralToFitness
},
```
| Increasing coop rewards to 5 | Increasing coop rewards to 6 |
---|---
 | 
> Under these circusinstances, it looks that unless cooperativeness reach 100% of the population, having just some remaning aggressive members is enough to remove all the cooperative population.
### BE3c. Limiting Offspring using Descreasing Chances Instead
Note the following experiments will be addressed using the following confrontation-reward table:
| | Collaborate | Agressive
--|--|--
**Collaborate** | 2, 2 | 0, 3
**Aggressive** | 3, 0 | 0, 0
```python
chosen = []
for i in range(0, len(population)):
if len(chosen) >= population_limit:
break
skip_chance = 1 - (len(chosen) / population_limit)
# Skip chance increases as the population approaches the limit.
if random.random() > skip_chance:
continue
chosen.append(population[i])
population = chosen
```
```json
"be3c.limiting_population": {
"lore": "BE3 variant. Limiting using a curved survivval. Where as the population grows, the chances of survival decreases. Using the POPULATION_LIMIT as an asymptote.",
"both_coop": 5,
"mixed_coop": 0,
"mixed_defect": 3,
"both_defect_winner": 1,
"POPULATION_SIZE": 100,
"INITIAL_COOPERATIE_RATE": .5,
"POPULATION_LIMIT": 150,
"P_CROSSOVER": 0.0,
"P_MUTATION": 0.0,
"RANDOMIZE_SEED": False,
"encounterEval": "prisonDilemmaEval",
"select": selLiteralToFitness,
"limit_strategy": "INCREASING_DIFFICULTY"
},
```
This strategy should curve the genetic shift allowing bottom strategies a chance into remaining in the gene pool.
**Comparison coop reward of 6**
| Limiting Strategy | Decreasing Chances Strategy |
---|----
 | 
**Comparison coop reward of 5**
| Limiting Strategy | Decreasing Chances Strategy |
---|---
 |
> Here we can see that, because there exists a possibility for the offspring not to survive. Although an individual might have enough resources to have an offspring. The population dies off slowly every generation.
```json
"be3c.limiting_population": {
"lore": "BE3 variant. Limiting using a curved survivval. Where as the population grows, the chances of survival decreases. Using the POPULATION_LIMIT as an asymptote.",
"both_coop": 2,
"mixed_coop": 0,
"mixed_defect": 3,
"both_defect_winner": 1,
"POPULATION_SIZE": 100,
"INITIAL_COOPERATIE_RATE": .5,
"POPULATION_LIMIT": 150,
"P_CROSSOVER": 0.0,
"P_MUTATION": 0.0,
"RANDOMIZE_SEED": False,
"encounterEval": "prisonDilemmaEval",
"select": selLiteralToFitness,
"limit_strategy": "INCREASING_DIFFICULTY"
},
```
Limiting Strateg (Standard) | Limiting Strategy (4 coop reward) | Decreasing Chances Strategy (Standard) | Decreasing Chances Strategy (4 coop reward)
---|---|---|---
|  || 
> We can see here, how having Increasing Difficulty seems to smooth the line chart..
## BE4. Introducing Mutation and Crossover.
Let's simulate adding Mutation and Crossover into the simulation.
- Crossover: After pairing the solutions. The chance of each genes to exchange
- Mutation: The mutation of the offspring
pseudocode
```js
rankedPopulation = generateEncounters(population).sortby(performance)
pairedPopulation = selectedChildrenParentsPairs(rankedPopulation) // The higher their rank the more frequent they are as parents
offspring = PairAndReproduce(pairedPopulation, CrossoverRate)
mutate(offspring, mutationRate)
```
Pseudocode for PairAndReproduce
```python
for male, female in sortedByRankPopulation:
for idx in genesLenght:
if (DecideToCrossover(CrossoverChance)):
swapGene(male, female, idx)
offspring.append(male, female)
```
Pseudocode for Mutation:
```python
for individual in population:
for gene in genesLength:
if (DecideToMutate(mutationRate)):
flip(gene, individual)
```
```json
"be4.mutation_crossover": {
"lore": "BE1 variant. With Mutation and Crossover enabled.",
"both_coop": 2,
"mixed_coop": 0,
"mixed_defect": 3,
"both_defect_winner": 1,
"POPULATION_SIZE": 100,
"INITIAL_COOPERATIE_RATE": .5,
"POPULATION_LIMIT": 500000,
"P_CROSSOVER": 0.5,
"P_MUTATION": 0.1,
"RANDOMIZE_SEED": False,
"encounterEval": "prisonDilemmaEval",
"select": selLiteralToFitness,
},
```
| Control | Crossover (50%) | Mutation (10%) | Crossover and Mutation
|--|--|--|--|
 |  | | 
| |  | | 
Some take aways:
- I looks like by adding mutation. Population is able to reach a max population limit.
- And it seems that corssover and mutation is the fastest when it comes to reaching the limit (approx. 4 generations earlier)
### BE4b Changing into Decreasing Success limiting Strategy
We had seen how iton BE3c it seems that there is an eventual decay on population. How does that affect when there is mutation?
| Control | Crossover (50%) | Mutation (10%) | Crossover and Mutation
|--|--|--|--|
 |  | | 
 |  | |  |
### BE4c Nuclear Mutation
Using the following Reward table.
| | Collaborate | Agressive
--|--|--
**Collaborate** | 2, 2 | 0, 3
**Aggressive** | 3, 0 | 0, 0
| Control | Crossover (50%) | Mutation (10%) | Crossover and Mutation
|--|--|--|--|
 |  | | 
 |  | |  |
 | |  | 
> It Looks like having only mutation seems to be the most "Successful" strategy at seed 42.
## BE5 Introducing Dominant and Recessive Genes.
Where Documinant is Collaboration the strategy to determine behavior as:
G | 1 | 0
--|---|---
1 | A | C
0 | C | C
Psedocode:
```
Consider the genetic code: 0011110
Take only the first 2 digits: (00)
Only returns recessive trait if both are `1`
```
```python
def determineStrategyWithDominantRecessive(individual, limit=2):
"""
The strategy is determine as:
G | 1 | 0
--|---|---
1 | A | C
0 | C | C
"""
count1 = sum([1 for i in individual[:limit] if i == 1])
if count1 <= 0:
return AGGRESIVE
else:
return COOPERATIVE
```
### BE5a Dominant and Recessive
```json
"be5a.recessive_dominant": {
"lore": "BE4 variant. With Nuclear disagreements.",
"both_coop": 2,
"mixed_coop": 0,
"mixed_defect": 3,
"both_defect_winner": 0,
"POPULATION_SIZE": 100,
"INITIAL_COOPERATIE_RATE": .5,
"POPULATION_LIMIT": 500000,
"P_CROSSOVER": 0,
"P_MUTATION": 0.1,
"RANDOMIZE_SEED": False,
"encounterEval": "prisonDilemmaEval",
"select": selLiteralToFitness,
"limit_strategy": "INCREASING_DIFFICULTY",
"determine_strategy": determineStrategyWithDominantRecessive
},
```
| Control be4c.mutation_crossover | Dominant and Recessive Variant fo be4c.mutation_crossover |
|--|--|
| | |
> We can see that when there is a dominant/recessive system, (dominant being coop) then the genes pool increase faste population limit.
### BE5b Role of Dominant behaviour under
Using the following Reward table.
- This is following the traditional approach of values
| | Collaborate | Agressive
--|--|--
**Collaborate** | 5, 5 | 0, 10
**Aggressive** | 10, 0 | 1, 1
```json
"be5b.recessive_dominant_increasing": {
"lore": "BE4 variant. With Mutation and Crossover enabled.",
"both_coop": 5,
"mixed_coop": 0,
"mixed_defect": 10,
"both_defect_winner": 1,
"POPULATION_SIZE": 100,
"INITIAL_COOPERATIE_RATE": .5,
"POPULATION_LIMIT": 300000,
"P_CROSSOVER": 0.1,
"P_MUTATION": 0.05,
"RANDOMIZE_SEED": False,
"encounterEval": OPTIONS.PRISON_DILEMA_EVAL,
"limit_strategy": OPTIONS.INCREASING_DIFFICULTY,
"select": OPTIONS.selLiteralToFitness,
"determine_strategy": OPTIONS.determineStrategyWithDominantRecessive
},
```
Limiting Strategy | Without Recessive-Dominant | With Recessive-Dominant |
|--|--|--|
| LIMIT TOP |  ||
| INCREASING DIFFCULTY |  |  |
# Conclusions
Civilizational Cycling: It appears that civilizations may cycle between collaborative and aggressive dominant generations, each influencing societal dynamics in distinct ways.
Collaborative Societies and Population Limits: Collaborative societies tend to extend the maximum population limit, suggesting that cooperation may foster social cohesion and sustainability.
Aggressive Strategies and Population Fluctuations: Aggressive strategies seem to temporarily extend the population limit but are followed by population decreases, indicating potential drawbacks to aggressive behavior in the long term.
Mutation and Population Dynamics: Mutations have the potential to disrupt population "limits," introducing variability and unpredictability into population dynamics.
## Areas of Further Research
To expand the valuable insights, there are numerous additional research areas to explore. Below is a list of potential extensions for the project for further investigation:
- Introducing Concepts of Immunity: Investigate how incorporating concepts of immunity into genetic algorithms can provide any insights in the adaptions to explain how immune system's and cultural behaviours adapt.
- Simulate Mating Systems in Primates: Explore how for example monogamous, harem-polygynous or polygynandrous translate to the fitness dynamics.
- Introducing Knowledgeable agents: This allows agents to decide the action to use knowing previous actions of the agent they are interacting with.
- Neural MMO: Utilize the Massively Multiagent Game Environment Framework created by Joseph Suarez to create a complex and dynamic simulation environment where agents interact taking into account the environment and multiple indiivdual characteristics.^[Neural MMO: A Massively Multiagent Game Environment for Training and Evaluating Intelligent Agents: [https://arxiv.org/abs/1903.00784](https://arxiv.org/abs/1903.00784)]

> [Neural MMO: A massively multiagent game environment](https://openai.com/index/neural-mmo/)
# References
## Additional Resources
*Include things that you think might be relevant*
Nigel Gilbert, Klaus G Troitzsch - Simulation for the Social Scientist: https://www.amazon.com/Simulation-Social-Scientist-Nigel-Gilbert/dp/0335216005
The Bounds of Reason - Game Theory and the Unification of the Behavioral Sciences: https://www.amazon.com/Bounds-Reason-Unification-Behavioral-Sciences/dp/0691160848
> Includes Decisions Theory and Human Behaviour, Game Theory, Bayesian Rationality and Social Epistomology, Common Knowledge and Nash equilibrium, The Analytics of Human Society
Morality and Evolutionary Biology: https://plato.stanford.edu/entries/morality-biology/
> We simulated cooperative, aggressive, and non-aggressive behaviors. It would be interesting to see how morality to replicate the sustainability of morality as a trait.
VGsim: scalable viral genealogy simulator for global pandemic
https://www.ncbi.nlm.nih.gov/pmc/articles/PMC8095227/
> Wasn't able to implemental pandemic simulation on it yet.
Extending DEAP with Active Sampling for Evolutionary supervised Learning
https://www.scitepress.org/PublishedPapers/2021/106046/106046.pdf
> An Extension of the DEAP (Same framework used in this report's simulation) Framework with aditional supervised learning.