Skip to content

Commit

Permalink
Added support for evaluating basis at new points
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffrey-hokanson committed Aug 11, 2020
1 parent 852380e commit 96fb9b4
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 6 deletions.
10 changes: 6 additions & 4 deletions polyrat/basis.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ def _scale(self, X):


class LaguerrePolynomialBasis(TensorProductPolynomialBasis):
# TODO: Change scaling to match orthogonality conditions
def _vander(self, *args, **kwargs):
return lagvander(*args, **kwargs)
def _der(self, *args, **kwargs):
Expand All @@ -119,6 +118,9 @@ def _roots(self, *args, **kwargs):
return lagroots(*args, **kwargs)

def _set_scale(self, X):
r""" Laguerre polynomial expects x[i] to be distributed like exp[-lam*x] on [0,infty)
so we shift so that all entries are positive and then set a scaling
"""
self._lb = np.min(X, axis = 0)
self._a = 1./np.mean(X - self._lb[None,:], axis = 0)

Expand Down Expand Up @@ -243,8 +245,8 @@ def vandermonde_arnoldi_eval(X, R, indices, mode, weight = None):
W[:,0] = weight/R[0,0]

# Now work on the remaining columns
for k, ids in iteridx:
i, j = _update_vec(idx[:k], ids)
for k, ids in iter_indices:
i, j = update_rule(indices[:k], ids)
# Form new column
w = X[:,i] * W[:,j]

Expand Down Expand Up @@ -286,5 +288,5 @@ def basis(self):
return self._Q

def vandermonde(self, X, weight = None):
return vanderonde_arnoldi_eval(X, self._R, self._indices, self.mode, weight = weight)
return vandermonde_arnoldi_eval(X, self._R, self._indices, self.mode, weight = weight)

93 changes: 91 additions & 2 deletions tests/test_basis.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import numpy as np
import pytest
from polyrat import *

from scipy.linalg import subspace_angles



Expand Down Expand Up @@ -75,8 +75,97 @@ def test_monomial_max(M, degree, Basis, seed):
assert err_norm < 1e-8, "Vector not contained in space"


@pytest.mark.parametrize("n_grid", [10])
@pytest.mark.parametrize("degree",[
5,
(7,2),
(2,7),
(3,0,4)
])
@pytest.mark.parametrize("dim", [1,2,3])
@pytest.mark.parametrize("Basis",
[MonomialPolynomialBasis,
ChebyshevPolynomialBasis,
HermitePolynomialBasis,
LaguerrePolynomialBasis,
ArnoldiPolynomialBasis])
def test_subspace_angles_basis(n_grid, degree, dim, Basis):

# Exit without error if testing a total degree problem
try:
degree = int(degree)
except (TypeError, ValueError):
if len(degree) != dim: return

# Construct grid
Xs = np.meshgrid(*[np.linspace(-1,1,n_grid) for i in range(dim)])
X = np.vstack([Xi.flatten() for Xi in Xs]).T


# We use Legendre polynomials as a reference solution
leg = LegendrePolynomialBasis(X, degree)
basis = Basis(X, degree)

V1 = leg.basis()
V2 = basis.basis()

tol = 1e-10
# This Laguerre polynomials are not particularly well conditioned
if Basis is LaguerrePolynomialBasis: tol = 1e-7

for k in range(1,V1.shape[1]):
ang = subspace_angles(V1[:,:k], V2[:,:k])
print(basis._indices[k], np.max(ang))
assert np.max(ang) < tol



@pytest.mark.parametrize("seed", [0])
@pytest.mark.parametrize("degree",[
5,
(7,2),
(2,7),
(3,0,4)
])
@pytest.mark.parametrize("dim", [1,2,3])
@pytest.mark.parametrize("Basis",
[MonomialPolynomialBasis,
ChebyshevPolynomialBasis,
HermitePolynomialBasis,
LaguerrePolynomialBasis,
ArnoldiPolynomialBasis])
def test_subspace_angles(seed, degree, dim, Basis):

# Exit without error if testing a total degree problem
try:
degree = int(degree)
except (TypeError, ValueError):
if len(degree) != dim: return

# Construct grid
X = np.random.randn(500, dim)

X2 = np.random.randn(200, dim)
# We use Legendre polynomials as a reference solution
leg = LegendrePolynomialBasis(X, degree)
basis = Basis(X, degree)

V1 = leg.vandermonde(X2)
V2 = basis.vandermonde(X2)

tol = 1e-10
# This Laguerre polynomials are not particularly well conditioned
if Basis is LaguerrePolynomialBasis: tol = 1e-7

for k in range(1,V1.shape[1]):
ang = subspace_angles(V1[:,:k], V2[:,:k])
print(basis._indices[k], np.max(ang))
assert np.max(ang) < tol




if __name__ == '__main__':
#test_monomial_total(100, 10, 3, MonomialPolynomialBasis,0)
test_monomial_max(100, [4], MonomialPolynomialBasis,0)
#test_monomial_max(100, [4], MonomialPolynomialBasis,0)
test_subspace_angles(10, [1,4], 2, ArnoldiPolynomialBasis)

0 comments on commit 96fb9b4

Please sign in to comment.