diff --git a/examples/01_minimal/config.yml b/examples/01_minimal/config.yml index 8458eeb..218b762 100644 --- a/examples/01_minimal/config.yml +++ b/examples/01_minimal/config.yml @@ -76,25 +76,21 @@ graph: estimator: # Posterior estimator network _target_: falcon.estimators.Flow # Flow-based posterior estimation - loop: # Training loop parameters - max_epochs: 300 - batch_size: 128 - early_stop_patience: 32 # Early stopping patience - network: # Neural network architecture - net_type: nsf # Neural spline flow (alternatives: zuko_gf, maf, naf, etc.) - theta_norm: true # Normalize parameter space - norm_momentum: 0.003 # Momentum for online normalization updates + max_epochs: 300 + net_type: nsf # Neural spline flow (alternatives: zuko_gf, maf, naf, etc.) + lr: 0.01 + gamma: 0.5 # Mixing coefficient for amortization weighting embedding: # Neural embedding for observation x _target_: model.E _input_: [x] - optimizer: # Optimizer parameters - lr: 0.01 - lr_decay_factor: 0.5 # LR decay multiplier - scheduler_patience: 16 # LR decay after N stagnant epochs - inference: # Inference and sampling parameters - gamma: 0.5 # Mixing coefficient for amortization weighting - discard_samples: false - log_ratio_threshold: -20 # Stability cutoff for log ratios + batch_size: 128 + early_stop_patience: 32 + theta_norm: true # Normalize parameter space + norm_momentum: 0.003 # Momentum for online normalization updates + lr_decay_factor: 0.5 # LR decay multiplier + lr_patience: 16 # LR decay after N stagnant epochs + discard_samples: false + log_ratio_threshold: -20 # Stability cutoff for log ratios ray: num_gpus: 0 # GPU count per Ray worker (0 = CPU) diff --git a/examples/01_minimal/notebook.ipynb b/examples/01_minimal/notebook.ipynb new file mode 100644 index 0000000..0f035c3 --- /dev/null +++ b/examples/01_minimal/notebook.ipynb @@ -0,0 +1,671 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "99781568", + "metadata": {}, + "source": [ + "# 01 — Minimal Falcon run (notebook API)\n", + "\n", + "This notebook shows the simplest way to run Falcon from Python/Colab:\n", + "load a config, optionally tweak a parameter, launch training, and inspect\n", + "the result. The matching CLI command is:\n", + "\n", + "```bash\n", + "cd examples/01_minimal\n", + "falcon launch -o output/my_run\n", + "```\n", + "\n", + "**Prerequisites**: install Falcon and its dependencies, then run this\n", + "notebook from the `examples/01_minimal/` directory so that the relative\n", + "paths in `config.yml` resolve correctly." + ] + }, + { + "cell_type": "markdown", + "id": "8002b0ce", + "metadata": {}, + "source": [ + "## 1. Load the config" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "5ba40301", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "```yaml\n", + "logging:\n", + " wandb:\n", + " enabled: false\n", + " project: falcon_examples\n", + " group: 01_minimal\n", + " dir: ${run_dir}\n", + " local:\n", + " enabled: true\n", + " dir: ${paths.graph}\n", + "paths:\n", + " imports:\n", + " - ./src\n", + " graph: ${run_dir}/graph\n", + " samples: ${run_dir}/samples\n", + "buffer:\n", + " min_samples: 4096\n", + " max_samples: 32768\n", + " validation_samples: 256\n", + " simulate_count: 64\n", + " simulate_when_full: true\n", + " simulate_interval: 1\n", + " snapshot_every: 10\n", + "graph:\n", + " z:\n", + " evidence:\n", + " - x\n", + " simulator:\n", + " _target_: falcon.priors.Hypercube\n", + " priors:\n", + " - - uniform\n", + " - -100.0\n", + " - 100.0\n", + " - - uniform\n", + " - -100.0\n", + " - 100.0\n", + " - - uniform\n", + " - -100.0\n", + " - 100.0\n", + " estimator:\n", + " _target_: falcon.estimators.Flow\n", + " loop:\n", + " max_epochs: 300\n", + " batch_size: 128\n", + " early_stop_patience: 32\n", + " network:\n", + " net_type: nsf\n", + " theta_norm: true\n", + " norm_momentum: 0.003\n", + " embedding:\n", + " _target_: model.E\n", + " _input_:\n", + " - x\n", + " optimizer:\n", + " lr: 0.01\n", + " lr_decay_factor: 0.5\n", + " scheduler_patience: 16\n", + " inference:\n", + " gamma: 0.5\n", + " discard_samples: false\n", + " log_ratio_threshold: -20\n", + " ray:\n", + " num_gpus: 0\n", + " x:\n", + " parents:\n", + " - z\n", + " simulator:\n", + " _target_: model.Simulate\n", + " npar: 3\n", + " observed: ./data/mock_data.npz['x']\n", + "sample:\n", + " posterior:\n", + " 'n': 1000\n", + "\n", + "```" + ], + "text/plain": [ + "Config(\n", + "logging:\n", + " wandb:\n", + " enabled: false\n", + " project: falcon_examples\n", + " group: 01_minimal\n", + " dir: ${run_dir}\n", + " local:\n", + " enabled: true\n", + " dir: ${paths.graph}\n", + "paths:\n", + " imports:\n", + " - ./src\n", + " graph: ${run_dir}/graph\n", + " samples: ${run_dir}/samples\n", + "buffer:\n", + " min_samples: 4096\n", + " max_samples: 32768\n", + " validation_samples: 256\n", + " simulate_count: 64\n", + " simulate_when_full: true\n", + " simulate_interval: 1\n", + " snapshot_every: 10\n", + "graph:\n", + " z:\n", + " evidence:\n", + " - x\n", + " simulator:\n", + " _target_: falcon.priors.Hypercube\n", + " priors:\n", + " - - uniform\n", + " - -100.0\n", + " - 100.0\n", + " - - uniform\n", + " - -100.0\n", + " - 100.0\n", + " - - uniform\n", + " - -100.0\n", + " - 100.0\n", + " estimator:\n", + " _target_: falcon.estimators.Flow\n", + " loop:\n", + " max_epochs: 300\n", + " batch_size: 128\n", + " early_stop_patience: 32\n", + " network:\n", + " net_type: nsf\n", + " theta_norm: true\n", + " norm_momentum: 0.003\n", + " embedding:\n", + " _target_: model.E\n", + " _input_:\n", + " - x\n", + " optimizer:\n", + " lr: 0.01\n", + " lr_decay_factor: 0.5\n", + " scheduler_patience: 16\n", + " inference:\n", + " gamma: 0.5\n", + " discard_samples: false\n", + " log_ratio_threshold: -20\n", + " ray:\n", + " num_gpus: 0\n", + " x:\n", + " parents:\n", + " - z\n", + " simulator:\n", + " _target_: model.Simulate\n", + " npar: 3\n", + " observed: ./data/mock_data.npz['x']\n", + "sample:\n", + " posterior:\n", + " 'n': 1000\n", + ")" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import falcon\n", + "\n", + "cfg = falcon.config(\"config.yml\")\n", + "cfg # rich repr renders the full YAML in Jupyter" + ] + }, + { + "cell_type": "markdown", + "id": "f0dbca9f", + "metadata": {}, + "source": [ + "## 2. Override parameters for a quick demo run\n", + "\n", + "`override()` returns a new `Config`; the original is unchanged.\n", + "Use dotted paths matching the YAML structure." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1982d332", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "```yaml\n", + "logging:\n", + " wandb:\n", + " enabled: false\n", + " project: falcon_examples\n", + " group: 01_minimal\n", + " dir: ${run_dir}\n", + " local:\n", + " enabled: true\n", + " dir: ${paths.graph}\n", + "paths:\n", + " imports:\n", + " - ./src\n", + " graph: ${run_dir}/graph\n", + " samples: ${run_dir}/samples\n", + "buffer:\n", + " min_samples: 4096\n", + " max_samples: 32768\n", + " validation_samples: 64\n", + " simulate_count: 64\n", + " simulate_when_full: true\n", + " simulate_interval: 1\n", + " snapshot_every: 10\n", + "graph:\n", + " z:\n", + " evidence:\n", + " - x\n", + " simulator:\n", + " _target_: falcon.priors.Hypercube\n", + " priors:\n", + " - - uniform\n", + " - -100.0\n", + " - 100.0\n", + " - - uniform\n", + " - -100.0\n", + " - 100.0\n", + " - - uniform\n", + " - -100.0\n", + " - 100.0\n", + " estimator:\n", + " _target_: falcon.estimators.Flow\n", + " loop:\n", + " max_epochs: 20\n", + " batch_size: 128\n", + " early_stop_patience: 50\n", + " network:\n", + " net_type: nsf\n", + " theta_norm: true\n", + " norm_momentum: 0.003\n", + " embedding:\n", + " _target_: model.E\n", + " _input_:\n", + " - x\n", + " optimizer:\n", + " lr: 0.01\n", + " lr_decay_factor: 0.5\n", + " scheduler_patience: 16\n", + " inference:\n", + " gamma: 0.5\n", + " discard_samples: false\n", + " log_ratio_threshold: -20\n", + " ray:\n", + " num_gpus: 0.3\n", + " x:\n", + " parents:\n", + " - z\n", + " simulator:\n", + " _target_: model.Simulate\n", + " npar: 3\n", + " observed: ./data/mock_data.npz['x']\n", + "sample:\n", + " posterior:\n", + " 'n': 10000\n", + "\n", + "```" + ], + "text/plain": [ + "Config(\n", + "logging:\n", + " wandb:\n", + " enabled: false\n", + " project: falcon_examples\n", + " group: 01_minimal\n", + " dir: ${run_dir}\n", + " local:\n", + " enabled: true\n", + " dir: ${paths.graph}\n", + "paths:\n", + " imports:\n", + " - ./src\n", + " graph: ${run_dir}/graph\n", + " samples: ${run_dir}/samples\n", + "buffer:\n", + " min_samples: 4096\n", + " max_samples: 32768\n", + " validation_samples: 64\n", + " simulate_count: 64\n", + " simulate_when_full: true\n", + " simulate_interval: 1\n", + " snapshot_every: 10\n", + "graph:\n", + " z:\n", + " evidence:\n", + " - x\n", + " simulator:\n", + " _target_: falcon.priors.Hypercube\n", + " priors:\n", + " - - uniform\n", + " - -100.0\n", + " - 100.0\n", + " - - uniform\n", + " - -100.0\n", + " - 100.0\n", + " - - uniform\n", + " - -100.0\n", + " - 100.0\n", + " estimator:\n", + " _target_: falcon.estimators.Flow\n", + " loop:\n", + " max_epochs: 20\n", + " batch_size: 128\n", + " early_stop_patience: 50\n", + " network:\n", + " net_type: nsf\n", + " theta_norm: true\n", + " norm_momentum: 0.003\n", + " embedding:\n", + " _target_: model.E\n", + " _input_:\n", + " - x\n", + " optimizer:\n", + " lr: 0.01\n", + " lr_decay_factor: 0.5\n", + " scheduler_patience: 16\n", + " inference:\n", + " gamma: 0.5\n", + " discard_samples: false\n", + " log_ratio_threshold: -20\n", + " ray:\n", + " num_gpus: 0.3\n", + " x:\n", + " parents:\n", + " - z\n", + " simulator:\n", + " _target_: model.Simulate\n", + " npar: 3\n", + " observed: ./data/mock_data.npz['x']\n", + "sample:\n", + " posterior:\n", + " 'n': 10000\n", + ")" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cfg = cfg.override(\n", + " \"buffer.min_samples=512\",\n", + " \"buffer.max_samples=1024\",\n", + " \"buffer.validation_samples=64\",\n", + " \"graph.z.estimator.loop.max_epochs=20\",\n", + " \"graph.z.estimator.loop.early_stop_patience=50\",\n", + " \"graph.z.ray.num_gpus=0.3\",\n", + " \"sample.posterior.n=1000\",\n", + ")\n", + "cfg" + ] + }, + { + "cell_type": "markdown", + "id": "42ff1816", + "metadata": {}, + "source": [ + "## 3. Launch training\n", + "\n", + "`falcon.launch()` blocks until training completes and returns a `Run`\n", + "object pointing at the output directory. Ray is started automatically\n", + "on the first call if it is not already running." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "c41270d0", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/weniger/.local/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n", + "2026-06-08 14:27:14,241\tINFO util.py:154 -- Missing packages: ['ipywidgets']. Run `pip install -U ipywidgets`, then restart the notebook server for rich notebook output.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2026-06-08T14:27:18 [INFO] falcon v0.4.3.dev10+gbbaf70e3c.d20260608\n", + "2026-06-08T14:27:18 [INFO] Output: output/notebook_run3\n", + "2026-06-08T14:27:18 [INFO] Ray: 145.136.62.39:58813 (new local instance)\n", + "2026-06-08T14:27:18 [INFO] Resources: 72 CPU, 1 GPU, 317.9 GB\n", + "2026-06-08T14:27:18 [INFO] Falcon graph structure:\n", + " Node name List of parents Class name\n", + "* z <- | falcon.priors.Hypercube\n", + "* x <- z | model.Simulate \n", + "\n", + "2026-06-08T14:27:18 [INFO] Observed: x [1, 3]\n", + "2026-06-08T14:27:18 [INFO] Spinning up graph...\n", + "2026-06-08T14:27:21 [INFO] ✓ z\n", + "2026-06-08T14:27:23 [INFO] ✓ x\n", + "2026-06-08T14:27:26 [INFO] Generating 4160 initial samples...\n", + "2026-06-08T14:27:29 [ERROR] \u001b[36m(DatasetManagerActor pid=405947)\u001b[0m Using blocking ray.get inside async actor. This blocks the event loop. Please use `await` on object ref with asyncio.gather if you want to yield execution to the event loop instead.\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[36m(DatasetManagerActor pid=405947)\u001b[0m Using blocking ray.get inside async actor. This blocks the event loop. Please use `await` on object ref with asyncio.gather if you want to yield execution to the event loop instead.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2026-06-08T14:27:30 [INFO] Initial samples ready (0 loaded, 4160 generated)\n", + "2026-06-08T14:27:30 [INFO] \n", + "2026-06-08T14:27:30 [INFO] Starting analysis. Monitor with: falcon monitor\n", + "2026-06-08T14:27:30 [INFO] [z] Training started\n", + "2026-06-08T14:28:33 [INFO] [z] epoch 15/20, loss -7.83\n", + "2026-06-08T14:28:33 [INFO] Buffer: 5504 train, 64 val (5568 total)\n", + "2026-06-08T14:28:52 [INFO] [z] Training completed (loss: -3.9760)\n", + "2026-06-08T14:28:52 [INFO] \n", + "2026-06-08T14:28:52 [INFO] Analysis completed.\n", + "2026-06-08T14:28:52 [INFO] Generating 10000 posterior samples...\n", + "2026-06-08T14:30:31 [INFO] ============================================================\n", + "2026-06-08T14:30:31 [INFO] falcon launch failed (RayTaskError(OutOfMemoryError): \u001b[36mray::NodeWrapper.sample_posterior()\u001b[39m (pid=405936, ip=145.136.62.39, actor_id=837d11a5132792cd1f3844c901000000, repr=)\n", + " File \"/home/weniger/.conda/envs/emri_few_timm/lib/python3.10/concurrent/futures/_base.py\", line 438, in result\n", + " return self.__get_result()\n", + " File \"/home/weniger/.conda/envs/emri_few_timm/lib/python3.10/concurrent/futures/_base.py\", line 390, in __get_result\n", + " raise self._exception\n", + " File \"/gpfs/home2/weniger/falcon/falcon/core/deployed_graph.py\", line 348, in sample_posterior\n", + " return self._chunked_sample(n_samples, condition_refs, self._sample_posterior)\n", + " File \"/gpfs/home2/weniger/falcon/falcon/core/deployed_graph.py\", line 320, in _chunked_sample\n", + " output = method(end - start, chunk)\n", + " File \"/gpfs/home2/weniger/falcon/falcon/core/deployed_graph.py\", line 398, in _sample_posterior\n", + " return self.estimator_instance.sample_posterior(n_samples, conditions=conditions)\n", + " File \"/gpfs/home2/weniger/falcon/falcon/estimators/flow.py\", line 429, in sample_posterior\n", + " samples, logprob = self._importance_sample(num_samples, mode=\"posterior\", conditions=conditions or {})\n", + " File \"/gpfs/home2/weniger/falcon/falcon/estimators/flow.py\", line 499, in _importance_sample\n", + " log_prob_marg = marginal_net.log_prob(samples_proposals, s * 0)\n", + " File \"/gpfs/home2/weniger/falcon/falcon/estimators/flow_density.py\", line 96, in log_prob\n", + " log_prob = self.net.log_prob(theta.float(), condition=s.float())\n", + " File \"/home/weniger/.conda/envs/emri_few_timm/lib/python3.10/site-packages/sbi/neural_nets/estimators/nflows_flow.py\", line 109, in log_prob\n", + " log_probs = self.net.log_prob(input, context=condition)\n", + " File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/distributions/base.py\", line 40, in log_prob\n", + " return self._log_prob(inputs, context)\n", + " File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/flows/base.py\", line 39, in _log_prob\n", + " noise, logabsdet = self._transform(inputs, context=embedded_context)\n", + " File \"/home/weniger/.conda/envs/emri_few_timm/lib/python3.10/site-packages/torch/nn/modules/module.py\", line 1736, in _wrapped_call_impl\n", + " return self._call_impl(*args, **kwargs)\n", + " File \"/home/weniger/.conda/envs/emri_few_timm/lib/python3.10/site-packages/torch/nn/modules/module.py\", line 1747, in _call_impl\n", + " return forward_call(*args, **kwargs)\n", + " File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/base.py\", line 56, in forward\n", + " return self._cascade(inputs, funcs, context)\n", + " File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/base.py\", line 50, in _cascade\n", + " outputs, logabsdet = func(outputs, context)\n", + " File \"/home/weniger/.conda/envs/emri_few_timm/lib/python3.10/site-packages/torch/nn/modules/module.py\", line 1736, in _wrapped_call_impl\n", + " return self._call_impl(*args, **kwargs)\n", + " File \"/home/weniger/.conda/envs/emri_few_timm/lib/python3.10/site-packages/torch/nn/modules/module.py\", line 1747, in _call_impl\n", + " return forward_call(*args, **kwargs)\n", + " File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/coupling.py\", line 84, in forward\n", + " transform_split, logabsdet = self._coupling_transform_forward(\n", + " File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/coupling.py\", line 194, in _coupling_transform_forward\n", + " return self._coupling_transform(inputs, transform_params, inverse=False)\n", + " File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/coupling.py\", line 211, in _coupling_transform\n", + " outputs, logabsdet = self._piecewise_cdf(inputs, transform_params, inverse)\n", + " File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/coupling.py\", line 492, in _piecewise_cdf\n", + " return spline_fn(\n", + " File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/splines/rational_quadratic.py\", line 46, in unconstrained_rational_quadratic_spline\n", + " ) = rational_quadratic_spline(\n", + " File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/splines/rational_quadratic.py\", line 92, in rational_quadratic_spline\n", + " cumwidths = (right - left) * cumwidths + left\n", + "torch.OutOfMemoryError: CUDA out of memory. Tried to allocate 216.00 MiB. GPU 0 has a total capacity of 39.49 GiB of which 147.25 MiB is free. Including non-PyTorch memory, this process has 39.34 GiB memory in use. Of the allocated memory 37.85 GiB is allocated by PyTorch, and 1011.64 MiB is reserved by PyTorch but unallocated. If reserved but unallocated memory is large try setting PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True to avoid fragmentation. See documentation for Memory Management (https://pytorch.org/docs/stable/notes/cuda.html#environment-variables))\n", + "2026-06-08T14:30:31 [INFO] Output: output/notebook_run3\n", + "2026-06-08T14:30:31 [INFO] Samples: output/notebook_run3/samples\n", + "2026-06-08T14:30:31 [INFO] Logs: output/notebook_run3/graph/driver/output.log (driver)\n", + "2026-06-08T14:30:31 [INFO] output/notebook_run3/graph//output.log (per-node: z, x)\n", + "2026-06-08T14:30:31 [INFO] Started: 2026-06-08 14:27:18\n", + "2026-06-08T14:30:31 [INFO] Ended: 2026-06-08 14:30:31\n", + "2026-06-08T14:30:31 [INFO] Runtime: 3m 14s\n", + "2026-06-08T14:30:31 [INFO] Ray: 1 node(s) | 72 CPU, 1 GPU, 317.9 GB\n", + "2026-06-08T14:30:31 [INFO] Nodes:\n", + "2026-06-08T14:30:31 [INFO] z: done | 20/20 epochs | loss=-3.976 | 5952 sims\n", + "2026-06-08T14:30:31 [INFO] x: idle\n", + "2026-06-08T14:30:31 [INFO] Samples generated: 6080 total | 6016 train, 64 val (6080 live in buffer)\n", + "2026-06-08T14:30:31 [INFO] ============================================================\n" + ] + }, + { + "ename": "RayTaskError(OutOfMemoryError)", + "evalue": "\u001b[36mray::NodeWrapper.sample_posterior()\u001b[39m (pid=405936, ip=145.136.62.39, actor_id=837d11a5132792cd1f3844c901000000, repr=)\n File \"/home/weniger/.conda/envs/emri_few_timm/lib/python3.10/concurrent/futures/_base.py\", line 438, in result\n return self.__get_result()\n File \"/home/weniger/.conda/envs/emri_few_timm/lib/python3.10/concurrent/futures/_base.py\", line 390, in __get_result\n raise self._exception\n File \"/gpfs/home2/weniger/falcon/falcon/core/deployed_graph.py\", line 348, in sample_posterior\n return self._chunked_sample(n_samples, condition_refs, self._sample_posterior)\n File \"/gpfs/home2/weniger/falcon/falcon/core/deployed_graph.py\", line 320, in _chunked_sample\n output = method(end - start, chunk)\n File \"/gpfs/home2/weniger/falcon/falcon/core/deployed_graph.py\", line 398, in _sample_posterior\n return self.estimator_instance.sample_posterior(n_samples, conditions=conditions)\n File \"/gpfs/home2/weniger/falcon/falcon/estimators/flow.py\", line 429, in sample_posterior\n samples, logprob = self._importance_sample(num_samples, mode=\"posterior\", conditions=conditions or {})\n File \"/gpfs/home2/weniger/falcon/falcon/estimators/flow.py\", line 499, in _importance_sample\n log_prob_marg = marginal_net.log_prob(samples_proposals, s * 0)\n File \"/gpfs/home2/weniger/falcon/falcon/estimators/flow_density.py\", line 96, in log_prob\n log_prob = self.net.log_prob(theta.float(), condition=s.float())\n File \"/home/weniger/.conda/envs/emri_few_timm/lib/python3.10/site-packages/sbi/neural_nets/estimators/nflows_flow.py\", line 109, in log_prob\n log_probs = self.net.log_prob(input, context=condition)\n File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/distributions/base.py\", line 40, in log_prob\n return self._log_prob(inputs, context)\n File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/flows/base.py\", line 39, in _log_prob\n noise, logabsdet = self._transform(inputs, context=embedded_context)\n File \"/home/weniger/.conda/envs/emri_few_timm/lib/python3.10/site-packages/torch/nn/modules/module.py\", line 1736, in _wrapped_call_impl\n return self._call_impl(*args, **kwargs)\n File \"/home/weniger/.conda/envs/emri_few_timm/lib/python3.10/site-packages/torch/nn/modules/module.py\", line 1747, in _call_impl\n return forward_call(*args, **kwargs)\n File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/base.py\", line 56, in forward\n return self._cascade(inputs, funcs, context)\n File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/base.py\", line 50, in _cascade\n outputs, logabsdet = func(outputs, context)\n File \"/home/weniger/.conda/envs/emri_few_timm/lib/python3.10/site-packages/torch/nn/modules/module.py\", line 1736, in _wrapped_call_impl\n return self._call_impl(*args, **kwargs)\n File \"/home/weniger/.conda/envs/emri_few_timm/lib/python3.10/site-packages/torch/nn/modules/module.py\", line 1747, in _call_impl\n return forward_call(*args, **kwargs)\n File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/coupling.py\", line 84, in forward\n transform_split, logabsdet = self._coupling_transform_forward(\n File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/coupling.py\", line 194, in _coupling_transform_forward\n return self._coupling_transform(inputs, transform_params, inverse=False)\n File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/coupling.py\", line 211, in _coupling_transform\n outputs, logabsdet = self._piecewise_cdf(inputs, transform_params, inverse)\n File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/coupling.py\", line 492, in _piecewise_cdf\n return spline_fn(\n File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/splines/rational_quadratic.py\", line 46, in unconstrained_rational_quadratic_spline\n ) = rational_quadratic_spline(\n File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/splines/rational_quadratic.py\", line 92, in rational_quadratic_spline\n cumwidths = (right - left) * cumwidths + left\ntorch.OutOfMemoryError: CUDA out of memory. Tried to allocate 216.00 MiB. GPU 0 has a total capacity of 39.49 GiB of which 147.25 MiB is free. Including non-PyTorch memory, this process has 39.34 GiB memory in use. Of the allocated memory 37.85 GiB is allocated by PyTorch, and 1011.64 MiB is reserved by PyTorch but unallocated. If reserved but unallocated memory is large try setting PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True to avoid fragmentation. See documentation for Memory Management (https://pytorch.org/docs/stable/notes/cuda.html#environment-variables)", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mRayTaskError(OutOfMemoryError)\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[4], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m run \u001b[38;5;241m=\u001b[39m \u001b[43mfalcon\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlaunch\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcfg\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43moutput\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43moutput/notebook_run3\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 2\u001b[0m run\n", + "File \u001b[0;32m/gpfs/home2/weniger/falcon/falcon/api.py:310\u001b[0m, in \u001b[0;36mlaunch\u001b[0;34m(target, output, overrides, auto_sample, timeout, wait)\u001b[0m\n\u001b[1;32m 307\u001b[0m init()\n\u001b[1;32m 309\u001b[0m obs \u001b[38;5;241m=\u001b[39m prebuilt_graph\u001b[38;5;241m.\u001b[39m_api_observations \u001b[38;5;28;01mif\u001b[39;00m prebuilt_graph \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m--> 310\u001b[0m \u001b[43m_run_pipeline\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 311\u001b[0m \u001b[43m \u001b[49m\u001b[43mcfg\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 312\u001b[0m \u001b[43m \u001b[49m\u001b[43mauto_sample\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mauto_sample\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 313\u001b[0m \u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtimeout\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 314\u001b[0m \u001b[43m \u001b[49m\u001b[43mgraph\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mprebuilt_graph\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 315\u001b[0m \u001b[43m \u001b[49m\u001b[43mobservations\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mobs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 316\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 318\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m load_run(output_dir)\n", + "File \u001b[0;32m/gpfs/home2/weniger/falcon/falcon/cli.py:621\u001b[0m, in \u001b[0;36m_run_pipeline\u001b[0;34m(cfg, auto_sample, timeout, stop_check, log_handler, on_graph_ready, summary_sink, graph, observations)\u001b[0m\n\u001b[1;32m 619\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m auto_sample \u001b[38;5;129;01mand\u001b[39;00m num_posterior_samples \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m 620\u001b[0m info(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mGenerating \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mnum_posterior_samples\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m posterior samples...\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m--> 621\u001b[0m sample_refs \u001b[38;5;241m=\u001b[39m \u001b[43mdeployed_graph\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msample_posterior\u001b[49m\u001b[43m(\u001b[49m\u001b[43mnum_posterior_samples\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mobservations_tensors\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 622\u001b[0m samples \u001b[38;5;241m=\u001b[39m deployed_graph\u001b[38;5;241m.\u001b[39m_refs_to_arrays(sample_refs)\n\u001b[1;32m 623\u001b[0m _save_samples(samples\u001b[38;5;241m=\u001b[39msamples, sample_cfg\u001b[38;5;241m=\u001b[39msample_cfg, sample_type\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mposterior\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 624\u001b[0m graph\u001b[38;5;241m=\u001b[39mgraph, cfg\u001b[38;5;241m=\u001b[39mcfg, info_fn\u001b[38;5;241m=\u001b[39minfo)\n", + "File \u001b[0;32m/gpfs/home2/weniger/falcon/falcon/core/deployed_graph.py:703\u001b[0m, in \u001b[0;36mDeployedGraph.sample_posterior\u001b[0;34m(self, num_samples, conditions)\u001b[0m\n\u001b[1;32m 693\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Run posterior sampling through the inference graph.\u001b[39;00m\n\u001b[1;32m 694\u001b[0m \n\u001b[1;32m 695\u001b[0m \u001b[38;5;124;03mArgs:\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 700\u001b[0m \u001b[38;5;124;03m List[Dict[str, ObjectRef]]: One dict per sample with refs to all node values\u001b[39;00m\n\u001b[1;32m 701\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 702\u001b[0m condition_refs \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_arrays_to_condition_refs(conditions, num_samples) \u001b[38;5;28;01mif\u001b[39;00m conditions \u001b[38;5;28;01melse\u001b[39;00m {}\n\u001b[0;32m--> 703\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_execute_graph\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 704\u001b[0m \u001b[43m \u001b[49m\u001b[43mnum_samples\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgraph\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbackward_order\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcondition_refs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43msample_posterior\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 705\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m/gpfs/home2/weniger/falcon/falcon/core/deployed_graph.py:666\u001b[0m, in \u001b[0;36mDeployedGraph._execute_graph\u001b[0;34m(self, num_samples, node_order, condition_refs, sample_method)\u001b[0m\n\u001b[1;32m 663\u001b[0m node_condition_refs[evidence] \u001b[38;5;241m=\u001b[39m ref_trace[evidence]\n\u001b[1;32m 665\u001b[0m remote_method \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mgetattr\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mwrapped_nodes_dict[name], sample_method)\n\u001b[0;32m--> 666\u001b[0m node_refs \u001b[38;5;241m=\u001b[39m \u001b[43mray\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 667\u001b[0m \u001b[43m \u001b[49m\u001b[43mremote_method\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mremote\u001b[49m\u001b[43m(\u001b[49m\u001b[43mnum_samples\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcondition_refs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mnode_condition_refs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 668\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 670\u001b[0m \u001b[38;5;66;03m# Update trace with value refs for downstream nodes\u001b[39;00m\n\u001b[1;32m 671\u001b[0m ref_trace[name] \u001b[38;5;241m=\u001b[39m [d[\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mname\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m.value\u001b[39m\u001b[38;5;124m'\u001b[39m] \u001b[38;5;28;01mfor\u001b[39;00m d \u001b[38;5;129;01min\u001b[39;00m node_refs]\n", + "File \u001b[0;32m~/.conda/envs/emri_few_timm/lib/python3.10/site-packages/ray/_private/auto_init_hook.py:21\u001b[0m, in \u001b[0;36mwrap_auto_init..auto_init_wrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[38;5;129m@wraps\u001b[39m(fn)\n\u001b[1;32m 19\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21mauto_init_wrapper\u001b[39m(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m 20\u001b[0m auto_init_ray()\n\u001b[0;32m---> 21\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfn\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/.conda/envs/emri_few_timm/lib/python3.10/site-packages/ray/_private/client_mode_hook.py:103\u001b[0m, in \u001b[0;36mclient_mode_hook..wrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 101\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m func\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m \u001b[38;5;241m!=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124minit\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01mor\u001b[39;00m is_client_mode_enabled_by_default:\n\u001b[1;32m 102\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mgetattr\u001b[39m(ray, func\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m)(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m--> 103\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfunc\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/.conda/envs/emri_few_timm/lib/python3.10/site-packages/ray/_private/worker.py:2771\u001b[0m, in \u001b[0;36mget\u001b[0;34m(object_refs, timeout)\u001b[0m\n\u001b[1;32m 2765\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[1;32m 2766\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mInvalid type of object refs, \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mtype\u001b[39m(object_refs)\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m, is given. \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 2767\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mobject_refs\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m must either be an ObjectRef or a list of ObjectRefs. \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 2768\u001b[0m )\n\u001b[1;32m 2770\u001b[0m \u001b[38;5;66;03m# TODO(ujvl): Consider how to allow user to retrieve the ready objects.\u001b[39;00m\n\u001b[0;32m-> 2771\u001b[0m values, debugger_breakpoint \u001b[38;5;241m=\u001b[39m \u001b[43mworker\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_objects\u001b[49m\u001b[43m(\u001b[49m\u001b[43mobject_refs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtimeout\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 2772\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i, value \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28menumerate\u001b[39m(values):\n\u001b[1;32m 2773\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(value, RayError):\n", + "File \u001b[0;32m~/.conda/envs/emri_few_timm/lib/python3.10/site-packages/ray/_private/worker.py:919\u001b[0m, in \u001b[0;36mWorker.get_objects\u001b[0;34m(self, object_refs, timeout, return_exceptions, skip_deserialization)\u001b[0m\n\u001b[1;32m 917\u001b[0m global_worker\u001b[38;5;241m.\u001b[39mcore_worker\u001b[38;5;241m.\u001b[39mdump_object_store_memory_usage()\n\u001b[1;32m 918\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(value, RayTaskError):\n\u001b[0;32m--> 919\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m value\u001b[38;5;241m.\u001b[39mas_instanceof_cause()\n\u001b[1;32m 920\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 921\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m value\n", + "\u001b[0;31mRayTaskError(OutOfMemoryError)\u001b[0m: \u001b[36mray::NodeWrapper.sample_posterior()\u001b[39m (pid=405936, ip=145.136.62.39, actor_id=837d11a5132792cd1f3844c901000000, repr=)\n File \"/home/weniger/.conda/envs/emri_few_timm/lib/python3.10/concurrent/futures/_base.py\", line 438, in result\n return self.__get_result()\n File \"/home/weniger/.conda/envs/emri_few_timm/lib/python3.10/concurrent/futures/_base.py\", line 390, in __get_result\n raise self._exception\n File \"/gpfs/home2/weniger/falcon/falcon/core/deployed_graph.py\", line 348, in sample_posterior\n return self._chunked_sample(n_samples, condition_refs, self._sample_posterior)\n File \"/gpfs/home2/weniger/falcon/falcon/core/deployed_graph.py\", line 320, in _chunked_sample\n output = method(end - start, chunk)\n File \"/gpfs/home2/weniger/falcon/falcon/core/deployed_graph.py\", line 398, in _sample_posterior\n return self.estimator_instance.sample_posterior(n_samples, conditions=conditions)\n File \"/gpfs/home2/weniger/falcon/falcon/estimators/flow.py\", line 429, in sample_posterior\n samples, logprob = self._importance_sample(num_samples, mode=\"posterior\", conditions=conditions or {})\n File \"/gpfs/home2/weniger/falcon/falcon/estimators/flow.py\", line 499, in _importance_sample\n log_prob_marg = marginal_net.log_prob(samples_proposals, s * 0)\n File \"/gpfs/home2/weniger/falcon/falcon/estimators/flow_density.py\", line 96, in log_prob\n log_prob = self.net.log_prob(theta.float(), condition=s.float())\n File \"/home/weniger/.conda/envs/emri_few_timm/lib/python3.10/site-packages/sbi/neural_nets/estimators/nflows_flow.py\", line 109, in log_prob\n log_probs = self.net.log_prob(input, context=condition)\n File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/distributions/base.py\", line 40, in log_prob\n return self._log_prob(inputs, context)\n File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/flows/base.py\", line 39, in _log_prob\n noise, logabsdet = self._transform(inputs, context=embedded_context)\n File \"/home/weniger/.conda/envs/emri_few_timm/lib/python3.10/site-packages/torch/nn/modules/module.py\", line 1736, in _wrapped_call_impl\n return self._call_impl(*args, **kwargs)\n File \"/home/weniger/.conda/envs/emri_few_timm/lib/python3.10/site-packages/torch/nn/modules/module.py\", line 1747, in _call_impl\n return forward_call(*args, **kwargs)\n File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/base.py\", line 56, in forward\n return self._cascade(inputs, funcs, context)\n File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/base.py\", line 50, in _cascade\n outputs, logabsdet = func(outputs, context)\n File \"/home/weniger/.conda/envs/emri_few_timm/lib/python3.10/site-packages/torch/nn/modules/module.py\", line 1736, in _wrapped_call_impl\n return self._call_impl(*args, **kwargs)\n File \"/home/weniger/.conda/envs/emri_few_timm/lib/python3.10/site-packages/torch/nn/modules/module.py\", line 1747, in _call_impl\n return forward_call(*args, **kwargs)\n File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/coupling.py\", line 84, in forward\n transform_split, logabsdet = self._coupling_transform_forward(\n File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/coupling.py\", line 194, in _coupling_transform_forward\n return self._coupling_transform(inputs, transform_params, inverse=False)\n File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/coupling.py\", line 211, in _coupling_transform\n outputs, logabsdet = self._piecewise_cdf(inputs, transform_params, inverse)\n File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/coupling.py\", line 492, in _piecewise_cdf\n return spline_fn(\n File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/splines/rational_quadratic.py\", line 46, in unconstrained_rational_quadratic_spline\n ) = rational_quadratic_spline(\n File \"/home/weniger/.local/lib/python3.10/site-packages/nflows/transforms/splines/rational_quadratic.py\", line 92, in rational_quadratic_spline\n cumwidths = (right - left) * cumwidths + left\ntorch.OutOfMemoryError: CUDA out of memory. Tried to allocate 216.00 MiB. GPU 0 has a total capacity of 39.49 GiB of which 147.25 MiB is free. Including non-PyTorch memory, this process has 39.34 GiB memory in use. Of the allocated memory 37.85 GiB is allocated by PyTorch, and 1011.64 MiB is reserved by PyTorch but unallocated. If reserved but unallocated memory is large try setting PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True to avoid fragmentation. See documentation for Memory Management (https://pytorch.org/docs/stable/notes/cuda.html#environment-variables)" + ] + } + ], + "source": [ + "run = falcon.launch(cfg, output=\"output/notebook_run3\")\n", + "run" + ] + }, + { + "cell_type": "markdown", + "id": "a219b641", + "metadata": {}, + "source": [ + "## 4. Inspect the result" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3a7a3f0d", + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'run' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[4], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# Path where everything was written\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mOutput dir:\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[43mrun\u001b[49m\u001b[38;5;241m.\u001b[39mrun_dir)\n\u001b[1;32m 4\u001b[0m \u001b[38;5;66;03m# Loaded config (identical to what was saved at the start of the run)\u001b[39;00m\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124mConfig keys:\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28mlist\u001b[39m(run\u001b[38;5;241m.\u001b[39mconfig\u001b[38;5;241m.\u001b[39mkeys()))\n", + "\u001b[0;31mNameError\u001b[0m: name 'run' is not defined" + ] + } + ], + "source": [ + "# Path where everything was written\n", + "print(\"Output dir:\", run.run_dir)\n", + "\n", + "# Loaded config (identical to what was saved at the start of the run)\n", + "print(\"\\nConfig keys:\", list(run.config.keys()))\n", + "\n", + "# Posterior samples (written by auto_sample=True)\n", + "samples = run.samples\n", + "print(\"\\nSamples:\", samples)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d7fd92f7", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING:root:Too few points to create valid contours\n", + "WARNING:root:Too few points to create valid contours\n", + "WARNING:root:Too few points to create valid contours\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAqgAAAKoCAYAAAC7uA1cAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQABAABJREFUeJzs3XlUVPX/BvBn2HdCRzFUBJcKTUwypTT3JTRcExXRVFp+LmiWmJZ908pSMRW1zBJMwyVNJEkltXLJck3FZVQkkM0FStkHYYbfH5y5zbDNALNc4Hmd4zkyXO793Fn04bO9JaWlpaUgIiIiIhIJM1M3gIiIiIhIHQMqEREREYkKAyoRERERiQoDKhERERGJCgMqEREREYkKAyoRERERiQoDKhERERGJCgMqEREREYmKhakboA9KpRIZGRlwdHSERCIxdXOIRKW0tBS5ublwc3ODmRl/JyUiIvFrEAE1IyMDrVu3NnUziEQtNTUVrVq1MnUziIiItGoQAdXR0RFA2X/ATk5OJm4Nkbjk5OSgdevWwueEiIhI7BpEQFUN6zs5OTGgElWB01+IiKi+4IQ0IiIiIhIVBlQiIiIiEhUGVCIiIiISFQZUIiIiIhIVBlQiIiIiEhUGVCIiIiISFQZUIiIiIhIVBlQiIiIiEhUGVCIiIiISFQZUIiIiIhIVBlQiIiIiEhUGVCIiIiISFQZUIiIiIhIVBlQiIiIiEhULUzeAxCElJQVZWVlaj5NKpXB3dzdCi4iIiKixYkAlpKSkwMvLCwUFBVqPtbOzg0wmY0glIiIig2FAJWRlZaGgoABRUVHw8vKq8jiZTIagoCBkZWUxoBIREZHBMKCSwMvLCz4+PqZuBhERETVyXCRFRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREomJh6gY0FikpKcjKytJ6nFQqhbu7u1GvK5PJ9HY9IiIiorpiQDWClJQUeHl5oaCgQOuxdnZ2kMlkegmpNb2uVCqt8zWJiIiI6ooB1QiysrJQUFCAqKgoeHl5VXmcTCZDUFAQsrKy9BJQdb0uoP+eWyIiIqLaYkA1Ii8vL/j4+DSa6xIRERHVBhdJEREREZGoMKASERERkagwoBIRERGRqDCgEhEREZGoMKASERERkagwoBIRERGRqHCbKaJqmKoCGBERUWPGgEpUBVNVACMiImrsGFCJqmCqCmBERESNHQMqkRasxEVERGRcXCRFRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwm2m6ildKhzJZDIjtab2TFWpqaE8f0RERA0RA2o9VNMKR1Kp1AitqjlTVWpqKM8fERFRQ8WAWg/pWuEIEHeNeFNVamoozx8REVFDxYBajzWUCkemuo+G8vwRERE1NFwkRURERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosJtpoj0RJfKU9xXlYiISDsGVKI6kkqlsLOzQ1BQkNZj9VkRi4iIqKFiQCWqI3d3d8hkMmRlZVV7nL4rYhERETVUDKhEeuDu7s7QSUREpCdcJEVEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosJ9UEVIW8lMXUpqGpK+rm/q+yAiIiJxYkAVkZqWzJRKpUZo1X9q0j5dmeI+iIiISNwYUEVE15KZQFlYNHblopq0T1emuA8iIiISNwZUkRF7yUyxt4+IiIjqPy6SIiIiIiJRYUAlIiIiIlFhQCUiIiIiUWFAJSIiIiJRYUAlIiIiIlFhQCUiIiIiUeE2U3WUkpKidV9QVkyimtLlfQVwH1kiImqYGFDrICUlBV5eXigoKNB6LCsmka5q+r6SyWQMqURE1KAwoNZBVlYWCgoKEBUVBS8vr2qPZU8X6UrX95VMJkNQUBCysrL43iIiogaFAVUPvLy84OPjY+pmUAPD9xURETVWXCRFRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREomJh6gYQNTYymaxO36/p8Xl5eTU6HxERkakxoBIZiVQqhZ2dHYKCgrQea2dnB6lUqrfzERER1ScMqERG4u7uDplMhqysLK3HSqVSuLu76+V858+fxxtvvFGjthIREZkSAyqREbm7u2sNnvo+H4f4iYiovuEiKSIiIiISFQZUIiIiIhIVBlQiIiIiEhUGVCIiIiISFQZUIiIiIhIVBlQiIiIiEhVuM0X1Rk0rLBn6PERERGQYDKgkeoaomKRLpSYiIiIyDQZUEr2aVGDSlS6VmoiIiMg0GFCpXtB3BSYiIiISLy6SIiIiIiJRYUAlIiIiIlFhQCUiIiIiUWFAJSIiIiJRYUAlIiIiIlFhQCUiIiIiUWl020ylpKTotJ8m98kkIiIiMo1GFVBTUlLg5eWFgoICrcfa2dlBJpMxpBIREREZWaMKqFlZWSgoKEBUVBS8vLyqPE4mkyEoKAhZWVkMqERERERG1qgCqoqXlxd8fHxM3QwiIiIiqgQXSRERERGRqDCgEhEREZGoMKASERERkagwoBIRERGRqDCgEhEREZGoMKASERERkagwoBIRERGRqDCgEhEREZGoMKASERERkagwoBIRERGRqDCgEhEREZGoMKASERERkagwoBIRERGRqDCgEhEREZGoMKASERERkagwoBIRERGRqDCgEhEREZGoMKASERERkagwoBIRERGRqDCgEhEREZGoMKASERERkagwoBIRERGRqDCgEhEREZGoMKASERERkagwoBIRERGRqDCgEhEREZGoWJi6Afp08eJFODg4VPl9mUxmxNYQERERUW00qIDap08frcfY2dlBKpUaoTVEREREVBsNKqB+/fXXePbZZ6s9RiqVwt3d3UgtIiIiIqKaalAB9cknn4SPj4+pm0FEREREdcBFUkREREQkKgyoRERERCQqDKhEREREJCoMqEREREQkKgyoRERERCQqDKhEREREJCoMqEREREQkKg1qH1R901YalaVTiYiIiPSPAbUSUqkUdnZ2CAoK0nosS6cSERER6RcDaiXc3d0hk8mQlZWl9ViWTiUiIiLSLwbUKri7uzN4EhEREZkAF0kRERERkagwoBIRERGRqDCgEhEREZGoMKASERERkagwoBIRERGRqDCgEhEREZGoNIhtpkpLSwEA+fn5yMnJMXFriMQlPz8fwH+fEyIiIrFrEAE1NzcXADB06FATt4RIvHJzc+Hs7GzqZhAREWklKW0A3SpKpRIZGRlwdHSERCKp8c/n5OSgdevWSE1NhZOTkwFaWHdso340xjaWlpYiNzcXbm5uMDPjrB4iIhK/BtGDamZmhlatWtX5PE5OTqINLSpso340tjay55SIiOoTdqcQERERkagwoBIRERGRqDCgArC2tsaHH34Ia2trUzelSmyjfrCNRERE4tcgFkkRERERUcPBHlQiIiIiEhUGVCIiIiISlQaxzVRd90Elash03QeVnyOiqnE/YSLjahABNSMjA61btzZ1M4hELTU1tdr9gvk5ItJO2+eIiPSjQQRUR0dHABB1dSBTefjwocbXEyZMwB9//IF169Zh+PDhwuP5+fmwt7fXer7yxwUGBuLkyZP4/PPPMXDgQNja2gqrzx977LEat69NmzYAgIEDByIiIkLje7qcTx9ee+017N69G66urhg2bBgiIyMBAG+++aZGz8nVq1dx/PhxeHp64vnnn8f27dsBAJmZmbCysjLY+WpKVZlK9TmpCj9HRFXT9XNERPrRIAKqajiyPlQHMjalUqnxtYVF2Utua2ur8VyZmZnBwcFB6/nKH6c6n5OTE9zd3TWO1eW1KN8+FUtLywo/b6zX1tLSEkDZvaoHQ2tra41Aqbr38sc5OTlpfK3v89WWtmF7fo6ItOP0FyLj4ESaRkpfu4txlzIiIiLSNwbURkbVS7dv3746h8u0tDScPXsWwH+9hHXVsWNHAECfPn30cr7aUD1HDx8+1HiOcnJyNI7Lzs4GUNbjeefOnSrPp3puMjMz8eDBA+Hx27dvC39XKpVITU0VznfhwoU63gUREVH9xYDayLz66quQSCSIjY3F/Pnzax1S09LS4O/vj8LCQnh4eKBv3756ad/SpUsRGBiI8ePH6+V8tfF///d/AIDCwkL88ssvwsKhw4cPC89XZmamECI9PDzwyy+/AADc3NwqDMfPmzcPZmZmKCkpwQ8//AAPDw8AwE8//YTk5GQolUocPnwYCQkJkEgkKC0txaVLlwAAnTp10svwPhERUX3CgNrIDB8+HOvWrYNEIsGm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", + "text/plain": [ + "
" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAqgAAAKoCAYAAAC7uA1cAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQABAABJREFUeJzs3XlUVPX/BvBn2HdCRzFUBJcKTUwypTT3JTRcExXRVFp+LmiWmJZ908pSMRW1zBJMwyVNJEkltXLJck3FZVQkkM0FStkHYYbfH5y5zbDNALNc4Hmd4zkyXO793Fn04bO9JaWlpaUgIiIiIhIJM1M3gIiIiIhIHQMqEREREYkKAyoRERERiQoDKhERERGJCgMqEREREYkKAyoRERERiQoDKhERERGJCgMqEREREYmKhakboA9KpRIZGRlwdHSERCIxdXOIRKW0tBS5ublwc3ODmRl/JyUiIvFrEAE1IyMDrVu3NnUziEQtNTUVrVq1MnUziIiItGoQAdXR0RFA2X/ATk5OJm4Nkbjk5OSgdevWwueEiIhI7BpEQFUN6zs5OTGgElWB01+IiKi+4IQ0IiIiIhIVBlQiIiIiEhUGVCIiIiISFQZUIiIiIhIVBlQiIiIiEhUGVCIiIiISFQZUIiIiIhIVBlQiIiIiEhUGVCIiIiISFQZUIiIiIhIVBlQiIiIiEhUGVCIiIiISFQZUIiIiIhIVBlQiIiIiEhULUzeAxCElJQVZWVlaj5NKpXB3dzdCi4iIiKixYkAlpKSkwMvLCwUFBVqPtbOzg0wmY0glIiIig2FAJWRlZaGgoABRUVHw8vKq8jiZTIagoCBkZWUxoBIREZHBMKCSwMvLCz4+PqZuBhERETVyXCRFRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREomJh6gY0FikpKcjKytJ6nFQqhbu7u1GvK5PJ9HY9IiIiorpiQDWClJQUeHl5oaCgQOuxdnZ2kMlkegmpNb2uVCqt8zWJiIiI6ooB1QiysrJQUFCAqKgoeHl5VXmcTCZDUFAQsrKy9BJQdb0uoP+eWyIiIqLaYkA1Ii8vL/j4+DSa6xIRERHVBhdJEREREZGoMKASERERkagwoBIRERGRqDCgEhEREZGoMKASERERkagwoBIRERGRqHCbKaJqmKoCGBERUWPGgEpUBVNVACMiImrsGFCJqmCqCmBERESNHQMqkRasxEVERGRcXCRFRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwm2m6ildKhzJZDIjtab2TFWpqaE8f0RERA0RA2o9VNMKR1Kp1AitqjlTVWpqKM8fERFRQ8WAWg/pWuEIEHeNeFNVamoozx8REVFDxYBajzWUCkemuo+G8vwRERE1NFwkRURERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosJtpoj0RJfKU9xXlYiISDsGVKI6kkqlsLOzQ1BQkNZj9VkRi4iIqKFiQCWqI3d3d8hkMmRlZVV7nL4rYhERETVUDKhEeuDu7s7QSUREpCdcJEVEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosJ9UEVIW8lMXUpqGpK+rm/q+yAiIiJxYkAVkZqWzJRKpUZo1X9q0j5dmeI+iIiISNwYUEVE15KZQFlYNHblopq0T1emuA8iIiISNwZUkRF7yUyxt4+IiIjqPy6SIiIiIiJRYUAlIiIiIlFhQCUiIiIiUWFAJSIiIiJRYUAlIiIiIlFhQCUiIiIiUeE2U3WUkpKidV9QVkyimtLlfQVwH1kiImqYGFDrICUlBV5eXigoKNB6LCsmka5q+r6SyWQMqURE1KAwoNZBVlYWCgoKEBUVBS8vr2qPZU8X6UrX95VMJkNQUBCysrL43iIiogaFAVUPvLy84OPjY+pmUAPD9xURETVWXCRFRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREosKASkRERESiwoBKRERERKLCgEpEREREomJh6gYQNTYymaxO36/p8Xl5eTU6HxERkakxoBIZiVQqhZ2dHYKCgrQea2dnB6lUqrfzERER1ScMqERG4u7uDplMhqysLK3HSqVSuLu76+V858+fxxtvvFGjthIREZkSAyqREbm7u2sNnvo+H4f4iYiovuEiKSIiIiISFQZUIiIiIhIVBlQiIiIiEhUGVCIiIiISFQZUIiIiIhIVBlQiIiIiEhVuM0X1Rk0rLBn6PERERGQYDKgkeoaomKRLpSYiIiIyDQZUEr2aVGDSlS6VmoiIiMg0GFCpXtB3BSYiIiISLy6SIiIiIiJRYUAlIiIiIlFhQCUiIiIiUWFAJSIiIiJRYUAlIiIiIlFhQCUiIiIiUWl020ylpKTotJ8m98kkIiIiMo1GFVBTUlLg5eWFgoICrcfa2dlBJpMxpBIREREZWaMKqFlZWSgoKEBUVBS8vLyqPE4mkyEoKAhZWVkMqERERERG1qgCqoqXlxd8fHxM3QwiIiIiqgQXSRERERGRqDCgEhEREZGoMKASERERkagwoBIRERGRqDCgEhEREZGoMKASERERkagwoBIRERGRqDCgEhEREZGoMKASERERkagwoBIRERGRqDCgEhEREZGoMKASERERkagwoBIRERGRqDCgEhEREZGoMKASERERkagwoBIRERGRqDCgEhEREZGoMKASERERkagwoBIRERGRqDCgEhEREZGoMKASERERkagwoBIRERGRqDCgEhEREZGoMKASERERkagwoBIRERGRqDCgEhEREZGoWJi6Afp08eJFODg4VPl9mUxmxNYQERERUW00qIDap08frcfY2dlBKpUaoTVEREREVBsNKqB+/fXXePbZZ6s9RiqVwt3d3UgtIiIiIqKaalAB9cknn4SPj4+pm0FEREREdcBFUkREREQkKgyoRERERCQqDKhEREREJCoMqEREREQkKgyoRERERCQqDKhEREREJCoMqEREREQkKg1qH1R901YalaVTiYiIiPSPAbUSUqkUdnZ2CAoK0nosS6cSERER6RcDaiXc3d0hk8mQlZWl9ViWTiUiIiLSLwbUKri7uzN4EhEREZkAF0kRERERkagwoBIRERGRqDCgEhEREZGoMKASERERkagwoBIRERGRqDCgEhEREZGoNIhtpkpLSwEA+fn5yMnJMXFriMQlPz8fwH+fEyIiIrFrEAE1NzcXADB06FATt4RIvHJzc+Hs7GzqZhAREWklKW0A3SpKpRIZGRlwdHSERCKp8c/n5OSgdevWSE1NhZOTkwFaWHdso340xjaWlpYiNzcXbm5uMDPjrB4iIhK/BtGDamZmhlatWtX5PE5OTqINLSpso340tjay55SIiOoTdqcQERERkagwoBIRERGRqDCgArC2tsaHH34Ia2trUzelSmyjfrCNRERE4tcgFkkRERERUcPBHlQiIiIiEhUGVCIiIiISlQaxzVRd90Elash03QeVnyOiqnE/YSLjahABNSMjA61btzZ1M4hELTU1tdr9gvk5ItJO2+eIiPSjQQRUR0dHABB1dSBTefjwocbXEyZMwB9//IF169Zh+PDhwuP5+fmwt7fXer7yxwUGBuLkyZP4/PPPMXDgQNja2gqrzx977LEat69NmzYAgIEDByIiIkLje7qcTx9ee+017N69G66urhg2bBgiIyMBAG+++aZGz8nVq1dx/PhxeHp64vnnn8f27dsBAJmZmbCysjLY+WpKVZlK9TmpCj9HRFXT9XNERPrRIAKqajiyPlQHMjalUqnxtYVF2Utua2ur8VyZmZnBwcFB6/nKH6c6n5OTE9zd3TWO1eW1KN8+FUtLywo/b6zX1tLSEkDZvaoHQ2tra41Aqbr38sc5OTlpfK3v89WWtmF7fo6ItOP0FyLj4ESaRkpfu4txlzIiIiLSNwbURkbVS7dv3746h8u0tDScPXsWwH+9hHXVsWNHAECfPn30cr7aUD1HDx8+1HiOcnJyNI7Lzs4GUNbjeefOnSrPp3puMjMz8eDBA+Hx27dvC39XKpVITU0VznfhwoU63gUREVH9xYDayLz66quQSCSIjY3F/Pnzax1S09LS4O/vj8LCQnh4eKBv3756ad/SpUsRGBiI8ePH6+V8tfF///d/AIDCwkL88ssvwsKhw4cPC89XZmamECI9PDzwyy+/AADc3NwqDMfPmzcPZmZmKCkpwQ8//AAPDw8AwE8//YTk5GQolUocPnwYCQkJkEgkKC0txaVLlwAAnTp10svwPhERUX3CgNrIDB8+HOvWrYNEIsGm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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "z = samples['posterior'].stacked['z']\n", + "import corner\n", + "corner.corner(z)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "882c8a74", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "jupytext": { + "cell_metadata_filter": "-all", + "main_language": "python", + "notebook_metadata_filter": "-all" + }, + "kernelspec": { + "display_name": "emri_few_timm", + "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.10.1" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/02_bimodal/config_amortized.yml b/examples/02_bimodal/config_amortized.yml index 45a1249..d725ce9 100644 --- a/examples/02_bimodal/config_amortized.yml +++ b/examples/02_bimodal/config_amortized.yml @@ -43,29 +43,25 @@ graph: - ['uniform', -10000.0, 10000.0] estimator: _target_: falcon.estimators.Flow - loop: - max_epochs: 300 - batch_size: 128 - early_stop_patience: 32 - network: - net_type: nsf # zuko_gf, maf, nice, sospf, naf, gf - theta_norm: true - norm_momentum: 0.003 - use_log_update: true - adaptive_momentum: false + max_epochs: 300 + net_type: nsf # zuko_gf, maf, nice, sospf, naf, gf + lr: 0.01 + gamma: 0.5 embedding: _target_: model.E _input_: [x] - optimizer: - lr: 0.01 - lr_decay_factor: 0.5 - scheduler_patience: 16 - inference: - gamma: 0.5 - discard_samples: false - log_ratio_threshold: -20 - sample_reference_posterior: false - use_best_models_during_inference: true + batch_size: 128 + early_stop_patience: 32 + theta_norm: true + norm_momentum: 0.003 + use_log_update: true + adaptive_momentum: false + lr_decay_factor: 0.5 + lr_patience: 16 + discard_samples: false + log_ratio_threshold: -20 + sample_reference_posterior: false + use_best_models: true ray: num_gpus: 1 diff --git a/examples/02_bimodal/config_regular.yml b/examples/02_bimodal/config_regular.yml index c37c7fa..417fac1 100644 --- a/examples/02_bimodal/config_regular.yml +++ b/examples/02_bimodal/config_regular.yml @@ -43,29 +43,25 @@ graph: - ['uniform', -10000.0, 10000.0] estimator: _target_: falcon.estimators.Flow - loop: - max_epochs: 300 - batch_size: 128 - early_stop_patience: 32 - network: - net_type: nsf # zuko_gf, maf, nice, sospf, naf, gf - theta_norm: true - norm_momentum: 0.003 - use_log_update: true - adaptive_momentum: false + max_epochs: 300 + net_type: nsf # zuko_gf, maf, nice, sospf, naf, gf + lr: 0.01 + gamma: 0.5 embedding: _target_: model.E _input_: [x] - optimizer: - lr: 0.01 - lr_decay_factor: 0.5 - scheduler_patience: 16 - inference: - gamma: 0.5 - discard_samples: true - log_ratio_threshold: -20 - sample_reference_posterior: false - use_best_models_during_inference: true + batch_size: 128 + early_stop_patience: 32 + theta_norm: true + norm_momentum: 0.003 + use_log_update: true + adaptive_momentum: false + lr_decay_factor: 0.5 + lr_patience: 16 + discard_samples: true + log_ratio_threshold: -20 + sample_reference_posterior: false + use_best_models: true ray: num_gpus: 1 diff --git a/examples/02_bimodal/config_rounds_fill.yml b/examples/02_bimodal/config_rounds_fill.yml index f8c4794..4feca28 100644 --- a/examples/02_bimodal/config_rounds_fill.yml +++ b/examples/02_bimodal/config_rounds_fill.yml @@ -43,29 +43,25 @@ graph: - ['uniform', -10000.0, 10000.0] estimator: _target_: falcon.estimators.Flow - loop: - max_epochs: 300 - batch_size: 128 - early_stop_patience: 32 - network: - net_type: nsf # zuko_gf, maf, nice, sospf, naf, gf - theta_norm: true - norm_momentum: 0.0005 - use_log_update: true - adaptive_momentum: false + max_epochs: 300 + net_type: nsf # zuko_gf, maf, nice, sospf, naf, gf + lr: 0.003 + gamma: 0.5 embedding: _target_: model.E _input_: [x] - optimizer: - lr: 0.003 - lr_decay_factor: 0.5 - scheduler_patience: 16 - inference: - gamma: 0.5 - discard_samples: false - log_ratio_threshold: -20 - sample_reference_posterior: false - use_best_models_during_inference: true + batch_size: 128 + early_stop_patience: 32 + theta_norm: true + norm_momentum: 0.0005 + use_log_update: true + adaptive_momentum: false + lr_decay_factor: 0.5 + lr_patience: 16 + discard_samples: false + log_ratio_threshold: -20 + sample_reference_posterior: false + use_best_models: true ray: num_gpus: 1 diff --git a/examples/02_bimodal/config_rounds_renew.yml b/examples/02_bimodal/config_rounds_renew.yml index 521f488..97a56a6 100644 --- a/examples/02_bimodal/config_rounds_renew.yml +++ b/examples/02_bimodal/config_rounds_renew.yml @@ -43,29 +43,25 @@ graph: - ['uniform', -10000.0, 10000.0] estimator: _target_: falcon.estimators.Flow - loop: - max_epochs: 600 - batch_size: 128 - early_stop_patience: 32 - network: - net_type: nsf # zuko_gf, maf, nice, sospf, naf, gf - theta_norm: true - norm_momentum: 0.002 - use_log_update: true - adaptive_momentum: false + max_epochs: 600 + net_type: nsf # zuko_gf, maf, nice, sospf, naf, gf + lr: 0.006 + gamma: 0.5 embedding: _target_: model.E _input_: [x] - optimizer: - lr: 0.006 - lr_decay_factor: 0.5 - scheduler_patience: 16 - inference: - gamma: 0.5 - discard_samples: false - log_ratio_threshold: -20 - sample_reference_posterior: false - use_best_models_during_inference: true + batch_size: 128 + early_stop_patience: 32 + theta_norm: true + norm_momentum: 0.002 + use_log_update: true + adaptive_momentum: false + lr_decay_factor: 0.5 + lr_patience: 16 + discard_samples: false + log_ratio_threshold: -20 + sample_reference_posterior: false + use_best_models: true ray: num_gpus: 1 diff --git a/examples/03_composite/config.yml b/examples/03_composite/config.yml index ec1be6b..d362235 100644 --- a/examples/03_composite/config.yml +++ b/examples/03_composite/config.yml @@ -45,13 +45,10 @@ graph: - ['uniform', -1.0, 1.0] estimator: _target_: falcon.estimators.Flow - loop: - max_epochs: 300 - batch_size: 128 - early_stop_patience: 32 - network: - net_type: zuko_gf # nsf, zuko_gf, maf, nice, sospf, naf, gf - theta_norm: true + max_epochs: 300 + net_type: zuko_gf # nsf, zuko_gf, maf, nice, sospf, naf, gf + lr: 0.001 + gamma: 0.5 embedding: _target_: model.Concatenate _input_: @@ -66,24 +63,23 @@ graph: - _target_: model.Linear out_features: 512 _input_: [x] - optimizer: - lr: 0.001 - lr_decay_factor: 0.5 - scheduler_patience: 16 - inference: - gamma: 0.5 - discard_samples: false - log_ratio_threshold: -20 - sample_reference_posterior: false - use_best_models_during_inference: true + batch_size: 128 + early_stop_patience: 32 + theta_norm: true + lr_decay_factor: 0.5 + lr_patience: 16 + discard_samples: false + log_ratio_threshold: -20 + sample_reference_posterior: false + use_best_models: true ray: num_gpus: 0.5 z2: evidence: [x] - simulator: + simulator: _target_: falcon.priors.Hypercube - priors: + priors: - ['uniform', -1.2, 1.2] - ['uniform', -1.2, 1.2] - ['uniform', -1.2, 1.2] @@ -91,13 +87,10 @@ graph: - ['uniform', -1.2, 1.2] estimator: _target_: falcon.estimators.Flow - loop: - max_epochs: 300 - batch_size: 128 - early_stop_patience: 32 - network: - net_type: nsf # nsf, zuko_gf, maf, nice, sospf, naf, gf - theta_norm: true + max_epochs: 300 + net_type: nsf # nsf, zuko_gf, maf, nice, sospf, naf, gf + lr: 0.001 + gamma: 0.5 embedding: _target_: timm.create_model model_name: resnet18 #convnext_tiny @@ -107,16 +100,15 @@ graph: _input_: _target_: model.Unsqueeze _input_: [x] - optimizer: - lr: 0.001 - lr_decay_factor: 0.5 - scheduler_patience: 16 - inference: - gamma: 0.5 - discard_samples: false - log_ratio_threshold: -20 - sample_reference_posterior: false - use_best_models_during_inference: true + batch_size: 128 + early_stop_patience: 32 + theta_norm: true + lr_decay_factor: 0.5 + lr_patience: 16 + discard_samples: false + log_ratio_threshold: -20 + sample_reference_posterior: false + use_best_models: true ray: num_gpus: 0.5 diff --git a/examples/04_gaussian/config.yml b/examples/04_gaussian/config.yml index 20b5c0a..49decd6 100644 --- a/examples/04_gaussian/config.yml +++ b/examples/04_gaussian/config.yml @@ -69,26 +69,22 @@ graph: estimator: _target_: falcon.estimators.GaussianFullCov - loop: - max_epochs: 8000 - batch_size: 128 - early_stop_patience: 128 - network: - hidden_dim: 128 # MLP hidden layer dimension - num_layers: 3 # Number of hidden layers - momentum: 0.01 # EMA momentum for running statistics - min_var: 1.0e-20 # Minimum variance for numerical stability - eig_update_freq: 1 # Eigendecomposition update frequency + max_epochs: 8000 + lr: 0.01 + gamma: 0.1 # Tempering for proposal sampling embedding: _target_: model.E_identity _input_: [x] - optimizer: - lr: 0.01 - lr_decay_factor: 1.0 # 1.0 = no LR decay - inference: - gamma: 0.1 # Tempering for proposal sampling - discard_samples: false - log_ratio_threshold: -20.0 + batch_size: 128 + early_stop_patience: 128 + hidden_dim: 128 # MLP hidden layer dimension + num_layers: 3 # Number of hidden layers + momentum: 0.01 # EMA momentum for running statistics + min_var: 1.0e-20 # Minimum variance for numerical stability + eig_update_freq: 1 # Eigendecomposition update frequency + lr_decay_factor: 1.0 # 1.0 = no LR decay + discard_samples: false + log_ratio_threshold: -20.0 ray: num_gpus: 1 diff --git a/examples/04_gaussian/notebook.ipynb b/examples/04_gaussian/notebook.ipynb new file mode 100644 index 0000000..93f6d79 --- /dev/null +++ b/examples/04_gaussian/notebook.ipynb @@ -0,0 +1,377 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "65ae874c", + "metadata": {}, + "source": [ + "# 04 — Gaussian posterior: programmatic graph API\n", + "\n", + "This notebook demonstrates the **Python-first** way to define a Falcon model:\n", + "build the graph with `Graph.add_node()` instead of a YAML config file.\n", + "The forward model and embedding are plain Python callables defined right here\n", + "in the notebook — no separate `src/model.py` needed.\n", + "\n", + "The same model is also runnable via the CLI:\n", + "```bash\n", + "cd examples/04_gaussian\n", + "falcon launch -o output/cli_run\n", + "```\n", + "That CLI path uses `config.yml` + `src/model.py`. Both paths produce\n", + "identical results; the notebook path is the \"define your own\" lesson.\n", + "\n", + "**Prerequisites**: run `python data/gen_mock_data.py` once to create the\n", + "mock observation, then execute this notebook from `examples/04_gaussian/`." + ] + }, + { + "cell_type": "markdown", + "id": "ad262282", + "metadata": {}, + "source": [ + "## 1. Define the forward model and embedding in Python" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "09925d35", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import torch\n", + "import torch.nn as nn\n", + "import falcon\n", + "\n", + "\n", + "class ExpPlusNoise:\n", + " \"\"\"Forward model: x = exp(z) + noise. Plain callable, no base class needed.\"\"\"\n", + "\n", + " def __init__(self, sigma: float = 1e-6):\n", + " self.sigma = sigma\n", + "\n", + " def simulate_batch(self, batch_size, z):\n", + " z = torch.tensor(z)\n", + " x = torch.exp(z) + torch.randn_like(z) * self.sigma\n", + " return x.numpy()\n", + "\n", + "\n", + "class IdentityEmbedding(nn.Module):\n", + " \"\"\"Pass-through embedding: observation x is fed directly to the network.\"\"\"\n", + "\n", + " def forward(self, inputs: dict) -> torch.Tensor:\n", + " return inputs[\"x\"]" + ] + }, + { + "cell_type": "markdown", + "id": "ba177816", + "metadata": {}, + "source": [ + "## 2. Load the observation" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "308371e2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Observation shape: (3,) values: [6.73794700e-03 1.00000000e+00 1.48413159e+02]\n" + ] + } + ], + "source": [ + "obs = np.load(\"data/mock_data.npz\")[\"x\"] # shape (3,)\n", + "print(\"Observation shape:\", obs.shape, \" values:\", obs)" + ] + }, + { + "cell_type": "markdown", + "id": "4264809c", + "metadata": {}, + "source": [ + "## 3. Build the graph programmatically\n", + "\n", + "`falcon.Graph()` starts empty. `add_node()` accepts live Python objects\n", + "for `simulator=` and `estimator=`; they are shipped to Ray actors via\n", + "cloudpickle — no importable path required." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "43999ff3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "
\n",
+       "flowchart LR\n",
+       "    z[\"z
sim:Product
est:GaussianFullCov
\"]\n", + " style z fill:#d6eaf8,stroke:#2980b9\n", + " x[\"x
ExpPlusNoise · observed\"]\n", + " style x fill:#d5f5e3,stroke:#27ae60\n", + " z --> x\n", + " x -.->|evidence| z\n", + "
\n", + "
\n", + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "graph = falcon.Graph()\n", + "\n", + "graph.add_node(\n", + " \"z\",\n", + " simulator=falcon.priors.Product([\n", + " [\"normal\", 0.0, 0.1],\n", + " [\"normal\", 0.0, 1.0],\n", + " [\"normal\", 0.0, 10.0],\n", + " ]),\n", + " estimator=falcon.estimators.GaussianFullCov(\n", + " max_epochs=8000,\n", + " lr=0.01,\n", + " gamma=0.1,\n", + " embedding=None, # pass-through: equivalent to E_identity\n", + " batch_size=128,\n", + " early_stop_patience=128,\n", + " hidden_dim=128,\n", + " num_layers=3,\n", + " momentum=0.01,\n", + " min_var=1e-20,\n", + " eig_update_freq=1,\n", + " lr_decay_factor=1.0,\n", + " discard_samples=False,\n", + " log_ratio_threshold=-20.0,\n", + " ),\n", + " evidence=[\"x\"],\n", + " ray_num_gpus=0.5,\n", + ")\n", + "\n", + "graph.add_node(\n", + " \"x\",\n", + " simulator=ExpPlusNoise(sigma=1e-6),\n", + " parents=[\"z\"],\n", + " observed=obs,\n", + " ray_num_gpus=0.5,\n", + ")\n", + "\n", + "graph" + ] + }, + { + "cell_type": "markdown", + "id": "181817c8", + "metadata": {}, + "source": [ + "## 4. Launch training\n", + "\n", + "`falcon.launch(graph)` synthesises a default config (buffer, paths, logging),\n", + "saves it as `config.yml` in the output directory, and runs training.\n", + "Pass `overrides=` to customise buffer size or epoch count." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "28ff8ef9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2026-06-08T23:01:39 [INFO] falcon v0.4.3.dev26+g518dce194.d20260608\n", + "2026-06-08T23:01:39 [INFO] Output: output/260608-230139-gifted-spaniel\n", + "2026-06-08T23:01:39 [INFO] Ray: 145.136.62.31:56908 (new local instance)\n", + "2026-06-08T23:01:39 [INFO] Resources: 72 CPU, 1 GPU, 319.0 GB\n", + "2026-06-08T23:01:39 [INFO] Falcon graph structure:\n", + " Node name List of parents Class name\n", + "* z <- | \n", + "* x <- z | <__main__.ExpPlusNoise object at 0x1526a3bb6080>\n", + "\n", + "2026-06-08T23:01:39 [INFO] Observed: x [1, 3]\n", + "2026-06-08T23:01:39 [WARNING] Could not create monitor bridge: The name falcon:monitor_bridge (namespace=None) is already taken. Please use a different name or get the existing actor using ray.get_actor('falcon:monitor_bridge', namespace='None')\n", + "2026-06-08T23:01:39 [INFO] Spinning up graph...\n" + ] + } + ], + "source": [ + "run = falcon.launch(\n", + " graph,\n", + " #output=\"output/notebook_run\",\n", + " overrides=[\n", + " \"buffer.min_samples=1024\",\n", + " \"buffer.max_samples=1024\",\n", + " \"buffer.validation_samples=256\",\n", + " \"buffer.simulate_count=128\",\n", + " \"buffer.simulate_when_full=true\",\n", + " \"buffer.simulate_interval=0.001\",\n", + " \"buffer.snapshot_every=10\",\n", + " \"sample.posterior.n=1000\",\n", + " ],\n", + ")\n", + "run" + ] + }, + { + "cell_type": "markdown", + "id": "e4782c80", + "metadata": {}, + "source": [ + "## 5. Inspect the saved config\n", + "\n", + "The saved `config.yml` is human-readable; live Python objects appear as\n", + "`` placeholders so the file is honest about\n", + "reproducibility." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6aa99746", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "logging:\n", + " local:\n", + " enabled: true\n", + " dir: output/260608-225713-diamond-binturong/graph\n", + "paths:\n", + " imports: []\n", + " graph: output/260608-225713-diamond-binturong/graph\n", + " samples: output/260608-225713-diamond-binturong/samples\n", + "buffer:\n", + " min_samples: 1024\n", + " max_samples: 1024\n", + " validation_samples: 256\n", + " simulate_count: 128\n", + " simulate_when_full: true\n", + " simulate_interval: 0.001\n", + " snapshot_every: 10\n", + "sample:\n", + " posterior:\n", + " 'n': 1000\n", + "graph:\n", + " z:\n", + " evidence:\n", + " - x\n", + " simulator: ''\n", + " estimator: ''\n", + " ray:\n", + " num_gpus: 0.5\n", + " x:\n", + " parents:\n", + " - z\n", + " simulator: ''\n", + " observed: ''\n", + " ray:\n", + " num_gpus: 0.5\n", + "run_dir: output/260608-225713-diamond-binturong\n", + "\n" + ] + } + ], + "source": [ + "cfg_path = run.run_dir / \"config.yml\"\n", + "print(cfg_path.read_text())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e454047e", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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QYMGYeXKlRg0aBC2b9+OJ598Em1tbXjppZcAAL/73e/Q2tqKuro6vPLKKwCAQYMGYezYsXjmmWfw5JNP4qGHHsL1118PANL/0Nu3b8e8efOQnJyMp556ClqtFjk5Objhhhvw73//GykpKbL23nnnnRg9ejSef/55iKJo9WexZMkShIaG4umnn8bhw4exadMmHDt2TCrcoKajowOzZs1CRUUFlixZgoSEBHz44YdIT09HS0sLHnvsMURGRmLTpk149NFHMX/+fNx+++0AgGuuucZsW06ePIlp06ahvb0dy5YtQ0REBN5++23ccsst+OijjzB//nzMmDEDW7Zswb333osbb7zR5H9Wpd/97nd48MEHZdfeeecdfPXVV6r/iBqrr6/HqVOnMHHiRJPnUlJS8MUXX1h8vTm//OUv8dvf/hYffPABHn/8cdlzH3zwAW666SaEhYXh/PnzmDNnDrq6urB06VIMHz4c9fX1+Oyzz9DS0oKQkBC7P7uiogJ33HEHHnjgASxatAhvvfUW0tPTkZycjCuvvBJAdzBPTU2FTqfDmjVrMHDgQLz++uuqnfAtW7Zg0aJFmDNnDl588UW0t7dj06ZNuO6663DgwAHEx8fjhhtuwG9+8xusX78et912GyZMmIATJ05g6dKlSEtLwyOPPNKjnyM5B+PjJYyPrnfzzTdj0KBB+OCDDzBz5kzZc++//z6uvPJK6fdywYIF+O9//4ulS5ciPj4ep06dwjfffIOamhrEx8fb/dnNzc2YO3cubr/9dvzyl7/ERx99hNWrV+Pqq6/GvHnzAHT//c6ePRs1NTVYtmwZoqKisGXLFmzfvt3k/Wz5/Rw7diyeffZZPP7447jjjjtwyy234Ny5c0hPT8fll1+OZ555xv4fIjkVY+QljJH2a2hoAAAMGTKkR69njPSwGCmSQ3z99deij4+P6OPjI06dOlX87W9/K3711Vfi+fPnZfeVl5eLWq1WnD9/vqjX62XPCYIg/bm9vd3kMx5++GExKChI7OzslK7dfPPNYlxcnMm9e/fuFQGIOTk5Jp8xevRocc6cOSafl5CQIN54443StaeeekoEIN599902/QxycnJEAGJycrLs+/7Tn/4kAhA//fRT6drMmTPFmTNnSo83bNggAhDfeecd6dr58+fFqVOnioMGDRLb2tpEURTFn376SQQgPvXUUza1afny5SIA8d///rd07cyZM2JCQoIYHx8v+zsAIGZmZtr0vsZ2794tDhgwQLz//vula4afnZLh7+V///d/TZ57/PHHRQCyv19RvPRz3bt3r8V2TJ06VUxOTpZdKykpkX3egQMHRADihx9+aPP3Z7Bo0SJx4MCBsmtxcXEiAHHnzp3StVOnTon+/v7iqlWrpGuGv4fi4mLZfSEhISIAsbq6WhTF7r+b0NBQcfHixbLPaWhoEENCQmTXz507J44aNUq88sorxc7OTvHmm28Wg4ODxWPHjtn9vZFzMT4yPtoSH5UyMzOt3ldQUGBTTLv77rvFoUOHijqdTrp24sQJUavVis8884woiqLY3NwsAhBfeuklq21TMnxPP/30k3Rt5syZJvG+q6tLHD58uLhgwQLpmuHv94MPPpCuGeIbALGgoEAURft+P/V6vXjdddeJw4YNE0+fPi1mZmaKvr6+Vv8dIfdgjGSM7EmMNEhLSxODg4PF5uZmk+cYI70vRnJZu4PceOONKCwsxC233IL//Oc/+NOf/oQ5c+Zg5MiR+L//+z/pvk8++QSCIODJJ5+EViv/8RuPCBrPKJ45cwanT5/G9ddfj/b2dvz44489bmdZWRnKy8vx61//Go2NjTh9+jROnz6Nc+fOYfbs2di5c6fJUmN7ZyEfeughDBgwQHr86KOPwtfX1+Ks8BdffIHhw4fj7rvvlq4NGDAAy5Ytw9mzZ1WX2tjiiy++QEpKimwp1aBBg/DQQw/h6NGj+OGHH3r0vgYNDQ244447MG7cOPztb3+zen9HRwcAwN/f3+S5gIAA2T32uuuuu1BaWorKykrp2vvvvw9/f3/ceuutACDNjH/11Vdob2/v0ecoXXHFFdLIOgBERkbisssuQ1VVlXTtiy++wJQpU2Qj6pGRkbjnnntk7/XNN9+gpaUFd999t/S7efr0afj4+GDy5MkoKCiQ7g0KCkJubi4OHTqEGTNm4PPPP8crr7wi2y5AnoHx8RLGR/e46667cOrUKVmV5o8++giCIOCuu+4C0P175efnhx07dti0jNYWgwYNkhV18vPzQ0pKikl8HDFiBO644w7pWlBQkEn9EXt+P7VaLXJzc3H27FnMmzcPf/vb37B27VrVVVvkfoyRlzBG2uf5559HXl4eXnjhhV7teWeM9JwYyeTcgSZNmoSPP/4Yzc3NKCkpwdq1a3HmzBnccccd0v/AlZWV0Gq1uOKKKyy+13//+1/Mnz8fISEhCA4ORmRkpPTL25O9wQbl5eUAgEWLFiEyMlL29cYbb6Crq8vk/RMSEuz6jNGjR8seDxo0CCNGjLC4H+XYsWMYPXq0yT82Y8eOlZ7viWPHjuGyyy4zud7b9wUAnU6HX/7yl9Dr9fj4449VE24lwz+YavtkDMdg9HS/5Z133gmtVov3338fACCKIj788EPMmzcPwcHBALr/LleuXIk33ngDQ4YMwZw5c5Cdnd2r3ym1ZDgsLEwWuA1/v0rKvxvD7+cNN9xg8vv59ddfmxTGmT59Oh599FGUlJRgzpw5uP/++3v8fZBzMT52Y3x0D8P+Q0N8BLoHL8eNG4cxY8YA6B40ffHFF/Gvf/0Lw4YNw4wZM/CnP/1JWjLaE9HR0SZLcdXi46hRo0zuMxcfbf39TEpKwtNPP429e/fiyiuvxB/+8Icefx/kfIyR3Rgjbff+++/j97//PR544AE8+uijPW4LwBjpSTGSe86dwM/PD5MmTcKkSZMwZswYZGRk4MMPP8RTTz1l0+tbWlowc+ZMBAcH45lnnkFSUhICAgKwf/9+rF692mwRLVsYXvvSSy+ZPR5DeZa1o4vz9BWPP/44CgsLkZeXh+joaJteM2LECADAiRMnTJ47ceIEwsPDe9yJjYqKwvXXX48PPvgATzzxBIqKilBTU4MXX3xRdt+f//xnpKen49NPP8XXX3+NZcuWYf369SgqKrL5+zDm4+Ojel20YW+ZkuH3c8uWLRg+fLjJ876+8pDV1dUljfJWVlaivb0dQUFBdn8uuQ7jY//Qk/joTP7+/rjtttuwbds2/O1vf8PJkyexe/dukyOGli9fjl/84hf45JNP8NVXX+EPf/gD1q9fj+3bt2P8+PF2f64z4qM9v5+GImHHjx9HY2Ojalwlz8IY2T/0NkZ+8803uO+++3DzzTfjtdde63V7GCM9J0YyOXcyw/IIQzKWlJQEQRDwww8/mP3F2bFjBxobG/Hxxx9jxowZ0vXq6mqTe80VxzB3PSkpCQAQHBzstOMWysvLkZqaKj0+e/YsTpw4gZ/97GdmXxMXF4fvvvsOgiDIRj4Ny6/i4uIAmP++LL3v4cOHTa4r39de7733HjZs2IANGzaYFM+wZOTIkYiMjMS+fftMnispKen1eaJ33XUXfvOb3+Dw4cN4//33ERQUhF/84hcm91199dW4+uqr8fvf/x579uzB9OnT8dprr+G5557r1eebExcXJ41oGlP+3Rh+P4cOHWrT7+dTTz2FQ4cO4eWXX8bq1auxZs0avPrqq45pNDkd4yPjoyvdddddePvtt5Gfn49Dhw5BFEVpuaaxpKQkrFq1CqtWrUJ5eTnGjRuHP//5z3jnnXec0q64uDgcPHgQoijK/g7NxUdbfz9fe+01fPPNN/jjH/+I9evX4+GHH8ann37q2MaTUzFGMkaqKS4uxvz58zFx4kR88MEHJhMXPcUY6RkxksvaHaSgoEB1lMewR8aw9OK2226DVqvFM888YzJ6aXi9YRTJ+P3Onz+vuh9l4MCBqkuUDOdItrS0yK4nJycjKSkJL7/8Ms6ePWvyup9++sns92ir119/HRcuXJAeb9q0CTqdTqq6qOZnP/sZGhoaZMtpdDodNm7ciEGDBknByzArqvy+LL1vSUkJCgsLpWvnzp3D66+/jvj4eKtLw9QcPHgQDz74IBYuXIjHHnvM7tcvWLAAn332GWpra6Vr+fn5OHLkCO68806730/53j4+PvjnP/+JDz/8ED//+c9lZ4q2tbVBp9PJXnP11VdDq9WaPZLCEX72s5+hqKgIJSUl0rWffvoJ//jHP2T3zZkzB8HBwXj++edlv0PGrzEoLi7Gyy+/jOXLl2PVqlV4/PHH8de//rXHe8vIeRgfL2F8dJ+0tDSEh4fj/fffx/vvv4+UlBTZktv29nZpe5FBUlISBg8e7PT4ePz4cXz00Ueytrz++uuy++z5/ayursbjjz+OBQsW4IknnsDLL7+M//u//1M95pLcjzHyEsZIyw4dOoSbb74Z8fHx+Oyzzxy6MoEx0jNiJGfOHWTp0qVob2/H/Pnzcfnll+P8+fPYs2cP3n//fcTHxyMjIwMAMGrUKPzud7/Ds88+i+uvvx633347/P39sXfvXkRFRWH9+vWYNm0awsLCsGjRIixbtgwajQZbtmxRDdzJycl4//33sXLlSkyaNAmDBg3CL37xCyQlJSE0NBSvvfYaBg8ejIEDB2Ly5MlISEjAG2+8gXnz5uHKK69ERkYGRo4cifr6ehQUFCA4OBj/7//9v179LM6fP4/Zs2fjl7/8JQ4fPoy//e1vuO6663DLLbeYfc1DDz2EzZs3Iz09HaWlpYiPj8dHH32E3bt3Y8OGDRg8eDCA7uVRV1xxBd5//32MGTMG4eHhuOqqq8wePbJmzRr885//xLx587Bs2TKEh4fj7bffRnV1NbZu3WqyP8kWhr/LGTNmmIwSTps2DYmJiRZf/8QTT+DDDz9EamoqHnvsMZw9exYvvfQSrr76aum9e2ro0KFITU3FX/7yF5w5c8ZkxHP79u1YsmQJ7rzzTowZMwY6nQ5btmyBj48PFixY0KvPtuS3v/0ttmzZgrlz5+Kxxx6TjlIzjHYbBAcHY9OmTbj33nsxYcIE/OpXv0JkZCRqamrw+eefY/r06fjrX/+Kzs5OLFq0CKNHj8Yf//hHAN3Hy/y///f/kJGRge+//142KEHuxfh4CeOj5fh47NgxbNmyBQCkFUaGFT1xcXG499577W6TwYABA3D77bfjvffew7lz5/Dyyy/Lnj9y5Ij0d3PFFVfA19cX27Ztw8mTJ/GrX/2qx59rzeLFi/HXv/4V9913H0pLSzFixAhs2bLFZIuOVqu16fdTFEXcf//9CAwMxKZNmwAADz/8MLZu3YrHHnsMaWlpiIqKctr3Q/ZjjLyEMdJ8jDxz5gzmzJmD5uZmPP7447Lz1oHuRHnq1Kl2t8mAMdJDYqQrS8P3Zf/617/E+++/X7z88svFQYMGiX5+fuKoUaPEpUuXiidPnjS5/6233hLHjx8v+vv7i2FhYeLMmTPFb775Rnp+9+7d4pQpU8TAwEAxKipKOlYDRkcGiKIonj17Vvz1r38thoaGigBkR2J8+umn4hVXXCH6+vqaHIlx4MAB8fbbbxcjIiJEf39/MS4uTvzlL38p5ufnS/eoHXtgieEYjG+//VZ86KGHxLCwMHHQoEHiPffcIzY2NsruVR6DIYqiePLkSTEjI0McMmSI6OfnJ1599dUmx3iIoiju2bNHTE5OFv38/Gw6EqOyslK84447xNDQUDEgIEBMSUkRP/vsM5P7YOMxGIbjw9S+DO21dgzGwYMHxZtuukkMCgoSQ0NDxXvuuUdsaGhQvdfWo9QM/v73v4sAxMGDB4sdHR2y56qqqsT7779fTEpKEgMCAsTw8HAxNTVVzMvLs/q+5o5Su/nmm03uVfv7/e6778SZM2eKAQEB4siRI8Vnn31WfPPNN2VHqRkUFBSIc+bMEUNCQsSAgAAxKSlJTE9PF/ft2yeKoiiuWLFC9PHxkR3NJoqiuG/fPtHX11d89NFHrX4/5DqMj4yPtsZHw7E/al/Kn4nx/bYeD/nNN9+IAESNRiPW1tbKnjMcp3P55ZeLAwcOFENCQsTJkyfLju8xx9wxQVdeeaXJvYsWLTI5vurYsWPiLbfcIgYFBYlDhgwRH3vsMfHLL780+Z0WReu/n1lZWSIAcevWrbLX1dTUiMHBweLPfvYzq98PuRZjJGOkLTGyurra7GsBiIsWLTJ5DWOk98VIjSj2YMc9kYrc3FxkZGRg7969HnEUgTs9/fTTWLduHX766SdoNBpERETY/R7nz59HW1sb3nvvPSxdupQ/VyIvxvh4iSPio16vR3NzM3bv3o3bbrsNH374oeyYHSLyLoyRlzBG9m9c1k7kRJGRkRg4cKDq3hdrvvjiC8yfP98JrSIicr/exMfvv/++R5WBiYi8BWNk/8TknMgJ7rvvPlx33XUATI//stX06dPxzTffSI/VztokIvI2joiPo0aNksXHa665xiFtIyJyN8bI/o3JOZETJCYmWi18ZE1kZKTTjiohInIXR8THQYMGMT4SUZ/EGNm/cc85ERERERERkZvxnHMiIiIiIiIiN2NyTkRERERERORm/WrPuSAIOH78OAYPHgyNRuPu5hCRlxFFEWfOnEFUVBS02r41tsn4SES91VdjJOMjEfWWrfGxXyXnx48fR0xMjLubQURerra2FtHR0e5uhkMxPhKRo/S1GMn4SESOYi0+9qvkfPDgwQC6fyjBwcFubg0ReZu2tjbExMRIscSTbNq0CZs2bcLRo0cBAFdeeSWefPJJzJs3z6bXMz4SUW95cozsDcZHIuotW+Njv0rODUuRgoODGVyJqMc8cVljdHQ0XnjhBYwePRqiKOLtt9/GrbfeigMHDuDKK6+0+nrGRyJyFE+Mkb3B+EhEjmItPvar5JyIqK/6xS9+IXv8xz/+EZs2bUJRUZFNyTkRERERuReTcyKiPkav1+PDDz/EuXPnMHXqVNV7urq60NXVJT1ua2tzVfOIiIiISEXfKaVJRNTPff/99xg0aBD8/f3xyCOPYNu2bbjiiitU712/fj1CQkKkLxY7IiIiInIvJudERH3EZZddhrKyMhQXF+PRRx/FokWL8MMPP6jeu3btWrS2tkpftbW1Lm4tERERERnjsnYioj7Cz88Po0aNAgAkJydj7969yMrKwubNm03u9ff3h7+/v6ubSERERERmcOaciKiPEgRBtq+ciIiIiDwXZ86JiPqAtWvXYt68eYiNjcWZM2fw7rvvYseOHfjqq6/c3TQiIiIisgGTcyKiPuDUqVO47777cOLECYSEhOCaa67BV199hRtvvNHdTSMiIiIiGzA5JyLqA9588013N4GIiIiIeoHJuYvo9AKyCyqx92gTJsWHIzM1Cb4+3PJPRH0X4x4Rkesw5hJ5PybnLpJdUIkNeUcgAthdcRoA8FjaaPc2iojIiRj3iIhchzGXyPt5zXDa+vXrMWnSJAwePBhDhw7FbbfdhsOHD7u7WTbbe7QJ4sU/ixcfExH1ZYx7RESuw5hL5P28Jjn/9ttvkZmZiaKiInzzzTe4cOECbrrpJpw7d87dTbPJpPhwaC7+WXPxMRFRX8a4R0TkOoy5RN7Pa5a1f/nll7LHubm5GDp0KEpLSzFjxgw3tcp2malJACDbB0RE1Jcx7hERuQ5jLpH385rkXKm1tRUAEB5uflSwq6sLXV1d0uO2tjant8scXx8t9/0QUb/CuEdE5DqMuUTez2uWtRsTBAHLly/H9OnTcdVVV5m9b/369QgJCZG+YmJiXNhKIiIiIiIiItt4ZXKemZmJgwcP4r333rN439q1a9Ha2ip91dbWOrVdOr2ArLxyLHyjGFl55dDpBad+HhEREREREfUNXresfcmSJfjss8+wc+dOREdHW7zX398f/v7+LmqZ9SMseP4kERERERERqfGa5FwURSxduhTbtm3Djh07kJCQ4O4mmbB2hAXPnyQiIiIiIiI1XjNtm5mZiXfeeQfvvvsuBg8ejIaGBjQ0NKCjo8PdTZNYO8KC508SERERERGRGq+ZOd+0aRMAYNasWbLrOTk5SE9Pd32DVFg7wmJSfDh2V5yGCJ4/SURERERERJd4TXIuiqL1m9zM3BEWhr3mJdWNmJIYAa0GSEmI4PmTREREREREBMCLknNvZrzXXANgedoY7jUnon6NBTKJiIiI5Jic28neDqVOL2Dr/jruNSciMsICmURERERyTM7tZG+HMrugEjVN7bJr3GtORP0dC2QSERERyXENoZ2UHcqS6kZk5ZVj4RvFyMorh04vmNxvLDY8iHvNiajfs3a6BREREVF/w5lzOykrrgsiLM6kK+9fMCGa+yqJqN+zdroFERERUX/D5NxOyg5lSXWjbCZ96/46WWeTHVAiIlPmTrcgIiIi6q+YnNtJ2aHMygP2VF5K0Gua2lHT1C6bRWcHlIiIiIiIiCxhct5LmalJEAQRuYVH0dpxQbrOAkdERERERERkK25+7iVfHy20Wo0sMTdggSMiIiIiIiKyBZNzB1CbIZ+aGMH95URERERERGQTJucOoJwhn5oYgS0PpLAqOxEREZEHqK+vx8KFCxEREYHAwEBcffXV2Ldvn7ubRUQkwz3nDqBWkV0tMdfpBWQXVGLv0SYkx4YBGhGlx1osvoaIiIiIeq65uRnTp09Hamoq/vWvfyEyMhLl5eUICwtzd9OIiGSYnDuArUcCZRdUSmei77pYzR1QPx+diIiIiHrvxRdfRExMDHJycqRrCQkJZu/v6upCV1eX9Litrc2p7SMiMuBUrQvtPdokHblmjJXdiYiIiJzj//7v/zBx4kTceeedGDp0KMaPH4+///3vZu9fv349QkJCpK+YmBgXtpaI+jMm5y40KT4cGjPP6QUROr3g0vYQERER9XVVVVXYtGkTRo8eja+++gqPPvooli1bhrffflv1/rVr16K1tVX6qq2tdXGLiai/4rJ2BzPeVz4pPhwPz0jA5p3V0j7zZbNHofRYC5Jjw1Bc3Yii6u4Z88KqRtz7ZgkLyRERERE5kCAImDhxIp5//nkAwPjx43Hw4EG89tprWLRokcn9/v7+8Pf3d3UziYiYnDua8b7y3RWnUVTViKKqRmmf+dTECPhoNdBqNfDRyufRC6sakV1Qyb3nRERERA4yYsQIXHHFFbJrY8eOxdatW93UIiIidUzOHcx4X7kI4NCJNtk+88KqRgDdifuUxAjV1xMR9RXK1UQ8mYKIXG369Ok4fPiw7NqRI0cQFxfnphYREaljD8nBjPeVawCMHRGsus9cBKDVdJ+JDqP7lWemExF5M8Nqol0Vp7Eh7wiyCyptep1OLyArrxwL3yhGVl45a3IQUY+tWLECRUVFeP7551FRUYF3330Xr7/+OjIzM93dtF5hnCTqezhz7mDKM8+N95zrBVFa4q4BkJIQgczUJJNZJSKivkK5msjW1UHKLUIAj5skop6ZNGkStm3bhrVr1+KZZ55BQkICNmzYgHvuucfdTesVxkmivofJuRX2LslUO/Pc8NjcezGQElFfNSk+HLsrTkuDkrauDuppUk9EpObnP/85fv7zn7u7GQ7FOEnU9zA5t8KRo5JMxImov1GuJrJ1dVBPk3oiov6CcZKo72FybkVJdaNsVLKkuhFAzxJsFkYiImdZv349Pv74Y/z4448IDAzEtGnT8OKLL+Kyyy5zaTvU4lxPBiV7mtQTEfUXjJNEfQ+TcysE0fJje3BvEBE5y7fffovMzExMmjQJOp0OTzzxBG666Sb88MMPGDhwoMva4ag4x5VGRESWMU4S9T1Mzs0wzP78cKJVdl2rVnrdRtwbRETO8uWXX8oe5+bmYujQoSgtLcWMGTNc1g7GOSIi1+GqTKK+hcm5GcazPwaGCutqbAmO3BtERK7S2to9sBgerh5nurq60NXVJT1ua2tzyOcyzhERuQ5XZRL1LUzOzTCe/QGA0MAByJieYHY/jy3BkXuDiMgVBEHA8uXLMX36dFx11VWq96xfvx7r1q1z+GczzhERuQ5XKxH1LUzOzVDO/mRMTzA7EqnTC9i6v85qcDTsDTLMsqfn7OUSJCJyuMzMTBw8eBC7du0ye8/atWuxcuVK6XFbWxtiYmJ6/dncA0lE5DqeslqJy+uJHMOrkvOdO3fipZdeQmlpKU6cOIFt27bhtttuc8pn2TP7k11QiZqmdtk1S8GRS5CIyFmWLFmCzz77DDt37kR0dLTZ+/z9/eHv7+/ClhERkaMZ+qcl1Y0QxO7/ZuXB5ckx+7ZEjuFVyfm5c+dw7bXX4v7778ftt9/u1M8yN/ujNjKonCWPDQ+ymMxzCRIROZooili6dCm2bduGHTt2ICEhwd1NIiIiJ1H2RyfGh+HV/AqIAPZUNgJwbXLMvi2RY3hVcj5v3jzMmzfPZZ/XeV6H9Jy9KKttgZ+vBmOHB+N4aydqmzsAXBoZVC4pWjAh2uJopfH9AFDT1I6svHIuASKiHsvMzMS7776LTz/9FIMHD0ZDQwMAICQkBIGBgW5uHREROVJ2QSVeyTsCANhVcRr+vlq3JseesryeyNt5VXJur95WI87I3Yei6u7g1qkDio82y54XAWzdX4evl18PwPYCSIbnt+6vQ01TO2qa2rHhYoDlEiAi6olNmzYBAGbNmiW7npOTg/T0dNc3iIiInEaZfHfpBOnP7kiObdkOyn3pRNb16eS8t9WID52wnszXNLVj885qu5Jqw5L5vUebpL3qXAJERL0hiqL1m4iIqE+YFB+OXRdXcBoE+GoxMT7c6SdlmEuyrfWFuS+dyLo+PVy1du1atLa2Sl+1tbV2vX7siGCb7utpUj0pPhyai3/mEiAiIiIiskVmahKiw+RblsbHhiE3YxIAID1nL7LyyqHTC2ov7xVDkr2r4jQ25B1BdkGlTa/jvnQi6/r0zHlvqxHnpE802XPu66OFIAJFVY293lfD84CJiMzjEkgiInW+PlrkrZiBjNx9OHSiDWNHBOPv907AvW+WoLCquyCcs2anlUn2ph0V2Lq/DvPHR2HpDaPNxmnuSyeyrk8n570V4OeL9x6eanLd0GHs7bEVPA+YiMg8LoEkIjIvwM8X/3xoivQ4K69cSswB581OKwsbd+qE7uLG+RXYduA4FkyIVu0Tc1KKyDqvSs7Pnj2LiooK6XF1dTXKysoQHh6O2NhYh36WpRkbQ1KdlQep42g4tiIzNUlK3PWCiPqWDmg0Gmk0EQBngoiIzDCOvTVN7VwCSURkI7UY6YzZaUNSnbO7Gi0dF2TPWSpyrJyU0ukFZOWVs09MZMSrkvN9+/YhNTVVerxy5UoAwKJFi5Cbm+vQz7JlxkZt70x2AaSjLYxl5VdAq+kOOJwJIiK6xDgh1wuitG3IGJdAEhGpM8RQQ5Fhg6mJEU6ZnTZOstX6vIY+sbWtSVwdRWTKq5LzWbNmuawisaWiFWpB0NBxtDSzY3iOM0FE1Nf0Zn+4cQdNKTY8CLHhQVwCSURkhjKGRocGABoNfjjRinvfLEFO+kQE+Dmmy28c65Njw7A0NQmv/7tadpQb0N0nVibfgtDdwm1l9QC6Txkx7hN/VFrLWXTq97wqOXclS0UrlEEwNjxI2l+TXQCToy2M3xMAi2EQUZ/TmxkQ48FQYxoACyZEcyaFiMgCZQw906VH68Xl5oVVjcjI3Sfbm94bxrF+V8VpxIYHSScPGfhqNXhgehzmvbpLlny/trPSJIk3VtvcgdrmDuyqOI1NOyowLiYUk+LDcKC2lQk79RtMzs0wV7RCpxewdX+dLAjGhgdJncfM1CQUVTXKCnKEBPoifVq8bNaHxTCIqC/pzRE5yuJCUxMj4KPVMEYSEdlAOaHUdUEve/7QiTaHfZZyIEC5lB4AdIKIB/+3FLXNHbLrlhJzpU6dgKLqJhRVd/9bsqviNLLyj8BXq4EgiBAAXJyIh1YD+FwcIbggXLomKEZ9Bw7QoEMnQhABPx8Nro0OQUNbl6w2FJN/cjcm52aYK1qxdX+dSSAynv329dFiywMpFpd3chaIiPqa3hyRozYYyg4SEZFlxqcHTUmMgFYDpCREoLDytJTUAsDYEcEO+yy1ZFyNM7ZtCiJwXm+6zkoQTRNx5WMAOHfh0sXzehF7j7VIj7PyK5CVX2H6IiIL/Hw02LNmFoYMDnLYezI5t1F2QaVq0YvY8CCTmR0ekUZE/U1vjshhzCQisp/xEnMNgOVpY5CZmgSdTsChhjPouqDHuJhQ5KRPdOhn2UIlhybqc87rRUx/8Vscfm6ew96TybmNzI0ALpgQDQB2HQXReV6HjNx9OHSiDWNHBDu0UAcRkTvwiBwiItcyd2rQX3dUSAn71KQhDuljmqsNQtTf2bNdwxbsKdlIbYlmTFigdK75hrwj2FVxGhvyjiC7oNLie2Xk7kNhVSNaOi5IhTqIiPoSe+MiERHZZ1J8uFSMTQMgOTZMVhfJkacCGX8WEV3i7+vYdJrTtTbKTE3Ch6W1qDMqbhEdFgRfH63JyOXW/XUWZ4mUhTnMFerozdFERETu1JsCcUREZJ1yO5EgChbrIjnqs5Jjw5CzpxptnTqHvDeRt/Lz0WD36pkOfU8m5zby9dEiLjxIlpxrLw4hTooPlx2fVtPUjuyCSpM9lIZkW7ksyFyhjt4cTURE5E69KRAHcHCSiMga5XaihW8Uy54P8NVCEAXo9ILD42dwwACXJudTEsLxzoOT+e8A9XlMzu2QkhCBPZWNUnJd29yBrLxyPDwjwaSKu9oskbKYRoCvFuNjw8wW6uDMExF5q94UiAM4OElEZC/lsZSdOgGv5ldAq7G96Ka5gVHl+eauEhsehAUTojlAS/0Gk3M7PDwjAUVVjThQ04xOXffSoQ0XK7gvmBAtq5ipNkukLKYxMT4cuRmTzM4O9XbmiYjIW3FwkojIPpmpSRAEEZt3VqLzYpEqe+OnMgkvqmqEj1aDmqZ2pxeEiwkLxMjQQNS3dPDsceq3mJzbYfPOahRVNcqCkyHo5WZMAmB5lkgt2bY0O9TbmSciIldQm2np7cw3ByeJiOzj66OFVquREnMDe+KnciKpsKrR5tcO9veBKIo4e9726tUaAMGBvrhvShweSxvDRJz6PSbndjB3jIRhj/nDMxKk+7ILumfaN++sljqsxs8bOrDpOXvNzg7x7F8i8gZqiXhvZ745OElEZJnawKgy1saGB9kVP5VL49WMDA3AyJAAlBxrkV0/06W3o/XdpiZF4N3FU+x+HVFfxeTcDsqAFRzgi7ZOHWqa2vFK3hHsqfgJxUebAXQvBSqsPI3i6iZZh7V7RulSAp8cF8rZISLyaiXVjbJEvKS6ESkJEb2KbRycJCKyTG1gVLnqaMGEaLtmow2J/Fu7q9DaoV7wrb6lE2d7kIirqWlqd0rBOiJvxeTcDsqZnI9Ka2WVKktrWmT3l9W2yDqsObu7l8UblsbvrjiNZTeMxvK0MZwdIiKvJYimjznzTUTkXGorlGzZZmmJYWC0qKrR4pL2rguOSc7rmjtUTzgi6q+YnNtBOZOzdX+d7HnlEiD/AT7o0gnS9ZaOC7JAJwIorWnGOw9Odk6DiYhcwHCspPFjznwTETlXclyorHJ6clyow2KvMq4rjYsJRVG1fAm9YUWpvVjwk+gSriHpIZ1eQFRIgOzaxNgw2ePLhw1CTHgQAnzVf8xcxk5EfUFKQgQM/TjNxcdERORkosby414wjutKIYG+mBQfhikJl/qwGgAZ0xKwIm0MYsODbP4c9oWJ5DhzbiND0Y2S6kYIIlDX3I7a5g7p+amJEchJnygVgNMLoklld2OhgQOQMT1BttzI3NmSRESejEvYiYhcr7Sm2eJjWyj7t1pNd2L+8IwECIKIbWX1EEVROuKstrkDrR06/LWgEstuGI2pSUOk1+471oSUhAh8vfx6bNpRhdzCo2jtuGD2s43PMCeibkzObaDTC7j3zRKLe298tBoE+PlKS4kWvlFssdLl2BHBUlE4QxLe26OHiIjcgUvYiYhcT1n8LTk2DFl55XZN8hj3PQ32VHb3d7VaDWovnm9e19yBGKMZceOtmVl5kN7D+LXGiXl0WCDqFJNaWx5I4SQUkQKTcxtkF1RaTMzVluSYO4oiJMAXgwMHSO9nnIT39ughIiJ34uofIiLXUa5aEkQBG/LKIaL71KCt++ukmWlzsVjtmGDjPqhxvxTo7vMqT+FQ9l9zdlcjOHCA7D3jwoNwZ3IM/30gsoLJuQ0sJcnmluQYHm/dX4eapnYA3YHsiqgQk6JwhvdXjoByDw4ReROu/iEich3jVUs6vYAb/vytLNGuaWrHhrwjAMzHYrXJJOM+qHHBuaiQANx67Qh8+p8TAABBFNB5Xge94siOlo4LaDGaNTfUIuG/B0TWMTm3waT4cFlwMrC0JMcQMLvPNb80k1RSbToDbwiAhoTesHenpLoRWXng6CIReQVrq3/smVnnLDwRke2yCyqlySBj1lZiKvuehj3nmalJ0OkFfFhaKy1HL65ugkZzaan7q/kVKKluNru6NDY8CDFhgezTEtmBybkNDIErZ3e1bCTQR6uxGmCUezGz8oDdlZeC2NTECOn9Dfeq7d3haCMReTq1Y30MlLU7rM2scxaeiMh25hJwaysxL/VTTeNrdkGlbJ+4COBATbNsEPaAhSJ0I0MDMTE+DK/mV7BPS2QjJucWKGduFk2LkwKMLcvO1WZ+1KoaKxN87j0nIq9k4VgfZe0OQ2wzN0POOEhEZLvk2DDZ4OiUhHD4+mh7dYKGWtzt1AkWHxsXfiuqakR9SwdjOZEdmJxbkJV3BBsLKgF077nJnJmI5WljZJ1IS0svzc38WBsx5N5zIvJGlo71UeuQTYoPNxsnGQeJiOygke/7npwYjhU3XtartzS3rTPAVytLymPDgxAbHiRt3zQk55aKyBGROibnFvxvUY3s8TsltfjPUzfJrmXllZtdemlp5sdSUs+950TkjSwl1MpOnmFLT3rOXpM4qdMLEARROrZn/vgonoNLRGRB6bEWi497Qq24MQD4D/CRknMNgAUToqW+b1Ze9/J1w78D88eNhFarkfV3icg8JucWdF3QW3wMWE7ALXVULe2n5N5zIvJGatt2LD1nWHKpjJMbt5cja3uF7L1ZOI6ISJ1OL5hUTNcLInR6oVfxUFnc2JCkG84vVzuxyJbtm0RkHpNzC8bFhKKoukn2WEk5G2QcDC11VEuqG2VJfXcVd3nizT2XRNRXKItjGijj5MMzEjB5fb7snm0HjptdnsnCcUTUnymLbRoUVTUiu6DSofGwzagoMtCdnCvf31ysJyLbMDm3IDdjEjJy9+HQiTaMHRGMnPSJJrM0D89IQFFVoxQUjYOhpQClGOA0eQxw7zkReQ97q7ErY2luxiT4+miRlVeO1g6dzZ/LQUwi6s+UxTYNRHQvR+/tzLW55J/9UiLn8LrkPDs7Gy+99BIaGhpw7bXXYuPGjUhJSXHKZwX4+eKfD02RXTPeY76r4jSKqhpx6ESb9LytnUONxvJjwPISUSIiYzt37sRLL72E0tJSnDhxAtu2bcNtt93mss83V43d0v1qM95qr5k/bqTqeyiXcrKzSET9TffKS3U1Te245+/F+MfiyT1O0M0l/yPDAvHwjIQevScRmedVm0Def/99rFy5Ek899RT279+Pa6+9FnPmzMGpU6dc1gbjWRoAKKxqlJ19DnQvbV/4RjGy8sqh0wvQ6QVk5ZXLromKmXLlY+DS0qB3HpwszcQTEak5d+4crr32WmRnZ7vl89WS6pqmdinmqd2vNuOtTK6nJkZg6exRqp+p7DSys0hE1rzwwgvQaDRYvny5u5viEGorL40VH21C9sWTh+yl0wv4qLRW9bm65g6kvbITnedtX+lERNZ51cz5X/7yFyxevBgZGRkAgNdeew2ff/453nrrLaxZs8Ypn6lcepkcFyotNVcK8NV271OvapTNBgEwmSHSKmbKlY+JiOwxb948zJs3z22fr3bkTk1TOzbkHQFgurzd3LadzNQkCIKIbWX1AICUhDCzn6kcEKhr7sDmndXc70hEqvbu3YvNmzfjmmuucXdTHMaW/mNPt/tkF1Si9uKxaGrqmjuQnrMX7z08tUfvT0SmvCY5P3/+PEpLS7F27VrpmlarRVpaGgoLC1Vf09XVha6uLulxW1ub6n3mqO2hXHbDaCxPG2NyrAQAdOoEHG/tlM0G5eyuRnDgAJNrY0cEy859TEmIkD6TlYeJyNl6Gx+VjLfhHGs8J3XozBW8NLdtx9dHC61Wg9qmdogAXs2vgFajXr9DbUCAe86JSM3Zs2dxzz334O9//zuee+45dzfHYVISIrC70vzSdqDn231siadltS09em8iUuc1Wd/p06eh1+sxbNgw2fVhw4ahoaFB9TXr169HSEiI9BUTE2PXZ6rtoSytacZjaaMRe/H8XTXGg5gtHRdMkviWjgsorGrElMQIXDdqCJanjZE6poZ9mLsqTmND3pEeL0UiIrKkt/HRwLBtJz1nL4DuQprRYfL4aLzsUu1+5bYd9dMsTGWmJmFqYoT0mHvOiciczMxM3HzzzUhLS7N6b1dXF9ra2mRfniozNQnRoQGya4P9fRDgq0VIoC+Wpib1qGaR2vFsAOCjmKr3H+Bj93sTkXleM3PeE2vXrsXKlSulx21tbXZ1QNVGDL+vb8WMPxUgKiRAmvk20KC7cJFWq0HO7mrZXvSQwAHSuZAGPloN3nlwsslnsvIwETlbb+OjgVphN+UySw1EZOWVY+/RJugF0WTrj3JW3JbTLIDuWfYtD6SYrDYiIjL23nvvYf/+/di7d69N969fvx7r1q1zcqscw9dHi5jwgahr6ZSuXTUy1KSgsb2UE1R+PhoEDPCBIAg4e/5SUL5vclyvPoeI5LwmOR8yZAh8fHxw8uRJ2fWTJ09i+PDhqq/x9/eHv79/jz9Tbclka8cFtF6cDY8OC0RsWCBEaKDVdC8tMl6GbuiwaqCenKvN8PD4NCJyhd7GR6B7ZmXr/jqTWW7jZLp7EFMjxUNjhvuz8uTL2+2pycEzdYnIktraWjz22GP45ptvEBAQYP0FcNzgpas4o46RcnLovF7Eef2l4m+x4UFYMCGaA6JEDuY1ybmfnx+Sk5ORn58vHQ8kCALy8/OxZMkSp3ymIeCUVDfi4PFWk7N365o7cGdyjGrHULmfUhAFZOVXSM9PTYwwCWg6vQBBEBFzccn8/PFRDHpE5LGyCypNtu0IImSzLVMSI6DVQLWIpubi/cqZ95SECOypbDSpyUFEZK/S0lKcOnUKEyZMkK7p9Xrs3LkTf/3rX9HV1QUfH/nSbEcMXrqSM2Km8WSRmtjwIA6MEjmB1yTnALBy5UosWrQIEydOREpKCjZs2IBz585J1dsdzTAjk5UHs8U2zC07N57N0ekFbMyvkPap33rtCGi1GqTn7MWk+HA8PCMBm3dW46PSWpOqmCwGR0S2OHv2LCoqLg0AVldXo6ysDOHh4YiNjXXKZyrjX2x4kMmMjY9Wg0nx4VLHEegenDRcV+4v37q/Dl8vv156fy5VJ6LemD17Nr7//nvZtYyMDFx++eVYvXq1SWLujcwV2LTEWgFiw3sot2ka6AUROr3AfiqRg3lVcn7XXXfhp59+wpNPPomGhgaMGzcOX375pUmROEczV4zI1mXn2QWVeHV7uTSiue9Yi2zPZVFVo/TY2LYDx7Hixst62Xoi6g/27duH1NRU6bFhSeaiRYuQm5vrlM9UbsNZMCEagijIBjOT40Jlq5AEsXvJpXEH0vj+mqZ2HodGRA4zePBgXHXVVbJrAwcOREREhMl1b9WT7T1q9UKM38P4PV+5eCSmsaKqRmQXVDJWEzmYVyXnALBkyRKnLWM3R1mMKDosEPERA20enVQWeTt0os3sY2OtHRew8I1iHqlGRFbNmjULomhuAaJzqM3WbDTavgMAH++vh1ajle41dAb3XEzIM1OTTI6m3Lq/jjGPiMiJlH3TrfvrVGfRjeN8TVO7FKsNr2GsJnIsr0vO3UG5TDMuPMikyro5yqMoNADGjgiWZsqVj421dlzArorTZisaExG5k2FmxbA8Mj1nr8ke9NrmDmy4OOuidhqFr89oLJgQLZuZqWlq54wMETnNjh073N0Eh7G2PN0c5Z5yQ+Jt3Oc0fu/k2DDo9IIsxjNWEzkek3Mb9KbQhvIoiimJEchJn4jNO6ulQGrYc2685LO2uUM2Oskj1YjIUxkvj1RjiGHmTqNQmz1nzCMiss7a8nRzLM2IG+JvdkGlNHCqPL3IgLGayLGYnNvA3kIbxiONylmkQyfasHln9cWRzUvBszuQXnr8ytdHkLW9XHqcHBvmgO+EiMjxjGfEAUjFLw3xz5CIm4ulvj5aLJgQLTt+ksdIEhFZp7YiyRbGe8qz8spV46+192KsJnI8Juc2sLfQxsb8Cllibayl44K0xDMzNcn8UiSNYg5K+ZiIyEOoFYYzF9/MxdKeVBsmIurvzK1Isoe5+DspPtzsjDnPOSdyDibnNrB3P8+2snrZ4+AAX5zXCejUCQAujWxmF5ie72vY47PtwHHZe5Qea3Hkt0RE5DBqHTtLibi5mNqd0F+Kjyw0RERkmSMGNs3F68zUJBRVNcq2Zxon5YzPRI7H5NwGPd3PY6DRaKTE3GBSfLjZpUjZBZUmy+G5bIiIPJW9q4vMxdTexloiov7GmQObvj5abHkgxWQwFUCPitARkXVMzm2gTKJLqhuRlWc6S2Qwf3wUsoyOEwoO8EVrxwXpcWx4kBRI1ZYiKff4GO4nIuoLzA1M9nTvJBFRf6XTC7j3zRJpdtvRA5tqg6/Ge9Q5kErkWBzmssGk+HAYTlPToPvc8w15R7Cr4jReyTuCe98swcI3ipGVVw6dXsCjM5MwNTECoYEDMDUxAreNi5K9fsGEaACAIIiICQ9CbHgQls0eJdvjo7yfI5JE1FcoY5xhYDI5LlR2n/IxERHJKU8FMpw/rtMLJvfq9AKy8splfdae4EAqkfNw5twGyv08JdXyM8mVo5UApHPLC6saUdfcjimJEdBquo9hMxRKenV7ufQ+JdXNSM/ZKx2tZvx5nDUnIm+nPC932exRKD3WIo9xokb+IuVjIiKSUUuMzZ0/7qitQ44oQkdE6pic20C5pCcrD9K558aMRw+Nn6tt7kBdcweWp42R3kd59JAywWdhJCLydPYUy1R2CpenjcE7D06W3VNa02zxMRERyZmrqK6WtDtqxpunaxA5D5PzHjAOSnpBlGbJjUcPDSOKBiKAnN3V0uuNRx2huM9SJXciIk9hzyyMWqdQmdwnx4VyNoaIyA6GPunW/XVSMWFz8bO3M97KmJ2bMYkTR0QOxuS8B4xn0tVmjgyMAyVgesY5cKmDWlR9afQyOTaM+3mIyOPZE6fUOoXK5H7ZDaOxPG0MZ2OIiGxk6JMatkxaip/2zHir9W95ogaR8zE57yVzRwgZB8qc3dVouVit3dCB9fUZLZ1pvvCNYvmLNSL38xCRx7MnTql1CtNz9sqS+21l9YgND+rx0Tz2LLMnIupLbDnS0pZ7dHoBG/MrkFt4VDppyJCIc+KIyPmYnPeApQ6guZl0w0ijsgObXVApmzUHgNJjLcjNmASA+3mIyHPZOgtjLmYqt/fUNLWjpqkduypOo6iqET5ajV1JdnZBJV65uDrJ8B5bHkhhgk5EZKON+RXI2l4uu2ZIxDlxROR8TM57wNKyHrXnLHVg1UYd9YIoVW7nfh4i8lRqszD2LIU0jo2GxNygJ2f2KuNpYVWjasViIiJSt62sXvW6cf+VE0dEzsPkvAeUy3r+tqMCD0yPw6BAP9UlP4Yl7GqUVTajwwKlAnPcz0NE3kYtETe3FNKQ3Hee1yHtlZ2q72fP0km1qsVcdklE1DvRYYHSCib2SYmci1OyPaBcxtOlEzD31V3Sc4aTeW1Z8pOZmoQVaWNw3aghWJE2BnHhQbJObM7uamTllUOnFxz6PRAROYNaIm4tLmbk7kNdc4f02Ed76Xxze5ZOZqYmYWpiRI9eS0REwPzxUSbX4sKDuIqTyEU4c26F2hLNzNQkaWbIoKG1E8ClJewl1Y0QxO7/ZuWZnlNu7jgK5RnqxhXeOVpJRJ5ObU+itaWQh060yR7rhe4IGBsehAUTom1eOunro8WWB1KsViwmIuqPbCma+ejMJGzdXy8NmGoApCREqLwbETkDk3MrzO2VHBkWKJvpGR4SAODSMs2svEtF4PZUNkqvs/a+ho6kWoV3IiJPYm7wEoBJ58/S4OLYEcHSHnNjseFBZl9nrpPJZZdEROpsOQpt885qWf92SmIEBzmJXIjJuRXm9kp+uew6zH11FxpaOzE8JABfLrvOpteZe76kuhGvfC1KhTguHz4YxdVNrIhJRB7LXEfP1uTYkGBrICI6LBA/nelCl657C4+1uKdWmT0nfSI276zmUWpERCpsOQpNec1Hq2EcJXIhJudWmDs2YlCgH3atvsHu15l7XhAhO7qipqkdUxMjZEcJERF5kt6eeWuc3GsALLthNLRajU1L0tUqs2fk7lMtqMnzz4mIrPdNlfcA3f3RrLxyxk0iF2FybkVPj43ITE2CIFyaCRdEATq9IAU24/dNjg3DxwfqTN7DR6vBOw9OdsS3QUTkcD0589aQKJdUN+Lg8VZZcl9a02xzzDNXmV1tsMCWpZxERH2dtb6p8T25hUfR2nEBNU3trH1E5EJMzq3o6f5FXx8ttFoNapvaIQJ4Nb8CWs2l9zJ+36y8ctQa7e8x4FJ2IvJkPRm8NE6UleyJeZmpSSiqapTtVdcJl97VeLBAmbTn7K6GIIiARkTpsRbOphNRv2Ctb2q4BxoRrRfrHgGsfUTkSkzOHUC5ZPLhGQnYvLMaOburbVryqbwe4KvFwzMTuZSdiDyavYOXOr2ArfvrVBPz2PAgu2Ker48WOekTkZG7D3uPNskS89DAAciYniC9n3KZZkvHBdk2Is6mE1F/oRys3Lq/zmTLz7YDx01exwkjItdgcu4AyiWTRVWN0r5HA0tLPpVLQx+dNYqdRCLqc7ILKlHT1G5yXQNg/riRdu8L37yz2qTKuwZAxvQEWQxVOwXDmKGDytlzIurr1PaU1zS1Y1fFaQiigBU3XmbympDAAZwwInIR9kIcQDkKeehEmywxDw0cgOVpY8wGtszUJCy7YTRiw4MQEx4k7QEiIupLzK0empIYAWhEbMg7gl0Vp/FK3hHc8OdvkZVXbjEWqr2f2rE/hhn+jOkJZt+rpqkd2QWVNn4nRETeKTM1CcvTxuC6UUMQEiifozPMmM8fN1J2PX1qPAcuiVyEM+c2sFbpVzkKqZwxV87iKCn3AGXlVyB3zzGEBA7A/PFRWHrDaAZFIvIY5rbymIuROr2AjfkV+L6+VfX9fLQalB5rkcVOW4oQqRWFUx7703leh4zcfTh0og2XDx+MyfFhKD7arPp+3FNJRH2d8XakGX8qQGuHTnpOFEVk5ZVj79FGRIcF4kznBVwxIgSPzkp0V3OJ+h0m5zawVunXMEuzdX8daprapSIaseFBWDAh2qalQMaz7wDQ2nEBrR0XkKVSrIOIyJ0sbeVRxkidXsC9b5aYLD83MN7yYzzICZjfD2mgLApn/F6GAYHXdlZKZ6cXVTfB39f8QKdeEE0qFxMReSJHHBE5f9xIWf2NkaGBJgU7i6oasXlnNfuhRC7iNcn5H//4R3z++ecoKyuDn58fWlpaXPbZ1s7yNYxC7j3aJNtPGRseZHMwU86+Kz+fiMhTKGNiiUo1dKA7ec4uqFRNzGPDgxATFghBBEqqGzExLhzLZo/Cx/vrZadXGPZDqg2M+vposeWBFJMOKtA9gGDc6TQwJOoGwQG+aOvsnjkqqmpEdkElO6FE5PEccUTk0tmjoNVqpPhZUt1o0g9lpXYi1/Ka6YHz58/jzjvvxKOPPuryz1YWcjPMrqjdp7n4Z8MMjk4vICuvHAvfKLa4f9KwByg2PMjq5xMRuZNaTDTW0nEBG/KOSEmzmvnjRkIQgcKqRuyubMSr28uh1Whx+4SRqverdRAtzRzZ2pk0JOaGz9i6v85qvCYicjdrE0e2MEwu5WZMAgCzBTvZDyVyHa+ZOV+3bh0AIDc31+WfrVw6aW52Re3MX1tHNg0BMjM1CRvzK7CtrB4AMH98FCtkEpFHyUxNwqYdFeg0moUO8NUiYICPVA3d0FlU2xceExYIaETZjLrhflFUWz/UTacXZMvOswsq8crFfem7Li6vz0mfiE07qszub7fGuHLxR6W1uCM5xuqeeiIiV1Oe9KNMoO1Z9m7cVzUWHOCLB67j0b5EruQ1yXlPdHV1oaurS3rc1tbWo/fx9dHCR6uRHovoXoaZlQeToKdMvE2Wf6q8DoAsgC6dPQorbhrTo7YSETmbr48W42PDZMn1uJhQaDQak/3fysFNAIgOC8Lbe46ZvO/4mBBsKzM9X9egqLpJNjCqnCkqrGpEyvP5stlwAAgO8AGgMblu4O+rhZ8PcLZLkHVOa5s7sCHviMU99URE7qA2IWTMnmXvasvZAUCr0TDWEblYn07O169fL82495ZyhFIQYRL0DDPlxoHSltcBptcYDInIk+WkT5SqoI8dEYyJcaHYaHQUmeFIM+W+cL0gSomu0t6jzagz2m+uZu/RJmlGSG0JploCHhrkr3qvQZdOQJd63g4RwA8nWnu9fJSIyJHUJoSMWVr2rpxVV25NMhg7ItiBLSYiW7g1OV+zZg1efPFFi/ccOnQIl19+eY/ef+3atVi5cqX0uK2tDTExMT16L+UIpfEooyHoZReoJ+zWXmf4s/IaEZGnCvDzxT8fmiI9XvhGsex54yPNjDuRC98oVk3MAeDHhjNWP3dSfLjZJZjmKJfKGxeBs8Vg/wFo69CZXT5KRGTMEZXUe8vSsnflrPrI0ADZa320QEp8BHLSJ7q0zUTk5uR81apVSE9Pt3hPYmLPz1b09/eHv79/j19vTDlCmZUH7KlslAU9tVFKX5/RZl8HdBdSqm+RzxTxOB8i8jbW9j+q3ac0KMBX2rNuLCRwAEICB0g1ONJz9tqcmA/290FL+wXFNfuS81NnOjElMQJaDZCSEMH9l0RkkSMqqfeW8eRQcmwYBFHAwjeKVSeKznTpZa9NiY+QDb4Skeu4NTmPjIxEZGSkO5vQY+rF32C1c2r8OnPLOwurGnHDn7+Vzkhnkk5EtsjOzsZLL72EhoYGXHvttdi4cSNSUlJc8tnW9j+q3ZccGwZoRJQea4FekBeICw7wxVUjQzA5IcIkDlpK8H00wIjQQGjQvWdc2ekEgNPnztv1vZ3Xd7ctNjwIKQnd1wznqH98oA6tFwcUQgIH4PYJI7H0htGM20T9mCMqqfeW8aRSVl45NuSVS4MFUxIjoLnYNg26422r0cCoUZklInIxr9lzXlNTg6amJtTU1ECv16OsrAwAMGrUKAwaNMjl7VHb62NL59TW5Z01Te3YcLEKMfefE5E177//PlauXInXXnsNkydPxoYNGzBnzhwcPnwYQ4cOdfrnW9v/aO0+5bL4tk4dJidEqN5raZBTLwL1zR2IUTmW0iBggI/Jeee2qGlqxyt5R6QK8UptnTpk5VcgK7/C7vcm8lSD/X3x79/OROjAAOs3EwDbVxK5inKwQKsBlqeNkfqrgijg1fwKqb0pCRHuayxRP+c1yfmTTz6Jt99+W3o8fvx4AEBBQQFmzZrlplbJ2do5NbA0+wNw/zkR2e4vf/kLFi9ejIyMDADAa6+9hs8//xxvvfUW1qxZY3K/o06z6Am1/ZhqR66Zi3/GsbbzvA4Zufu6C8VdLGokArJZIKXLhw1CfUsH6lo6HfMNEfVhZ7p0mPHSt/ju6TnuborXsHUlkasoBwtSLg58GmLxvqPN3LpD5CG8JjnPzc11yxnnjqLWGVVb3rntwHGpqrAnjLYSkec7f/48SktLsXbtWumaVqtFWloaCgsLVV/jyNMs7KW2H1N55Joh/lkrrLR5Z7Xq9iBLyXnJ0WaMDAt08HdF1HfZU6OB7J+scQbD1pttZfUQRRGTE8Lho9XIkm/jWKxB92y6u9tN1N95TXLu7cwVBzHsVTd0PL9efj0276xWLeDB/edEpOb06dPQ6/UYNmyY7PqwYcPw448/qr7GkadZ2Mtc8UzjI9cu1fKwXFjJ+L0AIDRwAIIDB1g8Ok0EcKLF8pFtRHRJcAC7i94mu6ASWdvLpce1zR2YmhghnS708IwEbN1f5/a98UQkx2jrIIallYYzf3PSJyLA79KP11xxEEsdT2UBD+PniMhz9GRJeHCwe8+PddRpFtZmts0tYVfbj6k222StsJJye1Bw4ACMDA1EbVO7xYruelvLvRP1c4P9fbHz8ZnubgbZSS3RNqxM2l1xGoWVp00GMfWCyAkhIjezOTkPD7dvebVGo8H+/fsRFxdnd6M8kbkOqOH6W7urpWWUhVWNyMjdJ5sF0guirDKmoTNqqePpCdU+ici60NBQaDS2l7fVaDQ4cuRIr46KNDZkyBD4+Pjg5MmTsusnT57E8OHDHfIZ5lgaYNTpBdz7ZomsQwjYtx/TWmGlzNQkCIKI3MKjaO24gJqmdtQ0tWNKQjjKalvQ2YPCb442QAtEDByAhjPml9qr8fPRIGCAD0ICB+CWa0Zg79Em7K9thV4QMSjAFxAFaDRaACKCA/0QGx6kWt2eyJ36e//RXdTqeBiIAMpqW2TX/H21UqzeVXEaH5bWIm/FDNlEExE5n83/x7W0tGDDhg0ICQmxeq8oivjNb34Dvd70CBtvZa4Danzd2KETbSbPTU2MgI9WI+uMWup4elq1TyIy76OPPrKpEyqKIn72s5859LP9/PyQnJyM/Px83HbbbQAAQRCQn5+PJUuWOPSzlCwNImYXVMqORzNewm7rKiBribyvjxZarcZkj/mhhjNOT8yjQwMRP2Sg7Eg4zjgRyfX3/qM11lYf9VRmahI+Kq1FbbPpFh4NAP8BPrIYqRxermvuQNorO7Hjf2YxnhG5kF3DYb/61a9sPpJn6dKlPWqQpzLXAVXudzQYOyLY5DkfrQbvPDhZdp+ljqenVfskInVxcXGYMWMGIiJsO34mMTERAwYMcGgbVq5ciUWLFmHixIlISUnBhg0bcO7cOal6uzPo9AL0wqUopxxEVFvtY+8go9pSd2VntqS60eR1lgrCOYK/rxZ5KzmrRGSL/tx/tMZaXQ01tiT0vj5a3JEcY3aS6PwFHbK/rZLuvzY6FMWKmF3X3IHsgkpuqSRyIZt7FYJg3wzEmTNn7G6MJzM3i63c7xjgq8X42DDkpE/E5p3VVme+LVX09IRqn0RkXXV1tV33Hzx40OFtuOuuu/DTTz/hySefRENDA8aNG4cvv/zSpEicIylnxqckyo/gUS6rnJromCN6lJ3ZKYnyQZGQQF+0dthXXdrfR4MuOzail/5uNhNzIhv09/6jNT3ZwmhrQm9ukmdjfgW2FNco7hbh76tFl2LFEbdUErkWexY2Mhfg1K4bRi85801ErrRkyRKnL2M3puy0GbbzGOKguRiYlVeuGjNtXd6p7MxqNcCKtDHS6wRRQFZ+hV3fizIx99FqZKsCjGXOTMSgQD+73p+ISE1PtjDamtCrTfJk5ZXLqrgbFB9tNrnGLZVErmd3cn7+/Hl88sknKCwsRENDAwBg+PDhmDZtGm699Vb4+fXNDou5WWxbllzmZkzifh2ifu7kyZPYvHkznnzySXc3xWGUK4daOi5gQ94RAN2zOOY6huZmfGydDVJ2ZlMSImT3ne04j5zdR3t1NvPk+DBMThwiHWup3FNORParq6tDaGgoBg0aJLt+4cIFFBYWYsaMGW5qmfv0ZCKnNzWJbJkJjw0PQmx4EOMdkRvYlZxXVFRgzpw5OH78OCZPniwtlzxw4ABee+01REdH41//+hdGjRrllMZ6i57sHyKivq2hoQHr1q3rM8m5Ti9AEETEhAfhVFunVFjI2rLMnpxQoRzwfHhGgnS/svOo0wuY++ouWWI+MjQAdyRHY/O3VTYVidMAmJw4hHGbyEFOnDiBW2+9FaWlpdBoNPj1r3+Nv/3tb1KS3tTUhNTU1H5VCM6gJ1sYe7MyU62Ke3RYIOqbO6Rkf8GEaMY/IjexKzl/9NFHcfXVV+PAgQMmZ/S2tbXhvvvuQ2ZmJr766iuHNtKb6PQCtu6v4xFoRP3Md999Z/H5w4cPu6glrpFdUIlXt5ebFMQ0nsWx54xzwPxskD0DntkFlahTVCc+2dYFrUaLxdcnYGNBpXQ9OjQAMeEDUdfcLqtorNw7T0S9s2bNGmi1WhQXF6OlpQVr1qxBamoqvv76a4SFhQHortTuLOvXr8fHH3+MH3/8EYGBgZg2bRpefPFFXHbZZU77TGfqSUJviMcl1Y2YkhCO+pYOaDQazB8fhUdnJmHTjipsK6sHAAiiAJ1e4KpPIjewKznfvXs3SkpKTBJzAAgODsazzz6LyZMnq7yy/8guqERNU7vsmi3LjdRmhjbvrHb40RpE5Bzjxo2DRqNR7WAarttzFrqnU55GobYMUi2p7skJFSXVjbIBz+7q7OodU7XBUJ0g4pW8I5iSEI6YsEC0deoQHOCL2yeMxNIbRiM9Z68sOffRahhviRwoLy8P27Ztw8SJEwF09yfvvPNO3HDDDcjPzwcAp8bHb7/9FpmZmZg0aRJ0Oh2eeOIJ3HTTTfjhhx8wcOBAp32uOyn7lTq9XjY4+dgNo7HipjHSfdvK6qX+66v5FdBqWJSYyB3sSs5DQ0Nx9OhRXHXVVarPHz16FKGhoY5ol9dSdgxjw4NsmoFRdmKLqhpRVNXIpfFEXiI8PBx/+tOfMHv2bNXn//vf/+IXv/iFi1vlPMpZ7gUTopGZmoTsgkqk5+yVjjgzTqrf2lWFoqpGaDXd+8SVg47mZoOUddnM1GmT2qVcsmlQVH0pPrd2XJA6oMq98zVN7cjKK+egKJGDtLa2SjPkAODv74+PP/4Yd955J1JTU/HOO+849fO//PJL2ePc3FwMHToUpaWlfXafu7JfGRwoP75zW1k9Vtw0RnafAVd9ErmPXcn5gw8+iPvuuw9/+MMfMHv2bGnP+cmTJ5Gfn4/nnnuu351PqaTWYbWlc6fca3noRBuXxhN5keTkZBw/fhxxcXGqz7e0tDh12aarGc9qC2L3f5WDilMSI6ABpFjW2qmTjl7bU9n9X1sGHbUay48NDPvgY8ODAABRIQEorm4yWXpvYJiFf/v+FADA1v11qGlqR01Tu6ywHRH1TmJiIr777juMHn3p/ydfX198+OGHuPPOO/Hzn//cpe1pbW0F0D2oqqarqwtdXV3S47a2Npe0y5GU/cquC+r7+ZWroABWaSdyJ7uS82eeeQYDBw7ESy+9hFWrVklLkERRxPDhw7F69Wr89re/dUpDvUVPi3Qok/qxI4KlTq4hSNp6zBARud4jjzyCc+fOmX0+NjYWOTk5LmyRcxlmubPyYDLrAnR3Bn843oopiRH44USrybnjhsQ4K0/9KEpjKQkR2FN5KR6mJESY3AMAG7eXI2v7pSPUbr12BKYmdVdc1wuiFFON6QVR+l72Hm2SlnVyUJTIcebNm4fXX38dCxYskF03JOgLFixAXV2dS9oiCAKWL1+O6dOnm10Jun79eqxbt84l7XEW5YogP1+trCDm/PFRAIDkuFDZaqOYsEDckRzDuhtEbmL3UWqrV6/G6tWrUV1dLTtKLSEhweGN80Y9KdIBmCb1anvOWQWeyHPNnz/f4vNhYWFYtGiRi1rjOmqzLgatnToUVTViSmKESWKsQffydFtimq2DntsOHJc9/vQ/J7Dzt6kAgM7zOmTk7jNpR33Lpb3mvTmeiIjM++Mf/4j29nbV53x9fbF161bU19e7pC2ZmZk4ePAgdu3aZfaetWvXYuXKldLjtrY2xMTEuKJ5DmOIk4YVQYYTLGLDg6RtSAAAUb4UaWRoICd/iNzI7uTcICEhgQm5Axkn9eZmyC0dQURE5A7K2ZmpiRE4dKINLR0XAHTHKq0GWJ42RloCb9hzrtyTbi6m9XTQ09jmndWqM+fGRah6czwREZnn6+urWkzY+HlzW4IcacmSJfjss8+wc+dOREdHm73P398f/v7+Tm9PT9i6ilJtRRDQXW/j4RkJ0mtKa5plryuqbkJ2QSUnf4jcxOZhsZUrV1pcsqm0du1aNDUxeewJwwz5rorT2JB3BNkXq2tOig+HoRvJWR0iz9Gf42NmahKWp43BdaOGYEXaGGx5IAUZ0xNksSolIQKPpY3GPxZPwT8fmoJ/LJ6Cx9JGIyUhoscxTacXkJVXjoVvFCMrrxyd53WICgmQ3dPSfh6vfHMYOr1gdoZ//riR0p8Nndl3HpyMx9JGc+aIyAE8IT6KooglS5Zg27Zt2L59u1dPLpnrI5qjjKutHReQkbvP7PNA92y7Ti+YXCci59OINlYo8vHxQUNDAyIjI2164+DgYJSVlSExMbFXDXSktrY2hISEoLW11eIIrj2csQ984RvFsv0/140agncenMw950RuZi6GMD7K2RqrehPTsvLKZXvdo8MCTc43N1iRNgaAfG+88dJOxlEix1CLI54QH3/zm9/g3Xffxaeffio72zwkJASBgYFWX++M/qM15uKjuT6ipfe56qmvZPvNQwMHoOypmwB0b/lJe2WnSfxckTaGs+dEDmRrHLF5WbsoihgzZozN51DaM0rqzRy1D9w4COsFUapwbDyb5IilnUTkeIyPcuZilVpn09p2HuPXbsyvwLay7n2poijKZsLNJeZA9zL13IxJ0p85uEnkOp4QHzdt2gQAmDVrlux6Tk4O0tPTHf55PaXsC6odqWtrbQzDe5VUN5oUgxs74lJisHlntWr85NZJIvewOTnvSZVhw1FrfZmj9oErz5mcmhgBH62G+x6JvEB/j4+WEmtbOpuA9YHO7IJKZG0v71H7JsWHc3CTyE08IT56yzGWameOA/L+pa21Mcy912B/H9Q1t2PGnwowf3wU9h1tNnktt04SuY/NyblxleEbbrgBM2fOxFNPPSW7p7m5GQsWLMD27dsd10IP56jqvsr9kD5ajcVlSkTkOfp7fDSXWOv0Au59s0Q629yYcjDT2kCn2sBnSOAAtF4sPKfGV6vBiJAACKIAnV7gTDmRG/T3+GgPS6df1DS1IyuvXLbiqCfvdaZLjzNd3TPlWfkVmJoYIa3WBLq3/MwfNxKCKGDhG8VcaUTkYj2q1r5jxw58//33OHDgAP7xj39g4MCBAIDz58/j22+/dWgDPZ2jqvvyCB+ivqE/xkdziXV2QaVqYg6YxjlrMXBSfLhsnyVgmpwHKJZu6gQRtc0deDW/AloNZ86J3K0/xkd7qJ1+Ud/SgZqmdtQ0tWND3hEAtm2fVL6XOYbTNPYebUJybBigEbHtQL1U4Z1H9xK5Vo+PUsvLy8PDDz+MKVOm4P/9v/+H+Ph4BzbLezhqqSSP8CHqO/pbfDSXWKvNdk+OD8OJti4AkM1oW4uBmalJEARR2nM+f3wUAODV/Arpcx+ekQStViMdHWToXPLoSSLP0d/ioz3U4mB6zt4exTLDexVXnUZNcwfOdF7A4IABJvvLDadpAIZCm+WyhJ7xk8i1epycjxgxAt9++y0yMjIwadIkfPjhhxg7dqwj29avcD8kUd/R3+KjucRabbZbo9GgtqkdIiCb0bYWA319tFhx0xisuGmMrNDRlMQIaCBChAb7jjUhJSECuRmTZEvtuRqJyHP0t/hoD7U42NOVlYb3euUbAXuqKgAArR06DPb3gVarRXCAL26fMFI2EKq2FJ7xk8i1epScGypu+vv7491338Vzzz2HuXPnYvXq1Q5tXH/CY9KI+ob+GB8NM9/ZBd2du435IgRRwCdlx+Gj1UAvXOru/dhwptdFNJWJ95TECKnQ3J7K7mX0XI1E5Hn6Y3w0x9ZCmsmxYVg2exRKj7X0KJZtO3Bc9vhMlx4a6HH/9ASLAwGA/MhJInKNHiXnyqqXv//97zF27FhZ0Q+yT3ZBJV65uJdoV8VpFFU1YssDKSZHCTGBJ/Js/TU+GifMytlyAw26j/AxJNI9nZFR7nE/dKJN9njr/jqbiyYRkev01/ioxtIJFcrnlqeNcWiRYHMDo2qDmuxnErlWj5Lz6upqREZGyq4tWLAAl19+Ofbt2+eQhvU3yiBZWNWI7IJKk6OErCXwRORe/TU+WqoyDAChgQOQMT0BD89IwOad1b2a0VYu8xw7IlhWeK6mqd0kfhKR+/XX+KjG0gkVas/1dIJm/riRJsdQmhsY5RZLIvfrUXIeFxenev3KK6/ElVde2asG9XXmgqva3kxrRwmpJfBE5F79NT5aqwycYbSEsicxy3ifuV4QER0WCI1Gg/njo/DozCTctOHfUtEkgAWMiDxRf42PaiztJVd7ztJMuyVLZ48CAHx8oA5tnd17zqPDglBS3YisPEj9UK7OJPIMPS4I50pHjx7Fs88+i+3bt6OhoQFRUVFYuHAhfve738HPz8/dzbOLMrgKggitVoOS6kZEhwVKVTQNwdg4WOr0gsn7GZZvMoASkTsZL4dMjg2DIAr49D8nAHRXVu/tnkXj2GmgAaDVaBHg54sFE6JZAI6IvIJOL0AQRMSEBwEwjZHmqrb3pF6Hr48WWq0Gdc0dEAG0dlxAXUsngEs1Oh5LG93j5J+IHMsrkvMff/wRgiBg8+bNGDVqFA4ePIjFixfj3LlzePnll93dPLsolyptK6uXKhcD3Wda+mg1UjBW65Aaq2lqx71vlnB5OxG5hXK2JTdjkhSLVs25XHZfVl55j2dl1JbNG3dQWQCOiLxFdkElXt1eLg0majVa1WJwyhWWPanaDpjfdmQcQy0tsyci1/GK5Hzu3LmYO3eu9DgxMRGHDx/Gpk2bvC45VwZXALKA6aPVyIp+WNvHCXB5OxG5j62zLfbOyig7qMlxoSbL5o07qNwrSUTewlIibC5W9mYA0ty2I+MY2pvkn4gcxyuSczWtra0ID7ccOLq6utDV1SU9bmtrc3azrFIGV0EU8Gp+hdlgaG0fpwFHOInIHWydbbF3VkbZQV0yaxSmJEbgh+OtGBw4ALHhQZicEMEZciLySJb2cFtKhM3FSuMBSFv3hxvX6piSGAGtBpgYFw5oRJOj2bj6iMgzeGVyXlFRgY0bN1qdNV+/fj3WrVvnolbZRjm7o9ML0Gq0ZoOhch8nNCL2HW3GsaZ2k/3pRESuZutsi72zMsoO6qffHZe2ALV16nBncgxnyonIY1laLWQpEVbGyuTYMJMtQT1ZsaQBsDxtjNm4ydVHRJ7Brcn5mjVr8OKLL1q859ChQ7j88kv7Fuvr6zF37lzceeedWLx4scXXrl27FitXrpQet7W1ISYmpneNtpGjql6aC5Zq709E5Gq2zrZYuk8tnlnaAsT9kETk6SytFrKUCKutsNyQ170/3XCM7g8nWmXvXVLdCMD0/aytWGKFdiLP49bkfNWqVUhPT7d4T2JiovTn48ePIzU1FdOmTcPrr79u9f39/f3h7+/f22b2SE/3YRqqt1sLlBzhJCJPYGsssnSfWry0dwsQEZEn6ekebmWsXPhGsWxrY2FVo8lrBDN7H621gRXaiTyPW5PzyMhIREZG2nRvfX09UlNTkZycjJycHGi1nj2y19N9mMbV240DZed5HTJy96nut+QoJxF5M7V46esz2q4tQEREnsRRe7htqT2k1ahfVzvicuEbxdKf//7valns5fG8RO7nFXvO6+vrMWvWLMTFxeHll1/GTz/9JD03fPhwN7bMvJ7uwwRMl27q9ALSXtkp7TFv7dShrrkDeyobUVTVyGPUiMir2RIvLc28Gxc9EsTujmoKBy+JyI3Uagz15DhJ4wRbL4goqmo0ObUiJSHCahuy8srxSl45gO7l8Wpqmtp5+g+Rm3lFcv7NN9+goqICFRUViI6Olj0nitbqmLtHT/dhqi3dzC6olBJzJR6jRkTezp4ZJrU9ksZLMw32VHYv/WRsJCJ30+kF3PtmibQk3Z4l5GpV2tUGItU+c2N+BbaV1QOwvb/Meh5E7uUVyXl6errVvemepqf7MNWWbqbn7LX4HgykROTNbImXhk7p1v11qGlqB3Cpg2u8LN6AReOIyFNkF1TK9orbE5/UBiRt6V9mF1Qia3u5Xe1kPQ8i9/OK5Lw/UeukTooPN7sECQD0ggidXuDyTSLqs7ILKvFK3hHZNUMHV21PJjuZROQp1BJxW+NTT4u2qX2mv68WXTpBehwSOADBAb4YGRoIH63G7Cw8EbkOk/NecNYRFMr3fXhGAgAgZ3c1WjoumNxfxKXtRNQHGS/hPHi8VfWe5NgwqTNpy1JPIiJXU06yTE20PT7ZWmDY2mcCwNDB/rgjOYZHpxF5MCbnveCsIygsva9y5gjg8k2i/u6Pf/wjPv/8c5SVlcHPzw8tLS0ub4M9g5W23qu2l9yERjRaccQBSiLyPGp1NWxNint6JFtmahIKK0+jqPpS//D28dF4LG20FIPTc/YySSfyMEzOe6Gno5k9fd/M1CQIgojNOyvRabQsCeDyTaL+7Pz587jzzjsxdepUvPnmm25pgz2Dlbbeq7aXXGnf0eZetJqIyPnM1dWwZaDy4RkJKKpqxKETbRg7IlhaTWnLZ77z4GST91cWp9tVcRpb99dhwYRoJulEHoDJeS/0dDSzJ+9rCOClNc0YHxsmKyxiz/IoIup71q1bBwDIzc11WxvsGay09V5r9TYAQPDMAzuIiKwyHqjcVXEaRVWN8NFqZIn65p3V0vFpRVWN2Lyz2uZVmmqDAll55bI+JNB9hNqGiyszuUWSyL2YnPeCPcf/9PZ9N+ZXyKpuRocG4myXDmNHBCMnfSJHOonILl1dXejq6pIet7W19er9lIOKybFhZs/0TY4NkyXdybFhJu+n0wsQBBE+Wg30FjJwraZXzSYichprM+PK1UFqR605epWmudeL6K7bwe1BRO7F5LwXbD0uzRHvazin0qCupfvc88KqRmzaUYUVN41xeDuIqO9av369NOPuCMpBRUEUsCGvXH3pukaRbCsfo3tG6dXt5RaXtWvQXfiNiMgTWdvCo3bSBCBPwi2tpuzpHnZzK5K4EonI/Tjd2gcoE3ci8n5r1qyBRqOx+PXjjz/2+P3Xrl2L1tZW6au2trZX7TUMKr7z4GQ8ljYapcdazM72lB5rkb02d88x3PP3ImTllUOn766nYW6/+ciQACxNTcJ1o4ZgedoYbukhIo+lNuut0wvIyivHwjeKIQgils0ehdjwIJPXGrZKZqYmYXnaGFnMMyT9uypOY0PeEWQXVNrcpszUJNXPA7gSicgTcObcS8wfH4Ws/Ap3N4OIXGTVqlVIT0+3eE9iYmKP39/f3x/+/v49fr01lmpyKGduWjsuYHdlI/ZUdi/pfCxttNkZpfrWTnz6nxMsXkREHk8tDipn05enjUFseBBqmtql1/loNVg0NQaA+mpKe5a6q82yL5gQbXISBlciEXkGJucezDigJseG4bHZo1B6rAU6vSA7GmP++Cg3tpKInCEyMhKRkZHubkaPWarJkZmahK3762SdUcD0dArD62ua2mX31jS145W8I6rFk4iIPIVaHEzP2WuSWCfHhcoGLPWCiOv/tAPp0+Lx6X9OAOju6y29YTR8fbR2FSTeuL1cmtzZVXEaH5XW4vbx0Vg2exT2HW2GIHbPmKcksLgwkSdgcu5hjBNyvSBKFToNo6vvPDhZdRSUiPqvmpoaNDU1oaamBnq9HmVlZQCAUaNGYdCgQW5pk7Wjg9QYdzKNX5+VV6563rnxUUA6vR6r5lzusPYTEfWWIY4ZnyuuF0RoAFliLahs9j7TpcdGo1iZlV8Brab7/ewpSLztwHHZ49rmDry6vRzL08bgH4unOOLbJCIHYnLuYYyXOxkTAWzdX6co/sGKmkQEPPnkk3j77belx+PHjwcAFBQUYNasWW5qlTpljIsJC0R0WJDFmRvDNbXZdoP/LTrG5JyIPJIy7k1JCMfx1k4AgCAK2Hes2ab3Maws6m1BYkdUfSci52By7mHMFUECIC3tVKv4SUT9V25urlvOONfpBWzMr5CKUhovuzRXTVgZ4+IiBuKdByebfX/j9/h6+fXYvLMae482oaiqETqj2aauC4Izv1Uioh5Txr3jrZ2obWqHiO4Z8eiwQJvex9LydXPmjxspO4oXsL4Unojch8m5h1EWQZqaGAGtBjh4vBWtHToA3SOeOburAYD7LInIbbILKmWdPsOyy8zUJNz7Zonqmb327JW0dAzRrzYXympvjIsJdej3RkTkKMq+3am2TlmyXtfcIf05OiwQceFBmBjXfSSl8Z7zzNQku49RWzp7FLRaDUqqG7m/nMgLMDn3MGr7iLILKrH7YhVjg5aOC9iQdwQAZ9CJyD3UlkXuPdqE7IJL+8EB84XerO2VtFSRODdjEjJy9+HQiTaMHRGMnPSJvf5+iIicQbk1p1NnfqVPfMRA5GZMwsb8CtVicMY1OHZVnMbW/XUWT6+4tASefUUib8Dk3MOYOzJDDfcMEZE7KY9EA4Dk2DBs3V+nei9g315J5fvrBRE6vQBfHy0C/Hzxz4dYzIiIPJ8h7hlOnzAIDRyAsSOCpeK/xsetqa1KMryH8ax7TVO71cka5Wz7wzMSpC1CPO2CyLMwOfdwOr0AvUoVT4PkuFDXNYaIyEhmahIEQZTtOQdEk6JtUxPNL6G0tEQzMzUJRVWN0ix8UVUjsgsquVqIiLyScltPxvQEaYWk8rg1JcNkTHJsmMmgqLXJGuUWoaKqRtlpQABXYRJ5CibnHi67oFK2PNSEqHFdY4iIjPj6aLHipjFYcdMY6drCN4pl98SGB2HLAylmZ2Us7Sv39dHCR3spxnG1EBF5A3NH3gqCiJjwIACX9pD7+mgvJuiXtgUpzz0HjOpzaEwnbKzV71BuETp0os3sliEici8m5x5OGTADfLWyvUqlNbYdv0FE5ArKmaEFE6Jtrt6u1km0p4AcEZEnUBt0BCBbql5S3Wz2/mU3jMZjN4yWrUoyJPilx1pknxUaOECagTdHGUfVltITkWdgcu7hlAF1fGyYbCbdeA8mEZG7mSv4Zm6G3Frybfx+ybFhEEQBC98o5j5JIvJY1gYdge6imYZtOiXVjYr7GzE5cQhiw4OkPeKGwU29IEJz8T7D0nhrS9KVcVltzzkReQYm5x5OLaBm5O7jHkwi8kjmCr6Z66xaq95u/H7dVYrLuU+SiDyaWjHLlATTveKGOKgsLVTT3IFCM3vEASAkcABCAgfIZtSV1FcrXYqXjJ1EnonJuYdT6+hyDyYReRtlEaPk2DAAtldv1+kFbN1fJ0vwt+6v4+w5EXkctWKWKfHhmJoYIV0zXimkVZQPOtN5wewecQBo7biA1o4L+Hh/PbQarWoctFTPg4g8F3s0XmhSfDgMcZx7hYjIKyiLGGm6t+Rk5ZVj4RvFyMorh05v/uzf7IJKkyrwNU3tyC6odEZriYh6TK2YZWlNM7Y8kIIVaWNw3aghWJ42Rpr1TkmIkPXrrhgRIns8dkQw1Mr/1jZ3YEPeEdU4aMvSeiLyPJw593A6vYCN+RWyoiCPzuwO5sVVp1HT3IG3dlehqKoROekTEeDHv1Ii8jzKIkalx1rsmtkx17Fkh5OIPJHaaiFzK4Ws7Ql/eEYCNu2oQvaOCugUa+DNJd4spknknZjJebjsgkpZdc+s/ApoNd3B/e7XG1HX3AGgu7BIRu4+/POhKe5qKhGRWWodRXtmdoxfb8AOJxF5LMVqIUHsXimkPLECMN3eo7aKqORok0libqBWHNhaPQ8i8kxMzj2cWmfVcO2H462y68rHRESeQq2jmF0Am2d2DK8vqW6EIHbv0UxJiGCHk4g8knK10Kf/OYHapnabVgopVxUZ719Xo1Yc2NZ6HkTkWZice7jkuFCT6p41Te3IyivH4IABaO3USdcHBw5wdfOIiGyi1lHMTE2CIIjSth1BFMweDXnp9exsEpHnU64WAmDzSiHlqqJDJ9pM7gnw1aJTJ9j0fkTkPZicezCdXkBxlWmwrWlqxyt5RxAcIP/riw0PclXTiIh6zddHC61WI80mvWq0bYeIyJspVwsJooBX8yukZD05NszsMnflNh7lYvapiRFISQiTvR+3+BD1DV6TnN9yyy0oKyvDqVOnEBYWhrS0NLz44ouIiopyd9OcJrugEkXV5kdC24xmzQFgckKEs5tERORQrChMRK6SnZ2Nl156CQ0NDbj22muxceNGpKSkOOWzjFcLGYr7xlycRJk/PgqAiA155arL3A2J/db9dahpakdrxwUA3ZMwCyZES89rNVruKSfqY7wmOU9NTcUTTzyBESNGoL6+Hv/zP/+DO+64A3v27HF305ympNr8/iKlkMABDMxE5HVYUZiIXOH999/HypUr8dprr2Hy5MnYsGED5syZg8OHD2Po0KFO+UxDUp5beFRKsDUAIGqwraze7MCkIbHfe7RJdoRk28X3ML6HiPoWr0nOV6xYIf05Li4Oa9aswW233YYLFy5gwIC+uddarShncIAvrhoZgv8eb5MCPdCdnKvt0yQichadXkB2QaXqskxbsaIwEbnCX/7yFyxevBgZGRkAgNdeew2ff/453nrrLaxZs8Ypn6k8cQfoTsQ/PlCH2oun7Rjo9KY1NybFh8vqDrV0XMAreUewdX+dNIPOvh9R3+I1ybmxpqYm/OMf/8C0adMsJuZdXV3o6uqSHre1mRbU8GRajem1tk4dRBFInxovC/jzx410YcuIiEwrCgMwOQ7IWvJuz+yPIwYDiKj/OX/+PEpLS7F27VrpmlarRVpaGgoLC03ud1T/0dw2nbbOCybXiqqbTCquZ6YmqVZqr2lqx4a8IwDMV3wnIu/kVb2a1atXY+DAgYiIiEBNTQ0+/fRTi/evX78eISEh0ldMTIyLWmobnb77zMuFbxQjK6/c5FzLFDN7yA+daMPS2aOwIm0Mrhs1BCvSxmDp7FGuaDIRkcTafnFD8r6r4jQ25B1BdkFlrz7P0e9HRP3D6dOnodfrMWzYMNn1YcOGoaGhweR+R/UfzW3TCQ5Qn1jaur9O1hf09dHCR22mBt0xN2d3tWr/kYi8l1uT8zVr1kCj0Vj8+vHHH6X7H3/8cRw4cABff/01fHx8cN9990EUVdZ+X7R27Vq0trZKX7W1ta74tmxmraOZmZqEx24YDX9f+V/T2BHB0mxTbsYkAMCit0pw9+tFuOfvRQzUROQSk+LDpSOC1PaLO7rYG4vHEZErOKL/qNMLEAQR0aEBsgRbA+D28dGYmmg6AVPT1G7SF7RUh6Ol4wIHKon6GLcua1+1ahXS09Mt3pOYmCj9eciQIRgyZAjGjBmDsWPHIiYmBkVFRZg6darqa/39/eHv7+/IJjuUtY6mr48WK24ag0dnJSIjdx8OnWjD2BHByEmfKN2zMb/CZD/Tnsru5U9c6kREzmRtv7iji72xeBwR9cSQIUPg4+ODkydPyq6fPHkSw4cPN7nfEf3H7IJKvLq93OQYtKjQAHx8oA4AMDk+DGV1rejSXZpQKaluRFbepbj68IwEAN2Pk2PDAI2It/ccQ8vFukMcqCTqW9yanEdGRiIyMrJHrxWE7kBmvCfI29ja0Qzw88U/H5qi+ty2snqTawzUROQK1vaLO7rYG4vHEVFP+Pn5ITk5Gfn5+bjtttsAdPcj8/PzsWTJEqd8pvEEjLH6lk7pz7XNHZiaGIGiqkapLyiIMKnlkZmahOyCS7Fv0bS4Hp1xzrodRJ7PKwrCFRcXY+/evbjuuusQFhaGyspK/OEPf0BSUpLZWXNv4KyOJmeUiMgTOPqoH+W5wexkEpGtVq5ciUWLFmHixIlISUnBhg0bcO7cOal6u6MZT8BYotUAy9PGoKS6EYII/HCi1WRV5cbtArLyKwAAuypOY3J8GJbNHoXSYy129R+tFfEkIvfziuQ8KCgIH3/8MZ566imcO3cOI0aMwNy5c/H73//eo5etW2Nrx9VSJ3T++CgpYANATFgg7kiO4YwSEfUpxnEwOTYMxdWNKKruXiHETiYRWXPXXXfhp59+wpNPPomGhgaMGzcOX375pUmROEcx9MOKq06jprkDZzovYHDAANQpjlBLSYgwW5XdMNmydX+d7Hrx0WZotVpseSDFrkFJ1u0g8nxekZxfffXV2L59u7ub4TaWRjofnZmEkupm2X70AD+v+GslIrKZcRw0PvcXYCeTiGyzZMkSpy1jVzJMwGTlAYUXY1drhw5TEsJxvLV7afv88VEXl6xXmiTmoYEDkDE9AZmpSSbJOQAUVjWaHL1mDet2EHk+ZnFewNJI5+ad1dJepaKqRmzeWS0Fei73JCJXc9Zyc3P7Nw3YySQiT6SMXb4+WmxfNVOKk9kFlSipbjR5Xcb0BCnxnj9upEnxX8N724N1O4g8H5NzL2BppLOkulGWuL+1uwpFVY1Sws7lnkTkSs7a02hp/+aUBHYyicgzKftwybFhuPfNEmmmfHfFaUxRHKsWHRYoVW3PTE3C0tmjAAC5hUfRerFKe09mvh1dB4SIHI/JuRewNNKpF+Rd1dYOnWxpFJd7EpErOWtPo3Ec1OkFab85AExODOfqICLySMo+nCAKJv00rQZYkTYGe482QS+IKKpqRF1zh+xo3BU3jcHS2aNMViYRUd/C5NwLWBrprG/pUL1ujMs9icjRzC1fd9aeRuM4uPCNYtlzpcdaHPIZRESOpuzDKeMX0F0Uzji+mRvg5Mw3Ud/H5NzLaTQai8+HBA7gyCoROZy55evO3tOo0wuyFUMsakRE3mRSfLisqOXUxAgpTjK+ERGTcy+m0wuICglATVO72XtCAgdwuScROZy55evOntlRVjWeYtSxJSLyVIbVRiXVjZiaGAGt5tIxaoZ+mjK+jVTsPWd/jqjvY3LupXR6AQvfKJbtu1QzItgfOr3AgE5EDuWuI3mUe9h9tBrGNyLyeMarjTQAlqeNMRnIVMa3uuYOk73nRNS3sUfjpbILKlUTcz8f+TL34qPN2Khy/AYRUW9kpiZhedoYXDdqCJanjXHZ7PWk+HAYohyXfBKRt7ClWKZxfDPG4r5E/Qdnzr2UuSB9Xm960NC2A8ex4sbLnN0kInKDo0eP4tlnn8X27dvR0NCAqKgoLFy4EL/73e/g5+fntM91V2EintNLRN7IltVGxvHNULXd1auTiMi9mJx7KWVBESLqn3788UcIgoDNmzdj1KhROHjwIBYvXoxz587h5ZdfdnfzHI7VionIG9kysGgc39ROxDB3nVt7iPoOJudeKjM1CYIg4uMDdahr6YBoOmEumT9upOsaRkQuNXfuXMydO1d6nJiYiMOHD2PTpk19MjknIvIW6om0bYOL5gYizZ2UQUR9A5NzL+Xro8WKm8ZAq9XglbwjqvcE+Grx8MxELL1hlItbR0Tu1NraivBwy0sgu7q60NXVJT1ua2uz6zM4e0NEZJlxIr2r4jTe2l2NkMABmD8+CktvGG0xZpqLsbbsXSci78Xk3MtZCsqdOgFajZYdZqJ+pKKiAhs3brQ6a75+/XqsW7eux5/D2RsiIsuME2kAaO24gNaOC8jKr4BW0z0zbi4JV8ZYQRCh1Wpkx+dyLzpR38Pk3MtZ23ues7saAM/HJPI2a9aswYsvvmjxnkOHDuHyyy+XHtfX12Pu3Lm48847sXjxYouvXbt2LVauXCk9bmtrQ0xMjM3t4+wNEZE6Q8JtnEgrGWKmuST8rd1Vshibs6cabZ066fWx4UFYMCGaRTGJ+hgm514uMzUJRVWNKKxqVH2+peMCNlxc9s5ZLSLvsWrVKqSnp1u8JzExUfrz8ePHkZqaimnTpuH111+3+v7+/v7w9/fvcfvcdc45EZGnM064ASAkcABaOy7I7kmODUNWXjlydlfLkvBtZfWobWqHspSQcWIOdCfn7NcR9T1Mzr2cr48WWx5IkZZE6fSCyfnnIoCt++s4e07kRSIjIxEZGWnTvfX19UhNTUVycjJycnKg1Tr//3MeaUZEpE65nD04wBf3TYnFp/85AQCYPz4KgIgNeeWy+wxnnFuo8SvhgChR38TkvA8wVPTU6QXc8OdvVe+paWpHdkElR1mJ+pj6+nrMmjULcXFxePnll/HTTz9Jzw0fPtxpn8sjzYiI1Cm3HNY2d8DXxwc7f5sqXVv4RrEsCQ8NHICM6QkQRAGv5ldYTNCnJkZwQJSoj2Jy3ods3F5u0/4mIuo7vvnmG1RUVKCiogLR0dGy50RLZywSEZFTZKYmYev+OlmfzNAHM7cffeyIYCnh1mq0KKluhCACWg0wMS4cgihIM+8pCWEu+k6IyNW4xrmP0OkF5Ow+avEeLoEi6nvS09MhiqLqFxERuZ6vjxYLJsgHS482nsPZjvO4980SvJJ3xCQ5L6pqRHZBpbQq6R+Lp2DLAylISYhAaU0z9h1rQW1TO2qa2vFqfgWyCypd+S0RkYtw5ryPyC6oNCkWYoxLoIjIU/HMdCLqazJTk/BhaS3qmjsAAHXNHZj76i7psZLaqRfKwnKW7iWivoHJeR9hKUhHhwUiJ30ifH207AQTkcfhmelE1Nf4+mhxVjFpUm8mMQfUT71QFpazdC8R9Q3MyvoIS0G6rrkDm3ZUAbjUCd5VcRob8o5wWRQRuR3PTCeivmjsiGDZY3ObjUICByAmPAiCKECnF6Trk+LDpQruADAlIRyx4UGq9xJR38CZ8z5ApxcgCCJiwgLR1qlD5wU9unTygJ1beBRLZ49iJ5iIPA7PTCeivignfSImr89Ha8elGfTY8CDEhAVKxd4EsXu/eWvHBbyaXwGt5tJJGMojK40ruSvvJaK+gcl5H5BdUIlXt186K9PfR2NyT2vHBWQXVLITTEQeh2emE1FfFODni/unJ0rbdjQA5o8bCa1WI8W7kupGs5MmyiMrjY9f4wQLUd/E5LwPUO5J6tKrL5wqqW7E2/enSK9hJ5iIPAHPTCeivkpt9ntDXrlUY2NKYgQ0gE2TJpxgIer7mJz3AcbB2hJBZCeYiIiIyFWszX5rNcDytDGySRNzxXu5yoio72Ny3gcYgvPW/XUm52Ya05qudiciIiIiF1HOfk+MM539NneCBSdYiPo+Jud9gCFYZ6Ym4YY/f2s2QZ8YH+bilhERERH1L5aOrbW2zN3wHPeWE/VPXneUWldXF8aNGweNRoOysjJ3N8ej+PposWBCNMxOkIucOiciIiJyJkvH1homVN55cDIeSxuN0mMtskQ8Z3c19IIo9eW4t5yof/G65Py3v/0toqKi3N0Mj5WZmoTlaWMQGjjA5LnSmmY3tIiIiIio/7Bn5lt5lnlLxwUUVjViSmIErhs1BMvTxnBvOVE/4lXJ+b/+9S98/fXXePnll93dFI9lGJHNmJ5g8tyxxnPIyiuHTi+ovJKIiIiIess44bY2821uUsVHq5Fm1w1L4omo7/OaPecnT57E4sWL8cknnyAoKMim13R1daGrq0t63NbW5qzmeZzM1CQUVp5GUfWl0dra5g68kncERVWN2PJACoM9ERERkYOZq6pubi+6ocib8XnoXMpO1D95RXIuiiLS09PxyCOPYOLEiTh69KhNr1u/fj3WrVvn3MZ5KF8frdnku7CqEdkFlaz4SURERORg5qqqm6vCDphP6Imof3Hr1OmaNWug0Wgsfv3444/YuHEjzpw5g7Vr19r1/mvXrkVra6v0VVtb66TvxDMp9zEZK6ludGlbiIiIiPoz5V70nN3V0nZDZaE4rm4k6p/cOnO+atUqpKenW7wnMTER27dvR2FhIfz9/WXPTZw4Effccw/efvtt1df6+/ubvKY/MYy6llQ34vv6VrR16qTnBNHcq4iIiIjI0YzPOAe6i79tyDsCAFzNSEQA3JycR0ZGIjIy0up9r776Kp577jnp8fHjxzFnzhy8//77mDx5sjOb6NV8fbTITE2CTiegqEo+U156rAm/2lwIH60GKQkRsjM4iYiIiKj3jPeZJ8eGYdnsUXh7zzG0dFwAwHPMiUjOK/acx8bGyh4PGjQIAJCUlITo6Gh3NMlrbNxejo07Kkyun9eLUrG4PZXdiTtHbYmIiIgcR7nPfHnaGGRMT1At/mauYBwR9R9ekZxTz207cNzqPRy1JSIiInI8tTPPczMmSc8ZF3+zVDCOiPoHr0zO4+PjIYrcNG0LW39OPLKDiJyBM0FE1J8Z7zM3zJKbq+aulsgTUf/ilck52W5kaCBqmzss3jMlgUd2EJFzcCaIiPoze45IU0vkiah/YXLex2m15g5Tu2RyYjhnsojIKTgTRET9mblZcjWZqUkQBBHbyuoBAIIoSMesEVH/wP/b+zhbVrWXHmtxejuIqH+aFB8OwxAhZ4KIiMzz9dECGhE1Te2oaWpHVn4FNm4vd3eziMiFOHPex2lgPTvX6TkyS0TOYc+STiKi/kStJoeykO+2A8ex4sbL3NRCInI1Jud9nAjry9qLqpuQXVDJfaBE5HD2LOkkIupP1GpyEFH/xqnSPs6GLecAgOLqRuc2hIiIiIgkajU55o8bKbsnKiQAC98oRlZeOXR6weVtJCLX4sx5H5eSEIE9lY1WF7fXNLW7pD1EREREpF6dPTM1CVqtBnuPNkEviCiqauRpF0T9CJPzPs6wvzNndzVaOi6Yva+t47yrmkRERETU76nV5DDeCrTwjWKedkHUz3BZez8RHDjAyvN+LmoJEREREVnD0y6I+h/OnPdxxsVGACAkcADOdumgF+QL3WPDAl3fOCIiIiInOnr0KJ599lls374dDQ0NiIqKwsKFC/G73/0Ofn7unZhQKwhnvGydp10Q9T9Mzvs442IjANBqZmn75MQhrmkQERERkYv8+OOPEAQBmzdvxqhRo3Dw4EEsXrwY586dw8svv+ySNqgdmebro1UtCGeMp10Q9T9Mzvs442Ij5kxJ4GgsERER9T1z587F3LlzpceJiYk4fPgwNm3aZDY57+rqQldXl/S4ra2tV20wN0OuVhCOiPo3Jud9nPGSKOOqnwAQ4KvFuJhQTIoPQ3rOXtloLhEREVFf1NraivBw84nw+vXrsW7dOod9nrkZci5bJyIlJud9nPGSKMOyqq3761DT1I5OnYCi6iYUVXf/I7Gr4jQKK0/jnQcnM0EnIiKiPqeiogIbN260uKR97dq1WLlypfS4ra0NMTExPf5MtRlyc0vdiah/YxToRwyJemx4kNl7iqqbcMOfv0VWXjl0esGFrSMiIiKyzZo1a6DRaCx+/fjjj7LX1NfXY+7cubjzzjuxePFis+/t7++P4OBg2VdvZKYmYXnaGFw3agiWp41BZmqStNR9V8VpbMg7guyCyl59BhH1DZw574es7UOvaWrHhrwjAMBCJERe4JZbbkFZWRlOnTqFsLAwpKWl4cUXX0RUVJS7m0ZE5BSrVq1Cenq6xXsSExOlPx8/fhypqamYNm0aXn/9dae2TW1WXNmfslYMjoj6Jybn/YxOL0AQRMSEB6G144LZ6u0igJLqRgBMzok8XWpqKp544gmMGDEC9fX1+J//+R/ccccd2LNnj7ubRkTkFJGRkYiMjLTp3vr6eqSmpiI5ORk5OTnQap27cNTaEWmA+lJ3e3BZPFHfxOS8n8kuqMSr28stVm83EGy5iYjcbsWKFdKf4+LisGbNGtx22224cOECBgwY4MaWERG5V319PWbNmoW4uDi8/PLL+Omnn6Tnhg8f7pTPtGVWvLfF4GwZACAi78PkvJ9RnntuiVbj1KYQkRM0NTXhH//4B6ZNm2YxMXf0UUFERJ7om2++QUVFBSoqKhAdHS17ThSdMwthy6x4b88w57J4or6J61/6mUnx4bAl59YASEmIcHZziMhBVq9ejYEDByIiIgI1NTX49NNPLd6/fv16hISESF+9qURMROSp0tPTIYqi6pezqBWAczTj/hzPSCfqOzSiM6OTh2lra0NISAhaW1t7XXnTWxnvUSqsaoReZe26v68GD12fiMfSxnD/EpERV8aQNWvW4MUXX7R4z6FDh3D55ZcDAE6fPo2mpiYcO3YM69atQ0hICD777DNoNOrDcWoz5zExMf06PhJR7/TVfpYnfl/cc07kXWyNI0zO+7Fr131ttiDcyNAAfPt4KgM9kRFXxpCffvoJjY2NFu9JTEyEn5+fyfW6ujrExMRgz549mDp1qk2fx/hIRL3VV+NIX/2+iMh1bI0j3HPejy1MiUH2t1Wqz9W3dGJjfgVW3DTGxa0iIsC+SsRKgiAAgGxmnIiIiIg8G6dF+zFfX8t//bmFR6HTCy5qDRH1RHFxMf7617+irKwMx44dw/bt23H33XcjKSnJ5llzIiIiInI/Juf9WOmxFovPt3ZcwL1vljBBJ/JgQUFB+PjjjzF79mxcdtlleOCBB3DNNdfg22+/hb+/v7ubR0REF+n0ArLyyrHwjWJk5ZWzf0VEJrisvR8zPuoDAPx8tTivk/9DUVjViMv+8CUG+fvgvilxLBJH5GGuvvpqbN++3d3NICIiK3g2ORFZwyyrH3t4RgKmJEYgNHAApiZGIDk2VPU+vSCitUOHjQWVyC6odG0jiYiIiPoAnk1ORNYwOe/HNu+sRlFVI1o6LqCoqhGw4QR0/kNCREREZD9rZ5Nz2TsRec2y9vj4eBw7dkx2bf369VizZo2bWuT9lCO4Wg0wMiQA9a2dZl9zrPEcfrW5EPUtHdBoNLj12hHQajUoPdaC8dGh2HusCT82nMHYEcHISZ+IAD+v+RUjIiIicprM1CQAkJ1NbozL3onIqzKnZ555BosXL5YeDx482I2t8X7Ge841AFISIlBcbXlmvLa5A7XNHdLjjUbL3Hdd/IcE6N6rfvmTX0mPtQBGhAYgLmIgJidEIDM1iXvXiYiIqN/w9dFaTLa57J2IvCo5Hzx4MIYPH+7uZvQZaiO4r+YfccpnCeg+O72+pRN7KhvxSp5zPoeoJ6JCAvD18usxKNDP3U0hIqI+QqcXkF1QKetnWZqYUE6aKJe9E1Hf51XJ+QsvvIBnn30WsbGx+PWvf40VK1bA19f8t9DV1YWuri7pcVtbmyua6TXURnCHhwSivqXDzCuI+qbjrZ2Y++ou7Fp9g7ubQkREfYS9y9StLXsnor7Pa5LzZcuWYcKECQgPD8eePXuwdu1anDhxAn/5y1/Mvmb9+vVYt26dC1vp/eLCmZxT/9RgodYCERGRvexdpm5t2TsR9X1u3fS7Zs0aaDQai18//vgjAGDlypWYNWsWrrnmGjzyyCP485//jI0bN8pmxpXWrl2L1tZW6au2ttZV35rXmpw4xN1NIHKL4SEB7m4CqWD1YiLyVtaqs1vD+EfU/7h15nzVqlVIT0+3eE9iYqLq9cmTJ0On0+Ho0aO47LLLVO/x9/eHv79/b5vZr2SmJqGoqhGFVY3ubgqRy0SFBODLZde5uxmkgtWLichb9XaZOuMfUf/j1uQ8MjISkZGRPXptWVkZtFothg4d6uBW9W++PlpseSAFG/MrsK2sHifbOtGl69lI7cjQAHy+dDreLqxFcdVp1DR34EznBVwxIoTHrBGRTVi9mIi8VW+XqTP+EfU/XpEdFRYWori4GKmpqRg8eDAKCwuxYsUKLFy4EGFhYe5uXp/j66PFipvGYMVNY5CVVy6N2gKAr1aDgf4+WJgSC61Wg0/KjqOtU4fgAF/cPmEklt4w2qQSafc/TBzpJSL7sXoxEfVXjH9E/Y9XJOf+/v5477338PTTT6OrqwsJCQlYsWIFVq5c6e6m9XlqS7KMk+9Vcy53V9OIqB9g9WIi6q8Y/4j6H69IzidMmICioiJ3N6NfYuVQInInxiAi6q8Y/4j6H7dWayciIiIiIiIiJudEREREREREbsfknIiIiIiIiMjNmJwTERERERERuRmTcyIiIiIiIiI3Y3JORERERERE5GZMzomIiIiIiIjcjMk5ERERERERkZsxOSciIiIiIiJyM193N8CVRFEEALS1tbm5JUTkjQyxwxBL+hLGRyLqrb4aIxkfiai3bI2P/So5P3PmDAAgJibGzS0hIm925swZhISEuLsZDsX4SESO0tdiJOMjETmKtfioEfva8KYFgiDg+PHjGDx4MDQajdX729raEBMTg9raWgQHB7ughY7BdrsW2+1a7my3KIo4c+YMoqKioNX2rV1BjI+eje12Lba7Z/pqjLQ3PgLu/7voKW9stze2GWC7Xc3d7bY1PvarmXOtVovo6Gi7XxccHOxVv3wGbLdrsd2u5a5296XZIGOMj96B7XYtttt+fTFG9jQ+AvwdciVvbDPAdruap8fHvjOsSUREREREROSlmJwTERERERERuRmTcwv8/f3x1FNPwd/f391NsQvb7Vpst2t5a7v7Gm/9e2C7XYvtdi1vbXdf5K1/F97Ybm9sM8B2u5q3tLtfFYQjIiIiIiIi8kScOSciIiIiIiJyMybnRERERERERG7G5JyIiIiIiIjIzZicExEREREREbkZk3MLsrOzER8fj4CAAEyePBklJSVua8v69esxadIkDB48GEOHDsVtt92Gw4cPy+6ZNWsWNBqN7OuRRx6R3VNTU4Obb74ZQUFBGDp0KB5//HHodDqntfvpp582adPll18uPd/Z2YnMzExERERg0KBBWLBgAU6ePOnWNgNAfHy8Sbs1Gg0yMzMBeM7PeufOnfjFL36BqKgoaDQafPLJJ7LnRVHEk08+iREjRiAwMBBpaWkoLy+X3dPU1IR77rkHwcHBCA0NxQMPPICzZ8/K7vnuu+9w/fXXIyAgADExMfjTn/7ktHZfuHABq1evxtVXX42BAwciKioK9913H44fPy57D7W/oxdeeMGp7aZLGB97j/GR8dHedjM+egfGx95jfGR8tLfdfSY+iqTqvffeE/38/MS33npL/O9//ysuXrxYDA0NFU+ePOmW9syZM0fMyckRDx48KJaVlYk/+9nPxNjYWPHs2bPSPTNnzhQXL14snjhxQvpqbW2VntfpdOJVV10lpqWliQcOHBC/+OILcciQIeLatWud1u6nnnpKvPLKK2Vt+umnn6TnH3nkETEmJkbMz88X9+3bJ06ZMkWcNm2aW9ssiqJ46tQpWZu/+eYbEYBYUFAgiqLn/Ky/+OIL8Xe/+5348ccfiwDEbdu2yZ5/4YUXxJCQEPGTTz4R//Of/4i33HKLmJCQIHZ0dEj3zJ07V7z22mvFoqIi8d///rc4atQo8e6775aeb21tFYcNGybec8894sGDB8V//vOfYmBgoLh582antLulpUVMS0sT33//ffHHH38UCwsLxZSUFDE5OVn2HnFxceIzzzwj+zsw/v/BGe2mboyPjsH4yPhob7sZHz0f46NjMD4yPtrb7r4SH5mcm5GSkiJmZmZKj/V6vRgVFSWuX7/eja265NSpUyIA8dtvv5WuzZw5U3zsscfMvuaLL74QtVqt2NDQIF3btGmTGBwcLHZ1dTmlnU899ZR47bXXqj7X0tIiDhgwQPzwww+la4cOHRIBiIWFhW5rs5rHHntMTEpKEgVBEEXRM3/WyiAlCII4fPhw8aWXXpKutbS0iP7+/uI///lPURRF8YcffhABiHv37pXu+de//iVqNBqxvr5eFEVR/Nvf/iaGhYXJ2r169Wrxsssuc0q71ZSUlIgAxGPHjknX4uLixFdeecXsa5zd7v6M8dExGB8ZH+1ttxrGR8/C+OgYjI+Mj/a2W403xkcua1dx/vx5lJaWIi0tTbqm1WqRlpaGwsJCN7bsktbWVgBAeHi47Po//vEPDBkyBFdddRXWrl2L9vZ26bnCwkJcffXVGDZsmHRtzpw5aGtrw3//+1+ntbW8vBxRUVFITEzEPffcg5qaGgBAaWkpLly4IPs5X3755YiNjZV+zu5qs7Hz58/jnXfewf333w+NRiNd98SftbHq6mo0NDTIfr4hISGYPHmy7OcbGhqKiRMnSvekpaVBq9WiuLhYumfGjBnw8/OTfS+HDx9Gc3OzS76X1tZWaDQahIaGyq6/8MILiIiIwPjx4/HSSy/Jln15Qrv7IsZHx2J8dE+7GR/d3+6+iPHRsRgf3dNuxkf3ttvX6Z/ghU6fPg29Xi/7HwMAhg0bhh9//NFNrbpEEAQsX74c06dPx1VXXSVd//Wvf424uDhERUXhu+++w+rVq3H48GF8/PHHAICGhgbV78nwnDNMnjwZubm5uOyyy3DixAmsW7cO119/PQ4ePIiGhgb4+fmZ/A8zbNgwqT3uaLPSJ598gpaWFqSnp0vXPPFnrWT4HLV2GP98hw4dKnve19cX4eHhsnsSEhJM3sPwXFhYmFPab9DZ2YnVq1fj7rvvRnBwsHR92bJlmDBhAsLDw7Fnzx6sXbsWJ06cwF/+8hePaHdfxfjoOIyP7ms34yPjozMwPjoO46P72s346N52Mzn3QpmZmTh48CB27dolu/7QQw9Jf7766qsxYsQIzJ49G5WVlUhKSnJ1MwEA8+bNk/58zTXXYPLkyYiLi8MHH3yAwMBAt7TJXm+++SbmzZuHqKgo6Zon/qz7ogsXLuCXv/wlRFHEpk2bZM+tXLlS+vM111wDPz8/PPzww1i/fj38/f1d3VTyEIyPrsX46D6Mj2QvxkfXYnx0H2+Oj1zWrmLIkCHw8fExqfp48uRJDB8+3E2t6rZkyRJ89tlnKCgoQHR0tMV7J0+eDACoqKgAAAwfPlz1ezI85wqhoaEYM2YMKioqMHz4cJw/fx4tLS0mbTK0x91tPnbsGPLy8vDggw9avM8Tf9aGz7H0ezx8+HCcOnVK9rxOp0NTU5Pb/w4MgfXYsWP45ptvZKOeaiZPngydToejR49KbXP330FfxPjoPIyPjI+2Ynz0TIyPzsP4yPhoK2+Pj0zOVfj5+SE5ORn5+fnSNUEQkJ+fj6lTp7qlTaIoYsmSJdi2bRu2b99ustxCTVlZGQBgxIgRAICpU6fi+++/l/3PZPilveKKK5zSbqWzZ8+isrISI0aMQHJyMgYMGCD7OR8+fBg1NTXSz9ndbc7JycHQoUNx8803W7zPE3/WCQkJGD58uOzn29bWhuLiYtnPt6WlBaWlpdI927dvhyAI0j8YU6dOxc6dO3HhwgXZ93LZZZc5bWmPIbCWl5cjLy8PERERVl9TVlYGrVYrLbNyR7v7A8ZH52F8ZHy0BeOj52J8dB7GR8ZHW/SJ+OiSsnNe6L333hP9/f3F3Nxc8YcffhAfeughMTQ0VFY90ZUeffRRMSQkRNyxY4es9H97e7soiqJYUVEhPvPMM+K+ffvE6upq8dNPPxUTExPFGTNmSO9hOJ7hpptuEsvKysQvv/xSjIyMdOqxEqtWrRJ37NghVldXi7t37xbT0tLEIUOGiKdOnRJFsfsojNjYWHH79u3ivn37xKlTp4pTp051a5sN9Hq9GBsbK65evVp23ZN+1mfOnBEPHDggHjhwQAQg/uUvfxEPHDggVaV84YUXxNDQUPHTTz8Vv/vuO/HWW29VPQpj/PjxYnFxsbhr1y5x9OjRsqMwWlpaxGHDhon33nuvePDgQfG9994Tg4KCenWkhKV2nz9/XrzlllvE6OhosaysTPb7bqicuWfPHvGVV14Ry8rKxMrKSvGdd94RIyMjxfvuu8+p7aZujI+OwfjI+GhvuxkfPR/jo2MwPjI+2tvuvhIfmZxbsHHjRjE2Nlb08/MTU1JSxKKiIre1BYDqV05OjiiKolhTUyPOmDFDDA8PF/39/cVRo0aJjz/+uOzsRFEUxaNHj4rz5s0TAwMDxSFDhoirVq0SL1y44LR233XXXeKIESNEPz8/ceTIkeJdd90lVlRUSM93dHSIv/nNb8SwsDAxKChInD9/vnjixAm3ttngq6++EgGIhw8fll33pJ91QUGB6u/FokWLRFHsPg7jD3/4gzhs2DDR399fnD17tsn309jYKN59993ioEGDxODgYDEjI0M8c+aM7J7//Oc/4nXXXSf6+/uLI0eOFF944QWntbu6utrs77vhnNDS0lJx8uTJYkhIiBgQECCOHTtWfP7558XOzk6ntpsuYXzsPcZHxkd728346B0YH3uP8ZHx0d5295X4qBFFUezhpDsREREREREROQD3nBMRERERERG5GZNzIiIiIiIiIjdjck5ERERERETkZkzOiYiIiIiIiNyMyTkRERH9/3buJRTaNo7j+G+mIeOUhIxi6bSw8EQppyKUxcjCxmIUC1lYiQULKQuStVLKsdiwMslGJsVGzcKhEBlSFlbklLne3fROzyyente8l/h+VnPf1/++u67Nr34zNQAAwDLKOQAAAAAAllHOAQAAAACwjHIOAAAAAIBllHPgXxwOhzY2NmxvAwC+HPIRAGIjH/FZKOf4Nrq6utTW1mZ7GwDw5ZCPABAb+YivhHIOAAAAAIBllHN8S/X19erv79fg4KAyMzOVm5ur0dHRqJmzszPV1tYqKSlJpaWl2t7e/u09oVBIHR0dysjIUGZmprxer66uriRJp6enSk5O1srKSmR+bW1Nbrdbx8fH8TweAPw18hEAYiMfYRvlHN/W/Py8UlJSdHBwoMnJSY2NjUUCNBwOq729XYmJiTo4ONDMzIyGhoainn9/f1dzc7PS0tIUCAS0t7en1NRUtbS06O3tTcXFxZqamlJfX5+ur691c3Oj3t5eTUxMqLS01MaRAeCPkI8AEBv5CKsM8E34fD7j9XqNMcbU1dWZ6urqqPWKigozNDRkjDFma2vLuFwuc3t7G1n3+/1GkllfXzfGGLO4uGiKiopMOByOzLy+vhq32222trYi91pbW01NTY1paGgwTU1NUfMA8BWQjwAQG/mIr8Rl+bsBIG7Kysqirj0ej+7v7yVJJycnys/PV15eXmS9qqoqaj4YDOr8/FxpaWlR919eXnRxcRG5npubU2FhoZxOp46OjuRwOD77KADwqchHAIiNfIRNlHN8WwkJCVHXDodD4XD4j59/fHzUr1+/tLy8/NtadnZ25HMwGNTT05OcTqfu7u7k8Xj+ftMA8D8gHwEgNvIRNlHO8SOVlJQoFApFheH+/n7UTHl5uVZXV5WTk6P09PSY73l4eFBXV5eGh4d1d3enzs5OHR4eyu12x/0MABAP5CMAxEY+It74Qzj8SI2NjSosLJTP51MwGFQgENDw8HDUTGdnp7KysuT1ehUIBHR5eamdnR319/fr5uZGktTb26v8/HyNjIxoenpaHx8fGhgYsHEkAPgU5CMAxEY+It4o5/iRnE6n1tfX9fz8rMrKSvX09Gh8fDxqJjk5Wbu7uyooKFB7e7tKSkrU3d2tl5cXpaena2FhQZubm1pcXJTL5VJKSoqWlpY0Ozsrv99v6WQA8N+QjwAQG/mIeHMYY4ztTQAAAAAA8JPxyzkAAAAAAJZRzgEAAAAAsIxyDgAAAACAZZRzAAAAAAAso5wDAAAAAGAZ5RwAAAAAAMso5wAAAAAAWEY5BwAAAADAMso5AAAAAACWUc4BAAAAALCMcg4AAAAAgGX/AOVq/zUnvtMRAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "z = run.buffer.stacked['z.value']\n", + "import pylab as plt\n", + "# Plot scatter plot as function of index for all three dimensions\n", + "plt.figure(figsize=(12, 4))\n", + "for i in range(3):\n", + " plt.subplot(1, 3, i + 1)\n", + " plt.scatter(range(len(z)), z[:, i], s=5)\n", + " plt.xlabel(\"Index\")\n", + " plt.ylabel(f\"z[{i}]\")\n", + " plt.title(f\"Scatter plot of z[{i}] vs Index\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "635bc836", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "jupytext": { + "cell_metadata_filter": "-all", + "main_language": "python", + "notebook_metadata_filter": "-all" + }, + "kernelspec": { + "display_name": "emri_few_timm", + "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.10.1" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/05_linear_regression/config.yml b/examples/05_linear_regression/config.yml index b99ef63..faead5f 100644 --- a/examples/05_linear_regression/config.yml +++ b/examples/05_linear_regression/config.yml @@ -78,18 +78,9 @@ graph: estimator: _target_: falcon.estimators.GaussianFullCov - loop: - max_epochs: 1000 - batch_size: 128 - early_stop_patience: 32 - cache_sync_every: 1 - cache_on_device: false - network: - hidden_dim: 128 - num_layers: 3 - momentum: 0.1 - min_var: 1.0e-20 - eig_update_freq: 1 + max_epochs: 1000 + lr: 0.001 + gamma: 0.2 embedding: _target_: model.E_fft_whiten #_target_: model.E_fft_norm @@ -97,15 +88,20 @@ graph: n_bins: 1000000 n_features: 128 n_modes: 128 - optimizer: - lr: 0.001 - betas: [0.9, 0.9] - lr_decay_factor: 0.5 - scheduler_patience: 16 - inference: - gamma: 0.2 - discard_samples: false - log_ratio_threshold: -20.0 + batch_size: 128 + early_stop_patience: 32 + cache_sync_every: 1 + cache_on_device: false + hidden_dim: 128 + num_layers: 3 + momentum: 0.1 + min_var: 1.0e-20 + eig_update_freq: 1 + betas: [0.9, 0.9] + lr_decay_factor: 0.5 + lr_patience: 16 + discard_samples: false + log_ratio_threshold: -20.0 sample_chunk_size: 128 ray: diff --git a/falcon/__init__.py b/falcon/__init__.py index ac4eca4..3219932 100644 --- a/falcon/__init__.py +++ b/falcon/__init__.py @@ -16,6 +16,10 @@ "read_run", "load_run", "read_samples", + "config", + "init", + "launch", + "shutdown", "estimators", "priors", "embeddings", @@ -41,6 +45,10 @@ "read_run": ".core.run_reader", "load_run": ".core.run_loader", "read_samples": ".core.samples_reader", + "config": ".api", + "init": ".api", + "launch": ".api", + "shutdown": ".api", } diff --git a/falcon/api.py b/falcon/api.py new file mode 100644 index 0000000..6796dbf --- /dev/null +++ b/falcon/api.py @@ -0,0 +1,323 @@ +"""Python/notebook API entry points for Falcon.""" + +from pathlib import Path +from typing import List, Optional, Union + +from omegaconf import DictConfig, OmegaConf + + +class Config: + """Thin wrapper over OmegaConf DictConfig with fluent override and display helpers.""" + + def __init__(self, cfg: DictConfig): + self._cfg = cfg + + def override(self, *dotted_strings: str) -> "Config": + """Return a new Config with the given dotted overrides applied. + + Example:: + + cfg = falcon.config("config.yml").override( + "buffer.max_samples=500", + "graph.theta.estimator.loop.max_epochs=200", + ) + """ + overrides = OmegaConf.from_dotlist(list(dotted_strings)) + return Config(OmegaConf.merge(self._cfg, overrides)) + + def to_yaml(self) -> str: + """Return the config as a YAML string.""" + return OmegaConf.to_yaml(self._cfg) + + def _repr_markdown_(self) -> str: + return f"```yaml\n{self.to_yaml()}\n```" + + def __repr__(self) -> str: + return f"Config(\n{self.to_yaml()})" + + @property + def _dict_config(self) -> DictConfig: + return self._cfg + + +def config(source) -> Config: + """Load or wrap a Falcon configuration. + + Args: + source: Path to a YAML file (str or Path), a plain dict, or a DictConfig. + + Returns: + :class:`Config` with ``.override()`` and ``.to_yaml()`` methods. + """ + if isinstance(source, (str, Path)): + cfg = OmegaConf.load(source) + elif isinstance(source, dict): + cfg = OmegaConf.create(source) + elif isinstance(source, DictConfig): + cfg = source + else: + raise TypeError( + f"config() expected a path, dict, or DictConfig; got {type(source).__name__}" + ) + return Config(cfg) + + +# --------------------------------------------------------------------------- +# Ray lifecycle +# --------------------------------------------------------------------------- + + +def init(**ray_init_kwargs) -> None: + """Connect to or start a Ray cluster. + + Idempotent: a second call is a no-op if Ray is already initialised. + Pass any ``ray.init()`` keyword argument directly. + + Examples:: + + falcon.init() # local cluster, auto-detect resources + falcon.init(address="auto") # connect to existing local cluster + falcon.init(address="ray://...") # connect to remote cluster + """ + import ray + if ray.is_initialized(): + return + ray_init_kwargs.setdefault("namespace", "falcon") + ray_init_kwargs.setdefault("logging_level", "ERROR") + ray_init_kwargs.setdefault("log_to_driver", True) + ray.init(**ray_init_kwargs) + + +def shutdown() -> None: + """Shut down the Ray cluster started by :func:`falcon.init`.""" + import ray + ray.shutdown() + + +# --------------------------------------------------------------------------- +# Default config for programmatic Graph-based runs +# --------------------------------------------------------------------------- + +_DEFAULT_GRAPH_CONFIG = { + "logging": { + "local": {"enabled": True, "dir": "${paths.graph}"}, + }, + "paths": { + "imports": [], + "graph": "${run_dir}/graph", + "samples": "${run_dir}/samples", + }, + "buffer": { + "min_samples": 4096, + "max_samples": 32768, + "validation_samples": 256, + "simulate_count": 64, + "simulate_when_full": True, + "simulate_interval": 1, + "snapshot_every": 0, + }, + "sample": { + "posterior": {"n": 1000}, + }, +} + + +def _cls_to_target(cls_or_instance) -> str: + """Return a ``_target_`` string or a ```` placeholder.""" + if isinstance(cls_or_instance, str): + return cls_or_instance + obj = cls_or_instance + if isinstance(obj, type): + cls = obj + else: + cls = type(obj) + mod = getattr(cls, "__module__", None) + qualname = getattr(cls, "__qualname__", cls.__name__) + if mod in (None, "__main__") or not isinstance(cls_or_instance, type): + return f"" + return f"{mod}.{qualname}" + + +def _graph_to_config_dict(graph) -> dict: + """Serialise a Graph to a config dict with live-object placeholders.""" + import numpy as np + result = {} + for node in graph.node_list: + nd: dict = {} + if node.parents: + nd["parents"] = list(node.parents) + if node.evidence: + nd["evidence"] = list(node.evidence) + if node.scaffolds: + nd["scaffolds"] = list(node.scaffolds) + + # Simulator + sim = node.simulator_cls + target = _cls_to_target(sim) + if target.startswith("" + ) + else: + nd["observed"] = True + + # Ray actor config + if node.actor_config: + nd["ray"] = dict(node.actor_config) + + result[node.name] = nd + return result + + +# --------------------------------------------------------------------------- +# Config preparation (shared between launch() and the CLI) +# --------------------------------------------------------------------------- + + +def _prepare_config( + target, + output: Optional[Union[str, Path]], + overrides: Optional[List[str]], +): + """Resolve *target* into a runnable OmegaConf config with ``run_dir`` set. + + Returns: + (cfg, output_dir_path, prebuilt_graph_or_None) + """ + from datetime import datetime + from falcon.core.graph import Graph + from falcon.core.run_name import generate_run_dir + + OmegaConf.register_new_resolver("now", lambda fmt: datetime.now().strftime(fmt), replace=True) + + # Determine output directory first + if output is None: + run_dir = generate_run_dir() + else: + run_dir = str(output) + + run_dir_path = Path(run_dir) + saved_config = run_dir_path / "config.yml" + + prebuilt_graph = None + + if isinstance(target, Graph): + # Graph target: always use the live graph object (saved config has + # placeholders that can't be re-parsed). + prebuilt_graph = target + if saved_config.exists(): + cfg = OmegaConf.load(saved_config) + else: + base = OmegaConf.create(_DEFAULT_GRAPH_CONFIG) + graph_dict = _graph_to_config_dict(target) + cfg = OmegaConf.merge(base, {"graph": OmegaConf.create(graph_dict)}) + elif saved_config.exists(): + # Resume an existing non-Graph run from its saved config. + cfg = OmegaConf.load(saved_config) + elif isinstance(target, Config): + cfg = OmegaConf.merge(target._dict_config, {}) + elif isinstance(target, DictConfig): + cfg = OmegaConf.merge(target, {}) + elif isinstance(target, dict): + cfg = OmegaConf.create(target) + elif isinstance(target, (str, Path)): + cfg = OmegaConf.load(target) + else: + raise TypeError( + f"launch() target must be a Graph, Config, path, or dict; " + f"got {type(target).__name__}" + ) + + # Apply overrides + if overrides: + cfg = OmegaConf.merge(cfg, OmegaConf.from_dotlist(list(overrides))) + + # Inject run_dir and resolve interpolations + cfg.run_dir = run_dir + OmegaConf.resolve(cfg) + + # Persist config so the run is reproducible + run_dir_path.mkdir(parents=True, exist_ok=True) + if not saved_config.exists(): + OmegaConf.save(cfg, saved_config) + + return cfg, run_dir_path, prebuilt_graph + + +# --------------------------------------------------------------------------- +# launch() +# --------------------------------------------------------------------------- + + +def launch( + target, + output=None, + *, + overrides=None, + auto_sample: bool = True, + timeout: float = None, + wait: bool = True, +): + """Run a Falcon training pipeline from a notebook or script. + + Blocks by default (``wait=True``) and returns a finished :class:`Run`. + Lazily calls :func:`falcon.init` if Ray is not yet initialised. + + Args: + target: A :class:`Config` object, path to a YAML config file, or plain + dict. Passing a ``Graph`` is supported in Step 5. + output: Output directory. Auto-generated (``output/``) + if *None*. An existing directory with a ``config.yml`` is resumed. + overrides: Iterable of dotted override strings applied on top of + *target* (e.g. ``["buffer.max_samples=500"]``). + auto_sample: Generate posterior samples after training (default True). + timeout: Stop training gracefully after this many seconds. + wait: Block until training completes (default True). ``wait=False`` is + not yet implemented. + + Returns: + :class:`falcon.core.run_loader.Run` with config, metrics, and samples. + """ + if not wait: + raise NotImplementedError( + "wait=False (non-blocking launch) is not yet implemented. " + "Use wait=True (the default) or run falcon.launch() in a thread manually." + ) + + from falcon.cli import _run_pipeline + from falcon.core.run_loader import load_run + + cfg, output_dir, prebuilt_graph = _prepare_config(target, output, overrides) + + # Lazy Ray init + import ray + if not ray.is_initialized(): + init() + + obs = prebuilt_graph._api_observations if prebuilt_graph is not None else None + _run_pipeline( + cfg, + auto_sample=auto_sample, + timeout=timeout, + graph=prebuilt_graph, + observations=obs, + ) + + return load_run(output_dir) diff --git a/falcon/cli.py b/falcon/cli.py index 44a2316..46aa71a 100644 --- a/falcon/cli.py +++ b/falcon/cli.py @@ -483,10 +483,43 @@ def _save_samples(samples, sample_cfg, sample_type, graph, cfg, info_fn=print): info_fn(f"Saved {num_samples} {sample_type} samples to: {output_dir}/") -def launch_mode(cfg, interactive: bool = False, log_lines: int = 16, auto_sample: bool = True, timeout: float = None) -> None: - """Launch mode: Full training and inference pipeline.""" - import logging - import threading +def _run_pipeline( + cfg, + *, + auto_sample: bool = True, + timeout: float = None, + stop_check=None, + log_handler=None, + on_graph_ready=None, + summary_sink=None, + graph=None, + observations=None, +) -> Path: + """Pure training pipeline, decoupled from CLI frontend and Ray lifecycle. + + Assumes Ray is already initialised. Does not call ray.init() or ray.shutdown(). + + Args: + cfg: Resolved OmegaConf config. + auto_sample: Run configured post-training sampling when True. + timeout: Stop training after this many seconds (None = no limit). + stop_check: Callable returning True when training should stop gracefully. + Defaults to never stopping. + log_handler: Optional logging.Handler to replace the stdout console + handler (used by the TUI to route log lines to its display buffer). + on_graph_ready: Optional callable(graph_path: Path) invoked just before + training starts; used by the TUI to start its status polling thread. + summary_sink: Optional list; the end-of-run summary lines are appended + to it so the caller can echo them after display teardown. + graph: Pre-built Graph object (from the Python API). When provided, + ``cfg.graph`` is not parsed; this graph is used directly. + observations: Dict of node_name -> np.ndarray from graph._api_observations. + Only used when *graph* is provided. + + Returns: + output_dir Path. + """ + import logging as _logging import time as _time import torch import ray @@ -495,187 +528,79 @@ def launch_mode(cfg, interactive: bool = False, log_lines: int = 16, auto_sample from falcon.core.graph import create_graph_from_config from falcon.core.logger import Logger, set_logger, info - launch_start = _time.time() + if stop_check is None: + stop_check = lambda: False - # Initialize interactive display or graceful shutdown handler - display = None - shutdown_handler = None - if interactive: - try: - from falcon.interactive import InteractiveDisplay - # Footer height = log_lines + 4 (separator, status bar, sub-separator, help) - display = InteractiveDisplay(footer_height=log_lines + 4) - display.start() - except ImportError: - print("Interactive display unavailable (install falcon-sbi[blessed] to enable it)") - if display is None: - # Non-interactive mode: install double Ctrl+C handler - shutdown_handler = _GracefulShutdown() - shutdown_handler.install() - - # Get output directory from config + launch_start = _time.time() output_dir = Path(cfg.run_dir) path_cfg = _resolve_paths(cfg) - # Generate wandb group if not set - use run-dir folder name + # Build logging config logging_cfg = OmegaConf.to_container(cfg.get("logging", {}), resolve=True) if logging_cfg.get("wandb", {}).get("enabled", False): if not logging_cfg.get("wandb", {}).get("group"): - # Use the run-dir folder name as the group name logging_cfg.setdefault("wandb", {})["group"] = output_dir.name - - # Ensure local dir is set to graph path logging_cfg.setdefault("local", {})["dir"] = path_cfg["graph"] # Create driver logger and set as module-level logger - # This enables falcon.info(), falcon.log() etc. for DeployedGraph and other components driver_logger = Logger("driver", logging_cfg, capture_exceptions=True) set_logger(driver_logger) - # If interactive mode, replace console handler with one that routes to display - if display: + # Replace stdout handler with the injected one (e.g. TUI routing) + if log_handler is not None: for handler in driver_logger._logger.handlers[:]: - if isinstance(handler, logging.StreamHandler) and handler.stream == sys.stdout: + if isinstance(handler, _logging.StreamHandler) and handler.stream == sys.stdout: driver_logger._logger.removeHandler(handler) - # Add custom handler that routes to display - interactive_handler = logging.StreamHandler(_InteractiveStream(display)) - interactive_handler.setFormatter(logging.Formatter( - '%(asctime)s [%(levelname)s] %(message)s', - datefmt='%H:%M:%S' - )) - interactive_handler.setLevel(logging.INFO) - driver_logger._logger.addHandler(interactive_handler) break + driver_logger._logger.addHandler(log_handler) - # Log startup info + # Startup info info(f"falcon v{falcon.__version__}") info(f"Output: {output_dir}") - # Initialize Ray - ray_init_args = cfg.get("ray", {}).get("init", {}) - # Forward actor stdout/stderr to driver when console.level is set, - # so node log messages and crash output reach the terminal. - console_level = logging_cfg.get("console", {}).get("level", None) - ray_init_args.setdefault("log_to_driver", console_level is not None) - # Use a fixed namespace so falcon monitor can discover actors - ray_init_args.setdefault("namespace", "falcon") - # Suppress Ray startup banner - ray_init_args.setdefault("logging_level", "ERROR") - ray.init(**ray_init_args) - - # Show Ray cluster info with resources + # Ray cluster info (Ray must already be initialised by the caller) ctx = ray.get_runtime_context() gcs_address = ctx.gcs_address - is_local = ray_init_args.get("address") is None + is_local = cfg.get("ray", {}).get("init", {}).get("address") is None ray_status = "new local instance" if is_local else "existing cluster" resources = ray.cluster_resources() cpu = int(resources.get("CPU", 0)) gpu = int(resources.get("GPU", 0)) mem_gb = resources.get("memory", 0) / (1024**3) - info(f"Ray: {gcs_address} ({ray_status})") info(f"Resources: {cpu} CPU, {gpu} GPU, {mem_gb:.1f} GB") - ######################## - ### Model definition ### - ######################## - - # Instantiate model components directly from graph - graph, observations = create_graph_from_config(cfg.graph, _cfg=cfg) - - # Convert observations to tensors, adding batch dimension - observations = { - k: torch.from_numpy(v).unsqueeze(0) for k, v in observations.items() - } - - # Log graph info + # Build graph and observations + if graph is None: + graph, obs_raw = create_graph_from_config(cfg.graph, _cfg=cfg) + observations_tensors = { + k: torch.from_numpy(v).unsqueeze(0) for k, v in obs_raw.items() + } + else: + import numpy as np + observations_tensors = { + k: torch.from_numpy(np.asarray(v)).unsqueeze(0) + for k, v in (observations or {}).items() + } info(str(graph)) - for name, shape in observations.items(): + for name, shape in observations_tensors.items(): info(f"Observed: {name} {list(shape.shape)}") - #################### - ### Run analysis ### - #################### - - # Start status polling thread for interactive mode - status_thread = None graph_path = Path(path_cfg["graph"]) - if display: - # Set log directory so display can read node output.log files - display.set_log_dir(str(graph_path)) - - def poll_status(): - """Background thread to poll MonitorBridge and update display.""" - import time - while display.is_running: - try: - bridge = ray.get_actor("falcon:monitor_bridge") - status = ray.get(bridge.get_status.remote()) - - # Update nodes - for name, node_status in status.get("nodes", {}).items(): - display.update_node( - name=name, - status=node_status.get("status", "unknown"), - current_epoch=node_status.get("current_epoch", 0), - total_epochs=node_status.get("total_epochs", 0), - loss=node_status.get("loss"), - samples=node_status.get("samples", 0), - ) - - # Add dataset manager as a viewable node (for its output.log) - display.update_node(name="dataset", status="active") - - # Update buffer stats - buffer = status.get("buffer", {}) - display.update_buffer( - training=buffer.get("training", 0), - validation=buffer.get("validation", 0), - ) - except Exception: - pass # MonitorBridge may not be ready yet - # Redraw footer to refresh log tail - with display._lock: - display._draw_footer() - - time.sleep(1.0) - - status_thread = threading.Thread(target=poll_status, daemon=True) - status_thread.start() - - # Create stop check callback for graceful shutdown (handles Ctrl+C and timeout) - _start_time = _time.time() - _timeout_logged = False - - def stop_check(): - nonlocal _timeout_logged - # Check user interrupt (Ctrl+C) - if display and display.stop_requested: - return True - if shutdown_handler and shutdown_handler.stop_requested: - return True - # Check timeout - if timeout is not None: - elapsed = _time.time() - _start_time - if elapsed >= timeout: - if not _timeout_logged: - info(f"Timeout reached ({timeout}s), stopping gracefully...") - _timeout_logged = True - return True - return False + # Notify caller that graph path is known (TUI uses this to start status thread) + if on_graph_ready is not None: + on_graph_ready(graph_path) run_status = "completed" deployed_graph = None try: - # 1) Deploy graph (pass logging config) deployed_graph = falcon.DeployedGraph( graph, import_dirs=path_cfg["imports"], log_config=logging_cfg, ) - # 2) Prepare dataset manager for deployed graph and store initial samples from omegaconf import OmegaConf as _OmegaConf from falcon.core.raystore import BufferConfig as _BufferConfig buffer_cfg = _OmegaConf.merge(_OmegaConf.structured(_BufferConfig), cfg.buffer) @@ -686,50 +611,27 @@ def stop_check(): log_config=logging_cfg, ) - deployed_graph.launch(dataset_manager, observations, graph_path=graph_path, stop_check=stop_check) - - ############################# - ### Posterior sampling ### - ############################# + deployed_graph.launch(dataset_manager, observations_tensors, graph_path=graph_path, stop_check=stop_check) - # Check if posterior sampling is configured and enabled + # Auto-sample posterior sample_cfg = cfg.get("sample", {}).get("posterior", {}) num_posterior_samples = sample_cfg.get("n", 0) - if auto_sample and num_posterior_samples > 0: info(f"Generating {num_posterior_samples} posterior samples...") - - sample_refs = deployed_graph.sample_posterior(num_posterior_samples, observations) + sample_refs = deployed_graph.sample_posterior(num_posterior_samples, observations_tensors) samples = deployed_graph._refs_to_arrays(sample_refs) + _save_samples(samples=samples, sample_cfg=sample_cfg, sample_type="posterior", + graph=graph, cfg=cfg, info_fn=info) - # Save posterior samples - _save_samples( - samples=samples, - sample_cfg=sample_cfg, - sample_type="posterior", - graph=graph, - cfg=cfg, - info_fn=info, - ) - - # Check if PPD sampling is configured and enabled + # Auto-sample PPD ppd_cfg = cfg.get("sample", {}).get("ppd", {}) num_ppd_samples = ppd_cfg.get("n", 0) - if auto_sample and num_ppd_samples > 0: info(f"Generating {num_ppd_samples} PPD samples...") - - sample_refs = deployed_graph.sample_ppd(num_ppd_samples, observations) + sample_refs = deployed_graph.sample_ppd(num_ppd_samples, observations_tensors) samples = deployed_graph._refs_to_arrays(sample_refs) - - _save_samples( - samples=samples, - sample_cfg=ppd_cfg, - sample_type="ppd", - graph=graph, - cfg=cfg, - info_fn=info, - ) + _save_samples(samples=samples, sample_cfg=ppd_cfg, sample_type="ppd", + graph=graph, cfg=cfg, info_fn=info) except KeyboardInterrupt: run_status = "interrupted" @@ -738,43 +640,142 @@ def stop_check(): run_status = f"failed ({type(e).__name__}: {e})" raise finally: - ########################## - ### Clean up resources ### - ########################## - - # A graceful Ctrl+C / timeout exits the launch normally, not via an - # exception, so reflect that here. - if run_status == "completed": - if (display and display.stop_requested) or ( - shutdown_handler and shutdown_handler.stop_requested - ): - run_status = "interrupted" - - # Build the end-of-run summary and route it through the driver logger - # so it lands in driver/output.log (and, in plain mode, on stdout). + # A graceful stop_check exit is not an exception, so detect it here. + if run_status == "completed" and stop_check(): + run_status = "interrupted" + summary_lines = _build_run_summary( run_status, output_dir, cfg, deployed_graph, start_time=launch_start, end_time=_time.time(), ) for line in summary_lines: info(line) + if summary_sink is not None: + summary_sink.extend(summary_lines) + + if deployed_graph is not None: + deployed_graph.shutdown() + driver_logger.shutdown() + + return output_dir + + +def launch_mode(cfg, interactive: bool = False, log_lines: int = 16, auto_sample: bool = True, timeout: float = None) -> None: + """Launch mode: CLI frontend over _run_pipeline.""" + import logging + import threading + import time as _time + import ray + from omegaconf import OmegaConf + + # Set up interactive display or graceful shutdown handler + display = None + shutdown_handler = None + if interactive: + try: + from falcon.interactive import InteractiveDisplay + display = InteractiveDisplay(footer_height=log_lines + 4) + display.start() + except ImportError: + print("Interactive display unavailable (install falcon-sbi[blessed] to enable it)") + if display is None: + shutdown_handler = _GracefulShutdown() + shutdown_handler.install() + + # Initialize Ray + logging_cfg = OmegaConf.to_container(cfg.get("logging", {}), resolve=True) + ray_init_args = cfg.get("ray", {}).get("init", {}) + console_level = logging_cfg.get("console", {}).get("level", None) + ray_init_args.setdefault("log_to_driver", console_level is not None) + ray_init_args.setdefault("namespace", "falcon") + ray_init_args.setdefault("logging_level", "ERROR") + ray.init(**ray_init_args) + + # Build stop_check: handles Ctrl+C, display stop, and timeout + _start_time = _time.time() + _timeout_logged = False + + def stop_check(): + nonlocal _timeout_logged + if display and display.stop_requested: + return True + if shutdown_handler and shutdown_handler.stop_requested: + return True + if timeout is not None: + elapsed = _time.time() - _start_time + if elapsed >= timeout: + if not _timeout_logged: + from falcon.core.logger import info + info(f"Timeout reached ({timeout}s), stopping gracefully...") + _timeout_logged = True + return True + return False + + # Build log handler for TUI routing (replaces stdout in the driver logger) + log_handler = None + if display: + interactive_handler = logging.StreamHandler(_InteractiveStream(display)) + interactive_handler.setFormatter(logging.Formatter( + '%(asctime)s [%(levelname)s] %(message)s', datefmt='%H:%M:%S' + )) + interactive_handler.setLevel(logging.INFO) + log_handler = interactive_handler + + # Build on_graph_ready: TUI sets log dir and starts status polling thread + def on_graph_ready(graph_path): + if display is None: + return + display.set_log_dir(str(graph_path)) + + def poll_status(): + import time + while display.is_running: + try: + bridge = ray.get_actor("falcon:monitor_bridge") + status = ray.get(bridge.get_status.remote()) + for name, node_status in status.get("nodes", {}).items(): + display.update_node( + name=name, + status=node_status.get("status", "unknown"), + current_epoch=node_status.get("current_epoch", 0), + total_epochs=node_status.get("total_epochs", 0), + loss=node_status.get("loss"), + samples=node_status.get("samples", 0), + ) + display.update_node(name="dataset", status="active") + buffer = status.get("buffer", {}) + display.update_buffer( + training=buffer.get("training", 0), + validation=buffer.get("validation", 0), + ) + except Exception: + pass + with display._lock: + display._draw_footer() + time.sleep(1.0) - # Stop interactive display first (restores terminal) + threading.Thread(target=poll_status, daemon=True).start() + + summary_lines = [] + try: + _run_pipeline( + cfg, + auto_sample=auto_sample, + timeout=timeout, + stop_check=stop_check, + log_handler=log_handler, + on_graph_ready=on_graph_ready, + summary_sink=summary_lines, + ) + finally: if display: display.stop() - # The TUI used the alternate screen buffer, so nothing the user - # saw survives. Echo the summary to real stdout as the receipt. + # TUI used alternate screen buffer; echo summary to restored terminal. for line in summary_lines: print(line) - - # Uninstall shutdown handler if shutdown_handler: shutdown_handler.uninstall() - if deployed_graph is not None: - deployed_graph.shutdown() - driver_logger.shutdown() - def sample_mode(cfg, sample_type: str) -> None: """Sample mode: Generate samples using different sampling strategies. diff --git a/falcon/core/base_estimator.py b/falcon/core/base_estimator.py index 6963a38..af30d00 100644 --- a/falcon/core/base_estimator.py +++ b/falcon/core/base_estimator.py @@ -14,92 +14,62 @@ class BaseEstimator(ABC): """ Fully abstract base class defining the estimator interface. - All methods are abstract - no implementation details. - Concrete implementations must provide all functionality. + Subclasses implement a two-phase lifecycle: - Conditions are passed as Dict[str, Tensor] mapping node names to values. - Sampling methods return dicts with 'value' (ndarray) and optionally 'log_prob' (ndarray). + 1. ``__init__``: pure config storage — stores all parameters as instance + attributes. Defaults live here; nothing runtime is wired up. + + 2. ``setup()``: load-bearing runtime wiring — called by ``NodeWrapper`` + inside a Ray actor before training begins. Applies any flat YAML + overrides (``config`` dict), then initialises networks, devices, and + all runtime objects. + + Example:: + + graph.add_node("z", estimator=Flow(max_epochs=300, net_type="nsf")) """ @abstractmethod - async def train(self, buffer) -> None: - """ - Train the estimator. + def setup( + self, + simulator_instance, + theta_key: Optional[str], + condition_keys, + ) -> None: + """Wire up runtime components. + + Called by ``NodeWrapper`` before training. Args: - buffer: BufferView providing access to training/validation data + simulator_instance: Live prior/simulator, already constructed. + theta_key: Name of the parameter node being estimated. + condition_keys: List of evidence/scaffold node names. """ - pass @abstractmethod - def sample_prior( - self, num_samples: int, conditions: Optional[Conditions] = None - ) -> dict: - """ - Sample from the prior distribution. - - Args: - num_samples: Number of samples to generate - conditions: Conditioning values from parent nodes (usually None for prior) - - Returns: - Dict with 'value' (ndarray) and optionally 'log_prob' (ndarray) - """ + async def train(self, buffer) -> None: pass @abstractmethod - def sample_posterior( - self, num_samples: int, conditions: Optional[Conditions] = None - ) -> dict: - """ - Sample from the posterior distribution. - - Args: - num_samples: Number of samples to generate - conditions: Dict mapping node names to condition tensors - - Returns: - Dict with 'value' (ndarray) and optionally 'log_prob' (ndarray) - """ + def sample_prior(self, num_samples: int, conditions: Optional[Conditions] = None) -> dict: pass @abstractmethod - def sample_proposal( - self, num_samples: int, conditions: Optional[Conditions] = None - ) -> dict: - """ - Sample from the proposal distribution for adaptive resampling. - - Args: - num_samples: Number of samples to generate - conditions: Dict mapping node names to condition tensors + def sample_posterior(self, num_samples: int, conditions: Optional[Conditions] = None) -> dict: + pass - Returns: - Dict with 'value' (ndarray) and optionally 'log_prob' (ndarray) - """ + @abstractmethod + def sample_proposal(self, num_samples: int, conditions: Optional[Conditions] = None) -> dict: pass @abstractmethod def save(self, node_dir: Path) -> None: - """ - Save estimator state to directory. - - Args: - node_dir: Directory to save state to - """ pass @abstractmethod def load(self, node_dir: Path) -> None: - """ - Load estimator state from directory. - - Args: - node_dir: Directory to load state from - """ pass @abstractmethod def interrupt(self) -> None: - """Terminate training loop.""" pass diff --git a/falcon/core/deployed_graph.py b/falcon/core/deployed_graph.py index bd273cf..95b00f5 100644 --- a/falcon/core/deployed_graph.py +++ b/falcon/core/deployed_graph.py @@ -1,6 +1,5 @@ import time import ray -import asyncio import torch import os import sys @@ -154,20 +153,36 @@ def __init__(self, node, graph, import_dirs=None, log_config=None): # Status tracking for monitoring self._status = "initializing" - simulator_cls = LazyLoader(node.simulator_cls) - self.simulator_instance = simulator_cls(**node.simulator_config) + # Live instances (from Python API) are used directly; string / class + # paths go through LazyLoader for deferred import + instantiation. + if isinstance(node.simulator_cls, (str, type)): + simulator_cls = LazyLoader(node.simulator_cls) + self.simulator_instance = simulator_cls(**node.simulator_config) + else: + self.simulator_instance = node.simulator_cls # Condition keys for embedding (evidence + scaffolds) self.condition_keys = self.node.evidence + self.node.scaffolds debug(f"Condition keys: {self.condition_keys}") if node.estimator_cls is not None: - estimator_cls = LazyLoader(node.estimator_cls) - self.estimator_instance = estimator_cls( + from falcon.core.base_estimator import BaseEstimator as _BaseEstimator + if isinstance(node.estimator_cls, _BaseEstimator): + # Notebook path: already a configured instance (e.g. Flow(max_epochs=200)) + self.estimator_instance = node.estimator_cls + elif isinstance(node.estimator_cls, (str, type)): + # YAML path: pass flat config dict as kwargs to __init__ + estimator_cls = LazyLoader(node.estimator_cls) + self.estimator_instance = estimator_cls(**node.estimator_config) + else: + raise TypeError( + f"estimator_cls must be a BaseEstimator instance, class, or " + f"string; got {type(node.estimator_cls).__name__}" + ) + self.estimator_instance.setup( self.simulator_instance, theta_key=node.name, condition_keys=self.condition_keys, - config=node.estimator_config, ) else: self.estimator_instance = None @@ -427,8 +442,8 @@ def get_status(self) -> dict: if status["loss_history"]: status["loss"] = status["loss_history"][-1] status["current_epoch"] = len(est.history.get("epochs", [])) - if hasattr(est, "loop_config"): - status["total_epochs"] = est.loop_config.max_epochs + if hasattr(est, "max_epochs"): + status["total_epochs"] = est.max_epochs if hasattr(est, "history") and est.history.get("n_samples"): status["samples"] = est.history["n_samples"][-1] @@ -777,14 +792,13 @@ def launch(self, dataset_manager, observations, graph_path=None, stop_check=None graph_path: Path to save/load graph stop_check: Optional callable that returns True when graceful stop is requested """ - asyncio.run(self._launch(dataset_manager, observations, graph_path=graph_path, stop_check=stop_check)) + self._launch(dataset_manager, observations, graph_path=graph_path, stop_check=stop_check) - async def _launch(self, dataset_manager, observations, graph_path=None, stop_check=None): + def _launch(self, dataset_manager, observations, graph_path=None, stop_check=None): # Load graph if saved model files exist (not just logging directories) if graph_path is not None and any(graph_path.glob("*/*.pth")): self.load(graph_path) - # TODO: Make distrinction clearer between dataset_manager and dataset_manager_actor dataset_manager = dataset_manager.dataset_manager_actor # Register dataset manager with monitor bridge for monitoring diff --git a/falcon/core/graph.py b/falcon/core/graph.py index ea483fa..9fb64af 100644 --- a/falcon/core/graph.py +++ b/falcon/core/graph.py @@ -54,8 +54,27 @@ def __init__( self.sample_chunk_size = sample_chunk_size +def _short_cls_name(obj) -> str: + """Return a short display name for a class, instance, or string target.""" + if obj is None: + return "None" + if isinstance(obj, str): + if obj.startswith("").strip() + return obj.rsplit(".", 1)[-1] + if isinstance(obj, type): + return obj.__name__ + return type(obj).__name__ + + class Graph: - def __init__(self, node_list): + def __init__(self, node_list=None): + # Observations supplied directly as arrays via add_node(observed=array) + self._api_observations = {} + self._build(list(node_list) if node_list is not None else []) + + def _build(self, node_list): + """(Re)compute all derived topology from *node_list*.""" # Storing the node list self.node_list = node_list self.node_dict = {node.name: node for node in node_list} @@ -89,7 +108,8 @@ def __init__(self, node_list): if name in backward_set: continue backward_set.add(name) - for parent in self.forward_deps[name]: + # Guard: node may reference a not-yet-added peer + for parent in self.forward_deps.get(name, []): if parent not in backward_set: queue.append(parent) @@ -112,6 +132,79 @@ def __init__(self, node_list): backward_names, self.backward_deps ) + def add_node( + self, + name: str, + simulator, + estimator=None, + *, + parents=None, + evidence=None, + scaffolds=None, + observed=None, + num_actors: int = 1, + sample_chunk_size: int = 0, + **ray_kwargs, + ) -> "Graph": + """Add a node to the graph and return *self* for chaining. + + Args: + name: Node name (must be unique in this graph). + simulator: Simulator class, string ``_target_``, or a live instance. + Live instances (e.g. ``Product([...])``) are shipped to Ray + actors via cloudpickle. + estimator: Estimator class, string ``_target_``, config builder + (e.g. ``Flow(max_epochs=300)``), or ``None`` for + observation-only nodes. + parents: List of parent node names (forward / simulation direction). + evidence: List of evidence node names (inference direction). + scaffolds: List of scaffold node names. + observed: Observed value — a numpy/torch array (used directly), or + ``True`` / a file-path string (YAML semantics). + num_actors: Number of Ray actors to spawn for this node. + sample_chunk_size: Chunk size for sampling (0 = no chunking). + **ray_kwargs: Node-level Ray actor options, prefixed with ``ray_`` + (e.g. ``ray_num_gpus=0.5``, ``ray_num_cpus=2``, + ``ray_runtime_env={...}``). The ``ray_`` prefix is stripped + before passing to Ray. + + Returns: + *self*, so calls can be chained. + """ + import numpy as np + + # Collect actor config from ray_* kwargs + actor_config = {} + for key, val in ray_kwargs.items(): + if not key.startswith("ray_"): + raise TypeError( + f"add_node() got unexpected keyword argument '{key}'. " + f"Ray actor options must be prefixed with 'ray_' " + f"(e.g. ray_num_gpus=0.5)." + ) + actor_config[key[4:]] = val # strip "ray_" prefix + + # Handle observed= as a live array + if observed is not None and not isinstance(observed, (str, bool)): + self._api_observations[name] = np.asarray(observed) + observed = True # mark as observed for the Node + + node = Node( + name=name, + simulator_cls=simulator, + estimator_cls=estimator, + parents=list(parents or []), + evidence=list(evidence or []), + scaffolds=list(scaffolds or []), + observed=bool(observed) if observed is not None else False, + actor_config=actor_config, + num_actors=num_actors, + sample_chunk_size=sample_chunk_size, + ) + + self._build(self.node_list + [node]) + return self + def get_parents(self, node_name): return self.forward_deps[node_name] @@ -163,6 +256,61 @@ def __add__(self, other): new_node_list = self.node_list + other.node_list return Graph(new_node_list) + # ------------------------------------------------------------------ + # Rich display helpers + # ------------------------------------------------------------------ + + def _repr_html_(self) -> str: + """Mermaid flowchart for Jupyter/Colab.""" + import uuid + + uid = uuid.uuid4().hex[:8] + lines = ["flowchart LR"] + + for node in self.node_list: + sim = _short_cls_name(node.simulator_cls) + if node.observed: + label = f'"{node.name}
{sim} · observed"' + color = "fill:#d5f5e3,stroke:#27ae60" + elif node.estimator_cls is not None: + est = _short_cls_name(node.estimator_cls) + label = f'"{node.name}
sim:{sim}
est:{est}
"' + color = "fill:#d6eaf8,stroke:#2980b9" + else: + label = f'"{node.name}
{sim}"' + color = "fill:#fef9e7,stroke:#f39c12" + lines.append(f" {node.name}[{label}]") + lines.append(f" style {node.name} {color}") + + for node in self.node_list: + for parent in node.parents: + lines.append(f" {parent} --> {node.name}") + + for node in self.node_list: + for ev in node.evidence: + lines.append(f" {ev} -.->|evidence| {node.name}") + + mermaid_src = "\n".join(lines) + return f"""
+
+{mermaid_src}
+
+
+""" + def __str__(self): # Return graph structure # - Based on topological sort diff --git a/falcon/core/raystore.py b/falcon/core/raystore.py index b9434bf..db82f32 100644 --- a/falcon/core/raystore.py +++ b/falcon/core/raystore.py @@ -135,7 +135,7 @@ class SampleStatus(IntEnum): DELETED = 4 # Permanently deleted -@ray.remote(name="DatasetManager") +@ray.remote class DatasetManagerActor: def __init__( self, diff --git a/falcon/core/run_loader.py b/falcon/core/run_loader.py index 5f90d6f..a45a228 100644 --- a/falcon/core/run_loader.py +++ b/falcon/core/run_loader.py @@ -122,6 +122,116 @@ def observations(self) -> Dict[str, np.ndarray]: return self._observations + def plot_metrics(self, nodes=None, metrics=("train", "val"), figsize=None): + """Plot training metric curves. + + Args: + nodes: Node names to plot. Defaults to all nodes with metric data. + metrics: Metric names to look for (e.g. ``("train", "val")``). + figsize: Matplotlib figure size. Auto-scaled if *None*. + + Returns: + ``matplotlib.figure.Figure`` + """ + import matplotlib.pyplot as plt + + available = self.metrics.list_nodes() + plot_nodes = [n for n in (nodes or available) if n in available] + + if not plot_nodes: + print("No metric data found.") + return None + + n_cols = len(plot_nodes) + fig, axes = plt.subplots(1, n_cols, figsize=figsize or (5 * n_cols, 4), squeeze=False) + axes = axes[0] + + for ax, node_name in zip(axes, plot_nodes): + node_reader = self.metrics[node_name] + node_metrics = node_reader.list_metrics() + plotted = False + for metric in metrics: + if metric in node_metrics: + try: + r = node_reader[metric] + ax.plot(r.steps, r.values, label=metric) + plotted = True + except Exception: + pass + if not plotted: + ax.text(0.5, 0.5, "no data", ha="center", va="center", transform=ax.transAxes) + ax.set_title(node_name) + ax.set_xlabel("step") + ax.set_ylabel("loss") + if plotted: + ax.legend() + + fig.tight_layout() + return fig + + def _repr_html_(self) -> str: + """Status card for Jupyter/Colab.""" + rows = [] + + # Per-node metrics summary + metric_rows = [] + for node_name in self.metrics.list_nodes(): + node_reader = self.metrics[node_name] + available = node_reader.list_metrics() + final_loss = "" + for key in ("val", "train"): + if key in available: + try: + vals = node_reader[key].values + if len(vals): + final_loss = f"{vals[-1]:.4f}" + except Exception: + pass + break + n_steps = "" + if "epoch" in available: + try: + n_steps = str(int(node_reader["epoch"].values[-1])) + except Exception: + pass + td = "padding:2px 8px" + metric_rows.append( + f"" + f"{node_name}" + f"{final_loss}" + f"{n_steps}" + f"" + ) + + if metric_rows: + rows.append( + "" + "" + "" + "" + "" + "" + + "".join(metric_rows) + + "
nodefinal lossepochs
" + ) + + # Sample counts + try: + post = self.samples.posterior + n_files = len(list(post._sample_dir.glob("*.npz"))) if hasattr(post, "_sample_dir") else "?" + rows.append(f"
posterior samples: {n_files} file(s)
") + except Exception: + pass + + inner = "\n".join(rows) + return ( + f"
" + f"Run {self.run_dir}" + f"{inner}" + f"
" + ) + def __repr__(self): return f"" diff --git a/falcon/embeddings/builder.py b/falcon/embeddings/builder.py index 48d4c57..4f71a9d 100644 --- a/falcon/embeddings/builder.py +++ b/falcon/embeddings/builder.py @@ -333,8 +333,28 @@ def _flatten_config_to_modules( return modules, input_keys_list, output_keys, temp_counter +class _PassthroughEmbedding(nn.Module): + """Identity embedding: concatenates all condition tensors along the last dim. + + Casts to float32 so the output is compatible with the default network dtype. + """ + + def forward(self, data_dict: Dict[str, Any]): + import torch + tensors = [v.float() for v in data_dict.values() if hasattr(v, "shape")] + if not tensors: + raise ValueError("PassthroughEmbedding received an empty conditions dict.") + return torch.cat(tensors, dim=-1) + + def instantiate_embedding(embedding_config: Dict[str, Any]) -> EmbeddingWrapper: - """Instantiate embedding pipeline from config.""" + """Instantiate embedding pipeline from config. + + When *embedding_config* is ``None``, returns a pass-through embedding that + concatenates all condition tensors along the last dimension. + """ + if embedding_config is None: + return _PassthroughEmbedding() required_input_keys = _collect_input_keys(embedding_config) modules, input_keys_list, output_keys, _ = _flatten_config_to_modules( embedding_config diff --git a/falcon/estimators/__init__.py b/falcon/estimators/__init__.py index cef0d22..01b1300 100644 --- a/falcon/estimators/__init__.py +++ b/falcon/estimators/__init__.py @@ -12,19 +12,12 @@ TrainingLoopConfig, ) from falcon.estimators.gaussian import Gaussian -from falcon.estimators.gaussian_fullcov import ( - GaussianConfig, - GaussianFullCov, - GaussianPosterior, -) +from falcon.estimators.gaussian_fullcov import GaussianFullCov __all__ = [ "Flow", - "FlowConfig", "Gaussian", - "GaussianConfig", "GaussianFullCov", - "GaussianPosterior", "StepwiseEstimator", "LossBasedEstimator", "TrainingLoopConfig", @@ -33,7 +26,6 @@ # Lazy imports for sbi-dependent classes _LAZY_IMPORTS = { "Flow": "falcon.estimators.flow", - "FlowConfig": "falcon.estimators.flow", } diff --git a/falcon/estimators/flow.py b/falcon/estimators/flow.py index f4ca9a5..a8ba86a 100644 --- a/falcon/estimators/flow.py +++ b/falcon/estimators/flow.py @@ -2,125 +2,131 @@ import copy import time -from dataclasses import dataclass, field from pathlib import Path -from typing import Any, Dict, List, Optional +from typing import Dict, List, Optional import numpy as np import torch -from omegaconf import OmegaConf from torch.optim import AdamW from torch.optim.lr_scheduler import ReduceLROnPlateau -from falcon.core.logger import log, debug, info, warning, error +from falcon.core.logger import log, debug from falcon.estimators.flow_density import FlowDensity -from falcon.estimators.stepwise_base import StepwiseEstimator, TrainingLoopConfig +from falcon.estimators.stepwise_base import StepwiseEstimator from falcon.embeddings import instantiate_embedding -# ==================== Configuration Dataclasses ==================== - - -@dataclass -class NetworkConfig: - """Neural network architecture parameters.""" - - net_type: str = "zuko_nice" - theta_norm: bool = True - norm_momentum: float = 1e-2 - adaptive_momentum: bool = False - use_log_update: bool = False - - -@dataclass -class OptimizerConfig: - """Optimizer parameters (training-time).""" - - lr: float = 1e-2 - betas: tuple = (0.9, 0.9) # Lower beta2 for dynamic SBI setting - lr_decay_factor: float = 0.1 - scheduler_patience: int = 8 - - -@dataclass -class InferenceConfig: - """Inference and sampling parameters.""" - - gamma: float = 0.5 - discard_samples: bool = True - log_ratio_threshold: float = -20.0 - sample_reference_posterior: bool = False - use_best_models_during_inference: bool = True - # Importance sampling parameters - num_proposals: int = 256 - reference_samples: int = 128 - hypercube_bound: float = 2.0 - out_of_bounds_penalty: float = 100.0 - nan_replacement: float = -100.0 - - -@dataclass -class FlowConfig: - """Top-level Flow estimator configuration.""" - - loop: TrainingLoopConfig = field(default_factory=TrainingLoopConfig) - network: NetworkConfig = field(default_factory=NetworkConfig) - optimizer: OptimizerConfig = field(default_factory=OptimizerConfig) - inference: InferenceConfig = field(default_factory=InferenceConfig) - embedding: Optional[Any] = None - device: Optional[str] = None - - -# ==================== Flow Implementation ==================== - - class Flow(StepwiseEstimator): - """ - Flow-based posterior estimation (formerly SNPE_A). - - Implementation-specific features: - - Dual flow architecture (conditional + marginal) - - Parameter space normalization via hypercube mapping - - Importance sampling for posterior/proposal + """Flow-based posterior estimation using a conditional + marginal flow pair. + + Args: + max_epochs: Maximum training epochs. + net_type: Flow architecture (``zuko_nice``, ``nsf``, ``maf``, ``zuko_gf``, ...). + lr: Learning rate. + gamma: Proposal tempering coefficient. + embedding: Embedding config dict (with ``_target_`` etc.) or ``None``. + device: Device string (e.g. ``"cuda:0"``); auto-detected if ``None``. + batch_size: Mini-batch size. + early_stop_patience: Epochs without improvement before stopping. + prior_epochs: Epochs to sample from prior before switching to proposal. + cache_on_device: Cache training data on the estimator device. + cache_sync_every: Resync buffer cache every N epochs (0 = every epoch). + max_cache_samples: Cap on cached training samples (0 = all). + theta_norm: Normalise parameter space online. + norm_momentum: EMA momentum for online normalisation. + adaptive_momentum: Adaptive momentum for normalisation. + use_log_update: Use log-space normalisation update. + betas: AdamW beta coefficients. + lr_decay_factor: LR decay factor for plateau scheduler. + lr_patience: Plateau patience before LR decay. + discard_samples: Discard low log-ratio training samples. + log_ratio_threshold: Log-ratio cutoff for discarding. + sample_reference_posterior: Sample reference posterior for proposals. + use_best_models: Use best-checkpoint networks for sampling. + num_proposals: Importance sampling proposal count. + reference_samples: Reference posterior sample count. + hypercube_bound: Hypercube clipping bound for proposals. + out_of_bounds_penalty: Log-weight penalty for out-of-bounds samples. + nan_replacement: Replacement for NaN/−∞ log-weights. """ def __init__( self, - simulator_instance, - theta_key: Optional[str] = None, - condition_keys: Optional[List[str]] = None, - config: Optional[dict] = None, + *, + # Most commonly changed + max_epochs: int = 100, + net_type: str = "zuko_nice", + lr: float = 1e-2, + gamma: float = 0.5, + embedding=None, + device: Optional[str] = None, + # Training loop + batch_size: int = 128, + early_stop_patience: int = 16, + prior_epochs: int = 0, + cache_on_device: bool = False, + cache_sync_every: int = 0, + max_cache_samples: int = 0, + # Network + theta_norm: bool = True, + norm_momentum: float = 1e-2, + adaptive_momentum: bool = False, + use_log_update: bool = False, + # Optimizer + betas: tuple = (0.9, 0.9), + lr_decay_factor: float = 0.1, + lr_patience: int = 8, + # Inference + discard_samples: bool = True, + log_ratio_threshold: float = -20.0, + sample_reference_posterior: bool = False, + use_best_models: bool = True, + num_proposals: int = 256, + reference_samples: int = 128, + hypercube_bound: float = 2.0, + out_of_bounds_penalty: float = 100.0, + nan_replacement: float = -100.0, ): - """ - Initialize Flow estimator. - - Args: - simulator_instance: Prior/simulator instance - theta_key: Key for theta in batch data - condition_keys: Keys for condition data in batch - config: Configuration dict with loop, network, optimizer, inference sections - """ - # Merge user config with defaults using OmegaConf structured config - schema = OmegaConf.structured(FlowConfig) - config = OmegaConf.merge(schema, config or {}) - - super().__init__( - simulator_instance=simulator_instance, - loop_config=config.loop, - theta_key=theta_key, - condition_keys=condition_keys, - ) - - self.config = config - - # Device setup - self.device = self._setup_device(config.device) + self.max_epochs = max_epochs + self.net_type = net_type + self.lr = lr + self.gamma = gamma + self.embedding = embedding + self.device = device + self.batch_size = batch_size + self.early_stop_patience = early_stop_patience + self.prior_epochs = prior_epochs + self.cache_on_device = cache_on_device + self.cache_sync_every = cache_sync_every + self.max_cache_samples = max_cache_samples + self.theta_norm = theta_norm + self.norm_momentum = norm_momentum + self.adaptive_momentum = adaptive_momentum + self.use_log_update = use_log_update + self.betas = betas + self.lr_decay_factor = lr_decay_factor + self.lr_patience = lr_patience + self.discard_samples = discard_samples + self.log_ratio_threshold = log_ratio_threshold + self.sample_reference_posterior = sample_reference_posterior + self.use_best_models = use_best_models + self.num_proposals = num_proposals + self.reference_samples = reference_samples + self.hypercube_bound = hypercube_bound + self.out_of_bounds_penalty = out_of_bounds_penalty + self.nan_replacement = nan_replacement + + def setup(self, simulator_instance, theta_key=None, condition_keys=None): + super().setup(simulator_instance, theta_key, condition_keys) + + if self.device: + self.device = torch.device(self.device) + else: + self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + debug(f"Auto-detected device: {self.device}") - # Embedding network - embedding_config = OmegaConf.to_container(config.embedding, resolve=True) - self._embedding = instantiate_embedding(embedding_config).to(self.device) + self._embedding = instantiate_embedding(self.embedding).to(self.device) - # Flow networks (initialized lazily) self._conditional_flow = None self._marginal_flow = None self._best_conditional_flow = None @@ -128,52 +134,30 @@ def __init__( self._best_embedding = None self._init_parameters = None - # Best loss tracking self.best_conditional_flow_val_loss = float("inf") self.best_marginal_flow_val_loss = float("inf") - # Optimizer/scheduler (initialized lazily) self._optimizer = None self._scheduler = None - # Extended history for Flow-specific tracking - self.history.update({ - "theta_mins": [], - "theta_maxs": [], - }) - - def _setup_device(self, device: Optional[str]) -> torch.device: - """Setup compute device.""" - if device: - return torch.device(device) - dev = torch.device("cuda" if torch.cuda.is_available() else "cpu") - debug(f"Auto-detected device: {dev}") - return dev + self.history.update({"theta_mins": [], "theta_maxs": []}) # ==================== Network Initialization ==================== def _initialize_networks(self, theta: torch.Tensor, conditions: Dict) -> None: - """Initialize flow networks and optimizer.""" - self._init_parameters = [theta, conditions] debug("Initializing networks...") - debug(f"GPU available: {torch.cuda.is_available()}") - - cfg_net = self.config.network - cfg_opt = self.config.optimizer + self._init_parameters = [theta, conditions] - # Embed conditions to get embedding dimension conditions_device = {k: v.to(self.device) for k, v in conditions.items()} s = self._embed(conditions_device, train=False).detach() theta_device = theta.to(self.device) - # Create flow networks self._conditional_flow = self._create_flow(theta_device, s, is_conditional=True) self._conditional_flow.to(self.device) self._marginal_flow = self._create_flow(theta_device, s, is_conditional=False) self._marginal_flow.to(self.device) - # Best-fit copies self._best_conditional_flow = self._create_flow(theta_device, s, is_conditional=True) self._best_conditional_flow.to(self.device) self._best_conditional_flow.load_state_dict(self._conditional_flow.state_dict()) @@ -184,82 +168,57 @@ def _initialize_networks(self, theta: torch.Tensor, conditions: Dict) -> None: self._best_embedding = copy.deepcopy(self._embedding) - # Optimizer and scheduler parameters = ( list(self._conditional_flow.parameters()) + list(self._marginal_flow.parameters()) + list(self._embedding.parameters()) ) - self._optimizer = AdamW(parameters, lr=cfg_opt.lr, betas=cfg_opt.betas) + self._optimizer = AdamW(parameters, lr=self.lr, betas=self.betas) self._scheduler = ReduceLROnPlateau( self._optimizer, mode="min", - factor=cfg_opt.lr_decay_factor, - patience=cfg_opt.scheduler_patience, + factor=self.lr_decay_factor, + patience=self.lr_patience, ) self.networks_initialized = True debug("Networks initialized.") def _create_flow(self, theta, s, is_conditional=True): - """Create a FlowDensity network with current config.""" - cfg = self.config.network return FlowDensity( theta, s if is_conditional else s * 0, - theta_norm=cfg.theta_norm, - norm_momentum=cfg.norm_momentum, - net_type=cfg.net_type, - use_log_update=cfg.use_log_update, - adaptive_momentum=cfg.adaptive_momentum, + theta_norm=self.theta_norm, + norm_momentum=self.norm_momentum, + net_type=self.net_type, + use_log_update=self.use_log_update, + adaptive_momentum=self.adaptive_momentum, ) # ==================== Train/Val Steps ==================== def _unpack_batch(self, batch, phase: str): - """Unpack batch data and convert to tensors. - - Args: - batch: Batch object with theta, logprob, and conditions - phase: "train" or "val" for logging and history - - Returns: - Tuple of (ids, theta, theta_logprob, conditions, u, u_device, conditions_device) - """ ids = batch._ids theta = self._to_tensor(batch[f"{self.theta_key}.value"]) theta_logprob = self._to_tensor(batch[f"{self.theta_key}.log_prob"]) conditions = { - k: self._to_tensor(batch[f"{k}.value"]) for k in self.condition_keys if f"{k}.value" in batch + k: self._to_tensor(batch[f"{k}.value"]) + for k in self.condition_keys if f"{k}.value" in batch } - # Record IDs for history ts = time.time() self.history[f"{phase}_ids"].extend((ts, id) for id in ids.tolist()) log({f"{phase}:theta_logprob_min": theta_logprob.min().item()}) log({f"{phase}:theta_logprob_max": theta_logprob.max().item()}) - # Transform to hypercube space u = self.simulator_instance.inverse(theta) - - # Move to device conditions_device = {k: v.to(self.device) for k, v in conditions.items()} u_device = u.to(self.device) return ids, theta, theta_logprob, conditions, u, u_device, conditions_device def _compute_flow_losses(self, u_device, s, train: bool): - """Compute conditional and marginal flow losses. - - Args: - u_device: Transformed parameters on device - s: Embedded conditions - train: Whether in training mode - - Returns: - Tuple of (loss_cond, loss_marg) tensors - """ if train: self._conditional_flow.train() self._marginal_flow.train() @@ -268,122 +227,92 @@ def _compute_flow_losses(self, u_device, s, train: bool): self._marginal_flow.eval() loss_cond = self._conditional_flow.loss(u_device, s).mean() - # Zero out conditions for marginal flow (detach in train mode to avoid backprop) s_marginal = s.detach() * 0 if train else s * 0 loss_marg = self._marginal_flow.loss(u_device, s_marginal).mean() return loss_cond, loss_marg def train_step(self, batch) -> Dict[str, float]: - """Flow training step with gradient update and optional sample discarding.""" ids, theta, theta_logprob, conditions, u, u_device, conditions_device = \ self._unpack_batch(batch, "train") - # Initialize networks on first batch if not self.networks_initialized: self._initialize_networks(u, conditions) - # Embed conditions s = self._embed(conditions_device, train=True) - # Track theta ranges with torch.no_grad(): self.history["theta_mins"].append(theta.min(dim=0).values.cpu().numpy()) self.history["theta_maxs"].append(theta.max(dim=0).values.cpu().numpy()) - # Forward and backward pass self._optimizer.zero_grad() loss_cond, loss_marg = self._compute_flow_losses(u_device, s, train=True) (loss_cond + loss_marg).backward() self._optimizer.step() - # Discard samples based on log-likelihood ratio - if self.config.inference.discard_samples: + if self.discard_samples: discard_mask = self._compute_discard_mask(theta, theta_logprob, conditions_device) batch.discard(discard_mask) return {"loss": loss_cond.item(), "loss_aux": loss_marg.item()} def val_step(self, batch) -> Dict[str, float]: - """Flow validation step without gradient computation.""" _, theta, theta_logprob, conditions, u, u_device, conditions_device = \ self._unpack_batch(batch, "val") - # Embed conditions (eval mode) s = self._embed(conditions_device, train=False) - # Compute losses without gradients with torch.no_grad(): loss_cond, loss_marg = self._compute_flow_losses(u_device, s, train=False) return {"loss": loss_cond.item(), "loss_aux": loss_marg.item()} def on_epoch_end(self, epoch: int, val_metrics: Dict[str, float]) -> Optional[Dict[str, float]]: - """Update best weights and scheduler.""" val_loss = val_metrics.get("loss", float("inf")) val_aux_loss = val_metrics.get("loss_aux", float("inf")) - # Update best conditional flow if val_loss < self.best_conditional_flow_val_loss: self.best_conditional_flow_val_loss = val_loss self._update_best_weights("conditional") log({"checkpoint:conditional": epoch}) - # Update best marginal flow if val_aux_loss < self.best_marginal_flow_val_loss: self.best_marginal_flow_val_loss = val_aux_loss self._update_best_weights("marginal") log({"checkpoint:marginal": epoch}) - # LR scheduler step self._scheduler.step(val_loss) lr = self._optimizer.param_groups[0]["lr"] log({"lr": lr}) return {"lr": lr} - # ==================== Sampling Methods ==================== + # ==================== Sampling ==================== - def sample_prior(self, num_samples: int, conditions: Optional[Dict] = None) -> dict: - """Sample from the prior distribution.""" + def sample_prior(self, num_samples: int, conditions=None) -> dict: if conditions: raise ValueError("Conditions are not supported for sample_prior.") samples = self.simulator_instance.simulate_batch(num_samples) - # Log probability for uniform prior over hypercube [-bound, bound]^d - bound = self.config.inference.hypercube_bound - log_prob = np.ones(num_samples) * (-np.log(2 * bound) ** self.param_dim) + log_prob = np.ones(num_samples) * (-np.log(2 * self.hypercube_bound) ** self.param_dim) return {'value': samples, 'log_prob': log_prob} - def sample_posterior( - self, - num_samples: int, - conditions: Optional[Dict] = None, - ) -> dict: - """Sample from the posterior distribution q(theta|x).""" - # Fall back to prior if networks not yet initialized (training hasn't started) + def sample_posterior(self, num_samples: int, conditions=None) -> dict: if not self.networks_initialized: return self.sample_prior(num_samples) - samples, logprob = self._importance_sample(num_samples, mode="posterior", conditions=conditions or {}) return {'value': samples.numpy(), 'log_prob': logprob.numpy()} - def sample_proposal( - self, - num_samples: int, - conditions: Optional[Dict] = None, - ) -> dict: - """Sample from the widened proposal distribution for adaptive resampling.""" - if self._total_epochs_trained < self.loop_config.prior_epochs: + def sample_proposal(self, num_samples: int, conditions=None) -> dict: + if self._total_epochs_trained < self.prior_epochs: return self.sample_prior(num_samples) - # Fall back to prior if networks not yet initialized (training hasn't started) if not self.networks_initialized: return self.sample_prior(num_samples) - cfg_inf = self.config.inference conditions = conditions or {} - - if cfg_inf.sample_reference_posterior: - post_samples, _ = self._importance_sample(cfg_inf.reference_samples, mode="posterior", conditions=conditions) + if self.sample_reference_posterior: + post_samples, _ = self._importance_sample( + self.reference_samples, mode="posterior", conditions=conditions + ) mean, std = post_samples.mean(dim=0).cpu(), post_samples.std(dim=0).cpu() log({f"sample_proposal:posterior_mean_{i}": mean[i].item() for i in range(len(mean))}) log({f"sample_proposal:posterior_std_{i}": std[i].item() for i in range(len(std))}) @@ -396,21 +325,11 @@ def sample_proposal( }) return {'value': samples.numpy(), 'log_prob': logprob.numpy()} - def _importance_sample( - self, - num_samples: int, - mode: str = "posterior", - conditions: Dict = {}, - ): - """Sample using importance sampling.""" - cfg_inf = self.config.inference - + def _importance_sample(self, num_samples: int, mode: str = "posterior", conditions: Dict = {}): assert conditions, "Conditions must be provided." - # Move conditions to device (handles both numpy arrays and tensors) conditions = {k: self._to_tensor(v, self.device) for k, v in conditions.items()} - # Use best models if available and configured, otherwise fall back to current - use_best = cfg_inf.use_best_models_during_inference and self._best_conditional_flow is not None + use_best = self.use_best_models and self._best_conditional_flow is not None if use_best: conditional_net = self._best_conditional_flow marginal_net = self._best_marginal_flow @@ -422,42 +341,34 @@ def _importance_sample( s = s.expand(num_samples, *s.shape[1:]) - # Generate proposals from conditional flow conditional_net.eval() - samples_proposals = conditional_net.sample(cfg_inf.num_proposals, s).detach() + samples_proposals = conditional_net.sample(self.num_proposals, s).detach() log({ "importance_sample:proposal_mean": samples_proposals.mean().item(), "importance_sample:proposal_std": samples_proposals.std().item(), }) - # Compute log probs log_prob_cond = conditional_net.log_prob(samples_proposals, s) marginal_net.eval() log_prob_marg = marginal_net.log_prob(samples_proposals, s * 0) - # Mask samples outside hypercube bounds - bound = cfg_inf.hypercube_bound - mask = (samples_proposals < -bound) | (samples_proposals > bound) - mask = mask.any(dim=-1).float() * cfg_inf.out_of_bounds_penalty + mask = (samples_proposals < -self.hypercube_bound) | (samples_proposals > self.hypercube_bound) + mask = mask.any(dim=-1).float() * self.out_of_bounds_penalty - # Compute importance weights if mode == "proposal": - log_weights = -1.0 / (1.0 + cfg_inf.gamma) * log_prob_cond - mask - else: # "posterior" - reweight by marginal + log_weights = -1.0 / (1.0 + self.gamma) * log_prob_cond - mask + else: log_weights = -log_prob_marg - mask - nan_val = cfg_inf.nan_replacement - log_weights = torch.nan_to_num(log_weights, nan=nan_val, neginf=nan_val) + log_weights = torch.nan_to_num(log_weights, nan=self.nan_replacement, neginf=self.nan_replacement) log_weights = log_weights - torch.logsumexp(log_weights, dim=0, keepdim=True) weights = torch.exp(log_weights) - # Effective sample size n_eff = 1 / (weights**2).sum(dim=0).cpu().detach().numpy() log({"importance_sample:n_eff_min": n_eff.min()}) log({"importance_sample:n_eff_max": n_eff.max()}) - # Resample idx = torch.multinomial(weights.T, 1, replacement=True).squeeze(-1) samples = samples_proposals[idx, torch.arange(num_samples), :] samples = self.simulator_instance.forward(samples).cpu() @@ -468,7 +379,6 @@ def _importance_sample( # ==================== Save/Load ==================== def save(self, node_dir: Path) -> None: - """Save Flow state.""" debug(f"Saving: {node_dir}") if not self.networks_initialized: raise RuntimeError("Networks not initialized.") @@ -478,7 +388,6 @@ def save(self, node_dir: Path) -> None: torch.save(self._init_parameters, node_dir / "init_parameters.pth") torch.save(self._total_epochs_trained, node_dir / "total_epochs_trained.pth") - # Save history torch.save(self.history["train_ids"], node_dir / "train_id_history.pth") torch.save(self.history["val_ids"], node_dir / "validation_id_history.pth") torch.save(self.history["theta_mins"], node_dir / "theta_mins_batches.pth") @@ -493,17 +402,12 @@ def save(self, node_dir: Path) -> None: torch.save(self._best_embedding.state_dict(), node_dir / "embedding.pth") def load(self, node_dir: Path) -> None: - """Load Flow state.""" debug(f"Loading: {node_dir}") init_parameters = torch.load(node_dir / "init_parameters.pth") self._initialize_networks(init_parameters[0], init_parameters[1]) - self._best_conditional_flow.load_state_dict( - torch.load(node_dir / "conditional_flow.pth") - ) - self._best_marginal_flow.load_state_dict( - torch.load(node_dir / "marginal_flow.pth") - ) + self._best_conditional_flow.load_state_dict(torch.load(node_dir / "conditional_flow.pth")) + self._best_marginal_flow.load_state_dict(torch.load(node_dir / "marginal_flow.pth")) if (node_dir / "embedding.pth").exists() and self._best_embedding is not None: self._best_embedding.load_state_dict(torch.load(node_dir / "embedding.pth")) @@ -514,17 +418,14 @@ def load(self, node_dir: Path) -> None: # ==================== Private Helpers ==================== def _embed(self, conditions: Dict, train: bool = True, use_best_fit: bool = False): - """Run conditions through embedding network.""" embedding = ( - self._best_embedding - if use_best_fit and self._best_embedding is not None + self._best_embedding if use_best_fit and self._best_embedding is not None else self._embedding ) embedding.train() if train else embedding.eval() return embedding(conditions) def _update_best_weights(self, network_type: str) -> None: - """Copy current network weights to best-fit checkpoint.""" if network_type == "conditional": self._best_conditional_flow.load_state_dict( {k: v.clone() for k, v in self._conditional_flow.state_dict().items()} @@ -537,12 +438,7 @@ def _update_best_weights(self, network_type: str) -> None: {k: v.clone() for k, v in self._marginal_flow.state_dict().items()} ) - def _compute_discard_mask( - self, theta: torch.Tensor, theta_logprob: torch.Tensor, conditions: Dict - ): - """Compute boolean mask of samples to discard based on log-likelihood ratio.""" - cfg_inf = self.config.inference - + def _compute_discard_mask(self, theta, theta_logprob, conditions): u = self.simulator_instance.inverse(theta) s = self._embed(conditions, train=False, use_best_fit=True) @@ -553,4 +449,4 @@ def _compute_discard_mask( self._conditional_flow.eval() log_prob = self._conditional_flow.log_prob(u.unsqueeze(0), s).squeeze(0).cpu() log_ratio = log_prob - theta_logprob.cpu() - return log_ratio < cfg_inf.log_ratio_threshold + return log_ratio < self.log_ratio_threshold diff --git a/falcon/estimators/gaussian.py b/falcon/estimators/gaussian.py index 9080916..ae29a2c 100644 --- a/falcon/estimators/gaussian.py +++ b/falcon/estimators/gaussian.py @@ -1,79 +1,28 @@ -"""Gaussian posterior estimation — Gaussian factory for LossBasedEstimator.""" +"""Gaussian posterior estimation — deprecated factory wrapper. -from typing import List, Optional - -from omegaconf import OmegaConf - -from falcon.priors.product import TransformedPrior -from falcon.estimators.stepwise_base import LossBasedEstimator -from falcon.estimators.gaussian_fullcov import GaussianConfig, GaussianPosterior # noqa: F401 +Use ``falcon.estimators.GaussianFullCov`` directly instead. +""" - -# ==================== Factory Function ==================== +import warnings +from typing import List, Optional def Gaussian( simulator_instance, theta_key: Optional[str] = None, condition_keys: Optional[List[str]] = None, - config: Optional[dict] = None, -) -> LossBasedEstimator: - """Create a LossBasedEstimator with GaussianPosterior. - - This is the main entry point for using Gaussian posterior estimation. - It provides sensible defaults while allowing full customization. +): + """Create a GaussianFullCov estimator (deprecated factory). - Args: - simulator_instance: Prior/simulator instance - theta_key: Key for theta in batch data - condition_keys: Keys for condition data in batch - config: Configuration dict with sections: - - loop: TrainingLoopConfig options - - network: NetworkConfig options - - optimizer: OptimizerConfig options - - inference: InferenceConfig options - - embedding: Embedding configuration with _target_ - - device: Device string (optional) - - Returns: - Configured LossBasedEstimator ready for training - - Example YAML: - estimator: - _target_: falcon.estimators.Gaussian - network: - hidden_dim: 128 - num_layers: 3 - embedding: - _target_: model.E - _input_: [x] + .. deprecated:: + Use :class:`falcon.estimators.GaussianFullCov` directly. """ - # Check simulator supports transformation interface - if not isinstance(simulator_instance, TransformedPrior): - raise TypeError( - f"Gaussian requires a TransformedPrior (e.g., Product), " - f"got {type(simulator_instance).__name__}. " - f"The simulator must support forward/inverse with mode='standard_normal'." - ) - - # Merge with defaults - schema = OmegaConf.structured(GaussianConfig) - cfg = OmegaConf.merge(schema, config or {}) - - # Extract configs as plain dicts - embedding_config = OmegaConf.to_container(cfg.embedding, resolve=True) - posterior_config = OmegaConf.to_container(cfg.network, resolve=True) - - return LossBasedEstimator( - simulator_instance=simulator_instance, - posterior_cls=GaussianPosterior, - embedding_config=embedding_config, - loop_config=cfg.loop, - optimizer_config=cfg.optimizer, - inference_config=cfg.inference, - posterior_config=posterior_config, - theta_key=theta_key, - condition_keys=condition_keys, - device=cfg.device, - latent_mode="standard_normal", # GaussianPosterior assumes N(0,I) prior + warnings.warn( + "falcon.estimators.Gaussian is deprecated; use GaussianFullCov directly.", + DeprecationWarning, + stacklevel=2, ) + from falcon.estimators.gaussian_fullcov import GaussianFullCov + est = GaussianFullCov() + est.setup(simulator_instance, theta_key, condition_keys) + return est diff --git a/falcon/estimators/gaussian_fullcov.py b/falcon/estimators/gaussian_fullcov.py index 945930c..d4c52ba 100644 --- a/falcon/estimators/gaussian_fullcov.py +++ b/falcon/estimators/gaussian_fullcov.py @@ -2,72 +2,25 @@ import copy import time -from dataclasses import dataclass, field from pathlib import Path -from typing import Any, Dict, List, Optional +from typing import Dict, List, Optional import numpy as np import torch import torch.nn as nn -from omegaconf import OmegaConf from torch.optim import AdamW from torch.optim.lr_scheduler import ReduceLROnPlateau from falcon.priors.product import TransformedPrior from falcon.estimators.networks import build_mlp -from falcon.estimators.stepwise_base import StepwiseEstimator, TrainingLoopConfig +from falcon.estimators.stepwise_base import StepwiseEstimator from falcon.core.logger import log, debug -# ==================== Configuration Dataclasses ==================== +# ==================== _GaussianPosterior Module ==================== -@dataclass -class NetworkConfig: - """Configuration for GaussianPosterior network.""" - - hidden_dim: int = 128 - num_layers: int = 3 - momentum: float = 0.01 - min_var: float = 1e-20 - eig_update_freq: int = 1 - - -@dataclass -class OptimizerConfig: - """Optimizer and scheduler parameters.""" - - lr: float = 1e-2 - betas: tuple = (0.9, 0.9) # Lower beta2 for dynamic SBI setting - lr_decay_factor: float = 1.0 # 1.0 = no LR decay (scheduler disabled) - scheduler_patience: int = 8 - - -@dataclass -class InferenceConfig: - """Inference and sampling parameters.""" - - gamma: float = 0.5 - discard_samples: bool = False - log_ratio_threshold: float = -20.0 - - -@dataclass -class GaussianConfig: - """Top-level Gaussian estimator configuration.""" - - loop: TrainingLoopConfig = field(default_factory=TrainingLoopConfig) - network: NetworkConfig = field(default_factory=NetworkConfig) - optimizer: OptimizerConfig = field(default_factory=OptimizerConfig) - inference: InferenceConfig = field(default_factory=InferenceConfig) - embedding: Optional[Any] = None - device: Optional[str] = None - - -# ==================== GaussianPosterior Module ==================== - - -class GaussianPosterior(nn.Module): +class _GaussianPosterior(nn.Module): """Full covariance Gaussian posterior with eigenvalue-based operations. Implements the Posterior contract: @@ -260,21 +213,90 @@ def _update_eigendecomp(self) -> None: class GaussianFullCov(StepwiseEstimator): """Full-covariance Gaussian posterior estimator for TransformedPrior simulators. - Works in the standard-normal latent space defined by the simulator's - forward/inverse transforms. Samples are mapped back to parameter space - after generation. - - Gamma is resolved once at initialisation: - - proposal sampling uses _proposal_gamma (widens the distribution) - - posterior sampling uses _posterior_gamma (corrects for proposal bias) + Works in the standard-normal latent space; samples are mapped back to + parameter space after generation. + + Args: + max_epochs: Maximum training epochs. + lr: Learning rate. + gamma: Proposal tempering coefficient. + embedding: Embedding config dict or ``None``. + device: Device string; auto-detected if ``None``. + batch_size: Mini-batch size. + early_stop_patience: Epochs without improvement before stopping. + prior_epochs: Epochs to sample from prior before switching to proposal. + cache_on_device: Cache training data on the estimator's device. + cache_sync_every: Resync buffer cache every N epochs (0 = every epoch). + max_cache_samples: Cap on cached training samples (0 = all). + hidden_dim: MLP hidden layer width. + num_layers: MLP depth. + momentum: EMA momentum for running statistics. + min_var: Minimum variance for numerical stability. + eig_update_freq: Eigendecomposition update frequency. + betas: AdamW beta coefficients. + lr_decay_factor: LR decay factor (1.0 = no decay). + lr_patience: Plateau patience before LR decay. + discard_samples: Discard low log-ratio training samples. + log_ratio_threshold: Log-ratio cutoff for discarding. """ def __init__( + self, + *, + # Most commonly changed + max_epochs: int = 100, + lr: float = 1e-2, + gamma: float = 0.5, + embedding=None, + device=None, + # Training loop + batch_size: int = 128, + early_stop_patience: int = 16, + prior_epochs: int = 0, + cache_on_device: bool = False, + cache_sync_every: int = 0, + max_cache_samples: int = 0, + # Network architecture + hidden_dim: int = 128, + num_layers: int = 3, + momentum: float = 0.01, + min_var: float = 1e-20, + eig_update_freq: int = 1, + # Optimizer + betas: tuple = (0.9, 0.9), + lr_decay_factor: float = 1.0, + lr_patience: int = 8, + # Inference / sampling + discard_samples: bool = False, + log_ratio_threshold: float = -20.0, + ): + self.max_epochs = max_epochs + self.lr = lr + self.gamma = gamma + self.embedding = embedding + self.device = device + self.batch_size = batch_size + self.early_stop_patience = early_stop_patience + self.prior_epochs = prior_epochs + self.cache_on_device = cache_on_device + self.cache_sync_every = cache_sync_every + self.max_cache_samples = max_cache_samples + self.hidden_dim = hidden_dim + self.num_layers = num_layers + self.momentum = momentum + self.min_var = min_var + self.eig_update_freq = eig_update_freq + self.betas = betas + self.lr_decay_factor = lr_decay_factor + self.lr_patience = lr_patience + self.discard_samples = discard_samples + self.log_ratio_threshold = log_ratio_threshold + + def setup( self, simulator_instance, theta_key: Optional[str] = None, condition_keys: Optional[List[str]] = None, - config: Optional[dict] = None, ): if not isinstance(simulator_instance, TransformedPrior): raise TypeError( @@ -282,30 +304,20 @@ def __init__( f"got {type(simulator_instance).__name__}." ) - schema = OmegaConf.structured(GaussianConfig) - cfg = OmegaConf.merge(schema, config or {}) - - super().__init__( - simulator_instance=simulator_instance, - loop_config=cfg.loop, - theta_key=theta_key, - condition_keys=condition_keys, - ) - - self.cfg = cfg + super().setup(simulator_instance, theta_key, condition_keys) - if cfg.device: - self.device = torch.device(cfg.device) + if self.device: + self.device = torch.device(self.device) else: self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu") debug(f"Auto-detected device: {self.device}") - # Resolve gamma once: proposal widens, posterior corrects back - gamma = cfg.inference.gamma - self._proposal_gamma = gamma - self._posterior_gamma = (1.0 + gamma) / gamma if gamma is not None else None + self._proposal_gamma = self.gamma + self._posterior_gamma = ( + (1.0 + self.gamma) / self.gamma + if self.gamma is not None else None + ) - # Model state (initialised lazily on first batch) self._model: Optional[nn.Module] = None self._best_model: Optional[nn.Module] = None self._best_loss: float = float("inf") @@ -314,12 +326,21 @@ def __init__( self._optimizer = None self._scheduler = None + # ==================== Optimizer ==================== + + def _build_optimizer(self): + self._optimizer = AdamW(self._model.parameters(), lr=self.lr, betas=self.betas) + self._scheduler = ( + ReduceLROnPlateau( + self._optimizer, mode="min", + factor=self.lr_decay_factor, patience=self.lr_patience, + ) + if self.lr_decay_factor < 1.0 else None + ) + # ==================== Model Building ==================== def _build_model(self, batch) -> nn.Module: - from falcon.estimators.embedded_posterior import EmbeddedPosterior - from falcon.embeddings import instantiate_embedding - theta = self._to_tensor(batch[f"{self.theta_key}.value"]) conditions = { k: self._to_tensor(batch[f"{k}.value"]) @@ -335,18 +356,20 @@ def _create_model(self, theta: torch.Tensor, conditions: Dict[str, torch.Tensor] theta_latent = self.simulator_instance.inverse(theta, mode="standard_normal") - embedding_config = OmegaConf.to_container(self.cfg.embedding, resolve=True) - embedding = instantiate_embedding(embedding_config).to(self.device) + embedding = instantiate_embedding(self.embedding).to(self.device) embedding.eval() with torch.no_grad(): conditions_device = {k: v.to(self.device) for k, v in conditions.items()} embedded = embedding(conditions_device) - network_config = OmegaConf.to_container(self.cfg.network, resolve=True) - posterior = GaussianPosterior( + posterior = _GaussianPosterior( param_dim=theta_latent.shape[1], condition_dim=embedded.shape[1], - **network_config, + hidden_dim=self.hidden_dim, + num_layers=self.num_layers, + momentum=self.momentum, + min_var=self.min_var, + eig_update_freq=self.eig_update_freq, ).to(self.device) debug(f"GaussianFullCov model built: param_dim={theta_latent.shape[1]}") @@ -359,17 +382,7 @@ def _initialize_model(self, batch) -> None: {k: v.clone() for k, v in self._model.state_dict().items()} ) - opt_cfg = self.cfg.optimizer - self._optimizer = AdamW(self._model.parameters(), lr=opt_cfg.lr, betas=opt_cfg.betas) - self._scheduler = ( - ReduceLROnPlateau( - self._optimizer, - mode="min", - factor=opt_cfg.lr_decay_factor, - patience=opt_cfg.scheduler_patience, - ) - if opt_cfg.lr_decay_factor < 1.0 else None - ) + self._build_optimizer() self.networks_initialized = True debug("GaussianFullCov initialised.") @@ -390,11 +403,11 @@ def _compute_loss(self, batch): loss = self._model.loss(theta_latent, conditions) - if self.cfg.inference.discard_samples: + if self.discard_samples: with torch.no_grad(): self._model.eval() log_prob = self._model.log_prob(theta_latent, conditions).cpu() - discard_mask = (log_prob - theta_logprob) < self.cfg.inference.log_ratio_threshold + discard_mask = (log_prob - theta_logprob) < self.log_ratio_threshold batch.discard(discard_mask) return loss, {"loss": loss.item()} @@ -472,7 +485,7 @@ def sample_posterior(self, num_samples: int, conditions=None) -> dict: return self._sample(num_samples, conditions, gamma=self._posterior_gamma) def sample_proposal(self, num_samples: int, conditions=None) -> dict: - if self._total_epochs_trained < self.loop_config.prior_epochs: + if self._total_epochs_trained < self.prior_epochs: return self.sample_prior(num_samples) result = self._sample(num_samples, conditions, gamma=self._proposal_gamma) log({ @@ -513,17 +526,7 @@ def load(self, node_dir) -> None: self._model = self._create_model(self._init_theta, self._init_conditions) self._best_model = copy.deepcopy(self._model) - opt_cfg = self.cfg.optimizer - self._optimizer = AdamW(self._model.parameters(), lr=opt_cfg.lr, betas=opt_cfg.betas) - self._scheduler = ( - ReduceLROnPlateau( - self._optimizer, - mode="min", - factor=opt_cfg.lr_decay_factor, - patience=opt_cfg.scheduler_patience, - ) - if opt_cfg.lr_decay_factor < 1.0 else None - ) + self._build_optimizer() self.networks_initialized = True tep = node_dir / "total_epochs_trained.pth" diff --git a/falcon/estimators/stepwise_base.py b/falcon/estimators/stepwise_base.py index aead236..435d811 100644 --- a/falcon/estimators/stepwise_base.py +++ b/falcon/estimators/stepwise_base.py @@ -45,38 +45,20 @@ class StepwiseEstimator(BaseEstimator): - save/load """ - def __init__( + def setup( self, simulator_instance, - loop_config: TrainingLoopConfig, theta_key: Optional[str] = None, condition_keys: Optional[List[str]] = None, ): - """ - Initialize the stepwise estimator. - - Args: - simulator_instance: Prior/simulator instance - loop_config: Training loop configuration - theta_key: Key for theta in batch data - condition_keys: Keys for condition data in batch - """ + """Initialise runtime state shared by all stepwise estimators.""" self.simulator_instance = simulator_instance - self.loop_config = loop_config self.param_dim = simulator_instance.param_dim - self.cache_on_device = loop_config.cache_on_device - - # Key configuration for Batch access self.theta_key = theta_key self.condition_keys = condition_keys or [] - self._terminated = False self._total_epochs_trained: int = 0 - - # Networks initialized flag (managed by subclass) self.networks_initialized = False - - # History tracking self.history = { "train_ids": [], "val_ids": [], @@ -155,22 +137,16 @@ def on_epoch_end(self, epoch: int, val_metrics: Dict[str, float]) -> Optional[Di # ==================== Concrete Methods ==================== async def train(self, buffer) -> None: - """ - Main training loop with epochs and early stopping. - - Args: - buffer: BufferView providing access to training/validation data - """ - cfg = self.loop_config + """Main training loop with epochs and early stopping.""" keys = [f"{self.theta_key}.value", f"{self.theta_key}.log_prob", *[f"{k}.value" for k in self.condition_keys]] - await self._train(buffer, cfg, keys) + await self._train(buffer, keys) - async def _train(self, buffer, cfg, keys) -> None: + async def _train(self, buffer, keys) -> None: """Epoch-based training with CPU-cached dataloader.""" - sync_every = cfg.cache_sync_every if cfg.cache_sync_every > 0 else 1 + sync_every = self.cache_sync_every if self.cache_sync_every > 0 else 1 - train_cache = buffer.cached_loader(keys, max_cache_samples=cfg.max_cache_samples) + train_cache = buffer.cached_loader(keys, max_cache_samples=self.max_cache_samples) val_cache = buffer.cached_val_loader(keys, max_cache_samples=0) train_cache.sync() @@ -181,7 +157,7 @@ async def _train(self, buffer, cfg, keys) -> None: total_steps = 0 t0 = time.perf_counter() - for epoch in range(cfg.max_epochs): + for epoch in range(self.max_epochs): log({"epoch": self._total_epochs_trained + 1}) # Periodic incremental sync @@ -190,12 +166,12 @@ async def _train(self, buffer, cfg, keys) -> None: val_cache.sync() # === Training phase === - steps_per_epoch = max(1, train_cache.count // cfg.batch_size) + steps_per_epoch = max(1, train_cache.count // self.batch_size) train_metrics_sum = {} num_train_batches = 0 for step in range(steps_per_epoch): - batch = train_cache.sample_batch(cfg.batch_size) + batch = train_cache.sample_batch(self.batch_size) metrics = self.train_step(batch) for k, v in metrics.items(): @@ -215,10 +191,10 @@ async def _train(self, buffer, cfg, keys) -> None: # === Validation phase === val_metrics_sum = {} num_val_samples = 0 - val_steps = max(1, val_cache.count // cfg.batch_size) + val_steps = max(1, val_cache.count // self.batch_size) for step in range(val_steps): - batch = val_cache.sample_batch(cfg.batch_size) + batch = val_cache.sample_batch(self.batch_size) metrics = self.val_step(batch) bs = len(batch) @@ -249,7 +225,7 @@ async def _train(self, buffer, cfg, keys) -> None: train_loss = train_metrics_avg.get("loss", float("nan")) val_loss = val_metrics_avg.get("loss", float("inf")) summary = ( - f"Epoch {self._total_epochs_trained + 1}/{cfg.max_epochs}" + f"Epoch {self._total_epochs_trained + 1}/{self.max_epochs}" f" | steps={total_steps}" ) if n_sims is not None: @@ -274,7 +250,7 @@ async def _train(self, buffer, cfg, keys) -> None: ) self._total_epochs_trained += 1 - if epochs_no_improve >= cfg.early_stop_patience: + if epochs_no_improve >= self.early_stop_patience: info("Early stopping triggered.") break @@ -343,12 +319,26 @@ def __init__( "standard_normal": transform to N(0,I) via simulator.inverse/forward "hypercube": transform to hypercube via simulator.inverse/forward """ - super().__init__( - simulator_instance=simulator_instance, - loop_config=loop_config, - theta_key=theta_key, - condition_keys=condition_keys, - ) + self.max_epochs = loop_config.max_epochs + self.batch_size = loop_config.batch_size + self.early_stop_patience = loop_config.early_stop_patience + self.cache_sync_every = loop_config.cache_sync_every + self.max_cache_samples = loop_config.max_cache_samples + self.cache_on_device = loop_config.cache_on_device + self.prior_epochs = loop_config.prior_epochs + + # Runtime state normally set by StepwiseEstimator.setup() + self.simulator_instance = simulator_instance + self.param_dim = simulator_instance.param_dim + self.theta_key = theta_key + self.condition_keys = condition_keys or [] + self._terminated = False + self._total_epochs_trained: int = 0 + self.networks_initialized = False + self.history = { + "train_ids": [], "val_ids": [], "epochs": [], + "train_loss": [], "val_loss": [], "n_samples": [], "elapsed_min": [], + } self.posterior_cls = posterior_cls self.embedding_config = embedding_config @@ -357,26 +347,26 @@ def __init__( self.inference_config = inference_config self.latent_mode = latent_mode - # Device setup if device: self.device = torch.device(device) else: self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu") debug(f"Auto-detected device: {self.device}") - # Model (initialized lazily) self._model: Optional[nn.Module] = None self._best_model: Optional[nn.Module] = None self._best_loss: float = float("inf") - # Stored tensors from first batch (for model rebuild on load) self._init_theta: Optional[torch.Tensor] = None self._init_conditions: Optional[Dict[str, torch.Tensor]] = None - # Optimizer/scheduler (initialized lazily) self._optimizer: Optional[AdamW] = None self._scheduler: Optional[ReduceLROnPlateau] = None + def setup(self, simulator_instance=None, theta_key=None, condition_keys=None): + """No-op: LossBasedEstimator is fully initialised in __init__ (deprecated factory pattern).""" + pass + # ==================== Model Creation ==================== def _build_model(self, batch) -> nn.Module: @@ -471,29 +461,23 @@ def _update_best_model(self) -> None: # ==================== Training Implementation ==================== - def _initialize_model(self, batch) -> None: - """Initialize model, best model, optimizer, and scheduler.""" - debug("Initializing model...") - - # Build model - self._model = self._build_model(batch) - - # Clone for best model - self._best_model = self._clone_model(self._model) - - # Setup optimizer and scheduler + def _build_optimizer(self): cfg = self.optimizer_config self._optimizer = AdamW(self._model.parameters(), lr=cfg.lr, betas=cfg.betas) self._scheduler = ( ReduceLROnPlateau( - self._optimizer, - mode="min", - factor=cfg.lr_decay_factor, - patience=cfg.scheduler_patience, + self._optimizer, mode="min", + factor=cfg.lr_decay_factor, patience=cfg.scheduler_patience, ) if cfg.lr_decay_factor < 1.0 else None ) + def _initialize_model(self, batch) -> None: + """Initialize model, best model, optimizer, and scheduler.""" + debug("Initializing model...") + self._model = self._build_model(batch) + self._best_model = self._clone_model(self._model) + self._build_optimizer() self.networks_initialized = True debug("Model initialized.") @@ -592,14 +576,14 @@ def _sample(self, num_samples: int, conditions: Optional[Dict], gamma: Optional[ def sample_posterior(self, num_samples: int, conditions: Optional[Dict] = None) -> dict: """Sample from the posterior distribution q(theta|x).""" - # TODO: refactor — this corrects for the bias from training on proposal data. + # Corrects for the bias from training on proposal data. gamma = self.inference_config.gamma gamma_correct = (1 + gamma) / gamma if gamma is not None else None return self._sample(num_samples, conditions, gamma=gamma_correct) def sample_proposal(self, num_samples: int, conditions: Optional[Dict] = None) -> dict: """Sample from widened proposal distribution for adaptive resampling.""" - if self._total_epochs_trained < self.loop_config.prior_epochs: + if self._total_epochs_trained < self.prior_epochs: return self.sample_prior(num_samples) result = self._sample(num_samples, conditions, gamma=self.inference_config.gamma) log({ @@ -647,19 +631,7 @@ def load(self, node_dir) -> None: self._model = self._create_model(self._init_theta, self._init_conditions) self._best_model = self._clone_model(self._model) - # Setup optimizer and scheduler - cfg = self.optimizer_config - self._optimizer = AdamW(self._model.parameters(), lr=cfg.lr, betas=cfg.betas) - self._scheduler = ( - ReduceLROnPlateau( - self._optimizer, - mode="min", - factor=cfg.lr_decay_factor, - patience=cfg.scheduler_patience, - ) - if cfg.lr_decay_factor < 1.0 else None - ) - + self._build_optimizer() self.networks_initialized = True _tep = node_dir / "total_epochs_trained.pth" diff --git a/tests/test_examples_smoke.py b/tests/test_examples_smoke.py index 34b7482..f2fc401 100644 --- a/tests/test_examples_smoke.py +++ b/tests/test_examples_smoke.py @@ -18,22 +18,22 @@ # Each tuple: (example_dir_name, config_name, epoch_overrides) EXAMPLE_CONFIGS = [ # 01_minimal: single estimator 'z' - ("01_minimal", "config.yml", ["graph.z.estimator.loop.max_epochs=2"]), + ("01_minimal", "config.yml", ["graph.z.estimator.max_epochs=2"]), # 02_bimodal: single estimator 'z', using config_regular (needs GPU override) - ("02_bimodal", "config_regular.yml", ["graph.z.estimator.loop.max_epochs=2", "graph.z.ray.num_gpus=0"]), + ("02_bimodal", "config_regular.yml", ["graph.z.estimator.max_epochs=2", "graph.z.ray.num_gpus=0"]), # 03_composite: two ResNet18 + Ray actors exceed CI runner memory pytest.param( "03_composite", "config.yml", - ["graph.z1.estimator.loop.max_epochs=2", "graph.z2.estimator.loop.max_epochs=2", + ["graph.z1.estimator.max_epochs=2", "graph.z2.estimator.max_epochs=2", "graph.z1.ray.num_gpus=0", "graph.z2.ray.num_gpus=0"], marks=_skip_ci, ), # 04_gaussian: SNPE_gaussian with exponential forward model (needs GPU override) - ("04_gaussian", "config.yml", ["graph.z.estimator.loop.max_epochs=2", "graph.z.ray.num_gpus=0"]), + ("04_gaussian", "config.yml", ["graph.z.estimator.max_epochs=2", "graph.z.ray.num_gpus=0"]), # 05_linear_regression: requires GPU pytest.param( "05_linear_regression", "config.yml", - ["graph.theta.estimator.loop.max_epochs=2", "graph.theta.ray.num_gpus=0"], + ["graph.theta.estimator.max_epochs=2", "graph.theta.ray.num_gpus=0"], marks=_skip_ci, ), ]