diff --git a/examples/how_pso_topologies_behave_in_pyswarms.ipynb b/examples/how_pso_topologies_behave_in_pyswarms.ipynb new file mode 100644 index 00000000..1a3c792b --- /dev/null +++ b/examples/how_pso_topologies_behave_in_pyswarms.ipynb @@ -0,0 +1,6483 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# How PSO Topologies Behave In `pyswarms`\n", + "\n", + "\n", + "In particle swarm optimization (PSO) a topology is a \"rule\" which indicates how to particles are connected with each other. These connection guide the information flow in the swarm. In the `pyswarms` library there exist five different topologies:\n", + "\n", + "- **The Star topology**: All the particles are connected with each other. A swarm with a Star topology is often called a FIPS (Fully Informed Particle Swarm). This means that every particle has knowledge of the best position that has been found yet in the swarm.\n", + "\n", + "\n", + "- **The Ring topology**: The particles are connected to the $n$ nearest particles.\n", + "\n", + " - The VonNeumann topology: This is a special variant of the Ring topology. It connects to a certain amount of neighbours depending on the dimension and range.\n", + "\n", + "\n", + "- **The Pyramid topology**: The particles are connected in $n$-dimensional simplices (triangles, tetraeder etc.)\n", + "\n", + "\n", + "- **The Random topology**: The particles are connected to $n$ randomly chosen neighbours.\n", + "\n", + "\n", + "The `pyswarms` library also offers the possiblity to choose whether the neighbours are static or dynamic. That is whether the neighbours are assigned only at the start or every iteration. This feature is only available for the Ring, Random and Pyramid topologies. The Star and the VonNeumann topology are always static. In the follwing section we will take a look at the different topologies and how they behave when they traverse the Goldstein-Price function." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "# Change directory to access the pyswarms module\n", + "sys.path.append('../')" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Running on Python version: 3.6.5 (default, Mar 31 2018, 19:45:04) [GCC]\n" + ] + } + ], + "source": [ + "print('Running on Python version: {}'.format(sys.version))" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# Import modules\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from matplotlib import animation, rc\n", + "from IPython.display import HTML\n", + "\n", + "# Import from package\n", + "import pyswarms as ps\n", + "import pyswarms.backend.topology as top\n", + "from pyswarms.utils.functions import single_obj as fx\n", + "from pyswarms.utils.plotters import plot_contour, plot_surface\n", + "from pyswarms.utils.plotters.formatters import Mesher, Designer\n", + "\n", + "# Some more magic so that the notebook will reload external python modules;\n", + "# see http://stackoverflow.com/questions/1907993/autoreload-of-modules-in-ipython\n", + "%load_ext autoreload\n", + "%autoreload 2\n", + "\n", + "rc('animation', html='html5')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Setup\n", + "\n", + "First, we are going to setup a plotting functions so we don't have to reapeat the same code everytime we plot the optimization:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_optimization(options, topology):\n", + "\n", + " bounds = (np.array([-10, -10]), np.array([10, 10]))\n", + " optimizer = ps.single.GeneralOptimizerPSO(n_particles=12,\n", + " dimensions=2,\n", + " options=options,\n", + " topology=topology,\n", + " bounds=bounds)\n", + " \n", + " optimizer.optimize(fx.holdertable, iters=100)\n", + " \n", + " m = Mesher(func=fx.holdertable,\n", + " delta=0.01,\n", + " limits=[(-10, 10), (-10, 10)],\n", + " levels=np.arange(-20, 0, 1))\n", + " \n", + " d = Designer(limits=[(-10, 10), (-10, 10), (-20, 0)],\n", + " label=['x-axis', 'y-axis', 'z-axis'])\n", + " \n", + " animation = plot_contour(pos_history=optimizer.pos_history,\n", + " designer=d,\n", + " mesher=m,\n", + " mark=([8.05502, -8.05502, 9.66459, -9.66459],\n", + " [9.66459, -9.66459, 8.05502, -8.05502]))\n", + " \n", + " pos_history_3d = m.compute_history_3d(optimizer.pos_history)\n", + " animation3d = plot_surface(pos_history=pos_history_3d,\n", + " mesher=m,\n", + " designer=d,\n", + " mark=([8.05502, -8.05502, 8.05502, -8.05502],\n", + " [9.66459, -9.66459, -9.66459, 9.66459],\n", + " [19.2085, 19.2085, 19.2085, 19.2085]))\n", + " \n", + " return animation, animation3d" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The Star topology\n", + "\n", + "The first topology that we are going to visualise is the Star topology. As previously mentioned, every particle has full information about the best performances of the other particles." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "%%capture\n", + "\n", + "# Set up the Star topology optimizer\n", + "options = {\"c1\": 1.49617, \"c2\": 1.49617, \"w\": 0.72984}\n", + "topology = top.Star()\n", + "\n", + "star1, star2 = plot_optimization(options, topology)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "HTML(star1.to_html5_video())" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "HTML(star2.to_html5_video())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Star topology with a high `c1` value\n", + "Now we can play around with the parameters. As you may imagine, if we pass high values for $c1$ (the cognitive parameter) and small values for $c2$ (the social parameter) we can expect the particles to not be seriously affected by the topology. In this case the particles roam around on their own without much notice of the other ones and they will mostly go for their best found value:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "%%capture\n", + "\n", + "options = {\"c1\": 2.0, \"c2\": 0.1, \"w\": 1.0}\n", + "star1, star2 = plot_optimization(options, topology)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "HTML(star1.to_html5_video())" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "HTML(star2.to_html5_video())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "# Save as GIF# Save a \n", + "star1.save('plot_contour.gif', writer='imagemagick', dpi=96)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Star topology with a high `c2` value\n", + "\n", + "This behaviour won't differ in different topologies, so we are not going to inspect a high $c1$ value for other topologies. We can now try out a high $c2$ value. This means that the topology has a huge influence on the particles:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%capture\n", + "\n", + "options = {\"c1\": 0.1, \"c2\": 2, \"w\": 1.0}\n", + "star1, star2 = plot_optimization(options, topology)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "HTML(star1.to_html5_video())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "HTML(star2.to_html5_video())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Star topology with different `w` values\n", + "\n", + "The last parameter we can tweak in the Star topology is the $w$ value. It is called inertia and defines the impact of the the values $c1$ and $c2$ on the randomly assigned velocity. If we use a high intertia $c1$ and $c2$ will only have small effect on the particles and if we use a low inertia they will have a huge effect on the particles. Let's see how it looks with a high inertia value:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%capture\n", + "\n", + "options = {\"c1\": 1.49617, \"c2\": 1.49617, \"w\": 10.0}\n", + "star1, star2 = plot_optimization(options, topology)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "HTML(star1.to_html5_video())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "HTML(star2.to_html5_video())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And now with a small inertia value:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%capture\n", + "\n", + "options = {\"c1\": 1.49617, \"c2\": 1.49617, \"w\": 0.1}\n", + "star1, star2 = plot_optimization(options, topology)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "HTML(star1.to_html5_video())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "HTML(star2.to_html5_video())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}