def build_from_interface(self, m, fun, dfun=None): self.m = m # number of gradient samples M = 6 * (m + 1) * np.log(m) # sample points if self.bflag: X = np.random.uniform(-1.0, 1.0, size=(M, m)) else: X = np.random.normal(size=(M, m)) self.X = X # sample the simulation's outputs sr = SimulationRunner(fun) self.f_runner = sr # sample the simulation's gradients if dfun == None: df = finite_difference_gradients(X, sr) else: sgr = SimulationGradientRunner(dfun) df = sgr.run(X) self.df_runner = sgr self.df = df # compute the active subspaces self.subspaces = build_subspaces(df)
def av_integrate(avfun, avmap, N): """Approximate the integral of a function of active variables. Parameters ---------- avfun : function a function of the active variables avmap : ActiveVariableMap a domains.ActiveVariableMap N : int the number of points in the quadrature rule Returns ------- mu : float an estimate of the integral Notes ----- This function is usually used when one has already constructed a response surface on the active variables and wants to estimate its integral. """ if not isinstance(avmap, ActiveVariableMap): raise TypeError('avmap should be an ActiveVariableMap.') if not isinstance(N, Integral): raise TypeError('N should be an integer.') Yp, Yw = av_quadrature_rule(avmap, N) if isinstance(avfun, ActiveSubspaceResponseSurface): avf = avfun.predict_av(Yp)[0] else: avf = SimulationRunner(avfun).run(Yp) mu = np.dot(Yw.T, avf)[0, 0] return mu
def finite_difference_gradients(X, fun, h=1e-6): """Compute finite difference gradients with a given interface. Parameters ---------- X : ndarray M-by-m matrix that contains the points to estimate the gradients with finite differences fun : function function that returns the simulation's quantity of interest given inputs h : float, optional the finite difference step size (default 1e-6) Returns ------- df : ndarray M-by-m matrix that contains estimated partial derivatives approximated by finite differences """ X, M, m = process_inputs(X) # points to run simulations including the perturbed inputs XX = np.kron(np.ones((m+1, 1)),X) + \ h*np.kron(np.vstack((np.zeros((1, m)), np.eye(m))), np.ones((M, 1))) # run the simulation if isinstance(fun, SimulationRunner): F = fun.run(XX) else: F = SimulationRunner(fun).run(XX) df = (F[M:].reshape((m, M)).transpose() - F[:M]) / h return df.reshape((M,m))
def train_with_interface(self, fun, N, NMC=10): """Train the response surface with input/output pairs. Parameters ---------- fun : function a function that returns the simulation quantity of interest given a point in the input space as an 1-by-m ndarray N : int the number of points used in the design-of-experiments for constructing the response surface NMC : int, optional the number of points used to estimate the conditional expectation and conditional variance of the function given a value of the active variables Notes ----- The training methods exploit the eigenvalues from the active subspace analysis to determine length scales for each variable when tuning the parameters of the radial bases. The method sets attributes of the object for further use. The method uses the response_surfaces.av_design function to get the design for the appropriate `avmap`. """ Y, X, ind = av_design(self.avmap, N, NMC=NMC) if isinstance(self.avmap.domain, BoundedActiveVariableDomain): X = np.vstack((X, self.avmap.domain.vertX)) Y = np.vstack((Y, self.avmap.domain.vertY)) il = np.amax(ind) + 1 iu = np.amax(ind) + self.avmap.domain.vertX.shape[0] + 1 iind = np.arange(il, iu) ind = np.vstack((ind, iind.reshape((iind.size, 1)))) # run simulation interface at all design points if isinstance(fun, SimulationRunner): f = fun.run(X) else: f = SimulationRunner(fun).run(X) Ef, Vf = conditional_expectations(f, ind) self._train(Y, Ef, v=Vf)
def as_integrate(fun, domain, subspace, N, NMC=10): """ Description of as_integrate Arguments: fun: domain: subspace: N: NMC: (default=10) Outputs: mu: lb: ub: """ w, x, ind = as_quadrature_rule(domain, subspace, N, NMC) f = SimulationRunner(fun).run(x) return compute_integral(w, f, ind)
def integrate(fun, avmap, N, NMC=10): """Approximate the integral of a function of m variables. Parameters ---------- fun : function an interface to the simulation that returns the quantity of interest given inputs as an 1-by-m ndarray avmap : ActiveVariableMap a domains.ActiveVariableMap N : int the number of points in the quadrature rule NMC : int, optional the number of points in the Monte Carlo estimates of the conditional expectation and conditional variance (default 10) Returns ------- mu : float an estimate of the integral of the function computed against the weight function on the simulation inputs lb : float a central-limit-theorem 95% lower confidence from the Monte Carlo part of the integration ub : float a central-limit-theorem 95% upper confidence from the Monte Carlo part of the integration See Also -------- integrals.quadrature_rule Notes ----- The CLT-based bounds `lb` and `ub` are likely poor estimators of the error. They only account for the variance from the Monte Carlo portion. They do not include any error from the integration rule on the active variables. """ if not isinstance(avmap, ActiveVariableMap): raise TypeError('avmap should be an ActiveVariableMap.') if not isinstance(N, Integral): raise TypeError('N should be an integer') # get the quadrature rule Xp, Xw, ind = quadrature_rule(avmap, N, NMC=NMC) # compute the simulation output at each quadrature node if isinstance(fun, SimulationRunner): f = fun.run(Xp) else: f = SimulationRunner(fun).run(Xp) # estimate conditional expectations and variances Ef, Vf = conditional_expectations(f, ind) # get weights for the conditional expectations w = conditional_expectations(Xw * NMC, ind)[0] # estimate the average mu = np.dot(Ef.T, w) # estimate the variance due to Monte Carlo sig2 = np.dot(Vf.T, w * w) / NMC # compute 95% confidence bounds from the Monte Carlo lb, ub = mu - 1.96 * np.sqrt(sig2), mu + 1.96 * np.sqrt(sig2) return mu[0, 0], lb[0, 0], ub[0, 0]