prisma-oed 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. prisma/__init__.py +1 -0
  2. prisma/apf/__init__.py +0 -0
  3. prisma/apf/api/__init__.py +7 -0
  4. prisma/apf/api/active_parameter_fit.py +182 -0
  5. prisma/apf/util/__init__.py +0 -0
  6. prisma/apf/util/active_parameter_fit_jax_lib.py +262 -0
  7. prisma/bnlr/__init__.py +3 -0
  8. prisma/bnlr/posterior_optim.py +12 -0
  9. prisma/bnlr/posterior_optim_iter_jax_lib.py +57 -0
  10. prisma/bonlr/__init__.py +7 -0
  11. prisma/bonlr/bonlr_jax_lib.py +152 -0
  12. prisma/calc/__init__.py +0 -0
  13. prisma/calc/dim_analysis/__init__.py +3 -0
  14. prisma/calc/dim_analysis/dimensional_analysis_lib.py +34 -0
  15. prisma/calc/metric/__init__.py +3 -0
  16. prisma/calc/metric/metric_lib.py +21 -0
  17. prisma/experiment/__init__.py +9 -0
  18. prisma/experiment/performance_survey.py +95 -0
  19. prisma/experiment/spectroscopy.py +35 -0
  20. prisma/experiment/spectroscopy_series.py +234 -0
  21. prisma/file/__init__.py +3 -0
  22. prisma/file/io_lib.py +12 -0
  23. prisma/format/__init__.py +3 -0
  24. prisma/format/format_lib.py +6 -0
  25. prisma/nlr/__init__.py +5 -0
  26. prisma/nlr/nlr_parameter_fit_lib.py +59 -0
  27. prisma/physics_models/__init__.py +0 -0
  28. prisma/physics_models/jax/__init__.py +3 -0
  29. prisma/physics_models/jax/phys_mod_jax.py +51 -0
  30. prisma/physics_models/jax/phys_mod_jax_lib.py +211 -0
  31. prisma/physics_models/python/__init__.py +4 -0
  32. prisma/physics_models/python/phys_mod.py +128 -0
  33. prisma/physics_models/python/phys_mod_lib.py +79 -0
  34. prisma/plot/__init__.py +19 -0
  35. prisma/plot/matplotlibrc.py +54 -0
  36. prisma/plot/plot_lib.py +441 -0
  37. prisma/samplers/__init__.py +0 -0
  38. prisma/samplers/abstract/__init__.py +3 -0
  39. prisma/samplers/abstract/abstract_samplers.py +226 -0
  40. prisma/samplers/instruments/__init__.py +0 -0
  41. prisma/samplers/instruments/nanonis/__init__.py +4 -0
  42. prisma/samplers/instruments/nanonis/nanonis_sampler.py +223 -0
  43. prisma/samplers/pseudorandom/__init__.py +0 -0
  44. prisma/samplers/pseudorandom/function/__init__.py +6 -0
  45. prisma/samplers/pseudorandom/function/function_samplers.py +118 -0
  46. prisma/samplers/pseudorandom/noise/__init__.py +3 -0
  47. prisma/samplers/pseudorandom/noise/noise_samplers.py +136 -0
  48. prisma_oed-0.0.1.dist-info/METADATA +97 -0
  49. prisma_oed-0.0.1.dist-info/RECORD +53 -0
  50. prisma_oed-0.0.1.dist-info/WHEEL +5 -0
  51. prisma_oed-0.0.1.dist-info/licenses/LICENSE.txt +30 -0
  52. prisma_oed-0.0.1.dist-info/licenses/LICENSES_bundled.txt +8 -0
  53. prisma_oed-0.0.1.dist-info/top_level.txt +1 -0
