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.
- prisma/__init__.py +1 -0
- prisma/apf/__init__.py +0 -0
- prisma/apf/api/__init__.py +7 -0
- prisma/apf/api/active_parameter_fit.py +182 -0
- prisma/apf/util/__init__.py +0 -0
- prisma/apf/util/active_parameter_fit_jax_lib.py +262 -0
- prisma/bnlr/__init__.py +3 -0
- prisma/bnlr/posterior_optim.py +12 -0
- prisma/bnlr/posterior_optim_iter_jax_lib.py +57 -0
- prisma/bonlr/__init__.py +7 -0
- prisma/bonlr/bonlr_jax_lib.py +152 -0
- prisma/calc/__init__.py +0 -0
- prisma/calc/dim_analysis/__init__.py +3 -0
- prisma/calc/dim_analysis/dimensional_analysis_lib.py +34 -0
- prisma/calc/metric/__init__.py +3 -0
- prisma/calc/metric/metric_lib.py +21 -0
- prisma/experiment/__init__.py +9 -0
- prisma/experiment/performance_survey.py +95 -0
- prisma/experiment/spectroscopy.py +35 -0
- prisma/experiment/spectroscopy_series.py +234 -0
- prisma/file/__init__.py +3 -0
- prisma/file/io_lib.py +12 -0
- prisma/format/__init__.py +3 -0
- prisma/format/format_lib.py +6 -0
- prisma/nlr/__init__.py +5 -0
- prisma/nlr/nlr_parameter_fit_lib.py +59 -0
- prisma/physics_models/__init__.py +0 -0
- prisma/physics_models/jax/__init__.py +3 -0
- prisma/physics_models/jax/phys_mod_jax.py +51 -0
- prisma/physics_models/jax/phys_mod_jax_lib.py +211 -0
- prisma/physics_models/python/__init__.py +4 -0
- prisma/physics_models/python/phys_mod.py +128 -0
- prisma/physics_models/python/phys_mod_lib.py +79 -0
- prisma/plot/__init__.py +19 -0
- prisma/plot/matplotlibrc.py +54 -0
- prisma/plot/plot_lib.py +441 -0
- prisma/samplers/__init__.py +0 -0
- prisma/samplers/abstract/__init__.py +3 -0
- prisma/samplers/abstract/abstract_samplers.py +226 -0
- prisma/samplers/instruments/__init__.py +0 -0
- prisma/samplers/instruments/nanonis/__init__.py +4 -0
- prisma/samplers/instruments/nanonis/nanonis_sampler.py +223 -0
- prisma/samplers/pseudorandom/__init__.py +0 -0
- prisma/samplers/pseudorandom/function/__init__.py +6 -0
- prisma/samplers/pseudorandom/function/function_samplers.py +118 -0
- prisma/samplers/pseudorandom/noise/__init__.py +3 -0
- prisma/samplers/pseudorandom/noise/noise_samplers.py +136 -0
- prisma_oed-0.0.1.dist-info/METADATA +97 -0
- prisma_oed-0.0.1.dist-info/RECORD +53 -0
- prisma_oed-0.0.1.dist-info/WHEEL +5 -0
- prisma_oed-0.0.1.dist-info/licenses/LICENSE.txt +30 -0
- prisma_oed-0.0.1.dist-info/licenses/LICENSES_bundled.txt +8 -0
- 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
|
prisma/bnlr/__init__.py
ADDED
|
@@ -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
|
prisma/bonlr/__init__.py
ADDED
|
@@ -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
|
prisma/calc/__init__.py
ADDED
|
File without changes
|