Esempio n. 1
0
def interp_nd_coef(z, x, dx, y, dy, beta, gamma, \
                   order_set, boundary_set, boundary_zeta):
  """
  Calculate interpolation coefficients in n-dimensional spacee.
  z is the point where the interpolation is evaluated, the size of z
    is the dimension of the space.
  x is the points where the function value is available, the columns of x
    must be the same as the size of z.
  dx is the measurement error at x, its size must be same as the rows of x.
  y is the points where the function gradient is available, the columns of y
    must be the same as the size of z.
  dy is the measurement error at y, must has same shape as y.
  beta is the `magnitude' of the target function.
  gamma is the `wave number' of the target function.
    combined with beta, it provides an estimate of the derivative growth:
      f^(k) = O(beta * gamma**k)
    larger gamma = more conservative and lower order interpolation.
  order_set is the expansion order set of the Taylor expansions.
  boundary_set is the boundary of order_set.
  boundary_zeta.
  return values:
    a, b, er2 = interp_nd_coef(...)
  a and b are the interpolation coefficients.
  er2 is the expected squared residual.
  """
  # verifying arguments
  gamma = float(gamma)
  d, n, m = z.size, x.shape[0], y.shape[0]
  assert z.shape == (d,)
  assert x.shape == (n, d) and dx.shape == (n,)
  assert y.shape == (m, d) and dy.shape == (m, d) or m == 0
  assert len(order_set) > 1 and order_set[0] == (0,) * d
  # calculate interpolant at z
  d2 = ((x - z)**2).sum(1)
  if d2.min() < 1.0E-18:    # exactly matches a data point
    imatch = d2.argmin()
    if dx[imatch] == 0.0:   # and function value on that point is exact
      a = numpy.array([0]*imatch+[1]+[0]*(n-imatch-1))
      b = numpy.zeros([m, d])
      return a, b, 0.0
  # construct X = [Xa,Xb]
  N = len(order_set) - 1
  X = zeros([N, n+m*d], dtype=float)
  for i, kappa in enumerate(order_set[1:]):
    # Xa part
    X[i,:n] = gamma**sum(kappa) / factorial(kappa) * ((x - z)**kappa).prod(1)
    # Xb part
    if m > 0:
      for k in range(d):
        if kappa[k] > 0:
          kappa_p = kappa[:k] + (kappa[k] - 1,) + kappa[k+1:]
          X[i,n+k*m:n+(k+1)*m] = gamma**sum(kappa) / factorial(kappa_p) * \
                                 ((y - z)**kappa_p).prod(1)
  X *= beta
  # construct diagonal G matrix for the Lagrange residual
  G2 = zeros(n+m*d)
  for kappa, zeta in zip(boundary_set, boundary_zeta):
    Gi = gamma**sum(kappa) / factorial(kappa) * \
         ((x - z)**kappa).prod(1) * sum(zeta) / sum(kappa)
    G2[:n] += Gi**2
    if m > 0:
      for k in range(d):
        if kappa[k] > 0:
          kappa_p = kappa[:k] + (kappa[k] - 1,) + kappa[k+1:]
          zeta_p = zeta[:k] + (max(0, zeta[k] - 1),) + zeta[k+1:]
          Gi = gamma**sum(kappa) / factorial(kappa_p) * \
               ((y - z)**kappa_p).prod(1) * sum(zeta_p) / sum(kappa_p)
          G2[n+k*m:n+(k+1)*m] += Gi**2
  G = sqrt(G2) * beta
  # construct diagonal H matrix for measurement errors
  H = zeros(n+m*d)
  H[:n] = dx
  if m > 0:
    for k in range(d):
      H[n+k*m:n+(k+1)*m] = dy[:,k]
  # construct c
  c = zeros(n+m*d); c[:n] = 1.0
  # first try to assemble the diagonal of matrix A, and sort by its diagonal
  diagA = (X**2).sum(0) + G**2 + H**2
  isort = sorted(range(n+m*d), key=diagA.__getitem__)
  irevt = sorted(range(n+m*d), key=isort.__getitem__)
  # permute columns of X and diagonal of G and H
  X = X[:,isort]
  G = G[isort]
  H = H[isort]
  c = c[isort]
  ab = quad_prog(X, G, H, c)
  # reverse sorting permutation to get a and b and normalize
  abrevt = ab[irevt]
  a = abrevt[:n]
  b = zeros([m,d])
  for k in range(d):
    b[:,k] = abrevt[n+k*m:n+(k+1)*m]
  # compute the expeted squared residual
  finite = (ab != 0)
  Xab = dot(X[:,finite], ab[finite])**2
  Gab = (G*ab)[finite]**2
  Hab = (H*ab)[finite]**2
  er2 = Xab.sum() + Gab.sum() + Hab.sum()
  return a, b, er2
