Genetic Algorithms › Example

Michael BrenndoerferOctober 29, 20266 min read
Machine Learning from ScratchAll chapters
Part 15 of 15Heuristic and Evolutionary Optimization
Chapter 91Genetic Algorithms › Example
Reading section 5 of 10 · Example · 6 minSection 5 of 10 · 6 min

Section 5 of 10 · 6 min read

Genetic Algorithms › ExampleSection view · Sections in this chapter5 / 10 ↓
Reading tools Definitions, links & notes

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Notes & comments

The formulas are only convincing if they reproduce on a single generation. We therefore work through one generation by hand on the shared instance, with a population of four so the arithmetic stays visible. The costs below are computed from the distance matrix; the implementation re-derives them from code, which lets us check that the hand calculation and the program agree.

Step 1: decode and score four individuals

Take the population

Decoded tours and costs for the four worked-example individuals.
IndividualPermutationVehicle 1Vehicle 2Cost
P1P_1(1, 7, 8, 3, 6, 5, 4, 2)0→1→7→8→3→00→6→5→4→2→040.8563
P2P_2(1, 2, 3, 8, 6, 5, 4, 7)0→1→2→3→8→00→6→5→4→7→038.2665
P3P_3(1, 2, 3, 7, 4, 5, 6, 8)0→1→2→3→7→00→4→5→6→8→039.1233
P4P_4(2, 6, 1, 5, 3, 7, 4, 8)0→2→6→1→5→00→3→7→4→8→060.0227

Distances and totals below are rounded independently from full-precision values, so summing the displayed arc lengths can differ in the final decimal place. The first individual is the nearest-neighbour construction, which is where every method in this chapter starts. Its cost is the sum of the arcs d(0,1)=3.1623d(0,1)=3.1623, d(1,7)=2.8284d(1,7)=2.8284, d(7,8)=2.8284d(7,8)=2.8284, d(8,3)=2.2361d(8,3)=2.2361, d(3,0)=6.4031d(3,0)=6.4031 for the first vehicle, giving 17.458317.4583, and d(0,6)=6.0828d(0,6)=6.0828, d(6,5)=2.8284d(6,5)=2.8284, d(5,4)=3.1623d(5,4)=3.1623, d(4,2)=5.0000d(4,2)=5.0000, d(2,0)=6.3246d(2,0)=6.3246 for the second, giving 23.398023.3980. In total 40.856340.8563. The other rows are decoded the same way: split the permutation after position four, close each half with the depot, and sum the five arcs in each route.

Step 2: select parents by tournament

For this illustrative update, two size-k=2k=2 tournaments select the intended parents. The first pits P2P_2 against P4P_4 and returns P2P_2, since 38.2665<60.022738.2665<60.0227. The second pits P3P_3 against P1P_1 and returns P3P_3, since 39.1233<40.856339.1233<40.8563. Thus p=P2=(1,2,3,8,6,5,4,7)p=P_2=(1,2,3,8,6,5,4,7) and q=P3=(1,2,3,7,4,5,6,8)q=P_3=(1,2,3,7,4,5,6,8).

Each tournament returns its cheaper contender. The two sampled pairs are supplied for the hand calculation, rather than a claim about which individuals a random run will select. The example uses four scored parents and one illustrated offspring before survival.

Step 3: order crossover with cuts a=4a=4, b=6b=6

The block is copied first. Note that positions 44, 55, 66 of pp hold the values 6,5,46, 5, 4, so U={4,5,6}U = \{4,5,6\}.

Order-crossover copy step for the worked cut positions.
Position01234567
pp12386547
qq12374568
child after copy––––654–

Next, list qq cyclically starting at position b+1=7b+1 = 7: the values are q7=8q_7=8, then q0=1q_0=1, q1=2q_1=2, q2=3q_2=3, q3=7q_3=7, and then q4=4q_4=4, q5=5q_5=5, q6=6q_6=6 which are all in UU and are skipped. The filtered list is therefore 8,1,2,3,78, 1, 2, 3, 7. The empty positions in cyclic order from 77 are 7,0,1,2,37, 0, 1, 2, 3, so we assign

