From 8b245e69e8dde6cafb7e9e103e4e5af901150867 Mon Sep 17 00:00:00 2001 From: Ahmed Gad Date: Mon, 7 Jul 2025 13:15:03 -0400 Subject: [PATCH 01/10] Accept gene values in gene_constraint callables --- README.md | 2 +- .DS_Store => docs/.DS_Store | Bin 8196 -> 6148 bytes examples/example_gene_constraint.py | 37 +++++++++++++++ pygad/helper/misc.py | 42 ++++++++++++------ pygad/helper/unique.py | 4 +- pygad/pygad.py | 21 ++++++--- .../__pycache__/__init__.cpython-310.pyc | Bin 237 -> 0 bytes .../__pycache__/plot.cpython-310.pyc | Bin 13830 -> 0 bytes 8 files changed, 84 insertions(+), 22 deletions(-) rename .DS_Store => docs/.DS_Store (64%) create mode 100644 examples/example_gene_constraint.py delete mode 100644 pygad/visualize/__pycache__/__init__.cpython-310.pyc delete mode 100644 pygad/visualize/__pycache__/plot.cpython-310.pyc diff --git a/README.md b/README.md index 08bd7e4..deff145 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Check documentation of the [PyGAD](https://pygad.readthedocs.io/en/latest). [![PyPI Downloads](https://pepy.tech/badge/pygad)](https://pepy.tech/project/pygad) [![Conda Downloads](https://img.shields.io/conda/dn/conda-forge/pygad.svg?label=Conda%20Downloads)]( -https://anaconda.org/conda-forge/PyGAD) [![PyPI version](https://badge.fury.io/py/pygad.svg)](https://badge.fury.io/py/pygad) ![Docs](https://readthedocs.org/projects/pygad/badge) [![PyGAD PyTest / Python 3.11](https://github.com/ahmedfgad/GeneticAlgorithmPython/actions/workflows/main_py311.yml/badge.svg)](https://github.com/ahmedfgad/GeneticAlgorithmPython/actions/workflows/main_py311.yml) [![PyGAD PyTest / Python 3.10](https://github.com/ahmedfgad/GeneticAlgorithmPython/actions/workflows/main_py310.yml/badge.svg)](https://github.com/ahmedfgad/GeneticAlgorithmPython/actions/workflows/main_py310.yml) [![PyGAD PyTest / Python 3.9](https://github.com/ahmedfgad/GeneticAlgorithmPython/actions/workflows/main_py39.yml/badge.svg)](https://github.com/ahmedfgad/GeneticAlgorithmPython/actions/workflows/main_py39.yml) [![PyGAD PyTest / Python 3.8](https://github.com/ahmedfgad/GeneticAlgorithmPython/actions/workflows/main_py38.yml/badge.svg)](https://github.com/ahmedfgad/GeneticAlgorithmPython/actions/workflows/main_py38.yml) [![PyGAD PyTest / Python 3.7](https://github.com/ahmedfgad/GeneticAlgorithmPython/actions/workflows/main_py37.yml/badge.svg)](https://github.com/ahmedfgad/GeneticAlgorithmPython/actions/workflows/main_py37.yml) [![License](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) [![Translation](https://hosted.weblate.org/widgets/weblate/-/svg-badge.svg)](https://hosted.weblate.org/engage/weblate/) [![REUSE](https://api.reuse.software/badge/github.com/WeblateOrg/weblate)](https://api.reuse.software/info/github.com/WeblateOrg/weblate) [![Stack Overflow](https://img.shields.io/badge/stackoverflow-Ask%20questions-blue.svg)]( +https://anaconda.org/conda-forge/PyGAD) [![PyPI version](https://badge.fury.io/py/pygad.svg)](https://badge.fury.io/py/pygad)![Docs](https://readthedocs.org/projects/pygad/badge)[![PyGAD PyTest / Python 3.13](https://github.com/ahmedfgad/GeneticAlgorithmPython/actions/workflows/main_py313.yml/badge.svg)](https://github.com/ahmedfgad/GeneticAlgorithmPython/actions/workflows/main_py313.yml) [![PyGAD PyTest / Python 3.12](https://github.com/ahmedfgad/GeneticAlgorithmPython/actions/workflows/main_py312.yml/badge.svg)](https://github.com/ahmedfgad/GeneticAlgorithmPython/actions/workflows/main_py312.yml) [![PyGAD PyTest / Python 3.11](https://github.com/ahmedfgad/GeneticAlgorithmPython/actions/workflows/main_py311.yml/badge.svg)](https://github.com/ahmedfgad/GeneticAlgorithmPython/actions/workflows/main_py311.yml) [![PyGAD PyTest / Python 3.10](https://github.com/ahmedfgad/GeneticAlgorithmPython/actions/workflows/main_py310.yml/badge.svg)](https://github.com/ahmedfgad/GeneticAlgorithmPython/actions/workflows/main_py310.yml) [![PyGAD PyTest / Python 3.9](https://github.com/ahmedfgad/GeneticAlgorithmPython/actions/workflows/main_py39.yml/badge.svg)](https://github.com/ahmedfgad/GeneticAlgorithmPython/actions/workflows/main_py39.yml) [![PyGAD PyTest / Python 3.8](https://github.com/ahmedfgad/GeneticAlgorithmPython/actions/workflows/main_py38.yml/badge.svg)](https://github.com/ahmedfgad/GeneticAlgorithmPython/actions/workflows/main_py38.yml) [![License](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) [![Translation](https://hosted.weblate.org/widgets/weblate/-/svg-badge.svg)](https://hosted.weblate.org/engage/weblate/) [![REUSE](https://api.reuse.software/badge/github.com/WeblateOrg/weblate)](https://api.reuse.software/info/github.com/WeblateOrg/weblate) [![Stack Overflow](https://img.shields.io/badge/stackoverflow-Ask%20questions-blue.svg)]( https://stackoverflow.com/questions/tagged/pygad) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/ahmedfgad/GeneticAlgorithmPython/badge)](https://securityscorecards.dev/viewer/?uri=github.com/ahmedfgad/GeneticAlgorithmPython) [![DOI](https://zenodo.org/badge/DOI/10.1007/s11042-023-17167-y.svg)](https://doi.org/10.1007/s11042-023-17167-y) ![PYGAD-LOGO](https://user-images.githubusercontent.com/16560492/101267295-c74c0180-375f-11eb-9ad0-f8e37bd796ce.png) diff --git a/.DS_Store b/docs/.DS_Store similarity index 64% rename from .DS_Store rename to docs/.DS_Store index ab7c2436eb413e1c9453b4c7975a553eb520ecd3..a8f1c983bebbd362b8a138670780f77cd57696dd 100644 GIT binary patch delta 287 zcmZp1XfcprU|?W$DortDU=RQ@Ie-{MGjUEV6q~50D9Q?w2aD-3Brzm1lz8UkCvPlV z&Ip#_V8{iEWizBQKxHS(2*_u0F!(}6(-<-tau`xUdXjSTlc0uQ2GZ95!2rl&U|?e? zX2@qKWhi1uMpw%iiBIk1w}QtcQFNCD7v<&T=cNO6F>WkuU|G!0!6C>DvIOV{ZXn?b g^4rG3@640=WgJ1C2lK?u}x^Rb=@=+Ra(i{lBN|%sd~V55}`mLQEXC&wwSd&ahI-V%EJLX&JB#{4W_$=Yxx^WF?U!BlXdNLWcm5(`eQSI^qCr<0i6_$dQrS6l0p` zfhDFa2{D*4N58A!kd;J^j5OxNj5)DnW|l-KOwSHGSHp=_jI^a?z%p=}0TsK?(kdNN zOiwfMyV^?cBj5W|Cv7}U9iZA2rQ&>r`#FQl6Q=|6s7HMYpl9%G_n+{sVbo8)BYfZL z2YwVUFaOG>E=+H3wlC+sR<#LoJe%h)KAKiZ1$;U5*~m2Iya>52!}#lccieK%~i^ z0hx!?1+AS)?=&gH~6@`YFCUcGo}-nm@7QYv08E-aK5 zt}QOScK!A1P3KC>Yd`CTYSmX|Aj4`f;E%eY->LPzwlBJkm>{S@JCs4NB_lufrPzHO!F@Mk-rEp+ z5|i)4bvOH}E85{<1le>lHjP~`3_a21)x#%&*W$sZsLD8&y@ubG!o0-19v0QDkgFlf zZ~qQQK`K|?8!Jmjaj0w*IBjXHC6d*J6ueNb?3jiE{Q3=e?Ity_!M~ud=^Of%zM~)L z7y6C?AYW@e)C6XW z^qdD2PtK^1w6uL5NDlk}Pram`JcC!eJB^=98], + lambda x, v: [val for val in v if val>=98], + lambda x, v: [val for val in v if 80 0: + if len(filtered_values) > 0: # At least one value was found that meets the gene constraint. pass else: # No value found for the current gene that satisfies the constraint. - if not self.suppress_warnings: - warnings.warn(f"No value found for the gene at index {gene_idx} with value {solution[gene_idx]} that satisfies its gene constraint.") + if not self.suppress_warnings: warnings.warn(f"Failed to find a value that satisfies its gene constraint for the gene at index {gene_idx} with value {solution[gene_idx]} at generation {self.generations_completed}.") return None - filtered_values = values[filtered_values_indices] - return filtered_values def get_gene_dtype(self, gene_index): diff --git a/pygad/helper/unique.py b/pygad/helper/unique.py index 60b2507..ec79d9c 100644 --- a/pygad/helper/unique.py +++ b/pygad/helper/unique.py @@ -69,7 +69,7 @@ def solve_duplicate_genes_randomly(self, if temp_val in new_solution: num_unsolved_duplicates = num_unsolved_duplicates + 1 - if not self.suppress_warnings: warnings.warn(f"Failed to find a unique value for gene with index {duplicate_index} whose value is {solution[duplicate_index]}. Consider adding more values in the gene space or use a wider range for initial population or random mutation.") + if not self.suppress_warnings: warnings.warn(f"Failed to find a unique value for gene with index {duplicate_index} whose value is {solution[duplicate_index]} at generation {self.generations_completed}. Consider adding more values in the gene space or use a wider range for initial population or random mutation.") else: # Unique gene value found. new_solution[duplicate_index] = temp_val @@ -320,7 +320,7 @@ def unique_genes_by_space(self, if temp_val in solution: num_unsolved_duplicates = num_unsolved_duplicates + 1 - if not self.suppress_warnings: warnings.warn(f"Failed to find a unique value for gene with index {duplicate_index} whose value is {solution[duplicate_index]}. Consider adding more values in the gene space or use a wider range for initial population or random mutation.") + if not self.suppress_warnings: warnings.warn(f"Failed to find a unique value for gene with index {duplicate_index} whose value is {solution[duplicate_index]} at generation {self.generations_completed+1}. Consider adding more values in the gene space or use a wider range for initial population or random mutation.") else: solution[duplicate_index] = temp_val diff --git a/pygad/pygad.py b/pygad/pygad.py index 0ed9d82..c709c57 100644 --- a/pygad/pygad.py +++ b/pygad/pygad.py @@ -545,13 +545,13 @@ def __init__(self, if item is None: pass elif item and callable(item): - if item.__code__.co_argcount == 1: - # Every callable is valid if it receives a single argument. - # This argument represents the solution. + if item.__code__.co_argcount == 2: + # Every callable is valid if it receives 2 arguments. + # The 2 arguments: 1) solution 2) A list or numpy.ndarray of values to check if they meet the constraint. pass else: self.valid_parameters = False - raise ValueError(f"Every callable inside the gene_constraint parameter must accept a single argument representing the solution/chromosome. But the callable at index {constraint_idx} named '{item.__code__.co_name}' accepts {item.__code__.co_argcount} argument(s).") + raise ValueError(f"Every callable inside the gene_constraint parameter must accept 2 arguments representing 1) The solution/chromosome where the gene exists 2) A list of NumPy array of values to check if they meet the constraint. But the callable at index {constraint_idx} named '{item.__code__.co_name}' accepts {item.__code__.co_argcount} argument(s).") else: self.valid_parameters = False raise TypeError(f"The expected type of an element in the 'gene_constraint' parameter is None or a callable (e.g. function). But {item} at index {constraint_idx} of type {type(item)} found.") @@ -1424,7 +1424,18 @@ def initialize_population(self, for gene_idx in range(self.num_genes): # Check that a constraint is available for the gene and that the current value does not satisfy that constraint if self.gene_constraint[gene_idx]: - if not self.gene_constraint[gene_idx](solution): + # Remember that the second argument to the gene constraint callable is a list/numpy.ndarray of the values to check if they meet the gene constraint. + values = [solution[gene_idx]] + filtered_values = self.gene_constraint[gene_idx](solution, values) + result = self.validate_gene_constraint_callable_output(selected_values=filtered_values, + values=values) + if result: + pass + else: + raise Exception("The output from the gene_constraint callable/function must be a list or NumPy array that is subset of the passed values (second argument).") + + # Check if the gene value satisfies the gene constraint. + if len(filtered_values) == 1 and filtered_values[0] == solution[gene_idx]: range_min, range_max = self.get_initial_population_range(gene_index=gene_idx) # While initializing the population, we follow a mutation by replacement approach. So, the original gene value is not needed. values_filtered = self.get_valid_gene_constraint_values(range_min=range_min, diff --git a/pygad/visualize/__pycache__/__init__.cpython-310.pyc b/pygad/visualize/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 473b3f831e39a308d92cef5e00424e43e5c2b1cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 237 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 m)~eND+nysX=wjf-qj>by=Yx^Hh@~Sqbkrz From 079475f4853b73c770cc145e356674802bd1d108 Mon Sep 17 00:00:00 2001 From: Ahmed Gad Date: Mon, 7 Jul 2025 13:17:18 -0400 Subject: [PATCH 02/10] Delete docs/.DS_Store --- docs/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 docs/.DS_Store diff --git a/docs/.DS_Store b/docs/.DS_Store deleted file mode 100644 index a8f1c983bebbd362b8a138670780f77cd57696dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK!A{#i5S>JO%+10+ayj~(w-C=)+s7*v3oU!4f`Gs*m`&E?_+~!$XbvpN|vD92%X|?>;YU@+@ZbFK4a8pp}oEFJaQ>qok%;;cvqrXcI5pnQCn6@5MG>S56@O>Ja5eBbkX?alFc z=U{g`*nd6Q4#o$&9fW)PlZo$bY`r=>>s{wJh5pKV;O)ojZ*0xs6uu#tS^ix#C~{qV zMt)i|@H7RP680Kb5t<8 From f5ecabbb76bbc73c4f3e63db3ed2641da7fc43a7 Mon Sep 17 00:00:00 2001 From: Ahmed Gad Date: Mon, 7 Jul 2025 13:48:03 -0400 Subject: [PATCH 03/10] Edit gene_constraint callables --- .DS_Store | Bin 0 -> 8196 bytes examples/example_gene_constraint.py | 8 +-- pygad/.DS_Store | Bin 0 -> 10244 bytes pygad/helper/.DS_Store | Bin 0 -> 6148 bytes pygad/pygad.py | 17 ++++++- pygad/utils/.DS_Store | Bin 0 -> 6148 bytes pygad/visualize/.DS_Store | Bin 0 -> 6148 bytes tests/test_gene_constraint.py | 73 +++++++++++++++++++++++++--- 8 files changed, 86 insertions(+), 12 deletions(-) create mode 100644 .DS_Store create mode 100644 pygad/.DS_Store create mode 100644 pygad/helper/.DS_Store create mode 100644 pygad/utils/.DS_Store create mode 100644 pygad/visualize/.DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..2f034958172052b7a3bef5fd41e0e5c179f3d3b1 GIT binary patch literal 8196 zcmeHML2nyH6n-yFVsAs6ZR(_fMUqJN00Q`yFPaTsG{(@T!!TeNFbo(53b#F-|d1o71=>;Ur739B8S{0kt_`yfVfa3aZt~&QWl{l9r}53>XH+8IZaAEUd#Z zMDQe&ze`v8nCjiXRZ+&%&>~b5!bF}galcN&HTq#U{ypHwM%VYkXm#~>oH{o>Gn>m< zxw+iq$`jGAL~hgz%Wm*cK2?SA8$;b~?0KwTw+rinN3O?NpbWegBgmr%9&d?$S@d`- zRJIj8U|D&qZeKY$xq0W-b!YAN>2>Gi&aG8a-&;F9wepL_8+Ui>&-@M-U#pD)#*qas z=;u-U4QZooA65eH3*M$aiO&OrBXFSuUGPcI(1QDfNzyllKO6LnZ7V}l4(`Jiow7~% z1S+tZK0Ej_L(&Y9c?@l$wUtIrvB}7@L1bdvFqfm^K)-qxHxZL zTDV+TSX@|IDlA=DUV8iLJ6G%W<%ZjQ)()gotP5WRWxvNBwgazK>AFpiw`&nQiYnf7 zR<{>2&|TL0{8d-=xJ#JAs}42Y2LWST&9{AU5VEM2(Dy%ckE)~D=fh?oe1AuTUgQbB z|0pEy-ilafiysJD{E$3*yDNvnJr;x{>vqPbw(kak%iFAc{MdIJ%-`l^5k;a?^O}O| zP0Xul>2W7ua?0ZSf6_srQY?KmR93WNLs2W_yM>_^ORRFinN=+9=?;tB`&~M<+fXA1 ze*xdZckn&@06)QR@CW>bvsl1ucmvn)9)5`T@l)KxHu~7XLp{ONFr-{duY`SiPJHT& zw_H@`zY76H+NTs$niQK?s0w-uKkX4JKL4DE&lc>Gm)(O68rdYPPS%H1q)u9#Pg#8R zIvW|ru%1}OrgvlTCG@~kT8ExEybVcqqgO?E@iJu`X z1y{L38mS_}1mszX2&1iMj)@IbB2XTSfIfpu_m2ZR$wQN-N*e{=Hh z{~Bdl!+>GnOfrDe8=98], - lambda x, v: [val for val in v if val>=98], - lambda x, v: [val for val in v if 80=98], + lambda x,v: [val for val in v if val>=98], + lambda x,v: [val for val in v if 80sgusdb#Rm^N z$&QgrEje`Hz$pOA8ZL9gIpzUu;~Cj8a;YVo;xl#jpp2<9DTdPKc;6#+lpQ0NT55Ap z+8mVmW@R!I#ovy09;<`uXepx*5CZE2D0gpi&K^Nh$lott#_1r4(*QN-P`$!_{FfWf z0ID!Ri^S6UwOK2eWh3*fAHgV&vPrxBTUDyH`i|qcPSg3+J4`}6t!(ZQZ~ z_-wJ~&5sV+IDLA!Sh$Vdhfj`Q_s`=mN&1bQ0%hV0+|}2s@jK3p%NMdgTDJa>v5417{FIjAgM9#>FF32`wZA z-Ev?lxMZPm;GCe~5z1)K6yb2x`I(D4mUcPtSWa1hDqF&A9t-P~0|vWdA!y*ix#Wm4 zkLTz+<z~y+9T#m;JD#t&9Y;&&=fJp=tk7uPlNd}UE zWFQ$x27aCa+}V`j$T8bwAQ?yoJ{jQoP@u#b*c|QXKw~8UZ~(UnY(AEmQvz#Xb3_kB zJr(Gw8YPB$I{YQ#YG8BpbkQh2G-m!NUespC_{G9St7EpwKr*n;0Bc{!nD_q$KAGMk z-$JrU29kmQ%76~0*V74h7kBHoee$j?&^suFag7E9_TD1^e|V0ZSf}?F+K8)x&5@(f RZ|T5%2pA#RBm=*|z&j>5H7WoA literal 0 HcmV?d00001 diff --git a/pygad/pygad.py b/pygad/pygad.py index c709c57..3661dab 100644 --- a/pygad/pygad.py +++ b/pygad/pygad.py @@ -1434,8 +1434,15 @@ def initialize_population(self, else: raise Exception("The output from the gene_constraint callable/function must be a list or NumPy array that is subset of the passed values (second argument).") - # Check if the gene value satisfies the gene constraint. - if len(filtered_values) == 1 and filtered_values[0] == solution[gene_idx]: + if len(filtered_values) ==1 and filtered_values[0] != solution[gene_idx]: + # Error by the user's defined gene constraint callable. + raise Exception(f"It is expected to receive a list/numpy.ndarray from the gene_constraint callable with a single value equal to {values[0]}, but the value {filtered_values[0]} found.") + + # Check if the gene value does not satisfy the gene constraint. + # Note that we already passed a list of a single value. + # It is expected to receive a list of either a single value or an empty list. + if len(filtered_values) < 1: + # Search for a value that satisfies the gene constraint. range_min, range_max = self.get_initial_population_range(gene_index=gene_idx) # While initializing the population, we follow a mutation by replacement approach. So, the original gene value is not needed. values_filtered = self.get_valid_gene_constraint_values(range_min=range_min, @@ -1450,6 +1457,12 @@ def initialize_population(self, warnings.warn(f"No value satisfied the constraint for the gene at index {gene_idx} with value {solution[gene_idx]} while creating the initial population.") else: self.population[sol_idx, gene_idx] = random.choice(values_filtered) + elif len(filtered_values) == 1: + # The value already satisfied the gene constraint. + pass + else: + # Error by the user's defined gene constraint callable. + raise Exception(f"It is expected to receive a list/numpy.ndarray from the gene_constraint callable that is either empty or has a single value equal, but received a list/numpy.ndarray of length {len(filtered_values)}.") # 4) Solve duplicate genes. if allow_duplicate_genes == False: diff --git a/pygad/utils/.DS_Store b/pygad/utils/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..a364f0c0bd6445a262c5f5901cffdae298ec52af GIT binary patch literal 6148 zcmeHKu};G<5Pc3s3JOCd7Dj&o609syRR#toCMIY@gd&9o5sJi?f8+!B6nN*eDw+gF zgsQvf{Orp;J9)O^7=W9t?@xg#fRrwn9IzNMxi3DjBu4g$F7#311-HCT@HEJ_z<*Rg z<}M3!R$+zj^Y?aHH^s7UmdudlaYaA>48|I8hyu@O(DG{Vijpmv_df5v$II}DHP^|4 zUXi&PW4W6iD`j4b2eQsa^FMm|M|_e6pQt2H)?~|CO)q{MH7R?&uxVxrm;$E24l2Ms zTP)2KtuzHp0aIY3fP5c3T`-T>DTYr6i*N)WP8bfxy8J8($4AT~c8a`1b4n#D)x{%* zQ##{5=H(GPMWw^V!-tC_yLduzVRZKILpofpXr(D&3T!K|r_HJC{}(@>|F=ojG6hV5 zol?L}=GXHXUn%abgO`)N*3<9kVv^S>ZYZpTt(dv86(7@sG47>8%p-P+jL_^yAjn{a JDe$KXd;wTAS1$kn literal 0 HcmV?d00001 diff --git a/pygad/visualize/.DS_Store b/pygad/visualize/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..d6d23e9a0eb73b7451abf68d89614969ed97732f GIT binary patch literal 6148 zcmeHKF-`+P474Err&K)!M}G6zxW8l$m|3?dfTBRyB$>f?Ll==6r_L@kOERb3P=I&*|hm0QBev= z0V(jU0KX3nPV5SY#Q1a|@c7R48Igu@+$Dgm=3U{Ch!vP86_`}7D~2Z>`BrsZ;gFbg z^XQD{RA;Xnibr?kTa=r3iHcG{3XByv&gqi-|0VpF`~R4vnG}!$|4IR$t#8&Vyi)D0 wlb7RO+u--`FGFpVBa99Km~bmT-K%RHqpm9)5`&I>(1AJ#P#2jL_zML-0WRSuwg3PC literal 0 HcmV?d00001 diff --git a/tests/test_gene_constraint.py b/tests/test_gene_constraint.py index 43cf38a..7b6912e 100644 --- a/tests/test_gene_constraint.py +++ b/tests/test_gene_constraint.py @@ -69,7 +69,11 @@ def fitness_func_no_batch_multi(ga, solution, idx): #### Single-Objective def test_initial_population_int_by_replacement(): - gene_constraint=[lambda x: x[0]>=8,lambda x: x[1]>=8,lambda x: 5>=x[2]>=1,lambda x: 5>x[3]>3,lambda x: x[4]<2] + gene_constraint=[lambda x,v: [val for val in v if val>=8], + lambda x,v: [val for val in v if val>=8], + lambda x,v: [val for val in v if 5>=val>=1], + lambda x,v: [val for val in v if 5>val>3], + lambda x,v: [val for val in v if val<2]] ga_instance = population_gene_constraint(gene_constraint=gene_constraint, init_range_low=0, init_range_high=10, @@ -79,7 +83,6 @@ def test_initial_population_int_by_replacement(): gene_type=int, mutation_by_replacement=True) initial_population = ga_instance.initial_population - # print(initial_population) assert numpy.all(initial_population[:, 0] >= 8), "Not all values in column 0 are >= 8" assert numpy.all(initial_population[:, 1] >= 8), "Not all values in column 1 are >= 8" @@ -87,9 +90,14 @@ def test_initial_population_int_by_replacement(): assert numpy.all((initial_population[:, 2] >= 1) & (initial_population[:, 2] <= 5)), "Not all values in column 2 between 1 and 5 (inclusive)" assert numpy.all(initial_population[:, 3] == 4), "Not all values in column 3 between 3 and 5 (exclusive)" assert numpy.all(initial_population[:, 4] < 2), "Not all values in column 4 < 2" + print("All constraints are met") def test_initial_population_int_by_replacement_no_duplicates(): - gene_constraint=[lambda x: x[0]>=5,lambda x: x[1]>=5,lambda x: x[2]>=5,lambda x: x[3]>=5,lambda x: x[4]>=5] + gene_constraint=[lambda x,v: [val for val in v if val>=5], + lambda x,v: [val for val in v if val>=5], + lambda x,v: [val for val in v if val>=5], + lambda x,v: [val for val in v if val>=5], + lambda x,v: [val for val in v if val>=5]] ga_instance = population_gene_constraint(gene_constraint=gene_constraint, init_range_low=1, init_range_high=10, @@ -117,9 +125,15 @@ def test_initial_population_int_by_replacement_no_duplicates(): assert numpy.all(initial_population[:, 2] >= 5), "Not all values in column 2 >= 5" assert numpy.all(initial_population[:, 3] >= 5), "Not all values in column 3 >= 5" assert numpy.all(initial_population[:, 4] >= 5), "Not all values in column 4 >= 5" + print("All constraints are met") def test_initial_population_int_by_replacement_no_duplicates2(): - gene_constraint=[lambda x: x[0]>=98,lambda x: x[1]>=98,lambda x: 20=98], + lambda x,v: [val for val in v if val>=98], + lambda x,v: [val for val in v if 20=5,lambda x: x[1]>=5,lambda x: x[2]>=5,lambda x: x[3]>=5,lambda x: x[4]>=5] + gene_constraint=[lambda x,v: [val for val in v if val>=5], + lambda x,v: [val for val in v if val>=5], + lambda x,v: [val for val in v if val>=5], + lambda x,v: [val for val in v if val>=5], + lambda x,v: [val for val in v if val>=5]] ga_instance = population_gene_constraint(gene_constraint=gene_constraint, init_range_low=1, init_range_high=10, @@ -178,9 +197,48 @@ def test_initial_population_float_by_replacement_no_duplicates(): assert numpy.all(initial_population[:, 2] >= 5), "Not all values in column 2 >= 5" assert numpy.all(initial_population[:, 3] >= 5), "Not all values in column 3 >= 5" assert numpy.all(initial_population[:, 4] >= 5), "Not all values in column 4 >= 5" + print("All constraints are met") def test_initial_population_float_by_replacement_no_duplicates2(): - gene_constraint=[lambda x: x[0]>=1,lambda x: x[1]>=1,lambda x: x[2]>=1,lambda x: x[3]>=1,lambda x: x[4]>=1] + gene_constraint=[lambda x,v: [val for val in v if val>=1], + lambda x,v: [val for val in v if val>=1], + lambda x,v: [val for val in v if val>=1], + lambda x,v: [val for val in v if val>=1], + lambda x,v: [val for val in v if val>=1]] + ga_instance = population_gene_constraint(gene_constraint=gene_constraint, + init_range_low=1, + init_range_high=2, + gene_type=[float, 1], + num_genes=5, + crossover_type=None, + mutation_by_replacement=False, + allow_duplicate_genes=False) + + num_duplicates = 0 + for idx, solution in enumerate(ga_instance.solutions): + num = len(solution) - len(set(solution)) + if num != 0: + print(solution, idx) + num_duplicates += num + + assert num_duplicates == 0 + + initial_population = ga_instance.initial_population + # print(initial_population) + + assert numpy.all(initial_population[:, 0] >= 1), "Not all values in column 0 >= 1" + assert numpy.all(initial_population[:, 1] >= 1), "Not all values in column 1 >= 1" + assert numpy.all(initial_population[:, 2] >= 1), "Not all values in column 2 >= 1" + assert numpy.all(initial_population[:, 3] >= 1), "Not all values in column 3 >= 1" + assert numpy.all(initial_population[:, 4] >= 1), "Not all values in column 4 >= 1" + print("All constraints are met") + +def test_initial_population_float_by_replacement_no_duplicates_None_constraints(): + gene_constraint=[lambda x,v: [val for val in v if val>=1], + None, + lambda x,v: [val for val in v if val>=1], + None, + lambda x,v: [val for val in v if val>=1]] ga_instance = population_gene_constraint(gene_constraint=gene_constraint, init_range_low=1, init_range_high=2, @@ -207,6 +265,7 @@ def test_initial_population_float_by_replacement_no_duplicates2(): assert numpy.all(initial_population[:, 2] >= 1), "Not all values in column 2 >= 1" assert numpy.all(initial_population[:, 3] >= 1), "Not all values in column 3 >= 1" assert numpy.all(initial_population[:, 4] >= 1), "Not all values in column 4 >= 1" + print("All constraints are met") if __name__ == "__main__": #### Single-objective @@ -221,3 +280,5 @@ def test_initial_population_float_by_replacement_no_duplicates2(): print() test_initial_population_float_by_replacement_no_duplicates2() print() + test_initial_population_float_by_replacement_no_duplicates_None_constraints() + print() From 086e1f43963fe7d61170b7993c795e762c95655c Mon Sep 17 00:00:00 2001 From: Ahmed Gad Date: Mon, 7 Jul 2025 13:48:37 -0400 Subject: [PATCH 04/10] Delete .DS_Store --- .DS_Store | Bin 8196 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 2f034958172052b7a3bef5fd41e0e5c179f3d3b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8196 zcmeHML2nyH6n-yFVsAs6ZR(_fMUqJN00Q`yFPaTsG{(@T!!TeNFbo(53b#F-|d1o71=>;Ur739B8S{0kt_`yfVfa3aZt~&QWl{l9r}53>XH+8IZaAEUd#Z zMDQe&ze`v8nCjiXRZ+&%&>~b5!bF}galcN&HTq#U{ypHwM%VYkXm#~>oH{o>Gn>m< zxw+iq$`jGAL~hgz%Wm*cK2?SA8$;b~?0KwTw+rinN3O?NpbWegBgmr%9&d?$S@d`- zRJIj8U|D&qZeKY$xq0W-b!YAN>2>Gi&aG8a-&;F9wepL_8+Ui>&-@M-U#pD)#*qas z=;u-U4QZooA65eH3*M$aiO&OrBXFSuUGPcI(1QDfNzyllKO6LnZ7V}l4(`Jiow7~% z1S+tZK0Ej_L(&Y9c?@l$wUtIrvB}7@L1bdvFqfm^K)-qxHxZL zTDV+TSX@|IDlA=DUV8iLJ6G%W<%ZjQ)()gotP5WRWxvNBwgazK>AFpiw`&nQiYnf7 zR<{>2&|TL0{8d-=xJ#JAs}42Y2LWST&9{AU5VEM2(Dy%ckE)~D=fh?oe1AuTUgQbB z|0pEy-ilafiysJD{E$3*yDNvnJr;x{>vqPbw(kak%iFAc{MdIJ%-`l^5k;a?^O}O| zP0Xul>2W7ua?0ZSf6_srQY?KmR93WNLs2W_yM>_^ORRFinN=+9=?;tB`&~M<+fXA1 ze*xdZckn&@06)QR@CW>bvsl1ucmvn)9)5`T@l)KxHu~7XLp{ONFr-{duY`SiPJHT& zw_H@`zY76H+NTs$niQK?s0w-uKkX4JKL4DE&lc>Gm)(O68rdYPPS%H1q)u9#Pg#8R zIvW|ru%1}OrgvlTCG@~kT8ExEybVcqqgO?E@iJu`X z1y{L38mS_}1mszX2&1iMj)@IbB2XTSfIfpu_m2ZR$wQN-N*e{=Hh z{~Bdl!+>GnOfrDe8 Date: Mon, 7 Jul 2025 13:48:50 -0400 Subject: [PATCH 05/10] Delete pygad/.DS_Store --- pygad/.DS_Store | Bin 10244 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 pygad/.DS_Store diff --git a/pygad/.DS_Store b/pygad/.DS_Store deleted file mode 100644 index 3e6d027cc6e2afc8222e9c82ed6348bdefdf5e7b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10244 zcmeI1&2G~`5P)a%Q^yKOIZ$!nVu=ff3epOsR=q@_95`?x2!sFyJF!};#*X5oQHdhu z3NOS{a6;nBqrlAUHnKO#g+tX^v(fIX*E3G$)9zR^0RYvV4)*~(0BB$**}8+nhDP_P zueFLsgusdb#Rm^N z$&QgrEje`Hz$pOA8ZL9gIpzUu;~Cj8a;YVo;xl#jpp2<9DTdPKc;6#+lpQ0NT55Ap z+8mVmW@R!I#ovy09;<`uXepx*5CZE2D0gpi&K^Nh$lott#_1r4(*QN-P`$!_{FfWf z0ID!Ri^S6UwOK2eWh3*fAHgV&vPrxBTUDyH`i|qcPSg3+J4`}6t!(ZQZ~ z_-wJ~&5sV+IDLA!Sh$Vdhfj`Q_s`=mN&1bQ0%hV0+|}2s@jK3p%NMdgTDJa>v5417{FIjAgM9#>FF32`wZA z-Ev?lxMZPm;GCe~5z1)K6yb2x`I(D4mUcPtSWa1hDqF&A9t-P~0|vWdA!y*ix#Wm4 zkLTz+<z~y+9T#m;JD#t& Date: Mon, 7 Jul 2025 13:49:31 -0400 Subject: [PATCH 06/10] Delete pygad/visualize/.DS_Store --- pygad/visualize/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 pygad/visualize/.DS_Store diff --git a/pygad/visualize/.DS_Store b/pygad/visualize/.DS_Store deleted file mode 100644 index d6d23e9a0eb73b7451abf68d89614969ed97732f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKF-`+P474Err&K)!M}G6zxW8l$m|3?dfTBRyB$>f?Ll==6r_L@kOERb3P=I&*|hm0QBev= z0V(jU0KX3nPV5SY#Q1a|@c7R48Igu@+$Dgm=3U{Ch!vP86_`}7D~2Z>`BrsZ;gFbg z^XQD{RA;Xnibr?kTa=r3iHcG{3XByv&gqi-|0VpF`~R4vnG}!$|4IR$t#8&Vyi)D0 wlb7RO+u--`FGFpVBa99Km~bmT-K%RHqpm9)5`&I>(1AJ#P#2jL_zML-0WRSuwg3PC From a2c4a1013802eff879f49e255ca01a68338b4597 Mon Sep 17 00:00:00 2001 From: Ahmed Gad Date: Mon, 7 Jul 2025 13:49:39 -0400 Subject: [PATCH 07/10] Delete pygad/utils/.DS_Store --- pygad/utils/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 pygad/utils/.DS_Store diff --git a/pygad/utils/.DS_Store b/pygad/utils/.DS_Store deleted file mode 100644 index a364f0c0bd6445a262c5f5901cffdae298ec52af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKu};G<5Pc3s3JOCd7Dj&o609syRR#toCMIY@gd&9o5sJi?f8+!B6nN*eDw+gF zgsQvf{Orp;J9)O^7=W9t?@xg#fRrwn9IzNMxi3DjBu4g$F7#311-HCT@HEJ_z<*Rg z<}M3!R$+zj^Y?aHH^s7UmdudlaYaA>48|I8hyu@O(DG{Vijpmv_df5v$II}DHP^|4 zUXi&PW4W6iD`j4b2eQsa^FMm|M|_e6pQt2H)?~|CO)q{MH7R?&uxVxrm;$E24l2Ms zTP)2KtuzHp0aIY3fP5c3T`-T>DTYr6i*N)WP8bfxy8J8($4AT~c8a`1b4n#D)x{%* zQ##{5=H(GPMWw^V!-tC_yLduzVRZKILpofpXr(D&3T!K|r_HJC{}(@>|F=ojG6hV5 zol?L}=GXHXUn%abgO`)N*3<9kVv^S>ZYZpTt(dv86(7@sG47>8%p-P+jL_^yAjn{a JDe$KXd;wTAS1$kn From 83a5dc855245e49520b771da76e0dd3ad30e5255 Mon Sep 17 00:00:00 2001 From: Ahmed Gad Date: Mon, 7 Jul 2025 13:49:46 -0400 Subject: [PATCH 08/10] Delete pygad/helper/.DS_Store --- pygad/helper/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 pygad/helper/.DS_Store diff --git a/pygad/helper/.DS_Store b/pygad/helper/.DS_Store deleted file mode 100644 index 454433a030f4e32ab25ec5ede0cc4bed68fb2861..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKyG}zf47H&WMO`{F<_nORS)!^83`|T+pcaNoEd{k5*z%`*3Y=pbL@#$l2qC+2 zj_cTY9O)*pi0EW@e9Y;&&=fJp=tk7uPlNd}UE zWFQ$x27aCa+}V`j$T8bwAQ?yoJ{jQoP@u#b*c|QXKw~8UZ~(UnY(AEmQvz#Xb3_kB zJr(Gw8YPB$I{YQ#YG8BpbkQh2G-m!NUespC_{G9St7EpwKr*n;0Bc{!nD_q$KAGMk z-$JrU29kmQ%76~0*V74h7kBHoee$j?&^suFag7E9_TD1^e|V0ZSf}?F+K8)x&5@(f RZ|T5%2pA#RBm=*|z&j>5H7WoA From 39d8d29c94e0207f5c69c88a08a5a2d4b61135f4 Mon Sep 17 00:00:00 2001 From: Ahmed Gad Date: Mon, 7 Jul 2025 13:58:53 -0400 Subject: [PATCH 09/10] Edit version and docs --- README.md | 33 --------------------------------- pygad/visualize/.DS_Store | Bin 0 -> 6148 bytes pyproject.toml | 2 +- 3 files changed, 1 insertion(+), 34 deletions(-) create mode 100644 pygad/visualize/.DS_Store diff --git a/README.md b/README.md index deff145..33710b4 100644 --- a/README.md +++ b/README.md @@ -253,16 +253,6 @@ Get started with the genetic algorithm by reading the tutorial titled [**Introdu [![Introduction to Genetic Algorithm](https://user-images.githubusercontent.com/16560492/82078259-26252d00-96e1-11ea-9a02-52a99e1054b9.jpg)](https://www.linkedin.com/pulse/introduction-optimization-genetic-algorithm-ahmed-gad) -## Tutorial: Build Neural Networks in Python - -Read about building neural networks in Python through the tutorial titled [**Artificial Neural Network Implementation using NumPy and Classification of the Fruits360 Image Dataset**](https://www.linkedin.com/pulse/artificial-neural-network-implementation-using-numpy-fruits360-gad) available at these links: - -* [LinkedIn](https://www.linkedin.com/pulse/artificial-neural-network-implementation-using-numpy-fruits360-gad) -* [Towards Data Science](https://towardsdatascience.com/artificial-neural-network-implementation-using-numpy-and-classification-of-the-fruits360-image-3c56affa4491) -* [KDnuggets](https://www.kdnuggets.com/2019/02/artificial-neural-network-implementation-using-numpy-and-image-classification.html) - -[![Building Neural Networks Python](https://user-images.githubusercontent.com/16560492/82078281-30472b80-96e1-11ea-8017-6a1f4383d602.jpg)](https://www.linkedin.com/pulse/artificial-neural-network-implementation-using-numpy-fruits360-gad) - ## Tutorial: Optimize Neural Networks with Genetic Algorithm Read about training neural networks using the genetic algorithm through the tutorial titled [**Artificial Neural Networks Optimization using Genetic Algorithm with Python**](https://www.linkedin.com/pulse/artificial-neural-networks-optimization-using-genetic-ahmed-gad) available at these links: @@ -273,29 +263,6 @@ Read about training neural networks using the genetic algorithm through the tuto [![Training Neural Networks using Genetic Algorithm Python](https://user-images.githubusercontent.com/16560492/82078300-376e3980-96e1-11ea-821c-aa6b8ceb44d4.jpg)](https://www.linkedin.com/pulse/artificial-neural-networks-optimization-using-genetic-ahmed-gad) -## Tutorial: Building CNN in Python - -To start with coding the genetic algorithm, you can check the tutorial titled [**Building Convolutional Neural Network using NumPy from Scratch**](https://www.linkedin.com/pulse/building-convolutional-neural-network-using-numpy-from-ahmed-gad) available at these links: - -- [LinkedIn](https://www.linkedin.com/pulse/building-convolutional-neural-network-using-numpy-from-ahmed-gad) -- [Towards Data Science](https://towardsdatascience.com/building-convolutional-neural-network-using-numpy-from-scratch-b30aac50e50a) -- [KDnuggets](https://www.kdnuggets.com/2018/04/building-convolutional-neural-network-numpy-scratch.html) -- [Chinese Translation](http://m.aliyun.com/yunqi/articles/585741) - -[This tutorial](https://www.linkedin.com/pulse/building-convolutional-neural-network-using-numpy-from-ahmed-gad)) is prepared based on a previous version of the project but it still a good resource to start with coding CNNs. - -[![Building CNN in Python](https://user-images.githubusercontent.com/16560492/82431022-6c3a1200-9a8e-11ea-8f1b-b055196d76e3.png)](https://www.linkedin.com/pulse/building-convolutional-neural-network-using-numpy-from-ahmed-gad) - -## Tutorial: Derivation of CNN from FCNN - -Get started with the genetic algorithm by reading the tutorial titled [**Derivation of Convolutional Neural Network from Fully Connected Network Step-By-Step**](https://www.linkedin.com/pulse/derivation-convolutional-neural-network-from-fully-connected-gad) which is available at these links: - -* [LinkedIn](https://www.linkedin.com/pulse/derivation-convolutional-neural-network-from-fully-connected-gad) -* [Towards Data Science](https://towardsdatascience.com/derivation-of-convolutional-neural-network-from-fully-connected-network-step-by-step-b42ebafa5275) -* [KDnuggets](https://www.kdnuggets.com/2018/04/derivation-convolutional-neural-network-fully-connected-step-by-step.html) - -[![Derivation of CNN from FCNN](https://user-images.githubusercontent.com/16560492/82431369-db176b00-9a8e-11ea-99bd-e845192873fc.png)](https://www.linkedin.com/pulse/derivation-convolutional-neural-network-from-fully-connected-gad) - ## Book: Practical Computer Vision Applications Using Deep Learning with CNNs You can also check my book cited as [**Ahmed Fawzy Gad 'Practical Computer Vision Applications Using Deep Learning with CNNs'. Dec. 2018, Apress, 978-1-4842-4167-7**](https://www.amazon.com/Practical-Computer-Vision-Applications-Learning/dp/1484241665) which discusses neural networks, convolutional neural networks, deep learning, genetic algorithm, and more. diff --git a/pygad/visualize/.DS_Store b/pygad/visualize/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..d6d23e9a0eb73b7451abf68d89614969ed97732f GIT binary patch literal 6148 zcmeHKF-`+P474Err&K)!M}G6zxW8l$m|3?dfTBRyB$>f?Ll==6r_L@kOERb3P=I&*|hm0QBev= z0V(jU0KX3nPV5SY#Q1a|@c7R48Igu@+$Dgm=3U{Ch!vP86_`}7D~2Z>`BrsZ;gFbg z^XQD{RA;Xnibr?kTa=r3iHcG{3XByv&gqi-|0VpF`~R4vnG}!$|4IR$t#8&Vyi)D0 wlb7RO+u--`FGFpVBa99Km~bmT-K%RHqpm9)5`&I>(1AJ#P#2jL_zML-0WRSuwg3PC literal 0 HcmV?d00001 diff --git a/pyproject.toml b/pyproject.toml index aed6e1d..34ae65c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta" [project] name = "pygad" -version = "3.4.0" +version = "3.5.0" description = "PyGAD: A Python Library for Building the Genetic Algorithm and Training Machine Learning Algoithms (Keras & PyTorch)." readme = {file = "README.md", content-type = "text/markdown"} requires-python = ">=3" From 1de702882108234bf4aa0a789284e0b3d270f5b6 Mon Sep 17 00:00:00 2001 From: Ahmed Gad Date: Mon, 7 Jul 2025 13:59:20 -0400 Subject: [PATCH 10/10] Delete pygad/visualize/.DS_Store --- pygad/visualize/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 pygad/visualize/.DS_Store diff --git a/pygad/visualize/.DS_Store b/pygad/visualize/.DS_Store deleted file mode 100644 index d6d23e9a0eb73b7451abf68d89614969ed97732f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKF-`+P474Err&K)!M}G6zxW8l$m|3?dfTBRyB$>f?Ll==6r_L@kOERb3P=I&*|hm0QBev= z0V(jU0KX3nPV5SY#Q1a|@c7R48Igu@+$Dgm=3U{Ch!vP86_`}7D~2Z>`BrsZ;gFbg z^XQD{RA;Xnibr?kTa=r3iHcG{3XByv&gqi-|0VpF`~R4vnG}!$|4IR$t#8&Vyi)D0 wlb7RO+u--`FGFpVBa99Km~bmT-K%RHqpm9)5`&I>(1AJ#P#2jL_zML-0WRSuwg3PC