Esempio n. 2
0
def interp_nd_grad_coef(ix, x, gamma, \
                        order_set, boundary_set, boundary_zeta):
  """
  Calculate interpolation gradient coefficients in n-dimensional spacee.
  x[ix] is the point where the interpolation is evaluated.
  x is the points where the function value is available, the columns of x
    must be the same as the size of z.
  gamma is the `wave number' of the target function.
    it provides an estimate of the derivative growth: f^(k) = O(gamma**k)
    larger gamma = more conservative and lower order interpolation.
  order_set is the expansion order set of the Taylor expansions.
  boundary_set is the boundary of order_set.
  boundary_zeta.
  return values:
    da = interp_nd_coef(...)
  da are the interpolation gradient coefficients.
  """
  # verifying arguments
  gamma = float(gamma)
  d, n = x.shape[1], x.shape[0]
  assert len(order_set) > 1 and order_set[0] == (0,) * d
  # construct X
  N = len(order_set) - 1
  X = zeros([N, n], dtype=float)
  for i, kappa in enumerate(order_set[1:]):
    X[i,:] = gamma**sum(kappa) / factorial(kappa) * \
              ((x - x[ix,:])**kappa).prod(1)
  # construct diagonal G matrix for the Lagrange residual
  G2 = zeros(n)
  for kappa, zeta in zip(boundary_set, boundary_zeta):
    Gi = gamma**sum(kappa) / factorial(kappa) * \
         ((x - x[ix,:])**kappa).prod(1) * sum(zeta) / sum(kappa)
    G2[:n] += Gi**2
  G = sqrt(G2)
  # construct c
  c = ones(n)
  # first try to assemble the diagonal of matrix A, and sort by its diagonal
  diagA = (X**2).sum(0) + G**2
  finite = numpy.isfinite(diagA)
  isort = sorted(range(n), key=diagA.__getitem__)
  irevt = sorted(range(n), key=isort.__getitem__)
  # drop first one -- all 0
  assert isort[0] == ix
  isort = isort[1:]
  # permute columns of X and diagonal of G and H
  X = X[:,isort]
  G = G[isort]
  c = c[isort]
  finite = finite[isort]
  # filter out faraway elements
  X = X[:,finite]
  G = G[finite]
  # QR decomposition of X, R is now cholesky factor of A
  n1, n2 = X.shape
  A = zeros([n1+n2, n2])
  A[:n1,:] = X
  A[range(n1,n1+n2), range(n2)] = G
  R = numpy.linalg.qr(A, mode='r')
  # ------------------- gradient part -----------------
  da = zeros([c.size + 1, d])
  for i in range(d):
    # calculate rhs = dA * a
    kappa = (0,) * i + (1,) + (0,) * (d-i-1)
    ind = order_set.index(kappa) - 1
    rhs = - gamma * X[ind,:]
    # solve for da
    tmp = solve_L(R.transpose(), rhs)
    da[1:,i][finite] = solve_R(R, tmp)
    da[0,i] = -dot(da[1:,i], c)
  # reverse sorting permutation to get a and b and normalize
  da = da[irevt,:]
  return -da