From 3e4b425160729a3fd8df13f8b17a93a1ba292d72 Mon Sep 17 00:00:00 2001 From: Rebecca Kohlhaas <rebecca.kohlhaas@iws.uni-stuttgart.de> Date: Fri, 19 Apr 2024 19:34:42 +0000 Subject: [PATCH] Revert "Some cleanup" This reverts commit acf483a1c6473affa69a0f7baa2e896c6bfa265f --- .../inspectionProfiles/profiles_settings.xml | 1 - .idea/misc.xml | 3 - .../diagrams/.$Structure_BayesInf.drawio.dtmp | 964 +++++++ docs/diagrams/Structure_BayesInf.drawio | 83 +- examples/OHagan-function/example_OHagan.py | 2 +- .../bayesvalidrox/__init__.py | 25 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 795 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 941 bytes .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 860 bytes .../bayesvalidrox/bayes_inference/__init__.py | 9 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 303 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 382 bytes .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 368 bytes .../bayes_inference.cpython-310.pyc | Bin 0 -> 31276 bytes .../bayes_inference.cpython-311.pyc | Bin 0 -> 60773 bytes .../bayes_inference.cpython-39.pyc | Bin 0 -> 31419 bytes .../bayes_model_comparison.cpython-310.pyc | Bin 0 -> 15645 bytes .../bayes_model_comparison.cpython-311.pyc | Bin 0 -> 27765 bytes .../bayes_model_comparison.cpython-39.pyc | Bin 0 -> 15716 bytes .../__pycache__/discrepancy.cpython-310.pyc | Bin 0 -> 3806 bytes .../__pycache__/discrepancy.cpython-311.pyc | Bin 0 -> 4963 bytes .../__pycache__/discrepancy.cpython-39.pyc | Bin 0 -> 3869 bytes .../__pycache__/mcmc.cpython-310.pyc | Bin 0 -> 18924 bytes .../__pycache__/mcmc.cpython-311.pyc | Bin 0 -> 35891 bytes .../__pycache__/mcmc.cpython-39.pyc | Bin 0 -> 18959 bytes .../bayes_inference/bayes_inference.py | 1530 +++++++++++ .../bayes_inference/bayes_model_comparison.py | 680 +++++ .../bayes_inference/discrepancy.py | 118 + .../bayesvalidrox/bayes_inference/mcmc.py | 909 +++++++ .../bayesvalidrox/bayesvalidrox.mplstyle | 16 + .../bayesvalidrox/desktop.ini | 2 + .../bayesvalidrox/post_processing/__init__.py | 7 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 261 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 323 bytes .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 326 bytes .../post_processing.cpython-310.pyc | Bin 0 -> 28679 bytes .../post_processing.cpython-311.pyc | Bin 0 -> 65551 bytes .../post_processing.cpython-39.pyc | Bin 0 -> 28771 bytes .../post_processing/post_processing.py | 1491 +++++++++++ .../bayesvalidrox/pylink/__init__.py | 7 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 247 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 309 bytes .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 312 bytes .../pylink/__pycache__/pylink.cpython-310.pyc | Bin 0 -> 18654 bytes .../pylink/__pycache__/pylink.cpython-311.pyc | Bin 0 -> 35238 bytes .../pylink/__pycache__/pylink.cpython-39.pyc | Bin 0 -> 18646 bytes .../bayesvalidrox/pylink/pylink.py | 807 ++++++ .../surrogate_models/__init__.py | 7 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 258 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 320 bytes .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 323 bytes .../__pycache__/adaptPlot.cpython-311.pyc | Bin 0 -> 4921 bytes .../apoly_construction.cpython-310.pyc | Bin 0 -> 2815 bytes .../apoly_construction.cpython-311.pyc | Bin 0 -> 5201 bytes .../apoly_construction.cpython-39.pyc | Bin 0 -> 2886 bytes .../__pycache__/bayes_linear.cpython-310.pyc | Bin 0 -> 14412 bytes .../__pycache__/bayes_linear.cpython-311.pyc | Bin 0 -> 21679 bytes .../__pycache__/bayes_linear.cpython-39.pyc | Bin 0 -> 14506 bytes .../__pycache__/engine.cpython-311.pyc | Bin 0 -> 85430 bytes .../__pycache__/eval_rec_rule.cpython-310.pyc | Bin 0 -> 5560 bytes .../__pycache__/eval_rec_rule.cpython-311.pyc | Bin 0 -> 8182 bytes .../__pycache__/eval_rec_rule.cpython-39.pyc | Bin 0 -> 5648 bytes .../__pycache__/exp_designs.cpython-310.pyc | Bin 0 -> 17477 bytes .../__pycache__/exp_designs.cpython-311.pyc | Bin 0 -> 19243 bytes .../__pycache__/exp_designs.cpython-39.pyc | Bin 0 -> 17597 bytes .../__pycache__/exp_designs_.cpython-311.pyc | Bin 0 -> 20552 bytes .../__pycache__/exploration.cpython-310.pyc | Bin 0 -> 8154 bytes .../__pycache__/exploration.cpython-311.pyc | Bin 0 -> 12450 bytes .../__pycache__/exploration.cpython-39.pyc | Bin 0 -> 8190 bytes .../__pycache__/glexindex.cpython-310.pyc | Bin 0 -> 7185 bytes .../__pycache__/glexindex.cpython-311.pyc | Bin 0 -> 7925 bytes .../__pycache__/glexindex.cpython-39.pyc | Bin 0 -> 7232 bytes .../__pycache__/input_space.cpython-311.pyc | Bin 0 -> 16827 bytes .../__pycache__/inputs.cpython-310.pyc | Bin 0 -> 2413 bytes .../__pycache__/inputs.cpython-311.pyc | Bin 0 -> 2897 bytes .../__pycache__/inputs.cpython-39.pyc | Bin 0 -> 2474 bytes .../__pycache__/loss_function.cpython-311.pyc | Bin 0 -> 13488 bytes .../meta_model_engine.cpython-310.pyc | Bin 0 -> 42392 bytes .../meta_model_engine.cpython-311.pyc | Bin 0 -> 87269 bytes .../meta_model_engine.cpython-39.pyc | Bin 0 -> 42705 bytes ...rthogonal_matching_pursuit.cpython-310.pyc | Bin 0 -> 8915 bytes ...rthogonal_matching_pursuit.cpython-311.pyc | Bin 0 -> 14805 bytes ...orthogonal_matching_pursuit.cpython-39.pyc | Bin 0 -> 8930 bytes .../__pycache__/reg_fast_ard.cpython-310.pyc | Bin 0 -> 11629 bytes .../__pycache__/reg_fast_ard.cpython-311.pyc | Bin 0 -> 19760 bytes .../__pycache__/reg_fast_ard.cpython-39.pyc | Bin 0 -> 11717 bytes .../reg_fast_laplace.cpython-310.pyc | Bin 0 -> 9509 bytes .../reg_fast_laplace.cpython-311.pyc | Bin 0 -> 19013 bytes .../reg_fast_laplace.cpython-39.pyc | Bin 0 -> 9581 bytes .../sequential_design.cpython-311.pyc | Bin 0 -> 87535 bytes .../surrogate_models.cpython-310.pyc | Bin 0 -> 35103 bytes .../surrogate_models.cpython-311.pyc | Bin 0 -> 64796 bytes .../surrogate_models.cpython-39.pyc | Bin 0 -> 35188 bytes .../__pycache__/wrapper.cpython-311.pyc | Bin 0 -> 10433 bytes .../surrogate_models/adaptPlot.py | 109 + .../surrogate_models/apoly_construction.py | 124 + .../surrogate_models/bayes_linear.py | 523 ++++ .../surrogate_models/desktop.ini | 2 + .../bayesvalidrox/surrogate_models/engine.py | 2233 +++++++++++++++++ .../surrogate_models/eval_rec_rule.py | 197 ++ .../surrogate_models/exp_designs.py | 479 ++++ .../surrogate_models/exploration.py | 367 +++ .../surrogate_models/glexindex.py | 161 ++ .../surrogate_models/input_space.py | 398 +++ .../bayesvalidrox/surrogate_models/inputs.py | 79 + .../surrogate_models/meta_model_engine.py | 2195 ++++++++++++++++ .../orthogonal_matching_pursuit.py | 366 +++ .../surrogate_models/reg_fast_ard.py | 475 ++++ .../surrogate_models/reg_fast_laplace.py | 452 ++++ .../surrogate_models/sequential_design.py | 2187 ++++++++++++++++ .../surrogate_models/surrogate_models.py | 1581 ++++++++++++ .../example_analytical_function.py | 2 +- examples/borehole/example_borehole.py | 2 +- examples/ishigami/example_ishigami.py | 2 +- .../example_model_comparison.py | 5 +- examples/pollution/example_pollution.py | 2 +- src/bayesvalidrox/surrogate_models/engine.py | 2 +- .../surrogate_models/exp_designs.py | 21 +- .../surrogate_models/input_space.py | 196 +- .../surrogate_models/sequential_design.py | 2 +- .../surrogate_models/surrogate_models.py | 619 ++--- tests/itest_MetaModel.py | 92 +- 122 files changed, 19001 insertions(+), 533 deletions(-) create mode 100644 docs/diagrams/.$Structure_BayesInf.drawio.dtmp create mode 100644 examples/analytical-function/bayesvalidrox/__init__.py create mode 100644 examples/analytical-function/bayesvalidrox/__pycache__/__init__.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/__pycache__/__init__.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/__pycache__/__init__.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/bayes_inference/__init__.py create mode 100644 examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/__init__.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/__init__.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/__init__.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/bayes_inference.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/bayes_inference.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/bayes_inference.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/bayes_model_comparison.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/bayes_model_comparison.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/bayes_model_comparison.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/discrepancy.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/discrepancy.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/discrepancy.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/mcmc.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/mcmc.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/mcmc.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/bayes_inference/bayes_inference.py create mode 100644 examples/analytical-function/bayesvalidrox/bayes_inference/bayes_model_comparison.py create mode 100644 examples/analytical-function/bayesvalidrox/bayes_inference/discrepancy.py create mode 100644 examples/analytical-function/bayesvalidrox/bayes_inference/mcmc.py create mode 100644 examples/analytical-function/bayesvalidrox/bayesvalidrox.mplstyle create mode 100644 examples/analytical-function/bayesvalidrox/desktop.ini create mode 100644 examples/analytical-function/bayesvalidrox/post_processing/__init__.py create mode 100644 examples/analytical-function/bayesvalidrox/post_processing/__pycache__/__init__.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/post_processing/__pycache__/__init__.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/post_processing/__pycache__/__init__.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/post_processing/__pycache__/post_processing.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/post_processing/__pycache__/post_processing.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/post_processing/__pycache__/post_processing.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/post_processing/post_processing.py create mode 100644 examples/analytical-function/bayesvalidrox/pylink/__init__.py create mode 100644 examples/analytical-function/bayesvalidrox/pylink/__pycache__/__init__.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/pylink/__pycache__/__init__.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/pylink/__pycache__/__init__.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/pylink/__pycache__/pylink.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/pylink/__pycache__/pylink.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/pylink/__pycache__/pylink.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/pylink/pylink.py create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__init__.py create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/__init__.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/__init__.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/__init__.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/adaptPlot.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/apoly_construction.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/apoly_construction.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/apoly_construction.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/bayes_linear.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/bayes_linear.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/bayes_linear.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/engine.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/eval_rec_rule.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/eval_rec_rule.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/eval_rec_rule.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/exp_designs.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/exp_designs.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/exp_designs.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/exp_designs_.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/exploration.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/exploration.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/exploration.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/glexindex.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/glexindex.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/glexindex.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/input_space.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/inputs.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/inputs.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/inputs.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/loss_function.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/meta_model_engine.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/meta_model_engine.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/meta_model_engine.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/orthogonal_matching_pursuit.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/orthogonal_matching_pursuit.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/orthogonal_matching_pursuit.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/reg_fast_ard.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/reg_fast_ard.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/reg_fast_ard.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/reg_fast_laplace.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/reg_fast_laplace.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/reg_fast_laplace.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/sequential_design.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/surrogate_models.cpython-310.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/surrogate_models.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/surrogate_models.cpython-39.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/wrapper.cpython-311.pyc create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/adaptPlot.py create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/apoly_construction.py create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/bayes_linear.py create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/desktop.ini create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/engine.py create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/eval_rec_rule.py create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/exp_designs.py create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/exploration.py create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/glexindex.py create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/input_space.py create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/inputs.py create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/meta_model_engine.py create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/orthogonal_matching_pursuit.py create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/reg_fast_ard.py create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/reg_fast_laplace.py create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/sequential_design.py create mode 100644 examples/analytical-function/bayesvalidrox/surrogate_models/surrogate_models.py diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml index dd4c951ef..105ce2da2 100644 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -1,6 +1,5 @@ <component name="InspectionProjectProfileManager"> <settings> - <option name="PROJECT_PROFILE" value="Default" /> <option name="USE_PROJECT_PROFILE" value="false" /> <version value="1.0" /> </settings> diff --git a/.idea/misc.xml b/.idea/misc.xml index a6218fed0..a971a2c93 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,7 +1,4 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> - <component name="Black"> - <option name="sdkName" value="Python 3.11" /> - </component> <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11" project-jdk-type="Python SDK" /> </project> \ No newline at end of file diff --git a/docs/diagrams/.$Structure_BayesInf.drawio.dtmp b/docs/diagrams/.$Structure_BayesInf.drawio.dtmp new file mode 100644 index 000000000..14663ecb0 --- /dev/null +++ b/docs/diagrams/.$Structure_BayesInf.drawio.dtmp @@ -0,0 +1,964 @@ +<mxfile host="Electron" modified="2024-04-19T16:08:46.718Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.1.11 Chrome/114.0.5735.289 Electron/25.9.8 Safari/537.36" etag="QkifmTMxwBp7UqUSeBiS" version="22.1.11" type="device" pages="4"> + <diagram name="Class and function structure" id="efOe0Jku58RX-i1bv-3b"> + <mxGraphModel dx="3735" dy="1372" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0"> + <root> + <mxCell id="0" /> + <mxCell id="1" parent="0" /> + <mxCell id="xary-zVek9Bg-A1b1ZmA-22" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>MCMC</b></p><hr size="1"><div style="height:2px;"></div>" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="1270" y="360" width="770" height="380" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-1" value="_kernel_rbf" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="1020" y="200" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-2" value="_logpdf" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="820" y="140" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-10" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>BayesInf</b></p><hr size="1"><div style="height:2px;"></div>" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="-120" y="290" width="1310" height="680" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-24" value="if self.bootstrap <br>or self.bayes_loocv <br>or self.just_analysis" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;labelBackgroundColor=#ffae00;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="xary-zVek9Bg-A1b1ZmA-13"> + <mxGeometry x="0.2902" relative="1" as="geometry"> + <mxPoint as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-31" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="xary-zVek9Bg-A1b1ZmA-18"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-42" value="if self.name != 'valid'<br>and self.inference_method != 'rejection'" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=default;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-31"> + <mxGeometry x="0.5646" relative="1" as="geometry"> + <mxPoint as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-32" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="HiMKSJFquRK0mIlwyRFI-5"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-43" value="if self.inference_method == 'mcmc'" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-32"> + <mxGeometry x="-0.0958" y="-1" relative="1" as="geometry"> + <mxPoint as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-33" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="xary-zVek9Bg-A1b1ZmA-19"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-52" value="always" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#C2C2C2;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-33"> + <mxGeometry x="-0.112" y="1" relative="1" as="geometry"> + <mxPoint as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-34" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="xary-zVek9Bg-A1b1ZmA-21"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-47" value="if self.plot_post_pred" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-34"> + <mxGeometry x="0.2399" y="-1" relative="1" as="geometry"> + <mxPoint y="1" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-35" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="xary-zVek9Bg-A1b1ZmA-20"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-46" value="if self.plot_map_pred" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-35"> + <mxGeometry x="0.4183" y="-1" relative="1" as="geometry"> + <mxPoint as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-54" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="xary-zVek9Bg-A1b1ZmA-53"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-55" value="if self.bootstrap" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#FF9A03;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-54"> + <mxGeometry x="0.1816" y="3" relative="1" as="geometry"> + <mxPoint x="1" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-57" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="xary-zVek9Bg-A1b1ZmA-56"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-58" value="always" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#FF9A03;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-57"> + <mxGeometry x="0.7182" y="2" relative="1" as="geometry"> + <mxPoint as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-60" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="xary-zVek9Bg-A1b1ZmA-59"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-61" value="if self.error_model<br>and self.name == 'calib'" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-60"> + <mxGeometry x="0.3024" y="2" relative="1" as="geometry"> + <mxPoint x="67" y="1" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-54" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="HiMKSJFquRK0mIlwyRFI-51"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-55" value="always" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#FF9A03;" vertex="1" connectable="0" parent="HiMKSJFquRK0mIlwyRFI-54"> + <mxGeometry x="0.8253" y="3" relative="1" as="geometry"> + <mxPoint as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-9" value="create_inference" style="html=1;whiteSpace=wrap;strokeWidth=2;" vertex="1" parent="1"> + <mxGeometry x="405" y="539" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-25" value="if len(self.perturbed_data) == 0" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-13" target="xary-zVek9Bg-A1b1ZmA-14"> + <mxGeometry x="0.3402" relative="1" as="geometry"> + <mxPoint y="1" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-27" value="if not self.emulator" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-13" target="xary-zVek9Bg-A1b1ZmA-15"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-29" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-13" target="xary-zVek9Bg-A1b1ZmA-16"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-44" value="always" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#cdcbcb;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-29"> + <mxGeometry x="0.4722" y="1" relative="1" as="geometry"> + <mxPoint as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-30" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-13" target="xary-zVek9Bg-A1b1ZmA-17"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-41" value="if self.emulator" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-30"> + <mxGeometry x="0.6143" y="-3" relative="1" as="geometry"> + <mxPoint as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-62" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-13" target="xary-zVek9Bg-A1b1ZmA-59"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="340" y="680" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-63" value="if self.error_model<br>and self.name == 'valid'" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=default;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-62"> + <mxGeometry x="-0.3906" relative="1" as="geometry"> + <mxPoint y="121" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-13" value="perform_bootstrap" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="50" y="335" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-14" value="_perturb_data" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="-75" y="460" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-15" value="_eval_model" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="1050" y="660" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-16" target="xary-zVek9Bg-A1b1ZmA-1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-49" value="if hasattr bias_inputs&nbsp;<br>and not hasattr error_model" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#ffae00;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-38"> + <mxGeometry x="0.3126" y="-3" relative="1" as="geometry"> + <mxPoint x="-103" y="31" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-39" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-16" target="xary-zVek9Bg-A1b1ZmA-2"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-16" value="normpdf" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="650" y="455" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-40" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-17" target="xary-zVek9Bg-A1b1ZmA-2"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-50" value="always" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#cdcbcb;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-40"> + <mxGeometry x="-0.6073" y="-5" relative="1" as="geometry"> + <mxPoint as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-17" value="_corr_factor_BME" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="650" y="385" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-18" value="_rejection_sampling" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="280" y="890" width="120" height="50" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-26" value="if not self.emulator&nbsp;<br>and not self.inference_method == 'rejection'&nbsp;<br>and self.name == 'calib" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-19" target="xary-zVek9Bg-A1b1ZmA-15"> + <mxGeometry x="-0.0559" y="15" relative="1" as="geometry"> + <mxPoint as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-37" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-19" target="xary-zVek9Bg-A1b1ZmA-1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-48" value="if sigma2_prior is not None<br>and if hasattr bias_inputs<br>and if not hasattr error_model" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#ffae00;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-37"> + <mxGeometry x="-0.5544" y="-1" relative="1" as="geometry"> + <mxPoint x="1" y="-5" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-19" value="_posterior_predictive" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="690" y="589" width="130" height="50" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-28" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-20" target="xary-zVek9Bg-A1b1ZmA-15"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-45" value="always" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#cdcbcb;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-28"> + <mxGeometry x="0.0517" relative="1" as="geometry"> + <mxPoint as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-20" value="_plot_max_a_posteriori" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="495" y="790" width="140" height="50" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-21" value="plot_post_predictive" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="630" y="720" width="120" height="50" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-36" value="Note: Arrows indicate function calls, beginning calls the end" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1"> + <mxGeometry x="10" y="10" width="190" height="30" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-51" value="Color meanings:<br><span style="white-space: pre;">	</span>red: wrong, change<br><span style="white-space: pre;">	</span>orange: seems off, look at again<br><span style="white-space: pre;">	</span>light beige: has been removed" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1"> + <mxGeometry x="20" y="70" width="220" height="30" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-53" value="plot_log_BME" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="150" y="820" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-56" value="plot_post_params" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="660" y="840" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="xary-zVek9Bg-A1b1ZmA-59" value="create_error_model" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="45" y="740" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-1" value="_check_ranges" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="1595" y="280" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-2" value="gelman_rubin" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="1350" y="250" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-3" value="_iterative_scheme" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f9f7ed;strokeColor=#CCC1AA;fontColor=#CCC1AA;" vertex="1" parent="1"> + <mxGeometry x="2055" y="620" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-21" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#f9f7ed;strokeColor=#CCC1AA;fontColor=#CCC1AA;" edge="1" parent="1" source="HiMKSJFquRK0mIlwyRFI-4" target="HiMKSJFquRK0mIlwyRFI-2"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-24" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;fillColor=#f9f7ed;strokeColor=#CCC1AA;fontColor=#CCC1AA;" edge="1" parent="1" source="HiMKSJFquRK0mIlwyRFI-4" target="HiMKSJFquRK0mIlwyRFI-11"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-4" value="_my_ESS" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f9f7ed;strokeColor=#CCC1AA;fontColor=#CCC1AA;" vertex="1" parent="1"> + <mxGeometry x="1350" y="100" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-14" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="HiMKSJFquRK0mIlwyRFI-5" target="HiMKSJFquRK0mIlwyRFI-8"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-19" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="HiMKSJFquRK0mIlwyRFI-5" target="HiMKSJFquRK0mIlwyRFI-10"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="HiMKSJFquRK0mIlwyRFI-5" target="HiMKSJFquRK0mIlwyRFI-2"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-53" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="HiMKSJFquRK0mIlwyRFI-5" target="HiMKSJFquRK0mIlwyRFI-52"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-56" value="if opts_sigma != 'B'" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#FF9A03;" vertex="1" connectable="0" parent="HiMKSJFquRK0mIlwyRFI-53"> + <mxGeometry x="0.7377" y="1" relative="1" as="geometry"> + <mxPoint as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-5" value="run_sampler" style="rounded=0;whiteSpace=wrap;html=1;strokeWidth=2;" vertex="1" parent="1"> + <mxGeometry x="1350" y="534" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-20" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="HiMKSJFquRK0mIlwyRFI-6" target="HiMKSJFquRK0mIlwyRFI-1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-6" value="log_prior" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="1595" y="510" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="HiMKSJFquRK0mIlwyRFI-7" target="HiMKSJFquRK0mIlwyRFI-9"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-16" value="always" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="HiMKSJFquRK0mIlwyRFI-15"> + <mxGeometry x="0.0246" y="2" relative="1" as="geometry"> + <mxPoint as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-7" value="log_likelihood" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="1760" y="539" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="HiMKSJFquRK0mIlwyRFI-8" target="HiMKSJFquRK0mIlwyRFI-6"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-17" value="always" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="HiMKSJFquRK0mIlwyRFI-12"> + <mxGeometry x="0.4587" y="4" relative="1" as="geometry"> + <mxPoint as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="HiMKSJFquRK0mIlwyRFI-8" target="HiMKSJFquRK0mIlwyRFI-7"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-18" value="always" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="HiMKSJFquRK0mIlwyRFI-13"> + <mxGeometry x="0.6826" y="4" relative="1" as="geometry"> + <mxPoint as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-8" value="log_posterior" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="1480" y="610" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-9" value="eval_model" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="1760" y="400" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-10" value="train_error_model" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="1450" y="420" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-23" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#f9f7ed;strokeColor=#CCC1AA;fontColor=#CCC1AA;" edge="1" parent="1" source="HiMKSJFquRK0mIlwyRFI-11" target="HiMKSJFquRK0mIlwyRFI-3"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-11" value="marginal_llk_emcee" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f9f7ed;strokeColor=#CCC1AA;fontColor=#CCC1AA;" vertex="1" parent="1"> + <mxGeometry x="1870" y="620" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-25" value="Never used!" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#CCC1AA;" vertex="1" parent="1"> + <mxGeometry x="1880" y="680" width="100" height="30" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-26" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>BayesModelComp</b></p><hr size="1"><div style="height:2px;"></div>" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="-1096" y="380" width="840" height="420" as="geometry" /> + </mxCell> + <mxCell id="HC1H8j6nMwEtLoyIrXXk-9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="HiMKSJFquRK0mIlwyRFI-27" target="HC1H8j6nMwEtLoyIrXXk-3"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HC1H8j6nMwEtLoyIrXXk-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;" edge="1" parent="1" source="HiMKSJFquRK0mIlwyRFI-27" target="HC1H8j6nMwEtLoyIrXXk-1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HC1H8j6nMwEtLoyIrXXk-14" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="HiMKSJFquRK0mIlwyRFI-27" target="HiMKSJFquRK0mIlwyRFI-31"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-27" value="model_comparison_all" style="html=1;whiteSpace=wrap;strokeWidth=2;" vertex="1" parent="1"> + <mxGeometry x="-896" y="566" width="160" height="50" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-42" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="HC1H8j6nMwEtLoyIrXXk-1" target="xary-zVek9Bg-A1b1ZmA-9"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="-630" y="564" as="sourcePoint" /> + </mxGeometry> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-47" value="always" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="HiMKSJFquRK0mIlwyRFI-42"> + <mxGeometry x="-0.4883" relative="1" as="geometry"> + <mxPoint as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-37" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="HiMKSJFquRK0mIlwyRFI-29" target="HiMKSJFquRK0mIlwyRFI-30"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-49" value="if perturbed_data is None" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="HiMKSJFquRK0mIlwyRFI-37"> + <mxGeometry x="-0.0507" y="4" relative="1" as="geometry"> + <mxPoint x="-1" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-29" value="generate_dataset" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="-546" y="566" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-30" value="_perturb_data" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="-376" y="636" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="HC1H8j6nMwEtLoyIrXXk-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="HiMKSJFquRK0mIlwyRFI-31" target="HC1H8j6nMwEtLoyIrXXk-1"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HC1H8j6nMwEtLoyIrXXk-10" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="HiMKSJFquRK0mIlwyRFI-31" target="HiMKSJFquRK0mIlwyRFI-33"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HC1H8j6nMwEtLoyIrXXk-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="HiMKSJFquRK0mIlwyRFI-31" target="HC1H8j6nMwEtLoyIrXXk-2"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-31" value="cal_model_weight" style="html=1;whiteSpace=wrap;strokeWidth=2;" vertex="1" parent="1"> + <mxGeometry x="-871" y="466" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-32" value="plot_just_analysis" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="-871" y="736" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-33" value="plot_model_weights" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="-1016" y="416" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-34" value="plot_bayes_factor" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="-446" y="431" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-51" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>Discrepancy</b></p><hr size="1"><div style="height:2px;"></div>" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="360" y="1039.82" width="200" height="130" as="geometry" /> + </mxCell> + <mxCell id="HiMKSJFquRK0mIlwyRFI-52" value="get_sample" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="400" y="1079.82" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="HC1H8j6nMwEtLoyIrXXk-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;" edge="1" parent="1" source="HC1H8j6nMwEtLoyIrXXk-1" target="HiMKSJFquRK0mIlwyRFI-34"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HC1H8j6nMwEtLoyIrXXk-20" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="HC1H8j6nMwEtLoyIrXXk-1" target="HC1H8j6nMwEtLoyIrXXk-17"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HC1H8j6nMwEtLoyIrXXk-21" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.75;exitDx=0;exitDy=0;" edge="1" parent="1" source="HC1H8j6nMwEtLoyIrXXk-1" target="HiMKSJFquRK0mIlwyRFI-29"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HC1H8j6nMwEtLoyIrXXk-1" value="calc_bayes_factors" style="html=1;whiteSpace=wrap;strokeWidth=2;" vertex="1" parent="1"> + <mxGeometry x="-666" y="466" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="HC1H8j6nMwEtLoyIrXXk-2" value="calc_model_weights" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="-1066" y="566" width="130" height="50" as="geometry" /> + </mxCell> + <mxCell id="HC1H8j6nMwEtLoyIrXXk-4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="HC1H8j6nMwEtLoyIrXXk-3" target="HiMKSJFquRK0mIlwyRFI-32"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HC1H8j6nMwEtLoyIrXXk-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="HC1H8j6nMwEtLoyIrXXk-3" target="HC1H8j6nMwEtLoyIrXXk-2"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HC1H8j6nMwEtLoyIrXXk-16" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.75;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="HC1H8j6nMwEtLoyIrXXk-3" target="xary-zVek9Bg-A1b1ZmA-9"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HC1H8j6nMwEtLoyIrXXk-23" value="always" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="HC1H8j6nMwEtLoyIrXXk-16"> + <mxGeometry x="-0.5478" y="3" relative="1" as="geometry"> + <mxPoint as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="HC1H8j6nMwEtLoyIrXXk-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;" edge="1" parent="1" source="HC1H8j6nMwEtLoyIrXXk-3" target="HC1H8j6nMwEtLoyIrXXk-17"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HC1H8j6nMwEtLoyIrXXk-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="HC1H8j6nMwEtLoyIrXXk-3" target="HiMKSJFquRK0mIlwyRFI-29"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="HC1H8j6nMwEtLoyIrXXk-3" value="calc_justifiability_analysis" style="html=1;whiteSpace=wrap;strokeWidth=2;" vertex="1" parent="1"> + <mxGeometry x="-896" y="666" width="160" height="50" as="geometry" /> + </mxCell> + <mxCell id="HC1H8j6nMwEtLoyIrXXk-17" value="setup" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="-666" y="566" width="110" height="50" as="geometry" /> + </mxCell> + </root> + </mxGraphModel> + </diagram> + <diagram id="sQf09xvhinkT827TE7Va" name="Function structure Engine"> + <mxGraphModel dx="1436" dy="968" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0"> + <root> + <mxCell id="0" /> + <mxCell id="1" parent="0" /> + <mxCell id="JXjM7l_erEiZMkSmYBvl-1" value="<p style="margin:0px;margin-top:4px;text-align:center;"><b>Engine</b></p><hr size="1"><div style="height:2px;"></div>" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="130" y="140" width="1390" height="690" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-2" value="hellinger_distance" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="1340" y="50" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-3" value="logpdf" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="1050" y="50" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-4" value="subdomain" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="625" y="50" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-5" value="start_engine" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="250" y="680" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-32" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-6" target="JXjM7l_erEiZMkSmYBvl-5"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-6" value="train_normal" style="html=1;whiteSpace=wrap;strokeWidth=2;" vertex="1" parent="1"> + <mxGeometry x="170" y="420" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-10" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-7" target="JXjM7l_erEiZMkSmYBvl-9"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="335" y="335" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-33" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-7" target="JXjM7l_erEiZMkSmYBvl-6"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-7" value="train_sequential" style="html=1;whiteSpace=wrap;strokeWidth=2;" vertex="1" parent="1"> + <mxGeometry x="170" y="310" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-8" value="eval_metamodel" style="html=1;whiteSpace=wrap;strokeWidth=2;" vertex="1" parent="1"> + <mxGeometry x="190" y="210" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-7" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-9" target="JXjM7l_erEiZMkSmYBvl-18"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-19" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-9" target="JXjM7l_erEiZMkSmYBvl-23"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-20" value="if len(obs_data) != 0" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="W5_FOelZ0qj-h3Gb0n3K-19"> + <mxGeometry x="0.8137" relative="1" as="geometry"> + <mxPoint x="-57" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-21" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.25;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-9" target="JXjM7l_erEiZMkSmYBvl-24"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-22" value="if len(obs_data) != 0" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="W5_FOelZ0qj-h3Gb0n3K-21"> + <mxGeometry x="0.7684" y="3" relative="1" as="geometry"> + <mxPoint x="1" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-23" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-9" target="JXjM7l_erEiZMkSmYBvl-25"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-24" value="if expdes.valid_model_runs" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="W5_FOelZ0qj-h3Gb0n3K-23"> + <mxGeometry x="0.606" y="3" relative="1" as="geometry"> + <mxPoint x="-16" y="3" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-25" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-9" target="JXjM7l_erEiZMkSmYBvl-26"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-26" value="if mc_ref and pce" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="W5_FOelZ0qj-h3Gb0n3K-25"> + <mxGeometry x="0.7094" y="-3" relative="1" as="geometry"> + <mxPoint x="-31" y="-3" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-9" value="train_seq_design" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="315" y="310" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-12" value="util_VarBasedDesign" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="670" y="648" width="130" height="50" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-28" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-13" target="JXjM7l_erEiZMkSmYBvl-3"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-31" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-13" target="JXjM7l_erEiZMkSmYBvl-5"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-15" target="JXjM7l_erEiZMkSmYBvl-13"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-39" value="if method == 'bayesactdesign'" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=default;" vertex="1" connectable="0" parent="JXjM7l_erEiZMkSmYBvl-38"> + <mxGeometry x="-0.6235" y="2" relative="1" as="geometry"> + <mxPoint x="289" y="2" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-13" target="JXjM7l_erEiZMkSmYBvl-21"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-15" value="always" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="W5_FOelZ0qj-h3Gb0n3K-12"> + <mxGeometry x="0.7865" y="4" relative="1" as="geometry"> + <mxPoint x="-91" y="185" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-13" value="util_BayesianActiveDesign" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="1020" y="680" width="150" height="50" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-34" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-14" target="JXjM7l_erEiZMkSmYBvl-6"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-14" target="JXjM7l_erEiZMkSmYBvl-21"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-16" value="always" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="W5_FOelZ0qj-h3Gb0n3K-13"> + <mxGeometry x="0.197" y="-3" relative="1" as="geometry"> + <mxPoint x="-1" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-14" value="utilBayesianDesign" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="880" y="730" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-37" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-15" target="JXjM7l_erEiZMkSmYBvl-12"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-42" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-15" target="JXjM7l_erEiZMkSmYBvl-14"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-43" value="if method == 'bayesoptdesign'" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="JXjM7l_erEiZMkSmYBvl-42"> + <mxGeometry x="0.6143" y="-3" relative="1" as="geometry"> + <mxPoint x="3" y="29" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-15" value="run_util_func" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="660" y="450" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-36" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-16" target="JXjM7l_erEiZMkSmYBvl-12"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-41" value="if method == 'varoptdesign'" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="JXjM7l_erEiZMkSmYBvl-36"> + <mxGeometry x="-0.5992" relative="1" as="geometry"> + <mxPoint x="-197" y="62" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-44" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-16" target="JXjM7l_erEiZMkSmYBvl-13"> + <mxGeometry relative="1" as="geometry"> + <Array as="points"> + <mxPoint x="965" y="590" /> + <mxPoint x="1095" y="590" /> + </Array> + </mxGeometry> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-27" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-16" target="JXjM7l_erEiZMkSmYBvl-14"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-16" value="dual_annealing" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="910" y="450" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-17" target="JXjM7l_erEiZMkSmYBvl-18"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-6" value="if exploit _method is 'bayesoptdesign',<br style="border-color: var(--border-color);">'bayesactdesign' or 'varoptdesign'" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="W5_FOelZ0qj-h3Gb0n3K-5"> + <mxGeometry x="0.1312" y="2" relative="1" as="geometry"> + <mxPoint x="17" y="-2" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-17" value="tradeoff_weights" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="980" y="210" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-30" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-18" target="JXjM7l_erEiZMkSmYBvl-4"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-18" target="JXjM7l_erEiZMkSmYBvl-15"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="790" y="280.0000000000002" as="sourcePoint" /> + <mxPoint x="690" y="499.9999999999998" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-2" value="if exploit _method is 'bayesoptdesign',<br>'bayesactdesign' or 'varoptdesign'" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="W5_FOelZ0qj-h3Gb0n3K-1"> + <mxGeometry x="0.1579" relative="1" as="geometry"> + <mxPoint x="-15" y="49" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-18" target="JXjM7l_erEiZMkSmYBvl-16"> + <mxGeometry relative="1" as="geometry"> + <mxPoint x="680" y="205.05882352941194" as="sourcePoint" /> + <mxPoint x="805" y="779.9999999999998" as="targetPoint" /> + </mxGeometry> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-4" value="if explore_method == 'dual annealing'" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="W5_FOelZ0qj-h3Gb0n3K-3"> + <mxGeometry x="-0.6061" relative="1" as="geometry"> + <mxPoint x="270" y="46" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-18" target="JXjM7l_erEiZMkSmYBvl-20"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-10" value="if exploit_method == 'alphabetic'" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="W5_FOelZ0qj-h3Gb0n3K-9"> + <mxGeometry x="0.8144" y="1" relative="1" as="geometry"> + <mxPoint x="74" y="-1" as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-18" value="choose_next_sample" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="610" y="210" width="140" height="50" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-20" value="util_AlphOptDesign" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="330" y="210" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-21" value="_normpdf" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="1340" y="430" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-29" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-22" target="JXjM7l_erEiZMkSmYBvl-3"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-22" value="_corr_factor_BME" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="1130" y="220" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-23" value="_posteriorPlot" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="520" y="440" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-27" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-24" target="JXjM7l_erEiZMkSmYBvl-2"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-24" target="JXjM7l_erEiZMkSmYBvl-21"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-14" value="always" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="W5_FOelZ0qj-h3Gb0n3K-11"> + <mxGeometry x="0.0929" y="-1" relative="1" as="geometry"> + <mxPoint as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="JXjM7l_erEiZMkSmYBvl-24" target="JXjM7l_erEiZMkSmYBvl-22"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="W5_FOelZ0qj-h3Gb0n3K-18" value="commented out?" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="W5_FOelZ0qj-h3Gb0n3K-17"> + <mxGeometry x="-0.1477" y="3" relative="1" as="geometry"> + <mxPoint as="offset" /> + </mxGeometry> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-24" value="_BME_Calculator" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="1340" y="220" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-25" value="_validError" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="520" y="510" width="110" height="50" as="geometry" /> + </mxCell> + <mxCell id="JXjM7l_erEiZMkSmYBvl-26" value="_error_Mean_Std" style="html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="520" y="580" width="110" height="50" as="geometry" /> + </mxCell> + </root> + </mxGraphModel> + </diagram> + <diagram id="ME5gyYpVqUByTnAIOcMV" name="Parameter and function interaction"> + <mxGraphModel dx="2049" dy="1366" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0"> + <root> + <mxCell id="0" /> + <mxCell id="1" parent="0" /> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-33" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-1" target="K5oJ7VEt7dPmeK6pba1f-32"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-54" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-1" target="K5oJ7VEt7dPmeK6pba1f-53"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-61" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-1" target="K5oJ7VEt7dPmeK6pba1f-60"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-1" value="engine" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="160" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-3" value="Discrepancy" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="240" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-71" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-4" target="K5oJ7VEt7dPmeK6pba1f-60"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-4" value="emulator" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="320" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-37" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-5" target="K5oJ7VEt7dPmeK6pba1f-32"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-57" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-5" target="K5oJ7VEt7dPmeK6pba1f-53"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-65" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-5" target="K5oJ7VEt7dPmeK6pba1f-60"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-5" value="name" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="400" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-47" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-6" target="K5oJ7VEt7dPmeK6pba1f-32"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-6" value="bootstrap" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="480" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-7" value="req_outputs" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="560" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-79" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-8" target="K5oJ7VEt7dPmeK6pba1f-60"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-8" value="selected_indices" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="640" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-35" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-9" target="K5oJ7VEt7dPmeK6pba1f-32"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-55" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-9" target="K5oJ7VEt7dPmeK6pba1f-53"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-67" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-9" target="K5oJ7VEt7dPmeK6pba1f-60"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-9" value="prior_samples" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="720" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-36" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-11" target="K5oJ7VEt7dPmeK6pba1f-32"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-68" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-11" target="K5oJ7VEt7dPmeK6pba1f-60"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-11" value="n_prior_samples" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="800" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-12" target="K5oJ7VEt7dPmeK6pba1f-32"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-80" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-12" target="K5oJ7VEt7dPmeK6pba1f-60"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-12" value="measured_data" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="880" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-58" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-13" target="K5oJ7VEt7dPmeK6pba1f-53"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-13" value="inference_method" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="960" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-14" value="mcmc_params" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="1040" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-63" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-15" target="K5oJ7VEt7dPmeK6pba1f-60"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-15" value="perturbed_data" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="1120" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-45" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-16" target="K5oJ7VEt7dPmeK6pba1f-32"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-77" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-16" target="K5oJ7VEt7dPmeK6pba1f-60"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-16" value="bayes_loocv" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="1200" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-64" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-17" target="K5oJ7VEt7dPmeK6pba1f-60"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-17" value="n_bootstrap_itrs" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="1280" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-18" value="bootstrap_noise" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="1360" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-46" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-19" target="K5oJ7VEt7dPmeK6pba1f-32"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-78" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-19" target="K5oJ7VEt7dPmeK6pba1f-60"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-19" value="just_analysis" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="1440" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-20" value="valid_metrics" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="1520" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-52" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-21" target="K5oJ7VEt7dPmeK6pba1f-32"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-21" value="plot_post_pred" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="1600" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-51" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-22" target="K5oJ7VEt7dPmeK6pba1f-32"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-22" value="plot_map_pred" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="1680" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-23" value="max_a_posteriori" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="1760" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-24" value="corner_title_fmt" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="1840" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-34" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-25" target="K5oJ7VEt7dPmeK6pba1f-32"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-25" value="out_dir" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="1920" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-50" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-26" target="K5oJ7VEt7dPmeK6pba1f-32"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-66" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-26" target="K5oJ7VEt7dPmeK6pba1f-60"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-26" value="error_model" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="2000" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-56" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-27" target="K5oJ7VEt7dPmeK6pba1f-53"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-72" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-27" target="K5oJ7VEt7dPmeK6pba1f-60"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-27" value="bias_inputs" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="2080" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-41" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-28" target="K5oJ7VEt7dPmeK6pba1f-32"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-28" value="measurement_error" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="2160" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-44" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-29" target="K5oJ7VEt7dPmeK6pba1f-32"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-81" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-29" target="K5oJ7VEt7dPmeK6pba1f-60"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-29" value="sigma2s" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="2240" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-30" value="log_likes" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="2320" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-82" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-31" target="K5oJ7VEt7dPmeK6pba1f-60"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-31" value="dtype" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="2400" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-32" value="create_inference" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="400" y="20" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-40" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-39" target="K5oJ7VEt7dPmeK6pba1f-32"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-39" value="n_tot_measurement" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="2480" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-43" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-42" target="K5oJ7VEt7dPmeK6pba1f-32"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-42" value="Discrepancy" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="2560" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-49" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-48" target="K5oJ7VEt7dPmeK6pba1f-32"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-59" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-48" target="K5oJ7VEt7dPmeK6pba1f-53"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-48" value="posterior_df" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="2640" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-53" value="create_error_model" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="560" y="20" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-60" value="perform_bootstrap" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="720" y="20" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-75" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-69" target="K5oJ7VEt7dPmeK6pba1f-60"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-69" value="__mean_pce_prior_pred" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="2720" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-76" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-70" target="K5oJ7VEt7dPmeK6pba1f-60"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-70" value="_std_pce_prior_pred" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="2800" width="120" height="60" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-74" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-73" target="K5oJ7VEt7dPmeK6pba1f-60"> + <mxGeometry relative="1" as="geometry" /> + </mxCell> + <mxCell id="K5oJ7VEt7dPmeK6pba1f-73" value="__model_prior_pred" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> + <mxGeometry x="40" y="2880" width="120" height="60" as="geometry" /> + </mxCell> + </root> + </mxGraphModel> + </diagram> + <diagram id="QgiNX2WXFOBDsDgzoFY9" name="Folder structure"> + <mxGraphModel dx="1436" dy="968" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0"> + <root> + <mxCell id="0" /> + <mxCell id="1" parent="0" /> + <mxCell id="KLYezTmecfuvBG8KQe-n-1" value="" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="140" y="80" width="750" height="550" as="geometry" /> + </mxCell> + <mxCell id="KLYezTmecfuvBG8KQe-n-2" value="" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="170" y="110" width="700" height="220" as="geometry" /> + </mxCell> + <mxCell id="KLYezTmecfuvBG8KQe-n-3" value="" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="170" y="370" width="180" height="50" as="geometry" /> + </mxCell> + <mxCell id="KLYezTmecfuvBG8KQe-n-4" value="" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="170" y="440" width="180" height="50" as="geometry" /> + </mxCell> + <mxCell id="KLYezTmecfuvBG8KQe-n-5" value="" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="170" y="500" width="180" height="50" as="geometry" /> + </mxCell> + <mxCell id="KLYezTmecfuvBG8KQe-n-6" value="adaptPlot" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="190" y="150" width="70" height="50" as="geometry" /> + </mxCell> + <mxCell id="KLYezTmecfuvBG8KQe-n-7" value="apoly_construction" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="280" y="150" width="140" height="50" as="geometry" /> + </mxCell> + <mxCell id="KLYezTmecfuvBG8KQe-n-8" value="bayes_linear" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="440" y="150" width="90" height="50" as="geometry" /> + </mxCell> + <mxCell id="KLYezTmecfuvBG8KQe-n-9" value="engine" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="550" y="150" width="70" height="50" as="geometry" /> + </mxCell> + <mxCell id="KLYezTmecfuvBG8KQe-n-11" value="eval_rec_rule" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="640" y="150" width="100" height="50" as="geometry" /> + </mxCell> + <mxCell id="KLYezTmecfuvBG8KQe-n-12" value="exp_designs" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="760" y="150" width="90" height="50" as="geometry" /> + </mxCell> + <mxCell id="KLYezTmecfuvBG8KQe-n-13" value="exploration" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="190" y="210" width="80" height="50" as="geometry" /> + </mxCell> + <mxCell id="KLYezTmecfuvBG8KQe-n-14" value="glexindex" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="290" y="210" width="70" height="50" as="geometry" /> + </mxCell> + <mxCell id="KLYezTmecfuvBG8KQe-n-15" value="input_space" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="380" y="210" width="80" height="50" as="geometry" /> + </mxCell> + <mxCell id="KLYezTmecfuvBG8KQe-n-16" value="inputs" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="480" y="210" width="70" height="50" as="geometry" /> + </mxCell> + <mxCell id="KLYezTmecfuvBG8KQe-n-17" value="meta_model_engine" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="570" y="210" width="160" height="50" as="geometry" /> + </mxCell> + </root> + </mxGraphModel> + </diagram> +</mxfile> diff --git a/docs/diagrams/Structure_BayesInf.drawio b/docs/diagrams/Structure_BayesInf.drawio index 33e150b1e..2e28cbcb3 100644 --- a/docs/diagrams/Structure_BayesInf.drawio +++ b/docs/diagrams/Structure_BayesInf.drawio @@ -1,4 +1,4 @@ -<mxfile host="Electron" modified="2024-04-19T16:26:58.726Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.1.11 Chrome/114.0.5735.289 Electron/25.9.8 Safari/537.36" etag="Yc6sjpTEYy9MY2e4nR0l" version="22.1.11" type="device" pages="4"> +<mxfile host="Electron" modified="2024-04-19T16:08:43.773Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.1.11 Chrome/114.0.5735.289 Electron/25.9.8 Safari/537.36" etag="2ELAo-FvqOEnLxZhqqO4" version="22.1.11" type="device" pages="4"> <diagram name="Class and function structure" id="efOe0Jku58RX-i1bv-3b"> <mxGraphModel dx="3735" dy="1372" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0"> <root> @@ -910,86 +910,53 @@ <root> <mxCell id="0" /> <mxCell id="1" parent="0" /> - <mxCell id="KLYezTmecfuvBG8KQe-n-1" value="" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;fillColor=#B0A8FB;strokeColor=#56517e;" vertex="1" parent="1"> - <mxGeometry x="140" y="50" width="780" height="490" as="geometry" /> + <mxCell id="KLYezTmecfuvBG8KQe-n-1" value="" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="140" y="80" width="750" height="550" as="geometry" /> </mxCell> - <mxCell id="KLYezTmecfuvBG8KQe-n-2" value="" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;fillColor=#eeeeee;strokeColor=#36393d;" vertex="1" parent="1"> - <mxGeometry x="170" y="110" width="720" height="250" as="geometry" /> + <mxCell id="KLYezTmecfuvBG8KQe-n-2" value="" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="170" y="110" width="700" height="220" as="geometry" /> </mxCell> - <mxCell id="KLYezTmecfuvBG8KQe-n-5" value="" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;fillColor=#eeeeee;strokeColor=#36393d;" vertex="1" parent="1"> - <mxGeometry x="170" y="380" width="550" height="130" as="geometry" /> + <mxCell id="KLYezTmecfuvBG8KQe-n-3" value="" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="170" y="370" width="180" height="50" as="geometry" /> + </mxCell> + <mxCell id="KLYezTmecfuvBG8KQe-n-4" value="" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="170" y="440" width="180" height="50" as="geometry" /> + </mxCell> + <mxCell id="KLYezTmecfuvBG8KQe-n-5" value="" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="170" y="500" width="180" height="50" as="geometry" /> </mxCell> <mxCell id="KLYezTmecfuvBG8KQe-n-6" value="adaptPlot" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> - <mxGeometry x="190" y="170" width="70" height="50" as="geometry" /> + <mxGeometry x="190" y="150" width="70" height="50" as="geometry" /> </mxCell> <mxCell id="KLYezTmecfuvBG8KQe-n-7" value="apoly_construction" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> - <mxGeometry x="280" y="170" width="140" height="50" as="geometry" /> + <mxGeometry x="280" y="150" width="140" height="50" as="geometry" /> </mxCell> <mxCell id="KLYezTmecfuvBG8KQe-n-8" value="bayes_linear" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> - <mxGeometry x="440" y="170" width="90" height="50" as="geometry" /> + <mxGeometry x="440" y="150" width="90" height="50" as="geometry" /> </mxCell> <mxCell id="KLYezTmecfuvBG8KQe-n-9" value="engine" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> - <mxGeometry x="550" y="170" width="70" height="50" as="geometry" /> + <mxGeometry x="550" y="150" width="70" height="50" as="geometry" /> </mxCell> <mxCell id="KLYezTmecfuvBG8KQe-n-11" value="eval_rec_rule" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> - <mxGeometry x="640" y="170" width="100" height="50" as="geometry" /> + <mxGeometry x="640" y="150" width="100" height="50" as="geometry" /> </mxCell> <mxCell id="KLYezTmecfuvBG8KQe-n-12" value="exp_designs" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> - <mxGeometry x="190" y="230" width="90" height="50" as="geometry" /> + <mxGeometry x="760" y="150" width="90" height="50" as="geometry" /> </mxCell> <mxCell id="KLYezTmecfuvBG8KQe-n-13" value="exploration" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> - <mxGeometry x="300" y="230" width="80" height="50" as="geometry" /> + <mxGeometry x="190" y="210" width="80" height="50" as="geometry" /> </mxCell> <mxCell id="KLYezTmecfuvBG8KQe-n-14" value="glexindex" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> - <mxGeometry x="400" y="230" width="70" height="50" as="geometry" /> + <mxGeometry x="290" y="210" width="70" height="50" as="geometry" /> </mxCell> <mxCell id="KLYezTmecfuvBG8KQe-n-15" value="input_space" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> - <mxGeometry x="490" y="230" width="80" height="50" as="geometry" /> + <mxGeometry x="380" y="210" width="80" height="50" as="geometry" /> </mxCell> <mxCell id="KLYezTmecfuvBG8KQe-n-16" value="inputs" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> - <mxGeometry x="590" y="230" width="70" height="50" as="geometry" /> - </mxCell> - <mxCell id="KLYezTmecfuvBG8KQe-n-17" value="orthogonal_matching_pursuit" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> - <mxGeometry x="680" y="230" width="190" height="50" as="geometry" /> - </mxCell> - <mxCell id="KLYezTmecfuvBG8KQe-n-18" value="reg_fast_ard" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> - <mxGeometry x="190" y="290" width="90" height="50" as="geometry" /> - </mxCell> - <mxCell id="KLYezTmecfuvBG8KQe-n-19" value="reg_fast_laplace" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> - <mxGeometry x="300" y="290" width="110" height="50" as="geometry" /> - </mxCell> - <mxCell id="KLYezTmecfuvBG8KQe-n-20" value="sequential_design" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> - <mxGeometry x="430" y="290" width="120" height="50" as="geometry" /> - </mxCell> - <mxCell id="KLYezTmecfuvBG8KQe-n-21" value="surrogate_models" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> - <mxGeometry x="565" y="290" width="120" height="50" as="geometry" /> - </mxCell> - <mxCell id="KLYezTmecfuvBG8KQe-n-22" value="surrogate_models" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontStyle=1" vertex="1" parent="1"> - <mxGeometry x="190" y="130" width="120" height="30" as="geometry" /> - </mxCell> - <mxCell id="KLYezTmecfuvBG8KQe-n-23" value="bayes_inference" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontStyle=1" vertex="1" parent="1"> - <mxGeometry x="190" y="400" width="110" height="30" as="geometry" /> - </mxCell> - <mxCell id="KLYezTmecfuvBG8KQe-n-24" value="pylink" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> - <mxGeometry x="760" y="380" width="90" height="50" as="geometry" /> - </mxCell> - <mxCell id="KLYezTmecfuvBG8KQe-n-26" value="postprocessing" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> - <mxGeometry x="760" y="460" width="110" height="50" as="geometry" /> - </mxCell> - <mxCell id="KLYezTmecfuvBG8KQe-n-29" value="bayes_inference" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> - <mxGeometry x="190" y="440" width="110" height="50" as="geometry" /> - </mxCell> - <mxCell id="KLYezTmecfuvBG8KQe-n-30" value="bayes_model_comparison" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> - <mxGeometry x="320" y="440" width="170" height="50" as="geometry" /> - </mxCell> - <mxCell id="KLYezTmecfuvBG8KQe-n-31" value="discrepancy" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> - <mxGeometry x="510" y="440" width="100" height="50" as="geometry" /> - </mxCell> - <mxCell id="KLYezTmecfuvBG8KQe-n-32" value="mcmc" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> - <mxGeometry x="630" y="440" width="70" height="50" as="geometry" /> + <mxGeometry x="480" y="210" width="70" height="50" as="geometry" /> </mxCell> - <mxCell id="KLYezTmecfuvBG8KQe-n-33" value="bayesvalidrox" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontStyle=1" vertex="1" parent="1"> - <mxGeometry x="170" y="66" width="100" height="30" as="geometry" /> + <mxCell id="KLYezTmecfuvBG8KQe-n-17" value="meta_model_engine" style="shape=folder;fontStyle=1;spacingTop=10;tabWidth=40;tabHeight=14;tabPosition=left;html=1;whiteSpace=wrap;" vertex="1" parent="1"> + <mxGeometry x="570" y="210" width="160" height="50" as="geometry" /> </mxCell> </root> </mxGraphModel> diff --git a/examples/OHagan-function/example_OHagan.py b/examples/OHagan-function/example_OHagan.py index df572a3af..8c7690767 100644 --- a/examples/OHagan-function/example_OHagan.py +++ b/examples/OHagan-function/example_OHagan.py @@ -137,7 +137,7 @@ if __name__ == "__main__": ExpDesign.max_func_itr = 200 # Use when 'Voronoi' or 'random' or 'latin_hypercube' chosen - ExpDesign.n_candidate = 10000 + ExpDesign.n_canddidate = 10000 ExpDesign.n_cand_groups = 4 # -------- Exploitation ------ diff --git a/examples/analytical-function/bayesvalidrox/__init__.py b/examples/analytical-function/bayesvalidrox/__init__.py new file mode 100644 index 000000000..8e865af80 --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +__version__ = "0.0.5" + +from .pylink.pylink import PyLinkForwardModel +from .surrogate_models.surrogate_models import MetaModel +#from .surrogate_models.meta_model_engine import MetaModelEngine +from .surrogate_models.engine import Engine +from .surrogate_models.inputs import Input +from .post_processing.post_processing import PostProcessing +from .bayes_inference.bayes_inference import BayesInference +from .bayes_inference.bayes_model_comparison import BayesModelComparison +from .bayes_inference.discrepancy import Discrepancy + +__all__ = [ + "__version__", + "PyLinkForwardModel", + "Input", + "Discrepancy", + "MetaModel", + #"MetaModelEngine", + "Engine", + "PostProcessing", + "BayesInference", + "BayesModelComparison" + ] diff --git a/examples/analytical-function/bayesvalidrox/__pycache__/__init__.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..beaab3c798a63fcfbc361982388fdf10830a787e GIT binary patch literal 795 zcmZWn%Wl*#6m>Gm%w#4reNc%7iwY!=W|MT&9YUy-LJ>tHAvWGvZenJv`VrYl%kVku z_$5oMSn&(2uy5%A!BI}mJ-L3IBkS30g8WGCJ!aoxguaL3@8LD{+`qQ*P$P`$sE$P> zV;o0;55zzwI02rBR1WbFcq&G6jK{!-B9jw50X`B_nd2PzSj^-c&w*!RNABX?2(3^( z`4Zv1diowM^3Ul}aa0`ti2Ux0$n7sTZ@IcU)8>Yn`a;)Ccs09VExjvtw#7@e;)?nI z>A7mU)|2^C+jePm#jNFO6_gXYVfI{oWQM6KG#`KhtG&>&p@v(nygohUwlb`ts@g0v zHznkn8OyaI#DtJc8XyZW2#^FA1{ehxdw93lHz92|Yc|5$C~iM6-95COF?vN?Mr811 zi@pHsx<`Gvkly|69Kygd?CtLV*T_Q*77pqT8y^K}wpkRt8jkJ`FGD<p-{n*EYVhWs z^wi&7V1rcK5FrEipx<2o$ra*rBSNSUgnUKjAVe47=bKWhwyeqz)~8;YE4>zLN^N<n zt4=c2+VT}|Uw4<~nb0>&+OA93=b8#$8~v#y-UM$6@tM2vQ-8EhuxH^`*|2;P<#8VU H^TfXZNO$QO literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/__pycache__/__init__.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..afe0b0529fcde6ca9dbc06ed8932485f099ca476 GIT binary patch literal 941 zcmZuv%Wl&^6dmVbCvg%=#Y^g<VuKVARu>?lf>_W}T8W|v#Ky8Tn%L81)OlDlPD@zz zFWAEZvEn260WTx3BC%o@sk^S28JZ$n9bcU}_jo+_-XnkS^*TVWZ`;4{Mje3PCRwf8 zB{`Rxd;tjvLE<De>abc^a}2N3I%|Xt%Nw-G+|aeWNj=sITb8@D%{pPna*z6~8+I*k z(H`rEeaqYQ23rf)954n+=c^OmO#BaE(EZ%p3bul$e;i$Z;1uh_*;~So_k=t}GC33p zrdn+u;tZ`4_cb3Aj<wu8;OR8eq(2lY8%hylr3fDz<rSJ?b-<6X#5^{KZ&}4&vLjfE zBvFEE-QOiDmN-Q`o(<ZC58(-xiU<y&)NTRk8ZZvZhJmI5&p^vSTf@7-y7cv4^wJsC z-3R|R`+0F+O{ElLlwrusI4Y<L_TJ)dRSvM7(-yquEitnz+g-7l>iJ=MWk68LZNJ6l z$an(D%9Nmz+kuJ)74`Cz?H$Hf&e_3>jq2g#znRvv!h;Y|3gHiMt{nmw?{~JNk4ifn z$zw606NFT>E8;1`JX6sdlI>4N(H<42LzGRT5#dof(`6GJ*-|Hnl0=G65!7>#3_|Vo zMeBv`Zc6b>c~6%xf0FvCVOe(^XVJfX<}bkGyc~1zEHB3bJj%;42M_ad%)#@#9M>uP aIVi;(Jju(kZ1}#r1S>f6%p>pUp8o>+Iw3#+ literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/__pycache__/__init__.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d5ebaedb4c8b77b5d7dbd0a6945f09079d8b10e4 GIT binary patch literal 860 zcmZWm&x_MQ6i(8gY18gn1P>k-JqSG{?6T}dM8vK_!Ae02G6aU%%(M=jnS`07Zujif zf5Mypf>*&mqE}D;3!Z#4b*sh+`SQIlZ{E!N9vKXJ9;^>vzS3`j=Y6-q-wQPF8N8+d zpdRw5PXpo000q9~4bhNI)O5TlTC$DWj<-Zdc2U>ywg_bp^&IbrzKl@hcvlSM5Dgs< z#gRNl$G*4nXz!Dc?$G`lZyepUPLtE*;)f5XkNw?fzJ0~j`em-)6HRA1WdhW2#!7M< z936reYQ+_U|E;MisuIX>o||&6^Nbn8)ygW*$(EU^S~AU4W|Qwa#Z{Z+vLKq9T!G%d z<R;UsAS&CA!(AWa4bz6_3S(_e(k%<2g@%Qug|>x`g)YGB@km>@(V*B0Xd~Hw+;;T9 zR9fdNQZg)UUnZ#wt}c35mlFxy@AqKlT6Slnd;cYJYlCqYMJEMVfs2C|NiB9)M<-X- z9?Wn3Nouj{4Lz!<zq4E$I6Ii=JV5vB$@Gt}&c0m-V<H5`pFJH}>n!~IIC-2d3^<-@ zw$9H|TFL5qkFkU?Ya;j!DPbP*l995~ES^s0@#SK+czd2)q*oOeG|nVhvy>EtNO@MI z3?P=vbjcMFnwd(JW^?uq+bmtF)LnH0m8s6JQw%=v5@Q(KuKNVKs|0&$M{h;|%^>ps Gd4gX;Q2|8& literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/bayes_inference/__init__.py b/examples/analytical-function/bayesvalidrox/bayes_inference/__init__.py new file mode 100644 index 000000000..df8d93568 --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/bayes_inference/__init__.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- + +from .bayes_inference import BayesInference +from .mcmc import MCMC + +__all__ = [ + "BayesInference", + "MCMC" + ] diff --git a/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/__init__.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..430b9885a8c8bd658da24bbc4ac1a6a0a74f69e6 GIT binary patch literal 303 zcmYjNJ5B>J5cMx4LJ1UHffU=|3m}9D;!`9-LNwc0j&0Z#_8Qq<AV=W{T*)mJSD-+Q z7ez4AJilkZnbFwKX1fT29n8%eoF7H}4+7#8G9ChGq_IT~*BBR0EOE4^z^P^rq-J__ zi>jSZ4Au(gy)(Hn@w&S=!F0;N4O=dji%?ny3b3k1d4F9@qTRZN*UX%9YVhQ-5Yk#9 z-ccBr!UA74cU|I&-$fH550AdFjg*m}d(}JBrN}Sabk(o<h4n8tGBtb{^DJ$vgMa;1 ie?z$d-X<ZAo;G=M?7Z%+IVo$z@;g&9#e@<(`ThY0HBIvX literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/__init__.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..72c63a98588c54dfec12536a99537cfa3a67e0cf GIT binary patch literal 382 zcmZ9Hu};G<5QgnIX`xkNf=57#Ks*3K9S9OIlm)RwmP{HSG{R0IJ3;NnTU0y&;t6<- zj#XABwn*JNafzq|J)h3MeV<Ri-v@&p!FZT|!W-^i&0!PHuUH+Sm=j4PRYcQ}(ndSV z(JW-BnRK6=(3RdD@jKrXVV_oe7tsvtP5KB1(irf@9R;JnFl-wa%dPKK`{M=@$%bmX zm8)YNw@lR)B2r3-53<51WNm^oes958Zl1G=nnaQ1mswnDNDIralH$4?^LFS<q!MYe zDTisKa|M<ci3SNdq!QsRXv+r|=qV|LIL&A4opYVZQo+#l(L(b*JH%2mN@?98^khMf b|K^e$F8(J{-oeuC)gJ42Uc1dQyEx(pNH1+* literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/__init__.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..287257c1ca9b3f3a6d7e176e006ad432f8c685bf GIT binary patch literal 368 zcmYk1K}rKL6ow}=(^{m}OStJ`3Ps$Ah&XP#s0cD3Lm;G+HyWDE49TRlE<J%4@Bm)H zt+$x1E3e=}d}$GVkT3tA{CT|a(P%%wdU|^o&$xeh^S?qg7r5*ZLIi@SK$DyhuR|5; zD34G_BEApvSoCg#asQKGbWFN~OTGa+t4c6X6@Vx4Je{Y;w=@yrdfe*{7e2(~Z)$s+ z$GXtPHq-4f#+731H86eu(BtbRJ*AliW2u2<J*C2Fx85<)vI4`EeB`aHtE2?pIs?fp zy-BXJd3JX^IiU+Dl}HNBmq2;bC@PDF0wU2REoH@(0qaz2SJMaPQ^r+vJLw8L3sbLm h?r(0&P|KFFNwet&XSx<n!MXpX9Uz8e7=<MK{sG1iY1;q* literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/bayes_inference.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/bayes_inference.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e89dfb5e6b3a873ac2f40dcc2084aa52caaedcd6 GIT binary patch literal 31276 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 literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/bayes_inference.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/bayes_inference.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..05467b4a003342c6353478050dd6b67db4347dcb GIT binary patch literal 60773 zcmeFa3vgT4nI;GjAPEp40TSRFB*BMBf=}_G_gkdiqAc4=Y|D0FkQbytk)V75y%@lD zc9Ra|Q94jYX)}pDLDI5Ax9MtjuQS8h>fTnT)6?m$=~-OPoe}m{saIWDPbxDzTk<B^ z$)sj$_WRGpeSwr8>GalAO<z$5=iGbV=Rg1X&wu{^Ki?}aFEim0-ttWU-~Z8M`Y{ER zr!?>RS=wwey<y@^oO#Z4-pqcB&KI#?%Xtg?wVp4=Z_!-Ie98F|GsU&cmCoDF+nC=x zXP+-S@5uX|=bbD~`S}X=>pJgZzwYyH_FH+rlKoblufnf&&NJ^l@13tcU(M1N&(+M= zp08#8lDWG1`t$Yqd>iH)&-<9abgpT>`FwN!eapQ6d@KAm&OX;R-+sQ`Yznu|b|}rv zY*Bpr-*C}vrxMO|DL(zLAx5|Ui{cLl-bT;8i~sV&nd%j<i7VqAZ(Hyc|K-OR*K8^> z9W!yxFPgaWw~G)D|K;a=4`+Vb6sY(q1<wS`k~RJ^H;>=qSUePu1&XAq`EV#2jJ<q0 z#D}?HnCBOG$;J-{V^a%!7!k`a@!?DS!c;gGi$rHA<=Iet>H<8rv)uIA&`db?Q>rvx zSSQ9N#uhCD1A~h-lcDS3*p<*+gyR>k4a{Gfi^Z?cg{S0N$!<+P@Uz?SykQD6Z~>^8 z0VYNGXW^_|G4mC1CHO7H|6<NIW8&=iEt@eTMlt8$oYOU2`4`RStz5+yO#m$y+!D?W zx0Gw-s_@0ec@VO5KF*6!8CQ*vgR6n-<Z9uTb9HblxO%uQt^ux_D?+z5Nfn2w9VepG zVLlw43WuJmG?~i$cn<le=0dTUKfd6<6y~QF_<28z8VN=HhoYgm>#;~|psY-e8;|pm z$;<I@j0OAEhXp6X@zBHq7oPL)_AgA%vUgMhz4y<v4|pA(iVv_)TqHJy5eY@7t`{UY zcOmT8f0a}DQ8#}apJI`j`Ot8z&mS2G53n~}Bs8;ty86RWR4`vVDtcj>eZLao(VVHU ze?Elo*H})d(&f2$gnf#K{ZTX=8O%j4hUX#|78W?UlF`t77`2PV`9A-`rFeu&Q5#0} zj9<SLreZ?*uIlrLBd8?rp908C@*zs%?|x~FLN5jUXaa*J_Fm1X`=!qkfV~tL@Uymu zr$eZlKN9o5)WuSEy(CvBj5>$n$Yi&Fa$#X^lR7Cw=D&(+_|^E`>fmfr#yS3SI9~vA zjia%lOOG$%uo{I1LuvQMnja0##guIM@XNu4%kfK><1u7B7m39;sX8^CK2dif!R2r) z9_IXVG6K)Zu>W!lZxlFCi&p!wu=CC=L{S6(iD^Ii`uw4}IT>EU(~+o}cTCNZ0jZi> z9_%m*RIEGzu`uR7suhexxd>1RT7%!sT62hfAb{bo%Y#APrKI;O>Cx73XzGG8KUg2J zzErEh>7YSt&`ZoKHwlO@c9{>)1N!}!79vq}GH{^WS&=BUSk27XXR#3Q8EZs{=R?=2 z<6{>>0O)QYQu$k-KN`Fg;zRSXz+;9?$wW6oa-kmq8)`e$iqRW3HcEEX0*((|jryng zg?aV~*n2WGNgxuLLI(nx{H$u>c$il+%8weFLjA3RJz*pj^{B1G@S(dlY1o;|^OKmw z)FJsk`ZUekww0dzlp;I?2vqU`I7JuYer5dP7w{s)&s=7scQpbC1)KvRM`j2@Cqo4B zKq2};jBcphOyo*9Dnn=<7`Px80^0p#;5oGrjfWypEQ_qu7A9k1{)&vcD3^_MTOL2P z&m+^i_5dB~)90sJ9wg-T!7xT@F4|Zbrd&i>vx4*C_=N=yZQ2|iAM)oT5P}F@0<>I< z0O2dGy0id%!bk88Ym2;&5pK>`Oj+~P+Ni~%wD6^kUC_mc380Wg*Gql=s}~}e#2`hY z9788+Hfk&x08p6$EV&aQ{^G(F|JViex_<(_ANG%h__>8Vl+fxCB{+yhFhQ@YnW@-g z@;V@&(J@#dh*(h;i214csr-EXgk#Uv2>@V>;oJylClwtkeS$v9lMM`!snvOjN(O#C zhl#ckOUWbyLH}7sUm%jccC^wmXq#S`n_IYwj@hlHpj7+!@7E{T{du)q`btk1KsK%* zs;=F6B=2uWeIxM*R`dLv+n6vKyc(Lj80KS0HMDhWpC5^|S(X3h@1COZ32c^}U?QIw zGrb`Fd<cMdd7c4|Oex9rmEEpraPl%AMajb(QqqThfCS5aW4ZGSSHe^(O+QxV1ietl zD?C3H2Fx&or6EM6>@G&{XcRE=VM{d2sNmbiqOXMc$%R;0Nre8A-$ddXcq%0&)#L;j zk$8AMhIM5Ds5~@@3bVzDkh20apop;8vvoQYCCKJ6k%4_9TIUhUM08rU`xw+1(gG|C z@FuWzBu{5f65$)1TUeO7f+_JBvPlK?)8WvSa6kIDAB2a0j9&n0%!o6F4mZMjp2`7+ zR~!8jqo?F*o_^wqvCsNhr*l}MiKJsR4C)8+hR~Bd30NhG<Yov`&FaXN2uI|)zx(jS zkwBg#4XQ+1FcRm91o^l%Oie(8A=9KATQVe5O8V~74S?1tGy#9uW`ROQGiV^=3vr^I z!_gVgocWd4un1rgQQH&?=LZJcjre7L62w$~soF?{s1;`|C0Yd8ZbpcF1}l~VAheH> zGxl%3dOiPQA+;NfE<|EP=ugirgf^oG4q?%z7<1t(*x#Vp`7&f!q?MMMwE+`u9oV`p zU)Jp9SUjkZUyldGlZY0Xj)W#7bC_C>C!rYJ$pFDN6tp<<k*SX$uTSSmYZ@??L|)+Y z>EybrxR{nwmK~8{vCEe(E%2avbr^bRz(2Pz69ibIE%0H76~8dA48A&@<ZWL#55_7C z3=jBEogPQZQ<vxFCPPyf`%i}>lXDouaZob+48gn_d1QbVpdjt-7A{@i?LQHvU8-FB z{7W@1AshuY07_qazAInLE@jLw%`L=(L<<DL4<KUVF&N=2;(?l0Xa<T5LLasBQx3pZ zg+=LhQLK#l(4|jO1PzDWOUef63O3{P65D3^gHrZFRKxZ8HAZcCNULka-<?O5pd<Y+ zA!abdTFj`Q2zH?=)vQ9TnvcHo^gFo1T+nfwQ(+VN#ZO<M0Z=K#o#}cB0L@VV+yDvy zxI$M#kvUNH*vjjARILvUVm_@5?cnA_!+bCviO+?D)ARAiR^%MTptTX8qArozfEtKE z8Zdd2cIi53%&1!YCBP;)L;jcKVmBdnx(0^P6mUpr^*eJ;DrOt@qmj&SnN5;iCI5Kh zIR50D-=OE61Cj+3N3v3%fXy@<o~p~Ukm!eaUc?{!*;9-InJ_0zL3+=ggn3rwtl_=p zw;-f)%Mw<ER32NR7$K{gLkU8~YN!;U5;bH)Na28*5_W`a>bEk4>}tq?5aXiKn}ib~ zhx)A?A*UL0BUG-2DiEqrLoS3|YN!$+w;HNK2wW=pNq7*dQbS&ZJZh*KA+H*$L8w{{ z)gq)Y=)j=`Gt7J@P%D*Su>v(A*(VgPmE;)LI8u^LVVy`;;sHr^bt#e@I&OyKR%mjC zBOsOLsZPnRZZoBF!>&wns|0m^Pa`>Wq_I??E?{hBlpMM>S#pDXR5&nfRg_#>m@QIL zxnZr5$_)zyayMW=@I@)CU@OU8IMXF};gk#1Nmev_nx{VJsjDT2j$g;u(rbcfo;bgJ z138W4_{eD@r<t4<a{T19k<(62D>=la=7~Yg6E~VCMl?^nW<Eep51bffuh5%?zrT8Q zZ1)R95yW1=HtWLNg-|H=!uY}z+hfOGI2MT?zdZQ@>r~b?*eJdbz9#SUUtmi#7!0Ag z{^`q6w!tfiDvyRbgz{Gme}0cNaOt{a3nGlYNpP{2ErnRJWWMWw^5HdV#Qy^4HPa)n zskSL)z3Ir+w}|xt_$qRZohhqmtIO5-5iHMn>+oaG)wdZw`nOV~rd(|^UOSbqO+ECs zA*Xy*vTE+5_l;`S%J-H5dhg3A>6Bk3z7kgA=YO-dCj9*jEig@~SO@`{%?x`@`c0-U zo4!2y<!xWy{)Xv>X%-*kCuv4VO*5-vtz;3fn~JrPmPFC4inV4{jP?3<LuwUw&8m1S zX+;bbZ@t#LdHjru%anT2FXF0LjVm&qLEO+`!{`%simR3~t75-oakRGG6xU(&4ijHy zHpEUAKWB<subQq|o-<uFCyF^UXZ{in3=)<v6-^gu=Oy|Q4W+60l(QIOt93_g70bTn zPZVWTEL+f872mE{jb||^Tg@R(b2I<wbB@zY%|Ej$J~sARtU0bbYtmxr^Lc#9h^5vr zqvCj_O!|Er|KC+#aK#rHJn`j#9(5H!Thuim>ckg9QS8xwi4Q4n2@bfDf_B_3=moXo z<D*(SV;a5!^;hF@rK;ET`e?LN|LyfrL++!qgfQ9j5xMuKMyJi3?TfY>y7(EwvKt;_ zFO3)U8hU}yGJB$1?WXuXC1f(q5}Ia@zLX6krlofS`VZ!l;0MreF`M-89^a;YHP$Ox zV(0~3-#xw;lBJwEX^W3(dEVG=tlhZjMezkdMbe%uOO*0s3EOLjID68j?|=Q+Bprq? zW!k8rpVWY%k7xm7Pr{*%Ttb)9Sfivf`XzlCTAD9(aSpUb-~Vdfo2U55Ql5HTf6l5i zI(}TKJLVF4Njr0mjc`uZODZ1Fm!)C6Srr>4%MCSG=Y67FkEaUz0@PzkqHHg!ar56K z45Je4RO*%}(YHRRo=r0>td2>BsDup<QmS~-ST@F!NDB5uOWREhPAxK4Myej=Tg-(} zuNtB{_9>xs34cHSyb@w7$bb?umd07~xT*DqDKn_V(f=Y}wXXrihS5M>)qJD%pR7cr z*{bAUfZYnt*ZJEhTg89;R}lKNc$cl*{3WDRSH;Y*Qo8<^v#eAYdnPlY|E~BsSHdz~ zWQ>`tNSHG^e5=I89;9N$ZH&w2yesKO3LVDLQlO^Wl~964SZ(o2rBO-&{kTJkxjBR* zwF+bKtGzy56eqyWKeIa(-%6Enbd!~j%~#FK*t%rZr%vJd)G555Iz=^Fze{N)fBSKx zg;*+-Y&vc=$=XB>`hB;OSE3f7Jxb_fpm`ti*PxjwMs@r$y75qQW3yI;1;kcMHI5R4 zs5;cF?vvFlVdgx>9C#aOTot<~>!Y1mz3QXwzzF-b+Gsv~KXKlbYGZDw#Q`NQ<rDvc z5;B<#E23#u#T`Z{LjEdzaW!1+O5NL_x!+ak?r~Gv^5UPfb~n7f4Y9ScB`m1+Q?ilK zGiq&;jrgizOrmvEjLEkcpz4rP=NsFMb<?jIXz5`kUi{07kBys(F*D=Zd(CI0Ftk;R za}mw0E*&Og*-4+i6hnQFD0wG*#x%xIvdNIcSCmvHNQupu6HSYFk!UiGXF(3lscot4 z(?t;HG0-=OW@EfUYA)H5uyIa#t%<n{W=eyxM7|4<cTB6B=1VjtTG*<qu8@iPmBzQR z4|^B?<tI@o?_3fM(?v9`qW+K04LSIX@Ku<Dp{G^K#PIfnQo7;oN#(6RM{RTsSoo9@ zw-5^(`_&i%2daVEXqW@k-qT8M`d{ihN}<)jxS}Mg<lHzTlzdCeLr<5@syiQ)enyF7 z97$tsubB7;T(bcJf0KFtzM(&#P->JptN8T49IdVD>S(OBevT*ozxIeesgzeZqRG}o zt0C8?l$eQDV~;I5FdzLF8EhxpP-As{O0;RCm~1!XrqVZ?L!CaQv9x4IqQeLui|C<* zHxCtme<Sy!`1h0^048dQzoUg_Kco1KICBwwQc(LXhIF4*(j~SS<83n~J2&qy!`o-n z^qrXr#jpRxXlVSR66MS6v#Reo#b?O(yz(~DKC4pbi7lK9^e3oQofN8p(l)li7)o{# z#^cOJC^nm-j&{?KDQ3M|B<~(*Ct=1v;}|Ep*eG`}w^|<S_&--_iM{rVil6hZ6u_q$ zEAh?0NK|4a{G1Xi;Xx><gwRX76hB{@sKU3Gl<?mpo+(XuQBp`P>F*DAOB0|jgOf^0 zhW6siHS?^#FVwa#Vt+bSWay_UC67<UQ)<ia+qTC4Qb|YaKmlZQC%Q9X?YrhfJyjYd zQNUF~d#06`(Pt3Tt%N>N&Dxb6<zsnl8WyvzbQq!5P<B05vKggp{jU)h=+ndnEgn}e z^UWs1*G^+!K`z~F;2lPkoMvYgU+|*h`vh_4l(_m*(VJ@DX6BU``d?$)3hSuPi|g9( zRo!0@EELMC^Zy>Dt1<W=f9jD{_?Z6!DStg^El+f7yB>_2x&w;d0e$GmLr%HAmo(}) z8HhG-{zc_g7tKbMzI2$3eCuQ&5%_!9`}aI<H<{?!bPxF(-}_^ZEGTW({~F;4(A^Cl zvpSQ%W#R(*@&A_TO>43@{<m5Vvo9<DL@)MWJ;r&8RfNV%=C7PgSTnp5TmPFfffwA1 zox)GFw*_1xm5kB2f3tBVwh_LKp~4-8@hj%~e^7G48g^On>)|JJMR}|LHTGM=3YCby z@0vO6^k=Us@wk4jmK)#(BW7+Z{?&3r+|bJK+ra7X;=lYP`*aZfw+0%ZO^K7}o4uy^ zjrHH0`=sx?M8Vm}M}6DCvFd-^h!o~(tQEM{iR3_{KQWLP(4Pq<2NQ#t>q<-Xzv#8i zs3h8GvL`X10zkpqg%Q+2O=4g}O|~buvYKrD4b^1p<7;wr$IWE?KPhzvJS7yr5n3=S zbR&x1s%1TsRATFYxvj<)nN2sr!O>AmPHv=N#*V&eNe)HJ3g5q3lpIR*WnR(euK2kE z{sq-A^Q!Vy|I2Mp^nS~f7y@S4@urpAxw5Np#-nzxDJgi+SD7y;A^mS*k04c#@;z<l z&!x?Am6L;>{2!HXnJ+3n{V!72C}H?jT1w;Z>vwA_yNz|m3iBl;wPE~zOL=RoE#oN- zCkIhS-Pz=9N{NjcsQD!Zxjn#(dyTvUP{fZ<tJWTA_W^6{UpZjpU0`$uGdGmd^uOG} zLTEwE*Yz<JKX<4wCTdixe8v815B?oq88hxS3gYZT{q`5enJG$+pwydMUYaj4vNB#+ zE_!R15`%YgM;-&s1@8%(4P&K3>&HW=A>CJ$vW;U5yz+@=GHU<ZN)8O#zp8}vzlC|< zAZebXi@&W(Ydswg@lbvt={ZdtqfGt$R2X8RQB9~gufC>!H;QUNunc+%>PHeXAptcO zNy}c<D^Vk!kxF<-xh>4|*i@R{fi~e3lsKefNR&h-rOLb{5UG3Ql@yCFMj;z*5TYnW zN;*#e8SzuTZhpfQF(phdwk6F8b6iF7n9!>KMv*2)kuX0Fx&Gs#o9$1V-Z2F%Qc?60 zgm_-&<5HO_4H%>M16w8YMafFCP%)x7{QlSYe*FHbY%d8wPA$w|+P^qr?5Y7M@<EbW zCj+y0ZUOC$?H|w*NysEdJnmmY<i%v}IbznkKYDVx^}VN7o>@Kje(>It;<jT#|8cSZ zxIT*P=LeC6WIiMnvmutuhb8lv<Y4-qK_)LrT@E3{7!$dB$IPUTNU8G-<hbyym?ND% z$;!`TRP1L-BjhZEJKrf{5hcsT@b$&E!-|O2B}ILNBwf*@DN?|L(nstZI;)roK1)_E z9GjAgL$Rqy#4wB{s45#qYWCNQ^21oqFrS&ZMM=wzV*P;KuqKK~3Pc-13|hm}CZ0}? zm=h@Bi47^4Ba(TRr=tW^020WOQx+f%lDt|hMr9Msz9tVJe*ocMYuug(kj1D(Hg1-t znnxzZ`QJwNt`7ad^y<rNt?AR5%G*z5&MmhtA6jm|``jao5{X5ZN3Arkx(RLF64@(R zVsS2D=AWZxST4?Sk^{r4$ol5@qyOiDpVCyq7?wdYI4{5s=}G9iNX1No3&UDEwJ>*i zJ{tR#xomMzRZNvVXH_xY*yZ_oDC8A<UmPxY@d<)b#S^kZW01{-pkxlB7Pc?|FCJXD zXn+G+gBctULz|}a3{B@|$UzmU+g;sc-h3)+l2NycZnoqhB4Fid$(HOVNF9zQEhHMD z%@ct-YK+O?1uP6)_@@z#?}bx1t4W{kQ_pHO(SJ5Thq>}7&1%)X*P8Z<m91iBuUNTl zH6&K<6f5`XBglRR9RbTvM%eRb2lBM&!viz&oBwcNMwXoY%L9^a8tPK9$YS`XJ~ZYi zPdopBQ!0TBad<8!*`b&ajYpu>C^<;yL>3grdsSdqvazU_LY!0%T?|M*#xDfp;cIcp zDaW~ZmDHgm7n6&mnI-E~N>2GjI2wawzEnO9os%GG&MjQ#V}R#*po|NWP5vF?7Ttp? z*aa~#@t|Z6Dng}!qMz2G-an-+;;)JZ27hH8xWr8ZpG0OZ!~sT*$;pLlK&Mj|!ZCoo zmD(#6&+y@JlyG$D8kUoVIViXnLtm2vGMj`3&7ysRDOr=Mh?OVWiT^Efz6?hyW{qBS zK^(p#`1zr&$quGcvgkR>lqzLy1L&Gi+ZIdDJu%^@Y%G#}Iy4oQ%d&^L8QIGd*@SwP zUcf?!u3jt~MC>3`8RNk~nn{E**-)vN)kv}_I;2vGJZYq2hNL9>k!zR6!=&pd*|7}C zs7uDf?)+2_D+*pra8xS6e221-RB=erML)tc{i!1$Hrq^Xbz?Q+NK-`7Vq_CRDvLnz zpH%dw!cx&CPO^_<Y>z^<6<rGrv@m*;>6b{A(I5~zL~~WOTFJq_1R1iSX2(J(UY>eZ zS{8Xan3k+qJ7PS^8t_Dn@w@4z{T!AXxsvuUl*|Z!p+u(a!e5{mz=0@xF$`rR$qp^^ zAj6FSM^dYi1H**+6kRv|8Ooei2w8A;3(ExRH%xj~Di7x6hne)SELKY=qkI*`E9Jwi ztE7rBT0`>3vX+5Vm0!f!8k#3f9Fvhy3~)$_+mcIOV>N;4Ql>34w4Dk3N*yvHR7G8b z)PWfIsW8+au*foH2+0!!!Y_R3ma9V0D;Lb4qN+NA+Iy*WWA-e*mN!r2ic}h1h*DQF ziDSu1h>9l5<!D?gfdnuX0Lii#xkT~!d75+<ObLWSQL3(F317P;mCY?gXSjvS&`OZ} z8_I<^G#|vYfF3^SzepCyPRoMI#P0)Pfk`3BeY1U(zFw0o(9n`x1xj|3ed^L>U=XUB z^(@r+B?r*S6rdx@Amk)r4aq`vbTDWM#x6lANHU+3ie{$Rf=9~elATmsNS!h!mFBfw zBv0Oh?A6Lj7U<mYbPgg*UOQMH^OqGdbsiW_Stx@j)Du*-7vwnzQb;OBf1|#ovM~gd z$VE`A&~-?#L(e3?21_;y@C#RCl8tC17>xj_g()Pjm{PT-j>4cqR;-bV0RKpN5t=rH zQGt@f=*eRA=L}R=sJ11tD7s{eF9b1_E?sBB;6(1B@iwSn1+UFT<|XGOI+Y8?FOzmV zdT@?FU=Hewl68iUaFUB+5>CydSd!Vl0`0;XCS@+w1oI;CM#UMPmT^$?7b3%wg};IY zM(O1E!aPd9JW0t=UMz}!xyXenD3!^zqSZ<EUuT$@C%!yZtuW9W2Lz9$ipjZC-x%cc z<-Q5*U~9LGT4}Sz(|(En8acEM^2>0f3Ke+-r{_X5{P*Z(DUeby!d>IfP^gk^Hi8&6 z#rOtKr)W}n)PV2o6Nk<Qv5x{-S$sW+fMmbUW-fUv(C*W!p$v39A^$M|8o!RLc##|e zGfH|PguZ7<r7{*`5GmPVuz;75VkwjuseXVU836z-#h`To{EcbJRNdjp+e?t_v>>DU zfP3rZXarNkP?ONqRQM7!)v%l>pe$997YmIcB2fGVS|%j(B^m4yf$aq(8)-EMpO~EG z|1Gt_PMQ&NPm}_FQ8eZWKt)~L`F}^zimpf4k}DNmi%2#aLZ&uiK}^Xdk8%*UBWT+f z<7qp<(_t(BSvavBa9$!>{Zl>%4<2M&GiYcO?7tRUK4ydVyHxH6AU}SI2m7%)Q+56A zGbww{?Y->~-L0wOoX016wxn#iTHo!2SQ|(=p@ne!l;{nJ-jS63QHjavzPUH+XvsCU z+}R^GZoS`lXua_eWl)i^eP}WJdVX$#lN!HyI(7O{iKV<N*U)^YPi*K<m!?a9`M}c( z;;+0*bJ%D4mM(o{!57r*k<H|5&kV7Dk<7JBB(oPKQI;sbx$VviV$<NNS!^1{t22n~ zbc>FrtYb^Awex=Kj`h|ZYv=yxxoqnWq4k*9dMq_AI-5Um)h~634SnxTuFMIpJ)&z5 zYG6NXe$d)}*SE}x0|$lHLt^V87FllPuCE?={ea-`i4I?;bluUFb#&#n^xS=(qO@h5 zZ4bBfh+DR^&@W0%?%H%b+q6}14T-LyM<%De{()R%&wJy_OG|louC`IE?OHAsYqzGY zY3oB4Oj}vpJA?0y3a+i9YwIIZX?gvlqQc!Ws*L?}u77AHc)$P9djBDze@yHjL$~4e zhwLLdAO5seba!Umo#_9{`Um}k@&;SzKO*)YNso)(o~*a$mk(<F$gr|rb1>BDapYE6 zk3slFnW@fq>&opbDd&Uw_RP50G5UQ@sNW;j?@3jVYKr}VZ%bxQ@QsMRkw+%49b*dT z#_80t^wSSrO^;0O^6i;Gwr%90uO)5Ib#x<#)n~+xeOY&FuDwfaA6Y#nw(q67`XAIc z-l;=Wv2FiaOl%ty>c_?U@pMVL<Y8qs+e-9hD|fPtSkz31*fuP-?OU4?+YSr$V`BXn zMgE|=C1Vx+TSfowKOPgR4~o?XADOJ>+vOVgJ4FBR>WJvyA^P`={_%9VoY%h9N>oOu z-zL^?LxKLz)afOU;B3k|n;vdqYBF`Atu5C*N*XipZb7%&D=`7Y#@_pl+t(Ynug2eh zMQA)KHXfDX{+Ad##BjP(;{?uZ((Hd^iWS*+Eu9ma`epB`R~#DqkiC82s!ETFo=(Bl zCAzwnht^$vSy$h~&Yt_7JJ&mRqPs<J=d$xdOHo(N&rNWs*V?o0_FvdcfxhK&vG0J; zeNgN^Nbk4g!ExzD!PP6edI62)HLF%}D>?(doTv8ot~U;R?SSCv5Ir5srR$!-tY`3{ z&wuCieP92&uYYwY>+2VM+eF{C`@VhazI|&i-|JqR7ksBh-|4g+Gp?ime*2#F_C5Db zWZU-$?PtXHGlJWnE>2%ZW4nj$ca5!gjj>vHWWuW*?*|@POx@#v(V}jue>bat$1mKb zX8)aMGx58xtj5J1r?Z_C5BdgHP67m*cLJW9cLJQ7cc#vKP+NcdTE;83ZWn5IinTja z#~;+x-M&C$y-lduA=d0j9eYsaz1_VuF8YRqsu8hjBsKP+!FQ*d0C$(rut#jzlRAZ( zyS+D)k4$ytt+|%&`z<@xTXx*D{?M6i*&(z{h%FPhoM^=5T>mh2WKXUavs83<qeH!o zOQV@4!80g&1|OM<v9BE$N5`2j*WD*}@4eqWvEDtAtMiF<-OC+f&o~Av(16AU8U*i_ z^vO&yx@LGUO}~NM;3)m}$@%WeObecV(F3rsRBp-n19vOZC(<V#`a9?cb?zO!-?MwY zXLpW<X!#=gvUd-<vX{EDmvv<q@@{HP+mT^g=L2uk5+^nf3EpARI}H3PHVo$K_uV`9 zsMOk4^PvgO&&hcNMbh%Xhs?cIo-SSTKB_PQ+heP4sob4w>lEAercb3$JtW_*^eL19 zIP|m=!Z>Ko#Ko>%vX>3oYFy~sEB5VOdlJA%tqY(sbv_!Af&0GEb>FDq+b+`IzO~TW z<l3a@J0#Q|7Hba!{WUbd$=|uY?ES{8cU~1522tU3DZPwk4rNA`YrnH^wM%H(Ew=2I zM-od#k%7^qF{eI2<7WhKC+5qeV#N87*j7I$2Y~B0d7Cnpbx(WN)Be`g<@oAzLe~MY z>i~kep>6-n_lLe*U3=!aRcEfH{Z3-F{!y`Mct3I&#yG-BpUE#uGnw6jcOdH>c;qw< zZ`Y^uZTaXlzi^s5I`3|O;H|lR5>396iLO3L|JF)Z&x@T0sV64@{(g)v9DqObRqutb zdhdr8O9!>3qXvUjiV26}mGNo-6yERNzuvt+SJ#@^yIQ+eD-IpfU@(1r=^4P`qcW4X z{>|~XJa0XH_c_7|hlSQLv2{%FVVuUZ9{S69{BMoF=XvkxmFL#1;?9#o;FK6RC3Kt? zJ5Fak^!Gty)16)4-v7=0;QO6h`JB**^_d2~5d)7=Z{KpabGdoV%>M0ID-#1_4+e); z7SXVFYFIlptbGq4%isIn;gzGSdxX9Ngu?s>?v1av98Vw5`8)19m!B2=+tVkIVNc&m zZLY2}^D_Ng?#e8Rb;GMW#X9szQ4h_ro`x*OyUf(FeXaCfskrmF(0)8Uwp4nHC<brq z$28|bOIv2!dk4hcaiRC9*n3oHKPt2w6I+g@k3XpI7VG<$F9`KJ#QGhNOeNLLYeNsZ z0(Y;z$FIDS^EG|@$TyErZ5=>GqJNL*Kk&fccDG{r`pW0mj{j&V>z@$(6QY0O!{VZ* zC(NiS+z&0*t<9K%Tbn;L6?el2XUX}<g3MV7%=wVY`Z+n;yUl#Gz-$)FZR#6Y-68hw zS(_7jPv+`+K%DjUrcY%`1#dT&jY`k$vP>xJ?iSqLKyk7M$Oa0aL{*i51j|!gGRicU zkLG$u7&?6D^1f+(^Xa!dck5~C*)KF55StDNbqB?|gIO2-<r<sQ*4wt6%lDS`t*77f ztke^_JSuECCT=+<_>YVJ<5?H|<=O`*OFzm}irEEXGVQ$WB<#LZaPK5PJ`<7WzwhW= zcXSGlZqd=be01G0oOKL;P}{gPerxgeVhUi>ecwO2?jJ=KqPs0~8t~Ctg-&m+B07y$ zbhNOd>gID_4Za=}%A3XV=1kXmc_3RJ_yEJ^1T?>JZ<jh~x<sv8?)!JHqeA}Opf1=4 z0H(bn#och+bfg>)Y~|UC5y3Vp+D5as(OjVaD@8ZUpph%uI&+;pYM>nvQ=C}Qa=)T` zy`o#F=n*S=1Y56Y>&@DF>ErZ`@|)$Ua^&vxq(_&U1V@+X0C81quc6-F%X~SP=jQdV zzWVyBg3B+u{F!6xuHLMx7q3NE$9-4Nx~oTU^@*;&)sl7B_N;4ru4@p8j{3SI>+Yag zp<+TtjE#zzkf+n99};Cofwe>QFMHtZz3LyfWDlN&FT3}w*#2ai=2TPQ|6fu8bK72i z-`2KnYZGi8qOBuq>j3ui?9FVuyE|L82Y;*9_wBMTRr<hIcGHnQmf_H+YUdIVRWDiA z9gSH>W6oK9-|1U-`ar6wjB8rX6jt^F;K_DcM+d~_onrH0p<zsH7!$l$*%*y{lqhb* z1}cLK)LafggM+20yo!kD=G)24IqVSbZ#l5O<$$o|khtYgu5Vjz@L-nxVa3S}j);Tf zxq+eF$d25|zBN8Od^oplcWxM=9l5?ie0fywtQ+~z1n1}Eq@0hMb**^dslL5)31nHn z;297-1NS}K*FD=GRC?3T-D<ww{FW#4+;^JqHfP;iF%!Hr6TFxS0Igczn`0UKH_qHS zBh>VYHJ}lT%a4PJPj0#>S6#o<wluladHV$f+*NNlzUEjOzjF%2mFU~Q#*4ngf_qGK zk7eDUvRX1l-w50ZJTetkQWoT<59jKemL@Z8OVf9J2zYDWIQ6wt8EYO*9=<m$`i~0U zW1{z1mi;{{rerjuoHy<AjKXkvTEr?MH|&kfNgd8PE53T{^<(KHH_qHVlfu7;4%bbh zSL{1-wFj2Btn_4S56FM1<Ei5hYq!hqwr6X%BWUy9w{@)BIx^1+wgJ&LkhKlu=$&uf z=F2wi%5=e5-U&zk%LTTA*0MKYpzXsLXZtW!V;Cre?KmmW10w&vvuoYiB{&13Gmv!# z2+Z6!K{hnm>;9h-lYh&d#c#jz%~u#o>Ldgs_8+)s7W)q)Z~p-3I6sYxpJ6B;5OZzA z?YUdg+tC}xQe)|=zj3;5o?5aJQTf#B)q7mlc}j4e5}l{uVc%%$?aWjyZ(sA~YFg2c z<?YC`yd8O#qwmPEnaW*Xop^mB+t4dG`$T77*4alr$zBZ#&aI+zYu33Hm94DFl&<c$ z7s$F#3+~gR`}E(qt1~65o%bB-8&Fj(RjDWBOi#RiVre0DLU0a<&Vj6R;33cw$ZJda zwp`=B<>HmHY~w!pFKtWP9yX53??$tYqiNd*)U<5f=+ZNAG8f>;fA_kw&Xa=kr06^e z&jZ9de&giLlPTssapTm@Q=sJK1p#Ygkv;H`#-MZE*(o@?MQ3-`*^PRn9I-L5JN|Ug zd1$ZcPxn?Hc3XbnGQ<4~U-Pj&roY%zcHCz9QK=d3zZ~wEs5Sj{ZP7%d<^M1r3WT>8 zf3V#e-fjP2pBe5HahR2d*ryc!Sq=DtZ{R>rJIaIU0&_xlgsYv?C#?yqcD%=qfQyqQ z32VGm$rh*j#Ajqrp@5i6XG&Sih0~q)!`Ml&n%Xo=hrsONVW34bp@3Lwd3dkInnmr1 zG0C3C)k%wC6hhJ0E?H_wZQnG{GUaWe)R+_Mq}Go!uM`=@XP_RfenoH5IIssIfE&c} z6Sk*KhS*Luwyq3)-)s=yv;C&}gzC2!#m5_!I*=-uzO6=qDu}c_NZKD$`{G2&hMJo7 zImer{QW6D9w8q{>Ij<$l4CSZ-SqUp_S6jbSlqk~+{u$FJ9SH|#&WjVnvNeSh7E&5X zIt{t10<oLt8du>EqgtudK0~Kg8y*NDTl6zYKL?D^l5jHh6$lW#OF{(ffm){8DjJcS zUw~5P$HBcWhOzy6xKG#;c9!Gc5ab0)LS-ma6%EP@Ai)S0Oka_~U1of<(4dc>4o+Z2 zPqhLho3T@KAt|J3oRGvRA|#Qf<}Txqg-Jav@DX<OZ#2OQj=5|*i}=ehMf(yN?-`iX z>>|EI7X8S68SDxBhq->Ga<WlHo{3GtRvOh-tp!YXlgtmtYRk-e(Wx73s~Syl=M7^~ z$!E!oFd25-Ab|yO3pHQj??dzocELGVFH?_b)$f$k6WY;kLEnHwkF!eo92vRL>7OCx zX}nO3)X8!E>?B%O&5x53gAq!co93&@ddg73S%dLGW?)T|Kw~0d{1Jd06HYoa^IzWi zaD8I(?16wsHhOfMKK%|kbbt&Qrx*?<`8VlB8#(Rd{44rYA`gI67J`|x5DwmlA<w{M z5|km}-=@evCg=B93S@=DSIH9MIG!C<mdIAm1LgAJl6oS6<8HEc7-ZHCB^yp+<fG*O zSI&mc@o>yV2Q+0`Z%8FL$T@*?919&bF@c_9mQ9Srv}xGXhn-sR@8b2Mui&7<aCZG9 zCQpoJ5Kbt%P2iB%^rRf%S}r+pG$DHWa5~}dzFQ&Kno{NIE4kLdd&4U`SC0$5`^4UT z*`9r3>wd9y9O7i){exrM3>r~%FbZ-H<3h9DTWg+z!21S!bFQl4cF&uWcP?bE-CY!# zhsEaMY}2sJMFeZQ{;lD=`&K<d`!=zC8)H@Gy1~*kH}rxuZ0H4P*wC9g`GK=Sbo!Rg zFINiAUeVc`b@t{wwC4m_3sz)Zj#$~9%T}>_f7X2f1bG7yehpQrlc-D6mOCfkD_XIw z*1g{#bngX2G268lyt35E^vgFUh{%Qk1hIXm(6CEv0N>47et<dYk_U`A+O%4d_3x0` zqhP2t`a%1@AhZsPt;0g&h}Z}gy{!@~KR9W|84YBPFF#5DRxQh)1#4bt*d{h?OONGh z8<s*}yOzF|Yi?h%<a{leUcuL&KJoxuo$atpm8oR^#xgaaNgvcT+_B%U>s|+WS_u)b zYb&p;g~Y*wLfs*;?$Es>LfwfEi&du8_);bNH?~xB3tLU>={kGveirh7&#rRsPYeC~ z#QuHRzJ21B{pqr$?Si{4>u!6<dXR|<O{o+TK!|7oMu)uuQKUCadilu0buVd+Q_TFM zQBVmBqcQ+!+8U88HmqH0iH5f-tz~$tu49Q}<4W;SAy9#!8A&lPS(+%#=qMbezMvfR zwO7|GG9NWv1RBave`8rm8`eu3t%QjZrhJI?j}%@F^;TQM6&u!Km3rH#2ug2Qo$U!b zTkl@QAgK6o3c{jvTLfF1=F}5o&8m55(@Pj|IIY^})*<Fkwtid#+CTT)*&}Kt2<wa= zd3x-r6KBtzc;bw<5|X?JBFmx`R69eG$FDI{u-pyf&77RlkZ5e7@T!TtHQdKE>EqTK z5->o`P#hDrF_d+BVFv4)c3p+~@f_qSzXhO~kpbu7pZp{bK?nI4;0u(=%Yl{THYD5B zg#`#nT)ZwXI2Opq@PCY0kSWDVE?GE;FxU|%7+aXTLUL0Pr0=B&=4-M*kp=xBnWK{V zG{n$IV8FtKuRy+O?$U*jERcd)#)#He@xNa_wl0NL<{5~$EY=h*0`mKRMCkw9NcfuR z7oDbZciMX6#LW{a^8@UvCzjeX=d#Wo!Pz4^d+^RxdGpHGCvQ)``P7|fGEaWv{GIbc zO}ALnEw}=r3r6*F6|Qv0jSDGD&h2@l^lPPWTJKaWo0ms3*H_zxy6s{e(990ey#puT zRW(c1xB4<(p=t|a9Db+d`&IAPteOA#@E;xd=XPP}usC#B=sqk|9Zr?zTs5f*S-8~# z(Fnr^k){(vOoWm)Y!Ek<_r&(l{8}%z1V|x2n$%}TMM26p`qgh;3hmWlo2R0pXd|;D zs)qGC7YVZwSr|5v){Kg13d&XUg2b|ERznhqwqh|NBW0s&H-TtZV?z4{c1rbO=-dGL zamA#v1Z#lSjJicMlwAtMZa{X>zb-XeZ%Pz1bo3oPIyyqKgP>Vs{-X;#ggiOf+V-bL zF?j=@3hrRHM0~1iGiV~H*o;WTjpl^O#Jh&7Ai{&vHaECSnVrIS!kKh|1G^}NZU+Eu zp103UGG4N94TLOl2?|VDgAm7E3R(%23vDcP_J6wo&|SLD`8Z@HmmpKs%Ec%uQlk7P zn0RVFf-d7Tj2b0*QW8}{JNQEwHlD+n2OOF-DbM7dZs9HekIA78t}Oh-$lI!ot(4_H z9T4{mLOP42$^tf-)b&wX5{S|ys$is*$sgtG$BKveS|l%(O0$3(L61zoejjfZ8wydE zCbIZFLSO$HkwCq6Y>=;c=%`8^_=K`E`4gB2P5w;nH(t2&0-eh|Z1mr699eH10pIcF z=}dcuyBqmVKRAiLQIMj(A&{at0JqhFGJg3{SuunV8d~mvDLRV3W$#M8?88Y(Rm0NL zw+2#UIcMd4XVbc~Y3ahUMdc2HL1>g=c<AzFZN3=sQGQ_UJ3M6i!BElRZ59LOQ%SPd z8Ro-gy=cxfZ%$gE52O+q*yO9^%-hI~wgd7*OtQydy8=uFA`L{0@@ydYN)oWCNpiCC z1KfhkxO8D#kttzGlondPOxhFl#a>9h5wQacf+esq$#60M8RS>YmFTrKl8!iSck++M z#!8fF3<e{%1^Z=);YVk(JW&Q)c;(YY*YHoPC%wzFSG<PYRZN<281sz6LItyWV3{gn z?1<q+8Sr6g=nT4Cos%bG3uIC~GUd<Tn&yY_EAS5F=V8tt*JDJ(bGm7I9Kz|a&^|}j z;~|0#TlgV{VPuJSd{OM>;zAo(`G(9KABOpDx*otkwGiSVj;$80yPk!tn&+t`Ts$S; zLPNXj0sm<d%GSyw$xy8fHLH0l;%a1OW-iZ9xr#dz{4m{%jX1J{5q&;9LmE4{P$hm9 z67+sUG5H&lbnRr)*THGjnJmuF$<!;fMr6*4O5mZ+lik+>+U8!x=pV`7cov8ptc}Or zw-kJqZaJ6+YX#Ru#B{k|fD}1T=v!u?AeV6nL8`q#Xz6rlev%9Macc<=>12q^vWt@B zYZ(j?KV=IkZ{?AbZbkp1dLRkOa=V`ihT{U28OW&nQSdzOX2YE}JPg+phX{NeStHI+ z2_;84aU6o8bn6XW^nr_SNW7liG{+zel)8Gs6^pK|TOYS5VYnc1dWEz+=;pVN>w85O zIu?A^c<;+8HXHmGyD>h`;wBEYDU79qwafC<;iHVH1HV)5b6h<b!kq?0be{>7N&eVH zOc_2pFcZ3ryL(7BUcQcSK%Qzb{sb+1gghnZL?k*9y7n~7fcQG`AfPrHBXjnQe3!}f zQrtoo<-*rwmeB~32P*Q^`LmL%0AyJ9QpJ1(!~n#z<;qF6XM=cy7ZA2(;04KR8IT~- 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 RA@-J^u;ZWZbCz|N{{`+TMNt3% literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/bayes_inference.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/bayes_inference.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a37330680c29bbfdba5a1bfd98041dda24957604 GIT binary patch literal 31419 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 literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/bayes_model_comparison.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/bayes_model_comparison.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..57322b839ff7d50ea32d3b36ce011c09cf91e232 GIT binary patch literal 15645 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 literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/bayes_model_comparison.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/bayes_model_comparison.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5f608d0ecf37288d6330349caabd5e7789533748 GIT binary patch literal 27765 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 M_dkEiS4Ii{7kUZ4g#Z8m literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/bayes_model_comparison.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/bayes_model_comparison.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b58f792ac36504c702205afc34228600f9bbba77 GIT binary patch literal 15716 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 literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/discrepancy.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/discrepancy.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bc71688a4cae4f74ec3a67838fca659881c520c9 GIT binary patch literal 3806 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 I`#)>`7Zrzs-v9sr literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/discrepancy.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/discrepancy.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f505c78056d5629a52177e4fc2d67abdbd2aa48f GIT binary patch literal 4963 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 COKi9R literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/discrepancy.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/discrepancy.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f154800917aeaef9c499abf13d47fcca6ffc639b GIT binary patch literal 3869 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 C(w;v6 literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/mcmc.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/mcmc.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1d2122246d54ec5697803cbce28900e077b2306a GIT binary patch literal 18924 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 W6YnAs1G%l!A8`@AH@FHoxc@Kt+VTSc literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/mcmc.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/mcmc.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..245146ac5f5f72cb819fa504cdf288da3a5b75d3 GIT binary patch literal 35891 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 G_<sRhY*nWK literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/mcmc.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/bayes_inference/__pycache__/mcmc.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b9fe4689524895c2149048d489b22b08e85026df GIT binary patch literal 18959 zcmd^nYj9gve&2loxB&PjMN&^+*|JT@B1BRT+gjPOo|YVoR!prNb7^BQaV|)J04{Xy z1tr24*^Z^G<xaF!8fV+=)*W)DlNtBJw)KadblT2zGCOV34?F$Prpe7rvUzkiYV#p! zb~>F*WA*nx=i&mC<h7e=zq9~x?z!jv`oI5&c7K0H!RN-<KVysEP?SHWm)?(#msjxf zZX;j{Q>)6Ne5#9@c-I$o@iZ0_;+d?a7EP7PXw`HrvzQTawVGYbiu}G>|Kfm1)2oBE zp~c}Se`Ik)<c}_nGQ&|SV=Qq}c~xOamb$I5)Gcjs2U8c6oOvH3QRZ`MXkKBZEB1=x zQM|b7Rvm9`BUER@!8a~nDa?QMa^dR5H_x9ww@{=Sy`OkiK2jZJQDq8dqhcl+({C$_ z1~XU!&xGuKG09Ap#(RooSQbx{^|5|D(`<kZ;+bK4*)SWqtzwS**bX+1SRb2UlgR65 zJJ~Kg2iR`52hTw^idj4n8kf&rK5N%8l#GSXX{%VZJ<lq++*-Cb9ItHGt#ZBOaHn2$ zto5>O+16#7ues~fXIJfV-MZ}7eP{Zt&8x08MUCY|Lko7TQFXZGyO!N(aQ9}pX8Vri zuR2!4^?Zky(E}@cJ})mf{jyuP+>*#WL%mYW<xcH{XzRd%#?%s0d^=b|E2~Aj`rbx6 zXT4-CmAGAe54qjsK$gr|ojSR;XoP0>g`e$B<=XiJ2Qs4e)zz{WEltf{b9$EKM%iDr zoLbSr#O&f44ubWy*>|j_SFW#ESiIAvQn~I}m+I>_$71@Tx$||;sV!F>%Zrw2>hz`a z3pwj+bMNG3ht$ReS^~R1eHraK8;7iO`9s!4cV&fQZz2A=T^Dh5!>m_bm!a?>>ow%e z&CDLji$Td1q>0ng)BaeicCF^{ymh6yTrC%ET70jw`lqoWZr!aRy=pDE#j@jXM0xQl zUa^biQn`4@nw>i~_2S&I+##!xKQePXZ>{=%!#i>Ku;@9@9h;$3<`%tt**)yk4|~3i zNgs}8IQLHPpv5HKa%}FzQ<%wH4=<EwiS@R{qQ)aCM~ho@^43|mR%_PddEtcO{8h^i zv*?UqJ^gag6P*>^TBGTU`P<dFEe~_XQ9ooIo0_GWHS))gO}{XMZ4pII`|`v(o_L*( zKjKv!-ZvV)XPvOz<x1SBJk&^Wihf?C7PTHsKymt=#m^&57^s0#0P+Hes)S?Gal<(+ zG(4wT;wcpSMB!;X{_4H6CzihIIow;~&YC;B^hVt|$II)^(mCKF-)$@{G&y%y0D#`o zg{pg_ft4tDowOw!P`k<<uUYlI_1V<|op9c)FD(-&uG`fz1N_RjLW~QRYQ<VH-`EJv z0usx9q3|4yUQA1C_0vhqcXEn^={lcdh|s7h%`*@Sl#0^U1HGcQjligA?F6M%^mZ~x zRE%~CX^Bd*ZQ_~w5V#*pV=@hS>F+8`7iAIq*l4HyOeMS77o@jT@9TbMv!7zBT+D$$ zL%l(U-U>s^Kse0MPho^55sr%VF_uDnhX}`+i4je#EBpuaWads$)1O3tL;lXnu3H*% z5U=b;ogtQvO8>sUN0d+RRBq8oM_DGy`5#eECdwIRS($TB<wK%QR`fB(`r`B{k=`fL zcd-6A{S}ekFVe^Ty_J2NPcT)?6(eFwQ$d^ms5KIpn-<16yrow5w=-`k_2a5SU$LT3 zA}vdGD^K|cf-H@;GR#tJ;I7{83$g)vZD-zA>e`G_|2JZ$PqV=_4K4o%dizlQK>0u| zX>5oM-!}bcsP--O9A@3l)W7ZT-F%i(?kFW~3n?o~yWfB24sy>a?=;#2$e*HCKx>s> z(1L-Iwo^g5L8Rv%lRgymZypQ=gCS~7Rs82Fhv+RBoK)DzU9CMF3|FS9KQ?+-4Km$U zPhusm|9Q|)GcM$VWaTg$Ths4p{L>)0IYTwj>j-+C4Kl%q9BYuN%(20p%7+TdCo1{& zDAhKUN<J8U9&lR7`$yOg)K$a@9RFCqMW>8T<HW~Wd(1ytIktH`7(>fDf*qUBQ!jUv zEe&Oq%8q+F|HnZ}?2*n5|AoyLx0H4Y&l5pvOZ_|FY>%V<S7aT8C-EB##)BPf@@}#{ zfj7CoI$y>pc8Z=SDlcL5N@axYV!N?>lflI1^INpfla-g-lXWA=v?oz|Ph6T#@u)1l zg!1j3?OktSCk%XV>8es6nN{xT-anWTr$trX#`B(9|DDH-YzJD|`_Rb#=ih8(Ol|MR zPMo5#VeR(dY`)Uo%l5VR1rrr3=!|(6d*ZHf4&!;}V*3f?oDTMlEB6fk`aR?NasN!9 zGwYUy_iq74&Wb0>u>Ipoux||Iyl=IJ0%h}DFtJ7Oc^**FC!s=~b@V=tTEBrgJh^#+ z+TT)X-7vCO@pcg-vyk^xV6g+=H9pp&HNC`C_Vit~y&vUX3-+V!J;CmiO0b&^KCiTa zBhYFB?9dVROs7P*K2m-LV|pF!U*1yL{w=NjBuYLTJb4SJ2D$UWei}WEW{u$Fso*I} z#qW(^Z?Jz7X~F*83Y((b%StD|r_Ee92jggAKNHvA5B9hB(yC!aCMxj^up)a51$%v^ z^0W668{d<w!w$Ch%N6pe-#2NFw^X$C1IqFDu;-AvK&fMd0}deN5K^voQkV+3OLFDm z^t#3d+fSqauLcL$uHb1ljT0=_sI%HVs}n)?0m2#*XT+<O7rS(X9gdze=w0kY&pIDr zv%%A#6=K)0!gIlap0^{xGnKiX_icOJvmZy;(WsAO(errp>|%xIBdkEQ>stHS81tm~ z9{(BO+hpaf%Fo@x3IZSQYEK2v0>6p0U}`7u3Sqf>sp}F`=i7u6$M2c^48aC_VNId9 z|8|gOFHX>EAM_VDzXm+=T#RG?q<tt(TdXXx6Zn1w-;;NZ_H^*v<~zYO*7BuaAn9p; zXD!?L;JHdS=OtR<6(z{Cm$4^@yEy)xGZ-<>YA_Y;$DxuAYB3Y!H{T6r*eQYQ4p$1n z4E7W|wNqiQu+!`eJIl`9O^BI&in3o1a={_O`@mHBO`Dw$o~8GRPRcU7Ao31YiotX2 zRd(?%LBrxEBix47xf&eYbOfFwylQ&?Et>Icun&7*VuJ*IXiXba+H=7k(D>anmi7^p zdpDTFcOPKp(iSjYlyZbdj`#|=jJeI+mcZJ0UuCK|-A4eOuXSR0UJZ~ksf^K>Wz91C z89|{IH!JLQG5T4Io@m46kF|IX;2(l#f@j%0XxGu;DA>F==D7-nC>(gB>4Piv3WDP+ zglgeFL;C&SL{Q%Rrm9>B`vkisB?m7|)e8`(8eW*L7jD>9aBg0hsJZKo7Y^3I(Ul>5 z6&;VnkubIH@MYI?1QS_qIbn)BjjCOA?o;1I3OXO+<A_Te#m}2UfODX{W3|;gkWzhR zQ}vaKwyA@zA%#|WLir`_x<L%<kH7P)^!ewfaz?1t8=)zOQQZiW9FmG#3lsFLf1-t2 zekN4Qh!}NNM!FF41W(I}4GuFWs}K>1QGdBX12GXKRqcVP_C07F5IiOr)j}ji<xf^! z$SvN>h;*u9syb4`gohmG6P1rsyXu+NvzeFivBWZO7jlJ!AtWV|f?Got#1`&5EN`6@ zpVqJxaN=%PkL7eu3l$m-*R6)BWfIuxthF~|ooVv=G=z`_NxaO06e(K6Zk)JE3IpuU z3RrKC%3k3vYZiqtj9G0f8+E`BQZMOsh!HNw2Hu~;drl8CWk}Rgk_!#LS$8-w<6*`D z+s`k%%&FcdcDt3%Ea0r1u-<F8c3pNLo!Z5s)9`JQ?MalTzE4;!J%6P1i5lv@TW#%? z<(j@*bU6rEx#n1ohX<qy6diljsgjKPW^);{yo#KIC#;qC#=iIJAGU6vT9HTLFHYT0 zp!@rDsD6weK0iA3i5{k)04Um=g+{4r`xyCZxgM&S){$7Ml94Mt8UuT!jyK3~50z={ zsfh_;pwl!`2Q89Xfd-6mCaG;a)5~&05FMdTt)kFkc&m1UicMz@T0+)`*wb{ZTGR8b zs=Z+?JN^yFsarGoxg$q~^f;40mTyf_X~%<Ngo=Bz{4&J)nq3vzk5#PkY<@Q1ntN!t zU*ff8SzZ(S<9VfKwYp&u7*w5}gP17~J&R2pJnUoZ0LZTI<r}PY-@y7tEB{-k007BV z52^_#Ox_UB`w#Fza`q;cajj}EJ5?`CVg<Of@mK2feS-EdLrA4m#w=KvS*61UJ&#=t zjTLTh;KZ3wi1_|S!wIv<bdX1@9VUuy)#a^$ctk>z)XGw8R=rtUb~vECyt3-!@Mo8o z-J1{|i&(;zK0Uq0ccSaope#pf2Z7mI!(wL-EUnu9drQ9EY#(UtJZwiNGTP???K90D z?WQn@X07h!)`XNCrY}QvB%mNP#p8|TN|-%|vj_Btvk$~nFBBV1;L!6o8<3gHE11b^ zDBy=?z0k0^T?3*mx=pCMIB=C+b3)Da0PYZ^!=!T)B|YFd$jz(_{F`-`A&sxgCF%2B zEL;JN*6g`3OUS!}yUluxvFmg$F%B_fiA=OwgYTfd$daht8AhfIR1O>hkPWp43)AOp z-@bqmVt?f+4E1u|=etmo@1g3@7hn^UveQt#8k*d`QDCSRCZVq^qanTO)cKQCm{9YI z6DC>?#{~5n08+2nH^U^fC_rhUhBZk+zXH@)3w6Hkg?-Cd7gq3_IGk8Px8cjVhM5%y zQK8_XBj^Ju0u2+Og^32o7{i266oqDlFTF5x@!W+o5_w`I04$%6(Wuhcoq|~Z(6~Y< zcCe!uT968~u)pfA6k^RHrU<e?%Z4esE@z;LPOaf@(At#3bc`;;)T-^-(CP3Q>Sq|| zwp=d=v{|ST-V6ujOZNyRY3hWn=v0QIT?|_2V9;=wX5KlV;$(tM+jUVP!D+d|z7>Ht z3!LyKz=p6;r~_*tSjJiE)DHVkM+f~p;qow1_Rtaz3Yw#Bp(kplsYlsJ8t1h@M--cJ zsSaL(4mx1K<}0M<@i<}OP;XTIFj*?EG`SO+uktcmXgI|%YcmGT&@v$t9B&a4q=zQ< zqOef~kxo<0FZ)#oNCMHD0)vDp&t7-XUZ@wVB}}LaJ_Dyl9w*}_)igx?WK<!!Au8sM zaiZ#ck%F($&`d#-0i*mfy(R?6@;4~|3MHg*cw8=^Gvf+wsQ{?sOOyxR2s4(4!V3o^ zzX24(aLPU2q#~&@yNL?mHlPV3bkxMj22?Ye=70p#=-7JU5K@bUo)aFLK#C46ub{;| zCz_O}oMTl5R^aY3PC8H`uw!Q<FR`2aSEz6j7|g9QoSY5@16Q^Y0sg8efis1}1o~?? z!xXVHg%u7MaO)_!La<E8qFm=EsC1uD-^mep{JTivmPnU)s~~qk2Wkv;+MguSF&M(+ zWfrDtbl~YEZ4|^tV;_mk0J)*?EKP%$O9MjzsK<o3z)F%$+fV%oUM<_hi5*6&_if@Q zwWLa4Gx{afakWp)P^vC-qEOEueL&6NIi%6APwngcbi`Fn9Z{3WNrLrD>O=Yf+UV2F z&&=eIY9N0S-vN}_r<+t>AJ8+14QYm&e2_8Fx;BtBQQt(X21**AC6lO+xcMNNFp+NP z@@*#hx%oQvlvE9j-N1;nzwS$-HGK?YGBiycLS7QB458Fe0zIlG-p182%xg@w)LmjV zOr1)OU==WOZA8tB@&{0o$`0T=gl`68qfw0+G~zLJQZuO^q|vBH)Llr^uo44!_UR+4 z@gRdZTE)y!LbOKZM`$eSK{bOfR`Ee{_kh+KdYE<IrjE{H-}>+q8d``Pq_<KkD)eFW z)Y@90RdkZ)`OAnw!iDyho=NCuRS`4Wh7XM>B-2DagBax8tkO>0QBcZkC&e=X&8}L> zFb(aL0<~@i>SmVd&~B(m?_&leHPi2}3}h9*e{(P}NwWYQ?@(Y0srk3t(0OeRLsbrq zDs*QW|HvQtKq;vV_A+QBhtSKY)JWb^`46GhO$V8iO8o#@8-w<52i1g@H<68W36=3J z6?zm=DxTp-oj#}>Go_>)=uvMfdP~dR#Jn?|{-7m&rPJf}kEqRrvXka978tVU-u9^9 z=ds);6_kZ;TWDE-9@0J5U;&!N1@sKbDr5gXHX}AFoVBaPCRkW$F0()YErA)WYI)76 zmRDgAvX-X0cCe+KV8$S0St~FO)Z>N(q5xybE#UJhFGsbc70p`8MfNBQpDV-&Q8{V* zprkGv8@DE8IM_dI4o*=paYXX1sg9WD9kMz+l{6JnJM@X0r(vK}IS+FV<RjozkS%IS z2xWrGc|F5=)A4~09~o0TAS{enmlIa0>Vo5kQ1{T-;-STLXgse!W<m4TC1IxYZJ5z8 zraJg?7v??g-Z*607D?H#>Pg|D+#M1%$Hg#VhjOt({6-m40|{WXN<EX|#C`Kg1fOW) z!B0^Fq0&d>bArz!_<0rrNavG~&IP0fDs)KD?5t_mpeebo35&JHJrtV<@17P!vH)`w z{}@SOnn+)Pn0dYr?>SWv-X1YLeR9RAJ2xBr<zK@<Jd!Vf{vNdU3p64)FCxi3@^`2F z3W|!){3D~MR>bIuNyX^L+R!ZAfwcx>SJsu@k%tCxoG^s(-$B`Ekl}!!&9#`XA$5fy zMf`UW`xGPnOFWg_gpdN{oCFuKP6dCK0>KcNf=eQPL##$t9F~F*m3Wm(3C0+z62ZIj z4N4N+^*0d<4Q#*1YZUDV2j&#lB*pdkFH^w<%76x9h5tKxEhETfCCBp=CD4Gv;fJ}5 z4&%`?6p}<D86qQ-Y1jB~QGK)CA=+l=uyc!ArzOd0a_YZF34&6m;~o13ZRbT~C?lXX zpuHxj1b##(@twrmh}NeOH8vlBdV-oxJ}?s*L3<3OW*(p{p5ubXnp$gM`;mBru8`UC zEPmb(5fD8Q)I<dZk+g*@fReV%AV#z$;lmCHN|FR6Nk)_;8JFUL3U3JwHl!r*GoGZg zB+4RFVJAd-l&aPZrU|N(VmheK?TG4_%n(#Z*#xE9QkOK?8nr^khkcGEVCVZDED3$k zQ)}%suzY`DVypxB4F;eoEO|EpN|XV9PTAkVdd4^emT2&zz|N20W3og;9rfPZ?T)ts zaC7AU03Z|s2IRZAr6_9($k(3E3AqFw2*4=7j?fs9rvYL09;wqJ@vaB0#JIJKlm4%v z?#E$n8s6U+dlzT{e;P&EPDfq`-tI1W&msuiIxn&6Z{zrd2CqRG3PqRav)s^6M-yFC z!2f{iW*lJoNJbom3YHZbMW-Mkv%ww4@1PX_FH|&Dhr|f}yDQ^tLjeR5J=p1w>GeNT zy<`OMX%ZaKG&uh>S?#4HNT4oOMk4AM`-KCY49NrhYl87-(4I0(ymkcTfZ7bW%}Ii2 zaMNRgv(-LJ8m-Y7g1d{j4UCg$ijcPe<4+L*y9TrTn#Kp1VB;zPJ^&%uM3MS)V4*Yu zEMKn}Sr8?DLdL+_L^%Zhn+Yld7XUplCcyU8uXS@}d0*d51~34F4Kxr>1$xvXm`2fK z0!{(MKI#0|WP3q^%nN}Lz=^BVF4F<3hW-9yL6y#FtVQTKMPP|K{zQQldmFvo&Pk>! zhE%FAm@7B~b(kdwE+27$|K9-daf{ir91<9@6<|!#g3wC(dLJoWBFl-8^B*Ay6F0y- zIYNt{OZL#wA5#fYi^_)Cx?3k-l>&tQhv0+1j{<)|KtaroG7P~ALK47&KmtPJh&~QN zNMfUDv_@iJh$pfQ7W&abOw#@gFWX3(4q?e4QGy=?2{AyF)VoAp5+G*Z_7k@h`e_i1 z;OYYLiM)O)DRTb9*SMQN$rMB&a(qcwglO^36w=ZlHz^_XBuJp~$>jwxuuc6q>q$zx z{x0eaYz}TIECFcv)E|PNWK>3AhJw2b`bbSEFmwWL$SDD?4M-8L4Jm&#fUp6g_a_+l z7($rVHpda42ohTwde6c+BoQP_8lWg`ulGXHdE$Fxc_gA%mLyl;ySuP~*#9HcDaOno zPtY+*?>^%8>2sM35_0;4ypatRxpe=cY(X=S{<x|OKIDYbV=Bjp1g5NikMkBL3Uov- zz}5z~&{=;Ide3<`Ou=CgM2YjSqm0xdo26!5j37*kDg_C9e;WmIlRdO=o?0~>80~Br znZf}{=dfX7CZs1T`r(MsuabgP=%ryMsPd~+G3`KmPqrv1|D-81ObBJ9gyuR8hdAgk zT`kwwq|otwdWQi5exOy@2x~rf9R5`*Ni;Of_NZey4L2O>(q5^n4KruTwkP;_FW29L z7XAsfLTW_*Pbv6ws%>@_KFo+I6`(})I6*RL(1mVH#}oQ|?B5llx+&D4$itX~0DeEz zsop_Elo6rI(vsQ;lvBVTYVxy8f>bc$P|WN>notiBRv8pnr8|j7P>PA>1bKZJrNC1| zg=7bE2VWBdo*KL0sR7hdNo+*ET}*Eqk)KA=Pi+Euke>#BjnaK+6p)soG~uO@KuQ8B z*-nbk>fC-f6})c}C<<DcAOWog{E*=fkb)Oenx)}EK)!GN5sz&KW(8~j%iL8r2Z3ym zBfP4p%n-QctU!R7Hu=5{1Feie2Lmr=wAUB(0i_JI9>hodDk<a1SJM(FAcBU-v(|bQ z8cE@v46`X2$*eaWVM!G*7Ps-`=xwCG1tdZ!j_VSTO3&UXzlU&rk<vk)+1P6En3hlX z&Z?(nA?tH8?DC@&9HZbk1*8?Y%AZF#59_R9!|cTWJKn+sR6*rsh{pspxzQeA{uUDW zdldW%1>dINmnjee?BAnUiGsgR!LL&A9SRmG_(ckc*X4hWARK|U3}7u;UI}&_9`;HH z-u@+(?84g*==I-HKw4`4n+Tw}?-+8!bj@xQ1RV$y8}K-7glR%pjG_X_ABMFL(ZDr= zwF8JKgQRFBH7Y4eq0EIE^$_CY`lK-gRu(E<y)`bN>=BF3g>BxbeQ1nq(*oN5AtI8Q zB}sCp0&+)C1Be6ZCXx)&E#4B)G16NS<Te2xL~RuQsv=D#xPaWKPbz!KuTK?Zp9p#q zXWSIE&8T)7dO?Fq!n4cR4ISnLJT3!`-yvzzSHTcxg7j`Muz;2<bbxg4AZ7oC-XmjP z75u6X`)e5v+rq~IVqwRNpahFPv|UqI7T&y&vlz@Xb	o4MB>fKYEXpNq!HIDoLFs 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 literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/bayes_inference/bayes_inference.py b/examples/analytical-function/bayesvalidrox/bayes_inference/bayes_inference.py new file mode 100644 index 000000000..7ac43b62b --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/bayes_inference/bayes_inference.py @@ -0,0 +1,1530 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import numpy as np +import os +import copy +import pandas as pd +from tqdm import tqdm +from scipy import stats +import scipy.linalg as spla +import joblib +import seaborn as sns +import corner +import h5py +import multiprocessing +import gc +from sklearn.metrics import mean_squared_error, r2_score +from sklearn import preprocessing +from matplotlib.patches import Patch +import matplotlib.lines as mlines +from matplotlib.backends.backend_pdf import PdfPages +import matplotlib.pylab as plt + +from .mcmc import MCMC + +# Load the mplstyle +plt.style.use(os.path.join(os.path.split(__file__)[0], + '../', 'bayesvalidrox.mplstyle')) + + +class BayesInference: + """ + A class to perform Bayesian Analysis. + + + Attributes + ---------- + MetaModel : obj + Meta model object. + discrepancy : obj + The discrepancy object for the sigma2s, i.e. the diagonal entries + of the variance matrix for a multivariate normal likelihood. + name : str, optional + The type of analysis, either calibration (`Calib`) or validation + (`Valid`). The default is `'Calib'`. + emulator : bool, optional + Analysis with emulator (MetaModel). The default is `True`. + bootstrap : bool, optional + Bootstrap the analysis. The default is `False`. + req_outputs : list, optional + The list of requested output to be used for the analysis. + The default is `None`. If None, all the defined outputs for the model + object is used. + selected_indices : dict, optional + A dictionary with the selected indices of each model output. The + default is `None`. If `None`, all measurement points are used in the + analysis. + samples : array of shape (n_samples, n_params), optional + The samples to be used in the analysis. The default is `None`. If + None the samples are drawn from the probablistic input parameter + object of the MetaModel object. + n_samples : int, optional + Number of samples to be used in the analysis. The default is `500000`. + If samples is not `None`, this argument will be assigned based on the + number of samples given. + measured_data : dict, optional + A dictionary containing the observation data. The default is `None`. + if `None`, the observation defined in the Model object of the + MetaModel is used. + inference_method : str, optional + A method for approximating the posterior distribution in the Bayesian + inference step. The default is `'rejection'`, which stands for + rejection sampling. A Markov Chain Monte Carlo sampler can be simply + selected by passing `'MCMC'`. + mcmc_params : dict, optional + A dictionary with args required for the Bayesian inference with + `MCMC`. The default is `None`. + + Pass the mcmc_params like the following: + + >>> mcmc_params:{ + 'init_samples': None, # initial samples + 'n_walkers': 100, # number of walkers (chain) + 'n_steps': 100000, # number of maximum steps + 'n_burn': 200, # number of burn-in steps + 'moves': None, # Moves for the emcee sampler + 'multiprocessing': False, # multiprocessing + 'verbose': False # verbosity + } + The items shown above are the default values. If any parmeter is + not defined, the default value will be assigned to it. + bayes_loocv : bool, optional + Bayesian Leave-one-out Cross Validation. The default is `False`. If + `True`, the LOOCV procedure is used to estimate the bayesian Model + Evidence (BME). + n_bootstrap_itrs : int, optional + Number of bootstrap iteration. The default is `1`. If bayes_loocv is + `True`, this is qualt to the total length of the observation data + set. + perturbed_data : array of shape (n_bootstrap_itrs, n_obs), optional + User defined perturbed data. The default is `[]`. + bootstrap_noise : float, optional + A noise level to perturb the data set. The default is `0.05`. + just_analysis : bool, optional + Justifiability analysis. The default is False. + valid_metrics : list, optional + List of the validation metrics. The following metrics are supported: + + 1. log_BME : logarithm of the Bayesian model evidence + 2. KLD : Kullback-Leibler Divergence + 3. inf_entropy: Information entropy + The default is `['log_BME']`. + plot_post_pred : bool, optional + Plot posterior predictive plots. The default is `True`. + plot_map_pred : bool, optional + Plot the model outputs vs the metamodel predictions for the maximum + a posteriori (defined as `max_a_posteriori`) parameter set. The + default is `False`. + max_a_posteriori : str, optional + Maximum a posteriori. `'mean'` and `'mode'` are available. The default + is `'mean'`. + corner_title_fmt : str, optional + Title format for the posterior distribution plot with python + package `corner`. The default is `'.2e'`. + + """ + + def __init__(self, engine, MetaModel = None, discrepancy=None, emulator=True, + name='Calib', bootstrap=False, req_outputs=None, + selected_indices=None, samples=None, n_samples=100000, + measured_data=None, inference_method='rejection', + mcmc_params=None, bayes_loocv=False, n_bootstrap_itrs=1, + perturbed_data=[], bootstrap_noise=0.05, just_analysis=False, + valid_metrics=['BME'], plot_post_pred=True, + plot_map_pred=False, max_a_posteriori='mean', + corner_title_fmt='.2e'): + + self.engine = engine + self.MetaModel = engine.MetaModel + self.Discrepancy = discrepancy + self.emulator = emulator + self.name = name + self.bootstrap = bootstrap + self.req_outputs = req_outputs + self.selected_indices = selected_indices + self.samples = samples + self.n_samples = n_samples + self.measured_data = measured_data + self.inference_method = inference_method + self.mcmc_params = mcmc_params + self.perturbed_data = perturbed_data + self.bayes_loocv = bayes_loocv + self.n_bootstrap_itrs = n_bootstrap_itrs + self.bootstrap_noise = bootstrap_noise + self.just_analysis = just_analysis + self.valid_metrics = valid_metrics + self.plot_post_pred = plot_post_pred + self.plot_map_pred = plot_map_pred + self.max_a_posteriori = max_a_posteriori + self.corner_title_fmt = corner_title_fmt + + # ------------------------------------------------------------------------- + def create_inference(self): + """ + Starts the inference. + + Returns + ------- + BayesInference : obj + The Bayes inference object. + + """ + + # Set some variables + MetaModel = self.MetaModel + Model = self.engine.Model + n_params = MetaModel.n_params + output_names = Model.Output.names + par_names = self.engine.ExpDesign.par_names + + # If the prior is set by the user, take it. + if self.samples is None: + self.samples = self.engine.ExpDesign.generate_samples( + self.n_samples, 'random') + else: + try: + samples = self.samples.values + except AttributeError: + samples = self.samples + + # Take care of an additional Sigma2s + self.samples = samples[:, :n_params] + + # Update number of samples + self.n_samples = self.samples.shape[0] + + # ---------- Preparation of observation data ---------- + # Read observation data and perturb it if requested. + if self.measured_data is None: + self.measured_data = Model.read_observation(case=self.name) + # Convert measured_data to a data frame + if not isinstance(self.measured_data, pd.DataFrame): + self.measured_data = pd.DataFrame(self.measured_data) + + # Extract the total number of measurement points + if self.name.lower() == 'calib': + self.n_tot_measurement = Model.n_obs + else: + self.n_tot_measurement = Model.n_obs_valid + + # Find measurement error (if not given) for post predictive plot + if not hasattr(self, 'measurement_error'): + if isinstance(self.Discrepancy, dict): + Disc = self.Discrepancy['known'] + else: + Disc = self.Discrepancy + if isinstance(Disc.parameters, dict): + self.measurement_error = {k: np.sqrt(Disc.parameters[k]) for k + in Disc.parameters.keys()} + else: + try: + self.measurement_error = np.sqrt(Disc.parameters) + except TypeError: + pass + + # ---------- Preparation of variance for covariance matrix ---------- + # Independent and identically distributed + total_sigma2 = dict() + opt_sigma_flag = isinstance(self.Discrepancy, dict) + opt_sigma = None + for key_idx, key in enumerate(output_names): + # Find opt_sigma + if opt_sigma_flag and opt_sigma is None: + # Option A: known error with unknown bias term + opt_sigma = 'A' + known_discrepancy = self.Discrepancy['known'] # TODO: the syntax here looks different from expected + self.Discrepancy = self.Discrepancy['infer'] # TODO: the syntax here looks different from expected + sigma2 = np.array(known_discrepancy.parameters[key]) + + elif self.Discrepancy.parameters is not None: + # Option B: The sigma2 is known (no bias term) + opt_sigma = 'B' + sigma2 = np.array(self.Discrepancy.parameters[key]) + + elif not isinstance(self.Discrepancy.InputDisc, str): + # Option C: The sigma2 is unknown (bias term including error) + opt_sigma = 'C' + n_measurement = self.measured_data[key].values.shape + sigma2 = np.zeros((n_measurement[0])) + + total_sigma2[key] = sigma2 + + self.Discrepancy.opt_sigma = opt_sigma + self.Discrepancy.total_sigma2 = total_sigma2 + + # If inferred sigma2s obtained from e.g. calibration are given + try: + self.sigma2s = self.Discrepancy.get_sample(self.n_samples) + except: + pass #TODO: should an error be raised in this case? + + # ---------------- Bootstrap & TOM -------------------- + if self.bootstrap or self.bayes_loocv or self.just_analysis: + if len(self.perturbed_data) == 0: + # zero mean noise Adding some noise to the observation function + self.perturbed_data = self._perturb_data( + self.measured_data, output_names + ) + else: + self.n_bootstrap_itrs = len(self.perturbed_data) + + # -------- Model Discrepancy ----------- + if hasattr(self, 'error_model') and self.error_model \ + and self.name.lower() != 'calib': + # Select posterior mean as MAP + MAP_theta = self.samples.mean(axis=0).reshape((1, n_params)) + # MAP_theta = stats.mode(self.samples,axis=0)[0] + + # Evaluate the (meta-)model at the MAP + y_MAP, y_std_MAP = MetaModel.eval_metamodel(samples=MAP_theta) + + # Train a GPR meta-model using MAP + self.error_MetaModel = MetaModel.create_model_error( + self.bias_inputs, y_MAP, Name=self.name + ) + + # ----------------------------------------------------- + # ----- Loop over the perturbed observation data ------ + # ----------------------------------------------------- + # Initilize arrays + logLikelihoods = np.zeros((self.n_samples, self.n_bootstrap_itrs), + dtype=np.float16) + BME_Corr = np.zeros((self.n_bootstrap_itrs)) + log_BME = np.zeros((self.n_bootstrap_itrs)) + KLD = np.zeros((self.n_bootstrap_itrs)) + inf_entropy = np.zeros((self.n_bootstrap_itrs)) + + # Compute the prior predtions + # Evaluate the MetaModel + if self.emulator: + y_hat, y_std = MetaModel.eval_metamodel(samples=self.samples) + self.__mean_pce_prior_pred = y_hat + self._std_pce_prior_pred = y_std + + # Correct the predictions with Model discrepancy + if hasattr(self, 'error_model') and self.error_model: + y_hat_corr, y_std = self.error_MetaModel.eval_model_error( + self.bias_inputs, self.__mean_pce_prior_pred + ) + self.__mean_pce_prior_pred = y_hat_corr + self._std_pce_prior_pred = y_std + + # Surrogate model's error using RMSE of test data + if hasattr(MetaModel, 'rmse'): + surrError = MetaModel.rmse + else: + surrError = None + + else: + # Evaluate the original model + self.__model_prior_pred = self._eval_model( + samples=self.samples, key='PriorPred' + ) + surrError = None + + # Start the likelihood-BME computations for the perturbed data + for itr_idx, data in tqdm( + enumerate(self.perturbed_data), + total=self.n_bootstrap_itrs, + desc="Bootstrapping the BME calculations", ascii=True + ): + + # ---------------- Likelihood calculation ---------------- + if self.emulator: + model_evals = self.__mean_pce_prior_pred + else: + model_evals = self.__model_prior_pred + + # Leave one out + if self.bayes_loocv or self.just_analysis: + self.selected_indices = np.nonzero(data)[0] + + # Prepare data dataframe + nobs = list(self.measured_data.count().values[1:]) + numbers = list(np.cumsum(nobs)) + indices = list(zip([0] + numbers, numbers)) + data_dict = { + output_names[i]: data[j:k] for i, (j, k) in + enumerate(indices) + } + #print(output_names) + #print(indices) + #print(numbers) + #print(nobs) + #print(self.measured_data) + #for i, (j, k) in enumerate(indices): + # print(i,j,k) + #print(data) + #print(data_dict) + #stop + + # Unknown sigma2 + if opt_sigma == 'C' or hasattr(self, 'sigma2s'): + logLikelihoods[:, itr_idx] = self.normpdf( + model_evals, data_dict, total_sigma2, + sigma2=self.sigma2s, std=surrError + ) + else: + # known sigma2 + logLikelihoods[:, itr_idx] = self.normpdf( + model_evals, data_dict, total_sigma2, + std=surrError + ) + # ---------------- BME Calculations ---------------- + # BME (log) + log_BME[itr_idx] = np.log( + np.nanmean(np.exp(logLikelihoods[:, itr_idx], + dtype=np.longdouble))#float128)) + ) + + # BME correction when using Emulator + if self.emulator: + BME_Corr[itr_idx] = self.__corr_factor_BME( + data_dict, total_sigma2, log_BME[itr_idx] + ) + + # Rejection Step + if 'kld' in list(map(str.lower, self.valid_metrics)) and\ + 'inf_entropy' in list(map(str.lower, self.valid_metrics)): + # Random numbers between 0 and 1 + unif = np.random.rand(1, self.n_samples)[0] + + # Reject the poorly performed prior + Likelihoods = np.exp(logLikelihoods[:, itr_idx], + dtype=np.float64) + accepted = (Likelihoods/np.max(Likelihoods)) >= unif + posterior = self.samples[accepted] + + # Posterior-based expectation of likelihoods + postExpLikelihoods = np.mean( + logLikelihoods[:, itr_idx][accepted] + ) + + # Calculate Kullback-Leibler Divergence + KLD[itr_idx] = postExpLikelihoods - log_BME[itr_idx] + + # Posterior-based expectation of prior densities + if 'inf_entropy' in list(map(str.lower, self.valid_metrics)): + n_thread = int(0.875 * multiprocessing.cpu_count()) + with multiprocessing.Pool(n_thread) as p: + postExpPrior = np.mean(np.concatenate( + p.map( + self.engine.ExpDesign.JDist.pdf, + np.array_split(posterior.T, n_thread, axis=1)) + ) + ) + # Information Entropy based on Entropy paper Eq. 38 + inf_entropy[itr_idx] = log_BME[itr_idx] - postExpPrior - \ + postExpLikelihoods + + # Clear memory + gc.collect(generation=2) + + # ---------- Store metrics for perturbed data set ---------------- + # Likelihoods (Size: n_samples, n_bootstrap_itr) + self.log_likes = logLikelihoods + + # BME (log), KLD, infEntropy (Size: 1,n_bootstrap_itr) + self.log_BME = log_BME + + # BMECorrFactor (log) (Size: 1,n_bootstrap_itr) + if self.emulator: + self.log_BME_corr_factor = BME_Corr + + if 'kld' in list(map(str.lower, self.valid_metrics)): + self.KLD = KLD + if 'inf_entropy' in list(map(str.lower, self.valid_metrics)): + self.inf_entropy = inf_entropy + + # BME = BME + BMECorrFactor + if self.emulator: + self.log_BME += self.log_BME_corr_factor + + # ---------------- Parameter Bayesian inference ---------------- + if self.inference_method.lower() == 'mcmc': + # Instantiate the MCMC object + MCMC_Obj = MCMC(self) + self.posterior_df = MCMC_Obj.run_sampler( + self.measured_data, total_sigma2 + ) + + elif self.name.lower() == 'valid': + # Convert to a dataframe if samples are provided after calibration. + self.posterior_df = pd.DataFrame(self.samples, columns=par_names) + + else: + # Rejection sampling + self.posterior_df = self._rejection_sampling() + + # Provide posterior's summary + print('\n') + print('-'*15 + 'Posterior summary' + '-'*15) + pd.options.display.max_columns = None + pd.options.display.max_rows = None + print(self.posterior_df.describe()) + print('-'*50) + + # -------- Model Discrepancy ----------- + if hasattr(self, 'error_model') and self.error_model \ + and self.name.lower() == 'calib': + if self.inference_method.lower() == 'mcmc': + self.error_MetaModel = MCMC_Obj.error_MetaModel + else: + # Select posterior mean as MAP + if opt_sigma == "B": + posterior_df = self.posterior_df.values + else: + posterior_df = self.posterior_df.values[:, :-Model.n_outputs] + + # Select posterior mean as Maximum a posteriori + map_theta = posterior_df.mean(axis=0).reshape((1, n_params)) + # map_theta = stats.mode(Posterior_df,axis=0)[0] + + # Evaluate the (meta-)model at the MAP + y_MAP, y_std_MAP = MetaModel.eval_metamodel(samples=map_theta) + + # Train a GPR meta-model using MAP + self.error_MetaModel = MetaModel.create_model_error( + self.bias_inputs, y_MAP, Name=self.name + ) + + # -------- Posterior perdictive ----------- + self._posterior_predictive() + + # ----------------------------------------------------- + # ------------------ Visualization -------------------- + # ----------------------------------------------------- + # Create Output directory, if it doesn't exist already. + out_dir = f'Outputs_Bayes_{Model.name}_{self.name}' + os.makedirs(out_dir, exist_ok=True) + + # -------- Posteior parameters -------- + if opt_sigma != "B": + par_names.extend( + [self.Discrepancy.InputDisc.Marginals[i].name for i + in range(len(self.Discrepancy.InputDisc.Marginals))] + ) + # Pot with corner + figPosterior = corner.corner(self.posterior_df.to_numpy(), + labels=par_names, + quantiles=[0.15, 0.5, 0.85], + show_titles=True, + title_fmt=self.corner_title_fmt, + labelpad=0.2, + use_math_text=True, + title_kwargs={"fontsize": 28}, + plot_datapoints=False, + plot_density=False, + fill_contours=True, + smooth=0.5, + smooth1d=0.5) + + # Loop over axes and set x limits + if opt_sigma == "B": + axes = np.array(figPosterior.axes).reshape( + (len(par_names), len(par_names)) + ) + for yi in range(len(par_names)): + ax = axes[yi, yi] + ax.set_xlim(self.engine.ExpDesign.bound_tuples[yi]) + for xi in range(yi): + ax = axes[yi, xi] + ax.set_xlim(self.engine.ExpDesign.bound_tuples[xi]) + plt.close() + + # Turn off gridlines + for ax in figPosterior.axes: + ax.grid(False) + + if self.emulator: + plotname = f'/Posterior_Dist_{Model.name}_emulator' + else: + plotname = f'/Posterior_Dist_{Model.name}' + + figPosterior.set_size_inches((24, 16)) + figPosterior.savefig(f'./{out_dir}{plotname}.pdf', + bbox_inches='tight') + + # -------- Plot MAP -------- + if self.plot_map_pred: + self._plot_max_a_posteriori() + + # -------- Plot log_BME dist -------- + if self.bootstrap: + + # Computing the TOM performance + self.log_BME_tom = stats.chi2.rvs( + self.n_tot_measurement, size=self.log_BME.shape[0] + ) + + fig, ax = plt.subplots() + sns.kdeplot(self.log_BME_tom, ax=ax, color="green", shade=True) + sns.kdeplot( + self.log_BME, ax=ax, color="blue", shade=True, + label='Model BME') + + ax.set_xlabel('log$_{10}$(BME)') + ax.set_ylabel('Probability density') + + legend_elements = [ + Patch(facecolor='green', edgecolor='green', label='TOM BME'), + Patch(facecolor='blue', edgecolor='blue', label='Model BME') + ] + ax.legend(handles=legend_elements) + + if self.emulator: + plotname = f'/BME_hist_{Model.name}_emulator' + else: + plotname = f'/BME_hist_{Model.name}' + + plt.savefig(f'./{out_dir}{plotname}.pdf', bbox_inches='tight') + plt.show() + plt.close() + + # -------- Posteior perdictives -------- + if self.plot_post_pred: + # Plot the posterior predictive + self._plot_post_predictive() + + return self + + # ------------------------------------------------------------------------- + def _perturb_data(self, data, output_names): + """ + Returns an array with n_bootstrap_itrs rowsof perturbed data. + The first row includes the original observation data. + If `self.bayes_loocv` is True, a 2d-array will be returned with + repeated rows and zero diagonal entries. + + Parameters + ---------- + data : pandas DataFrame + Observation data. + output_names : list + List of the output names. + + Returns + ------- + final_data : array + Perturbed data set. + + """ + noise_level = self.bootstrap_noise + obs_data = data[output_names].values + n_measurement, n_outs = obs_data.shape + self.n_tot_measurement = obs_data[~np.isnan(obs_data)].shape[0] + # Number of bootstrap iterations + if self.bayes_loocv: + self.n_bootstrap_itrs = self.n_tot_measurement + + # Pass loocv dataset + if self.bayes_loocv: + obs = obs_data.T[~np.isnan(obs_data.T)] + final_data = np.repeat(np.atleast_2d(obs), self.n_bootstrap_itrs, + axis=0) + np.fill_diagonal(final_data, 0) + return final_data + + else: + final_data = np.zeros( + (self.n_bootstrap_itrs, self.n_tot_measurement) + ) + final_data[0] = obs_data.T[~np.isnan(obs_data.T)] + for itrIdx in range(1, self.n_bootstrap_itrs): + data = np.zeros((n_measurement, n_outs)) + for idx in range(len(output_names)): + std = np.nanstd(obs_data[:, idx]) + if std == 0: + std = 0.001 + noise = std * noise_level + data[:, idx] = np.add( + obs_data[:, idx], + np.random.normal(0, 1, obs_data.shape[0]) * noise, + ) + + final_data[itrIdx] = data.T[~np.isnan(data.T)] + + return final_data + + # ------------------------------------------------------------------------- + def _logpdf(self, x, mean, cov): + """ + computes the likelihood based on a multivariate normal distribution. + + Parameters + ---------- + x : TYPE + DESCRIPTION. + mean : array_like + Observation data. + cov : 2d array + Covariance matrix of the distribution. + + Returns + ------- + log_lik : float + Log likelihood. + + """ + n = len(mean) + L = spla.cholesky(cov, lower=True) + beta = np.sum(np.log(np.diag(L))) + dev = x - mean + alpha = dev.dot(spla.cho_solve((L, True), dev)) + log_lik = -0.5 * alpha - beta - n / 2. * np.log(2 * np.pi) + return log_lik + + # ------------------------------------------------------------------------- + def _eval_model(self, samples=None, key='MAP'): + """ + Evaluates Forward Model. + + Parameters + ---------- + samples : array of shape (n_samples, n_params), optional + Parameter sets. The default is None. + key : str, optional + Key string to be passed to the run_model_parallel method. + The default is 'MAP'. + + Returns + ------- + model_outputs : dict + Model outputs. + + """ + MetaModel = self.MetaModel + Model = self.engine.Model + + if samples is None: + self.samples = self.engine.ExpDesign.generate_samples( + self.n_samples, 'random') + else: + self.samples = samples + self.n_samples = len(samples) + + model_outputs, _ = Model.run_model_parallel( + self.samples, key_str=key+self.name) + + # Clean up + # Zip the subdirectories + try: + dir_name = f'{Model.name}MAP{self.name}' + key = dir_name + '_' + Model.zip_subdirs(dir_name, key) + except: + pass + + return model_outputs + + # ------------------------------------------------------------------------- + def _kernel_rbf(self, X, hyperparameters): + """ + Isotropic squared exponential kernel. + + Higher l values lead to smoother functions and therefore to coarser + approximations of the training data. Lower l values make functions + more wiggly with wide uncertainty regions between training data points. + + sigma_f controls the marginal variance of b(x) + + Parameters + ---------- + X : ndarray of shape (n_samples_X, n_features) + + hyperparameters : Dict + Lambda characteristic length + sigma_f controls the marginal variance of b(x) + sigma_0 unresolvable error nugget term, interpreted as random + error that cannot be attributed to measurement error. + Returns + ------- + var_cov_matrix : ndarray of shape (n_samples_X,n_samples_X) + Kernel k(X, X). + + """ + from sklearn.gaussian_process.kernels import RBF + min_max_scaler = preprocessing.MinMaxScaler() + X_minmax = min_max_scaler.fit_transform(X) + + nparams = len(hyperparameters) + # characteristic length (0,1] + Lambda = hyperparameters[0] + # sigma_f controls the marginal variance of b(x) + sigma2_f = hyperparameters[1] + + # cov_matrix = sigma2_f*rbf_kernel(X_minmax, gamma = 1/Lambda**2) + + rbf = RBF(length_scale=Lambda) + cov_matrix = sigma2_f * rbf(X_minmax) + if nparams > 2: + # (unresolvable error) nugget term that is interpreted as random + # error that cannot be attributed to measurement error. + sigma2_0 = hyperparameters[2:] + for i, j in np.ndindex(cov_matrix.shape): + cov_matrix[i, j] += np.sum(sigma2_0) if i == j else 0 + + return cov_matrix + + # ------------------------------------------------------------------------- + def normpdf(self, outputs, obs_data, total_sigma2s, sigma2=None, std=None): + """ + Calculates the likelihood of simulation outputs compared with + observation data. + + Parameters + ---------- + outputs : dict + A dictionary containing the simulation outputs as array of shape + (n_samples, n_measurement) for each model output. + obs_data : dict + A dictionary/dataframe containing the observation data. + total_sigma2s : dict + A dictionary with known values of the covariance diagonal entries, + a.k.a sigma^2. + sigma2 : array, optional + An array of the sigma^2 samples, when the covariance diagonal + entries are unknown and are being jointly inferred. The default is + None. + std : dict, optional + A dictionary containing the root mean squared error as array of + shape (n_samples, n_measurement) for each model output. The default + is None. + + Returns + ------- + logLik : array of shape (n_samples) + Likelihoods. + + """ + Model = self.engine.Model + logLik = 0.0 + + # Extract the requested model outputs for likelihood calulation + if self.req_outputs is None: + req_outputs = Model.Output.names + else: + req_outputs = list(self.req_outputs) + + # Loop over the outputs + for idx, out in enumerate(req_outputs): + + # (Meta)Model Output + nsamples, nout = outputs[out].shape + + # Prepare data and remove NaN + try: + data = obs_data[out].values[~np.isnan(obs_data[out])] + except AttributeError: + data = obs_data[out][~np.isnan(obs_data[out])] + + # Prepare sigma2s + non_nan_indices = ~np.isnan(total_sigma2s[out]) + tot_sigma2s = total_sigma2s[out][non_nan_indices][:nout] + + # Add the std of the PCE is chosen as emulator. + if self.emulator: + if std is not None: + tot_sigma2s += std[out]**2 + + # Covariance Matrix + covMatrix = np.diag(tot_sigma2s) + + # Select the data points to compare + try: + indices = self.selected_indices[out] + except: + indices = list(range(nout)) + covMatrix = np.diag(covMatrix[indices, indices]) + + # If sigma2 is not given, use given total_sigma2s + if sigma2 is None: + logLik += stats.multivariate_normal.logpdf( + outputs[out][:, indices], data[indices], covMatrix) + #print('In if') + #print(logLik) + continue + + # Loop over each run/sample and calculate logLikelihood + logliks = np.zeros(nsamples) + for s_idx in range(nsamples): + + # Simulation run + tot_outputs = outputs[out] + + # Covariance Matrix + covMatrix = np.diag(tot_sigma2s) + + if sigma2 is not None: + # Check the type error term + if hasattr(self, 'bias_inputs') and \ + not hasattr(self, 'error_model'): + # Infer a Bias model usig Gaussian Process Regression + bias_inputs = np.hstack( + (self.bias_inputs[out], + tot_outputs[s_idx].reshape(-1, 1))) + + params = sigma2[s_idx, idx*3:(idx+1)*3] + covMatrix = self._kernel_rbf(bias_inputs, params) + else: + # Infer equal sigma2s + try: + sigma_2 = sigma2[s_idx, idx] + except TypeError: + sigma_2 = 0.0 + + covMatrix += sigma_2 * np.eye(nout) + # covMatrix = np.diag(sigma2 * total_sigma2s) + + # Select the data points to compare + try: + indices = self.selected_indices[out] + except: + indices = list(range(nout)) + covMatrix = np.diag(covMatrix[indices, indices]) + + # Compute loglikelihood + logliks[s_idx] = self._logpdf( + tot_outputs[s_idx, indices], data[indices], covMatrix + ) + #print('Continued') + #print(logliks) + logLik += logliks + #print(logLik) + return logLik + + # ------------------------------------------------------------------------- + def _corr_factor_BME_old(self, Data, total_sigma2s, posterior): + """ + Calculates the correction factor for BMEs. + """ + MetaModel = self.MetaModel + OrigModelOutput = self.engine.ExpDesign.Y + Model = self.engine.Model + + # Posterior with guassian-likelihood + postDist = stats.gaussian_kde(posterior.T) + + # Remove NaN + Data = Data[~np.isnan(Data)] + total_sigma2s = total_sigma2s[~np.isnan(total_sigma2s)] + + # Covariance Matrix + covMatrix = np.diag(total_sigma2s[:self.n_tot_measurement]) + + # Extract the requested model outputs for likelihood calulation + if self.req_outputs is None: + OutputType = Model.Output.names + else: + OutputType = list(self.req_outputs) + + # SampleSize = OrigModelOutput[OutputType[0]].shape[0] + + + # Flatten the OutputType for OrigModel + TotalOutputs = np.concatenate([OrigModelOutput[x] for x in OutputType], 1) + + NrofBayesSamples = self.n_samples + # Evaluate MetaModel on the experimental design + Samples = self.engine.ExpDesign.X + OutputRS, stdOutputRS = MetaModel.eval_metamodel(samples=Samples) + + # Reset the NrofSamples to NrofBayesSamples + self.n_samples = NrofBayesSamples + + # Flatten the OutputType for MetaModel + TotalPCEOutputs = np.concatenate([OutputRS[x] for x in OutputRS], 1) + TotalPCEstdOutputRS= np.concatenate([stdOutputRS[x] for x in stdOutputRS], 1) + + logweight = 0 + for i, sample in enumerate(Samples): + # Compute likelilhood output vs RS + covMatrix = np.diag(TotalPCEstdOutputRS[i]**2) + logLik = self._logpdf(TotalOutputs[i], TotalPCEOutputs[i], covMatrix) + # Compute posterior likelihood of the collocation points + logpostLik = np.log(postDist.pdf(sample[:, None]))[0] + if logpostLik != -np.inf: + logweight += logLik + logpostLik + return logweight + + # ------------------------------------------------------------------------- + def __corr_factor_BME(self, obs_data, total_sigma2s, logBME): + """ + Calculates the correction factor for BMEs. + """ + MetaModel = self.MetaModel + samples = self.engine.ExpDesign.X + model_outputs = self.engine.ExpDesign.Y + Model = self.engine.Model + n_samples = samples.shape[0] + + # Extract the requested model outputs for likelihood calulation + output_names = Model.Output.names + + # Evaluate MetaModel on the experimental design and ValidSet + OutputRS, stdOutputRS = MetaModel.eval_metamodel(samples=samples) + + logLik_data = np.zeros((n_samples)) + logLik_model = np.zeros((n_samples)) + # Loop over the outputs + for idx, out in enumerate(output_names): + + # (Meta)Model Output + nsamples, nout = model_outputs[out].shape + + # Prepare data and remove NaN + try: + data = obs_data[out].values[~np.isnan(obs_data[out])] + except AttributeError: + data = obs_data[out][~np.isnan(obs_data[out])] + + # Prepare sigma2s + non_nan_indices = ~np.isnan(total_sigma2s[out]) + tot_sigma2s = total_sigma2s[out][non_nan_indices][:nout] + + # Covariance Matrix + covMatrix_data = np.diag(tot_sigma2s) + + for i, sample in enumerate(samples): + + # Simulation run + y_m = model_outputs[out][i] + + # Surrogate prediction + y_m_hat = OutputRS[out][i] + + # CovMatrix with the surrogate error + covMatrix = np.eye(len(y_m)) * 1/(2*np.pi) + + # Select the data points to compare + try: + indices = self.selected_indices[out] + except: + indices = list(range(nout)) + covMatrix = np.diag(covMatrix[indices, indices]) + covMatrix_data = np.diag(covMatrix_data[indices, indices]) + + # Compute likelilhood output vs data + logLik_data[i] += self._logpdf( + y_m_hat[indices], data[indices], + covMatrix_data + ) + + # Compute likelilhood output vs surrogate + logLik_model[i] += self._logpdf( + y_m_hat[indices], y_m[indices], + covMatrix + ) + + # Weight + logLik_data -= logBME + weights = np.mean(np.exp(logLik_model+logLik_data)) + + return np.log(weights) + + # ------------------------------------------------------------------------- + def _rejection_sampling(self): + """ + Performs rejection sampling to update the prior distribution on the + input parameters. + + Returns + ------- + posterior : pandas.dataframe + Posterior samples of the input parameters. + + """ + + MetaModel = self.MetaModel + try: + sigma2_prior = self.Discrepancy.sigma2_prior + except: + sigma2_prior = None + + # Check if the discrepancy is defined as a distribution: + samples = self.samples + + if sigma2_prior is not None: + samples = np.hstack((samples, sigma2_prior)) + + # Take the first column of Likelihoods (Observation data without noise) + if self.just_analysis or self.bayes_loocv: + index = self.n_tot_measurement-1 + likelihoods = np.exp(self.log_likes[:, index], dtype=np.longdouble)#np.float128) + else: + likelihoods = np.exp(self.log_likes[:, 0], dtype=np.longdouble)#np.float128) + + n_samples = len(likelihoods) + norm_ikelihoods = likelihoods / np.max(likelihoods) + + # Normalize based on min if all Likelihoods are zero + if all(likelihoods == 0.0): + likelihoods = self.log_likes[:, 0] + norm_ikelihoods = likelihoods / np.min(likelihoods) + + # Random numbers between 0 and 1 + unif = np.random.rand(1, n_samples)[0] + + # Reject the poorly performed prior + accepted_samples = samples[norm_ikelihoods >= unif] + + # Output the Posterior + par_names = self.engine.ExpDesign.par_names + if sigma2_prior is not None: + for name in self.Discrepancy.name: + par_names.append(name) + + return pd.DataFrame(accepted_samples, columns=sigma2_prior) + + # ------------------------------------------------------------------------- + def _posterior_predictive(self): + """ + Stores the prior- and posterior predictive samples, i.e. model + evaluations using the samples, into hdf5 files. + + priorPredictive.hdf5 : Prior predictive samples. + postPredictive_wo_noise.hdf5 : Posterior predictive samples without + the additive noise. + postPredictive.hdf5 : Posterior predictive samples with the additive + noise. + + Returns + ------- + None. + + """ + + MetaModel = self.MetaModel + Model = self.engine.Model + + # Make a directory to save the prior/posterior predictive + out_dir = f'Outputs_Bayes_{Model.name}_{self.name}' + os.makedirs(out_dir, exist_ok=True) + + # Read observation data and perturb it if requested + if self.measured_data is None: + self.measured_data = Model.read_observation(case=self.name) + + if not isinstance(self.measured_data, pd.DataFrame): + self.measured_data = pd.DataFrame(self.measured_data) + + # X_values + x_values = self.engine.ExpDesign.x_values + + try: + sigma2_prior = self.Discrepancy.sigma2_prior + except: + sigma2_prior = None + + # Extract posterior samples + posterior_df = self.posterior_df + + # Take care of the sigma2 + if sigma2_prior is not None: + try: + sigma2s = posterior_df[self.Discrepancy.name].values + posterior_df = posterior_df.drop( + labels=self.Discrepancy.name, axis=1 + ) + except: + sigma2s = self.sigma2s + + # Posterior predictive + if self.emulator: + if self.inference_method == 'rejection': + prior_pred = self.__mean_pce_prior_pred + if self.name.lower() != 'calib': + post_pred = self.__mean_pce_prior_pred + post_pred_std = self._std_pce_prior_pred + else: + post_pred, post_pred_std = MetaModel.eval_metamodel( + samples=posterior_df.values + ) + + else: + if self.inference_method == 'rejection': + prior_pred = self.__model_prior_pred + if self.name.lower() != 'calib': + post_pred = self.__mean_pce_prior_pred, + post_pred_std = self._std_pce_prior_pred + else: + post_pred = self._eval_model( + samples=posterior_df.values, key='PostPred' + ) + # Correct the predictions with Model discrepancy + if hasattr(self, 'error_model') and self.error_model: + y_hat, y_std = self.error_MetaModel.eval_model_error( + self.bias_inputs, post_pred + ) + post_pred, post_pred_std = y_hat, y_std + + # Add discrepancy from likelihood Sample to the current posterior runs + total_sigma2 = self.Discrepancy.total_sigma2 + post_pred_withnoise = copy.deepcopy(post_pred) + for varIdx, var in enumerate(Model.Output.names): + for i in range(len(post_pred[var])): + pred = post_pred[var][i] + + # Known sigma2s + clean_sigma2 = total_sigma2[var][~np.isnan(total_sigma2[var])] + tot_sigma2 = clean_sigma2[:len(pred)] + cov = np.diag(tot_sigma2) + + # Check the type error term + if sigma2_prior is not None: + # Inferred sigma2s + if hasattr(self, 'bias_inputs') and \ + not hasattr(self, 'error_model'): + # TODO: Infer a Bias model usig GPR + bias_inputs = np.hstack(( + self.bias_inputs[var], pred.reshape(-1, 1))) + params = sigma2s[i, varIdx*3:(varIdx+1)*3] + cov = self._kernel_rbf(bias_inputs, params) + else: + # Infer equal sigma2s + try: + sigma2 = sigma2s[i, varIdx] + except TypeError: + sigma2 = 0.0 + + # Convert biasSigma2s to a covMatrix + cov += sigma2 * np.eye(len(pred)) + + if self.emulator: + if hasattr(MetaModel, 'rmse') and \ + MetaModel.rmse is not None: + stdPCE = MetaModel.rmse[var] + else: + stdPCE = post_pred_std[var][i] + # Expected value of variance (Assump: i.i.d stds) + cov += np.diag(stdPCE**2) + + # Sample a multivariate normal distribution with mean of + # prediction and variance of cov + post_pred_withnoise[var][i] = np.random.multivariate_normal( + pred, cov, 1 + ) + + # ----- Prior Predictive ----- + if self.inference_method.lower() == 'rejection': + # Create hdf5 metadata + hdf5file = f'{out_dir}/priorPredictive.hdf5' + hdf5_exist = os.path.exists(hdf5file) + if hdf5_exist: + os.remove(hdf5file) + file = h5py.File(hdf5file, 'a') + + # Store x_values + if type(x_values) is dict: + grp_x_values = file.create_group("x_values/") + for varIdx, var in enumerate(Model.Output.names): + grp_x_values.create_dataset(var, data=x_values[var]) + else: + file.create_dataset("x_values", data=x_values) + + # Store posterior predictive + grpY = file.create_group("EDY/") + for varIdx, var in enumerate(Model.Output.names): + grpY.create_dataset(var, data=prior_pred[var]) + + # ----- Posterior Predictive only model evaluations ----- + # Create hdf5 metadata + hdf5file = out_dir+'/postPredictive_wo_noise.hdf5' + hdf5_exist = os.path.exists(hdf5file) + if hdf5_exist: + os.remove(hdf5file) + file = h5py.File(hdf5file, 'a') + + # Store x_values + if type(x_values) is dict: + grp_x_values = file.create_group("x_values/") + for varIdx, var in enumerate(Model.Output.names): + grp_x_values.create_dataset(var, data=x_values[var]) + else: + file.create_dataset("x_values", data=x_values) + + # Store posterior predictive + grpY = file.create_group("EDY/") + for varIdx, var in enumerate(Model.Output.names): + grpY.create_dataset(var, data=post_pred[var]) + + # ----- Posterior Predictive with noise ----- + # Create hdf5 metadata + hdf5file = out_dir+'/postPredictive.hdf5' + hdf5_exist = os.path.exists(hdf5file) + if hdf5_exist: + os.remove(hdf5file) + file = h5py.File(hdf5file, 'a') + + # Store x_values + if type(x_values) is dict: + grp_x_values = file.create_group("x_values/") + for varIdx, var in enumerate(Model.Output.names): + grp_x_values.create_dataset(var, data=x_values[var]) + else: + file.create_dataset("x_values", data=x_values) + + # Store posterior predictive + grpY = file.create_group("EDY/") + for varIdx, var in enumerate(Model.Output.names): + grpY.create_dataset(var, data=post_pred_withnoise[var]) + + return + + # ------------------------------------------------------------------------- + def _plot_max_a_posteriori(self): + """ + Plots the response of the model output against that of the metamodel at + the maximum a posteriori sample (mean or mode of posterior.) + + Returns + ------- + None. + + """ + + MetaModel = self.MetaModel + Model = self.engine.Model + out_dir = f'Outputs_Bayes_{Model.name}_{self.name}' + opt_sigma = self.Discrepancy.opt_sigma + + # -------- Find MAP and run MetaModel and origModel -------- + # Compute the MAP + if self.max_a_posteriori.lower() == 'mean': + if opt_sigma == "B": + Posterior_df = self.posterior_df.values + else: + Posterior_df = self.posterior_df.values[:, :-Model.n_outputs] + map_theta = Posterior_df.mean(axis=0).reshape( + (1, MetaModel.n_params)) + else: + map_theta = stats.mode(Posterior_df.values, axis=0)[0] + # Prin report + print("\nPoint estimator:\n", map_theta[0]) + + # Run the models for MAP + # MetaModel + map_metamodel_mean, map_metamodel_std = MetaModel.eval_metamodel( + samples=map_theta) + self.map_metamodel_mean = map_metamodel_mean + self.map_metamodel_std = map_metamodel_std + + # origModel + map_orig_model = self._eval_model(samples=map_theta) + self.map_orig_model = map_orig_model + + # Extract slicing index + x_values = map_orig_model['x_values'] + + # List of markers and colors + Color = ['k', 'b', 'g', 'r'] + Marker = 'x' + + # Create a PdfPages object + pdf = PdfPages(f'./{out_dir}MAP_PCE_vs_Model_{self.name}.pdf') + fig = plt.figure() + for i, key in enumerate(Model.Output.names): + + y_val = map_orig_model[key] + y_pce_val = map_metamodel_mean[key] + y_pce_val_std = map_metamodel_std[key] + + plt.plot(x_values, y_val, color=Color[i], marker=Marker, + lw=2.0, label='$Y_{MAP}^{M}$') + + plt.plot( + x_values, y_pce_val[i], color=Color[i], lw=2.0, + marker=Marker, linestyle='--', label='$Y_{MAP}^{PCE}$' + ) + # plot the confidence interval + plt.fill_between( + x_values, y_pce_val[i] - 1.96*y_pce_val_std[i], + y_pce_val[i] + 1.96*y_pce_val_std[i], + color=Color[i], alpha=0.15 + ) + + # Calculate the adjusted R_squared and RMSE + R2 = r2_score(y_pce_val.reshape(-1, 1), y_val.reshape(-1, 1)) + rmse = np.sqrt(mean_squared_error(y_pce_val, y_val)) + + plt.ylabel(key) + plt.xlabel("Time [s]") + plt.title(f'Model vs MetaModel {key}') + + ax = fig.axes[0] + leg = ax.legend(loc='best', frameon=True) + fig.canvas.draw() + p = leg.get_window_extent().inverse_transformed(ax.transAxes) + ax.text( + p.p0[1]-0.05, p.p1[1]-0.25, + f'RMSE = {rmse:.3f}\n$R^2$ = {R2:.3f}', + transform=ax.transAxes, color='black', + bbox=dict(facecolor='none', edgecolor='black', + boxstyle='round,pad=1')) + + plt.show() + + # save the current figure + pdf.savefig(fig, bbox_inches='tight') + + # Destroy the current plot + plt.clf() + + pdf.close() + + # ------------------------------------------------------------------------- + def _plot_post_predictive(self): + """ + Plots the posterior predictives against the observation data. + + Returns + ------- + None. + + """ + + Model = self.engine.Model + out_dir = f'Outputs_Bayes_{Model.name}_{self.name}' + # Plot the posterior predictive + for out_idx, out_name in enumerate(Model.Output.names): + fig, ax = plt.subplots() + with sns.axes_style("ticks"): + x_key = list(self.measured_data)[0] + + # --- Read prior and posterior predictive --- + if self.inference_method == 'rejection' and \ + self.name.lower() != 'valid': + # --- Prior --- + # Load posterior predictive + f = h5py.File( + f'{out_dir}/priorPredictive.hdf5', 'r+') + + try: + x_coords = np.array(f[f"x_values/{out_name}"]) + except: + x_coords = np.array(f["x_values"]) + + X_values = np.repeat(x_coords, 10000) + + prior_pred_df = {} + prior_pred_df[x_key] = X_values + prior_pred_df[out_name] = np.array( + f[f"EDY/{out_name}"])[:10000].flatten('F') + prior_pred_df = pd.DataFrame(prior_pred_df) + + tags_post = ['prior'] * len(prior_pred_df) + prior_pred_df.insert( + len(prior_pred_df.columns), "Tags", tags_post, + True) + f.close() + + # --- Posterior --- + f = h5py.File(f"{out_dir}/postPredictive.hdf5", 'r+') + + X_values = np.repeat( + x_coords, np.array(f[f"EDY/{out_name}"]).shape[0]) + + post_pred_df = {} + post_pred_df[x_key] = X_values + post_pred_df[out_name] = np.array( + f[f"EDY/{out_name}"]).flatten('F') + + post_pred_df = pd.DataFrame(post_pred_df) + + tags_post = ['posterior'] * len(post_pred_df) + post_pred_df.insert( + len(post_pred_df.columns), "Tags", tags_post, True) + f.close() + # Concatenate two dataframes based on x_values + frames = [prior_pred_df, post_pred_df] + all_pred_df = pd.concat(frames) + + # --- Plot posterior predictive --- + sns.violinplot( + x_key, y=out_name, data=all_pred_df, hue="Tags", + legend=False, ax=ax, split=True, inner=None, + color=".8") + + # --- Plot Data --- + # Find the x,y coordinates for each point + x_coords = np.arange(x_coords.shape[0]) + first_header = list(self.measured_data)[0] + obs_data = self.measured_data.round({first_header: 6}) + sns.pointplot( + x=first_header, y=out_name, color='g', markers='x', + linestyles='', capsize=16, data=obs_data, ax=ax) + + ax.errorbar( + x_coords, obs_data[out_name].values, + yerr=1.96*self.measurement_error[out_name], + ecolor='g', fmt=' ', zorder=-1) + + # Add labels to the legend + handles, labels = ax.get_legend_handles_labels() + labels.append('Data') + + data_marker = mlines.Line2D( + [], [], color='lime', marker='+', linestyle='None', + markersize=10) + handles.append(data_marker) + + # Add legend + ax.legend(handles=handles, labels=labels, loc='best', + fontsize='large', frameon=True) + + else: + # Load posterior predictive + f = h5py.File(f"{out_dir}/postPredictive.hdf5", 'r+') + + try: + x_coords = np.array(f[f"x_values/{out_name}"]) + except: + x_coords = np.array(f["x_values"]) + + mu = np.mean(np.array(f[f"EDY/{out_name}"]), axis=0) + std = np.std(np.array(f[f"EDY/{out_name}"]), axis=0) + + # --- Plot posterior predictive --- + plt.plot( + x_coords, mu, marker='o', color='b', + label='Mean Post. Predictive') + plt.fill_between( + x_coords, mu-1.96*std, mu+1.96*std, color='b', + alpha=0.15) + + # --- Plot Data --- + ax.plot( + x_coords, self.measured_data[out_name].values, + 'ko', label='data', markeredgecolor='w') + + # --- Plot ExpDesign --- + orig_ED_Y = self.engine.ExpDesign.Y[out_name] + for output in orig_ED_Y: + plt.plot( + x_coords, output, color='grey', alpha=0.15 + ) + + # Add labels for axes + plt.xlabel('Time [s]') + plt.ylabel(out_name) + + # Add labels to the legend + handles, labels = ax.get_legend_handles_labels() + + patch = Patch(color='b', alpha=0.15) + handles.insert(1, patch) + labels.insert(1, '95 $\\%$ CI') + + # Add legend + ax.legend(handles=handles, labels=labels, loc='best', + frameon=True) + + # Save figure in pdf format + if self.emulator: + plotname = f'/Post_Prior_Perd_{Model.name}_emulator' + else: + plotname = f'/Post_Prior_Perd_{Model.name}' + + fig.savefig(f'./{out_dir}{plotname}_{out_name}.pdf', + bbox_inches='tight') diff --git a/examples/analytical-function/bayesvalidrox/bayes_inference/bayes_model_comparison.py b/examples/analytical-function/bayesvalidrox/bayes_inference/bayes_model_comparison.py new file mode 100644 index 000000000..769ad2cea --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/bayes_inference/bayes_model_comparison.py @@ -0,0 +1,680 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import emcee +import numpy as np +import os +from scipy import stats +import seaborn as sns +import matplotlib.patches as patches +import matplotlib.colors as mcolors +import matplotlib.pylab as plt +from .bayes_inference import BayesInference + +# Load the mplstyle +plt.style.use(os.path.join(os.path.split(__file__)[0], + '../', 'bayesvalidrox.mplstyle')) + + +class BayesModelComparison: + """ + A class to perform Bayesian Analysis. + + + Attributes + ---------- + justifiability : bool, optional + Whether to perform the justifiability analysis. The default is + `True`. + perturbed_data : array of shape (n_bootstrap_itrs, n_obs), optional + User defined perturbed data. The default is `None`. + n_bootstrap : int + Number of bootstrap iteration. The default is `1000`. + data_noise_level : float + A noise level to perturb the data set. The default is `0.01`. + just_n_meas : int + Number of measurements considered for visualization of the + justifiability results. + + """ + + def __init__(self, justifiability=True, perturbed_data=None, + n_bootstrap=1000, data_noise_level=0.01, just_n_meas=2): + + # TODO: check valid ranges of the parameters + + self.justifiability = justifiability + self.perturbed_data = perturbed_data + self.n_bootstrap = n_bootstrap + self.data_noise_level = data_noise_level + self.just_n_meas = just_n_meas # TODO: what is this parameter? + + # -------------------------------------------------------------------------- + def create_model_comparison(self, model_dict, opts_dict): + """ + Starts the two-stage model comparison. + Stage I: Compare models using Bayes factors. + Stage II: Compare models via justifiability analysis. + + Parameters + ---------- + model_dict : dict + A dictionary including the metamodels. + opts_dict : dict + A dictionary given the `BayesInference` options. + + Example: + + >>> opts_bootstrap = { + "bootstrap": True, + "n_samples": 10000, + "Discrepancy": DiscrepancyOpts, + "emulator": True, + "plot_post_pred": True + } + + Returns + ------- + output : dict + A dictionary containing the objects and the model weights for the + comparison using Bayes factors and justifiability analysis. + + """ + # TODO: why are these two separate calls of the same function? + # They should be performable at the same time + + # Bayes factor + bayes_dict_bf, model_weights_dict_bf = self.compare_models( + model_dict, opts_dict + ) + + output = { + 'Bayes objects BF': bayes_dict_bf, + 'Model weights BF': model_weights_dict_bf + } + + # Justifiability analysis + if self.justifiability: + bayes_dict_ja, model_weights_dict_ja = self.compare_models( + model_dict, opts_dict, justifiability=True + ) + + # TODO: why does this version of the call not return a summarized confusion matrix? + output['Bayes objects JA'] = bayes_dict_ja + output['Model weights JA'] = model_weights_dict_ja + + return output + + # -------------------------------------------------------------------------- + def compare_models(self, model_dict, opts_dict, justifiability=False): + """ + Passes the options to instantiates the BayesInference class for each + model and passes the options from `opts_dict`. Then, it starts the + computations. + It also creates a folder and saves the diagrams, e.g., Bayes factor + plot, confusion matrix, etc. + + Parameters + ---------- + model_dict : dict + A dictionary including the metamodels. + opts_dict : dict + A dictionary given the `BayesInference` options. + justifiability : bool, optional + Whether to perform the justifiability analysis. The default is + `False`. + + Returns + ------- + bayes_dict : dict + A dictionary with `BayesInference` objects. + model_weights_dict : dict + A dictionary containing the model weights. + + """ + + if not isinstance(model_dict, dict): + raise Exception("To run model comparsion, you need to pass a " + "dictionary of models.") + + # Extract model names + self.model_names = [*model_dict] + + # Compute total number of the measurement points + # TODO: there could be a different option for this here + Engine = list(model_dict.items())[0][1] + Engine.Model.read_observation() + self.n_meas = Engine.Model.n_obs + + # ----- Generate data ----- + # Find n_bootstrap + if self.perturbed_data is None: + n_bootstrap = self.n_bootstrap + else: + n_bootstrap = self.perturbed_data.shape[0] + + # Create dataset + justData = self.generate_dataset( + model_dict, justifiability, n_bootstarp=n_bootstrap) + + # Run create Interface for each model + self.bayes_dict = {} + for model in model_dict.keys(): + print("-"*20) + print("Bayesian inference of {}.\n".format(model)) + + BayesOpts = BayesInference(model_dict[model]) + + # Explicitly set the settings of the BayesOpts + if self.use_Bayes_settings: + BayesOpts.emulator= True + BayesOpts.plot_post_pred = True + #BayesOpts.inference_method = 'rejection' + BayesOpts.bootstrap = True + BayesOpts.n_bootstrap_itrs = 10 + BayesOpts.bootstrap_noise = 0.05 + + # Set the MCMC parameters + BayesOpts.inference_method = "MCMC" + BayesOpts.mcmc_params = { + 'n_steps': 1e3,#5, + 'n_walkers': 30, + 'moves': emcee.moves.KDEMove(), + 'multiprocessing': False, + 'verbose': False + } + + # Set BayesInference options + for key, value in opts_dict.items(): + if key in BayesOpts.__dict__.keys(): + if key == "Discrepancy" and isinstance(value, dict): + setattr(BayesOpts, key, value[model]) + else: + setattr(BayesOpts, key, value) + + # Pass justifiability data as perturbed data + BayesOpts.perturbed_data = justData + BayesOpts.just_analysis = justifiability + + self.bayes_dict[model] = BayesOpts.create_inference() + print("-"*20) + + # Compute model weights + self.BME_Dict = dict() + for modelName, bayesObj in self.bayes_dict.items(): + self.BME_Dict[modelName] = np.exp(bayesObj.log_BME, dtype=np.longdouble)#float128) + + # BME correction in BayesInference class + self.model_weights = self.cal_model_weight( + self.BME_Dict, justifiability, n_bootstarp=n_bootstrap) + + # Plot model weights + if justifiability: + model_names = self.model_names + model_names.insert(0, 'Observation') + + # Split the model weights and save in a dict + list_ModelWeights = np.split( + self.model_weights, self.model_weights.shape[1]/self.n_meas, axis=1) + model_weights_dict = {key: weights for key, weights in + zip(model_names, list_ModelWeights)} + + #self.plot_just_analysis(model_weights_dict) + else: + # Create box plot for model weights + self.plot_model_weights(self.model_weights, 'model_weights') + + # Create kde plot for bayes factors + self.plot_bayes_factor(self.BME_Dict, 'kde_plot') + + # Store model weights in a dict + model_weights_dict = {key: weights for key, weights in + zip(self.model_names, self.model_weights)} + + return self.bayes_dict, model_weights_dict + + # ------------------------------------------------------------------------- + def generate_dataset(self, model_dict, justifiability=False, + n_bootstrap=1): + """ + Generates the perturbed data set for the Bayes factor calculations and + the data set for the justifiability analysis. + + Parameters + ---------- + model_dict : dict + A dictionary including the metamodels. + bool, optional + Whether to perform the justifiability analysis. The default is + `False`. + n_bootstrap : int, optional + Number of bootstrap iterations. The default is `1`. + + Returns + ------- + all_just_data: array + Created data set. + + """ + # Compute some variables + all_just_data = [] + Engine = list(model_dict.items())[0][1] + out_names = Engine.Model.Output.names + + # Perturb observations for Bayes Factor + if self.perturbed_data is None: + self.perturbed_data = self.__perturb_data( + Engine.Model.observations, out_names, n_bootstrap, + noise_level=self.data_noise_level) + + # Only for Bayes Factor + if not justifiability: + return self.perturbed_data + + # Evaluate metamodel + runs = {} + for key, metaModel in model_dict.items(): + y_hat, _ = metaModel.eval_metamodel(nsamples=n_bootstrap) + runs[key] = y_hat + + # Generate data + for i in range(n_bootstrap): + y_data = self.perturbed_data[i].reshape(1, -1) + justData = np.tril(np.repeat(y_data, y_data.shape[1], axis=0)) + # Use surrogate runs for data-generating process + for key, metaModel in model_dict.items(): + model_data = np.array( + [runs[key][out][i] for out in out_names]).reshape(y_data.shape) + justData = np.vstack(( + justData, + np.tril(np.repeat(model_data, model_data.shape[1], axis=0)) + )) + # Save in a list + all_just_data.append(justData) + + # Squeeze the array + all_just_data = np.array(all_just_data).transpose(1, 0, 2).reshape( + -1, np.array(all_just_data).shape[2] + ) + + return all_just_data + + # ------------------------------------------------------------------------- + def __perturb_data(self, data, output_names, n_bootstrap, noise_level): + """ + Returns an array with n_bootstrap_itrs rowsof perturbed data. + The first row includes the original observation data. + If `self.bayes_loocv` is True, a 2d-array will be returned with + repeated rows and zero diagonal entries. + + Parameters + ---------- + data : pandas DataFrame + Observation data. + output_names : list + List of the output names. + + Returns + ------- + final_data : array + Perturbed data set. + + """ + obs_data = data[output_names].values + n_measurement, n_outs = obs_data.shape + n_tot_measurement = obs_data[~np.isnan(obs_data)].shape[0] + final_data = np.zeros( + (n_bootstrap, n_tot_measurement) + ) + final_data[0] = obs_data.T[~np.isnan(obs_data.T)] + for itrIdx in range(1, n_bootstrap): + data = np.zeros((n_measurement, n_outs)) + for idx in range(len(output_names)): + std = np.nanstd(obs_data[:, idx]) + if std == 0: + std = 0.001 + noise = std * noise_level + data[:, idx] = np.add( + obs_data[:, idx], + np.random.normal(0, 1, obs_data.shape[0]) * noise, + ) + + final_data[itrIdx] = data.T[~np.isnan(data.T)] + + return final_data + + # ------------------------------------------------------------------------- + def cal_model_weight(self, BME_Dict, justifiability=False, n_bootstrap=1): + """ + Normalize the BME (Asumption: Model Prior weights are equal for models) + + Parameters + ---------- + BME_Dict : dict + A dictionary containing the BME values. + + Returns + ------- + model_weights : array + Model weights. + + """ + # Stack the BME values for all models + all_BME = np.vstack(list(BME_Dict.values())) + + if justifiability: + # Compute expected log_BME for justifiabiliy analysis + all_BME = all_BME.reshape( + all_BME.shape[0], -1, n_bootstrap).mean(axis=2) + + # Model weights + model_weights = np.divide(all_BME, np.nansum(all_BME, axis=0)) + + return model_weights + + # ------------------------------------------------------------------------- + def plot_just_analysis(self, model_weights_dict): + """ + Visualizes the confusion matrix and the model wights for the + justifiability analysis. + + Parameters + ---------- + model_weights_dict : dict + Model weights. + + Returns + ------- + None. + + """ + + directory = 'Outputs_Comparison/' + os.makedirs(directory, exist_ok=True) + Color = [*mcolors.TABLEAU_COLORS] + names = [*model_weights_dict] + + model_names = [model.replace('_', '$-$') for model in self.model_names] + for name in names: + fig, ax = plt.subplots() + for i, model in enumerate(model_names[1:]): + plt.plot(list(range(1, self.n_meas+1)), + model_weights_dict[name][i], + color=Color[i], marker='o', + ms=10, linewidth=2, label=model + ) + + plt.title(f"Data generated by: {name.replace('_', '$-$')}") + plt.ylabel("Weights") + plt.xlabel("No. of measurement points") + ax.set_xticks(list(range(1, self.n_meas+1))) + plt.legend(loc="best") + fig.savefig( + f'{directory}modelWeights_{name}.svg', bbox_inches='tight' + ) + plt.close() + + # Confusion matrix for some measurement points + epsilon = 1 if self.just_n_meas != 1 else 0 + for index in range(0, self.n_meas+epsilon, self.just_n_meas): + weights = np.array( + [model_weights_dict[key][:, index] for key in model_weights_dict] + ) + g = sns.heatmap( + weights.T, annot=True, cmap='Blues', xticklabels=model_names, + yticklabels=model_names[1:], annot_kws={"size": 24} + ) + + # x axis on top + g.xaxis.tick_top() + g.xaxis.set_label_position('top') + g.set_xlabel(r"\textbf{Data generated by:}", labelpad=15) + g.set_ylabel(r"\textbf{Model weight for:}", labelpad=15) + g.figure.savefig( + f"{directory}confusionMatrix_ND_{index+1}.pdf", + bbox_inches='tight' + ) + plt.close() + + # ------------------------------------------------------------------------- + def plot_model_weights(self, model_weights, plot_name): + """ + Visualizes the model weights resulting from BMS via the observation + data. + + Parameters + ---------- + model_weights : array + Model weights. + plot_name : str + Plot name. + + Returns + ------- + None. + + """ + font_size = 40 + # mkdir for plots + directory = 'Outputs_Comparison/' + os.makedirs(directory, exist_ok=True) + + # Create figure + fig, ax = plt.subplots() + + # Filter data using np.isnan + mask = ~np.isnan(model_weights.T) + filtered_data = [d[m] for d, m in zip(model_weights, mask.T)] + + # Create the boxplot + bp = ax.boxplot(filtered_data, patch_artist=True, showfliers=False) + + # change outline color, fill color and linewidth of the boxes + for box in bp['boxes']: + # change outline color + box.set(color='#7570b3', linewidth=4) + # change fill color + box.set(facecolor='#1b9e77') + + # change color and linewidth of the whiskers + for whisker in bp['whiskers']: + whisker.set(color='#7570b3', linewidth=2) + + # change color and linewidth of the caps + for cap in bp['caps']: + cap.set(color='#7570b3', linewidth=2) + + # change color and linewidth of the medians + for median in bp['medians']: + median.set(color='#b2df8a', linewidth=2) + + # change the style of fliers and their fill + # for flier in bp['fliers']: + # flier.set(marker='o', color='#e7298a', alpha=0.75) + + # Custom x-axis labels + model_names = [model.replace('_', '$-$') for model in self.model_names] + ax.set_xticklabels(model_names) + + ax.set_ylabel('Weight', fontsize=font_size) + + # Title + plt.title('Posterior Model Weights') + + # Set y lim + ax.set_ylim((-0.05, 1.05)) + + # Set size of the ticks + for t in ax.get_xticklabels(): + t.set_fontsize(font_size) + for t in ax.get_yticklabels(): + t.set_fontsize(font_size) + + # Save the figure + fig.savefig( + f'./{directory}{plot_name}.pdf', bbox_inches='tight' + ) + + plt.close() + + # ------------------------------------------------------------------------- + def plot_bayes_factor(self, BME_Dict, plot_name=''): + """ + Plots the Bayes factor distibutions in a :math:`N_m \\times N_m` + matrix, where :math:`N_m` is the number of the models. + + Parameters + ---------- + BME_Dict : dict + A dictionary containing the BME values of the models. + plot_name : str, optional + Plot name. The default is ''. + + Returns + ------- + None. + + """ + + font_size = 40 + + # mkdir for plots + directory = 'Outputs_Comparison/' + os.makedirs(directory, exist_ok=True) + + Colors = ["blue", "green", "gray", "brown"] + + model_names = list(BME_Dict.keys()) + nModels = len(model_names) + + # Plots + fig, axes = plt.subplots( + nrows=nModels, ncols=nModels, sharex=True, sharey=True + ) + + for i, key_i in enumerate(model_names): + + for j, key_j in enumerate(model_names): + ax = axes[i, j] + # Set size of the ticks + for t in ax.get_xticklabels(): + t.set_fontsize(font_size) + for t in ax.get_yticklabels(): + t.set_fontsize(font_size) + + if j != i: + + # Null hypothesis: key_j is the better model + BayesFactor = np.log10( + np.divide(BME_Dict[key_i], BME_Dict[key_j]) + ) + + # sns.kdeplot(BayesFactor, ax=ax, color=Colors[i], shade=True) + # sns.histplot(BayesFactor, ax=ax, stat="probability", + # kde=True, element='step', + # color=Colors[j]) + + # taken from seaborn's source code (utils.py and + # distributions.py) + def seaborn_kde_support(data, bw, gridsize, cut, clip): + if clip is None: + clip = (-np.inf, np.inf) + support_min = max(data.min() - bw * cut, clip[0]) + support_max = min(data.max() + bw * cut, clip[1]) + return np.linspace(support_min, support_max, gridsize) + + kde_estim = stats.gaussian_kde( + BayesFactor, bw_method='scott' + ) + + # manual linearization of data + # linearized = np.linspace( + # quotient.min(), quotient.max(), num=500) + + # or better: mimic seaborn's internal stuff + bw = kde_estim.scotts_factor() * np.std(BayesFactor) + linearized = seaborn_kde_support( + BayesFactor, bw, 100, 3, None) + + # computes values of the estimated function on the + # estimated linearized inputs + Z = kde_estim.evaluate(linearized) + + # https://stackoverflow.com/questions/29661574/normalize- + # numpy-array-columns-in-python + def normalize(x): + return (x - x.min(0)) / x.ptp(0) + + # normalize so it is between 0;1 + Z2 = normalize(Z) + ax.plot(linearized, Z2, "-", color=Colors[i], linewidth=4) + ax.fill_between( + linearized, 0, Z2, color=Colors[i], alpha=0.25 + ) + + # Draw BF significant levels according to Jeffreys 1961 + # Strong evidence for both models + ax.axvline( + x=np.log10(3), ymin=0, linewidth=4, color='dimgrey' + ) + # Strong evidence for one model + ax.axvline( + x=np.log10(10), ymin=0, linewidth=4, color='orange' + ) + # Decisive evidence for one model + ax.axvline( + x=np.log10(100), ymin=0, linewidth=4, color='r' + ) + + # legend + BF_label = key_i.replace('_', '$-$') + \ + '/' + key_j.replace('_', '$-$') + legend_elements = [ + patches.Patch(facecolor=Colors[i], edgecolor=Colors[i], + label=f'BF({BF_label})') + ] + ax.legend( + loc='upper left', handles=legend_elements, + fontsize=font_size-(nModels+1)*5 + ) + + elif j == i: + # build a rectangle in axes coords + left, width = 0, 1 + bottom, height = 0, 1 + + # axes coordinates are 0,0 is bottom left and 1,1 is upper + # right + p = patches.Rectangle( + (left, bottom), width, height, color='white', + fill=True, transform=ax.transAxes, clip_on=False + ) + ax.grid(False) + ax.add_patch(p) + # ax.text(0.5*(left+right), 0.5*(bottom+top), key_i, + fsize = font_size+20 if nModels < 4 else font_size + ax.text(0.5, 0.5, key_i.replace('_', '$-$'), + horizontalalignment='center', + verticalalignment='center', + fontsize=fsize, color=Colors[i], + transform=ax.transAxes) + + # Defining custom 'ylim' values. + custom_ylim = (0, 1.05) + + # Setting the values for all axes. + plt.setp(axes, ylim=custom_ylim) + + # set labels + for i in range(nModels): + axes[-1, i].set_xlabel('log$_{10}$(BF)', fontsize=font_size) + axes[i, 0].set_ylabel('Probability', fontsize=font_size) + + # Adjust subplots + plt.subplots_adjust(wspace=0.2, hspace=0.1) + + plt.savefig( + f'./{directory}Bayes_Factor{plot_name}.pdf', bbox_inches='tight' + ) + + plt.close() diff --git a/examples/analytical-function/bayesvalidrox/bayes_inference/discrepancy.py b/examples/analytical-function/bayesvalidrox/bayes_inference/discrepancy.py new file mode 100644 index 000000000..b3c235ebe --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/bayes_inference/discrepancy.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import scipy.stats as stats +from bayesvalidrox.surrogate_models.exp_designs import ExpDesigns + + +class Discrepancy: + """ + Discrepancy class for Bayesian inference method. + We define the reference or reality to be equal to what we can model and a + descripancy term \\( \\epsilon \\). We consider the followin format: + + $$\\textbf{y}_{\\text{reality}} = \\mathcal{M}(\\theta) + \\epsilon,$$ + + where \\( \\epsilon \\in R^{N_{out}} \\) represents the the effects of + measurement error and model inaccuracy. For simplicity, it can be defined + as an additive Gaussian disrepancy with zeromean and given covariance + matrix \\( \\Sigma \\): + + $$\\epsilon \\sim \\mathcal{N}(\\epsilon|0, \\Sigma). $$ + + In the context of model inversion or calibration, an observation point + \\( \\textbf{y}_i \\in \\mathcal{y} \\) is a realization of a Gaussian + distribution with mean value of \\(\\mathcal{M}(\\theta) \\) and covariance + matrix of \\( \\Sigma \\). + + $$ p(\\textbf{y}|\\theta) = \\mathcal{N}(\\textbf{y}|\\mathcal{M} + (\\theta))$$ + + The following options are available: + + * Option A: With known redidual covariance matrix \\(\\Sigma\\) for + independent measurements. + + * Option B: With unknown redidual covariance matrix \\(\\Sigma\\), + paramethrized as \\(\\Sigma(\\theta_{\\epsilon})=\\sigma^2 \\textbf{I}_ + {N_{out}}\\) with unknown residual variances \\(\\sigma^2\\). + This term will be jointly infered with the uncertain input parameters. For + the inversion, you need to define a prior marginal via `Input` class. Note + that \\(\\sigma^2\\) is only a single scalar multiplier for the diagonal + entries of the covariance matrix \\(\\Sigma\\). + + Attributes + ---------- + InputDisc : obj + Input object. When the \\(\\sigma^2\\) is expected to be inferred + jointly with the parameters (`Option B`).If multiple output groups are + defined by `Model.Output.names`, each model output needs to have. + a prior marginal using the `Input` class. The default is `''`. + disc_type : str + Type of the noise definition. `'Gaussian'` is only supported so far. + parameters : dict or pandas.DataFrame + Known residual variance \\(\\sigma^2\\), i.e. diagonal entry of the + covariance matrix of the multivariate normal likelihood in case of + `Option A`. + + """ + + def __init__(self, InputDisc='', disc_type='Gaussian', parameters=None): + # Set the values + self.InputDisc = InputDisc + self.disc_type = disc_type + self.parameters = parameters + + # Other inits + self.ExpDesign = None + self.n_samples = None + self.sigma2_prior = None + self.name = None + self.opt_sigma = None # This will be set in the inference class and used in mcmc + # ------------------------------------------------------------------------- + def get_sample(self, n_samples): + """ + Generate samples for the \\(\\sigma^2\\), i.e. the diagonal entries of + the variance-covariance matrix in the multivariate normal distribution. + + Parameters + ---------- + n_samples : int + Number of samples (parameter sets). + + Returns + ------- + sigma2_prior: array of shape (n_samples, n_params) + \\(\\sigma^2\\) samples. + + """ + self.n_samples = n_samples # TODO: not used again in here - needed from the outside? + + if self.InputDisc == '': + raise AttributeError('Cannot create new samples, please provide input distributions') + + # Create and store BoundTuples + self.ExpDesign = ExpDesigns(self.InputDisc) + self.ExpDesign.sampling_method = 'random' + + # TODO: why does it call 'generate_ED' instead of 'generate_samples? + # ExpDesign.bound_tuples, onp_sigma, prior_space needed from the outside + # Discrepancy opt_sigma, InputDisc needed from the outside + # TODO: opt_sigma not defined here, but called from the outside?? + self.ExpDesign.generate_ED( + n_samples, max_pce_deg=1 + ) + # TODO: need to recheck the following line + # This used to simply be the return from the call above + self.sigma2_prior = self.ExpDesign.X + + # Naive approach: Fit a gaussian kernel to the provided data + self.ExpDesign.JDist = stats.gaussian_kde(self.ExpDesign.raw_data) + + # Save the names of sigmas + if len(self.InputDisc.Marginals) != 0: + self.name = [] + for Marginalidx in range(len(self.InputDisc.Marginals)): + self.name.append(self.InputDisc.Marginals[Marginalidx].name) + + return self.sigma2_prior diff --git a/examples/analytical-function/bayesvalidrox/bayes_inference/mcmc.py b/examples/analytical-function/bayesvalidrox/bayes_inference/mcmc.py new file mode 100644 index 000000000..d78d15b5f --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/bayes_inference/mcmc.py @@ -0,0 +1,909 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import os +import numpy as np +import emcee +import pandas as pd +import matplotlib.pyplot as plt +from matplotlib.backends.backend_pdf import PdfPages +import multiprocessing +import scipy.stats as st +from scipy.linalg import cholesky as chol +import warnings +import shutil +os.environ["OMP_NUM_THREADS"] = "1" + + +class MCMC: + """ + A class for bayesian inference via a Markov-Chain Monte-Carlo (MCMC) + Sampler to approximate the posterior distribution of the Bayes theorem: + $$p(\\theta|\\mathcal{y}) = \\frac{p(\\mathcal{y}|\\theta) p(\\theta)} + {p(\\mathcal{y})}.$$ + + This class make inference with emcee package [1] using an Affine Invariant + Ensemble sampler (AIES) [2]. + + [1] Foreman-Mackey, D., Hogg, D.W., Lang, D. and Goodman, J., 2013.emcee: + the MCMC hammer. Publications of the Astronomical Society of the + Pacific, 125(925), p.306. https://emcee.readthedocs.io/en/stable/ + + [2] Goodman, J. and Weare, J., 2010. Ensemble samplers with affine + invariance. Communications in applied mathematics and computational + science, 5(1), pp.65-80. + + + Attributes + ---------- + BayesOpts : obj + Bayes object. + """ + + def __init__(self, BayesOpts): + + self.BayesOpts = BayesOpts + + def run_sampler(self, observation, total_sigma2): + + BayesObj = self.BayesOpts + MetaModel = BayesObj.engine.MetaModel + Model = BayesObj.engine.Model + Discrepancy = self.BayesOpts.Discrepancy + n_cpus = Model.n_cpus + priorDist = BayesObj.engine.ExpDesign.JDist + ndim = MetaModel.n_params + self.counter = 0 + output_dir = f'Outputs_Bayes_{Model.name}_{self.BayesOpts.name}' + if not os.path.exists(output_dir): + os.makedirs(output_dir) + + self.observation = observation + self.total_sigma2 = total_sigma2 + + # Unpack mcmc parameters given to BayesObj.mcmc_params + self.initsamples = None + self.nwalkers = 100 + self.nburn = 200 + self.nsteps = 100000 + self.moves = None + self.mp = False + self.verbose = False + + # Extract initial samples + if 'init_samples' in BayesObj.mcmc_params: + self.initsamples = BayesObj.mcmc_params['init_samples'] + if isinstance(self.initsamples, pd.DataFrame): + self.initsamples = self.initsamples.values + + # Extract number of steps per walker + if 'n_steps' in BayesObj.mcmc_params: + self.nsteps = int(BayesObj.mcmc_params['n_steps']) + # Extract number of walkers (chains) + if 'n_walkers' in BayesObj.mcmc_params: + self.nwalkers = int(BayesObj.mcmc_params['n_walkers']) + # Extract moves + if 'moves' in BayesObj.mcmc_params: + self.moves = BayesObj.mcmc_params['moves'] + # Extract multiprocessing + if 'multiprocessing' in BayesObj.mcmc_params: + self.mp = BayesObj.mcmc_params['multiprocessing'] + # Extract verbose + if 'verbose' in BayesObj.mcmc_params: + self.verbose = BayesObj.mcmc_params['verbose'] + + # Set initial samples + np.random.seed(0) + if self.initsamples is None: + try: + initsamples = priorDist.sample(self.nwalkers).T + except: + # when aPCE selected - gaussian kernel distribution + inputSamples = self.BayesOpts.engine.ExpDesign.raw_data.T + random_indices = np.random.choice( + len(inputSamples), size=self.nwalkers, replace=False + ) + initsamples = inputSamples[random_indices] + + else: + if self.initsamples.ndim == 1: + # When MAL is given. + theta = self.initsamples + initsamples = [theta + 1e-1*np.multiply( + np.random.randn(ndim), theta) for i in + range(self.nwalkers)] + else: + # Pick samples based on a uniform dist between min and max of + # each dim + initsamples = np.zeros((self.nwalkers, ndim)) + bound_tuples = [] + for idx_dim in range(ndim): + lower = np.min(self.initsamples[:, idx_dim]) + upper = np.max(self.initsamples[:, idx_dim]) + bound_tuples.append((lower, upper)) + dist = st.uniform(loc=lower, scale=upper-lower) + initsamples[:, idx_dim] = dist.rvs(size=self.nwalkers) + + # Update lower and upper + MetaModel.ExpDesign.bound_tuples = bound_tuples + + # Check if sigma^2 needs to be inferred + if Discrepancy.opt_sigma != 'B': + sigma2_samples = Discrepancy.get_sample(self.nwalkers) + + # Update initsamples + initsamples = np.hstack((initsamples, sigma2_samples)) + + # Update ndim + ndim = initsamples.shape[1] + + # Discrepancy bound + disc_bound_tuple = Discrepancy.ExpDesign.bound_tuples + + # Update bound_tuples + BayesObj.engine.ExpDesign.bound_tuples += disc_bound_tuple + + print("\n>>>> Bayesian inference with MCMC for " + f"{self.BayesOpts.name} started. <<<<<<") + + # Set up the backend + filename = f"{output_dir}/emcee_sampler.h5" + backend = emcee.backends.HDFBackend(filename) + # Clear the backend in case the file already exists + backend.reset(self.nwalkers, ndim) + + # Define emcee sampler + # Here we'll set up the computation. emcee combines multiple "walkers", + # each of which is its own MCMC chain. The number of trace results will + # be nwalkers * nsteps. + if self.mp: + # Run in parallel + if n_cpus is None: + n_cpus = multiprocessing.cpu_count() + + with multiprocessing.Pool(n_cpus) as pool: + sampler = emcee.EnsembleSampler( + self.nwalkers, ndim, self.log_posterior, moves=self.moves, + pool=pool, backend=backend + ) + + # Check if a burn-in phase is needed! + if self.initsamples is None: + # Burn-in + print("\n Burn-in period is starting:") + pos = sampler.run_mcmc( + initsamples, self.nburn, progress=True + ) + + # Reset sampler + sampler.reset() + pos = pos.coords + else: + pos = initsamples + + # Production run + print("\n Production run is starting:") + pos, prob, state = sampler.run_mcmc( + pos, self.nsteps, progress=True + ) + + else: + # Run in series and monitor the convergence + sampler = emcee.EnsembleSampler( + self.nwalkers, ndim, self.log_posterior, moves=self.moves, + backend=backend, vectorize=True + ) + + # Check if a burn-in phase is needed! + if self.initsamples is None: + # Burn-in + print("\n Burn-in period is starting:") + pos = sampler.run_mcmc( + initsamples, self.nburn, progress=True + ) + + # Reset sampler + sampler.reset() + pos = pos.coords + else: + pos = initsamples + + # Production run + print("\n Production run is starting:") + + # Track how the average autocorrelation time estimate changes + autocorrIdx = 0 + autocorr = np.empty(self.nsteps) + tauold = np.inf + autocorreverynsteps = 50 + + # sample step by step using the generator sampler.sample + for sample in sampler.sample(pos, + iterations=self.nsteps, + tune=True, + progress=True): + + # only check convergence every autocorreverynsteps steps + if sampler.iteration % autocorreverynsteps: + continue + + # Train model discrepancy/error + if hasattr(BayesObj, 'errorModel') and BayesObj.errorModel \ + and not sampler.iteration % 3 * autocorreverynsteps: + try: + self.error_MetaModel = self.train_error_model(sampler) + except: + pass + + # Print the current mean acceptance fraction + if self.verbose: + print("\nStep: {}".format(sampler.iteration)) + acc_fr = np.mean(sampler.acceptance_fraction) + print(f"Mean acceptance fraction: {acc_fr:.3f}") + + # compute the autocorrelation time so far + # using tol=0 means that we'll always get an estimate even if + # it isn't trustworthy + tau = sampler.get_autocorr_time(tol=0) + # average over walkers + autocorr[autocorrIdx] = np.nanmean(tau) + autocorrIdx += 1 + + # output current autocorrelation estimate + if self.verbose: + print(f"Mean autocorr. time estimate: {np.nanmean(tau):.3f}") + list_gr = np.round(self.gelman_rubin(sampler.chain), 3) + print("Gelman-Rubin Test*: ", list_gr) + + # check convergence + converged = np.all(tau*autocorreverynsteps < sampler.iteration) + converged &= np.all(np.abs(tauold - tau) / tau < 0.01) + converged &= np.all(self.gelman_rubin(sampler.chain) < 1.1) + + if converged: + break + tauold = tau + + # Posterior diagnostics + try: + tau = sampler.get_autocorr_time(tol=0) + except emcee.autocorr.AutocorrError: + tau = 5 + + if all(np.isnan(tau)): + tau = 5 + + burnin = int(2*np.nanmax(tau)) + thin = int(0.5*np.nanmin(tau)) if int(0.5*np.nanmin(tau)) != 0 else 1 + finalsamples = sampler.get_chain(discard=burnin, flat=True, thin=thin) + acc_fr = np.nanmean(sampler.acceptance_fraction) + list_gr = np.round(self.gelman_rubin(sampler.chain[:, burnin:]), 3) + + # Print summary + print('\n') + print('-'*15 + 'Posterior diagnostics' + '-'*15) + print(f"Mean auto-correlation time: {np.nanmean(tau):.3f}") + print(f"Thin: {thin}") + print(f"Burn-in: {burnin}") + print(f"Flat chain shape: {finalsamples.shape}") + print(f"Mean acceptance fraction*: {acc_fr:.3f}") + print("Gelman-Rubin Test**: ", list_gr) + + print("\n* This value must lay between 0.234 and 0.5.") + print("** These values must be smaller than 1.1.") + print('-'*50) + + print(f"\n>>>> Bayesian inference with MCMC for {self.BayesOpts.name} " + "successfully completed. <<<<<<\n") + + # Extract parameter names and their prior ranges + par_names = self.BayesOpts.engine.ExpDesign.par_names + + if Discrepancy.opt_sigma != 'B': + for i in range(len(Discrepancy.InputDisc.Marginals)): + par_names.append(Discrepancy.InputDisc.Marginals[i].name) + + params_range = self.BayesOpts.engine.ExpDesign.bound_tuples + + # Plot traces + if self.verbose and self.nsteps < 10000: + pdf = PdfPages(output_dir+'/traceplots.pdf') + fig = plt.figure() + for parIdx in range(ndim): + # Set up the axes with gridspec + fig = plt.figure() + grid = plt.GridSpec(4, 4, hspace=0.2, wspace=0.2) + main_ax = fig.add_subplot(grid[:-1, :3]) + y_hist = fig.add_subplot(grid[:-1, -1], xticklabels=[], + sharey=main_ax) + + for i in range(self.nwalkers): + samples = sampler.chain[i, :, parIdx] + main_ax.plot(samples, '-') + + # histogram on the attached axes + y_hist.hist(samples[burnin:], 40, histtype='stepfilled', + orientation='horizontal', color='gray') + + main_ax.set_ylim(params_range[parIdx]) + main_ax.set_title('traceplot for ' + par_names[parIdx]) + main_ax.set_xlabel('step number') + + # save the current figure + pdf.savefig(fig, bbox_inches='tight') + + # Destroy the current plot + plt.clf() + + pdf.close() + + # plot development of autocorrelation estimate + if not self.mp: + fig1 = plt.figure() + steps = autocorreverynsteps*np.arange(1, autocorrIdx+1) + taus = autocorr[:autocorrIdx] + plt.plot(steps, steps / autocorreverynsteps, "--k") + plt.plot(steps, taus) + plt.xlim(0, steps.max()) + plt.ylim(0, np.nanmax(taus)+0.1*(np.nanmax(taus)-np.nanmin(taus))) + plt.xlabel("number of steps") + plt.ylabel(r"mean $\hat{\tau}$") + fig1.savefig(f"{output_dir}/autocorrelation_time.pdf", + bbox_inches='tight') + + # logml_dict = self.marginal_llk_emcee(sampler, self.nburn, logp=None, + # maxiter=5000) + # print('\nThe Bridge Sampling Estimation is " + # f"{logml_dict['logml']:.5f}.') + + # # Posterior-based expectation of posterior probablity + # postExpPostLikelihoods = np.mean(sampler.get_log_prob(flat=True) + # [self.nburn*self.nwalkers:]) + + # # Posterior-based expectation of prior densities + # postExpPrior = np.mean(self.log_prior(emcee_trace.T)) + + # # Posterior-based expectation of likelihoods + # postExpLikelihoods_emcee = postExpPostLikelihoods - postExpPrior + + # # Calculate Kullback-Leibler Divergence + # KLD_emcee = postExpLikelihoods_emcee - logml_dict['logml'] + # print("Kullback-Leibler divergence: %.5f"%KLD_emcee) + + # # Information Entropy based on Entropy paper Eq. 38 + # infEntropy_emcee = logml_dict['logml'] - postExpPrior - + # postExpLikelihoods_emcee + # print("Information Entropy: %.5f" %infEntropy_emcee) + + Posterior_df = pd.DataFrame(finalsamples, columns=par_names) + + return Posterior_df + + # ------------------------------------------------------------------------- + def log_prior(self, theta): + """ + Calculates the log prior likelihood \\( p(\\theta)\\) for the given + parameter set(s) \\( \\theta \\). + + Parameters + ---------- + theta : array of shape (n_samples, n_params) + Parameter sets, i.e. proposals of MCMC chains. + + Returns + ------- + logprior: float or array of shape n_samples + Log prior likelihood. If theta has only one row, a single value is + returned otherwise an array. + + """ + + MetaModel = self.BayesOpts.MetaModel + Discrepancy = self.BayesOpts.Discrepancy + + # Find the number of sigma2 parameters + if Discrepancy.opt_sigma != 'B': + disc_bound_tuples = Discrepancy.ExpDesign.bound_tuples + disc_marginals = Discrepancy.ExpDesign.InputObj.Marginals + disc_prior_space = Discrepancy.ExpDesign.prior_space + n_sigma2 = len(disc_bound_tuples) + else: + n_sigma2 = -len(theta) + prior_dist = self.BayesOpts.engine.ExpDesign.prior_space + params_range = self.BayesOpts.engine.ExpDesign.bound_tuples + theta = theta if theta.ndim != 1 else theta.reshape((1, -1)) + nsamples = theta.shape[0] + logprior = -np.inf*np.ones(nsamples) + + for i in range(nsamples): + # Check if the sample is within the parameters' range + if self._check_ranges(theta[i], params_range): + # Check if all dists are uniform, if yes priors are equal. + if all(MetaModel.input_obj.Marginals[i].dist_type == 'uniform' + for i in range(MetaModel.n_params)): + logprior[i] = 0.0 + else: + logprior[i] = np.log( + prior_dist.pdf(theta[i, :-n_sigma2].T) + ) + + # Check if bias term needs to be inferred + if Discrepancy.opt_sigma != 'B': + if self._check_ranges(theta[i, -n_sigma2:], + disc_bound_tuples): + if all('unif' in disc_marginals[i].dist_type for i in + range(Discrepancy.ExpDesign.ndim)): + logprior[i] = 0.0 + else: + logprior[i] += np.log( + disc_prior_space.pdf(theta[i, -n_sigma2:]) + ) + + if nsamples == 1: + return logprior[0] + else: + return logprior + + # ------------------------------------------------------------------------- + def log_likelihood(self, theta): + """ + Computes likelihood \\( p(\\mathcal{Y}|\\theta)\\) of the performance + of the (meta-)model in reproducing the observation data. + + Parameters + ---------- + theta : array of shape (n_samples, n_params) + Parameter set, i.e. proposals of the MCMC chains. + + Returns + ------- + log_like : array of shape (n_samples) + Log likelihood. + + """ + + BayesOpts = self.BayesOpts + MetaModel = BayesOpts.MetaModel + Discrepancy = self.BayesOpts.Discrepancy + + # Find the number of sigma2 parameters + if Discrepancy.opt_sigma != 'B': + disc_bound_tuples = Discrepancy.ExpDesign.bound_tuples + n_sigma2 = len(disc_bound_tuples) + else: + n_sigma2 = -len(theta) + # Check if bias term needs to be inferred + if Discrepancy.opt_sigma != 'B': + sigma2 = theta[:, -n_sigma2:] + theta = theta[:, :-n_sigma2] + else: + sigma2 = None + theta = theta if theta.ndim != 1 else theta.reshape((1, -1)) + + # Evaluate Model/MetaModel at theta + mean_pred, BayesOpts._std_pce_prior_pred = self.eval_model(theta) + + # Surrogate model's error using RMSE of test data + surrError = MetaModel.rmse if hasattr(MetaModel, 'rmse') else None + + # Likelihood + log_like = BayesOpts.normpdf( + mean_pred, self.observation, self.total_sigma2, sigma2, + std=surrError + ) + return log_like + + # ------------------------------------------------------------------------- + def log_posterior(self, theta): + """ + Computes the posterior likelihood \\(p(\\theta| \\mathcal{Y})\\) for + the given parameterset. + + Parameters + ---------- + theta : array of shape (n_samples, n_params) + Parameter set, i.e. proposals of the MCMC chains. + + Returns + ------- + log_like : array of shape (n_samples) + Log posterior likelihood. + + """ + + nsamples = 1 if theta.ndim == 1 else theta.shape[0] + + if nsamples == 1: + if self.log_prior(theta) == -np.inf: + return -np.inf + else: + # Compute log prior + log_prior = self.log_prior(theta) + # Compute log Likelihood + log_likelihood = self.log_likelihood(theta) + + return log_prior + log_likelihood + else: + # Compute log prior + log_prior = self.log_prior(theta) + + # Initialize log_likelihood + log_likelihood = -np.inf*np.ones(nsamples) + + # find the indices for -inf sets + non_inf_idx = np.where(log_prior != -np.inf)[0] + + # Compute loLikelihoods + if non_inf_idx.size != 0: + log_likelihood[non_inf_idx] = self.log_likelihood( + theta[non_inf_idx] + ) + + return log_prior + log_likelihood + + # ------------------------------------------------------------------------- + def eval_model(self, theta): + """ + Evaluates the (meta-) model at the given theta. + + Parameters + ---------- + theta : array of shape (n_samples, n_params) + Parameter set, i.e. proposals of the MCMC chains. + + Returns + ------- + mean_pred : dict + Mean model prediction. + std_pred : dict + Std of model prediction. + + """ + + BayesObj = self.BayesOpts + MetaModel = BayesObj.MetaModel + Model = BayesObj.engine.Model + + if BayesObj.emulator: + # Evaluate the MetaModel + mean_pred, std_pred = MetaModel.eval_metamodel(samples=theta) + else: + # Evaluate the origModel + mean_pred, std_pred = dict(), dict() + + model_outs, _ = Model.run_model_parallel( + theta, prevRun_No=self.counter, + key_str='_MCMC', mp=False, verbose=False) + + # Save outputs in respective dicts + for varIdx, var in enumerate(Model.Output.names): + mean_pred[var] = model_outs[var] + std_pred[var] = np.zeros((mean_pred[var].shape)) + + # Remove the folder + if Model.link_type.lower() != 'function': + shutil.rmtree(f"{Model.name}_MCMC_{self.counter+1}") + + # Add one to the counter + self.counter += 1 + + if hasattr(self, 'error_MetaModel') and BayesObj.error_model: + meanPred, stdPred = self.error_MetaModel.eval_model_error( + BayesObj.BiasInputs, mean_pred + ) + + return mean_pred, std_pred + + # ------------------------------------------------------------------------- + def train_error_model(self, sampler): + """ + Trains an error model using a Gaussian Process Regression. + + Parameters + ---------- + sampler : obj + emcee sampler. + + Returns + ------- + error_MetaModel : obj + A error model. + + """ + BayesObj = self.BayesOpts + MetaModel = BayesObj.MetaModel + + # Prepare the poster samples + try: + tau = sampler.get_autocorr_time(tol=0) + except emcee.autocorr.AutocorrError: + tau = 5 + + if all(np.isnan(tau)): + tau = 5 + + burnin = int(2*np.nanmax(tau)) + thin = int(0.5*np.nanmin(tau)) if int(0.5*np.nanmin(tau)) != 0 else 1 + finalsamples = sampler.get_chain(discard=burnin, flat=True, thin=thin) + posterior = finalsamples[:, :MetaModel.n_params] + + # Select posterior mean as MAP + map_theta = posterior.mean(axis=0).reshape((1, MetaModel.n_params)) + # MAP_theta = st.mode(Posterior_df,axis=0)[0] + + # Evaluate the (meta-)model at the MAP + y_map, y_std_map = MetaModel.eval_metamodel(samples=map_theta) + + # Train a GPR meta-model using MAP + error_MetaModel = MetaModel.create_model_error( + BayesObj.BiasInputs, y_map, name='Calib') + + return error_MetaModel + + # ------------------------------------------------------------------------- + def gelman_rubin(self, chain, return_var=False): + """ + The potential scale reduction factor (PSRF) defined by the variance + within one chain, W, with the variance between chains B. + Both variances are combined in a weighted sum to obtain an estimate of + the variance of a parameter \\( \\theta \\).The square root of the + ratio of this estimates variance to the within chain variance is called + the potential scale reduction. + For a well converged chain it should approach 1. Values greater than + 1.1 typically indicate that the chains have not yet fully converged. + + Source: http://joergdietrich.github.io/emcee-convergence.html + + https://github.com/jwalton3141/jwalton3141.github.io/blob/master/assets/posts/ESS/rwmh.py + + Parameters + ---------- + chain : array (n_walkers, n_steps, n_params) + The emcee ensamples. + + Returns + ------- + R_hat : float + The Gelman-Robin values. + + """ + m_chains, n_iters = chain.shape[:2] + + # Calculate between-chain variance + θb = np.mean(chain, axis=1) + θbb = np.mean(θb, axis=0) + B_over_n = ((θbb - θb)**2).sum(axis=0) + B_over_n /= (m_chains - 1) + + # Calculate within-chain variances + ssq = np.var(chain, axis=1, ddof=1) + W = np.mean(ssq, axis=0) + + # (over) estimate of variance + var_θ = W * (n_iters - 1) / n_iters + B_over_n + + if return_var: + return var_θ + else: + # The square root of the ratio of this estimates variance to the + # within chain variance + R_hat = np.sqrt(var_θ / W) + return R_hat + + # ------------------------------------------------------------------------- + def marginal_llk_emcee(self, sampler, nburn=None, logp=None, maxiter=1000): + """ + The Bridge Sampling Estimator of the Marginal Likelihood based on + https://gist.github.com/junpenglao/4d2669d69ddfe1d788318264cdcf0583 + + Parameters + ---------- + sampler : TYPE + MultiTrace, result of MCMC run. + nburn : int, optional + Number of burn-in step. The default is None. + logp : TYPE, optional + Model Log-probability function. The default is None. + maxiter : int, optional + Maximum number of iterations. The default is 1000. + + Returns + ------- + marg_llk : dict + Estimated Marginal log-Likelihood. + + """ + r0, tol1, tol2 = 0.5, 1e-10, 1e-4 + + if logp is None: + logp = sampler.log_prob_fn + + # Split the samples into two parts + # Use the first 50% for fiting the proposal distribution + # and the second 50% in the iterative scheme. + if nburn is None: + mtrace = sampler.chain + else: + mtrace = sampler.chain[:, nburn:, :] + + nchain, len_trace, nrofVars = mtrace.shape + + N1_ = len_trace // 2 + N1 = N1_*nchain + N2 = len_trace*nchain - N1 + + samples_4_fit = np.zeros((nrofVars, N1)) + samples_4_iter = np.zeros((nrofVars, N2)) + effective_n = np.zeros((nrofVars)) + + # matrix with already transformed samples + for var in range(nrofVars): + + # for fitting the proposal + x = mtrace[:, :N1_, var] + + samples_4_fit[var, :] = x.flatten() + # for the iterative scheme + x2 = mtrace[:, N1_:, var] + samples_4_iter[var, :] = x2.flatten() + + # effective sample size of samples_4_iter, scalar + effective_n[var] = self._my_ESS(x2) + + # median effective sample size (scalar) + neff = np.median(effective_n) + + # get mean & covariance matrix and generate samples from proposal + m = np.mean(samples_4_fit, axis=1) + V = np.cov(samples_4_fit) + L = chol(V, lower=True) + + # Draw N2 samples from the proposal distribution + gen_samples = m[:, None] + np.dot( + L, st.norm.rvs(0, 1, size=samples_4_iter.shape) + ) + + # Evaluate proposal distribution for posterior & generated samples + q12 = st.multivariate_normal.logpdf(samples_4_iter.T, m, V) + q22 = st.multivariate_normal.logpdf(gen_samples.T, m, V) + + # Evaluate unnormalized posterior for posterior & generated samples + q11 = logp(samples_4_iter.T) + q21 = logp(gen_samples.T) + + # Run iterative scheme: + tmp = self._iterative_scheme( + N1, N2, q11, q12, q21, q22, r0, neff, tol1, maxiter, 'r' + ) + if ~np.isfinite(tmp['logml']): + warnings.warn( + "Logml could not be estimated within maxiter, rerunning with " + "adjusted starting value. Estimate might be more variable than" + " usual.") + # use geometric mean as starting value + r0_2 = np.sqrt(tmp['r_vals'][-2]*tmp['r_vals'][-1]) + tmp = self._iterative_scheme( + q11, q12, q21, q22, r0_2, neff, tol2, maxiter, 'logml' + ) + + marg_llk = dict( + logml=tmp['logml'], niter=tmp['niter'], method="normal", + q11=q11, q12=q12, q21=q21, q22=q22 + ) + return marg_llk + + # ------------------------------------------------------------------------- + def _iterative_scheme(self, N1, N2, q11, q12, q21, q22, r0, neff, tol, + maxiter, criterion): + """ + Iterative scheme as proposed in Meng and Wong (1996) to estimate the + marginal likelihood + + """ + l1 = q11 - q12 + l2 = q21 - q22 + # To increase numerical stability, + # subtracting the median of l1 from l1 & l2 later + lstar = np.median(l1) + s1 = neff/(neff + N2) + s2 = N2/(neff + N2) + r = r0 + r_vals = [r] + logml = np.log(r) + lstar + criterion_val = 1 + tol + + i = 0 + while (i <= maxiter) & (criterion_val > tol): + rold = r + logmlold = logml + numi = np.exp(l2 - lstar)/(s1 * np.exp(l2 - lstar) + s2 * r) + deni = 1/(s1 * np.exp(l1 - lstar) + s2 * r) + if np.sum(~np.isfinite(numi))+np.sum(~np.isfinite(deni)) > 0: + warnings.warn( + """Infinite value in iterative scheme, returning NaN. + Try rerunning with more samples.""") + r = (N1/N2) * np.sum(numi)/np.sum(deni) + r_vals.append(r) + logml = np.log(r) + lstar + i += 1 + if criterion == 'r': + criterion_val = np.abs((r - rold)/r) + elif criterion == 'logml': + criterion_val = np.abs((logml - logmlold)/logml) + + if i >= maxiter: + return dict(logml=np.NaN, niter=i, r_vals=np.asarray(r_vals)) + else: + return dict(logml=logml, niter=i) + + # ------------------------------------------------------------------------- + def _my_ESS(self, x): + """ + Compute the effective sample size of estimand of interest. + Vectorised implementation. + https://github.com/jwalton3141/jwalton3141.github.io/blob/master/assets/posts/ESS/rwmh.py + + + Parameters + ---------- + x : array of shape (n_walkers, n_steps) + MCMC Samples. + + Returns + ------- + int + Effective sample size. + + """ + m_chains, n_iters = x.shape + + def variogram(t): + variogram = ((x[:, t:] - x[:, :(n_iters - t)])**2).sum() + variogram /= (m_chains * (n_iters - t)) + return variogram + + post_var = self.gelman_rubin(x, return_var=True) + + t = 1 + rho = np.ones(n_iters) + negative_autocorr = False + + # Iterate until the sum of consecutive estimates of autocorrelation is + # negative + while not negative_autocorr and (t < n_iters): + rho[t] = 1 - variogram(t) / (2 * post_var) + + if not t % 2: + negative_autocorr = sum(rho[t-1:t+1]) < 0 + + t += 1 + + return int(m_chains*n_iters / (1 + 2*rho[1:t].sum())) + + # ------------------------------------------------------------------------- + def _check_ranges(self, theta, ranges): + """ + This function checks if theta lies in the given ranges. + + Parameters + ---------- + theta : array + Proposed parameter set. + ranges : nested list + List of the praremeter ranges. + + Returns + ------- + c : bool + If it lies in the given range, it return True else False. + + """ + c = True + # traverse in the list1 + for i, bounds in enumerate(ranges): + x = theta[i] + # condition check + if x < bounds[0] or x > bounds[1]: + c = False + return c + return c diff --git a/examples/analytical-function/bayesvalidrox/bayesvalidrox.mplstyle b/examples/analytical-function/bayesvalidrox/bayesvalidrox.mplstyle new file mode 100644 index 000000000..1f31c01f2 --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/bayesvalidrox.mplstyle @@ -0,0 +1,16 @@ +figure.titlesize : 30 +axes.titlesize : 30 +axes.labelsize : 30 +axes.linewidth : 3 +axes.grid : True +lines.linewidth : 3 +lines.markersize : 10 +xtick.labelsize : 30 +ytick.labelsize : 30 +legend.fontsize : 30 +font.family : serif +font.serif : Arial +font.size : 30 +text.usetex : True +grid.linestyle : - +figure.figsize : 24, 16 diff --git a/examples/analytical-function/bayesvalidrox/desktop.ini b/examples/analytical-function/bayesvalidrox/desktop.ini new file mode 100644 index 000000000..632de13ae --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/desktop.ini @@ -0,0 +1,2 @@ +[LocalizedFileNames] +exploration.py=@exploration.py,0 diff --git a/examples/analytical-function/bayesvalidrox/post_processing/__init__.py b/examples/analytical-function/bayesvalidrox/post_processing/__init__.py new file mode 100644 index 000000000..81c982542 --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/post_processing/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- + +from .post_processing import PostProcessing + +__all__ = [ + "PostProcessing" + ] diff --git a/examples/analytical-function/bayesvalidrox/post_processing/__pycache__/__init__.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/post_processing/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c8590a242166b2e8d40de7ee2eece71980bd1571 GIT binary patch literal 261 zcmZ8bu};G<5Vf5GRYl8y)IVUz!u<fM7!d7*A|aM6CpWel3nz|z4z!=dFJ)!o7g*rZ ziSnd-r+4q2?!tUN6O76AjZNG?NAVYm#XT1-nT#;fi$<1G3Zr(iR3>{C`Q%Honag2O z1WH8=l_hfRE{@Ajc{W^iJjd?T7%mXC_lO@No^kL<-z79{f(l;9MuPYnYF}$j@DQrL zv27w)yR_-I@aV&Pp;HZ8eX#VVy)!ZF;ol`dbgfH>x7}fw-ZjDW-mb=X>740Oscic5 E3kw-WVE_OC literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/post_processing/__pycache__/__init__.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/post_processing/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e84acd550fed2f7af8a071adf99001f44547bdf6 GIT binary patch literal 323 zcmZ3^%ge<81PRl(r<MTe#~=<2FhLogC4h|S3@HpLj5!Rsj8Tk?3@J?Mj8RM}%)tzr zEH4>>(wdC7_yY2aO9G1WlT(X}GxO4mn1RB6n#{NO3xMMB1*j6Y*yH09b8_P2S2BDC zS@WyN*(xTqIJKxarYJi<BPSy<u{g#hKe;qFHLs*N#yzvdqckZdDX}uOxGXUzGo>iM zA||yWF}ENmwK%3EGdDFQwIDSw1*jNJ5t`*O@$s2?nI-Y@dIgogIBatBQ%ZAE?TR>o rP5^nMSQAKmU}j`w{J_S*sB?iq8yNw`SVccDGjX#uu!CR`J5V(MP1av^ literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/post_processing/__pycache__/__init__.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/post_processing/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..58a0eb24635d0b97a14d13708e616de6a0659976 GIT binary patch literal 326 zcmZ9G&q@O^5XO_;ibbs6e1|=xP{fOf2=(GYS&#)Ofsk&pH8lT7Hl_9IbNB$hg4e#q zUOo8=UUarz)Pea8Gv7DE@X_c1K|H^0g@O9sH@_o;<_a>N00a_PBZFrcBatoeEED-X zDh3}I!~%CmrHgGDTrFc%b`kpJyCUz7J<OT^D|GveajhA9MPUz&JAA%O&uJB9h&0Hh zn^2KVTK|w3Wo6)6J@HmKOB%`B6ePKsmgKs+tsYLtXLO#F7Nj<ODJl0}Q&oE^0mL-4 zQI_i<W72J0O&(eA3dzzr-^jRv%Obcn{r4<oOj*@3HujrtcwwAKT3+VxaU1{+^X%&z DlmueV literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/post_processing/__pycache__/post_processing.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/post_processing/__pycache__/post_processing.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0924d8afac04d4fe82ebe791bc55a8ae48d7c117 GIT binary patch literal 28679 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 literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/post_processing/__pycache__/post_processing.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/post_processing/__pycache__/post_processing.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..797c6f82a4d9b29d81d7edc3a3df54e9cf3983aa GIT binary patch literal 65551 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 literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/post_processing/__pycache__/post_processing.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/post_processing/__pycache__/post_processing.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..312575d7655db85df423489051f494f3dce62692 GIT binary patch literal 28771 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 literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/post_processing/post_processing.py b/examples/analytical-function/bayesvalidrox/post_processing/post_processing.py new file mode 100644 index 000000000..24ca8d9b9 --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/post_processing/post_processing.py @@ -0,0 +1,1491 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import numpy as np +import math +import os +from itertools import combinations, cycle +import pandas as pd +import scipy.stats as stats +from sklearn.linear_model import LinearRegression +from sklearn.metrics import mean_squared_error, r2_score +import matplotlib.pyplot as plt +import matplotlib.ticker as ticker +from matplotlib.offsetbox import AnchoredText +from matplotlib.patches import Patch +# Load the mplstyle +plt.style.use(os.path.join(os.path.split(__file__)[0], + '../', 'bayesvalidrox.mplstyle')) + + +class PostProcessing: + """ + This class provides many helper functions to post-process the trained + meta-model. + + Attributes + ---------- + MetaModel : obj + MetaModel object to do postprocessing on. + name : str + Type of the anaylsis. The default is `'calib'`. If a validation is + expected to be performed change this to `'valid'`. + out_dir : str + Directory to print the results into + """ + + def __init__(self, engine, name='calib', out_dir = '.'): + self.engine = engine + self.MetaModel = engine.MetaModel + self.ExpDesign = engine.ExpDesign + self.ModelObj = engine.Model + self.name = name + self.out_dir = out_dir + + newpath = (f'Outputs_PostProcessing_{self.name}/') + if not os.path.exists(self.out_dir+newpath): + os.makedirs(self.out_dir+newpath) + + # ------------------------------------------------------------------------- + + def plot_moments(self, xlabel='Time [s]', plot_type=None, + use_mc=False, num_mc_samples=1e2): + """ + Plots the moments in a pdf format in the directory + `Outputs_PostProcessing`. + + Parameters + ---------- + xlabel : str, optional + String to be displayed as x-label. The default is `'Time [s]'`. + plot_type : str, optional + Options: bar or line. The default is `None`. + use_mc : bool, optional + Toggles if the moments are calculated from pce coefficients or + are estimated from samples + num_mc_samples : int, optional + The number of samples to use for estimating the moments via MC + + Returns + ------- + pce_means: dict + Mean of the model outputs. + pce_means: dict + Standard deviation of the model outputs. + + """ + + bar_plot = True if plot_type == 'bar' else False + meta_model_type = self.MetaModel.meta_model_type + Model = self.ModelObj + + # Read Monte-Carlo reference + self.mc_reference = Model.read_observation('mc_ref') + + # Set the x values + x_values_orig = self.engine.ExpDesign.x_values + + # Compute the moments with the PCEModel object + # TODO: optimize this call, what is really wanted is if it has polynomial coefficients to use here + if self.engine.MetaModel.meta_model_type.lower() == 'gpe' or use_mc == True: + self.pce_means, self.pce_stds = self.compute_mc_moments(num_mc_samples) + else: + self.pce_means, self.pce_stds = self.compute_pce_moments() + + # Get the variables + out_names = Model.Output.names + + # Open a pdf for the plots + newpath = (f'Outputs_PostProcessing_{self.name}/') + if not os.path.exists(newpath): + os.makedirs(newpath) + + # Plot the best fit line, set the linewidth (lw), color and + # transparency (alpha) of the line + for key in out_names: + fig, ax = plt.subplots(nrows=1, ncols=2) + + # Extract mean and std + mean_data = self.pce_means[key] + std_data = self.pce_stds[key] + + # Extract a list of x values + if type(x_values_orig) is dict: + x = x_values_orig[key] + else: + x = x_values_orig + + # Plot: bar plot or line plot + if bar_plot: + ax[0].bar(list(map(str, x)), mean_data, color='b', + width=0.25) + ax[1].bar(list(map(str, x)), std_data, color='b', + width=0.25) + ax[0].legend(labels=[meta_model_type]) + ax[1].legend(labels=[meta_model_type]) + else: + ax[0].plot(x, mean_data, lw=3, color='k', marker='x', + label=meta_model_type) + ax[1].plot(x, std_data, lw=3, color='k', marker='x', + label=meta_model_type) + + if self.mc_reference is not None: + if bar_plot: + ax[0].bar(list(map(str, x)), self.mc_reference['mean'], + color='r', width=0.25) + ax[1].bar(list(map(str, x)), self.mc_reference['std'], + color='r', width=0.25) + ax[0].legend(labels=[meta_model_type]) + ax[1].legend(labels=[meta_model_type]) + else: + ax[0].plot(x, self.mc_reference['mean'], lw=3, marker='x', + color='r', label='Ref.') + ax[1].plot(x, self.mc_reference['std'], lw=3, marker='x', + color='r', label='Ref.') + + # Label the axes and provide a title + ax[0].set_xlabel(xlabel) + ax[1].set_xlabel(xlabel) + ax[0].set_ylabel(key) + ax[1].set_ylabel(key) + + # Provide a title + ax[0].set_title('Mean of ' + key) + ax[1].set_title('Std of ' + key) + + if not bar_plot: + ax[0].legend(loc='best') + ax[1].legend(loc='best') + + plt.tight_layout() + + # save the current figure + fig.savefig( + f'{self.out_dir}/{newpath}Mean_Std_PCE_{key}.pdf', + bbox_inches='tight' + ) + + return self.pce_means, self.pce_stds + + # ------------------------------------------------------------------------- + def valid_metamodel(self, n_samples=1, samples=None, model_out_dict=None, + x_axis='Time [s]'): + """ + Evaluates and plots the meta model and the PCEModel outputs for the + given number of samples or the given samples. + + Parameters + ---------- + n_samples : int, optional + Number of samples to be evaluated. The default is 1. + samples : array of shape (n_samples, n_params), optional + Samples to be evaluated. The default is None. + model_out_dict: dict + The model runs using the samples provided. + x_axis : str, optional + Label of x axis. The default is `'Time [s]'`. + + Returns + ------- + None. + + """ + MetaModel = self.MetaModel + Model = self.ModelObj + + if samples is None: + self.n_samples = n_samples + samples = self._get_sample() + else: + self.n_samples = samples.shape[0] + + # Extract x_values + x_values = self.engine.ExpDesign.x_values + + if model_out_dict is not None: + self.model_out_dict = model_out_dict + else: + self.model_out_dict = self._eval_model(samples, key_str='valid') + self.pce_out_mean, self.pce_out_std = MetaModel.eval_metamodel(samples) + + try: + key = Model.Output.names[1] + except IndexError: + key = Model.Output.names[0] + + n_obs = self.model_out_dict[key].shape[1] + + if n_obs == 1: + self._plot_validation() + else: + self._plot_validation_multi(x_values=x_values, x_axis=x_axis) + + # ------------------------------------------------------------------------- + def check_accuracy(self, n_samples=None, samples=None, outputs=None): + """ + Checks accuracy of the metamodel by computing the root mean square + error and validation error for all outputs. + + Parameters + ---------- + n_samples : int, optional + Number of samples. The default is None. + samples : array of shape (n_samples, n_params), optional + Parameter sets to be checked. The default is None. + outputs : dict, optional + Output dictionary with model outputs for all given output types in + `Model.Output.names`. The default is None. + + Raises + ------ + Exception + When neither n_samples nor samples are provided. + + Returns + ------- + rmse: dict + Root mean squared error for each output. + valid_error : dict + Validation error for each output. + + """ + MetaModel = self.MetaModel + Model = self.ModelObj + + # Set the number of samples + if n_samples: + self.n_samples = n_samples + elif samples is not None: + self.n_samples = samples.shape[0] + else: + raise Exception("Please provide either samples or pass the number" + " of samples!") + + # Generate random samples if necessary + Samples = self._get_sample() if samples is None else samples + + # Run the original model with the generated samples + if outputs is None: + outputs = self._eval_model(Samples, key_str='validSet') + + # Run the PCE model with the generated samples + pce_outputs, _ = MetaModel.eval_metamodel(samples=Samples) + + self.rmse = {} + self.valid_error = {} + # Loop over the keys and compute RMSE error. + for key in Model.Output.names: + # Root mean square + self.rmse[key] = mean_squared_error(outputs[key], pce_outputs[key], + squared=False, + multioutput='raw_values') + # Validation error + self.valid_error[key] = (self.rmse[key]**2) / \ + np.var(outputs[key], ddof=1, axis=0) + + # Print a report table + print("\n>>>>> Errors of {} <<<<<".format(key)) + print("\nIndex | RMSE | Validation Error") + print('-'*35) + print('\n'.join(f'{i+1} | {k:.3e} | {j:.3e}' for i, (k, j) + in enumerate(zip(self.rmse[key], + self.valid_error[key])))) + # Save error dicts in PCEModel object + self.MetaModel.rmse = self.rmse + self.MetaModel.valid_error = self.valid_error + + return + + # ------------------------------------------------------------------------- + def plot_seq_design_diagnostics(self, ref_BME_KLD=None): + """ + Plots the Bayesian Model Evidence (BME) and Kullback-Leibler divergence + (KLD) for the sequential design. + + Parameters + ---------- + ref_BME_KLD : array, optional + Reference BME and KLD . The default is `None`. + + Returns + ------- + None. + + """ + engine = self.engine + PCEModel = self.MetaModel + n_init_samples = engine.ExpDesign.n_init_samples + n_total_samples = engine.ExpDesign.X.shape[0] + + newpath = f'Outputs_PostProcessing_{self.name}/seq_design_diagnostics/' + if not os.path.exists(newpath): + os.makedirs(newpath) + + plotList = ['Modified LOO error', 'Validation error', 'KLD', 'BME', + 'RMSEMean', 'RMSEStd', 'Hellinger distance'] + seqList = [engine.SeqModifiedLOO, engine.seqValidError, + engine.SeqKLD, engine.SeqBME, engine.seqRMSEMean, + engine.seqRMSEStd, engine.SeqDistHellinger] + + markers = ('x', 'o', 'd', '*', '+') + colors = ('k', 'darkgreen', 'b', 'navy', 'darkred') + + # Plot the evolution of the diagnostic criteria of the + # Sequential Experimental Design. + for plotidx, plot in enumerate(plotList): + fig, ax = plt.subplots() + seq_dict = seqList[plotidx] + name_util = list(seq_dict.keys()) + + if len(name_util) == 0: + continue + + # Box plot when Replications have been detected. + if any(int(name.split("rep_", 1)[1]) > 1 for name in name_util): + # Extract the values from dict + sorted_seq_opt = {} + # Number of replications + n_reps = engine.ExpDesign.n_replication + + # Get the list of utility function names + # Handle if only one UtilityFunction is provided + if not isinstance(engine.ExpDesign.util_func, list): + util_funcs = [engine.ExpDesign.util_func] + else: + util_funcs = engine.ExpDesign.util_func + + for util in util_funcs: + sortedSeq = {} + # min number of runs available from reps + n_runs = min([seq_dict[f'{util}_rep_{i+1}'].shape[0] + for i in range(n_reps)]) + + for runIdx in range(n_runs): + values = [] + for key in seq_dict.keys(): + if util in key: + values.append(seq_dict[key][runIdx].mean()) + sortedSeq['SeqItr_'+str(runIdx)] = np.array(values) + sorted_seq_opt[util] = sortedSeq + + # BoxPlot + def draw_plot(data, labels, edge_color, fill_color, idx): + pos = labels - (idx-1) + bp = plt.boxplot(data, positions=pos, labels=labels, + patch_artist=True, sym='', widths=0.75) + elements = ['boxes', 'whiskers', 'fliers', 'means', + 'medians', 'caps'] + for element in elements: + plt.setp(bp[element], color=edge_color[idx]) + + for patch in bp['boxes']: + patch.set(facecolor=fill_color[idx]) + + if engine.ExpDesign.n_new_samples != 1: + step1 = engine.ExpDesign.n_new_samples + step2 = 1 + else: + step1 = 5 + step2 = 5 + edge_color = ['red', 'blue', 'green'] + fill_color = ['tan', 'cyan', 'lightgreen'] + plot_label = plot + # Plot for different Utility Functions + for idx, util in enumerate(util_funcs): + all_errors = np.empty((n_reps, 0)) + + for key in list(sorted_seq_opt[util].keys()): + errors = sorted_seq_opt.get(util, {}).get(key)[:, None] + all_errors = np.hstack((all_errors, errors)) + + # Special cases for BME and KLD + if plot == 'KLD' or plot == 'BME': + # BME convergence if refBME is provided + if ref_BME_KLD is not None: + if plot == 'BME': + refValue = ref_BME_KLD[0] + plot_label = r'BME/BME$^{Ref.}$' + if plot == 'KLD': + refValue = ref_BME_KLD[1] + plot_label = '$D_{KL}[p(\\theta|y_*),p(\\theta)]'\ + ' / D_{KL}^{Ref.}[p(\\theta|y_*), '\ + 'p(\\theta)]$' + + # Difference between BME/KLD and the ref. values + all_errors = np.divide(all_errors, + np.full((all_errors.shape), + refValue)) + + # Plot baseline for zero, i.e. no difference + plt.axhline(y=1.0, xmin=0, xmax=1, c='green', + ls='--', lw=2) + + # Plot each UtilFuncs + labels = np.arange(n_init_samples, n_total_samples+1, step1) + draw_plot(all_errors[:, ::step2], labels, edge_color, + fill_color, idx) + + plt.xticks(labels, labels) + # Set the major and minor locators + ax.xaxis.set_major_locator(ticker.AutoLocator()) + ax.xaxis.set_minor_locator(ticker.AutoMinorLocator()) + ax.xaxis.grid(True, which='major', linestyle='-') + ax.xaxis.grid(True, which='minor', linestyle='--') + + # Legend + legend_elements = [] + for idx, util in enumerate(util_funcs): + legend_elements.append(Patch(facecolor=fill_color[idx], + edgecolor=edge_color[idx], + label=util)) + plt.legend(handles=legend_elements[::-1], loc='best') + + if plot != 'BME' and plot != 'KLD': + plt.yscale('log') + plt.autoscale(True) + plt.xlabel('\\# of training samples') + plt.ylabel(plot_label) + plt.title(plot) + + # save the current figure + plot_name = plot.replace(' ', '_') + fig.savefig( + f'{self.out_dir}/{newpath}/seq_{plot_name}.pdf', + bbox_inches='tight' + ) + # Destroy the current plot + plt.clf() + # Save arrays into files + f = open(f'{self.out_dir}/{newpath}/seq_{plot_name}.txt', 'w') + f.write(str(sorted_seq_opt)) + f.close() + else: + for idx, name in enumerate(name_util): + seq_values = seq_dict[name] + if engine.ExpDesign.n_new_samples != 1: + step = engine.ExpDesign.n_new_samples + else: + step = 1 + x_idx = np.arange(n_init_samples, n_total_samples+1, step) + if n_total_samples not in x_idx: + x_idx = np.hstack((x_idx, n_total_samples)) + + if plot == 'KLD' or plot == 'BME': + # BME convergence if refBME is provided + if ref_BME_KLD is not None: + if plot == 'BME': + refValue = ref_BME_KLD[0] + plot_label = r'BME/BME$^{Ref.}$' + if plot == 'KLD': + refValue = ref_BME_KLD[1] + plot_label = '$D_{KL}[p(\\theta|y_*),p(\\theta)]'\ + ' / D_{KL}^{Ref.}[p(\\theta|y_*), '\ + 'p(\\theta)]$' + + # Difference between BME/KLD and the ref. values + values = np.divide(seq_values, + np.full((seq_values.shape), + refValue)) + + # Plot baseline for zero, i.e. no difference + plt.axhline(y=1.0, xmin=0, xmax=1, c='green', + ls='--', lw=2) + + # Set the limits + plt.ylim([1e-1, 1e1]) + + # Create the plots + plt.semilogy(x_idx, values, marker=markers[idx], + color=colors[idx], ls='--', lw=2, + label=name.split("_rep", 1)[0]) + else: + plot_label = plot + + # Create the plots + plt.plot(x_idx, seq_values, marker=markers[idx], + color=colors[idx], ls='--', lw=2, + label=name.split("_rep", 1)[0]) + + else: + plot_label = plot + seq_values = np.nan_to_num(seq_values) + + # Plot the error evolution for each output + plt.semilogy(x_idx, seq_values.mean(axis=1), + marker=markers[idx], ls='--', lw=2, + color=colors[idx], + label=name.split("_rep", 1)[0]) + + # Set the major and minor locators + ax.xaxis.set_major_locator(ticker.AutoLocator()) + ax.xaxis.set_minor_locator(ticker.AutoMinorLocator()) + ax.xaxis.grid(True, which='major', linestyle='-') + ax.xaxis.grid(True, which='minor', linestyle='--') + + ax.tick_params(axis='both', which='major', direction='in', + width=3, length=10) + ax.tick_params(axis='both', which='minor', direction='in', + width=2, length=8) + plt.xlabel('Number of runs') + plt.ylabel(plot_label) + plt.title(plot) + plt.legend(frameon=True) + + # save the current figure + plot_name = plot.replace(' ', '_') + fig.savefig( + f'{self.out_dir}/{newpath}/seq_{plot_name}.pdf', + bbox_inches='tight' + ) + # Destroy the current plot + plt.clf() + + # ---------------- Saving arrays into files --------------- + np.save(f'{self.out_dir}/{newpath}/seq_{plot_name}.npy', seq_values) + + return + + # ------------------------------------------------------------------------- + def sobol_indices(self, xlabel='Time [s]', plot_type=None): + """ + Provides Sobol indices as a sensitivity measure to infer the importance + of the input parameters. See Eq. 27 in [1] for more details. For the + case with Principal component analysis refer to [2]. + + [1] Global sensitivity analysis: A flexible and efficient framework + with an example from stochastic hydrogeology S. Oladyshkin, F.P. + de Barros, W. Nowak https://doi.org/10.1016/j.advwatres.2011.11.001 + + [2] Nagel, J.B., Rieckermann, J. and Sudret, B., 2020. Principal + component analysis and sparse polynomial chaos expansions for global + sensitivity analysis and model calibration: Application to urban + drainage simulation. Reliability Engineering & System Safety, 195, + p.106737. + + Parameters + ---------- + xlabel : str, optional + Label of the x-axis. The default is `'Time [s]'`. + plot_type : str, optional + Plot type. The default is `None`. This corresponds to line plot. + Bar chart can be selected by `bar`. + + Returns + ------- + sobol_cell: dict + Sobol indices. + total_sobol: dict + Total Sobol indices. + + """ + # Extract the necessary variables + PCEModel = self.MetaModel + basis_dict = PCEModel.basis_dict + coeffs_dict = PCEModel.coeffs_dict + n_params = PCEModel.n_params + if hasattr(PCEModel, 'n_inner_params'): + n_params = PCEModel.n_inner_params + max_order = np.max(PCEModel.pce_deg) + sobol_cell_b = {} + total_sobol_b = {} + cov_Z_p_q = np.zeros((n_params)) + + outputs = self.ModelObj.Output.names + if hasattr(PCEModel, 'trafo_type'): + if PCEModel.trafo_type == 'space': + outputs = ['Z'] + + for b_i in range(PCEModel.n_bootstrap_itrs): + + sobol_cell_, total_sobol_ = {}, {} + + for output in outputs: + + n_meas_points = len(coeffs_dict[f'b_{b_i+1}'][output]) + + # Initialize the (cell) array containing the (total) Sobol indices. + sobol_array = dict.fromkeys(range(1, max_order+1), []) + sobol_cell_array = dict.fromkeys(range(1, max_order+1), []) + + for i_order in range(1, max_order+1): + n_comb = math.comb(n_params, i_order) + + sobol_cell_array[i_order] = np.zeros((n_comb, n_meas_points)) + + total_sobol_array = np.zeros((n_params, n_meas_points)) + + # Initialize the cell to store the names of the variables + TotalVariance = np.zeros((n_meas_points)) + # Loop over all measurement points and calculate sobol indices + for pIdx in range(n_meas_points): + + # Extract the basis indices (alpha) and coefficients + Basis = basis_dict[f'b_{b_i+1}'][output][f'y_{pIdx+1}'] + + try: + clf_poly = PCEModel.clf_poly[f'b_{b_i+1}'][output][f'y_{pIdx+1}'] + PCECoeffs = clf_poly.coef_ + except: + PCECoeffs = coeffs_dict[f'b_{b_i+1}'][output][f'y_{pIdx+1}'] + + # Compute total variance + TotalVariance[pIdx] = np.sum(np.square(PCECoeffs[1:])) + + nzidx = np.where(PCECoeffs != 0)[0] + # Set all the Sobol indices equal to zero in the presence of a + # null output. + if len(nzidx) == 0: + # This is buggy. + for i_order in range(1, max_order+1): + sobol_cell_array[i_order][:, pIdx] = 0 + + # Otherwise compute them by summing well-chosen coefficients + else: + nz_basis = Basis[nzidx] + for i_order in range(1, max_order+1): + idx = np.where(np.sum(nz_basis > 0, axis=1) == i_order) + subbasis = nz_basis[idx] + Z = np.array(list(combinations(range(n_params), i_order))) + + for q in range(Z.shape[0]): + Zq = Z[q] + subsubbasis = subbasis[:, Zq] + subidx = np.prod(subsubbasis, axis=1) > 0 + sum_ind = nzidx[idx[0][subidx]] + if TotalVariance[pIdx] == 0.0: + sobol_cell_array[i_order][q, pIdx] = 0.0 + else: + sobol = np.sum(np.square(PCECoeffs[sum_ind])) + sobol /= TotalVariance[pIdx] + sobol_cell_array[i_order][q, pIdx] = sobol + + # Compute the TOTAL Sobol indices. + for ParIdx in range(n_params): + idx = nz_basis[:, ParIdx] > 0 + sum_ind = nzidx[idx] + + if TotalVariance[pIdx] == 0.0: + total_sobol_array[ParIdx, pIdx] = 0.0 + else: + sobol = np.sum(np.square(PCECoeffs[sum_ind])) + sobol /= TotalVariance[pIdx] + total_sobol_array[ParIdx, pIdx] = sobol + + # ----- if PCA selected: Compute covariance ----- + if PCEModel.dim_red_method.lower() == 'pca': + # Extract the basis indices (alpha) and coefficients for + # next component + if pIdx < n_meas_points-1: + nextBasis = basis_dict[f'b_{b_i+1}'][output][f'y_{pIdx+2}'] + if PCEModel.bootstrap_method != 'fast' or b_i == 0: + clf_poly = PCEModel.clf_poly[f'b_{b_i+1}'][output][f'y_{pIdx+2}'] + nextPCECoeffs = clf_poly.coef_ + else: + nextPCECoeffs = coeffs_dict[f'b_{b_i+1}'][output][f'y_{pIdx+2}'] + + # Choose the common non-zero basis + mask = (Basis[:, None] == nextBasis).all(-1).any(-1) + n_mask = (nextBasis[:, None] == Basis).all(-1).any(-1) + + # Compute the covariance in Eq 17. + for ParIdx in range(n_params): + idx = (mask) & (Basis[:, ParIdx] > 0) + n_idx = (n_mask) & (nextBasis[:, ParIdx] > 0) + try: + cov_Z_p_q[ParIdx] += np.sum(np.dot( + PCECoeffs[idx], nextPCECoeffs[n_idx]) + ) + except: + pass + + # Compute the sobol indices according to Ref. 2 + if PCEModel.dim_red_method.lower() == 'pca': + n_c_points = self.engine.ExpDesign.Y[output].shape[1] + PCA = PCEModel.pca[f'b_{b_i+1}'][output] + compPCA = PCA.components_ + nComp = compPCA.shape[0] + var_Z_p = PCA.explained_variance_ + + # Extract the sobol index of the components + for i_order in range(1, max_order+1): + n_comb = math.comb(n_params, i_order) + sobol_array[i_order] = np.zeros((n_comb, n_c_points)) + Z = np.array(list(combinations(range(n_params), i_order))) + + # Loop over parameters + for q in range(Z.shape[0]): + S_Z_i = sobol_cell_array[i_order][q] + + for tIdx in range(n_c_points): + var_Y_t = np.var( + self.engine.ExpDesign.Y[output][:, tIdx]) + if var_Y_t == 0.0: + term1, term2 = 0.0, 0.0 + else: + # Eq. 17 + term1 = 0.0 + for i in range(nComp): + a = S_Z_i[i] * var_Z_p[i] + a *= compPCA[i, tIdx]**2 + term1 += a + + # TODO: Term 2 + # term2 = 0.0 + # for i in range(nComp-1): + # term2 += cov_Z_p_q[q] * compPCA[i, tIdx] + # term2 *= compPCA[i+1, tIdx] + # term2 *= 2 + + sobol_array[i_order][q, tIdx] = term1 #+ term2 + + # Devide over total output variance Eq. 18 + sobol_array[i_order][q, tIdx] /= var_Y_t + + # Compute the TOTAL Sobol indices. + total_sobol = np.zeros((n_params, n_c_points)) + for ParIdx in range(n_params): + S_Z_i = total_sobol_array[ParIdx] + + for tIdx in range(n_c_points): + var_Y_t = np.var(self.engine.ExpDesign.Y[output][:, tIdx]) + if var_Y_t == 0.0: + term1, term2 = 0.0, 0.0 + else: + term1 = 0 + for i in range(nComp): + term1 += S_Z_i[i] * var_Z_p[i] * \ + (compPCA[i, tIdx]**2) + + # Term 2 + term2 = 0 + for i in range(nComp-1): + term2 += cov_Z_p_q[ParIdx] * compPCA[i, tIdx] \ + * compPCA[i+1, tIdx] + term2 *= 2 + + total_sobol[ParIdx, tIdx] = term1 #+ term2 + + # Devide over total output variance Eq. 18 + total_sobol[ParIdx, tIdx] /= var_Y_t + + sobol_cell_[output] = sobol_array + total_sobol_[output] = total_sobol + else: + sobol_cell_[output] = sobol_cell_array + total_sobol_[output] = total_sobol_array + + # Save for each bootsrtap iteration + sobol_cell_b[b_i] = sobol_cell_ + total_sobol_b[b_i] = total_sobol_ + + # Average total sobol indices + total_sobol_all = {} + for i in sorted(total_sobol_b): + for k, v in total_sobol_b[i].items(): + if k not in total_sobol_all: + total_sobol_all[k] = [None] * len(total_sobol_b) + total_sobol_all[k][i] = v + sobol_all = {} + for i in sorted(sobol_cell_b): + for k, v in sobol_cell_b[i].items(): + for l,m in v.items(): + if l not in sobol_all: + sobol_all[l]={} + if k not in sobol_all[l]: + sobol_all[l][k] = [None] * len(sobol_cell_b) + sobol_all[l][k][i] = v[l] + #print(sobol_all) + + self.sobol = {} + # Will receive a set of indices for each possible degree of polynomial/interaction + for i_order in range(1, max_order+1): + self.sobol[i_order]={} + for output in outputs: + self.sobol[i_order][output] = np.mean([sobol_all[i_order][output]], axis=0) + + self.total_sobol = {} + for output in outputs: + self.total_sobol[output] = np.mean(total_sobol_all[output], axis=0) + + # ---------------- Plot ----------------------- + par_names = self.engine.ExpDesign.par_names + x_values_orig = self.engine.ExpDesign.x_values + + # Check if the x_values match the number of metamodel outputs + if not np.array(x_values_orig).shape[0] == self.total_sobol[outputs[0]].shape[1]: + print('The number of MetaModel outputs does not match the x_values' + ' specified in ExpDesign. Images are created with ' + 'equidistant numbers on the x-axis') + x_values_orig = np.arange(0,1,self.total_sobol[output].shape[0]) + + # Check if it uses a wrapper structure + if hasattr(PCEModel, 'trafo_type'): + if PCEModel.trafo_type == 'time': + par_names.append('time') + + newpath = (f'Outputs_PostProcessing_{self.name}/') + if not os.path.exists(newpath): + os.makedirs(newpath) + + if 1: + fig = plt.figure() + + for i_order in range(1, max_order+1): + # Change labels to combined params sets for higher order indices + if i_order == 1: + par_names_i = par_names + else: + par_names_i = list(combinations(par_names, i_order)) + for outIdx, output in enumerate(outputs): + + # Extract total Sobol indices + sobol = self.sobol[i_order][output][0] + + # Compute quantiles + q_5 = np.quantile(sobol_all[i_order][output], q=0.05, axis=0) + q_97_5 = np.quantile(sobol_all[i_order][output], q=0.975, axis=0) + + # Extract a list of x values + if type(x_values_orig) is dict: + x = x_values_orig[output] + else: + x = x_values_orig + + if plot_type == 'bar': + ax = fig.add_axes([0, 0, 1, 1]) + dict1 = {xlabel: x} + dict2 = {param: sobolIndices for param, sobolIndices + in zip(par_names_i, sobol)} + + df = pd.DataFrame({**dict1, **dict2}) + df.plot(x=xlabel, y=par_names_i, kind="bar", ax=ax, rot=0, + colormap='Dark2', yerr=q_97_5-q_5) + ax.set_ylabel('Sobol indices, $S^T$') + + else: + for i, sobolIndices in enumerate(sobol): + plt.plot(x, sobolIndices, label=par_names_i[i], + marker='x', lw=2.5) + plt.fill_between(x, q_5[i], q_97_5[i], alpha=0.15) + + plt.ylabel('Sobol indices, $S^T$') + plt.xlabel(xlabel) + + plt.title(f'{i_order} degree Sensitivity analysis of {output}') + if plot_type != 'bar': + plt.legend(loc='best', frameon=True) + + # Save indices + np.savetxt(f'{self.out_dir}/{newpath}sobol_{i_order}_' + + output.replace('/', '_') + '.csv', + sobol.T, delimiter=',', + header=','.join(par_names), comments='') + + # save the current figure + #print(f'{self.out_dir}/{newpath}Sobol_indices_{i_order}_{output}.pdf') + fig.savefig( + f'{self.out_dir}/{newpath}Sobol_indices_{i_order}_{output}.pdf', + bbox_inches='tight' + ) + + # Destroy the current plot + plt.clf() + + fig = plt.figure() + + for outIdx, output in enumerate(outputs): + + # Extract total Sobol indices + total_sobol = self.total_sobol[output] + + # Compute quantiles + q_5 = np.quantile(total_sobol_all[output], q=0.05, axis=0) + q_97_5 = np.quantile(total_sobol_all[output], q=0.975, axis=0) + + # Extract a list of x values + if type(x_values_orig) is dict: + x = x_values_orig[output] + else: + x = x_values_orig + + if plot_type == 'bar': + ax = fig.add_axes([0, 0, 1, 1]) + dict1 = {xlabel: x} + dict2 = {param: sobolIndices for param, sobolIndices + in zip(par_names, total_sobol)} + + df = pd.DataFrame({**dict1, **dict2}) + df.plot(x=xlabel, y=par_names, kind="bar", ax=ax, rot=0, + colormap='Dark2', yerr=q_97_5-q_5) + ax.set_ylabel('Total Sobol indices, $S^T$') + + else: + for i, sobolIndices in enumerate(total_sobol): + plt.plot(x, sobolIndices, label=par_names[i], + marker='x', lw=2.5) + plt.fill_between(x, q_5[i], q_97_5[i], alpha=0.15) + + plt.ylabel('Total Sobol indices, $S^T$') + plt.xlabel(xlabel) + + plt.title(f'Sensitivity analysis of {output}') + if plot_type != 'bar': + plt.legend(loc='best', frameon=True) + + # Save indices + np.savetxt(f'{self.out_dir}/{newpath}totalsobol_' + + output.replace('/', '_') + '.csv', + total_sobol.T, delimiter=',', + header=','.join(par_names), comments='') + + # save the current figure + fig.savefig( + f'{self.out_dir}/{newpath}TotalSobol_indices_{output}.pdf', + bbox_inches='tight' + ) + + # Destroy the current plot + plt.clf() + + return self.sobol, self.total_sobol + + # ------------------------------------------------------------------------- + def check_reg_quality(self, n_samples=1000, samples=None): + """ + Checks the quality of the metamodel for single output models based on: + https://towardsdatascience.com/how-do-you-check-the-quality-of-your-regression-model-in-python-fa61759ff685 + + + Parameters + ---------- + n_samples : int, optional + Number of parameter sets to use for the check. The default is 1000. + samples : array of shape (n_samples, n_params), optional + Parameter sets to use for the check. The default is None. + + Returns + ------- + None. + + """ + MetaModel = self.MetaModel + + if samples is None: + self.n_samples = n_samples + samples = self._get_sample() + else: + self.n_samples = samples.shape[0] + + # Evaluate the original and the surrogate model + y_val = self._eval_model(samples, key_str='valid') + y_pce_val, _ = MetaModel.eval_metamodel(samples=samples) + + # Open a pdf for the plots + newpath = f'Outputs_PostProcessing_{self.name}/' + if not os.path.exists(newpath): + os.makedirs(newpath) + + # Fit the data(train the model) + for key in y_pce_val.keys(): + + y_pce_val_ = y_pce_val[key] + y_val_ = y_val[key] + residuals = y_val_ - y_pce_val_ + + # ------ Residuals vs. predicting variables ------ + # Check the assumptions of linearity and independence + fig1 = plt.figure() + for i, par in enumerate(self.engine.ExpDesign.par_names): + plt.title(f"{key}: Residuals vs. {par}") + plt.scatter( + x=samples[:, i], y=residuals, color='blue', edgecolor='k') + plt.grid(True) + xmin, xmax = min(samples[:, i]), max(samples[:, i]) + plt.hlines(y=0, xmin=xmin*0.9, xmax=xmax*1.1, color='red', + lw=3, linestyle='--') + plt.xlabel(par) + plt.ylabel('Residuals') + plt.show() + + # save the current figure + fig1.savefig(f'{self.out_dir}/{newpath}/Residuals_vs_Par_{i+1}.pdf', + bbox_inches='tight') + # Destroy the current plot + plt.clf() + + # ------ Fitted vs. residuals ------ + # Check the assumptions of linearity and independence + fig2 = plt.figure() + plt.title(f"{key}: Residuals vs. fitted values") + plt.scatter(x=y_pce_val_, y=residuals, color='blue', edgecolor='k') + plt.grid(True) + xmin, xmax = min(y_val_), max(y_val_) + plt.hlines(y=0, xmin=xmin*0.9, xmax=xmax*1.1, color='red', lw=3, + linestyle='--') + plt.xlabel(key) + plt.ylabel('Residuals') + plt.show() + + # save the current figure + fig2.savefig(f'{self.out_dir}/{newpath}/Fitted_vs_Residuals.pdf', + bbox_inches='tight') + # Destroy the current plot + plt.clf() + + # ------ Histogram of normalized residuals ------ + fig3 = plt.figure() + resid_pearson = residuals / (max(residuals)-min(residuals)) + plt.hist(resid_pearson, bins=20, edgecolor='k') + plt.ylabel('Count') + plt.xlabel('Normalized residuals') + plt.title(f"{key}: Histogram of normalized residuals") + + # Normality (Shapiro-Wilk) test of the residuals + ax = plt.gca() + _, p = stats.shapiro(residuals) + if p < 0.01: + annText = "The residuals seem to come from a Gaussian Process." + else: + annText = "The normality assumption may not hold." + at = AnchoredText(annText, prop=dict(size=30), frameon=True, + loc='upper left') + at.patch.set_boxstyle("round,pad=0.,rounding_size=0.2") + ax.add_artist(at) + + plt.show() + + # save the current figure + fig3.savefig(f'{self.out_dir}/{newpath}/Hist_NormResiduals.pdf', + bbox_inches='tight') + # Destroy the current plot + plt.clf() + + # ------ Q-Q plot of the normalized residuals ------ + plt.figure() + stats.probplot(residuals[:, 0], plot=plt) + plt.xticks() + plt.yticks() + plt.xlabel("Theoretical quantiles") + plt.ylabel("Sample quantiles") + plt.title(f"{key}: Q-Q plot of normalized residuals") + plt.grid(True) + plt.show() + + # save the current figure + plt.savefig(f'{self.out_dir}/{newpath}/QQPlot_NormResiduals.pdf', + bbox_inches='tight') + # Destroy the current plot + plt.clf() + + # ------------------------------------------------------------------------- + def eval_pce_model_3d(self): + + self.n_samples = 1000 + + PCEModel = self.MetaModel + Model = self.ModelObj + n_samples = self.n_samples + + # Create 3D-Grid + # TODO: Make it general + x = np.linspace(-5, 10, n_samples) + y = np.linspace(0, 15, n_samples) + + X, Y = np.meshgrid(x, y) + PCE_Z = np.zeros((self.n_samples, self.n_samples)) + Model_Z = np.zeros((self.n_samples, self.n_samples)) + + for idxMesh in range(self.n_samples): + sample_mesh = np.vstack((X[:, idxMesh], Y[:, idxMesh])).T + + univ_p_val = PCEModel.univ_basis_vals(sample_mesh) + + for Outkey, ValuesDict in PCEModel.coeffs_dict.items(): + + pce_out_mean = np.zeros((len(sample_mesh), len(ValuesDict))) + pce_out_std = np.zeros((len(sample_mesh), len(ValuesDict))) + model_outs = np.zeros((len(sample_mesh), len(ValuesDict))) + + for Inkey, InIdxValues in ValuesDict.items(): + idx = int(Inkey.split('_')[1]) - 1 + basis_deg_ind = PCEModel.basis_dict[Outkey][Inkey] + clf_poly = PCEModel.clf_poly[Outkey][Inkey] + + PSI_Val = PCEModel.create_psi(basis_deg_ind, univ_p_val) + + # Perdiction with error bar + y_mean, y_std = clf_poly.predict(PSI_Val, return_std=True) + + pce_out_mean[:, idx] = y_mean + pce_out_std[:, idx] = y_std + + # Model evaluation + model_out_dict, _ = Model.run_model_parallel(sample_mesh, + key_str='Valid3D') + model_outs[:, idx] = model_out_dict[Outkey].T + + PCE_Z[:, idxMesh] = y_mean + Model_Z[:, idxMesh] = model_outs[:, 0] + + # ---------------- 3D plot for PCEModel ----------------------- + fig_PCE = plt.figure() + ax = plt.axes(projection='3d') + ax.plot_surface(X, Y, PCE_Z, rstride=1, cstride=1, + cmap='viridis', edgecolor='none') + ax.set_title('PCEModel') + ax.set_xlabel('$x_1$') + ax.set_ylabel('$x_2$') + ax.set_zlabel('$f(x_1,x_2)$') + + plt.grid() + plt.show() + + # Saving the figure + newpath = f'Outputs_PostProcessing_{self.name}/' + if not os.path.exists(newpath): + os.makedirs(newpath) + + # save the figure to file + fig_PCE.savefig(f'{self.out_dir}/{newpath}/3DPlot_PCEModel.pdf', + bbox_inches='tight') + plt.close(fig_PCE) + + # ---------------- 3D plot for Model ----------------------- + fig_Model = plt.figure() + ax = plt.axes(projection='3d') + ax.plot_surface(X, Y, PCE_Z, rstride=1, cstride=1, + cmap='viridis', edgecolor='none') + ax.set_title('Model') + ax.set_xlabel('$x_1$') + ax.set_ylabel('$x_2$') + ax.set_zlabel('$f(x_1,x_2)$') + + plt.grid() + plt.show() + + # Save the figure + fig_Model.savefig(f'{self.out_dir}/{newpath}/3DPlot_Model.pdf', + bbox_inches='tight') + plt.close(fig_Model) + + return + + # ------------------------------------------------------------------------- + def compute_pce_moments(self): + """ + Computes the first two moments using the PCE-based meta-model. + + Returns + ------- + pce_means: dict + The first moments (mean) of outpust. + pce_means: dict + The first moments (mean) of outpust. + + """ + + MetaModel = self.MetaModel + outputs = self.ModelObj.Output.names + pce_means_b = {} + pce_stds_b = {} + + # Loop over bootstrap iterations + for b_i in range(MetaModel.n_bootstrap_itrs): + # Loop over the metamodels + coeffs_dicts = MetaModel.coeffs_dict[f'b_{b_i+1}'].items() + means = {} + stds = {} + for output, coef_dict in coeffs_dicts: + + pce_mean = np.zeros((len(coef_dict))) + pce_var = np.zeros((len(coef_dict))) + + for index, values in coef_dict.items(): + idx = int(index.split('_')[1]) - 1 + coeffs = MetaModel.coeffs_dict[f'b_{b_i+1}'][output][index] + + # Mean = c_0 + if coeffs[0] != 0: + pce_mean[idx] = coeffs[0] + else: + clf_poly = MetaModel.clf_poly[f'b_{b_i+1}'][output] + pce_mean[idx] = clf_poly[index].intercept_ + # Var = sum(coeffs[1:]**2) + pce_var[idx] = np.sum(np.square(coeffs[1:])) + + # Save predictions for each output + if MetaModel.dim_red_method.lower() == 'pca': + PCA = MetaModel.pca[f'b_{b_i+1}'][output] + means[output] = PCA.inverse_transform(pce_mean) + stds[output] = np.sqrt(np.dot(pce_var, + PCA.components_**2)) + else: + means[output] = pce_mean + stds[output] = np.sqrt(pce_var) + + # Save predictions for each bootstrap iteration + pce_means_b[b_i] = means + pce_stds_b[b_i] = stds + + # Change the order of nesting + mean_all = {} + for i in sorted(pce_means_b): + for k, v in pce_means_b[i].items(): + if k not in mean_all: + mean_all[k] = [None] * len(pce_means_b) + mean_all[k][i] = v + std_all = {} + for i in sorted(pce_stds_b): + for k, v in pce_stds_b[i].items(): + if k not in std_all: + std_all[k] = [None] * len(pce_stds_b) + std_all[k][i] = v + + # Back transformation if PCA is selected. + pce_means, pce_stds = {}, {} + for output in outputs: + pce_means[output] = np.mean(mean_all[output], axis=0) + pce_stds[output] = np.mean(std_all[output], axis=0) + + # Print a report table + print("\n>>>>> Moments of {} <<<<<".format(output)) + print("\nIndex | Mean | Std. deviation") + print('-'*35) + print('\n'.join(f'{i+1} | {k:.3e} | {j:.3e}' for i, (k, j) + in enumerate(zip(pce_means[output], + pce_stds[output])))) + print('-'*40) + + return pce_means, pce_stds + + # ------------------------------------------------------------------------- + def compute_mc_moments(self, num_mc_samples): + """ + Computes the first two moments of the metamodel using MC samples. + + Parameters + ---------- + num_mc_samples : int + The number of samples to estimate the moments by + + Returns + ------- + pce_means: dict + The first moments (mean) of outpust. + pce_means: dict + The first moments (mean) of outpust. + + """ + # Get the MC-samples + samples = self.engine.ExpDesign.generate_samples(num_mc_samples) + print('Random samples are genereated, now starting the evaluations') + + # Run the metamodel on the samples + approx, stds = self.engine.MetaModel.eval_metamodel(samples) + + # Estimate the overall mean and std from this + pce_means = {} + pce_stds = {} + for key in approx.keys(): + if key == 'x_values': + continue + pce_means[key] = np.mean(approx[key], axis = 0) + pce_stds[key] = np.std(approx[key], axis = 0) + + return pce_means, pce_stds + + # ------------------------------------------------------------------------- + def _get_sample(self, n_samples=None): + """ + Generates random samples taken from the input parameter space. + + Returns + ------- + samples : array of shape (n_samples, n_params) + Generated samples. + + """ + if n_samples is None: + n_samples = self.n_samples + self.samples = self.ExpDesign.generate_samples(n_samples, + sampling_method='random') + return self.samples + + # ------------------------------------------------------------------------- + def _eval_model(self, samples=None, key_str='Valid'): + """ + Evaluates Forward Model for the given number of self.samples or given + samples. + + Parameters + ---------- + samples : array of shape (n_samples, n_params), optional + Samples to evaluate the model at. The default is None. + key_str : str, optional + Key string pass to the model. The default is 'Valid'. + + Returns + ------- + model_outs : dict + Dictionary of results. + + """ + Model = self.ModelObj + + if samples is None: + samples = self._get_sample() + self.samples = samples + else: + self.n_samples = len(samples) + + model_outs, _ = Model.run_model_parallel(samples, key_str=key_str) + + return model_outs + + # ------------------------------------------------------------------------- + def _plot_validation(self): + """ + Plots outputs for visual comparison of metamodel outputs with that of + the (full) original model. + + Returns + ------- + None. + + """ + PCEModel = self.MetaModel + + # get the samples + x_val = self.samples + y_pce_val = self.pce_out_mean + y_val = self.model_out_dict + + # Open a pdf for the plots + newpath = f'Outputs_PostProcessing_{self.name}/' + if not os.path.exists(newpath): + os.makedirs(newpath) + + fig = plt.figure() + # Fit the data(train the model) + for key in y_pce_val.keys(): + + y_pce_val_ = y_pce_val[key] + y_val_ = y_val[key] + + regression_model = LinearRegression() + regression_model.fit(y_pce_val_, y_val_) + + # Predict + x_new = np.linspace(np.min(y_pce_val_), np.max(y_val_), 100) + y_predicted = regression_model.predict(x_new[:, np.newaxis]) + + plt.scatter(y_pce_val_, y_val_, color='gold', linewidth=2) + plt.plot(x_new, y_predicted, color='k') + + # Calculate the adjusted R_squared and RMSE + # the total number of explanatory variables in the model + # (not including the constant term) + length_list = [] + for key, value in PCEModel.coeffs_dict['b_1'][key].items(): + length_list.append(len(value)) + n_predictors = min(length_list) + n_samples = x_val.shape[0] + + R2 = r2_score(y_pce_val_, y_val_) + AdjR2 = 1 - (1 - R2) * (n_samples - 1) / \ + (n_samples - n_predictors - 1) + rmse = mean_squared_error(y_pce_val_, y_val_, squared=False) + + plt.annotate(f'RMSE = {rmse:.3f}\n Adjusted $R^2$ = {AdjR2:.3f}', + xy=(0.05, 0.85), xycoords='axes fraction') + + plt.ylabel("Original Model") + plt.xlabel("PCE Model") + plt.grid() + plt.show() + + # save the current figure + plot_name = key.replace(' ', '_') + fig.savefig(f'{self.out_dir}/{newpath}/Model_vs_PCEModel_{plot_name}.pdf', + bbox_inches='tight') + + # Destroy the current plot + plt.clf() + + # ------------------------------------------------------------------------- + def _plot_validation_multi(self, x_values=[], x_axis="x [m]"): + """ + Plots outputs for visual comparison of metamodel outputs with that of + the (full) multioutput original model + + Parameters + ---------- + x_values : list or array, optional + List of x values. The default is []. + x_axis : str, optional + Label of the x axis. The default is "x [m]". + + Returns + ------- + None. + + """ + Model = self.ModelObj + + newpath = f'Outputs_PostProcessing_{self.name}/' + if not os.path.exists(newpath): + os.makedirs(newpath) + + # List of markers and colors + color = cycle((['b', 'g', 'r', 'y', 'k'])) + marker = cycle(('x', 'd', '+', 'o', '*')) + + fig = plt.figure() + # Plot the model vs PCE model + for keyIdx, key in enumerate(Model.Output.names): + + y_pce_val = self.pce_out_mean[key] + y_pce_val_std = self.pce_out_std[key] + y_val = self.model_out_dict[key] + try: + x = self.model_out_dict['x_values'][key] + except (TypeError, IndexError): + x = x_values + + for idx in range(y_val.shape[0]): + Color = next(color) + Marker = next(marker) + + plt.plot(x, y_val[idx], color=Color, marker=Marker, + label='$Y_{%s}^M$'%(idx+1)) + + plt.plot(x, y_pce_val[idx], color=Color, marker=Marker, + linestyle='--', + label='$Y_{%s}^{PCE}$'%(idx+1)) + plt.fill_between(x, y_pce_val[idx]-1.96*y_pce_val_std[idx], + y_pce_val[idx]+1.96*y_pce_val_std[idx], + color=Color, alpha=0.15) + + # Calculate the RMSE + rmse = mean_squared_error(y_pce_val, y_val, squared=False) + R2 = r2_score(y_pce_val[idx].reshape(-1, 1), + y_val[idx].reshape(-1, 1)) + + plt.annotate(f'RMSE = {rmse:.3f}\n $R^2$ = {R2:.3f}', + xy=(0.85, 0.1), xycoords='axes fraction') + + plt.ylabel(key) + plt.xlabel(x_axis) + plt.legend(loc='best') + plt.grid() + + # save the current figure + plot_name = key.replace(' ', '_') + fig.savefig(f'{self.out_dir}/{newpath}/Model_vs_PCEModel_{plot_name}.pdf', + bbox_inches='tight') + + # Destroy the current plot + plt.clf() + + # Zip the subdirectories + Model.zip_subdirs(f'{Model.name}valid', f'{Model.name}valid_') diff --git a/examples/analytical-function/bayesvalidrox/pylink/__init__.py b/examples/analytical-function/bayesvalidrox/pylink/__init__.py new file mode 100644 index 000000000..4bd81739f --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/pylink/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- + +from .pylink import PyLinkForwardModel + +__all__ = [ + "PyLinkForwardModel" + ] diff --git a/examples/analytical-function/bayesvalidrox/pylink/__pycache__/__init__.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/pylink/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5b7c1b3926506fb279b856f55ca6120df31b8888 GIT binary patch literal 247 zcmYk0F>V4e5Jhb-0ThKMNZf#88|DHCrHFtcL7*rNjb*UKTFkDI?G5aaa;0rk<q9+~ z3k_eIKl*yo{BgbBGb6S7LlbEKHQ`Z$!W&H(kZGnlvYf9uXIkv|TIl49rLBKXFy-~@ zvih*ae(L;DdHw0MLEju$q)FXAR7mWW>yDHPQOaNDpNQY=yn?)lu!Zknd;q_98D>fa zcz4?}H$@CEvvFQ-V2bXzR562%s!aG%Xtj4IxEFwwwy;sk(V?ol<J{>I&7^rSw8>tC HNV=CRubV&? literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/pylink/__pycache__/__init__.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/pylink/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1947ad354716d0293953761f0d35193f706cedc1 GIT binary patch literal 309 zcmZ8bJ5Izf5cR~6@X<C@Z~;&n4uB912q*xpglJZlj2DksYwb9)6WDazVvm400oR~T zOGOuHyRDe;kq~c2^LtNv^E?=AFv9Kp6(jZce)&c6Gc2}gm@~~ZSms~^z;tpCqeSy- zmalvO(K)nR!{)*i(^DTFRnV7SqYa#>tDLuK*;wMf_BNAJSu5oWTl5Y~b9^9fB8Di! z)KBb0sVGkTUG1=_qBt|vc|8_m)nI&3*68480%yvV7Ne+)LyaXCn#BJ^-=0EBQ<zH1 u{jyoE9XhXTi$`IdocqUPPNm}j(4`Fa-q`Nnq}%FF$CJ(UDeEI-r2YgLk691^ literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/pylink/__pycache__/__init__.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/pylink/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0bbb522855ad250ad55bca46123c0f5023076291 GIT binary patch literal 312 zcmYk0%}N6?6or$S`h(bw3*TWDDHL%dB0@zFtQ2HGN+6_7M#J1>hGbGZZhZw`!dGzX zTg=v#ui!@Sv>Pwn?{YYo!;!<`0l|6w_*8)Rs~7(#L2-#2juDC|3dGVmr9>r<be^d6 zo@9e>ie^T;qgi`vTzOsjXX(|nQW|_8aF?asZruWU8{O>*ApwMVCw>S04SwDxXFLzu z2kv!Qjk$_8uD4{?IPE2v7ulG~u|mrxdd+SoGj^3v^M{ksDPKebiY=`yHJ5b_+$?LZ z5zH36FiwKkAwm;Y<0sL7`RMpUwmPgZS@~+sw;j0<#+gQlQQda?=eAN2^hJtA!vJxZ GCcl4{ja-8O literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/pylink/__pycache__/pylink.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/pylink/__pycache__/pylink.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b6ae7c14b35b60388e38fcbd3af64d04771a947c GIT binary patch literal 18654 zcmbVUTZ|;vS*}}mS6BD+Tz2+qJ1N_-cN=zRY?FlGERG%TZZL_*i+AJL1EHs;t7fKp zd#Za+RqxI;)nJ%KIDm;GA#RqH87@Lb2q8cMo`46Q@_>ZIO9A2m2`LW|NJu;wlI8pV zQ&nBvGwWTa*K@k6&Z+<0{`39Uc5i0JQt<iV@0|5^d`0<px+#7P+&quJFhb!fuG&?$ z)m2rcYptuTYW%IQ>ili28vI>aE%SF}wZh-#s>$EgRg1rCt2KP<-TL;->P$+jvD)~8 z;u>!0j^dWQ**$%A&eg6d&GNU=v(i+Ps_R5fyX%DE3hpX>M?}8UZBuRWvxuAL@fZFH z3Qt*8T?M05S9Q+-ea+QDU-wFT`ksnWqCdCfD{h&-@vpq8Y|>pNy+<AW+gNl>w|Ym# zd@Q$iN5On-cgAhtN!6Wo=kUaG=iLQ-*W6?7BEIYHarXqiXWWzSDSS7o<!Z%!)IH-q zgtunhhuuf;bk6;l`*D2FyCux^v1H-u?w9=F#+9D9?Fjefp6hj;f1Fno%f{ygdqY0A zx2eKj_XF1x7S~<h@<Y4rbi>dNJ#otmZ3q9^Z8WrR3#Z@r#FEX8(mUJfc6+x&JKFMW zZ^vs7BEJ{dy$z=3;IS{<3$)0)cG%m9FdT0=>~(K>!oKaJHsCkIcCYW@E&KD%t{1-M zbba^L-p-O7(+g1~{PjWPg-rB9{^8p$=GlsN@%poN7zutxv%HQ0@ncY>!4*dD*{-+Y z47!nx$*!I4?-Gr(Yw5(qAmHibl#ZH%-4nJGq%(HbyPiD={a_PI6?)w+)@ys)30$6{ zz3Jcbf}ENk^aqi>;di}oDSvp)YxmH+*XPyaQEd!@Hr<_Fvu|(t?JaCXIN0`FOvZ`Q zooizV>z<7f%kFb}j-9=ZdHYf11sE50!HK-?u8l=^?5n%c7IrFZ3%?)9kp#~6^eV2< zqjUwCTV%`rZi{9xwd5&Du3=iV!#&J)ZK=PzhQ-1-LSm1omkk@7$h)(4HXHESwR{%& zmaX(6Y$nZ{c9Kb_W9rLUaF?{;+$gQfDCYFG2Vq1VhyJ$T?K&AJXYFjR7hc=<Zc%rh zO)IwTMV<(G&9H1jIJ-GL^b>A5;JmeSK`V5&``FX-cF^M2!sZ${#I=PN4FovKv0a}x z)DgRqFVI6yYNvI}=?>_)5gQC5;t}pFq{Av%D0@!xPkD!i-g3ldh@BwvIlUKL*C+0A zx*)R&z6l~piKjJQG~)Tm<M1=1HMz&(7C5<;aq{Hhx<++5m&@&xrymSD-qY-4<%f^Q z$0wk`KXjJ5emEXH4QYH#Qf}#k|B3s1yffoddlc=+!(M>bC4U~G|AL)2_~_k8^dpAL z7dzuC!pZ(F9hbH79C3Vc3hcFuulvuf*%(&av$uL(Aa1@;+&HIJU^>8*A7IiFTO`qN z&1UI!Uefi!&;&fRufbq@9b{ARB@oPM$$cK5OfPWhtq{kv>teCn-2o7OZ7J$^*FX_l zC{KXXjs{LQAKUl{r)O-ue&=~Q-VPsw^Y)rN1VnI&8>L+340i6f^~4Lbh-m6}eL5~Q z?$8cA&wT*)0w3Z8V#z02_Hr(qxYFOScY6b@VYo#+MG#6$C?(>(IXGVl!qA|HR|F0o zFeB=T-NT1zr5AW>*eM3^c25W|>;vc_Uzm+^YV854+CgOB?ui?;F=LwCMj`?)T#JuC zCYLQ!QRsasT{`B5Y3R=IBf>7GOL};s`H(X3E%yJQUCULJgXXycbO&^Lv;G_a({AXe zD3;C+90Q$WYTH&0%_42aynOB+5~hjGgtSPpT<Q&U9%x<G4lU+1P(R~dVC>Cd8mlG1 zlcIN9p0<3Eh+YQW=WTCkbIINT2=oL_7w{(}=!txYP$`=rsy)fu!hz02kVZqw$w4p; zfLp9VNf|&3<~fl5#U&;6g>eB)n9YW_1}Y4R%A6iAg0tzM9T-)fXlj^AbY8=IiA^aE z*NfC3I`Os?4;X3WxB8;j_QLR4d%f2i!^Bs%JWNYUb~$jVRI%94<pf4WAkpnY2hA8` zjO+O%GDbWksjiEGm!eA0YWD{ig&#~xksJ|is!t`!1SjSrkmHntqYX$$ln-M(vRvXE z8qtRxcg!=V<=k@oE^Cc6taLp+CoCXi-u5~HdtuME(QY6-lIRd)JJE%8hffwDlJEz* zBkwB9Bq)^;Hb1A8u_`I`#JZBL+r92!o8SzZN8o{d`SwW8V}#4e6}4!d`jY)h0R3_b zs9C4?p{l+VY=8@ccE&;3j7j(L-Km5B5$2ukmCbbc{Cr;n9ltJ5em3xY!qXFIw}iLx zAe)v$Za&nPu{GX>7ah@s@bS`hvCm<5c_;EN!wCBV8xCjwmd{gb(lnteF4-@^4j`2_ z-DZ0&+g|`$VS{s8a%Ul%sh7M>C~c1d7p#Smn^&{-!+l9>Bd5m42yzS>A`X!R7oeNJ z4d8QuS5oJcstc58=Yl+8IQ7JO{azSd$Z4f8!YWDR^;1R$FZYO_#>a)2l6X`?xI8$$ z^{_>{FZgFt1?F4QfuTX9OO$C!A9{$=Wz7e7pXIfEXp{Nr;hQ7RPEL<`bHW5Ao%<sl zoovqe$$8+J7kK<Wi;$1^L3r%Gi;z=Gx9$*j=61)nJXIfcOYd`_;2V$!DIdu9f1vWo z=CqDHQ8`~6b)E>`iujpNpVSnF@dxAnHr!JaA02nk<1c&$MdrBrGF)!ty7Ee{b`g%N z)v{N?wZYdWUzg~b9A(2t4m*#QUSW0Q5?p7Al9Z(iwvv=s>qsn;I8rZdRui+um#tP} zwOTmy1Jt#WdaHF4mIS@fYKbz&mgvx2li60w37|+bw1uduP?bT-tuS%<z9MGv#l;7& zEN=(Va(ns9&=bRDaih1@-Ey38`BJYfP2A-#_|cCI)|aoqCw0|{wwBk)pTs;bdOOR~ z9!<aClSr)byl$YEkb1O~x>i@`Q~`e(&6T}FE24zE>+RzxvkzU<(--j<zJnrGW2L3U z8cH=Tq10j>r5+n7jkt`m6jxA|V-sa1uA(&K8I;wyfzpbVPA#s-wb*jix9Qz_gxXHM z)7T^0v+*p-xp)rcd_0eGAznavEIx*EF<wM@+*MGXa24#Ow$jvjt$9^>J)0+!YVI;i z4BC%mX2R5mPgHt$l4|Z=NUX6zn>6HgW<w`tX455RW_u+w6Y617mI_+Bq;k;{z3T;X zyQ@J<!a|r-36)r+CbRjagt?@aLIbf|QU?aYLn-+tSt#D6&FiwcR5_Az8!n5NE;WxQ z23&L-;utneke64SpyDJIw4>q_6{o2<L&ZZVl6g72f&qs9`AA5%PiE3Pc{0Sq^yVW} zJW9o5R6LF%F*D>&8rjv<<Oui1EHCExtyaqq{0K(~ci~eg%9XNu_@AL_{LlPuqg1T5 z^x;EC9O{f}o80r+hd5fpA9M95aN(*W1DvhhF!q%LMa<z^zoE!$S3{ivPSaPeT!%Yd zhnCwciF0@@(Xk{+dD{=<x3k0FK0JW%edK3aPOvV0!7bqgo8GVEZ9a*HdP+6$Z}{;e z248$5DZyp!ueWL3*@xyq^Wu5Drqb!8F}vywO?)oGY3gW^zNd-P5l&}E+f#8>>Xi3! zK0DfhI?@6USEj2CRPj_)?O6M@sJdT2!0GCk2iizS>zP=0b=P=XL+h24CTM`_XNd}) zz8E#!(w_PYYTA1lz5gt?oaNqM=iX=0`|Ek{v)ucWpn%W?dhbp3K6ga#vnfs4`w;KW zqIUzmSGadzQfI!ia9Y_vcA)Gp9w?pTRMO7otMWUHTpFX*2^#;kY|UuY?{n=e*PbN$ z*ANE5&YQ!(&BfrWp5ungeL=2fsSp;9<#JKqpdbwC!uhMbf$&d5UrXKoBnV%X&eObA z>iW;`Ng!PzA8r1G-g?0%@*DJgY{C~h;Oasz;?v-hl@HYO?^Afl>%u(@pYQM&uXce& zP*p|m7I>D`*1~+4iVTm?nN1Z<DCu^g5gfW%^n!c=nZ<9n!&?{FPGe^jwCI<|X5AIQ z+xWGl#NzAwAI&QToE($=K1b6$m6RY`JpqY;fCnj6ZBGzPBnGWQVvr*s(fV#u%{K>v zMD(^<NoPDvv|gAPH1ovh^!y+xZ+cPtwwss&4AjEfB-P71ZI7cN;t3F!2>LO)V*Q{3 zjUgCxyU-y9+euj(L{LXsSo);KUlLX`Ff!WMNk9^+tE{b1@8XL@a0-g%cnpOtd>4(v zizw=~6Hp5*brEGlHC0oq8+CkZcjvU?(=+9|CegQ^Vzlwy;p0a@*mO^Apj7@LEX(oh zmvMtL2lN_Xz!`dV3?L0O0y?P~`ryeE5i|`(v?n6HV`PX1t$<K~PPL?@0td}bb>E82 z{Tkz%0%TF~PCZsB#Q8R9GU+=m=^yEJ(-{7Be&AjT*|m4xhDX)0kJiGW%1+pD`O6yv z0b@|WZ*#%Lc5g|uuwV^38#sw}!F-Ga92zj=3di?;AVIDP8A&8?SP?&r#T1`G(VStS zENFAZlT>_;isz~LQ7WFJ;sq)`PX&n*afyn{R9r#P)L7VwSLneMC(ZNz7L|~HK&z0n z3d^d4ZOR%kRJm;ZFR@fvFW)Vz!%y6cQHq2nIE9pHQe0Wm1-PL7?WovENVr&q=BVyL z7HujcXq2ciE-7D~0rKnnrKsGg>_ZprRAb`+QcqQG&JU}E^c^dPbR3nwqQnR(8%k8$ z{j{pkKhz@VJu1DyHMbE{cTRwD^F4i)gaCsj+xgO|E7c?Enj%M278Uam=Axii{&q2> zng!<A`v4vi-pv7g?Fg%GA)rar*`+`gGRB5SV?u|VsT{-uxbP_8b<3OHkAYs1zSw6u zsG7e;%#_whtuK$c7DzYif>DbNo(f=&!~q#b{&v47pwY2Xo|GxF9=OwNM!F~Ks7duY zBHWjS=!s@os#kMzNn5O=vl?G3JdtD#5+zAlKA&dKnuH&o+kc>=kQ86D-p~w~Kc}Ea zHdI5ef6syfrhRYtv3s$lB;MBXa`vHIkShL|A^!pwu}08!8Vo2iCjeGpp-T$b2nq<; z@e89;q{T2u_q4CqN9DM@uR}Shd<8ii2AFS8SCzngS_z-L4Hl(;Z{QEAlM!os8s4w} zlr}O))wr@>f@xKC%kP4nN0pmTG1UsF&M?(-Tp=buMEBJq-J5fqMPWL3ifnxaSrWw7 z;6um`pi&@pi;J&6{T%R%*)i~LLs3WUR{8`bqsx#V7@aiMG4~MrqP=wH*(4yDgbX}@ zp`7hj=tV^~y_!d(b1Hc%#MqTKH3k_c%3mO+Ee45rwDLfVRVBxD`sBl7>s~t9=)HVU z@U+Qc<^gcTzqvMSPV|(I7}*ENG05xgci;%I3(W<|#R<qG;YbSpHT;ESY;6MczG{t- zr32BWo>bn2a{8YB4echWsQOU5`1-er$Or0kd<@>#5^d?JMD?c+g>{iU59HE(ZUHZZ z)X~Gr@Yy4{f6#}P>81NEXTNl@+k>7NK8K5pOrnaFq4CtxC%r_y-K-=fP8mo_Z0aNi z@?L_(pre@RL%*L?pgdEII4M!$hS#*@X>Uw!Yf{ZOBPp%)Hm*9!G4e6Dq8_-$5$&xO z4InW|*I{rl=t|y`a-1|Ko3l^H*$$`I<Jb|i#L-Ko*!%)1K~R1kzPn&7sCB)LEA36= ze}+#!*n&;KMrN@Ql!QYRRV7mPp^4CujkJB(S_kUaaO{6c*-$yf%ZzdO_aNcK$>1Th zK;l)bzN@@P_L~mdta3vaPe*0f+#?EQw;JnU4C_7AoxppLc94<#6}Lt`#LB+O77^LA zb>}Cr^<#!jbAk#fPFZ3EXZP6ayL@`#6Gzl*98Q*%ETzWh2>#{vme;-kc_dSlB!s4? zaLYmR$+`ytx9J5QW$d_+e~4C7ZV7=#r-x{&KaOd-<PayQ0mOg>1VZ*QjiewIS#-iV zk3%gxI~O+LaRxbo2)K7XpD5FyEH1<@sk3aB97HS}$^2xG$8iJ}Wp7VL;%$7cgEo7e z@*c2im{%4Y9IuufZ^82d^da8PhfL&F$ka<y5(=xCAz0q_e!w%<88U~|kyr=ofbx7~ zPg9t8Z90Zqgz)R%Cgx7mr9)^&&wq#*pQP~56Pi^<P~6^9ZYi(fz}?iyq4&PJ!Uq&u z=T8$I!|Qt6Fj`A=xYM)C4x{QtVxFD8c<!@wSjmpi-aMfUpFZMPA~c(2`4sRgdw*D3 zT3%XOW(XeEtd|k&bv8Zw>1T(HD!7s@FIxGt!)MM?I-O$&z2L&o6FphSJR5M32q8}n zZ9~0B!rXRfTSIMW2_9pELgWC(uIKex1xhNk!^nXU<m*bx;VxKrJ1O-A0=#hcY*E!J zsxtGgl5(18Qv1qP8I?{J4)3P~xE(Z;o~K%2`j63Ck-Daxuwdt%fDSaL!_HHotgGd_ z+W%NHrfz6Q>q6sIoNz<cK`vL${|X(%>QCt-xQ|9gM2b29Xip2_(Cw(3WMZlOROhD; z;i=9~btvy}D0fI#Iy)-E7%SgW#0BU{hN~U`BB5KA;}WzVdIFeqjnhhOoP_=a7%Y=K zd`~;6<hA9~%1MRQeH&EEhg*&+QKe(<L!&xS!&X$;x1{Ejj=>z2quPEQF73*J2JT$P z^BK1SXVq<fjyqX{HyiTJhzwP@#aUlFF7-9c!^Awk5u1g1n0RN7v^b{x3xMT$IMX${ z8=eM@g?%`?J8-*UhR_&KlhJC$R{9h(!&8*>^eaj*ml`eic<&7*g44Wnd`}Jk5&fPZ zGq`meeV&ZT8GovC8gy!LjT~Lh^`c0Sq4qRM({4k86J~~k^*nVakM(kP55o17WJExX zEHPi=YYt3-M`;w}TqmF*tD0kCQki6xjF5R7sUARknB9c>60vh?gxpf}r03!zBlpe@ zfG-*#qcJB+IE&0VdX^@PQ8bnH5K56G74JNyR%RJ2Y3>D$`-X??UnKE<B(pum@uPIj z6nKB|X-47oDFl82t4w*C>}`X@OJ#FPj|NOqdMYBEh0bA)PRy8=a-97`lc6W$X_E07 zA{7Q(j}$QUmYM?8Doyq|M2|;T*pd&_<!|4`XJ}Bm97AoQw!}{YI#!xzq<ew`5)Fba z5)c5(e%Fu0b$Y--jL*~6i&Rxc3Vs-ciMj3E@W4MI@N)}k*<Ao9(i5MNVU0Jb{U*0Z zN(RKI2<Zt&K(^?LeIIOqva{n3J!4ar&<tknIeaDB&Q4;sTYWh3&|{gfH0UK2>~{<M zEjrYu;s-5?6(tquu<Z1!<^d!*nHnj#8G^q-9Zh*s=7=!7#gxp>%GAq*)HHePSY5Y( z&#+Q8OEY1!E)rVbg<tOODR}3A<9Y)%4SX*G$s71r*EPKX&zy0W{B$PVFmzYGYk|@n z;ro%kx~UOJn}p2z>_Y)1S{st&;jaQJfaFk3M`a(DEU-k~*V6FAiAZO+KLP`I4n!Q0 z3#JTbzXI(M4jHJS)qtEeW!SW3SHGc!&DaPpPf&Rl7^!ZkK1q@4@2kJ2j;x>$<g#D^ z0Ttg;VtoUW08c59Q44=OHpCx+dL78Be*GFytvIG`T-%?C8nIcV$ZkOG7qw`%Gq(X5 z11ziur=$5;WfdGad&i6x;<B{mW0F<nMOf>j8KMUIRy;%R#3k{YZiSTZ_q0(XIu<Q< z77^ww#|_tfo194&LKVm2I$gmw*CuTKKPcMf5wN*)qH~gZ{OT7WMP|RIMyFycIt|C? z-$k?gXJYFucp5P8xnPlNj-lqCFoQF{gw=B48@OY}7MTrr_K<5Kcr%Ch9>(7z`1@Eq zcfb<W#k^gEXRVIr(e~pAe9gn`sJ*R^7SPh>XLH%J12wL^rCwBS{wel-eh+(aLw`pV zXQD@4%nRnnqwY-l-5^S*l|4wbL$&E#@a9<rfoCDjD(>t>C0K|abLZUoJBl3po{APf zf)?26aVzZp<DgwZXjp$sIVi!Xsl*E#WCJfapMVyaL(!{b(C|?zVi_A6+kMjGA|%(@ z=h6&?W~#+aL0?V{cneI7@GB1qfP}G>)>pu|2Q(N`C^=H=KAd4c9sp$1i#_}jrJbsn z3`q95%v(&tsX4YO5TUw-6=<#W&=H{PeEQ3aLZ&lGyQ^sC_mDRT_(_wiA#b6~QdEf7 z0uD*!;o<i~$mIzA&45-8(Pg9q!)lut-F3)=V!p>yY33sJlfos&0?@q2SP;|l<Zm_b zYm!u$vVy_UAvtRdGd!GJbQZsC$%lf?mARVt=;me0>Kyyu4^t~7UDD9;JD&Ak=zS>7 z*SL)z9g!cMQp<;TKl=<^m04Yw2L+t+S7|g@q;VvU+-=Clm9ZhP0;S=?jOcUZi}=I# z-6rc}pqiS+X)Y$wqR(Z@yd~u&RTjvu9=pDn1CILr2h77}Va-{(O)>Vwu)oZnB+?7- z$HC+Xa0(~Zc6(4H5e%E4ml@H}M%$!TZXi;&E1d@u>Kbt?GD&;4h*@(Aa1y0j?Fy?P zQqn=-<{!v5IAs-uBwk3`2YcVjBUr03d~ee0R*>OeMH3_kSmR?SE6G$9YbgF1)c>2P zE-J$xxrd3$V8vcWMwTNyZNn2d(-a$`b3v*?3UEy=DMiRI>LNsmGjz!GK5{B#dY?Wt zmE7>A+%8N>zXe^6m6d!h-@#nOZ(}Z~F1hpzG#KcH1Dz~Ut>NMi9Pt@GWf44V(DvV+ zP^!rTY>z!c>1I7^C1$3t9yuFQ<v7m7jsz2tAZ$#8DA3rIAa2nRHK|;3u#0x7uxUIY z^1`XunAC%CN*R9Uqi#>;NN9dSe4Kh9rV*c|;#DfHQNbBFkKhV9Ka&8IRFNSK-Ea^@ zGDYV%s6Ban6XPmHnhoTe_66x&i55s5lh&G5Tj5e;Qkvmnxan>uRS!l9`_!Z=OR?nf z3M3T=78neNq_WZNInk#-nUn{C4~R#Klh{PiNx)0thk=8LHPQrN^(2-PQIbH^dd3w$ zM;+--u$wGE`-L&kDwqk)V=_?qb?WlBsQ3mo*GMl;K{T=8h{<&6S^?@3^GbRmIj1O@ z*%ZA&AGybDcqD2+F=-VL@fP4T{2ENWOSF+VAX<J>d4)qfVNzLfR$9Khlhlid#9IzV z;4!^N1EZZ!79dP0d(Z3UXYO}M=_b#KX&Y)oU(l?QrIxiil<7sN-w1Z!wV-l0G>&H8 zHCW*`zSn?CP3{y;weFg__U6O?wRp_Z5J*Qm1MfVBYtTb&qeRXYJcDX(LYbG8Q47T! zPmJLc55#=!X{|huMg27RB!<TX=`3}Zf}9j5(BIQX<)GqH8c=>8sU0|+<1+NfN@S2< z#VtXTHRDRSg7CUV9tLQT6=>|2;k__j_(?|92nl^1t5aj`bQapF1ueUZaC%L?5!axt znQxQF<dZ=)Ham4VteKX4I`RIWrSDh5b?%`W*T`oB4ZMQ;891}kd-yvnN-Iid_Oo#v zbZfCe+BSl<d7r^&hL1*#{n;45L5^#fd7ayk2StU(KK1lR6||j0aw1dMAeVXr{*)Pn zg6DVtIQ6P<-Kg<~5~#No?stZKNvzjnmg&g8m5%IN+@f)KWH+x5A5X`G1S5>w7|qI& z#?XK#Mwixq=;;3Uo}-&f`zE`CcHw%|=qyk|8-9;H550aauDqj$CwaXW4%EQlmB!Tw zJ}6pcXx-1t+3?l8TxrZ$O?U7ZMK;lrbpOxARFC<heood0{_r99m>k8_92c+yX-zu2 zg&0;>y6$ya_jlCY&2(;a`KnVN6RQqOYCMMb(cj`d`%7y+q`z+-*&o)iu*)W;lF{$) zVP_ndnX-v>d8dDgb>bFW$Xo8lr;_Sx^fQlZUerodNBk~;WLV9_*fON0L4m2Earx34 z(%lTKrKHE9wafuY=)J9^TDV-{Xe+g7EYtP4YG&eAe3Jl8zkKQS;S7o~wc$M7PPA<v zpK_;&uhGlK)~EWr;&r|xk<RHMNnLvVS`5eHk5D@nD@h}*q)9=HCpv=v;tz>JNeY?r zEm%zL8;SWvZ<izc;!lYJ2}yWry3nd8WX4}o<=;?2f`j2YF=<^nuxHU#i#<Q0M-=Lt zqTk9^molWpOYV*!d`}Eiy@9NNu8XA>e^1odh4i;s<?G2JDhu}1RW_%lm4iP=`#LEH zZ{fl;kQ4<OPzPGeBq;;e=3VXXLTM2afNJNoGpdHa1-RC!CF<~ulBCcMZ#4=vC$u^J z4CKlJKh@sUAOqmK;d@HCTF@FAB+AsYx_+dLI4q7Q0*~_;KgkI8+&l{@N2xOSgNJ@! zg)gRrZ)7JNkk8=^y!Yi%g(Ly)7DiR*yjA$HpN!y>-Z$W>hTj_gXe8If7JJwiZz4?; zZJ!v`m=1!CxO*h0W8&`ksGh!Gj_Y_I=NZ9FHJ;grS6}+~Q-A$uZa#hU2ck-B0A+N9 zH{V6_R+T(H<m<<qjkxjk1t2da`BX-;aRdG!B$NW{+VHHDCp;^IqGyFYIu+N1M@QMO zQB)z#&ybYnqB=Y}@Qr}dTSzOdvM&Rk3=XIweHQ1xjPqX`emA!yR{cIKCKy*_DRGD@ zGo(n#rH8Ps&fzDoE^PDstq1cIz_H1x*V1UtUxv|UU&?-u%i+JV?MsH-;YcJ-AB}*b zwlZ=~)<a=9_cKYSa}@?)q_N!umoB3EVjT}xj#Sl29p;!H+fY!|$%X<yX|XzON2SIG zdwF3~=$Oxx?ePwsM*JyI)So#*SHe(QGC~m+LVbCvf;hmd!zPWGw+og>C_~W_%iIZr z@=>cfD-)K;L7W)3o$if7iX3@o1tEh(v<iqaQdL&{{uP8Pg->-ODt-k8oX6Xd@I2O{ zoAc7WY-YPG{*{{WE$21JU!0IL8GdeR#C~N%^m<WJ!#)2V8!;BKOYc>)C-}h!j4Y&| zU!~mBv>~&Rpu9Pm9>H}cEftNI(Ns>0?Yw_MyEJl0P14m|r-i?WDr4SIO??r{t4Tg* z6~Og>W`#Y^1b*LzXS#w^KT4Ybh&}whQzg2hw)coD7CLFFoT%J1*dmudNV(oz5CmO< za;`)TMN(<C++G`*WyA=8`SlJ~gMWD;mZ{OFsJKeSPf$T&RO$P_Lsx8H{T*Eqyo>Kp z!4n@BY#EZ#Ot=|7g~C*jBlgCES}y$Rz)-CZ%*U;Y`APGndB%Lq{6XzyHUUKaH9>DT z=dlA2j{JW!z*f<4B|i~Ah;N}lM(<!7f|tam_!%nxjh^E7NBB)-D6=(xkDl-^RU+7f qA)A8YeQNukR8UVxO&~EZ!n(n4lb!?K%M)1F$ml5kqwL;A{r>?eX<)Vh literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/pylink/__pycache__/pylink.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/pylink/__pycache__/pylink.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6b8b695cb653d82323fc0c075eca519e389c960e GIT binary patch literal 35238 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 literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/pylink/__pycache__/pylink.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/pylink/__pycache__/pylink.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..746c82eb52be2e437c61bd201433f9d38b8ab177 GIT binary patch literal 18646 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 literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/pylink/pylink.py b/examples/analytical-function/bayesvalidrox/pylink/pylink.py new file mode 100644 index 000000000..0ef7d48e2 --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/pylink/pylink.py @@ -0,0 +1,807 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Calls to the model and evaluations +""" + +from dataclasses import dataclass + +import os +import shutil +import h5py +import numpy as np +import time +import zipfile +import pandas as pd +import multiprocessing +from functools import partial +import tqdm + +#from multiprocessing import get_context +from multiprocess import get_context + + + +def within_range(out, minout, maxout): + """ + Checks if all the values in out lie between minout and maxout + + Parameters + ---------- + out : array or list + Data to check against range + minout : int + Lower bound of the range + maxout : int + Upper bound of the range + + Returns + ------- + inside : bool + True if all values in out are in the specified range + + """ + try: + out = np.array(out) + except: + raise AttributeError('The given values should be a 1D array, but are not') + if out.ndim != 1: + raise AttributeError('The given values should be a 1D array, but are not') + + if minout > maxout: + raise ValueError('The lower and upper bounds do not form a valid range, they might be switched') + + inside = False + if (out > minout).all() and (out < maxout).all(): + inside = True + return inside + + +class PyLinkForwardModel(object): + """ + A forward model binder + + This calss serves as a code wrapper. This wrapper allows the execution of + a third-party software/solver within the scope of BayesValidRox. + + Attributes + ---------- + link_type : str + The type of the wrapper. The default is `'pylink'`. This runs the + third-party software or an executable using a shell command with given + input files. + Second option is `'function'` which assumed that model can be run using + a function written separately in a Python script. + name : str + Name of the model. + py_file : str + Python file name without `.py` extension to be run for the `'function'` + wrapper. Note that the name of the python file and that of the function + must be simillar. This function must recieve the parameters in an array + of shape `(n_samples, n_params)` and returns a dictionary with the + x_values and output arrays for given output names. + func_args : dict + Additional arguments for the python file. The default is `{}`. + shell_command : str + Shell command to be executed for the `'pylink'` wrapper. + input_file : str or list + The input file to be passed to the `'pylink'` wrapper. + input_template : str or list + A template input file to be passed to the `'pylink'` wrapper. This file + must be a copy of `input_file` with `<Xi>` place holder for the input + parameters defined using `inputs` class, with i being the number of + parameter. The file name ending should include `.tpl` before the actual + extension of the input file, for example, `params.tpl.input`. + aux_file : str or list + The list of auxiliary files needed for the `'pylink'` wrapper. + exe_path : str + Execution path if you wish to run the model for the `'pylink'` wrapper + in another directory. The default is `None`, which corresponds to the + currecnt working directory. + output_file_names : list of str + List of the name of the model output text files for the `'pylink'` + wrapper. + output_names : list of str + List of the model outputs to be used for the analysis. + output_parser : str + Name of the model parser file (without `.py` extension) that recieves + the `output_file_names` and returns a 2d-array with the first row being + the x_values, e.g. x coordinates or time and the rest of raws pass the + simulation output for each model output defined in `output_names`. Note + that again here the name of the file and that of the function must be + the same. + multi_process: bool + Whether the model runs to be executed in parallel for the `'pylink'` + wrapper. The default is `True`. + n_cpus: int + The number of cpus to be used for the parallel model execution for the + `'pylink'` wrapper. The default is `None`, which corresponds to all + available cpus. + meas_file : str + The name of the measurement text-based file. This file must contain + x_values as the first column and one column for each model output. The + default is `None`. Only needed for the Bayesian Inference. + meas_file_valid : str + The name of the measurement text-based file for the validation. The + default is `None`. Only needed for the validation with Bayesian + Inference. + mc_ref_file : str + The name of the text file for the Monte-Carlo reference (mean and + standard deviation) values. It must contain `x_values` as the first + column, `mean` as the second column and `std` as the third. It can be + used to compare the estimated moments using meta-model in the post- + processing step. This is only available for one output. + obs_dict : dict + A dictionary containing the measurement text-based file. It must + contain `x_values` as the first item and one item for each model output + . The default is `{}`. Only needed for the Bayesian Inference. + obs_dict_valid : dict + A dictionary containing the validation measurement text-based file. It + must contain `x_values` as the first item and one item for each model + output. The default is `{}`. + mc_ref_dict : dict + A dictionary containing the Monte-Carlo reference (mean and standard + deviation) values. It must contain `x_values` as the first item and + `mean` as the second item and `std` as the third. The default is `{}`. + This is only available for one output. + """ + + # Nested class + @dataclass + class OutputData(object): + parser: str = "" + names: list = None + file_names: list = None + + def __init__(self, link_type='pylink', name=None, py_file=None, + func_args={}, shell_command='', input_file=None, + input_template=None, aux_file=None, exe_path='', + output_file_names=[], output_names=[], output_parser='', + multi_process=True, n_cpus=None, meas_file=None, + meas_file_valid=None, mc_ref_file=None, obs_dict={}, + obs_dict_valid={}, mc_ref_dict={}): + self.link_type = link_type + self.name = name + self.shell_command = shell_command + self.py_file = py_file + self.func_args = func_args + self.input_file = input_file + self.input_template = input_template + self.aux_file = aux_file + self.exe_path = exe_path + self.multi_process = multi_process + self.n_cpus = n_cpus + self.Output = self.OutputData( + parser=output_parser, + names=output_names, + file_names=output_file_names, + ) + self.n_outputs = len(self.Output.names) + self.meas_file = meas_file + self.meas_file_valid = meas_file_valid + self.mc_ref_file = mc_ref_file + self.observations = obs_dict + self.observations_valid = obs_dict_valid + self.mc_reference = mc_ref_dict + + # ------------------------------------------------------------------------- + def read_observation(self, case='calib'): + """ + Reads/prepare the observation/measurement data for + calibration. + + Parameters + ---------- + case : str + The type of observation to read in. Can be either 'calib', + 'valid' or 'mc_ref' + + Returns + ------- + DataFrame + A dataframe with the calibration data. + + """ + # TOOD: check that what is read in/transformed matches the expected form of data/reference + if case.lower() == 'calib': + if isinstance(self.observations, dict) and bool(self.observations): + self.observations = pd.DataFrame.from_dict(self.observations) + elif self.meas_file is not None: + file_path = os.path.join(os.getcwd(), self.meas_file) + self.observations = pd.read_csv(file_path, delimiter=',') + elif isinstance(self.observations, pd.DataFrame): + self.observations = self.observations + else: + raise Exception("Please provide the observation data as a " + "dictionary via observations attribute or pass" + " the csv-file path to MeasurementFile " + "attribute") + # Compute the number of observation + self.n_obs = self.observations[self.Output.names].notnull().sum().values.sum() + return self.observations + + elif case.lower() == 'valid': + if isinstance(self.observations_valid, dict) and \ + bool(self.observations_valid): + self.observations_valid = pd.DataFrame.from_dict(self.observations_valid) + elif self.meas_file_valid is not None: + file_path = os.path.join(os.getcwd(), self.meas_file_valid) + self.observations_valid = pd.read_csv(file_path, delimiter=',') + elif isinstance(self.observations_valid, pd.DataFrame): + self.observations_valid = self.observations_valid + else: + raise Exception("Please provide the observation data as a " + "dictionary via observations attribute or pass" + " the csv-file path to MeasurementFile " + "attribute") + # Compute the number of observation + self.n_obs_valid = self.observations_valid[self.Output.names].notnull().sum().values.sum() + return self.observations_valid + + elif case.lower() == 'mc_ref': + if self.mc_ref_file is None and \ + isinstance(self.mc_reference, pd.DataFrame): + return self.mc_reference + elif isinstance(self.mc_reference, dict) and bool(self.mc_reference): + self.mc_reference = pd.DataFrame.from_dict(self.mc_reference) + elif self.mc_ref_file is not None: + file_path = os.path.join(os.getcwd(), self.mc_ref_file) + self.mc_reference = pd.read_csv(file_path, delimiter=',') + else: + self.mc_reference = None + return self.mc_reference + + + # ------------------------------------------------------------------------- + def read_output(self): + """ + Reads the the parser output file and returns it as an + executable function. It is required when the models returns the + simulation outputs in csv files. + + Returns + ------- + Output : func + Output parser function. + + """ + output_func_name = self.Output.parser + + output_func = getattr(__import__(output_func_name), output_func_name) + + file_names = [] + for File in self.Output.file_names: + file_names.append(os.path.join(self.exe_path, File)) + try: + output = output_func(self.name, file_names) + except TypeError: + output = output_func(file_names) + return output + + # ------------------------------------------------------------------------- + def update_input_params(self, new_input_file, param_set): + """ + Finds this pattern with <X1> in the new_input_file and replace it with + the new value from the array param_sets. + + Parameters + ---------- + new_input_file : list + List of the input files with the adapted names. + param_set : array of shape (n_params) + Parameter set. + + Returns + ------- + None. + + """ + NofPa = param_set.shape[0] + text_to_search_list = [f'<X{i+1}>' for i in range(NofPa)] + + for filename in new_input_file: + # Read in the file + with open(filename, 'r') as file: + filedata = file.read() + + # Replace the target string + for text_to_search, params in zip(text_to_search_list, param_set): + filedata = filedata.replace(text_to_search, f'{params:0.4e}') + + # Write the file out again + with open(filename, 'w') as file: + file.write(filedata) + + # ------------------------------------------------------------------------- + def run_command(self, command, output_file_names): + """ + Runs the execution command given by the user to run the given model. + It checks if the output files have been generated. If yes, the jobe is + done and it extracts and returns the requested output(s). Otherwise, + it executes the command again. + + Parameters + ---------- + command : str + The shell command to be executed. + output_file_names : list + Name of the output file names. + + Returns + ------- + simulation_outputs : array of shape (n_obs, n_outputs) + Simulation outputs. + + """ + + # Check if simulation is finished + while True: + time.sleep(3) + files = os.listdir(".") + if all(elem in files for elem in output_file_names): + break + else: + # Run command + Process = os.system(f'./../{command}') + if Process != 0: + print('\nMessage 1:') + print(f'\tIf the value of \'{Process}\' is a non-zero value' + ', then compilation problems occur \n' % Process) + os.chdir("..") + + # Read the output + simulation_outputs = self.read_output() + + return simulation_outputs + + # ------------------------------------------------------------------------- + def run_forwardmodel(self, xx): + """ + This function creates subdirectory for the current run and copies the + necessary files to this directory and renames them. Next, it executes + the given command. + + Parameters + ---------- + xx : tuple + A tuple including parameter set, simulation number and key string. + + Returns + ------- + output : array of shape (n_outputs+1, n_obs) + An array passed by the output paraser containing the x_values as + the first row and the simulations results stored in the the rest of + the array. + + """ + c_points, run_no, key_str = xx + + # Handle if only one imput file is provided + if not isinstance(self.input_template, list): + self.input_template = [self.input_template] + if not isinstance(self.input_file, list): + self.input_file = [self.input_file] + + new_input_file = [] + # Loop over the InputTemplates: + for in_temp in self.input_template: + if '/' in in_temp: + in_temp = in_temp.split('/')[-1] + new_input_file.append(in_temp.split('.tpl')[0] + key_str + + f"_{run_no+1}" + in_temp.split('.tpl')[1]) + + # Create directories + newpath = self.name + key_str + f'_{run_no+1}' + if not os.path.exists(newpath): + os.makedirs(newpath) + + # Copy the necessary files to the directories + print(self.input_template) + for in_temp in self.input_template: + # Input file(s) of the model + shutil.copy2(in_temp, newpath) + # Auxiliary file + if self.aux_file is not None: + shutil.copy2(self.aux_file, newpath) # Auxiliary file + + # Rename the Inputfile and/or auxiliary file + os.chdir(newpath) + for input_tem, input_file in zip(self.input_template, new_input_file): + if '/' in input_tem: + input_tem = input_tem.split('/')[-1] + os.rename(input_tem, input_file) + + # Update the parametrs in Input file + self.update_input_params(new_input_file, c_points) + + # Update the user defined command and the execution path + try: + new_command = self.shell_command.replace(self.input_file[0], + new_input_file[0]) + new_command = new_command.replace(self.input_file[1], + new_input_file[1]) + except: + new_command = self.shell_command.replace(self.input_file[0], + new_input_file[0]) + # Set the exe path if not provided + if not bool(self.exe_path): + self.exe_path = os.getcwd() + + # Run the model + print(new_command) + output = self.run_command(new_command, self.Output.file_names) + + return output + + # ------------------------------------------------------------------------- + def run_model_parallel(self, c_points, prevRun_No=0, key_str='', + mp=True, verbose=True): + """ + Runs model simulations. If mp is true (default), then the simulations + are started in parallel. + + Parameters + ---------- + c_points : array of shape (n_samples, n_params) + Collocation points (training set). + prevRun_No : int, optional + Previous run number, in case the sequential design is selected. + The default is `0`. + key_str : str, optional + A descriptive string for validation runs. The default is `''`. + mp : bool, optional + Multiprocessing. The default is `True`. + verbose: bool, optional + Verbosity. The default is `True`. + + Returns + ------- + all_outputs : dict + A dictionary with x values (time step or point id) and all outputs. + Each key contains an array of the shape `(n_samples, n_obs)`. + new_c_points : array + Updated collocation points (training set). If a simulation does not + executed successfully, the parameter set is removed. + + """ + + # Initilization + n_c_points = len(c_points) + all_outputs = {} + + # If the link type is UM-Bridge, then no parallel needs to be started from here + if self.link_type.lower() == 'umbridge': + import umbridge + if not hasattr(self, 'x_values'): + raise AttributeError('For model type `umbridge` the attribute `x_values` needs to be set for the model!') + # Init model + #model = umbridge.HTTPModel('http://localhost:4242', 'forward') + self.model = umbridge.HTTPModel(self.host, 'forward') # TODO: is this always forward? + Function = self.uMBridge_model + + # Extract the function + if self.link_type.lower() == 'function': + # Prepare the function + Function = getattr(__import__(self.py_file), self.py_file) + # --------------------------------------------------------------- + # -------------- Multiprocessing with Pool Class ---------------- + # --------------------------------------------------------------- + # Start a pool with the number of CPUs + if self.n_cpus is None: + n_cpus = multiprocessing.cpu_count() + else: + n_cpus = self.n_cpus + + # Run forward model + if n_c_points == 1 or not mp: + if n_c_points== 1: + if self.link_type.lower() == 'function' or self.link_type.lower() == 'umbridge': + group_results = Function(c_points, **self.func_args) + else: + group_results = self.run_forwardmodel( + (c_points[0], prevRun_No, key_str) + ) + else: + for i in range(c_points.shape[0]): + if i == 0: + if self.link_type.lower() == 'function' or self.link_type.lower() == 'umbridge': + group_results = Function(np.array([c_points[0]]), **self.func_args) + else: + group_results = self.run_forwardmodel( + (c_points[0], prevRun_No, key_str) + ) + for key in group_results: + if key != 'x_values': + group_results[key] = [group_results[key]] + else: + if self.link_type.lower() == 'function' or self.link_type.lower() == 'umbridge': + res = Function(np.array([c_points[i]]), **self.func_args) + else: + res = self.run_forwardmodel( + (c_points[i], prevRun_No, key_str) + ) + for key in res: + if key != 'x_values': + group_results[key].append(res[key]) + + for key in group_results: + if key != 'x_values': + group_results[key]= np.array(group_results[key]) + + elif self.multi_process or mp: + with get_context('spawn').Pool(n_cpus) as p: + #with multiprocessing.Pool(n_cpus) as p: + + if self.link_type.lower() == 'function' or self.link_type.lower() == 'umbridge': + imap_var = p.imap(partial(Function, **self.func_args), + c_points[:, np.newaxis]) + else: + args = zip(c_points, + [prevRun_No+i for i in range(n_c_points)], + [key_str]*n_c_points) + imap_var = p.imap(self.run_forwardmodel, args) + + if verbose: + desc = f'Running forward model {key_str}' + group_results = list(tqdm.tqdm(imap_var, total=n_c_points, + desc=desc)) + else: + group_results = list(imap_var) + + # Check for NaN + for var_i, var in enumerate(self.Output.names): + # If results are given as one dictionary + if isinstance(group_results, dict): + Outputs = np.asarray(group_results[var]) + # If results are given as list of dictionaries + elif isinstance(group_results, list): + cnt = 0 + for item in group_results: + #print(var, c_points[cnt],item[var]) + cnt+=1 + Outputs = np.asarray([item[var] for item in group_results], + dtype=np.float64) + NaN_idx = np.unique(np.argwhere(np.isnan(Outputs))[:, 0]) + new_c_points = np.delete(c_points, NaN_idx, axis=0) + all_outputs[var] = np.atleast_2d( + np.delete(Outputs, NaN_idx, axis=0) + ) + + # Print the collocation points whose simulations crashed + if len(NaN_idx) != 0: + print('\n') + print('*'*20) + print("\nThe following parameter sets have been removed:\n", + c_points[NaN_idx]) + print("\n") + print('*'*20) + + # Save time steps or x-values + if isinstance(group_results, dict): + all_outputs["x_values"] = group_results["x_values"] + elif any(isinstance(i, dict) for i in group_results): + all_outputs["x_values"] = group_results[0]["x_values"] + + # Store simulations in a hdf5 file + self._store_simulations( + c_points, all_outputs, NaN_idx, key_str, prevRun_No + ) + + return all_outputs, new_c_points + + def uMBridge_model(self, params): + """ + Function that calls a UMBridge model and transforms its output into the + shape expected for the surrogate. + + Parameters + ---------- + params : 2d np.array, shape (#samples, #params) + The parameter values for which the model is run. + + Returns + ------- + dict + The transformed model outputs. + + """ + # Run the model + #out = np.array(model(np.ndarray.tolist(params), {'level':0})) + out = np.array(self.model(np.ndarray.tolist(params), self.modelparams)) + + # Sort into dict + out_dict = {} + cnt = 0 + for key in self.Output.names: + # # If needed resort into single-value outputs + # if self.output_type == 'single-valued': + # if out.shape[1]>1: # TODO: this doesn't fully seem correct?? + # for i in range(out[:,key]): # TODO: this doesn't fully seem correct?? + # new_key = key+str(i) + # if new_key not in self.Output.names: + # self.Output.names.append(new_key) + # if i == 0: + # self.Ouptut.names.remove(key) + # out_dict[new_key] = out[:,cnt,i] # TODO: not sure about this, need to test + # else: + # out_dict[key] = out[:,cnt] + # + # + # else: + out_dict[key] = out[:,cnt] + cnt += 1 + + + ## TODO: how to deal with the x-values? + #if self.output_type == 'single-valued': + # out_dict['x_values'] = [0] + #else: + # out_dict['x_values'] = np.arange(0,out[:,0].shape[0],1) + out_dict['x_values'] = self.x_values + + #return {'T1':out[:,0], 'T2':out[:,1], 'H1':out[:,2], 'H2':out[:,3], + # 'x_values':[0]} + return out_dict + + # ------------------------------------------------------------------------- + def _store_simulations(self, c_points, all_outputs, NaN_idx, key_str, + prevRun_No): + """ + + + Parameters + ---------- + c_points : TYPE + DESCRIPTION. + all_outputs : TYPE + DESCRIPTION. + NaN_idx : TYPE + DESCRIPTION. + key_str : TYPE + DESCRIPTION. + prevRun_No : TYPE + DESCRIPTION. + + Returns + ------- + None. + + """ + + # Create hdf5 metadata + if key_str == '': + hdf5file = f'ExpDesign_{self.name}.hdf5' + else: + hdf5file = f'ValidSet_{self.name}.hdf5' + hdf5_exist = os.path.exists(hdf5file) + file = h5py.File(hdf5file, 'a') + + # ---------- Save time steps or x-values ---------- + if not hdf5_exist: + if type(all_outputs["x_values"]) is dict: + grp_x_values = file.create_group("x_values/") + for varIdx, var in enumerate(self.Output.names): + grp_x_values.create_dataset( + var, data=all_outputs["x_values"][var] + ) + else: + file.create_dataset("x_values", data=all_outputs["x_values"]) + + # ---------- Save outputs ---------- + for varIdx, var in enumerate(self.Output.names): + if not hdf5_exist: + grpY = file.create_group("EDY/"+var) + else: + grpY = file.get("EDY/"+var) + + if prevRun_No == 0 and key_str == '': + grpY.create_dataset(f'init_{key_str}', data=all_outputs[var]) + else: + try: + oldEDY = np.array(file[f'EDY/{var}/adaptive_{key_str}']) + del file[f'EDY/{var}/adaptive_{key_str}'] + data = np.vstack((oldEDY, all_outputs[var])) + except KeyError: + data = all_outputs[var] + grpY.create_dataset('adaptive_'+key_str, data=data) + + if prevRun_No == 0 and key_str == '': + grpY.create_dataset(f"New_init_{key_str}", + data=all_outputs[var]) + else: + try: + name = f'EDY/{var}/New_adaptive_{key_str}' + oldEDY = np.array(file[name]) + del file[f'EDY/{var}/New_adaptive_{key_str}'] + data = np.vstack((oldEDY, all_outputs[var])) + except KeyError: + data = all_outputs[var] + grpY.create_dataset(f'New_adaptive_{key_str}', data=data) + + # ---------- Save CollocationPoints ---------- + new_c_points = np.delete(c_points, NaN_idx, axis=0) + grpX = file.create_group("EDX") if not hdf5_exist else file.get("EDX") + if prevRun_No == 0 and key_str == '': + grpX.create_dataset("init_"+key_str, data=c_points) + if len(NaN_idx) != 0: + grpX.create_dataset("New_init_"+key_str, data=new_c_points) + + else: + try: + name = f'EDX/adaptive_{key_str}' + oldCollocationPoints = np.array(file[name]) + del file[f'EDX/adaptive_{key_str}'] + data = np.vstack((oldCollocationPoints, new_c_points)) + except KeyError: + data = new_c_points + grpX.create_dataset('adaptive_'+key_str, data=data) + + if len(NaN_idx) != 0: + try: + name = f'EDX/New_adaptive_{key_str}' + oldCollocationPoints = np.array(file[name]) + del file[f'EDX/New_adaptive_{key_str}'] + data = np.vstack((oldCollocationPoints, new_c_points)) + except KeyError: + data = new_c_points + grpX.create_dataset('New_adaptive_'+key_str, data=data) + + # Close h5py file + file.close() + + # ------------------------------------------------------------------------- + def zip_subdirs(self, dir_name, key): + """ + Zips all the files containing the key(word). + + Parameters + ---------- + dir_name : str + Directory name. + key : str + Keyword to search for. + + Returns + ------- + None. + + """ + # setup file paths variable + dir_list = [] + file_paths = [] + + # Read all directory, subdirectories and file lists + dir_path = os.getcwd() + + for root, directories, files in os.walk(dir_path): + for directory in directories: + # Create the full filepath by using os module. + if key in directory: + folderPath = os.path.join(dir_path, directory) + dir_list.append(folderPath) + + # Loop over the identified directories to store the file paths + for direct_name in dir_list: + for root, directories, files in os.walk(direct_name): + for filename in files: + # Create the full filepath by using os module. + filePath = os.path.join(root, filename) + file_paths.append('.'+filePath.split(dir_path)[1]) + + # writing files to a zipfile + if len(file_paths) != 0: + zip_file = zipfile.ZipFile(dir_name+'.zip', 'w') + with zip_file: + # writing each file one by one + for file in file_paths: + zip_file.write(file) + + file_paths = [path for path in os.listdir('.') if key in path] + + for path in file_paths: + shutil.rmtree(path) + + print("\n") + print(f'{dir_name}.zip has been created successfully!\n') + + return diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__init__.py b/examples/analytical-function/bayesvalidrox/surrogate_models/__init__.py new file mode 100644 index 000000000..70bfb20f5 --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/surrogate_models/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- + +from .surrogate_models import MetaModel + +__all__ = [ + "MetaModel" + ] diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/__init__.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8c10c82287a57ba1e3b4dd428962e57cdfbc5c58 GIT binary patch literal 258 zcmZ8bL23d)5S*DcQG-Gt;14|P#r}Xu4ncEKgy2OF&FBp7;_ObCo;C4Ferd0s{DPOH z*HcJAS5s6M)xO_<5{%Z%&>nbS8u1s3#VZdDn2a#ei9)WW6h`gkTAAcSq^+xDGnI9B zZlj)iV_j%+i!`a9sS3gGb+lMC2Hl;yji{YNJd5zamv_2tpeQ5kU_~|%goDpqrZvHv z-&KVzBf%_>@6{Hj&VMa+%wVfemX6xxCirjoUj>MHnMcIY=c(?DxxaFD()>z~Og*KN G&d)E$kVM1) literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/__init__.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4b73e63a3096fbc9afc41bae35a3fcc1d7851166 GIT binary patch literal 320 zcmZ8cy-EW?5Z<}foKXTPeFJli4<KTrpiOMVCM>KQcSw%x-X6Pql61aB9zlEpU&H!Z zE4zbqshkx9l9^$CzVCyXc^eFl8QIhN0~b`k(y+7aui2bZvu2uUFwDXPfaz=olT7mm zRvdf-(FL^qF-A3Z8ja_K+!wqZhQ@n0QxT<2MEGUeTuNn(l<#blR&2xdg?J3;gYXMC zH*=+exN*;o#VQ7ITgJO)DyC|M;YFEJd$$z0RJJx4L@X_8tg+H0-V^O_7gCm08Kpe0 sSKFgYI;k;u<@<C)`XLmQIt~C`kHP4Zo&68O4u>7jPI|9-a-Wm>2c0-wy8r+H literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/__init__.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f1a3fcc2eed66172304cd27ab5fe111ca0198bf5 GIT binary patch literal 323 zcmZ9Hy-EW?5XX1#B7R`N%6GV813_#=M2L;Wi693O7M4wRE-u;KJN6?aw!VkGuV9<E zxYo*7u+h2Lhy(K*hX2g)A2}Qz5sa7jtx{M&`sQzB*j!_VQ-mUl8e-{`Qlhd2on|V3 zAjRO5qFB)Gu!JbfMuGAD-d&M*Cn0&?EMx>>dm-$UZeIv#j1X_c@8RSQU$2u3UIp-h zdssGOu98jbUoxv5cxm*rjJk2G1{sqFc00LeH&t0Zo{i4=ENP?I+{z_z*|vu3dCLL8 zY|U%!r121viD5N<68)4<j?d%<!U``d->mt6w_FJAbQEILZn}d@d?6XQ%F%KdAdd6w F`v>INVKD#z literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/adaptPlot.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/adaptPlot.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2854217e56fecb2456011a91a984951fed9cbcbb GIT binary patch literal 4921 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 literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/apoly_construction.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/apoly_construction.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ffab8b4f67e52a3128aa8740301f958a0d72c502 GIT binary patch literal 2815 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 C4-2yZ literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/apoly_construction.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/apoly_construction.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..331e387822163df3108bcfc6ee48301f71d7b4c3 GIT binary patch literal 5201 zcma)9S!^4}8J^`Oo{~u2wo|VX*w#VOk`Kj_1zVCSU-7NPIjY1RahK#;<SxCtluU(0 zg&;*J!v$7`4AX@JFsPf#O$($z9uy!2925xp$SwGwZXv)x;RnAdFbWuX>OV{ISjjFj z5{Gkq^WXnJ!#{dFP6X}u!+&SLX+-EhWKwRX&B60#7~De)VyGDUfMQIaq7O_AHHo^- z&j{o~sEi~tH+;<Sd9KtU^cnihdk-z5>tsi73^hY`k=P*X-<zwZFDZn+f={V^LZvB& znukfoBwNd?2q+nGx4bfNDYxsE@@OkAV_rmQ^Sle8TPTaN-mr-=e`=RuUT%yfZJGy8 zjD>JDatWd@VeP9j6lE+1uD0?9V>O=3SPi&}q-n4o;Zpt%Z_z$utCg&bGSUtr#q{C7 zGSn+LY+A2u#cdqw{{J~6uZ+P`Wtv7z5Pc|Q90s{JW!Q%EXPjwAnwrtgCVJBrm^q0( zI?9Gb={m9&HjTi_?G7ES$C&6zJK<z$T*pubTpyWLX~^CRIV3k#$3~P<I^&GQ3qk8r zBz~4|4H-v`wBTo+Vr*&qCXGf1k}J`I&~-ich-CSiNHj=l{}Ocls*+zB7eD$2qFzOX z<leTHt}|+taT|Q^DIZ9?)AsB2<=Ixg?<3xP)BHY~BbjO2^gxS&QbYM{+M0H4Id9cZ zl`{VviJ(mi7RDB#G9JFwK&hH3fZP_l9s?GtR;dA3&o-<v11k|hB;1Z=>T2Ue-czQG z4Dn;&UbSA`R-KJjuce%}8~5fR4vZ_tnO>LdGkSFse<AOy%EdU0NQjKuUFX(a#+IqC zjpIeH5dm5J%Zvk14YjCOX8cg5u_hYY(+yzP#%cya&8^ADbmP1oA)?DXSS{0Vo7VAE zx-o3}*=L5+_2~wv(Lia@OY&2vReyWR;1zOV=`CGv)X%8>EA{F%=;bwPm9E$8f-S8} zzFDClzKwdk1m#yuxBso*Lq2j3)mpgrj!WB&G8<>$p`9R|jd3xq-<Y=WG;i9N)U6tX zF5|AW4Q^~Vu7fag($G!_yd;askjx1@ErjVHmT?~=a<eQ?Ulir2zzbp=$LLE!EX50P z4u<1c;w1g>SP}r@FdY;FeP{ScfR5s6E*79CSuw(<=!-GTq@?H!$Lr`Io4}$RXL*@0 znv{i56iYG}q9?g{GKO^tFwfAFILyi^`U)$tSPVt!uprW>Q;aA`DM@DICDvy^Y)($f ztiF9-VAxoU<0Co{Cu2aBkec9UIZ@yVPY`^v=KMQ6s3=ODj9D3ENy>5rg!9vv!Z;je z`8gZ|BLKa_*iXONe|T`H3euIC=!;`6HoU27psMO9Hzx&>Jl7|ci3S)}KN6MY#PI(8 zb8~Y6!1TqWgD=Ou9cAfIQWS}yq>#uZWSW!cX)Lh}4NhX%FvoLce_?T&lSM41=tR{+ zU|6AKCiZ3m^AhoG7ru0&+fUC$IWQ^EONd}!UIv;RPs_kEEW~2M9ML(B`DBUlur7F2 zIX^ua&<*=;fW9Ei;hBITV3K@@6=lrv;JzD4%*$Mu3zZz3lz_5MjqrN4)O1DS07O8H zBLT$$xd}eP@hq$RWbdXYb#kR>@zWDAiJj$G(NA9u&;$L0;K~3^54<_lH!#%irw{ZG z90=$Kf)~#W10XQaKQOredH~EI1@zti!-4*O0O_bpSj2Hwh7i%GeU(<C0a-#1gBl`E z=?f&4uHZSEfsGOyhK-0U3m~vY1#%wWgjkQ)`l^K6<a&jblOk_msh_RMzO7vKXc5>j zSegTWN+h?4i6I1MvB+V_5TPcIt5G6t@_a_#+w&bH@o6b4Bx4Lc4IZKgf+hVzmG?N{ zpyDF(ih9mKch__eMNk@j=!X|*4eEMjY*?+lUlvVi%J?!cR<}j{jlN{M-8YFI!S4&r z#3wYfl#FZEgfPd7-4@Lh=+~%(W+75*c3#5qL<}5BE=QVPSokS^VtDEu3A{HY&Ir+1 z6k};BD1?%v5=c|0IQevPdg>&^`z0(#r=~f6Dv`Ptf+{jKjZ>^Ni(?!VoSRb;<e?A& zBVLP>5+hAvVn9Gvt7agP`pG#G<0LsG#1qHn_r3%&5)(o=CLIe@ar;43=@4`;7Er-= zzVyG^dH2Bb;ODPD=*k~j@v1v|i#vMNCV#QXzw(~ibhv_h4(HG_V$g1rNWMg(xjuSE zJQINrv?s^s_d6kSkI`eY44Ok77>0@;Pb6hME1@P%fPNw^3j!VGB2l_?zPEJXk|<2a z*f@dnP$(lTq&5kybC88tq$h<KtX}AD(JVZ}#kG21Aac`Ck9C5YImYrLdBACwIE#7B zDq=puYF0L$kW-p<o`q_zndA7TX2#Q!W`o*|V-d|N5xSZs!SS=2nGs}-dRw#MM1tiR z%@&np9GcN=v--D4Vi6(&N`kCeq#L5#?Gwq{SF@FJN;5Hx<~$GVFNXCvafx^i{HVu( z<|R3Gf+Wth3j%)uZaK|aO*74OKCYRrhBS)PsOvCFXf}}P8mwA~@S5$?HF7g*7IH?T zW<>G^l;BE7zaq7uwvCG9J+1k+$Avfu8|0^ebO!wQ0wQ5!7}?#Qrj&tCG7FjY`dx+B zj;QrR#rmOweQ3jmoQ+E7;*N#!^#-4EXfbs=wQ%~sHsotwZp$?<y|(<?!r3)fgW_B~ zz7Pa-(*>#$F);XB^6}-z;`eX=qx1W#-)6qcz>?}aU-X?{cngSh?0jI)x2o-3#rCd( zrDfgQwA`LMki+*6<$d|FFPd|H)w{3g-M4V|sjn?($_?DNEcGt;ZlF=hdXD<B^p&-( zdm3)Pr_AQ?(#?G93iU;Mp|wZ#^cFq6SyRoP>gg<cI<qDseOn2>w0n8?268z3dY2tr zZ`qL>%y-^DvUF|v+6J<EI`vMW)|y*#wmWB)vunG1Rt8osKRQ_4y<ZtuZsa-@dFixr z`bleBZt%{GGP6RhT>X=4#kIDZuI|48%e1s9H<l+pKk)~1emsBU;lvlthtB&KA6!(M zd$Z%&8;cX!iEWZmL^9~IV{08da^c_Y%<WXhl(Ci0@`(+b#j%&zt>fPAJG;SZS5$9T z(c1<4<1aQ$CfICgTYmrEM|VETkE<>FiY@!HCkehaXUm%&T2$|zqIVBL1OCN}CoZpY z`PR|w(RKRuhmJze(bX#|JzAtk3+~q{dut6XIq$8HvmdXucPNr#Q7li}I+ls)y?K|~ z<}bGS6-$Xg@5m}s=sBU%!6F?58c%hyusU7n8B^);B0a8CuK%rc_uyUW^8*hC^RMTp z?;m?`Ol|8aw)OmF@@wCtcmMpZ+I9$PQL*W;+Avsb7*t(@t4;rOjTBrX>uzts7gXI7 zMfXI(J)uuWRrgrYJyvj!ZMc!I2_nSXs@yC&+wSPzK+u6no0_x1EgrXcPE#9*^x*TR zj@;!tN0p;%&FzI<eJi-QtN-iZs`r~ytC#<JR^4@6Z9c99mEe=ocKB<&!WDNNSq(n+ zes}8e<!=FUN^L%+L)<=v$&D>V@^-bgOLcc;Pi9X(1vj+iT8UU$+f$HGkKmG&7RNav z2lOCk#ok>*tDVKJk=3he*9pZ5kvfnYQXBUa8uvVbt-X&sSG$W{!N;)umT~(>hfc5_ zSsmH4s-<-yxbE@YJ*dnt9bZ1Kdfq5{-heo>jsj28XQ{QFd-9n4flry@&fb;z)v-sv zR(BrHI+X$a4=aaMdwap&{>0S+xhs(>_=AH!*<<>l=jf?@R=7f~d@`O$=_OgOIwC1M zBKg^@SErxsBXGebW9%{U2&|C{TpECG!%R^WBn;J5K)%xdhHaLjS~t+kd!6L}02RCr AvH$=8 literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/apoly_construction.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/apoly_construction.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..82737a42dd7351d06b703b3da838031ba95979da GIT binary patch literal 2886 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 UGiz{V6;d({`I`N<wKeJd7wkkSHUIzs literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/bayes_linear.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/bayes_linear.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..92d0cc0e7a0a07123fdfbc2c777d1b9281a43344 GIT binary patch literal 14412 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 literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/bayes_linear.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/bayes_linear.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..15917cec53bee82813d19f9029552d6ccba086cf GIT binary patch literal 21679 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 aVS!C3*>=l@S*%V;7Wn8FYeXPj{Qm)<CTwE> literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/bayes_linear.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/bayes_linear.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..063355b16a397fb5fd89d38daa0d3ca5a8506766 GIT binary patch literal 14506 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 B<oN&q literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/engine.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/engine.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..129cf9a600a5d44a75d32f91f8b5a3691faff286 GIT binary patch literal 85430 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®C;;p)So-&<f!ufvcz<s-fKwU1W(}y&>dLTZ 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 QfA}H0{=>)IWnKNh0p>%3V*mgE literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/eval_rec_rule.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/eval_rec_rule.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cbfe4d97e8e83ebc276e45ba6e84f514784f1d0b GIT binary patch literal 5560 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 Z-$TZ+G!?TsR$7>|U8i)t^vVlo{{y+urp*8V literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/eval_rec_rule.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/eval_rec_rule.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1d789b4515f89e02f006dafd2c9d85b8e7bea110 GIT binary patch literal 8182 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 literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/eval_rec_rule.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/eval_rec_rule.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..27878248cbdaa2abf0af9d51d061aa6e2db86f43 GIT binary patch literal 5648 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 Qn=09pu6MokM(NCd0M{nQGXMYp literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/exp_designs.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/exp_designs.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fc01f0f01b8bc70d438a3317b87d304883456f15 GIT binary patch literal 17477 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т#dTfa#8J56>f8$ut6T)8sKb87ka10Av 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 WxdKn&n8;-&>4E+sNkEpU=>G#}NHw+q literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/exp_designs.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/exp_designs.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e6dfce1df1a397fca74f54ccdfe90908cfd615f1 GIT binary patch literal 19243 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 T+io8&wfuoS`RXOlS=;{~1k$cv literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/exp_designs.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/exp_designs.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e7e0226dc1e28c09b9cd09a610599007b2267e3c GIT binary patch literal 17597 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 C=1mCz literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/exp_designs_.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/exp_designs_.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..076580dd7fa9e11559ef202903d44e00e25b8a26 GIT binary patch literal 20552 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 literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/exploration.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/exploration.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..af7431ce432969f095d1c07f429b8129cb5a2def GIT binary patch literal 8154 zcmdT}&yU;4mF90zYDumBVRzdznGo4YY$0lOw>{%zoyjC#x9#yHZVzH78+0<^P$XNT zOp)p$Wp_8IJ*+24c7Z+Yc@dy}oMR9mm;ER9OkjZkIRyR(a_}LY?-fN#YPT`TZI=Q| z#bVW~SFh^5@4d&cR;viOe)sCC`{a%w{E;4JFBuQt#~pnGg(EnkFYJl<mwag;@5!QY zPjF;M`CM?6=hB|yh>wJ(`VxJG-KLo8ju*vNV7oT8%w7fEAEMReH1{M&+>^_av&<=q zpr$(7=fa-qlpG!ZnzQ0moQ2QDy^>RPYG~2R_41;#>NK1sw3eMRX1|aw+&LWjA+usH z3@iaNRSaCWnQO(aV|1(tWf&N7&ov&67z?{-Hy(tJ>w7`hcpQd)Cp<K+KKk*4hfU*W z+n=^8oB(RZy^wiP<OVHcr`<Acha>yR=qPR(_wlsj4qP{iUDh%_p~s%(25!rE+%~Mh z!Svyv<Jt!;;|J{)r$<a(+uGi08@G(8;A4>UL4z#E8phsJ*NCjakaHJLxZ4kzVTXg^ z2=f)xvZXn0<aL9#@o_j}f#n<FzA>=uo)@@=?^-ONMKU)+)$X-7Zd-#6^PDa?ePBh= z3~$@pEn_%rU)y?rdjrM$ZE!gVzfVQm3u4!9kGgIUw>z$}Vf5m7cyn{}oR^vKZpAV4 zI^Z_q+-?*Xe|+G^7T*BlrV)1f#e$~oXm#zl&EEv34dHkWZQD%)tQ7rsN02e26;FF` z(YaAJbYPn{^B^-E4UCQAsqh}TK4zeH^l-B-ZR0TxiR12DBR@90$oTBaz}}$6vj|i+ zhAixF#Jww@VGn~42Wm<##KwWv`C~AE^Ze|M{4=aD92mn8lSNn~Kdor7P^G<hv7_0k zaA~=ix)4Il(1|uVawh_NwR#@cwlbrTRF`ny#vOePMIt7GDRc#tVj`iG5*elJP`ly? z&@^fHrGuVLH7yq#g{sB69?o5qF3fCHTAdYrDn4r}sS>&VKGQ&g=~R?ad?BzZ{$BlJ za}dOv_U4Zxh<cMf344CevZBqM&>jtN>Y~kiUi{Ihvw7DKpM7G*z0Hnw<VH^|-*Z@a zh=Vv$Y?CWgwCPT5LVI|W>ZS=H#isdH%odRi)Fe%$Uqw7#oiQNoyrV6mQ+}zakjS{W zet}9N^o6mQh<&jyjinf3dM=6r{-s3vFPO;R$dhN@o=A@JL}Fi0gcIe3@N;P_j}?el z*_R%H(usPut*Kf+$MnS(KkngN?T>=&yh00ISUWeGp8Cj$Lj#Hl3FA=1-dT|mxX*Bu z$u^KdDrn*8cnt5O(Dt~2oRO3f*&$5D!~l}P`jH#Ms$@z`&l5c^s9C;0)y@dV+hWW* zq9Yphtf6aMojDUNBQS>+vj$PK7*8~B89rcxk0G;{>n^>T;myo=o6HcMKgB%ZnQbjr zMpWra#mceD)&01=f#ci@9a7#|0YXx<3>X96tDTm960$G|y{5(wb6UncJ6zCdJ!9B4 zv%aZ1WKigIx$DN}(~x11Ik8V^o!X!zljo+&7I3aI^;kwNt<TFgU4C5{Tz9gfMnl$! z=3KW-pjYrRT1BB%by1fZxOJ&2>1y>ax^(;x;6KOD_8Tb7X~ShuD&gkZa1mx?q76b{ z9K&?<rM}!(#&RO}RY$xe;H(QL8rn;V{6fO%SI1hcpOm31(0~`>xYQNKdR&PY67@Os zWk>k*f5v6>uO?-Tt|S%Ekx*Mm790tB^if=MGX1JSi_nL3EzwWvN%;k82Ui_wT*Y0( zEQ`qkW~djn#ki6z@HyTeH_+Mug%amt2{SGwOGzbZT!MS!sQ)34m(gQ6Sq6obWF@I5 zjSmF;SD&ctUy_w^HECdum6O$cR9AGg7xH+Ok6L{pCW|!UU@sA!68QeDqhkf)8r-Tx zc}rNq|GKa$j4$Nvs9#JjBz63+C2PsWWN}sa7V5zkD3n3re;s|i?o^WXRUuh;OBi2@ zFJO*KPapx7#(MuExaZH{L~<6ef(mb~pJ`nSN=Y4bm3YmmJ{SL01jp;i+6&RC;aC5q z3<=Z{>6avRl42t%fpYDVknPvORXhvkB~DvS^lUD)T!suU;l50kt+{C3{adWqL<6Rt z8Z?FU%dlPFkGMC*jaFeaV5DHBh9R5+f<11tGPi>?`^!ug>|(BT|Bvj|OM)Xt#qr)_ z7^eNu2NLr2a~(H&F!>$V4UFiCHyo1V>)O^Ra>-X<uJMeDAe=(R#G8P8SvZ34>Ba4K z`|%fIT5>`&I$&{HwtH^pDC)USUoE}nQ2Ys;;QGV&7~$ee@+B}<u@1fH)fO@M;P%Gt z!u2`|NAN)pM&vJZI}7j0u%23;Z*_dPz5DVMSMx3I5@gN+cN3OCH5GrFsvJzx6>A6& z?9dwkx5%8*Az_5&sT2%T)g27uqf~_})pb+ZcZ0NU`(cDR&CIW2E7Vs56*q8F_1I-$ zlxj~Ave-}3b+a?_e8;2^#>5QFJIscq^1uriEihGWdYj5taFl9@AK*5o<y~vw-hubQ z(h^*uD1_t|X3iK}!^r04%(|1y!`GMUA?CWXWBxQ%aEu3O%_S1WsxH!WjU0{g^O`Pn zET?!-y})q~(@Np{MrkcDXQoaY1MAQP_k2+lm!<U%iK7^iF4Nn>!R7t3Hga{jE0MK{ zeRhLbs=Ff_E|+U%G_$^E+UjS<UU=qu-5!8xerVo&ruR}D#+ILLL#EoPYWc&Sm8uS{ z<qYOAf;B|4LX@D;YH;YJim1q%sGrs~MQlhFxgzVbE>_Vl;f(^9uY#w#q{tOfJFQ5- zL`4ztldGa~+5k4Li&aq<>%d6`HMHW^PN}~n>VMHxNdl$Qw^gF0oodQ5=pDav7Dwk1 zf7hlnlwTK6p)<}g^aOeht0@3ICGJte_3o38C_3UuV9R(?#%iF#-^`Fu<^8m=mS|{! zwH}uyeOvVA1lG9^5A%gYJ}T_89+yuli3%K>*2=)!3~j#&Os<T9tw1zFT@5Ie;a?5o zYDtX{6zHcX72sc;<KG_e1HDhO-h_IKyze4VuT1?8zMCi<_5M8phrm4GEXO=~U2t?D zTw~Hs^`)ed&_A#iSX$<&w+z%%IO_c#sE1TQvI5jofqJVkkUm-EsQ0_L++V~R`E!AK zB5&2tv@Qen^zkxKuaTi1m(3F96inQT&|k(HRtWFEg6N3a;1Qseqgl<W!qgQY^d_Ht z63M*=YWMuGgXsK0h-lKdZ81MANM+9A4ALRge;wgkQ-GW%DG2Z=Q8AZpFn(ycY+waZ z%ea$eBc{oT7Udwe+s2*!eb4p~SruFmsc2}~?#907^W+1iB!V#5uz@w!Fv?;~81W$X zu#!n^ftVWRxa%PtL7+NM%^Qq-o|f6jQWbf!1JjRKID{3M&00JhQdmPt93LQ_B`oIX zf%onAu3m5QJjIP~U*EX#k2kWwns}#c=i&XEJU0;`IpKs}J7nEWq+GVQwr_0q+ipK( zNN`~NTkp5Gu3wuv4fiSVpg<Gwly3(@s!7Ua;$z&L<7T^QyoQQ%9j=|z0ojA;q_<c% z3vP>H^Jx-V(R>h)J1i|D%QsklF_bz#%G`Yl26N7V{uAzLdtOg)?1q7hbjE$kIC#@I zkEq$moV5x!;TaAEg_wEt2?yhdQYFYUL1dK0LfQiPDI}jJ34y;OjGO_je2M1=c>kwj z$X)J_u}d)Hj~N9;>}@K(Ld82&kZZ&!<G>6mzJ{W?nuU1e+AxaqW_+Hn)8o4+(nc=j z9PAl61dQT1wm}`rZh)ghn#VS&af^y;R9vUxJt_#Wx%ZK30gS<D(7cd&A)FR>u+A{> zEgJD{DsEBnPbgB+gCm&d-_klfiU(e>Gs*L^9qLE$%kENfkBX0|xKG8$RQ!MnO7ctt zRYvIdTij6xh4!|NJPbe>(5(Yvb(wNA%Bcq6t^mLR*?@BZH9(vLHJ$*|@|$5A;0;jL zC8D!R(0utUG*1I>TLugHMIkr|hT5V(qk#1n5Xk~lCy^}G5EcC!CCnzRz%3QAu5=<3 zq5*S(%0Lt)RuT0oz(c_-{Yuyu2~$7UV?9wQ{(MgDWjrC~Ma0_zf(!i$Qg2#PLiD9M zB}8vJXe=Z;@R#D@62-cXv_@Q^4lEY><t#=<zbYa$K9*v%><v)(J&tRoMCFK9Lcbb~ zCIsf3)j2J}T+IIaJSWvGTmKE0q_8cwkV2Ze-p17d2QiyKtZ6)@<S0^~$oV|5VmS0y zBBO}l!U1r|nXv?ai_OcibCT;R*dU|y(03>)gN!a&>nRLn`7gvfJojajC1-g$l@h2E zj^=3b_;QA~FN+*4d{QWKTyvD>1T+x_S>8ep6v<ves09L3#G1G5H;XhF&!NrR;@5Iy zlq2Rz;n^vsq^FiC)iRG{E`vj!D4lZ(h$6CFl=%I$JQic&1fP3;&Ex$4lnyA07dfq_ zlv$sv=-iZ2slCM>qWXoH*$b}UJO@?zfU<c6KOf$}8H#AC%fj*XSq+>yOnJo9{=g4y zWRX8aB_BUAs+4?fHZrrxO(eIS^daf2RaCivS(9FUlM1qp2>4i+0*5v|$S`23g7agi z8V|Xm=0au_c_3MuoIO5US`Kpio9f72^5lG~P5x!iIZVs>7q4g<Y-S|Vl_7JVnr9+V zE~m%D8VQSi1I0Q?sfCKRM4?MvuET0oWrQG#f@iXOtFVI<YE%)@Ec4Xe@mIe@o<N8^ z+`4O%1oMlwoo*g@(EPOJi5QdllDZ;{f(&O~O%%46s7OyEg}1`9|JK{s%Hq`DwtSnM zJGgyx(2Ee#$OS_700%tRK^)gyt@rV1ENh<8y-z4HOrK$<=e}@;Hi}tu66fWaC-2_m zAy7^NG52}KW2!cMYjY2zn3e3#t(nXT?=>Bi`HL7e`+14R<S3bEjthd53=4*I@O|$M z&fGuukZ*<&gJokp3txy9$!}&v2P2$zXWDqyw<~5NRzAB6-GZYxbw0n$*ya0pzQN0v zHv6rBdpb>pr%Kp1P8PQqh~DXw0FvcAzx^|`BP~v<lxmse*jv>1Gb*@x@PexcsqZ6F z5BgqoagAbk<g4GEJ^F9T+Q4j)_tg}4VYzJ7?lvp*6)3<dGtIPO(ubmvPxY#4LYDsI zP02K!&^Aq0#~`*&#VQr#vT%LP9Ih#+Q+CN~AWkE4uyjEYrM1ebuIukqe7!4uM-uC& zjQZdUnhN)Ac$5jK7TMnLsEyc*;;Kx1)NMu@#T=>rLB{uo5Q`9zBJ0RnEX#idPQR4o literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/exploration.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/exploration.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3ca9d281b7fd88a0951f52dac6bff569d402740d GIT binary patch literal 12450 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 b3RJIb{VP_*T{aMPclr%^|Lq=Mi7@{Sjc@{2 literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/exploration.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/exploration.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..98964152a4ea29f85f061ea6ec7daa3df7487230 GIT binary patch literal 8190 zcmdT}&yU;MbtWlNqBN4`r#)l)#Uav{*h*&P89UEO+=rLAGxn>Kc>GX1iQ$aF$06@X z)KH}6k{Ztps7?KXw2J^~H(eA3>`j2T3{Z5_uKH(iRUnJN>jGW8MJC_5{2^&P?n`%# z1YKQT-h1x3hv%H{oI|V8s7d%-S^BN>Pn(kTJGz+slyLC_{K9XbaU@6fq-Qez6;J7x zo|R<jW63Ew>SvOpzEqy6j{I0^X>TxB+HT2-?zmxO`8Km@Wb#wcy^m2QXg*UM`B}+X z5cFiw(wy>V(lgDeI6D5z&Z1LuW<HajRh+uhz=-ZFIdjfDMygH~`(8+9?i~%hfLoCp z_?Cn{Y6d==oLLcbj9n{48~8@lWya$n=RpVK#>2p2p6hpvCqdxt21myA$3J=asAc?o z<9WL#2%u+t9B?-bnZIgmwO5VJU}*0TkE2!N0j{=KpRq7veAW1bF1r@<*{boRZCJj8 z?SuX<vkz8{AGKEnJ!0zS`o?<OxNC$3AN`yUT4XuaAaW0x5nBC$;4aFz+Y7j12mQei z`xVsEqd6>eJAT{vVKC&r<r%@A(YNfb>odb+7We6poQ3Gx-S*n1)!*f=(*dUstuUP6 zZDV8A7!2As*FV@;L-Ro!T=s(>P}6q(h}rF7hxt)^ml<nDH;M*#ZrnKMW-7e9QN-O{ za2pD4*NTt0e8?h8JOJa45$yJg1C7Tq%Iv5u?)at+;kXVxwmSw`DdukvA!AM_9?uY> zV_~|qZ<{uEAv353)`rnoc#oNf9cUagSURO`Jb{upY|k2ck>Q5Mr`P)S8Xca8pt3gL zL2oVUUi%c!&<~(cV{!o=9B7@t1`7nwFW$*N#|eYJF$l0(h%*Xp#fXJ2J$r^Hnra23 z<6`SV2oc95ddMNm1op+!d0gA-geg*A!EY14@M~ydIhIVRBcYXJ1+5a7(3Tt;R~-qK zrfk1)Ftep4)#5>+Yw?Z?y$h3>i3gR`Cq<vgFIsA%hRoaJWsu-HHB~g9OT3Q1FJ5lm z+4)HbG4F7;A8hPA^4S)LCG2dma6bwLJB8(jJNLcd#lVWXW?@A;d&B{h9FHwL+~}Hp zYoGC<zq4x{v+&UJT!#loJH>ocSY5co#*U*sI8Joagd`)={3=)qg^N_ma{4`4n(#91 ze4;I5X8zI8A-M{fK1C;%deTUa<(}MAMoI)(zLaGN|4OX<Gd$?Ol(K6v9xINzukfu{ zdZoUWc9c<Rr22JSY55hNh`OhcueEltaiIZEx=_2lp`WTVjFiC{vT$q^p%DcJ>=q9I zIuCbfg@(^wK-0-}kiRNuL9<+r`(a?a!hcT4$O!EKLeBgn`Ln-a5u8qH<8+;wc|pzc zys`0y(0+?^>zFh+>{<h6T%S;xRl_$27PtCgt5{Do?;0NPM64mNn431;n&8b$dCPVP z&);I2@WcZxPDWJelgPCbO?ZQo_8PRk8#rX!lLCaKCK)jLVpcn;{50T!AGocu(DkH> zeW1k<bka;2W@b7!(FPp$o-A}&WF7__i_FY@B~2QG4Q1CYjn6=%QtMejFKJH8Hd%OE z7{avDra?=ViRRR_RG`;zGbEx?y)5gBF3%}wm1e1~ocsm2&%w3*j`dSka2aGO_z5ex z3LleMfz*>n@GCu~SL&&wQe5h3j(kZPsnGB;#w&5@wF0fzM&(F<RfUZ}*I&z{N=F*$ zQ7xK@wU@AyE$P?t^WTiBSW%CwSYL~4proKT6VEsbEa)GjhLc)W0~UihWM#4bsu@>b zqj&I$qm1hKHL%ZYJcB)&MQ=8$#WS?a^WJC<qjR885q!*J$N6|ZuEleg5cfFRuS%l@ z%vgvQKw&XnjGOV?hZ6ql`x^g4yf~`IbJ%0?)l$ByBRl2SrO}dDwe(t!XKBU3zs0gs z*;jro^F2q$8RTU|T(NpZTEzc~v?Pr#<m2dHj4#AZ{4dAL@x^#{N%{`@z5^OnLE}Fi zeYE1#;*}*Sp1C58E=3ox&!v4x0XzIhr1vi33}OWQD9#MdQ4^!hGo#DC8aF{(kCvVK zOZjhQ@Vyc*zm}Z_zRh2hAcsb*{DNdpvYd-6pxn45rO)l)6I@H?B|%$@^>i<cT!ths z;dfd1vRUi?pW@3hI~a#^uotp2!)BfrijYgVuEKS|Rl!#c0z?jkjly%Ku?gAtmpLwY z$K3S(jJ(zxf+J4N$+IVLPkVs}tQ6-LmTq+6_;(rejd0%`3@AEgwlxeH1r(eaFR1Z@ zF>qud2jt6xAp%r4YPZ`@K9`e<6PV!vkCLk0WxK~=mmPjF|5nuTdvJo!e|?`5F213F z18Y_5$PK?(Ck7vGu5A|a*>NyLpn5Q*pjvoagjj}kXt|!X>#_Fsn^SyRS47;9Mi3&F zm<QEFewt_kQj$e$fH3XI?E}5Ysgja#!tzA%2Z_e|gXlQX5N~x@Qt}v_vh4*S_B7Mr zi!ajLGN>@$NwgEjgD@!{BBQbQlNED!=z5Mx84iLB#JET4vZT~^eNG2VG@I@wCCfif z%1AO0TPD?QtIzHs_uxqd@lqH-ax)V;#+R|ObvgC%6c>r}C3=9p?roV*6BTOQPa2F! z6sNjK+s);el<R9UvuioUh35JWJ4$LrfE*?b-<;Swnd@6eCb$=eqO>h(?vgl)70CkK zEuvsCFCC+JSOgU5nB3#HiKQkR+6cLrmC{V-o*8SNS$p9Hb30wY)AZ7O_{{A2D2OaC zeGI8-Cz|CAx>lk&be1#7$Ctp?J^aELjnqI$r_|(HNtMf|dbug9%0j7zuMYI9%QacS z9TopIr4AHC@08~2s*X_=*Y#6XnZwA6T$gpZi5|ve(7~ND&6kxw=vrA(WaU)V-XmJ4 zWwk6XC?{9X;^{Q*Z`-6p`R4*Uq~iihe*?RQ*OY*wiiju?pZ5?W!t={RiNB94b)@+< z#G5G|YGPh_RF2CSfwvx2vbj&`&MSE5o=T`oF)IAB9#vn}Vhw0E?p1-i0(GDN6xduF z0bzk_guP`TRf>WQtZT##!ckzL9@l_^O@V^{3jCl5Hl0n_H!J4O0{f~o@8Bd>Gwiz< zgGV4A@KzvSX+?5$;M`m`PW}0KE~bBAE-<w!ux|m_r)Jp4fqkeK#EZZ_4cNC70rTUf z4EwyO+MC5m#YlmDvKZCRj4lBC^w9#aZ!X0?A)$HfE1CGIQf~n#StRWL3KA(ALv(;q zfoTn^4u@Aj(YxaFEa`g-+CKJzT_o}k10<ftrp3LWAe9D=6L^QJz}q;tI)=${J%eD6 zY8q3O3FF5W<9*8ySB-mV;bL6JSfz5sM%%czx98d}QvZSrA{7oSo2~7+o~Tn$^}-MQ zH5-Uy4Z<`Xg)8?X7bnT`45Z(1${iP}33A$LYHok%i3-kITGhzwBG`V&g8_WWWP#(+ zfKnW)_jrKvw6-xt54>-D`}(bxC~4gO?ya@k-@BdW;KVz9wjMpWBgz;d>KIPowgcX| zf$Gf0`o`@Wy*BFw9JLUffBl2@`mLMe(BT0kA$^<-AeBE3q*qyWCW|!gOmVZ(GTy?* zsR=jFnSesWc+<PQGo(G=O10M33PRHfK_0fO8fj_5@`{Oc{KskNPl;j9Ibwi}dwM)? z*Fv@fpP};cfQl3Dm=U68qsX>e1Pd>q6qIh}nJB`HW2&m4Bn6RC!3z}*l(JB#%4!Gy zhm>*xy7D8QpX~j=$|tu)RK_pCnLpu_BJuaA`3f~xsi6RgQ{90Z)O-z1Ybj0lD8S*A zo=rqPU#H9W(Ij)Zlyk`E6c%vG>G&E=s4^d_Lzc&H(BL{XH>tTr&9|u`*cLHJQug5t zhW*xsG!_xGM3{Akf$z|Y?^1J@n!iGm$S%Ucyi}Jo5m!8P{jIDR%(rMBfiS;M&BxUI zH8l^Y`5`qwqK4{0<D``n2L2Yma2JjA9uibkWC*AUuJNM^&8b={mk6%sN(9ekfN%!a z;z}+3Z(v<N)zvc6U8?geDJPfD0`xcuw@buA_Mvo~1Vdxt|Db{Qmyp*2S+l&BddQ9b zo@#5^D6mUI=BvCa5vl=sfz3b^HPVm+t3XA`to%~ilL=Wr(<41rDHnZ7<5gTC14d^0 z6gV#RYN*nc;|g-HvQt40r-Q~!tOJE9H?C0L>nO{_75YGAsaH+&Wz4H1PZMh?Q%mmv zi@O5XDzPRIt%7+CT1_Y{IBN=8k~y3H_tIKa)%te?CWUXgi*nL905`7p1&G-MVlCs4 z>ZquaqW<&HiV)Uc3ymU=3;MtzXTlTwDLya9&aCcJut84gk>^l>2E||UoMRYDYhlQG zL><f~PtNnoE7e*vj;3gdEOUalFUub-ynQI@T~m~%1e6JbJZ~Wf%4e@3;R1m%Vom$@ zJ4H!M)YGPY@muvWDkqEj@#Gd`(qqq*l+%c0s-8pfDCs$+MIm`Esu4e57|D_J3h#ve zPGtN4pd6^EOUi;)OG&-Ybxdw4iPB!@kI?;GPW^?jZ&8n`eMpr(f}f9WLx=twlcbYd zllC{EN_p1P{?H3-l$$?7CtsbpR4Tx>=2E9A9Hj7^KgQ@;pQs7(@)q6t7B%D<k@WEn zB@b=7D8YRtDzwK=$|CIwTQjLo6v<>I(>$?TQuTB1o9L)wiYk6m&i+fTbCgu`mtx^K z;Y>*+iv!LM%`;i3kkS)kjYP%2fo26V3RlsQ=F{}0sWjzssV=Xmbw#8YNMV*_N=9m@ z^>R~LfLA;D>X*n9_>iYu_id73{-K9XKaqTV6CHZsu^f@}QaUnRLJ0xA7OVVftUX4+ z?Z}IGP2f<0x@5fvy(#p5)ADQz?-2Nrsu!uGkqd=90#rP=LMUu**n4=7mJUx?-zQWi zrgt`D%`aXsjpL!5#CcWc?B2U#1gcFS_dd^kj15OT-aG~=&Ptx=?nDJe%o;CBBSx&6 zd>2J)a-7WT$OXZy(t;(scp3PPaPDVaRG;C-;M=&U$rqwUDV!VO!4Mknj0ev~cg1eR z%BS~XUkLTa;pdmRyZkwx@AC4aO};r0vCei&6*UvS0re7218F?HAwcb1l)HB@jw(6X zQ&LVv$FI;_iyC1gq7gPiHvE`ugx)Sm%NK$Ds&exFr2fCFd;`x#0a#1khVydJyWgtO z>mVO$W|~ROq&G%GkNS1fgfPAAPQ^5xz&1_Z#3H^z%@Q>fwFsk4W3Dl$V|FQUAWlPC zfXc$MbXwE(tGZX~=zl56(kZ7Ic-y8Sej6O8;%S7oJ2-A5`J%)s6&_8SkVUaWqJNlj O{Slolq(+zPr9T4XZ>fI( literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/glexindex.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/glexindex.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..16a383b994853cdb226f7b7fb291cdbef789e1f7 GIT binary patch literal 7185 zcmds6-E$Pj5#P_d(@DrOU<}wvO-SPC;^Pj1LsGIuj6WcDVUjY~4-(?Ew>zg>-QMmo zyN4vQ_hRfSSEcwHB0c(F+Sfd!c*}Dt4*B)W-j_JQ_{CLOakD#L-90@$-M=29W5>!G z9_z%fd6Q|{Kd3VK%%So=e(_xtp0=)ex@QFXx-Q?wx;|&k+1_!l;1$2t*G=z)SMuiY zWqD<9{%dXBp2MGa(p%vAPGP6$9pfc$5x-YZpKF!8CGXX*?e(%}+|nwqJ@{Msvwo2H z%nv=^<uPkTf_0-X>iSN=_+Bpxd6>kt@`r+ZezM9wjY21BJ0ZKq{jkZ!cDbD-y?C`= z-}aMszgcsmZhc1%YSqJjw-*Kb^=1$?>s=>KxEQtd6F-RS+X3GLYra?O?Ux^8!P?Eo zI?8|2r>6bukJsFS`jlk}Wf8v*@r%DjkwPndP0V>lsu{*W8|aC)qo-P8c;+MHz&z9j znrzW0S}^9oN--C2J2ejVL-USFa|eagL|ehL4)v4Tz)XrXDm5RPgJN3TDTxo#Vls!X za%!cvXFoE}Xw(Bu7Myz!tjzFS=OGtP!r8WPJnk`Cq8p*oYx^#=+9idbpHz6#<};N} z)UJx{cvaG+TAVl{Vas2HeiUx_VNzwJ<NaFbIYK!5o0aiU8h#sugJ_ov7735a79(Cc z?;880#pFEdkks6$kL_kotfr0l60s)wJZT`@aofz<^I;d%K~J1Sy=Ti+WjA3+v!v^S zOt;@<aog#UU~bTd&ZK0p!6f0{s-pegdA0a=a~+_5VZ@yzz*?{b=EtljqWeCmR9Vau zxfVxk^EhEiltBMd6;H2yida6e-|InZ&t16ZcX=3NJ7TsB{xdcJJA{KmDxMhYhjJ%y z!W=n!tVvfyaok8mKXjc0blGw%h#c(n?S3!d8+k>(jw<wvn6vgiL~cfb?=ne=O;C#6 zHt%w%f#EdwU3|e9M&eB=07tbOL!smYatTSp$!^5%J3$|w!V!Ez(=A^>!B9TTO(|@e z+-Nyfw%hgt#X4}X!GcX_S#5k6>@(Pl;#5`rQ{>c+fSVJ?{Vwcf)SI8V<z^HGNA}{n zI*xH95<lFovMzT*d`zAQxhN;tb@pRM<8XSL`@;czZ^T7fe7{>`AJ?{PY-?-zVwKUq z%GMTZ<M22PV$qIYt}+LQX4ek_A|p8bD`!nUMahNnz+MFl$W8?Y!oN17q)n7BRoM#u z5oMx;7OGa+CA5r}E%<#du=}&t{kiIU+7acNm{5e1<P3;9c5|kfP)gi&f?z0VE+l4D zVK8v=jyH5PQLh)pe!`WYpYx<I!U=B{_;E7ru>LIF6tydtB!iNg{qdgD#Q~U@e&xy) z>HZL6YNJ51{7$8o!2IK6xiS)eW8=bRm2Iq0agmBko13G~*<`St<Kwz^aW>H^Q*`t9 z1?<cV2}>8g2J+-G*RZ`WWP`CoHgW}EbMb|2Hee%|cxm&Ql1~Ud{*+6Ag7AJhHdW<r zCLGtA3Qd04`q3hgsnd21rBR=>vV8qF1)+uS^vw1WIKIaQY84|ZC^wK5^K(&|&ul48 zX3Kb&nQ+xvu_YZ)m@PF$<ajOsN<((Xna#VsWIwauh2pH-7+F_l#r^}Hm8gM^Pp03l zlrmfHDf+OZS$Vvl+0s#GE(pB{f-#xi$clL&{!SBT(e&>-^=_Ed-8%fZi0h&gwS%_f z#PyFN7hVp5xqjVG{?u>Quffay1vsqUboO}+hwOVI+N;NXA);+Sk4880_z`%O&5c%Z z49wz_C`y&GejI;i^+jVrFX$(AOBZjV!!=P1p9Or3P}edPp6Ul0kd>JLX+6{jR$}a! zsl=&3T|iQ)=~*33ypDD&G*H?D8zs<{L`?>8R>3no;~VNLwhTg1Nh!6w!fDX^NZYIr zN@+>Fuh15#p*=Oc!Wr$ML|ln+P)>`~-ZBmiAh5#0JY*?81Xeq%9Re>;(VoNjg%r3A zqxC`Y-UZ^+F+>C!KzJRSXmtR(NsjO=Av~-`@zjaupe)<;NjV1d7*$T^ugY0i$1zB| z2ux@kyy6v8>yYqu>A^2QaNG{haTA5x(I&7KB0L57nzZ4YFk9Pcbp24ioV~{yG%YOX zUXWEkeuAg6l$k(GnHlg<P@<4oZs7MayAON*Lsp>I%H^!!2q)a;Suy0h1k*BG)fcDC zk!Kb#IL``#_qdZ}3vLwjyI}*y>~;htDPo>j;1Ef4R#^~aGvYNWUZ);g#$j=a8f<DP zNIng5hAO7-?PYdLL^x`;M4^zA0F^X$RlGq{mrzJV|0{fytdhP2LtKPeE*X}2T3@o5 zwPcpeQ~F8cq`sh^GUSXY6D2i`O!P}KQNz<ac3k>Y^Nff3R|NI-R6o=Yj6);@2Qb$i z%Y!jVpsx}Eq!Jy}#WE6x0zv<WdP`4Ap7jV@DN_X+0TU8;Fk%iSf)wBzgHn)=K}Jk( zO3NM@I2x2%fS*`LN>QE~YtmSx6*LbLK+@79^D`W$)V!tSHpDJC%+rzTz*LE%XLj^~ z>CI7svSU+PGVFOz3(utnS{Go_-{O6Ydf$KnkLQK2DtgqO8YhN*<<xjXLrv0##ELqt zY_t;6Q2gDe+E+MQFz9*bEvQ<C&f5yo@rgjq`Y{2j8;u?dBhgiHyH;aexT<lSNB8nx zg{`qW07(s>rF#v(-fZ~k-5$I9*Ohv2!0rV69$S%Yb_q4HRY_tCqX2^lK~XLe6H-c; z%trD7Ahm^DBI*Z}sRXb(CB$?VHO#%1Z}EG59=e=TsiR=}lRP5^T5bZa=Bu56nhJyx z=&!Qp5xR|2uf`5fyiB5Y{RCMQxrCuOE?{36CB$w5391DU;v}7pvVjrDnVA6b-0A_s zsWf8?I^Q}k_k`WT8ARklm&~=|9BJNYT*wjTjRrz?jxC>pY##tu12>OkhIY2L@&y1g zVo_}d%i!ZY5uJPwpr5u8s~y3viM+%Wz=*<kSUU>5JgJ-w_lBxk%ky3tu9p?i=xz(& z+gM!zSU>^Xllv_K=jT@{wc8`sg!pnw8`CZkyD1^3#7?BIwF{NaiJ6KY;G~2{C?yuD zjwsVM;h}zozi8m*<`{{-4C|E_vi<?wG32EMkm3V(Nd-Jxip|;U9xhjgwFf^7IS`3| zpO4&vv~lDQxR>x`Xp=$ireN^lKynsEtP0-5{hA;kQdv~NuH?imxdVbAiFgGCuovAN zWTq4DXZ8b*<XN1fc8fAVGzWpGP~C*HA=uXvzd*HO$rvSS_!gICf7DNo1}2)ggI`P( zm)`t2P!a-@aZWGmzXeh%8K?Bq_&%+lGnio+ijmdf`|$+MLwKdMXDVD#upEV}byVPd zfu(>>%+wHzKsE>tz%Yb%D3rjxBV?JlsRG(cb@6s;p#?vL0y!38$dVxl$m<b8)ER^@ zjI`jgZRa|!(4>XlqH|B;<&HW}mXBUg$qN!Va^-n$Ik+-FPP?_Gj#-X;DcfuIalI16 z5wcz7Q*wfosOHF9@_jyoY2QrZjbjBJrZ3ff13V2O?y);m%%;a)|NqbNrx%<j_fK6i z{^Ys+Rl1Ly#0D}}lUOq5Nh@@MD8GM+d))O~KCTwV*NQI_0giZNnKq7`at#pV8Bd-i zkKOsudC~YuU%fiKY0b@l7$_>^dxVMDF!KG<`_6QeiY5AK><hRKFE~hhKRM&-@My15 zoS(h^>BY@l|Fnvp5g~J}&su*qzg~Zi6r_9^$mwHtutL8YMdJL3U6_*M2Wn=5;j=U| zA@*#|06i;joEzOcRrb3o-8SMr32<j+_N)z>GfSCI?;`0#Qp+jl1XYxlkzKrlxK$~t z$Xs?3z(U-gT=Zn-m=*JLk`-~MNp>sNFkGCVIktG8zQ<P~HhBY;H69JY$1(En_{EfD zmfyCJ7a}XfRmExDdSd9t6NFtFQ?YL<EJ1kT+O>+VfP;b0`K;Jzc#+#^C|MVj=5Swx z7$<K#WIm~)cR@90bJBm^@H<?*3yMgk)&H<aW)nivy^WwOHY>e{OP7AYuOR!>;<r#( kMyXKJ4b#xePs*1|zcGGq=+^fI2yGa~f6@NEWi9^ae+LhfX#fBK literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/glexindex.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/glexindex.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3d5029084d1c61da714440410f73c745713a34cd GIT binary patch literal 7925 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 literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/glexindex.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/glexindex.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c3f24cf9cb753b59f9e226f828a7c3598ac65a9a GIT binary patch literal 7232 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 literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/input_space.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/input_space.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7ddbbbd244be38568b61c4e2bf42cddfabf3fdc2 GIT binary patch literal 16827 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 TZ8WIx^zdu){P%mjB~txA+f~EU literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/inputs.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/inputs.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ed2b0f6f101965fb42fe059ec79e8084a4b3a9bf GIT binary patch literal 2413 zcmc&$&2HO95GE<=$Exk5b`J%5Sp;rf0g2e4$i-+38*SqTXoVt4f!2mWued9jDYYx_ zE*;y*EqR6B+hbmdKu>*(o;ow6D5(mJ-ns_IoZZ>knc4Y1N^fj*Js9Ekr}DS9=lzAs z;%I<!0FPxLjy&NB|1CUkf@9PI(EzOhnlHlVUay&e)zSz+JAlXTfRG;8dB=h9j~gO5 z4n;$RZ@uHDXo?p6Z;3Ye=oHPTYMML#C+zJq7>6v$xV6k_CgdnplDTuqa+OHqc&b>6 z=4{FhpGYT-?RU#<&Y5(WJ84OMP!Cdn;AWgEo>{iX^zbFk;bF6RoRo>PefC^Rc1CB| z{%rNEPaB?TE7dUL&ViSq)>-Z5>4?E%z3L2CcBIXOyHrEOmKk}Gr$!0}vy_jJQ>lbh zuFR+Qw364iS9~(fma`)3S#XvmT(P07swEh=a7vcxSE(BBmBrcL-)B^2+vh^WlUX%B z?~$v8<=X4X7pHv%C1#J=?$7bV-CGSsYF+HEr(~V06m!3Q$2?Cs;N-!h`|Qza87tHh zF5E~go6;=NlL^#NaK~|mU-B&F!%W_%GM3Fii&YiI>7`T@?Eg>)3MZy;9+wwO3Wf6` z@c|UGf$xZxui>$GL5#iEUJO_R38(>N1cN8NpjfLfr0CB3@10+SR%WAjo@v3}zki7) z%0)@^lLbIT=2v~5opWxZZ*-DRpvi1>l)CToVe|yr;z#bzqanYR7HcVtzKU#aj2?3* z<B1kBvrz?r>2=YG<5Z<Cj_+ZlA&8dW^=~$*o%*xImE4d?D7P(mdF{RQe)nDQ#{0wf zAxF&a=7Oq%AUqTTE|w|z>fd-o5<v8q*IZ(>!aHt!CS7h+33${i%-4<wTFC|TL9b!3 z=0%H75q(8xR$PO5Q7KCS+~^e>OHla?rY!E>TD#dUlV4gN^x9Y}giIV4-54vGXZXGz z#}_%zs+D#e3!T99-Koy5<3!8R$i}0Lk4*=I_y7f7>Vm*<40a5LX_3M^Ug(FPbb|Ge z<`bA&8W`vSJoaM{%S4PM4rELOZqOJ12&}1QhpOU1K%GLe1qPw|+o?>_QJN5+S*8i1 ztfmoSHOZ6nIZczl8sz_pqls<ym<1kJ<M|yT2UQ2o{jnF&74UiBc?Jw>+1c*SRs3*g zw_@r!AKmH?&FG^6EZtvmiQQBAs}IKSM+Up<@V*CSB|M;HZH%;2tpt^@?Bd1a7_udu zS-V<HXW?w>{gPAm7&nGr*E<d`d72>^RsccbS<U0*w8~<li3@H^p)x7IcPpUAt|Cz1 zgBPMI_=!*w7RZ1otU)tjMPWBhx|d$F2=RK0wfbg??!2f)cb;U?u3~r}CJ7=(a5#aW z<(GdzM<33RTr<+3*EH*3X*N)7qPT;CK=wX-Ar!uZ$KoR5YkiyGG3W(^F;W&lNj``u SI$xDo-$#fNMQ%2>qJID($9<0g literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/inputs.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/inputs.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1532dc02c21ed5bd3cdc6f0b98478d396f56071b GIT binary patch literal 2897 zcmc&$&2Jk;6rXkM#4%0!6+~Ma7@<HgZ7q6e4-t)2QCf;hgxVsZ)MY!~89N)+v+m5g zZ6XdmaOk1;3JD}6q@t>S1~*OxArY<A6aRp#^wbmYz1<x<F^ae`j-O}d&Aj*Kef(a2 znVG3E7(Xxls(zbd>~CBYqnuB+mtpdVNw&&L>=KjScTAQZml%5r-)yXU#F+q2c^9W7 zE7w?ka`Qy(vhMX0%Y~NQs7NGA@~$wQP>YDm&?Y8q^^-8xwiXm}@z={2+wZ{S5mRi{ z15--UTb+=l)v^Sos})%WI+>|TE2K$02lHwi#(5q@!djlhT&i}c6;IX_@9RLBM1-1$ zXc+GaBf2V4#x`o%wInl1Sz4ZQgO;D?rdz(m<JLOup|WBhH&u|>2EV2hzePH1qu}0Z z(1ok9Rk{VfNI*&}jw2`La+?FwaT6o7ZO5i7&_g`5;KJMe(0~tNm);{)Pid)ilD)@C z8hh6#_e8fB?R*uTE{wB05Sq7C?k&lM1uan&-wkzVDRa*9@-oi?+7MFu-NGC1*Gbd} z+ey9g;mw8y7xQy`@hkuI;+_XFA^c>cN2mKb#JBH#WB5)`aO2dOll;uh%vSIv1l%Ze zn~r%9ce~(2DH4G@;*N+y(Tdbba$}YZ#LT_W3GXOP#{Lg}Aai^&=Uf(8T97%{gQ7OD zM6ehq;G5S;hkeU@+@~QuSh>@ZK}nWYF4jxwv<pvK8)oAZFD+XYwJl!Zuf)eo%`Yuf zM$>!~uSIJ@*ye>e=yxI8Z1Yl>eA;g{FG7BNA(FLbE7Z;2h9AUIHCtjsS#+>8@x7+) z8xwb+^8GF_BiqcYqPLM&eLvJ;;`^Jklva&m{VrHw=YZU2TSwn~P<}YOb?j~U+5Z4O z+xWO0UO><yFI<JmBk;jG9-;A*dw;Qmze#1ddJNO2ZuuC_KXrFJ06z5E=56vl;fj=y zK3uE2yQ?0d1~Dc}rVI&kRKbf^Rnj+rb2!J5Ba2(F#9ECUU#U+Rv@)F(J*@GxS_I7i zX0t3vW*Se->?p>~!<jF4Y}WD00+9P`aEMLMJe>WjI{!y?{>QcN*MC_5y;}dXT7Opj znb+XpN_`6BgSG4XY0byz^&_0`^Zna>5#^jI-<NR!+Xs4agbAS9ZR@uq(J|O%%zhwG z7>Oin4F-w`J>vqb?z_*RbgWVxFeGQ$k>k(GbAxiJ!UxQe>U8CU0UIZo0+b!V*Nq~Q z+ect)cOQZ70i6WmTQ;-67IUt5=p4uaHZ*n%fIteZ?WrJahXDby<uPH5YiJ0VhAR=Q z4f_m**P+yZYBB_uOB{Qn?hMldK{Qu5l*g|_!a;u%{Rmos<+m0W?)j$|7V}m!1k^p{ zjW*)Om`F^_T%J>m4KM<<cII7y#h7`}Q(|M3?ZsM>3$p?lRmTzTNv9Jv`kWEnR8|=% zE^%Ru*l;(_-w|PiXr9*|BIo!!ZrsdY(Txei_Ig5oBx~3^u*M<o70M{WSeI@R@wdo1 z_~!{$c%BAfGbShv;+2Oh!sg8iMXz2-%a{b|w2NO_8@fKN4PB8=<(BRS1uDMHg9T<d zWc>_OT0{dt);UDh>8+#l8Nj}U0K0YUIQ_hVynPSglcPb!9DrNqAd*8!4kMuwe;sFt z8Cij2Em1+8g^4`{WVFB!Vu2%huTnWaVB;i{ghCJkNee*+iQTE{RrR9`m6pvsoJYr7 tg#N*V=Xrz4l2-=g08%~S0cebq7r6Iw$oSej>VZw;<OS}%{1*lp`wyu<@&*6^ literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/inputs.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/inputs.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b0c91ff3182adb1245aa7f20656e8e94336a438c GIT binary patch literal 2474 zcmc&$&2HO95GM6w$!hGRO%DZnSp-I10g+lG@Wp5h8*UpIXoMn(fxxCgued9jF}b97 zmyRvu<~&9Z?J=*=Yu|!EPkoD?Iy0mwsS1qVy2g&Vf3rK^&iAeO+FHkfa{K!q;;`j7 ze_><3)S<Bl)i5y69N`G}J=ELUF}7-=4y`)0T+w*xbejRpS|~MW?LjpgV59@{oa35s zkL#j#+z@rqc<&rHMN_Q6{}s^!AMLz(sM5^xKVfZ$LD^?P#EoG#VM2~VC7C^!EK`Bh zmWPUkIGv?j^H^G`O}|qtvsQ=0%t}MeUR9|1oa=F@cx2cPONMW#4>z0kW2X$P>9dzo zvNPJl^rxd|eOmA$F;Wd9ZY_8jCP`GeIUF$<tVXTo%8U{na~mdbV#Bn&%t9>%gI<b9 z$W$sJl`Z0_JT1lb!!?i7XfZ09Jw2RZ0at7&OSA;z26l;}<ZY<NI|VqqySt2FHhnIH zA5YQvx=XI+hAXcp-=6jrK+K-9&DZ|c=A9EoXsmB<QktEq5M#f4#Vk(P;H0<xm~EdH zX9X<b!nH)$RKkKJjsZi#Eyo^y#iNi9Bl(zMERul+OBBZ8l~i=t{{aU&j!(yVT3jqO z=s2$e7f3NJ_>F8ifNCCq89VPBAGih<SOd(c4Swv_^401>^3E*(KDc?q$Y}Jz(JQd_ z?_Umfydwi-@U*;0wmgx=*>z!iF;GYYXcJ1t-biwrY1unG___D}(etC%Px{;5FbgBm z3u1mDJ)WkK7Y3;(!Sv#h2OQ*)mL`j=x!O91?75ISQ{Ir@NQ2iQbaL&POzULKt@PtW z$jEplhtiw8?fan$t?xg=U>jf@cg3BoQ%3fugG=zB7!f?5!N)u2jq|H(Yq!pCt_v_B zK$A-X7J0lc1mp%&^6kGVjXHt?Qe;X&^HMT!;R^|9s6sQaUCKt~c#tSLH+|5pYrM96 z1z-XK=k4kJXpD<)qc9+^PQJFlwy&Ve;A&@e@~{YgVSLbSAy&vb-_JWfBAG?_eb4tV zGai*AE#DVO0NoGLB)ai~M2<$rA4Pnu+u&S(f(G+q&fsx0CLJEr;Iy{e__9%JH>fv& zj)j89+=FVq0JEs%_zHlU(+i;SJ>j3jY(i{bl|l-%RjAe=L4>|ZWe|?SfO62VggDMB z9U@tjJUE}}Jo&3s;y;Nz$<+=s@DQl+>;_T9$_;1!*el2hcwabVHR{UQ=Ek+ZwXs=B z{Y=pA^oP^v)d89BFS*3rDg9L&;{z1Is_J+@L1XE7py`PQ%B6`C1YwcG^V>0$TiUa7 zH6PC0-jw-;DD5z=HNUA=>|gOPLNzVvfy%WU$H{3KMV!R&V%-@+Ii+|omne-{MU;L7 zAEb5g8>3J>ur<=aI`uS44V*OTUb@Y^f!CX_RyUJ(W}xPsS&(_FJj2HrNd$QYn;ZHe z1Ts|oO+KCSxYDCRx2f;JOudF?9nF0-M6r*t3q3x8N(u+;dPw9LbZf*gYRnOmJdjAV PzbkmYOVmV&*1!1&Ix?AS literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/loss_function.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/loss_function.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a1e26394365e683dbec6da95fbe223ebcee10ef4 GIT binary patch literal 13488 zcmdTqTTC2Tc2(UCG;}vKxM{FypfK1N42)mcGaefcHh$m*`~W|u<#lh-RY2kD$5d5g zLz<Np%_{AYqxDLThFLKRQoN3>@hbk9mDtTjag<FopVg=&cPg@C?P{c~qDahoRy$hd zBj?=es_w$ZkJU!X7RBvb_i<kL+<VVG=l-qFS3$w^%U|;RzwDx@U*U)Oxbm52ahjq& zrZ|eDMJjCk(qRYrc7~ng*A;e=-;!8qxQxa&4$&Pe50{fXEmnj*Q05f9F>lyQ%3Pu^ zRvE6!*ZX7D;Tn=J5jVsF;XuB;HWrLJXew40uFIFyhwA}Sskkw=DZDAx5N^nqhr%H! zFB2PMP2r|kbGSLigc(xj7F%MQ!<$LI9P+K<)_k9~@D}J(A#RPehucY+N8A?c2zQXY zSL}>!4{s-VpV$@a4tJA$rPvdDEBqG8SBX1fJHtCk-Y@Qo?GEpb?FsLpDF?+<)4irB zx$3(h!_VN~c(DFB#npUBaU1SBpa%YpC%l)VN2!j$ukmxFgVw#nLVTFLHX3C`UV?9z z@&OlvU+3u~{qR$NoK4BHz{XEYi6}42XZcA9eiBlLLwBEMB~}!9Q7_|ok)7qa4yW#p z32`AN%<=k$kwjb+;yf!INyKGEVuiS(`-j$)0FKfat4P8%$d$<nafX*<$W|P^mK@+^ zVKR<i<&z?RO^9<mwyNT1STT}{3p0^%Ru-_nI!~97h#zBRrT^>z6xP}chuEaZMtP{% zcuG>H5|fEID-N?tbV`U%o=!<}N>G5Sn)8PZ8VkMknxoH`l>%uAiI3(5OMXl-KidYM zAHxuZX^sL_ra_H8T-k>-sImJ)DqO;OxeE9y<;r0&e7biiA<M^7@u&g}uy4c6s9@m1 zQpPMMB_tV}5@aSSvQR0+k|H1D<BH6P*mxojLuQl&GtM(9ndg|RQ-a7dWB`CuhGm9% zg&j`7nDyl0@kVa|D<?%kVPK>Zj4~zhJd<Q4Mcz-^AxS$sn6W9IX$Qd@o!S`|kU<d{ zcUEMsCZsEf20Jo|i3w6^BhJ8z(C{JL2=S<x;&_=kH8jewagK?x@mVGY^0hGU>R@0* zQX(q}b1ce<QFtjv7-cz*Nf;#aj76E%bGJb=v=T_a!~~O^nw14mc_wP9CI~YQvYC+B z7>_&<KnRzKrX&eO%vb=CY?hm0<1izzmjO-g7UB~LDFzacp>RP6q{qmqv7;aaR$=4> zGr>xb2SLN!m}R6?9L6jmG3@Chq%BGM6_^g=DTS9UjL1|(nN1eNA@P&;f}}vc3qyre zw#S5PJXgeIy9H8)0a^<b=H7ThE+DZQw=yvQlf0w|z%j`0^q^G*(_JwzGcd`!7?}rU zM1{Z#!4Pp?@W?5tfsunDoZ&$tIN!T0U`Vqt!L-luQbKOW#xN$Lh(J-JcXToB@kBf+ zw4-JlXaGct4C_?^CUt7fFcq<GDypo2W)clefSy~ZWftZV6h~q_z~T0<;Rc0|oRemN zn#?R@C_2SQiNYgiMd<8IwI3ZQqS=~@d1%0v1X`bnwKE9-BY}1l4ZcNURGf$;6XL8@ zfQlEfmFmufDC;f|60euw>KN5ah%k>u%ZgSiT&SGz|13-vsx+OZB35<U0bkZ$l6JzE zxv)`b7kpt)@}x`Q%iPDQbP0Twm~|XAO5LYNI!g6&OM7*<skVAqUSD-jks|74c@5Od zEw$<>(_JzzPDsrFSz<70!DKTgZJ4w|A|rRGJ@EYg(vkg_&dIQkT#~LNro<_hl`jn> zqA9XaUOFx)CsN~=j){q@r&(p{(m3o~GVCY<Cnc_3l3}tZCRv4#kV!0G!lf%>uB$!C zS=}9p5aJ?pwYWf=>vNA;Jc#7r)_k3Mx^Z*Hb+a;8&%lo_SJwnT-dw}hj7xLZua;8v z%~$}LO|9521Aot;BNeqI3?Cl&Cu0=^*?vr=scCFN9tpOVIL$fcVT`7&5nHlG%WQ|g zcj5mttAKM}A+4m4QluBt)>v|m2QIr!Q9QP{9PzR@##oZaxWk6A)Fg>3<;pnVC++0i zoEvn|@u2)}InWIM##2lIw4<giU5i*e+@j+@dt=Hf@|3mND07>5^Hh}rT^`OuDD$pQ z8Bj3$#uWJS6f`IsOso{xxI`M2T-5{rUEuXIi{D~N0KWb=##f!kw@Ilj#+RmX6du&v z1wHu8(uFnHD&82|28%muoG5A<^_n~{*R}Y{8{-S)@ip4U(_6sD)dH8nyD+Ohvu0W` zm+^%+##xug8B`ifJUD_cn?-T{jj_~QSQ=j&%dR)ZvN4aPR>3tl|8ScgG_1cO01m&| z^0n5VP#y=Pw3_`uCu+<*z_YadIjq(k;TlIN{O@R*W35eb6b+D6l2{s+F^Ic)DypQw zptKsE<>5PCFtWOh$Et_(3*S>{K6Xsn2;{-}!8ZXW57-X86y=kO?i`mS;Xgr<CQtm` z&wu!v$8&v?-A6+I^~=4R4t134rSXUWEp?}o5T#B4pqInBAqM*moRNIdL@WuGUPO+9 zt*e)@VseU&>@+jGbhpUH#yKo9bGvjWD{+(mbN{QA;qlXefdG|y0J8KJCS90xW3mI2 zotVJco04`zqL)p;`3L|AU9ewF{{25Z{<r@~|NFs?l69c~dr`T=l_z~%VC4uJ-UT$e z3v6<*Ipj%B5;8D09ZsXMJH}okyc24`GKnR1=ghdMJ9$VPJRUR46G?>}7bU&aV0EM; zKz4Mp-|Ho?OM~znV$3``79Gpnrs<>m4&x>c$JDa|H_7YeV26PvG0Ahf56*&xE>blL z0<}!{48Z{^F$AO^Ij?(1kDIL$l7#vt1u((Yk(e90E1JN)pX2!?$@y%y7szJ|Hr)q_ zUOGg^jEshit0)>J(pIdh07EvFjG#?1S7);x3KbWjp?n8+=j+sJ4b`&cj#sVUx8PcE zJ=~J<fvw>6-|TzrX<qR(XFV;Nr)BBfil<ZcbUq0+X`#24c{MbU4Gn0afy}_o;Tyv_ zU-iw)k9{pGzLu=7Rr9qjrB-}hs;`T*?|L|}%;omJo7=TFxA#bHNAGefw{zd4t*f4r z#*_3{6sBL36rrtpsrK!d(Y&o$Z|l>SgI?~<Lw#%aaxk}J4<K3}^o`-wN~*GE4XLv$ zz8$J>$CFU^^3mMxeYt%DxgEQgYgfyhjqd?<n0`%CgV)uH=RsK9?tD~|+xK2>&)dt~ zYKfz90QzJ4HA(aR-Ou-*S@CtNzHX4#;>dEX8ak8>9nwOFutR3}c?lFXKefCCxo%r^ z(u7(}zosxXI>T5#$FN0h@1vt?=wvo@QVX4250}-rXZf5OI+6_?(LzUFqj5kD^<_hS zTBr{j8!C0+v8Qpx)0p)%Yo6w%w^uydRnPV(pnZ+^ln3+KmV;W$!OVc>ZBog*>ZH6~ z&_Y5_$B6B0f%Y2is?UA{zQ4Z!i}gm4#mdq7b>9J2YgyX0WLd4y!+M^xRmm<r?^dim z0rm<~hF#JQ`wqdmu8=yZo-2919&=!e%$LU<T<LuI4Qk1<d@O<xi#uIz_odOunMKiS zaZ;A&{-@{$ny+wB>54RMr(W_az5-sZ++Isl@hV$=#oBtMs?dAdvSEwu%C#76b&hG` zu|*hm$adc6JvPZ&wp<!4WZWf<#|~lM1M;%0uz4E3EKcVgX{@a@dqylS(%7z0Zdn;= zhpikJcJgp8Te)RXK<S%}mDd=nTeRd))AQc6W8SB<n^-{qaDyOEnx3|-XwJ1R_m!OQ z|7^^Q=?a>3*{H2EOSwv0dA(Vlu1tIFV>}1)O8e54b1)y~pqYI%L7o<?MjI&EWJ0?_ z=Jh0Phd5uAu39RxkImL=Pp34sj&@Z}hs-{9YW~D@t17<^{7!k-<cFd%)CA4>KXh|0 zuEc&enfIst^VOuj`a}184M@7l?8nvQVf8A9%rY3a8k+<evj%!vGq6Z&ORS+>Gs@hC zboGOP{X96o!G^y!kAFXuTJv<N#l%?r3w|btT_eaEYW147W<9JgHf~^Dc_Ae>E(@#B zhG}#Uk>^iZPl9>b{v*h?)#T`nWNY;*$QEF=nXuO6x0vNP-@oT5XvGaGf(9&kifJi8 zCF`yQx47@i=jNM2gZ7rb{NcNV4QufpQGjig#v6)pzP|L+WzrU#ep;(^F}#8V?V4J= zlgtO=9X3d4b(v#fQCxsjG_%*=j{<22SW3hTxYS|7EB>`xVba?+3h*RL9$V=j%pt6K zt~G0306fouf(Fjlf_JKptNWfK9hfN6%=zGprD^M1m#!;rRnQydg2~6)J!rnZxJSC4 zt3Lou)3uP>NOD2QZ6dik$Tg5$J@_I*?2kdHmKWg|#M8j*jZsq!TBT$RJz%V$sL%*G zFi9yfBXB%d<aEFgE7XE7+X9$(Q^1c^bdlN5u#&{ik_g2V3!#c_@rV^%h({)P7JVOb zht&m+q|6w`WRaX1KB^=jc5@YC4?JV_WFSt3l*UuBaSTcnq8|{fut6$dc)pK`yAbx9 zeJQzXXk_6SuQ1@BPw{dA1co+b@WF5b#^7GWJvu4mE?@@YTx@I&=ff#c5g=Y?bO**_ zSTF;zMezJH7-NYiVi3G4!U)5a4-El266r$M1;&tVk{CETdgScj>9N66BRwQk%JCB{ z07tp3aVWjY|0EIrR0LvL5uj56v;**C!v@NwK)jKc!HL3>A;f43Z?HFr@p1^rkwD)? z5>|~S_=yQ2DqzI8NXsO&$;NbNGRjK0Ap9Dwx5>Z!@1HFF?q47F>7~(`Yrt%@_^gI! zB=nO!OGEN8RZc1JYd)`vMWokQ8S^yWN@!gNM&YE_MoBK3dLR6%qtsREn)7|?Dt+HM zw?8jQh;gTQRN^=z#KEnGGEXLC2t&^B-7pRqw&A;&8G&VvOeI8KzA`&@?7mBP#FOBC z5@0ANb$2vh0}dh~-Y-rbg?Ny3-=Wiobvh!WbWCTCOOQ_w%r)8EIN%xVIUpt=v@G}a zVEsQshi4}s0dJ1WRo(KWe$!(4<ND5(`p$bhv-RCtefO>YTtoB1o^PJiZM;3J)pe~> zbahK1$u%$wy$ikIMW}B1=9_Pxq5byf&8^hm1m1Q2jDFWSw_^<E=+KGLVs@DVyH>C< z%EsYNz@!kL+i%T$D2pc)h+D=WI2Hxr;C#=+!U|J-7CfE4rk8*|BxnDBs)IBJ;*ri_ zg0aow0h7KB1+N;fUt!P7m_#6%gnxLR9@715Bk3<@|7~dfSM<k}QZ!czv*89kP4-)a z33CAQpIP6dl!P`tI8V>R54jWri;`XnanjSWaNi+)2a1W8(ctMi@hJY@eZX*=_RVcx zUlGkVaMg*D@vQpIb?PTIpKn~=^YeEfeURNbsO=oQP7z;@jjd8>N+$VD$Pl*R*L(_W zz1ZPz6M@t01tP$ugFI_R0Cm<8eGc3Z9Q|O;ae<@fz@-73taIeoC^_&TI};MuQA&g+ z;bxA(Z*WiZn012Wbl1^=$omqGWU=6+DJXaynZbf%gmXb=pPpTO|F19q@bZrjKNx(- zeLnSw&UPKvx(+|u^NV+~T|?^FxrNKw#`9X^dG-BpHWbdwR0<(3FRV_o(rsK3fQv?@ z#;&h>j1s&aCF>>RdILK9C*elGBtIezU|;{*WnFiZ66CLxEb4Mcm$Vt0O8uA+6>`FU zCXL`{3nY3;QUVkbx?FU}2T2Ln5uF~>ONiwl#js%<6T}E}9JY#xPG8jNS-rvvc0_bX zG^xAK<4!p)!W{z{tqr{lu7|*9Om`2%B1^7+m4A?8xd>i}(dpwlJq1nivWH$mwsHx* zOh)(~{e?tAx)WAUL(PYf1bSL`2>p6lJ_Mqdfo$+DgI)?dI>-hBAtFo=Ar7H_MR(yI z*|E{^!~Yq=#GOg^*(?RUk`rPPiRbcLIc#~tMNGi8PxeVcnI%qqX&52kf?-HvLZ?sb z^aq4G-35l)IOv%eg<uS%KzJ&yJHfsJ8sl>jfxD&$jBVGrp=KH?c_e(~qJ-O}UbSY6 zm(kq)4w_~!ddP&AGSFnszjm%KK&jjUvj?<vbqB-<G*83A)fLZH)w4BM*N{2!G_d(` zVB1PyTQ<<C1v>BXD}mja^4~%@q4MV5TP-)<x%til{ZU`0FIOA<v}Q55M1QhzapMoZ zojH~{_Oy0m<`}q%%YEOk`lxE5d}(ji-Kn`dRd?r0oX4x~QXgz%R#Hj%0~zI3|Bb6R zudY%~-x&SGU#kXBWc`Dhe^4dwmsoN(>mSwpqpE-O%Rs~Jlb_Bkv7gK?&i**~kpA3x zzu`ecHqfgDdNW6V>!xb!Zl72<x3qgPoDFQ#0^2f2pZWv0-I@Lz{FKAb=63XPYu@Hu zQ#0mno+@P8w;6S9Pd!yP?GEsL5L3x|I&=PN1O>?xf6Z;rLjU6NrT)c}S%16cZ_o7q z5m<x~2n28M|8#uu%Dvq`aeVGwJ_D=Dj>FoH!`aTmkIsBi{ZHqzohP$R-_n}Cm229( zII;A>C)4)^9voX~+NCz`{>n)QdLgO+@)&@@@Kt~R<VPoO4BZ^c41EcJPb{2SypRoS z(E?lkFwwkVfYsLC6;H3~=|$Sx)%HQ_{i5ZI{_KVkZNo@rAXgL29Ld#$Rr7_fstq^4 zyHvJP)vi{xKM6K1$Ui!K=fu6S2Nxe)Uhdbr`?76^w6;TE^r(WU24mS^Obf<tIgM_0 zD^=Uns%<!~zQ_KS6@SZ8%hDNRBvgNUu0FKr)9Sb1Dj|TEjy@bwN6)Ll3)$cWEqLLU z(~!pK;<+E3x_#=8CX1#0E1quE)BO}?oVV$*ck_yO^U}^GHtXG{dAF(FZ6Lo8qcwDE z4Z9x>e0~ge+`W(5e$oEZK6THa)_|d%p<JL|3vAT_UH8sFtYzljMJ=%Rc>=d;oA+p& z_b=~U9{c(E<+ruXB)+$fVsF>l-_hFhE!tFX+o~H><L2;VZ{v!$ae-Z`hVUH(@l<as z)OZ6hAItlm1nX~4F9q&2YAt)R!Co!c`;gUwZ)c8Yj(-VN!jkKbPh)m#%sb018gn2U zJg5Z^W{xB1%3IYR9sB-)j}F}EyV(b(YxzkUp$R{7+^M*?=fOd3dta70q%nsc(He93 zQ9l?R!9guJm^uEmx$E8qt+`iqhjJSNx6a_-LfNhG?SmP2uDbSiqgLIvbU~}`&Xnew z+TfOyPjfeb;x#mXvUPE5rYg6!^G+;NwNR0Dx8`~dXR6ft&a8WTZflQO*wzU-ch=pK zt7=l+O~lFpg8`RX3H{YZf+rxd3mpU7Vq^qvoxwe?IGnvB5xpXUm%&mZ=Dm>!Y;0n_ zrYsWS646LRLdS=(*W&to->{{O1sgr=5+>+mkuO1V-TGT~G?utmDNOo2C9SKJJ!v{n z0@AdS_Z(A>lIB(FWhr6LK(|kKUu7jc;G<oUiX~?ayTAoU#VOr2)e8abYRD(Wgdz&# zaJLO}U~wA1&ZMa5wel4aZg9tYk`fQQ9$o<lcoLd(u%Sl<0O636k_*4Bwj7Vw8py#b z5tq=UgTS`|2X2+a)|iJ0M=pSET(r}@#b454>{M?yoXlTBkK{>^&@k1R^{RWW@KT(I zdyxLM9rZG^%8`)u(rGYSgmI}1ph;j?QqoC;TS@rpv2G?11BKWt=wO!4VuHpKF{LCH zbKiwT@3h?{>{)x0u!p~vjKCddywWbA(@x*^iVoJLcM1LCde<wOlWXyCBRwL4s!A9r z)3?8(3pzFMLP!K|gpj)t`dhEtLo}|_8<#2ezoJ*dx^N!>g(ElaBT3`RJ-Kc1N<s<z zh@m2ds~LLbgdl>W$5eBo_Y(RojcKqIa&SU2CU2kg3-|<Uo|3EJ>;UI!nufKD_Fu2U zzZ_Mgns1KsTql1;nP!!;y*a8!wZC=<wJK$MbJT9t{^qC_)&AzFgR1?_QM=T2-W*ka zo&4pfHuXiXMf_9hq`Ll_qc*DcH%Dz!?Qbz_aLIx`OsiCX@tdRiRQsEwPN?=bM-8g> zH%FaO?Qf3yj%t5%)MfQWZ;q<F?$)R}SlX!;jmUA;d%;D+`uO7XD^mXTI<-V${ud*9 Bp;Z6? literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/meta_model_engine.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/meta_model_engine.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7ebbfad9c34b1f9e6c819ea7cf7852af65591444 GIT binary patch literal 42392 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 J{$pjC|2Gc|fYty2 literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/meta_model_engine.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/meta_model_engine.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b2b3f8f40181637b13ee1156ffa8a03c1ffce8b3 GIT binary patch literal 87269 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 literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/meta_model_engine.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/meta_model_engine.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bd6eb8fcd459fd95ff1b85514f996344b6e4880c GIT binary patch literal 42705 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 X0Qd@E+a(_g`Az8O{>jTCN=^RXpccWy literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/orthogonal_matching_pursuit.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/orthogonal_matching_pursuit.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..543416416ef052c2402c2e9a97976dc4aab22866 GIT binary patch literal 8915 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 StX4>a*409eT+%Xuv;M!r+lnOs literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/orthogonal_matching_pursuit.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/orthogonal_matching_pursuit.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ef8b32284f1c504f9e5aaf483cbaceba9a47185d GIT binary patch literal 14805 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 WP-NpWQ<eSmKhSr7+@uAa!+!w0g|jLE literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/orthogonal_matching_pursuit.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/orthogonal_matching_pursuit.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9f1ec9479869fec42f363e7f46e07dba2f1c6be5 GIT binary patch literal 8930 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 H7PS8b3n7jV literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/reg_fast_ard.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/reg_fast_ard.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..97ed55acc1e800a138ddf489ccea709a8b28f634 GIT binary patch literal 11629 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 avA&6Yk^<6Wno`U`AM%$xPx3uy*Z&u-bVhUl literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/reg_fast_ard.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/reg_fast_ard.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9809c07a1479221297a3af1a9c0efeccc4e6863e GIT binary patch literal 19760 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 H!@>UtRJn6V literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/reg_fast_ard.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/reg_fast_ard.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0843cdf8bd820d9cccfdcde3a1193f3f416ccc10 GIT binary patch literal 11717 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 Zi*F}O^<C;cm`0%G$mvY}IHnd?{}%}UP3r&v literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/reg_fast_laplace.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/reg_fast_laplace.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..30079dce4bc04802324f720381b872c1a2f64018 GIT binary patch literal 9509 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 X4&uxQi9kPt=A@8#$;cEg3d(;2)UokG literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/reg_fast_laplace.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/reg_fast_laplace.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1aff76e3864a194b97534ad92aa7bb35db1038da GIT binary patch literal 19013 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 BC>;O* literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/reg_fast_laplace.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/reg_fast_laplace.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7a3bbc05003eab405d52a934e83053ae50080d25 GIT binary patch literal 9581 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 literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/sequential_design.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/sequential_design.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..af35ff42f1ea1e8ee19d476f7b51c19199513cde GIT binary patch literal 87535 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 E|3L9E)c^nh literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/surrogate_models.cpython-310.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/surrogate_models.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b856dfef2c2658af8ecc6b1ab85b99c499a39705 GIT binary patch literal 35103 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 RfEonip2Lr$Q;xp){{<f=hrs{< literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/surrogate_models.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/surrogate_models.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f46bce593fcfaf95cb1a46ef07808179601d655b GIT binary patch literal 64796 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 H?&$vjP0|dq literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/surrogate_models.cpython-39.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/surrogate_models.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f44a774b4165e6ff769d8db2f2c13c4dd0cbe8b3 GIT binary patch literal 35188 zcmchA3y>V?U0-+4dv^A{+Lu<k(c>hoPFg+g<<m)br{`H9?FmVo@76j-v(vM?Gn$>* z?e3MdLk~8VvCmHA2p8dDb7a@pgrh3pkc0}vm?A|Hha`@nQWzRT9239?gd_%xbJ%zJ z{r+Ef&&=-Xq_b1mt@*n9>+k*efB$#qJ3G@F{_-Qq;zz!sX@AUz*1rfIp25!^)HTi2 zOueE_sjEI^$a7>WBG>3tRIai4_*6n?8l#e&PfexdUazF5IuIABWacwd8HtNlI_JBl zy8ZV(^Sx7jav!Vo&ksxu`0<<O2MtZv=7*++{FvdXVU!fFjLeTtjm~eL+U&=VO^qQw zQQ0!Tb!w}`B`XiiXQ#4qpQ>z|-#)cn?$ebW^E;<@%6&)W!TDWNyW~Do**(8!YLDD^ zR>tS|PVJq4XzC$dD{3qI%&t{k*PhkPZnNk8n%Q&9nA&gZm$dQT*EnL6<GPnQU#gzZ z-@H`FSBe&%qt2o^k89+@$>X>TKbv2&?NYva!KxLCwtcZUYvEF}#tkodA#dd?m14z9 zn8iwdxo9Fo`t;3(Q$@QpTeb0&nynOXma1m)CLX$r*YlO!QnhqFH=VajeBbMrSE^Od z<Zb8p#Z!pf)E;>*zfj2+ig+>doaM~bW^2`a<$T^L%$2IM7nUr0spOzFeb1jbSE?5C zRx`KPcY1wX98IfP#R3PQ^)H2oXYjK>kD#bc>86I|qGPE%W~R-K_v=_JkDHxl7w%%_ zJ7h@pskqr|_Pt-5N|^oT0Io@MlR1cM${aF>aZQ^~m?P#W@^qM+%`wDe%p>Mj^8v(k znopWpa~tlu%<bk5yz4fPnmf%05z}KHGk2N0ao1};WsaMBao1-)ZSFJo<F4PFFb^R8 z0H*e!c?eT`sJQ7?WNOfS#yo63j1)uWBj%$>F>Gcq-N(Ju`J$6QU*kOGJ2Wkw#UG=x zd+a64s?Fw|;&^tR@6+<`@?6Qz7Akq$&N^1URJF7DY?x9doXDPaviU-xxZvPzHCw7K zEIHZQbh%h?vU}tyho^BVuTZNxC<Zf@b>@m$d!bk;&6Emx2Q#0o%}AtKvK^~5y~H>> zJ5#f=OVvWrV!rGGmfC#LDO$D^m#>;=khC|b@kYs+LmN=UQbCn~lILnSvQ8~)Emft4 zLTw&xluGjzzZa^%#~oF5QI)?x{FCa!&Sa0UI*H>5o^9>2G=QBeRnhi&ziX;u)lxM= z&8|#HLFiUKCkb-S@<I_+pbudcmxAf>d&?yDME3HWRm3oE^fH^b_-0|DW;sRkNLbQB zt+HIL&6m*g!d$*)XNxx%@>QD?u;=Q9lc%qa??cw<66V`l&LRTQd5OpDnqe^kK*%mA zh>*1uNKoZGdjaK4WKR`m@=Fybi$#PIR6iFA#T?S+(BHY5xu%<}uB9M94W>>_S<#=q z;tUo|saSPn2#Q!Fl}hafR#n)%b%kJUVm$KK^QB6Dx>7u%=9{y3Xd?UExl2c~&sk=v z%08bf0tRI-EiN&KYC>4<;fd^tix-b%PXNvl9%e6=%-Lf0V%YgG<--%%bH^{DTvc4Y z3K-bZw=mr!6IsB!mJ;!_QF)I}WPR9pL~fc*xJ!n|CbEEqN3zf7tx~Yo!)BvV7Pn#8 zjK?RkfRabDr{@=n7ItK%S^m1TEz^1xLw8k8>~yW>V9DkeHlErO!E0`QHL4i+1+_;x z(pPr_AkXJ3yRUMg;c*7ju=^?(c`<9Ml@vA?E2^0Q0BF95HH_7f$6~8yi}?b80KkOW zeZ`xEPO^4pN*3m}RxR#BP+1Pk<AyENWL;rd$y&kTkgpV$Du9V*Hr&;<V3ky4mDsJT zM2$l=*BlA#A{$G*RCU6dCYR=?ixz=h*gys4*n}`=*3Qo_R4`O+-RDNSddMGdZX~lf ztBTJ8OjZCmrQDX<E;M&L(gIlQv9T}D&H!vmauhgQx?Zee&sVc~GmrVWj%`wztyuu1 z^Q>^mE;hG4w&Dy9av96%BI;A6Hpd71kkME(*Ngj~tKx^#pkUQ(dq0l-k|{G14#u8y z&pkJuE#m00vU~937|fMs=U9YY!1;Xa(0(Rq10`)Eu$bej!63|3YWe0UzZ3A$nyyt! z1u1uNKU0n45W`ub76lKMc>t%<e)OjVq=rK$5!YqI6vIX~Atu00>)JmwanPR&vosH& zW^TOlPnG720$|a9XBjZSR7aD)3*?An$7@Rtk4}35XpWlp5L|_A@gX9n1-KK|C7||# zRjL+B3xwx5*RZs?et{b;1GmcVA^xTcYqmTrja$y&VFZr&IX7zA8~J5yrCQc5R(OV2 z!v!0bZy({R2#di`7f@>+fY3j~ai&yoUK7%0WjJwyV{(Br&ebYrcF%Otxlt@uvj=6X zA3AtYp$7!VdlXE_9v|nLHcQxs4*FQM3sy;>1?y<GWOvZMAm54c7TC@LpL*&k!Ew$L ztwG`T#G2VUmfej}+8uUh<4ovAZlRFRHG6R^`@|CyPdxENHoL<IWZC2QD5NSyG+UoN zmOXU1nf-)1m9BH?+C%{W4=Q1i7ckMlvFxS!c^*^#P`8|P7$hv{HH-92zG4@#Or@B~ znxm%8M{FeWa*f~>NV9Ce0Py&$lQ^B)?t%akc-uuszy&55M+MflgSBT0vM=Qk`^s~| z?K#i|*=d2^DBk2c#F{Js)G!iDH9NiR&(```%9~~`q$2i=s}5Yo`rM#i0E@ZeJoYfx za1-evpx=)r2SoI$I$W-fvp>?z5Zc+r#U*rt7}1`q%?Bh^ow5~NKZE7CQPoy)2JjsF z<!abkI~Z>-I*BHbiaPB@a8!Cx9%`?FBGvv3Km7f#r#+)uJ5vBQ9{%y(!0#k}_A>}v z-PLlMYarC!2tvb+B8<2(gi$w+Fy<x@#@!^sgquQ`G?^=9YQX%B$ur|=FBKxNUQ+Fb z>9W@ikkX2HdR^@pn%5H^N<Mh=de$CsUcx_&yfkkVO!m6k_nDXQ*Y$XZ7X@sYu}07} zFQsr^;M3M-JX>Q7wlLVr-~k3%2HO~HNARj<J&4QeA31sC%J<r!1+G}dYqdjHo~ss5 zSvbC~fbhKL)E2IUNV9$A49=y6yfc>zapf!FU9M2bRf^SFXYPqywRi*Yv}RqICW0p? zmQ}mil2%%4uZx&iSoV^+97r1{mn))m_5cDc7T4GQ*Za-~G}uItVY0yK4*nvziQy;H z|690mbt~;J0j;bx3<nciHp-D(oZzTTGZsQQzLHo4@8X(aU2w1r%BfqrlP-5G>3B}B zWEit5O9FSD<t{UVlrv7Z8NH>yPp|IvV|B#79G2PR8fMIl-!^ounnc<J(;}r-?v>h- zNd23VvrnE=*CKc}R{C9|Jiy<_H8cH+v5NdI7h*^K4`lNZ#$Iyr7T_6=z7V$fK#gm1 zzYKMFI;tl{R|1A8Lb8d!N-=`U$l<UtdB<8W7M&%ls^~jDw?aZbvuagWJCVnCm(f(d zZzDN<(8~8-TtOKxf^FcXo3Nz*<OSl3MIM{Y!{~H%mQYvG*ThFS6wORN_}O;(RbAG7 zebTR=bQ6<r1dWz!OTaJy&}^cub9p;k1^AohVOs)52_RYJi{+v-;l&r0fnr|sqG*-n z>ACSu)+m;n7r}1uH|P1hg*M^{@sc>ZNPXL0X9(xcRPwX3YrPopJ_~Fk;$7UcfNBd~ zqH5+XE5Gc;)Fl<>^x_yt^ut3Gk#mrZUazbI!RLV3l6T~#*gm0$z3$*(3ZPI&y|jSs zJPj1V_M%nr1;!)R4pgl=5j)TGULb`EcCl4G1*-^zo@J<6zK&RXF9NM2Dtom{j~iWj zkKScubVE1Zj7Kww?};R%h<np8295gYdE}PjC)O5M;N}hf2*AisVw|nTHSJ{s+c)yE zu>vT*s$Vf0(MAk$#!3VmmmBW{-bGiDE{AykE*{<`s%OIcWO$bf@6zF2M|hVB?>fV~ z1nTUPIteUR!uW1CTJAxs;tix&>BWf>Up3H{zA!~Ua`v6lUV5Q{`pf+*1FKpi<tCj? z<v};)44IMJ#&zBLoHLBKBe!&<+=ueg4Ya2`inFQ1jNUdH85gZ8_dA>2<Sl(f!?oj< zepFlh+T!OBAB;xij&2=A&0}tKRc~~fF*kNyL);5)%#4k2EVtyg^8Of3M#L{T511IM zvH_5jcm=>wXPU5|NbylTXH9@C-kTV=Toy6gWF*oO`)RYI(N)qK-T3uXqh_YjC1rov z&lyF|FFV_v9elo}OKhjvVRqe)HhQb+AimM-_MX!2L|*z@qtER#yRSv>7*-EPX=nLC zoYrx(2cytm?Q%A)>~eOy0Kn*BKhE_25$!`dYBa3x@@tfPXS*9)*@HC#E+cXdRFmqt zG2jkJJs-d*Z)yx8PqV*<^<UgBl=R`S1s`^M+)W(0+&EJ1bq86WnKAos8&@KYp$|nG z!|o8?bejXnlN{1MuDxQ6Xzr$?nw0b<DTyumk~_?@j^a>IrF;mhI-EJ<4h{k5p<7yG z#2s1L_cD6-A<Z2@iueX4>qz}hXFoZn=Fn~9gW3m;4@PDp=CC>P{v<{;QtmO6BN|uJ zE&Z0>7_A<0CQ#Oam-SgacsrmWk8X~dn>WZ4X>4{5x|^A|y}XwWHpbjhcT84OY;D^x zHe>EsFb+pCpNn_y7>m!log6oe;vrYR6SW2~HWBMj{jtGwOJ8)qFI(=~mn$s8UO*X9 zYj0S_g7on420h%mQ4d>tbt~HJt(5wau+)z@53fApjsgkjmN```GirTW(tR3x?a`Mp zqI^4|twz?4)*bz&(Z&{x*A|S-12SgG4aaOtbIknISxKF`&(zx_b^1P2Z<o{^_nCT! zq|V%D>Yb9h^Ioa%L>E8Hm2pR3{44C<nDxyTSoENRMdmJ`KfCjv0q!4SKtc}9fF;56 zFI%bA7Qlr7mMn;XVh1StOBh-XXe}^>iwg%9YM=y#Fq<hkO;m>HLlZq|!AmHi!Ha-x zPE;l2Z0`?S!{eQDoV9c(lN0j@-;;jz5iCWF2YfT19qTje$UM4iEfp2{#8TP`Td?5d z;LkTnTqYt?A?QthJuXD%o?QZZ0*)V!_jSxMA$D6jelKK?WXO6nkH@=@eJXsjr9>|> zy8wa?oPbw#FJ=<ofz&Ck*kE4VCw-DPbD$l7gw^}gplqMQIJAg8>YH1zOwh_?&`)HK z%3s<V1h(*+iNM-~;PRRJ$cb7_7^@_{gE<xybv)w5oEpe)FA9XI05r=klu8!KOUTKh zcBx*h_nj#@4s$jc1>?H)-7Nnh1fDUSd+km9fe<7&%xC8#1G`ntm21<smzd5Mt`)0h zfh7ljBw2vdXb<Bj7?i8Mw7sD_+RJ(waQbCHNE5=;A2M8h2B*j^<9P@}7ZG<!dsUwt zH>?CQdLy&GWHIO0oGYRod8cN*YIw%PK`&A=Z=#=(7jl;byYu20u-T&1g4Css&K9dc zhOMV|pn-N0<wgzT&7|J*W__ZGtF1#XCyrKX;PKi|O@sxk>mdoTe)f=b=`4ttmj)W> zTWimL*jS8S(yU8Jpc?hPxC74qVi+N)XZk2PuG~9M?L{;H8gI4wf%|J-nA0<sbL-j| z&cZ$vi5Bj>`z*Nntw?hoq|L!h^al(Pif6z|qDaVMS1|gi7jkO!rWJ<W-Zg6qsUGFf zQzRda8sAFmUApncx`uwcgK51R<u)hWx`M}JsLy(d@n;Ztu|<+zUR;>?piyKogB};w zu9pTA`Q-DL$Wiu^h008hJl#4(odFpDrV-`ZGfS1qvJj9JfXn8loE(2lQ5Ah$X%H(E zo2)6tw%{)Cdh<(8EqA?iJrrtsiP;6I%mYZUMY`@K&YcvFx0eLe$f1Fb*P-Bs|DgJy z9?~Ks_wR)zF83CB42mT}Hh~uduMKc%Bp0ryTu$+CDI);i-%GJFMTT_)%%7m>{j5Jc z(QCzJ+j^7*C1)%M2XRz*G2y6tsUjG_(q${l1Oq<FquLb=a0CF#>uw753I1&B9mrt4 zleuE#Qag&JBg`GrL|)8-Sgh#9aWQN2UV>L7^Wr#(@WMJEiO?EQonShV{o3T6dVRu< zMM@jQuoARd1WH~fPDQR)^}^!z@FMg11?w{JqTEbgTH3n6c3L@!F4V}wF^k0ox$9k8 zfUu&7N{grzC!9ULRRN%6a1aVrZau@?y(cMxRHB6oJe_SX4ao<N$y1!)R5d5$Ymt;H z*kWFUv*Jj-ivVz*zUXzfji~hjzU(5quqjXSQX;>~0X6VCsxlU8Wh6OC6tjDg>0HT6 zAy89my_dyAFuz`0wa1e60?5vh^y2=SjIhXr&p@``#Y}ohcHDT>dI68tRR%j4$mZY0 zyC)H>;Aejsfz}7YInt%4@t-jmHvbVD0ZhP;|9wUuNNSMQ#%QERPa`cz>_}Yii;dyh zqet-{H=>a~q>YjY|5h@_{LI;9B$2z%NJhFMJ<J`6>d7}Vkzs=+B_lmX9M@r#KOD(? zD-8x5Ta<Y-`bIRyoQF})pgtVUd@~&zL@NKSk@+Uxqr5Jo2PLN8j7A2G2|f5fg4WeH zhkI*c-BD7Aas>Q8LO~uv9BKQb2pmmO{Eet%fGHL+LG=oC>@;FdbR`C!E+|?Pr{t<` zMn<$o+yRw%3-@5B4f}7ShzE~%B|%PaIk{>ygvkf0nk>2)&e<5xSvO(E&4ih}9Rp>a zVws>T{nFhysO(`Er`32We*=3Z#QnZk7Q14`Q3&6Zg;D@W^nv11g_pjC1T-u!;AV0C z673WH0-w1j{A3G5xUhhNTX3uULsMS>ekyQ`xTk=<?4EFY?aKyis-{GVNaf`K|AO$M ziH|Pdt0?RWdrd(=g!hE71-ec?FA!S?vNsz_8Q~Zpv+Pb(LLeW;OM6g^EFu|NCHP|^ zoVhKs9VM*}<;454rHK}7n&l833>n#eQ-ZOF2v>M_8}SKSM*UtmG9*LL*Sc3{6tsk- zC>UsDpft1Dsg^1Q$F-)hGXz()3b>oJ$T2?ytTPS#BVh6+Aq~aiahAu^)(4sXWd<&T z1qO0vC91V*y$BhyoEK^TfLgFi3W!E<93VSkm#4qr>45S<ZvbH1dT0F;CQ4MR^&FtG z#k~t$-!6F_e*ZWQ3K4mb)e98-5boYh>}MD^+F&};7a0UZ%K$<}^#R~P@i>@<Ezo1# z$<oF(BqRx;2U&=Y26nt|8biSC%HR%}5i@GWZpRxDH-eoU&;Jc74_DVoVQ@lBSQKRd zg#>`(D+tluWZl^o88>OKu(WlGSH8H_-q(@^jB277`?7NzO5MZ4TBPqvUe~fD?r-m_ zim;(@!iL3iAFR`JXl_G=S|Lxnh5&PI++M8VKue&df%n=bZKwB!a0N)!JjQKf0CoPY zR1sRn8t^6TxY|6V7tdTCj{^rJDG9O<vM(<UEJJA>0Cf`m3t&V+w|LSMC<FDHwelvQ zm|>AoZ5={@17D8$GmLna0k^^0MSl}<ALgRZ;703L2X*vY@o0T(^O)QSRcs>)P=Lnu zE+-{B;;1za@s_FIro1y^8d&3zdO7U%StVYEP7~z48;L;H(d_q{I?8BUh83i9nuI}4 zSp1V14{k>hh$vj2Xf0@H86^P&AuRAZ+oaZ?<N(EyT1&<C=$rMS=FqgIYZL$VA~`V# z850+WG{tQVj73?8jDTG6-vbU|n8uQh`za@~5|!r&FoH;Zz=^HIT|fxp60VU;yi2QY zk7`bGd0Gekt!w^!U<B&@i(1t<2o8EVQBIk0U<*brjk-F@nQ~_%TH<q8{gl&vi)p&d z#8J)ZA;%iL{k`Bi$AGJ-8k25Z@r%LBCXOPhQ66!QA4e;8Nh|)ctrZE?3RSLZNm%*| zs`UD(Uw(?^LzoEs2sI>8;$D_`M_)eCR;EhV5v23`2P~=FC2je-8(HaH#Yj|tz@$*L zquhsbJ70-3Qciz)U}cjFF)2sc>~d2>S|jbprX}`2n(;=5+1<!U?4X-j8B%4q9jk_< z_za{RJ&$XR4sZj1wEaEHS{a6PJ}m-K$VkwtG=8IIFM7EdC5-_C?7JOB-#a0D=;RE# zkU`|OAk|jvhpo;7I05=^kqf_zeZo4>aDM?u?EqySuD-I(?G))!ccTYfdX~_QoZAs% zE~}7UFdu}&-IBA+C%%V(cc-~Y1iW}IZ=d1L8_XYS#S<@BMI6Z3ctkul+I&T*je&tV zO+BYPh&izGKu}6@Ux{bBMV$;3R-S4;fJ~wkY?p-j11zW&&fVYHAiEWS7u!FC6$J7s zemzjgmw>H>DHT67d<><MVGN6c-kk8=sDnc$727E)CzP>*e|5bCSjrm+K`YBGAmv^V z==7-^IV|51VoQZVPE0`eq9vFGYGm6rG-*0NT_WWRjkqw0^q_fCq7^T0fUBwjY?&G$ zz`}wXS8Q77_$Xwr1^2ZmQk|?D)<gBq)2CiIFj>5zlq2dXK8l`%I=<eCg!NRwFFjC? zo<8;BfqJ?nM_eUuu_?&aV-s`c%%ffu+GM%<5W`TkocsR9_c!FVpqZC}QKrHkdmZ!n zn?lnAmGJZz>%i_OsU42x47}$?-U6mX!Ev@)ESeb28da6BJh!Fm-{Z^h{fW-{OFiF$ z<8m$MvuxT7xYW!YHcMKRlV}VcSSnR#V*EkHA~}pP@KVes3B2gsqu@nE&!7y!aIMFY z!1@$ZCBM74e46@_g8zD5RW+<WcR`p`*2kDIMv1s>{cGMwiG^D?B)U+6YMJ#k?~NMR z5!8zD;xNy!!Lx{$Y_`ygV=TZ?0cWPjV!Vzf+v}8djCsLNxv2#Gy@hqGkIZy!scPn& zC9X&>0WE|)6zi?;XU0AZrmyD?NTLi!x@Czy7xGK2N08Dwf?&K?9kb6cg6FQM&v+@K z@6tUl4z;|q;GaZr_4J$8&oD_cm;f)sl@UHA3TPHtTS<0OI)>Gjd%;Wi`_JR!i(X=B zA;*}tIL{0U|K~i?%ec`7<6v_T$v1%HXY@hbrNO>1aNmO%#*w{Y=%ZjVjNvIA1A9SF z;ztI@sHDq8lEUIhe=8lOrcg36EGg8zVrkUJnrK6F9s>KCHrj!>Mhri}9oS01ao`Q0 z6m()#;3jOx`2d{CiGmZX17i?+Vo9?elT%hJCsy?;coc$ffXiTimz0pQF3UCDh(anJ z0Ux6S3P}by6H&+;A(_WX5zYTR#wLW9rzrpt9F3edrBWNnAZpNx&R1$U9F#4D((?Sa zpuWHGH$=GocXva%FDZ!Ggnw9<`I{&S#Km1?Q!tUj2{qq>kNdRGI!V-3B9(y}AkU6_ z9RW?=>3y97>=au2(4ltr#Bl)QjmLXwf#66oHGBLT&UQ_}<m7lp?XNURK~cG}t&iZX za0SU+7V27oqt7vyX!-Ogl|r85InloIqIuDMVkwGkY7v<ok1P5+;m--c6Ps^+i8XZO zo2h-qtWZ;H_g@`}htOiX4>wwG5{$hbu=%)4qLD76KGNJL&CwK2blWEBL}sd3$|j*G z#=#a@ftU(tB}i&8+^|KU*n$OKhISp;ZbY!7WTj!L>;7FFY&G8FJ+{?VCuVY!$urQ& zs2fEXdnHD6%7JDcR5jx>KoA=V=;rz91d0CHMiTE+An@a698A0<nRw9RgVKxCn5s`< zt3k<z@eLr0K{_`*15|h=Eet>AOff~7$}$}&v7<en=xJ-rQSDvYq6-8%1_XM$t~FrU zSnqK&@6+F<y$Bn{M&<`Hi>|sJ)D9x8o4_Vd<X>(@2ipbMFcT}zQ{|hdsnX!e;uNt; zH?tS)QWFtWYI-uo*lVx~41orj7H20<ojrN_QmA*_vYfe0eA^`&5dypj1}2j&to#;~ z>;90&|9@0FVF3S{jctWl8*wnd%`JXac2*ncc}rCHc?zlpr3j~i?X2d6Ux5h%hO6)u z8#>#fPKZe@%(aa5y<i(SXsw;yh-oX8wZk%DiL5_4TIyANMC@R#zU4AGp@dUn$k9Hp zd+L3n_uV@9d+Oa#@UB&NLzRHt*|rTJ&@*hxM1YupH<B#b{$0YU3CCICT<PYBDgI*= zpxzdyq!+sZ>ZfS^A)4eRK_ft*URfURR7i~QQ9giI)+z%sTddnmneYeO`Z+%7^PZ8< zdr9d7ksD)r+KWJBxE3D%G*Ul7cu2XgHk<(_k&Hr6f`5o#foDL(@@6#N1+m9gJZJP> z`W`^cF}*&}gp^Hg>E!~^hv2UpHzAZff?8a_HXsTl4G9qiW{SRXqyYu=a>UwYMyiGx z1%#tW1F+7F0W!YRj0ew~wMG)?Ljr<}=!${7)E=I5;^hPwnyK4*BXviwZuj3oA<z18 zyh}p8E`#?GK(9`-6XK2})a_D@6k<}jRP}3q`fjBEw@9D%({><rkJ%&XdzrraIX`6| zQhvpODx#DLgI#kIg(cOW_1_PQDxl$@R;cQ+_93YErK&Ic?}z36R@BuQw7XjI-;Kz- zr|_-|??#b#^KCE|s^|RoWAgq5YF(=yR}cGdw#XaH=?ULJP$Q$XRo;Bq=`|lPvm7Ni zwbDoQYn58nfZx{7V}$$NRC$17&Qqe=hZrz2$^+#=#^6lg$q~C|tPHJEiSny>Kir;+ zLL?}CrGeC?Q3en^6aP3@(sJ@-Sem@)1Y07N8*oOT;0G3o+huNpf?x-(+i}g{x&zlv zTz67&5U0k2`G3}WYCt0;zytxmefbj4jHcoNCG%8s4v6ZOO@DuY{hm^y8R!8ofs@e= zb1nzsi|a5us#*K8vY!DA13VKtO>Ak?C@Odnn3WKA@~@f;YM>red!FD;6A^oBNz|G) z3h@oQDk>N?i)aUV8zGVZuNcs(gIP|OFQ)-?hXTM|kmggTFP*%2_QK_}&rPmFlh?3b z?{$z^qP*WKj5@VevPN|$us)#wUIJX_6cUIR<uKWQme_`hv5PMVis4H-l{Imbw>~Ly z^2=wMJoee!|Kne+{M~PU`YA6`tI%tKs2PA(p!M5=1IfE(mA)E*me4zY;WHom+866j z&F()r_7`7yZ1m~z6jiB2t0LmmD%Rfswn8U>G<F3#T3)Bps4GH4gc>S|d}U!SpF0%X z9QKlx{QR`ZsNn9f7Xhzg_M5N%@83B;eE~H{q1HE0vh{x$e4WAHF?gN9-!u3ogKr`5 z5){m$fYLskp0oevSHJlC|JD72W8<;AmV)jTY_P&r)2B;$TkwNsHPEZTsR`-BtZ9{A z?gz>rQHhhl^QG_78VnxP4kFj5D>%{+7)837NKq4T9z$V?V$172Yv;@pL0}PRq=*g2 zN0pt>Hg<@rH%b+Q(m?CC**~K)@AaHp>j<JVuzwb-Z7&5Y5{N-&i>B8JBkGGywI?2Y z79|^A$2nlNwR7m&$>+VyrDuawV8D=$u(}xVth7GK;1dYE7}r$JdJiKgrNmTKD&Va^ zJPfh-uOVi<TVVub=?Kq4$yiqSD7b-+X_0yK;^$=QmBP=fNZ<`9tVDUw2oyck0NF)w zEvA{Md(Bo^i#xEj4uG=#KHO-7Nm@OK`bH0EDRM9};6p(50{`Gv{Czy0ggpe5Hq<j> zk_qA)@(lG1@-&e0jbyY7DipAxfVcxH8sLzqUpkVZf``$E_oD_h^FX^%<s<3;*E^dS z3B<JpGBJWb&MKu-La%)ZZ$Lk3N;pu`O0bk`0Hg5lQjN5K*U`xMcVMLZcVLJ+V1!VO zuN?V=?f|2KI(@HtcA$#k_LAnJn)!(K3BAz=R!2WDngKJ`*aVe~KB$lnf+iY*()%Ve zF{E9Ca13dNP->z>bM%#@+gtV(IR>=Ga7+B)s*acuC*}5%?z>~W^dsoQD3rBREEh5Q zOIHyy1{G_x&WTZB9mWwccMGo#F#kd8AuNNEYdnCbj0;hKyA@}47EhfnOdB9>$(kt% zafSm!pdeveV>@znnH_>hTvh4H-DoXGqjyy=_gy1Sa8<RovCZA)j<{nuyR#-sNuUj5 z>@AHn5SKw*YE2w#?r4kKs>Z?XY>R~uqV0JIqKlnQKiV?jj;vzb-A!UFvC|z1;?VaU zxZi}|pu1z0R626FJKaqkF!UIL=;nuH&WPQxG#z8Rcm%131P7&w%kQeV#otBjFzabN zh#o$OHV?a_=o5SRpz0ywl6V>o`^%m--=*8$vB%AKnYMTAck^9W+dGay^IcEtJFK!{ z*Izf+K;L6T1~4KK>qvWiV;9H7WjNyQTGfY%<L$;1$FkquZFZ?~;dq(d?!bU{jV31j zDCrDFBeHk}>6#<-8!B$`HxP^Zkq0B&*dt@HN7moC%f74oy)OHz?jJ&qQRZmubJ<H3 zyWeH6)ctn1Hz*ZzIRSH@K8`*1QXkgk7z`gS;{6tP9JOL58wcFI?g3m6I$MFiN7xeZ zQhJpdJ>vS@UU!d~7}iD@-;WVHcuU9Kfb)R5clU1w2j&(Hfi}GYi$w@Mx5Bt2;f%P$ zw=h!X(8r^%7=AorfJH~4wEr=rg3*$s9`&!m^Je4(wv7~HXmd8G-;djZdiMfqs1y*< zspp^_e*6PSLyVn!F$+_snDtR-TY0;=&D?%l$38vOIP7d&*<oUhqo!@;o$f>B2jK`P zW<Gd3!kCp^<}USaWw*JTcPvW`gZ5zU$E*wHIP!Fxdp{mEAA&&hVRIjz$IbofS=Y=7 zDYF|KCZ;*?3d*hSY{_*{avfTq3hmiTr$X+-<|FRm@<ZmMw`0<#eH5i)Tpp7V+Yg%H z5%(eY5i^N>HG%8nxc1@t4qV4^P2;*3*C%k@hwBksx8wRGu8)9LIGVqMV<}`s9QS=v zK=};kf<mOJpr(X05O5K70(Tj_Wa8L@KnVxHEX}|!8&a0AD5X3C&NB?!l|zWPO;u1T za4${<S_3P|c9b1bptYv*O~jothqo-Wy{yZv=)Y14gH1#rj|5UKP5?wS#}RqUs+IHv zm9N#O5kxs~F`%S-%?96>8Hac)pkR=~QaUVHhx@->V-1DTJP%Y14ZaV&zr{bvK1lJP zh^S_LU$&_Y&czTekSzZ0LJnA`fPe@saOO3j_?q<x2reuBQ<2XdMA!uLN}K^|4Rq2< zBWm)sH(*;~J%=Q(_b36Ea)?1T>FfHD`iaY!BcE6yF$|r?7X3@1O3)@BP0hl+O$!gy z*M_RcmHU<YNLI1z_FTdmq|zLw74%N_ShjAAPt>=Zp{^U{;po5bbj7c^cqChoOgvny zKb&qF2Ho#n{qV83{a4@0!S??yH9cActGAw1JNZbuK5&9lCy%?qffQA<BlXV7=O$!* zQmN`ly}P~3N9tXY3(J_UU5=z71dhOQlNZ6nj2o{JwSP_I5;{ns(yUm@3<bu{u*90( zUnyNHR!Va<*eJue`1&$R0A63ISz?r2yiqbCH;r8qf-QX(1Fx9Tpp&MpdUEF#q2Z2U zR1eM6jh*RwYUdS2#2tGbBRx}(>^yhub$utUX#`i!9h*g)@b}fH{hKd8{Tk&Qs5dzS zYj-x$`XxlvFTCy1zDEYJps?~NTQo5(lXsLJj!!hTER_t}Ml4Knpvu3@M51ts#~JI- z`A7+~MXsbMUJ6A7<ui~<IoP%puIE7B;b9C3pyDqyF02gbCk>N8_dO4Tsx2<qUIZY6 z>{q-4(M&@o*n&fdJu{=IyHphpZmd}fkSK}*ah<R7;X13{&fpUaMBW^;D2ui%ri(08 z91u!N(+d^&s)FrQ$$_vt$|o<O7F^DYFT+C^ycx!C%2miqFX0p5uy8Nlgg(D06db=v zeSY{CxuJ-<M-@@`Mb`cM48FiX+Cw(4FnqoAB4l(Y#h}1THE;VE?Jw7yEasxuyFMzz zWPt&T*U|bQ1y?U~KS;s;Z3lA%7ANWEy^M%Vy4NN1a<)oVFmz(PZWss56${twz;*;$ z27biiB&}=`Rk60Qy)Jn^orku|C2AeQoB#|A8}=+rCz}IG1=zD-V_W}-V{nJT4<qn0 zCt6KVA|UOd&H;UE=rOVoS%6+&OF{4qP(53nVR;oNk8%mqb1<CnXU>0Z*l<=LuLvs$ zk`-|+V46$Y(=VtMFVu8@Ycqn8hsy9QnD95PQ-I-ANT$ySo;+*G=p4%XiUBhEtGLmI zY0KdMM+PANj~e&~i5mqu9Zd|A00s$6RRK{JAVK}DWE{!^Z$@F)kQB9n0oW(>#NcuO zHVAY?Fb0bTs0~25AY+Vyc`yIbQM?&2vUnFqDw5sMIL1G1DKbb8#R8DtNn-$Y!<xZ} zzY&e}z#anX1;`_0H`+RYl*168lHiARg|xi~_dWU`>?sC}L8fdW(^bCumL{>jfzenS z@lK`ABz{7?|0zb3!dBOC3?aP@SVlnP>LdOnz#%Xd7bX*?F{?w|N^R#zVA}v)LrDSs zLZciLVj+nVU@K7;Uj@+MgU$kksnFmvqt~L=9XLQqLKK?9H3JekrE;z6D_yG^$mn!6 zBRRU61KN2~7Pa#rLe<JWc<u#b8(t917@qs!2qn_U)WLkGgA?daMu)XVCo~bqd<{hA zhgJkct@6g#Xw*R5QY_mAmN>{!klMRUqtT5YYuE&@3o*Ryg@=QlVa@HO-W}ox-A*&n zPc6+Z2u`~36mv7f8t!}f7QZ1E#Jm5VCBY_NG!V;Z>xh&+ioTG{>O;LC@$G*|;tM03 z1WBn|KZ`u0s{gn{%Q1=&DzHrCNxBJ1^*M@AT##EJs$y>6kOnqJe>E<3^h3X}AJ1Tr zxC0oAP3|Vue%O~xM_bVNlYuKeg~9Vo0D~QT+9oPOvxOD`0B|AysYM;#mnL6@K=CT@ zeV{{uLX7fJ)r!4k!4O9UDCgaWUJ|7L-G^Ul!T1?_0!n=Id3e8jc4A-l@WF#mz!_uU z1W$3<TJfzl{xZdFUmNlW{c7c?6sQ-q0P}FDN~DeyhfQs4c-JFZ)^yKyszx!x8VhK6 zKqaS8^6tx?gc8_15P<z>0H#^e;qlg99B%7{RCQ^|1jO2xJt3Vs1P7P*>Qq}VilIZ$ za0HdJ!?ivvC$isF16%}739MDIu%*pwx^rO;uILKTd_Vl~!99<`z39Ti#Nme@d368b zhaY>qr7IUmINj4q9fu##f2GdZ*6g*6|0cb1AL8dgBD03n0&Xrs+&~HqU#h<6;g)p) zFMHui#nc2?t*k|oDk3@-e3Ii73crIY_qEq~S_v+&atpPlo71q=??6x#mT~bOE|4zf z4x`!Y%_W3vf<Mu~jiW-!vwOrx<H_fRq-YrcAOa<G39DlxS(Gm}ThsZAK^7(4%I;at z?#E6lQhyO6qSQ{|!Lli*X%c3Wv%P=5{|A5K#}<zXSq8j03T-XhI*rpu$Th*M-~0ZF z<Kts3T9tw`3c5&S*5}uoKnV5AUL5X+;0x1>f&w$GKf!w-C$$Rb-#_Jjq_|wPc<=*- zELE>tG=aAMlFw->x0$siP<il;rrNJi*BA|zfHl%#DbOWxAL_+QHZWN00FjLtP|E^5 z4CJTn@j<0D6~USp)c}Rf{0wTa1b0beW#<%}vS?S~>62aph}32LJpH^E#r3?W&w0sU zF1#3)a&8%VqrlH#YQLaxa?mujnvb3n@duh~<<5J_%ek360hHGtLTsY)ex?W(%36fz zAe!+hP{{TqiqWz(2=)CZ8PH0AaV3x(`c#T$jM1n8lp_w!Nuo{Ei3I9m^g;SCfL|O4 z&#*p*a4;Gta@6j3X$?`)rr<^DF2p$~5u;U!3HF>th9i``po9Qh35XF4u-%})DDNY9 ze;Dtf&QQG$(Ex3%#F7EZ3^)<N<boO(6%t&rlrR&w4Kq0)wg`171AsZ7bR*Yrl9K^1 zzcg5=DPjjuv+7v>n2#f5pg0!0Wi(Pgb|BAg>K4@~4D0ut&Rb-t!K;uk)H-3KK)VOn zC-~2PyriOnLYLVMAx7FwuXKqDTZfw_&N4&Wu%7&HVLrl*59zkDiB_kuzn$PARWxty z@$B_dK1;@p@+W!{tTm{%z}d!eYy<ieZSK4K1J<gBw*dg!m|HE|{9Ygnrr@Xrr$X3Q zf?@wiu&?3#vZ`?M>7N@-Agx$3=arJ${llqnAVZ+EP8`41Tpi6@%Ve7jJ*$RRdNh+? z<IJ_y62j}{_7%JLz?rJgEqL)6>j$yY#h1Ub?UtFdUyC6Y5>^<t7a$OaQT|y(G^N_F zAHH8UPcvQpK@O#mz)DY?I1ZE?z~kgI#zfpD*E50?sCK~HT;76b+iNg2dl_pI-tn%R zIR#814gC*n)CUo-7!K?TQiSuSgsWog880l&gFRq9$wEeetI*LbT<^*e4g4!7jF_DD z7gB`qF;A220FCuhRagSnExdxd>kif_#_U3(OYNeLm2T>8$e?<eLXG3Duup;G(g$Tq z5AqWqO@Ow$@MYJ+!}p<*K48N3W4O@<(jdP;kOAJ2pd+znya~xEAff>sEs$Z*D5oDf zNJv2r#sLS@Myvk!dY1=nN?UD^Zxka0byh$nSoY8Yo$9Bcwj8lQH$hq5HU^La&xCeR z9SWagcv4p6kpXR%kSS{Y9DJfBW}(6b;RbBeVgGd$&=UezC*h{e6u*ve8%kPk3XFV& zP)&uRE9nV{DM*v4xHRZ4z|zGl5V~og%#y1VZYHW*QA(Vm#h@hGkhPQ$GdsoJZ4j{; zRW4{We22k@irsDuP_ie4k`S^A6zzjGR(~k&@zaYc>p=b|K)8qS0<Z$2fo$m4{(|q< z{<Lt`L7PB(n*4Mhq$wR%iSSj1!jga*VyCxm+xr8S-<D(nkO)jNNI!x~3HSK-9UzLT z0H`o6&5Du-K$jqcchT>eT$+VH9^pN&<MC6!$CptA8<a>eY@>oo=rZM!@-(gd9p9yv zbMTI(oMYKF_`$kXw5r9566PrADYHYq&$>qVf`*_*Gz9D@1&{Ai8JY5mcdit@))o0S z^_FHAP~CmeEaA9VLx30K#_aDmyubaz*FJj$aQ=~9e|s%+5{PX^xvNzUWxW2@CpZfM zyVIWi*iZ29-#-m-`=f-EG2yqOyus)H?5BPq@;gV>xl#VcGyVbcji;fo!=%=aF}+b; zvIs!V!23^J4YoH>g=-)&GPZM}!VVmf0OpGxQ*K$#l}YO#u$V0j@HHE)zJI-p10RUM z;n4h!10H-C$G-YN=xqPu_Z?O=#*wT=Mg8$Eg}94~Pr_dUUgYA5Gx&szPkMgOQr_ed zQ1Ie7*0D+ySDMG5Vo1l~cLKhwydiM;0n(L!(_9O?9|x7Nmanh_<RJ%V#iv*Xv2Qp- z^|ywXZmwTp_j-x%Rx8spW})YF;{0jxDPRHn)2!VL9%LyJ?Bd;J1m}4`yc0LtC_I~p zXOu9c|A22sQ$&xW;LC~1%^NT!f`1Ys(@?;91IGjo6DsWVsGm{a(d5wG)xnn4K!t70 zI-ZE3&hMuqf%#AwX1>%0h4wErP0C_$OePmBB=A(`J2_0`S$QFjLi3j<LpTDQ6i{Po zt;hk>i1Qf1FX_<uw$s;zc>!9jfd}I#G&b(wsmqMRfr&`}>4p-_x&g#?uZ=}n9r$H{ z0QanFqDS)$98A#qLCw7mm~}99?Q?NZi2X(PhOuxl38$T1VF_1ILLc-cTG|AL+4teO zzrB9969=6T2yn)^uFZVw_Mz=yj6r*LfQK8LZ5oZi#!&V1NWW=)X_9^z8a;#1_yFq> zPBgXh5VUt-`fdLtMnpL<eI2pGcga0kA9P1i-$-kHAVl_n5E+5J$JZ4p;*Kh<o5mo< zWYmR*Qe#LFCD2M<H_~BWps@r~<q>x?+SZa2I#Jy~8>lf17ABB@A-AXPxz|j<EV_5` z>nM9nyhUe3W9O&vyk&h);F@!6Wvkl_24{!c3A6Lm$^&k9Ig95EpBMin44UN)n2<pX ztX>2G$$%IGBC<Gxm9fRy=0Xbu2+J90Q6=21m@!!?FCE5AJkZEOk7~<xx*;`8eU@tl zseu@6aUVc0vb<szx55FavG_;$ecp|stecHav}iltVveChwSympy3K2X*Ty!y-5I=f zw_y!zcT#Zwy4|Gyy5YARJHRBHHDbLNZ+C@nr9V|_uTz_gt4Ly?w=)V|m5B98<Odo= zB9C`u8Jql~S9ktdY}@b<X&T{yu@?9=1lN>!OVdlV&x^t5Sm=$K9|Eb^wUDzK7FG?? zy<I9WP?3Hs`U?8e5L#1l;x0$>rNF)!9{?bC2(Vq;xA~45^Xrd&bw&rLe$e{2Joj5D zvSxJwiy31s7$SN;B66`IGl`W6f!94c1Y;svw4C6XN|+x_THUxr5&;Tp0z$aC*D zwA9<yoZaLd*XDOOF)t<63N_o`68j?k4cD7$P~KJ}@UbF%fZ}bC^5l%c86>F4BkTPp zoySX#2N$r<R|E0cq6Kd|=3O&i!e=SqkQ`rID}vDh&OFH0w<>GW+K&Sfo<5$y#X6zx zzruSmx0=RBaL^ve2y>`k{B{a$C~QaMpCj(FyJ?(leU|yfoVh1hUBNtvjKAqq(4x`f z8mmi7{2$5Z5$5=Ip22$&crkGFoMmOHSz_!WF^($lewx7+21Nv3iYrSI#%W<m3I=4A zn0^~mon)$Bur=u?rp22cQ9Q*ZjpO@&;L2K$F=hY(^wn);CuQ>qJ^{_~9g58UZ!9et z>_KHh-qpSUy@bz(QeK-n!gY|F1}ngy*4(u9V=O8y`d`ZVT`Eio*}k97i>tzDAWkz0 zi!HK#k-@u|AIjJ{I>qZaTLmoumNwGR$LMA2pR(!kWo%9`Xk*KqP%j2S2sp_<hnz|e zdzyDZ+Td$2tUQ;mRFwZH{hFs=_d1mJLe8q)ur2zBT7&sP?2fh(2;`+RKSCt%r%<Lg znuhRJbgkcr#?>_*R~pvoH{vlMf<XPcAfg=ruOJGc@*qUUxWW>4E5ySCaHE%r3_@5e zy4!D(2MghDL~PI@)`h4SDTg8YC9;XS@FVYaKt#X;s2dyz#g!0LltOE~H3rZoa3hAB zsAYQxycnc>rRf64CHU*cO$tA*Ci{;N;H;<hShNi0YXfWsy7&RE6J5m{e8eQU1H%Er zNEoW)B#p~?yF$xZuo2>}IF0EB1_?o|Ji&zu^pAzrx>Z=Mu8-fyTlFqrwn9HK?WVvw zNJ1Q}vn&W~5w75S7-n?U5FC-XWVf3EKGca8^}v>iI@eubtO6foYBL7RfR=Fh?239? ze20ABBA(YbVk%rXy<f@Fl-i=`TeN`0?}R_#ZyFkliY@jU&BL?uZ9>_V@}))|@1V8h zYl`_Qlqzdhf$Rg7m;NgXHT8`%x>u^rw4EXF_yVq<h+=5*-8@P*W;O&(YZq{l7*xXm zVp4qOg}RF8k6#ck)7TU6A=BonkKP(^Al%)`NY<WG!eTG5wfv8bt)tzq?v}Lp@KqC$ zxfg#KEC%H$8dB@FApz@RCgduIZ@dTyTyR~Z1<0U9`%g{_FS49F1eX@0*a+gKLk<F8 z{|4qK*jX@ovq+J9ow7(mRiCsx%J*5l9=g_nw@(y(U8r7lJ}eQ&e1_nwEBub7KzQX9 zH9iN@y>LxzQ-uX8r004|l&9IaXV`=eHGz|KB!Vx*LOBQqbLJ_`y!8s-Cm^(<pFF5$ zG43ZB7Zc?iFMR?QLbCR3<vx^Pbu9qw^KDNRESC=Mi~&yUK|$I8nV<kT08Vt0(PL0p zlmQrnX$im_wPBzg)5aWKUtF752sTMg$66j9KpRBxqb)1gqof^Q`Yb2{y0pSaC;%6f z<z%Am32v_ZwC_b)us@lbDT%4WY7!Rs;S;swr4*q)CXt?0sR30BUD9-|BtRj7MXD%M zIEzY>-htbuj&cgr6CjdMi@i|C;O96%^+1<8Db!DO@hQZ>aVX+oPs{6KA02Xt+oo8a zCx5sen{)sXCmCtA2V1tl+XO;k*~E3#Ot-*;yW(IMlrU5wZDASr+J507dsm!LkU>$l z@G&}UKp*C|b(gK>Uw|lVR3P?AJDwP#iFYY9>_>B}U$$Pw1i<a&f8xS_FIJn{r1X(u zeV)M$#{D+${*ZUS#DJ4F-mg%mPa%Sc2zzGzGSmGE0&(L@%tcwD+th>hQcR;TmZaPY z(sH(nbk=8?Q+A*1PrVFbHB0;=3rqP_Rqhf|9q7|ozs}^sosxhoDz8VK^K^@(B){+C zF5Qk-T0fByc;%(vT!z$o6Eq@84K$()Eg#ESTTFo^wEp4f)Ski59!Aji@n!Ir@EK!> zDL~`KT77A*^SE9A!EiRt1|K{UAW2l8ez~ATd>lOI=UcpVXMJ6amfdg(nk@yWMbA0T zf_>z`0fC+THUl`}HzuI$av*=;u}2TR<MAgB9D2vWcN~7?(Z|Dj+uZp@(3MaaeH0J% zE)mASifz?+7o6b(V=<P2L-XGOE(ALg#L)qdOM5FLuDys<2Q@m*R}R~wqHgMS<Z|G< zLqT>vm$N>DlC4J&_#Z*?qI^MdKTz8>6Kef;O!95cVHz1UpotXH_v!WBP1J7PxZ-1F zVQrJ+F@EigXL2s*rE~P>v{d1JCYOUsL&blS$mPsh0j*<&EsY45mK=2-U`vQJLQgU- zF>PR*Z#am8LY~8o8a|O_LDvr7!o$~;;3pDcISLd~UE`1^>E$HMrx=@RKIPITav`om zyr)L;7tpqF>cpW5&=1<4L!y}%zBB|Z6oQ8z>VPDOF2aQfMOuZv`yaD-`(ht~ozG2| z0f{z{5D;4u+$=;g1biVl&;9t8`6NY{FYM#JfGxg(*K{M#4`$xIWf+DM2zAx&mfZu@ z8(1;Wr_cv6VajQ*AUz{|B;jlQA_6ZNbY79H2l?V748%9aFXJxoMhd@?{)fGK*R`)@ zWeL0*;Oq!t<vSXKu)_YwTxC?K*Lq=kDk4_8;sV#)XmeS*LDshANd9;nKQ2l8%LvqR zEQ@dz_t?R551&EA1<Em~MMA*@XTCVsvY){{9e2ag7AT%Xm5Q74JWEwh#C%Z0hm3#~ zygw;^HQ?t0y!472fsphlK6gdV`umVS4SUBZ?qcw{5eGLN!c=h7;rf%G-f$_{g>uR; zpb0igin)O;P$l*Y$lFQvSMVJp))$ZupZ%g|prKG97VSx}HB>4AyiMjwJcr9i3F`t& zjBKbQNX%kGw+Ky?-o{eqt_jOp_p!T{HFSUY2)*fJeXdolI2Cxm4H-Ova-siy-LMHw z*ADATS;r1+Y2Lkd5tPr>=N5dfXILTk?{R(=FQCInesS=GNNa^3ZLV?!Kw`NOi?y$W z>khM|JBCB>2M#c7bYa&BJoX51O{h4*!$%COA%eMu3u%{Jd4w@oPO3Mnuz{xgdD<p# z!IB0JIp&g&Y)mR8y12qxgy|y)i;J3}y+)^jDWw~R@1~AN@jbu%%~Nox2v;^Z9H(nO zC&a{eP-H`gAm2-!&n+!Dwe$I#|Cw7-9YJZJ4So7{y}qw`1g-gkMe}PdVFBW0Qe=+S zhX@}A(Kzc(1mitxS!N&QdjUMZ${x_S57ag=<XPr<oWWrR1Uyt#nWeVK4Q3i+^ur9^ zgJ8TvVQ11Q(H2Rd=QNb?63CL{7(`*UVp)HS%wB@a007JSYd)ozLgdQI`a%ZfZ&-=I zt?o5F{zZ;Y7L{uKqTElre4tsG1OS*Z3L+>9N8{klw0S;TQwAJE5a?N4HsWDjaVKS@ zBpBig;#+6N`Bk1X>N0tGT*n=xzmsR+0eNy#goTK)K8NPw!a~PKtUqJpzsle>27k_A zH%mOu;7JA_VsMkezhE%KK$x08&AU%BpcREh%|YvZyrW3e`geT%JqCZw;MW*O!r1yN zJ}&Z3hOZfL46R-S+wilWK>&o}q~KM$_N{bpdT;tY+R@~J<Y=-pIg{R=d@@}{%&Fvj z`bngEGySZD@4*4_aPmM;cY2GIHa_7c;TM!j7O+hLgj-lvi|c=~A-{rZyk6`F8WDl} zg%81sIT60C$*Xk~iM&m|Ces8kZ|H^dOEV}<k>#*<DWSwaK{*!BlxAXRY*7J^TI2W< z5BI<I5tKGH5R?Xi0QB0_83&z!mM06|+%#`ENVrx6Y++$(UiNOUCj!ZO&$^7Su+P8F z+;Myv3jLL@tH`IE<f!-dwtYBvBK$UiYNb5^g)RT%p0>Ev_V(N(!)yh<NomF?9?HFa z_ed@@25bv*77$W#J?K4jk1SB$hMFr(i69!Vc)WWD?l(sz5A`$X{8R7BJ93X)P33WF zk`?B#1ab>Ymc0aM(a8et)lexPe0t7$)A0zuVNe0TELfwmXgAs$Uh=5I)1Ts6vL_G( X?l%ZtK(YD%eZCe!@XRZi#_|6P0+p{e literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/wrapper.cpython-311.pyc b/examples/analytical-function/bayesvalidrox/surrogate_models/__pycache__/wrapper.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a6d61c979e164a0fd590b3f925c2d1ac68adb4fc GIT binary patch literal 10433 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 LLnU{FOrHM&T=ouO literal 0 HcmV?d00001 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/adaptPlot.py b/examples/analytical-function/bayesvalidrox/surrogate_models/adaptPlot.py new file mode 100644 index 000000000..102f0373c --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/surrogate_models/adaptPlot.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Thu Aug 13 13:46:24 2020 + +@author: farid +""" +import os +from sklearn.metrics import mean_squared_error, r2_score +from itertools import cycle +from matplotlib.backends.backend_pdf import PdfPages +import matplotlib.pyplot as plt + + +def adaptPlot(PCEModel, Y_Val, Y_PC_Val, Y_PC_Val_std, x_values=[], + plotED=False, SaveFig=True): + + NrofSamples = PCEModel.ExpDesign.n_new_samples + initNSamples = PCEModel.ExpDesign.n_init_samples + itrNr = 1 + (PCEModel.ExpDesign.X.shape[0] - initNSamples)//NrofSamples + + oldEDY = PCEModel.ExpDesign.Y + + if SaveFig: + newpath = 'adaptivePlots' + os.makedirs(newpath, exist_ok=True) + + # create a PdfPages object + pdf = PdfPages(f'./{newpath}/Model_vs_PCEModel_itr_{itrNr}.pdf') + + # List of markers and colors + color = cycle((['b', 'g', 'r', 'y', 'k'])) + marker = cycle(('x', 'd', '+', 'o', '*')) + + OutNames = list(Y_Val.keys()) + x_axis = 'Time [s]' + + if len(OutNames) == 1: + OutNames.insert(0, x_axis) + try: + x_values = Y_Val['x_values'] + except KeyError: + x_values = x_values + + fig = plt.figure(figsize=(24, 16)) + + # Plot the model vs PCE model + for keyIdx, key in enumerate(PCEModel.ModelObj.Output.names): + Y_PC_Val_ = Y_PC_Val[key] + Y_PC_Val_std_ = Y_PC_Val_std[key] + Y_Val_ = Y_Val[key] + if Y_Val_.ndim == 1: + Y_Val_ = Y_Val_.reshape(1, -1) + old_EDY = oldEDY[key] + if isinstance(x_values, dict): + x = x_values[key] + else: + x = x_values + + for idx, y in enumerate(Y_Val_): + Color = next(color) + Marker = next(marker) + + plt.plot( + x, y, color=Color, marker=Marker, + lw=2.0, label='$Y_{%s}^{M}$'%(idx+itrNr) + ) + + plt.plot( + x, Y_PC_Val_[idx], color=Color, marker=Marker, + lw=2.0, linestyle='--', label='$Y_{%s}^{PCE}$'%(idx+itrNr) + ) + plt.fill_between( + x, Y_PC_Val_[idx]-1.96*Y_PC_Val_std_[idx], + Y_PC_Val_[idx]+1.96*Y_PC_Val_std_[idx], color=Color, + alpha=0.15 + ) + + if plotED: + for output in old_EDY: + plt.plot(x, output, color='grey', alpha=0.1) + + # Calculate the RMSE + RMSE = mean_squared_error(Y_PC_Val_, Y_Val_, squared=False) + R2 = r2_score(Y_PC_Val_.reshape(-1, 1), Y_Val_.reshape(-1, 1)) + + plt.ylabel(key) + plt.xlabel(x_axis) + plt.title(key) + + ax = fig.axes[0] + ax.legend(loc='best', frameon=True) + fig.canvas.draw() + ax.text(0.65, 0.85, + f'RMSE = {round(RMSE, 3)}\n$R^2$ = {round(R2, 3)}', + transform=ax.transAxes, color='black', + bbox=dict(facecolor='none', + edgecolor='black', + boxstyle='round,pad=1') + ) + plt.grid() + + if SaveFig: + # save the current figure + pdf.savefig(fig, bbox_inches='tight') + + # Destroy the current plot + plt.clf() + pdf.close() diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/apoly_construction.py b/examples/analytical-function/bayesvalidrox/surrogate_models/apoly_construction.py new file mode 100644 index 000000000..40830fe8a --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/surrogate_models/apoly_construction.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +import numpy as np + + +def apoly_construction(Data, degree): + """ + Construction of Data-driven Orthonormal Polynomial Basis + Author: Dr.-Ing. habil. Sergey Oladyshkin + Department of Stochastic Simulation and Safety Research for Hydrosystems + Institute for Modelling Hydraulic and Environmental Systems + Universitaet Stuttgart, Pfaffenwaldring 5a, 70569 Stuttgart + E-mail: Sergey.Oladyshkin@iws.uni-stuttgart.de + http://www.iws-ls3.uni-stuttgart.de + The current script is based on definition of arbitrary polynomial chaos + expansion (aPC), which is presented in the following manuscript: + Oladyshkin, S. and W. Nowak. Data-driven uncertainty quantification using + the arbitrary polynomial chaos expansion. Reliability Engineering & System + Safety, Elsevier, V. 106, P. 179-190, 2012. + DOI: 10.1016/j.ress.2012.05.002. + + Parameters + ---------- + Data : array + Raw data. + degree : int + Maximum polynomial degree. + + Returns + ------- + Polynomial : array + The coefficients of the univariate orthonormal polynomials. + + """ + if Data.ndim !=1: + raise AttributeError('Data should be a 1D array') + + # Initialization + dd = degree + 1 + nsamples = len(Data) + + # Forward linear transformation (Avoiding numerical issues) + MeanOfData = np.mean(Data) + Data = Data/MeanOfData + + # Compute raw moments of input data + raw_moments = [np.sum(np.power(Data, p))/nsamples for p in range(2*dd+2)] + + # Main Loop for Polynomial with degree up to dd + PolyCoeff_NonNorm = np.empty((0, 1)) + Polynomial = np.zeros((dd+1, dd+1)) + + for degree in range(dd+1): + Mm = np.zeros((degree+1, degree+1)) + Vc = np.zeros((degree+1)) + + # Define Moments Matrix Mm + for i in range(degree+1): + for j in range(degree+1): + if (i < degree): + Mm[i, j] = raw_moments[i+j] + + elif (i == degree) and (j == degree): + Mm[i, j] = 1 + + # Numerical Optimization for Matrix Solver + Mm[i] = Mm[i] / max(abs(Mm[i])) + + # Defenition of Right Hand side ortogonality conditions: Vc + for i in range(degree+1): + Vc[i] = 1 if i == degree else 0 + + # Solution: Coefficients of Non-Normal Orthogonal Polynomial: Vp Eq.(4) + try: + Vp = np.linalg.solve(Mm, Vc) + except: + inv_Mm = np.linalg.pinv(Mm) + Vp = np.dot(inv_Mm, Vc.T) + + if degree == 0: + PolyCoeff_NonNorm = np.append(PolyCoeff_NonNorm, Vp) + + if degree != 0: + if degree == 1: + zero = [0] + else: + zero = np.zeros((degree, 1)) + PolyCoeff_NonNorm = np.hstack((PolyCoeff_NonNorm, zero)) + + PolyCoeff_NonNorm = np.vstack((PolyCoeff_NonNorm, Vp)) + + if 100*abs(sum(abs(np.dot(Mm, Vp)) - abs(Vc))) > 0.5: + print('\n---> Attention: Computational Error too high !') + print('\n---> Problem: Convergence of Linear Solver') + + # Original Numerical Normalization of Coefficients with Norm and + # orthonormal Basis computation Matrix Storrage + # Note: Polynomial(i,j) correspont to coefficient number "j-1" + # of polynomial degree "i-1" + P_norm = 0 + for i in range(nsamples): + Poly = 0 + for k in range(degree+1): + if degree == 0: + Poly += PolyCoeff_NonNorm[k] * (Data[i]**k) + else: + Poly += PolyCoeff_NonNorm[degree, k] * (Data[i]**k) + + P_norm += Poly**2 / nsamples + + P_norm = np.sqrt(P_norm) + + for k in range(degree+1): + if degree == 0: + Polynomial[degree, k] = PolyCoeff_NonNorm[k]/P_norm + else: + Polynomial[degree, k] = PolyCoeff_NonNorm[degree, k]/P_norm + + # Backward linear transformation to the real data space + Data *= MeanOfData + for k in range(len(Polynomial)): + Polynomial[:, k] = Polynomial[:, k] / (MeanOfData**(k)) + + return Polynomial diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/bayes_linear.py b/examples/analytical-function/bayesvalidrox/surrogate_models/bayes_linear.py new file mode 100644 index 000000000..3bd827ac0 --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/surrogate_models/bayes_linear.py @@ -0,0 +1,523 @@ +import numpy as np +from sklearn.base import RegressorMixin +from sklearn.linear_model._base import LinearModel +from sklearn.utils import check_X_y, check_array, as_float_array +from sklearn.utils.validation import check_is_fitted +from scipy.linalg import svd +import warnings +from sklearn.preprocessing import normalize as f_normalize + + + +class BayesianLinearRegression(RegressorMixin,LinearModel): + ''' + Superclass for Empirical Bayes and Variational Bayes implementations of + Bayesian Linear Regression Model + ''' + def __init__(self, n_iter, tol, fit_intercept,copy_X, verbose): + self.n_iter = n_iter + self.fit_intercept = fit_intercept + self.copy_X = copy_X + self.verbose = verbose + self.tol = tol + + + def _check_convergence(self, mu, mu_old): + ''' + Checks convergence of algorithm using changes in mean of posterior + distribution of weights + ''' + return np.sum(abs(mu-mu_old)>self.tol) == 0 + + + def _center_data(self,X,y): + ''' Centers data''' + X = as_float_array(X,copy = self.copy_X) + # normalisation should be done in preprocessing! + X_std = np.ones(X.shape[1], dtype = X.dtype) + if self.fit_intercept: + X_mean = np.average(X,axis = 0) + y_mean = np.average(y,axis = 0) + X -= X_mean + y = y - y_mean + else: + X_mean = np.zeros(X.shape[1],dtype = X.dtype) + y_mean = 0. if y.ndim == 1 else np.zeros(y.shape[1], dtype=X.dtype) + return X,y, X_mean, y_mean, X_std + + + def predict_dist(self,X): + ''' + Calculates mean and variance of predictive distribution for each data + point of test set.(Note predictive distribution for each data point is + Gaussian, therefore it is uniquely determined by mean and variance) + + Parameters + ---------- + x: array-like of size (n_test_samples, n_features) + Set of features for which corresponding responses should be predicted + + Returns + ------- + :list of two numpy arrays [mu_pred, var_pred] + + mu_pred : numpy array of size (n_test_samples,) + Mean of predictive distribution + + var_pred: numpy array of size (n_test_samples,) + Variance of predictive distribution + ''' + # Note check_array and check_is_fitted are done within self._decision_function(X) + mu_pred = self._decision_function(X) + data_noise = 1./self.beta_ + model_noise = np.sum(np.dot(X,self.eigvecs_)**2 * self.eigvals_,1) + var_pred = data_noise + model_noise + return [mu_pred,var_pred] + + + + +class EBLinearRegression(BayesianLinearRegression): + ''' + Bayesian Regression with type II maximum likelihood (Empirical Bayes) + + Parameters: + ----------- + n_iter: int, optional (DEFAULT = 300) + Maximum number of iterations + + tol: float, optional (DEFAULT = 1e-3) + Threshold for convergence + + optimizer: str, optional (DEFAULT = 'fp') + Method for optimization , either Expectation Maximization or + Fixed Point Gull-MacKay {'em','fp'}. Fixed point iterations are + faster, but can be numerically unstable (especially in case of near perfect fit). + + fit_intercept: bool, optional (DEFAULT = True) + If True includes bias term in model + + perfect_fit_tol: float (DEAFAULT = 1e-5) + Prevents overflow of precision parameters (this is smallest value RSS can have). + ( !!! Note if using EM instead of fixed-point, try smaller values + of perfect_fit_tol, for better estimates of variance of predictive distribution ) + + alpha: float (DEFAULT = 1) + Initial value of precision paramter for coefficients ( by default we define + very broad distribution ) + + copy_X : boolean, optional (DEFAULT = True) + If True, X will be copied, otherwise will be + + verbose: bool, optional (Default = False) + If True at each iteration progress report is printed out + + Attributes + ---------- + coef_ : array, shape = (n_features) + Coefficients of the regression model (mean of posterior distribution) + + intercept_: float + Value of bias term (if fit_intercept is False, then intercept_ = 0) + + alpha_ : float + Estimated precision of coefficients + + beta_ : float + Estimated precision of noise + + eigvals_ : array, shape = (n_features, ) + Eigenvalues of covariance matrix (from posterior distribution of weights) + + eigvecs_ : array, shape = (n_features, n_featues) + Eigenvectors of covariance matrix (from posterior distribution of weights) + + ''' + + def __init__(self,n_iter = 300, tol = 1e-3, optimizer = 'fp', fit_intercept = True, + normalize=True, perfect_fit_tol = 1e-6, alpha = 1, copy_X = True, verbose = False): + super(EBLinearRegression,self).__init__(n_iter, tol, fit_intercept, copy_X, verbose) + if optimizer not in ['em','fp']: + raise ValueError('Optimizer can be either "em" or "fp" ') + self.optimizer = optimizer + self.alpha = alpha + self.perfect_fit = False + self.normalize = True + self.scores_ = [np.NINF] + self.perfect_fit_tol = perfect_fit_tol + + def _check_convergence(self, mu, mu_old): + ''' + Checks convergence of algorithm using changes in mean of posterior + distribution of weights + ''' + return np.sum(abs(mu-mu_old)>self.tol) == 0 + + + def _center_data(self,X,y): + ''' Centers data''' + X = as_float_array(X,copy = self.copy_X) + # normalisation should be done in preprocessing! + X_std = np.ones(X.shape[1], dtype = X.dtype) + if self.fit_intercept: + X_mean = np.average(X, axis=0) + X -= X_mean + if self.normalize: + X, X_std = f_normalize(X, axis=0, copy=False, + return_norm=True) + else: + X_std = np.ones(X.shape[1], dtype=X.dtype) + y_mean = np.average(y, axis=0) + y = y - y_mean + else: + X_mean = np.zeros(X.shape[1],dtype = X.dtype) + y_mean = 0. if y.ndim == 1 else np.zeros(y.shape[1], dtype=X.dtype) + return X,y, X_mean, y_mean, X_std + + def fit(self, X, y): + ''' + Fits Bayesian Linear Regression using Empirical Bayes + + Parameters + ---------- + X: array-like of size [n_samples,n_features] + Matrix of explanatory variables (should not include bias term) + + y: array-like of size [n_features] + Vector of dependent variables. + + Returns + ------- + object: self + self + + ''' + # preprocess data + X, y = check_X_y(X, y, dtype=np.float64, y_numeric=True) + n_samples, n_features = X.shape + X, y, X_mean, y_mean, X_std = self._center_data(X, y) + self._x_mean_ = X_mean + self._y_mean = y_mean + self._x_std = X_std + + # precision of noise & and coefficients + alpha = self.alpha + var_y = np.var(y) + # check that variance is non zero !!! + if var_y == 0 : + beta = 1e-2 + else: + beta = 1. / np.var(y) + + # to speed all further computations save svd decomposition and reuse it later + u,d,vt = svd(X, full_matrices = False) + Uy = np.dot(u.T,y) + dsq = d**2 + mu = 0 + + for i in range(self.n_iter): + + # find mean for posterior of w ( for EM this is E-step) + mu_old = mu + if n_samples > n_features: + mu = vt.T * d/(dsq+alpha/beta) + else: + # clever use of SVD here , faster for large n_features + mu = u * 1./(dsq + alpha/beta) + mu = np.dot(X.T,mu) + mu = np.dot(mu,Uy) + + # precompute errors, since both methods use it in estimation + error = y - np.dot(X,mu) + sqdErr = np.sum(error**2) + + if sqdErr / n_samples < self.perfect_fit_tol: + self.perfect_fit = True + warnings.warn( ('Almost perfect fit!!! Estimated values of variance ' + 'for predictive distribution are computed using only RSS')) + break + + if self.optimizer == "fp": + gamma = np.sum(beta*dsq/(beta*dsq + alpha)) + # use updated mu and gamma parameters to update alpha and beta + # !!! made computation numerically stable for perfect fit case + alpha = gamma / (np.sum(mu**2) + np.finfo(np.float32).eps ) + beta = ( n_samples - gamma ) / (sqdErr + np.finfo(np.float32).eps ) + else: + # M-step, update parameters alpha and beta to maximize ML TYPE II + eigvals = 1. / (beta * dsq + alpha) + alpha = n_features / ( np.sum(mu**2) + np.sum(1/eigvals) ) + beta = n_samples / ( sqdErr + np.sum(dsq/eigvals) ) + + # if converged or exceeded maximum number of iterations => terminate + converged = self._check_convergence(mu_old,mu) + if self.verbose: + print( "Iteration {0} completed".format(i) ) + if converged is True: + print("Algorithm converged after {0} iterations".format(i)) + if converged or i==self.n_iter -1: + break + eigvals = 1./(beta * dsq + alpha) + self.coef_ = beta*np.dot(vt.T*d*eigvals ,Uy) + self._set_intercept(X_mean,y_mean,X_std) + self.beta_ = beta + self.alpha_ = alpha + self.eigvals_ = eigvals + self.eigvecs_ = vt.T + + # set intercept_ + if self.fit_intercept: + self.coef_ = self.coef_ / X_std + self.intercept_ = y_mean - np.dot(X_mean, self.coef_.T) + else: + self.intercept_ = 0. + + return self + + def predict(self,X, return_std=False): + ''' + Computes predictive distribution for test set. + Predictive distribution for each data point is one dimensional + Gaussian and therefore is characterised by mean and variance. + + Parameters + ----------- + X: {array-like, sparse} (n_samples_test, n_features) + Test data, matrix of explanatory variables + + Returns + ------- + : list of length two [y_hat, var_hat] + + y_hat: numpy array of size (n_samples_test,) + Estimated values of targets on test set (i.e. mean of predictive + distribution) + + var_hat: numpy array of size (n_samples_test,) + Variance of predictive distribution + ''' + y_hat = np.dot(X,self.coef_) + self.intercept_ + + if return_std: + if self.normalize: + X = (X - self._x_mean_) / self._x_std + data_noise = 1./self.beta_ + model_noise = np.sum(np.dot(X,self.eigvecs_)**2 * self.eigvals_,1) + var_pred = data_noise + model_noise + std_hat = np.sqrt(var_pred) + return y_hat, std_hat + else: + return y_hat + + +# ============================== VBLR ========================================= + +def gamma_mean(a,b): + ''' + Computes mean of gamma distribution + + Parameters + ---------- + a: float + Shape parameter of Gamma distribution + + b: float + Rate parameter of Gamma distribution + + Returns + ------- + : float + Mean of Gamma distribution + ''' + return float(a) / b + + + +class VBLinearRegression(BayesianLinearRegression): + ''' + Implements Bayesian Linear Regression using mean-field approximation. + Assumes gamma prior on precision parameters of coefficients and noise. + + Parameters: + ----------- + n_iter: int, optional (DEFAULT = 100) + Maximum number of iterations for KL minimization + + tol: float, optional (DEFAULT = 1e-3) + Convergence threshold + + fit_intercept: bool, optional (DEFAULT = True) + If True will use bias term in model fitting + + a: float, optional (Default = 1e-4) + Shape parameter of Gamma prior for precision of coefficients + + b: float, optional (Default = 1e-4) + Rate parameter of Gamma prior for precision coefficients + + c: float, optional (Default = 1e-4) + Shape parameter of Gamma prior for precision of noise + + d: float, optional (Default = 1e-4) + Rate parameter of Gamma prior for precision of noise + + verbose: bool, optional (Default = False) + If True at each iteration progress report is printed out + + Attributes + ---------- + coef_ : array, shape = (n_features) + Coefficients of the regression model (mean of posterior distribution) + + intercept_: float + Value of bias term (if fit_intercept is False, then intercept_ = 0) + + alpha_ : float + Mean of precision of coefficients + + beta_ : float + Mean of precision of noise + + eigvals_ : array, shape = (n_features, ) + Eigenvalues of covariance matrix (from posterior distribution of weights) + + eigvecs_ : array, shape = (n_features, n_featues) + Eigenvectors of covariance matrix (from posterior distribution of weights) + + ''' + + def __init__(self, n_iter = 100, tol =1e-4, fit_intercept = True, + a = 1e-4, b = 1e-4, c = 1e-4, d = 1e-4, copy_X = True, + verbose = False): + super(VBLinearRegression,self).__init__(n_iter, tol, fit_intercept, copy_X, + verbose) + self.a,self.b = a, b + self.c,self.d = c, d + + + def fit(self,X,y): + ''' + Fits Variational Bayesian Linear Regression Model + + Parameters + ---------- + X: array-like of size [n_samples,n_features] + Matrix of explanatory variables (should not include bias term) + + Y: array-like of size [n_features] + Vector of dependent variables. + + Returns + ------- + object: self + self + ''' + # preprocess data + X, y = check_X_y(X, y, dtype=np.float64, y_numeric=True) + n_samples, n_features = X.shape + X, y, X_mean, y_mean, X_std = self._center_data(X, y) + self._x_mean_ = X_mean + self._y_mean = y_mean + self._x_std = X_std + + # SVD decomposition, done once , reused at each iteration + u,D,vt = svd(X, full_matrices = False) + dsq = D**2 + UY = np.dot(u.T,y) + + # some parameters of Gamma distribution have closed form solution + a = self.a + 0.5 * n_features + c = self.c + 0.5 * n_samples + b,d = self.b, self.d + + # initial mean of posterior for coefficients + mu = 0 + + for i in range(self.n_iter): + + # update parameters of distribution Q(weights) + e_beta = gamma_mean(c,d) + e_alpha = gamma_mean(a,b) + mu_old = np.copy(mu) + mu,eigvals = self._posterior_weights(e_beta,e_alpha,UY,dsq,u,vt,D,X) + + # update parameters of distribution Q(precision of weights) + b = self.b + 0.5*( np.sum(mu**2) + np.sum(eigvals)) + + # update parameters of distribution Q(precision of likelihood) + sqderr = np.sum((y - np.dot(X,mu))**2) + xsx = np.sum(dsq*eigvals) + d = self.d + 0.5*(sqderr + xsx) + + # check convergence + converged = self._check_convergence(mu,mu_old) + if self.verbose is True: + print("Iteration {0} is completed".format(i)) + if converged is True: + print("Algorithm converged after {0} iterations".format(i)) + + # terminate if convergence or maximum number of iterations are achieved + if converged or i==(self.n_iter-1): + break + + # save necessary parameters + self.beta_ = gamma_mean(c,d) + self.alpha_ = gamma_mean(a,b) + self.coef_, self.eigvals_ = self._posterior_weights(self.beta_, self.alpha_, UY, + dsq, u, vt, D, X) + self._set_intercept(X_mean,y_mean,X_std) + self.eigvecs_ = vt.T + return self + + + def _posterior_weights(self, e_beta, e_alpha, UY, dsq, u, vt, d, X): + ''' + Calculates parameters of approximate posterior distribution + of weights + ''' + # eigenvalues of covariance matrix + sigma = 1./ (e_beta*dsq + e_alpha) + + # mean of approximate posterior distribution + n_samples, n_features = X.shape + if n_samples > n_features: + mu = vt.T * d/(dsq + e_alpha/e_beta)# + np.finfo(np.float64).eps) + else: + mu = u * 1./(dsq + e_alpha/e_beta)# + np.finfo(np.float64).eps) + mu = np.dot(X.T,mu) + mu = np.dot(mu,UY) + return mu,sigma + + def predict(self,X, return_std=False): + ''' + Computes predictive distribution for test set. + Predictive distribution for each data point is one dimensional + Gaussian and therefore is characterised by mean and variance. + + Parameters + ----------- + X: {array-like, sparse} (n_samples_test, n_features) + Test data, matrix of explanatory variables + + Returns + ------- + : list of length two [y_hat, var_hat] + + y_hat: numpy array of size (n_samples_test,) + Estimated values of targets on test set (i.e. mean of predictive + distribution) + + var_hat: numpy array of size (n_samples_test,) + Variance of predictive distribution + ''' + x = (X - self._x_mean_) / self._x_std + y_hat = np.dot(x,self.coef_) + self._y_mean + + if return_std: + data_noise = 1./self.beta_ + model_noise = np.sum(np.dot(X,self.eigvecs_)**2 * self.eigvals_,1) + var_pred = data_noise + model_noise + std_hat = np.sqrt(var_pred) + return y_hat, std_hat + else: + return y_hat \ No newline at end of file diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/desktop.ini b/examples/analytical-function/bayesvalidrox/surrogate_models/desktop.ini new file mode 100644 index 000000000..632de13ae --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/surrogate_models/desktop.ini @@ -0,0 +1,2 @@ +[LocalizedFileNames] +exploration.py=@exploration.py,0 diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/engine.py b/examples/analytical-function/bayesvalidrox/surrogate_models/engine.py new file mode 100644 index 000000000..387cec501 --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/surrogate_models/engine.py @@ -0,0 +1,2233 @@ +# -*- coding: utf-8 -*- +""" +Engine to train the surrogate + +""" +import copy +from copy import deepcopy, copy +import h5py +import joblib +import numpy as np +import os + +from scipy import stats, signal, linalg, sparse +from scipy.spatial import distance +from tqdm import tqdm +import scipy.optimize as opt +from sklearn.metrics import mean_squared_error +import multiprocessing +import matplotlib.pyplot as plt +import pandas as pd +import sys +import seaborn as sns +from joblib import Parallel, delayed + + +from bayesvalidrox.bayes_inference.bayes_inference import BayesInference +from bayesvalidrox.bayes_inference.discrepancy import Discrepancy +from .exploration import Exploration +import pathlib + +#from .inputs import Input +#from .exp_designs import ExpDesigns +#from .surrogate_models import MetaModel +#from bayesvalidrox.post_processing.post_processing import PostProcessing + +def hellinger_distance(P, Q): + """ + Hellinger distance between two continuous distributions. + + The maximum distance 1 is achieved when P assigns probability zero to + every set to which Q assigns a positive probability, and vice versa. + 0 (identical) and 1 (maximally different) + + Parameters + ---------- + P : array + Reference likelihood. + Q : array + Estimated likelihood. + + Returns + ------- + float + Hellinger distance of two distributions. + + """ + P = np.array(P) + Q= np.array(Q) + + mu1 = P.mean() + Sigma1 = np.std(P) + + mu2 = Q.mean() + Sigma2 = np.std(Q) + + term1 = np.sqrt(2*Sigma1*Sigma2 / (Sigma1**2 + Sigma2**2)) + + term2 = np.exp(-.25 * (mu1 - mu2)**2 / (Sigma1**2 + Sigma2**2)) + + H_squared = 1 - term1 * term2 + + return np.sqrt(H_squared) + + +def logpdf(x, mean, cov): + """ + Computes the likelihood based on a multivariate normal distribution. + + Parameters + ---------- + x : TYPE + DESCRIPTION. + mean : array_like + Observation data. + cov : 2d array + Covariance matrix of the distribution. + + Returns + ------- + log_lik : float + Log likelihood. + + """ + n = len(mean) + L = linalg.cholesky(cov, lower=True) + beta = np.sum(np.log(np.diag(L))) + dev = x - mean + alpha = dev.dot(linalg.cho_solve((L, True), dev)) + log_lik = -0.5 * alpha - beta - n / 2. * np.log(2 * np.pi) + + return log_lik + +def subdomain(Bounds, n_new_samples): + """ + Divides a domain defined by Bounds into sub domains. + + Parameters + ---------- + Bounds : list of tuples + List of lower and upper bounds. + n_new_samples : int + Number of samples to divide the domain for. + n_params : int + The number of params to build the subdomains for + + Returns + ------- + Subdomains : List of tuples of tuples + Each tuple of tuples divides one set of bounds into n_new_samples parts. + + """ + n_params = len(Bounds) + n_subdomains = n_new_samples + 1 + LinSpace = np.zeros((n_params, n_subdomains)) + + for i in range(n_params): + LinSpace[i] = np.linspace(start=Bounds[i][0], stop=Bounds[i][1], + num=n_subdomains) + Subdomains = [] + for k in range(n_subdomains-1): + mylist = [] + for i in range(n_params): + mylist.append((LinSpace[i, k+0], LinSpace[i, k+1])) + Subdomains.append(tuple(mylist)) + + return Subdomains + +class Engine(): + + + def __init__(self, MetaMod, Model, ExpDes): + self.MetaModel = MetaMod + self.Model = Model + self.ExpDesign = ExpDes + self.parallel = False + self.trained = False + + def start_engine(self) -> None: + """ + Do all the preparations that need to be run before the actual training + + Returns + ------- + None + + """ + self.out_names = self.Model.Output.names + self.MetaModel.out_names = self.out_names + + + def train_normal(self, parallel = False, verbose = False, save = False) -> None: + """ + Trains surrogate on static samples only. + Samples are taken from the experimental design and the specified + model is run on them. + Alternatively the samples can be read in from a provided hdf5 file. + + + Returns + ------- + None + + """ + + ExpDesign = self.ExpDesign + MetaModel = self.MetaModel + + # Read ExpDesign (training and targets) from the provided hdf5 + if ExpDesign.hdf5_file is not None: + # TODO: need to run 'generate_ED' as well after this or not? + ExpDesign.read_from_file(self.out_names) + else: + # Check if an old hdf5 file exists: if yes, rename it + hdf5file = f'ExpDesign_{self.Model.name}.hdf5' + if os.path.exists(hdf5file): + # os.rename(hdf5file, 'old_'+hdf5file) + file = pathlib.Path(hdf5file) + file.unlink() + + # Prepare X samples + # For training the surrogate use ExpDesign.X_tr, ExpDesign.X is for the model to run on + ExpDesign.generate_ED(ExpDesign.n_init_samples, + transform=True, + max_pce_deg=np.max(MetaModel.pce_deg)) + + # Run simulations at X + if not hasattr(ExpDesign, 'Y') or ExpDesign.Y is None: + print('\n Now the forward model needs to be run!\n') + ED_Y, up_ED_X = self.Model.run_model_parallel(ExpDesign.X, mp = parallel) + ExpDesign.Y = ED_Y + else: + # Check if a dict has been passed. + if not type(ExpDesign.Y) is dict: + raise Exception('Please provide either a dictionary or a hdf5' + 'file to ExpDesign.hdf5_file argument.') + + # Separate output dict and x-values + if 'x_values' in ExpDesign.Y: + ExpDesign.x_values = ExpDesign.Y['x_values'] + del ExpDesign.Y['x_values'] + else: + print('No x_values are given, this might lead to issues during PostProcessing') + + + # Fit the surrogate + MetaModel.fit(ExpDesign.X, ExpDesign.Y, parallel, verbose) + + # Save what there is to save + if save: + # Save surrogate + with open(f'surrogates/surrogate_{self.Model.name}.pk1', 'wb') as output: + joblib.dump(MetaModel, output, 2) + + # Zip the model run directories + if self.Model.link_type.lower() == 'pylink' and\ + self.ExpDesign.sampling_method.lower() != 'user': + self.Model.zip_subdirs(self.Model.name, f'{self.Model.name}_') + + # Set that training was done + self.trained = True + + + def train_sequential(self, parallel = False, verbose = False) -> None: + """ + Train the surrogate in a sequential manner. + First build and train evereything on the static samples, then iterate + choosing more samples and refitting the surrogate on them. + + Returns + ------- + None + + """ + #self.train_normal(parallel, verbose) + self.parallel = parallel + self.train_seq_design(parallel, verbose) + + + # ------------------------------------------------------------------------- + def eval_metamodel(self, samples=None, nsamples=None, + sampling_method='random', return_samples=False): + """ + Evaluates meta-model at the requested samples. One can also generate + nsamples. + + Parameters + ---------- + samples : array of shape (n_samples, n_params), optional + Samples to evaluate meta-model at. The default is None. + nsamples : int, optional + Number of samples to generate, if no `samples` is provided. The + default is None. + sampling_method : str, optional + Type of sampling, if no `samples` is provided. The default is + 'random'. + return_samples : bool, optional + Retun samples, if no `samples` is provided. The default is False. + + Returns + ------- + mean_pred : dict + Mean of the predictions. + std_pred : dict + Standard deviatioon of the predictions. + """ + # Generate or transform (if need be) samples + if samples is None: + # Generate + samples = self.ExpDesign.generate_samples( + nsamples, + sampling_method + ) + + # Transformation to other space is to be done in the MetaModel + # TODO: sort the transformations better + mean_pred, std_pred = self.MetaModel.eval_metamodel(samples) + + if return_samples: + return mean_pred, std_pred, samples + else: + return mean_pred, std_pred + + + # ------------------------------------------------------------------------- + def train_seq_design(self, parallel = False, verbose = False): + """ + Starts the adaptive sequential design for refining the surrogate model + by selecting training points in a sequential manner. + + Returns + ------- + MetaModel : object + Meta model object. + + """ + self.parallel = parallel + + # Initialization + self.SeqModifiedLOO = {} + self.seqValidError = {} + self.SeqBME = {} + self.SeqKLD = {} + self.SeqDistHellinger = {} + self.seqRMSEMean = {} + self.seqRMSEStd = {} + self.seqMinDist = [] + + if not hasattr(self.MetaModel, 'valid_samples'): + self.ExpDesign.valid_samples = [] + self.ExpDesign.valid_model_runs = [] + self.valid_likelihoods = [] + + validError = None + + + # Determine the metamodel type + if self.MetaModel.meta_model_type.lower() != 'gpe': + pce = True + else: + pce = False + mc_ref = True if bool(self.Model.mc_reference) else False + if mc_ref: + self.Model.read_observation('mc_ref') + + # Get the parameters + max_n_samples = self.ExpDesign.n_max_samples + mod_LOO_threshold = self.ExpDesign.mod_LOO_threshold + n_canddidate = self.ExpDesign.n_canddidate + post_snapshot = self.ExpDesign.post_snapshot + n_replication = self.ExpDesign.n_replication + util_func = self.ExpDesign.util_func + output_name = self.out_names + + # Handle if only one UtilityFunctions is provided + if not isinstance(util_func, list): + util_func = [self.ExpDesign.util_func] + + # Read observations or MCReference + # TODO: recheck the logic in this if statement + if (len(self.Model.observations) != 0 or self.Model.meas_file is not None) and hasattr(self.MetaModel, 'Discrepancy'): + self.observations = self.Model.read_observation() + obs_data = self.observations + else: + obs_data = [] + # TODO: TotalSigma2 not defined if not in this else??? + # TODO: no self.observations if in here + TotalSigma2 = {} + + # ---------- Initial self.MetaModel ---------- + if not self.trained: + self.train_normal(parallel = parallel, verbose=verbose) + + initMetaModel = deepcopy(self.MetaModel) + + # Validation error if validation set is provided. + if self.ExpDesign.valid_model_runs: + init_rmse, init_valid_error = self._validError(initMetaModel) + init_valid_error = list(init_valid_error.values()) + else: + init_rmse = None + + # Check if discrepancy is provided + if len(obs_data) != 0 and hasattr(self.MetaModel, 'Discrepancy'): + TotalSigma2 = self.MetaModel.Discrepancy.parameters + + # Calculate the initial BME + out = self._BME_Calculator( + obs_data, TotalSigma2, init_rmse) + init_BME, init_KLD, init_post, init_likes, init_dist_hellinger = out + print(f"\nInitial BME: {init_BME:.2f}") + print(f"Initial KLD: {init_KLD:.2f}") + + # Posterior snapshot (initial) + if post_snapshot: + parNames = self.ExpDesign.par_names + print('Posterior snapshot (initial) is being plotted...') + self.__posteriorPlot(init_post, parNames, 'SeqPosterior_init') + + # Check the convergence of the Mean & Std + if mc_ref and pce: + init_rmse_mean, init_rmse_std = self._error_Mean_Std() + print(f"Initial Mean and Std error: {init_rmse_mean:.2f}," + f" {init_rmse_std:.2f}") + + # Read the initial experimental design + Xinit = self.ExpDesign.X + init_n_samples = len(self.ExpDesign.X) + initYprev = self.ExpDesign.Y#initMetaModel.ModelOutputDict + #self.MetaModel.ModelOutputDict = self.ExpDesign.Y + initLCerror = initMetaModel.LCerror + n_itrs = max_n_samples - init_n_samples + + ## Get some initial statistics + # Read the initial ModifiedLOO + if pce: + Scores_all, varExpDesignY = [], [] + for out_name in output_name: + y = self.ExpDesign.Y[out_name] + Scores_all.append(list( + self.MetaModel.score_dict['b_1'][out_name].values())) + if self.MetaModel.dim_red_method.lower() == 'pca': + pca = self.MetaModel.pca['b_1'][out_name] + components = pca.transform(y) + varExpDesignY.append(np.var(components, axis=0)) + else: + varExpDesignY.append(np.var(y, axis=0)) + + Scores = [item for sublist in Scores_all for item in sublist] + weights = [item for sublist in varExpDesignY for item in sublist] + init_mod_LOO = [np.average([1-score for score in Scores], + weights=weights)] + + prevMetaModel_dict = {} + #prevExpDesign_dict = {} + # Can run sequential design multiple times for comparison + for repIdx in range(n_replication): + print(f'\n>>>> Replication: {repIdx+1}<<<<') + + # util_func: the function to use inside the type of exploitation + for util_f in util_func: + print(f'\n>>>> Utility Function: {util_f} <<<<') + # To avoid changes ub original aPCE object + self.ExpDesign.X = Xinit + self.ExpDesign.Y = initYprev + self.ExpDesign.LCerror = initLCerror + + # Set the experimental design + Xprev = Xinit + total_n_samples = init_n_samples + Yprev = initYprev + + Xfull = [] + Yfull = [] + + # Store the initial ModifiedLOO + if pce: + print("\nInitial ModifiedLOO:", init_mod_LOO) + SeqModifiedLOO = np.array(init_mod_LOO) + + if len(self.ExpDesign.valid_model_runs) != 0: + SeqValidError = np.array(init_valid_error) + + # Check if data is provided + if len(obs_data) != 0 and hasattr(self.MetaModel, 'Discrepancy'): + SeqBME = np.array([init_BME]) + SeqKLD = np.array([init_KLD]) + SeqDistHellinger = np.array([init_dist_hellinger]) + + if mc_ref and pce: + seqRMSEMean = np.array([init_rmse_mean]) + seqRMSEStd = np.array([init_rmse_std]) + + # ------- Start Sequential Experimental Design ------- + postcnt = 1 + for itr_no in range(1, n_itrs+1): + print(f'\n>>>> Iteration number {itr_no} <<<<') + + # Save the metamodel prediction before updating + prevMetaModel_dict[itr_no] = deepcopy(self.MetaModel) + #prevExpDesign_dict[itr_no] = deepcopy(self.ExpDesign) + if itr_no > 1: + pc_model = prevMetaModel_dict[itr_no-1] + self._y_hat_prev, _ = pc_model.eval_metamodel( + samples=Xfull[-1].reshape(1, -1)) + del prevMetaModel_dict[itr_no-1] + + # Optimal Bayesian Design + #self.MetaModel.ExpDesignFlag = 'sequential' + Xnew, updatedPrior = self.choose_next_sample(TotalSigma2, + n_canddidate, + util_f) + S = np.min(distance.cdist(Xinit, Xnew, 'euclidean')) + self.seqMinDist.append(S) + print(f"\nmin Dist from OldExpDesign: {S:2f}") + print("\n") + + # Evaluate the full model response at the new sample + Ynew, _ = self.Model.run_model_parallel( + Xnew, prevRun_No=total_n_samples + ) + total_n_samples += Xnew.shape[0] + + # ------ Plot the surrogate model vs Origninal Model ------ + if hasattr(self.ExpDesign, 'adapt_verbose') and \ + self.ExpDesign.adapt_verbose: + from .adaptPlot import adaptPlot + y_hat, std_hat = self.MetaModel.eval_metamodel( + samples=Xnew + ) + adaptPlot( + self.MetaModel, Ynew, y_hat, std_hat, + plotED=False + ) + + # -------- Retrain the surrogate model ------- + # Extend new experimental design + Xfull = np.vstack((Xprev, Xnew)) + + # Updating experimental design Y + for out_name in output_name: + Yfull = np.vstack((Yprev[out_name], Ynew[out_name])) + self.ExpDesign.Y[out_name] = Yfull + + # Pass new design to the metamodel object + self.ExpDesign.sampling_method = 'user' + self.ExpDesign.X = Xfull + #self.ExpDesign.Y = self.MetaModel.ModelOutputDict + + # Save the Experimental Design for next iteration + Xprev = Xfull + Yprev = self.ExpDesign.Y + + # Pass the new prior as the input + # TODO: another look at this - no difference apc to pce to gpe? + self.MetaModel.input_obj.poly_coeffs_flag = False + if updatedPrior is not None: + self.MetaModel.input_obj.poly_coeffs_flag = True + print("updatedPrior:", updatedPrior.shape) + # Arbitrary polynomial chaos + for i in range(updatedPrior.shape[1]): + self.MetaModel.input_obj.Marginals[i].dist_type = None + x = updatedPrior[:, i] + self.MetaModel.input_obj.Marginals[i].raw_data = x + + # Train the surrogate model for new ExpDesign + self.train_normal(parallel=False) + + # -------- Evaluate the retrained surrogate model ------- + # Extract Modified LOO from Output + if pce: + Scores_all, varExpDesignY = [], [] + for out_name in output_name: + y = self.ExpDesign.Y[out_name] + Scores_all.append(list( + self.MetaModel.score_dict['b_1'][out_name].values())) + if self.MetaModel.dim_red_method.lower() == 'pca': + pca = self.MetaModel.pca['b_1'][out_name] + components = pca.transform(y) + varExpDesignY.append(np.var(components, + axis=0)) + else: + varExpDesignY.append(np.var(y, axis=0)) + Scores = [item for sublist in Scores_all for item + in sublist] + weights = [item for sublist in varExpDesignY for item + in sublist] + ModifiedLOO = [np.average( + [1-score for score in Scores], weights=weights)] + + print('\n') + print(f"Updated ModifiedLOO {util_f}:\n", ModifiedLOO) + print('\n') + + # Compute the validation error + if self.ExpDesign.valid_model_runs: + rmse, validError = self._validError(self.MetaModel) + ValidError = list(validError.values()) + else: + rmse = None + + # Store updated ModifiedLOO + if pce: + SeqModifiedLOO = np.vstack( + (SeqModifiedLOO, ModifiedLOO)) + if len(self.ExpDesign.valid_model_runs) != 0: + SeqValidError = np.vstack( + (SeqValidError, ValidError)) + # -------- Caclulation of BME as accuracy metric ------- + # Check if data is provided + if len(obs_data) != 0: + # Calculate the initial BME + out = self._BME_Calculator(obs_data, TotalSigma2, rmse) + BME, KLD, Posterior, likes, DistHellinger = out + print('\n') + print(f"Updated BME: {BME:.2f}") + print(f"Updated KLD: {KLD:.2f}") + print('\n') + + # Plot some snapshots of the posterior + step_snapshot = self.ExpDesign.step_snapshot + if post_snapshot and postcnt % step_snapshot == 0: + parNames = self.ExpDesign.par_names + print('Posterior snapshot is being plotted...') + self.__posteriorPlot(Posterior, parNames, + f'SeqPosterior_{postcnt}') + postcnt += 1 + + # Check the convergence of the Mean&Std + if mc_ref and pce: + print('\n') + RMSE_Mean, RMSE_std = self._error_Mean_Std() + print(f"Updated Mean and Std error: {RMSE_Mean:.2f}, " + f"{RMSE_std:.2f}") + print('\n') + + # Store the updated BME & KLD + # Check if data is provided + if len(obs_data) != 0: + SeqBME = np.vstack((SeqBME, BME)) + SeqKLD = np.vstack((SeqKLD, KLD)) + SeqDistHellinger = np.vstack((SeqDistHellinger, + DistHellinger)) + if mc_ref and pce: + seqRMSEMean = np.vstack((seqRMSEMean, RMSE_Mean)) + seqRMSEStd = np.vstack((seqRMSEStd, RMSE_std)) + + if pce and any(LOO < mod_LOO_threshold + for LOO in ModifiedLOO): + break + + # Clean up + if len(obs_data) != 0: + del out + print() + print('-'*50) + print() + + # Store updated ModifiedLOO and BME in dictonary + strKey = f'{util_f}_rep_{repIdx+1}' + if pce: + self.SeqModifiedLOO[strKey] = SeqModifiedLOO + if len(self.ExpDesign.valid_model_runs) != 0: + self.seqValidError[strKey] = SeqValidError + + # Check if data is provided + if len(obs_data) != 0: + self.SeqBME[strKey] = SeqBME + self.SeqKLD[strKey] = SeqKLD + if hasattr(self.MetaModel, 'valid_likelihoods') and \ + self.valid_likelihoods: + self.SeqDistHellinger[strKey] = SeqDistHellinger + if mc_ref and pce: + self.seqRMSEMean[strKey] = seqRMSEMean + self.seqRMSEStd[strKey] = seqRMSEStd + + # return self.MetaModel + + # ------------------------------------------------------------------------- + def util_VarBasedDesign(self, X_can, index, util_func='Entropy'): + """ + Computes the exploitation scores based on: + active learning MacKay(ALM) and active learning Cohn (ALC) + Paper: Sequential Design with Mutual Information for Computer + Experiments (MICE): Emulation of a Tsunami Model by Beck and Guillas + (2016) + + Parameters + ---------- + X_can : array of shape (n_samples, n_params) + Candidate samples. + index : int + Model output index. + UtilMethod : string, optional + Exploitation utility function. The default is 'Entropy'. + + Returns + ------- + float + Score. + + """ + MetaModel = self.MetaModel + ED_X = self.ExpDesign.X + out_dict_y = self.ExpDesign.Y + out_names = self.out_names + + # Run the Metamodel for the candidate + X_can = X_can.reshape(1, -1) + Y_PC_can, std_PC_can = MetaModel.eval_metamodel(samples=X_can) + + if util_func.lower() == 'alm': + # ----- Entropy/MMSE/active learning MacKay(ALM) ----- + # Compute perdiction variance of the old model + canPredVar = {key: std_PC_can[key]**2 for key in out_names} + + varPCE = np.zeros((len(out_names), X_can.shape[0])) + for KeyIdx, key in enumerate(out_names): + varPCE[KeyIdx] = np.max(canPredVar[key], axis=1) + score = np.max(varPCE, axis=0) + + elif util_func.lower() == 'eigf': + # ----- Expected Improvement for Global fit ----- + # Find closest EDX to the candidate + distances = distance.cdist(ED_X, X_can, 'euclidean') + index = np.argmin(distances) + + # Compute perdiction error and variance of the old model + predError = {key: Y_PC_can[key] for key in out_names} + canPredVar = {key: std_PC_can[key]**2 for key in out_names} + + # Compute perdiction error and variance of the old model + # Eq (5) from Liu et al.(2018) + EIGF_PCE = np.zeros((len(out_names), X_can.shape[0])) + for KeyIdx, key in enumerate(out_names): + residual = predError[key] - out_dict_y[key][int(index)] + var = canPredVar[key] + EIGF_PCE[KeyIdx] = np.max(residual**2 + var, axis=1) + score = np.max(EIGF_PCE, axis=0) + + return -1 * score # -1 is for minimization instead of maximization + + # ------------------------------------------------------------------------- + def util_BayesianActiveDesign(self, y_hat, std, sigma2Dict, var='DKL'): + """ + Computes scores based on Bayesian active design criterion (var). + + It is based on the following paper: + Oladyshkin, Sergey, Farid Mohammadi, Ilja Kroeker, and Wolfgang Nowak. + "Bayesian3 active learning for the gaussian process emulator using + information theory." Entropy 22, no. 8 (2020): 890. + + Parameters + ---------- + X_can : array of shape (n_samples, n_params) + Candidate samples. + sigma2Dict : dict + A dictionary containing the measurement errors (sigma^2). + var : string, optional + BAL design criterion. The default is 'DKL'. + + Returns + ------- + float + Score. + + """ + + # Get the data + obs_data = self.observations + # TODO: this should be optimizable to be calculated explicitly + if hasattr(self.Model, 'n_obs'): + n_obs = self.Model.n_obs + else: + n_obs = self.n_obs + mc_size = 10000 + + # Sample a distribution for a normal dist + # with Y_mean_can as the mean and Y_std_can as std. + Y_MC, std_MC = {}, {} + logPriorLikelihoods = np.zeros((mc_size)) + # print(y_hat) + # print(list[y_hat]) + #print(std) + for key in list(y_hat): + #print(std[key]) + cov = np.diag(std[key]**2) + #print(y_hat[key], cov) + print(key, y_hat[key], std[key]) + # TODO: added the allow_singular = True here + rv = stats.multivariate_normal(mean=y_hat[key], cov=cov,allow_singular = True) + Y_MC[key] = rv.rvs(size=mc_size) + logPriorLikelihoods += rv.logpdf(Y_MC[key]) + std_MC[key] = np.zeros((mc_size, y_hat[key].shape[0])) + + # Likelihood computation (Comparison of data and simulation + # results via PCE with candidate design) + likelihoods = self._normpdf(Y_MC, std_MC, obs_data, sigma2Dict) + + # Rejection Step + # Random numbers between 0 and 1 + unif = np.random.rand(1, mc_size)[0] + + # Reject the poorly performed prior + accepted = (likelihoods/np.max(likelihoods)) >= unif + + # Prior-based estimation of BME + logBME = np.log(np.nanmean(likelihoods), dtype=np.longdouble)#float128) + + # Posterior-based expectation of likelihoods + postLikelihoods = likelihoods[accepted] + postExpLikelihoods = np.mean(np.log(postLikelihoods)) + + # Posterior-based expectation of prior densities + postExpPrior = np.mean(logPriorLikelihoods[accepted]) + + # Utility function Eq.2 in Ref. (2) + # Posterior covariance matrix after observing data y + # Kullback-Leibler Divergence (Sergey's paper) + if var == 'DKL': + + # TODO: Calculate the correction factor for BME + # BMECorrFactor = self.BME_Corr_Weight(PCE_SparseBayes_can, + # ObservationData, sigma2Dict) + # BME += BMECorrFactor + # Haun et al implementation + # U_J_d = np.mean(np.log(Likelihoods[Likelihoods!=0])- logBME) + U_J_d = postExpLikelihoods - logBME + + # Marginal log likelihood + elif var == 'BME': + U_J_d = np.nanmean(likelihoods) + + # Entropy-based information gain + elif var == 'infEntropy': + logBME = np.log(np.nanmean(likelihoods)) + infEntropy = logBME - postExpPrior - postExpLikelihoods + U_J_d = infEntropy * -1 # -1 for minimization + + # Bayesian information criterion + elif var == 'BIC': + coeffs = self.MetaModel.coeffs_dict.values() + nModelParams = max(len(v) for val in coeffs for v in val.values()) + maxL = np.nanmax(likelihoods) + U_J_d = -2 * np.log(maxL) + np.log(n_obs) * nModelParams + + # Akaike information criterion + elif var == 'AIC': + coeffs = self.MetaModel.coeffs_dict.values() + nModelParams = max(len(v) for val in coeffs for v in val.values()) + maxlogL = np.log(np.nanmax(likelihoods)) + AIC = -2 * maxlogL + 2 * nModelParams + # 2 * nModelParams * (nModelParams+1) / (n_obs-nModelParams-1) + penTerm = 0 + U_J_d = 1*(AIC + penTerm) + + # Deviance information criterion + elif var == 'DIC': + # D_theta_bar = np.mean(-2 * Likelihoods) + N_star_p = 0.5 * np.var(np.log(likelihoods[likelihoods != 0])) + Likelihoods_theta_mean = self._normpdf( + y_hat, std, obs_data, sigma2Dict + ) + DIC = -2 * np.log(Likelihoods_theta_mean) + 2 * N_star_p + + U_J_d = DIC + + else: + print('The algorithm you requested has not been implemented yet!') + + # Handle inf and NaN (replace by zero) + if np.isnan(U_J_d) or U_J_d == -np.inf or U_J_d == np.inf: + U_J_d = 0.0 + + # Clear memory + del likelihoods + del Y_MC + del std_MC + + return -1 * U_J_d # -1 is for minimization instead of maximization + + # ------------------------------------------------------------------------- + def util_BayesianDesign(self, X_can, X_MC, sigma2Dict, var='DKL'): + """ + Computes scores based on Bayesian sequential design criterion (var). + + Parameters + ---------- + X_can : array of shape (n_samples, n_params) + Candidate samples. + sigma2Dict : dict + A dictionary containing the measurement errors (sigma^2). + var : string, optional + Bayesian design criterion. The default is 'DKL'. + + Returns + ------- + float + Score. + + """ + + # To avoid changes ub original aPCE object + MetaModel = self.MetaModel + out_names = self.out_names + if X_can.ndim == 1: + X_can = X_can.reshape(1, -1) + + # Compute the mean and std based on the MetaModel + # pce_means, pce_stds = self._compute_pce_moments(MetaModel) + if var == 'ALC': + Y_MC, Y_MC_std = MetaModel.eval_metamodel(samples=X_MC) + + # Old Experimental design + oldExpDesignX = self.ExpDesign.X + oldExpDesignY = self.ExpDesign.Y + + # Evaluate the PCE metamodels at that location ??? + Y_PC_can, Y_std_can = MetaModel.eval_metamodel(samples=X_can) + PCE_Model_can = deepcopy(MetaModel) + engine_can = deepcopy(self) + # Add the candidate to the ExpDesign + NewExpDesignX = np.vstack((oldExpDesignX, X_can)) + + NewExpDesignY = {} + for key in oldExpDesignY.keys(): + NewExpDesignY[key] = np.vstack( + (oldExpDesignY[key], Y_PC_can[key]) + ) + + engine_can.ExpDesign.sampling_method = 'user' + engine_can.ExpDesign.X = NewExpDesignX + #engine_can.ModelOutputDict = NewExpDesignY + engine_can.ExpDesign.Y = NewExpDesignY + + # Train the model for the observed data using x_can + engine_can.MetaModel.input_obj.poly_coeffs_flag = False + engine_can.start_engine() + engine_can.train_normal(parallel=False) + engine_can.MetaModel.fit(NewExpDesignX, NewExpDesignY) +# engine_can.train_norm_design(parallel=False) + + # Set the ExpDesign to its original values + engine_can.ExpDesign.X = oldExpDesignX + engine_can.ModelOutputDict = oldExpDesignY + engine_can.ExpDesign.Y = oldExpDesignY + + if var.lower() == 'mi': + # Mutual information based on Krause et al + # Adapted from Beck & Guillas (MICE) paper + _, std_PC_can = engine_can.MetaModel.eval_metamodel(samples=X_can) + std_can = {key: std_PC_can[key] for key in out_names} + + std_old = {key: Y_std_can[key] for key in out_names} + + varPCE = np.zeros((len(out_names))) + for i, key in enumerate(out_names): + varPCE[i] = np.mean(std_old[key]**2/std_can[key]**2) + score = np.mean(varPCE) + + return -1 * score + + elif var.lower() == 'alc': + # Active learning based on Gramyc and Lee + # Adaptive design and analysis of supercomputer experiments Techno- + # metrics, 51 (2009), pp. 130–145. + + # Evaluate the MetaModel at the given samples + Y_MC_can, Y_MC_std_can = engine_can.MetaModel.eval_metamodel(samples=X_MC) + + # Compute the score + score = [] + for i, key in enumerate(out_names): + pce_var = Y_MC_std_can[key]**2 + pce_var_can = Y_MC_std[key]**2 + score.append(np.mean(pce_var-pce_var_can, axis=0)) + score = np.mean(score) + + return -1 * score + + # ---------- Inner MC simulation for computing Utility Value ---------- + # Estimation of the integral via Monte Varlo integration + MCsize = X_MC.shape[0] + ESS = 0 + + while ((ESS > MCsize) or (ESS < 1)): + + # Enriching Monte Carlo samples if need be + if ESS != 0: + X_MC = self.ExpDesign.generate_samples( + MCsize, 'random' + ) + + # Evaluate the MetaModel at the given samples + Y_MC, std_MC = PCE_Model_can.eval_metamodel(samples=X_MC) + + # Likelihood computation (Comparison of data and simulation + # results via PCE with candidate design) + likelihoods = self._normpdf( + Y_MC, std_MC, self.observations, sigma2Dict + ) + + # Check the Effective Sample Size (1<ESS<MCsize) + ESS = 1 / np.sum(np.square(likelihoods/np.sum(likelihoods))) + + # Enlarge sample size if it doesn't fulfill the criteria + if ((ESS > MCsize) or (ESS < 1)): + print("--- increasing MC size---") + MCsize *= 10 + ESS = 0 + + # Rejection Step + # Random numbers between 0 and 1 + unif = np.random.rand(1, MCsize)[0] + + # Reject the poorly performed prior + accepted = (likelihoods/np.max(likelihoods)) >= unif + + # -------------------- Utility functions -------------------- + # Utility function Eq.2 in Ref. (2) + # Kullback-Leibler Divergence (Sergey's paper) + if var == 'DKL': + + # Prior-based estimation of BME + logBME = np.log(np.nanmean(likelihoods, dtype=np.longdouble))#float128)) + + # Posterior-based expectation of likelihoods + postLikelihoods = likelihoods[accepted] + postExpLikelihoods = np.mean(np.log(postLikelihoods)) + + # Haun et al implementation + U_J_d = np.mean(np.log(likelihoods[likelihoods != 0]) - logBME) + + # U_J_d = np.sum(G_n_m_all) + # Ryan et al (2014) implementation + # importanceWeights = Likelihoods[Likelihoods!=0]/np.sum(Likelihoods[Likelihoods!=0]) + # U_J_d = np.mean(importanceWeights*np.log(Likelihoods[Likelihoods!=0])) - logBME + + # U_J_d = postExpLikelihoods - logBME + + # Marginal likelihood + elif var == 'BME': + + # Prior-based estimation of BME + logBME = np.log(np.nanmean(likelihoods)) + U_J_d = logBME + + # Bayes risk likelihood + elif var == 'BayesRisk': + + U_J_d = -1 * np.var(likelihoods) + + # Entropy-based information gain + elif var == 'infEntropy': + # Prior-based estimation of BME + logBME = np.log(np.nanmean(likelihoods)) + + # Posterior-based expectation of likelihoods + postLikelihoods = likelihoods[accepted] + postLikelihoods /= np.nansum(likelihoods[accepted]) + postExpLikelihoods = np.mean(np.log(postLikelihoods)) + + # Posterior-based expectation of prior densities + postExpPrior = np.mean(logPriorLikelihoods[accepted]) + + infEntropy = logBME - postExpPrior - postExpLikelihoods + + U_J_d = infEntropy * -1 # -1 for minimization + + # D-Posterior-precision + elif var == 'DPP': + X_Posterior = X_MC[accepted] + # covariance of the posterior parameters + U_J_d = -np.log(np.linalg.det(np.cov(X_Posterior))) + + # A-Posterior-precision + elif var == 'APP': + X_Posterior = X_MC[accepted] + # trace of the posterior parameters + U_J_d = -np.log(np.trace(np.cov(X_Posterior))) + + else: + print('The algorithm you requested has not been implemented yet!') + + # Clear memory + del likelihoods + del Y_MC + del std_MC + + return -1 * U_J_d # -1 is for minimization instead of maximization + + + # ------------------------------------------------------------------------- + def run_util_func(self, method, candidates, index, sigma2Dict=None, + var=None, X_MC=None): + """ + Runs the utility function based on the given method. + + Parameters + ---------- + method : string + Exploitation method: `VarOptDesign`, `BayesActDesign` and + `BayesOptDesign`. + candidates : array of shape (n_samples, n_params) + All candidate parameter sets. + index : int + ExpDesign index. + sigma2Dict : dict, optional + A dictionary containing the measurement errors (sigma^2). The + default is None. + var : string, optional + Utility function. The default is None. + X_MC : TYPE, optional + DESCRIPTION. The default is None. + + Returns + ------- + index : TYPE + DESCRIPTION. + List + Scores. + + """ + + if method.lower() == 'varoptdesign': + # U_J_d = self.util_VarBasedDesign(candidates, index, var) + U_J_d = np.zeros((candidates.shape[0])) + for idx, X_can in tqdm(enumerate(candidates), ascii=True, + desc="varoptdesign"): + U_J_d[idx] = self.util_VarBasedDesign(X_can, index, var) + + elif method.lower() == 'bayesactdesign': + NCandidate = candidates.shape[0] + U_J_d = np.zeros((NCandidate)) + # Evaluate all candidates + y_can, std_can = self.MetaModel.eval_metamodel(samples=candidates) + # loop through candidates + for idx, X_can in tqdm(enumerate(candidates), ascii=True, + desc="BAL Design"): + y_hat = {key: items[idx] for key, items in y_can.items()} + std = {key: items[idx] for key, items in std_can.items()} + + # print(y_hat) + # print(std) + U_J_d[idx] = self.util_BayesianActiveDesign( + y_hat, std, sigma2Dict, var) + + elif method.lower() == 'bayesoptdesign': + NCandidate = candidates.shape[0] + U_J_d = np.zeros((NCandidate)) + for idx, X_can in tqdm(enumerate(candidates), ascii=True, + desc="OptBayesianDesign"): + U_J_d[idx] = self.util_BayesianDesign(X_can, X_MC, sigma2Dict, + var) + return (index, -1 * U_J_d) + + # ------------------------------------------------------------------------- + def dual_annealing(self, method, Bounds, sigma2Dict, var, Run_No, + verbose=False): + """ + Exploration algorithm to find the optimum parameter space. + + Parameters + ---------- + method : string + Exploitation method: `VarOptDesign`, `BayesActDesign` and + `BayesOptDesign`. + Bounds : list of tuples + List of lower and upper boundaries of parameters. + sigma2Dict : dict + A dictionary containing the measurement errors (sigma^2). + Run_No : int + Run number. + verbose : bool, optional + Print out a summary. The default is False. + + Returns + ------- + Run_No : int + Run number. + array + Optimial candidate. + + """ + + Model = self.Model + max_func_itr = self.ExpDesign.max_func_itr + + if method == 'VarOptDesign': + Res_Global = opt.dual_annealing(self.util_VarBasedDesign, + bounds=Bounds, + args=(Model, var), + maxfun=max_func_itr) + + elif method == 'BayesOptDesign': + Res_Global = opt.dual_annealing(self.util_BayesianDesign, + bounds=Bounds, + args=(Model, sigma2Dict, var), + maxfun=max_func_itr) + + if verbose: + print(f"Global minimum: xmin = {Res_Global.x}, " + f"f(xmin) = {Res_Global.fun:.6f}, nfev = {Res_Global.nfev}") + + return (Run_No, Res_Global.x) + + # ------------------------------------------------------------------------- + def tradeoff_weights(self, tradeoff_scheme, old_EDX, old_EDY): + """ + Calculates weights for exploration scores based on the requested + scheme: `None`, `equal`, `epsilon-decreasing` and `adaptive`. + + `None`: No exploration. + `equal`: Same weights for exploration and exploitation scores. + `epsilon-decreasing`: Start with more exploration and increase the + influence of exploitation along the way with a exponential decay + function + `adaptive`: An adaptive method based on: + Liu, Haitao, Jianfei Cai, and Yew-Soon Ong. "An adaptive sampling + approach for Kriging metamodeling by maximizing expected prediction + error." Computers & Chemical Engineering 106 (2017): 171-182. + + Parameters + ---------- + tradeoff_scheme : string + Trade-off scheme for exloration and exploitation scores. + old_EDX : array (n_samples, n_params) + Old experimental design (training points). + old_EDY : dict + Old model responses (targets). + + Returns + ------- + exploration_weight : float + Exploration weight. + exploitation_weight: float + Exploitation weight. + + """ + if tradeoff_scheme is None: + exploration_weight = 0 + + elif tradeoff_scheme == 'equal': + exploration_weight = 0.5 + + elif tradeoff_scheme == 'epsilon-decreasing': + # epsilon-decreasing scheme + # Start with more exploration and increase the influence of + # exploitation along the way with a exponential decay function + initNSamples = self.ExpDesign.n_init_samples + n_max_samples = self.ExpDesign.n_max_samples + + itrNumber = (self.ExpDesign.X.shape[0] - initNSamples) + itrNumber //= self.ExpDesign.n_new_samples + + tau2 = -(n_max_samples-initNSamples-1) / np.log(1e-8) + exploration_weight = signal.exponential(n_max_samples-initNSamples, + 0, tau2, False)[itrNumber] + + elif tradeoff_scheme == 'adaptive': + + # Extract itrNumber + initNSamples = self.ExpDesign.n_init_samples + n_max_samples = self.ExpDesign.n_max_samples + itrNumber = (self.ExpDesign.X.shape[0] - initNSamples) + itrNumber //= self.ExpDesign.n_new_samples + + if itrNumber == 0: + exploration_weight = 0.5 + else: + # New adaptive trade-off according to Liu et al. (2017) + # Mean squared error for last design point + last_EDX = old_EDX[-1].reshape(1, -1) + lastPCEY, _ = self.MetaModel.eval_metamodel(samples=last_EDX) + pce_y = np.array(list(lastPCEY.values()))[:, 0] + y = np.array(list(old_EDY.values()))[:, -1, :] + mseError = mean_squared_error(pce_y, y) + + # Mean squared CV - error for last design point + pce_y_prev = np.array(list(self._y_hat_prev.values()))[:, 0] + mseCVError = mean_squared_error(pce_y_prev, y) + + exploration_weight = min([0.5*mseError/mseCVError, 1]) + + # Exploitation weight + exploitation_weight = 1 - exploration_weight + + return exploration_weight, exploitation_weight + + # ------------------------------------------------------------------------- + def choose_next_sample(self, sigma2=None, n_candidates=5, var='DKL'): + """ + Runs optimal sequential design. + + Parameters + ---------- + sigma2 : dict, optional + A dictionary containing the measurement errors (sigma^2). The + default is None. + n_candidates : int, optional + Number of candidate samples. The default is 5. + var : string, optional + Utility function. The default is None. # TODO: default is set to DKL, not none + + Raises + ------ + NameError + Wrong utility function. + + Returns + ------- + Xnew : array (n_samples, n_params) + Selected new training point(s). + """ + + # Initialization + Bounds = self.ExpDesign.bound_tuples + n_new_samples = self.ExpDesign.n_new_samples + explore_method = self.ExpDesign.explore_method + exploit_method = self.ExpDesign.exploit_method + n_cand_groups = self.ExpDesign.n_cand_groups + tradeoff_scheme = self.ExpDesign.tradeoff_scheme + + old_EDX = self.ExpDesign.X + old_EDY = self.ExpDesign.Y.copy() + ndim = self.ExpDesign.X.shape[1] + OutputNames = self.out_names + + # ----------------------------------------- + # ----------- CUSTOMIZED METHODS ---------- + # ----------------------------------------- + # Utility function exploit_method provided by user + if exploit_method.lower() == 'user': + if not hasattr(self.ExpDesign, 'ExploitFunction'): + raise AttributeError('Function `ExploitFunction` not given to the ExpDesign, thus cannor run user-defined sequential scheme') + # TODO: syntax does not fully match the rest - can test this?? + Xnew, filteredSamples = self.ExpDesign.ExploitFunction(self) + + print("\n") + print("\nXnew:\n", Xnew) + + return Xnew, filteredSamples + + + # Dual-Annealing works differently from the rest, so deal with this first + # Here exploration and exploitation are performed simulataneously + if explore_method == 'dual annealing': + # ------- EXPLORATION: OPTIMIZATION ------- + import time + start_time = time.time() + + # Divide the domain to subdomains + subdomains = subdomain(Bounds, n_new_samples) + + # Multiprocessing + if self.parallel: + args = [] + for i in range(n_new_samples): + args.append((exploit_method, subdomains[i], sigma2, var, i)) + pool = multiprocessing.Pool(multiprocessing.cpu_count()) + + # With Pool.starmap_async() + results = pool.starmap_async(self.dual_annealing, args).get() + + # Close the pool + pool.close() + # Without multiprocessing + else: + results = [] + for i in range(n_new_samples): + results.append(self.dual_annealing(exploit_method, subdomains[i], sigma2, var, i)) + + # New sample + Xnew = np.array([results[i][1] for i in range(n_new_samples)]) + print("\nXnew:\n", Xnew) + + # Computational cost + elapsed_time = time.time() - start_time + print("\n") + print(f"Elapsed_time: {round(elapsed_time,2)} sec.") + print('-'*20) + + return Xnew, None + + # Generate needed Exploration class + explore = Exploration(self.ExpDesign, n_candidates) + explore.w = 100 # * ndim #500 # TODO: where does this value come from? + + # Select criterion (mc-intersite-proj-th, mc-intersite-proj) + explore.mc_criterion = 'mc-intersite-proj' + + # Generate the candidate samples + # TODO: here use the sampling method provided by the expdesign? + sampling_method = self.ExpDesign.sampling_method + + # TODO: changed this from 'random' for LOOCV + if explore_method == 'LOOCV': + allCandidates = self.ExpDesign.generate_samples(n_candidates, + sampling_method) + else: + allCandidates, scoreExploration = explore.get_exploration_samples() + + # ----------------------------------------- + # ---------- EXPLORATION METHODS ---------- + # ----------------------------------------- + if explore_method == 'LOOCV': + # ----------------------------------------------------------------- + # TODO: LOOCV model construnction based on Feng et al. (2020) + # 'LOOCV': + # Initilize the ExploitScore array + + # Generate random samples + allCandidates = self.ExpDesign.generate_samples(n_candidates, + 'random') + + # Construct error model based on LCerror + errorModel = self.MetaModel.create_ModelError(old_EDX, self.LCerror) + self.errorModel.append(copy(errorModel)) + + # Evaluate the error models for allCandidates + eLCAllCands, _ = errorModel.eval_errormodel(allCandidates) + # Select the maximum as the representative error + eLCAllCands = np.dstack(eLCAllCands.values()) + eLCAllCandidates = np.max(eLCAllCands, axis=1)[:, 0] + + # Normalize the error w.r.t the maximum error + scoreExploration = eLCAllCandidates / np.sum(eLCAllCandidates) + + else: + # ------- EXPLORATION: SPACE-FILLING DESIGN ------- + # Generate candidate samples from Exploration class + explore = Exploration(self.ExpDesign, n_candidates) + explore.w = 100 # * ndim #500 + # Select criterion (mc-intersite-proj-th, mc-intersite-proj) + explore.mc_criterion = 'mc-intersite-proj' + allCandidates, scoreExploration = explore.get_exploration_samples() + + # Temp: ---- Plot all candidates ----- + if ndim == 2: + def plotter(points, allCandidates, Method, + scoreExploration=None): + if Method == 'Voronoi': + from scipy.spatial import Voronoi, voronoi_plot_2d + vor = Voronoi(points) + fig = voronoi_plot_2d(vor) + ax1 = fig.axes[0] + else: + fig = plt.figure() + ax1 = fig.add_subplot(111) + ax1.scatter(points[:, 0], points[:, 1], s=10, c='r', + marker="s", label='Old Design Points') + ax1.scatter(allCandidates[:, 0], allCandidates[:, 1], s=10, + c='b', marker="o", label='Design candidates') + for i in range(points.shape[0]): + txt = 'p'+str(i+1) + ax1.annotate(txt, (points[i, 0], points[i, 1])) + if scoreExploration is not None: + for i in range(allCandidates.shape[0]): + txt = str(round(scoreExploration[i], 5)) + ax1.annotate(txt, (allCandidates[i, 0], + allCandidates[i, 1])) + + plt.xlim(self.bound_tuples[0]) + plt.ylim(self.bound_tuples[1]) + # plt.show() + plt.legend(loc='upper left') + + # ----------------------------------------- + # --------- EXPLOITATION METHODS ---------- + # ----------------------------------------- + if exploit_method == 'BayesOptDesign' or\ + exploit_method == 'BayesActDesign': + + # ------- Calculate Exoploration weight ------- + # Compute exploration weight based on trade off scheme + explore_w, exploit_w = self.tradeoff_weights(tradeoff_scheme, + old_EDX, + old_EDY) + print(f"\n Exploration weight={explore_w:0.3f} " + f"Exploitation weight={exploit_w:0.3f}\n") + + # ------- EXPLOITATION: BayesOptDesign & ActiveLearning ------- + if explore_w != 1.0: + # Check if all needed properties are set + if not hasattr(self.ExpDesign, 'max_func_itr'): + raise AttributeError('max_func_itr not given to the experimental design') + + # Create a sample pool for rejection sampling + MCsize = 15000 + X_MC = self.ExpDesign.generate_samples(MCsize, 'random') + candidates = self.ExpDesign.generate_samples( + n_candidates, 'latin_hypercube') + + # Split the candidates in groups for multiprocessing + split_cand = np.array_split( + candidates, n_cand_groups, axis=0 + ) + # print(candidates) + # print(split_cand) + if self.parallel: + results = Parallel(n_jobs=-1, backend='multiprocessing')( + delayed(self.run_util_func)( + exploit_method, split_cand[i], i, sigma2, var, X_MC) + for i in range(n_cand_groups)) + else: + results = [] + for i in range(n_cand_groups): + results.append(self.run_util_func(exploit_method, split_cand[i], i, sigma2, var, X_MC)) + + # Retrieve the results and append them + U_J_d = np.concatenate([results[NofE][1] for NofE in + range(n_cand_groups)]) + + # Check if all scores are inf + if np.isinf(U_J_d).all() or np.isnan(U_J_d).all(): + U_J_d = np.ones(len(U_J_d)) + + # Get the expected value (mean) of the Utility score + # for each cell + if explore_method == 'Voronoi': + U_J_d = np.mean(U_J_d.reshape(-1, n_candidates), axis=1) + + # Normalize U_J_d + norm_U_J_d = U_J_d / np.sum(U_J_d) + else: + norm_U_J_d = np.zeros((len(scoreExploration))) + + # ------- Calculate Total score ------- + # ------- Trade off between EXPLORATION & EXPLOITATION ------- + # Accumulate the samples + finalCandidates = np.concatenate((allCandidates, candidates), axis = 0) + finalCandidates = np.unique(finalCandidates, axis = 0) + + # Calculations take into account both exploration and exploitation + # samples without duplicates + totalScore = np.zeros(finalCandidates.shape[0]) + #self.totalScore = totalScore + + for cand_idx in range(finalCandidates.shape[0]): + # find candidate indices + idx1 = np.where(allCandidates == finalCandidates[cand_idx])[0] + idx2 = np.where(candidates == finalCandidates[cand_idx])[0] + + # exploration + if idx1 != []: + idx1 = idx1[0] + totalScore[cand_idx] += explore_w * scoreExploration[idx1] + + # exploitation + if idx2 != []: + idx2 = idx2[0] + totalScore[cand_idx] += exploit_w * norm_U_J_d[idx2] + + + # Total score + totalScore = exploit_w * norm_U_J_d + totalScore += explore_w * scoreExploration + + # temp: Plot + # dim = self.ExpDesign.X.shape[1] + # if dim == 2: + # plotter(self.ExpDesign.X, allCandidates, explore_method) + + # ------- Select the best candidate ------- + # find an optimal point subset to add to the initial design by + # maximization of the utility score and taking care of NaN values + temp = totalScore.copy() + temp[np.isnan(totalScore)] = -np.inf + sorted_idxtotalScore = np.argsort(temp)[::-1] + bestIdx = sorted_idxtotalScore[:n_new_samples] + + # select the requested number of samples + if explore_method == 'Voronoi': + Xnew = np.zeros((n_new_samples, ndim)) + for i, idx in enumerate(bestIdx): + X_can = explore.closestPoints[idx] + + # Calculate the maxmin score for the region of interest + newSamples, maxminScore = explore.get_mc_samples(X_can) + + # select the requested number of samples + Xnew[i] = newSamples[np.argmax(maxminScore)] + else: + # Changed this from allCandiates to full set of candidates + # TODO: still not changed for e.g. 'Voronoi' + Xnew = finalCandidates[sorted_idxtotalScore[:n_new_samples]] + + + elif exploit_method == 'VarOptDesign': + # ------- EXPLOITATION: VarOptDesign ------- + UtilMethod = var + + # ------- Calculate Exoploration weight ------- + # Compute exploration weight based on trade off scheme + explore_w, exploit_w = self.tradeoff_weights(tradeoff_scheme, + old_EDX, + old_EDY) + print(f"\nweightExploration={explore_w:0.3f} " + f"weightExploitation={exploit_w:0.3f}") + + # Generate candidate samples from Exploration class + nMeasurement = old_EDY[OutputNames[0]].shape[1] + + # print(UtilMethod) + + # Find sensitive region + if UtilMethod == 'LOOCV': + LCerror = self.MetaModel.LCerror + allModifiedLOO = np.zeros((len(old_EDX), len(OutputNames), + nMeasurement)) + for y_idx, y_key in enumerate(OutputNames): + for idx, key in enumerate(LCerror[y_key].keys()): + allModifiedLOO[:, y_idx, idx] = abs( + LCerror[y_key][key]) + + ExploitScore = np.max(np.max(allModifiedLOO, axis=1), axis=1) + # print(allModifiedLOO.shape) + + elif UtilMethod in ['EIGF', 'ALM']: + # ----- All other in ['EIGF', 'ALM'] ----- + # Initilize the ExploitScore array + ExploitScore = np.zeros((len(old_EDX), len(OutputNames))) + + # Split the candidates in groups for multiprocessing + if explore_method != 'Voronoi': + split_cand = np.array_split(allCandidates, + n_cand_groups, + axis=0) + goodSampleIdx = range(n_cand_groups) + else: + # Find indices of the Vornoi cells with samples + goodSampleIdx = [] + for idx in range(len(explore.closest_points)): + if len(explore.closest_points[idx]) != 0: + goodSampleIdx.append(idx) + split_cand = explore.closest_points + + # Split the candidates in groups for multiprocessing + args = [] + for index in goodSampleIdx: + args.append((exploit_method, split_cand[index], index, + sigma2, var)) + + # Multiprocessing + pool = multiprocessing.Pool(multiprocessing.cpu_count()) + # With Pool.starmap_async() + results = pool.starmap_async(self.run_util_func, args).get() + + # Close the pool + pool.close() + + # Retrieve the results and append them + if explore_method == 'Voronoi': + ExploitScore = [np.mean(results[k][1]) for k in + range(len(goodSampleIdx))] + else: + ExploitScore = np.concatenate( + [results[k][1] for k in range(len(goodSampleIdx))]) + + else: + raise NameError('The requested utility function is not ' + 'available.') + + # print("ExploitScore:\n", ExploitScore) + + # find an optimal point subset to add to the initial design by + # maximization of the utility score and taking care of NaN values + # Total score + # Normalize U_J_d + ExploitScore = ExploitScore / np.sum(ExploitScore) + totalScore = exploit_w * ExploitScore + # print(totalScore.shape) + # print(explore_w) + # print(scoreExploration.shape) + totalScore += explore_w * scoreExploration + + temp = totalScore.copy() + sorted_idxtotalScore = np.argsort(temp, axis=0)[::-1] + bestIdx = sorted_idxtotalScore[:n_new_samples] + + Xnew = np.zeros((n_new_samples, ndim)) + if explore_method != 'Voronoi': + Xnew = allCandidates[bestIdx] + else: + for i, idx in enumerate(bestIdx.flatten()): + X_can = explore.closest_points[idx] + # plotter(self.ExpDesign.X, X_can, explore_method, + # scoreExploration=None) + + # Calculate the maxmin score for the region of interest + newSamples, maxminScore = explore.get_mc_samples(X_can) + + # select the requested number of samples + Xnew[i] = newSamples[np.argmax(maxminScore)] + + elif exploit_method == 'alphabetic': + # ------- EXPLOITATION: ALPHABETIC ------- + Xnew = self.util_AlphOptDesign(allCandidates, var) + + elif exploit_method == 'Space-filling': + # ------- EXPLOITATION: SPACE-FILLING ------- + totalScore = scoreExploration + + # ------- Select the best candidate ------- + # find an optimal point subset to add to the initial design by + # maximization of the utility score and taking care of NaN values + temp = totalScore.copy() + temp[np.isnan(totalScore)] = -np.inf + sorted_idxtotalScore = np.argsort(temp)[::-1] + + # select the requested number of samples + Xnew = allCandidates[sorted_idxtotalScore[:n_new_samples]] + + else: + raise NameError('The requested design method is not available.') + + print("\n") + print("\nRun No. {}:".format(old_EDX.shape[0]+1)) + print("Xnew:\n", Xnew) + + # TODO: why does it also return None? + return Xnew, None + + # ------------------------------------------------------------------------- + def util_AlphOptDesign(self, candidates, var='D-Opt'): + """ + Enriches the Experimental design with the requested alphabetic + criterion based on exploring the space with number of sampling points. + + Ref: Hadigol, M., & Doostan, A. (2018). Least squares polynomial chaos + expansion: A review of sampling strategies., Computer Methods in + Applied Mechanics and Engineering, 332, 382-407. + + Arguments + --------- + NCandidate : int + Number of candidate points to be searched + + var : string + Alphabetic optimality criterion + + Returns + ------- + X_new : array of shape (1, n_params) + The new sampling location in the input space. + """ + MetaModelOrig = self # TODO: this doesn't fully seem correct? + n_new_samples = MetaModelOrig.ExpDesign.n_new_samples + NCandidate = candidates.shape[0] + + # TODO: Loop over outputs + OutputName = self.out_names[0] + + # To avoid changes ub original aPCE object + MetaModel = deepcopy(MetaModelOrig) + + # Old Experimental design + oldExpDesignX = self.ExpDesign.X + + # TODO: Only one psi can be selected. + # Suggestion: Go for the one with the highest LOO error + # TODO: this is just a patch, need to look at again! + Scores = list(self.MetaModel.score_dict['b_1'][OutputName].values()) + #print(Scores) + #print(self.MetaModel.score_dict) + #print(self.MetaModel.score_dict.values()) + #print(self.MetaModel.score_dict['b_1'].values()) + #print(self.MetaModel.score_dict['b_1'][OutputName].values()) + ModifiedLOO = [1-score for score in Scores] + outIdx = np.argmax(ModifiedLOO) + + # Initialize Phi to save the criterion's values + Phi = np.zeros((NCandidate)) + + # TODO: also patched here + BasisIndices = self.MetaModel.basis_dict['b_1'][OutputName]["y_"+str(outIdx+1)] + P = len(BasisIndices) + + # ------ Old Psi ------------ + univ_p_val = self.MetaModel.univ_basis_vals(oldExpDesignX) + Psi = self.MetaModel.create_psi(BasisIndices, univ_p_val) + + # ------ New candidates (Psi_c) ------------ + # Assemble Psi_c + univ_p_val_c = self.MetaModel.univ_basis_vals(candidates) + Psi_c = self.MetaModel.create_psi(BasisIndices, univ_p_val_c) + + for idx in range(NCandidate): + + # Include the new row to the original Psi + Psi_cand = np.vstack((Psi, Psi_c[idx])) + + # Information matrix + PsiTPsi = np.dot(Psi_cand.T, Psi_cand) + M = PsiTPsi / (len(oldExpDesignX)+1) + + if np.linalg.cond(PsiTPsi) > 1e-12 \ + and np.linalg.cond(PsiTPsi) < 1 / sys.float_info.epsilon: + # faster + invM = linalg.solve(M, sparse.eye(PsiTPsi.shape[0]).toarray()) + else: + # stabler + invM = np.linalg.pinv(M) + + # ---------- Calculate optimality criterion ---------- + # Optimality criteria according to Section 4.5.1 in Ref. + + # D-Opt + if var.lower() == 'd-opt': + Phi[idx] = (np.linalg.det(invM)) ** (1/P) + + # A-Opt + elif var.lower() == 'a-opt': + Phi[idx] = np.trace(invM) + + # K-Opt + elif var.lower() == 'k-opt': + Phi[idx] = np.linalg.cond(M) + + else: + # print(var.lower()) + raise Exception('The optimality criterion you requested has ' + 'not been implemented yet!') + + # find an optimal point subset to add to the initial design + # by minimization of the Phi + sorted_idxtotalScore = np.argsort(Phi) + + # select the requested number of samples + Xnew = candidates[sorted_idxtotalScore[:n_new_samples]] + + return Xnew + + # ------------------------------------------------------------------------- + def _normpdf(self, y_hat_pce, std_pce, obs_data, total_sigma2s, + rmse=None): + """ + Calculated gaussian likelihood for given y+std based on given obs+sigma + # TODO: is this understanding correct? + + Parameters + ---------- + y_hat_pce : dict of 2d np arrays + Mean output of the surrogate. + std_pce : dict of 2d np arrays + Standard deviation output of the surrogate. + obs_data : dict of 1d np arrays + Observed data. + total_sigma2s : pandas dataframe, matches obs_data + Estimated uncertainty for the observed data. + rmse : dict, optional + RMSE values from validation of the surrogate. The default is None. + + Returns + ------- + likelihoods : dict of float + The likelihood for each surrogate eval in y_hat_pce compared to the + observations (?). + + """ + + likelihoods = 1.0 + + # Loop over the outputs + for idx, out in enumerate(self.out_names): + + # (Meta)Model Output + # print(y_hat_pce[out]) + nsamples, nout = y_hat_pce[out].shape + + # Prepare data and remove NaN + try: + data = obs_data[out].values[~np.isnan(obs_data[out])] + except AttributeError: + data = obs_data[out][~np.isnan(obs_data[out])] + + # Prepare sigma2s + non_nan_indices = ~np.isnan(total_sigma2s[out]) + tot_sigma2s = total_sigma2s[out][non_nan_indices][:nout].values + + # Surrogate error if valid dataset is given. + if rmse is not None: + tot_sigma2s += rmse[out]**2 + else: + tot_sigma2s += np.mean(std_pce[out])**2 + + likelihoods *= stats.multivariate_normal.pdf( + y_hat_pce[out], data, np.diag(tot_sigma2s), + allow_singular=True) + + # TODO: remove this here + self.Likelihoods = likelihoods + + return likelihoods + + # ------------------------------------------------------------------------- + def _corr_factor_BME(self, obs_data, total_sigma2s, logBME): + """ + Calculates the correction factor for BMEs. + """ + MetaModel = self.MetaModel + samples = self.ExpDesign.X # valid_samples + model_outputs = self.ExpDesign.Y # valid_model_runs + n_samples = samples.shape[0] + + # Extract the requested model outputs for likelihood calulation + output_names = self.out_names + + # TODO: Evaluate MetaModel on the experimental design and ValidSet + OutputRS, stdOutputRS = MetaModel.eval_metamodel(samples=samples) + + logLik_data = np.zeros((n_samples)) + logLik_model = np.zeros((n_samples)) + # Loop over the outputs + for idx, out in enumerate(output_names): + + # (Meta)Model Output + nsamples, nout = model_outputs[out].shape + + # Prepare data and remove NaN + try: + data = obs_data[out].values[~np.isnan(obs_data[out])] + except AttributeError: + data = obs_data[out][~np.isnan(obs_data[out])] + + # Prepare sigma2s + non_nan_indices = ~np.isnan(total_sigma2s[out]) + tot_sigma2s = total_sigma2s[out][non_nan_indices][:nout] + + # Covariance Matrix + covMatrix_data = np.diag(tot_sigma2s) + + for i, sample in enumerate(samples): + + # Simulation run + y_m = model_outputs[out][i] + + # Surrogate prediction + y_m_hat = OutputRS[out][i] + + # CovMatrix with the surrogate error + # covMatrix = np.diag(stdOutputRS[out][i]**2) + covMatrix = np.diag((y_m-y_m_hat)**2) + covMatrix = np.diag( + np.mean((model_outputs[out]-OutputRS[out]), axis=0)**2 + ) + + # Compute likelilhood output vs data + logLik_data[i] += logpdf( + y_m_hat, data, covMatrix_data + ) + + # Compute likelilhood output vs surrogate + logLik_model[i] += logpdf(y_m_hat, y_m, covMatrix) + + # Weight + logLik_data -= logBME + weights = np.exp(logLik_model+logLik_data) + + return np.log(np.mean(weights)) + + # ------------------------------------------------------------------------- + def _posteriorPlot(self, posterior, par_names, key): + """ + Plot the posterior of a specific key as a corner plot + + Parameters + ---------- + posterior : 2d np.array + Samples of the posterior. + par_names : list of strings + List of the parameter names. + key : string + Output key that this posterior belongs to. + + Returns + ------- + figPosterior : corner.corner + Plot of the posterior. + + """ + + # Initialization + newpath = (r'Outputs_SeqPosteriorComparison/posterior') + os.makedirs(newpath, exist_ok=True) + + bound_tuples = self.ExpDesign.bound_tuples + n_params = len(par_names) + font_size = 40 + if n_params == 2: + + figPosterior, ax = plt.subplots(figsize=(15, 15)) + + sns.kdeplot(x=posterior[:, 0], y=posterior[:, 1], + fill=True, ax=ax, cmap=plt.cm.jet, + clip=bound_tuples) + # Axis labels + plt.xlabel(par_names[0], fontsize=font_size) + plt.ylabel(par_names[1], fontsize=font_size) + + # Set axis limit + plt.xlim(bound_tuples[0]) + plt.ylim(bound_tuples[1]) + + # Increase font size + plt.xticks(fontsize=font_size) + plt.yticks(fontsize=font_size) + + # Switch off the grids + plt.grid(False) + + else: + import corner + figPosterior = corner.corner(posterior, labels=par_names, + title_fmt='.2e', show_titles=True, + title_kwargs={"fontsize": 12}) + + figPosterior.savefig(f'./{newpath}/{key}.pdf', bbox_inches='tight') + plt.close() + + # Save the posterior as .npy + np.save(f'./{newpath}/{key}.npy', posterior) + + return figPosterior + + + # ------------------------------------------------------------------------- + def _BME_Calculator(self, obs_data, sigma2Dict, rmse=None): + """ + This function computes the Bayesian model evidence (BME) via Monte + Carlo integration. + + Parameters + ---------- + obs_data : dict of 1d np arrays + Observed data. + sigma2Dict : pandas dataframe, matches obs_data + Estimated uncertainty for the observed data. + rmse : dict of floats, optional + RMSE values for each output-key. The dafault is None. + + Returns + ------- + (logBME, KLD, X_Posterior, Likelihoods, distHellinger) + + """ + # Initializations + if hasattr(self, 'valid_likelihoods'): + valid_likelihoods = self.valid_likelihoods + else: + valid_likelihoods = [] + valid_likelihoods = np.array(valid_likelihoods) + + post_snapshot = self.ExpDesign.post_snapshot + if post_snapshot or valid_likelihoods.shape[0] != 0: + newpath = (r'Outputs_SeqPosteriorComparison/likelihood_vs_ref') + os.makedirs(newpath, exist_ok=True) + + SamplingMethod = 'random' + MCsize = 10000 + ESS = 0 + + # Estimation of the integral via Monte Varlo integration + while (ESS > MCsize) or (ESS < 1): + + # Generate samples for Monte Carlo simulation + X_MC = self.ExpDesign.generate_samples( + MCsize, SamplingMethod + ) + + # Monte Carlo simulation for the candidate design + Y_MC, std_MC = self.MetaModel.eval_metamodel(samples=X_MC) + + # Likelihood computation (Comparison of data and + # simulation results via PCE with candidate design) + Likelihoods = self._normpdf( + Y_MC, std_MC, obs_data, sigma2Dict, rmse + ) + + # Check the Effective Sample Size (1000<ESS<MCsize) + ESS = 1 / np.sum(np.square(Likelihoods/np.sum(Likelihoods))) + + # Enlarge sample size if it doesn't fulfill the criteria + if (ESS > MCsize) or (ESS < 1): + print(f'ESS={ESS} MC size should be larger.') + MCsize *= 10 + ESS = 0 + + # Rejection Step + # Random numbers between 0 and 1 + unif = np.random.rand(1, MCsize)[0] + + # Reject the poorly performed prior + accepted = (Likelihoods/np.max(Likelihoods)) >= unif + X_Posterior = X_MC[accepted] + + # ------------------------------------------------------------ + # --- Kullback-Leibler Divergence & Information Entropy ------ + # ------------------------------------------------------------ + # Prior-based estimation of BME + logBME = np.log(np.nanmean(Likelihoods)) + + # TODO: Correction factor + # log_weight = self.__corr_factor_BME(obs_data, sigma2Dict, logBME) + + # Posterior-based expectation of likelihoods + postExpLikelihoods = np.mean(np.log(Likelihoods[accepted])) + + # Posterior-based expectation of prior densities + postExpPrior = np.mean( + np.log(self.ExpDesign.JDist.pdf(X_Posterior.T)) + ) + + # Calculate Kullback-Leibler Divergence + # KLD = np.mean(np.log(Likelihoods[Likelihoods!=0])- logBME) + KLD = postExpLikelihoods - logBME + + # Information Entropy based on Entropy paper Eq. 38 + infEntropy = logBME - postExpPrior - postExpLikelihoods + + # If post_snapshot is True, plot likelihood vs refrence + if post_snapshot or valid_likelihoods: + # Hellinger distance + valid_likelihoods = np.array(valid_likelihoods) + ref_like = np.log(valid_likelihoods[(valid_likelihoods > 0)]) + est_like = np.log(Likelihoods[Likelihoods > 0]) + distHellinger = hellinger_distance(ref_like, est_like) + + idx = len([name for name in os.listdir(newpath) if 'Likelihoods_' + in name and os.path.isfile(os.path.join(newpath, name))]) + + fig, ax = plt.subplots() + try: + sns.kdeplot(np.log(valid_likelihoods[valid_likelihoods > 0]), + shade=True, color="g", label='Ref. Likelihood') + sns.kdeplot(np.log(Likelihoods[Likelihoods > 0]), shade=True, + color="b", label='Likelihood with PCE') + except: + pass + + text = f"Hellinger Dist.={distHellinger:.3f}\n logBME={logBME:.3f}" + "\n DKL={KLD:.3f}" + + plt.text(0.05, 0.75, text, bbox=dict(facecolor='wheat', + edgecolor='black', + boxstyle='round,pad=1'), + transform=ax.transAxes) + + fig.savefig(f'./{newpath}/Likelihoods_{idx}.pdf', + bbox_inches='tight') + plt.close() + + else: + distHellinger = 0.0 + + # Bayesian inference with Emulator only for 2D problem + if post_snapshot and self.MetaModel.n_params == 2 and not idx % 5: + BayesOpts = BayesInference(self) + + BayesOpts.emulator = True + BayesOpts.plot_post_pred = False + + # Select the inference method + import emcee + BayesOpts.inference_method = "MCMC" + # Set the MCMC parameters passed to self.mcmc_params + BayesOpts.mcmc_params = { + 'n_steps': 1e5, + 'n_walkers': 30, + 'moves': emcee.moves.KDEMove(), + 'verbose': False + } + + # ----- Define the discrepancy model ------- + # TODO: check with Farid if this first line is how it should be + BayesOpts.measured_data = obs_data + obs_data = pd.DataFrame(obs_data, columns=self.out_names) + BayesOpts.measurement_error = obs_data + # TODO: shouldn't the uncertainty be sigma2Dict instead of obs_data? + + # # -- (Option B) -- + DiscrepancyOpts = Discrepancy('') + DiscrepancyOpts.type = 'Gaussian' + DiscrepancyOpts.parameters = obs_data**2 + BayesOpts.Discrepancy = DiscrepancyOpts + # Start the calibration/inference + Bayes_PCE = BayesOpts.create_inference() + X_Posterior = Bayes_PCE.posterior_df.values + + return (logBME, KLD, X_Posterior, Likelihoods, distHellinger) + + # ------------------------------------------------------------------------- + def _validError(self): + """ + Evaluate the metamodel on the validation samples and calculate the + error against the corresponding model runs + + Returns + ------- + rms_error : dict + RMSE for each validation run. + valid_error : dict + Normed (?)RMSE for each validation run. + + """ + # Extract the original model with the generated samples + valid_model_runs = self.ExpDesign.valid_model_runs + + # Run the PCE model with the generated samples + valid_PCE_runs, _ = self.MetaModel.eval_metamodel(samples=self.ExpDesign.valid_samples) + + rms_error = {} + valid_error = {} + # Loop over the keys and compute RMSE error. + for key in self.out_names: + rms_error[key] = mean_squared_error( + valid_model_runs[key], valid_PCE_runs[key], + multioutput='raw_values', + sample_weight=None, + squared=False) + # Validation error + valid_error[key] = (rms_error[key]**2) + valid_error[key] /= np.var(valid_model_runs[key], ddof=1, axis=0) + + # Print a report table + print("\n>>>>> Updated Errors of {} <<<<<".format(key)) + print("\nIndex | RMSE | Validation Error") + print('-'*35) + print('\n'.join(f'{i+1} | {k:.3e} | {j:.3e}' for i, (k, j) + in enumerate(zip(rms_error[key], + valid_error[key])))) + + return rms_error, valid_error + + # ------------------------------------------------------------------------- + def _error_Mean_Std(self): + """ + Calculates the error in the overall mean and std approximation of the + surrogate against the mc-reference provided to the model. + This can only be applied to metamodels of polynomial type + + Returns + ------- + RMSE_Mean : float + RMSE of the means + RMSE_std : float + RMSE of the standard deviations + + """ + # Compute the mean and std based on the MetaModel + pce_means, pce_stds = self.MetaModel._compute_pce_moments() + + # Compute the root mean squared error + for output in self.out_names: + + # Compute the error between mean and std of MetaModel and OrigModel + RMSE_Mean = mean_squared_error( + self.Model.mc_reference['mean'], pce_means[output], squared=False + ) + RMSE_std = mean_squared_error( + self.Model.mc_reference['std'], pce_stds[output], squared=False + ) + + return RMSE_Mean, RMSE_std diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/eval_rec_rule.py b/examples/analytical-function/bayesvalidrox/surrogate_models/eval_rec_rule.py new file mode 100644 index 000000000..b583c7eb2 --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/surrogate_models/eval_rec_rule.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" + + +Based on the implementation in UQLab [1]. + +References: +1. S. Marelli, and B. Sudret, UQLab: A framework for uncertainty quantification +in Matlab, Proc. 2nd Int. Conf. on Vulnerability, Risk Analysis and Management +(ICVRAM2014), Liverpool, United Kingdom, 2014, 2554-2563. + +2. S. Marelli, N. Lüthen, B. Sudret, UQLab user manual – Polynomial chaos +expansions, Report # UQLab-V1.4-104, Chair of Risk, Safety and Uncertainty +Quantification, ETH Zurich, Switzerland, 2021. + +Author: Farid Mohammadi, M.Sc. +E-Mail: farid.mohammadi@iws.uni-stuttgart.de +Department of Hydromechanics and Modelling of Hydrosystems (LH2) +Institute for Modelling Hydraulic and Environmental Systems (IWS), University +of Stuttgart, www.iws.uni-stuttgart.de/lh2/ +Pfaffenwaldring 61 +70569 Stuttgart + +Created on Fri Jan 14 2022 +""" +import numpy as np +from numpy.polynomial.polynomial import polyval + + +def poly_rec_coeffs(n_max, poly_type, params=None): + """ + Computes the recurrence coefficients for classical Wiener-Askey orthogonal + polynomials. + + Parameters + ---------- + n_max : int + Maximum polynomial degree. + poly_type : string + Polynomial type. + params : list, optional + Parameters required for `laguerre` poly type. The default is None. + + Returns + ------- + AB : dict + The 3 term recursive coefficients and the applicable ranges. + + """ + + if poly_type == 'legendre': + + def an(n): + return np.zeros((n+1, 1)) + + def sqrt_bn(n): + sq_bn = np.zeros((n+1, 1)) + sq_bn[0, 0] = 1 + for i in range(1, n+1): + sq_bn[i, 0] = np.sqrt(1./(4-i**-2)) + return sq_bn + + bounds = [-1, 1] + + elif poly_type == 'hermite': + + def an(n): + return np.zeros((n+1, 1)) + + def sqrt_bn(n): + sq_bn = np.zeros((n+1, 1)) + sq_bn[0, 0] = 1 + for i in range(1, n+1): + sq_bn[i, 0] = np.sqrt(i) + return sq_bn + + bounds = [-np.inf, np.inf] + + elif poly_type == 'laguerre': + + def an(n): + a = np.zeros((n+1, 1)) + for i in range(1, n+1): + a[i] = 2*n + params[1] + return a + + def sqrt_bn(n): + sq_bn = np.zeros((n+1, 1)) + sq_bn[0, 0] = 1 + for i in range(1, n+1): + sq_bn[i, 0] = -np.sqrt(i * (i+params[1]-1)) + return sq_bn + + bounds = [0, np.inf] + + AB = {'alpha_beta': np.concatenate((an(n_max), sqrt_bn(n_max)), axis=1), + 'bounds': bounds} + + return AB + + +def eval_rec_rule(x, max_deg, poly_type): + """ + Evaluates the polynomial that corresponds to the Jacobi matrix defined + from the AB. + + Parameters + ---------- + x : array (n_samples) + Points where the polynomials are evaluated. + max_deg : int + Maximum degree. + poly_type : string + Polynomial type. + + Returns + ------- + values : array of shape (n_samples, max_deg+1) + Polynomials corresponding to the Jacobi matrix. + + """ + AB = poly_rec_coeffs(max_deg, poly_type) + AB = AB['alpha_beta'] + + values = np.zeros((len(x), AB.shape[0]+1)) + values[:, 1] = 1 / AB[0, 1] + + for k in range(AB.shape[0]-1): + values[:, k+2] = np.multiply((x - AB[k, 0]), values[:, k+1]) - \ + np.multiply(values[:, k], AB[k, 1]) + values[:, k+2] = np.divide(values[:, k+2], AB[k+1, 1]) + return values[:, 1:] + + +def eval_rec_rule_arbitrary(x, max_deg, poly_coeffs): + """ + Evaluates the polynomial at sample array x. + + Parameters + ---------- + x : array (n_samples) + Points where the polynomials are evaluated. + max_deg : int + Maximum degree. + poly_coeffs : dict + Polynomial coefficients computed based on moments. + + Returns + ------- + values : array of shape (n_samples, max_deg+1) + Univariate Polynomials evaluated at samples. + + """ + values = np.zeros((len(x), max_deg+1)) + + for deg in range(max_deg+1): + values[:, deg] = polyval(x, poly_coeffs[deg]).T + + return values + + +def eval_univ_basis(x, max_deg, poly_types, apoly_coeffs=None): + """ + Evaluates univariate regressors along input directions. + + Parameters + ---------- + x : array of shape (n_samples, n_params) + Training samples. + max_deg : int + Maximum polynomial degree. + poly_types : list of strings + List of polynomial types for all parameters. + apoly_coeffs : dict , optional + Polynomial coefficients computed based on moments. The default is None. + + Returns + ------- + univ_vals : array of shape (n_samples, n_params, max_deg+1) + Univariate polynomials for all degrees and parameters evaluated at x. + + """ + # Initilize the output array + n_samples, n_params = x.shape + univ_vals = np.zeros((n_samples, n_params, max_deg+1)) + + for i in range(n_params): + + if poly_types[i] == 'arbitrary': + polycoeffs = apoly_coeffs[f'p_{i+1}'] + univ_vals[:, i] = eval_rec_rule_arbitrary(x[:, i], max_deg, + polycoeffs) + else: + univ_vals[:, i] = eval_rec_rule(x[:, i], max_deg, poly_types[i]) + + return univ_vals diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/exp_designs.py b/examples/analytical-function/bayesvalidrox/surrogate_models/exp_designs.py new file mode 100644 index 000000000..fa03fe17d --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/surrogate_models/exp_designs.py @@ -0,0 +1,479 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Experimental design with associated sampling methods +""" + +import numpy as np +import math +import itertools +import chaospy +import scipy.stats as st +from tqdm import tqdm +import h5py +import os + +from .apoly_construction import apoly_construction +from .input_space import InputSpace + +# ------------------------------------------------------------------------- +def check_ranges(theta, ranges): + """ + This function checks if theta lies in the given ranges. + + Parameters + ---------- + theta : array + Proposed parameter set. + ranges : nested list + List of the praremeter ranges. + + Returns + ------- + c : bool + If it lies in the given range, it return True else False. + + """ + c = True + # traverse in the list1 + for i, bounds in enumerate(ranges): + x = theta[i] + # condition check + if x < bounds[0] or x > bounds[1]: + c = False + return c + return c + + +class ExpDesigns(InputSpace): + """ + This class generates samples from the prescribed marginals for the model + parameters using the `Input` object. + + Attributes + ---------- + Input : obj + Input object containing the parameter marginals, i.e. name, + distribution type and distribution parameters or available raw data. + meta_Model_type : str + Type of the meta_Model_type. + sampling_method : str + Name of the sampling method for the experimental design. The following + sampling method are supported: + + * random + * latin_hypercube + * sobol + * halton + * hammersley + * chebyshev(FT) + * grid(FT) + * user + hdf5_file : str + Name of the hdf5 file that contains the experimental design. + n_new_samples : int + Number of (initial) training points. + n_max_samples : int + Number of maximum training points. + mod_LOO_threshold : float + The modified leave-one-out cross validation threshold where the + sequential design stops. + tradeoff_scheme : str + Trade-off scheme to assign weights to the exploration and exploitation + scores in the sequential design. + n_canddidate : int + Number of candidate training sets to calculate the scores for. + explore_method : str + Type of the exploration method for the sequential design. The following + methods are supported: + + * Voronoi + * random + * latin_hypercube + * LOOCV + * dual annealing + exploit_method : str + Type of the exploitation method for the sequential design. The + following methods are supported: + + * BayesOptDesign + * BayesActDesign + * VarOptDesign + * alphabetic + * Space-filling + util_func : str or list + The utility function to be specified for the `exploit_method`. For the + available utility functions see Note section. + n_cand_groups : int + Number of candidate groups. Each group of candidate training sets will + be evaulated separately in parallel. + n_replication : int + Number of replications. Only for comparison. The default is 1. + post_snapshot : int + Whether to plot the posterior in the sequential design. The default is + `True`. + step_snapshot : int + The number of steps to plot the posterior in the sequential design. The + default is 1. + max_a_post : list or array + Maximum a posteriori of the posterior distribution, if known. The + default is `[]`. + adapt_verbose : bool + Whether to plot the model response vs that of metamodel for the new + trining point in the sequential design. + + Note + ---------- + The following utiliy functions for the **exploitation** methods are + supported: + + #### BayesOptDesign (when data is available) + - DKL (Kullback-Leibler Divergence) + - DPP (D-Posterior-percision) + - APP (A-Posterior-percision) + + #### VarBasedOptDesign -> when data is not available + - Entropy (Entropy/MMSE/active learning) + - EIGF (Expected Improvement for Global fit) + - LOOCV (Leave-one-out Cross Validation) + + #### alphabetic + - D-Opt (D-Optimality) + - A-Opt (A-Optimality) + - K-Opt (K-Optimality) + """ + + def __init__(self, Input, meta_Model_type='pce', + sampling_method='random', hdf5_file=None, + n_new_samples=1, n_max_samples=None, mod_LOO_threshold=1e-16, + tradeoff_scheme=None, n_canddidate=1, explore_method='random', + exploit_method='Space-filling', util_func='Space-filling', + n_cand_groups=4, n_replication=1, post_snapshot=False, + step_snapshot=1, max_a_post=[], adapt_verbose=False, max_func_itr=1): + + self.InputObj = Input + self.meta_Model_type = meta_Model_type + self.sampling_method = sampling_method + self.hdf5_file = hdf5_file + self.n_new_samples = n_new_samples + self.n_max_samples = n_max_samples + self.mod_LOO_threshold = mod_LOO_threshold + self.explore_method = explore_method + self.exploit_method = exploit_method + self.util_func = util_func + self.tradeoff_scheme = tradeoff_scheme + self.n_canddidate = n_canddidate + self.n_cand_groups = n_cand_groups + self.n_replication = n_replication + self.post_snapshot = post_snapshot + self.step_snapshot = step_snapshot + self.max_a_post = max_a_post + self.adapt_verbose = adapt_verbose + self.max_func_itr = max_func_itr + + # Other + self.apce = None + self.ndim = None + + # Init + self.check_valid_inputs() + + # ------------------------------------------------------------------------- + def generate_samples(self, n_samples, sampling_method='random', + transform=False): + """ + Generates samples with given sampling method + + Parameters + ---------- + n_samples : int + Number of requested samples. + sampling_method : str, optional + Sampling method. The default is `'random'`. + transform : bool, optional + Transformation via an isoprobabilistic transformation method. The + default is `False`. + + Returns + ------- + samples: array of shape (n_samples, n_params) + Generated samples from defined model input object. + + """ + try: + samples = chaospy.generate_samples( + int(n_samples), domain=self.origJDist, rule=sampling_method + ) + except: + samples = self.random_sampler(int(n_samples)).T + + return samples.T + + + + # ------------------------------------------------------------------------- + def generate_ED(self, n_samples, transform=False, + max_pce_deg=None): + """ + Generates experimental designs (training set) with the given method. + + Parameters + ---------- + n_samples : int + Number of requested training points. + sampling_method : str, optional + Sampling method. The default is `'random'`. + transform : bool, optional + Isoprobabilistic transformation. The default is `False`. + max_pce_deg : int, optional + Maximum PCE polynomial degree. The default is `None`. + + Returns + ------- + None + + """ + if n_samples <0: + raise ValueError('A negative number of samples cannot be created. Please provide positive n_samples') + n_samples = int(n_samples) + + if not hasattr(self, 'n_init_samples'): + self.n_init_samples = n_samples + + # Generate the samples based on requested method + self.init_param_space(max_pce_deg) + + sampling_method = self.sampling_method + # Pass user-defined samples as ED + if sampling_method == 'user': + if not hasattr(self, 'X'): + raise AttributeError('User-defined sampling cannot proceed as no samples provided. Please add them to this class as attribute X') + if not self.X.ndim == 2: + raise AttributeError('The provided samples shuld have 2 dimensions') + samples = self.X + self.n_samples = len(samples) + + # Sample the distribution of parameters + elif self.input_data_given: + # Case II: Input values are directly given by the user. + + if sampling_method == 'random': + samples = self.random_sampler(n_samples) + + elif sampling_method == 'PCM' or \ + sampling_method == 'LSCM': + samples = self.pcm_sampler(n_samples, max_pce_deg) + + else: + # Create ExpDesign in the actual space using chaospy + try: + samples = chaospy.generate_samples(n_samples, + domain=self.JDist, + rule=sampling_method).T + except: + samples = self.JDist.resample(n_samples).T + + elif not self.input_data_given: + # Case I = User passed known distributions + samples = chaospy.generate_samples(n_samples, domain=self.JDist, + rule=sampling_method).T + + self.X = samples + + def read_from_file(self, out_names): + """ + Reads in the ExpDesign from a provided h5py file and saves the results. + + Parameters + ---------- + out_names : list of strings + The keys that are in the outputs (y) saved in the provided file. + + Returns + ------- + None. + + """ + if self.hdf5_file == None: + raise AttributeError('ExpDesign cannot be read in, please provide hdf5 file first') + + # Read hdf5 file + f = h5py.File(self.hdf5_file, 'r+') + + # Read EDX and pass it to ExpDesign object + try: + self.X = np.array(f["EDX/New_init_"]) + except KeyError: + self.X = np.array(f["EDX/init_"]) + + # Update number of initial samples + self.n_init_samples = self.X.shape[0] + + # Read EDX and pass it to ExpDesign object + self.Y = {} + + # Extract x values + try: + self.Y["x_values"] = dict() + for varIdx, var in enumerate(out_names): + x = np.array(f[f"x_values/{var}"]) + self.Y["x_values"][var] = x + except KeyError: + self.Y["x_values"] = np.array(f["x_values"]) + + # Store the output + for varIdx, var in enumerate(out_names): + try: + y = np.array(f[f"EDY/{var}/New_init_"]) + except KeyError: + y = np.array(f[f"EDY/{var}/init_"]) + self.Y[var] = y + f.close() + print(f'Experimental Design is read in from file {self.hdf5_file}') + print('') + + + + # ------------------------------------------------------------------------- + def random_sampler(self, n_samples, max_deg = None): + """ + Samples the given raw data randomly. + + Parameters + ---------- + n_samples : int + Number of requested samples. + + max_deg : int, optional + Maximum degree. The default is `None`. + This will be used to run init_param_space, if it has not been done + until now. + + Returns + ------- + samples: array of shape (n_samples, n_params) + The sampling locations in the input space. + + """ + if not hasattr(self, 'raw_data'): + self.init_param_space(max_deg) + else: + if np.array(self.raw_data).ndim !=2: + raise AttributeError('The given raw data for sampling should have two dimensions') + samples = np.zeros((n_samples, self.ndim)) + sample_size = self.raw_data.shape[1] + + # Use a combination of raw data + if n_samples < sample_size: + for pa_idx in range(self.ndim): + # draw random indices + rand_idx = np.random.randint(0, sample_size, n_samples) + # store the raw data with given random indices + samples[:, pa_idx] = self.raw_data[pa_idx, rand_idx] + else: + try: + samples = self.JDist.resample(int(n_samples)).T + except AttributeError: + samples = self.JDist.sample(int(n_samples)).T + # Check if all samples are in the bound_tuples + for idx, param_set in enumerate(samples): + if not check_ranges(param_set, self.bound_tuples): + try: + proposed_sample = chaospy.generate_samples( + 1, domain=self.JDist, rule='random').T[0] + except: + proposed_sample = self.JDist.resample(1).T[0] + while not check_ranges(proposed_sample, + self.bound_tuples): + try: + proposed_sample = chaospy.generate_samples( + 1, domain=self.JDist, rule='random').T[0] + except: + proposed_sample = self.JDist.resample(1).T[0] + samples[idx] = proposed_sample + + return samples + + # ------------------------------------------------------------------------- + def pcm_sampler(self, n_samples, max_deg): + """ + Generates collocation points based on the root of the polynomial + degrees. + + Parameters + ---------- + n_samples : int + Number of requested samples. + max_deg : int + Maximum degree defined by user. Will also be used to run + init_param_space if that has not been done beforehand. + + Returns + ------- + opt_col_points: array of shape (n_samples, n_params) + Collocation points. + + """ + + if not hasattr(self, 'raw_data'): + self.init_param_space(max_deg) + + raw_data = self.raw_data + + # Guess the closest degree to self.n_samples + def M_uptoMax(deg): + result = [] + for d in range(1, deg+1): + result.append(math.factorial(self.ndim+d) // + (math.factorial(self.ndim) * math.factorial(d))) + return np.array(result) + #print(M_uptoMax(max_deg)) + #print(np.where(M_uptoMax(max_deg) > n_samples)[0]) + + guess_Deg = np.where(M_uptoMax(max_deg) > n_samples)[0][0] + + c_points = np.zeros((guess_Deg+1, self.ndim)) + + def PolynomialPa(parIdx): + return apoly_construction(self.raw_data[parIdx], max_deg) + + for i in range(self.ndim): + poly_coeffs = PolynomialPa(i)[guess_Deg+1][::-1] + c_points[:, i] = np.trim_zeros(np.roots(poly_coeffs)) + + # Construction of optimal integration points + Prod = itertools.product(np.arange(1, guess_Deg+2), repeat=self.ndim) + sort_dig_unique_combos = np.array(list(filter(lambda x: x, Prod))) + + # Ranking relatively mean + Temp = np.empty(shape=[0, guess_Deg+1]) + for j in range(self.ndim): + s = abs(c_points[:, j]-np.mean(raw_data[j])) + Temp = np.append(Temp, [s], axis=0) + temp = Temp.T + + index_CP = np.sort(temp, axis=0) + sort_cpoints = np.empty((0, guess_Deg+1)) + + for j in range(self.ndim): + #print(index_CP[:, j]) + sort_cp = c_points[index_CP[:, j], j] + sort_cpoints = np.vstack((sort_cpoints, sort_cp)) + + # Mapping of Combination to Cpoint Combination + sort_unique_combos = np.empty(shape=[0, self.ndim]) + for i in range(len(sort_dig_unique_combos)): + sort_un_comb = [] + for j in range(self.ndim): + SortUC = sort_cpoints[j, sort_dig_unique_combos[i, j]-1] + sort_un_comb.append(SortUC) + sort_uni_comb = np.asarray(sort_un_comb) + sort_unique_combos = np.vstack((sort_unique_combos, sort_uni_comb)) + + # Output the collocation points + if self.sampling_method.lower() == 'lscm': + opt_col_points = sort_unique_combos + else: + opt_col_points = sort_unique_combos[0:self.n_samples] + + return opt_col_points diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/exploration.py b/examples/analytical-function/bayesvalidrox/surrogate_models/exploration.py new file mode 100644 index 000000000..6abb652f1 --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/surrogate_models/exploration.py @@ -0,0 +1,367 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Exploration for sequential training of metamodels +""" + +import numpy as np +from scipy.spatial import distance + + +class Exploration: + """ + Created based on the Surrogate Modeling Toolbox (SUMO) [1]. + + [1] Gorissen, D., Couckuyt, I., Demeester, P., Dhaene, T. and Crombecq, K., + 2010. A surrogate modeling and adaptive sampling toolbox for computer + based design. Journal of machine learning research.-Cambridge, Mass., + 11, pp.2051-2055. sumo@sumo.intec.ugent.be - http://sumo.intec.ugent.be + + Attributes + ---------- + ExpDesign : obj + ExpDesign object. + n_candidate : int + Number of candidate samples. + mc_criterion : str + Selection crieterion. The default is `'mc-intersite-proj-th'`. Another + option is `'mc-intersite-proj'`. + w : int + Number of random points in the domain for each sample of the + training set. + """ + + def __init__(self, ExpDesign, n_candidate, + mc_criterion='mc-intersite-proj-th'): + self.ExpDesign = ExpDesign + self.n_candidate = n_candidate + self.mc_criterion = mc_criterion + self.w = 100 + + def get_exploration_samples(self): + """ + This function generates candidates to be selected as new design and + their associated exploration scores. + + Returns + ------- + all_candidates : array of shape (n_candidate, n_params) + A list of samples. + exploration_scores: arrays of shape (n_candidate) + Exploration scores. + """ + explore_method = self.ExpDesign.explore_method + + print("\n") + print(f' The {explore_method}-Method is selected as the exploration ' + 'method.') + print("\n") + + if explore_method == 'Voronoi': + # Generate samples using the Voronoi method + all_candidates, exploration_scores = self.get_vornoi_samples() + else: + # Generate samples using the MC method + all_candidates, exploration_scores = self.get_mc_samples() + + return all_candidates, exploration_scores + + # ------------------------------------------------------------------------- + def get_vornoi_samples(self): + """ + This function generates samples based on voronoi cells and their + corresponding scores + + Returns + ------- + new_samples : array of shape (n_candidate, n_params) + A list of samples. + exploration_scores: arrays of shape (n_candidate) + Exploration scores. + """ + + mc_criterion = self.mc_criterion + n_candidate = self.n_candidate + # Get the Old ExpDesign #samples + old_ED_X = self.ExpDesign.X + ndim = old_ED_X.shape[1] + + # calculate error #averageErrors + error_voronoi, all_candidates = self.approximate_voronoi( + self.w, old_ED_X + ) + + # Pick the best candidate point in the voronoi cell + # for each best sample + selected_samples = np.empty((0, ndim)) + bad_samples = [] + + for index in range(len(error_voronoi)): + + # get candidate new samples from voronoi tesselation + candidates = self.closest_points[index] + + # get total number of candidates + n_new_samples = candidates.shape[0] + + # still no candidate samples around this one, skip it! + if n_new_samples == 0: + print('The following sample has been skipped because there ' + 'were no candidate samples around it...') + print(old_ED_X[index]) + bad_samples.append(index) + continue + + # find candidate that is farthest away from any existing sample + max_min_distance = 0 + best_candidate = 0 + min_intersite_dist = np.zeros((n_new_samples)) + min_projected_dist = np.zeros((n_new_samples)) + + for j in range(n_new_samples): + + new_samples = np.vstack((old_ED_X, selected_samples)) + + # find min distorted distance from all other samples + euclidean_dist = self._build_dist_matrix_point( + new_samples, candidates[j], do_sqrt=True) + min_euclidean_dist = np.min(euclidean_dist) + min_intersite_dist[j] = min_euclidean_dist + + # Check if this is the maximum minimum distance from all other + # samples + if min_euclidean_dist >= max_min_distance: + max_min_distance = min_euclidean_dist + best_candidate = j + + # Projected distance + projected_dist = distance.cdist( + new_samples, [candidates[j]], 'chebyshev') + min_projected_dist[j] = np.min(projected_dist) + + if mc_criterion == 'mc-intersite-proj': + weight_euclidean_dist = 0.5 * ((n_new_samples+1)**(1/ndim) - 1) + weight_projected_dist = 0.5 * (n_new_samples+1) + total_dist_scores = weight_euclidean_dist * min_intersite_dist + total_dist_scores += weight_projected_dist * min_projected_dist + + elif mc_criterion == 'mc-intersite-proj-th': + alpha = 0.5 # chosen (tradeoff) + d_min = 2 * alpha / n_new_samples + if any(min_projected_dist < d_min): + candidates = np.delete( + candidates, [min_projected_dist < d_min], axis=0 + ) + total_dist_scores = np.delete( + min_intersite_dist, [min_projected_dist < d_min], + axis=0 + ) + else: + total_dist_scores = min_intersite_dist + else: + raise NameError( + 'The MC-Criterion you requested is not available.' + ) + + # Add the best candidate to the list of new samples + best_candidate = np.argsort(total_dist_scores)[::-1][:n_candidate] + selected_samples = np.vstack( + (selected_samples, candidates[best_candidate]) + ) + + self.new_samples = selected_samples + self.exploration_scores = np.delete(error_voronoi, bad_samples, axis=0) + + return self.new_samples, self.exploration_scores + + # ------------------------------------------------------------------------- + def get_mc_samples(self, all_candidates=None): + """ + This function generates random samples based on Global Monte Carlo + methods and their corresponding scores, based on [1]. + + [1] Crombecq, K., Laermans, E. and Dhaene, T., 2011. Efficient + space-filling and non-collapsing sequential design strategies for + simulation-based modeling. European Journal of Operational Research + , 214(3), pp.683-696. + DOI: https://doi.org/10.1016/j.ejor.2011.05.032 + + Implemented methods to compute scores: + 1) mc-intersite-proj + 2) mc-intersite-proj-th + + Arguments + --------- + all_candidates : array, optional + Samples to compute the scores for. The default is `None`. In this + case, samples will be generated by defined model input marginals. + + Returns + ------- + new_samples : array of shape (n_candidate, n_params) + A list of samples. + exploration_scores: arrays of shape (n_candidate) + Exploration scores. + """ + explore_method = self.ExpDesign.explore_method + mc_criterion = self.mc_criterion + if all_candidates is None: + n_candidate = self.n_candidate + else: + n_candidate = all_candidates.shape[0] + + # Get the Old ExpDesign #samples + old_ED_X = self.ExpDesign.X + ndim = old_ED_X.shape[1] + + # ----- Compute the number of random points ----- + if all_candidates is None: + # Generate MC Samples + all_candidates = self.ExpDesign.generate_samples( + self.n_candidate, explore_method + ) + self.all_candidates = all_candidates + + # initialization + min_intersite_dist = np.zeros((n_candidate)) + min_projected_dist = np.zeros((n_candidate)) + + for i, candidate in enumerate(all_candidates): + + # find candidate that is farthest away from any existing sample + maxMinDistance = 0 + + # find min distorted distance from all other samples + euclidean_dist = self._build_dist_matrix_point( + old_ED_X, candidate, do_sqrt=True + ) + min_euclidean_dist = np.min(euclidean_dist) + min_intersite_dist[i] = min_euclidean_dist + + # Check if this is the maximum minimum distance from all other + # samples + if min_euclidean_dist >= maxMinDistance: + maxMinDistance = min_euclidean_dist + + # Projected distance + projected_dist = self._build_dist_matrix_point( + old_ED_X, candidate, 'chebyshev' + ) + min_projected_dist[i] = np.min(projected_dist) + + if mc_criterion == 'mc-intersite-proj': + weight_euclidean_dist = ((n_candidate+1)**(1/ndim) - 1) * 0.5 + weight_projected_dist = (n_candidate+1) * 0.5 + total_dist_scores = weight_euclidean_dist * min_intersite_dist + total_dist_scores += weight_projected_dist * min_projected_dist + + elif mc_criterion == 'mc-intersite-proj-th': + alpha = 0.5 # chosen (tradeoff) + d_min = 2 * alpha / n_candidate + if any(min_projected_dist < d_min): + all_candidates = np.delete( + all_candidates, [min_projected_dist < d_min], axis=0 + ) + total_dist_scores = np.delete( + min_intersite_dist, [min_projected_dist < d_min], axis=0 + ) + else: + total_dist_scores = min_intersite_dist + else: + raise NameError('The MC-Criterion you requested is not available.') + + self.new_samples = all_candidates + self.exploration_scores = total_dist_scores + self.exploration_scores /= np.nansum(total_dist_scores) + + return self.new_samples, self.exploration_scores + + # ------------------------------------------------------------------------- + def approximate_voronoi(self, w, samples): + """ + An approximate (monte carlo) version of Matlab's voronoi command. + + Arguments + --------- + samples : array + Old experimental design to be used as center points for voronoi + cells. + + Returns + ------- + areas : array + An approximation of the voronoi cells' areas. + all_candidates: list of arrays + A list of samples in each voronoi cell. + """ + n_samples = samples.shape[0] + ndim = samples.shape[1] + + # Compute the number of random points + n_points = w * samples.shape[0] + # Generate w random points in the domain for each sample + points = self.ExpDesign.generate_samples(n_points, 'random') + self.all_candidates = points + + # Calculate the nearest sample to each point + self.areas = np.zeros((n_samples)) + self.closest_points = [np.empty((0, ndim)) for i in range(n_samples)] + + # Compute the minimum distance from all the samples of old_ED_X for + # each test point + for idx in range(n_points): + # calculate the minimum distance + distances = self._build_dist_matrix_point( + samples, points[idx], do_sqrt=True + ) + closest_sample = np.argmin(distances) + + # Add to the voronoi list of the closest sample + self.areas[closest_sample] = self.areas[closest_sample] + 1 + prev_closest_points = self.closest_points[closest_sample] + self.closest_points[closest_sample] = np.vstack( + (prev_closest_points, points[idx]) + ) + + # Divide by the amount of points to get the estimated volume of each + # voronoi cell + self.areas /= n_points + + self.perc = np.max(self.areas * 100) + + self.errors = self.areas + + return self.areas, self.all_candidates + + # ------------------------------------------------------------------------- + def _build_dist_matrix_point(self, samples, point, method='euclidean', + do_sqrt=False): + """ + Calculates the intersite distance of all points in samples from point. + + Parameters + ---------- + samples : array of shape (n_samples, n_params) + The old experimental design. + point : array + A candidate point. + method : str + Distance method. + do_sqrt : bool, optional + Whether to return distances or squared distances. The default is + `False`. + + Returns + ------- + distances : array + Distances. + + """ + distances = distance.cdist(samples, np.array([point]), method) + + # do square root? + if do_sqrt: + return distances + else: + return distances**2 + diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/glexindex.py b/examples/analytical-function/bayesvalidrox/surrogate_models/glexindex.py new file mode 100644 index 000000000..90877331e --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/surrogate_models/glexindex.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Multi indices for monomial exponents. +Credit: Jonathan Feinberg +https://github.com/jonathf/numpoly/blob/master/numpoly/utils/glexindex.py +""" + +import numpy +import numpy.typing + + +def glexindex(start, stop=None, dimensions=1, cross_truncation=1., + graded=False, reverse=False): + """ + Generate graded lexicographical multi-indices for the monomial exponents. + Args: + start (Union[int, numpy.ndarray]): + The lower order of the indices. If array of int, counts as lower + bound for each axis. + stop (Union[int, numpy.ndarray, None]): + The maximum shape included. If omitted: stop <- start; start <- 0 + If int is provided, set as largest total order. If array of int, + set as upper bound for each axis. + dimensions (int): + The number of dimensions in the expansion. + cross_truncation (float, Tuple[float, float]): + Use hyperbolic cross truncation scheme to reduce the number of + terms in expansion. If two values are provided, first is low bound + truncation, while the latter upper bound. If only one value, upper + bound is assumed. + graded (bool): + Graded sorting, meaning the indices are always sorted by the index + sum. E.g. ``(2, 2, 2)`` has a sum of 6, and will therefore be + consider larger than both ``(3, 1, 1)`` and ``(1, 1, 3)``. + reverse (bool): + Reversed lexicographical sorting meaning that ``(1, 3)`` is + considered smaller than ``(3, 1)``, instead of the opposite. + Returns: + list: + Order list of indices. + Examples: + >>> numpoly.glexindex(4).tolist() + [[0], [1], [2], [3]] + >>> numpoly.glexindex(2, dimensions=2).tolist() + [[0, 0], [1, 0], [0, 1]] + >>> numpoly.glexindex(start=2, stop=3, dimensions=2).tolist() + [[2, 0], [1, 1], [0, 2]] + >>> numpoly.glexindex([1, 2, 3]).tolist() + [[0, 0, 0], [0, 1, 0], [0, 0, 1], [0, 0, 2]] + >>> numpoly.glexindex([1, 2, 3], cross_truncation=numpy.inf).tolist() + [[0, 0, 0], [0, 1, 0], [0, 0, 1], [0, 1, 1], [0, 0, 2], [0, 1, 2]] + """ + if stop is None: + start, stop = 0, start + start = numpy.array(start, dtype=int).flatten() + stop = numpy.array(stop, dtype=int).flatten() + start, stop, _ = numpy.broadcast_arrays(start, stop, numpy.empty(dimensions)) + + cross_truncation = cross_truncation*numpy.ones(2) + + # Moved here from _glexindex + bound = stop.max() + dimensions = len(start) + start = numpy.clip(start, a_min=0, a_max=None) + dtype = numpy.uint8 if bound < 256 else numpy.uint16 + range_ = numpy.arange(bound, dtype=dtype) + indices = range_[:, numpy.newaxis] + + for idx in range(dimensions-1): + + # Truncate at each step to keep memory usage low + if idx: + indices = indices[cross_truncate(indices, bound-1, cross_truncation[1])] + + # Repeats the current set of indices. + # e.g. [0,1,2] -> [0,1,2,0,1,2,...,0,1,2] + indices = numpy.tile(indices, (bound, 1)) + + # Stretches ranges over the new dimension. + # e.g. [0,1,2] -> [0,0,...,0,1,1,...,1,2,2,...,2] + front = range_.repeat(len(indices)//bound)[:, numpy.newaxis] + + # Puts them two together. + indices = numpy.column_stack((front, indices)) + + # Complete the truncation scheme + if dimensions == 1: + indices = indices[(indices >= start) & (indices < bound)] + else: + lower = cross_truncate(indices, start-1, cross_truncation[0]) + upper = cross_truncate(indices, stop-1, cross_truncation[1]) + indices = indices[lower ^ upper] + + indices = numpy.array(indices, dtype=int).reshape(-1, dimensions) + if indices.size: + # moved here from glexsort + keys = indices.T + keys_ = numpy.atleast_2d(keys) + if reverse: + keys_ = keys_[::-1] + + indices_sort = numpy.array(numpy.lexsort(keys_)) + if graded: + indices_sort = indices_sort[numpy.argsort( + numpy.sum(keys_[:, indices_sort], axis=0))].T + + indices = indices[indices_sort] + return indices + +def cross_truncate(indices, bound, norm): + r""" + Truncate of indices using L_p norm. + .. math: + L_p(x) = \sum_i |x_i/b_i|^p ^{1/p} \leq 1 + where :math:`b_i` are bounds that each :math:`x_i` should follow. + Args: + indices (Sequence[int]): + Indices to be truncated. + bound (int, Sequence[int]): + The bound function for witch the indices can not be larger than. + norm (float, Sequence[float]): + The `p` in the `L_p`-norm. Support includes both `L_0` and `L_inf`. + Returns: + Boolean indices to ``indices`` with True for each index where the + truncation criteria holds. + Examples: + >>> indices = numpy.array(numpy.mgrid[:10, :10]).reshape(2, -1).T + >>> indices[cross_truncate(indices, 2, norm=0)].T + array([[0, 0, 0, 1, 2], + [0, 1, 2, 0, 0]]) + >>> indices[cross_truncate(indices, 2, norm=1)].T + array([[0, 0, 0, 1, 1, 2], + [0, 1, 2, 0, 1, 0]]) + >>> indices[cross_truncate(indices, [0, 1], norm=1)].T + array([[0, 0], + [0, 1]]) + """ + assert norm >= 0, "negative L_p norm not allowed" + bound = numpy.asfarray(bound).flatten()*numpy.ones(indices.shape[1]) + + if numpy.any(bound < 0): + return numpy.zeros((len(indices),), dtype=bool) + + if numpy.any(bound == 0): + out = numpy.all(indices[:, bound == 0] == 0, axis=-1) + if numpy.any(bound): + out &= cross_truncate(indices[:, bound != 0], bound[bound != 0], norm=norm) + return out + + if norm == 0: + out = numpy.sum(indices > 0, axis=-1) <= 1 + out[numpy.any(indices > bound, axis=-1)] = False + elif norm == numpy.inf: + out = numpy.max(indices/bound, axis=-1) <= 1 + else: + out = numpy.sum((indices/bound)**norm, axis=-1)**(1./norm) <= 1 + + assert numpy.all(out[numpy.all(indices == 0, axis=-1)]) + + return out diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/input_space.py b/examples/analytical-function/bayesvalidrox/surrogate_models/input_space.py new file mode 100644 index 000000000..4e010d66f --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/surrogate_models/input_space.py @@ -0,0 +1,398 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Input space built from set prior distributions +""" + +import numpy as np +import chaospy +import scipy.stats as st + + +class InputSpace: + """ + This class generates the input space for the metamodel from the + distributions provided using the `Input` object. + + Attributes + ---------- + Input : obj + Input object containing the parameter marginals, i.e. name, + distribution type and distribution parameters or available raw data. + meta_Model_type : str + Type of the meta_Model_type. + + """ + + def __init__(self, Input, meta_Model_type='pce'): + self.InputObj = Input + self.meta_Model_type = meta_Model_type + + # Other + self.apce = None + self.ndim = None + + # Init + self.check_valid_inputs() + + + def check_valid_inputs(self)-> None: + """ + Check if the given InputObj is valid to use for further calculations: + Has some Marginals + Marginals have valid priors + All Marginals given as the same type (samples vs dist) + + Returns + ------- + None + + """ + Inputs = self.InputObj + self.ndim = len(Inputs.Marginals) + + # Check if PCE or aPCE metamodel is selected. + # TODO: test also for 'pce'?? + if self.meta_Model_type.lower() == 'apce': + self.apce = True + else: + self.apce = False + + # check if marginals given + if not self.ndim >=1: + raise AssertionError('Cannot build distributions if no marginals are given') + + # check that each marginal is valid + for marginals in Inputs.Marginals: + if len(marginals.input_data) == 0: + if marginals.dist_type == None: + raise AssertionError('Not all marginals were provided priors') + break + if np.array(marginals.input_data).shape[0] and (marginals.dist_type != None): + raise AssertionError('Both samples and distribution type are given. Please choose only one.') + break + + # Check if input is given as dist or input_data. + self.input_data_given = -1 + for marg in Inputs.Marginals: + #print(self.input_data_given) + size = np.array(marg.input_data).shape[0] + #print(f'Size: {size}') + if size and abs(self.input_data_given) !=1: + self.input_data_given = 2 + break + if (not size) and self.input_data_given > 0: + self.input_data_given = 2 + break + if not size: + self.input_data_given = 0 + if size: + self.input_data_given = 1 + + if self.input_data_given == 2: + raise AssertionError('Distributions cannot be built as the priors have different types') + + + # Get the bounds if input_data are directly defined by user: + if self.input_data_given: + for i in range(self.ndim): + low_bound = np.min(Inputs.Marginals[i].input_data) + up_bound = np.max(Inputs.Marginals[i].input_data) + Inputs.Marginals[i].parameters = [low_bound, up_bound] + + + + # ------------------------------------------------------------------------- + def init_param_space(self, max_deg=None): + """ + Initializes parameter space. + + Parameters + ---------- + max_deg : int, optional + Maximum degree. The default is `None`. + + Creates + ------- + raw_data : array of shape (n_params, n_samples) + Raw data. + bound_tuples : list of tuples + A list containing lower and upper bounds of parameters. + + """ + # Recheck all before running! + self.check_valid_inputs() + + Inputs = self.InputObj + ndim = self.ndim + rosenblatt_flag = Inputs.Rosenblatt + mc_size = 50000 + + # Save parameter names + self.par_names = [] + for parIdx in range(ndim): + self.par_names.append(Inputs.Marginals[parIdx].name) + + # Create a multivariate probability distribution + # TODO: change this to make max_deg obligatory? at least in some specific cases? + if max_deg is not None: + JDist, poly_types = self.build_polytypes(rosenblatt=rosenblatt_flag) + self.JDist, self.poly_types = JDist, poly_types + + if self.input_data_given: + self.MCSize = len(Inputs.Marginals[0].input_data) + self.raw_data = np.zeros((ndim, self.MCSize)) + + for parIdx in range(ndim): + # Save parameter names + try: + self.raw_data[parIdx] = np.array( + Inputs.Marginals[parIdx].input_data) + except: + self.raw_data[parIdx] = self.JDist[parIdx].sample(mc_size) + + else: + # Generate random samples based on parameter distributions + self.raw_data = chaospy.generate_samples(mc_size, + domain=self.JDist) + + # Extract moments + for parIdx in range(ndim): + mu = np.mean(self.raw_data[parIdx]) + std = np.std(self.raw_data[parIdx]) + self.InputObj.Marginals[parIdx].moments = [mu, std] + + # Generate the bounds based on given inputs for marginals + bound_tuples = [] + for i in range(ndim): + if Inputs.Marginals[i].dist_type == 'unif': + low_bound = Inputs.Marginals[i].parameters[0] + up_bound = Inputs.Marginals[i].parameters[1] + else: + low_bound = np.min(self.raw_data[i]) + up_bound = np.max(self.raw_data[i]) + + bound_tuples.append((low_bound, up_bound)) + + self.bound_tuples = tuple(bound_tuples) + + # ------------------------------------------------------------------------- + def build_polytypes(self, rosenblatt): + """ + Creates the polynomial types to be passed to univ_basis_vals method of + the MetaModel object. + + Parameters + ---------- + rosenblatt : bool + Rosenblatt transformation flag. + + Returns + ------- + orig_space_dist : object + A chaospy JDist object or a gaussian_kde object. + poly_types : list + List of polynomial types for the parameters. + + """ + Inputs = self.InputObj + + all_data = [] + all_dist_types = [] + orig_joints = [] + poly_types = [] + + for parIdx in range(self.ndim): + + if Inputs.Marginals[parIdx].dist_type is None: + data = Inputs.Marginals[parIdx].input_data + all_data.append(data) + dist_type = None + else: + dist_type = Inputs.Marginals[parIdx].dist_type + params = Inputs.Marginals[parIdx].parameters + + if rosenblatt: + polytype = 'hermite' + dist = chaospy.Normal() + + elif dist_type is None: + polytype = 'arbitrary' + dist = None + + elif 'unif' in dist_type.lower(): + polytype = 'legendre' + if not np.array(params).shape[0]>=2: + raise AssertionError('Distribution has too few parameters!') + dist = chaospy.Uniform(lower=params[0], upper=params[1]) + + elif 'norm' in dist_type.lower() and \ + 'log' not in dist_type.lower(): + if not np.array(params).shape[0]>=2: + raise AssertionError('Distribution has too few parameters!') + polytype = 'hermite' + dist = chaospy.Normal(mu=params[0], sigma=params[1]) + + elif 'gamma' in dist_type.lower(): + polytype = 'laguerre' + if not np.array(params).shape[0]>=3: + raise AssertionError('Distribution has too few parameters!') + dist = chaospy.Gamma(shape=params[0], + scale=params[1], + shift=params[2]) + + elif 'beta' in dist_type.lower(): + if not np.array(params).shape[0]>=4: + raise AssertionError('Distribution has too few parameters!') + polytype = 'jacobi' + dist = chaospy.Beta(alpha=params[0], beta=params[1], + lower=params[2], upper=params[3]) + + elif 'lognorm' in dist_type.lower(): + polytype = 'hermite' + if not np.array(params).shape[0]>=2: + raise AssertionError('Distribution has too few parameters!') + mu = np.log(params[0]**2/np.sqrt(params[0]**2 + params[1]**2)) + sigma = np.sqrt(np.log(1 + params[1]**2 / params[0]**2)) + dist = chaospy.LogNormal(mu, sigma) + # dist = chaospy.LogNormal(mu=params[0], sigma=params[1]) + + elif 'expon' in dist_type.lower(): + polytype = 'exponential' + if not np.array(params).shape[0]>=2: + raise AssertionError('Distribution has too few parameters!') + dist = chaospy.Exponential(scale=params[0], shift=params[1]) + + elif 'weibull' in dist_type.lower(): + polytype = 'weibull' + if not np.array(params).shape[0]>=3: + raise AssertionError('Distribution has too few parameters!') + dist = chaospy.Weibull(shape=params[0], scale=params[1], + shift=params[2]) + + else: + message = (f"DistType {dist_type} for parameter" + f"{parIdx+1} is not available.") + raise ValueError(message) + + if self.input_data_given or self.apce: + polytype = 'arbitrary' + + # Store dists and poly_types + orig_joints.append(dist) + poly_types.append(polytype) + all_dist_types.append(dist_type) + + # Prepare final output to return + if None in all_dist_types: + # Naive approach: Fit a gaussian kernel to the provided data + Data = np.asarray(all_data) + try: + orig_space_dist = st.gaussian_kde(Data) + except: + raise ValueError('The samples provided to the Marginals should be 1D only') + self.prior_space = orig_space_dist + else: + orig_space_dist = chaospy.J(*orig_joints) + try: + self.prior_space = st.gaussian_kde(orig_space_dist.sample(10000)) + except: + raise ValueError('Parameter values are not valid, please set differently') + + return orig_space_dist, poly_types + + # ------------------------------------------------------------------------- + def transform(self, X, params=None, method=None): + """ + Transforms the samples via either a Rosenblatt or an isoprobabilistic + transformation. + + Parameters + ---------- + X : array of shape (n_samples,n_params) + Samples to be transformed. + method : string + If transformation method is 'user' transform X, else just pass X. + + Returns + ------- + tr_X: array of shape (n_samples,n_params) + Transformed samples. + + """ + # Check for built JDist + if not hasattr(self, 'JDist'): + raise AttributeError('Call function init_param_space first to create JDist') + + # Check if X is 2d + if X.ndim != 2: + raise AttributeError('X should have two dimensions') + + # Check if size of X matches Marginals + if X.shape[1]!= self.ndim: + raise AttributeError('The second dimension of X should be the same size as the number of marginals in the InputObj') + + if self.InputObj.Rosenblatt: + self.origJDist, _ = self.build_polytypes(False) + if method == 'user': + tr_X = self.JDist.inv(self.origJDist.fwd(X.T)).T + else: + # Inverse to original spcace -- generate sample ED + tr_X = self.origJDist.inv(self.JDist.fwd(X.T)).T + else: + # Transform samples via an isoprobabilistic transformation + n_samples, n_params = X.shape + Inputs = self.InputObj + origJDist = self.JDist + poly_types = self.poly_types + + disttypes = [] + for par_i in range(n_params): + disttypes.append(Inputs.Marginals[par_i].dist_type) + + # Pass non-transformed X, if arbitrary PCE is selected. + if None in disttypes or self.input_data_given or self.apce: + return X + + cdfx = np.zeros((X.shape)) + tr_X = np.zeros((X.shape)) + + for par_i in range(n_params): + + # Extract the parameters of the original space + disttype = disttypes[par_i] + if disttype is not None: + dist = origJDist[par_i] + else: + dist = None + polytype = poly_types[par_i] + cdf = np.vectorize(lambda x: dist.cdf(x)) + + # Extract the parameters of the transformation space based on + # polyType + if polytype == 'legendre' or disttype == 'uniform': + # Generate Y_Dists based + params_Y = [-1, 1] + dist_Y = st.uniform(loc=params_Y[0], + scale=params_Y[1]-params_Y[0]) + inv_cdf = np.vectorize(lambda x: dist_Y.ppf(x)) + + elif polytype == 'hermite' or disttype == 'norm': + params_Y = [0, 1] + dist_Y = st.norm(loc=params_Y[0], scale=params_Y[1]) + inv_cdf = np.vectorize(lambda x: dist_Y.ppf(x)) + + elif polytype == 'laguerre' or disttype == 'gamma': + if params == None: + raise AttributeError('Additional parameters have to be set for the gamma distribution!') + params_Y = [1, params[1]] + dist_Y = st.gamma(loc=params_Y[0], scale=params_Y[1]) + inv_cdf = np.vectorize(lambda x: dist_Y.ppf(x)) + + # Compute CDF_x(X) + cdfx[:, par_i] = cdf(X[:, par_i]) + + # Compute invCDF_y(cdfx) + tr_X[:, par_i] = inv_cdf(cdfx[:, par_i]) + + return tr_X diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/inputs.py b/examples/analytical-function/bayesvalidrox/surrogate_models/inputs.py new file mode 100644 index 000000000..094e1066f --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/surrogate_models/inputs.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Inputs and related marginal distributions +""" + +class Input: + """ + A class to define the uncertain input parameters. + + Attributes + ---------- + Marginals : obj + Marginal objects. See `inputs.Marginal`. + Rosenblatt : bool + If Rossenblatt transformation is required for the dependent input + parameters. + + Examples + ------- + Marginals can be defined as following: + + >>> Inputs.add_marginals() + >>> Inputs.Marginals[0].name = 'X_1' + >>> Inputs.Marginals[0].dist_type = 'uniform' + >>> Inputs.Marginals[0].parameters = [-5, 5] + + If there is no common data is avaliable, the input data can be given + as following: + + >>> Inputs.add_marginals() + >>> Inputs.Marginals[0].name = 'X_1' + >>> Inputs.Marginals[0].input_data = input_data + """ + poly_coeffs_flag = True + + def __init__(self): + self.Marginals = [] + self.Rosenblatt = False + + def add_marginals(self): + """ + Adds a new Marginal object to the input object. + + Returns + ------- + None. + + """ + self.Marginals.append(Marginal()) + + +# Nested class +class Marginal: + """ + An object containing the specifications of the marginals for each uncertain + parameter. + + Attributes + ---------- + name : string + Name of the parameter. The default is `'$x_1$'`. + dist_type : string + Name of the distribution. The default is `None`. + parameters : list + List of the parameters corresponding to the distribution type. The + default is `None`. + input_data : array + Available input data. The default is `[]`. + moments : list + List of the moments. + """ + + def __init__(self): + self.name = '$x_1$' + self.dist_type = None + self.parameters = None + self.input_data = [] + self.moments = None diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/meta_model_engine.py b/examples/analytical-function/bayesvalidrox/surrogate_models/meta_model_engine.py new file mode 100644 index 000000000..71c024421 --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/surrogate_models/meta_model_engine.py @@ -0,0 +1,2195 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Fri Jan 28 09:21:18 2022 + +@author: farid +""" +import numpy as np +from scipy import stats, signal, linalg, sparse +from scipy.spatial import distance +from copy import deepcopy, copy +from tqdm import tqdm +import scipy.optimize as opt +from sklearn.metrics import mean_squared_error +import multiprocessing +import matplotlib.pyplot as plt +import sys +import os +import gc +import seaborn as sns +from joblib import Parallel, delayed + +import bayesvalidrox +from .exploration import Exploration +from bayesvalidrox.bayes_inference.bayes_inference import BayesInference +from bayesvalidrox.bayes_inference.discrepancy import Discrepancy +import pandas as pd + + +class MetaModelEngine(): + """ Sequential experimental design + This class provieds method for trainig the meta-model in an iterative + manners. + The main method to execute the task is `train_seq_design`, which + recieves a model object and returns the trained metamodel. + """ + + def __init__(self, meta_model_opts): + self.MetaModel = meta_model_opts + + # ------------------------------------------------------------------------- + def run(self): + + Model = self.MetaModel.ModelObj + self.MetaModel.n_params = len(self.MetaModel.input_obj.Marginals) + self.MetaModel.ExpDesignFlag = 'normal' + # --- Prepare pce degree --- + if self.MetaModel.meta_model_type.lower() == 'pce': + if type(self.MetaModel.pce_deg) is not np.ndarray: + self.MetaModel.pce_deg = np.array(self.MetaModel.pce_deg) + + if self.MetaModel.ExpDesign.method == 'normal': + self.MetaModel.ExpDesignFlag = 'normal' + self.MetaModel.train_norm_design(parallel = False) + + elif self.MetaModel.ExpDesign.method == 'sequential': + self.train_seq_design() + else: + raise Exception("The method for experimental design you requested" + " has not been implemented yet.") + + # Zip the model run directories + if self.MetaModel.ModelObj.link_type.lower() == 'pylink' and\ + self.MetaModel.ExpDesign.sampling_method.lower() != 'user': + Model.zip_subdirs(Model.name, f'{Model.name}_') + + # ------------------------------------------------------------------------- + def train_seq_design(self): + """ + Starts the adaptive sequential design for refining the surrogate model + by selecting training points in a sequential manner. + + Returns + ------- + MetaModel : object + Meta model object. + + """ + # Set model to have shorter call + Model = self.MetaModel.ModelObj + # MetaModel = self.MetaModel + self.Model = Model + + # Initialization + self.MetaModel.SeqModifiedLOO = {} + self.MetaModel.seqValidError = {} + self.MetaModel.SeqBME = {} + self.MetaModel.SeqKLD = {} + self.MetaModel.SeqDistHellinger = {} + self.MetaModel.seqRMSEMean = {} + self.MetaModel.seqRMSEStd = {} + self.MetaModel.seqMinDist = [] + + # Determine the metamodel type + if self.MetaModel.meta_model_type.lower() != 'gpe': + pce = True + else: + pce = False + # If given, use mc reference data + mc_ref = True if bool(Model.mc_reference) else False + if mc_ref: + Model.read_mc_reference() + + # if valid_samples not defined, do so now + if not hasattr(self.MetaModel, 'valid_samples'): + self.MetaModel.valid_samples = [] + self.MetaModel.valid_model_runs = [] + self.MetaModel.valid_likelihoods = [] + + # Get the parameters + max_n_samples = self.MetaModel.ExpDesign.n_max_samples + mod_LOO_threshold = self.MetaModel.ExpDesign.mod_LOO_threshold + n_canddidate = self.MetaModel.ExpDesign.n_canddidate + post_snapshot = self.MetaModel.ExpDesign.post_snapshot + n_replication = self.MetaModel.ExpDesign.n_replication + util_func = self.MetaModel.ExpDesign.util_func + output_name = Model.Output.names + validError = None + # Handle if only one UtilityFunctions is provided + if not isinstance(util_func, list): + util_func = [self.MetaModel.ExpDesign.util_func] + + # Read observations or MCReference + if len(Model.observations) != 0 or Model.meas_file is not None: + self.observations = Model.read_observation() + obs_data = self.observations + else: + obs_data = [] + TotalSigma2 = {} + + # TODO: ---------- Initial self.MetaModel ---------- + # First run MetaModel on non-sequential design + self.MetaModel.train_norm_design(parallel = False) + initMetaModel = deepcopy(self.MetaModel) + + # Validation error if validation set is provided. - use as initial errors + if self.MetaModel.valid_model_runs: + init_rmse, init_valid_error = self.__validError(initMetaModel) + init_valid_error = list(init_valid_error.values()) + else: + init_rmse = None + + # Check if discrepancy is provided + if len(obs_data) != 0 and hasattr(self.MetaModel, 'Discrepancy'): + TotalSigma2 = self.MetaModel.Discrepancy.parameters + + # Calculate the initial BME + out = self.__BME_Calculator( + initMetaModel, obs_data, TotalSigma2, init_rmse) + init_BME, init_KLD, init_post, init_likes, init_dist_hellinger = out + print(f"\nInitial BME: {init_BME:.2f}") + print(f"Initial KLD: {init_KLD:.2f}") + + # Posterior snapshot (initial) + if post_snapshot: + parNames = self.MetaModel.ExpDesign.par_names + print('Posterior snapshot (initial) is being plotted...') + self.__posteriorPlot(init_post, parNames, 'SeqPosterior_init') + + # Check the convergence of the Mean & Std + if mc_ref and pce: + init_rmse_mean, init_rmse_std = self.__error_Mean_Std() + print(f"Initial Mean and Std error: {init_rmse_mean:.2f}," + f" {init_rmse_std:.2f}") + + # Read the initial experimental design + # TODO: this sequential, or the non-sequential samples?? + Xinit = initMetaModel.ExpDesign.X + init_n_samples = len(initMetaModel.ExpDesign.X) + initYprev = initMetaModel.ModelOutputDict + initLCerror = initMetaModel.LCerror + n_itrs = max_n_samples - init_n_samples + + # Read the initial ModifiedLOO + if pce: + Scores_all, varExpDesignY = [], [] + for out_name in output_name: + y = self.MetaModel.ExpDesign.Y[out_name] + Scores_all.append(list( + self.MetaModel.score_dict['b_1'][out_name].values())) + if self.MetaModel.dim_red_method.lower() == 'pca': + pca = self.MetaModel.pca['b_1'][out_name] + components = pca.transform(y) + varExpDesignY.append(np.var(components, axis=0)) + else: + varExpDesignY.append(np.var(y, axis=0)) + + Scores = [item for sublist in Scores_all for item in sublist] + weights = [item for sublist in varExpDesignY for item in sublist] + init_mod_LOO = [np.average([1-score for score in Scores], + weights=weights)] + + prevMetaModel_dict = {} + # Replicate the sequential design + for repIdx in range(n_replication): # TODO: what does this do? + print(f'\n>>>> Replication: {repIdx+1}<<<<') + + # To avoid changes ub original aPCE object + self.MetaModel.ExpDesign.X = Xinit + self.MetaModel.ExpDesign.Y = initYprev + self.MetaModel.LCerror = initLCerror + + for util_f in util_func: # TODO: recheck choices for this + print(f'\n>>>> Utility Function: {util_f} <<<<') + # To avoid changes ub original aPCE object + self.MetaModel.ExpDesign.X = Xinit + self.MetaModel.ExpDesign.Y = initYprev + self.MetaModel.LCerror = initLCerror + + # Set the experimental design + Xprev = Xinit + total_n_samples = init_n_samples + Yprev = initYprev + + Xfull = [] + Yfull = [] + + # Store the initial ModifiedLOO + if pce: + print("\nInitial ModifiedLOO:", init_mod_LOO) + SeqModifiedLOO = np.array(init_mod_LOO) + + if len(self.MetaModel.valid_model_runs) != 0: + SeqValidError = np.array(init_valid_error) + + # Check if data is provided + if len(obs_data) != 0: + SeqBME = np.array([init_BME]) + SeqKLD = np.array([init_KLD]) + SeqDistHellinger = np.array([init_dist_hellinger]) + + if mc_ref and pce: + seqRMSEMean = np.array([init_rmse_mean]) + seqRMSEStd = np.array([init_rmse_std]) + + # ------- Start Sequential Experimental Design ------- + postcnt = 1 + for itr_no in range(1, n_itrs+1): + print(f'\n>>>> Iteration number {itr_no} <<<<') + + # Save the metamodel prediction before updating + prevMetaModel_dict[itr_no] = deepcopy(self.MetaModel) # Write last MetaModel here + if itr_no > 1: + pc_model = prevMetaModel_dict[itr_no-1] + self._y_hat_prev, _ = pc_model.eval_metamodel( # What's the use of this here?? + samples=Xfull[-1].reshape(1, -1)) + del prevMetaModel_dict[itr_no-1] # Delete second to last metamodel here? + + # Optimal Bayesian Design + self.MetaModel.ExpDesignFlag = 'sequential' + Xnew, updatedPrior = self.opt_SeqDesign(TotalSigma2, # TODO: check in this!! + n_canddidate, + util_f) + S = np.min(distance.cdist(Xinit, Xnew, 'euclidean')) + self.MetaModel.seqMinDist.append(S) + print(f"\nmin Dist from OldExpDesign: {S:2f}") + print("\n") + + # Evaluate the full model response at the new sample + Ynew, _ = Model.run_model_parallel( + Xnew, prevRun_No=total_n_samples + ) + total_n_samples += Xnew.shape[0] + + # ------ Plot the surrogate model vs Origninal Model ------ + if hasattr(self.MetaModel, 'adapt_verbose') and \ + self.MetaModel.adapt_verbose: + from .adaptPlot import adaptPlot + y_hat, std_hat = self.MetaModel.eval_metamodel( + samples=Xnew + ) + adaptPlot( + self.MetaModel, Ynew, y_hat, std_hat, + plotED=False + ) + + # -------- Retrain the surrogate model ------- + # Extend new experimental design + Xfull = np.vstack((Xprev, Xnew)) + + # Updating experimental design Y + for out_name in output_name: + Yfull = np.vstack((Yprev[out_name], Ynew[out_name])) + self.MetaModel.ModelOutputDict[out_name] = Yfull + + # Pass new design to the metamodel object + self.MetaModel.ExpDesign.sampling_method = 'user' + self.MetaModel.ExpDesign.X = Xfull + self.MetaModel.ExpDesign.Y = self.MetaModel.ModelOutputDict + + # Save the Experimental Design for next iteration + Xprev = Xfull + Yprev = self.MetaModel.ModelOutputDict + + # Pass the new prior as the input + self.MetaModel.input_obj.poly_coeffs_flag = False + if updatedPrior is not None: + self.MetaModel.input_obj.poly_coeffs_flag = True + print("updatedPrior:", updatedPrior.shape) + # Arbitrary polynomial chaos + for i in range(updatedPrior.shape[1]): + self.MetaModel.input_obj.Marginals[i].dist_type = None + x = updatedPrior[:, i] + self.MetaModel.input_obj.Marginals[i].raw_data = x + + # Train the surrogate model for new ExpDesign + self.MetaModel.train_norm_design(parallel=False) + + # -------- Evaluate the retrained surrogate model ------- + # Extract Modified LOO from Output + if pce: + Scores_all, varExpDesignY = [], [] + for out_name in output_name: + y = self.MetaModel.ExpDesign.Y[out_name] + Scores_all.append(list( + self.MetaModel.score_dict['b_1'][out_name].values())) + if self.MetaModel.dim_red_method.lower() == 'pca': + pca = self.MetaModel.pca['b_1'][out_name] + components = pca.transform(y) + varExpDesignY.append(np.var(components, + axis=0)) + else: + varExpDesignY.append(np.var(y, axis=0)) + Scores = [item for sublist in Scores_all for item + in sublist] + weights = [item for sublist in varExpDesignY for item + in sublist] + ModifiedLOO = [np.average( + [1-score for score in Scores], weights=weights)] + + print('\n') + print(f"Updated ModifiedLOO {util_f}:\n", ModifiedLOO) + print('\n') + + # Compute the validation error + if self.MetaModel.valid_model_runs: + rmse, validError = self.__validError(self.MetaModel) + ValidError = list(validError.values()) + else: + rmse = None + + # Store updated ModifiedLOO + if pce: + SeqModifiedLOO = np.vstack( + (SeqModifiedLOO, ModifiedLOO)) + if len(self.MetaModel.valid_model_runs) != 0: + SeqValidError = np.vstack( + (SeqValidError, ValidError)) + # -------- Caclulation of BME as accuracy metric ------- + # Check if data is provided + if len(obs_data) != 0: + # Calculate the initial BME + out = self.__BME_Calculator(self.MetaModel, obs_data, + TotalSigma2, rmse) + BME, KLD, Posterior, likes, DistHellinger = out + print('\n') + print(f"Updated BME: {BME:.2f}") + print(f"Updated KLD: {KLD:.2f}") + print('\n') + + # Plot some snapshots of the posterior + step_snapshot = self.MetaModel.ExpDesign.step_snapshot + if post_snapshot and postcnt % step_snapshot == 0: + parNames = self.MetaModel.ExpDesign.par_names + print('Posterior snapshot is being plotted...') + self.__posteriorPlot(Posterior, parNames, + f'SeqPosterior_{postcnt}') + postcnt += 1 + + # Check the convergence of the Mean&Std + if mc_ref and pce: + print('\n') + RMSE_Mean, RMSE_std = self.__error_Mean_Std() + print(f"Updated Mean and Std error: {RMSE_Mean:.2f}, " + f"{RMSE_std:.2f}") + print('\n') + + # Store the updated BME & KLD + # Check if data is provided + if len(obs_data) != 0: + SeqBME = np.vstack((SeqBME, BME)) + SeqKLD = np.vstack((SeqKLD, KLD)) + SeqDistHellinger = np.vstack((SeqDistHellinger, + DistHellinger)) + if mc_ref and pce: + seqRMSEMean = np.vstack((seqRMSEMean, RMSE_Mean)) + seqRMSEStd = np.vstack((seqRMSEStd, RMSE_std)) + + if pce and any(LOO < mod_LOO_threshold + for LOO in ModifiedLOO): + break + + # Clean up + if len(obs_data) != 0: + del out + print() + print('-'*50) + print() + + # Store updated ModifiedLOO and BME in dictonary + strKey = f'{util_f}_rep_{repIdx+1}' + if pce: + self.MetaModel.SeqModifiedLOO[strKey] = SeqModifiedLOO + if len(self.MetaModel.valid_model_runs) != 0: + self.MetaModel.seqValidError[strKey] = SeqValidError + + # Check if data is provided + if len(obs_data) != 0: + self.MetaModel.SeqBME[strKey] = SeqBME + self.MetaModel.SeqKLD[strKey] = SeqKLD + if hasattr(self.MetaModel, 'valid_likelihoods') and \ + self.MetaModel.valid_likelihoods: + self.MetaModel.SeqDistHellinger[strKey] = SeqDistHellinger + if mc_ref and pce: + self.MetaModel.seqRMSEMean[strKey] = seqRMSEMean + self.MetaModel.seqRMSEStd[strKey] = seqRMSEStd + + # return self.MetaModel + + # ------------------------------------------------------------------------- + def util_VarBasedDesign(self, X_can, index, util_func='Entropy'): + """ + Computes the exploitation scores based on: + active learning MacKay(ALM) and active learning Cohn (ALC) + Paper: Sequential Design with Mutual Information for Computer + Experiments (MICE): Emulation of a Tsunami Model by Beck and Guillas + (2016) + + Parameters + ---------- + X_can : array of shape (n_samples, n_params) + Candidate samples. + index : int + Model output index. + UtilMethod : string, optional + Exploitation utility function. The default is 'Entropy'. + + Returns + ------- + float + Score. + + """ + MetaModel = self.MetaModel + ED_X = MetaModel.ExpDesign.X + out_dict_y = MetaModel.ExpDesign.Y + out_names = MetaModel.ModelObj.Output.names + + # Run the Metamodel for the candidate + X_can = X_can.reshape(1, -1) + Y_PC_can, std_PC_can = MetaModel.eval_metamodel(samples=X_can) + + if util_func.lower() == 'alm': + # ----- Entropy/MMSE/active learning MacKay(ALM) ----- + # Compute perdiction variance of the old model + canPredVar = {key: std_PC_can[key]**2 for key in out_names} + + varPCE = np.zeros((len(out_names), X_can.shape[0])) + for KeyIdx, key in enumerate(out_names): + varPCE[KeyIdx] = np.max(canPredVar[key], axis=1) + score = np.max(varPCE, axis=0) + + elif util_func.lower() == 'eigf': + # ----- Expected Improvement for Global fit ----- + # Find closest EDX to the candidate + distances = distance.cdist(ED_X, X_can, 'euclidean') + index = np.argmin(distances) + + # Compute perdiction error and variance of the old model + predError = {key: Y_PC_can[key] for key in out_names} + canPredVar = {key: std_PC_can[key]**2 for key in out_names} + + # Compute perdiction error and variance of the old model + # Eq (5) from Liu et al.(2018) + EIGF_PCE = np.zeros((len(out_names), X_can.shape[0])) + for KeyIdx, key in enumerate(out_names): + residual = predError[key] - out_dict_y[key][int(index)] + var = canPredVar[key] + EIGF_PCE[KeyIdx] = np.max(residual**2 + var, axis=1) + score = np.max(EIGF_PCE, axis=0) + + return -1 * score # -1 is for minimization instead of maximization + + # ------------------------------------------------------------------------- + def util_BayesianActiveDesign(self, y_hat, std, sigma2Dict, var='DKL'): + """ + Computes scores based on Bayesian active design criterion (var). + + It is based on the following paper: + Oladyshkin, Sergey, Farid Mohammadi, Ilja Kroeker, and Wolfgang Nowak. + "Bayesian3 active learning for the gaussian process emulator using + information theory." Entropy 22, no. 8 (2020): 890. + + Parameters + ---------- + X_can : array of shape (n_samples, n_params) + Candidate samples. + sigma2Dict : dict + A dictionary containing the measurement errors (sigma^2). + var : string, optional + BAL design criterion. The default is 'DKL'. + + Returns + ------- + float + Score. + + """ + + # Get the data + obs_data = self.observations + n_obs = self.Model.n_obs + mc_size = 10000 + + # Sample a distribution for a normal dist + # with Y_mean_can as the mean and Y_std_can as std. + Y_MC, std_MC = {}, {} + logPriorLikelihoods = np.zeros((mc_size)) + for key in list(y_hat): + cov = np.diag(std[key]**2) + rv = stats.multivariate_normal(mean=y_hat[key], cov=cov) + Y_MC[key] = rv.rvs(size=mc_size) + logPriorLikelihoods += rv.logpdf(Y_MC[key]) + std_MC[key] = np.zeros((mc_size, y_hat[key].shape[0])) + + # Likelihood computation (Comparison of data and simulation + # results via PCE with candidate design) + likelihoods = self.__normpdf(Y_MC, std_MC, obs_data, sigma2Dict) + + # Rejection Step + # Random numbers between 0 and 1 + unif = np.random.rand(1, mc_size)[0] + + # Reject the poorly performed prior + accepted = (likelihoods/np.max(likelihoods)) >= unif + + # Prior-based estimation of BME + logBME = np.log(np.nanmean(likelihoods), dtype=np.longdouble) + + # Posterior-based expectation of likelihoods + postLikelihoods = likelihoods[accepted] + postExpLikelihoods = np.mean(np.log(postLikelihoods)) + + # Posterior-based expectation of prior densities + postExpPrior = np.mean(logPriorLikelihoods[accepted]) + + # Utility function Eq.2 in Ref. (2) + # Posterior covariance matrix after observing data y + # Kullback-Leibler Divergence (Sergey's paper) + if var == 'DKL': + + # TODO: Calculate the correction factor for BME + # BMECorrFactor = self.BME_Corr_Weight(PCE_SparseBayes_can, + # ObservationData, sigma2Dict) + # BME += BMECorrFactor + # Haun et al implementation + # U_J_d = np.mean(np.log(Likelihoods[Likelihoods!=0])- logBME) + U_J_d = postExpLikelihoods - logBME + + # Marginal log likelihood + elif var == 'BME': + U_J_d = np.nanmean(likelihoods) + + # Entropy-based information gain + elif var == 'infEntropy': + logBME = np.log(np.nanmean(likelihoods)) + infEntropy = logBME - postExpPrior - postExpLikelihoods + U_J_d = infEntropy * -1 # -1 for minimization + + # Bayesian information criterion + elif var == 'BIC': + coeffs = self.MetaModel.coeffs_dict.values() + nModelParams = max(len(v) for val in coeffs for v in val.values()) + maxL = np.nanmax(likelihoods) + U_J_d = -2 * np.log(maxL) + np.log(n_obs) * nModelParams + + # Akaike information criterion + elif var == 'AIC': + coeffs = self.MetaModel.coeffs_dict.values() + nModelParams = max(len(v) for val in coeffs for v in val.values()) + maxlogL = np.log(np.nanmax(likelihoods)) + AIC = -2 * maxlogL + 2 * nModelParams + # 2 * nModelParams * (nModelParams+1) / (n_obs-nModelParams-1) + penTerm = 0 + U_J_d = 1*(AIC + penTerm) + + # Deviance information criterion + elif var == 'DIC': + # D_theta_bar = np.mean(-2 * Likelihoods) + N_star_p = 0.5 * np.var(np.log(likelihoods[likelihoods != 0])) + Likelihoods_theta_mean = self.__normpdf( + y_hat, std, obs_data, sigma2Dict + ) + DIC = -2 * np.log(Likelihoods_theta_mean) + 2 * N_star_p + + U_J_d = DIC + + else: + print('The algorithm you requested has not been implemented yet!') + + # Handle inf and NaN (replace by zero) + if np.isnan(U_J_d) or U_J_d == -np.inf or U_J_d == np.inf: + U_J_d = 0.0 + + # Clear memory + del likelihoods + del Y_MC + del std_MC + + return -1 * U_J_d # -1 is for minimization instead of maximization + + # ------------------------------------------------------------------------- + def update_metamodel(self, MetaModel, output, y_hat_can, univ_p_val, index, + new_pca=False): + BasisIndices = MetaModel.basis_dict[output]["y_"+str(index+1)] + clf_poly = MetaModel.clf_poly[output]["y_"+str(index+1)] + Mn = clf_poly.coef_ + Sn = clf_poly.sigma_ + beta = clf_poly.alpha_ + active = clf_poly.active_ + Psi = self.MetaModel.create_psi(BasisIndices, univ_p_val) + + Sn_new_inv = np.linalg.inv(Sn) + Sn_new_inv += beta * np.dot(Psi[:, active].T, Psi[:, active]) + Sn_new = np.linalg.inv(Sn_new_inv) + + Mn_new = np.dot(Sn_new_inv, Mn[active]).reshape(-1, 1) + Mn_new += beta * np.dot(Psi[:, active].T, y_hat_can) + Mn_new = np.dot(Sn_new, Mn_new).flatten() + + # Compute the old and new moments of PCEs + mean_old = Mn[0] + mean_new = Mn_new[0] + std_old = np.sqrt(np.sum(np.square(Mn[1:]))) + std_new = np.sqrt(np.sum(np.square(Mn_new[1:]))) + + # Back transformation if PCA is selected. + if MetaModel.dim_red_method.lower() == 'pca': + old_pca = MetaModel.pca[output] + mean_old = old_pca.mean_[index] + mean_old += np.sum(mean_old * old_pca.components_[:, index]) + std_old = np.sqrt(np.sum(std_old**2 * + old_pca.components_[:, index]**2)) + mean_new = new_pca.mean_[index] + mean_new += np.sum(mean_new * new_pca.components_[:, index]) + std_new = np.sqrt(np.sum(std_new**2 * + new_pca.components_[:, index]**2)) + # print(f"mean_old: {mean_old:.2f} mean_new: {mean_new:.2f}") + # print(f"std_old: {std_old:.2f} std_new: {std_new:.2f}") + # Store the old and new moments of PCEs + results = { + 'mean_old': mean_old, + 'mean_new': mean_new, + 'std_old': std_old, + 'std_new': std_new + } + return results + + # ------------------------------------------------------------------------- + def util_BayesianDesign_old(self, X_can, X_MC, sigma2Dict, var='DKL'): + """ + Computes scores based on Bayesian sequential design criterion (var). + + Parameters + ---------- + X_can : array of shape (n_samples, n_params) + Candidate samples. + sigma2Dict : dict + A dictionary containing the measurement errors (sigma^2). + var : string, optional + Bayesian design criterion. The default is 'DKL'. + + Returns + ------- + float + Score. + + """ + + # To avoid changes ub original aPCE object + Model = self.Model + MetaModel = deepcopy(self.MetaModel) + old_EDY = MetaModel.ExpDesign.Y + + # Evaluate the PCE metamodels using the candidate design + Y_PC_can, Y_std_can = self.MetaModel.eval_metamodel( + samples=np.array([X_can]) + ) + + # Generate y from posterior predictive + m_size = 100 + y_hat_samples = {} + for idx, key in enumerate(Model.Output.names): + means, stds = Y_PC_can[key][0], Y_std_can[key][0] + y_hat_samples[key] = np.random.multivariate_normal( + means, np.diag(stds), m_size) + + # Create the SparseBayes-based PCE metamodel: + MetaModel.input_obj.poly_coeffs_flag = False + univ_p_val = self.MetaModel.univ_basis_vals(X_can) + G_n_m_all = np.zeros((m_size, len(Model.Output.names), Model.n_obs)) + + for i in range(m_size): + for idx, key in enumerate(Model.Output.names): + if MetaModel.dim_red_method.lower() == 'pca': + # Equal number of components + new_outputs = np.vstack( + (old_EDY[key], y_hat_samples[key][i]) + ) + new_pca, _ = MetaModel.pca_transformation(new_outputs) + target = new_pca.transform( + y_hat_samples[key][i].reshape(1, -1) + )[0] + else: + new_pca, target = False, y_hat_samples[key][i] + + for j in range(len(target)): + + # Update surrogate + result = self.update_metamodel( + MetaModel, key, target[j], univ_p_val, j, new_pca) + + # Compute Expected Information Gain (Eq. 39) + G_n_m = np.log(result['std_old']/result['std_new']) - 1./2 + G_n_m += result['std_new']**2 / (2*result['std_old']**2) + G_n_m += (result['mean_new'] - result['mean_old'])**2 /\ + (2*result['std_old']**2) + + G_n_m_all[i, idx, j] = G_n_m + + U_J_d = G_n_m_all.mean(axis=(1, 2)).mean() + return -1 * U_J_d + + # ------------------------------------------------------------------------- + def util_BayesianDesign(self, X_can, X_MC, sigma2Dict, var='DKL'): + """ + Computes scores based on Bayesian sequential design criterion (var). + + Parameters + ---------- + X_can : array of shape (n_samples, n_params) + Candidate samples. + sigma2Dict : dict + A dictionary containing the measurement errors (sigma^2). + var : string, optional + Bayesian design criterion. The default is 'DKL'. + + Returns + ------- + float + Score. + + """ + + # To avoid changes ub original aPCE object + MetaModel = self.MetaModel + out_names = MetaModel.ModelObj.Output.names + if X_can.ndim == 1: + X_can = X_can.reshape(1, -1) + + # Compute the mean and std based on the MetaModel + # pce_means, pce_stds = self._compute_pce_moments(MetaModel) + if var == 'ALC': + Y_MC, Y_MC_std = MetaModel.eval_metamodel(samples=X_MC) + + # Old Experimental design + oldExpDesignX = MetaModel.ExpDesign.X + oldExpDesignY = MetaModel.ExpDesign.Y + + # Evaluate the PCE metamodels at that location ??? + Y_PC_can, Y_std_can = MetaModel.eval_metamodel(samples=X_can) + PCE_Model_can = deepcopy(MetaModel) + # Add the candidate to the ExpDesign + NewExpDesignX = np.vstack((oldExpDesignX, X_can)) + + NewExpDesignY = {} + for key in oldExpDesignY.keys(): + NewExpDesignY[key] = np.vstack( + (oldExpDesignY[key], Y_PC_can[key]) + ) + + PCE_Model_can.ExpDesign.sampling_method = 'user' + PCE_Model_can.ExpDesign.X = NewExpDesignX + PCE_Model_can.ModelOutputDict = NewExpDesignY + PCE_Model_can.ExpDesign.Y = NewExpDesignY + + # Train the model for the observed data using x_can + PCE_Model_can.input_obj.poly_coeffs_flag = False + PCE_Model_can.train_norm_design(parallel=False) + + # Set the ExpDesign to its original values + PCE_Model_can.ExpDesign.X = oldExpDesignX + PCE_Model_can.ModelOutputDict = oldExpDesignY + PCE_Model_can.ExpDesign.Y = oldExpDesignY + + if var.lower() == 'mi': + # Mutual information based on Krause et al + # Adapted from Beck & Guillas (MICE) paper + _, std_PC_can = PCE_Model_can.eval_metamodel(samples=X_can) + std_can = {key: std_PC_can[key] for key in out_names} + + std_old = {key: Y_std_can[key] for key in out_names} + + varPCE = np.zeros((len(out_names))) + for i, key in enumerate(out_names): + varPCE[i] = np.mean(std_old[key]**2/std_can[key]**2) + score = np.mean(varPCE) + + return -1 * score + + elif var.lower() == 'alc': + # Active learning based on Gramyc and Lee + # Adaptive design and analysis of supercomputer experiments Techno- + # metrics, 51 (2009), pp. 130–145. + + # Evaluate the MetaModel at the given samples + Y_MC_can, Y_MC_std_can = PCE_Model_can.eval_metamodel(samples=X_MC) + + # Compute the score + score = [] + for i, key in enumerate(out_names): + pce_var = Y_MC_std_can[key]**2 + pce_var_can = Y_MC_std[key]**2 + score.append(np.mean(pce_var-pce_var_can, axis=0)) + score = np.mean(score) + + return -1 * score + + # ---------- Inner MC simulation for computing Utility Value ---------- + # Estimation of the integral via Monte Varlo integration + MCsize = X_MC.shape[0] + ESS = 0 + + while ((ESS > MCsize) or (ESS < 1)): + + # Enriching Monte Carlo samples if need be + if ESS != 0: + X_MC = self.MetaModel.ExpDesign.generate_samples( + MCsize, 'random' + ) + + # Evaluate the MetaModel at the given samples + Y_MC, std_MC = PCE_Model_can.eval_metamodel(samples=X_MC) + + # Likelihood computation (Comparison of data and simulation + # results via PCE with candidate design) + likelihoods = self.__normpdf( + Y_MC, std_MC, self.observations, sigma2Dict + ) + + # Check the Effective Sample Size (1<ESS<MCsize) + ESS = 1 / np.sum(np.square(likelihoods/np.sum(likelihoods))) + + # Enlarge sample size if it doesn't fulfill the criteria + if ((ESS > MCsize) or (ESS < 1)): + print("--- increasing MC size---") + MCsize *= 10 + ESS = 0 + + # Rejection Step + # Random numbers between 0 and 1 + unif = np.random.rand(1, MCsize)[0] + + # Reject the poorly performed prior + accepted = (likelihoods/np.max(likelihoods)) >= unif + + # -------------------- Utility functions -------------------- + # Utility function Eq.2 in Ref. (2) + # Kullback-Leibler Divergence (Sergey's paper) + if var == 'DKL': + + # Prior-based estimation of BME + logBME = np.log(np.nanmean(likelihoods, dtype=np.longdouble)) + + # Posterior-based expectation of likelihoods + postLikelihoods = likelihoods[accepted] + postExpLikelihoods = np.mean(np.log(postLikelihoods)) + + # Haun et al implementation + U_J_d = np.mean(np.log(likelihoods[likelihoods != 0]) - logBME) + + # U_J_d = np.sum(G_n_m_all) + # Ryan et al (2014) implementation + # importanceWeights = Likelihoods[Likelihoods!=0]/np.sum(Likelihoods[Likelihoods!=0]) + # U_J_d = np.mean(importanceWeights*np.log(Likelihoods[Likelihoods!=0])) - logBME + + # U_J_d = postExpLikelihoods - logBME + + # Marginal likelihood + elif var == 'BME': + + # Prior-based estimation of BME + logBME = np.log(np.nanmean(likelihoods)) + U_J_d = logBME + + # Bayes risk likelihood + elif var == 'BayesRisk': + + U_J_d = -1 * np.var(likelihoods) + + # Entropy-based information gain + elif var == 'infEntropy': + # Prior-based estimation of BME + logBME = np.log(np.nanmean(likelihoods)) + + # Posterior-based expectation of likelihoods + postLikelihoods = likelihoods[accepted] + postLikelihoods /= np.nansum(likelihoods[accepted]) + postExpLikelihoods = np.mean(np.log(postLikelihoods)) + + # Posterior-based expectation of prior densities + postExpPrior = np.mean(logPriorLikelihoods[accepted]) + + infEntropy = logBME - postExpPrior - postExpLikelihoods + + U_J_d = infEntropy * -1 # -1 for minimization + + # D-Posterior-precision + elif var == 'DPP': + X_Posterior = X_MC[accepted] + # covariance of the posterior parameters + U_J_d = -np.log(np.linalg.det(np.cov(X_Posterior))) + + # A-Posterior-precision + elif var == 'APP': + X_Posterior = X_MC[accepted] + # trace of the posterior parameters + U_J_d = -np.log(np.trace(np.cov(X_Posterior))) + + else: + print('The algorithm you requested has not been implemented yet!') + + # Clear memory + del likelihoods + del Y_MC + del std_MC + + return -1 * U_J_d # -1 is for minimization instead of maximization + + # ------------------------------------------------------------------------- + def subdomain(self, Bounds, n_new_samples): + """ + Divides a domain defined by Bounds into sub domains. + + Parameters + ---------- + Bounds : list of tuples + List of lower and upper bounds. + n_new_samples : TYPE + DESCRIPTION. + + Returns + ------- + Subdomains : TYPE + DESCRIPTION. + + """ + n_params = self.MetaModel.n_params + n_subdomains = n_new_samples + 1 + LinSpace = np.zeros((n_params, n_subdomains)) + + for i in range(n_params): + LinSpace[i] = np.linspace(start=Bounds[i][0], stop=Bounds[i][1], + num=n_subdomains) + Subdomains = [] + for k in range(n_subdomains-1): + mylist = [] + for i in range(n_params): + mylist.append((LinSpace[i, k+0], LinSpace[i, k+1])) + Subdomains.append(tuple(mylist)) + + return Subdomains + + # ------------------------------------------------------------------------- + def run_util_func(self, method, candidates, index, sigma2Dict=None, + var=None, X_MC=None): + """ + Runs the utility function based on the given method. + + Parameters + ---------- + method : string + Exploitation method: `VarOptDesign`, `BayesActDesign` and + `BayesOptDesign`. + candidates : array of shape (n_samples, n_params) + All candidate parameter sets. + index : int + ExpDesign index. + sigma2Dict : dict, optional + A dictionary containing the measurement errors (sigma^2). The + default is None. + var : string, optional + Utility function. The default is None. + X_MC : TYPE, optional + DESCRIPTION. The default is None. + + Returns + ------- + index : TYPE + DESCRIPTION. + List + Scores. + + """ + + if method.lower() == 'varoptdesign': + # U_J_d = self.util_VarBasedDesign(candidates, index, var) + U_J_d = np.zeros((candidates.shape[0])) + for idx, X_can in tqdm(enumerate(candidates), ascii=True, + desc="varoptdesign"): + U_J_d[idx] = self.util_VarBasedDesign(X_can, index, var) + + elif method.lower() == 'bayesactdesign': + NCandidate = candidates.shape[0] + U_J_d = np.zeros((NCandidate)) + # Evaluate all candidates + y_can, std_can = self.MetaModel.eval_metamodel(samples=candidates) + # loop through candidates + for idx, X_can in tqdm(enumerate(candidates), ascii=True, + desc="BAL Design"): + y_hat = {key: items[idx] for key, items in y_can.items()} + std = {key: items[idx] for key, items in std_can.items()} + U_J_d[idx] = self.util_BayesianActiveDesign( + y_hat, std, sigma2Dict, var) + + elif method.lower() == 'bayesoptdesign': + NCandidate = candidates.shape[0] + U_J_d = np.zeros((NCandidate)) + for idx, X_can in tqdm(enumerate(candidates), ascii=True, + desc="OptBayesianDesign"): + U_J_d[idx] = self.util_BayesianDesign(X_can, X_MC, sigma2Dict, + var) + return (index, -1 * U_J_d) + + # ------------------------------------------------------------------------- + def dual_annealing(self, method, Bounds, sigma2Dict, var, Run_No, + verbose=False): + """ + Exploration algorithim to find the optimum parameter space. + + Parameters + ---------- + method : string + Exploitation method: `VarOptDesign`, `BayesActDesign` and + `BayesOptDesign`. + Bounds : list of tuples + List of lower and upper boundaries of parameters. + sigma2Dict : dict + A dictionary containing the measurement errors (sigma^2). + Run_No : int + Run number. + verbose : bool, optional + Print out a summary. The default is False. + + Returns + ------- + Run_No : int + Run number. + array + Optimial candidate. + + """ + + Model = self.Model + max_func_itr = self.MetaModel.ExpDesign.max_func_itr + + if method == 'VarOptDesign': + Res_Global = opt.dual_annealing(self.util_VarBasedDesign, + bounds=Bounds, + args=(Model, var), + maxfun=max_func_itr) + + elif method == 'BayesOptDesign': + Res_Global = opt.dual_annealing(self.util_BayesianDesign, + bounds=Bounds, + args=(Model, sigma2Dict, var), + maxfun=max_func_itr) + + if verbose: + print(f"global minimum: xmin = {Res_Global.x}, " + f"f(xmin) = {Res_Global.fun:.6f}, nfev = {Res_Global.nfev}") + + return (Run_No, Res_Global.x) + + # ------------------------------------------------------------------------- + def tradoff_weights(self, tradeoff_scheme, old_EDX, old_EDY): + """ + Calculates weights for exploration scores based on the requested + scheme: `None`, `equal`, `epsilon-decreasing` and `adaptive`. + + `None`: No exploration. + `equal`: Same weights for exploration and exploitation scores. + `epsilon-decreasing`: Start with more exploration and increase the + influence of exploitation along the way with a exponential decay + function + `adaptive`: An adaptive method based on: + Liu, Haitao, Jianfei Cai, and Yew-Soon Ong. "An adaptive sampling + approach for Kriging metamodeling by maximizing expected prediction + error." Computers & Chemical Engineering 106 (2017): 171-182. + + Parameters + ---------- + tradeoff_scheme : string + Trade-off scheme for exloration and exploitation scores. + old_EDX : array (n_samples, n_params) + Old experimental design (training points). + old_EDY : dict + Old model responses (targets). + + Returns + ------- + exploration_weight : float + Exploration weight. + exploitation_weight: float + Exploitation weight. + + """ + if tradeoff_scheme is None: + exploration_weight = 0 + + elif tradeoff_scheme == 'equal': + exploration_weight = 0.5 + + elif tradeoff_scheme == 'epsilon-decreasing': + # epsilon-decreasing scheme + # Start with more exploration and increase the influence of + # exploitation along the way with a exponential decay function + initNSamples = self.MetaModel.ExpDesign.n_init_samples + n_max_samples = self.MetaModel.ExpDesign.n_max_samples + + itrNumber = (self.MetaModel.ExpDesign.X.shape[0] - initNSamples) + itrNumber //= self.MetaModel.ExpDesign.n_new_samples + + tau2 = -(n_max_samples-initNSamples-1) / np.log(1e-8) + exploration_weight = signal.exponential(n_max_samples-initNSamples, + 0, tau2, False)[itrNumber] + + elif tradeoff_scheme == 'adaptive': + + # Extract itrNumber + initNSamples = self.MetaModel.ExpDesign.n_init_samples + n_max_samples = self.MetaModel.ExpDesign.n_max_samples + itrNumber = (self.MetaModel.ExpDesign.X.shape[0] - initNSamples) + itrNumber //= self.MetaModel.ExpDesign.n_new_samples + + if itrNumber == 0: + exploration_weight = 0.5 + else: + # New adaptive trade-off according to Liu et al. (2017) + # Mean squared error for last design point + last_EDX = old_EDX[-1].reshape(1, -1) + lastPCEY, _ = self.MetaModel.eval_metamodel(samples=last_EDX) + pce_y = np.array(list(lastPCEY.values()))[:, 0] + y = np.array(list(old_EDY.values()))[:, -1, :] + mseError = mean_squared_error(pce_y, y) + + # Mean squared CV - error for last design point + pce_y_prev = np.array(list(self._y_hat_prev.values()))[:, 0] + mseCVError = mean_squared_error(pce_y_prev, y) + + exploration_weight = min([0.5*mseError/mseCVError, 1]) + + # Exploitation weight + exploitation_weight = 1 - exploration_weight + + return exploration_weight, exploitation_weight + + # ------------------------------------------------------------------------- + def opt_SeqDesign(self, sigma2, n_candidates=5, var='DKL'): + """ + Runs optimal sequential design. + + Parameters + ---------- + sigma2 : dict, optional + A dictionary containing the measurement errors (sigma^2). The + default is None. + n_candidates : int, optional + Number of candidate samples. The default is 5. + var : string, optional + Utility function. The default is None. + + Raises + ------ + NameError + Wrong utility function. + + Returns + ------- + Xnew : array (n_samples, n_params) + Selected new training point(s). + """ + + # Initialization + MetaModel = self.MetaModel + Bounds = MetaModel.bound_tuples + n_new_samples = MetaModel.ExpDesign.n_new_samples + explore_method = MetaModel.ExpDesign.explore_method + exploit_method = MetaModel.ExpDesign.exploit_method + n_cand_groups = MetaModel.ExpDesign.n_cand_groups + tradeoff_scheme = MetaModel.ExpDesign.tradeoff_scheme + + old_EDX = MetaModel.ExpDesign.X + old_EDY = MetaModel.ExpDesign.Y.copy() + ndim = MetaModel.ExpDesign.X.shape[1] + OutputNames = MetaModel.ModelObj.Output.names + + # ----------------------------------------- + # ----------- CUSTOMIZED METHODS ---------- + # ----------------------------------------- + # Utility function exploit_method provided by user + if exploit_method.lower() == 'user': + + Xnew, filteredSamples = MetaModel.ExpDesign.ExploitFunction(self) + + print("\n") + print("\nXnew:\n", Xnew) + + return Xnew, filteredSamples + + # ----------------------------------------- + # ---------- EXPLORATION METHODS ---------- + # ----------------------------------------- + if explore_method == 'dual annealing': + # ------- EXPLORATION: OPTIMIZATION ------- + import time + start_time = time.time() + + # Divide the domain to subdomains + args = [] + subdomains = self.subdomain(Bounds, n_new_samples) + for i in range(n_new_samples): + args.append((exploit_method, subdomains[i], sigma2, var, i)) + + # Multiprocessing + pool = multiprocessing.Pool(multiprocessing.cpu_count()) + + # With Pool.starmap_async() + results = pool.starmap_async(self.dual_annealing, args).get() + + # Close the pool + pool.close() + + Xnew = np.array([results[i][1] for i in range(n_new_samples)]) + + print("\nXnew:\n", Xnew) + + elapsed_time = time.time() - start_time + print("\n") + print(f"elapsed_time: {round(elapsed_time,2)} sec.") + print('-'*20) + + elif explore_method == 'LOOCV': + # ----------------------------------------------------------------- + # TODO: LOOCV model construnction based on Feng et al. (2020) + # 'LOOCV': + # Initilize the ExploitScore array + + # Generate random samples + allCandidates = MetaModel.ExpDesign.generate_samples(n_candidates, + 'random') + + # Construct error model based on LCerror + errorModel = MetaModel.create_ModelError(old_EDX, self.LCerror) + self.errorModel.append(copy(errorModel)) + + # Evaluate the error models for allCandidates + eLCAllCands, _ = errorModel.eval_errormodel(allCandidates) + # Select the maximum as the representative error + eLCAllCands = np.dstack(eLCAllCands.values()) + eLCAllCandidates = np.max(eLCAllCands, axis=1)[:, 0] + + # Normalize the error w.r.t the maximum error + scoreExploration = eLCAllCandidates / np.sum(eLCAllCandidates) + + else: + # ------- EXPLORATION: SPACE-FILLING DESIGN ------- + # Generate candidate samples from Exploration class + explore = Exploration(MetaModel, n_candidates) + explore.w = 100 # * ndim #500 + # Select criterion (mc-intersite-proj-th, mc-intersite-proj) + explore.mc_criterion = 'mc-intersite-proj' + allCandidates, scoreExploration = explore.get_exploration_samples() + + # Temp: ---- Plot all candidates ----- + if ndim == 2: + def plotter(points, allCandidates, Method, + scoreExploration=None): + if Method == 'Voronoi': + from scipy.spatial import Voronoi, voronoi_plot_2d + vor = Voronoi(points) + fig = voronoi_plot_2d(vor) + ax1 = fig.axes[0] + else: + fig = plt.figure() + ax1 = fig.add_subplot(111) + ax1.scatter(points[:, 0], points[:, 1], s=10, c='r', + marker="s", label='Old Design Points') + ax1.scatter(allCandidates[:, 0], allCandidates[:, 1], s=10, + c='b', marker="o", label='Design candidates') + for i in range(points.shape[0]): + txt = 'p'+str(i+1) + ax1.annotate(txt, (points[i, 0], points[i, 1])) + if scoreExploration is not None: + for i in range(allCandidates.shape[0]): + txt = str(round(scoreExploration[i], 5)) + ax1.annotate(txt, (allCandidates[i, 0], + allCandidates[i, 1])) + + plt.xlim(self.bound_tuples[0]) + plt.ylim(self.bound_tuples[1]) + # plt.show() + plt.legend(loc='upper left') + + # ----------------------------------------- + # --------- EXPLOITATION METHODS ---------- + # ----------------------------------------- + if exploit_method == 'BayesOptDesign' or\ + exploit_method == 'BayesActDesign': + + # ------- Calculate Exoploration weight ------- + # Compute exploration weight based on trade off scheme + explore_w, exploit_w = self.tradoff_weights(tradeoff_scheme, + old_EDX, + old_EDY) + print(f"\n Exploration weight={explore_w:0.3f} " + f"Exploitation weight={exploit_w:0.3f}\n") + + # ------- EXPLOITATION: BayesOptDesign & ActiveLearning ------- + if explore_w != 1.0: + + # Create a sample pool for rejection sampling + MCsize = 15000 + X_MC = MetaModel.ExpDesign.generate_samples(MCsize, 'random') + candidates = MetaModel.ExpDesign.generate_samples( + MetaModel.ExpDesign.max_func_itr, 'latin_hypercube') + + # Split the candidates in groups for multiprocessing + split_cand = np.array_split( + candidates, n_cand_groups, axis=0 + ) + + results = Parallel(n_jobs=-1, backend='multiprocessing')( + delayed(self.run_util_func)( + exploit_method, split_cand[i], i, sigma2, var, X_MC) + for i in range(n_cand_groups)) + # out = map(self.run_util_func, + # [exploit_method]*n_cand_groups, + # split_cand, + # range(n_cand_groups), + # [sigma2] * n_cand_groups, + # [var] * n_cand_groups, + # [X_MC] * n_cand_groups + # ) + # results = list(out) + + # Retrieve the results and append them + U_J_d = np.concatenate([results[NofE][1] for NofE in + range(n_cand_groups)]) + + # Check if all scores are inf + if np.isinf(U_J_d).all() or np.isnan(U_J_d).all(): + U_J_d = np.ones(len(U_J_d)) + + # Get the expected value (mean) of the Utility score + # for each cell + if explore_method == 'Voronoi': + U_J_d = np.mean(U_J_d.reshape(-1, n_candidates), axis=1) + + # create surrogate model for U_J_d + # from sklearn.preprocessing import MinMaxScaler + # # Take care of inf entries + # good_indices = [i for i, arr in enumerate(U_J_d) + # if np.isfinite(arr).all()] + # scaler = MinMaxScaler() + # X_S = scaler.fit_transform(candidates[good_indices]) + # gp = MetaModel.gaussian_process_emulator( + # X_S, U_J_d[good_indices], autoSelect=False + # ) + # U_J_d = gp.predict(scaler.transform(allCandidates)) + + # Normalize U_J_d + norm_U_J_d = U_J_d / np.sum(U_J_d) + else: + norm_U_J_d = np.zeros((len(scoreExploration))) + + # ------- Calculate Total score ------- + # ------- Trade off between EXPLORATION & EXPLOITATION ------- + # Accumulate the samples + # TODO: added this, recheck!! + finalCandidates = np.concatenate((allCandidates, candidates), axis = 0) + finalCandidates = np.unique(finalCandidates, axis = 0) + + #self.allCandidates = allCandidates + #self.candidates = candidates + #self.norm_U_J_d = norm_U_J_d + #self.exploit_w = exploit_w + #self.scoreExploration = scoreExploration + + # Total score + #totalScore = exploit_w * norm_U_J_d + #totalScore += explore_w * scoreExploration + + # TODO: changed this from the above to take into account both exploration and exploitation samples without duplicates + totalScore = np.zeros(finalCandidates.shape[0]) + #self.totalScore = totalScore + + for cand_idx in range(finalCandidates.shape[0]): + # find candidate indices + idx1 = np.where(allCandidates == finalCandidates[cand_idx])[0] + idx2 = np.where(candidates == finalCandidates[cand_idx])[0] + #print(f'Candidate number {cand_idx}') + #print(finalCandidates[cand_idx]) + #print(f'Idx1: {idx1}, Idx2: {idx2}') + + # exploration + if idx1 != []: + idx1 = idx1[0] + #print(f'Values1: {allCandidates[idx1]}') + totalScore[cand_idx] += explore_w * scoreExploration[idx1] + + # exploitation + if idx2 != []: + idx2 = idx2[0] + #print(f'Values1: {candidates[idx2]}') + totalScore[cand_idx] += exploit_w * norm_U_J_d[idx2] + + + # temp: Plot + # dim = self.ExpDesign.X.shape[1] + # if dim == 2: + # plotter(self.ExpDesign.X, allCandidates, explore_method) + + # ------- Select the best candidate ------- + # find an optimal point subset to add to the initial design by + # maximization of the utility score and taking care of NaN values + temp = totalScore.copy() + temp[np.isnan(totalScore)] = -np.inf + sorted_idxtotalScore = np.argsort(temp)[::-1] + bestIdx = sorted_idxtotalScore[:n_new_samples] + + # select the requested number of samples + if explore_method == 'Voronoi': + Xnew = np.zeros((n_new_samples, ndim)) + for i, idx in enumerate(bestIdx): + X_can = explore.closestPoints[idx] + + # Calculate the maxmin score for the region of interest + newSamples, maxminScore = explore.get_mc_samples(X_can) + + # select the requested number of samples + Xnew[i] = newSamples[np.argmax(maxminScore)] + else: + # TODO: changed this from allCandiates to full set of candidates - still not changed for e.g. 'Voronoi' + Xnew = finalCandidates[sorted_idxtotalScore[:n_new_samples]] # here candidates(exploitation) vs allCandidates (exploration)!! + + elif exploit_method == 'VarOptDesign': + # ------- EXPLOITATION: VarOptDesign ------- + UtilMethod = var + + # ------- Calculate Exoploration weight ------- + # Compute exploration weight based on trade off scheme + explore_w, exploit_w = self.tradoff_weights(tradeoff_scheme, + old_EDX, + old_EDY) + print(f"\nweightExploration={explore_w:0.3f} " + f"weightExploitation={exploit_w:0.3f}") + + # Generate candidate samples from Exploration class + nMeasurement = old_EDY[OutputNames[0]].shape[1] + + # Find sensitive region + if UtilMethod == 'LOOCV': + LCerror = MetaModel.LCerror + allModifiedLOO = np.zeros((len(old_EDX), len(OutputNames), + nMeasurement)) + for y_idx, y_key in enumerate(OutputNames): + for idx, key in enumerate(LCerror[y_key].keys()): + allModifiedLOO[:, y_idx, idx] = abs( + LCerror[y_key][key]) + + ExploitScore = np.max(np.max(allModifiedLOO, axis=1), axis=1) + + elif UtilMethod in ['EIGF', 'ALM']: + # ----- All other in ['EIGF', 'ALM'] ----- + # Initilize the ExploitScore array + ExploitScore = np.zeros((len(old_EDX), len(OutputNames))) + + # Split the candidates in groups for multiprocessing + if explore_method != 'Voronoi': + split_cand = np.array_split(allCandidates, + n_cand_groups, + axis=0) + goodSampleIdx = range(n_cand_groups) + else: + # Find indices of the Vornoi cells with samples + goodSampleIdx = [] + for idx in range(len(explore.closest_points)): + if len(explore.closest_points[idx]) != 0: + goodSampleIdx.append(idx) + split_cand = explore.closest_points + + # Split the candidates in groups for multiprocessing + args = [] + for index in goodSampleIdx: + args.append((exploit_method, split_cand[index], index, + sigma2, var)) + + # Multiprocessing + pool = multiprocessing.Pool(multiprocessing.cpu_count()) + # With Pool.starmap_async() + results = pool.starmap_async(self.run_util_func, args).get() + + # Close the pool + pool.close() + # out = map(self.run_util_func, + # [exploit_method]*len(goodSampleIdx), + # split_cand, + # range(len(goodSampleIdx)), + # [sigma2] * len(goodSampleIdx), + # [var] * len(goodSampleIdx) + # ) + # results = list(out) + + # Retrieve the results and append them + if explore_method == 'Voronoi': + ExploitScore = [np.mean(results[k][1]) for k in + range(len(goodSampleIdx))] + else: + ExploitScore = np.concatenate( + [results[k][1] for k in range(len(goodSampleIdx))]) + + else: + raise NameError('The requested utility function is not ' + 'available.') + + # print("ExploitScore:\n", ExploitScore) + + # find an optimal point subset to add to the initial design by + # maximization of the utility score and taking care of NaN values + # Total score + # Normalize U_J_d + ExploitScore = ExploitScore / np.sum(ExploitScore) + totalScore = exploit_w * ExploitScore + totalScore += explore_w * scoreExploration + + temp = totalScore.copy() + sorted_idxtotalScore = np.argsort(temp, axis=0)[::-1] + bestIdx = sorted_idxtotalScore[:n_new_samples] + + Xnew = np.zeros((n_new_samples, ndim)) + if explore_method != 'Voronoi': + Xnew = allCandidates[bestIdx] + else: + for i, idx in enumerate(bestIdx.flatten()): + X_can = explore.closest_points[idx] + # plotter(self.ExpDesign.X, X_can, explore_method, + # scoreExploration=None) + + # Calculate the maxmin score for the region of interest + newSamples, maxminScore = explore.get_mc_samples(X_can) + + # select the requested number of samples + Xnew[i] = newSamples[np.argmax(maxminScore)] + + elif exploit_method == 'alphabetic': + # ------- EXPLOITATION: ALPHABETIC ------- + Xnew = self.util_AlphOptDesign(allCandidates, var) + + elif exploit_method == 'Space-filling': + # ------- EXPLOITATION: SPACE-FILLING ------- + totalScore = scoreExploration + + # ------- Select the best candidate ------- + # find an optimal point subset to add to the initial design by + # maximization of the utility score and taking care of NaN values + temp = totalScore.copy() + temp[np.isnan(totalScore)] = -np.inf + sorted_idxtotalScore = np.argsort(temp)[::-1] + + # select the requested number of samples + Xnew = allCandidates[sorted_idxtotalScore[:n_new_samples]] + + else: + raise NameError('The requested design method is not available.') + + print("\n") + print("\nRun No. {}:".format(old_EDX.shape[0]+1)) + print("Xnew:\n", Xnew) + + return Xnew, None + + # ------------------------------------------------------------------------- + def util_AlphOptDesign(self, candidates, var='D-Opt'): + """ + Enriches the Experimental design with the requested alphabetic + criterion based on exploring the space with number of sampling points. + + Ref: Hadigol, M., & Doostan, A. (2018). Least squares polynomial chaos + expansion: A review of sampling strategies., Computer Methods in + Applied Mechanics and Engineering, 332, 382-407. + + Arguments + --------- + NCandidate : int + Number of candidate points to be searched + + var : string + Alphabetic optimality criterion + + Returns + ------- + X_new : array of shape (1, n_params) + The new sampling location in the input space. + """ + MetaModelOrig = self + Model = self.Model + n_new_samples = MetaModelOrig.ExpDesign.n_new_samples + NCandidate = candidates.shape[0] + + # TODO: Loop over outputs + OutputName = Model.Output.names[0] + + # To avoid changes ub original aPCE object + MetaModel = deepcopy(MetaModelOrig) + + # Old Experimental design + oldExpDesignX = MetaModel.ExpDesign.X + + # TODO: Only one psi can be selected. + # Suggestion: Go for the one with the highest LOO error + Scores = list(MetaModel.score_dict[OutputName].values()) + ModifiedLOO = [1-score for score in Scores] + outIdx = np.argmax(ModifiedLOO) + + # Initialize Phi to save the criterion's values + Phi = np.zeros((NCandidate)) + + BasisIndices = MetaModelOrig.basis_dict[OutputName]["y_"+str(outIdx+1)] + P = len(BasisIndices) + + # ------ Old Psi ------------ + univ_p_val = MetaModelOrig.univ_basis_vals(oldExpDesignX) + Psi = MetaModelOrig.create_psi(BasisIndices, univ_p_val) + + # ------ New candidates (Psi_c) ------------ + # Assemble Psi_c + univ_p_val_c = self.univ_basis_vals(candidates) + Psi_c = self.create_psi(BasisIndices, univ_p_val_c) + + for idx in range(NCandidate): + + # Include the new row to the original Psi + Psi_cand = np.vstack((Psi, Psi_c[idx])) + + # Information matrix + PsiTPsi = np.dot(Psi_cand.T, Psi_cand) + M = PsiTPsi / (len(oldExpDesignX)+1) + + if np.linalg.cond(PsiTPsi) > 1e-12 \ + and np.linalg.cond(PsiTPsi) < 1 / sys.float_info.epsilon: + # faster + invM = linalg.solve(M, sparse.eye(PsiTPsi.shape[0]).toarray()) + else: + # stabler + invM = np.linalg.pinv(M) + + # ---------- Calculate optimality criterion ---------- + # Optimality criteria according to Section 4.5.1 in Ref. + + # D-Opt + if var == 'D-Opt': + Phi[idx] = (np.linalg.det(invM)) ** (1/P) + + # A-Opt + elif var == 'A-Opt': + Phi[idx] = np.trace(invM) + + # K-Opt + elif var == 'K-Opt': + Phi[idx] = np.linalg.cond(M) + + else: + raise Exception('The optimality criterion you requested has ' + 'not been implemented yet!') + + # find an optimal point subset to add to the initial design + # by minimization of the Phi + sorted_idxtotalScore = np.argsort(Phi) + + # select the requested number of samples + Xnew = candidates[sorted_idxtotalScore[:n_new_samples]] + + return Xnew + + # ------------------------------------------------------------------------- + def __normpdf(self, y_hat_pce, std_pce, obs_data, total_sigma2s, + rmse=None): + + Model = self.Model + likelihoods = 1.0 + + # Loop over the outputs + for idx, out in enumerate(Model.Output.names): + + # (Meta)Model Output + nsamples, nout = y_hat_pce[out].shape + + # Prepare data and remove NaN + try: + data = obs_data[out].values[~np.isnan(obs_data[out])] + except AttributeError: + data = obs_data[out][~np.isnan(obs_data[out])] + + # Prepare sigma2s + non_nan_indices = ~np.isnan(total_sigma2s[out]) + tot_sigma2s = total_sigma2s[out][non_nan_indices][:nout].values + + # Surrogate error if valid dataset is given. + if rmse is not None: + tot_sigma2s += rmse[out]**2 + else: + tot_sigma2s += np.mean(std_pce[out])**2 + + likelihoods *= stats.multivariate_normal.pdf( + y_hat_pce[out], data, np.diag(tot_sigma2s), + allow_singular=True) + + self.Likelihoods = likelihoods + + return likelihoods + + # ------------------------------------------------------------------------- + def __corr_factor_BME(self, obs_data, total_sigma2s, logBME): + """ + Calculates the correction factor for BMEs. + """ + MetaModel = self.MetaModel + samples = MetaModel.ExpDesign.X # valid_samples + model_outputs = MetaModel.ExpDesign.Y # valid_model_runs + Model = MetaModel.ModelObj + n_samples = samples.shape[0] + + # Extract the requested model outputs for likelihood calulation + output_names = Model.Output.names + + # TODO: Evaluate MetaModel on the experimental design and ValidSet + OutputRS, stdOutputRS = MetaModel.eval_metamodel(samples=samples) + + logLik_data = np.zeros((n_samples)) + logLik_model = np.zeros((n_samples)) + # Loop over the outputs + for idx, out in enumerate(output_names): + + # (Meta)Model Output + nsamples, nout = model_outputs[out].shape + + # Prepare data and remove NaN + try: + data = obs_data[out].values[~np.isnan(obs_data[out])] + except AttributeError: + data = obs_data[out][~np.isnan(obs_data[out])] + + # Prepare sigma2s + non_nan_indices = ~np.isnan(total_sigma2s[out]) + tot_sigma2s = total_sigma2s[out][non_nan_indices][:nout] + + # Covariance Matrix + covMatrix_data = np.diag(tot_sigma2s) + + for i, sample in enumerate(samples): + + # Simulation run + y_m = model_outputs[out][i] + + # Surrogate prediction + y_m_hat = OutputRS[out][i] + + # CovMatrix with the surrogate error + # covMatrix = np.diag(stdOutputRS[out][i]**2) + covMatrix = np.diag((y_m-y_m_hat)**2) + covMatrix = np.diag( + np.mean((model_outputs[out]-OutputRS[out]), axis=0)**2 + ) + + # Compute likelilhood output vs data + logLik_data[i] += self.__logpdf( + y_m_hat, data, covMatrix_data + ) + + # Compute likelilhood output vs surrogate + logLik_model[i] += self.__logpdf(y_m_hat, y_m, covMatrix) + + # Weight + logLik_data -= logBME + weights = np.exp(logLik_model+logLik_data) + + return np.log(np.mean(weights)) + + # ------------------------------------------------------------------------- + def __logpdf(self, x, mean, cov): + """ + computes the likelihood based on a multivariate normal distribution. + + Parameters + ---------- + x : TYPE + DESCRIPTION. + mean : array_like + Observation data. + cov : 2d array + Covariance matrix of the distribution. + + Returns + ------- + log_lik : float + Log likelihood. + + """ + n = len(mean) + L = linalg.cholesky(cov, lower=True) + beta = np.sum(np.log(np.diag(L))) + dev = x - mean + alpha = dev.dot(linalg.cho_solve((L, True), dev)) + log_lik = -0.5 * alpha - beta - n / 2. * np.log(2 * np.pi) + + return log_lik + + # ------------------------------------------------------------------------- + def __posteriorPlot(self, posterior, par_names, key): + + # Initialization + newpath = (r'Outputs_SeqPosteriorComparison/posterior') + os.makedirs(newpath, exist_ok=True) + + bound_tuples = self.MetaModel.bound_tuples + n_params = len(par_names) + font_size = 40 + if n_params == 2: + + figPosterior, ax = plt.subplots(figsize=(15, 15)) + + sns.kdeplot(x=posterior[:, 0], y=posterior[:, 1], + fill=True, ax=ax, cmap=plt.cm.jet, + clip=bound_tuples) + # Axis labels + plt.xlabel(par_names[0], fontsize=font_size) + plt.ylabel(par_names[1], fontsize=font_size) + + # Set axis limit + plt.xlim(bound_tuples[0]) + plt.ylim(bound_tuples[1]) + + # Increase font size + plt.xticks(fontsize=font_size) + plt.yticks(fontsize=font_size) + + # Switch off the grids + plt.grid(False) + + else: + import corner + figPosterior = corner.corner(posterior, labels=par_names, + title_fmt='.2e', show_titles=True, + title_kwargs={"fontsize": 12}) + + figPosterior.savefig(f'./{newpath}/{key}.pdf', bbox_inches='tight') + plt.close() + + # Save the posterior as .npy + np.save(f'./{newpath}/{key}.npy', posterior) + + return figPosterior + + # ------------------------------------------------------------------------- + def __hellinger_distance(self, P, Q): + """ + Hellinger distance between two continuous distributions. + + The maximum distance 1 is achieved when P assigns probability zero to + every set to which Q assigns a positive probability, and vice versa. + 0 (identical) and 1 (maximally different) + + Parameters + ---------- + P : array + Reference likelihood. + Q : array + Estimated likelihood. + + Returns + ------- + float + Hellinger distance of two distributions. + + """ + mu1 = P.mean() + Sigma1 = np.std(P) + + mu2 = Q.mean() + Sigma2 = np.std(Q) + + term1 = np.sqrt(2*Sigma1*Sigma2 / (Sigma1**2 + Sigma2**2)) + + term2 = np.exp(-.25 * (mu1 - mu2)**2 / (Sigma1**2 + Sigma2**2)) + + H_squared = 1 - term1 * term2 + + return np.sqrt(H_squared) + + # ------------------------------------------------------------------------- + def __BME_Calculator(self, MetaModel, obs_data, sigma2Dict, rmse=None): + """ + This function computes the Bayesian model evidence (BME) via Monte + Carlo integration. + + """ + # Initializations + if hasattr(MetaModel, 'valid_likelihoods'): + valid_likelihoods = MetaModel.valid_likelihoods + else: + valid_likelihoods = [] + + post_snapshot = MetaModel.ExpDesign.post_snapshot + #print(f'post_snapshot: {post_snapshot}') + if post_snapshot or len(valid_likelihoods) != 0: + newpath = (r'Outputs_SeqPosteriorComparison/likelihood_vs_ref') + os.makedirs(newpath, exist_ok=True) + + SamplingMethod = 'random' + MCsize = 10000 + ESS = 0 + + # Estimation of the integral via Monte Varlo integration + while (ESS > MCsize) or (ESS < 1): + + # Generate samples for Monte Carlo simulation + X_MC = MetaModel.ExpDesign.generate_samples( + MCsize, SamplingMethod + ) + + # Monte Carlo simulation for the candidate design + Y_MC, std_MC = MetaModel.eval_metamodel(samples=X_MC) + + # Likelihood computation (Comparison of data and + # simulation results via PCE with candidate design) + Likelihoods = self.__normpdf( + Y_MC, std_MC, obs_data, sigma2Dict, rmse + ) + + # Check the Effective Sample Size (1000<ESS<MCsize) + ESS = 1 / np.sum(np.square(Likelihoods/np.sum(Likelihoods))) + + # Enlarge sample size if it doesn't fulfill the criteria + if (ESS > MCsize) or (ESS < 1): + print(f'ESS={ESS} MC size should be larger.') + MCsize *= 10 + ESS = 0 + + # Rejection Step + # Random numbers between 0 and 1 + unif = np.random.rand(1, MCsize)[0] + + # Reject the poorly performed prior + accepted = (Likelihoods/np.max(Likelihoods)) >= unif + X_Posterior = X_MC[accepted] + + # ------------------------------------------------------------ + # --- Kullback-Leibler Divergence & Information Entropy ------ + # ------------------------------------------------------------ + # Prior-based estimation of BME + logBME = np.log(np.nanmean(Likelihoods)) + + # TODO: Correction factor + # log_weight = self.__corr_factor_BME(obs_data, sigma2Dict, logBME) + + # Posterior-based expectation of likelihoods + postExpLikelihoods = np.mean(np.log(Likelihoods[accepted])) + + # Posterior-based expectation of prior densities + postExpPrior = np.mean( + np.log(MetaModel.ExpDesign.JDist.pdf(X_Posterior.T)) + ) + + # Calculate Kullback-Leibler Divergence + # KLD = np.mean(np.log(Likelihoods[Likelihoods!=0])- logBME) + KLD = postExpLikelihoods - logBME + + # Information Entropy based on Entropy paper Eq. 38 + infEntropy = logBME - postExpPrior - postExpLikelihoods + + # If post_snapshot is True, plot likelihood vs refrence + if post_snapshot or valid_likelihoods: + # Hellinger distance + #print('arrived here') + #print(np.array(valid_likelihoods)) + valid_likelihoods = np.array(valid_likelihoods) + #valid_likelihoods = np.array(valid_likelihoods) + ref_like = np.log(valid_likelihoods[(valid_likelihoods > 0)]) + est_like = np.log(Likelihoods[Likelihoods > 0]) + distHellinger = self.__hellinger_distance(ref_like, est_like) + + idx = len([name for name in os.listdir(newpath) if 'Likelihoods_' + in name and os.path.isfile(os.path.join(newpath, name))]) + fig, ax = plt.subplots() + try: + sns.kdeplot(np.log(valid_likelihoods[valid_likelihoods > 0]), + shade=True, color="g", label='Ref. Likelihood') + sns.kdeplot(np.log(Likelihoods[Likelihoods > 0]), shade=True, + color="b", label='Likelihood with PCE') + except: + pass + + text = f"Hellinger Dist.={distHellinger:.3f}\n logBME={logBME:.3f}" + "\n DKL={KLD:.3f}" + + plt.text(0.05, 0.75, text, bbox=dict(facecolor='wheat', + edgecolor='black', + boxstyle='round,pad=1'), + transform=ax.transAxes) + + fig.savefig(f'./{newpath}/Likelihoods_{idx}.pdf', + bbox_inches='tight') + plt.close() + + else: + distHellinger = 0.0 + + # Bayesian inference with Emulator only for 2D problem + if post_snapshot and MetaModel.n_params == 2 and not idx % 5: + BayesOpts = BayesInference(MetaModel) + BayesOpts.emulator = True + BayesOpts.plot_post_pred = False + + # Select the inference method + import emcee + BayesOpts.inference_method = "MCMC" + # Set the MCMC parameters passed to self.mcmc_params + BayesOpts.mcmc_params = { + 'n_steps': 1e5, + 'n_walkers': 30, + 'moves': emcee.moves.KDEMove(), + 'verbose': False + } + + # ----- Define the discrepancy model ------- + obs_data = pd.DataFrame(obs_data, columns=self.Model.Output.names) + BayesOpts.measurement_error = obs_data + + # # -- (Option B) -- + DiscrepancyOpts = Discrepancy('') + DiscrepancyOpts.type = 'Gaussian' + DiscrepancyOpts.parameters = obs_data**2 + BayesOpts.Discrepancy = DiscrepancyOpts + # Start the calibration/inference + Bayes_PCE = BayesOpts.create_inference() + X_Posterior = Bayes_PCE.posterior_df.values + + return (logBME, KLD, X_Posterior, Likelihoods, distHellinger) + + # ------------------------------------------------------------------------- + def __validError(self, MetaModel): + + # MetaModel = self.MetaModel + Model = MetaModel.ModelObj + OutputName = Model.Output.names + + # Extract the original model with the generated samples + valid_samples = MetaModel.valid_samples + valid_model_runs = MetaModel.valid_model_runs + + # Run the PCE model with the generated samples + valid_PCE_runs, _ = MetaModel.eval_metamodel(samples=valid_samples) + + rms_error = {} + valid_error = {} + # Loop over the keys and compute RMSE error. + for key in OutputName: + rms_error[key] = mean_squared_error( + valid_model_runs[key], valid_PCE_runs[key], + multioutput='raw_values', + sample_weight=None, + squared=False) + # Validation error + valid_error[key] = (rms_error[key]**2) + valid_error[key] /= np.var(valid_model_runs[key], ddof=1, axis=0) + + # Print a report table + print("\n>>>>> Updated Errors of {} <<<<<".format(key)) + print("\nIndex | RMSE | Validation Error") + print('-'*35) + print('\n'.join(f'{i+1} | {k:.3e} | {j:.3e}' for i, (k, j) + in enumerate(zip(rms_error[key], + valid_error[key])))) + + return rms_error, valid_error + + # ------------------------------------------------------------------------- + def __error_Mean_Std(self): + + MetaModel = self.MetaModel + # Extract the mean and std provided by user + df_MCReference = MetaModel.ModelObj.mc_reference + + # Compute the mean and std based on the MetaModel + pce_means, pce_stds = self._compute_pce_moments(MetaModel) + + # Compute the root mean squared error + for output in MetaModel.ModelObj.Output.names: + + # Compute the error between mean and std of MetaModel and OrigModel + RMSE_Mean = mean_squared_error( + df_MCReference['mean'], pce_means[output], squared=False + ) + RMSE_std = mean_squared_error( + df_MCReference['std'], pce_means[output], squared=False + ) + + return RMSE_Mean, RMSE_std + + # ------------------------------------------------------------------------- + def _compute_pce_moments(self, MetaModel): + """ + Computes the first two moments using the PCE-based meta-model. + + Returns + ------- + pce_means: dict + The first moment (mean) of the surrogate. + pce_stds: dict + The second moment (standard deviation) of the surrogate. + + """ + outputs = MetaModel.ModelObj.Output.names + pce_means_b = {} + pce_stds_b = {} + + # Loop over bootstrap iterations + for b_i in range(MetaModel.n_bootstrap_itrs): + # Loop over the metamodels + coeffs_dicts = MetaModel.coeffs_dict[f'b_{b_i+1}'].items() + means = {} + stds = {} + for output, coef_dict in coeffs_dicts: + + pce_mean = np.zeros((len(coef_dict))) + pce_var = np.zeros((len(coef_dict))) + + for index, values in coef_dict.items(): + idx = int(index.split('_')[1]) - 1 + coeffs = MetaModel.coeffs_dict[f'b_{b_i+1}'][output][index] + + # Mean = c_0 + if coeffs[0] != 0: + pce_mean[idx] = coeffs[0] + else: + clf_poly = MetaModel.clf_poly[f'b_{b_i+1}'][output] + pce_mean[idx] = clf_poly[index].intercept_ + # Var = sum(coeffs[1:]**2) + pce_var[idx] = np.sum(np.square(coeffs[1:])) + + # Save predictions for each output + if MetaModel.dim_red_method.lower() == 'pca': + PCA = MetaModel.pca[f'b_{b_i+1}'][output] + means[output] = PCA.inverse_transform(pce_mean) + stds[output] = PCA.inverse_transform(np.sqrt(pce_var)) + else: + means[output] = pce_mean + stds[output] = np.sqrt(pce_var) + + # Save predictions for each bootstrap iteration + pce_means_b[b_i] = means + pce_stds_b[b_i] = stds + + # Change the order of nesting + mean_all = {} + for i in sorted(pce_means_b): + for k, v in pce_means_b[i].items(): + if k not in mean_all: + mean_all[k] = [None] * len(pce_means_b) + mean_all[k][i] = v + std_all = {} + for i in sorted(pce_stds_b): + for k, v in pce_stds_b[i].items(): + if k not in std_all: + std_all[k] = [None] * len(pce_stds_b) + std_all[k][i] = v + + # Back transformation if PCA is selected. + pce_means, pce_stds = {}, {} + for output in outputs: + pce_means[output] = np.mean(mean_all[output], axis=0) + pce_stds[output] = np.mean(std_all[output], axis=0) + + return pce_means, pce_stds diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/orthogonal_matching_pursuit.py b/examples/analytical-function/bayesvalidrox/surrogate_models/orthogonal_matching_pursuit.py new file mode 100644 index 000000000..96ef9c1d5 --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/surrogate_models/orthogonal_matching_pursuit.py @@ -0,0 +1,366 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Fri Jul 15 14:08:59 2022 + +@author: farid +""" +import numpy as np +from sklearn.base import RegressorMixin +from sklearn.linear_model._base import LinearModel +from sklearn.utils import check_X_y + + +def corr(x, y): + return abs(x.dot(y))/np.sqrt((x**2).sum()) + + +class OrthogonalMatchingPursuit(LinearModel, RegressorMixin): + ''' + Regression with Orthogonal Matching Pursuit [1]. + + Parameters + ---------- + fit_intercept : boolean, optional (DEFAULT = True) + whether to calculate the intercept for this model. If set + to false, no intercept will be used in calculations + (e.g. data is expected to be already centered). + + copy_X : boolean, optional (DEFAULT = True) + If True, X will be copied; else, it may be overwritten. + + verbose : boolean, optional (DEFAULT = FALSE) + Verbose mode when fitting the model + + Attributes + ---------- + coef_ : array, shape = (n_features) + Coefficients of the regression model (mean of posterior distribution) + + active_ : array, dtype = np.bool, shape = (n_features) + True for non-zero coefficients, False otherwise + + References + ---------- + [1] Pati, Y., Rezaiifar, R., Krishnaprasad, P. (1993). Orthogonal matching + pursuit: recursive function approximation with application to wavelet + decomposition. Proceedings of 27th Asilomar Conference on Signals, + Systems and Computers, 40-44. + ''' + + def __init__(self, fit_intercept=True, normalize=False, copy_X=True, + verbose=False): + self.fit_intercept = fit_intercept + self.normalize = normalize + self.copy_X = copy_X + self.verbose = verbose + + def _preprocess_data(self, X, y): + """Center and scale data. + Centers data to have mean zero along axis 0. If fit_intercept=False or + if the X is a sparse matrix, no centering is done, but normalization + can still be applied. The function returns the statistics necessary to + reconstruct the input data, which are X_offset, y_offset, X_scale, such + that the output + X = (X - X_offset) / X_scale + X_scale is the L2 norm of X - X_offset. + """ + + if self.copy_X: + X = X.copy(order='K') + + y = np.asarray(y, dtype=X.dtype) + + if self.fit_intercept: + X_offset = np.average(X, axis=0) + X -= X_offset + if self.normalize: + X_scale = np.ones(X.shape[1], dtype=X.dtype) + std = np.sqrt(np.sum(X**2, axis=0)/(len(X)-1)) + X_scale[std != 0] = std[std != 0] + X /= X_scale + else: + X_scale = np.ones(X.shape[1], dtype=X.dtype) + y_offset = np.mean(y) + y = y - y_offset + else: + X_offset = np.zeros(X.shape[1], dtype=X.dtype) + X_scale = np.ones(X.shape[1], dtype=X.dtype) + if y.ndim == 1: + y_offset = X.dtype.type(0) + else: + y_offset = np.zeros(y.shape[1], dtype=X.dtype) + + return X, y, X_offset, y_offset, X_scale + + def fit(self, X, y): + ''' + Fits Regression with Orthogonal Matching Pursuit Algorithm. + + Parameters + ----------- + X: {array-like, sparse matrix} of size (n_samples, n_features) + Training data, matrix of explanatory variables + + y: array-like of size [n_samples, n_features] + Target values + + Returns + ------- + self : object + Returns self. + ''' + X, y = check_X_y(X, y, dtype=np.float64, y_numeric=True) + n_samples, n_features = X.shape + + X, y, X_mean, y_mean, X_std = self._preprocess_data(X, y) + self._x_mean_ = X_mean + self._y_mean = y_mean + self._x_std = X_std + + # Normalize columns of Psi, so that each column has norm = 1 + norm_X = np.linalg.norm(X, axis=0) + X_norm = X/norm_X + + # Initialize residual vector to full model response and normalize + R = y + norm_y = np.sqrt(np.dot(y, y)) + r = y/norm_y + + # Check for constant regressors + const_indices = np.where(~np.diff(X, axis=0).any(axis=0))[0] + bool_const = not const_indices + + # Start regression using OPM algorithm + precision = 0 # Set precision criterion to precision of program + early_stop = True + cond_early = True # Initialize condition for early stop + ind = [] + iindx = [] # index of selected columns + indtot = np.arange(n_features) # Full index set for remaining columns + kmax = min(n_samples, n_features) # Maximum number of iterations + LOO = np.PINF * np.ones(kmax) # Store LOO error at each iteration + LOOmin = np.PINF # Initialize minimum value of LOO + coeff = np.zeros((n_features, kmax)) + count = 0 + k = 0.1 # Percentage of iteration history for early stop + + # Begin iteration over regressors set (Matrix X) + while (np.linalg.norm(R) > precision) and (count <= kmax-1) and \ + ((cond_early or early_stop) ^ ~cond_early): + + # Update index set of columns yet to select + if count != 0: + indtot = np.delete(indtot, iindx) + + # Find column of X that is most correlated with residual + h = abs(np.dot(r, X_norm)) + iindx = np.argmax(h[indtot]) + indx = indtot[iindx] + + # initialize with the constant regressor, if it exists in the basis + if (count == 0) and bool_const: + # overwrite values for iindx and indx + iindx = const_indices[0] + indx = indtot[iindx] + + # Invert the information matrix at the first iteration, later only + # update its value on the basis of the previously inverted one, + if count == 0: + M = 1 / np.dot(X[:, indx], X[:, indx]) + else: + x = np.dot(X[:, ind].T, X[:, indx]) + r = np.dot(X[:, indx], X[:, indx]) + M = self.blockwise_inverse(M, x, x.T, r) + + # Add newly found index to the selected indexes set + ind.append(indx) + + # Select regressors subset (Projection subspace) + Xpro = X[:, ind] + + # Obtain coefficient by performing OLS + TT = np.dot(y, Xpro) + beta = np.dot(M, TT) + coeff[ind, count] = beta + + # Compute LOO error + LOO[count] = self.loo_error(Xpro, M, y, beta) + + # Compute new residual due to new projection + R = y - np.dot(Xpro, beta) + + # Normalize residual + norm_R = np.sqrt(np.dot(R, R)) + r = R / norm_R + + # Update counters and early-stop criterions + countinf = max(0, int(count-k*kmax)) + LOOmin = min(LOOmin, LOO[count]) + + if count == 0: + cond_early = (LOO[0] <= LOOmin) + else: + cond_early = (min(LOO[countinf:count+1]) <= LOOmin) + + if self.verbose: + print(f'Iteration: {count+1}, mod. LOOCV error : ' + f'{LOO[count]:.2e}') + + # Update counter + count += 1 + + # Select projection with smallest cross-validation error + countmin = np.argmin(LOO[:-1]) + self.coef_ = coeff[:, countmin] + self.active = coeff[:, countmin] != 0.0 + + # set intercept_ + if self.fit_intercept: + self.coef_ = self.coef_ / X_std + self.intercept_ = y_mean - np.dot(X_mean, self.coef_.T) + else: + self.intercept_ = 0. + + return self + + def predict(self, X): + ''' + Computes predictive distribution for test set. + + Parameters + ----------- + X: {array-like, sparse} (n_samples_test, n_features) + Test data, matrix of explanatory variables + + Returns + ------- + y_hat: numpy array of size (n_samples_test,) + Estimated values of targets on test set (i.e. mean of + predictive distribution) + ''' + + y_hat = np.dot(X, self.coef_) + self.intercept_ + + return y_hat + + def loo_error(self, psi, inv_inf_matrix, y, coeffs): + """ + Calculates the corrected LOO error for regression on regressor + matrix `psi` that generated the coefficients based on [1] and [2]. + + [1] Blatman, G., 2009. Adaptive sparse polynomial chaos expansions for + uncertainty propagation and sensitivity analysis (Doctoral + dissertation, Clermont-Ferrand 2). + + [2] Blatman, G. and Sudret, B., 2011. Adaptive sparse polynomial chaos + expansion based on least angle regression. Journal of computational + Physics, 230(6), pp.2345-2367. + + Parameters + ---------- + psi : array of shape (n_samples, n_feature) + Orthogonal bases evaluated at the samples. + inv_inf_matrix : array + Inverse of the information matrix. + y : array of shape (n_samples, ) + Targets. + coeffs : array + Computed regresssor cofficients. + + Returns + ------- + loo_error : float + Modified LOOCV error. + + """ + + # NrEvaluation (Size of experimental design) + N, P = psi.shape + + # h factor (the full matrix is not calculated explicitly, + # only the trace is, to save memory) + PsiM = np.dot(psi, inv_inf_matrix) + + h = np.sum(np.multiply(PsiM, psi), axis=1, dtype=np.longdouble) + + # ------ Calculate Error Loocv for each measurement point ---- + # Residuals + residual = np.dot(psi, coeffs) - y + + # Variance + varY = np.var(y) + + if varY == 0: + norm_emp_error = 0 + loo_error = 0 + else: + norm_emp_error = np.mean(residual**2)/varY + + loo_error = np.mean(np.square(residual / (1-h))) / varY + + # if there are NaNs, just return an infinite LOO error (this + # happens, e.g., when a strongly underdetermined problem is solved) + if np.isnan(loo_error): + loo_error = np.inf + + # Corrected Error for over-determined system + tr_M = np.trace(np.atleast_2d(inv_inf_matrix)) + if tr_M < 0 or abs(tr_M) > 1e6: + tr_M = np.trace(np.linalg.pinv(np.dot(psi.T, psi))) + + # Over-determined system of Equation + if N > P: + T_factor = N/(N-P) * (1 + tr_M) + + # Under-determined system of Equation + else: + T_factor = np.inf + + loo_error *= T_factor + + return loo_error + + def blockwise_inverse(self, Ainv, B, C, D): + """ + non-singular square matrix M defined as M = [[A B]; [C D]] . + B, C and D can have any dimension, provided their combination defines + a square matrix M. + + Parameters + ---------- + Ainv : float or array + inverse of the square-submatrix A. + B : float or array + Information matrix with all new regressor. + C : float or array + Transpose of B. + D : float or array + Information matrix with all selected regressors. + + Returns + ------- + M : array + Inverse of the information matrix. + + """ + if np.isscalar(D): + # Inverse of D + Dinv = 1/D + # Schur complement + SCinv = 1/(D - np.dot(C, np.dot(Ainv, B[:, None])))[0] + else: + # Inverse of D + Dinv = np.linalg.solve(D, np.eye(D.shape)) + # Schur complement + SCinv = np.linalg.solve((D - C*Ainv*B), np.eye(D.shape)) + + T1 = np.dot(Ainv, np.dot(B[:, None], SCinv)) + T2 = np.dot(C, Ainv) + + # Assemble the inverse matrix + M = np.vstack(( + np.hstack((Ainv+T1*T2, -T1)), + np.hstack((-(SCinv)*T2, SCinv)) + )) + return M diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/reg_fast_ard.py b/examples/analytical-function/bayesvalidrox/surrogate_models/reg_fast_ard.py new file mode 100644 index 000000000..e6883a3ed --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/surrogate_models/reg_fast_ard.py @@ -0,0 +1,475 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Tue Mar 24 19:41:45 2020 + +@author: farid +""" +import numpy as np +from scipy.linalg import solve_triangular +from numpy.linalg import LinAlgError +from sklearn.base import RegressorMixin +from sklearn.linear_model._base import LinearModel +import warnings +from sklearn.utils import check_X_y +from scipy.linalg import pinvh + + +def update_precisions(Q,S,q,s,A,active,tol,n_samples,clf_bias): + ''' + Selects one feature to be added/recomputed/deleted to model based on + effect it will have on value of log marginal likelihood. + ''' + # initialise vector holding changes in log marginal likelihood + deltaL = np.zeros(Q.shape[0]) + + # identify features that can be added , recomputed and deleted in model + theta = q**2 - s + add = (theta > 0) * (active == False) + recompute = (theta > 0) * (active == True) + delete = ~(add + recompute) + + # compute sparsity & quality parameters corresponding to features in + # three groups identified above + Qadd,Sadd = Q[add], S[add] + Qrec,Srec,Arec = Q[recompute], S[recompute], A[recompute] + Qdel,Sdel,Adel = Q[delete], S[delete], A[delete] + + # compute new alpha's (precision parameters) for features that are + # currently in model and will be recomputed + Anew = s[recompute]**2/ ( theta[recompute] + np.finfo(np.float32).eps) + delta_alpha = (1./Anew - 1./Arec) + + # compute change in log marginal likelihood + deltaL[add] = ( Qadd**2 - Sadd ) / Sadd + np.log(Sadd/Qadd**2 ) + deltaL[recompute] = Qrec**2 / (Srec + 1. / delta_alpha) - np.log(1 + Srec*delta_alpha) + deltaL[delete] = Qdel**2 / (Sdel - Adel) - np.log(1 - Sdel / Adel) + deltaL = deltaL / n_samples + + # find feature which caused largest change in likelihood + feature_index = np.argmax(deltaL) + + # no deletions or additions + same_features = np.sum( theta[~recompute] > 0) == 0 + + # changes in precision for features already in model is below threshold + no_delta = np.sum( abs( Anew - Arec ) > tol ) == 0 + # if same_features: print(abs( Anew - Arec )) + # print("same_features = {} no_delta = {}".format(same_features,no_delta)) + # check convergence: if no features to add or delete and small change in + # precision for current features then terminate + converged = False + if same_features and no_delta: + converged = True + return [A,converged] + + # if not converged update precision parameter of weights and return + if theta[feature_index] > 0: + A[feature_index] = s[feature_index]**2 / theta[feature_index] + if active[feature_index] == False: + active[feature_index] = True + else: + # at least two active features + if active[feature_index] == True and np.sum(active) >= 2: + # do not remove bias term in classification + # (in regression it is factored in through centering) + if not (feature_index == 0 and clf_bias): + active[feature_index] = False + A[feature_index] = np.PINF + + return [A,converged] + + +class RegressionFastARD(LinearModel, RegressorMixin): + ''' + Regression with Automatic Relevance Determination (Fast Version uses + Sparse Bayesian Learning) + https://github.com/AmazaspShumik/sklearn-bayes/blob/master/skbayes/rvm_ard_models/fast_rvm.py + + Parameters + ---------- + n_iter: int, optional (DEFAULT = 100) + Maximum number of iterations + + start: list, optional (DEFAULT = None) + Initial selected features. + + tol: float, optional (DEFAULT = 1e-3) + If absolute change in precision parameter for weights is below threshold + algorithm terminates. + + fit_intercept : boolean, optional (DEFAULT = True) + whether to calculate the intercept for this model. If set + to false, no intercept will be used in calculations + (e.g. data is expected to be already centered). + + copy_X : boolean, optional (DEFAULT = True) + If True, X will be copied; else, it may be overwritten. + + compute_score : bool, default=False + If True, compute the log marginal likelihood at each iteration of the + optimization. + + verbose : boolean, optional (DEFAULT = FALSE) + Verbose mode when fitting the model + + Attributes + ---------- + coef_ : array, shape = (n_features) + Coefficients of the regression model (mean of posterior distribution) + + alpha_ : float + estimated precision of the noise + + active_ : array, dtype = np.bool, shape = (n_features) + True for non-zero coefficients, False otherwise + + lambda_ : array, shape = (n_features) + estimated precisions of the coefficients + + sigma_ : array, shape = (n_features, n_features) + estimated covariance matrix of the weights, computed only + for non-zero coefficients + + scores_ : array-like of shape (n_iter_+1,) + If computed_score is True, value of the log marginal likelihood (to be + maximized) at each iteration of the optimization. + + References + ---------- + [1] Fast marginal likelihood maximisation for sparse Bayesian models + (Tipping & Faul 2003) (http://www.miketipping.com/papers/met-fastsbl.pdf) + [2] Analysis of sparse Bayesian learning (Tipping & Faul 2001) + (http://www.miketipping.com/abstracts.htm#Faul:NIPS01) + ''' + + def __init__(self, n_iter=300, start=None, tol=1e-3, fit_intercept=True, + normalize=False, copy_X=True, compute_score=False, verbose=False): + self.n_iter = n_iter + self.start = start + self.tol = tol + self.scores_ = list() + self.fit_intercept = fit_intercept + self.normalize = normalize + self.copy_X = copy_X + self.compute_score = compute_score + self.verbose = verbose + + def _preprocess_data(self, X, y): + """Center and scale data. + Centers data to have mean zero along axis 0. If fit_intercept=False or + if the X is a sparse matrix, no centering is done, but normalization + can still be applied. The function returns the statistics necessary to + reconstruct the input data, which are X_offset, y_offset, X_scale, such + that the output + X = (X - X_offset) / X_scale + X_scale is the L2 norm of X - X_offset. + """ + + if self.copy_X: + X = X.copy(order='K') + + y = np.asarray(y, dtype=X.dtype) + + if self.fit_intercept: + X_offset = np.average(X, axis=0) + X -= X_offset + if self.normalize: + X_scale = np.ones(X.shape[1], dtype=X.dtype) + std = np.sqrt(np.sum(X**2, axis=0)/(len(X)-1)) + X_scale[std != 0] = std[std != 0] + X /= X_scale + else: + X_scale = np.ones(X.shape[1], dtype=X.dtype) + y_offset = np.mean(y) + y = y - y_offset + else: + X_offset = np.zeros(X.shape[1], dtype=X.dtype) + X_scale = np.ones(X.shape[1], dtype=X.dtype) + if y.ndim == 1: + y_offset = X.dtype.type(0) + else: + y_offset = np.zeros(y.shape[1], dtype=X.dtype) + + return X, y, X_offset, y_offset, X_scale + + def fit(self, X, y): + ''' + Fits ARD Regression with Sequential Sparse Bayes Algorithm. + + Parameters + ----------- + X: {array-like, sparse matrix} of size (n_samples, n_features) + Training data, matrix of explanatory variables + + y: array-like of size [n_samples, n_features] + Target values + + Returns + ------- + self : object + Returns self. + ''' + X, y = check_X_y(X, y, dtype=np.float64, y_numeric=True) + n_samples, n_features = X.shape + + X, y, X_mean, y_mean, X_std = self._preprocess_data(X, y) + self._x_mean_ = X_mean + self._y_mean = y_mean + self._x_std = X_std + + # precompute X'*Y , X'*X for faster iterations & allocate memory for + # sparsity & quality vectors + XY = np.dot(X.T, y) + XX = np.dot(X.T, X) + XXd = np.diag(XX) + + # initialise precision of noise & and coefficients + var_y = np.var(y) + + # check that variance is non zero !!! + if var_y == 0: + beta = 1e-2 + self.var_y = True + else: + beta = 1. / np.var(y) + self.var_y = False + + A = np.PINF * np.ones(n_features) + active = np.zeros(n_features, dtype=np.bool) + + if self.start is not None and not hasattr(self, 'active_'): + start = self.start + # start from a given start basis vector + proj = XY**2 / XXd + active[start] = True + A[start] = XXd[start]/(proj[start] - var_y) + + else: + # in case of almost perfect multicollinearity between some features + # start from feature 0 + if np.sum(XXd - X_mean**2 < np.finfo(np.float32).eps) > 0: + A[0] = np.finfo(np.float16).eps + active[0] = True + + else: + # start from a single basis vector with largest projection on + # targets + proj = XY**2 / XXd + start = np.argmax(proj) + active[start] = True + A[start] = XXd[start]/(proj[start] - var_y + + np.finfo(np.float32).eps) + + warning_flag = 0 + scores_ = [] + for i in range(self.n_iter): + # Handle variance zero + if self.var_y: + A[0] = y_mean + active[0] = True + converged = True + break + + XXa = XX[active, :][:, active] + XYa = XY[active] + Aa = A[active] + + # mean & covariance of posterior distribution + Mn, Ri, cholesky = self._posterior_dist(Aa, beta, XXa, XYa) + if cholesky: + Sdiag = np.sum(Ri**2, 0) + else: + Sdiag = np.copy(np.diag(Ri)) + warning_flag += 1 + + # raise warning in case cholesky fails + if warning_flag == 1: + warnings.warn(("Cholesky decomposition failed! Algorithm uses " + "pinvh, which is significantly slower. If you " + "use RVR it is advised to change parameters of " + "the kernel!")) + + # compute quality & sparsity parameters + s, q, S, Q = self._sparsity_quality(XX, XXd, XY, XYa, Aa, Ri, + active, beta, cholesky) + + # update precision parameter for noise distribution + rss = np.sum((y - np.dot(X[:, active], Mn))**2) + + # if near perfect fit , then terminate + if (rss / n_samples/var_y) < self.tol: + warnings.warn('Early termination due to near perfect fit') + converged = True + break + beta = n_samples - np.sum(active) + np.sum(Aa * Sdiag) + beta /= rss + # beta /= (rss + np.finfo(np.float32).eps) + + # update precision parameters of coefficients + A, converged = update_precisions(Q, S, q, s, A, active, self.tol, + n_samples, False) + + if self.compute_score: + scores_.append(self.log_marginal_like(XXa, XYa, Aa, beta)) + + if self.verbose: + print(('Iteration: {0}, number of features ' + 'in the model: {1}').format(i, np.sum(active))) + + if converged or i == self.n_iter - 1: + if converged and self.verbose: + print('Algorithm converged!') + break + + # after last update of alpha & beta update parameters + # of posterior distribution + XXa, XYa, Aa = XX[active, :][:, active], XY[active], A[active] + Mn, Sn, cholesky = self._posterior_dist(Aa, beta, XXa, XYa, True) + self.coef_ = np.zeros(n_features) + self.coef_[active] = Mn + self.sigma_ = Sn + self.active_ = active + self.lambda_ = A + self.alpha_ = beta + self.converged = converged + if self.compute_score: + self.scores_ = np.array(scores_) + + # set intercept_ + if self.fit_intercept: + self.coef_ = self.coef_ / X_std + self.intercept_ = y_mean - np.dot(X_mean, self.coef_.T) + else: + self.intercept_ = 0. + return self + + def log_marginal_like(self, XXa, XYa, Aa, beta): + """Computes the log of the marginal likelihood.""" + N, M = XXa.shape + A = np.diag(Aa) + + Mn, sigma_, cholesky = self._posterior_dist(Aa, beta, XXa, XYa, + full_covar=True) + + C = sigma_ + np.dot(np.dot(XXa.T, np.linalg.pinv(A)), XXa) + + score = np.dot(np.dot(XYa.T, np.linalg.pinv(C)), XYa) +\ + np.log(np.linalg.det(C)) + N * np.log(2 * np.pi) + + return -0.5 * score + + def predict(self, X, return_std=False): + ''' + Computes predictive distribution for test set. + Predictive distribution for each data point is one dimensional + Gaussian and therefore is characterised by mean and variance based on + Ref.[1] Section 3.3.2. + + Parameters + ----------- + X: {array-like, sparse} (n_samples_test, n_features) + Test data, matrix of explanatory variables + + Returns + ------- + : list of length two [y_hat, var_hat] + + y_hat: numpy array of size (n_samples_test,) + Estimated values of targets on test set (i.e. mean of + predictive distribution) + + var_hat: numpy array of size (n_samples_test,) + Variance of predictive distribution + References + ---------- + [1] Bishop, C. M. (2006). Pattern recognition and machine learning. + springer. + ''' + + y_hat = np.dot(X, self.coef_) + self.intercept_ + + if return_std: + # Handle the zero variance case + if self.var_y: + return y_hat, np.zeros_like(y_hat) + + if self.normalize: + X -= self._x_mean_[self.active_] + X /= self._x_std[self.active_] + var_hat = 1./self.alpha_ + var_hat += np.sum(X.dot(self.sigma_) * X, axis=1) + std_hat = np.sqrt(var_hat) + return y_hat, std_hat + else: + return y_hat + + def _posterior_dist(self, A, beta, XX, XY, full_covar=False): + ''' + Calculates mean and covariance matrix of posterior distribution + of coefficients. + ''' + # compute precision matrix for active features + Sinv = beta * XX + np.fill_diagonal(Sinv, np.diag(Sinv) + A) + cholesky = True + + # try cholesky, if it fails go back to pinvh + try: + # find posterior mean : R*R.T*mean = beta*X.T*Y + # solve(R*z = beta*X.T*Y) =>find z=> solve(R.T*mean = z)=>find mean + R = np.linalg.cholesky(Sinv) + Z = solve_triangular(R, beta*XY, check_finite=True, lower=True) + Mn = solve_triangular(R.T, Z, check_finite=True, lower=False) + + # invert lower triangular matrix from cholesky decomposition + Ri = solve_triangular(R, np.eye(A.shape[0]), check_finite=False, + lower=True) + if full_covar: + Sn = np.dot(Ri.T, Ri) + return Mn, Sn, cholesky + else: + return Mn, Ri, cholesky + except LinAlgError: + cholesky = False + Sn = pinvh(Sinv) + Mn = beta*np.dot(Sinv, XY) + return Mn, Sn, cholesky + + def _sparsity_quality(self, XX, XXd, XY, XYa, Aa, Ri, active, beta, cholesky): + ''' + Calculates sparsity and quality parameters for each feature + + Theoretical Note: + ----------------- + Here we used Woodbury Identity for inverting covariance matrix + of target distribution + C = 1/beta + 1/alpha * X' * X + C^-1 = beta - beta^2 * X * Sn * X' + ''' + bxy = beta*XY + bxx = beta*XXd + if cholesky: + # here Ri is inverse of lower triangular matrix obtained from + # cholesky decomp + xxr = np.dot(XX[:, active], Ri.T) + rxy = np.dot(Ri, XYa) + S = bxx - beta**2 * np.sum(xxr**2, axis=1) + Q = bxy - beta**2 * np.dot(xxr, rxy) + else: + # here Ri is covariance matrix + XXa = XX[:, active] + XS = np.dot(XXa, Ri) + S = bxx - beta**2 * np.sum(XS*XXa, 1) + Q = bxy - beta**2 * np.dot(XS, XYa) + # Use following: + # (EQ 1) q = A*Q/(A - S) ; s = A*S/(A-S) + # so if A = np.PINF q = Q, s = S + qi = np.copy(Q) + si = np.copy(S) + # If A is not np.PINF, then it should be 'active' feature => use (EQ 1) + Qa, Sa = Q[active], S[active] + qi[active] = Aa * Qa / (Aa - Sa) + si[active] = Aa * Sa / (Aa - Sa) + + return [si, qi, S, Q] diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/reg_fast_laplace.py b/examples/analytical-function/bayesvalidrox/surrogate_models/reg_fast_laplace.py new file mode 100644 index 000000000..7fdcb5cf6 --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/surrogate_models/reg_fast_laplace.py @@ -0,0 +1,452 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +import numpy as np +from sklearn.utils import as_float_array +from sklearn.model_selection import KFold + + +class RegressionFastLaplace(): + ''' + Sparse regression with Bayesian Compressive Sensing as described in Alg. 1 + (Fast Laplace) of Ref.[1], which updated formulas from [2]. + + sigma2: noise precision (sigma^2) + nu fixed to 0 + + uqlab/lib/uq_regression/BCS/uq_bsc.m + + Parameters + ---------- + n_iter: int, optional (DEFAULT = 1000) + Maximum number of iterations + + tol: float, optional (DEFAULT = 1e-7) + If absolute change in precision parameter for weights is below + threshold algorithm terminates. + + fit_intercept : boolean, optional (DEFAULT = True) + whether to calculate the intercept for this model. If set + to false, no intercept will be used in calculations + (e.g. data is expected to be already centered). + + copy_X : boolean, optional (DEFAULT = True) + If True, X will be copied; else, it may be overwritten. + + verbose : boolean, optional (DEFAULT = FALSE) + Verbose mode when fitting the model + + Attributes + ---------- + coef_ : array, shape = (n_features) + Coefficients of the regression model (mean of posterior distribution) + + alpha_ : float + estimated precision of the noise + + active_ : array, dtype = np.bool, shape = (n_features) + True for non-zero coefficients, False otherwise + + lambda_ : array, shape = (n_features) + estimated precisions of the coefficients + + sigma_ : array, shape = (n_features, n_features) + estimated covariance matrix of the weights, computed only + for non-zero coefficients + + References + ---------- + [1] Babacan, S. D., Molina, R., & Katsaggelos, A. K. (2009). Bayesian + compressive sensing using Laplace priors. IEEE Transactions on image + processing, 19(1), 53-63. + [2] Fast marginal likelihood maximisation for sparse Bayesian models + (Tipping & Faul 2003). + (http://www.miketipping.com/papers/met-fastsbl.pdf) + ''' + + def __init__(self, n_iter=1000, n_Kfold=10, tol=1e-7, fit_intercept=False, + bias_term=True, copy_X=True, verbose=False): + self.n_iter = n_iter + self.n_Kfold = n_Kfold + self.tol = tol + self.fit_intercept = fit_intercept + self.bias_term = bias_term + self.copy_X = copy_X + self.verbose = verbose + + def _center_data(self, X, y): + ''' Centers data''' + X = as_float_array(X, copy = self.copy_X) + + # normalisation should be done in preprocessing! + X_std = np.ones(X.shape[1], dtype=X.dtype) + if self.fit_intercept: + X_mean = np.average(X, axis=0) + y_mean = np.average(y, axis=0) + X -= X_mean + y -= y_mean + else: + X_mean = np.zeros(X.shape[1], dtype=X.dtype) + y_mean = 0. if y.ndim == 1 else np.zeros(y.shape[1], dtype=X.dtype) + return X, y, X_mean, y_mean, X_std + + def fit(self, X, y): + + k_fold = KFold(n_splits=self.n_Kfold) + + varY = np.var(y, ddof=1) if np.var(y, ddof=1) != 0 else 1.0 + sigma2s = len(y)*varY*(10**np.linspace(-16, -1, self.n_Kfold)) + + errors = np.zeros((len(sigma2s), self.n_Kfold)) + for s, sigma2 in enumerate(sigma2s): + for k, (train, test) in enumerate(k_fold.split(X, y)): + self.fit_(X[train], y[train], sigma2) + errors[s, k] = np.linalg.norm( + y[test] - self.predict(X[test]) + )**2/len(test) + + KfCVerror = np.sum(errors, axis=1)/self.n_Kfold/varY + i_minCV = np.argmin(KfCVerror) + + self.kfoldCVerror = np.min(KfCVerror) + + return self.fit_(X, y, sigma2s[i_minCV]) + + def fit_(self, X, y, sigma2): + + N, P = X.shape + # n_samples, n_features = X.shape + + X, y, X_mean, y_mean, X_std = self._center_data(X, y) + self._x_mean_ = X_mean + self._y_mean = y_mean + self._x_std = X_std + + # check that variance is non zero !!! + if np.var(y) == 0: + self.var_y = True + else: + self.var_y = False + beta = 1./sigma2 + + # precompute X'*Y , X'*X for faster iterations & allocate memory for + # sparsity & quality vectors X=Psi + PsiTY = np.dot(X.T, y) + PsiTPsi = np.dot(X.T, X) + XXd = np.diag(PsiTPsi) + + # initialize with constant regressor, or if that one does not exist, + # with the one that has the largest correlation with Y + ind_global_to_local = np.zeros(P, dtype=np.int32) + + # identify constant regressors + constidx = np.where(~np.diff(X, axis=0).all(axis=0))[0] + + if self.bias_term and constidx.size != 0: + ind_start = constidx[0] + ind_global_to_local[ind_start] = True + else: + # start from a single basis vector with largest projection on + # targets + proj = np.divide(np.square(PsiTY), XXd) + ind_start = np.argmax(proj) + ind_global_to_local[ind_start] = True + + num_active = 1 + active_indices = [ind_start] + deleted_indices = [] + bcs_path = [ind_start] + gamma = np.zeros(P) + # for the initial value of gamma(ind_start), use the RVM formula + # gamma = (q^2 - s) / (s^2) + # and the fact that initially s = S = beta*Psi_i'*Psi_i and q = Q = + # beta*Psi_i'*Y + gamma[ind_start] = np.square(PsiTY[ind_start]) + gamma[ind_start] -= sigma2 * PsiTPsi[ind_start, ind_start] + gamma[ind_start] /= np.square(PsiTPsi[ind_start, ind_start]) + + Sigma = 1. / (beta * PsiTPsi[ind_start, ind_start] + + 1./gamma[ind_start]) + + mu = Sigma * PsiTY[ind_start] * beta + tmp1 = beta * PsiTPsi[ind_start] + S = beta * np.diag(PsiTPsi).T - Sigma * np.square(tmp1) + Q = beta * PsiTY.T - mu*(tmp1) + + tmp2 = np.ones(P) # alternative computation for the initial s,q + q0tilde = PsiTY[ind_start] + s0tilde = PsiTPsi[ind_start, ind_start] + tmp2[ind_start] = s0tilde / (q0tilde**2) / beta + s = np.divide(S, tmp2) + q = np.divide(Q, tmp2) + Lambda = 2*(num_active - 1) / np.sum(gamma) + + Delta_L_max = [] + for i in range(self.n_iter): + # Handle variance zero + if self.var_y: + mu = np.mean(y) + break + + if self.verbose: + print(' lambda = {0:.6e}\n'.format(Lambda)) + + # Calculate the potential updated value of each gamma[i] + if Lambda == 0.0: # RVM + gamma_potential = np.multiply(( + (q**2 - s) > Lambda), + np.divide(q**2 - s, s**2) + ) + else: + a = Lambda * s**2 + b = s**2 + 2*Lambda*s + c = Lambda + s - q**2 + gamma_potential = np.multiply( + (c < 0), np.divide( + -b + np.sqrt(b**2 - 4*np.multiply(a, c)), 2*a) + ) + + l_gamma = - np.log(np.absolute(1 + np.multiply(gamma, s))) + l_gamma += np.divide(np.multiply(q**2, gamma), + (1 + np.multiply(gamma, s))) + l_gamma -= Lambda*gamma # omitted the factor 1/2 + + # Contribution of each updated gamma(i) to L(gamma) + l_gamma_potential = - np.log( + np.absolute(1 + np.multiply(gamma_potential, s)) + ) + l_gamma_potential += np.divide( + np.multiply(q**2, gamma_potential), + (1 + np.multiply(gamma_potential, s)) + ) + # omitted the factor 1/2 + l_gamma_potential -= Lambda*gamma_potential + + # Check how L(gamma) would change if we replaced gamma(i) by the + # updated gamma_potential(i), for each i separately + Delta_L_potential = l_gamma_potential - l_gamma + + # deleted indices should not be chosen again + if len(deleted_indices) != 0: + values = -np.inf * np.ones(len(deleted_indices)) + Delta_L_potential[deleted_indices] = values + + Delta_L_max.append(np.nanmax(Delta_L_potential)) + ind_L_max = np.nanargmax(Delta_L_potential) + + # in case there is only 1 regressor in the model and it would now + # be deleted + if len(active_indices) == 1 and ind_L_max == active_indices[0] \ + and gamma_potential[ind_L_max] == 0.0: + Delta_L_potential[ind_L_max] = -np.inf + Delta_L_max[i] = np.max(Delta_L_potential) + ind_L_max = np.argmax(Delta_L_potential) + + # If L did not change significantly anymore, break + if Delta_L_max[i] <= 0.0 or\ + (i > 0 and all(np.absolute(Delta_L_max[i-1:]) + < sum(Delta_L_max)*self.tol)) or \ + (i > 0 and all(np.diff(bcs_path)[i-1:] == 0.0)): + if self.verbose: + print('Increase in L: {0:.6e} (eta = {1:.3e})\ + -- break\n'.format(Delta_L_max[i], self.tol)) + break + + # Print information + if self.verbose: + print(' Delta L = {0:.6e} \n'.format(Delta_L_max[i])) + + what_changed = int(gamma[ind_L_max] == 0.0) + what_changed -= int(gamma_potential[ind_L_max] == 0.0) + + # Print information + if self.verbose: + if what_changed < 0: + print(f'{i+1} - Remove regressor #{ind_L_max+1}..\n') + elif what_changed == 0: + print(f'{i+1} - Recompute regressor #{ind_L_max+1}..\n') + else: + print(f'{i+1} - Add regressor #{ind_L_max+1}..\n') + + # --- Update all quantities ---- + if what_changed == 1: + # adding a regressor + + # update gamma + gamma[ind_L_max] = gamma_potential[ind_L_max] + + Sigma_ii = 1.0 / (1.0/gamma[ind_L_max] + S[ind_L_max]) + try: + x_i = np.matmul( + Sigma, PsiTPsi[active_indices, ind_L_max].reshape(-1, 1) + ) + except ValueError: + x_i = Sigma * PsiTPsi[active_indices, ind_L_max] + tmp_1 = - (beta * Sigma_ii) * x_i + Sigma = np.vstack( + (np.hstack(((beta**2 * Sigma_ii) * np.dot(x_i, x_i.T) + + Sigma, tmp_1)), np.append(tmp_1.T, Sigma_ii)) + ) + mu_i = Sigma_ii * Q[ind_L_max] + mu = np.vstack((mu - (beta * mu_i) * x_i, mu_i)) + + tmp2_1 = PsiTPsi[:, ind_L_max] - beta * np.squeeze( + np.matmul(PsiTPsi[:, active_indices], x_i) + ) + if i == 0: + tmp2_1[0] /= 2 + tmp2 = beta * tmp2_1.T + S = S - Sigma_ii * np.square(tmp2) + Q = Q - mu_i * tmp2 + + num_active += 1 + ind_global_to_local[ind_L_max] = num_active + active_indices.append(ind_L_max) + bcs_path.append(ind_L_max) + + elif what_changed == 0: + # recomputation + # zero if regressor has not been chosen yet + if not ind_global_to_local[ind_L_max]: + raise Exception('Cannot recompute index{0} -- not yet\ + part of the model!'.format(ind_L_max)) + Sigma = np.atleast_2d(Sigma) + mu = np.atleast_2d(mu) + gamma_i_new = gamma_potential[ind_L_max] + gamma_i_old = gamma[ind_L_max] + # update gamma + gamma[ind_L_max] = gamma_potential[ind_L_max] + + # index of regressor in Sigma + local_ind = ind_global_to_local[ind_L_max]-1 + + kappa_i = (1.0/gamma_i_new - 1.0/gamma_i_old) + kappa_i = 1.0 / kappa_i + kappa_i += Sigma[local_ind, local_ind] + kappa_i = 1 / kappa_i + Sigma_i_col = Sigma[:, local_ind] + + Sigma = Sigma - kappa_i * (Sigma_i_col * Sigma_i_col.T) + mu_i = mu[local_ind] + mu = mu - (kappa_i * mu_i) * Sigma_i_col[:, None] + + tmp1 = beta * np.dot( + Sigma_i_col.reshape(1, -1), PsiTPsi[active_indices])[0] + S = S + kappa_i * np.square(tmp1) + Q = Q + (kappa_i * mu_i) * tmp1 + + # no change in active_indices or ind_global_to_local + bcs_path.append(ind_L_max + 0.1) + + elif what_changed == -1: + gamma[ind_L_max] = 0 + + # index of regressor in Sigma + local_ind = ind_global_to_local[ind_L_max]-1 + + Sigma_ii_inv = 1. / Sigma[local_ind, local_ind] + Sigma_i_col = Sigma[:, local_ind] + + Sigma = Sigma - Sigma_ii_inv * (Sigma_i_col * Sigma_i_col.T) + + Sigma = np.delete( + np.delete(Sigma, local_ind, axis=0), local_ind, axis=1) + + mu = mu - (mu[local_ind] * Sigma_ii_inv) * Sigma_i_col[:, None] + mu = np.delete(mu, local_ind, axis=0) + + tmp1 = beta * np.dot(Sigma_i_col, PsiTPsi[active_indices]) + S = S + Sigma_ii_inv * np.square(tmp1) + Q = Q + (mu_i * Sigma_ii_inv) * tmp1 + + num_active -= 1 + ind_global_to_local[ind_L_max] = 0.0 + v = ind_global_to_local[ind_global_to_local > local_ind] - 1 + ind_global_to_local[ind_global_to_local > local_ind] = v + del active_indices[local_ind] + deleted_indices.append(ind_L_max) + # and therefore ineligible + bcs_path.append(-ind_L_max) + + # same for all three cases + tmp3 = 1 - np.multiply(gamma, S) + s = np.divide(S, tmp3) + q = np.divide(Q, tmp3) + + # Update lambda + Lambda = 2*(num_active - 1) / np.sum(gamma) + + # Prepare the result object + self.coef_ = np.zeros(P) + self.coef_[active_indices] = np.squeeze(mu) + self.sigma_ = Sigma + self.active_ = active_indices + self.gamma = gamma + self.Lambda = Lambda + self.beta = beta + self.bcs_path = bcs_path + + # set intercept_ + if self.fit_intercept: + self.coef_ = self.coef_ / X_std + self.intercept_ = y_mean - np.dot(X_mean, self.coef_.T) + else: + self.intercept_ = 0. + + return self + + def predict(self, X, return_std=False): + ''' + Computes predictive distribution for test set. + Predictive distribution for each data point is one dimensional + Gaussian and therefore is characterised by mean and variance based on + Ref.[1] Section 3.3.2. + + Parameters + ----------- + X: {array-like, sparse} (n_samples_test, n_features) + Test data, matrix of explanatory variables + + Returns + ------- + : list of length two [y_hat, var_hat] + + y_hat: numpy array of size (n_samples_test,) + Estimated values of targets on test set (i.e. mean of + predictive distribution) + + var_hat: numpy array of size (n_samples_test,) + Variance of predictive distribution + + References + ---------- + [1] Bishop, C. M. (2006). Pattern recognition and machine learning. + springer. + ''' + y_hat = np.dot(X, self.coef_) + self.intercept_ + + if return_std: + # Handle the zero variance case + if self.var_y: + return y_hat, np.zeros_like(y_hat) + + var_hat = 1./self.beta + var_hat += np.sum(X.dot(self.sigma_) * X, axis=1) + std_hat = np.sqrt(var_hat) + return y_hat, std_hat + else: + return y_hat + +# l2norm = 0.0 +# for idx in range(10): +# sigma2 = np.genfromtxt('./test/sigma2_{0}.csv'.format(idx+1), delimiter=',') +# Psi_train = np.genfromtxt('./test/Psi_train_{0}.csv'.format(idx+1), delimiter=',') +# Y_train = np.genfromtxt('./test/Y_train_{0}.csv'.format(idx+1)) +# Psi_test = np.genfromtxt('./test/Psi_test_{0}.csv'.format(idx+1), delimiter=',') +# Y_test = np.genfromtxt('./test/Y_test_{0}.csv'.format(idx+1)) + +# clf = RegressionFastLaplace(verbose=True) +# clf.fit_(Psi_train, Y_train, sigma2) +# coeffs_fold = np.genfromtxt('./test/coeffs_fold_{0}.csv'.format(idx+1)) +# print("coeffs error: {0:.4g}".format(np.linalg.norm(clf.coef_ - coeffs_fold))) +# l2norm += np.linalg.norm(Y_test - clf.predict(Psi_test))**2/len(Y_test) +# print("l2norm error: {0:.4g}".format(l2norm)) diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/sequential_design.py b/examples/analytical-function/bayesvalidrox/surrogate_models/sequential_design.py new file mode 100644 index 000000000..fc81dcd45 --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/surrogate_models/sequential_design.py @@ -0,0 +1,2187 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Fri Jan 28 09:21:18 2022 + +@author: farid +""" +import numpy as np +from scipy import stats, signal, linalg, sparse +from scipy.spatial import distance +from copy import deepcopy, copy +from tqdm import tqdm +import scipy.optimize as opt +from sklearn.metrics import mean_squared_error +import multiprocessing +import matplotlib.pyplot as plt +import sys +import os +import gc +import seaborn as sns +from joblib import Parallel, delayed +import resource +from .exploration import Exploration + + +class SeqDesign(): + """ Sequential experimental design + This class provieds method for trainig the meta-model in an iterative + manners. + The main method to execute the task is `train_seq_design`, which + recieves a model object and returns the trained metamodel. + """ + + # ------------------------------------------------------------------------- + def train_seq_design(self, MetaModel): + """ + Starts the adaptive sequential design for refining the surrogate model + by selecting training points in a sequential manner. + + Parameters + ---------- + Model : object + An object containing all model specifications. + + Returns + ------- + MetaModel : object + Meta model object. + + """ + # MetaModel = self + Model = MetaModel.ModelObj + self.MetaModel = MetaModel + self.Model = Model + + # Initialization + MetaModel.SeqModifiedLOO = {} + MetaModel.seqValidError = {} + MetaModel.SeqBME = {} + MetaModel.SeqKLD = {} + MetaModel.SeqDistHellinger = {} + MetaModel.seqRMSEMean = {} + MetaModel.seqRMSEStd = {} + MetaModel.seqMinDist = [] + pce = True if MetaModel.meta_model_type.lower() != 'gpe' else False + mc_ref = True if bool(Model.mc_reference) else False + if mc_ref: + Model.read_mc_reference() + + if not hasattr(MetaModel, 'valid_likelihoods'): + MetaModel.valid_samples = [] + MetaModel.valid_model_runs = [] + MetaModel.valid_likelihoods = [] + + # Get the parameters + max_n_samples = MetaModel.ExpDesign.n_max_samples + mod_LOO_threshold = MetaModel.ExpDesign.mod_LOO_threshold + n_canddidate = MetaModel.ExpDesign.n_canddidate + post_snapshot = MetaModel.ExpDesign.post_snapshot + n_replication = MetaModel.ExpDesign.n_replication + util_func = MetaModel.ExpDesign.util_func + output_name = Model.Output.names + validError = None + # Handle if only one UtilityFunctions is provided + if not isinstance(util_func, list): + util_func = [MetaModel.ExpDesign.util_func] + + # Read observations or MCReference + if len(Model.observations) != 0 or Model.meas_file is not None: + self.observations = Model.read_observation() + obs_data = self.observations + else: + obs_data = [] + TotalSigma2 = {} + # ---------- Initial MetaModel ---------- + initMetaModel = deepcopy(MetaModel) + + # Validation error if validation set is provided. + if len(MetaModel.valid_model_runs) != 0: + init_rmse, init_valid_error = self.__validError(initMetaModel) + init_valid_error = list(init_valid_error.values()) + else: + init_rmse = None + + # Check if discrepancy is provided + if len(obs_data) != 0 and hasattr(MetaModel, 'Discrepancy'): + TotalSigma2 = MetaModel.Discrepancy.parameters + + # Calculate the initial BME + out = self.__BME_Calculator( + initMetaModel, obs_data, TotalSigma2, init_rmse) + init_BME, init_KLD, init_post, init_likes, init_dist_hellinger = out + print(f"\nInitial BME: {init_BME:.2f}") + print(f"Initial KLD: {init_KLD:.2f}") + + # Posterior snapshot (initial) + if post_snapshot: + parNames = MetaModel.ExpDesign.par_names + print('Posterior snapshot (initial) is being plotted...') + self.__posteriorPlot(init_post, parNames, 'SeqPosterior_init') + + # Check the convergence of the Mean & Std + if mc_ref and pce: + init_rmse_mean, init_rmse_std = self.__error_Mean_Std() + print(f"Initial Mean and Std error: {init_rmse_mean}," + f" {init_rmse_std}") + + # Read the initial experimental design + Xinit = initMetaModel.ExpDesign.X + init_n_samples = len(MetaModel.ExpDesign.X) + initYprev = initMetaModel.ModelOutputDict + initLCerror = initMetaModel.LCerror + n_itrs = max_n_samples - init_n_samples + + # Read the initial ModifiedLOO + if pce: + Scores_all, varExpDesignY = [], [] + for out_name in output_name: + y = initMetaModel.ExpDesign.Y[out_name] + Scores_all.append(list( + initMetaModel.score_dict['b_1'][out_name].values())) + if MetaModel.dim_red_method.lower() == 'pca': + pca = MetaModel.pca['b_1'][out_name] + components = pca.transform(y) + varExpDesignY.append(np.var(components, axis=0)) + else: + varExpDesignY.append(np.var(y, axis=0)) + + Scores = [item for sublist in Scores_all for item in sublist] + weights = [item for sublist in varExpDesignY for item in sublist] + init_mod_LOO = [np.average([1-score for score in Scores], + weights=weights)] + + prevMetaModel_dict = {} + # Replicate the sequential design + for repIdx in range(n_replication): + print(f'\n>>>> Replication: {repIdx+1}<<<<') + + # To avoid changes ub original aPCE object + MetaModel.ExpDesign.X = Xinit + MetaModel.ExpDesign.Y = initYprev + MetaModel.LCerror = initLCerror + + for util_f in util_func: + print(f'\n>>>> Utility Function: {util_f} <<<<') + # To avoid changes ub original aPCE object + MetaModel.ExpDesign.X = Xinit + MetaModel.ExpDesign.Y = initYprev + MetaModel.LCerror = initLCerror + + # Set the experimental design + Xprev = Xinit + total_n_samples = init_n_samples + Yprev = initYprev + + Xfull = [] + Yfull = [] + + # Store the initial ModifiedLOO + if pce: + print("\nInitial ModifiedLOO:", init_mod_LOO) + SeqModifiedLOO = np.array(init_mod_LOO) + + if len(MetaModel.valid_model_runs) != 0: + SeqValidError = np.array(init_valid_error) + + # Check if data is provided + if len(obs_data) != 0: + SeqBME = np.array([init_BME]) + SeqKLD = np.array([init_KLD]) + SeqDistHellinger = np.array([init_dist_hellinger]) + + if mc_ref and pce: + seqRMSEMean = np.array([init_rmse_mean]) + seqRMSEStd = np.array([init_rmse_std]) + + # ------- Start Sequential Experimental Design ------- + postcnt = 1 + for itr_no in range(1, n_itrs+1): + print(f'\n>>>> Iteration number {itr_no} <<<<') + + # Save the metamodel prediction before updating + prevMetaModel_dict[itr_no] = deepcopy(MetaModel) + if itr_no > 1: + pc_model = prevMetaModel_dict[itr_no-1] + self._y_hat_prev, _ = pc_model.eval_metamodel( + samples=Xfull[-1].reshape(1, -1)) + + # Optimal Bayesian Design + m_1 = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024 + MetaModel.ExpDesignFlag = 'sequential' + Xnew, updatedPrior = self.opt_SeqDesign(TotalSigma2, + n_canddidate, + util_f) + m_2 = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024 + S = np.min(distance.cdist(Xinit, Xnew, 'euclidean')) + MetaModel.seqMinDist.append(S) + print(f"\nmin Dist from OldExpDesign: {S:2f}") + print("\n") + + # Evaluate the full model response at the new sample + Ynew, _ = Model.run_model_parallel( + Xnew, prevRun_No=total_n_samples + ) + total_n_samples += Xnew.shape[0] + # ------ Plot the surrogate model vs Origninal Model ------ + if hasattr(MetaModel, 'adapt_verbose') and \ + MetaModel.adapt_verbose: + from .adaptPlot import adaptPlot + y_hat, std_hat = MetaModel.eval_metamodel(samples=Xnew) + adaptPlot(MetaModel, Ynew, y_hat, std_hat, plotED=False) + + # -------- Retrain the surrogate model ------- + # Extend new experimental design + Xfull = np.vstack((Xprev, Xnew)) + + # Updating experimental design Y + for out_name in output_name: + Yfull = np.vstack((Yprev[out_name], Ynew[out_name])) + MetaModel.ModelOutputDict[out_name] = Yfull + + # Pass new design to the metamodel object + MetaModel.ExpDesign.sampling_method = 'user' + MetaModel.ExpDesign.X = Xfull + MetaModel.ExpDesign.Y = MetaModel.ModelOutputDict + + # Save the Experimental Design for next iteration + Xprev = Xfull + Yprev = MetaModel.ModelOutputDict + + # Pass the new prior as the input + MetaModel.input_obj.poly_coeffs_flag = False + if updatedPrior is not None: + MetaModel.input_obj.poly_coeffs_flag = True + print("updatedPrior:", updatedPrior.shape) + # Arbitrary polynomial chaos + for i in range(updatedPrior.shape[1]): + MetaModel.input_obj.Marginals[i].dist_type = None + x = updatedPrior[:, i] + MetaModel.input_obj.Marginals[i].raw_data = x + + # Train the surrogate model for new ExpDesign + MetaModel.train_norm_design(parallel=False) + m_3 = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024 + + # -------- Evaluate the retrained surrogate model ------- + # Extract Modified LOO from Output + if pce: + Scores_all, varExpDesignY = [], [] + for out_name in output_name: + y = MetaModel.ExpDesign.Y[out_name] + Scores_all.append(list( + MetaModel.score_dict['b_1'][out_name].values())) + if MetaModel.dim_red_method.lower() == 'pca': + pca = MetaModel.pca['b_1'][out_name] + components = pca.transform(y) + varExpDesignY.append(np.var(components, + axis=0)) + else: + varExpDesignY.append(np.var(y, axis=0)) + Scores = [item for sublist in Scores_all for item + in sublist] + weights = [item for sublist in varExpDesignY for item + in sublist] + ModifiedLOO = [np.average( + [1-score for score in Scores], weights=weights)] + + print('\n') + print(f"Updated ModifiedLOO {util_f}:\n", ModifiedLOO) + print('\n') + + # Compute the validation error + if len(MetaModel.valid_model_runs) != 0: + rmse, validError = self.__validError(MetaModel) + ValidError = list(validError.values()) + else: + rmse = None + + # Store updated ModifiedLOO + if pce: + SeqModifiedLOO = np.vstack( + (SeqModifiedLOO, ModifiedLOO)) + if len(MetaModel.valid_model_runs) != 0: + SeqValidError = np.vstack( + (SeqValidError, ValidError)) + m_4 = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024 + # -------- Caclulation of BME as accuracy metric ------- + # Check if data is provided + if len(obs_data) != 0: + # Calculate the initial BME + out = self.__BME_Calculator(MetaModel, obs_data, + TotalSigma2, rmse) + BME, KLD, Posterior, likes, DistHellinger = out + print('\n') + print(f"Updated BME: {BME:.2f}") + print(f"Updated KLD: {KLD:.2f}") + print('\n') + + # Plot some snapshots of the posterior + step_snapshot = MetaModel.ExpDesign.step_snapshot + if post_snapshot and postcnt % step_snapshot == 0: + parNames = MetaModel.ExpDesign.par_names + print('Posterior snapshot is being plotted...') + self.__posteriorPlot(Posterior, parNames, + f'SeqPosterior_{postcnt}') + postcnt += 1 + m_5 = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024 + + # Check the convergence of the Mean&Std + if mc_ref and pce: + print('\n') + RMSE_Mean, RMSE_std = self.__error_Mean_Std() + print(f"Updated Mean and Std error: {RMSE_Mean:.2f}, " + f"{RMSE_std:.2f}") + print('\n') + + # Store the updated BME & KLD + # Check if data is provided + if len(obs_data) != 0: + SeqBME = np.vstack((SeqBME, BME)) + SeqKLD = np.vstack((SeqKLD, KLD)) + SeqDistHellinger = np.vstack((SeqDistHellinger, + DistHellinger)) + if mc_ref and pce: + seqRMSEMean = np.vstack((seqRMSEMean, RMSE_Mean)) + seqRMSEStd = np.vstack((seqRMSEStd, RMSE_std)) + + if pce and any(LOO < mod_LOO_threshold + for LOO in ModifiedLOO): + break + + print(f"Memory itr {itr_no}: I: {m_2-m_1:.2f} MB") + print(f"Memory itr {itr_no}: II: {m_3-m_2:.2f} MB") + print(f"Memory itr {itr_no}: III: {m_4-m_3:.2f} MB") + print(f"Memory itr {itr_no}: IV: {m_5-m_4:.2f} MB") + m_6 = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024 + print(f"Memory itr {itr_no}: total: {m_6:.2f} MB") + + # Clean up + if len(obs_data) != 0: + del out + gc.collect() + print() + print('-'*50) + print() + + # Store updated ModifiedLOO and BME in dictonary + strKey = f'{util_f}_rep_{repIdx+1}' + if pce: + MetaModel.SeqModifiedLOO[strKey] = SeqModifiedLOO + if len(MetaModel.valid_model_runs) != 0: + MetaModel.seqValidError[strKey] = SeqValidError + + # Check if data is provided + if len(obs_data) != 0: + MetaModel.SeqBME[strKey] = SeqBME + MetaModel.SeqKLD[strKey] = SeqKLD + if len(MetaModel.valid_likelihoods) != 0: + MetaModel.SeqDistHellinger[strKey] = SeqDistHellinger + if mc_ref and pce: + MetaModel.seqRMSEMean[strKey] = seqRMSEMean + MetaModel.seqRMSEStd[strKey] = seqRMSEStd + + return MetaModel + + # ------------------------------------------------------------------------- + def util_VarBasedDesign(self, X_can, index, util_func='Entropy'): + """ + Computes the exploitation scores based on: + active learning MacKay(ALM) and active learning Cohn (ALC) + Paper: Sequential Design with Mutual Information for Computer + Experiments (MICE): Emulation of a Tsunami Model by Beck and Guillas + (2016) + + Parameters + ---------- + X_can : array of shape (n_samples, n_params) + Candidate samples. + index : int + Model output index. + UtilMethod : string, optional + Exploitation utility function. The default is 'Entropy'. + + Returns + ------- + float + Score. + + """ + MetaModel = self.MetaModel + ED_X = MetaModel.ExpDesign.X + out_dict_y = MetaModel.ExpDesign.Y + out_names = MetaModel.ModelObj.Output.names + + # Run the Metamodel for the candidate + X_can = X_can.reshape(1, -1) + Y_PC_can, std_PC_can = MetaModel.eval_metamodel(samples=X_can) + + if util_func.lower() == 'alm': + # ----- Entropy/MMSE/active learning MacKay(ALM) ----- + # Compute perdiction variance of the old model + canPredVar = {key: std_PC_can[key]**2 for key in out_names} + + varPCE = np.zeros((len(out_names), X_can.shape[0])) + for KeyIdx, key in enumerate(out_names): + varPCE[KeyIdx] = np.max(canPredVar[key], axis=1) + score = np.max(varPCE, axis=0) + + elif util_func.lower() == 'eigf': + # ----- Expected Improvement for Global fit ----- + # Find closest EDX to the candidate + distances = distance.cdist(ED_X, X_can, 'euclidean') + index = np.argmin(distances) + + # Compute perdiction error and variance of the old model + predError = {key: Y_PC_can[key] for key in out_names} + canPredVar = {key: std_PC_can[key]**2 for key in out_names} + + # Compute perdiction error and variance of the old model + # Eq (5) from Liu et al.(2018) + EIGF_PCE = np.zeros((len(out_names), X_can.shape[0])) + for KeyIdx, key in enumerate(out_names): + residual = predError[key] - out_dict_y[key][int(index)] + var = canPredVar[key] + EIGF_PCE[KeyIdx] = np.max(residual**2 + var, axis=1) + score = np.max(EIGF_PCE, axis=0) + + return -1 * score # -1 is for minimization instead of maximization + + # ------------------------------------------------------------------------- + def util_BayesianActiveDesign(self, X_can, sigma2Dict, var='DKL'): + """ + Computes scores based on Bayesian active design criterion (var). + + It is based on the following paper: + Oladyshkin, Sergey, Farid Mohammadi, Ilja Kroeker, and Wolfgang Nowak. + "Bayesian3 active learning for the gaussian process emulator using + information theory." Entropy 22, no. 8 (2020): 890. + + Parameters + ---------- + X_can : array of shape (n_samples, n_params) + Candidate samples. + sigma2Dict : dict + A dictionary containing the measurement errors (sigma^2). + var : string, optional + BAL design criterion. The default is 'DKL'. + + Returns + ------- + float + Score. + + """ + + # Evaluate the PCE metamodels at that location ??? + Y_mean_can, Y_std_can = self.MetaModel.eval_metamodel( + samples=np.array([X_can]) + ) + + # Get the data + obs_data = self.observations + n_obs = self.Model.n_obs + # TODO: Analytical DKL + # Sample a distribution for a normal dist + # with Y_mean_can as the mean and Y_std_can as std. + + # priorMean, priorSigma2, Obs = np.empty((0)),np.empty((0)),np.empty((0)) + + # for key in list(Y_mean_can): + # # concatenate the measurement error + # Obs = np.hstack((Obs,ObservationData[key])) + + # # concatenate the mean and variance of prior predictive + # means, stds = Y_mean_can[key][0], Y_std_can[key][0] + # priorMean = np.hstack((priorSigma2,means)) + # priorSigma2 = np.hstack((priorSigma2,stds**2)) + + # # Covariance Matrix of prior + # covPrior = np.zeros((priorSigma2.shape[0], priorSigma2.shape[0]), float) + # np.fill_diagonal(covPrior, priorSigma2) + + # # Covariance Matrix of Likelihood + # covLikelihood = np.zeros((sigma2Dict.shape[0], sigma2Dict.shape[0]), float) + # np.fill_diagonal(covLikelihood, sigma2Dict) + + # # Calculate moments of the posterior (Analytical derivation) + # n = priorSigma2.shape[0] + # covPost = np.dot(np.dot(covPrior,np.linalg.inv(covPrior+(covLikelihood/n))),covLikelihood/n) + + # meanPost = np.dot(np.dot(covPrior,np.linalg.inv(covPrior+(covLikelihood/n))) , Obs) + \ + # np.dot(np.dot(covPrior,np.linalg.inv(covPrior+(covLikelihood/n))), + # priorMean/n) + # # Compute DKL from prior to posterior + # term1 = np.trace(np.dot(np.linalg.inv(covPrior),covPost)) + # deltaMean = priorMean-meanPost + # term2 = np.dot(np.dot(deltaMean,np.linalg.inv(covPrior)),deltaMean[:,None]) + # term3 = np.log(np.linalg.det(covPrior)/np.linalg.det(covPost)) + # DKL = 0.5 * (term1 + term2 - n + term3)[0] + + # ---------- Inner MC simulation for computing Utility Value ---------- + # Estimation of the integral via Monte Varlo integration + MCsize = 20000 + ESS = 0 + + while ((ESS > MCsize) or (ESS < 1)): + + # Sample a distribution for a normal dist + # with Y_mean_can as the mean and Y_std_can as std. + Y_MC, std_MC = {}, {} + logPriorLikelihoods = np.zeros((MCsize)) + for key in list(Y_mean_can): + means, stds = Y_mean_can[key][0], Y_std_can[key][0] + # cov = np.zeros((means.shape[0], means.shape[0]), float) + # np.fill_diagonal(cov, stds**2) + + Y_MC[key] = np.zeros((MCsize, n_obs)) + logsamples = np.zeros((MCsize, n_obs)) + for i in range(n_obs): + NormalDensity = stats.norm(means[i], stds[i]) + Y_MC[key][:, i] = NormalDensity.rvs(MCsize) + logsamples[:, i] = NormalDensity.logpdf(Y_MC[key][:, i]) + + logPriorLikelihoods = np.sum(logsamples, axis=1) + std_MC[key] = np.zeros((MCsize, means.shape[0])) + + # Likelihood computation (Comparison of data and simulation + # results via PCE with candidate design) + likelihoods = self.__normpdf(Y_MC, std_MC, obs_data, sigma2Dict) + + # Check the Effective Sample Size (1<ESS<MCsize) + ESS = 1 / np.sum(np.square(likelihoods/np.nansum(likelihoods))) + + # Enlarge sample size if it doesn't fulfill the criteria + if ((ESS > MCsize) or (ESS < 1)): + MCsize *= 10 + ESS = 0 + + # Rejection Step + # Random numbers between 0 and 1 + unif = np.random.rand(1, MCsize)[0] + + # Reject the poorly performed prior + accepted = (likelihoods/np.max(likelihoods)) >= unif + + # Prior-based estimation of BME + logBME = np.log(np.nanmean(likelihoods)) + + # Posterior-based expectation of likelihoods + postLikelihoods = likelihoods[accepted] + postExpLikelihoods = np.mean(np.log(postLikelihoods)) + + # Posterior-based expectation of prior densities + postExpPrior = np.mean(logPriorLikelihoods[accepted]) + + # Utility function Eq.2 in Ref. (2) + # Posterior covariance matrix after observing data y + # Kullback-Leibler Divergence (Sergey's paper) + if var == 'DKL': + + # TODO: Calculate the correction factor for BME + # BMECorrFactor = self.BME_Corr_Weight(PCE_SparseBayes_can, + # ObservationData, sigma2Dict) + # BME += BMECorrFactor + # Haun et al implementation + # U_J_d = np.mean(np.log(Likelihoods[Likelihoods!=0])- logBME) + U_J_d = postExpLikelihoods - logBME + + # Marginal log likelihood + elif var == 'BME': + U_J_d = logBME + + # Entropy-based information gain + elif var == 'infEntropy': + logBME = np.log(np.nanmean(likelihoods)) + infEntropy = logBME - postExpPrior - postExpLikelihoods + U_J_d = infEntropy * -1 # -1 for minimization + + # Bayesian information criterion + elif var == 'BIC': + coeffs = self.MetaModel.coeffs_dict.values() + nModelParams = max(len(v) for val in coeffs for v in val.values()) + maxL = np.nanmax(likelihoods) + U_J_d = -2 * np.log(maxL) + np.log(n_obs) * nModelParams + + # Akaike information criterion + elif var == 'AIC': + coeffs = self.MetaModel.coeffs_dict.values() + nModelParams = max(len(v) for val in coeffs for v in val.values()) + maxlogL = np.log(np.nanmax(likelihoods)) + AIC = -2 * maxlogL + 2 * nModelParams + # 2 * nModelParams * (nModelParams+1) / (n_obs-nModelParams-1) + penTerm = 0 + U_J_d = 1*(AIC + penTerm) + + # Deviance information criterion + elif var == 'DIC': + # D_theta_bar = np.mean(-2 * Likelihoods) + N_star_p = 0.5 * np.var(np.log(likelihoods[likelihoods != 0])) + Likelihoods_theta_mean = self.__normpdf( + Y_mean_can, Y_std_can, obs_data, sigma2Dict + ) + DIC = -2 * np.log(Likelihoods_theta_mean) + 2 * N_star_p + + U_J_d = DIC + + else: + print('The algorithm you requested has not been implemented yet!') + + # Handle inf and NaN (replace by zero) + if np.isnan(U_J_d) or U_J_d == -np.inf or U_J_d == np.inf: + U_J_d = 0.0 + + # Clear memory + del likelihoods + del Y_MC + del std_MC + gc.collect(generation=2) + + return -1 * U_J_d # -1 is for minimization instead of maximization + + # ------------------------------------------------------------------------- + def update_metamodel(self, MetaModel, output, y_hat_can, univ_p_val, index, + new_pca=False): + BasisIndices = MetaModel.basis_dict[output]["y_"+str(index+1)] + clf_poly = MetaModel.clf_poly[output]["y_"+str(index+1)] + Mn = clf_poly.coef_ + Sn = clf_poly.sigma_ + beta = clf_poly.alpha_ + active = clf_poly.active_ + Psi = self.MetaModel.create_psi(BasisIndices, univ_p_val) + + Sn_new_inv = np.linalg.inv(Sn) + Sn_new_inv += beta * np.dot(Psi[:, active].T, Psi[:, active]) + Sn_new = np.linalg.inv(Sn_new_inv) + + Mn_new = np.dot(Sn_new_inv, Mn[active]).reshape(-1, 1) + Mn_new += beta * np.dot(Psi[:, active].T, y_hat_can) + Mn_new = np.dot(Sn_new, Mn_new).flatten() + + # Compute the old and new moments of PCEs + mean_old = Mn[0] + mean_new = Mn_new[0] + std_old = np.sqrt(np.sum(np.square(Mn[1:]))) + std_new = np.sqrt(np.sum(np.square(Mn_new[1:]))) + + # Back transformation if PCA is selected. + if MetaModel.dim_red_method.lower() == 'pca': + old_pca = MetaModel.pca[output] + mean_old = old_pca.mean_[index] + mean_old += np.sum(mean_old * old_pca.components_[:, index]) + std_old = np.sqrt(np.sum(std_old**2 * + old_pca.components_[:, index]**2)) + mean_new = new_pca.mean_[index] + mean_new += np.sum(mean_new * new_pca.components_[:, index]) + std_new = np.sqrt(np.sum(std_new**2 * + new_pca.components_[:, index]**2)) + # print(f"mean_old: {mean_old:.2f} mean_new: {mean_new:.2f}") + # print(f"std_old: {std_old:.2f} std_new: {std_new:.2f}") + # Store the old and new moments of PCEs + results = { + 'mean_old': mean_old, + 'mean_new': mean_new, + 'std_old': std_old, + 'std_new': std_new + } + return results + + # ------------------------------------------------------------------------- + def util_BayesianDesign_old(self, X_can, X_MC, sigma2Dict, var='DKL'): + """ + Computes scores based on Bayesian sequential design criterion (var). + + Parameters + ---------- + X_can : array of shape (n_samples, n_params) + Candidate samples. + sigma2Dict : dict + A dictionary containing the measurement errors (sigma^2). + var : string, optional + Bayesian design criterion. The default is 'DKL'. + + Returns + ------- + float + Score. + + """ + + # To avoid changes ub original aPCE object + Model = self.Model + MetaModel = deepcopy(self.MetaModel) + old_EDY = MetaModel.ExpDesign.Y + + # Evaluate the PCE metamodels using the candidate design + Y_PC_can, Y_std_can = self.MetaModel.eval_metamodel( + samples=np.array([X_can]) + ) + + # Generate y from posterior predictive + m_size = 100 + y_hat_samples = {} + for idx, key in enumerate(Model.Output.names): + means, stds = Y_PC_can[key][0], Y_std_can[key][0] + y_hat_samples[key] = np.random.multivariate_normal( + means, np.diag(stds), m_size) + + # Create the SparseBayes-based PCE metamodel: + MetaModel.input_obj.poly_coeffs_flag = False + univ_p_val = self.MetaModel.univ_basis_vals(X_can) + G_n_m_all = np.zeros((m_size, len(Model.Output.names), Model.n_obs)) + + for i in range(m_size): + for idx, key in enumerate(Model.Output.names): + if MetaModel.dim_red_method.lower() == 'pca': + # Equal number of components + new_outputs = np.vstack( + (old_EDY[key], y_hat_samples[key][i]) + ) + new_pca, _ = MetaModel.pca_transformation(new_outputs) + target = new_pca.transform( + y_hat_samples[key][i].reshape(1, -1) + )[0] + else: + new_pca, target = False, y_hat_samples[key][i] + + for j in range(len(target)): + + # Update surrogate + result = self.update_metamodel( + MetaModel, key, target[j], univ_p_val, j, new_pca) + + # Compute Expected Information Gain (Eq. 39) + G_n_m = np.log(result['std_old']/result['std_new']) - 1./2 + G_n_m += result['std_new']**2 / (2*result['std_old']**2) + G_n_m += (result['mean_new'] - result['mean_old'])**2 /\ + (2*result['std_old']**2) + + G_n_m_all[i, idx, j] = G_n_m + + U_J_d = G_n_m_all.mean(axis=(1, 2)).mean() + return -1 * U_J_d + + # ------------------------------------------------------------------------- + def util_BayesianDesign(self, X_can, X_MC, sigma2Dict, var='DKL'): + """ + Computes scores based on Bayesian sequential design criterion (var). + + Parameters + ---------- + X_can : array of shape (n_samples, n_params) + Candidate samples. + sigma2Dict : dict + A dictionary containing the measurement errors (sigma^2). + var : string, optional + Bayesian design criterion. The default is 'DKL'. + + Returns + ------- + float + Score. + + """ + + # To avoid changes ub original aPCE object + Model = self.Model + MetaModel = deepcopy(self.MetaModel) + out_names = MetaModel.ModelObj.Output.names + if X_can.ndim == 1: + X_can = X_can.reshape(1, -1) + + # Compute the mean and std based on the MetaModel + # pce_means, pce_stds = self._compute_pce_moments(MetaModel) + if var == 'ALC': + Y_MC, Y_MC_std = MetaModel.eval_metamodel(samples=X_MC) + + # Old Experimental design + oldExpDesignX = MetaModel.ExpDesign.X + oldExpDesignY = MetaModel.ExpDesign.Y + + # Evaluate the PCE metamodels at that location ??? + Y_PC_can, Y_std_can = MetaModel.eval_metamodel(samples=X_can) + + # Add all suggestion as new ExpDesign + NewExpDesignX = np.vstack((oldExpDesignX, X_can)) + + NewExpDesignY = {} + for key in oldExpDesignY.keys(): + try: + NewExpDesignY[key] = np.vstack((oldExpDesignY[key], + Y_PC_can[key])) + except: + NewExpDesignY[key] = oldExpDesignY[key] + + MetaModel.ExpDesign.sampling_method = 'user' + MetaModel.ExpDesign.X = NewExpDesignX + MetaModel.ExpDesign.Y = NewExpDesignY + + # Train the model for the observed data using x_can + MetaModel.input_obj.poly_coeffs_flag = False + MetaModel.train_norm_design(parallel=False) + PCE_Model_can = MetaModel + + if var.lower() == 'mi': + # Mutual information based on Krause et al + # Adapted from Beck & Guillas (MICE) paper + _, std_PC_can = PCE_Model_can.eval_metamodel(samples=X_can) + std_can = {key: std_PC_can[key] for key in out_names} + + std_old = {key: Y_std_can[key] for key in out_names} + + varPCE = np.zeros((len(out_names))) + for i, key in enumerate(out_names): + varPCE[i] = np.mean(std_old[key]**2/std_can[key]**2) + score = np.mean(varPCE) + + return -1 * score + + elif var.lower() == 'alc': + # Active learning based on Gramyc and Lee + # Adaptive design and analysis of supercomputer experiments Techno- + # metrics, 51 (2009), pp. 130–145. + + # Evaluate the MetaModel at the given samples + Y_MC_can, Y_MC_std_can = PCE_Model_can.eval_metamodel(samples=X_MC) + + # Compute the score + score = [] + for i, key in enumerate(out_names): + pce_var = Y_MC_std_can[key]**2 + pce_var_can = Y_MC_std[key]**2 + score.append(np.mean(pce_var-pce_var_can, axis=0)) + score = np.mean(score) + + return -1 * score + + # ---------- Inner MC simulation for computing Utility Value ---------- + # Estimation of the integral via Monte Varlo integration + MCsize = X_MC.shape[0] + ESS = 0 + + while ((ESS > MCsize) or (ESS < 1)): + + # Enriching Monte Carlo samples if need be + if ESS != 0: + X_MC = self.MetaModel.ExpDesign.generate_samples( + MCsize, 'random' + ) + + # Evaluate the MetaModel at the given samples + Y_MC, std_MC = PCE_Model_can.eval_metamodel(samples=X_MC) + + # Likelihood computation (Comparison of data and simulation + # results via PCE with candidate design) + likelihoods = self.__normpdf( + Y_MC, std_MC, self.observations, sigma2Dict + ) + + # Check the Effective Sample Size (1<ESS<MCsize) + ESS = 1 / np.sum(np.square(likelihoods/np.sum(likelihoods))) + + # Enlarge sample size if it doesn't fulfill the criteria + if ((ESS > MCsize) or (ESS < 1)): + print("--- increasing MC size---") + MCsize *= 10 + ESS = 0 + + # Rejection Step + # Random numbers between 0 and 1 + unif = np.random.rand(1, MCsize)[0] + + # Reject the poorly performed prior + accepted = (likelihoods/np.max(likelihoods)) >= unif + + # -------------------- Utility functions -------------------- + # Utility function Eq.2 in Ref. (2) + # Kullback-Leibler Divergence (Sergey's paper) + if var == 'DKL': + + # Prior-based estimation of BME + logBME = np.log(np.nanmean(likelihoods, dtype=np.float128)) + + # Posterior-based expectation of likelihoods + postLikelihoods = likelihoods[accepted] + postExpLikelihoods = np.mean(np.log(postLikelihoods)) + + # Haun et al implementation + U_J_d = np.mean(np.log(likelihoods[likelihoods != 0]) - logBME) + + # U_J_d = np.sum(G_n_m_all) + # Ryan et al (2014) implementation + # importanceWeights = Likelihoods[Likelihoods!=0]/np.sum(Likelihoods[Likelihoods!=0]) + # U_J_d = np.mean(importanceWeights*np.log(Likelihoods[Likelihoods!=0])) - logBME + + # U_J_d = postExpLikelihoods - logBME + + # Marginal likelihood + elif var == 'BME': + + # Prior-based estimation of BME + logBME = np.log(np.nanmean(likelihoods)) + U_J_d = logBME + + # Bayes risk likelihood + elif var == 'BayesRisk': + + U_J_d = -1 * np.var(likelihoods) + + # Entropy-based information gain + elif var == 'infEntropy': + # Prior-based estimation of BME + logBME = np.log(np.nanmean(likelihoods)) + + # Posterior-based expectation of likelihoods + postLikelihoods = likelihoods[accepted] / np.nansum(likelihoods[accepted]) + postExpLikelihoods = np.mean(np.log(postLikelihoods)) + + # Posterior-based expectation of prior densities + postExpPrior = np.mean(logPriorLikelihoods[accepted]) + + infEntropy = logBME - postExpPrior - postExpLikelihoods + + U_J_d = infEntropy * -1 # -1 for minimization + + # D-Posterior-precision + elif var == 'DPP': + X_Posterior = X_MC[accepted] + # covariance of the posterior parameters + U_J_d = -np.log(np.linalg.det(np.cov(X_Posterior))) + + # A-Posterior-precision + elif var == 'APP': + X_Posterior = X_MC[accepted] + # trace of the posterior parameters + U_J_d = -np.log(np.trace(np.cov(X_Posterior))) + + else: + print('The algorithm you requested has not been implemented yet!') + + # Clear memory + del likelihoods + del Y_MC + del std_MC + gc.collect(generation=2) + + return -1 * U_J_d # -1 is for minimization instead of maximization + + # ------------------------------------------------------------------------- + def subdomain(self, Bounds, n_new_samples): + """ + Divides a domain defined by Bounds into sub domains. + + Parameters + ---------- + Bounds : list of tuples + List of lower and upper bounds. + n_new_samples : TYPE + DESCRIPTION. + + Returns + ------- + Subdomains : TYPE + DESCRIPTION. + + """ + n_params = self.MetaModel.n_params + n_subdomains = n_new_samples + 1 + LinSpace = np.zeros((n_params, n_subdomains)) + + for i in range(n_params): + LinSpace[i] = np.linspace(start=Bounds[i][0], stop=Bounds[i][1], + num=n_subdomains) + Subdomains = [] + for k in range(n_subdomains-1): + mylist = [] + for i in range(n_params): + mylist.append((LinSpace[i, k+0], LinSpace[i, k+1])) + Subdomains.append(tuple(mylist)) + + return Subdomains + + # ------------------------------------------------------------------------- + def run_util_func(self, method, candidates, index, sigma2Dict=None, + var=None, X_MC=None): + """ + Runs the utility function based on the given method. + + Parameters + ---------- + method : string + Exploitation method: `VarOptDesign`, `BayesActDesign` and + `BayesOptDesign`. + candidates : array of shape (n_samples, n_params) + All candidate parameter sets. + index : int + ExpDesign index. + sigma2Dict : dict, optional + A dictionary containing the measurement errors (sigma^2). The + default is None. + var : string, optional + Utility function. The default is None. + X_MC : TYPE, optional + DESCRIPTION. The default is None. + + Returns + ------- + index : TYPE + DESCRIPTION. + List + Scores. + + """ + + if method.lower() == 'varoptdesign': + # U_J_d = self.util_VarBasedDesign(candidates, index, var) + U_J_d = np.zeros((candidates.shape[0])) + for idx, X_can in tqdm(enumerate(candidates), ascii=True, + desc="varoptdesign"): + U_J_d[idx] = self.util_VarBasedDesign(X_can, index, var) + + elif method.lower() == 'bayesactdesign': + NCandidate = candidates.shape[0] + U_J_d = np.zeros((NCandidate)) + for idx, X_can in tqdm(enumerate(candidates), ascii=True, + desc="OptBayesianDesign"): + U_J_d[idx] = self.util_BayesianActiveDesign(X_can, sigma2Dict, + var) + elif method.lower() == 'bayesoptdesign': + NCandidate = candidates.shape[0] + U_J_d = np.zeros((NCandidate)) + for idx, X_can in tqdm(enumerate(candidates), ascii=True, + desc="OptBayesianDesign"): + U_J_d[idx] = self.util_BayesianDesign(X_can, X_MC, sigma2Dict, + var) + return (index, -1 * U_J_d) + + # ------------------------------------------------------------------------- + def dual_annealing(self, method, Bounds, sigma2Dict, var, Run_No, + verbose=False): + """ + Exploration algorithim to find the optimum parameter space. + + Parameters + ---------- + method : string + Exploitation method: `VarOptDesign`, `BayesActDesign` and + `BayesOptDesign`. + Bounds : list of tuples + List of lower and upper boundaries of parameters. + sigma2Dict : dict + A dictionary containing the measurement errors (sigma^2). + Run_No : int + Run number. + verbose : bool, optional + Print out a summary. The default is False. + + Returns + ------- + Run_No : int + Run number. + array + Optimial candidate. + + """ + + Model = self.Model + max_func_itr = self.MetaModel.ExpDesign.max_func_itr + + if method == 'VarOptDesign': + Res_Global = opt.dual_annealing(self.util_VarBasedDesign, + bounds=Bounds, + args=(Model, var), + maxfun=max_func_itr) + + elif method == 'BayesOptDesign': + Res_Global = opt.dual_annealing(self.util_BayesianDesign, + bounds=Bounds, + args=(Model, sigma2Dict, var), + maxfun=max_func_itr) + + if verbose: + print(f"global minimum: xmin = {Res_Global.x}, " + f"f(xmin) = {Res_Global.fun:.6f}, nfev = {Res_Global.nfev}") + + return (Run_No, Res_Global.x) + + # ------------------------------------------------------------------------- + def tradoff_weights(self, tradeoff_scheme, old_EDX, old_EDY): + """ + Calculates weights for exploration scores based on the requested + scheme: `None`, `equal`, `epsilon-decreasing` and `adaptive`. + + `None`: No exploration. + `equal`: Same weights for exploration and exploitation scores. + `epsilon-decreasing`: Start with more exploration and increase the + influence of exploitation along the way with a exponential decay + function + `adaptive`: An adaptive method based on: + Liu, Haitao, Jianfei Cai, and Yew-Soon Ong. "An adaptive sampling + approach for Kriging metamodeling by maximizing expected prediction + error." Computers & Chemical Engineering 106 (2017): 171-182. + + Parameters + ---------- + tradeoff_scheme : string + Trade-off scheme for exloration and exploitation scores. + old_EDX : array (n_samples, n_params) + Old experimental design (training points). + old_EDY : dict + Old model responses (targets). + + Returns + ------- + exploration_weight : float + Exploration weight. + exploitation_weight: float + Exploitation weight. + + """ + if tradeoff_scheme is None: + exploration_weight = 0 + + elif tradeoff_scheme == 'equal': + exploration_weight = 0.5 + + elif tradeoff_scheme == 'epsilon-decreasing': + # epsilon-decreasing scheme + # Start with more exploration and increase the influence of + # exploitation along the way with a exponential decay function + initNSamples = self.MetaModel.ExpDesign.n_init_samples + n_max_samples = self.MetaModel.ExpDesign.n_max_samples + + itrNumber = (self.MetaModel.ExpDesign.X.shape[0] - initNSamples) + itrNumber //= self.MetaModel.ExpDesign.n_new_samples + + tau2 = -(n_max_samples-initNSamples-1) / np.log(1e-8) + exploration_weight = signal.exponential(n_max_samples-initNSamples, + 0, tau2, False)[itrNumber] + + elif tradeoff_scheme == 'adaptive': + + # Extract itrNumber + initNSamples = self.MetaModel.ExpDesign.n_init_samples + n_max_samples = self.MetaModel.ExpDesign.n_max_samples + itrNumber = (self.MetaModel.ExpDesign.X.shape[0] - initNSamples) + itrNumber //= self.MetaModel.ExpDesign.n_new_samples + + if itrNumber == 0: + exploration_weight = 0.5 + else: + # New adaptive trade-off according to Liu et al. (2017) + # Mean squared error for last design point + last_EDX = old_EDX[-1].reshape(1, -1) + lastPCEY, _ = self.MetaModel.eval_metamodel(samples=last_EDX) + pce_y = np.array(list(lastPCEY.values()))[:, 0] + y = np.array(list(old_EDY.values()))[:, -1, :] + mseError = mean_squared_error(pce_y, y) + + # Mean squared CV - error for last design point + pce_y_prev = np.array(list(self._y_hat_prev.values()))[:, 0] + mseCVError = mean_squared_error(pce_y_prev, y) + + exploration_weight = min([0.5*mseError/mseCVError, 1]) + + # Exploitation weight + exploitation_weight = 1 - exploration_weight + + return exploration_weight, exploitation_weight + + # ------------------------------------------------------------------------- + def opt_SeqDesign(self, sigma2, n_candidates=5, var='DKL'): + """ + Runs optimal sequential design. + + Parameters + ---------- + sigma2 : dict, optional + A dictionary containing the measurement errors (sigma^2). The + default is None. + n_candidates : int, optional + Number of candidate samples. The default is 5. + var : string, optional + Utility function. The default is None. + + Raises + ------ + NameError + Wrong utility function. + + Returns + ------- + Xnew : array (n_samples, n_params) + Selected new training point(s). + """ + + # Initialization + MetaModel = self.MetaModel + Bounds = MetaModel.bound_tuples + n_new_samples = MetaModel.ExpDesign.n_new_samples + explore_method = MetaModel.ExpDesign.explore_method + exploit_method = MetaModel.ExpDesign.exploit_method + n_cand_groups = MetaModel.ExpDesign.n_cand_groups + tradeoff_scheme = MetaModel.ExpDesign.tradeoff_scheme + + old_EDX = MetaModel.ExpDesign.X + old_EDY = MetaModel.ExpDesign.Y.copy() + ndim = MetaModel.ExpDesign.X.shape[1] + OutputNames = MetaModel.ModelObj.Output.names + + # ----------------------------------------- + # ----------- CUSTOMIZED METHODS ---------- + # ----------------------------------------- + # Utility function exploit_method provided by user + if exploit_method.lower() == 'user': + + Xnew, filteredSamples = MetaModel.ExpDesign.ExploitFunction(self) + + print("\n") + print("\nXnew:\n", Xnew) + + return Xnew, filteredSamples + + # ----------------------------------------- + # ---------- EXPLORATION METHODS ---------- + # ----------------------------------------- + if explore_method == 'dual annealing': + # ------- EXPLORATION: OPTIMIZATION ------- + import time + start_time = time.time() + + # Divide the domain to subdomains + args = [] + subdomains = self.subdomain(Bounds, n_new_samples) + for i in range(n_new_samples): + args.append((exploit_method, subdomains[i], sigma2, var, i)) + + # Multiprocessing + pool = multiprocessing.Pool(multiprocessing.cpu_count()) + + # With Pool.starmap_async() + results = pool.starmap_async(self.dual_annealing, args).get() + + # Close the pool + pool.close() + + Xnew = np.array([results[i][1] for i in range(n_new_samples)]) + + print("\nXnew:\n", Xnew) + + elapsed_time = time.time() - start_time + print("\n") + print(f"elapsed_time: {round(elapsed_time,2)} sec.") + print('-'*20) + + elif explore_method == 'LOOCV': + # ----------------------------------------------------------------- + # TODO: LOOCV model construnction based on Feng et al. (2020) + # 'LOOCV': + # Initilize the ExploitScore array + + # Generate random samples + allCandidates = MetaModel.ExpDesign.generate_samples(n_candidates, + 'random') + + # Construct error model based on LCerror + errorModel = MetaModel.create_ModelError(old_EDX, self.LCerror) + self.errorModel.append(copy(errorModel)) + + # Evaluate the error models for allCandidates + eLCAllCands, _ = errorModel.eval_errormodel(allCandidates) + # Select the maximum as the representative error + eLCAllCands = np.dstack(eLCAllCands.values()) + eLCAllCandidates = np.max(eLCAllCands, axis=1)[:, 0] + + # Normalize the error w.r.t the maximum error + scoreExploration = eLCAllCandidates / np.sum(eLCAllCandidates) + + else: + # ------- EXPLORATION: SPACE-FILLING DESIGN ------- + # Generate candidate samples from Exploration class + explore = Exploration(MetaModel, n_candidates) + explore.w = 100 # * ndim #500 + # Select criterion (mc-intersite-proj-th, mc-intersite-proj) + explore.mc_criterion = 'mc-intersite-proj' + allCandidates, scoreExploration = explore.get_exploration_samples() + + # Temp: ---- Plot all candidates ----- + if ndim == 2: + def plotter(points, allCandidates, Method, + scoreExploration=None): + if Method == 'Voronoi': + from scipy.spatial import Voronoi, voronoi_plot_2d + vor = Voronoi(points) + fig = voronoi_plot_2d(vor) + ax1 = fig.axes[0] + else: + fig = plt.figure() + ax1 = fig.add_subplot(111) + ax1.scatter(points[:, 0], points[:, 1], s=10, c='r', + marker="s", label='Old Design Points') + ax1.scatter(allCandidates[:, 0], allCandidates[:, 1], s=10, + c='b', marker="o", label='Design candidates') + for i in range(points.shape[0]): + txt = 'p'+str(i+1) + ax1.annotate(txt, (points[i, 0], points[i, 1])) + if scoreExploration is not None: + for i in range(allCandidates.shape[0]): + txt = str(round(scoreExploration[i], 5)) + ax1.annotate(txt, (allCandidates[i, 0], + allCandidates[i, 1])) + + plt.xlim(self.bound_tuples[0]) + plt.ylim(self.bound_tuples[1]) + # plt.show() + plt.legend(loc='upper left') + + # ----------------------------------------- + # --------- EXPLOITATION METHODS ---------- + # ----------------------------------------- + if exploit_method == 'BayesOptDesign' or\ + exploit_method == 'BayesActDesign': + + # ------- Calculate Exoploration weight ------- + # Compute exploration weight based on trade off scheme + explore_w, exploit_w = self.tradoff_weights(tradeoff_scheme, + old_EDX, + old_EDY) + print(f"\n Exploration weight={explore_w:0.3f} " + f"Exploitation weight={exploit_w:0.3f}\n") + + # ------- EXPLOITATION: BayesOptDesign & ActiveLearning ------- + if explore_w != 1.0: + + # Create a sample pool for rejection sampling + MCsize = 15000 + X_MC = MetaModel.ExpDesign.generate_samples(MCsize, 'random') + candidates = MetaModel.ExpDesign.generate_samples( + MetaModel.ExpDesign.max_func_itr, 'latin_hypercube') + + # Split the candidates in groups for multiprocessing + split_cand = np.array_split( + candidates, n_cand_groups, axis=0 + ) + + results = Parallel(n_jobs=-1, backend='threading')( + delayed(self.run_util_func)( + exploit_method, split_cand[i], i, sigma2, var, X_MC) + for i in range(n_cand_groups)) + # out = map(self.run_util_func, + # [exploit_method]*n_cand_groups, + # split_cand, + # range(n_cand_groups), + # [sigma2] * n_cand_groups, + # [var] * n_cand_groups, + # [X_MC] * n_cand_groups + # ) + # results = list(out) + + # Retrieve the results and append them + U_J_d = np.concatenate([results[NofE][1] for NofE in + range(n_cand_groups)]) + + # Check if all scores are inf + if np.isinf(U_J_d).all() or np.isnan(U_J_d).all(): + U_J_d = np.ones(len(U_J_d)) + + # Get the expected value (mean) of the Utility score + # for each cell + if explore_method == 'Voronoi': + U_J_d = np.mean(U_J_d.reshape(-1, n_candidates), axis=1) + + # create surrogate model for U_J_d + from sklearn.preprocessing import MinMaxScaler + # Take care of inf entries + good_indices = [i for i, arr in enumerate(U_J_d) + if np.isfinite(arr).all()] + scaler = MinMaxScaler() + X_S = scaler.fit_transform(candidates[good_indices]) + gp = MetaModel.gaussian_process_emulator( + X_S, U_J_d[good_indices], autoSelect=True + ) + U_J_d = gp.predict(scaler.transform(allCandidates)) + + # Normalize U_J_d + norm_U_J_d = U_J_d / np.sum(U_J_d) + print("norm_U_J_d:\n", norm_U_J_d) + else: + norm_U_J_d = np.zeros((len(scoreExploration))) + + # ------- Calculate Total score ------- + # ------- Trade off between EXPLORATION & EXPLOITATION ------- + # Total score + totalScore = exploit_w * norm_U_J_d + totalScore += explore_w * scoreExploration + + # temp: Plot + # dim = self.ExpDesign.X.shape[1] + # if dim == 2: + # plotter(self.ExpDesign.X, allCandidates, explore_method) + + # ------- Select the best candidate ------- + # find an optimal point subset to add to the initial design by + # maximization of the utility score and taking care of NaN values + temp = totalScore.copy() + temp[np.isnan(totalScore)] = -np.inf + sorted_idxtotalScore = np.argsort(temp)[::-1] + bestIdx = sorted_idxtotalScore[:n_new_samples] + + # select the requested number of samples + if explore_method == 'Voronoi': + Xnew = np.zeros((n_new_samples, ndim)) + for i, idx in enumerate(bestIdx): + X_can = explore.closestPoints[idx] + + # Calculate the maxmin score for the region of interest + newSamples, maxminScore = explore.get_mc_samples(X_can) + + # select the requested number of samples + Xnew[i] = newSamples[np.argmax(maxminScore)] + else: + Xnew = allCandidates[sorted_idxtotalScore[:n_new_samples]] + + elif exploit_method == 'VarOptDesign': + # ------- EXPLOITATION: VarOptDesign ------- + UtilMethod = var + + # ------- Calculate Exoploration weight ------- + # Compute exploration weight based on trade off scheme + explore_w, exploit_w = self.tradoff_weights(tradeoff_scheme, + old_EDX, + old_EDY) + print(f"\nweightExploration={explore_w:0.3f} " + f"weightExploitation={exploit_w:0.3f}") + + # Generate candidate samples from Exploration class + nMeasurement = old_EDY[OutputNames[0]].shape[1] + + # Find sensitive region + if UtilMethod == 'LOOCV': + LCerror = MetaModel.LCerror + allModifiedLOO = np.zeros((len(old_EDX), len(OutputNames), + nMeasurement)) + for y_idx, y_key in enumerate(OutputNames): + for idx, key in enumerate(LCerror[y_key].keys()): + allModifiedLOO[:, y_idx, idx] = abs( + LCerror[y_key][key]) + + ExploitScore = np.max(np.max(allModifiedLOO, axis=1), axis=1) + + elif UtilMethod in ['EIGF', 'ALM']: + # ----- All other in ['EIGF', 'ALM'] ----- + # Initilize the ExploitScore array + ExploitScore = np.zeros((len(old_EDX), len(OutputNames))) + + # Split the candidates in groups for multiprocessing + if explore_method != 'Voronoi': + split_cand = np.array_split(allCandidates, + n_cand_groups, + axis=0) + goodSampleIdx = range(n_cand_groups) + else: + # Find indices of the Vornoi cells with samples + goodSampleIdx = [] + for idx in range(len(explore.closest_points)): + if len(explore.closest_points[idx]) != 0: + goodSampleIdx.append(idx) + split_cand = explore.closest_points + + # Split the candidates in groups for multiprocessing + args = [] + for index in goodSampleIdx: + args.append((exploit_method, split_cand[index], index, + sigma2, var)) + + # Multiprocessing + pool = multiprocessing.Pool(multiprocessing.cpu_count()) + # With Pool.starmap_async() + results = pool.starmap_async(self.run_util_func, args).get() + + # Close the pool + pool.close() + # out = map(self.run_util_func, + # [exploit_method]*len(goodSampleIdx), + # split_cand, + # range(len(goodSampleIdx)), + # [sigma2] * len(goodSampleIdx), + # [var] * len(goodSampleIdx) + # ) + # results = list(out) + + # Retrieve the results and append them + if explore_method == 'Voronoi': + ExploitScore = [np.mean(results[k][1]) for k in + range(len(goodSampleIdx))] + else: + ExploitScore = np.concatenate( + [results[k][1] for k in range(len(goodSampleIdx))]) + + else: + raise NameError('The requested utility function is not ' + 'available.') + + # print("ExploitScore:\n", ExploitScore) + + # find an optimal point subset to add to the initial design by + # maximization of the utility score and taking care of NaN values + # Total score + # Normalize U_J_d + ExploitScore = ExploitScore / np.sum(ExploitScore) + totalScore = exploit_w * ExploitScore + totalScore += explore_w * scoreExploration + + temp = totalScore.copy() + sorted_idxtotalScore = np.argsort(temp, axis=0)[::-1] + bestIdx = sorted_idxtotalScore[:n_new_samples] + + Xnew = np.zeros((n_new_samples, ndim)) + if explore_method != 'Voronoi': + Xnew = allCandidates[bestIdx] + else: + for i, idx in enumerate(bestIdx.flatten()): + X_can = explore.closest_points[idx] + # plotter(self.ExpDesign.X, X_can, explore_method, + # scoreExploration=None) + + # Calculate the maxmin score for the region of interest + newSamples, maxminScore = explore.get_mc_samples(X_can) + + # select the requested number of samples + Xnew[i] = newSamples[np.argmax(maxminScore)] + + elif exploit_method == 'alphabetic': + # ------- EXPLOITATION: ALPHABETIC ------- + Xnew = self.util_AlphOptDesign(allCandidates, var) + + elif exploit_method == 'Space-filling': + # ------- EXPLOITATION: SPACE-FILLING ------- + totalScore = scoreExploration + + # ------- Select the best candidate ------- + # find an optimal point subset to add to the initial design by + # maximization of the utility score and taking care of NaN values + temp = totalScore.copy() + temp[np.isnan(totalScore)] = -np.inf + sorted_idxtotalScore = np.argsort(temp)[::-1] + + # select the requested number of samples + Xnew = allCandidates[sorted_idxtotalScore[:n_new_samples]] + + else: + raise NameError('The requested design method is not available.') + + print("\n") + print("\nRun No. {}:".format(old_EDX.shape[0]+1)) + print("Xnew:\n", Xnew) + gc.collect() + + return Xnew, None + + # ------------------------------------------------------------------------- + def util_AlphOptDesign(self, candidates, var='D-Opt'): + """ + Enriches the Experimental design with the requested alphabetic + criterion based on exploring the space with number of sampling points. + + Ref: Hadigol, M., & Doostan, A. (2018). Least squares polynomial chaos + expansion: A review of sampling strategies., Computer Methods in + Applied Mechanics and Engineering, 332, 382-407. + + Arguments + --------- + NCandidate : int + Number of candidate points to be searched + + var : string + Alphabetic optimality criterion + + Returns + ------- + X_new : array of shape (1, n_params) + The new sampling location in the input space. + """ + MetaModelOrig = self + Model = self.Model + n_new_samples = MetaModelOrig.ExpDesign.n_new_samples + NCandidate = candidates.shape[0] + + # TODO: Loop over outputs + OutputName = Model.Output.names[0] + + # To avoid changes ub original aPCE object + MetaModel = deepcopy(MetaModelOrig) + + # Old Experimental design + oldExpDesignX = MetaModel.ExpDesign.X + + # TODO: Only one psi can be selected. + # Suggestion: Go for the one with the highest LOO error + Scores = list(MetaModel.score_dict[OutputName].values()) + ModifiedLOO = [1-score for score in Scores] + outIdx = np.argmax(ModifiedLOO) + + # Initialize Phi to save the criterion's values + Phi = np.zeros((NCandidate)) + + BasisIndices = MetaModelOrig.basis_dict[OutputName]["y_"+str(outIdx+1)] + P = len(BasisIndices) + + # ------ Old Psi ------------ + univ_p_val = MetaModelOrig.univ_basis_vals(oldExpDesignX) + Psi = MetaModelOrig.create_psi(BasisIndices, univ_p_val) + + # ------ New candidates (Psi_c) ------------ + # Assemble Psi_c + univ_p_val_c = self.univ_basis_vals(candidates) + Psi_c = self.create_psi(BasisIndices, univ_p_val_c) + + for idx in range(NCandidate): + + # Include the new row to the original Psi + Psi_cand = np.vstack((Psi, Psi_c[idx])) + + # Information matrix + PsiTPsi = np.dot(Psi_cand.T, Psi_cand) + M = PsiTPsi / (len(oldExpDesignX)+1) + + if np.linalg.cond(PsiTPsi) > 1e-12 \ + and np.linalg.cond(PsiTPsi) < 1 / sys.float_info.epsilon: + # faster + invM = linalg.solve(M, sparse.eye(PsiTPsi.shape[0]).toarray()) + else: + # stabler + invM = np.linalg.pinv(M) + + # ---------- Calculate optimality criterion ---------- + # Optimality criteria according to Section 4.5.1 in Ref. + + # D-Opt + if var == 'D-Opt': + Phi[idx] = (np.linalg.det(invM)) ** (1/P) + + # A-Opt + elif var == 'A-Opt': + Phi[idx] = np.trace(invM) + + # K-Opt + elif var == 'K-Opt': + Phi[idx] = np.linalg.cond(M) + + else: + raise Exception('The optimality criterion you requested has ' + 'not been implemented yet!') + + # find an optimal point subset to add to the initial design + # by minimization of the Phi + sorted_idxtotalScore = np.argsort(Phi) + + # select the requested number of samples + Xnew = candidates[sorted_idxtotalScore[:n_new_samples]] + + return Xnew + + # ------------------------------------------------------------------------- + def __normpdf(self, y_hat_pce, std_pce, obs_data, total_sigma2s, + rmse=None): + + Model = self.Model + likelihoods = 1.0 + + # Loop over the outputs + for idx, out in enumerate(Model.Output.names): + + # (Meta)Model Output + nsamples, nout = y_hat_pce[out].shape + + # Prepare data and remove NaN + try: + data = obs_data[out].values[~np.isnan(obs_data[out])] + except AttributeError: + data = obs_data[out][~np.isnan(obs_data[out])] + + # Prepare sigma2s + non_nan_indices = ~np.isnan(total_sigma2s[out]) + tot_sigma2s = total_sigma2s[out][non_nan_indices][:nout].values + + # Surrogate error if valid dataset is given. + if rmse is not None: + tot_sigma2s += rmse[out]**2 + + likelihoods *= stats.multivariate_normal.pdf( + y_hat_pce[out], data, np.diag(tot_sigma2s), + allow_singular=True) + self.Likelihoods = likelihoods + + return likelihoods + + # ------------------------------------------------------------------------- + def __corr_factor_BME(self, obs_data, total_sigma2s, logBME): + """ + Calculates the correction factor for BMEs. + """ + MetaModel = self.MetaModel + samples = MetaModel.ExpDesign.X # valid_samples + model_outputs = MetaModel.ExpDesign.Y # valid_model_runs + Model = MetaModel.ModelObj + n_samples = samples.shape[0] + + # Extract the requested model outputs for likelihood calulation + output_names = Model.Output.names + + # TODO: Evaluate MetaModel on the experimental design and ValidSet + OutputRS, stdOutputRS = MetaModel.eval_metamodel(samples=samples) + + logLik_data = np.zeros((n_samples)) + logLik_model = np.zeros((n_samples)) + # Loop over the outputs + for idx, out in enumerate(output_names): + + # (Meta)Model Output + nsamples, nout = model_outputs[out].shape + + # Prepare data and remove NaN + try: + data = obs_data[out].values[~np.isnan(obs_data[out])] + except AttributeError: + data = obs_data[out][~np.isnan(obs_data[out])] + + # Prepare sigma2s + non_nan_indices = ~np.isnan(total_sigma2s[out]) + tot_sigma2s = total_sigma2s[out][non_nan_indices][:nout] + + # Covariance Matrix + covMatrix_data = np.diag(tot_sigma2s) + + for i, sample in enumerate(samples): + + # Simulation run + y_m = model_outputs[out][i] + + # Surrogate prediction + y_m_hat = OutputRS[out][i] + + # CovMatrix with the surrogate error + # covMatrix = np.diag(stdOutputRS[out][i]**2) + covMatrix = np.diag((y_m-y_m_hat)**2) + covMatrix = np.diag( + np.mean((model_outputs[out]-OutputRS[out]), axis=0)**2 + ) + + # Compute likelilhood output vs data + logLik_data[i] += self.__logpdf( + y_m_hat, data, covMatrix_data + ) + + # Compute likelilhood output vs surrogate + logLik_model[i] += self.__logpdf(y_m_hat, y_m, covMatrix) + + # Weight + logLik_data -= logBME + weights = np.exp(logLik_model+logLik_data) + + return np.log(np.mean(weights)) + + # ------------------------------------------------------------------------- + def __logpdf(self, x, mean, cov): + """ + computes the likelihood based on a multivariate normal distribution. + + Parameters + ---------- + x : TYPE + DESCRIPTION. + mean : array_like + Observation data. + cov : 2d array + Covariance matrix of the distribution. + + Returns + ------- + log_lik : float + Log likelihood. + + """ + n = len(mean) + L = linalg.cholesky(cov, lower=True) + beta = np.sum(np.log(np.diag(L))) + dev = x - mean + alpha = dev.dot(linalg.cho_solve((L, True), dev)) + log_lik = -0.5 * alpha - beta - n / 2. * np.log(2 * np.pi) + + return log_lik + + # ------------------------------------------------------------------------- + def __posteriorPlot(self, posterior, par_names, key): + + # Initialization + newpath = (r'Outputs_SeqPosteriorComparison/posterior') + os.makedirs(newpath, exist_ok=True) + + bound_tuples = self.MetaModel.bound_tuples + n_params = len(par_names) + font_size = 40 + if n_params == 2: + + figPosterior, ax = plt.subplots(figsize=(15, 15)) + + sns.kdeplot(x=posterior[:, 0], y=posterior[:, 1], + fill=True, ax=ax, cmap=plt.cm.jet, + clip=bound_tuples) + # Axis labels + plt.xlabel(par_names[0], fontsize=font_size) + plt.ylabel(par_names[1], fontsize=font_size) + + # Set axis limit + plt.xlim(bound_tuples[0]) + plt.ylim(bound_tuples[1]) + + # Increase font size + plt.xticks(fontsize=font_size) + plt.yticks(fontsize=font_size) + + # Switch off the grids + plt.grid(False) + + else: + import corner + figPosterior = corner.corner(posterior, labels=par_names, + title_fmt='.2e', show_titles=True, + title_kwargs={"fontsize": 12}) + + figPosterior.savefig(f'./{newpath}/{key}.pdf', bbox_inches='tight') + plt.close() + + # Save the posterior as .npy + np.save(f'./{newpath}/{key}.npy', posterior) + + return figPosterior + + # ------------------------------------------------------------------------- + def __hellinger_distance(self, P, Q): + """ + Hellinger distance between two continuous distributions. + + The maximum distance 1 is achieved when P assigns probability zero to + every set to which Q assigns a positive probability, and vice versa. + 0 (identical) and 1 (maximally different) + + Parameters + ---------- + P : array + Reference likelihood. + Q : array + Estimated likelihood. + + Returns + ------- + float + Hellinger distance of two distributions. + + """ + mu1 = P.mean() + Sigma1 = np.std(P) + + mu2 = Q.mean() + Sigma2 = np.std(Q) + + term1 = np.sqrt(2*Sigma1*Sigma2 / (Sigma1**2 + Sigma2**2)) + + term2 = np.exp(-.25 * (mu1 - mu2)**2 / (Sigma1**2 + Sigma2**2)) + + H_squared = 1 - term1 * term2 + + return np.sqrt(H_squared) + + # ------------------------------------------------------------------------- + def __BME_Calculator(self, MetaModel, obs_data, sigma2Dict, rmse=None): + """ + This function computes the Bayesian model evidence (BME) via Monte + Carlo integration. + + """ + # Initializations + valid_likelihoods = MetaModel.valid_likelihoods + + post_snapshot = MetaModel.ExpDesign.post_snapshot + if post_snapshot or len(valid_likelihoods) != 0: + newpath = (r'Outputs_SeqPosteriorComparison/likelihood_vs_ref') + os.makedirs(newpath, exist_ok=True) + + SamplingMethod = 'random' + MCsize = 10000 + ESS = 0 + + # Estimation of the integral via Monte Varlo integration + while (ESS > MCsize) or (ESS < 1): + + # Generate samples for Monte Carlo simulation + X_MC = MetaModel.ExpDesign.generate_samples( + MCsize, SamplingMethod + ) + + # Monte Carlo simulation for the candidate design + m_1 = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024 + Y_MC, std_MC = MetaModel.eval_metamodel(samples=X_MC) + m_2 = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024 + print(f"\nMemory eval_metamodel in BME: {m_2-m_1:.2f} MB") + + # Likelihood computation (Comparison of data and + # simulation results via PCE with candidate design) + Likelihoods = self.__normpdf( + Y_MC, std_MC, obs_data, sigma2Dict, rmse + ) + + # Check the Effective Sample Size (1000<ESS<MCsize) + ESS = 1 / np.sum(np.square(Likelihoods/np.sum(Likelihoods))) + + # Enlarge sample size if it doesn't fulfill the criteria + if (ESS > MCsize) or (ESS < 1): + print(f'ESS={ESS} MC size should be larger.') + MCsize *= 10 + ESS = 0 + + # Rejection Step + # Random numbers between 0 and 1 + unif = np.random.rand(1, MCsize)[0] + + # Reject the poorly performed prior + accepted = (Likelihoods/np.max(Likelihoods)) >= unif + X_Posterior = X_MC[accepted] + + # ------------------------------------------------------------ + # --- Kullback-Leibler Divergence & Information Entropy ------ + # ------------------------------------------------------------ + # Prior-based estimation of BME + logBME = np.log(np.nanmean(Likelihoods)) + + # TODO: Correction factor + # log_weight = self.__corr_factor_BME(obs_data, sigma2Dict, logBME) + + # Posterior-based expectation of likelihoods + postExpLikelihoods = np.mean(np.log(Likelihoods[accepted])) + + # Posterior-based expectation of prior densities + postExpPrior = np.mean( + np.log(MetaModel.ExpDesign.JDist.pdf(X_Posterior.T)) + ) + + # Calculate Kullback-Leibler Divergence + # KLD = np.mean(np.log(Likelihoods[Likelihoods!=0])- logBME) + KLD = postExpLikelihoods - logBME + + # Information Entropy based on Entropy paper Eq. 38 + infEntropy = logBME - postExpPrior - postExpLikelihoods + + # If post_snapshot is True, plot likelihood vs refrence + if post_snapshot or len(valid_likelihoods) != 0: + # Hellinger distance + ref_like = np.log(valid_likelihoods[valid_likelihoods > 0]) + est_like = np.log(Likelihoods[Likelihoods > 0]) + distHellinger = self.__hellinger_distance(ref_like, est_like) + + idx = len([name for name in os.listdir(newpath) if 'Likelihoods_' + in name and os.path.isfile(os.path.join(newpath, name))]) + fig, ax = plt.subplots() + try: + sns.kdeplot(np.log(valid_likelihoods[valid_likelihoods > 0]), + shade=True, color="g", label='Ref. Likelihood') + sns.kdeplot(np.log(Likelihoods[Likelihoods > 0]), shade=True, + color="b", label='Likelihood with PCE') + except: + pass + + text = f"Hellinger Dist.={distHellinger:.3f}\n logBME={logBME:.3f}" + "\n DKL={KLD:.3f}" + + plt.text(0.05, 0.75, text, bbox=dict(facecolor='wheat', + edgecolor='black', + boxstyle='round,pad=1'), + transform=ax.transAxes) + + fig.savefig(f'./{newpath}/Likelihoods_{idx}.pdf', + bbox_inches='tight') + plt.close() + + else: + distHellinger = 0.0 + + # Bayesian inference with Emulator only for 2D problem + if post_snapshot and MetaModel.n_params == 2 and not idx % 5: + from bayes_inference.bayes_inference import BayesInference + from bayes_inference.discrepancy import Discrepancy + import pandas as pd + BayesOpts = BayesInference(MetaModel) + BayesOpts.emulator = True + BayesOpts.plot_post_pred = False + + # Select the inference method + import emcee + BayesOpts.inference_method = "MCMC" + # Set the MCMC parameters passed to self.mcmc_params + BayesOpts.mcmc_params = { + 'n_steps': 1e5, + 'n_walkers': 30, + 'moves': emcee.moves.KDEMove(), + 'verbose': False + } + + # ----- Define the discrepancy model ------- + obs_data = pd.DataFrame(obs_data, columns=self.Model.Output.names) + BayesOpts.measurement_error = obs_data + + # # -- (Option B) -- + DiscrepancyOpts = Discrepancy('') + DiscrepancyOpts.type = 'Gaussian' + DiscrepancyOpts.parameters = obs_data**2 + BayesOpts.Discrepancy = DiscrepancyOpts + # Start the calibration/inference + Bayes_PCE = BayesOpts.create_inference() + X_Posterior = Bayes_PCE.posterior_df.values + + # Clean up + del Y_MC, std_MC + gc.collect() + + return (logBME, KLD, X_Posterior, Likelihoods, distHellinger) + + # ------------------------------------------------------------------------- + def __validError(self, MetaModel): + + # MetaModel = self.MetaModel + Model = MetaModel.ModelObj + OutputName = Model.Output.names + + # Extract the original model with the generated samples + valid_samples = MetaModel.valid_samples + valid_model_runs = MetaModel.valid_model_runs + + # Run the PCE model with the generated samples + m_1 = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024 + valid_PCE_runs, valid_PCE_std = MetaModel.eval_metamodel(samples=valid_samples) + m_2 = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024 + print(f"\nMemory eval_metamodel: {m_2-m_1:.2f} MB") + + rms_error = {} + valid_error = {} + # Loop over the keys and compute RMSE error. + for key in OutputName: + rms_error[key] = mean_squared_error( + valid_model_runs[key], valid_PCE_runs[key], + multioutput='raw_values', + sample_weight=None, + squared=False) + + # Validation error + valid_error[key] = (rms_error[key]**2) + valid_error[key] /= np.var(valid_model_runs[key], ddof=1, axis=0) + + # Print a report table + print("\n>>>>> Updated Errors of {} <<<<<".format(key)) + print("\nIndex | RMSE | Validation Error") + print('-'*35) + print('\n'.join(f'{i+1} | {k:.3e} | {j:.3e}' for i, (k, j) + in enumerate(zip(rms_error[key], + valid_error[key])))) + + return rms_error, valid_error + + # ------------------------------------------------------------------------- + def __error_Mean_Std(self): + + MetaModel = self.MetaModel + # Extract the mean and std provided by user + df_MCReference = MetaModel.ModelObj.mc_reference + + # Compute the mean and std based on the MetaModel + pce_means, pce_stds = self._compute_pce_moments(MetaModel) + + # Compute the root mean squared error + for output in MetaModel.ModelObj.Output.names: + + # Compute the error between mean and std of MetaModel and OrigModel + RMSE_Mean = mean_squared_error( + df_MCReference['mean'], pce_means[output], squared=False + ) + RMSE_std = mean_squared_error( + df_MCReference['std'], pce_means[output], squared=False + ) + + return RMSE_Mean, RMSE_std + + # ------------------------------------------------------------------------- + def _compute_pce_moments(self, MetaModel): + """ + Computes the first two moments using the PCE-based meta-model. + + Returns + ------- + pce_means: dict + The first moment (mean) of the surrogate. + pce_stds: dict + The second moment (standard deviation) of the surrogate. + + """ + outputs = MetaModel.ModelObj.Output.names + pce_means_b = {} + pce_stds_b = {} + + # Loop over bootstrap iterations + for b_i in range(MetaModel.n_bootstrap_itrs): + # Loop over the metamodels + coeffs_dicts = MetaModel.coeffs_dict[f'b_{b_i+1}'].items() + means = {} + stds = {} + for output, coef_dict in coeffs_dicts: + + pce_mean = np.zeros((len(coef_dict))) + pce_var = np.zeros((len(coef_dict))) + + for index, values in coef_dict.items(): + idx = int(index.split('_')[1]) - 1 + coeffs = MetaModel.coeffs_dict[f'b_{b_i+1}'][output][index] + + # Mean = c_0 + if coeffs[0] != 0: + pce_mean[idx] = coeffs[0] + else: + clf_poly = MetaModel.clf_poly[f'b_{b_i+1}'][output] + pce_mean[idx] = clf_poly[index].intercept_ + # Var = sum(coeffs[1:]**2) + pce_var[idx] = np.sum(np.square(coeffs[1:])) + + # Save predictions for each output + if MetaModel.dim_red_method.lower() == 'pca': + PCA = MetaModel.pca[f'b_{b_i+1}'][output] + means[output] = PCA.mean_ + np.dot( + pce_mean, PCA.components_) + stds[output] = np.sqrt(np.dot(pce_var, + PCA.components_**2)) + else: + means[output] = pce_mean + stds[output] = np.sqrt(pce_var) + + # Save predictions for each bootstrap iteration + pce_means_b[b_i] = means + pce_stds_b[b_i] = stds + + # Change the order of nesting + mean_all = {} + for i in sorted(pce_means_b): + for k, v in pce_means_b[i].items(): + if k not in mean_all: + mean_all[k] = [None] * len(pce_means_b) + mean_all[k][i] = v + std_all = {} + for i in sorted(pce_stds_b): + for k, v in pce_stds_b[i].items(): + if k not in std_all: + std_all[k] = [None] * len(pce_stds_b) + std_all[k][i] = v + + # Back transformation if PCA is selected. + pce_means, pce_stds = {}, {} + for output in outputs: + pce_means[output] = np.mean(mean_all[output], axis=0) + pce_stds[output] = np.mean(std_all[output], axis=0) + + return pce_means, pce_stds diff --git a/examples/analytical-function/bayesvalidrox/surrogate_models/surrogate_models.py b/examples/analytical-function/bayesvalidrox/surrogate_models/surrogate_models.py new file mode 100644 index 000000000..e318dfc32 --- /dev/null +++ b/examples/analytical-function/bayesvalidrox/surrogate_models/surrogate_models.py @@ -0,0 +1,1581 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Implementation of metamodel as either PC, aPC or GPE +""" + +import warnings +import numpy as np +import math +import h5py +import matplotlib.pyplot as plt +from sklearn.preprocessing import MinMaxScaler +import scipy as sp +from scipy.optimize import minimize, NonlinearConstraint, LinearConstraint +from tqdm import tqdm +from sklearn.decomposition import PCA as sklearnPCA +import sklearn.linear_model as lm +from sklearn.gaussian_process import GaussianProcessRegressor +import sklearn.gaussian_process.kernels as kernels +import os +from joblib import Parallel, delayed +import copy + +from .input_space import InputSpace +from .glexindex import glexindex +from .eval_rec_rule import eval_univ_basis +from .reg_fast_ard import RegressionFastARD +from .reg_fast_laplace import RegressionFastLaplace +from .orthogonal_matching_pursuit import OrthogonalMatchingPursuit +from .bayes_linear import VBLinearRegression, EBLinearRegression +from .apoly_construction import apoly_construction +warnings.filterwarnings("ignore") +# Load the mplstyle +plt.style.use(os.path.join(os.path.split(__file__)[0], + '../', 'bayesvalidrox.mplstyle')) + + +class MetaModel(): + """ + Meta (surrogate) model + + This class trains a surrogate model. It accepts an input object (input_obj) + containing the specification of the distributions for uncertain parameters + and a model object with instructions on how to run the computational model. + + Attributes + ---------- + input_obj : obj + Input object with the information on the model input parameters. + meta_model_type : str + Surrogate model types. Three surrogate model types are supported: + polynomial chaos expansion (`PCE`), arbitrary PCE (`aPCE`) and + Gaussian process regression (`GPE`). Default is PCE. + pce_reg_method : str + PCE regression method to compute the coefficients. The following + regression methods are available: + + 1. OLS: Ordinary Least Square method + 2. BRR: Bayesian Ridge Regression + 3. LARS: Least angle regression + 4. ARD: Bayesian ARD Regression + 5. FastARD: Fast Bayesian ARD Regression + 6. VBL: Variational Bayesian Learning + 7. EBL: Emperical Bayesian Learning + Default is `OLS`. + bootstrap_method : str + Bootstraping method. Options are `'normal'` and `'fast'`. The default + is `'fast'`. It means that in each iteration except the first one, only + the coefficent are recalculated with the ordinary least square method. + n_bootstrap_itrs : int + Number of iterations for the bootstrap sampling. The default is `1`. + pce_deg : int or list of int + Polynomial degree(s). If a list is given, an adaptive algorithm is used + to find the best degree with the lowest Leave-One-Out cross-validation + (LOO) error (or the highest score=1-LOO). Default is `1`. + pce_q_norm : float + Hyperbolic (or q-norm) truncation for multi-indices of multivariate + polynomials. Default is `1.0`. + dim_red_method : str + Dimensionality reduction method for the output space. The available + method is based on principal component analysis (PCA). The Default is + `'no'`. There are two ways to select number of components: use + percentage of the explainable variance threshold (between 0 and 100) + (Option A) or direct prescription of components' number (Option B): + + >>> MetaModelOpts.dim_red_method = 'PCA' + >>> MetaModelOpts.var_pca_threshold = 99.999 # Option A + >>> MetaModelOpts.n_pca_components = 12 # Option B + apply_constraints : bool + If set to true constraints will be applied during training. + In this case the training uses OLS. In this version the constraints + need to be set explicitly in this class. + + verbose : bool + Prints summary of the regression results. Default is `False`. + + Note + ------- + To define the sampling methods and the training set, an experimental design + instance shall be defined. This can be done by: + + >>> MetaModelOpts.add_InputSpace() + + Two experimental design schemes are supported: one-shot (`normal`) and + adaptive sequential (`sequential`) designs. + For experimental design refer to `InputSpace`. + + """ + + def __init__(self, input_obj, meta_model_type='PCE', + pce_reg_method='OLS', bootstrap_method='fast', + n_bootstrap_itrs=1, pce_deg=1, pce_q_norm=1.0, + dim_red_method='no', apply_constraints = False, + verbose=False): + + self.input_obj = input_obj + self.meta_model_type = meta_model_type + self.pce_reg_method = pce_reg_method + self.bootstrap_method = bootstrap_method + self.n_bootstrap_itrs = n_bootstrap_itrs + self.pce_deg = pce_deg + self.pce_q_norm = pce_q_norm + self.dim_red_method = dim_red_method + self.apply_constraints = apply_constraints + self.verbose = verbose + + def build_metamodel(self, n_init_samples = None) -> None: + """ + Builds the parts for the metamodel (polynomes,...) that are neede before fitting. + + Returns + ------- + None + DESCRIPTION. + + """ + + # Generate general warnings + if self.apply_constraints or self.pce_reg_method.lower() == 'ols': + print('There are no estimations of surrogate uncertainty available' + ' for the chosen regression options. This might lead to issues' + ' in later steps.') + + # Add InputSpace to MetaModel if it does not have any + if not hasattr(self, 'InputSpace'): + self.InputSpace = InputSpace(self.input_obj) + self.InputSpace.n_init_samples = n_init_samples + self.InputSpace.init_param_space(np.max(self.pce_deg)) + + self.ndim = self.InputSpace.ndim + + if not hasattr(self, 'CollocationPoints'): + raise AttributeError('Please provide samples to the metamodel before building it.') + + # Transform input samples + # TODO: this is probably not yet correct! Make 'method' variable + self.CollocationPoints = self.InputSpace.transform(self.CollocationPoints, method='user') + + + self.n_params = len(self.input_obj.Marginals) + + # Generate polynomials + if self.meta_model_type.lower() != 'gpe': + self.generate_polynomials(np.max(self.pce_deg)) + + # Initialize the nested dictionaries + if self.meta_model_type.lower() == 'gpe': + self.gp_poly = self.auto_vivification() + self.x_scaler = self.auto_vivification() + self.LCerror = self.auto_vivification() + else: + self.deg_dict = self.auto_vivification() + self.q_norm_dict = self.auto_vivification() + self.coeffs_dict = self.auto_vivification() + self.basis_dict = self.auto_vivification() + self.score_dict = self.auto_vivification() + self.clf_poly = self.auto_vivification() + self.LCerror = self.auto_vivification() + if self.dim_red_method.lower() == 'pca': + self.pca = self.auto_vivification() + + # Define an array containing the degrees + self.CollocationPoints = np.array(self.CollocationPoints) + self.n_samples, ndim = self.CollocationPoints.shape + if self.ndim != ndim: + raise AttributeError('The given samples do not match the given number of priors. The samples should be a 2D array of size (#samples, #priors)') + + self.deg_array = self.__select_degree(ndim, self.n_samples) + + # Generate all basis indices + self.allBasisIndices = self.auto_vivification() + for deg in self.deg_array: + keys = self.allBasisIndices.keys() + if deg not in np.fromiter(keys, dtype=float): + # Generate the polynomial basis indices + for qidx, q in enumerate(self.pce_q_norm): + basis_indices = glexindex(start=0, stop=deg+1, + dimensions=self.n_params, + cross_truncation=q, + reverse=False, graded=True) + self.allBasisIndices[str(deg)][str(q)] = basis_indices + + + + def fit(self, X, y, parallel = True, verbose = False): + """ + Fits the surrogate to the given data (samples X, outputs y). + Note here that the samples X should be the transformed samples provided + by the experimental design if the transformation is used there. + + Parameters + ---------- + X : 2D list or np.array of shape (#samples, #dim) + The parameter value combinations that the model was evaluated at. + y : dict of 2D lists or arrays of shape (#samples, #timesteps) + The respective model evaluations. + + Returns + ------- + None. + + """ +# print(X) +# print(X.shape) +# print(y) +# print(y['Z'].shape) + X = np.array(X) + for key in y.keys(): + y_val = np.array(y[key]) + if y_val.ndim !=2: + raise ValueError('The given outputs y should be 2D') + y[key] = np.array(y[key]) + + # Output names are the same as the keys in y + self.out_names = list(y.keys()) + + # Build the MetaModel on the static samples + self.CollocationPoints = X + + # TODO: other option: rebuild every time + if not hasattr(self, 'deg_array'): + self.build_metamodel(n_init_samples = X.shape[1]) + + # Evaluate the univariate polynomials on InputSpace + if self.meta_model_type.lower() != 'gpe': + self.univ_p_val = self.univ_basis_vals(self.CollocationPoints) + + # --- Loop through data points and fit the surrogate --- + if verbose: + print(f"\n>>>> Training the {self.meta_model_type} metamodel " + "started. <<<<<<\n") + + # --- Bootstrap sampling --- + # Correct number of bootstrap if PCA transformation is required. + if self.dim_red_method.lower() == 'pca' and self.n_bootstrap_itrs == 1: + self.n_bootstrap_itrs = 100 + + # Check if fast version (update coeffs with OLS) is selected. + if self.bootstrap_method.lower() == 'fast': + fast_bootstrap = True + first_out = {} + n_comp_dict = {} + else: + fast_bootstrap = False + + # Prepare tqdm iteration maessage + if verbose and self.n_bootstrap_itrs > 1: + enum_obj = tqdm(range(self.n_bootstrap_itrs), + total=self.n_bootstrap_itrs, + desc="Bootstrapping the metamodel", + ascii=True) + else: + enum_obj = range(self.n_bootstrap_itrs) + + # Loop over the bootstrap iterations + for b_i in enum_obj: + if b_i > 0: + b_indices = np.random.randint(self.n_samples, size=self.n_samples) + else: + b_indices = np.arange(len(X)) + + X_train_b = X[b_indices] + + if verbose and self.n_bootstrap_itrs == 1: + items = tqdm(y.items(), desc="Fitting regression") + else: + items = y.items() + + # For loop over the components/outputs + for key, Output in items: + + # Dimensionality reduction with PCA, if specified + if self.dim_red_method.lower() == 'pca': + + # Use the stored n_comp for fast bootsrtrapping + if fast_bootstrap and b_i > 0: + self.n_pca_components = n_comp_dict[key] + + # Start transformation + pca, target, n_comp = self.pca_transformation( + Output[b_indices], verbose=False + ) + self.pca[f'b_{b_i+1}'][key] = pca + # Store the number of components for fast bootsrtrapping + if fast_bootstrap and b_i == 0: + n_comp_dict[key] = n_comp + else: + #print(b_indices) + target = Output[b_indices] + + # Parallel fit regression + if self.meta_model_type.lower() == 'gpe': + # Prepare the input matrix + scaler = MinMaxScaler() + X_S = scaler.fit_transform(X_train_b) + + self.x_scaler[f'b_{b_i+1}'][key] = scaler + if parallel: + out = Parallel(n_jobs=-1, backend='multiprocessing')( + delayed(self.gaussian_process_emulator)( + X_S, target[:, idx]) for idx in + range(target.shape[1])) + else: + results = map(self.gaussian_process_emulator, + [X_train_b]*target.shape[1], + [target[:, idx] for idx in + range(target.shape[1])] + ) + out = list(results) + + for idx in range(target.shape[1]): + self.gp_poly[f'b_{b_i+1}'][key][f"y_{idx+1}"] = out[idx] + + else: + self.univ_p_val = self.univ_p_val[b_indices] + if parallel and (not fast_bootstrap or b_i == 0): + out = Parallel(n_jobs=-1, backend='multiprocessing')( + delayed(self.adaptive_regression)(X_train_b, + target[:, idx], + idx) + for idx in range(target.shape[1])) + elif not parallel and (not fast_bootstrap or b_i == 0): + results = map(self.adaptive_regression, + [X_train_b]*target.shape[1], + [target[:, idx] for idx in + range(target.shape[1])], + range(target.shape[1])) + out = list(results) + + # Store the first out dictionary + if fast_bootstrap and b_i == 0: + first_out[key] = copy.deepcopy(out) + + if b_i > 0 and fast_bootstrap: + + # fast bootstrap + out = self.update_pce_coeffs( + X_train_b, target, first_out[key]) + + for i in range(target.shape[1]): + # Create a dict to pass the variables + self.deg_dict[f'b_{b_i+1}'][key][f"y_{i+1}"] = out[i]['degree'] + self.q_norm_dict[f'b_{b_i+1}'][key][f"y_{i+1}"] = out[i]['qnorm'] + self.coeffs_dict[f'b_{b_i+1}'][key][f"y_{i+1}"] = out[i]['coeffs'] + self.basis_dict[f'b_{b_i+1}'][key][f"y_{i+1}"] = out[i]['multi_indices'] + self.score_dict[f'b_{b_i+1}'][key][f"y_{i+1}"] = out[i]['LOOCVScore'] + self.clf_poly[f'b_{b_i+1}'][key][f"y_{i+1}"] = out[i]['clf_poly'] + #self.LCerror[f'b_{b_i+1}'][key][f"y_{i+1}"] = out[i]['LCerror'] + + if verbose: + print(f"\n>>>> Training the {self.meta_model_type} metamodel" + " sucessfully completed. <<<<<<\n") + + # ------------------------------------------------------------------------- + def update_pce_coeffs(self, X, y, out_dict = None): + """ + Updates the PCE coefficents using only the ordinary least square method + for the fast version of the bootstrapping. + + Parameters + ---------- + X : array of shape (n_samples, n_params) + Training set. + y : array of shape (n_samples, n_outs) + The (transformed) model responses. + out_dict : dict + The training output dictionary of the first iteration, i.e. + the surrogate model for the original experimental design. + + Returns + ------- + final_out_dict : dict + The updated training output dictionary. + + """ + # Make a copy + final_out_dict = copy.deepcopy(out_dict) + + # Loop over the points + for i in range(y.shape[1]): + + + # Extract nonzero basis indices + nnz_idx = np.nonzero(out_dict[i]['coeffs'])[0] + if len(nnz_idx) != 0: + basis_indices = out_dict[i]['multi_indices'] + + # Evaluate the multivariate polynomials on CollocationPoints + psi = self.create_psi(basis_indices, self.univ_p_val) + + # Calulate the cofficients of surrogate model + updated_out = self.regression( + psi, y[:, i], basis_indices, reg_method='OLS', + sparsity=False + ) + + # Update coeffs in out_dict + final_out_dict[i]['coeffs'][nnz_idx] = updated_out['coeffs'] + + return final_out_dict + + # ------------------------------------------------------------------------- + def add_InputSpace(self): + """ + Instanciates experimental design object. + + Returns + ------- + None. + + """ + self.InputSpace = InputSpace(self.input_obj, + meta_Model_type=self.meta_model_type) + + # ------------------------------------------------------------------------- + def univ_basis_vals(self, samples, n_max=None): + """ + Evaluates univariate regressors along input directions. + + Parameters + ---------- + samples : array of shape (n_samples, n_params) + Samples. + n_max : int, optional + Maximum polynomial degree. The default is `None`. + + Returns + ------- + univ_basis: array of shape (n_samples, n_params, n_max+1) + All univariate regressors up to n_max. + """ + # Extract information + poly_types = self.InputSpace.poly_types + if samples.ndim != 2: + samples = samples.reshape(1, len(samples)) + n_max = np.max(self.pce_deg) if n_max is None else n_max + + # Extract poly coeffs + if self.InputSpace.input_data_given or self.InputSpace.apce: + apolycoeffs = self.polycoeffs + else: + apolycoeffs = None + + # Evaluate univariate basis + univ_basis = eval_univ_basis(samples, n_max, poly_types, apolycoeffs) + + return univ_basis + + # ------------------------------------------------------------------------- + def create_psi(self, basis_indices, univ_p_val): + """ + This function assemble the design matrix Psi from the given basis index + set INDICES and the univariate polynomial evaluations univ_p_val. + + Parameters + ---------- + basis_indices : array of shape (n_terms, n_params) + Multi-indices of multivariate polynomials. + univ_p_val : array of (n_samples, n_params, n_max+1) + All univariate regressors up to `n_max`. + + Raises + ------ + ValueError + n_terms in arguments do not match. + + Returns + ------- + psi : array of shape (n_samples, n_terms) + Multivariate regressors. + + """ + # Check if BasisIndices is a sparse matrix + sparsity = sp.sparse.issparse(basis_indices) + if sparsity: + basis_indices = basis_indices.toarray() + + # Initialization and consistency checks + # number of input variables + n_params = univ_p_val.shape[1] + + # Size of the experimental design + n_samples = univ_p_val.shape[0] + + # number of basis terms + n_terms = basis_indices.shape[0] + + # check that the variables have consistent sizes + if n_params != basis_indices.shape[1]: + raise ValueError( + f"The shapes of basis_indices ({basis_indices.shape[1]}) and " + f"univ_p_val ({n_params}) don't match!!" + ) + + # Preallocate the Psi matrix for performance + psi = np.ones((n_samples, n_terms)) + # Assemble the Psi matrix + for m in range(basis_indices.shape[1]): + aa = np.where(basis_indices[:, m] > 0)[0] + try: + basisIdx = basis_indices[aa, m] + bb = univ_p_val[:, m, basisIdx].reshape(psi[:, aa].shape) + psi[:, aa] = np.multiply(psi[:, aa], bb) + except ValueError as err: + raise err + return psi + + # ------------------------------------------------------------------------- + def regression(self, X, y, basis_indices, reg_method=None, sparsity=True): + """ + Fit regression using the regression method provided. + + Parameters + ---------- + X : array of shape (n_samples, n_features) + Training vector, where n_samples is the number of samples and + n_features is the number of features. + y : array of shape (n_samples,) + Target values. + basis_indices : array of shape (n_terms, n_params) + Multi-indices of multivariate polynomials. + reg_method : str, optional + DESCRIPTION. The default is None. + + Returns + ------- + return_out_dict : Dict + Fitted estimator, spareMulti-Index, sparseX and coefficients. + + """ + if reg_method is None: + reg_method = self.pce_reg_method + + bias_term = self.dim_red_method.lower() != 'pca' + + compute_score = True if self.verbose else False + + # inverse of the observed variance of the data + if np.var(y) != 0: + Lambda = 1 / np.var(y) + else: + Lambda = 1e-6 + + # Bayes sparse adaptive aPCE + if reg_method.lower() == 'ols': + clf_poly = lm.LinearRegression(fit_intercept=False) + elif reg_method.lower() == 'brr': + clf_poly = lm.BayesianRidge(n_iter=1000, tol=1e-7, + fit_intercept=False, + #normalize=True, + compute_score=compute_score, + alpha_1=1e-04, alpha_2=1e-04, + lambda_1=Lambda, lambda_2=Lambda) + clf_poly.converged = True + + elif reg_method.lower() == 'ard': + if X.shape[0]<2: + raise ValueError('Regression with ARD can only be performed for more than 2 samples') + clf_poly = lm.ARDRegression(fit_intercept=False, + #normalize=True, + compute_score=compute_score, + n_iter=1000, tol=0.0001, + alpha_1=1e-3, alpha_2=1e-3, + lambda_1=Lambda, lambda_2=Lambda) + + elif reg_method.lower() == 'fastard': + clf_poly = RegressionFastARD(fit_intercept=False, + normalize=True, + compute_score=compute_score, + n_iter=300, tol=1e-10) + + elif reg_method.lower() == 'bcs': + if X.shape[0]<10: + raise ValueError('Regression with BCS can only be performed for more than 10 samples') + clf_poly = RegressionFastLaplace(fit_intercept=False, + bias_term=bias_term, + n_iter=1000, tol=1e-7) + + elif reg_method.lower() == 'lars': + if X.shape[0]<10: + raise ValueError('Regression with LARS can only be performed for more than 5 samples') + clf_poly = lm.LassoLarsCV(fit_intercept=False) + + elif reg_method.lower() == 'sgdr': + clf_poly = lm.SGDRegressor(fit_intercept=False, + max_iter=5000, tol=1e-7) + + elif reg_method.lower() == 'omp': + clf_poly = OrthogonalMatchingPursuit(fit_intercept=False) + + elif reg_method.lower() == 'vbl': + clf_poly = VBLinearRegression(fit_intercept=False) + + elif reg_method.lower() == 'ebl': + clf_poly = EBLinearRegression(optimizer='em') + + + # Training with constraints automatically uses L2 + if self.apply_constraints: + # TODO: set the constraints here + # Define the nonlin. constraint + nlc = NonlinearConstraint(lambda x: np.matmul(X,x),-1,1.1) + self.nlc = nlc + + fun = lambda x: (np.linalg.norm(np.matmul(X, x)-y, ord = 2))**2 + if self.init_type =='zeros': + res = minimize(fun, np.zeros(X.shape[1]), method = 'trust-constr', constraints = self.nlc) + if self.init_type == 'nonpi': + clf_poly.fit(X, y) + coeff = clf_poly.coef_ + res = minimize(fun, coeff, method = 'trust-constr', constraints = self.nlc) + + coeff = np.array(res.x) + clf_poly.coef_ = coeff + clf_poly.X = X + clf_poly.y = y + clf_poly.intercept_ = 0 + + # Training without constraints uses chosen regression method + else: + clf_poly.fit(X, y) + + # Select the nonzero entries of coefficients + if sparsity: + nnz_idx = np.nonzero(clf_poly.coef_)[0] + else: + nnz_idx = np.arange(clf_poly.coef_.shape[0]) + + # This is for the case where all outputs are zero, thereby + # all coefficients are zero + if (y == 0).all(): + nnz_idx = np.insert(np.nonzero(clf_poly.coef_)[0], 0, 0) + + sparse_basis_indices = basis_indices[nnz_idx] + sparse_X = X[:, nnz_idx] + coeffs = clf_poly.coef_[nnz_idx] + clf_poly.coef_ = coeffs + + # Create a dict to pass the outputs + return_out_dict = dict() + return_out_dict['clf_poly'] = clf_poly + return_out_dict['spareMulti-Index'] = sparse_basis_indices + return_out_dict['sparePsi'] = sparse_X + return_out_dict['coeffs'] = coeffs + return return_out_dict + + # ------------------------------------------------------------------------- + def create_psi(self, basis_indices, univ_p_val): + """ + This function assemble the design matrix Psi from the given basis index + set INDICES and the univariate polynomial evaluations univ_p_val. + + Parameters + ---------- + basis_indices : array of shape (n_terms, n_params) + Multi-indices of multivariate polynomials. + univ_p_val : array of (n_samples, n_params, n_max+1) + All univariate regressors up to `n_max`. + + Raises + ------ + ValueError + n_terms in arguments do not match. + + Returns + ------- + psi : array of shape (n_samples, n_terms) + Multivariate regressors. + + """ + # Check if BasisIndices is a sparse matrix + sparsity = sp.sparse.issparse(basis_indices) + if sparsity: + basis_indices = basis_indices.toarray() + + # Initialization and consistency checks + # number of input variables + n_params = univ_p_val.shape[1] + + # Size of the experimental design + n_samples = univ_p_val.shape[0] + + # number of basis terms + n_terms = basis_indices.shape[0] + + # check that the variables have consistent sizes + if n_params != basis_indices.shape[1]: + raise ValueError( + f"The shapes of basis_indices ({basis_indices.shape[1]}) and " + f"univ_p_val ({n_params}) don't match!!" + ) + + # Preallocate the Psi matrix for performance + psi = np.ones((n_samples, n_terms)) + # Assemble the Psi matrix + for m in range(basis_indices.shape[1]): + aa = np.where(basis_indices[:, m] > 0)[0] + try: + basisIdx = basis_indices[aa, m] + bb = univ_p_val[:, m, basisIdx].reshape(psi[:, aa].shape) + psi[:, aa] = np.multiply(psi[:, aa], bb) + except ValueError as err: + raise err + return psi + + # -------------------------------------------------------------------------------------------------------- + def adaptive_regression(self, ED_X, ED_Y, varIdx, verbose=False): + """ + Adaptively fits the PCE model by comparing the scores of different + degrees and q-norm. + + Parameters + ---------- + ED_X : array of shape (n_samples, n_params) + Experimental design. + ED_Y : array of shape (n_samples,) + Target values, i.e. simulation results for the Experimental design. + varIdx : int + Index of the output. + verbose : bool, optional + Print out summary. The default is False. + + Returns + ------- + returnVars : Dict + Fitted estimator, best degree, best q-norm, LOOCVScore and + coefficients. + + """ + + n_samples, n_params = ED_X.shape + # Initialization + qAllCoeffs, AllCoeffs = {}, {} + qAllIndices_Sparse, AllIndices_Sparse = {}, {} + qAllclf_poly, Allclf_poly = {}, {} + qAllnTerms, AllnTerms = {}, {} + qAllLCerror, AllLCerror = {}, {} + + # Extract degree array and qnorm array + deg_array = np.array([*self.allBasisIndices], dtype=int) + qnorm = [*self.allBasisIndices[str(int(deg_array[0]))]] + + # Some options for EarlyStop + errorIncreases = False + # Stop degree, if LOO error does not decrease n_checks_degree times + n_checks_degree = 3 + # Stop qNorm, if criterion isn't fulfilled n_checks_qNorm times + n_checks_qNorm = 2 + nqnorms = len(qnorm) + qNormEarlyStop = True + if nqnorms < n_checks_qNorm+1: + qNormEarlyStop = False + + # ===================================================================== + # basis adaptive polynomial chaos: repeat the calculation by increasing + # polynomial degree until the highest accuracy is reached + # ===================================================================== + # For each degree check all q-norms and choose the best one + scores = -np.inf * np.ones(deg_array.shape[0]) + qNormScores = -np.inf * np.ones(nqnorms) + + for degIdx, deg in enumerate(deg_array): + + for qidx, q in enumerate(qnorm): + + # Extract the polynomial basis indices from the pool of + # allBasisIndices + BasisIndices = self.allBasisIndices[str(deg)][str(q)] + + # Assemble the Psi matrix + Psi = self.create_psi(BasisIndices, self.univ_p_val) + + # Calulate the cofficients of the meta model + outs = self.regression(Psi, ED_Y, BasisIndices) + + # Calculate and save the score of LOOCV + score, LCerror = self.corr_loocv_error(outs['clf_poly'], + outs['sparePsi'], + outs['coeffs'], + ED_Y) + + # Check the convergence of noise for FastARD + if self.pce_reg_method == 'FastARD' and \ + outs['clf_poly'].alpha_ < np.finfo(np.float32).eps: + score = -np.inf + + qNormScores[qidx] = score + qAllCoeffs[str(qidx+1)] = outs['coeffs'] + qAllIndices_Sparse[str(qidx+1)] = outs['spareMulti-Index'] + qAllclf_poly[str(qidx+1)] = outs['clf_poly'] + qAllnTerms[str(qidx+1)] = BasisIndices.shape[0] + qAllLCerror[str(qidx+1)] = LCerror + + # EarlyStop check + # if there are at least n_checks_qNorm entries after the + # best one, we stop + if qNormEarlyStop and \ + sum(np.isfinite(qNormScores)) > n_checks_qNorm: + # If the error has increased the last two iterations, stop! + qNormScores_nonInf = qNormScores[np.isfinite(qNormScores)] + deltas = np.sign(np.diff(qNormScores_nonInf)) + if sum(deltas[-n_checks_qNorm+1:]) == 2: + # stop the q-norm loop here + break + if np.var(ED_Y) == 0: + break + + # Store the score in the scores list + best_q = np.nanargmax(qNormScores) + scores[degIdx] = qNormScores[best_q] + + AllCoeffs[str(degIdx+1)] = qAllCoeffs[str(best_q+1)] + AllIndices_Sparse[str(degIdx+1)] = qAllIndices_Sparse[str(best_q+1)] + Allclf_poly[str(degIdx+1)] = qAllclf_poly[str(best_q+1)] + AllnTerms[str(degIdx+1)] = qAllnTerms[str(best_q+1)] + AllLCerror[str(degIdx+1)] = qAllLCerror[str(best_q+1)] + + # Check the direction of the error (on average): + # if it increases consistently stop the iterations + if len(scores[scores != -np.inf]) > n_checks_degree: + scores_nonInf = scores[scores != -np.inf] + ss = np.sign(scores_nonInf - np.max(scores_nonInf)) + # ss<0 error decreasing + errorIncreases = np.sum(np.sum(ss[-2:])) <= -1*n_checks_degree + + if errorIncreases: + break + + # Check only one degree, if target matrix has zero variance + if np.var(ED_Y) == 0: + break + + # ------------------ Summary of results ------------------ + # Select the one with the best score and save the necessary outputs + best_deg = np.nanargmax(scores)+1 + coeffs = AllCoeffs[str(best_deg)] + basis_indices = AllIndices_Sparse[str(best_deg)] + clf_poly = Allclf_poly[str(best_deg)] + LOOCVScore = np.nanmax(scores) + P = AllnTerms[str(best_deg)] + LCerror = AllLCerror[str(best_deg)] + degree = deg_array[np.nanargmax(scores)] + qnorm = float(qnorm[best_q]) + + # ------------------ Print out Summary of results ------------------ + if self.verbose: + # Create PSI_Sparse by removing redundent terms + nnz_idx = np.nonzero(coeffs)[0] + BasisIndices_Sparse = basis_indices[nnz_idx] + + print(f'Output variable {varIdx+1}:') + print('The estimation of PCE coefficients converged at polynomial ' + f'degree {deg_array[best_deg-1]} with ' + f'{len(BasisIndices_Sparse)} terms (Sparsity index = ' + f'{round(len(BasisIndices_Sparse)/P, 3)}).') + + print(f'Final ModLOO error estimate: {1-max(scores):.3e}') + print('\n'+'-'*50) + + if verbose: + print('='*50) + print(' '*10 + ' Summary of results ') + print('='*50) + + print("Scores:\n", scores) + print("Degree of best score:", self.deg_array[best_deg-1]) + print("No. of terms:", len(basis_indices)) + print("Sparsity index:", round(len(basis_indices)/P, 3)) + print("Best Indices:\n", basis_indices) + + if self.pce_reg_method in ['BRR', 'ARD']: + fig, ax = plt.subplots(figsize=(12, 10)) + plt.title("Marginal log-likelihood") + plt.plot(clf_poly.scores_, color='navy', linewidth=2) + plt.ylabel("Score") + plt.xlabel("Iterations") + if self.pce_reg_method.lower() == 'bbr': + text = f"$\\alpha={clf_poly.alpha_:.1f}$\n" + f"$\\lambda={clf_poly.lambda_:.3f}$\n" + f"$L={clf_poly.scores_[-1]:.1f}$" + else: + text = f"$\\alpha={clf_poly.alpha_:.1f}$\n$" + f"\\L={clf_poly.scores_[-1]:.1f}$" + + plt.text(0.75, 0.5, text, fontsize=18, transform=ax.transAxes) + plt.show() + print('='*80) + + # Create a dict to pass the outputs + returnVars = dict() + returnVars['clf_poly'] = clf_poly + returnVars['degree'] = degree + returnVars['qnorm'] = qnorm + returnVars['coeffs'] = coeffs + returnVars['multi_indices'] = basis_indices + returnVars['LOOCVScore'] = LOOCVScore + returnVars['LCerror'] = LCerror + + return returnVars + + # ------------------------------------------------------------------------- + def corr_loocv_error(self, clf, psi, coeffs, y): + """ + Calculates the corrected LOO error for regression on regressor + matrix `psi` that generated the coefficients based on [1] and [2]. + + [1] Blatman, G., 2009. Adaptive sparse polynomial chaos expansions for + uncertainty propagation and sensitivity analysis (Doctoral + dissertation, Clermont-Ferrand 2). + + [2] Blatman, G. and Sudret, B., 2011. Adaptive sparse polynomial chaos + expansion based on least angle regression. Journal of computational + Physics, 230(6), pp.2345-2367. + + Parameters + ---------- + clf : object + Fitted estimator. + psi : array of shape (n_samples, n_features) + The multivariate orthogonal polynomials (regressor). + coeffs : array-like of shape (n_features,) + Estimated cofficients. + y : array of shape (n_samples,) + Target values. + + Returns + ------- + R_2 : float + LOOCV Validation score (1-LOOCV erro). + residual : array of shape (n_samples,) + Residual values (y - predicted targets). + + """ + psi = np.array(psi, dtype=float) + + # Create PSI_Sparse by removing redundent terms + nnz_idx = np.nonzero(coeffs)[0] + if len(nnz_idx) == 0: + nnz_idx = [0] + psi_sparse = psi[:, nnz_idx] + + # NrCoeffs of aPCEs + P = len(nnz_idx) + # NrEvaluation (Size of experimental design) + N = psi.shape[0] + + # Build the projection matrix + PsiTPsi = np.dot(psi_sparse.T, psi_sparse) + + if np.linalg.cond(PsiTPsi) > 1e-12: #and \ + # np.linalg.cond(PsiTPsi) < 1/sys.float_info.epsilon: + # faster + try: + M = sp.linalg.solve(PsiTPsi, + sp.sparse.eye(PsiTPsi.shape[0]).toarray()) + except: + raise AttributeError('There are too few samples for the corrected loo-cv error. Fit surrogate on at least as many samples as parameters to use this') + else: + # stabler + M = np.linalg.pinv(PsiTPsi) + + # h factor (the full matrix is not calculated explicitly, + # only the trace is, to save memory) + PsiM = np.dot(psi_sparse, M) + + h = np.sum(np.multiply(PsiM, psi_sparse), axis=1, dtype=np.longdouble)#float128) + + # ------ Calculate Error Loocv for each measurement point ---- + # Residuals + try: + residual = clf.predict(psi) - y + except: + residual = np.dot(psi, coeffs) - y + + # Variance + var_y = np.var(y) + + if var_y == 0: + norm_emp_error = 0 + loo_error = 0 + LCerror = np.zeros((y.shape)) + return 1-loo_error, LCerror + else: + norm_emp_error = np.mean(residual**2)/var_y + + # LCerror = np.divide(residual, (1-h)) + LCerror = residual / (1-h) + loo_error = np.mean(np.square(LCerror)) / var_y + # if there are NaNs, just return an infinite LOO error (this + # happens, e.g., when a strongly underdetermined problem is solved) + if np.isnan(loo_error): + loo_error = np.inf + + # Corrected Error for over-determined system + tr_M = np.trace(M) + if tr_M < 0 or abs(tr_M) > 1e6: + tr_M = np.trace(np.linalg.pinv(np.dot(psi.T, psi))) + + # Over-determined system of Equation + if N > P: + T_factor = N/(N-P) * (1 + tr_M) + + # Under-determined system of Equation + else: + T_factor = np.inf + + corrected_loo_error = loo_error * T_factor + + R_2 = 1 - corrected_loo_error + + return R_2, LCerror + + # ------------------------------------------------------------------------- + def pca_transformation(self, target, verbose=False): + """ + Transforms the targets (outputs) via Principal Component Analysis + + Parameters + ---------- + target : array of shape (n_samples,) + Target values. + + Returns + ------- + pca : obj + Fitted sklearnPCA object. + OutputMatrix : array of shape (n_samples,) + Transformed target values. + n_pca_components : int + Number of selected principal components. + + """ + # Transform via Principal Component Analysis + if hasattr(self, 'var_pca_threshold'): + var_pca_threshold = self.var_pca_threshold + else: + var_pca_threshold = 100.0 + n_samples, n_features = target.shape + + if hasattr(self, 'n_pca_components'): + n_pca_components = self.n_pca_components + else: + # Instantiate and fit sklearnPCA object + covar_matrix = sklearnPCA(n_components=None) + covar_matrix.fit(target) + var = np.cumsum(np.round(covar_matrix.explained_variance_ratio_, + decimals=5)*100) + # Find the number of components to explain self.varPCAThreshold of + # variance + try: + n_components = np.where(var >= var_pca_threshold)[0][0] + 1 + except IndexError: + n_components = min(n_samples, n_features) + + n_pca_components = min(n_samples, n_features, n_components) + + # Print out a report + if verbose: + print() + print('-' * 50) + print(f"PCA transformation is performed with {n_pca_components}" + " components.") + print('-' * 50) + print() + + # Fit and transform with the selected number of components + pca = sklearnPCA(n_components=n_pca_components, svd_solver='arpack') + scaled_target = pca.fit_transform(target) + + return pca, scaled_target, n_pca_components + + # ------------------------------------------------------------------------- + def gaussian_process_emulator(self, X, y, nug_term=None, autoSelect=False, + varIdx=None): + """ + Fits a Gaussian Process Emulator to the target given the training + points. + + Parameters + ---------- + X : array of shape (n_samples, n_params) + Training points. + y : array of shape (n_samples,) + Target values. + nug_term : float, optional + Nugget term. The default is None, i.e. variance of y. + autoSelect : bool, optional + Loop over some kernels and select the best. The default is False. + varIdx : int, optional + The index number. The default is None. + + Returns + ------- + gp : object + Fitted estimator. + + """ + + nug_term = nug_term if nug_term else np.var(y) + + Kernels = [nug_term * kernels.RBF(length_scale=1.0, + length_scale_bounds=(1e-25, 1e15)), + nug_term * kernels.RationalQuadratic(length_scale=0.2, + alpha=1.0), + nug_term * kernels.Matern(length_scale=1.0, + length_scale_bounds=(1e-15, 1e5), + nu=1.5)] + + # Automatic selection of the kernel + if autoSelect: + gp = {} + BME = [] + for i, kernel in enumerate(Kernels): + gp[i] = GaussianProcessRegressor(kernel=kernel, + n_restarts_optimizer=3, + normalize_y=False) + + # Fit to data using Maximum Likelihood Estimation + gp[i].fit(X, y) + + # Store the MLE as BME score + BME.append(gp[i].log_marginal_likelihood()) + + gp = gp[np.argmax(BME)] + + else: + gp = GaussianProcessRegressor(kernel=Kernels[0], + n_restarts_optimizer=3, + normalize_y=False) + gp.fit(X, y) + + # Compute score + if varIdx is not None: + Score = gp.score(X, y) + print('-'*50) + print(f'Output variable {varIdx}:') + print('The estimation of GPE coefficients converged,') + print(f'with the R^2 score: {Score:.3f}') + print('-'*50) + + return gp + + # ------------------------------------------------------------------------- + def eval_metamodel(self, samples): + """ + Evaluates meta-model at the requested samples. One can also generate + nsamples. + + Parameters + ---------- + samples : array of shape (n_samples, n_params), optional + Samples to evaluate meta-model at. The default is None. + nsamples : int, optional + Number of samples to generate, if no `samples` is provided. The + default is None. + sampling_method : str, optional + Type of sampling, if no `samples` is provided. The default is + 'random'. + return_samples : bool, optional + Retun samples, if no `samples` is provided. The default is False. + + Returns + ------- + mean_pred : dict + Mean of the predictions. + std_pred : dict + Standard deviatioon of the predictions. + """ + # Transform into np array - can also be given as list + samples = np.array(samples) + + # Transform samples to the independent space + samples = self.InputSpace.transform( + samples, + method='user' + ) + # Compute univariate bases for the given samples + if self.meta_model_type.lower() != 'gpe': + univ_p_val = self.univ_basis_vals( + samples, + n_max=np.max(self.pce_deg) + ) + + mean_pred_b = {} + std_pred_b = {} + # Loop over bootstrap iterations + for b_i in range(self.n_bootstrap_itrs): + + # Extract model dictionary + if self.meta_model_type.lower() == 'gpe': + model_dict = self.gp_poly[f'b_{b_i+1}'] + else: + model_dict = self.coeffs_dict[f'b_{b_i+1}'] + + # Loop over outputs + mean_pred = {} + std_pred = {} + for output, values in model_dict.items(): + + mean = np.empty((len(samples), len(values))) + std = np.empty((len(samples), len(values))) + idx = 0 + for in_key, InIdxValues in values.items(): + + # Prediction with GPE + if self.meta_model_type.lower() == 'gpe': + X_T = self.x_scaler[f'b_{b_i+1}'][output].transform(samples) + gp = self.gp_poly[f'b_{b_i+1}'][output][in_key] + y_mean, y_std = gp.predict(X_T, return_std=True) + + else: + # Prediction with PCE + # Assemble Psi matrix + basis = self.basis_dict[f'b_{b_i+1}'][output][in_key] + psi = self.create_psi(basis, univ_p_val) + + # Prediction + if self.bootstrap_method != 'fast' or b_i == 0: + # with error bar, i.e. use clf_poly + clf_poly = self.clf_poly[f'b_{b_i+1}'][output][in_key] + try: + y_mean, y_std = clf_poly.predict( + psi, return_std=True + ) + except TypeError: + y_mean = clf_poly.predict(psi) + y_std = np.zeros_like(y_mean) + else: + # without error bar + coeffs = self.coeffs_dict[f'b_{b_i+1}'][output][in_key] + y_mean = np.dot(psi, coeffs) + y_std = np.zeros_like(y_mean) + + mean[:, idx] = y_mean + std[:, idx] = y_std + idx += 1 + + # Save predictions for each output + if self.dim_red_method.lower() == 'pca': + PCA = self.pca[f'b_{b_i+1}'][output] + mean_pred[output] = PCA.inverse_transform(mean) + std_pred[output] = np.zeros(mean.shape) + else: + mean_pred[output] = mean + std_pred[output] = std + + # Save predictions for each bootstrap iteration + mean_pred_b[b_i] = mean_pred + std_pred_b[b_i] = std_pred + + # Change the order of nesting + mean_pred_all = {} + for i in sorted(mean_pred_b): + for k, v in mean_pred_b[i].items(): + if k not in mean_pred_all: + mean_pred_all[k] = [None] * len(mean_pred_b) + mean_pred_all[k][i] = v + + # Compute the moments of predictions over the predictions + for output in self.out_names: + # Only use bootstraps with finite values + finite_rows = np.isfinite( + mean_pred_all[output]).all(axis=2).all(axis=1) + outs = np.asarray(mean_pred_all[output])[finite_rows] + # Compute mean + mean_pred[output] = np.mean(outs, axis=0) + # Compute standard deviation + if self.n_bootstrap_itrs > 1: + std_pred[output] = np.std(outs, axis=0) + else: + std_pred[output] = std_pred_b[b_i][output] + + return mean_pred, std_pred + + # ------------------------------------------------------------------------- + def create_model_error(self, X, y, Model, name='Calib'): + """ + Fits a GPE-based model error. + + Parameters + ---------- + X : array of shape (n_outputs, n_inputs) + Input array. It can contain any forcing inputs or coordinates of + extracted data. + y : array of shape (n_outputs,) + The model response for the MAP parameter set. + name : str, optional + Calibration or validation. The default is `'Calib'`. + + Returns + ------- + self: object + Self object. + + """ + outputNames = self.out_names + self.errorRegMethod = 'GPE' + self.errorclf_poly = self.auto_vivification() + self.errorScale = self.auto_vivification() + + # Read data + # TODO: do this call outside the metamodel + MeasuredData = Model.read_observation(case=name) + + # Fitting GPR based bias model + for out in outputNames: + nan_idx = ~np.isnan(MeasuredData[out]) + # Select data + try: + data = MeasuredData[out].values[nan_idx] + except AttributeError: + data = MeasuredData[out][nan_idx] + + # Prepare the input matrix + scaler = MinMaxScaler() + delta = data # - y[out][0] + BiasInputs = np.hstack((X[out], y[out].reshape(-1, 1))) + X_S = scaler.fit_transform(BiasInputs) + gp = self.gaussian_process_emulator(X_S, delta) + + self.errorScale[out]["y_1"] = scaler + self.errorclf_poly[out]["y_1"] = gp + + return self + + # ------------------------------------------------------------------------- + def eval_model_error(self, X, y_pred): + """ + Evaluates the error model. + + Parameters + ---------- + X : array + Inputs. + y_pred : dict + Predictions. + + Returns + ------- + mean_pred : dict + Mean predition of the GPE-based error model. + std_pred : dict + standard deviation of the GPE-based error model. + + """ + mean_pred = {} + std_pred = {} + + for Outkey, ValuesDict in self.errorclf_poly.items(): + + pred_mean = np.zeros_like(y_pred[Outkey]) + pred_std = np.zeros_like(y_pred[Outkey]) + + for Inkey, InIdxValues in ValuesDict.items(): + + gp = self.errorclf_poly[Outkey][Inkey] + scaler = self.errorScale[Outkey][Inkey] + + # Transform Samples using scaler + for j, pred in enumerate(y_pred[Outkey]): + BiasInputs = np.hstack((X[Outkey], pred.reshape(-1, 1))) + Samples_S = scaler.transform(BiasInputs) + y_hat, y_std = gp.predict(Samples_S, return_std=True) + pred_mean[j] = y_hat + pred_std[j] = y_std + # pred_mean[j] += pred + + mean_pred[Outkey] = pred_mean + std_pred[Outkey] = pred_std + + return mean_pred, std_pred + + # ------------------------------------------------------------------------- + class auto_vivification(dict): + """ + Implementation of perl's AutoVivification feature. + + Source: https://stackoverflow.com/a/651879/18082457 + """ + + def __getitem__(self, item): + try: + return dict.__getitem__(self, item) + except KeyError: + value = self[item] = type(self)() + return value + + # ------------------------------------------------------------------------- + def copy_meta_model_opts(self): + """ + This method is a convinient function to copy the metamodel options. + + Returns + ------- + new_MetaModelOpts : object + The copied object. + + """ + # TODO: what properties should be moved to the new object? + new_MetaModelOpts = copy.deepcopy(self) + new_MetaModelOpts.input_obj = self.input_obj#InputObj + new_MetaModelOpts.InputSpace = self.InputSpace + #new_MetaModelOpts.InputSpace.meta_Model = 'aPCE' + #new_MetaModelOpts.InputSpace.InputObj = self.input_obj + #new_MetaModelOpts.InputSpace.ndim = len(self.input_obj.Marginals) + new_MetaModelOpts.n_params = len(self.input_obj.Marginals) + #new_MetaModelOpts.InputSpace.hdf5_file = None + + return new_MetaModelOpts + + # ------------------------------------------------------------------------- + def __select_degree(self, ndim, n_samples): + """ + Selects degree based on the number of samples and parameters in the + sequential design. + + Parameters + ---------- + ndim : int + Dimension of the parameter space. + n_samples : int + Number of samples. + + Returns + ------- + deg_array: array + Array containing the arrays. + + """ + # Define the deg_array + max_deg = np.max(self.pce_deg) + min_Deg = np.min(self.pce_deg) + + # TODO: remove the options for sequential? + #nitr = n_samples - self.InputSpace.n_init_samples + + # Check q-norm + if not np.isscalar(self.pce_q_norm): + self.pce_q_norm = np.array(self.pce_q_norm) + else: + self.pce_q_norm = np.array([self.pce_q_norm]) + + def M_uptoMax(maxDeg): + n_combo = np.zeros(maxDeg) + for i, d in enumerate(range(1, maxDeg+1)): + n_combo[i] = math.factorial(ndim+d) + n_combo[i] /= math.factorial(ndim) * math.factorial(d) + return n_combo + + deg_new = max_deg + #d = nitr if nitr != 0 and self.n_params > 5 else 1 + # d = 1 + # min_index = np.argmin(abs(M_uptoMax(max_deg)-ndim*n_samples*d)) + # deg_new = range(1, max_deg+1)[min_index] + + if deg_new > min_Deg and self.pce_reg_method.lower() != 'fastard': + deg_array = np.arange(min_Deg, deg_new+1) + else: + deg_array = np.array([deg_new]) + + return deg_array + + def generate_polynomials(self, max_deg=None): + # Check for InputSpace + if not hasattr(self, 'InputSpace'): + raise AttributeError('Generate or add InputSpace before generating polynomials') + + ndim = self.InputSpace.ndim + # Create orthogonal polynomial coefficients if necessary + if (self.meta_model_type.lower()!='gpe') and max_deg is not None:# and self.input_obj.poly_coeffs_flag: + self.polycoeffs = {} + for parIdx in tqdm(range(ndim), ascii=True, + desc="Computing orth. polynomial coeffs"): + poly_coeffs = apoly_construction( + self.InputSpace.raw_data[parIdx], + max_deg + ) + self.polycoeffs[f'p_{parIdx+1}'] = poly_coeffs + else: + raise AttributeError('MetaModel cannot generate polynomials in the given scenario!') + + # ------------------------------------------------------------------------- + def _compute_pce_moments(self): + """ + Computes the first two moments using the PCE-based meta-model. + + Returns + ------- + pce_means: dict + The first moment (mean) of the surrogate. + pce_stds: dict + The second moment (standard deviation) of the surrogate. + + """ + + # Check if its truly a pce-surrogate + if self.meta_model_type.lower() == 'gpe': + raise AttributeError('Moments can only be computed for pce-type surrogates') + + outputs = self.out_names + pce_means_b = {} + pce_stds_b = {} + + # Loop over bootstrap iterations + for b_i in range(self.n_bootstrap_itrs): + # Loop over the metamodels + coeffs_dicts = self.coeffs_dict[f'b_{b_i+1}'].items() + means = {} + stds = {} + for output, coef_dict in coeffs_dicts: + + pce_mean = np.zeros((len(coef_dict))) + pce_var = np.zeros((len(coef_dict))) + + for index, values in coef_dict.items(): + idx = int(index.split('_')[1]) - 1 + coeffs = self.coeffs_dict[f'b_{b_i+1}'][output][index] + + # Mean = c_0 + if coeffs[0] != 0: + pce_mean[idx] = coeffs[0] + else: + clf_poly = self.clf_poly[f'b_{b_i+1}'][output] + pce_mean[idx] = clf_poly[index].intercept_ + # Var = sum(coeffs[1:]**2) + pce_var[idx] = np.sum(np.square(coeffs[1:])) + + # Save predictions for each output + if self.dim_red_method.lower() == 'pca': + PCA = self.pca[f'b_{b_i+1}'][output] + means[output] = PCA.inverse_transform(pce_mean) + stds[output] = PCA.inverse_transform(np.sqrt(pce_var)) + else: + means[output] = pce_mean + stds[output] = np.sqrt(pce_var) + + # Save predictions for each bootstrap iteration + pce_means_b[b_i] = means + pce_stds_b[b_i] = stds + + # Change the order of nesting + mean_all = {} + for i in sorted(pce_means_b): + for k, v in pce_means_b[i].items(): + if k not in mean_all: + mean_all[k] = [None] * len(pce_means_b) + mean_all[k][i] = v + std_all = {} + for i in sorted(pce_stds_b): + for k, v in pce_stds_b[i].items(): + if k not in std_all: + std_all[k] = [None] * len(pce_stds_b) + std_all[k][i] = v + + # Back transformation if PCA is selected. + pce_means, pce_stds = {}, {} + for output in outputs: + pce_means[output] = np.mean(mean_all[output], axis=0) + pce_stds[output] = np.mean(std_all[output], axis=0) + + return pce_means, pce_stds diff --git a/examples/analytical-function/example_analytical_function.py b/examples/analytical-function/example_analytical_function.py index 1e10a97bb..37900127a 100644 --- a/examples/analytical-function/example_analytical_function.py +++ b/examples/analytical-function/example_analytical_function.py @@ -168,7 +168,7 @@ if __name__ == "__main__": ExpDesign.max_func_itr = 1000 # Use when 'Voronoi' or 'random' or 'latin_hypercube' chosen - ExpDesign.n_candidate = 1000 + ExpDesign.n_canddidate = 1000 ExpDesign.n_cand_groups = 4 # -------- Exploitation ------ diff --git a/examples/borehole/example_borehole.py b/examples/borehole/example_borehole.py index 1c552854f..869a05320 100644 --- a/examples/borehole/example_borehole.py +++ b/examples/borehole/example_borehole.py @@ -184,7 +184,7 @@ if __name__ == "__main__": ExpDesign.max_func_itr = 200 # Use when 'Voronoi' or 'random' or 'latin_hypercube' chosen - ExpDesign.n_candidate = 5000 + ExpDesign.n_canddidate = 5000 ExpDesign.n_cand_groups = 4 # -------- Exploitation ------ diff --git a/examples/ishigami/example_ishigami.py b/examples/ishigami/example_ishigami.py index 602c7d658..72c9dc2d3 100644 --- a/examples/ishigami/example_ishigami.py +++ b/examples/ishigami/example_ishigami.py @@ -143,7 +143,7 @@ if __name__ == "__main__": ExpDesign.max_func_itr = 200 # Use when 'Voronoi' or 'random' or 'latin_hypercube' chosen - ExpDesign.n_candidate = 1000 + ExpDesign.n_canddidate = 1000 ExpDesign.n_cand_groups = 4 # -------- Exploitation ------ diff --git a/examples/model-comparison/example_model_comparison.py b/examples/model-comparison/example_model_comparison.py index 950d3f991..d678898c1 100644 --- a/examples/model-comparison/example_model_comparison.py +++ b/examples/model-comparison/example_model_comparison.py @@ -27,14 +27,17 @@ sys.path.append("../../src/") from bayesvalidrox.pylink.pylink import PyLinkForwardModel from bayesvalidrox.surrogate_models.inputs import Input -from bayesvalidrox.surrogate_models.engine import Engine from bayesvalidrox.surrogate_models.exp_designs import ExpDesigns from bayesvalidrox.surrogate_models.surrogate_models import MetaModel +#from bayesvalidrox.surrogate_models.meta_model_engine import MetaModelEngine from bayesvalidrox.post_processing.post_processing import PostProcessing +from bayesvalidrox.bayes_inference.bayes_inference import BayesInference from bayesvalidrox.bayes_inference.discrepancy import Discrepancy from bayes_inference.bayes_model_comparison import BayesModelComparison +from bayesvalidrox.surrogate_models.engine import Engine + if __name__ == "__main__": # Read data sigma = 0.6 diff --git a/examples/pollution/example_pollution.py b/examples/pollution/example_pollution.py index ac9db0df9..f2de52e2c 100644 --- a/examples/pollution/example_pollution.py +++ b/examples/pollution/example_pollution.py @@ -186,7 +186,7 @@ if __name__ == "__main__": MetaModelOpts.ExpDesign.max_func_itr = 200 # Use when 'Voronoi' or 'random' or 'latin_hypercube' chosen - MetaModelOpts.ExpDesign.n_candidate = 5000 + MetaModelOpts.ExpDesign.n_canddidate = 5000 MetaModelOpts.ExpDesign.n_cand_groups = 8 # -------- Exploitation ------ diff --git a/src/bayesvalidrox/surrogate_models/engine.py b/src/bayesvalidrox/surrogate_models/engine.py index 797aa7456..a907625fd 100644 --- a/src/bayesvalidrox/surrogate_models/engine.py +++ b/src/bayesvalidrox/surrogate_models/engine.py @@ -340,7 +340,7 @@ class Engine(): # Get the parameters max_n_samples = self.ExpDesign.n_max_samples mod_LOO_threshold = self.ExpDesign.mod_LOO_threshold - n_canddidate = self.ExpDesign.n_candidate + n_canddidate = self.ExpDesign.n_canddidate post_snapshot = self.ExpDesign.post_snapshot n_replication = self.ExpDesign.n_replication util_func = self.ExpDesign.util_func diff --git a/src/bayesvalidrox/surrogate_models/exp_designs.py b/src/bayesvalidrox/surrogate_models/exp_designs.py index 0ef35b5a5..96012162a 100644 --- a/src/bayesvalidrox/surrogate_models/exp_designs.py +++ b/src/bayesvalidrox/surrogate_models/exp_designs.py @@ -81,7 +81,7 @@ class ExpDesigns(InputSpace): tradeoff_scheme : str Trade-off scheme to assign weights to the exploration and exploitation scores in the sequential design. - n_candidate : int + n_canddidate : int Number of candidate training sets to calculate the scores for. explore_method : str Type of the exploration method for the sequential design. The following @@ -143,15 +143,16 @@ class ExpDesigns(InputSpace): - K-Opt (K-Optimality) """ - def __init__(self, input_object, meta_model_type='pce', sampling_method='random', hdf5_file=None, n_new_samples=1, - n_max_samples=None, mod_LOO_threshold=1e-16, tradeoff_scheme=None, n_candidate=1, - explore_method='random', exploit_method='Space-filling', util_func='Space-filling', n_cand_groups=4, - n_replication=1, post_snapshot=False, step_snapshot=1, max_a_post=[], adapt_verbose=False, - max_func_itr=1): + def __init__(self, Input, meta_Model_type='pce', + sampling_method='random', hdf5_file=None, + n_new_samples=1, n_max_samples=None, mod_LOO_threshold=1e-16, + tradeoff_scheme=None, n_canddidate=1, explore_method='random', + exploit_method='Space-filling', util_func='Space-filling', + n_cand_groups=4, n_replication=1, post_snapshot=False, + step_snapshot=1, max_a_post=[], adapt_verbose=False, max_func_itr=1): - super().__init__(input_object, meta_model_type) - self.InputObj = input_object - self.meta_Model_type = meta_model_type + self.InputObj = Input + self.meta_Model_type = meta_Model_type self.sampling_method = sampling_method self.hdf5_file = hdf5_file self.n_new_samples = n_new_samples @@ -161,7 +162,7 @@ class ExpDesigns(InputSpace): self.exploit_method = exploit_method self.util_func = util_func self.tradeoff_scheme = tradeoff_scheme - self.n_candidate = n_candidate + self.n_canddidate = n_canddidate self.n_cand_groups = n_cand_groups self.n_replication = n_replication self.post_snapshot = post_snapshot diff --git a/src/bayesvalidrox/surrogate_models/input_space.py b/src/bayesvalidrox/surrogate_models/input_space.py index a4aedb2a7..d722e387a 100644 --- a/src/bayesvalidrox/surrogate_models/input_space.py +++ b/src/bayesvalidrox/surrogate_models/input_space.py @@ -16,7 +16,7 @@ class InputSpace: Attributes ---------- - input_object : obj + Input : obj Input object containing the parameter marginals, i.e. name, distribution type and distribution parameters or available raw data. meta_Model_type : str @@ -24,42 +24,33 @@ class InputSpace: """ - def __init__(self, input_object, meta_model_type='pce'): - self.InputObj = input_object - self.meta_Model_type = meta_model_type - + def __init__(self, Input, meta_Model_type='pce'): + self.InputObj = Input + self.meta_Model_type = meta_Model_type + # Other self.apce = None - self.bound_tuples = None - self.input_data_given = None - self.JDist = None - self.Marginals = None - self.MCSize = None self.ndim = None - self.origJDist = None - self.par_names = [] - self.poly_types = None - self.prior_space = None - self.raw_data = None - + # Init self.check_valid_inputs() - - def check_valid_inputs(self) -> None: + + + def check_valid_inputs(self)-> None: """ - Check if the given InputObj is valid to use for further calculations based on the following. - 1) It has some marginals - 2) The marginals have valid priors - 3) All marginals are given as the same type (samples vs dist) + Check if the given InputObj is valid to use for further calculations: + Has some Marginals + Marginals have valid priors + All Marginals given as the same type (samples vs dist) Returns ------- None """ - inputs = self.InputObj - self.ndim = len(inputs.Marginals) - + Inputs = self.InputObj + self.ndim = len(Inputs.Marginals) + # Check if PCE or aPCE metamodel is selected. # TODO: test also for 'pce'?? if self.meta_Model_type.lower() == 'apce': @@ -68,22 +59,26 @@ class InputSpace: self.apce = False # check if marginals given - if not self.ndim >= 1: + if not self.ndim >=1: raise AssertionError('Cannot build distributions if no marginals are given') - + # check that each marginal is valid - for marginals in inputs.Marginals: + for marginals in Inputs.Marginals: if len(marginals.input_data) == 0: - if marginals.dist_type is None: + if marginals.dist_type == None: raise AssertionError('Not all marginals were provided priors') - if np.array(marginals.input_data).shape[0] and (marginals.dist_type is not None): + break + if np.array(marginals.input_data).shape[0] and (marginals.dist_type != None): raise AssertionError('Both samples and distribution type are given. Please choose only one.') - + break + # Check if input is given as dist or input_data. self.input_data_given = -1 - for marg in inputs.Marginals: + for marg in Inputs.Marginals: + #print(self.input_data_given) size = np.array(marg.input_data).shape[0] - if size and abs(self.input_data_given) != 1: + #print(f'Size: {size}') + if size and abs(self.input_data_given) !=1: self.input_data_given = 2 break if (not size) and self.input_data_given > 0: @@ -93,16 +88,17 @@ class InputSpace: self.input_data_given = 0 if size: self.input_data_given = 1 - + if self.input_data_given == 2: raise AssertionError('Distributions cannot be built as the priors have different types') - + + # Get the bounds if input_data are directly defined by user: if self.input_data_given: for i in range(self.ndim): - low_bound = np.min(inputs.Marginals[i].input_data) - up_bound = np.max(inputs.Marginals[i].input_data) - inputs.Marginals[i].parameters = [low_bound, up_bound] + low_bound = np.min(Inputs.Marginals[i].input_data) + up_bound = np.max(Inputs.Marginals[i].input_data) + Inputs.Marginals[i].parameters = [low_bound, up_bound] # ------------------------------------------------------------------------- def init_param_space(self, max_deg=None): @@ -114,7 +110,7 @@ class InputSpace: max_deg : int, optional Maximum degree. The default is `None`. - Returns + Creates ------- raw_data : array of shape (n_params, n_samples) Raw data. @@ -124,31 +120,32 @@ class InputSpace: """ # Recheck all before running! self.check_valid_inputs() - - inputs = self.InputObj + + Inputs = self.InputObj ndim = self.ndim - rosenblatt_flag = inputs.Rosenblatt + rosenblatt_flag = Inputs.Rosenblatt mc_size = 50000 # Save parameter names + self.par_names = [] for parIdx in range(ndim): - self.par_names.append(inputs.Marginals[parIdx].name) + self.par_names.append(Inputs.Marginals[parIdx].name) # Create a multivariate probability distribution # TODO: change this to make max_deg obligatory? at least in some specific cases? if max_deg is not None: - j_dist, poly_types = self.build_polytypes(rosenblatt=rosenblatt_flag) - self.JDist, self.poly_types = j_dist, poly_types + JDist, poly_types = self.build_polytypes(rosenblatt=rosenblatt_flag) + self.JDist, self.poly_types = JDist, poly_types if self.input_data_given: - self.MCSize = len(inputs.Marginals[0].input_data) + self.MCSize = len(Inputs.Marginals[0].input_data) self.raw_data = np.zeros((ndim, self.MCSize)) for parIdx in range(ndim): # Save parameter names try: self.raw_data[parIdx] = np.array( - inputs.Marginals[parIdx].input_data) + Inputs.Marginals[parIdx].input_data) except: self.raw_data[parIdx] = self.JDist[parIdx].sample(mc_size) @@ -166,9 +163,9 @@ class InputSpace: # Generate the bounds based on given inputs for marginals bound_tuples = [] for i in range(ndim): - if inputs.Marginals[i].dist_type == 'unif': - low_bound = inputs.Marginals[i].parameters[0] - up_bound = inputs.Marginals[i].parameters[1] + if Inputs.Marginals[i].dist_type == 'unif': + low_bound = Inputs.Marginals[i].parameters[0] + up_bound = Inputs.Marginals[i].parameters[1] else: low_bound = np.min(self.raw_data[i]) up_bound = np.max(self.raw_data[i]) @@ -193,26 +190,25 @@ class InputSpace: orig_space_dist : object A chaospy JDist object or a gaussian_kde object. poly_types : list - A list of polynomial types for the parameters. + List of polynomial types for the parameters. """ - inputs = self.InputObj - + Inputs = self.InputObj + all_data = [] all_dist_types = [] orig_joints = [] poly_types = [] - params = None - + for parIdx in range(self.ndim): - if inputs.Marginals[parIdx].dist_type is None: - data = inputs.Marginals[parIdx].input_data + if Inputs.Marginals[parIdx].dist_type is None: + data = Inputs.Marginals[parIdx].input_data all_data.append(data) dist_type = None else: - dist_type = inputs.Marginals[parIdx].dist_type - params = inputs.Marginals[parIdx].parameters + dist_type = Inputs.Marginals[parIdx].dist_type + params = Inputs.Marginals[parIdx].parameters if rosenblatt: polytype = 'hermite' @@ -224,27 +220,27 @@ class InputSpace: elif 'unif' in dist_type.lower(): polytype = 'legendre' - if not np.array(params).shape[0] >= 2: + if not np.array(params).shape[0]>=2: raise AssertionError('Distribution has too few parameters!') dist = chaospy.Uniform(lower=params[0], upper=params[1]) elif 'norm' in dist_type.lower() and \ - 'log' not in dist_type.lower(): - if not np.array(params).shape[0] >= 2: + 'log' not in dist_type.lower(): + if not np.array(params).shape[0]>=2: raise AssertionError('Distribution has too few parameters!') polytype = 'hermite' dist = chaospy.Normal(mu=params[0], sigma=params[1]) elif 'gamma' in dist_type.lower(): polytype = 'laguerre' - if not np.array(params).shape[0] >= 3: + if not np.array(params).shape[0]>=3: raise AssertionError('Distribution has too few parameters!') dist = chaospy.Gamma(shape=params[0], scale=params[1], shift=params[2]) elif 'beta' in dist_type.lower(): - if not np.array(params).shape[0] >= 4: + if not np.array(params).shape[0]>=4: raise AssertionError('Distribution has too few parameters!') polytype = 'jacobi' dist = chaospy.Beta(alpha=params[0], beta=params[1], @@ -252,29 +248,29 @@ class InputSpace: elif 'lognorm' in dist_type.lower(): polytype = 'hermite' - if not np.array(params).shape[0] >= 2: + if not np.array(params).shape[0]>=2: raise AssertionError('Distribution has too few parameters!') - mu = np.log(params[0] ** 2 / np.sqrt(params[0] ** 2 + params[1] ** 2)) - sigma = np.sqrt(np.log(1 + params[1] ** 2 / params[0] ** 2)) + mu = np.log(params[0]**2/np.sqrt(params[0]**2 + params[1]**2)) + sigma = np.sqrt(np.log(1 + params[1]**2 / params[0]**2)) dist = chaospy.LogNormal(mu, sigma) # dist = chaospy.LogNormal(mu=params[0], sigma=params[1]) elif 'expon' in dist_type.lower(): polytype = 'exponential' - if not np.array(params).shape[0] >= 2: + if not np.array(params).shape[0]>=2: raise AssertionError('Distribution has too few parameters!') dist = chaospy.Exponential(scale=params[0], shift=params[1]) elif 'weibull' in dist_type.lower(): polytype = 'weibull' - if not np.array(params).shape[0] >= 3: + if not np.array(params).shape[0]>=3: raise AssertionError('Distribution has too few parameters!') dist = chaospy.Weibull(shape=params[0], scale=params[1], shift=params[2]) else: message = (f"DistType {dist_type} for parameter" - f"{parIdx + 1} is not available.") + f"{parIdx+1} is not available.") raise ValueError(message) if self.input_data_given or self.apce: @@ -288,16 +284,16 @@ class InputSpace: # Prepare final output to return if None in all_dist_types: # Naive approach: Fit a gaussian kernel to the provided data - data = np.asarray(all_data) + Data = np.asarray(all_data) try: - orig_space_dist = st.gaussian_kde(data) + orig_space_dist = st.gaussian_kde(Data) except: raise ValueError('The samples provided to the Marginals should be 1D only') self.prior_space = orig_space_dist else: orig_space_dist = chaospy.J(*orig_joints) try: - self.prior_space = st.gaussian_kde(orig_space_dist.sample(np.array([10000]))) + self.prior_space = st.gaussian_kde(orig_space_dist.sample(10000)) except: raise ValueError('Parameter values are not valid, please set differently') @@ -313,55 +309,51 @@ class InputSpace: ---------- X : array of shape (n_samples,n_params) Samples to be transformed. - params : list - Additional parameters for the gamma distribution method : string If transformation method is 'user' transform X, else just pass X. Returns ------- - tr_x: array of shape (n_samples,n_params) + tr_X: array of shape (n_samples,n_params) Transformed samples. """ # Check for built JDist if not hasattr(self, 'JDist'): raise AttributeError('Call function init_param_space first to create JDist') - + # Check if X is 2d if X.ndim != 2: raise AttributeError('X should have two dimensions') - + # Check if size of X matches Marginals - if X.shape[1] != self.ndim: - raise AttributeError( - 'The second dimension of X should be the same size as the number of marginals in the InputObj') - + if X.shape[1]!= self.ndim: + raise AttributeError('The second dimension of X should be the same size as the number of marginals in the InputObj') + if self.InputObj.Rosenblatt: self.origJDist, _ = self.build_polytypes(False) if method == 'user': - tr_x = self.JDist.inv(self.origJDist.fwd(X.T)).T + tr_X = self.JDist.inv(self.origJDist.fwd(X.T)).T else: # Inverse to original spcace -- generate sample ED - tr_x = self.origJDist.inv(self.JDist.fwd(X.T)).T + tr_X = self.origJDist.inv(self.JDist.fwd(X.T)).T else: # Transform samples via an isoprobabilistic transformation n_samples, n_params = X.shape - inputs = self.InputObj + Inputs = self.InputObj origJDist = self.JDist poly_types = self.poly_types - inv_cdf = None disttypes = [] for par_i in range(n_params): - disttypes.append(inputs.Marginals[par_i].dist_type) + disttypes.append(Inputs.Marginals[par_i].dist_type) # Pass non-transformed X, if arbitrary PCE is selected. if None in disttypes or self.input_data_given or self.apce: return X - cdfx = np.zeros(X.shape) - tr_x = np.zeros(X.shape) + cdfx = np.zeros((X.shape)) + tr_X = np.zeros((X.shape)) for par_i in range(n_params): @@ -378,29 +370,29 @@ class InputSpace: # polyType if polytype == 'legendre' or disttype == 'uniform': # Generate Y_Dists based - params_y = [-1, 1] - dist_y = st.uniform(loc=params_y[0], - scale=params_y[1] - params_y[0]) - inv_cdf = np.vectorize(lambda x: dist_y.ppf(x)) + params_Y = [-1, 1] + dist_Y = st.uniform(loc=params_Y[0], + scale=params_Y[1]-params_Y[0]) + inv_cdf = np.vectorize(lambda x: dist_Y.ppf(x)) elif polytype == 'hermite' or disttype == 'norm': - params_y = [0, 1] - dist_y = st.norm(loc=params_y[0], scale=params_y[1]) - inv_cdf = np.vectorize(lambda x: dist_y.ppf(x)) + params_Y = [0, 1] + dist_Y = st.norm(loc=params_Y[0], scale=params_Y[1]) + inv_cdf = np.vectorize(lambda x: dist_Y.ppf(x)) elif polytype == 'laguerre' or disttype == 'gamma': if params == None: raise AttributeError('Additional parameters have to be set for the gamma distribution!') - params_y = [1, params[1]] - + params_Y = [1, params[1]] + # TOOD: update the call to the gamma function, seems like source code has been changed! - dist_y = st.gamma(loc=params_y[0], scale=params_y[1]) - inv_cdf = np.vectorize(lambda x: dist_y.ppf(x)) + dist_Y = st.gamma(loc=params_Y[0], scale=params_Y[1]) + inv_cdf = np.vectorize(lambda x: dist_Y.ppf(x)) # Compute CDF_x(X) cdfx[:, par_i] = cdf(X[:, par_i]) # Compute invCDF_y(cdfx) - tr_x[:, par_i] = inv_cdf(cdfx[:, par_i]) + tr_X[:, par_i] = inv_cdf(cdfx[:, par_i]) - return tr_x + return tr_X diff --git a/src/bayesvalidrox/surrogate_models/sequential_design.py b/src/bayesvalidrox/surrogate_models/sequential_design.py index d2cc2d5ea..fc81dcd45 100644 --- a/src/bayesvalidrox/surrogate_models/sequential_design.py +++ b/src/bayesvalidrox/surrogate_models/sequential_design.py @@ -75,7 +75,7 @@ class SeqDesign(): # Get the parameters max_n_samples = MetaModel.ExpDesign.n_max_samples mod_LOO_threshold = MetaModel.ExpDesign.mod_LOO_threshold - n_canddidate = MetaModel.ExpDesign.n_candidate + n_canddidate = MetaModel.ExpDesign.n_canddidate post_snapshot = MetaModel.ExpDesign.post_snapshot n_replication = MetaModel.ExpDesign.n_replication util_func = MetaModel.ExpDesign.util_func diff --git a/src/bayesvalidrox/surrogate_models/surrogate_models.py b/src/bayesvalidrox/surrogate_models/surrogate_models.py index c4e3f9b26..5968d3a06 100644 --- a/src/bayesvalidrox/surrogate_models/surrogate_models.py +++ b/src/bayesvalidrox/surrogate_models/surrogate_models.py @@ -7,6 +7,7 @@ Implementation of metamodel as either PC, aPC or GPE import warnings import numpy as np import math +import h5py import matplotlib.pyplot as plt from sklearn.preprocessing import MinMaxScaler import scipy as sp @@ -28,85 +29,13 @@ from .reg_fast_laplace import RegressionFastLaplace from .orthogonal_matching_pursuit import OrthogonalMatchingPursuit from .bayes_linear import VBLinearRegression, EBLinearRegression from .apoly_construction import apoly_construction - warnings.filterwarnings("ignore") # Load the mplstyle plt.style.use(os.path.join(os.path.split(__file__)[0], '../', 'bayesvalidrox.mplstyle')) -def gaussian_process_emulator(X, y, nug_term=None, autoSelect=False, - varIdx=None): - """ - Fits a Gaussian Process Emulator to the target given the training - points. - - Parameters - ---------- - X : array of shape (n_samples, n_params) - Training points. - y : array of shape (n_samples,) - Target values. - nug_term : float, optional - Nugget term. The default is None, i.e. variance of y. - autoSelect : bool, optional - Loop over some kernels and select the best. The default is False. - varIdx : int, optional - The index number. The default is None. - - Returns - ------- - gp : object - Fitted estimator. - - """ - - nug_term = nug_term if nug_term else np.var(y) - - Kernels = [nug_term * kernels.RBF(length_scale=1.0, - length_scale_bounds=(1e-25, 1e15)), - nug_term * kernels.RationalQuadratic(length_scale=0.2, - alpha=1.0), - nug_term * kernels.Matern(length_scale=1.0, - length_scale_bounds=(1e-15, 1e5), - nu=1.5)] - - # Automatic selection of the kernel - if autoSelect: - gp = {} - BME = [] - for i, kernel in enumerate(Kernels): - gp[i] = GaussianProcessRegressor(kernel=kernel, - n_restarts_optimizer=3, - normalize_y=False) - - # Fit to data using Maximum Likelihood Estimation - gp[i].fit(X, y) - - # Store the MLE as BME score - BME.append(gp[i].log_marginal_likelihood()) - - gp = gp[np.argmax(BME)] - - else: - gp = GaussianProcessRegressor(kernel=Kernels[0], - n_restarts_optimizer=3, - normalize_y=False) - gp.fit(X, y) - - # Compute score - if varIdx is not None: - Score = gp.score(X, y) - print('-' * 50) - print(f'Output variable {varIdx}:') - print('The estimation of GPE coefficients converged,') - print(f'with the R^2 score: {Score:.3f}') - print('-' * 50) - - return gp - - -class MetaModel: +class MetaModel(): """ Meta (surrogate) model @@ -170,21 +99,18 @@ class MetaModel: To define the sampling methods and the training set, an experimental design instance shall be defined. This can be done by: - >>> MetaModelOpts.add_input_space() + >>> MetaModelOpts.add_InputSpace() Two experimental design schemes are supported: one-shot (`normal`) and adaptive sequential (`sequential`) designs. For experimental design refer to `InputSpace`. """ - input_obj: InputSpace - pce_reg_method: str - apply_constraints: bool def __init__(self, input_obj, meta_model_type='PCE', pce_reg_method='OLS', bootstrap_method='fast', n_bootstrap_itrs=1, pce_deg=1, pce_q_norm=1.0, - dim_red_method='no', apply_constraints=False, + dim_red_method='no', apply_constraints = False, verbose=False): self.input_obj = input_obj @@ -197,43 +123,10 @@ class MetaModel: self.dim_red_method = dim_red_method self.apply_constraints = apply_constraints self.verbose = verbose - - # More parameters and fields - self.allBasisIndices = None - self.basis_dict = None - self.clf_poly = None - self.coeffs_dict = None - self.collocation_points = None - self.deg_array = None - self.deg_dict = None - self.errorclf_poly = None - self.errorRegMethod = None - self.errorScale = None - self.gp_poly = None - self.init_type = None - self.InputSpace = None - self.LCerror = None - self.n_params = None - self.n_pca_components = None - self.n_samples = None - self.nlc = None - self.ndim = None - self.out_names = None - self.pca = None - self.polycoeffs = None - self.q_norm_dict = None - self.score_dict = None - self.univ_p_val = None - self.x_scaler = None - - def build_metamodel(self, n_init_samples: int = None) -> None: + + def build_metamodel(self, n_init_samples = None) -> None: """ - Builds the parts for the metamodel (polynomes,...) that are needed before fitting. - - Parameters - ---------- - n_init_samples : int - Number of initial samples + Builds the parts for the metamodel (polynomes,...) that are neede before fitting. Returns ------- @@ -241,75 +134,76 @@ class MetaModel: DESCRIPTION. """ - + # Generate general warnings if self.apply_constraints or self.pce_reg_method.lower() == 'ols': print('There are no estimations of surrogate uncertainty available' ' for the chosen regression options. This might lead to issues' ' in later steps.') - + # Add InputSpace to MetaModel if it does not have any if not hasattr(self, 'InputSpace'): self.InputSpace = InputSpace(self.input_obj) self.InputSpace.n_init_samples = n_init_samples self.InputSpace.init_param_space(np.max(self.pce_deg)) - + self.ndim = self.InputSpace.ndim - + if not hasattr(self, 'CollocationPoints'): raise AttributeError('Please provide samples to the metamodel before building it.') - self.collocation_points = np.array(self.collocation_points) - + self.CollocationPoints = np.array(self.CollocationPoints) + # Transform input samples # TODO: this is probably not yet correct! Make 'method' variable - self.collocation_points = self.InputSpace.transform(self.collocation_points, method='user') + self.CollocationPoints = self.InputSpace.transform(self.CollocationPoints, method='user') + self.n_params = len(self.input_obj.Marginals) - + # Generate polynomials if self.meta_model_type.lower() != 'gpe': self.generate_polynomials(np.max(self.pce_deg)) # Initialize the nested dictionaries if self.meta_model_type.lower() == 'gpe': - self.gp_poly = self.AutoVivification() - self.x_scaler = self.AutoVivification() - self.LCerror = self.AutoVivification() + self.gp_poly = self.auto_vivification() + self.x_scaler = self.auto_vivification() + self.LCerror = self.auto_vivification() else: - self.deg_dict = self.AutoVivification() - self.q_norm_dict = self.AutoVivification() - self.coeffs_dict = self.AutoVivification() - self.basis_dict = self.AutoVivification() - self.score_dict = self.AutoVivification() - self.clf_poly = self.AutoVivification() - self.LCerror = self.AutoVivification() + self.deg_dict = self.auto_vivification() + self.q_norm_dict = self.auto_vivification() + self.coeffs_dict = self.auto_vivification() + self.basis_dict = self.auto_vivification() + self.score_dict = self.auto_vivification() + self.clf_poly = self.auto_vivification() + self.LCerror = self.auto_vivification() if self.dim_red_method.lower() == 'pca': - self.pca = self.AutoVivification() + self.pca = self.auto_vivification() # Define an array containing the degrees - self.collocation_points = np.array(self.collocation_points) - self.n_samples, ndim = self.collocation_points.shape + self.CollocationPoints = np.array(self.CollocationPoints) + self.n_samples, ndim = self.CollocationPoints.shape if self.ndim != ndim: - raise AttributeError( - 'The given samples do not match the given number of priors. The samples should be a 2D array of size' - '(#samples, #priors)') - + raise AttributeError('The given samples do not match the given number of priors. The samples should be a 2D array of size (#samples, #priors)') + self.deg_array = self.__select_degree(ndim, self.n_samples) # Generate all basis indices - self.allBasisIndices = self.AutoVivification() + self.allBasisIndices = self.auto_vivification() for deg in self.deg_array: keys = self.allBasisIndices.keys() if deg not in np.fromiter(keys, dtype=float): # Generate the polynomial basis indices for qidx, q in enumerate(self.pce_q_norm): - basis_indices = glexindex(start=0, stop=deg + 1, + basis_indices = glexindex(start=0, stop=deg+1, dimensions=self.n_params, cross_truncation=q, reverse=False, graded=True) self.allBasisIndices[str(deg)][str(q)] = basis_indices - def fit(self, X, y, parallel=True, verbose=False): + + + def fit(self, X, y, parallel = True, verbose = False): """ Fits the surrogate to the given data (samples X, outputs y). Note here that the samples X should be the transformed samples provided @@ -321,37 +215,37 @@ class MetaModel: The parameter value combinations that the model was evaluated at. y : dict of 2D lists or arrays of shape (#samples, #timesteps) The respective model evaluations. - parallel : bool - Set to true to run the training for various input keys in parallel. - verbose : bool - Set to 'True' to get more outputs during the training. Returns ------- None. """ +# print(X) +# print(X.shape) +# print(y) +# print(y['Z'].shape) X = np.array(X) for key in y.keys(): y_val = np.array(y[key]) - if y_val.ndim != 2: + if y_val.ndim !=2: raise ValueError('The given outputs y should be 2D') y[key] = np.array(y[key]) - + # Output names are the same as the keys in y self.out_names = list(y.keys()) - + # Build the MetaModel on the static samples - self.collocation_points = X - + self.CollocationPoints = X + # TODO: other option: rebuild every time if not hasattr(self, 'deg_array'): - self.build_metamodel(n_init_samples=X.shape[1]) - + self.build_metamodel(n_init_samples = X.shape[1]) + # Evaluate the univariate polynomials on InputSpace if self.meta_model_type.lower() != 'gpe': - self.univ_p_val = self.univ_basis_vals(self.collocation_points) - + self.univ_p_val = self.univ_basis_vals(self.CollocationPoints) + # --- Loop through data points and fit the surrogate --- if verbose: print(f"\n>>>> Training the {self.meta_model_type} metamodel " @@ -363,10 +257,10 @@ class MetaModel: self.n_bootstrap_itrs = 100 # Check if fast version (update coeffs with OLS) is selected. - first_out = {} - n_comp_dict = {} if self.bootstrap_method.lower() == 'fast': fast_bootstrap = True + first_out = {} + n_comp_dict = {} else: fast_bootstrap = False @@ -406,8 +300,8 @@ class MetaModel: # Start transformation pca, target, n_comp = self.pca_transformation( Output[b_indices], verbose=False - ) - self.pca[f'b_{b_i + 1}'][key] = pca + ) + self.pca[f'b_{b_i+1}'][key] = pca # Store the number of components for fast bootsrtrapping if fast_bootstrap and b_i == 0: n_comp_dict[key] = n_comp @@ -416,28 +310,27 @@ class MetaModel: target = Output[b_indices] # Parallel fit regression - out = None if self.meta_model_type.lower() == 'gpe': # Prepare the input matrix scaler = MinMaxScaler() X_S = scaler.fit_transform(X_train_b) - self.x_scaler[f'b_{b_i + 1}'][key] = scaler + self.x_scaler[f'b_{b_i+1}'][key] = scaler if parallel: out = Parallel(n_jobs=-1, backend='multiprocessing')( - delayed(gaussian_process_emulator)( + delayed(self.gaussian_process_emulator)( X_S, target[:, idx]) for idx in range(target.shape[1])) else: - results = map(gaussian_process_emulator, - [X_train_b] * target.shape[1], + results = map(self.gaussian_process_emulator, + [X_train_b]*target.shape[1], [target[:, idx] for idx in range(target.shape[1])] ) out = list(results) for idx in range(target.shape[1]): - self.gp_poly[f'b_{b_i + 1}'][key][f"y_{idx + 1}"] = out[idx] + self.gp_poly[f'b_{b_i+1}'][key][f"y_{idx+1}"] = out[idx] else: self.univ_p_val = self.univ_p_val[b_indices] @@ -449,7 +342,7 @@ class MetaModel: for idx in range(target.shape[1])) elif not parallel and (not fast_bootstrap or b_i == 0): results = map(self.adaptive_regression, - [X_train_b] * target.shape[1], + [X_train_b]*target.shape[1], [target[:, idx] for idx in range(target.shape[1])], range(target.shape[1])) @@ -460,18 +353,19 @@ class MetaModel: first_out[key] = copy.deepcopy(out) if b_i > 0 and fast_bootstrap: + # fast bootstrap out = self.update_pce_coeffs( X_train_b, target, first_out[key]) for i in range(target.shape[1]): # Create a dict to pass the variables - self.deg_dict[f'b_{b_i + 1}'][key][f"y_{i + 1}"] = out[i]['degree'] - self.q_norm_dict[f'b_{b_i + 1}'][key][f"y_{i + 1}"] = out[i]['qnorm'] - self.coeffs_dict[f'b_{b_i + 1}'][key][f"y_{i + 1}"] = out[i]['coeffs'] - self.basis_dict[f'b_{b_i + 1}'][key][f"y_{i + 1}"] = out[i]['multi_indices'] - self.score_dict[f'b_{b_i + 1}'][key][f"y_{i + 1}"] = out[i]['LOOCVScore'] - self.clf_poly[f'b_{b_i + 1}'][key][f"y_{i + 1}"] = out[i]['clf_poly'] + self.deg_dict[f'b_{b_i+1}'][key][f"y_{i+1}"] = out[i]['degree'] + self.q_norm_dict[f'b_{b_i+1}'][key][f"y_{i+1}"] = out[i]['qnorm'] + self.coeffs_dict[f'b_{b_i+1}'][key][f"y_{i+1}"] = out[i]['coeffs'] + self.basis_dict[f'b_{b_i+1}'][key][f"y_{i+1}"] = out[i]['multi_indices'] + self.score_dict[f'b_{b_i+1}'][key][f"y_{i+1}"] = out[i]['LOOCVScore'] + self.clf_poly[f'b_{b_i+1}'][key][f"y_{i+1}"] = out[i]['clf_poly'] #self.LCerror[f'b_{b_i+1}'][key][f"y_{i+1}"] = out[i]['LCerror'] if verbose: @@ -479,7 +373,7 @@ class MetaModel: " sucessfully completed. <<<<<<\n") # ------------------------------------------------------------------------- - def update_pce_coeffs(self, X, y, out_dict=None): + def update_pce_coeffs(self, X, y, out_dict = None): """ Updates the PCE coefficents using only the ordinary least square method for the fast version of the bootstrapping. @@ -500,13 +394,13 @@ class MetaModel: The updated training output dictionary. """ - # TODO: recheck this whole function # Make a copy final_out_dict = copy.deepcopy(out_dict) # Loop over the points for i in range(y.shape[1]): + # Extract nonzero basis indices nnz_idx = np.nonzero(out_dict[i]['coeffs'])[0] if len(nnz_idx) != 0: @@ -519,7 +413,7 @@ class MetaModel: updated_out = self.regression( psi, y[:, i], basis_indices, reg_method='OLS', sparsity=False - ) + ) # Update coeffs in out_dict final_out_dict[i]['coeffs'][nnz_idx] = updated_out['coeffs'] @@ -527,7 +421,7 @@ class MetaModel: return final_out_dict # ------------------------------------------------------------------------- - def add_input_space(self): + def add_InputSpace(self): """ Instanciates experimental design object. @@ -537,7 +431,7 @@ class MetaModel: """ self.InputSpace = InputSpace(self.input_obj, - meta_model_type=self.meta_model_type) + meta_Model_type=self.meta_model_type) # ------------------------------------------------------------------------- def univ_basis_vals(self, samples, n_max=None): @@ -617,7 +511,7 @@ class MetaModel: raise ValueError( f"The shapes of basis_indices ({basis_indices.shape[1]}) and " f"univ_p_val ({n_params}) don't match!!" - ) + ) # Preallocate the Psi matrix for performance psi = np.ones((n_samples, n_terms)) @@ -625,8 +519,8 @@ class MetaModel: for m in range(basis_indices.shape[1]): aa = np.where(basis_indices[:, m] > 0)[0] try: - basis_idx = basis_indices[aa, m] - bb = univ_p_val[:, m, basis_idx].reshape(psi[:, aa].shape) + basisIdx = basis_indices[aa, m] + bb = univ_p_val[:, m, basisIdx].reshape(psi[:, aa].shape) psi[:, aa] = np.multiply(psi[:, aa], bb) except ValueError as err: raise err @@ -647,9 +541,7 @@ class MetaModel: basis_indices : array of shape (n_terms, n_params) Multi-indices of multivariate polynomials. reg_method : str, optional - The chosen regression method. The default is None. - sparsity : bool - Set to True when sparsity is considered. The default is True. + DESCRIPTION. The default is None. Returns ------- @@ -683,7 +575,7 @@ class MetaModel: clf_poly.converged = True elif reg_method.lower() == 'ard': - if X.shape[0] < 2: + if X.shape[0]<2: raise ValueError('Regression with ARD can only be performed for more than 2 samples') clf_poly = lm.ARDRegression(fit_intercept=False, #normalize=True, @@ -699,14 +591,14 @@ class MetaModel: n_iter=300, tol=1e-10) elif reg_method.lower() == 'bcs': - if X.shape[0] < 10: + if X.shape[0]<10: raise ValueError('Regression with BCS can only be performed for more than 10 samples') clf_poly = RegressionFastLaplace(fit_intercept=False, - bias_term=bias_term, - n_iter=1000, tol=1e-7) + bias_term=bias_term, + n_iter=1000, tol=1e-7) elif reg_method.lower() == 'lars': - if X.shape[0] < 10: + if X.shape[0]<10: raise ValueError('Regression with LARS can only be performed for more than 5 samples') clf_poly = lm.LassoLarsCV(fit_intercept=False) @@ -722,29 +614,29 @@ class MetaModel: elif reg_method.lower() == 'ebl': clf_poly = EBLinearRegression(optimizer='em') - + + # Training with constraints automatically uses L2 - if self.apply_constraints: + if self.apply_constraints: # TODO: set the constraints here # Define the nonlin. constraint - nlc = NonlinearConstraint(lambda x: np.matmul(X, x), -1, 1.1) + nlc = NonlinearConstraint(lambda x: np.matmul(X,x),-1,1.1) self.nlc = nlc - - fun = lambda x: (np.linalg.norm(np.matmul(X, x) - y, ord=2)) ** 2 - res = None - if self.init_type == 'zeros': - res = minimize(fun, np.zeros(X.shape[1]), method='trust-constr', constraints=self.nlc) + + fun = lambda x: (np.linalg.norm(np.matmul(X, x)-y, ord = 2))**2 + if self.init_type =='zeros': + res = minimize(fun, np.zeros(X.shape[1]), method = 'trust-constr', constraints = self.nlc) if self.init_type == 'nonpi': clf_poly.fit(X, y) coeff = clf_poly.coef_ - res = minimize(fun, coeff, method='trust-constr', constraints=self.nlc) - + res = minimize(fun, coeff, method = 'trust-constr', constraints = self.nlc) + coeff = np.array(res.x) clf_poly.coef_ = coeff clf_poly.X = X clf_poly.y = y clf_poly.intercept_ = 0 - + # Training without constraints uses chosen regression method else: clf_poly.fit(X, y) @@ -772,15 +664,76 @@ class MetaModel: return_out_dict['sparePsi'] = sparse_X return_out_dict['coeffs'] = coeffs return return_out_dict + + # ------------------------------------------------------------------------- + def create_psi(self, basis_indices, univ_p_val): + """ + This function assemble the design matrix Psi from the given basis index + set INDICES and the univariate polynomial evaluations univ_p_val. + + Parameters + ---------- + basis_indices : array of shape (n_terms, n_params) + Multi-indices of multivariate polynomials. + univ_p_val : array of (n_samples, n_params, n_max+1) + All univariate regressors up to `n_max`. + + Raises + ------ + ValueError + n_terms in arguments do not match. + + Returns + ------- + psi : array of shape (n_samples, n_terms) + Multivariate regressors. + + """ + # Check if BasisIndices is a sparse matrix + sparsity = sp.sparse.issparse(basis_indices) + if sparsity: + basis_indices = basis_indices.toarray() + + # Initialization and consistency checks + # number of input variables + n_params = univ_p_val.shape[1] + + # Size of the experimental design + n_samples = univ_p_val.shape[0] + + # number of basis terms + n_terms = basis_indices.shape[0] + + # check that the variables have consistent sizes + if n_params != basis_indices.shape[1]: + raise ValueError( + f"The shapes of basis_indices ({basis_indices.shape[1]}) and " + f"univ_p_val ({n_params}) don't match!!" + ) + + # Preallocate the Psi matrix for performance + psi = np.ones((n_samples, n_terms)) + # Assemble the Psi matrix + for m in range(basis_indices.shape[1]): + aa = np.where(basis_indices[:, m] > 0)[0] + try: + basisIdx = basis_indices[aa, m] + bb = univ_p_val[:, m, basisIdx].reshape(psi[:, aa].shape) + psi[:, aa] = np.multiply(psi[:, aa], bb) + except ValueError as err: + raise err + return psi # -------------------------------------------------------------------------------------------------------- - def adaptive_regression(self, ED_Y, varIdx, verbose=False): + def adaptive_regression(self, ED_X, ED_Y, varIdx, verbose=False): """ Adaptively fits the PCE model by comparing the scores of different degrees and q-norm. Parameters ---------- + ED_X : array of shape (n_samples, n_params) + Experimental design. ED_Y : array of shape (n_samples,) Target values, i.e. simulation results for the Experimental design. varIdx : int @@ -795,6 +748,8 @@ class MetaModel: coefficients. """ + + n_samples, n_params = ED_X.shape # Initialization qAllCoeffs, AllCoeffs = {}, {} qAllIndices_Sparse, AllIndices_Sparse = {}, {} @@ -814,7 +769,7 @@ class MetaModel: n_checks_qNorm = 2 nqnorms = len(qnorm) qNormEarlyStop = True - if nqnorms < n_checks_qNorm + 1: + if nqnorms < n_checks_qNorm+1: qNormEarlyStop = False # ===================================================================== @@ -847,25 +802,25 @@ class MetaModel: # Check the convergence of noise for FastARD if self.pce_reg_method == 'FastARD' and \ - outs['clf_poly'].alpha_ < np.finfo(np.float32).eps: + outs['clf_poly'].alpha_ < np.finfo(np.float32).eps: score = -np.inf qNormScores[qidx] = score - qAllCoeffs[str(qidx + 1)] = outs['coeffs'] - qAllIndices_Sparse[str(qidx + 1)] = outs['spareMulti-Index'] - qAllclf_poly[str(qidx + 1)] = outs['clf_poly'] - qAllnTerms[str(qidx + 1)] = BasisIndices.shape[0] - qAllLCerror[str(qidx + 1)] = LCerror + qAllCoeffs[str(qidx+1)] = outs['coeffs'] + qAllIndices_Sparse[str(qidx+1)] = outs['spareMulti-Index'] + qAllclf_poly[str(qidx+1)] = outs['clf_poly'] + qAllnTerms[str(qidx+1)] = BasisIndices.shape[0] + qAllLCerror[str(qidx+1)] = LCerror # EarlyStop check # if there are at least n_checks_qNorm entries after the # best one, we stop if qNormEarlyStop and \ - sum(np.isfinite(qNormScores)) > n_checks_qNorm: + sum(np.isfinite(qNormScores)) > n_checks_qNorm: # If the error has increased the last two iterations, stop! qNormScores_nonInf = qNormScores[np.isfinite(qNormScores)] deltas = np.sign(np.diff(qNormScores_nonInf)) - if sum(deltas[-n_checks_qNorm + 1:]) == 2: + if sum(deltas[-n_checks_qNorm+1:]) == 2: # stop the q-norm loop here break if np.var(ED_Y) == 0: @@ -875,11 +830,11 @@ class MetaModel: best_q = np.nanargmax(qNormScores) scores[degIdx] = qNormScores[best_q] - AllCoeffs[str(degIdx + 1)] = qAllCoeffs[str(best_q + 1)] - AllIndices_Sparse[str(degIdx + 1)] = qAllIndices_Sparse[str(best_q + 1)] - Allclf_poly[str(degIdx + 1)] = qAllclf_poly[str(best_q + 1)] - AllnTerms[str(degIdx + 1)] = qAllnTerms[str(best_q + 1)] - AllLCerror[str(degIdx + 1)] = qAllLCerror[str(best_q + 1)] + AllCoeffs[str(degIdx+1)] = qAllCoeffs[str(best_q+1)] + AllIndices_Sparse[str(degIdx+1)] = qAllIndices_Sparse[str(best_q+1)] + Allclf_poly[str(degIdx+1)] = qAllclf_poly[str(best_q+1)] + AllnTerms[str(degIdx+1)] = qAllnTerms[str(best_q+1)] + AllLCerror[str(degIdx+1)] = qAllLCerror[str(best_q+1)] # Check the direction of the error (on average): # if it increases consistently stop the iterations @@ -887,7 +842,7 @@ class MetaModel: scores_nonInf = scores[scores != -np.inf] ss = np.sign(scores_nonInf - np.max(scores_nonInf)) # ss<0 error decreasing - errorIncreases = np.sum(np.sum(ss[-2:])) <= -1 * n_checks_degree + errorIncreases = np.sum(np.sum(ss[-2:])) <= -1*n_checks_degree if errorIncreases: break @@ -898,7 +853,7 @@ class MetaModel: # ------------------ Summary of results ------------------ # Select the one with the best score and save the necessary outputs - best_deg = np.nanargmax(scores) + 1 + best_deg = np.nanargmax(scores)+1 coeffs = AllCoeffs[str(best_deg)] basis_indices = AllIndices_Sparse[str(best_deg)] clf_poly = Allclf_poly[str(best_deg)] @@ -914,24 +869,24 @@ class MetaModel: nnz_idx = np.nonzero(coeffs)[0] BasisIndices_Sparse = basis_indices[nnz_idx] - print(f'Output variable {varIdx + 1}:') + print(f'Output variable {varIdx+1}:') print('The estimation of PCE coefficients converged at polynomial ' - f'degree {deg_array[best_deg - 1]} with ' + f'degree {deg_array[best_deg-1]} with ' f'{len(BasisIndices_Sparse)} terms (Sparsity index = ' - f'{round(len(BasisIndices_Sparse) / P, 3)}).') + f'{round(len(BasisIndices_Sparse)/P, 3)}).') - print(f'Final ModLOO error estimate: {1 - max(scores):.3e}') - print('\n' + '-' * 50) + print(f'Final ModLOO error estimate: {1-max(scores):.3e}') + print('\n'+'-'*50) if verbose: - print('=' * 50) - print(' ' * 10 + ' Summary of results ') - print('=' * 50) + print('='*50) + print(' '*10 + ' Summary of results ') + print('='*50) print("Scores:\n", scores) - print("Degree of best score:", self.deg_array[best_deg - 1]) + print("Degree of best score:", self.deg_array[best_deg-1]) print("No. of terms:", len(basis_indices)) - print("Sparsity index:", round(len(basis_indices) / P, 3)) + print("Sparsity index:", round(len(basis_indices)/P, 3)) print("Best Indices:\n", basis_indices) if self.pce_reg_method in ['BRR', 'ARD']: @@ -950,7 +905,7 @@ class MetaModel: plt.text(0.75, 0.5, text, fontsize=18, transform=ax.transAxes) plt.show() - print('=' * 80) + print('='*80) # Create a dict to pass the outputs returnVars = dict() @@ -1013,16 +968,14 @@ class MetaModel: # Build the projection matrix PsiTPsi = np.dot(psi_sparse.T, psi_sparse) - if np.linalg.cond(PsiTPsi) > 1e-12: #and \ - # np.linalg.cond(PsiTPsi) < 1/sys.float_info.epsilon: + if np.linalg.cond(PsiTPsi) > 1e-12: #and \ + # np.linalg.cond(PsiTPsi) < 1/sys.float_info.epsilon: # faster try: M = sp.linalg.solve(PsiTPsi, - sp.sparse.eye(PsiTPsi.shape[0]).toarray()) + sp.sparse.eye(PsiTPsi.shape[0]).toarray()) except: - raise AttributeError( - 'There are too few samples for the corrected loo-cv error. Fit surrogate on at least as many ' - 'samples as parameters to use this') + raise AttributeError('There are too few samples for the corrected loo-cv error. Fit surrogate on at least as many samples as parameters to use this') else: # stabler M = np.linalg.pinv(PsiTPsi) @@ -1031,7 +984,7 @@ class MetaModel: # only the trace is, to save memory) PsiM = np.dot(psi_sparse, M) - h = np.sum(np.multiply(PsiM, psi_sparse), axis=1, dtype=np.longdouble) #float128) + h = np.sum(np.multiply(PsiM, psi_sparse), axis=1, dtype=np.longdouble)#float128) # ------ Calculate Error Loocv for each measurement point ---- # Residuals @@ -1044,15 +997,15 @@ class MetaModel: var_y = np.var(y) if var_y == 0: - # norm_emp_error = 0 + norm_emp_error = 0 loo_error = 0 - LCerror = np.zeros(y.shape) - return 1 - loo_error, LCerror + LCerror = np.zeros((y.shape)) + return 1-loo_error, LCerror else: - # norm_emp_error = np.mean(residual ** 2) / var_y + norm_emp_error = np.mean(residual**2)/var_y # LCerror = np.divide(residual, (1-h)) - LCerror = residual / (1 - h) + LCerror = residual / (1-h) loo_error = np.mean(np.square(LCerror)) / var_y # if there are NaNs, just return an infinite LOO error (this # happens, e.g., when a strongly underdetermined problem is solved) @@ -1066,7 +1019,7 @@ class MetaModel: # Over-determined system of Equation if N > P: - T_factor = N / (N - P) * (1 + tr_M) + T_factor = N/(N-P) * (1 + tr_M) # Under-determined system of Equation else: @@ -1112,7 +1065,7 @@ class MetaModel: covar_matrix = sklearnPCA(n_components=None) covar_matrix.fit(target) var = np.cumsum(np.round(covar_matrix.explained_variance_ratio_, - decimals=5) * 100) + decimals=5)*100) # Find the number of components to explain self.varPCAThreshold of # variance try: @@ -1137,6 +1090,77 @@ class MetaModel: return pca, scaled_target, n_pca_components + # ------------------------------------------------------------------------- + def gaussian_process_emulator(self, X, y, nug_term=None, autoSelect=False, + varIdx=None): + """ + Fits a Gaussian Process Emulator to the target given the training + points. + + Parameters + ---------- + X : array of shape (n_samples, n_params) + Training points. + y : array of shape (n_samples,) + Target values. + nug_term : float, optional + Nugget term. The default is None, i.e. variance of y. + autoSelect : bool, optional + Loop over some kernels and select the best. The default is False. + varIdx : int, optional + The index number. The default is None. + + Returns + ------- + gp : object + Fitted estimator. + + """ + + nug_term = nug_term if nug_term else np.var(y) + + Kernels = [nug_term * kernels.RBF(length_scale=1.0, + length_scale_bounds=(1e-25, 1e15)), + nug_term * kernels.RationalQuadratic(length_scale=0.2, + alpha=1.0), + nug_term * kernels.Matern(length_scale=1.0, + length_scale_bounds=(1e-15, 1e5), + nu=1.5)] + + # Automatic selection of the kernel + if autoSelect: + gp = {} + BME = [] + for i, kernel in enumerate(Kernels): + gp[i] = GaussianProcessRegressor(kernel=kernel, + n_restarts_optimizer=3, + normalize_y=False) + + # Fit to data using Maximum Likelihood Estimation + gp[i].fit(X, y) + + # Store the MLE as BME score + BME.append(gp[i].log_marginal_likelihood()) + + gp = gp[np.argmax(BME)] + + else: + gp = GaussianProcessRegressor(kernel=Kernels[0], + n_restarts_optimizer=3, + normalize_y=False) + gp.fit(X, y) + + # Compute score + if varIdx is not None: + Score = gp.score(X, y) + print('-'*50) + print(f'Output variable {varIdx}:') + print('The estimation of GPE coefficients converged,') + print(f'with the R^2 score: {Score:.3f}') + print('-'*50) + + return gp + # ------------------------------------------------------------------------- def eval_metamodel(self, samples): """ @@ -1147,6 +1171,14 @@ class MetaModel: ---------- samples : array of shape (n_samples, n_params), optional Samples to evaluate meta-model at. The default is None. + nsamples : int, optional + Number of samples to generate, if no `samples` is provided. The + default is None. + sampling_method : str, optional + Type of sampling, if no `samples` is provided. The default is + 'random'. + return_samples : bool, optional + Retun samples, if no `samples` is provided. The default is False. Returns ------- @@ -1157,18 +1189,18 @@ class MetaModel: """ # Transform into np array - can also be given as list samples = np.array(samples) - + # Transform samples to the independent space samples = self.InputSpace.transform( samples, method='user' - ) + ) # Compute univariate bases for the given samples if self.meta_model_type.lower() != 'gpe': univ_p_val = self.univ_basis_vals( samples, n_max=np.max(self.pce_deg) - ) + ) mean_pred_b = {} std_pred_b = {} @@ -1177,9 +1209,9 @@ class MetaModel: # Extract model dictionary if self.meta_model_type.lower() == 'gpe': - model_dict = self.gp_poly[f'b_{b_i + 1}'] + model_dict = self.gp_poly[f'b_{b_i+1}'] else: - model_dict = self.coeffs_dict[f'b_{b_i + 1}'] + model_dict = self.coeffs_dict[f'b_{b_i+1}'] # Loop over outputs mean_pred = {} @@ -1193,30 +1225,30 @@ class MetaModel: # Prediction with GPE if self.meta_model_type.lower() == 'gpe': - X_T = self.x_scaler[f'b_{b_i + 1}'][output].transform(samples) - gp = self.gp_poly[f'b_{b_i + 1}'][output][in_key] + X_T = self.x_scaler[f'b_{b_i+1}'][output].transform(samples) + gp = self.gp_poly[f'b_{b_i+1}'][output][in_key] y_mean, y_std = gp.predict(X_T, return_std=True) else: # Prediction with PCE # Assemble Psi matrix - basis = self.basis_dict[f'b_{b_i + 1}'][output][in_key] + basis = self.basis_dict[f'b_{b_i+1}'][output][in_key] psi = self.create_psi(basis, univ_p_val) # Prediction if self.bootstrap_method != 'fast' or b_i == 0: # with error bar, i.e. use clf_poly - clf_poly = self.clf_poly[f'b_{b_i + 1}'][output][in_key] + clf_poly = self.clf_poly[f'b_{b_i+1}'][output][in_key] try: y_mean, y_std = clf_poly.predict( psi, return_std=True - ) + ) except TypeError: y_mean = clf_poly.predict(psi) y_std = np.zeros_like(y_mean) else: # without error bar - coeffs = self.coeffs_dict[f'b_{b_i + 1}'][output][in_key] + coeffs = self.coeffs_dict[f'b_{b_i+1}'][output][in_key] y_mean = np.dot(psi, coeffs) y_std = np.zeros_like(y_mean) @@ -1226,7 +1258,7 @@ class MetaModel: # Save predictions for each output if self.dim_red_method.lower() == 'pca': - PCA = self.pca[f'b_{b_i + 1}'][output] + PCA = self.pca[f'b_{b_i+1}'][output] mean_pred[output] = PCA.inverse_transform(mean) std_pred[output] = np.zeros(mean.shape) else: @@ -1262,7 +1294,7 @@ class MetaModel: return mean_pred, std_pred # ------------------------------------------------------------------------- - def create_model_error(self, X, y, MeasuredData): + def create_model_error(self, X, y, MeasuredData, name='Calib'): """ Fits a GPE-based model error. @@ -1273,7 +1305,9 @@ class MetaModel: extracted data. y : array of shape (n_outputs,) The model response for the MAP parameter set. - MeasuredData : + MeasuredData : + name : str, optional + Calibration or validation. The default is `'Calib'`. Returns ------- @@ -1283,8 +1317,8 @@ class MetaModel: """ outputNames = self.out_names self.errorRegMethod = 'GPE' - self.errorclf_poly = self.AutoVivification() - self.errorScale = self.AutoVivification() + self.errorclf_poly = self.auto_vivification() + self.errorScale = self.auto_vivification() # Read data # TODO: do this call outside the metamodel @@ -1306,7 +1340,7 @@ class MetaModel: delta = data # - y[out][0] BiasInputs = np.hstack((X[out], y[out].reshape(-1, 1))) X_S = scaler.fit_transform(BiasInputs) - gp = gaussian_process_emulator(X_S, delta) + gp = self.gaussian_process_emulator(X_S, delta) self.errorScale[out]["y_1"] = scaler self.errorclf_poly[out]["y_1"] = gp @@ -1361,7 +1395,7 @@ class MetaModel: return mean_pred, std_pred # ------------------------------------------------------------------------- - class AutoVivification(dict): + class auto_vivification(dict): """ Implementation of perl's AutoVivification feature. @@ -1388,13 +1422,13 @@ class MetaModel: """ # TODO: what properties should be moved to the new object? new_MetaModelOpts = copy.deepcopy(self) - new_MetaModelOpts.input_obj = self.input_obj # InputObj + new_MetaModelOpts.input_obj = self.input_obj#InputObj new_MetaModelOpts.InputSpace = self.InputSpace - # new_MetaModelOpts.InputSpace.meta_Model = 'aPCE' - # new_MetaModelOpts.InputSpace.InputObj = self.input_obj - # new_MetaModelOpts.InputSpace.ndim = len(self.input_obj.Marginals) + #new_MetaModelOpts.InputSpace.meta_Model = 'aPCE' + #new_MetaModelOpts.InputSpace.InputObj = self.input_obj + #new_MetaModelOpts.InputSpace.ndim = len(self.input_obj.Marginals) new_MetaModelOpts.n_params = len(self.input_obj.Marginals) - # new_MetaModelOpts.InputSpace.hdf5_file = None + #new_MetaModelOpts.InputSpace.hdf5_file = None return new_MetaModelOpts @@ -1420,9 +1454,9 @@ class MetaModel: # Define the deg_array max_deg = np.max(self.pce_deg) min_Deg = np.min(self.pce_deg) - + # TODO: remove the options for sequential? - # nitr = n_samples - self.InputSpace.n_init_samples + #nitr = n_samples - self.InputSpace.n_init_samples # Check q-norm if not np.isscalar(self.pce_q_norm): @@ -1431,66 +1465,41 @@ class MetaModel: self.pce_q_norm = np.array([self.pce_q_norm]) def M_uptoMax(maxDeg): - """ - Unknown - - Parameters - ---------- - maxDeg : int - Maximum degree - - Returns - ------- - n_combo - """ n_combo = np.zeros(maxDeg) - for i, d in enumerate(range(1, maxDeg + 1)): - n_combo[i] = math.factorial(ndim + d) + for i, d in enumerate(range(1, maxDeg+1)): + n_combo[i] = math.factorial(ndim+d) n_combo[i] /= math.factorial(ndim) * math.factorial(d) return n_combo deg_new = max_deg - # d = nitr if nitr != 0 and self.n_params > 5 else 1 + #d = nitr if nitr != 0 and self.n_params > 5 else 1 # d = 1 # min_index = np.argmin(abs(M_uptoMax(max_deg)-ndim*n_samples*d)) # deg_new = range(1, max_deg+1)[min_index] if deg_new > min_Deg and self.pce_reg_method.lower() != 'fastard': - deg_array = np.arange(min_Deg, deg_new + 1) + deg_array = np.arange(min_Deg, deg_new+1) else: deg_array = np.array([deg_new]) return deg_array def generate_polynomials(self, max_deg=None): - """ - Generates (univariate) polynomials for the set maximum polynomial degree. - - Parameters - ---------- - max_deg : int - Maximum polynomial degree. - - Returns - ------- - None - - """ # Check for InputSpace if not hasattr(self, 'InputSpace'): raise AttributeError('Generate or add InputSpace before generating polynomials') - + ndim = self.InputSpace.ndim # Create orthogonal polynomial coefficients if necessary - if (self.meta_model_type.lower() != 'gpe') and max_deg is not None: # and self.input_obj.poly_coeffs_flag: + if (self.meta_model_type.lower()!='gpe') and max_deg is not None:# and self.input_obj.poly_coeffs_flag: self.polycoeffs = {} for parIdx in tqdm(range(ndim), ascii=True, desc="Computing orth. polynomial coeffs"): poly_coeffs = apoly_construction( self.InputSpace.raw_data[parIdx], max_deg - ) - self.polycoeffs[f'p_{parIdx + 1}'] = poly_coeffs + ) + self.polycoeffs[f'p_{parIdx+1}'] = poly_coeffs else: raise AttributeError('MetaModel cannot generate polynomials in the given scenario!') @@ -1507,11 +1516,11 @@ class MetaModel: The second moment (standard deviation) of the surrogate. """ - + # Check if its truly a pce-surrogate if self.meta_model_type.lower() == 'gpe': raise AttributeError('Moments can only be computed for pce-type surrogates') - + outputs = self.out_names pce_means_b = {} pce_stds_b = {} @@ -1519,7 +1528,7 @@ class MetaModel: # Loop over bootstrap iterations for b_i in range(self.n_bootstrap_itrs): # Loop over the metamodels - coeffs_dicts = self.coeffs_dict[f'b_{b_i + 1}'].items() + coeffs_dicts = self.coeffs_dict[f'b_{b_i+1}'].items() means = {} stds = {} for output, coef_dict in coeffs_dicts: @@ -1529,20 +1538,20 @@ class MetaModel: for index, values in coef_dict.items(): idx = int(index.split('_')[1]) - 1 - coeffs = self.coeffs_dict[f'b_{b_i + 1}'][output][index] + coeffs = self.coeffs_dict[f'b_{b_i+1}'][output][index] # Mean = c_0 if coeffs[0] != 0: pce_mean[idx] = coeffs[0] else: - clf_poly = self.clf_poly[f'b_{b_i + 1}'][output] + clf_poly = self.clf_poly[f'b_{b_i+1}'][output] pce_mean[idx] = clf_poly[index].intercept_ # Var = sum(coeffs[1:]**2) pce_var[idx] = np.sum(np.square(coeffs[1:])) # Save predictions for each output if self.dim_red_method.lower() == 'pca': - PCA = self.pca[f'b_{b_i + 1}'][output] + PCA = self.pca[f'b_{b_i+1}'][output] means[output] = PCA.inverse_transform(pce_mean) stds[output] = PCA.inverse_transform(np.sqrt(pce_var)) else: diff --git a/tests/itest_MetaModel.py b/tests/itest_MetaModel.py index ecc44c399..b5095fa34 100644 --- a/tests/itest_MetaModel.py +++ b/tests/itest_MetaModel.py @@ -71,7 +71,7 @@ def test_build_metamodel() -> None: inp.Marginals[0].dist_type = 'normal' inp.Marginals[0].parameters = [0,1] mm = MetaModel(inp) - mm.collocation_points = [[0.2], [0.8]] + mm.CollocationPoints = [[0.2],[0.8]] mm.build_metamodel() def test_build_metamodel_ninitsamples() -> None: @@ -83,7 +83,7 @@ def test_build_metamodel_ninitsamples() -> None: inp.Marginals[0].dist_type = 'normal' inp.Marginals[0].parameters = [0,1] mm = MetaModel(inp) - mm.collocation_points = [[0.2], [0.8]] + mm.CollocationPoints = [[0.2],[0.8]] mm.build_metamodel(n_init_samples = 2) def test_build_metamodel_gpe() -> None: @@ -96,7 +96,7 @@ def test_build_metamodel_gpe() -> None: inp.Marginals[0].parameters = [0,1] mm = MetaModel(inp) mm.meta_model_type = 'gpe' - mm.collocation_points = [[0.2], [0.8]] + mm.CollocationPoints = [[0.2],[0.8]] mm.build_metamodel() @@ -109,7 +109,7 @@ def test_build_metamodel_coldimerr() -> None: inp.Marginals[0].dist_type = 'normal' inp.Marginals[0].parameters = [0,1] mm = MetaModel(inp) - mm.collocation_points = [[0.2, 0.8]] + mm.CollocationPoints = [[0.2,0.8]] with pytest.raises(AttributeError) as excinfo: mm.build_metamodel() assert str(excinfo.value) == 'The given samples do not match the given number of priors. The samples should be a 2D array of size (#samples, #priors)' @@ -185,7 +185,7 @@ def test_add_InputSpace() -> None: inp.Marginals[0].dist_type = 'normal' inp.Marginals[0].parameters = [0,1] mm = MetaModel(inp) - mm.add_input_space() + mm.add_InputSpace() #%% Test MetaModel.fit # Faster without these @@ -260,7 +260,7 @@ def test_create_psi() -> None: inp.Marginals[0].parameters = [0,1] mm = MetaModel(inp) samples = np.array([[0.2],[0.8]]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -281,7 +281,7 @@ def test_regression() -> None: samples = np.array([[0.2]]) outputs = np.array([0.5]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -301,7 +301,7 @@ def test_regression_ols() -> None: samples = np.array([[0.2]]) outputs = np.array([0.5]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -321,7 +321,7 @@ def test_regression_olssparse() -> None: samples = np.array([[0.2]]) outputs = np.array([0.5]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -341,7 +341,7 @@ def test_regression_ard() -> None: samples = np.array([[0.2],[0.8]]) outputs = np.array([0.4,0.5]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -361,7 +361,7 @@ def test_regression_ardssparse() -> None: samples = np.array([[0.2],[0.8]]) outputs = np.array([0.4,0.5]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -381,7 +381,7 @@ def test_regression_fastard() -> None: samples = np.array([[0.2]]) outputs = np.array([0.5]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -401,7 +401,7 @@ def test_regression_fastardssparse() -> None: samples = np.array([[0.2]]) outputs = np.array([0.5]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -421,7 +421,7 @@ def test_regression_brr() -> None: samples = np.array([[0.2]]) outputs = np.array([0.5]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -441,7 +441,7 @@ def test_regression_brrssparse() -> None: samples = np.array([[0.2]]) outputs = np.array([0.5]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -461,7 +461,7 @@ def test_regression_bcs() -> None: samples = np.array([[0.0],[0.1],[0.2],[0.3],[0.4],[0.5],[0.6],[0.7],[0.8],[0.9]]) outputs = np.array([0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9]) mm.pce_deg = 3 - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(mm.pce_deg)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -481,7 +481,7 @@ def test_regression_bcsssparse() -> None: samples = np.array([[0.0],[0.1],[0.2],[0.3],[0.4],[0.5],[0.6],[0.7],[0.8],[0.9],[1.0]]) outputs = np.array([0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.1]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -502,7 +502,7 @@ def test_regression_lars() -> None: samples = np.array([[0.0],[0.1],[0.2],[0.3],[0.4],[0.5],[0.6],[0.7],[0.8],[0.9],[1.0]]) outputs = np.array([0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.1]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -522,7 +522,7 @@ def test_regression_larsssparse() -> None: samples = np.array([[0.0],[0.1],[0.2],[0.3],[0.4],[0.5],[0.6],[0.7],[0.8],[0.9],[1.0]]) outputs = np.array([0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.1]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -542,7 +542,7 @@ def test_regression_sgdr() -> None: samples = np.array([[0.2]]) outputs = np.array([0.5]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -562,7 +562,7 @@ def test_regression_sgdrssparse() -> None: samples = np.array([[0.2]]) outputs = np.array([0.5]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -583,7 +583,7 @@ def test_regression_omp() -> None: samples = np.array([[0.2]]) outputs = np.array([0.5]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -603,7 +603,7 @@ def test_regression_ompssparse() -> None: samples = np.array([[0.2]]) outputs = np.array([0.5]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -624,7 +624,7 @@ def test_regression_vbl() -> None: samples = np.array([[0.2]]) outputs = np.array([0.5]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -644,7 +644,7 @@ def test_regression_vblssparse() -> None: samples = np.array([[0.2]]) outputs = np.array([0.5]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -664,7 +664,7 @@ def test_regression_ebl() -> None: samples = np.array([[0.2]]) outputs = np.array([0.5]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -684,7 +684,7 @@ def test_regression_eblssparse() -> None: samples = np.array([[0.2]]) outputs = np.array([0.5]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -710,7 +710,7 @@ def test_univ_basis_vals() -> None: inp.Marginals[0].parameters = [0,1] mm = MetaModel(inp) samples = np.array([[0.2],[0.8]]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) mm.univ_basis_vals(samples) @@ -728,12 +728,12 @@ def test_adaptive_regression_fewsamples() -> None: samples = np.array([[0.2]]) outputs = np.array([0.8]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) # Evaluate the univariate polynomials on InputSpace if mm.meta_model_type.lower() != 'gpe': - mm.univ_p_val = mm.univ_basis_vals(mm.collocation_points) + mm.univ_p_val = mm.univ_basis_vals(mm.CollocationPoints) with pytest.raises(AttributeError) as excinfo: mm.adaptive_regression(samples, outputs, 0) @@ -751,12 +751,12 @@ def test_adaptive_regression() -> None: samples = np.array([[0.0],[0.1]]) outputs = np.array([0.0,0.1]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) # Evaluate the univariate polynomials on InputSpace if mm.meta_model_type.lower() != 'gpe': - mm.univ_p_val = mm.univ_basis_vals(mm.collocation_points) + mm.univ_p_val = mm.univ_basis_vals(mm.CollocationPoints) mm.adaptive_regression(samples, outputs, 0) def test_adaptive_regression_verbose() -> None: @@ -771,12 +771,12 @@ def test_adaptive_regression_verbose() -> None: samples = np.array([[0.0],[0.1]]) outputs = np.array([0.0,0.1]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) # Evaluate the univariate polynomials on InputSpace if mm.meta_model_type.lower() != 'gpe': - mm.univ_p_val = mm.univ_basis_vals(mm.collocation_points) + mm.univ_p_val = mm.univ_basis_vals(mm.CollocationPoints) mm.adaptive_regression(samples, outputs, 0, True) def test_adaptive_regression_ols() -> None: @@ -792,12 +792,12 @@ def test_adaptive_regression_ols() -> None: [0.9],[1.0]]) outputs = np.array([0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.1]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) # Evaluate the univariate polynomials on InputSpace if mm.meta_model_type.lower() != 'gpe': - mm.univ_p_val = mm.univ_basis_vals(mm.collocation_points) + mm.univ_p_val = mm.univ_basis_vals(mm.CollocationPoints) mm.pce_reg_method = 'ols' mm.adaptive_regression(samples, outputs, 0) @@ -816,7 +816,7 @@ def test_corr_loocv_error_nosparse() -> None: [0.8],[0.9],[1.0]]) outputs = np.array([0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.1]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -838,7 +838,7 @@ def test_corr_loocv_error_singley() -> None: samples = np.array([[0.2]]) outputs = np.array([0.1]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -861,7 +861,7 @@ def test_corr_loocv_error_sparse() -> None: [0.8],[0.9],[1.0]]) outputs = np.array([0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.1]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) @@ -936,7 +936,7 @@ def test_gaussian_process_emulator() -> None: inp.Marginals[0].dist_type = 'normal' inp.Marginals[0].parameters = [0,1] mm = MetaModel(inp) - gaussian_process_emulator( [[0.2],[0.8]], [0.4,0.5]) + mm.gaussian_process_emulator( [[0.2],[0.8]], [0.4,0.5]) def test_gaussian_process_emulator_nug() -> None: """ @@ -947,7 +947,7 @@ def test_gaussian_process_emulator_nug() -> None: inp.Marginals[0].dist_type = 'normal' inp.Marginals[0].parameters = [0,1] mm = MetaModel(inp) - gaussian_process_emulator( [[0.2],[0.8]], [0.4,0.5],nug_term=1.0) + mm.gaussian_process_emulator( [[0.2],[0.8]], [0.4,0.5],nug_term=1.0) def test_gaussian_process_emulator_autosel() -> None: """ @@ -958,7 +958,7 @@ def test_gaussian_process_emulator_autosel() -> None: inp.Marginals[0].dist_type = 'normal' inp.Marginals[0].parameters = [0,1] mm = MetaModel(inp) - gaussian_process_emulator( [[0.2],[0.8]], [0.4,0.5],autoSelect=True) + mm.gaussian_process_emulator( [[0.2],[0.8]], [0.4,0.5],autoSelect=True) def test_gaussian_process_emulator_varIdx() -> None: """ @@ -969,7 +969,7 @@ def test_gaussian_process_emulator_varIdx() -> None: inp.Marginals[0].dist_type = 'normal' inp.Marginals[0].parameters = [0,1] mm = MetaModel(inp) - gaussian_process_emulator( [[0.2],[0.8]], [0.4,0.5],varIdx=1) + mm.gaussian_process_emulator( [[0.2],[0.8]], [0.4,0.5],varIdx=1) #%% Test MetaModel.eval_metamodel @@ -1059,7 +1059,7 @@ def test_auto_vivification() -> None: inp.Marginals[0].dist_type = 'normal' inp.Marginals[0].parameters = [0,1] mm = MetaModel(inp) - mm.AutoVivification() + mm.auto_vivification() #%% Test MetaModel.copy_meta_model_opts @@ -1072,7 +1072,7 @@ def test_copy_meta_model_opts() -> None: inp.Marginals[0].dist_type = 'normal' inp.Marginals[0].parameters = [0,1] mm = MetaModel(inp) - mm.add_input_space() + mm.add_InputSpace() mm.copy_meta_model_opts() #%% Test MetaModel.__select_degree @@ -1131,7 +1131,7 @@ if __name__ == '__main__': samples = np.array([[0.2]]) outputs = np.array([0.5]) - mm.collocation_points = samples + mm.CollocationPoints = samples mm.build_metamodel(n_init_samples = 2) BasisIndices = mm.allBasisIndices[str(1)][str(1.0)] univ_bas = mm.univ_basis_vals(samples) -- GitLab