The one max problem is a starter problem for genetic algorithms. The optimization goal is to maximize the number of ones in a list. It is simple but contains all the components you need for genetic algorithms.
Initial Population
Each member of the population is a list. Each element in the lists are a 1 or 0. The apl operator ? is called roll and rolls a die up to the given number.
Because APL is 1 indexed we get a 1 or a 2. To generate a list of 1s or 2s we roll against a vector.
? 2 2 2 2 2 2 2 2 2
┌→────────────────┐
│2 2 2 1 2 2 1 1 2│
└~────────────────┘
We can use ⍴ to create a list of the correct size
?10⍴2
┌→──────────────────┐
│2 2 2 2 2 2 1 2 2 1│
└~──────────────────┘
We can use extend this to generate the entire population of p0
?10 10 ⍴ 2
┌→──────────────────┐
↓2 1 1 2 2 2 1 2 2 1│
│1 2 2 1 2 1 1 2 2 1│
│2 1 2 2 2 2 1 1 2 2│
│1 1 1 2 1 2 2 2 1 2│
│1 2 2 1 1 2 2 1 2 2│
│1 1 1 2 2 2 2 2 2 1│
│1 1 2 1 1 2 2 2 1 2│
│1 1 1 1 1 1 1 1 2 2│
│2 2 1 1 1 1 2 2 1 2│
│1 2 1 2 1 1 1 1 2 2│
└~──────────────────┘
To get 1s and 0s we subtract one
⎕←p0←1 -⍨ ?10 10 ⍴ 2
┌→──────────────────┐
↓1 1 1 0 1 0 0 0 0 0│
│1 0 0 0 1 0 0 0 1 0│
│0 1 0 1 1 1 1 0 0 0│
│0 0 0 1 0 1 1 0 0 0│
│1 1 1 0 1 0 1 1 1 1│
│1 1 0 1 0 0 0 1 1 1│
│1 0 0 1 1 0 1 0 0 0│
│0 1 1 1 0 1 1 0 1 1│
│1 0 0 1 0 1 0 1 0 1│
│0 0 1 1 1 0 1 1 0 0│
└~──────────────────┘
Crossover
This is a function that generates children from parents. This problem generally takes a pair of parents. Splits them at the same point (a different point for different pairs) and then swaps the tails.
[1,1,1,1] [1,1,1] [1] [1,1,1,2]
-> ->
[2,2,2,2] [2,2,2] [2] [2,2,2,1]
Do this for every pair of parents and you have your new population
Instead of splitting we are going to use ⌽ the rotation operator. ⌽ wraps around.
[1,1,1,1] [2,2,2,2] -> [1,1,1,1,2,2,2,2] -> [2,1,1,1,1,2,2,2] -> [2,1,1,1] [1,2,2,2]
Probably close enough
↓⍤2⊢group sort p0 ⍝ reshape
┌→────────────────────────────────────────────┐
↓ ┌→──────────────────┐ ┌→──────────────────┐ │
│ │1 1 1 0 1 0 1 1 1 1│ │0 1 1 1 0 1 1 0 1 1│ │
│ └~──────────────────┘ └~──────────────────┘ │
│ ┌→──────────────────┐ ┌→──────────────────┐ │
│ │1 1 0 1 0 0 0 1 1 1│ │0 1 0 1 1 1 1 0 0 0│ │
│ └~──────────────────┘ └~──────────────────┘ │
│ ┌→──────────────────┐ ┌→──────────────────┐ │
│ │1 0 0 1 0 1 0 1 0 1│ │0 0 1 1 1 0 1 1 0 0│ │
│ └~──────────────────┘ └~──────────────────┘ │
│ ┌→──────────────────┐ ┌→──────────────────┐ │
│ │1 1 1 0 1 0 0 0 0 0│ │1 0 0 1 1 0 1 0 0 0│ │
│ └~──────────────────┘ └~──────────────────┘ │
│ ┌→──────────────────┐ ┌→──────────────────┐ │
│ │1 0 0 0 1 0 0 0 1 0│ │0 0 0 1 0 1 1 0 0 0│ │
│ └~──────────────────┘ └~──────────────────┘ │
└∊────────────────────────────────────────────┘
,/↓⍤2⊢group sort p0 ⍝ ravel each pair of parents together
┌→──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ ┌→──────────────────────────────────────┐ ┌→──────────────────────────────────────┐ ┌→──────────────────────────────────────┐ ┌→──────────────────────────────────────┐ ┌→──────────────────────────────────────┐ │
│ │1 1 1 0 1 0 1 1 1 1 0 1 1 1 0 1 1 0 1 1│ │1 1 0 1 0 0 0 1 1 1 0 1 0 1 1 1 1 0 0 0│ │1 0 0 1 0 1 0 1 0 1 0 0 1 1 1 0 1 1 0 0│ │1 1 1 0 1 0 0 0 0 0 1 0 0 1 1 0 1 0 0 0│ │1 0 0 0 1 0 0 0 1 0 0 0 0 1 0 1 1 0 0 0│ │
│ └~──────────────────────────────────────┘ └~──────────────────────────────────────┘ └~──────────────────────────────────────┘ └~──────────────────────────────────────┘ └~──────────────────────────────────────┘ │
└∊──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
↑(?5⍴10) ,.(⊂2 10⍴⌽) ,/↓⍤2⊢group sort p0 ⍝ apply a different rotation to each pair of parents↑
┌→──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ ┌→──────────────────┐ ┌→──────────────────┐ ┌→──────────────────┐ ┌→──────────────────┐ ┌→──────────────────┐ │
│ ↓1 1 0 1 0 1 1 1 1 0│ ↓1 1 0 1 0 1 1 1 1 0│ ↓1 0 0 1 1 1 0 1 1 0│ ↓0 1 0 0 0 0 0 1 0 0│ ↓1 0 0 0 1 0 0 0 0 1│ │
│ │1 1 1 0 1 1 0 1 1 1│ │0 0 1 1 0 1 0 0 0 1│ │0 1 0 0 1 0 1 0 1 0│ │1 1 0 1 0 0 0 1 1 1│ │0 1 1 0 0 0 1 0 0 0│ │
│ └~──────────────────┘ └~──────────────────┘ └~──────────────────┘ └~──────────────────┘ └~──────────────────┘ │
└∊──────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
↑⍪/⎕←↑(?5⍴10) ,.(⊂2 10⍴⌽) ,/↓⍤2⊢group sort p0 ⍝ reshape into a new population
┌→──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ ┌→──────────────────┐ ┌→──────────────────┐ ┌→──────────────────┐ ┌→──────────────────┐ ┌→──────────────────┐ │
│ ↓1 1 1 0 1 1 1 0 1 1│ ↓0 0 1 1 1 0 1 0 1 1│ ↓0 0 1 0 1 0 1 0 1 0│ ↓1 1 0 1 0 0 0 0 0 1│ ↓0 1 0 0 0 1 0 0 0 0│ │
│ │0 1 1 1 1 1 0 1 0 1│ │1 1 0 0 0 1 1 0 1 0│ │0 1 1 1 0 1 1 0 0 1│ │0 0 1 1 0 1 0 0 0 1│ │1 0 1 1 0 0 0 1 0 0│ │
│ └~──────────────────┘ └~──────────────────┘ └~──────────────────┘ └~──────────────────┘ └~──────────────────┘ │
└∊──────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
┌→──────────────────┐
↓1 1 1 0 1 1 1 0 1 1│
│0 1 1 1 1 1 0 1 0 1│
│0 0 1 1 1 0 1 0 1 1│
│1 1 0 0 0 1 1 0 1 0│
│0 0 1 0 1 0 1 0 1 0│
│0 1 1 1 0 1 1 0 0 1│
│1 1 0 1 0 0 0 0 0 1│
│0 0 1 1 0 1 0 0 0 1│
│0 1 0 0 0 1 0 0 0 0│
│1 0 1 1 0 0 0 1 0 0│
└~──────────────────┘
crossover←{count len←⍺⋄↑⍪/↑(?count⍴len) ,.(⊂2 len⍴⌽) ,/↓⍤2⊢⍵}
(5 10) crossover group sort p0
┌→──────────────────┐
↓0 1 1 1 0 1 1 0 1 1│
│1 1 1 0 1 0 1 1 1 1│
│1 0 0 0 1 1 1 0 1 0│
│1 1 1 1 0 0 0 1 1 0│
│1 0 0 1 1 1 0 1 1 0│
│0 1 0 0 1 0 1 0 1 0│
│0 1 0 0 0 0 0 1 0 0│
│1 1 0 1 0 0 0 1 1 1│
│0 0 0 1 0 0 0 1 0 0│
│0 0 1 0 1 1 0 0 0 1│
└~──────────────────┘