예제 #1
0
    def __init__(self,
                 X,
                 Y,
                 U,
                 phi=observables.monomials(2),
                 psi=observables.monomials(2),
                 regressor='ols',
                 is_generator=False,
                 p_inv=True):
        self.X = X
        self.Y = Y
        self.U = U
        self.phi = phi
        self.psi = psi

        # Get number of data points
        self.N = self.X.shape[1]

        # Construct Phi and Psi matrices
        self.Phi_X = self.phi(X)
        self.Phi_Y = self.phi(Y)
        self.Psi_U = self.psi(U)

        # TODO: Create Koopman Generator Tensor if is_generator is True

        # Get dimensions
        self.dim_phi = self.Phi_X.shape[0]
        self.dim_psi = self.Psi_U.shape[0]

        # Make sure data is full rank
        # checkMatrixRank(self.Phi_X, "Phi_X")
        # checkMatrixRank(self.Phi_Y, "Phi_Y")
        # checkMatrixRank(self.Psi_U, "Psi_U")

        # Make sure condition numbers are small
        # checkConditionNumber(self.Phi_X, "Phi_X")
        # checkConditionNumber(self.Phi_Y, "Phi_Y")
        # checkConditionNumber(self.Psi_U, "Psi_U")

        # Build matrix of kronecker products between u_i and x_i for all 0 <= i <= N
        self.kronMatrix = np.empty([self.dim_psi * self.dim_phi, self.N])
        for i in range(self.N):
            self.kronMatrix[:, i] = np.kron(self.Psi_U[:, i], self.Phi_X[:, i])

        # Solve for M and B
        if regressor == 'rrr':
            self.M = estimate_L.rrr(self.kronMatrix.T, self.Phi_Y.T).T
            self.B = estimate_L.rrr(self.Phi_X.T, self.X.T)
        if regressor == 'sindy':
            self.M = estimate_L.SINDy(self.kronMatrix.T, self.Phi_Y.T).T
            self.B = estimate_L.SINDy(self.Phi_X.T, self.X.T)
        else:
            self.M = estimate_L.ols(self.kronMatrix.T, self.Phi_Y.T, p_inv).T
            self.B = estimate_L.ols(self.Phi_X.T, self.X.T, p_inv)

        # reshape M into tensor K
        self.K = np.empty([self.dim_phi, self.dim_phi, self.dim_psi])
        for i in range(self.dim_phi):
            self.K[i] = self.M[i].reshape([self.dim_phi, self.dim_psi],
                                          order='F')
예제 #2
0
def SINDy(X, eps=0.001, iterations=10):
    m = X.shape[1]
    psi = observables.monomials(m)
    PsiX = psi(X)

    # not sure what this is supposed to be
    Xi = Y @ _sp.linalg.pinv(PsiX) # least-squares initial guess

    for k in range(iterations):
        s = abs(Xi) < eps # find coefficients less than eps ...
        Xi[s] = 0         # ... and set them to zero

        for ind in range(m): # for each snapshot
            b = ~s[ind, :] # consider only functions corresponding to coefficients greater than eps
                           # '~' operator flips T/F of s
                           # if arr = [1,2] then arr[[False, True]] == [2]
            Xi[ind, b] = Y[ind, :] @ _sp.linalg.pinv(PsiX[b, :])
    return Xi
예제 #3
0
import observables
import tensorflow as tf
import tf_observables

x = tf.stack([[1], [5]])

order = 3
phi = observables.monomials(order)
tf_phi = tf_observables.monomials(order)

tf.assert_equal(tf.cast(phi(x), tf.float32), tf_phi(x))
예제 #4
0
N = 10000
action_range = 10
state_range = 10
U = np.random.rand(1, N) * action_range * np.random.choice(np.array([-1, 1]),
                                                           size=(1, N))
X0 = np.random.rand(2, N) * state_range * np.random.choice(np.array([-1, 1]),
                                                           size=(2, N))

#%% Construct snapshots of states following dynamics f
Y = f(X0, U)

#%% Estimate Koopman tensor
tensor = KoopmanTensor(X0,
                       Y,
                       U,
                       phi=observables.monomials(1),
                       psi=observables.monomials(1),
                       regressor='sindy')

#%% Training error
norms = np.empty((N))
for i in range(N):
    phi_x = np.vstack(tensor.Phi_X[:, i])  # current (lifted) state

    action = np.vstack(tensor.U[:, i])

    # true_x_prime = np.vstack(tensor.Y[:,i])
    true_phi_x_prime = np.vstack(tensor.Phi_Y[:, i])
    predicted_phi_x_prime = tensor.K_(action) @ phi_x

    # Compute norms
