# Basis

`DataDrivenDiffEq.Basis`

— Type`mutable struct Basis <: DataDrivenDiffEq.AbstractBasis`

A basis over the states with parameters, independent variable, and possible exogenous controls. It extends an `AbstractSystem`

as defined in `ModelingToolkit.jl`

. `f`

can either be a Julia function which is able to use ModelingToolkit variables or a vector of `eqs`

. It can be called with the typical SciML signature, meaning out of place with `f(u,p,t)`

or in place with `f(du, u, p, t)`

. If control inputs are present, it is assumed that no control corresponds to zero for all inputs. The corresponding function calls are `f(u,p,t,inputs)`

and `f(du,u,p,t,inputs)`

and need to be specified fully.

The optional `implicits`

declare implicit variables in the `Basis`

, meaning variables representing the (measured) target of the system. Right now only supported with the use of `ImplicitOptimizer`

s.

If `linear_independent`

is set to `true`

, a linear independent basis is created from all atom functions in `f`

.

If `simplify_eqs`

is set to `true`

, `simplify`

is called on `f`

.

Additional keyworded arguments include `name`

, which can be used to name the basis, and `observed`

for defining observables.

**Fields**

`eqs`

The equations of the basis

`states`

Dependent (state) variables

`ctrls`

Control variables

`ps`

Parameters

`observed`

Observed

`iv`

Independent variable

`implicit`

Implicit variables of the basis

`f`

Internal function representation of the basis

`name`

Name of the basis

`systems`

Internal systems

**Example**

```
using ModelingToolkit
using DataDrivenDiffEq
@parameters w[1:2] t
@variables u[1:2](t)
Ψ = Basis([u; sin.(w.*u)], u, parameters = p, iv = t)
```

**Note**

The keyword argument `eval_expression`

controls the function creation behavior. `eval_expression=true`

means that `eval`

is used, so normal world-age behavior applies (i.e. the functions cannot be called from the function that generates them). If `eval_expression=false`

, then construction via GeneralizedGenerated.jl is utilized to allow for same world-age evaluation. However, this can cause Julia to segfault on sufficiently large basis functions. By default eval_expression=false.

## Generators

`DataDrivenDiffEq.monomial_basis`

— Function```
monomial_basis(x)
monomial_basis(x, degree)
```

Constructs an array containing monomial basis in the variables `x`

up to degree `c`

of the form `[x₁, x₁^2, ... , x₁^c, x₂, x₂^2, ...]`

.

`DataDrivenDiffEq.polynomial_basis`

— Function```
polynomial_basis(x)
polynomial_basis(x, degree)
```

Constructs an array containing a polynomial basis in the variables `x`

up to degree `c`

of the form `[x₁, x₂, x₃, ..., x₁^1 * x₂^(c-1)]`

. Mixed terms are included.

`DataDrivenDiffEq.sin_basis`

— Function```
sin_basis(x, coefficients)
```

Constructs an array containing a Sine basis in the variables `x`

with coefficients `c`

. If `c`

is an `Int`

returns all coefficients from 1 to `c`

.

`DataDrivenDiffEq.cos_basis`

— Function```
cos_basis(x, coefficients)
```

Constructs an array containing a Cosine basis in the variables `x`

with coefficients `c`

. If `c`

is an `Int`

returns all coefficients from 1 to `c`

.

`DataDrivenDiffEq.fourier_basis`

— Function```
fourier_basis(x, coefficients)
```

Constructs an array containing a Fourier basis in the variables `x`

with (integer) coefficients `c`

. If `c`

is an `Int`

returns all coefficients from 1 to `c`

.

`DataDrivenDiffEq.chebyshev_basis`

— Function```
chebyshev_basis(x, coefficients)
```

Constructs an array containing a Chebyshev basis in the variables `x`

with coefficients `c`

. If `c`

is an `Int`

returns all coefficients from 1 to `c`

.

# Koopman

Since the results provided by `DMD-like`

have special information, they have a separate subtype.

`DataDrivenDiffEq.Koopman`

