Skip to content

Commit c76e47f

Browse files
authored
Merge pull request #353 from ahmedfgad/master
Sync
2 parents 579b006 + 0246a80 commit c76e47f

3 files changed

Lines changed: 111 additions & 3 deletions

File tree

.gitignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# =============================================================================
2+
# Python Compiled Files: Machine-generated bytecode that speeds up execution.
3+
# These vary by OS and Python version, so they should never be committed.
4+
# =============================================================================
5+
# Folders containing .pyc files (e.g., views.cpython-312.pyc)
6+
# Matches .pyc (compiled), .pyo (optimized), and .pyd (Windows DLLs)
7+
# Compiled Java class files generated by Jython
8+
__pycache__/
9+
*.py[cod]
10+
*$py.class

examples/example_gene_space.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
"""
2+
PyGAD Example: Using the gene_space Parameter
3+
==============================================
4+
5+
The `gene_space` parameter controls the set of valid values that each gene
6+
can take. This example demonstrates all major forms of `gene_space`.
7+
8+
Documentation:
9+
https://pygad.readthedocs.io/en/latest/pygad_more.html#more-about-the-gene-space-parameter
10+
11+
Dependencies:
12+
pip install pygad numpy
13+
"""
14+
15+
import numpy
16+
import pygad
17+
18+
19+
def fitness_func(ga_instance, solution, solution_idx):
20+
"""Return the sum of all gene values as the fitness score."""
21+
return numpy.sum(solution)
22+
23+
24+
# ===========================================================================
25+
# 1. Single flat list or NumPy array (shared across all genes)
26+
# ===========================================================================
27+
# Every gene independently draws its value from the same list.
28+
# Using None in the list means that gene value is unconstrained (random float).
29+
30+
# gene_space = [1, 2, 3, 4, 5]
31+
# gene_space = [1, 2, None]
32+
# gene_space = numpy.array([10, 20, 30, 40, 50])
33+
34+
# ===========================================================================
35+
# 2. A range or NumPy sequence (shared across all genes)
36+
# ===========================================================================
37+
38+
# gene_space = range(1, 11) # integers 1 through 10
39+
# gene_space = numpy.arange(0.0, 1.1, 0.1) # [0.0, 0.1, ..., 1.0]
40+
# gene_space = numpy.linspace(1, 5, num=9) # 9 evenly-spaced floats in [1, 5]
41+
42+
# ===========================================================================
43+
# 3. Per-gene list (each gene has its own independent space)
44+
# ===========================================================================
45+
# When gene_space is a list with length equal to num_genes, each element
46+
# defines the space for the corresponding gene. Elements can be a list,
47+
# a NumPy array, a range, or None (unconstrained).
48+
49+
# gene_space = [range(1, 5), range(5, 11), range(10, 21)]
50+
# gene_space = [[1, 2, 3], None, range(10, 21)]
51+
# gene_space = [[1, 2, 3], numpy.linspace(5, 10, num=6), [10, 12, 14, 16, 18, 20]]
52+
53+
# ===========================================================================
54+
# 4. Dictionary – continuous range (shared across all genes)
55+
# ===========================================================================
56+
# A dict with "low" and "high" makes every gene sample from a continuous
57+
# uniform distribution. An optional "step" key discretises the range.
58+
59+
# gene_space = {"low": 0.0, "high": 10.0}
60+
# gene_space = {"low": 0.0, "high": 10.0, "step": 0.5}
61+
62+
# ===========================================================================
63+
# 5. Per-gene list of dictionaries (each gene has its own continuous range)
64+
# ===========================================================================
65+
# Each gene gets its own dict-based range. This is the most expressive form
66+
# and is useful when each gene lives in a different numerical domain.
67+
68+
gene_space = [
69+
[1, 2, 3, 4, 5], # gene 0
70+
{"low": 5, "high": 10}, # gene 1
71+
range(10, 15), # gene 2
72+
None, # gene 3
73+
]
74+
75+
ga_instance = pygad.GA(
76+
num_generations=50,
77+
num_parents_mating=4,
78+
sol_per_pop=8,
79+
num_genes=4,
80+
fitness_func=fitness_func,
81+
gene_space=gene_space,
82+
)
83+
84+
ga_instance.run()
85+
86+
best_solution, best_fitness, _ = ga_instance.best_solution()
87+
print(f"Best solution : {best_solution}")
88+
print(f"Best fitness : {best_fitness:.4f}")

pygad/visualize/plot.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -322,9 +322,19 @@ def plot_genes(self,
322322

323323
# Create an axes instance
324324
ax = fig.add_subplot(111)
325-
boxeplots = ax.boxplot(solutions_to_plot,
326-
labels=range(self.num_genes),
327-
patch_artist=True)
325+
# Matplotlib 3.9 renamed the boxplot `labels=` kwarg to
326+
# `tick_labels=` and will drop the old name in 3.11. Use whichever
327+
# name this matplotlib supports so we work on either side of the
328+
# rename without forcing users to upgrade matplotlib.
329+
import inspect
330+
_tick_kw = (
331+
"tick_labels"
332+
if "tick_labels" in inspect.signature(ax.boxplot).parameters
333+
else "labels"
334+
)
335+
boxeplots = ax.boxplot(solutions_to_plot,
336+
patch_artist=True,
337+
**{_tick_kw: range(self.num_genes)})
328338
# adding horizontal grid lines
329339
ax.yaxis.grid(True)
330340

0 commit comments

Comments
 (0)