Mutation, Variation, and Novelty
Source:vignettes/mutation-variation-novelty.Rmd
mutation-variation-novelty.RmdPurpose
This article explains mutation, variation, and novelty in artificial-life models. Variation is essential because selection requires differences among individuals (Darwin 1859; Nowak 2006).
The purpose of this chapter is to show how novelty can enter an artificial population and why variation matters for adaptation-like dynamics.
The guiding question is:
How does novelty enter an artificial population?
Why variation matters
A population with no variation has limited capacity for adaptive change. If all agents are identical, selection has little to distinguish. Every agent has the same traits, the same potential advantages, and the same vulnerabilities.
Variation changes this. Once agents differ, some traits may become more successful than others under particular environmental conditions.
For example:
- faster agents may reach resources more easily;
- more efficient agents may convert resources into energy more effectively;
- agents with lower reproduction thresholds may reproduce earlier;
- agents with higher energy may survive longer.
In artificial-life models, variation provides the raw material for selection-like processes.
Variation versus mutation
Variation and mutation are related, but they are not the same.
Variation refers to differences among agents in a population.
Mutation refers to one mechanism that can create or modify those differences.
A population can have variation because agents were initialized differently. It can also gain variation over time because offspring differ from parents.
| Concept | Meaning |
|---|---|
| Variation | Differences among agents |
| Mutation | Random change to a trait |
| Novelty | New trait values or new combinations |
| Selection | Differential persistence or reproduction |
| Adaptation-like change | Shift in population traits over time |
In artificialLifeR, variation can appear through initial
trait differences and through mutation.
Mutation as controlled noise
In biological systems, mutation refers to changes in genetic
material. In artificialLifeR, mutation is much simpler. It
is represented as random numeric change applied to a selected trait.
This is not a full genetic mutation model. It does not represent DNA, RNA, molecular replication, recombination, repair, or developmental biology.
Instead, mutation is used as a teaching abstraction:
Mutation introduces small changes that can alter trait distributions.
This makes it possible to explore how novelty enters a population without modelling molecular genetics.
Relation to the package
The function simulate_mutation() applies mutation-like
changes to a selected trait.
| Argument | Conceptual meaning |
|---|---|
agents |
Starting population |
trait |
Trait to modify |
mutation_rate |
Probability that an agent’s trait changes |
mutation_sd |
Size of random mutation effect |
lower |
Lower bound for trait values |
upper |
Upper bound for trait values |
seed |
Reproducibility |
The mutation rate controls how often mutation occurs.
The mutation size controls how large the changes are.
The bounds prevent trait values from moving outside the allowed
range.
Example: create a population
Start by creating a simple population.
agents <- create_agents(
n_agents = 50,
seed = 5
)
head(agents)
#> agent x y energy speed efficiency
#> 1 1 0.2002145 0.3845769 1.2194873 0.01009226 0.5946089
#> 2 2 0.6852186 0.5662727 1.0281589 0.07270623 0.5751771
#> 3 3 0.9168758 0.9219906 1.1533034 0.06351589 0.4482623
#> 4 4 0.2843995 0.9758776 0.9112248 0.05416967 0.5808336
#> 5 5 0.1046501 0.9330338 0.9831699 0.04884309 0.4385465
#> 6 6 0.7010575 0.3811627 0.8612570 0.06787623 0.6238259
#> reproduction_threshold age alive
#> 1 1.488632 0 TRUE
#> 2 1.470490 0 TRUE
#> 3 1.598917 0 TRUE
#> 4 1.422487 0 TRUE
#> 5 1.527590 0 TRUE
#> 6 1.541078 0 TRUEMeasure the starting variation
Before mutation, summarize variation in the selected trait.
measure_life_like_complexity(
agents,
trait_col = "efficiency"
)
#> n unique_values entropy mean sd temporal_variability
#> 1 50 50 2.889669 0.5066717 0.0989657 NA
#> mean_abs_change
#> 1 NAApply mutation
Now apply mutation to the efficiency trait.
mutated <- simulate_mutation(
agents,
trait = "efficiency",
mutation_rate = 0.50,
mutation_sd = 0.08,
lower = 0.01,
upper = 1,
seed = 5
)
head(mutated)
#> agent x y energy speed efficiency
#> 1 1 0.2002145 0.3845769 1.2194873 0.01009226 0.5711303
#> 2 2 0.6852186 0.5662727 1.0281589 0.07270623 0.5751771
#> 3 3 0.9168758 0.9219906 1.1533034 0.06351589 0.4482623
#> 4 4 0.2843995 0.9758776 0.9112248 0.05416967 0.6943207
#> 5 5 0.1046501 0.9330338 0.9831699 0.04884309 0.5584484
#> 6 6 0.7010575 0.3811627 0.8612570 0.06787623 0.6238259
#> reproduction_threshold age alive
#> 1 1.488632 0 TRUE
#> 2 1.470490 0 TRUE
#> 3 1.598917 0 TRUE
#> 4 1.422487 0 TRUE
#> 5 1.527590 0 TRUE
#> 6 1.541078 0 TRUECompare before and after mutation
rbind(
before = measure_life_like_complexity(
agents,
trait_col = "efficiency"
),
after = measure_life_like_complexity(
mutated,
trait_col = "efficiency"
)
)
#> n unique_values entropy mean sd temporal_variability
#> before 50 50 2.889669 0.5066717 0.0989657 NA
#> after 50 50 3.015854 0.5154477 0.1213256 NA
#> mean_abs_change
#> before NA
#> after NAInterpretation
Mutation changes the distribution of efficiency values. It can increase, decrease, or reshape variation depending on mutation rate, mutation size, and trait bounds.
A careful interpretation is:
The simulation shows how random trait changes can alter variation in an artificial population.
An overstatement would be:
The simulation fully models biological mutation.
The first statement is appropriate. The second is not.
Visualizing trait change
If the plotting function supports point or histogram-style outputs, you can inspect trait values directly. A simple base R plot is also useful for this chapter.
plot(
agents$efficiency,
mutated$efficiency,
xlab = "Efficiency before mutation",
ylab = "Efficiency after mutation",
main = "Trait values before and after mutation"
)
abline(0, 1, lty = 2)
Interpretation of the plot
Each point represents one agent. Points close to the dashed line changed little. Points farther from the line changed more.
This plot helps show that mutation is not a population-level command to become better. It is a source of variation. Some changes may be useful, some may be harmful, and many may be neutral depending on the environment.
Mutation rate
The mutation_rate controls how many agents are affected
by mutation.
A low mutation rate means few agents change.
A high mutation rate means many agents change.
low_mutation <- simulate_mutation(
agents,
trait = "efficiency",
mutation_rate = 0.05,
mutation_sd = 0.08,
lower = 0.01,
upper = 1,
seed = 5
)
high_mutation <- simulate_mutation(
agents,
trait = "efficiency",
mutation_rate = 0.80,
mutation_sd = 0.08,
lower = 0.01,
upper = 1,
seed = 5
)
rbind(
original = measure_life_like_complexity(
agents,
trait_col = "efficiency"
),
low_mutation = measure_life_like_complexity(
low_mutation,
trait_col = "efficiency"
),
high_mutation = measure_life_like_complexity(
high_mutation,
trait_col = "efficiency"
)
)
#> n unique_values entropy mean sd
#> original 50 50 2.889669 0.5066717 0.09896570
#> low_mutation 50 50 2.856233 0.5084719 0.09675427
#> high_mutation 50 50 3.082754 0.5154907 0.12512048
#> temporal_variability mean_abs_change
#> original NA NA
#> low_mutation NA NA
#> high_mutation NA NAInterpretation of mutation rate
Changing the mutation rate changes how often novelty enters the population.
A low mutation rate may preserve continuity but introduce little novelty. A high mutation rate may introduce more novelty but may also disrupt inherited structure.
This is important because artificial-life systems often depend on a balance between continuity and change.
Mutation size
The mutation_sd controls the size of the mutation
effect.
Small mutation sizes create small changes.
Large mutation sizes create larger jumps in trait values.
small_mutation <- simulate_mutation(
agents,
trait = "efficiency",
mutation_rate = 0.50,
mutation_sd = 0.02,
lower = 0.01,
upper = 1,
seed = 5
)
large_mutation <- simulate_mutation(
agents,
trait = "efficiency",
mutation_rate = 0.50,
mutation_sd = 0.20,
lower = 0.01,
upper = 1,
seed = 5
)
rbind(
original = measure_life_like_complexity(
agents,
trait_col = "efficiency"
),
small_mutation = measure_life_like_complexity(
small_mutation,
trait_col = "efficiency"
),
large_mutation = measure_life_like_complexity(
large_mutation,
trait_col = "efficiency"
)
)
#> n unique_values entropy mean sd
#> original 50 50 2.889669 0.5066717 0.0989657
#> small_mutation 50 50 2.880960 0.5088657 0.1008750
#> large_mutation 50 50 2.907012 0.5286118 0.1977515
#> temporal_variability mean_abs_change
#> original NA NA
#> small_mutation NA NA
#> large_mutation NA NAInterpretation of mutation size
Mutation size affects how far traits can move. Small changes may preserve similarity between parent and offspring. Large changes can create more dramatic novelty but may also move traits away from previously successful values.
In artificial-life terms:
Mutation explores nearby or distant possibilities in trait space.
The best mutation size depends on the model and question.
Trait bounds
The lower and upper arguments define the
allowed trait range. These bounds are important because not every
numeric value makes sense.
For example, efficiency may be limited to a positive range. Speed may have a minimum and maximum. Reproduction thresholds may need to remain biologically or conceptually plausible.
Trait bounds represent simplified constraints.
bounded_mutation <- simulate_mutation(
agents,
trait = "efficiency",
mutation_rate = 0.80,
mutation_sd = 0.30,
lower = 0.01,
upper = 1,
seed = 6
)
range(bounded_mutation$efficiency)
#> [1] 0.01 1.00Interpretation of bounds
The range shows that mutation did not push the selected trait outside the specified limits.
This is important because artificial-life models often need constraints. Without constraints, mutation can create values that are mathematically possible but conceptually meaningless.
Novelty is not automatically improvement
Mutation introduces novelty, but novelty is not automatically beneficial.
A mutation may:
- improve performance in a particular environment;
- reduce performance;
- have no clear effect;
- matter only under certain conditions;
- become useful later if the environment changes.
Selection-like processes determine whether some variations become more common over time. Mutation introduces possibilities. Selection filters them.
This relationship is central:
Mutation generates variation. Selection changes the frequency of variation.
Balance between stability and novelty
Too little mutation may limit novelty. Too much mutation may disrupt inherited structure.
Artificial-life systems often become interesting when they balance continuity and change. This balance is related to broader complexity ideas: systems need enough stability to preserve organization and enough variability to explore new possibilities (Langton 1990; Mitchell 2009).
A useful way to think about it is:
| Mutation level | Possible consequence |
|---|---|
| Very low | Population may stagnate |
| Moderate | Population can explore new possibilities |
| Very high | Population may lose stable inheritance |
This is not a universal rule, but it is a useful educational guide.
Mutation and evolvability
Evolvability refers to the capacity of a system to generate heritable variation that can support adaptive change.
Mutation contributes to evolvability because it introduces new trait values. But mutation alone is not enough. Evolvability also depends on:
- inheritance;
- selection;
- environmental constraints;
- population structure;
- survival and reproduction;
- continuity across generations.
simulate_mutation() illustrates only one part of this
broader process.
Responsible interpretation
Mutation in this package is abstract. It does not represent DNA, molecular biology, or real genetic mechanisms. It represents the general idea that traits can vary.
It is better to say:
The simulation illustrates mutation-like trait variation.
than:
The simulation models real genetic mutation.
It is better to say:
Mutation can introduce novelty into an artificial population.
than:
Mutation automatically improves the population.
Careful interpretation keeps the model clear and academically credible.
Relation to other artificial-life processes
Mutation becomes most meaningful when connected to other artificial-life processes.
| Process | Role |
|---|---|
| Reproduction | Maintains continuity |
| Mutation | Introduces variation |
| Selection | Changes trait frequencies |
| Resource competition | Creates environmental pressure |
| Population dynamics | Shows system-level consequences |
Together, these processes help explain how artificial populations can change over time.
Educational use
This chapter can support several classroom or self-study questions:
- Why is variation necessary for selection?
- How does mutation differ from variation?
- What happens when mutation rate is low?
- What happens when mutation rate is high?
- What happens when mutation size changes?
- Why is novelty not automatically improvement?
- Why are trait bounds important?
- How does mutation support evolvability?
These questions help learners understand mutation as one part of a broader artificial-life system.
Key takeaway
Mutation introduces novelty into artificial populations by modifying traits. It is most meaningful when combined with inheritance, selection, resources, and population dynamics.
artificialLifeR represents mutation as simplified
numeric trait variation. This makes the concept visible and teachable
while preserving the distinction between artificial-life toy models and
real biological genetics.