├── README.md ├── .gitignore ├── LICENSE └── genetic.py /README.md: -------------------------------------------------------------------------------- 1 | GeneticAlgorithmProductionPlanning 2 | ================================== 3 | 4 | Example of Solving a Production Planning Problem with Genetic Algorithm 5 | 6 | I will add more information and explain functions in the python code 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | results.txt 2 | 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | 7 | # C extensions 8 | *.so 9 | 10 | # Distribution / packaging 11 | .Python 12 | env/ 13 | build/ 14 | develop-eggs/ 15 | dist/ 16 | downloads/ 17 | eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .cache 42 | nosetests.xml 43 | coverage.xml 44 | 45 | # Translations 46 | *.mo 47 | *.pot 48 | 49 | # Django stuff: 50 | *.log 51 | 52 | # Sphinx documentation 53 | docs/_build/ 54 | 55 | # PyBuilder 56 | target/ 57 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Fatih Pense 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /genetic.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | from deap import base 4 | from deap import creator 5 | from deap import tools 6 | from deap import algorithms 7 | 8 | 9 | from itertools import repeat 10 | from collections import Sequence 11 | 12 | def mutCustom(individual, mu, sigma, indpb): 13 | 14 | size = len(individual) 15 | 16 | 17 | #custom part 18 | degisim=1 19 | ileri=random.randint(0,1) 20 | if(ileri==1): 21 | s=random.randint(0,12-2) 22 | individual[s] -=degisim 23 | individual[s+1] +=degisim 24 | else: 25 | s=random.randint(1,12-1) 26 | individual[s] -=degisim 27 | individual[s-1] +=degisim 28 | #custom part end 29 | 30 | if not isinstance(mu, Sequence): 31 | mu = repeat(mu, size) 32 | elif len(mu) < size: 33 | raise IndexError("mu must be at least the size of individual: %d < %d" % (len(mu), size)) 34 | if not isinstance(sigma, Sequence): 35 | sigma = repeat(sigma, size) 36 | elif len(sigma) < size: 37 | raise IndexError("sigma must be at least the size of individual: %d < %d" % (len(sigma), size)) 38 | 39 | for i, m, s in zip(range(size), mu, sigma): 40 | if random.random() < indpb: 41 | individual[i] += random.gauss(m, s) 42 | 43 | return individual, 44 | 45 | 46 | def cxCustom(ind1, ind2): 47 | size = 12 #min(len(ind1), len(ind2)) 48 | cxpoint1 = random.randint(1, size) 49 | cxpoint2 = random.randint(1, size - 1) 50 | if cxpoint2 >= cxpoint1: 51 | cxpoint2 += 1 52 | else: # Swap the two cx points 53 | cxpoint1, cxpoint2 = cxpoint2, cxpoint1 54 | 55 | ind1[cxpoint1:cxpoint2], ind2[cxpoint1:cxpoint2] \ 56 | = ind2[cxpoint1:cxpoint2], ind1[cxpoint1:cxpoint2] 57 | 58 | ind1[12+cxpoint1:12+cxpoint2], ind2[12+cxpoint1:12+cxpoint2] \ 59 | = ind2[12+cxpoint1:12+cxpoint2], ind1[12+cxpoint1:12+cxpoint2] 60 | 61 | ind1[24+cxpoint1:24+cxpoint2], ind2[24+cxpoint1:24+cxpoint2] \ 62 | = ind2[24+cxpoint1:24+cxpoint2], ind1[24+cxpoint1:24+cxpoint2] 63 | return ind1, ind2 64 | 65 | def cxCustomOne(ind1, ind2): 66 | size = 12 67 | cxpoint = random.randint(1, size - 1) 68 | ind1[cxpoint:12], ind2[cxpoint:12] = ind2[cxpoint:12], ind1[cxpoint:12] 69 | ind1[12+cxpoint:24], ind2[12+cxpoint:24] = ind2[12+cxpoint:24], ind1[12+cxpoint:24] 70 | ind1[24+cxpoint:36], ind2[24+cxpoint:36] = ind2[24+cxpoint:36], ind1[24+cxpoint:36] 71 | 72 | return ind1, ind2 73 | 74 | ind1[cxpoint1:cxpoint2], ind2[cxpoint1:cxpoint2] \ 75 | = ind2[cxpoint1:cxpoint2], ind1[cxpoint1:cxpoint2] 76 | 77 | ind1[12+cxpoint1:12+cxpoint2], ind2[12+cxpoint1:12+cxpoint2] \ 78 | = ind2[12+cxpoint1:12+cxpoint2], ind1[12+cxpoint1:12+cxpoint2] 79 | 80 | ind1[24+cxpoint1:24+cxpoint2], ind2[24+cxpoint1:24+cxpoint2] \ 81 | = ind2[24+cxpoint1:24+cxpoint2], ind1[24+cxpoint1:24+cxpoint2] 82 | return ind1, ind2 83 | 84 | #uretim gunu sayisi 85 | aylik_uretim_gunu = [22,20,23,19,22,22,20,23,11,22,22,18] 86 | #birikimli talep ve guvenlik stogu miktari 87 | yedinci_sutun = [7800,11500,15500,20800,28200,37500,49100,57500,63600,69400,74300,79300] 88 | 89 | #maliyetler 90 | m_elde_bulundurma=51 91 | m_elde_bulundurmama=342 92 | m_isgucu_degistirme=200 93 | m_fazla_mesai=10 94 | m_fason_uretim=15 95 | 96 | #kisitlar 97 | #TODO 350 yap 98 | normal_mesai_kapasite=350 99 | fazla_mesai_kapasite=60 100 | baslangic_stogu=2800 101 | 102 | 103 | print("starting...") 104 | 105 | 106 | def evalPlan(plan,verbose=False): 107 | #sanitize, kısıtları uygula 108 | for i in range(0,12): 109 | plan[i]=round(plan[i]) 110 | for i in range(12,24): 111 | plan[i]=abs(round(plan[i])) 112 | if(plan[i]>fazla_mesai_kapasite): 113 | plan[i]=fazla_mesai_kapasite 114 | for i in range(24,36): 115 | plan[i]=abs(round(plan[i])) 116 | 117 | uretim_hizi_degistirme=plan[:12] 118 | fazla_mesai_uretim_gunluk=plan[12:24] 119 | fason_uretim_gunluk=plan[24:] 120 | 121 | #uretim miktari hesaplari: 122 | #uretim hizi (o ay icin gunluk) 123 | uretim_hizi= [] 124 | #toplam uretim hizi degistirme miktari 125 | toplam_uretim_hizi_degistirme=0 126 | #fazla mesaide uretilen toplam urun 127 | fazla_mesaide_uretilen_toplam=0 128 | #fason uretimle uretilen toplam urun 129 | fason_uretim_toplam=0 130 | 131 | normal_mesai_uretim_hizi=normal_mesai_kapasite #normal mesai kapasite 132 | for i in range(12): 133 | #if(uretim_hizi_degistirme[i]!=0): 134 | normal_mesai_uretim_hizi+=uretim_hizi_degistirme[i] 135 | if(normal_mesai_uretim_hizi>350): 136 | normal_mesai_uretim_hizi=350 137 | if(verbose): 138 | print("normal mesai kapasitesi düzeltildi, ay:",i) 139 | if(i!=0): 140 | toplam_uretim_hizi_degistirme+=abs(uretim_hizi_degistirme[i]) 141 | 142 | fazla_mesaide_uretilen_toplam+=fazla_mesai_uretim_gunluk[i]*aylik_uretim_gunu[i] 143 | fason_uretim_toplam+=fason_uretim_gunluk[i]*aylik_uretim_gunu[i] 144 | 145 | uretim_hizi.append(normal_mesai_uretim_hizi+fazla_mesai_uretim_gunluk[i]+fason_uretim_gunluk[i]) 146 | 147 | 148 | if(verbose): 149 | print("toplam uretim hizi degistirme") 150 | print(toplam_uretim_hizi_degistirme) 151 | print("fazla mesaide toplam") 152 | print(fazla_mesaide_uretilen_toplam) 153 | print("fason uretilen toplam") 154 | print(fason_uretim_toplam) 155 | print("sonuc uretim hizi") 156 | print(uretim_hizi) 157 | 158 | #stok hesaplarini yapalim 159 | #birikimli uretim miktari 160 | birikimli_uretim_miktari=[] 161 | #ikinci_yedinci_sutun 162 | ikinci_yedinci_sutun=[] 163 | for i in range(12): 164 | aylik_uretim_miktari=uretim_hizi[i]*aylik_uretim_gunu[i] 165 | if i==0: 166 | birikimli_uretim_temp=aylik_uretim_miktari+baslangic_stogu 167 | else: 168 | birikimli_uretim_temp=aylik_uretim_miktari+birikimli_uretim_miktari[i-1] 169 | birikimli_uretim_miktari.append(birikimli_uretim_temp) 170 | aylik_stok=birikimli_uretim_temp-yedinci_sutun[i] 171 | ikinci_yedinci_sutun.append(aylik_uretim_gunu[i]*aylik_stok) 172 | 173 | if(verbose): 174 | print("birikimli uretim miktari") 175 | print(birikimli_uretim_miktari) 176 | print("ikinci_yedinci_sutun") 177 | print(ikinci_yedinci_sutun) 178 | 179 | 180 | 181 | #toplam maliyet hesaplari 182 | # uretim_hizini_degistirme_maliyeti= 183 | m1=toplam_uretim_hizi_degistirme*m_isgucu_degistirme 184 | # fazla mesai maliyeti 185 | m2=fazla_mesaide_uretilen_toplam*m_fazla_mesai 186 | # fason uretim maliyeti 187 | m3=fason_uretim_toplam*m_fason_uretim 188 | # elde bulundurma / bulundurmama 189 | toplam_stok_elde=0 190 | toplam_ay_elde=0 191 | toplam_gun_elde=0 192 | toplam_stok_yok=0 193 | toplam_ay_yok=0 194 | toplam_gun_yok=0 195 | for i in range(12): 196 | s=ikinci_yedinci_sutun[i] 197 | if(s>0): 198 | toplam_ay_elde+= 1 199 | toplam_stok_elde+=s 200 | toplam_gun_elde+=aylik_uretim_gunu[i] 201 | if(s<0): 202 | toplam_ay_yok+= 1 203 | toplam_stok_yok += abs(s) 204 | toplam_gun_yok+=aylik_uretim_gunu[i] 205 | 206 | m4=0 207 | if(toplam_ay_elde>0): 208 | m4=(toplam_stok_elde/toplam_gun_elde)*(toplam_ay_elde/12)*m_elde_bulundurma 209 | if(verbose): 210 | print("toplam_gun_elde:",toplam_gun_elde,"toplam_stok_elde:",toplam_stok_elde) 211 | print("toplam_ay_elde:",toplam_ay_elde) 212 | m5=0 213 | if(toplam_ay_yok>0): 214 | m5=(toplam_stok_yok/toplam_gun_yok)*(toplam_ay_yok/12)*m_elde_bulundurmama 215 | if(verbose): 216 | print("toplam_gun_yok:",toplam_gun_yok,"toplam_stok_yok:",toplam_stok_yok) 217 | print("toplam_ay_yok:",toplam_ay_yok) 218 | 219 | maliyet=m1+m2+m3+m4+m5 220 | if(verbose): 221 | print("*maliyetler") 222 | print(m1,m2,m3,m4,m5) 223 | print("*toplam") 224 | print(maliyet) 225 | return maliyet, #this means return tuple with one element 226 | 227 | 228 | 229 | 230 | hof= tools.HallOfFame(1) 231 | 232 | def getNewPlan(): 233 | 234 | ind=[-122, 0, 9, 97, 16, 0, 0, 0, 0, -86, -17, 0, 0, 0, 0, 0, 0, 60, 60, 60, 60, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0] 235 | 236 | return mutCustom(ind,mu=0,sigma=1,indpb=0.3)[0] 237 | 238 | creator.create("FitnessMin", base.Fitness, weights=(-1.0,)) 239 | creator.create("Individual", list, fitness=creator.FitnessMin) 240 | 241 | toolbox = base.Toolbox() 242 | toolbox.register("individual", tools.initIterate, creator.Individual , getNewPlan ) 243 | toolbox.register("population", tools.initRepeat, list, toolbox.individual) 244 | toolbox.register("evaluate", evalPlan) 245 | toolbox.register("mate", cxCustomOne) 246 | toolbox.register("mutate", mutCustom, mu=0,sigma=1,indpb=0.1) 247 | toolbox.register("select", tools.selTournament, tournsize=10) 248 | 249 | 250 | 251 | def main(): 252 | 253 | file=open("results.txt","a") 254 | 255 | ''' plan2=[0,0,0,120,0,0, 0,0,0,-120,0,0, 256 | 0,0,0,56,56,56, 56,56,0,0,0,23, 257 | 0,0,0,0,0,0, 0,0,0,0,0,0] 258 | print(evalPlan(plan2)) 259 | ''' 260 | plan= [-145, 26, 69, 33, 16, 0, 1, 0, -1, -32, -69, 0, 261 | 20, 0, 0, 1, 1, 8,44,26, 60, 0, 0, 0, 262 | 2, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0] 263 | 264 | 265 | 266 | 267 | print(evalPlan(plan,verbose=True)) 268 | #return 269 | 270 | 271 | 272 | 273 | 274 | pop = toolbox.population(n=500) 275 | 276 | hof= tools.HallOfFame(1) 277 | 278 | 279 | print(pop[0]) 280 | 281 | #deap.algorithms.eaSimple(population, toolbox, cxpb, mutpb, ngen[, stats, halloffame, verbose]) 282 | #algorithms.eaSimple(pop, toolbox, 0.4, 0.8,1000, halloffame=hof,verbose=True) 283 | algorithms.eaMuPlusLambda(pop,toolbox,50,300, 0.5, 0.5 , 1000 , halloffame=hof) 284 | 285 | 286 | print(hof) 287 | print(hof,file=file) 288 | 289 | 290 | print("***best plan results") 291 | evalPlan(hof[0],verbose=True) 292 | print(evalPlan(hof[0]),file=file) 293 | 294 | 295 | 296 | 297 | main() 298 | --------------------------------------------------------------------------------