├── README.md └── SPGD V0.03.ipynb /README.md: -------------------------------------------------------------------------------- 1 | SPGD: Search Party Gradient Descent algorithm, a Simple Gradient-Based Parallel Algorithm for Bound-Constrained Optimization 2 | 3 | Read the paper for a clear understanding of how the algorithm works. 4 | Paper Link: https://www.mdpi.com/2227-7390/10/5/800 5 | 6 | What is Optimization (Video Explanation): https://www.youtube.com/watch?v=Gu7si5T0z_w 7 | 8 | If you find this algorithm useful, kindly consider citing my paper. 9 | Syed Shahul Hameed, A. S., & Rajagopalan, N. (2022). SPGD: Search Party Gradient Descent Algorithm, a Simple Gradient-Based Parallel Algorithm for Bound-Constrained Optimization. Mathematics, 10(5), 800. 10 | 11 | This is a preliminary code written for the SPGD paper. 12 | The code is not efficient and has lots of room for improvement. 13 | We plan to release an updated version of this code in the future. 14 | 15 | The benchmark functions are listed out at the top of the jupyter notebook. Any one of the benchmark functions can 16 | be executed, and then the functions of the SPGD algorithm can be executed to see how it performs. 17 | 18 | By default 50 times SPGD is executed on the chosen benchmark functions, so that statistical results (like mean, best, worst) can be obtained. 19 | 20 | The python code for the benchmark functions were taken from this repository: https://github.com/nathanrooy/landscapes/blob/master/landscapes/single_objective.py 21 | -------------------------------------------------------------------------------- /SPGD V0.03.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# SPGD: Search Party Gradient Descent algorithm, a Simple Gradient-Based Parallel Algorithm for Bound-Constrained Optimization\n", 8 | "\n", 9 | "Link: https://www.mdpi.com/2227-7390/10/5/800" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "#### This is a preliminary code written for the SPGD paper.\n", 17 | "The code is not efficient, and has lots of room for improvement.\n", 18 | "We plan to release an updated version of this code in future." 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 1, 24 | "metadata": {}, 25 | "outputs": [], 26 | "source": [ 27 | "import numpy as np\n", 28 | "import random\n", 29 | "import threading\n", 30 | "import time\n", 31 | "import math, statistics" 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": {}, 37 | "source": [ 38 | "### Benchmark Functions" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": 39, 44 | "metadata": { 45 | "code_folding": [ 46 | 0 47 | ] 48 | }, 49 | "outputs": [], 50 | "source": [ 51 | "def f(x): #F1Ackley \n", 52 | " x,y = x[0],x[1]\n", 53 | " '''\n", 54 | " Ackley Function\n", 55 | " wikipedia: https://en.wikipedia.org/wiki/Ackley_function\n", 56 | " global minium at f(x=0, y=0) = 0\n", 57 | " bounds: -35<=x,y<=35\n", 58 | " '''\n", 59 | " return (-20 * np.exp(-0.02 * np.sqrt(0.5 * (x*x + y*y))) -\n", 60 | " np.exp(0.5 * (np.cos(2.0*np.pi*x) + np.cos(2*np.pi*y))) + np.e + 20) #Ackley\n", 61 | "mrnge = [-35,35]\n", 62 | "optimum = 0\n", 63 | "dim = 2" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": 15, 69 | "metadata": { 70 | "code_folding": [ 71 | 0 72 | ] 73 | }, 74 | "outputs": [], 75 | "source": [ 76 | "def f(x): #F2beale\n", 77 | " x,y = x[0],x[1]\n", 78 | " '''\n", 79 | " Beale Function\n", 80 | " global minimum: f(x=3, y=0.5) = 0\n", 81 | " bounds: -4.5 <= x, y <= 4.5\n", 82 | " '''\n", 83 | " return ((1.500 - x + x*y)**2 +\n", 84 | " (2.250 - x + x*y**2)**2 +\n", 85 | " (2.625 - x + x*y**3)**2) #Beale\n", 86 | "mrnge = [-5,5]\n", 87 | "optimum = 0\n", 88 | "dim = 2" 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": 7, 94 | "metadata": { 95 | "code_folding": [ 96 | 0 97 | ] 98 | }, 99 | "outputs": [], 100 | "source": [ 101 | "def f(x): #F3Egg Holder\n", 102 | " x,y = x[0],x[1]\n", 103 | " '''\n", 104 | " Eggholder Function\n", 105 | " global minimum: f(x=512, y=404.2319) = -959.6407\n", 106 | " bounds: -512 <= x, y <= 512\n", 107 | " '''\n", 108 | "\n", 109 | " return (-(y+47)*np.sin(np.sqrt(abs((x/2.0) + (y+47)))) -\n", 110 | " x*np.sin(np.sqrt(abs(x-(y+47)))))\n", 111 | "mrnge = [-512,512]\n", 112 | "optimum = -959.6407\n", 113 | "dim = 2" 114 | ] 115 | }, 116 | { 117 | "cell_type": "code", 118 | "execution_count": 112, 119 | "metadata": { 120 | "code_folding": [ 121 | 0 122 | ] 123 | }, 124 | "outputs": [], 125 | "source": [ 126 | "def f(xy):#F4Gold-Stein\n", 127 | " '''\n", 128 | " Goldstein-Price Function\n", 129 | " global minimum: f(0, -1) = 3\n", 130 | " bounds: -2 <= x, y <= 2\n", 131 | " '''\n", 132 | " x, y = xy[0], xy[1]\n", 133 | " return ((1 + (x + y + 1)**2 * (19 - 14*x + 3*x**2 - 14*y + 6*x*y + 3*y**2)) *\n", 134 | " (30 + (2*x-3*y)**2 * (18 - 32*x + 12*x**2 + 48*y - 36*x*y + 27*y**2)))\n", 135 | "mrnge = [-2,2]\n", 136 | "optimum = 3\n", 137 | "dim = 2" 138 | ] 139 | }, 140 | { 141 | "cell_type": "code", 142 | "execution_count": 20, 143 | "metadata": { 144 | "code_folding": [ 145 | 0 146 | ] 147 | }, 148 | "outputs": [], 149 | "source": [ 150 | "def f(x):#F5Matyas\n", 151 | " x,y = x[0],x[1]\n", 152 | " '''\n", 153 | " Matyas Function\n", 154 | " global minimum: f(x=0, y=0) = 0\n", 155 | " bounds: -10 <= x, y <= 10\n", 156 | " '''\n", 157 | " return 0.26*(x**2 + y**2) - 0.48*x*y #matyas\n", 158 | "mrnge = [-10,10]\n", 159 | "optimum = 0\n", 160 | "dim = 2" 161 | ] 162 | }, 163 | { 164 | "cell_type": "code", 165 | "execution_count": 43, 166 | "metadata": { 167 | "code_folding": [ 168 | 0 169 | ] 170 | }, 171 | "outputs": [], 172 | "source": [ 173 | "def f(x): #F6Sahaffer\n", 174 | " x,y = x[0],x[1]\n", 175 | " '''\n", 176 | " Schaffer Function N.4\n", 177 | " Reference: https://www.sfu.ca/~ssurjano/schaffer4.html\n", 178 | " global minimum:\n", 179 | " f(x=0, y= 1.25313) = 0.292579\n", 180 | " f(x=0, y=-1.25313) = 0.292579\n", 181 | " bounds: -100 <= x, y <= 100\n", 182 | " '''\n", 183 | " return 0.5 + (np.cos(np.sin(x**2 - y**2))**2 - 0.5)/(1+0.001*(x**2 + y**2))**2 #N.4\n", 184 | "mrnge = [-100,100]\n", 185 | "optimum = 0.292579\n", 186 | "dim = 2" 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": 65, 192 | "metadata": { 193 | "code_folding": [ 194 | 0 195 | ] 196 | }, 197 | "outputs": [], 198 | "source": [ 199 | "def f(xy): #Colville\n", 200 | " '''Colville Function\n", 201 | " Parameters\n", 202 | " ----------\n", 203 | " xy : list\n", 204 | " Returns\n", 205 | " -------\n", 206 | " float\n", 207 | " Notes\n", 208 | " -----\n", 209 | " Bounds: The Colville function is a 4-dimensional function usually evaluated\n", 210 | " on the hypercube defined by x_i in [-10, 10] for i=1,2,3,4.\n", 211 | " Global minimum: f(x)=0 at x=[1,1,1,1]\n", 212 | " References\n", 213 | " ----------\n", 214 | " A.-R. Hedar, “Global Optimization Test Problems”\n", 215 | " '''\n", 216 | "\n", 217 | " x1, x2, x3, x4 = xy[0], xy[1], xy[2], xy[3]\n", 218 | " a = 100*(x1**2 - x2)**2\n", 219 | " b = (x1-1)**2\n", 220 | " c = (x3-1)**2\n", 221 | " d = 90*(x3**2 - x4)**2\n", 222 | " e = 10.1*((x2-1)**2 + (x4-1)**2)\n", 223 | " f = 19.8*(x2-1)*(x4-1)\n", 224 | " return a + b + c + d + e + f\n", 225 | "mrnge = [-10,10]\n", 226 | "optimum = 0\n", 227 | "dim = 4" 228 | ] 229 | }, 230 | { 231 | "cell_type": "code", 232 | "execution_count": 10, 233 | "metadata": { 234 | "code_folding": [ 235 | 0 236 | ] 237 | }, 238 | "outputs": [], 239 | "source": [ 240 | "def f(xy): #griewank\n", 241 | " '''Griwank Function\n", 242 | " Bounds: x_i in [-600, 600] for all i=1,...,d\n", 243 | " Global minimum: f(x)=0 at x=(0,...,0)\n", 244 | "\n", 245 | " '''\n", 246 | " a, b, = 0, 1\n", 247 | " for i, v in enumerate(xy):\n", 248 | " a += v**2 / 4000.0\n", 249 | " b *= np.cos(v/np.sqrt(i+1))\n", 250 | " return a - b + 1\n", 251 | "mrnge = [-600,600]\n", 252 | "optimum = 0\n", 253 | "dim = 5" 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": 93, 259 | "metadata": { 260 | "code_folding": [ 261 | 0 262 | ] 263 | }, 264 | "outputs": [], 265 | "source": [ 266 | "def f(x, m=10): #Michaelwicz\n", 267 | " '''Michalewicz Function\n", 268 | " Notes\n", 269 | " -----\n", 270 | " The parameter m defines the steepness of they valleys and ridges; a larger m leads to a more difficult search. The recommended value of m is m = 10.\n", 271 | " global minimum for 2D: f(x)=-1.8013 at x*=(2.20,1.57)\n", 272 | " bounds: x_i in [0, π] for i=1,..., d\n", 273 | " '''\n", 274 | " d = len(x)\n", 275 | " result = 0\n", 276 | " for i in range(d):\n", 277 | " result -= np.sin(x[i])*(np.sin((i+1)*x[i]**2/np.pi))**(2*m)\n", 278 | " return result\n", 279 | "mrnge = [0,4]\n", 280 | "optimum = -4.687658\n", 281 | "dim = 5" 282 | ] 283 | }, 284 | { 285 | "cell_type": "code", 286 | "execution_count": 81, 287 | "metadata": { 288 | "code_folding": [ 289 | 0 290 | ] 291 | }, 292 | "outputs": [], 293 | "source": [ 294 | "def f(x): #Rosenbrock\n", 295 | " '''\n", 296 | " Rosenbrock Function\n", 297 | " wikipedia: https://en.wikipedia.org/wiki/Rosenbrock_function\n", 298 | " global minimum:\n", 299 | " n=2 -> f(1,1)=0\n", 300 | " bounds:\n", 301 | " -5 <= x_i <= +10\n", 302 | " 1 <= i <= n\n", 303 | " '''\n", 304 | " total = 0\n", 305 | " for i in range(len(x)-1):\n", 306 | " total += 100*(x[i+1] - x[i]*x[i])**2 + (1-x[i])**2\n", 307 | " return total\n", 308 | "mrnge = [-30,30]\n", 309 | "optimum = 0\n", 310 | "dim = 10" 311 | ] 312 | }, 313 | { 314 | "cell_type": "code", 315 | "execution_count": 95, 316 | "metadata": { 317 | "code_folding": [ 318 | 0 319 | ] 320 | }, 321 | "outputs": [], 322 | "source": [ 323 | "def f(x): #10D_zakharov\n", 324 | " '''Zakharov Function\n", 325 | " '''\n", 326 | " a, b = 0, 0\n", 327 | " for i, val in enumerate(x):\n", 328 | " a += val**2\n", 329 | " b += 0.5*i*val\n", 330 | " return a + b**2 + b**4\n", 331 | "mrnge = [-5,10]\n", 332 | "optimum = 0\n", 333 | "dim = 10" 334 | ] 335 | }, 336 | { 337 | "cell_type": "code", 338 | "execution_count": 86, 339 | "metadata": { 340 | "code_folding": [ 341 | 0 342 | ] 343 | }, 344 | "outputs": [], 345 | "source": [ 346 | "def f(xy): #Rotated Ellipsoid\n", 347 | " '''Rotated Hyper-Ellipsoid\n", 348 | " Bounds: the rotated hyper-ellipsoid is usually evaluated on the hypercube\n", 349 | " defined by x_i in [-65.536, 65.536] for all i=1,...,d\n", 350 | " Global minimum: f(x)=0 at x=(0,...,0)\n", 351 | " References\n", 352 | " ----------\n", 353 | " Molga, M., & Smutnicki, C. Test functions for optimization needs (2005)\n", 354 | " '''\n", 355 | " a = 0\n", 356 | " for i in range(0, len(xy)): a += sum([xy[j]**2 for j in range(0, i)])\n", 357 | " return a\n", 358 | "mrnge = [-66,66]\n", 359 | "optimum = 0\n", 360 | "dim = 10" 361 | ] 362 | }, 363 | { 364 | "cell_type": "code", 365 | "execution_count": 8, 366 | "metadata": { 367 | "code_folding": [ 368 | 0 369 | ] 370 | }, 371 | "outputs": [], 372 | "source": [ 373 | "def f(x): #Rastrigin\n", 374 | " '''Rastrigin Function\n", 375 | " Notes\n", 376 | " -----\n", 377 | " Bounds: -5.12 <= x_i <= 5.12 for all i=1,...,d\n", 378 | " Global minimum: f(x)=0 at x=(0,...,0)\n", 379 | " References\n", 380 | " ----------\n", 381 | " wikipedia: https://en.wikipedia.org/wiki/Rastrigin_function\n", 382 | " '''\n", 383 | " return len(x)*10.0 + sum([item*item - 10.0*np.cos(2.0*np.pi*item) for item in x]) #Rastrigin\n", 384 | "mrnge = [-6,6]\n", 385 | "optimum = 0\n", 386 | "dim = 20" 387 | ] 388 | }, 389 | { 390 | "cell_type": "code", 391 | "execution_count": 23, 392 | "metadata": { 393 | "code_folding": [ 394 | 0 395 | ] 396 | }, 397 | "outputs": [], 398 | "source": [ 399 | "def f(xy): #Holder Table\n", 400 | " '''\n", 401 | " Holder Table Function\n", 402 | " global minimum:\n", 403 | " f(x= 8.05502, y= 9.66459) = -19.2085\n", 404 | " f(x=-8.05502, y= 9.66459) = -19.2085\n", 405 | " f(x= 8.05502, y=-9.66459) = -19.2085\n", 406 | " f(x=-8.05502, y=-9.66459) = -19.2085\n", 407 | " bounds: -10 <= x, y <= 10\n", 408 | " '''\n", 409 | " x, y = xy[0], xy[1]\n", 410 | " return -abs(np.sin(x)*np.cos(y)*np.exp(abs(1-(np.sqrt(x**2 + y**2)/np.pi))))\n", 411 | "mrnge = [-10,10]\n", 412 | "optimum = -19.2085" 413 | ] 414 | }, 415 | { 416 | "cell_type": "code", 417 | "execution_count": 21, 418 | "metadata": { 419 | "code_folding": [ 420 | 0 421 | ] 422 | }, 423 | "outputs": [], 424 | "source": [ 425 | "def f(xy): #tripod\n", 426 | " '''Tripod Function\n", 427 | " Parameters\n", 428 | " ----------\n", 429 | " xy : list\n", 430 | " Returns\n", 431 | " -------\n", 432 | " float\n", 433 | " Notes\n", 434 | " -----\n", 435 | " Bounds: x_i in [-100, 100] for i=1,2\n", 436 | " Global minimum: f(x)=0 at x=[0,-50]\n", 437 | " References\n", 438 | " ----------\n", 439 | " S. Rahnamyan, H. R. Tizhoosh, N. M. M. Salama, “A Novel Population\n", 440 | " Initialization Method for Accelerating Evolutionary Algorithms”\n", 441 | " Computers and Mathematics with Applications, vol. 53, no. 10,\n", 442 | " pp. 1605-1614, 2007.\n", 443 | " '''\n", 444 | "\n", 445 | " x1, x2 = xy[0], xy[1]\n", 446 | " p_x1 = 1 if x1>=0 else 0\n", 447 | " p_x2 = 1 if x2>=0 else 0\n", 448 | "\n", 449 | " a = p_x2 * (1 + p_x1)\n", 450 | " b = abs(x1 + 50*p_x2*(1-2*p_x1))\n", 451 | " c = abs(x2 + 50*(1-2*p_x2))\n", 452 | " return a + b + c\n", 453 | "mrnge = [-100,100]\n", 454 | "optimum = 0" 455 | ] 456 | }, 457 | { 458 | "cell_type": "markdown", 459 | "metadata": {}, 460 | "source": [ 461 | "## SPGD Begin" 462 | ] 463 | }, 464 | { 465 | "cell_type": "code", 466 | "execution_count": 7, 467 | "metadata": { 468 | "code_folding": [ 469 | 0 470 | ] 471 | }, 472 | "outputs": [], 473 | "source": [ 474 | "def derivative (arr, pos):\n", 475 | " h = 0.000000001\n", 476 | " temp = arr.copy()\n", 477 | " temp[pos] = temp[pos] + h\n", 478 | " num = f(temp) - f(arr)\n", 479 | " return num/h" 480 | ] 481 | }, 482 | { 483 | "cell_type": "code", 484 | "execution_count": 8, 485 | "metadata": { 486 | "code_folding": [ 487 | 0 488 | ] 489 | }, 490 | "outputs": [], 491 | "source": [ 492 | "def printing (minimalist):\n", 493 | " lst=[]\n", 494 | " for i in range (len(minimalist)):\n", 495 | " lst.append(f(minimalist[i]))\n", 496 | " minima_arr.append(min (lst))" 497 | ] 498 | }, 499 | { 500 | "cell_type": "code", 501 | "execution_count": 9, 502 | "metadata": { 503 | "code_folding": [ 504 | 0 505 | ] 506 | }, 507 | "outputs": [], 508 | "source": [ 509 | "def descent(tid, w, a, e):\n", 510 | " for i in range(e*Iter_P_Ep, e * Iter_P_Ep + Iter_P_Ep):\n", 511 | " for pos in range(dim):\n", 512 | " if (w[pos] < rnge[0] or w[pos] > rnge[1]):\n", 513 | " w[pos] = random.randint(rnge[0],rnge[1])\n", 514 | " \n", 515 | " V[tid][i] = w\n", 516 | " for pos in range(dim):\n", 517 | " w[pos] = w[pos] - a * derivative(w,pos)\n", 518 | " \n", 519 | " \n", 520 | " global CLM\n", 521 | " if f( V[tid][i]) < fval[0]:\n", 522 | " fval[0] = f( V[tid][i])\n", 523 | " CLM = V[tid][i]" 524 | ] 525 | }, 526 | { 527 | "cell_type": "code", 528 | "execution_count": 26, 529 | "metadata": { 530 | "code_folding": [ 531 | 0 532 | ] 533 | }, 534 | "outputs": [], 535 | "source": [ 536 | "def check_pre_convrg ():\n", 537 | " pre_convg = [] \n", 538 | " global Turn, skip\n", 539 | " for i in range(ep-5, len(minimalist)):\n", 540 | " pre_convg.append(f(minimalist[i]))\n", 541 | "\n", 542 | " if(statistics.stdev(pre_convg) == 0 and Turn == 0):\n", 543 | " lrn = np.linspace(0.1, 0.001, num=Tc)\n", 544 | " Turn +=1\n", 545 | " skip = 3\n", 546 | "\n", 547 | " if(skip > 0):\n", 548 | " skip = skip -1\n", 549 | "\n", 550 | " elif(statistics.stdev(pre_convg) == 0 and Turn == 1 and skip ==0):\n", 551 | " lrn = np.linspace(0.01, 0.0001, num=Tc)\n", 552 | " Turn +=1\n", 553 | " skip = 3\n", 554 | "\n", 555 | " elif(statistics.stdev(pre_convg) == 0 and Turn == 2 and skip == 0):\n", 556 | " lrn = np.linspace(0.001,0.000001, num = Tc)\n", 557 | " Turn +=1 " 558 | ] 559 | }, 560 | { 561 | "cell_type": "code", 562 | "execution_count": 30, 563 | "metadata": { 564 | "code_folding": [ 565 | 0, 566 | 1 567 | ] 568 | }, 569 | "outputs": [], 570 | "source": [ 571 | "def reduce_search_circle ():\n", 572 | " if(ep % 5 == 0 and ep !=0):\n", 573 | " dummy = 5\n", 574 | " tempmin, tempmax=[],[]\n", 575 | " for i in range(ep-dummy, len(minimalist)):\n", 576 | " tempmin.append(math.floor(min(minimalist[i])))\n", 577 | " tempmax.append(math.ceil(max(minimalist[i])))\n", 578 | " rnge[0]= min(tempmin)\n", 579 | " rnge[1] = max(tempmax)\n", 580 | " if (rnge[0] == rnge[1]):\n", 581 | " rnge[0],rnge[1] = mrnge[0],mrnge[1]" 582 | ] 583 | }, 584 | { 585 | "cell_type": "code", 586 | "execution_count": 66, 587 | "metadata": { 588 | "code_folding": [ 589 | 3 590 | ] 591 | }, 592 | "outputs": [ 593 | { 594 | "name": "stdout", 595 | "output_type": "stream", 596 | "text": [ 597 | "Run: 0\n", 598 | "0 20 0.0\n", 599 | "Run: 1\n", 600 | "1 16 0.0\n", 601 | "Finished in 0.67 second(s)\n" 602 | ] 603 | } 604 | ], 605 | "source": [ 606 | "minima_arr = []\n", 607 | "avg_epp = []\n", 608 | "start = time.perf_counter()\n", 609 | "for run in range(50): #Running SPGD 50 times for statistcal analysis\n", 610 | " print(\"Run: \", run)\n", 611 | " \n", 612 | " #Begin Intialization of various variables\n", 613 | " rnge = [mrnge[0],mrnge[1]]\n", 614 | " fval, CLM = [9999999],np.zeros(dim)\n", 615 | " Turn, skip = 0,-1\n", 616 | " Episodes, Iter_P_Ep = 50, 20\n", 617 | " LocMinima,minimalist, epsilon, Tc =[] ,[], 1, 25 #Threadcount\n", 618 | " decay = epsilon/Episodes\n", 619 | "\n", 620 | " V,T = np.zeros((Tc, Episodes * Iter_P_Ep, dim)), [0] * Tc\n", 621 | " lrn = np.linspace(1, 0.001, num=Tc)\n", 622 | " init_xy = np.random.uniform(rnge[0],rnge[1], size=(Tc, dim))\n", 623 | " \n", 624 | " #End Intialization\n", 625 | " \n", 626 | " #Begin SPGD Execution\n", 627 | " for ep in range(Episodes):\n", 628 | " \n", 629 | " for i in range(Tc):\n", 630 | " T[i] = threading.Thread(target=descent, args=(i, init_xy[i],lrn[i], ep)) \n", 631 | " T[i].start() \n", 632 | " for i in range(Tc):\n", 633 | " T[i].join()\n", 634 | "\n", 635 | " Edge_Loc = ep*Iter_P_Ep + (Iter_P_Ep-1)\n", 636 | "\n", 637 | " minimalist.append(CLM) #Remember Local Minima Encountered\n", 638 | " \n", 639 | " reduce_search_circle() \n", 640 | " if(ep > 5):\n", 641 | " check_pre_convrg()\n", 642 | " \n", 643 | " #Exploitation Vs Exploration\n", 644 | " if(random.uniform(0,1) >= epsilon): #Exploitation\n", 645 | " for Tid in range(Tc):\n", 646 | " if (random.uniform(0,1) >= 0.2):\n", 647 | " init_xy[Tid] = CLM #Assemble at best known location\n", 648 | " else: #Chooses to explore 20% of the time, to avoid loc minima.\n", 649 | " for pos in range(dim):\n", 650 | " init_xy[Tid][pos] = np.random.triangular(rnge[0],CLM[pos],rnge[1])\n", 651 | "\n", 652 | " else:\n", 653 | " #EXPLORATION\n", 654 | " for Tid in range (Tc):\n", 655 | " #Continue as and where you are\n", 656 | " if (random.uniform(0,1) >= 0.5): #Dont Change\n", 657 | " init_xy[Tid] = V[Tid][Edge_Loc]\n", 658 | " else: #Pure Exploration\n", 659 | " for pos in range(dim):\n", 660 | " init_xy[Tid][pos] = np.random.triangular(rnge[0],CLM[pos],rnge[1])\n", 661 | " \n", 662 | " \n", 663 | " if(ep >10 ):\n", 664 | " convergence = [] \n", 665 | " for i in range(ep-10, len(minimalist)):\n", 666 | " convergence.append(f(minimalist[i]))\n", 667 | " if(statistics.stdev(convergence) == 0):\n", 668 | " print(run, ep, f(CLM))\n", 669 | " avg_epp.append(ep)\n", 670 | " break\n", 671 | " epsilon = epsilon - decay\n", 672 | " printing(minimalist)\n", 673 | "finish = time.perf_counter()\n", 674 | "print(f'Finished in {round(finish-start, 2)} second(s)')" 675 | ] 676 | }, 677 | { 678 | "cell_type": "code", 679 | "execution_count": 35, 680 | "metadata": { 681 | "code_folding": [ 682 | 0 683 | ] 684 | }, 685 | "outputs": [ 686 | { 687 | "name": "stdout", 688 | "output_type": "stream", 689 | "text": [ 690 | "9.063286299237916e-08 2.0419683007588674e-05 1.0255157935290526e-05 1.4374809212325405e-05\n", 691 | "0.02\n" 692 | ] 693 | }, 694 | { 695 | "data": { 696 | "text/plain": [ 697 | "49.44" 698 | ] 699 | }, 700 | "execution_count": 35, 701 | "metadata": {}, 702 | "output_type": "execute_result" 703 | } 704 | ], 705 | "source": [ 706 | "#Summary\n", 707 | "import statistics\n", 708 | "print(min(minima_arr), max(minima_arr),statistics.mean(minima_arr) ,statistics.stdev(minima_arr))\n", 709 | "j=0\n", 710 | "for i in range(len(minima_arr)):\n", 711 | " if abs(minima_arr[i] - optimum )< 0.000001 :\n", 712 | " #print(j,\"success\", minima_arr[i])\n", 713 | " j+=1\n", 714 | "print(j/50)\n", 715 | "dum = avg_epp\n", 716 | "for _ in range(50 - len(avg_epp)):\n", 717 | " dum.append(50)\n", 718 | "statistics.mean(dum) " 719 | ] 720 | } 721 | ], 722 | "metadata": { 723 | "kernelspec": { 724 | "display_name": "Python 3", 725 | "language": "python", 726 | "name": "python3" 727 | }, 728 | "language_info": { 729 | "codemirror_mode": { 730 | "name": "ipython", 731 | "version": 3 732 | }, 733 | "file_extension": ".py", 734 | "mimetype": "text/x-python", 735 | "name": "python", 736 | "nbconvert_exporter": "python", 737 | "pygments_lexer": "ipython3", 738 | "version": "3.7.3" 739 | } 740 | }, 741 | "nbformat": 4, 742 | "nbformat_minor": 2 743 | } 744 | --------------------------------------------------------------------------------