{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Multi-objective optimization with achievement scalarizing functions\n", "\n", "Here we are going to a discrete optimization problem with multiple objectives. The experiment involves selecting fragments (A, B, and C) which are linked together to form a dye molecule. The molecules are then tested for emission." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd\n", "from scipy import stats\n", "import matplotlib.pyplot as plt\n", "import matplotlib\n", "%matplotlib inline\n", "import matplotlib.lines as mlines\n", "from matplotlib.colors import LinearSegmentedColormap, ListedColormap\n", "import seaborn as sns\n", "import os\n", "import sys\n", "import pickle\n", "from glob import glob\n", "\n", "from olympus import Surface\n", "from olympus.campaigns import ParameterSpace, Campaign\n", "from olympus.objects import ParameterContinuous\n", "from olympus.datasets import Dataset\n", "from atlas.planners.gp.planner import GPPlanner\n", "from atlas.unknown_constraints.benchmark_functions import BraninConstr\n", "\n", "sns.set(style='ticks', context='notebook', font_scale=1.2)\n", "from cmcrameri import cm\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The emission signature is characterized using spectroscopy, and we want to optimize multiple propertes:\n", " - Peak score: which is the integral in a wavelength region in the emission spectra (maximize);\n", " - Spectral overlap: which is the overlap between absorption and emission bands (minimize);\n", " - Fluorescence rate: rate of fluorescence (maximize)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "BUDGET = 200\n", "NUM_INIT_DESIGN = 10" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n",
"\n"
],
"text/plain": [
"\u001b[38;2;5;25;35m───────────────────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n", " Welcome to ATLAS! \n", "\n" ], "text/plain": [ "\u001b[1;38;2;5;166;251m \u001b[0m\u001b[1;38;2;5;166;251m \u001b[0m\u001b[1;38;2;5;166;251m \u001b[0m\n", "\u001b[1;38;2;5;166;251m \u001b[0m\u001b[1;38;2;5;166;251mWelcome to ATLAS!\u001b[0m\u001b[1;38;2;5;166;251m \u001b[0m\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
Made with 💕 in 🇨🇦 \n", " \n", "\n" ], "text/plain": [ "\u001b[38;2;0;100;148m \u001b[0m\u001b[38;2;0;100;148mMade with 💕 in 🇨🇦\u001b[0m\u001b[38;2;0;100;148m \u001b[0m\n", "\u001b[38;2;0;100;148m \u001b[0m\u001b[38;2;0;100;148m \u001b[0m\u001b[38;2;0;100;148m \u001b[0m\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n",
"\n"
],
"text/plain": [
"\u001b[38;2;5;25;35m───────────────────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"───────────────────────────── Initial design phase ─────────────────────────────\n",
"\n"
],
"text/plain": [
"\u001b[38;2;5;166;251m───────────────────────────── Initial design phase ─────────────────────────────\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"dataset = Dataset(kind='dye_lasers')\n",
"\n",
"campaign = Campaign()\n",
"campaign.set_param_space(dataset.param_space)\n",
"\n",
"planner = GPPlanner(\n",
" goal='minimize', # always use minimize if usign Hyparameter scalarizer\n",
" is_moo=True, # flag the multi-objective optimization\n",
" num_init_design=NUM_INIT_DESIGN,\n",
" scalarizer_kind='Hypervolume',\n",
" value_space=dataset.value_space,\n",
" goals=['max', 'min', 'max'], # goals here for each individual measurement goal\n",
")\n",
"planner.set_param_space(dataset.param_space)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"iter_ = 0\n",
"while len(campaign.observations.get_values()) < BUDGET: \n",
"\n",
" print(f'\\nITER : {iter_+1}/{BUDGET}\\n')\n",
"\n",
" samples = planner.recommend(campaign.observations)\n",
"\n",
" for sample in samples:\n",
" measurement = dataset.run(sample, return_paramvector=True, noiseless=True)[0]\n",
" print('SAMPLE : ', sample)\n",
" print('MEASUREMENT : ', measurement)\n",
" \n",
" campaign.add_and_scalarize(sample, measurement, planner.scalarizer)\n",
"\n",
" iter_ += 1\n",
"\n",
"x0_col = campaign.observations.get_params()[:, 0]\n",
"x1_col = campaign.observations.get_params()[:, 1]\n",
"x2_col = campaign.observations.get_params()[:, 2]\n",
"\n",
"obj0_col = campaign.observations.get_values()[:, 0]\n",
"obj1_col = campaign.observations.get_values()[:, 1]\n",
"obj2_col = campaign.observations.get_values()[:, 2]\n",
"\n",
"scalar = campaign.scalarized_values.flatten()\n",
"\n",
"\n",
"data = pd.DataFrame({\n",
" 'frag_a': x0_col,\n",
" 'frag_b': x1_col,\n",
" 'frag_c': x2_col,\n",
" 'peak_score': obj0_col,\n",
" 'spectral_overlap': obj1_col,\n",
" 'fluo_rate': obj2_col,\n",
" 'scalar': scalar\n",
"})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here we plot the results. Remember that we are scalarizing and optimizing the hypervolume, so the properties are not explicitly maximized, rather the combined score is. The traces of the optimization are shown below."
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"| \n", " | frag_a | \n", "frag_b | \n", "frag_c | \n", "peak_score | \n", "spectral_overlap | \n", "fluo_rate | \n", "scalar | \n", "
|---|---|---|---|---|---|---|---|
| 0 | \n", "OB(O)c1ccnc(F)c1 | \n", "C[N+]12CC(=O)O[B-]1(c1sccc1Br)OC(=O)C2 | \n", "Brc1ccc2c(c1)C1(c3ccccc3-c3ccccc31)c1cc(Br)ccc1-2 | \n", "0.782739 | \n", "0.103927 | \n", "0.494931 | \n", "0.536276 | \n", "
| 1 | \n", "OB(O)c1ccnc(-n2c3ccccc3c3ccccc32)c1 | \n", "C[N+]12CC(=O)O[B-]1(c1sccc1Br)OC(=O)C2 | \n", "Fc1cc(Br)c(F)cc1Br | \n", "0.009806 | \n", "0.043146 | \n", "0.003347 | \n", "0.999962 | \n", "
| 2 | \n", "OB(O)c1cc(F)cc(F)c1 | \n", "C[N+]12CC(=O)O[B-]1(c1cc(I)cc(C(F)(F)F)c1)OC(=... | \n", "Brc1ccc2nc3ccc(Br)cc3nc2c1 | \n", "0.006086 | \n", "0.003755 | \n", "0.001295 | \n", "0.999991 | \n", "
| 3 | \n", "CC(C)(C)OC(=O)n1ccc2cc(B3OC(C)(C)C(C)(C)O3)ccc21 | \n", "C[N+]12CC(=O)O[B-]1(c1c(F)cccc1Br)OC(=O)C2 | \n", "Brc1ccc(Br)o1 | \n", "0.102646 | \n", "0.108302 | \n", "0.310615 | \n", "0.962472 | \n", "
| 4 | \n", "OB(O)c1ccc(F)c2ccccc12 | \n", "C[N+]12CC(=O)O[B-]1(c1ccc(Br)cc1)OC(=O)C2 | \n", "C[Si](C)(c1ccc(Br)cc1)c1ccc(Br)cc1 | \n", "0.001499 | \n", "0.279819 | \n", "1.105198 | \n", "0.999658 | \n", "