@@ -595,24 +595,6 @@ Other Methods
595595- ``adaptive_mutation_population_fitness() ``: Returns the average
596596 fitness value used in the adaptive mutation to filter the solutions.
597597
598- - ``solve_duplicate_genes_randomly() ``: Solves the duplicates in a
599- solution by randomly selecting new values for the duplicating genes.
600-
601- - ``solve_duplicate_genes_by_space() ``: Solves the duplicates in a
602- solution by selecting values for the duplicating genes from the gene
603- space
604-
605- - ``unique_int_gene_from_range() ``: Finds a unique integer value for
606- the gene.
607-
608- - ``unique_genes_by_space() ``: Loops through all the duplicating genes
609- to find unique values that from their gene spaces to solve the
610- duplicates. For each duplicating gene, a call to the
611- ``unique_gene_by_space() `` is made.
612-
613- - ``unique_gene_by_space() ``: Returns a unique gene value for a single
614- gene based on its value space to solve the duplicates.
615-
616598- ``summary() ``: Prints a Keras-like summary of the PyGAD lifecycle.
617599 This helps to have an overview of the architecture. Supported in
618600 `PyGAD
@@ -961,31 +943,6 @@ generation.
961943It works only after completing at least 1 generation. If no generation
962944is completed (at least 1), an exception is raised.
963945
964- This method accepts the following parameters:
965-
966- 1. ``title ``: Title of the figure.
967-
968- 2. ``xlabel ``: X-axis label.
969-
970- 3. ``ylabel ``: Y-axis label.
971-
972- 4. ``linewidth ``: Line width of the plot. Defaults to ``3 ``.
973-
974- 5. ``font_size ``: Font size for the labels and title. Defaults to
975- ``14 ``.
976-
977- 6. ``plot_type ``: Type of the plot which can be either ``"plot" ``
978- (default), ``"scatter" ``, or ``"bar" ``.
979-
980- 7. ``color ``: Color of the plot which defaults to the greenish color
981- ``"#64f20c" ``.
982-
983- 8. ``label ``: The label used for the legend in the figures of
984- multi-objective problems. It is not used for single-objective
985- problems. It defaults to ``None `` which means no labels used.
986-
987- 9. ``save_dir ``: Directory to save the figure.
988-
989946.. _plotnewsolutionrate :
990947
991948``plot_new_solution_rate() ``
@@ -999,26 +956,6 @@ constructor of the ``pygad.GA`` class.
999956It works only after completing at least 1 generation. If no generation
1000957is completed (at least 1), an exception is raised.
1001958
1002- This method accepts the following parameters:
1003-
1004- 1. ``title ``: Title of the figure.
1005-
1006- 2. ``xlabel ``: X-axis label.
1007-
1008- 3. ``ylabel ``: Y-axis label.
1009-
1010- 4. ``linewidth ``: Line width of the plot. Defaults to ``3 ``.
1011-
1012- 5. ``font_size ``: Font size for the labels and title. Defaults to
1013- ``14 ``.
1014-
1015- 6. ``plot_type ``: Type of the plot which can be either ``"plot" ``
1016- (default), ``"scatter" ``, or ``"bar" ``.
1017-
1018- 7. ``color ``: Color of the plot which defaults to ``"#3870FF" ``.
1019-
1020- 8. ``save_dir ``: Directory to save the figure.
1021-
1022959.. _plotgenes :
1023960
1024961``plot_genes() ``
@@ -1039,43 +976,6 @@ This is controlled by the ``graph_type`` parameter.
1039976It works only after completing at least 1 generation. If no generation
1040977is completed (at least 1), an exception is raised.
1041978
1042- This method accepts the following parameters:
1043-
1044- 1. ``title ``: Title of the figure.
1045-
1046- 2. ``xlabel ``: X-axis label.
1047-
1048- 3. ``ylabel ``: Y-axis label.
1049-
1050- 4. ``linewidth ``: Line width of the plot. Defaults to ``3 ``.
1051-
1052- 5. ``font_size ``: Font size for the labels and title. Defaults to
1053- ``14 ``.
1054-
1055- 6. ``plot_type ``: Type of the plot which can be either ``"plot" ``
1056- (default), ``"scatter" ``, or ``"bar" ``.
1057-
1058- 7. ``graph_type ``: Type of the graph which can be either ``"plot" ``
1059- (default), ``"boxplot" ``, or ``"histogram" ``.
1060-
1061- 8. ``fill_color ``: Fill color of the graph which defaults to
1062- ``"#3870FF" ``. This has no effect if ``graph_type="plot" ``.
1063-
1064- 9. ``color ``: Color of the plot which defaults to ``"#3870FF" ``.
1065-
1066- 10. ``solutions ``: Defaults to ``"all" `` which means use all solutions.
1067- If ``"best" `` then only the best solutions are used.
1068-
1069- 11. ``save_dir ``: Directory to save the figure.
1070-
1071- An exception is raised if:
1072-
1073- - ``solutions="all" `` while ``save_solutions=False `` in the constructor
1074- of the ``pygad.GA `` class. .
1075-
1076- - ``solutions="best" `` while ``save_best_solutions=False `` in the
1077- constructor of the ``pygad.GA `` class. .
1078-
1079979``save() ``
1080980----------
1081981
@@ -1160,7 +1060,8 @@ optimization problem is single-objective or multi-objective.
11601060- If the fitness function returns a ``list ``, ``tuple ``, or
11611061 ``numpy.ndarray ``, then the problem is single-objective. Even if
11621062 there is only one element, the problem is still considered
1163- multi-objective.
1063+ multi-objective. Each element represents the fitness value of its
1064+ corresponding objective.
11641065
11651066Using a user-defined fitness function allows the user to freely use
11661067PyGAD to solve any problem by passing the appropriate fitness
@@ -1580,6 +1481,108 @@ below.
15801481 loaded_ga_instance = pygad.load(filename = filename)
15811482 loaded_ga_instance.plot_fitness()
15821483
1484+ Linear Model Optimization - Multi-Objective
1485+ -------------------------------------------
1486+
1487+ This is a multi-objective optimization example that optimizes these 2
1488+ functions:
1489+
1490+ 1. ``y1 = f(w1:w6) = w1x1 + w2x2 + w3x3 + w4x4 + w5x5 + 6wx6 ``
1491+
1492+ 2. ``y2 = f(w1:w6) = w1x7 + w2x8 + w3x9 + w4x10 + w5x11 + 6wx12 ``
1493+
1494+ Where:
1495+
1496+ 1. ``(x1,x2,x3,x4,x5,x6)=(4,-2,3.5,5,-11,-4.7) `` and ``y=50 ``
1497+
1498+ 2. ``(x7,x8,x9,x10,x11,x12)=(-2,0.7,-9,1.4,3,5) `` and ``y=30 ``
1499+
1500+ The 2 functions use the same parameters (weights) ``w1 `` to ``w6 ``.
1501+
1502+ The goal is to use PyGAD to find the optimal values for such weights
1503+ that satisfy the 2 functions ``y1 `` and ``y2 ``.
1504+
1505+ To use PyGAD to solve multi-objective problems, the only adjustment is
1506+ to return a ``list ``, ``tuple ``, or ``numpy.ndarray `` from the fitness
1507+ function. Each element represents the fitness of an objective in order.
1508+ That is the first element is the fitness of the first objective, the
1509+ second element is the fitness for the second objective, and so on.
1510+
1511+ .. code :: python
1512+
1513+ import pygad
1514+ import numpy
1515+
1516+ """
1517+ Given these 2 functions:
1518+ y1 = f(w1:w6) = w1x1 + w2x2 + w3x3 + w4x4 + w5x5 + 6wx6
1519+ y2 = f(w1:w6) = w1x7 + w2x8 + w3x9 + w4x10 + w5x11 + 6wx12
1520+ where (x1,x2,x3,x4,x5,x6)=(4,-2,3.5,5,-11,-4.7) and y=50
1521+ and (x7,x8,x9,x10,x11,x12)=(-2,0.7,-9,1.4,3,5) and y=30
1522+ What are the best values for the 6 weights (w1 to w6)? We are going to use the genetic algorithm to optimize these 2 functions.
1523+ This is a multi-objective optimization problem.
1524+
1525+ PyGAD considers the problem as multi-objective if the fitness function returns:
1526+ 1) List.
1527+ 2) Or tuple.
1528+ 3) Or numpy.ndarray.
1529+ """
1530+
1531+ function_inputs1 = [4 ,- 2 ,3.5 ,5 ,- 11 ,- 4.7 ] # Function 1 inputs.
1532+ function_inputs2 = [- 2 ,0.7 ,- 9 ,1.4 ,3 ,5 ] # Function 2 inputs.
1533+ desired_output1 = 50 # Function 1 output.
1534+ desired_output2 = 30 # Function 2 output.
1535+
1536+ def fitness_func (ga_instance , solution , solution_idx ):
1537+ output1 = numpy.sum(solution* function_inputs1)
1538+ output2 = numpy.sum(solution* function_inputs2)
1539+ fitness1 = 1.0 / (numpy.abs(output1 - desired_output1) + 0.000001 )
1540+ fitness2 = 1.0 / (numpy.abs(output2 - desired_output2) + 0.000001 )
1541+ return [fitness1, fitness2]
1542+
1543+ num_generations = 100
1544+ num_parents_mating = 10
1545+
1546+ sol_per_pop = 20
1547+ num_genes = len (function_inputs1)
1548+
1549+ ga_instance = pygad.GA(num_generations = num_generations,
1550+ num_parents_mating = num_parents_mating,
1551+ sol_per_pop = sol_per_pop,
1552+ num_genes = num_genes,
1553+ fitness_func = fitness_func,
1554+ parent_selection_type = ' nsga2' )
1555+
1556+ ga_instance.run()
1557+
1558+ ga_instance.plot_fitness(label = [' Obj 1' , ' Obj 2' ])
1559+
1560+ solution, solution_fitness, solution_idx = ga_instance.best_solution(ga_instance.last_generation_fitness)
1561+ print (f " Parameters of the best solution : { solution} " )
1562+ print (f " Fitness value of the best solution = { solution_fitness} " )
1563+
1564+ prediction = numpy.sum(numpy.array(function_inputs1)* solution)
1565+ print (f " Predicted output 1 based on the best solution : { prediction} " )
1566+ prediction = numpy.sum(numpy.array(function_inputs2)* solution)
1567+ print (f " Predicted output 2 based on the best solution : { prediction} " )
1568+
1569+ This is the result of the print statements. The predicted outputs are
1570+ close to the desired outputs.
1571+
1572+ .. code ::
1573+
1574+ Parameters of the best solution : [ 0.79676439 -2.98823386 -4.12677662 5.70539445 -2.02797016 -1.07243922]
1575+ Fitness value of the best solution = [ 1.68090829 349.8591915 ]
1576+ Predicted output 1 based on the best solution : 50.59491545442283
1577+ Predicted output 2 based on the best solution : 29.99714270722312
1578+
1579+ This is the figure created by the ``plot_fitness() `` method. The fitness
1580+ of the first objective has the green color. The blue color is used for
1581+ the second objective fitness.
1582+
1583+ .. image :: https://github.com/ahmedfgad/GeneticAlgorithmPython/assets/16560492/7896f8d8-01c5-4ff9-8d15-52191c309b63
1584+ :alt:
1585+
15831586Reproducing Images
15841587------------------
15851588
0 commit comments