{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Tutorial 4: visualizing bees" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "nbsphinx": "hidden" }, "outputs": [], "source": [ "# Set Plotly to render plots as interactive in notebooks (this cell will be hidden: I set \"nbsphinx\": \"hidden\" in the cell metadata)\n", "import plotly.io as pio\n", "pio.renderers.default = \"notebook\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this tutorial, you will learn how to use the `contourplot_bees` from the `beeoptimal.plotting` module.\n", "As its name suggests, the function allows plotting the positions of one or more bees over the function landscape.\n", "\n", "For its basic usage, `contourplot_bees` requires the two following key inputs:\n", "\n", "- `function`: The objective function you are optimizing, provide as a `BenchmarkFunction` object.\n", "- `bee_colony`: A list of bees to plot (e.g., optimal bee or the entire colony at a given iteration).\n", "\n", "Additional optional parameters can be specified to customize the plot, such as `title`, `figsize`, `bounds`, `zoom`, `bee_marker_size`, and `optimal_solution`." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "from beeoptimal.benchmarks import Schwefel2d\n", "from beeoptimal.plotting import contourplot_bees\n", "from beeoptimal import ArtificialBeeColony" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Before plotting the bees, we need to optimize first our function (check the previous tutorial for details)." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Running Optimization: 2%|▏ |[00:00<00:05]" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Early termination: Optimization stagnated at iteration 19 / 1000\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "ABC = ArtificialBeeColony(\n", " colony_size = 100,\n", " function = Schwefel2d.fun,\n", " bounds = Schwefel2d.bounds\n", " )\n", "\n", "ABC.optimize(\n", " max_iters = 1000,\n", " mutation = 'ABC/best/1',\n", " stagnation_tol = 1e-6,\n", " verbose = True,\n", " random_seed = 12345)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "One thing we might want to do is to visualize the optimal bee at the end of the optimization process:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ " \n", " " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "contourplot_bees(\n", " function = Schwefel2d,\n", " bee_colony = [ABC.optimal_bee],\n", " title = 'Optimal Bee after ABC optimization',\n", " )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Alternatively, we might want to visualize the entire colony at a given iteration. In the example below, we visualize the colony at initialization" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "contourplot_bees(\n", " function = Schwefel2d,\n", " bee_colony = ABC.colony_history[0],\n", " title = f\"{Schwefel2d.name} contourplot with bees\",\n", " figsize = (600,600),\n", " bounds = None,\n", " zoom = 1.05,\n", " bee_marker_size = 55,\n", " optimal_solution = ABC.optimal_bee.position\n", " )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, we can use this function in a more sophisticated way in order to visualize the entire optimization process as animated gif." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from PIL import Image\n", "from IPython.display import Image as IPImage\n", "from io import BytesIO\n", "\n", "plots = []\n", "# Adaptive step in order to have gifs with same number of frames\n", "step = max(1, (ABC.actual_iters+1) // 50) #Note: actual_iters +1 to include initial population\n", "for iteration in range(0,(ABC.actual_iters+1),step): \n", " plots.append(\n", " contourplot_bees(\n", " function = Schwefel2d,\n", " bee_colony = ABC.colony_history[iteration],\n", " title = f\"{Schwefel2d.name.upper()} optimization [Iteration {iteration} / {ABC.actual_iters}]\",\n", " optimal_solution = Schwefel2d.optimal_solution,\n", " bounds = None,\n", " zoom = 1.05,\n", " bee_marker_size = 55,\n", " figsize =(500,500)\n", " ))\n", "\n", "images = []\n", "for fig in plots:\n", " # Save each figure to a BytesIO object in memory instead of a file\n", " img_buf = BytesIO()\n", " fig.write_image(img_buf, format=\"png\", scale=1.5) # Save the Plotly figure as PNG into the buffer\n", " img_buf.seek(0) # Rewind the buffer to the start\n", " images.append(Image.open(img_buf)) # Open the image from the buffer\n", " \n", "# Create the GIF\n", "gif_path = '../_static/animated_optimization.gif'\n", "images[0].save(gif_path, save_all=True, append_images=images[1:], duration=200, loop=0)\n", "IPImage(url=gif_path)\n" ] } ], "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.12.1" } }, "nbformat": 4, "nbformat_minor": 2 }