def __call__(self, x, y=None, observed=True, regularize=True): if x is y: symm=True else: symm=False # Remember shape of x, and then 'regularize' it. orig_shape = np.shape(x) if len(orig_shape)>1: orig_shape = orig_shape[:-1] if regularize: x=regularize_array(x) ndimx = x.shape[-1] lenx = x.shape[0] # Safety if self.ndim is not None: if not self.ndim == ndimx: raise ValueError, "The number of spatial dimensions of x, "+\ ndimx.__str__()+\ ", does not match the number of spatial dimensions of the Covariance instance's base mesh, "+\ self.ndim.__str__()+"." # If there are observation points, prepare self(obs_mesh, x) # and chol(self(obs_mesh, obs_mesh)).T.I * self(obs_mesh, x) if self.observed and observed: Cxo = cvx_covariance(self.eval_fun, x, cutoff=self.cutoff, **self.params) Uo_Cxo = self.Uo_backsolver(Cxo) # Uo_Cxo = trisolve(self.Uo, Cxo, uplo='U', transa='T') # ========================================================== # = If only one argument is provided, return the diagonal. = # ========================================================== # See documentation. if y is None: V = diag_call(x=x, cov_fun = self.diag_cov_fun) for i in range(lenx): # Update return value using observations. if self.observed and observed: V[i] -= Uo_Cxo[:,i].T*Uo_Cxo[:,i] return V.reshape(orig_shape) else: # ==================================================================== # = If x and y are same np.array, return triangular-only sparse factor. = # ==================================================================== if symm: C = cvx_covariance(self.eval_fun, x, cutoff=self.cutoff, **self.params) # Update return value using observations. if self.observed and observed: C -= Uo_Cxo.T * Uo_Cxo return C # ====================================== # = # If x and y are different np.arrays: = # ====================================== else: if regularize: y=regularize_array(y) ndimy = y.shape[-1] leny = y.shape[0] if not ndimx==ndimy: raise ValueError, 'The last dimension of x and y (the number of spatial dimensions) must be the same.' C = cvx_covariance(self.eval_fun, x, y, cutoff=self.cutoff, **self.params) # Update return value using observations. if self.observed and observed: # If there are observation points, prepare self(obs_mesh, y) # and chol(self(obs_mesh, obs_mesh)).T.I * self(obs_mesh, y) cvx_covariance(self.eval_fun, self.obs_mesh, y, cutoff=self.cutoff, **self.params) Uo_Cyo = self.Uo_backsolver(Cyo.T) # Uo_Cyo = trisolve(self.Uo, Cyo,uplo='U', transa='T') # C -= Uo_Cxo.T * Uo_Cyo C -= Uo_Cxo.T * Uo_Cyo.T return C
def cvx_covariance(cov_fun, x, y=None, cutoff=1e-5, **params): """ cvx_covariance(cov_fun, x, y=None cutoff=1e-5, **params) Returns a sparse version of cov_fun(x,y,**params). If y=None, returns a sparse (cxopt) version of the upper triangle of cov_fun(x,x, **params) with all elements less than or equal to cov_fun(x,x, **params).max() * cutoff set to 0 (left out of the nonzero structure). """ m = x.shape[0] r_ind = [] c_ind = [] if y is None: n=m # Get the diagonal, to see what the largest element is, and scale the cutoff. bigdiag = diag_call(x=x, cov_fun = lambda xe: cov_fun(xe,xe,**params)) C = cvx.base.spmatrix(bigdiag, range(m), range(m)) maxval = bigdiag.max() cutoff = maxval * cutoff # Make sure you're passing np.arrays of the right dimensions into # cov_fun. if len(x.shape)>1: singleton_pt = np.zeros((1,x.shape[1]),dtype=float) else: singleton_pt = np.zeros(1,dtype=float) # Write in rows. for i in xrange(m): singleton_pt[:] = x[i,:] data_now = cov_fun(singleton_pt, x[i:,:], **params).view(np.ndarray).ravel() indices_now = np.where(data_now > cutoff)[0] for j in indices_now: C[i,j+i] = data_now[j] # C[j+i,i] = data_now[j] else: n=y.shape[0] C = cvx.base.spmatrix(0., range(m), range(n)) # Make sure you're passing np.arrays of the right dimensions into # cov_fun. if len(y.shape)>1: singleton_pt = np.zeros((1,y.shape[1]),dtype=float) else: singleton_pt = np.zeros(1,dtype=float) for i in xrange(n): singleton_pt[:] = y[i,:] data_now = cov_fun(singleton_pt, x, **params).view(np.ndarray).ravel() indices_now = np.where(data_now > cutoff)[0] for j in indices_now: C[i,j] = data_now[j] return C