c7←8,c0←1,c1←2,c2←3,c3←7,c_7 \leftarrow 8,\quad c_0 \leftarrow 1,\quad c_1 \leftarrow 2,\quad c_2 \leftarrow 3,\quad c_3 \leftarrow 7,

giving the child c=(1,2,3,7,6,5,4,8)c = (1,2,3,7,6,5,4,8).

The important point is that the child is a permutation without any repair. The copied block supplies 6,5,46,5,4; the filtered list supplies the remaining values in the order qq had them, after removing the copied ones. Nothing is duplicated and nothing is lost.

Step 4: score the child

The child decodes to the tours 0→1→2→3→7→00 \to 1 \to 2 \to 3 \to 7 \to 0 and 0→6→5→4→8→00 \to 6 \to 5 \to 4 \to 8 \to 0. Vehicle 1 costs d(0,1)+d(1,2)+d(2,3)+d(3,7)+d(7,0)≈3.1623+3.1623+2.2361+4.1231+3.1623≈15.8460d(0,1) + d(1,2) + d(2,3) + d(3,7) + d(7,0) \approx 3.1623 + 3.1623 + 2.2361 + 4.1231 + 3.1623 \approx 15.8460, and vehicle 2 costs d(0,6)+d(6,5)+d(5,4)+d(4,8)+d(8,0)≈6.0828+2.8284+3.1623+3.6056+5.8310≈21.5100d(0,6) + d(6,5) + d(5,4) + d(4,8) + d(8,0) \approx 6.0828 + 2.8284 + 3.1623 + 3.6056 + 5.8310 \approx 21.5100. The total is 15.8460+21.5100=37.356015.8460 + 21.5100 = 37.3560, which is shorter than either parent (38.266538.2665 and 39.123339.1233).

That is recombination doing real work. The child keeps the left block 1,2,31,2,3 in qq's order and appends the value 77 that qq had right after it, and it keeps pp's descending block 6,5,46,5,4 and closes it with 88 from qq. Neither parent contained both blocks in that arrangement. The example is small, but it shows the mechanism the population is supposed to exploit: crossover can assemble a combination that neither parent had.

Step 5: mutation, and elitist replacement

The loop applies swap mutation to a child with probability pmp_m (the per-child mutation rate, here 0.5) before scoring it, so only one of the two versions, the mutated one or the unmutated one, is charged to the budget. For illustration, swapping positions 55 and 66 of the child gives (1,2,3,7,6,4,5,8)(1,2,3,7,6,4,5,8) with cost 39.021039.0210, which is worse than the unmutated child; mutation is a perturbation, not an improvement operator. This one swap is worse; it does not establish how often all swaps lose.

Survivor selection is (μ+λ)(\mu+\lambda) with μ=4\mu=4. The pool is the four parents plus the child, and the four cheapest are kept: the child at 37.356037.3560, then P2P_2 at 38.266538.2665, P3P_3 at 39.123339.1233, and P1P_1 at 40.856340.8563. P4P_4 at 60.022760.0227 is discarded. The population mean falls from

40.8563+38.2665+39.1233+60.02274=44.5672to37.3560+38.2665+39.1233+40.85634=38.9005.\frac{40.8563+38.2665+39.1233+60.0227}{4} = 44.5672 \quad\text{to}\quad \frac{37.3560+38.2665+39.1233+40.8563}{4} = 38.9005 .

Whether this child is optimal is a question for enumeration, which we run in the implementation; on this instance enumeration confirms that the child is optimal, with minimum cost approximately 37.356037.3560 (rounded to four decimal places). The enumeration is an independent computation excluded from every search budget; the optimization figures and the summary table report that measured result. Scoring the four parents and both displayed child variants costs six illustrative evaluations, separate from every search budget. In the actual loop only the final, possibly mutated version of each child is scored. The hand example has shown the mechanics; the next section turns those mechanics into code and holds the result to the same budget as the other methods.

Comments

Add to the conversation

A question, a correction, or an example from your own work.

No comments yet. Be the first to share your thoughts!

Newsletter

Stay up to date

Get new articles, book updates, and notes on AI and technology.

Unsubscribe at any time. Privacy policy