Source code for polytex.kriging.mdKrig

# !/usr/bin/env python
# -*- coding: utf-8 -*-

import numpy as np
import sympy as sym


[docs]def func_select(drift_name, cov_name): """ Function for definition of drift and covariance function in dictionary drif_funcs and cov_funcs. Parameters ---------- drift_name: str. The name of the drift function. Possible values are: "const", "lin", "quad". cov_name: str. The name of the covariance function. Possible values are: "lin", "cub", "log". Returns ------- drift_func: Function. The drift function. cov_func: Function. The covariance function. a_len: int. The length of the drift function. """ # Definitions of drift functions by dictionary drift_funcs = { 'const': lambda x, y, a: [a[0]], 'lin': lambda x, y, a: [a[0], a[1] * x, a[2] * y], 'quad': lambda x, y, a: [a[0], a[1] * x, a[2] * y, a[3] * (x ** 2.0), a[4] * (y ** 2.0), a[5] * x * y], } # Definitions of covariance functions by dictionary cov_funcs = { 'lin': lambda h: h, 'cub': lambda h: h ** 3.0, # Natural logarithm, element-wise. 'log': lambda h: h ** 2.0 * sym.log(h) if h != 0 else 0, } # Int number of 'a_len', which is based on the drift function, # will be used in building of kriging matrix. a_len = len(drift_funcs[drift_name](0, 0, [1, 1, 1, 1, 1, 1])) return drift_funcs[drift_name], cov_funcs[cov_name], a_len
[docs]def dist(xy, type="Euclidean"): """ Calculate the distance between each pair of points. Parameters ---------- xy: numpy array. The coordinates of the points. The shape is (m, 2). type: str. The type of the distance. The default is "Euclidean". Other possible values are: "1-norm" : The 1-norm distance. "inf-norm" : The infinity-norm distance. Returns ------- distance : numpy array The distance between each pair of points. The shape is (m, m). """ x, y = xy[:, 0], xy[:, 1] b_len = x.size xc = np.repeat(x, repeats=b_len, axis=0) xc = xc.reshape((b_len, b_len)) xr = xc.T yc = np.repeat(y, repeats=b_len, axis=0) yc = yc.reshape((b_len, b_len)) yr = yc.T if type == "Euclidean": distance = np.sqrt((xr - xc) ** 2 + (yr - yc) ** 2) elif type == "1-norm": distance = np.abs(xr - xc) + np.abs(yr - yc) elif type == "inf-norm": distance = np.max(np.abs(xr - xc), np.abs(yr - yc)) return distance
[docs]def buildM(xy, drift_name, cov_name): """ Build the kriging matrix. Parameters ---------- xy: The coordinates of the points. The shape is (m, 2). drift_name: str. The name of the drift function. Possible values are: "const", "lin", "quad". cov_name: str. The name of the covariance function. Possible values are: "lin", "cub", "log". Returns ------- drift_func: The drift function. cov_func: The covariance function. a_len: The length of the drift function. M: The matrix of the kriging system. The shape is (n,n). """ # ------------drift and covariance function selection------------ drift_func, cov_func, a_len = func_select(drift_name, cov_name) # -------- distance between each pair of points -------- distance = dist(xy) # ------------initialize the kriging matrix------------ b_len = xy.shape[0] n = b_len + a_len M = np.zeros((n, n)) # -------- assembling the kriging matrix -------- M[:b_len, :b_len] = cov_func(distance) # -------- elements depending on drift function -------- adef = [1, 1, 1, 1, 1, 1, 1, 1] a = drift_func(xy[:, 0], xy[:, 1], adef) for i in np.arange(a_len): M[:b_len, b_len + i] = a[i] M[b_len + i, :b_len] = a[i] return M, drift_func, cov_func, a_len
# TODO: verify the function
[docs]def nugget(M, nugg, b_len): """ Introduce the nugget effect to the kriging matrix. Parameters ---------- M : numpy array. The kriging matrix. The shape is (n,n). nugg : float. The nugget effect. Returns ------- M: numpy array. The kriging matrix with nugget effect. """ # -------- identity matrix with the same size as M -------- I = np.identity(b_len) # -------- multiply nugg to the diagonal of I -------- I = I * nugg # -------- add I to M -------- M[:b_len, :b_len] = M[:b_len, :b_len] + I return M
[docs]def buildU(z, a_len): """ Build the result vector of the kriging linear system. Parameters ---------- z: The values of the target function. The shape is (m,). a_len: The length of the drift function. Returns ------- U: The result vector of the kriging linear system. The shape is (n,). """ n = z.size + a_len U = np.zeros((n, 1)) U[:z.size, 0] = z return U
[docs]def solveB(M, U): """ Solve the kriging linear system. Parameters ---------- M: numpy array. The kriging matrix. U: numpy array. The result vector of the kriging linear system. Returns ------- B: numpy array. The solution of the kriging linear system (vector contains b_i and a_i). """ b = np.linalg.solve(M, U) # print('solution Matrix b writes:') # print(b) return b
[docs]def buildKriging(xy, z, drift_name, cov_name, nugg=0): """ Build the kriging model and return the expression in string format. Parameters ---------- xy: array like. The coordinates of the points. The shape is (m, 2). z: array like. The values of the target function. The shape is (m,). drift_name: str. The name of the drift function. The possible values are: 'const', 'lin', 'cub'. cov_name: str. The name of the covariance function. The possible values are: 'lin', 'cub', 'log'. nugg: float. The nugget effect (variance). Returns ------- :return: The expression of kriging function in string format. """ # ------- build the kriging matrix ------- M, drift_func, cov_func, a_len = buildM(xy, drift_name, cov_name) # ------- introduce nugget effect ------- b_len = xy.shape[0] M = nugget(M, nugg, b_len) # ------- build the result vector ------- U = buildU(z, a_len) # ------- solve the kriging linear system ------- B = solveB(M, U) # ------- build the kriging model ------- x, y = sym.symbols('x y') doc_krig = drift_func(x, y, B[b_len:]) for i in np.arange(xy.shape[0]): bi_cov = ((cov_func((x - xy[:, 0][i]) ** 2 + (y - xy[:, 1][i]) ** 2)) ** (1 / 2)) * B[i, 0] # store all the terms including drift and generalized covariance doc_krig = np.append(doc_krig, bi_cov) return doc_krig.sum()
[docs]def interp(xy, expr): """ TODO: add description Parameters ---------- xy: numpy array. The coordinates of the points. The shape is (m, 2). expr: String. The expression of the target function. Returns ------- yinter: The values of the kriging function. The shape is (m,). """ x, y = sym.symbols('x y') yinter = np.empty(xy.shape[0]) for pts in range(xy.shape[0]): yinter[pts] = expr.subs({x: xy[pts, 0], y: xy[pts, 1]}) yinter[np.abs(yinter) < 1e-15] = 0. return yinter
if __name__ == '__main__': dataset = [[1, 0, 0], [0, 1, 0], [-1, 0, 0], [0, -1, 0], [0, 0, 1]] dataset = np.array(dataset) xy = dataset[:, :2] z = dataset[:, 2] expr = buildKriging(xy, z, 'lin', 'cub', nugg=0.01) zInterp = interp(dataset[:, :2], expr)