@@ -595,24 +595,6 @@ Other Methods
595
595
- ``adaptive_mutation_population_fitness() ``: Returns the average
596
596
fitness value used in the adaptive mutation to filter the solutions.
597
597
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
-
616
598
- ``summary() ``: Prints a Keras-like summary of the PyGAD lifecycle.
617
599
This helps to have an overview of the architecture. Supported in
618
600
`PyGAD
@@ -961,31 +943,6 @@ generation.
961
943
It works only after completing at least 1 generation. If no generation
962
944
is completed (at least 1), an exception is raised.
963
945
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
-
989
946
.. _plotnewsolutionrate :
990
947
991
948
``plot_new_solution_rate() ``
@@ -999,26 +956,6 @@ constructor of the ``pygad.GA`` class.
999
956
It works only after completing at least 1 generation. If no generation
1000
957
is completed (at least 1), an exception is raised.
1001
958
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
-
1022
959
.. _plotgenes :
1023
960
1024
961
``plot_genes() ``
@@ -1039,43 +976,6 @@ This is controlled by the ``graph_type`` parameter.
1039
976
It works only after completing at least 1 generation. If no generation
1040
977
is completed (at least 1), an exception is raised.
1041
978
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
-
1079
979
``save() ``
1080
980
----------
1081
981
@@ -1160,7 +1060,8 @@ optimization problem is single-objective or multi-objective.
1160
1060
- If the fitness function returns a ``list ``, ``tuple ``, or
1161
1061
``numpy.ndarray ``, then the problem is single-objective. Even if
1162
1062
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.
1164
1065
1165
1066
Using a user-defined fitness function allows the user to freely use
1166
1067
PyGAD to solve any problem by passing the appropriate fitness
@@ -1580,6 +1481,108 @@ below.
1580
1481
loaded_ga_instance = pygad.load(filename = filename)
1581
1482
loaded_ga_instance.plot_fitness()
1582
1483
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
+
1583
1586
Reproducing Images
1584
1587
------------------
1585
1588
0 commit comments