From 5d3278382a05ed0f002c8ac88547ac7192456cca Mon Sep 17 00:00:00 2001 From: sabinala Date: Tue, 23 Jul 2024 16:06:44 -0700 Subject: [PATCH] moving callback for progress_hook --- docs/source/interfaces.ipynb | 19 ++++++++++--------- pyciemss/interfaces.py | 5 ++++- pyciemss/ouu/ouu.py | 11 ++--------- tests/test_interfaces.py | 16 +++++++++------- 4 files changed, 25 insertions(+), 26 deletions(-) diff --git a/docs/source/interfaces.ipynb b/docs/source/interfaces.ipynb index 64310301..65bf0d72 100644 --- a/docs/source/interfaces.ipynb +++ b/docs/source/interfaces.ipynb @@ -16,7 +16,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -2514,7 +2514,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -2542,15 +2542,15 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - " 46%|██████████████████████▏ | 37/80 [00:41<00:47, 1.11s/it]\n", - " 45%|█████████████████████▋ | 38/84 [00:04<00:04, 9.46it/s]" + "100%|███████████████████████████████████████████████████| 4/4 [00:16<00:00, 4.16s/it]\n", + "100%|███████████████████████████████████████████████████| 4/4 [00:03<00:00, 1.08it/s]" ] }, { @@ -2564,7 +2564,7 @@ " x: [ 1.389e-01]\n", " nit: 3\n", " minimization_failures: 3\n", - " nfev: 38\n", + " nfev: 30\n", " lowest_optimization_result: message: Optimization terminated successfully.\n", " success: True\n", " status: 1\n", @@ -2591,10 +2591,11 @@ " start_time = intervention_time,\n", ")\n", "\n", + "# Progress bar\n", + "pbar = tqdm(total=maxiter + 1)\n", "\n", - "pbar = tqdm(total=(maxfeval + 1) * (maxiter + 1))\n", - "\n", - "def update_progress(xk):\n", + "# update_progress(coordinate, function_min, accept)\n", + "def update_progress(xk, xf, xa):\n", " pbar.update(1)\n", "\n", "opt_result = pyciemss.optimize(\n", diff --git a/pyciemss/interfaces.py b/pyciemss/interfaces.py index 6d852feb..f5508dc1 100644 --- a/pyciemss/interfaces.py +++ b/pyciemss/interfaces.py @@ -791,7 +791,7 @@ def optimize( maxfeval: int = 25, verbose: bool = False, roundup_decimal: int = 4, - progress_hook: Callable = lambda i, feval: None, + progress_hook: Callable[[np.array, float, bool], bool] = lambda x, f, accept: False, ) -> Dict[str, Any]: r""" Load a model from a file, compile it into a probabilistic program, and optimize under uncertainty with risk-based @@ -856,6 +856,9 @@ def optimize( - Whether to print out the optimization under uncertainty progress. roundup_decimal: int - Number of significant digits for the optimal policy. + progress_hook: Callable[[np.array, float, bool], bool], + - A callback function that takes in the current coordinate(s) as an np.array, the minimal function evaluation at the coordinate(s), and whether or not that minimal value was accepted. When the function returns True, the basinhopping routine will stop. + - This can be used to implement custom progress bars and/or early stopping criteria. Returns: result: Dict[str, Any] diff --git a/pyciemss/ouu/ouu.py b/pyciemss/ouu/ouu.py index ea03692b..962511fd 100644 --- a/pyciemss/ouu/ouu.py +++ b/pyciemss/ouu/ouu.py @@ -19,8 +19,6 @@ ) from pyciemss.ouu.risk_measures import alpha_superquantile -# from tqdm import tqdm - class RandomDisplacementBounds: """ @@ -187,7 +185,7 @@ def __init__( maxfeval: int = 100, maxiter: int = 100, u_bounds: np.ndarray = np.atleast_2d([[0], [1]]), - progress_hook: Callable = lambda i: None, + progress_hook: Callable[[np.array, float, bool], bool] = lambda x, f, accept: False, ): self.x0 = np.squeeze(np.array([x0])) self.objfun = objfun @@ -203,18 +201,12 @@ def __init__( # self.kwargs = kwargs def solve(self): - # pbar = tqdm(total=self.maxfeval * (self.maxiter + 1)) - - # def update_progress(xk): - # pbar.update(1) - # wrapper around SciPy optimizer(s) # rhobeg is set to 10% of longest euclidean distance minimizer_kwargs = dict( constraints=self.constraints, method="COBYLA", tol=1e-5, - callback=self.progress_hook, options={ "rhobeg": 0.1 * np.linalg.norm(self.u_bounds[1, :] - self.u_bounds[0, :]), @@ -234,6 +226,7 @@ def solve(self): niter=self.maxiter, minimizer_kwargs=minimizer_kwargs, take_step=take_step, + callback=self.progress_hook, interval=2, disp=False, ) diff --git a/tests/test_interfaces.py b/tests/test_interfaces.py index 32ce2c7e..d65e53d5 100644 --- a/tests/test_interfaces.py +++ b/tests/test_interfaces.py @@ -565,13 +565,16 @@ def test_optimize(model_fixture, start_time, end_time, num_samples): class TestProgressHook: def __init__(self): - self.iterations = [] - # self.function_evals = [] + self.coordinates = [] + self.function_min = [] + self.accept = [] - def __call__(self, iteration): + def __call__(self, x, f, accept): # Log the iteration number - self.iterations.append(iteration) - # self.function_evals.append(feval) + self.coordinates.append(x) + self.function_min.append(f) + self.accept.append(accept) + print(f"Coordinate(s): {x}, function min: {f}, accept: {accept}") progress_hook = TestProgressHook() @@ -631,10 +634,9 @@ def __call__(self, iteration): intervened_result_subset, start_time, end_time, logging_step_size, num_samples ) - assert len(progress_hook.iterations) == (optimize_kwargs["maxfeval"] + 1) * ( + assert len(progress_hook.coordinates) == ( optimize_kwargs["maxiter"] + 1 ) - # assert len(progress_hook.function_evals) == optimize_kwargs["maxfeval"] @pytest.mark.parametrize("model_fixture", MODELS)