From ec22cda48e7921ce93d28b44c2ac99cb7edebba9 Mon Sep 17 00:00:00 2001 From: relf Date: Thu, 30 Nov 2023 15:48:39 +0100 Subject: [PATCH] Add exmaple Egor as a service --- doc/Egor_Tutorial.ipynb | 264 ++++++++++++++++++++++++++++++---------- 1 file changed, 197 insertions(+), 67 deletions(-) diff --git a/doc/Egor_Tutorial.ipynb b/doc/Egor_Tutorial.ipynb index 766b8584..5f6180c0 100644 --- a/doc/Egor_Tutorial.ipynb +++ b/doc/Egor_Tutorial.ipynb @@ -158,25 +158,82 @@ "id": "45641636", "metadata": {}, "source": [ - "### Continuous optimization with _Egor_" + "### Continuous optimization" ] }, { "cell_type": "code", "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "egor = egx.Egor(xspecs_xsinx, n_cstr=n_cstr_xsinx) # see help(egor) for options" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimization f=[-15.12510323] at [18.93509877]\n", + "Optimization history: \n", + "Inputs = [[24.16632486]\n", + " [11.46890607]\n", + " [18.44757257]\n", + " [ 7.79926692]\n", + " [ 2.17759007]\n", + " [18.12777788]\n", + " [18.68945993]\n", + " [18.9361961 ]\n", + " [18.93481137]\n", + " [18.93489165]\n", + " [18.93509877]\n", + " [18.93564231]\n", + " [18.93490956]]\n", + "Outputs = [[ 6.01070335]\n", + " [ 4.53248411]\n", + " [-14.93205423]\n", + " [ 4.21159462]\n", + " [ 0.54035662]\n", + " [-14.60466485]\n", + " [-15.07551091]\n", + " [-15.12510243]\n", + " [-15.1251031 ]\n", + " [-15.12510315]\n", + " [-15.12510323]\n", + " [-15.12510308]\n", + " [-15.12510316]]\n" + ] + } + ], + "source": [ + "res = egor.minimize(xsinx, max_iters=8)\n", + "print(f\"Optimization f={res.y_opt} at {res.x_opt}\")\n", + "print(\"Optimization history: \")\n", + "print(f\"Inputs = {res.x_hist}\")\n", + "print(f\"Outputs = {res.y_hist}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 8, "id": "c8942031", "metadata": {}, "outputs": [], "source": [ - "egor = egx.Egor(g24, xspecs_g24, \n", - " n_doe=10, \n", - " n_cstr=n_cstr_g24, \n", - " cstr_tol=[1e-3, 1e-3],\n", - " infill_strategy=egx.InfillStrategy.WB2,\n", - " target=-5.5,\n", - " # outdir=\"./out\",\n", - " # hot_start=True\n", - " ) # see help(egor) for options\n", + "egor = egx.Egor(xspecs_g24, \n", + " n_doe=10, \n", + " n_cstr=n_cstr_g24, \n", + " cstr_tol=[1e-3, 1e-3],\n", + " infill_strategy=egx.InfillStrategy.WB2,\n", + " target=-5.5,\n", + " # outdir=\"./out\",\n", + " # hot_start=True\n", + " ) \n", "\n", "# Specify regression and/or correlation models used to build the surrogates of objective and constraints\n", "#egor = egx.Egor(g24, xlimits_g24, n_cstr=n_cstr_g24, n_doe=10,\n", @@ -186,7 +243,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 9, "id": "c12b8e9d", "metadata": {}, "outputs": [ @@ -194,45 +251,89 @@ "name": "stdout", "output_type": "stream", "text": [ - "Optimization f=[-5.50837809e+00 3.84933482e-04 3.56699512e-04] at [2.329518 3.17886009]\n", + "Optimization f=[-5.50857874e+00 -1.02345305e-04 8.35057110e-04] at [2.32959306 3.17898568]\n", "Optimization history: \n", - "Inputs = [[2.14941171 1.2022835 ]\n", - " [2.89591634 3.04421182]\n", - " [1.13129495 3.27983113]\n", - " [2.50882074 2.47459348]\n", - " [1.34917886 1.15978118]\n", - " [1.99449618 0.14570364]\n", - " [1.68323092 3.96900812]\n", - " [0.26740239 1.98981025]\n", - " [0.823056 0.52179224]\n", - " [0.34794318 2.23644392]\n", - " [2.3323044 3.09159185]\n", - " [2.32962545 3.17922313]\n", - " [2.329518 3.17886009]]\n", - "Outputs = [[-3.35169521e+00 -1.00398765e+00 -2.62111904e+00]\n", - " [-5.94012816e+00 -1.24186360e+01 2.88844914e+00]\n", - " [-4.41112609e+00 -6.51809729e-01 3.03904161e+00]\n", - " [-4.98341421e+00 -2.78451535e+00 2.77667993e-01]\n", - " [-2.50896004e+00 -2.38224715e+00 -1.69313518e-01]\n", - " [-2.14019982e+00 -1.85453736e+00 -3.85405403e+00]\n", - " [-5.65223904e+00 1.40041321e+00 7.31474755e-01]\n", - " [-2.25721264e+00 -4.39484898e-01 -1.40405159e+01]\n", - " [-1.34484824e+00 -3.35493157e+00 -7.17152437e-02]\n", - " [-2.58438710e+00 -4.24396527e-01 -9.72535570e+00]\n", - " [-5.42389625e+00 -1.09766687e-01 -7.37742400e-02]\n", - " [-5.50884858e+00 -1.29446921e-04 1.22477349e-03]\n", - " [-5.50837809e+00 3.84933482e-04 3.56699512e-04]]\n" + "Inputs = [[2.02750492 1.84783549]\n", + " [2.43770908 0.79253687]\n", + " [2.83077386 3.33954312]\n", + " [1.61764313 0.13863444]\n", + " [0.42165631 2.71057275]\n", + " [1.22945986 1.04947757]\n", + " [1.12529889 3.10581662]\n", + " [0.62145558 3.60508041]\n", + " [0.0868541 2.01094979]\n", + " [2.26033054 1.3874575 ]\n", + " [2.15407992 3.95417039]\n", + " [2.3260228 3.1921383 ]\n", + " [2.32959306 3.17898568]]\n", + "Outputs = [[-3.87534041e+00 -1.58384279e-01 -2.14611463e+00]\n", + " [-3.23024595e+00 -3.48447274e+00 -1.82157495e+00]\n", + " [-6.17031698e+00 -9.72175238e+00 2.95560230e+00]\n", + " [-1.75627757e+00 -2.62649202e+00 -2.77728535e+00]\n", + " [-3.13222905e+00 -1.75257198e-01 -6.18376493e+00]\n", + " [-2.27893743e+00 -2.74545955e+00 3.89263155e-01]\n", + " [-4.23111551e+00 -8.31877099e-01 2.88510841e+00]\n", + " [-4.22653599e+00 1.37196496e-01 3.62309923e-01]\n", + " [-2.09780388e+00 -4.42715310e-02 -2.62941582e+01]\n", + " [-3.64778804e+00 -1.30504948e+00 -2.08873873e+00]\n", + " [-6.10825031e+00 1.73385454e+00 1.41840902e-01]\n", + " [-5.51816110e+00 4.19898758e-02 -2.72575289e-03]\n", + " [-5.50857874e+00 -1.02345305e-04 8.35057110e-04]]\n" ] } ], "source": [ - "res = egor.minimize(max_iters=30)\n", + "res = egor.minimize(g24, max_iters=30)\n", "print(f\"Optimization f={res.y_opt} at {res.x_opt}\")\n", "print(\"Optimization history: \")\n", "print(f\"Inputs = {res.x_hist}\")\n", "print(f\"Outputs = {res.y_hist}\")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Egor as a service: ask-and-tell interface" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When the user needs to be in control of the optimization loop, `Egor` can be used as a service. \n", + "\n", + "For instance with the `xsinx` objective function, we can do:" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Optimization f=[-15.12510323] at [18.93528147]\n" + ] + } + ], + "source": [ + "xlimits = egx.to_specs([[0.0, 25.0]])\n", + "egor = egx.Egor(xlimits, seed=42) \n", + "\n", + "# initial doe\n", + "x_doe = egx.lhs(xlimits, 3, seed=42)\n", + "y_doe = xsinx(x_doe)\n", + "for _ in range(10): # run for 10 iterations\n", + " x = egor.suggest(x_doe, y_doe) # ask for best location\n", + " x_doe = np.concatenate((x_doe, x))\n", + " y_doe = np.concatenate((y_doe, xsinx(x))) \n", + "res = egor.get_result(x_doe, y_doe)\n", + "print(f\"Optimization f={res.y_opt} at {res.x_opt}\")" + ] + }, { "attachments": {}, "cell_type": "markdown", @@ -253,7 +354,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 11, "id": "6948efc1", "metadata": {}, "outputs": [], @@ -281,7 +382,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 12, "id": "928d1f38", "metadata": {}, "outputs": [ @@ -291,34 +392,28 @@ "text": [ "Optimization f=[-15.12161154] at [19.]\n", "Optimization history: \n", - "Inputs = [[ 7.]\n", - " [24.]\n", - " [11.]\n", - " [ 6.]\n", - " [ 5.]\n", - " [ 4.]\n", - " [17.]\n", + "Inputs = [[23.]\n", + " [ 8.]\n", + " [ 9.]\n", + " [20.]\n", " [18.]\n", " [19.]]\n", - "Outputs = [[ 3.14127616]\n", - " [ 4.91604976]\n", - " [ 5.1356682 ]\n", - " [ 1.78601478]\n", - " [ 0.68929352]\n", - " [ 0.07924194]\n", - " [-12.35295142]\n", + "Outputs = [[ -1.48334497]\n", + " [ 4.45696985]\n", + " [ 5.41123083]\n", + " [-14.15453288]\n", " [-14.43198471]\n", " [-15.12161154]]\n" ] } ], "source": [ - "egor = egx.Egor(mixint_xsinx, xspecs_mixint_xsinx, \n", + "egor = egx.Egor(xspecs_mixint_xsinx, \n", " n_doe=3, \n", " infill_strategy=egx.InfillStrategy.EI,\n", " target=-15.12,\n", " ) # see help(egor) for options\n", - "res = egor.minimize(max_iters=30)\n", + "res = egor.minimize(mixint_xsinx, max_iters=30)\n", "print(f\"Optimization f={res.y_opt} at {res.x_opt}\")\n", "print(\"Optimization history: \")\n", "print(f\"Inputs = {res.x_hist}\")\n", @@ -355,7 +450,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 13, "id": "f1615d5c", "metadata": {}, "outputs": [], @@ -391,7 +486,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 14, "id": "d14fff89", "metadata": {}, "outputs": [ @@ -447,8 +542,8 @@ " egx.XSpec(egx.XType.ENUM, xlimits=[2]),\n", " egx.XSpec(egx.XType.ORD, [0, 2, 3]),\n", "]\n", - "egor = egx.Egor(mixobj, xtypes, seed=42)\n", - "res = egor.minimize(max_iters=10)\n", + "egor = egx.Egor(xtypes, seed=42)\n", + "res = egor.minimize(mixobj, max_iters=10)\n", "print(f\"Optimization f={res.y_opt} at {res.x_opt}\")\n", "print(\"Optimization history: \")\n", "print(f\"Inputs = {res.x_hist}\")\n", @@ -465,7 +560,6 @@ }, { "cell_type": "markdown", - "id": "3b9fadfa", "metadata": {}, "source": [ "## Usage" @@ -473,7 +567,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 15, "id": "b91f14f2", "metadata": {}, "outputs": [ @@ -484,7 +578,7 @@ "Help on Egor in module builtins object:\n", "\n", "class Egor(object)\n", - " | Egor(fun, xspecs, n_cstr=0, cstr_tol=None, n_start=20, n_doe=0, doe=None, regr_spec=Ellipsis, corr_spec=Ellipsis, infill_strategy=Ellipsis, q_points=1, par_infill_strategy=Ellipsis, infill_optimizer=Ellipsis, kpls_dim=None, n_clusters=1, target=Ellipsis, outdir=None, hot_start=False, seed=None)\n", + " | Egor(xspecs, n_cstr=0, cstr_tol=None, n_start=20, n_doe=0, doe=None, regr_spec=Ellipsis, corr_spec=Ellipsis, infill_strategy=Ellipsis, q_points=1, par_infill_strategy=Ellipsis, infill_optimizer=Ellipsis, kpls_dim=None, n_clusters=1, target=Ellipsis, outdir=None, hot_start=False, seed=None)\n", " | \n", " | Optimizer constructor\n", " | \n", @@ -581,7 +675,30 @@ " | \n", " | Methods defined here:\n", " | \n", - " | minimize(self, /, max_iters=20)\n", + " | get_result(self, /, x_doe, y_doe)\n", + " | This function gives the best result given inputs and outputs\n", + " | of the function (objective wrt constraints) under minimization.\n", + " | \n", + " | # Parameters\n", + " | x_doe (array[ns, nx]): ns samples where function has been evaluated\n", + " | y_doe (array[ns, 1 + n_cstr]): ns values of objective and constraints\n", + " | \n", + " | # Returns\n", + " | optimization result\n", + " | x_opt (array[1, nx]): x value where fun is at its minimum subject to constraints\n", + " | y_opt (array[1, nx]): fun(x_opt)\n", + " | \n", + " | get_result_index(self, /, y_doe)\n", + " | This function gives the best evaluation index given the outputs\n", + " | of the function (objective wrt constraints) under minimization.\n", + " | \n", + " | # Parameters\n", + " | y_doe (array[ns, 1 + n_cstr]): ns values of objective and constraints\n", + " | \n", + " | # Returns\n", + " | index in y_doe of the best evaluation\n", + " | \n", + " | minimize(self, /, fun, max_iters=20)\n", " | This function finds the minimum of a given function `fun`\n", " | \n", " | # Parameters\n", @@ -590,9 +707,22 @@ " | \n", " | # Returns\n", " | optimization result\n", - " | x_opt (array[1, nx]): x value where fun is at its minimum subject to constraint\n", + " | x_opt (array[1, nx]): x value where fun is at its minimum subject to constraints\n", " | y_opt (array[1, nx]): fun(x_opt)\n", " | \n", + " | suggest(self, /, x_doe, y_doe)\n", + " | This function gives the next best location where to evaluate the function\n", + " | under optimization wrt to previous evaluations.\n", + " | The function returns several point when multi point qEI strategy is used.\n", + " | \n", + " | # Parameters\n", + " | x_doe (array[ns, nx]): ns samples where function has been evaluated\n", + " | y_doe (array[ns, 1 + n_cstr]): ns values of objecctive and constraints\n", + " | \n", + " | \n", + " | # Returns\n", + " | (array[1, nx]): suggested location where to evaluate objective and constraints\n", + " | \n", " | ----------------------------------------------------------------------\n", " | Static methods defined here:\n", " | \n", @@ -628,4 +758,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +}