diff --git a/.coverage b/.coverage new file mode 100644 index 0000000000000000000000000000000000000000..7bd62455cae2ec79af9cbc60f552afe43fca17d4 Binary files /dev/null and b/.coverage differ diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..13566b81b018ad684f3a35fee301741b2734c8f4 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/bayesvalidrox.iml b/.idea/bayesvalidrox.iml new file mode 100644 index 0000000000000000000000000000000000000000..fab03b6eca7d238814b681f1f06637c845bcc3f4 --- /dev/null +++ b/.idea/bayesvalidrox.iml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="PYTHON_MODULE" version="4"> + <component name="NewModuleRootManager"> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> + <sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + </component> + <component name="PyDocumentationSettings"> + <option name="format" value="NUMPY" /> + <option name="myDocStringFormat" value="NumPy" /> + </component> + <component name="TestRunnerService"> + <option name="PROJECT_TEST_RUNNER" value="py.test" /> + </component> +</module> \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000000000000000000000000000000000000..105ce2da2d6447d11dfe32bfb846c3d5b199fc99 --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ +<component name="InspectionProjectProfileManager"> + <settings> + <option name="USE_PROJECT_PROFILE" value="false" /> + <version value="1.0" /> + </settings> +</component> \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000000000000000000000000000000000000..a6218fed0aeb0cbb03b46a9064efeeda11861bf6 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ +<?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/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000000000000000000000000000000000000..482c611f35883d7c1998edbfac68f5b5b74300db --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="ProjectModuleManager"> + <modules> + <module fileurl="file://$PROJECT_DIR$/.idea/bayesvalidrox.iml" filepath="$PROJECT_DIR$/.idea/bayesvalidrox.iml" /> + </modules> + </component> +</project> \ No newline at end of file diff --git a/.idea/other.xml b/.idea/other.xml new file mode 100644 index 0000000000000000000000000000000000000000..2e75c2e2af6fe9ab3294dedf305ebb894bb324d7 --- /dev/null +++ b/.idea/other.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="PySciProjectComponent"> + <option name="PY_INTERACTIVE_PLOTS_SUGGESTED" value="true" /> + </component> +</project> \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000000000000000000000000000000000000..35eb1ddfbbc029bcab630581847471d7f238ec53 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="VcsDirectoryMappings"> + <mapping directory="" vcs="Git" /> + </component> +</project> \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index be1a9771212073e22232ba1c46b7bf3d84cdfb60..42c974fb5e5f8e31c58684551c68a4f55a74d621 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,9 @@ # CHANGELOG -## v1.0.0 +## [Unreleased] ### Requirements -* updated for python 3.10 +* numpy now at 1.23.3 +* .... ### Added Features diff --git a/examples/.coverage b/examples/.coverage new file mode 100644 index 0000000000000000000000000000000000000000..254e10e4371d703eefec0f0437f9c0575be3f5ec Binary files /dev/null and b/examples/.coverage differ diff --git a/examples/analytical-function/example_analytical_function.py b/examples/analytical-function/example_analytical_function.py index f80767befe54c1557601c870b9ea5a8b28f650ba..bdf22598a0c19b031a8b4bb4196c16744bddae14 100644 --- a/examples/analytical-function/example_analytical_function.py +++ b/examples/analytical-function/example_analytical_function.py @@ -139,7 +139,7 @@ if __name__ == "__main__": # One-shot (normal) or Sequential Adaptive (sequential) Design ExpDesign.method = 'sequential' - ExpDesign.n_init_samples = 100#3*ndim + ExpDesign.n_init_samples = 140#00#3*ndim # Sampling methods # 1) random 2) latin_hypercube 3) sobol 4) halton 5) hammersley @@ -225,7 +225,8 @@ if __name__ == "__main__": MetaModelOpts.ExpDesign = ExpDesign engine = Engine(MetaModelOpts, Model, ExpDesign) engine.start_engine() - engine.train_sequential() + #engine.train_sequential() + engine.train_normal() # Load the objects # with open(f"PCEModel_{Model.name}.pkl", "rb") as input: @@ -264,12 +265,12 @@ if __name__ == "__main__": # BayesOpts.selected_indices = [0, 3, 5, 7, 9] # BME Bootstrap - # BayesOpts.bootstrap = True - # BayesOpts.n_bootstrap_itrs = 500 - # BayesOpts.bootstrap_noise = 100 + BayesOpts.bootstrap = True + BayesOpts.n_bootstrap_itrs = 500 + BayesOpts.bootstrap_noise = 100 # Bayesian cross validation - # BayesOpts.bayes_loocv = True + BayesOpts.bayes_loocv = True # TODO: test what this does # Select the inference method import emcee @@ -294,31 +295,34 @@ if __name__ == "__main__": BayesOpts.Discrepancy = DiscrepancyOpts # -- (Option C) -- - # DiscOutputOpts = Input() - # # # OutputName = 'Z' - # DiscOutputOpts.add_marginals() - # DiscOutputOpts.Marginals[0].Nnme = '$\sigma^2_{\epsilon}$' - # DiscOutputOpts.Marginals[0].dist_type = 'uniform' - # DiscOutputOpts.Marginals[0].parameters = [0, 10] - # BayesOpts.Discrepancy = {'known': DiscrepancyOpts, - # 'infer': Discrepancy(DiscOutputOpts)} - - # BayesOpts.bias_inputs = {'Z':np.arange(0, 10, 1.).reshape(-1,1) / 9} - # DiscOutputOpts = Input() - # # OutputName = 'lambda' - # DiscOutputOpts.add_marginals() - # DiscOutputOpts.Marginals[0].name = '$\lambda$' - # DiscOutputOpts.Marginals[0].dist_type = 'uniform' - # DiscOutputOpts.Marginals[0].parameters = [0, 1] - - # # OutputName = 'sigma_f' - # DiscOutputOpts.add_marginals() - # DiscOutputOpts.Marginals[1].Name = '$\sigma_f$' - # DiscOutputOpts.Marginals[1].dist_type = 'uniform' - # DiscOutputOpts.Marginals[1].parameters = [0, 1e-4] - # BayesOpts.Discrepancy = Discrepancy(DiscOutputOpts) - # BayesOpts.Discrepancy = {'known': DiscrepancyOpts, - # 'infer': Discrepancy(DiscOutputOpts)} + if 0: + DiscOutputOpts = Input() + # # # OutputName = 'Z' + DiscOutputOpts.add_marginals() + DiscOutputOpts.Marginals[0].Nnme = '$\sigma^2_{\epsilon}$' + DiscOutputOpts.Marginals[0].dist_type = 'uniform' + DiscOutputOpts.Marginals[0].parameters = [0, 10] + #BayesOpts.Discrepancy = {'known': DiscrepancyOpts, + # 'infer': Discrepancy(DiscOutputOpts)} + + BayesOpts.bias_inputs = {'Z':np.arange(0, 10, 1.).reshape(-1,1) / 9} + + DiscOutputOpts = Input() + # OutputName = 'lambda' + DiscOutputOpts.add_marginals() + DiscOutputOpts.Marginals[0].name = '$\lambda$' + DiscOutputOpts.Marginals[0].dist_type = 'uniform' + DiscOutputOpts.Marginals[0].parameters = [0, 1] + + # # OutputName = 'sigma_f' + DiscOutputOpts.add_marginals() + DiscOutputOpts.Marginals[1].Name = '$\sigma_f$' + DiscOutputOpts.Marginals[1].dist_type = 'uniform' + DiscOutputOpts.Marginals[1].parameters = [0, 1e-4] + #BayesOpts.Discrepancy = Discrepancy(DiscOutputOpts) + BayesOpts.Discrepancy = {'known': DiscrepancyOpts, + 'infer': Discrepancy(DiscOutputOpts)} + # Start the calibration/inference Bayes_PCE = BayesOpts.create_inference() diff --git a/src/bayesvalidrox/bayes_inference/discrepancy.py b/src/bayesvalidrox/bayes_inference/discrepancy.py index fff32a2500ae20b3667c7b0ec2cc85c1da614688..b3c235ebeb6d6ae9e109ca862cc522cc21efb45e 100644 --- a/src/bayesvalidrox/bayes_inference/discrepancy.py +++ b/src/bayesvalidrox/bayes_inference/discrepancy.py @@ -36,7 +36,7 @@ class Discrepancy: * 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 infer with the uncertain input parameters. For + 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\\). @@ -58,10 +58,17 @@ class Discrepancy: """ 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): """ @@ -87,6 +94,11 @@ class Discrepancy: # 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 ) diff --git a/src/bayesvalidrox/surrogate_models/__init__.py b/src/bayesvalidrox/surrogate_models/__init__.py index 70bfb20f570464c2907a0a4128f4ed99b6c13736..6d8ce9f1c58fa154f2af63f0fb5a44097695df33 100644 --- a/src/bayesvalidrox/surrogate_models/__init__.py +++ b/src/bayesvalidrox/surrogate_models/__init__.py @@ -1,7 +1,12 @@ # -*- coding: utf-8 -*- - +from .engine import Engine +from .exp_designs import ExpDesigns +from .input_space import InputSpace from .surrogate_models import MetaModel __all__ = [ - "MetaModel" + "MetaModel", + "InputSpace", + "ExpDesigns", + "Engine" ] diff --git a/src/bayesvalidrox/surrogate_models/desktop.ini b/src/bayesvalidrox/surrogate_models/desktop.ini new file mode 100644 index 0000000000000000000000000000000000000000..632de13ae6b61cecf0d9fdbf9c97cfb16bfb51a4 --- /dev/null +++ b/src/bayesvalidrox/surrogate_models/desktop.ini @@ -0,0 +1,2 @@ +[LocalizedFileNames] +exploration.py=@exploration.py,0 diff --git a/src/bayesvalidrox/surrogate_models/exploration.py b/src/bayesvalidrox/surrogate_models/exploration.py index 6abb652f145fadb410ecf8f987142e8ceb544a41..67decae2bfef6d397bafbc10abdcb35ff77a63a3 100644 --- a/src/bayesvalidrox/surrogate_models/exploration.py +++ b/src/bayesvalidrox/surrogate_models/exploration.py @@ -33,6 +33,7 @@ class Exploration: def __init__(self, ExpDesign, n_candidate, mc_criterion='mc-intersite-proj-th'): + self.closestPoints = None self.ExpDesign = ExpDesign self.n_candidate = n_candidate self.mc_criterion = mc_criterion diff --git a/src/bayesvalidrox/surrogate_models/inputs.py b/src/bayesvalidrox/surrogate_models/inputs.py index 094e1066fe008e37288e44750524c5a1370bd7a2..40ae36337fa84c0bb9758e488f983ba29cdb9e77 100644 --- a/src/bayesvalidrox/surrogate_models/inputs.py +++ b/src/bayesvalidrox/surrogate_models/inputs.py @@ -4,6 +4,7 @@ Inputs and related marginal distributions """ + class Input: """ A class to define the uncertain input parameters. @@ -20,17 +21,18 @@ class Input: ------- 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] + >>> inputs = Inputs() + >>> 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 + >>> inputs.add_marginals() + >>> inputs.Marginals[0].name = 'X_1' + >>> inputs.Marginals[0].input_data = [0,0,1,0] """ poly_coeffs_flag = True @@ -63,12 +65,12 @@ class Marginal: dist_type : string Name of the distribution. The default is `None`. parameters : list - List of the parameters corresponding to the distribution type. 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. + Moments of the distribution. The default is `None`. """ def __init__(self): diff --git a/src/bayesvalidrox/surrogate_models/reg_fast_ard.py b/src/bayesvalidrox/surrogate_models/reg_fast_ard.py index e6883a3edd6d247c219b8be328f5206b75780fbb..fdd0ee7470dc5d0bdccd354cee16f6257ec01b02 100755 --- a/src/bayesvalidrox/surrogate_models/reg_fast_ard.py +++ b/src/bayesvalidrox/surrogate_models/reg_fast_ard.py @@ -236,7 +236,7 @@ class RegressionFastARD(LinearModel, RegressorMixin): self.var_y = False A = np.PINF * np.ones(n_features) - active = np.zeros(n_features, dtype=np.bool) + active = np.zeros(n_features, dtype=bool) if self.start is not None and not hasattr(self, 'active_'): start = self.start diff --git a/tests/test_BayesModelComparison.py b/tests/test_BayesModelComparison.py new file mode 100644 index 0000000000000000000000000000000000000000..91f328ec7ae39cf7cded6b228edc1442053a2dfb --- /dev/null +++ b/tests/test_BayesModelComparison.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +""" +Test the BayesModelComparison class in bayesvalidrox. +Tests are available for the following functions +Class BayesModelComparison: + create_model_comparison + compare_models + generate_dataset + __perturb_data + cal_model_weight + plot_just_analysis + plot_model_weights + plot_bayes_factor + +""" +import sys +sys.path.append("src/") +import pytest +import numpy as np + +from bayesvalidrox.bayes_inference.bayes_model_comparison import BayesModelComparison +#from bayesvalidrox.surrogate_models.input_space import InputSpace + +def test_BMC() -> None: + """ + Build BMC without inputs + """ + BayesModelComparison() \ No newline at end of file diff --git a/tests/test_Discrepancy.py b/tests/test_Discrepancy.py index c46e0a13751756e0583f3176489e7215da77f4ba..7fb948d905031e7d7e6235857c27792fb29ece57 100644 --- a/tests/test_Discrepancy.py +++ b/tests/test_Discrepancy.py @@ -36,22 +36,8 @@ def test_get_sample() -> None: """ Get discrepancy sample """ - inp = Input() - inp.add_marginals() - inp.Marginals[0].dist_type = 'normal' - inp.Marginals[0].parameters = [0,1] - disc = Discrepancy(InputDisc = inp) + disc = Discrepancy() with pytest.raises(AttributeError) as excinfo: disc.get_sample(2) assert str(excinfo.value) == 'Cannot create new samples, please provide input distributions' - - - - -if __name__ == '__main__': - inp = Input() - inp.add_marginals() - inp.Marginals[0].dist_type = 'normal' - inp.Marginals[0].parameters = [0,1] - disc = Discrepancy(InputDisc = inp) - disc.get_sample(2) \ No newline at end of file + \ No newline at end of file diff --git a/tests/test_ExpDesign.py b/tests/test_ExpDesign.py index 3da00d32e4c23bffe6f05d57ddd2a304fb64bd3e..0a1191799ca880dbdf28eb598a68120507bff1b2 100644 --- a/tests/test_ExpDesign.py +++ b/tests/test_ExpDesign.py @@ -135,6 +135,47 @@ def test_random_sampler() -> None: exp = ExpDesigns(inp) exp.random_sampler(4) +def test_random_sampler_largedatanoJDist() -> None: + """ + Sample randomly, init_param_space implicitly, more samples wanted than given, no JDist available + """ + x = np.random.uniform(0,1,1000) + inp = Input() + inp.add_marginals() + inp.Marginals[0].input_data = x + exp = ExpDesigns(inp) + with pytest.raises(AttributeError) as excinfo: + exp.random_sampler(100000) + assert str(excinfo.value) == 'Sampling cannot proceed, build ExpDesign with max_deg != 0 to create JDist!' + +def test_random_sampler_largedataJDist0() -> None: + """ + Sample randomly, init_param_space implicitly, more samples wanted than given, + JDist available, priors given via samples + """ + x = np.random.uniform(0,1,1000) + inp = Input() + inp.add_marginals() + inp.Marginals[0].input_data = x + exp = ExpDesigns(inp) + exp.init_param_space(max_deg = 1) + exp.random_sampler(100000) + +def test_random_sampler_largedataJDist1() -> None: + """ + Sample randomly, init_param_space implicitly, more samples wanted than given, + JDist available, prior distributions given + """ + inp = Input() + inp.add_marginals() + inp.Marginals[0].dist_type = 'normal' + inp.Marginals[0].parameters = [0,1] + exp = ExpDesigns(inp) + exp.init_param_space(max_deg = 1) + exp.random_sampler(100000) + + + def test_random_sampler_rawdata() -> None: """ Sample randomly, init_param_space implicitly, has 2d raw data @@ -374,11 +415,3 @@ def test_read_from_file(): exp = ExpDesigns(inp, sampling_method = 'user') exp.hdf5_file = 'tests/ExpDesign_testfile.hdf5' exp.read_from_file(['Z']) - -if __name__ == '__main__': - x = np.random.uniform(0,1,1000) - inp = Input() - inp.add_marginals() - inp.Marginals[0].input_data = x - exp = ExpDesigns(inp, sampling_method = 'PCM') - exp.generate_ED(4) \ No newline at end of file diff --git a/tests/test_Input.py b/tests/test_Input.py index 84b9b239cb1646ccc2a946fb7a76831f17d38c1f..41c0e5ab84a5178b1934504bc63b5d5c03d19078 100644 --- a/tests/test_Input.py +++ b/tests/test_Input.py @@ -9,10 +9,10 @@ Class Input: @author: Rebecca Kohlhaas """ import sys -sys.path.append("src/") -import pytest -from bayesvalidrox.surrogate_models.inputs import Marginal, Input +from bayesvalidrox.surrogate_models.inputs import Input + +sys.path.append("src/") def test_addmarginals() -> None: