## Appendix B Algorithm Creation and Applications for Problem-Solving
### Applying Random Search
The current example shows how GA can be applied to solve any type of problem when provided problem-specific initialization, mutation, and crossover functions. Note that, in context of GA, the LS's neighborhood's size and functions are seen as the GA's population's size and mutation operators, respectively, and vice-versa. From the figure, two dictionaries are created to store the problem-specific initialization and crossover functions: _pb_initializers_ and _pb_crossovers_, respectively. In the _for_ loop, these are appended to the problem-specific dictionary of the algorithm's parameters (_pars_). Once the set of algorithmic parameters is defined, the _GeneticAlgorithm_ constructor is provided the necessary parameters' dictionary, and the search is executed for a given number of iterations. Note that a detailed description of the crossover functions, along with the other operators, can be found in Section 4. ```
1 fromgpol.algorithms.genetic_algorithmimportGeneticAlgorithm
2 fromgpol.operators.initializersimportrnd_muniform,prn_rnd_mint,rnd_mshuffle,rhh
3 fromgpol.operators.variatorsgeometric_xo,one_point_xo,partially_mapped_xo,swap_crossover
4
5#Createsacidiometrywithproblem-specificPBinitializers
6 initializers={\"Rastrigin\":rnd_muniform,\"Knapsack01\":prn_rnd_mint(),
7\"KnapsackBounded\":prn_rnd_mint(0,max_rep1),\"TSP\":rnd_mshuffle,\"Boston\":rhh}
8#Createsacidiometrywithproblem-specificcrossovers
9<Consorvers={\"Rastrigin\":geometric_xo,\"Knapsack01\":one_point_xo,
10\"KnapsackBounded\":one_point_xo,\"TSP\":partially_mapped_xo,
11\"Boston\":swap_crossover}
12#AppliesGeneticAlgorithmon5 differentproblemstypes
13 forprob,pars.inpars.items():
14#Updatestheinitializer,andaddstheselectorandthecrossover
15 pars_i[\"initializer]=pb_initializers[prob]
16 pars_i[\"encoder\"]=prn_tournament(pressure=0.1)
17 pars_i[\"crossover\"]=pb_crossover[prob]
18#Renames'#_function'with\"mutator'and'nh_size'with'pop_size'
19 pars_i[\"mutator\"]=pars_i.pop(\"nf_function\")
20 pars_i[\"pop_size\"]=pars_i.pop(\"nh_size\")
21 print(\"Problem:{\"}.format(prob))
22 maineratic=GeneticAlgorithm(**pars_i,p_m=0.3,p_c=0.7,elitism=True,
23 reproduction=Falseif\"Boston\"inprobelseTrue)
24 maineristic.solve(n_iter)
25 print(\"Bestfitness:{:.3f}\".format(mheuristic.best_sol.fit.item()))
26 print(\"Bestsolution:\",mheuristic.best_sol.repr_,end='\
^'))
27
28>Problem:Rastrigin
29>Bestsolution'sfitness:0.0
30>Bestsolution:tensor([-9.9587e-04,-2.3533e-05])
31>Problem:Knapsack01
32>Bestsolution'sfitness:97.061
334>Bestsolution:tensor([1,1,0,0,0,1,1,1,1,0,0,1,0,1])
35
36>Problem:KnapsackBounded
37>Bestsolution'sfitness:457.866
38>Bestsolution:tensor([4,1,3,2,4,2,0,0,1,0,4,0,0,0,4,4,3])
39>Problem:TSP
39>Bestsolution'sfitness:8062.000
40>Bestsolution:tensor([3,4,11,12,6,8,1,10,5,9,2,7])
41>Problem:Boston
42>Bestsolution'sfitness:5.061
43>Bestsolution:[add,add,add,add,div,11,10,div,5,add,add,div,11,10,div,11,10,7,div,5,12,div,div,11,10,12,div,5,12]
```
Figure 17: Examples of _GeneticAlgorithm_ being used to solve various problems. ### Applying GSGP

Figure 14 shows how to use the GSGP algorithm to predict the median value of owner-occupied homes in Boston. Consider the main differences in the API's usage. First, unlike what happened when solving an instance of the _SML_ problem type, an instance of _SMLGS_ receives two tensors instead: \(X\) representing the input data and \(y\) the real-valued target. Second, to create an algorithm's instance, one must specify two additional parameters: _path_init_pop_ and _path_rts_, which represent the connection strings toward the initial and random trees' repositories, respectively. During GSGP's execution, constructed trees are stored in those folders to make individual reconstruction possible. ### Reconstructing Trees after GSGP

Figure 15 shows how to reconstruct individuals generated by means of GSGP (consult Appendix B.4 to see how these are created).