In my lastÂ post, I introduced the notion of deep contingency and contrasted it with deep hierarchy—the hypothesizedÂ property of fitness functions that genetic algorithms purportedly exploit. Here I provide evidence that recombinative evolution can optimize *multiple* deeply contingent components in parallel*.Â *Specifically, I generalize theÂ contingent parities function presented in the previous post (which you should read first) and examineÂ theÂ performance of a simple genetic algorithm on an instance of the generalized problem. For the sake of comparison, the behaviorÂ of simulated annealingÂ is also presented.

The pseudocode for a Contingent Parities Function with *multiple components* is given below:

The following figure shows the missteps of component 1 (in blue) and component 2 (in green) of a chromosome with maximal fitness in each generationÂ when aÂ simple genetic algorithm was applied to an contingent parities function with two components of order 2 and height 100. The y-coordinate of the green dots (representing the missteps of component 2) were dodged by +0.5 to reduce overlap. The maximal fitness in each generation is shown in red.

To regenerate this figure, clone the branch of this repositoryÂ as follows:

git clone -b multicomponent-cpf https://github.com/burjorjee/royal-roads.git

Then execute the following python code:

import royalroads as rr cpf = rr.ContingentParitiesFunction(order=2, height=100, numComponents=2) rr.evolve(fitnessFunction=cpf, popSize=500, maxGens=1000, probMutation=0.004, sigmaScaling=True, sigmaScalingCoeff=0.5, useClamping=True, rngSeed=1, visualize=True)

The figure shows that the simple genetic algorithm optimizes both components of the contingent parities function *concurrently*. The maximal fitness achieved was 199.

A plot showing the behavior of simulated annealing on the same function follows below:

To regenerate this figure execute the following python code:

import royalroads as rr cpf = rr.ContingentParitiesFunction(order=2, height=100, numComponents=2) rr.anneal(fitnessFunction=cpf, epochsPerPeriod=500, numPeriods=1000, initFitnessDropOfOneAcceptanceProb=0.6, finalFitnessDropOfOneAcceptanceProb=0.01)

The maximal fitness achieved was 168.