prisma/__init__.py ADDED
@@ -0,0 +1 @@
1
+ __version__ = '0.0.1'
prisma/apf/__init__.py ADDED
File without changes
@@ -0,0 +1,7 @@
1
+ from .active_parameter_fit import ActiveParameterFitSigmaSqPred, \
2
+ ActiveParameterFitRP, ActiveParameterFitEI, \
3
+ AbstractActiveParameterFit
4
+
5
+ __all__ = ['ActiveParameterFitSigmaSqPred', 'ActiveParameterFitRP',
6
+ 'ActiveParameterFitEI',
7
+ 'AbstractActiveParameterFit']
@@ -0,0 +1,182 @@
1
+ from abc import ABC, abstractmethod
2
+ import jax
3
+ import jax.numpy as jnp
4
+ from jax.stages import Wrapped
5
+ import numpy as np
6
+ from numpy.typing import ArrayLike
7
+
8
+ from ..util.active_parameter_fit_jax_lib import get_nonlin_f_x_j, \
9
+ acq_f_sigma_sq_predictive_j, acq_f_rp_j, \
10
+ acq_f_ei_j, \
11
+ init_arr_j, init_arr_rp_j, init_arr_ei_j, \
12
+ posterior_update_j
13
+ from prisma.file import save_np_val
14
+ from prisma.plot import plot_predictive_train_iter, \
15
+ plot_acq_train_iter, plot_predictive_acq_train_iter, plot_w_rmse, \
16
+ plot_w_i_err, plot_predictive_rmse
17
+ from prisma.samplers.abstract import AbstractDomainSampler
18
+
19
+
20
+ class AbstractActiveParameterFit(ABC):
21
+
22
+ def __init__(self, nonlin_f_j: Wrapped, acq_domain: ArrayLike,
23
+ t_sampler: AbstractDomainSampler,
24
+ beta: float, m_0: ArrayLike, S_0: ArrayLike,
25
+ sample_ct: int):
26
+ # TODO: initialize all jit argument vars as jnp
27
+ self.nonlin_f_j = nonlin_f_j
28
+ self.acq_domain = acq_domain
29
+ self.t_sampler = t_sampler
30
+ self.beta = beta
31
+ self.param_ct = len(m_0)
32
+ self.sample_ct = sample_ct
33
+ self.acq_domain_len = len(acq_domain)
34
+ self.nonlin_f_j_N = get_nonlin_f_x_j(nonlin_f_j, acq_domain)
35
+ self.x_n_jnp, self.t_n_jnp, self.phi_n_jnp, \
36
+ self.m_prior_jnp, self.var_prior_jnp, self.acq_val_jnp \
37
+ = init_arr_j(m_0, S_0, self.param_ct, sample_ct,
38
+ self.acq_domain_len)
39
+ self.x_n_np = self.t_n_np = self.phi_n_np \
40
+ = self.m_prior_np = self.var_prior_np = self.acq_val_np = None
41
+
42
+ def fit(self):
43
+ for i in range(self.sample_ct):
44
+ x_next, acq_val_next = self._acquisition_f(i)
45
+ t_next = self.t_sampler.sample(x_next)
46
+ self.x_n_jnp, self.t_n_jnp, self.acq_val_jnp, \
47
+ self.phi_n_jnp, self.m_prior_jnp, self.var_prior_jnp \
48
+ = posterior_update_j(x_next, acq_val_next, t_next,
49
+ self.nonlin_f_j, self.beta,
50
+ i, self.x_n_jnp, self.t_n_jnp,
51
+ self.phi_n_jnp, self.m_prior_jnp,
52
+ self.var_prior_jnp, self.acq_val_jnp)
53
+
54
+ def fit_sampler_reset(self):
55
+ self.t_sampler.reset()
56
+ self.fit()
57
+
58
+ def init_np_arrs(self):
59
+ self.x_n_np, self.t_n_np, self.phi_n_np, \
60
+ self.m_prior_np, self.var_prior_np, self.acq_val_np \
61
+ = self._jax_arrs_to_np_arrs(self.x_n_jnp, self.t_n_jnp,
62
+ self.phi_n_jnp, self.m_prior_jnp,
63
+ self.var_prior_jnp, self.acq_val_jnp)
64
+
65
+ def save_np_arrs(self, save_dir):
66
+ save_np_val(save_dir, "x_n.npy", self.x_n_np)
67
+ save_np_val(save_dir, "t_n.npy", self.t_n_np)
68
+ save_np_val(save_dir, "phi_n.npy", self.phi_n_np)
69
+ save_np_val(save_dir, "m_prior.npy", self.m_prior_np)
70
+ save_np_val(save_dir, "var_prior.npy", self.var_prior_np)
71
+ save_np_val(save_dir, "acq_n.npy", self.acq_val_np)
72
+
73
+ def plot_predictive_train_iter(self, y=None, title=True,
74
+ title_samples=False):
75
+ plot_predictive_train_iter(self.nonlin_f_j, self.acq_domain,
76
+ self.beta, self.m_prior_jnp,
77
+ self.var_prior_jnp,
78
+ y=y,
79
+ x_n=self.x_n_jnp, t_n=self.t_n_jnp,
80
+ title=title, title_samples=title_samples)
81
+
82
+ def plot_acq_train_iter(self):
83
+ plot_acq_train_iter(self.acq_domain, self.acq_val_jnp)
84
+
85
+ def plot_predictive_acq_train_iter(self, y=None, title=True,
86
+ title_samples=False):
87
+ plot_predictive_acq_train_iter(self.nonlin_f_j, self.acq_domain,
88
+ self.beta, self.m_prior_jnp,
89
+ self.var_prior_jnp,
90
+ self.acq_val_jnp,
91
+ y=y,
92
+ x_n=self.x_n_jnp, t_n=self.t_n_jnp,
93
+ title=title,
94
+ title_samples=title_samples)
95
+
96
+ def plot_w_rmse(self, w_act):
97
+ plot_w_rmse(w_act, m_N_l=self.m_prior_jnp)
98
+
99
+ def plot_w_i_err(self, w_act, i, w_i_name=None):
100
+ plot_w_i_err(w_act, i, m_N_l=self.m_prior_jnp, w_i_name=w_i_name)
101
+
102
+ def plot_predictive_rmse(self, t, y):
103
+ plot_predictive_rmse(self.nonlin_f_j, self.acq_domain, t, y,
104
+ m_N_l=self.m_prior_jnp)
105
+
106
+ @abstractmethod
107
+ def _acquisition_f(self, i):
108
+ ...
109
+
110
+ def _jax_arrs_to_np_arrs(self, *jax_arrs):
111
+ return tuple(map(np.array, jax_arrs))
112
+
113
+
114
+ class ActiveParameterFitSigmaSqPred(AbstractActiveParameterFit):
115
+ '''
116
+ Predictive variance
117
+ '''
118
+
119
+ def _acquisition_f(self, i):
120
+ x_next, acq = acq_f_sigma_sq_predictive_j(self.nonlin_f_j_N,
121
+ self.acq_domain,
122
+ self.beta, i,
123
+ self.m_prior_jnp,
124
+ self.var_prior_jnp)
125
+ return x_next, acq
126
+
127
+
128
+ class ActiveParameterFitRP(AbstractActiveParameterFit):
129
+ '''
130
+ Normal repulsion
131
+ '''
132
+
133
+ def __init__(self, nonlin_f_j: Wrapped, acq_domain: ArrayLike,
134
+ t_sampler: AbstractDomainSampler,
135
+ beta: float, m_0: ArrayLike, S_0: ArrayLike,
136
+ sample_ct: int,
137
+ magnitude_rp: float, scale_rp: float):
138
+ super().__init__(nonlin_f_j, acq_domain, t_sampler, beta, m_0, S_0,
139
+ sample_ct)
140
+ self.mag_rp = magnitude_rp
141
+ self.scl_rp = scale_rp
142
+ self.rp_jnp = init_arr_rp_j(self.acq_domain_len)
143
+
144
+ def _acquisition_f(self, i):
145
+ x_next, acq, rp_next = acq_f_rp_j(self.nonlin_f_j_N, self.acq_domain,
146
+ self.beta, i,
147
+ self.m_prior_jnp, self.var_prior_jnp,
148
+ self.mag_rp, self.scl_rp,
149
+ self.rp_jnp)
150
+ self.rp_jnp = rp_next
151
+ return x_next, acq
152
+
153
+
154
+ class ActiveParameterFitEI(AbstractActiveParameterFit):
155
+ '''
156
+ Expected Improvement
157
+ '''
158
+
159
+ def __init__(self, nonlin_f_j: Wrapped, acq_domain: ArrayLike,
160
+ t_sampler: AbstractDomainSampler,
161
+ beta: float, m_0: ArrayLike, S_0: ArrayLike,
162
+ sample_ct: int,
163
+ range_delta: ArrayLike,
164
+ m_mask: ArrayLike | None = None):
165
+ super().__init__(nonlin_f_j, acq_domain, t_sampler, beta, m_0, S_0,
166
+ sample_ct)
167
+ if m_mask is None:
168
+ m_mask = np.ones(self.param_ct)
169
+ if jax.config.read('jax_enable_x64'):
170
+ self.eps_j = jnp.finfo(jnp.float64).eps
171
+ else:
172
+ self.eps_j = jnp.finfo(jnp.float32).eps
173
+ self.m_mask_jnp, self.range_delta_jnp = init_arr_ei_j(m_mask,
174
+ range_delta)
175
+
176
+ def _acquisition_f(self, i):
177
+ x_next, acq, = acq_f_ei_j(self.nonlin_f_j_N, self.nonlin_f_j,
178
+ self.acq_domain, self.beta, i,
179
+ self.m_prior_jnp, self.var_prior_jnp,
180
+ self.range_delta_jnp, self.m_mask_jnp,
181
+ self.eps_j)
182
+ return x_next, acq
File without changes
@@ -0,0 +1,262 @@
1
+ from functools import partial
2
+ import jax
3
+ from jax import Array
4
+ from jax import jit
5
+ import jax.numpy as jnp
6
+ from jax.tree_util import Partial as Partialj
7
+
8
+ from prisma.bonlr import get_S_N_MAP_j, get_m_N_MAP_j, \
9
+ get_S_N_MAP_i_j, get_m_N_MAP_i_j, get_sigma_sq_predictive_j
10
+
11
+
12
+ @jit
13
+ def train_posterior_j(Phi, t, beta, m_prior, var_prior):
14
+ S_N = get_S_N_MAP_j(Phi, beta, var_prior)
15
+ m_N = get_m_N_MAP_j(Phi, t, beta, m_prior, var_prior, S_N)
16
+ return m_N, S_N
17
+
18
+
19
+ @jit
20
+ def train_posterior_i_j(phi, t, beta, m_prior, var_prior):
21
+ S_N = get_S_N_MAP_i_j(phi, beta, var_prior)
22
+ m_N = get_m_N_MAP_i_j(phi, t, beta, m_prior, var_prior, S_N)
23
+ return m_N, S_N
24
+
25
+
26
+ @partial(jit, static_argnames='nonlin_f_j')
27
+ def get_nonlin_f_x_j(nonlin_f_j, x):
28
+ return Partialj(nonlin_f_j, x)
29
+
30
+
31
+ @partial(jit, static_argnames='nonlin_f_j')
32
+ def get_nonlin_f_x_i_j(nonlin_f_j, x_i):
33
+ x_i_jnp = jnp.array([x_i])
34
+ nonlin_f_j_x_i = get_nonlin_f_x_j(nonlin_f_j, x_i_jnp)
35
+ return nonlin_f_j_x_i
36
+
37
+
38
+ # @jit
39
+ # def get_phi_ts_j(nonlin_f, m_prior):
40
+ # return jax.grad(nonlin_f)(m_prior)
41
+
42
+
43
+ @jit
44
+ def get_Phi_ts_j(nonlin_f, m_prior):
45
+ return jax.jacfwd(nonlin_f)(m_prior)
46
+
47
+
48
+ @jit
49
+ def get_Phi_vec_ts_j(nonlin_f, m_prior):
50
+ Phi = get_Phi_ts_j(nonlin_f, m_prior)
51
+ phi = jnp.squeeze(Phi)
52
+ return phi
53
+
54
+
55
+ @jit
56
+ def get_t_lin_ts_j(nonlin_f_x_n, t_n, Phi_n, m_prior):
57
+ return t_n - nonlin_f_x_n(m_prior) + Phi_n @ m_prior
58
+
59
+
60
+ @jit
61
+ def get_sigma_sq_predictive_N_j(nonlin_f_N, m_n, S_n, beta):
62
+ Phi = get_Phi_ts_j(nonlin_f_N, m_n)
63
+ sigma_sq_predictive = get_sigma_sq_predictive_j(Phi, S_n, beta)
64
+ return sigma_sq_predictive
65
+
66
+
67
+ @jit
68
+ def get_sigma_sq_predictive_N_acq_j(nonlin_f_N, m_prior_jnp, var_prior_jnp,
69
+ beta, i):
70
+ m_n = m_prior_jnp[i]
71
+ S_n = var_prior_jnp[i]
72
+ sigma_sq_predictive = get_sigma_sq_predictive_N_j(nonlin_f_N, m_n, S_n,
73
+ beta)
74
+ return sigma_sq_predictive
75
+
76
+
77
+ @jit
78
+ def get_x_next_j(acq, x):
79
+ n_next = jnp.argmax(acq)
80
+ x_next = x[n_next]
81
+ return x_next
82
+
83
+
84
+ @jit
85
+ def acq_f_sigma_sq_predictive_j(nonlin_f_N, acq_domain, beta, i,
86
+ m_prior_jnp, var_prior_jnp):
87
+ sigma_sq_predictive \
88
+ = get_sigma_sq_predictive_N_acq_j(nonlin_f_N, m_prior_jnp,
89
+ var_prior_jnp, beta, i)
90
+ x_next = get_x_next_j(sigma_sq_predictive, acq_domain)
91
+ return x_next, sigma_sq_predictive
92
+
93
+
94
+ @jit
95
+ def get_rp_es_j(x_next, x, mag_rp, scale_rp):
96
+ return mag_rp * jax.scipy.stats.norm.pdf(x, x_next, scale_rp)
97
+
98
+
99
+ @jit
100
+ def acq_f_rp_j(nonlin_f_N, acq_domain, beta, i,
101
+ m_prior_jnp, var_prior_jnp,
102
+ mag_rp, scale_rp, rp_prev):
103
+ sigma_sq_predictive \
104
+ = get_sigma_sq_predictive_N_acq_j(nonlin_f_N, m_prior_jnp,
105
+ var_prior_jnp, beta, i)
106
+ acq = sigma_sq_predictive - rp_prev
107
+ x_next = get_x_next_j(acq, acq_domain)
108
+ rp_next = rp_prev + get_rp_es_j(x_next, acq_domain, mag_rp, scale_rp)
109
+ return x_next, acq, rp_next
110
+
111
+
112
+ @jit
113
+ def posterior_improvement_j(t, nonlin_f_j_x, beta, phi_x,
114
+ m_n, S_n,
115
+ m_mask, eps_j):
116
+ m_hyp, S_hyp = get_next_posterior_x_j(t, nonlin_f_j_x, beta,
117
+ phi_x, m_n, S_n)
118
+ m_improvement_vec = m_hyp - m_n
119
+ m_n_eps = m_n + eps_j
120
+ m_improvement_prop_vec = m_improvement_vec / m_n_eps
121
+ m_improvement_prop_vec = jnp.where(m_mask, m_improvement_prop_vec, 0)
122
+ norm_improvement = jnp.linalg.norm(m_improvement_prop_vec)
123
+ return norm_improvement
124
+
125
+
126
+ @jit
127
+ def predictive_probability(t, predictive_loc, predictive_scale):
128
+ pred_prob = jax.scipy.stats.norm.pdf(t, predictive_loc, predictive_scale)
129
+ return pred_prob
130
+
131
+
132
+ @jit
133
+ def probability_weighted_improvement_j(nonlin_f_j_x, beta, phi_x,
134
+ m_n, S_n,
135
+ predictive_loc, predictive_scale,
136
+ m_mask, eps_j,
137
+ t):
138
+ norm_improvement = posterior_improvement_j(t, nonlin_f_j_x, beta,
139
+ phi_x, m_n, S_n, m_mask, eps_j)
140
+ pred_prob = predictive_probability(t, predictive_loc, predictive_scale)
141
+ prob_w_imp = pred_prob * norm_improvement
142
+ return prob_w_imp
143
+
144
+
145
+ @partial(jit, static_argnames='nonlin_f_j')
146
+ def expected_improvement_j(nonlin_f_j, beta,
147
+ m_n, S_n,
148
+ range_delta, m_mask, eps_j, x_i,
149
+ predictive_loc, predictive_scale):
150
+ nonlin_f_j_x_i = get_nonlin_f_x_i_j(nonlin_f_j, x_i)
151
+ phi_i = get_Phi_vec_ts_j(nonlin_f_j_x_i, m_n)
152
+ range_domain = predictive_loc + range_delta
153
+ probability_weighted_improvement_j_p \
154
+ = Partialj(probability_weighted_improvement_j,
155
+ nonlin_f_j_x_i, beta, phi_i, m_n, S_n,
156
+ predictive_loc, predictive_scale,
157
+ m_mask, eps_j)
158
+ probability_weighted_improvement_j_p_v \
159
+ = jax.vmap(probability_weighted_improvement_j_p,
160
+ in_axes=0)
161
+ y_trapezoid \
162
+ = probability_weighted_improvement_j_p_v(range_domain)
163
+ ei = jax.scipy.integrate.trapezoid(y_trapezoid, range_domain)
164
+ return ei
165
+
166
+
167
+ @partial(jit, static_argnames='nonlin_f_j')
168
+ def acq_f_ei_j(nonlin_f_j_N, nonlin_f_j,
169
+ acq_domain,
170
+ beta, i,
171
+ m_prior_jnp, var_prior_jnp,
172
+ range_delta, m_mask, eps_j):
173
+ m_n = m_prior_jnp[i]
174
+ S_n = var_prior_jnp[i]
175
+ Phi = get_Phi_ts_j(nonlin_f_j_N, m_n)
176
+ mu_predictive = Phi @ m_n
177
+ sigma_sq_predictive = get_sigma_sq_predictive_j(Phi, S_n, beta)
178
+ scale_predictive = jnp.sqrt(sigma_sq_predictive)
179
+ expected_improvement_j_p = Partialj(expected_improvement_j,
180
+ nonlin_f_j, beta, m_n, S_n,
181
+ range_delta, m_mask, eps_j)
182
+ expected_improvement_j_p_v = jax.vmap(expected_improvement_j_p,
183
+ in_axes=(0, 0, 0))
184
+ acq = expected_improvement_j_p_v(acq_domain,
185
+ mu_predictive, scale_predictive)
186
+ x_next = get_x_next_j(acq, acq_domain)
187
+ return x_next, acq
188
+
189
+
190
+ @partial(jit, static_argnames=('param_ct', 'sample_ct', 'acq_domain_len'))
191
+ def init_arr_j(m_prior, var_prior, param_ct, sample_ct, acq_domain_len):
192
+ prior_ct = sample_ct + 1
193
+ m_prior_jnp = jnp.zeros((prior_ct, param_ct))
194
+ m_prior_jnp = m_prior_jnp.at[0].set(m_prior)
195
+ var_prior_jnp = jnp.zeros((prior_ct, param_ct, param_ct))
196
+ var_prior_jnp = var_prior_jnp.at[0].set(var_prior)
197
+ x_n_jnp = jnp.zeros(sample_ct)
198
+ acq_val_jnp = jnp.zeros((sample_ct, acq_domain_len))
199
+ t_n_jnp = jnp.zeros(sample_ct)
200
+ phi_n_jnp = jnp.zeros((sample_ct, param_ct))
201
+ return x_n_jnp, t_n_jnp, phi_n_jnp, m_prior_jnp, var_prior_jnp, acq_val_jnp
202
+
203
+
204
+ @partial(jit, static_argnames='acq_domain_len')
205
+ def init_arr_rp_j(acq_domain_len):
206
+ rp_jnp = jnp.zeros(acq_domain_len)
207
+ return rp_jnp
208
+
209
+
210
+ @jit
211
+ def init_arr_ei_j(m_mask, range_delta):
212
+ m_mask_jnp = jnp.array(m_mask, dtype=bool)
213
+ range_delta_jnp = jnp.array(range_delta)
214
+ return m_mask_jnp, range_delta_jnp
215
+
216
+
217
+ @jit
218
+ def get_rp_next_es_j(x_next, x, rp_prev, mag_rp, scale_rp):
219
+ return rp_prev + get_rp_es_j(x_next, x, mag_rp, scale_rp)
220
+
221
+
222
+ def get_next_posterior_x_j(t, nonlin_f_j_x, beta,
223
+ phi, m_prior, var_prior):
224
+ t_lin = get_t_lin_ts_j(nonlin_f_j_x, t,
225
+ phi, m_prior)
226
+ m_n, S_n = train_posterior_i_j(phi, t_lin, beta,
227
+ m_prior, var_prior)
228
+ return m_n, S_n
229
+
230
+
231
+ @partial(jit, static_argnames='nonlin_f_j')
232
+ def get_next_posterior_j(nonlin_f_j, beta, i,
233
+ x_n_jnp, t_n_jnp,
234
+ m_prior_jnp, var_prior_jnp):
235
+ x_i = x_n_jnp[i]
236
+ t_i = t_n_jnp[i]
237
+ m_prior = m_prior_jnp[i]
238
+ var_prior = var_prior_jnp[i]
239
+ nonlin_f_j_x_i = get_nonlin_f_x_i_j(nonlin_f_j, x_i)
240
+ phi_i = get_Phi_vec_ts_j(nonlin_f_j_x_i, m_prior)
241
+ m_n, S_n = get_next_posterior_x_j(t_i, nonlin_f_j_x_i, beta,
242
+ phi_i, m_prior, var_prior)
243
+ return phi_i, m_n, S_n
244
+
245
+
246
+ @partial(jit, static_argnames='nonlin_f_j')
247
+ def posterior_update_j(x_next, acq_val_next, t_next,
248
+ nonlin_f_j, beta, i,
249
+ x_n_jnp: Array, t_n_jnp: Array,
250
+ phi_n_jnp: Array, m_prior_jnp: Array,
251
+ var_prior_jnp: Array, acq_val_jnp: Array):
252
+ x_n_jnp = x_n_jnp.at[i].set(x_next)
253
+ acq_val_jnp = acq_val_jnp.at[i].set(acq_val_next)
254
+ t_n_jnp = t_n_jnp.at[i].set(t_next)
255
+ phi_i, m_n, S_n = get_next_posterior_j(nonlin_f_j, beta, i,
256
+ x_n_jnp, t_n_jnp,
257
+ m_prior_jnp, var_prior_jnp)
258
+ phi_n_jnp = phi_n_jnp.at[i].set(phi_i)
259
+ i_posterior = i + 1
260
+ m_prior_jnp = m_prior_jnp.at[i_posterior].set(m_n)
261
+ var_prior_jnp = var_prior_jnp.at[i_posterior].set(S_n)
262
+ return x_n_jnp, t_n_jnp, acq_val_jnp, phi_n_jnp, m_prior_jnp, var_prior_jnp
@@ -0,0 +1,3 @@
1
+ from .posterior_optim import optimize_posterior
2
+
3
+ __all__ = ['optimize_posterior']
@@ -0,0 +1,12 @@
1
+ from .posterior_optim_iter_jax_lib import optimize_posterior_j
2
+
3
+
4
+ def optimize_posterior(beem_integral_f_vector_j,
5
+ beta, x_N, t_N,
6
+ m_prior, var_prior,
7
+ eps=1e-3, i_max=100):
8
+ Phi, m_N, S_N = optimize_posterior_j(beem_integral_f_vector_j,
9
+ beta, x_N, t_N,
10
+ m_prior, var_prior,
11
+ eps=eps, i_max=i_max)
12
+ return Phi, m_N, S_N
@@ -0,0 +1,57 @@
1
+ from functools import partial
2
+ from jax import jit, lax
3
+ import jax.numpy as jnp
4
+ from jax.tree_util import Partial as Partialj
5
+
6
+ from prisma.apf.util.active_parameter_fit_jax_lib \
7
+ import get_Phi_ts_j, get_t_lin_ts_j, train_posterior_j, \
8
+ get_nonlin_f_x_j
9
+
10
+
11
+ @jit
12
+ def gn_cond_posterior_j(Phi_mprior_mN_SN_i, eps=1e-3, i_max=100):
13
+ _, m_prior, m_N, _, i = Phi_mprior_mN_SN_i
14
+ m_delta = m_N - m_prior
15
+ # jax.debug.print("m_delta: {m_delta}", m_delta=m_delta)
16
+ # jax.debug.print("eps: {eps}", eps=jnp.any(jnp.abs(m_delta) > eps))
17
+ # jax.debug.print("i cond: {i}", i=i)
18
+ return jnp.logical_and(jnp.any(jnp.abs(m_delta) > eps), i < i_max)
19
+
20
+
21
+ @jit
22
+ def gn_step_posterior_j(Phi_mprior_mN_SN_i, nonlin_f_N, beta, t_N, var_prior):
23
+ _, _, m_prior, _, i = Phi_mprior_mN_SN_i
24
+ Phi = get_Phi_ts_j(nonlin_f_N, m_prior)
25
+ t_lin = get_t_lin_ts_j(nonlin_f_N, t_N, Phi, m_prior)
26
+ m_N, S_N = train_posterior_j(Phi, t_lin, beta, m_prior, var_prior)
27
+ # jax.debug.print("i: {i}", i=i)
28
+ i += 1
29
+ return Phi, m_prior, m_N, S_N, i
30
+
31
+
32
+ @partial(jit, static_argnames=['param_ct', 'sample_ct'])
33
+ def gn_opt_posterior_j(gn_cond_pj, gn_step_pj, param_ct, sample_ct, m_prior):
34
+ Phi, _, m_N, S_N, _ \
35
+ = lax.while_loop(gn_cond_pj, gn_step_pj,
36
+ (jnp.full((sample_ct, param_ct), jnp.nan),
37
+ jnp.full(param_ct, -jnp.inf),
38
+ m_prior,
39
+ jnp.full((param_ct, param_ct), jnp.nan),
40
+ 0)) # TODO: pass rather than generate?
41
+ return Phi, m_N, S_N
42
+
43
+
44
+ @partial(jit, static_argnames='nonlin_f')
45
+ def optimize_posterior_j(nonlin_f, beta, x_N, t_N, m_prior, var_prior,
46
+ eps=1e-3, i_max=100):
47
+ param_ct = len(m_prior)
48
+ sample_ct = len(x_N)
49
+ nonlin_f_N = get_nonlin_f_x_j(nonlin_f, x_N)
50
+ gn_cond = Partialj(gn_cond_posterior_j,
51
+ **{'eps': eps, 'i_max': i_max})
52
+ gn_step = Partialj(gn_step_posterior_j,
53
+ **{'nonlin_f_N': nonlin_f_N, 'beta': beta, 't_N': t_N,
54
+ 'var_prior': var_prior})
55
+ Phi, m_N, S_N = gn_opt_posterior_j(gn_cond, gn_step, param_ct, sample_ct,
56
+ m_prior)
57
+ return Phi, m_N, S_N
@@ -0,0 +1,7 @@
1
+ from .bonlr_jax_lib import get_S_N_MAP_j, get_m_N_MAP_j, \
2
+ get_S_N_MAP_i_j, get_m_N_MAP_i_j, get_sigma_sq_predictive_n_j, \
3
+ get_sigma_sq_predictive_j
4
+
5
+ __all__ = ['get_S_N_MAP_j', 'get_m_N_MAP_j', 'get_S_N_MAP_i_j',
6
+ 'get_m_N_MAP_i_j', 'get_sigma_sq_predictive_n_j',
7
+ 'get_sigma_sq_predictive_j',]
@@ -0,0 +1,152 @@
1
+ import jax
2
+ from jax import Array
3
+ from jax import jit
4
+ import jax.numpy as jnp
5
+ from numbers import Real
6
+
7
+
8
+ @jit
9
+ def get_S_N_MAP_j(Phi: Array, beta: Real, S_0: Array) -> Array:
10
+ '''
11
+ Maximum a posteriori closed from for posterior covariance matrix.
12
+
13
+ Parameters
14
+ ----------
15
+ Phi
16
+ Design matrix of linear model
17
+ beta
18
+ Precision (inverse variance) of measurement noise
19
+ S_0
20
+ Prior covariance matrix
21
+
22
+ Returns
23
+ -------
24
+ Posterior covariance matrix
25
+ '''
26
+ return jnp.linalg.pinv(jnp.linalg.pinv(S_0) + beta * Phi.T @ Phi)
27
+
28
+
29
+ @jit
30
+ def get_m_N_MAP_j(Phi: Array, t: Array, beta: Real, m_0: Array,
31
+ S_0: Array, S_N: Array) -> Array:
32
+ '''
33
+ Maximum a posteriori closed form for posterior mean.
34
+
35
+ Parameters
36
+ ----------
37
+ Phi
38
+ Design matrix of linear model
39
+ t
40
+ Measured outputs of system
41
+ beta
42
+ Precision (inverse variance) of measurement noise
43
+ m_0
44
+ Prior mean
45
+ S_0
46
+ Prior covariance matrix
47
+ S_N
48
+ Posterior covariance matrix
49
+
50
+ Returns
51
+ -------
52
+ Posterior mean
53
+ '''
54
+ return S_N @ (jnp.linalg.pinv(S_0) @ m_0 + beta * Phi.T @ t)
55
+
56
+
57
+ @jit
58
+ def get_S_N_MAP_i_j(phi: Array, beta: Real, S_0: Array) -> Array:
59
+ '''
60
+ Online maximum a posteriori closed from for posterior covariance matrix.
61
+
62
+ Parameters
63
+ ----------
64
+ phi
65
+ Next sample vector for design matrix of linear model
66
+ beta
67
+ Precision (inverse variance) of measurement noise
68
+ S_0
69
+ Prior covariance matrix
70
+
71
+ Returns
72
+ -------
73
+ Posterior covariance matrix
74
+ '''
75
+ S_N = jnp.linalg.pinv(jnp.linalg.pinv(S_0) + beta * jnp.outer(phi, phi))
76
+ return S_N
77
+
78
+
79
+ @jit
80
+ def get_m_N_MAP_i_j(phi: Array, t: Array, beta: Real, m_0: Array,
81
+ S_0: Array, S_N: Array) -> Array:
82
+ '''
83
+ Online maximum a posteriori closed form for posterior mean.
84
+
85
+ Parameters
86
+ ----------
87
+ phi
88
+ Next sample vector for design matrix of linear model
89
+ t
90
+ Measured outputs of system
91
+ beta
92
+ Precision (inverse variance) of measurement noise
93
+ m_0
94
+ Prior mean
95
+ S_0
96
+ Prior covariance matrix
97
+ S_N
98
+ Posterior covariance matrix
99
+
100
+ Returns
101
+ -------
102
+ Posterior mean
103
+ '''
104
+ return S_N @ (jnp.linalg.pinv(S_0) @ m_0 + beta * phi * t)
105
+
106
+
107
+ @jit
108
+ def get_sigma_sq_predictive_n_j(phi_n: Array, S_N: Array,
109
+ beta: Real) -> Real:
110
+ '''
111
+ Bayes' rule for Gaussian distributions predictive distribution variance
112
+ for a given domain value.
113
+
114
+ Parameters
115
+ ----------
116
+ phi_n
117
+ Sample vector for design matrix
118
+ S_N
119
+ Posterior covariance matrix
120
+ beta
121
+ Precision (inverse variance) of measurement noise
122
+
123
+ Returns
124
+ -------
125
+ Posterior predictive variance
126
+ '''
127
+ return 1. / beta + phi_n @ S_N @ phi_n
128
+
129
+
130
+ @jit
131
+ def get_sigma_sq_predictive_j(Phi_test: Array, S_N: Array,
132
+ beta: Real) -> Array:
133
+ '''
134
+ Get predictive distribution variance over domain.
135
+
136
+ Parameters
137
+ ----------
138
+ Phi_test
139
+ Design matrix over domain
140
+ S_N
141
+ Posterior covariance matrix
142
+ beta
143
+ Precision (inverse variance) of measurement noise
144
+
145
+ Returns
146
+ -------
147
+ Posterior predictive variance over domain
148
+ '''
149
+ get_sigma_sq_predictive_n_j_v = jax.vmap(get_sigma_sq_predictive_n_j,
150
+ in_axes=(0, None, None))
151
+ sigma_sq_N = get_sigma_sq_predictive_n_j_v(Phi_test, S_N, beta)
152
+ return sigma_sq_N
File without changes