예제 #5
0
Z = np.roll(X,-1)[:, :-1]
X = X[:, :-1]

#%%
'''======================= SETUP/DEFINITIONS ======================='''
import observables
from sympy import symbols
from sympy.polys.monomials import itermonomials, monomial_count
from sympy.polys.orderings import monomial_key

d = X.shape[0]
m = X.shape[1]
s = int(d*(d+1)/2) # number of second order poly terms
rtoler=1e-02
atoler=1e-02
psi = observables.monomials(2)

#%%
x_str = ""
for i in range(d):
    x_str += 'x_' + str(i) + ', '
x_syms = symbols(x_str)
M = itermonomials(x_syms, 2)
sortedM = sorted(M, key=monomial_key('grlex', np.flip(x_syms)))
# print(sortedM)

#%%
Psi_X = psi(X)
Psi_X_T = Psi_X.T
nablaPsi = psi.diff(X)
nabla2Psi = psi.ddiff(X)
예제 #6
0
 def __init__(self):
     self.p = observables.monomials(2)
예제 #7
0
# define domain
bounds = np.array([[-2, 2], [-2, 2]])
boxes = np.array([50, 50])
Omega = domain.discretization(bounds, boxes)

# define system
gamma = -0.8
delta = -0.7


def b(x):
    return np.array([gamma * x[0, :], delta * (x[1, :] - x[0, :]**2)])


# define observables
psi = observables.monomials(8)

# generate data
X = Omega.rand(1000)  # generate test points
Y = b(X)

# apply generator EDMD
evs = 8  # number of eigenvalues/eigenfunctions to be computed
K, d, V = algorithms.gedmd(X, Y, None, psi, evs=evs, operator='K')
# printMatrix(K, 'K_gEDMD')
printVector(np.real(d), 'd_gEDMD')

V[:, 1] /= V[3, 1]
V[:, 3] /= V[10, 3]
V[:, 4] /= V[6, 4]  # normalize eigenvectors for convenience
for i in range(evs):
예제 #8
0
#%% Traditional LQR
lq = dlqr(A, B, Q, R)
C = lq[0]

#%% Construct snapshots of u from random agent and initial states x0
N = 10000
action_range = 10
state_range = 10
U = np.random.rand(1,N)*action_range*np.random.choice(np.array([-1,1]), size=(1,N))
X0 = np.random.rand(2,N)*state_range*np.random.choice(np.array([-1,1]), size=(2,N))

#%% Construct snapshots of states following dynamics f
Y = f(X0, U)

#%% Estimate Koopman tensor
tensor = KoopmanTensor(X0, Y, U, phi=observables.monomials(2), psi=observables.monomials(2))

#%% Training error
norms = np.empty((N))
for i in range(N):
    phi_x = np.vstack(tensor.Phi_X[:,i]) # current (lifted) state

    action = np.vstack(U[:,i])

    true_x_prime = np.vstack(Y[:,i])
    predicted_x_prime = tensor.B.T @ tensor.K_(action) @ phi_x

    # Compute norms
    norms[i] = utilities.l2_norm(true_x_prime, predicted_x_prime)
print("Training error:", np.mean(norms))
예제 #9
0
Y = np.empty(X.shape)
Z = np.empty((2, 2, X.shape[1]))
for i in range(X.shape[1]):
    s.c = U[0, i]
    # X_prime[:, i] = f(X[:, 0], s.beta, s.c)
    # Y[:, i] = y + s.b(y)*h + s.sigma(y)*np.sqrt(h)*np.random.randn()
    Y[:, i] = s.b(X[:, i])
    Z[0, 0, i] = s.sigma(X[:, i])
    Z[0, 1, i] = 0
    Z[1, 1, i] = s.sigma(X[:, i])
    Z[1, 0, i] = 0

#%% Define observables
order = 6
phi = observables.monomials(order)
psi = observables.monomials(order)  #lambda u: np.array([1])

#%% Build Phi and Psi matrices
N = X.shape[1]
Phi_X = phi(X)
Psi_U = psi(U)  #np.ones((1,N))
dim_phi = Phi_X[:, 0].shape[0]
dim_psi = Psi_U[:, 0].shape[0]

dPhi_Y = np.einsum('ijk,jk->ik', phi.diff(X), Y)
ddPhi_X = phi.ddiff(X)  # second-order derivatives
S = np.einsum('ijk,ljk->ilk', Z, Z)  # sigma \cdot sigma^T
for i in range(dim_phi):
    dPhi_Y[i, :] += 0.5 * np.sum(ddPhi_X[i, :, :, :] * S, axis=(0, 1))