— Type`mutable struct Koopman{O, M, G, T} <: DataDrivenDiffEq.AbstractKoopman`

A special basis over the states with parameters , independent variable and possible exogenous controls. It extends an `AbstractBasis`

, which also stores information about the lifted dynamics, specified by a sufficient matrix factorization, an output mapping and internal variables to update the equations. It can be called with the typical SciML signature, meaning out of place with `f(u,p,t)`

or in place with `f(du, u, p, t)`

. If control inputs are present, it is assumed that no control corresponds to zero for all inputs. The corresponding function calls are `f(u,p,t,inputs)`

and `f(du,u,p,t,inputs)`

and need to be specified fully.

If `linear_independent`

is set to `true`

, a linear independent basis is created from all atom functions in `f`

.

If `simplify_eqs`

is set to `true`

, `simplify`

is called on `f`

.

Additional keyworded arguments include `name`

, which can be used to name the basis, and `observed`

for defining observeables.

**Fields**

`eqs`

The equations of the basis

`states`

Dependent (state) variables

`ctrls`

Control variables

`ps`

Parameters

`observed`

Observed

`iv`

Independent variable

`f`

Internal function representation of the basis

`lift`

Associated lifting of the operator

`name`

Name of the basis

`systems`

Internal systems

`is_discrete`

Discrete or time continuous

`K`

The operator/generator of the dynamics

`C`

Mapping back onto the observed states

`Q`

Internal matrix

`Q`

used for updating`P`

Internal matrix

`P`

used for updating

**Note**

The keyword argument `eval_expression`

controls the function creation behavior. `eval_expression=true`

means that `eval`

is used, so normal world-age behavior applies (i.e. the functions cannot be called from the function that generates them). If `eval_expression=false`

, then construction via GeneralizedGenerated.jl is utilized to allow for same world-age evaluation. However, this can cause Julia to segfault on sufficiently large basis functions. By default eval_expression=false.

## Functions

`DataDrivenDiffEq.is_discrete`

— Function```
is_discrete(k)
```

Returns `true`

if the `AbstractKoopmanOperator`

`k`

is discrete in time.

```
is_discrete(_)
```

Check if the problem is time discrete.

`DataDrivenDiffEq.is_continuous`

— Function```
is_continuous(k)
```

Returns `true`

if the `AbstractKoopmanOperator`

`k`

is continuous in time.

Check if the problem is time continuous.

`LinearAlgebra.eigen`

— Function```
eigen(k)
```

Return the eigendecomposition of the `AbstractKoopmanOperator`

.

`LinearAlgebra.eigvals`

— Function```
eigvals(k)
```

Return the eigenvalues of the `AbstractKoopmanOperator`

.

`LinearAlgebra.eigvecs`

— Function```
eigvecs(k)
```

Return the eigenvectors of the `AbstractKoopmanOperator`

.

`DataDrivenDiffEq.modes`

— Function```
modes(k)
```

Return the eigenvectors of a continuous `AbstractKoopmanOperator`

.

Missing docstring for `frequencies`

. Check Documenter's build log for details.

`DataDrivenDiffEq.operator`

— Function```
operator(k)
```

Return the approximation of the discrete Koopman operator stored in `k`

.

`DataDrivenDiffEq.generator`

— Function```
generator(k)
```

Return the approximation of the continuous Koopman generator stored in `k`

.

`DataDrivenDiffEq.updatable`

— Function```
updatable(k)
```

Returns `true`

if the `AbstractKoopmanOperator`

is updatable.

`DataDrivenDiffEq.is_stable`

— Function```
is_stable(k)
```

Returns `true`

if either:

- the Koopman operator has just eigenvalues with magnitude less than one or
- the Koopman generator has just eigenvalues with a negative real part

`DataDrivenDiffEq.update!`

— Function```
update!(k, X, Y; p, t, U, threshold)
```

Update the Koopman `k`

given new data `X`

and `Y`

. The operator is updated in place if the L2 error of the prediction exceeds the `threshold`

.

`p`

and `t`

are the parameters of the basis and the vector of timepoints, if necessary.