### Install DataDrivenSparse Source: https://docs.sciml.ai/DataDrivenDiffEq/stable Install the DataDrivenSparse subpackage for Sparse Regression algorithms to approximate systems of differential equations. ```julia using Pkg Pkg.add("DataDrivenSparse") ``` -------------------------------- ### Quick-start Example for DataDrivenDiffEq.jl Source: https://docs.sciml.ai/DataDrivenDiffEq/stable This example demonstrates how to use DataDrivenDiffEq.jl to find a system of equations from a dataset generated by the Lorenz system. It involves setting up an ODE problem, solving it, and then using the DataDrivenProblem and Basis to perform sparse regression. ```julia using DataDrivenDiffEq using ModelingToolkit using OrdinaryDiffEq using DataDrivenSparse using LinearAlgebra # Create a test problem function lorenz(u, p, t) x, y, z = u ẋ = 10.0 * (y - x) ẏ = x * (28.0 - z) - y ż = x * y - (8 / 3) * z return [ẋ, ẏ, ż] end u0 = [1.0; 0.0; 0.0] tspan = (0.0, 100.0) dt = 0.1 prob = ODEProblem(lorenz, u0, tspan) sol = solve(prob, Tsit5(), saveat = dt) ## Start the automatic discovery ddprob = DataDrivenProblem(sol) @variables t x(t) y(t) z(t) u = [x; y; z] basis = Basis(polynomial_basis(u, 5), u, iv = t) opt = STLSQ(exp10.(-5:0.1:-1)) ddsol = solve(ddprob, basis, opt, options = DataDrivenCommonOptions(digits = 1)) println(get_basis(ddsol)) ``` ```julia Model ##Basis#257 with 3 equations States : x(t) y(t) z(t) Parameters : 7 Independent variable: t Equations Differential(t)(x(t)) = p₁*x(t) + p₂*y(t) Differential(t)(y(t)) = p₃*x(t) + p₄*y(t) + p₅*x(t)*z(t) Differential(t)(z(t)) = p₇*z(t) + p₆*x(t)*y(t) ``` -------------------------------- ### Complete Copy-Pasteable Code for Autoregulation Example Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_04 A consolidated script containing all necessary imports and code for running the autoregulation example, suitable for direct copy-pasting. ```julia using DataDrivenDiffEq using ModelingToolkit using ModelingToolkit: t_nounits as t, D_nounits as D using OrdinaryDiffEq using LinearAlgebra using DataDrivenSparse @mtkmodel Autoregulation begin @parameters begin α = 1.0 β = 1.3 γ = 2.0 δ = 0.5 end @variables begin (x(t))[1:2] = [20.0; 12.0] end @equations begin D(x[1]) ~ α / (1 + x[2]) - β * x[1] D(x[2]) ~ γ / (1 + x[1]) - δ * x[2] end end @mtkbuild sys = Autoregulation() tspan = (0.0, 5.0) de_problem = ODEProblem{true, SciMLBase.NoSpecialize}(sys, [], tspan, []) de_solution = solve(de_problem, Tsit5(), saveat = 0.005); dd_prob = DataDrivenProblem(de_solution) x = sys.x eqs = [polynomial_basis(x, 4); D.(x); x .* D(x[1]); x .* D(x[2])] basis = Basis(eqs, x, independent_variable = t, implicits = D.(x)) sampler = DataProcessing(split = 0.8, shuffle = true, batchsize = 30) res = solve(dd_prob, basis, ImplicitOptimizer(STLSQ(1e-2:1e-2:1.0)), options = DataDrivenCommonOptions(data_processing = sampler, digits = 2)) system = get_basis(res) #hide # This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl ``` -------------------------------- ### Install DataDrivenDMD Source: https://docs.sciml.ai/DataDrivenDiffEq/stable Install the DataDrivenDMD subpackage for Koopman Based Inference using Dynamic Mode Decomposition (DMD) and Extended Dynamic Mode Decomposition (EDMD). ```julia using Pkg Pkg.add("DataDrivenDMD") ``` -------------------------------- ### Install DataDrivenSR Source: https://docs.sciml.ai/DataDrivenDiffEq/stable Install the DataDrivenSR subpackage for Symbolic Regression using SymbolicRegression.jl to find suitable equations matching data. ```julia using Pkg Pkg.add("DataDrivenSR") ``` -------------------------------- ### Complete Example Code Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_01 A complete, copy-pasteable code block demonstrating the entire workflow from imports to solving the problem. ```julia using DataDrivenDiffEq using ModelingToolkit using LinearAlgebra using DataDrivenSparse f(u) = u .^ 2 .+ 2.0u .- 1.0 X = randn(1, 100); Y = reduce(hcat, map(f, eachcol(X))); problem = DirectDataDrivenProblem(X, Y, name = :Test) @variables u basis = Basis(monomial_basis([u], 2), [u]) println(basis) # hide res = solve(problem, basis, STLSQ()) println(res) # hide # This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl ``` -------------------------------- ### Install DataDrivenDiffEq.jl Source: https://docs.sciml.ai/DataDrivenDiffEq/stable Use this command to add the DataDrivenDiffEq.jl package to your Julia environment. ```julia using Pkg Pkg.add("DataDrivenDiffEq") ``` -------------------------------- ### Continuous Data-Driven Problem Setup Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_02 Sets up a continuous data-driven problem using the generated noisy data. This involves defining the data, time points, kernel, and optional control inputs and parameters. ```julia prob = ContinuousDataDrivenProblem(X, ts, GaussianKernel(), U = (u, p, t) -> [exp(-((t - 5.0) / 5.0)^2)], p = ones(2)) ``` -------------------------------- ### Solving with Koopman Inference Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/solvers/common Example of using the `solve` function for Koopman-based inference using `DMDSVD`. It demonstrates passing common options and other keyword arguments. ```julia # Use a Koopman based inference without a basis res = solve(problem, DMDSVD(); options = DataDrivenCommonOptions(), kwargs...) ``` -------------------------------- ### Solving with Sparse Identification Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/solvers/common Example of using the `solve` function for sparse identification using `STLSQ`. It shows how to provide a basis and common options. ```julia # Use a sparse identification res = solve(problem, basis, STLSQ(); options = DataDrivenCommonOptions(), kwargs...) ``` -------------------------------- ### Define a Basis with Symbolic Variables Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/basis Example of creating a Basis using symbolic variables and parameters defined with ModelingToolkit. This is useful for defining complex state spaces for differential equations. ```julia using ModelingToolkit using DataDrivenDiffEq @parameters w[1:2] t @variables u[1:2](t) Ψ = Basis([u; sin.(w.*u)], u, parameters = p, iv = t) ``` -------------------------------- ### Get Algorithm Used Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/solutions Retrieves the algorithm that was used to derive the DataDrivenSolution. ```julia get_algorithm(r) ``` -------------------------------- ### Get Original Algorithm Output Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/solutions Retrieves the raw output from the algorithm that generated the DataDrivenSolution. ```julia get_results(r) ``` -------------------------------- ### Copy-Pasteable Code Block Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensr/examples/example_01 A consolidated block of all the code used in this example, suitable for direct copy-pasting. ```julia using DataDrivenDiffEq using LinearAlgebra using OrdinaryDiffEq using DataDrivenSR A = [-0.9 0.2; 0.0 -0.5] B = [0.0; 1.0] u0 = [10.0; -10.0] tspan = (0.0, 20.0) f(u, p, t) = A * u .+ B .* sin(0.5 * t) sys = ODEProblem(f, u0, tspan) sol = solve(sys, Tsit5(), saveat = 0.01); X = Array(sol) t = sol.t U = permutedims(sin.(0.5 * t)) prob = ContinuousDataDrivenProblem(X, t, U = U) eqsearch_options = SymbolicRegression.Options(binary_operators = [+, *], loss = L1DistLoss(), verbosity = -1, progress = false, npop = 30, timeout_in_seconds = 60.0) alg = EQSearch(eq_options = eqsearch_options) res = solve(prob, alg, options = DataDrivenCommonOptions(maxiters = 100)) loglikelihood(res) system = get_basis(res) # This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl ``` -------------------------------- ### Get Original DataDrivenProblem Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/solutions Retrieves the original DataDrivenProblem from a DataDrivenSolution. ```julia get_problem(r) ``` -------------------------------- ### Get Parameter Map with Default Values Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/basis Returns a vector of pairs representing the default values for the parameters of a Basis. Similar to `get_parameter_values`, it returns zero if no default is stored. ```julia get_parameter_map(x) ``` -------------------------------- ### Complete Copy-Pasteable Code for Implicit Dynamics Identification Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_03 A consolidated Julia script containing all necessary imports, function definitions, data generation, basis construction, and the sparse identification process for the Michaelis-Menten example. This snippet is ready to be copied and executed. ```julia using DataDrivenDiffEq using LinearAlgebra using OrdinaryDiffEq using DataDrivenSparse function michaelis_menten(u, p, t) [0.6 - 1.5u[1] / (0.3 + u[1])] end u0 = [0.5] ode_problem = ODEProblem(michaelis_menten, u0, (0.0, 4.0)); prob = DataDrivenDataset(map(1:2) do i solve(remake(ode_problem, u0 = i * u0), Tsit5(), saveat = 0.1, tspan = (0.0, 4.0)) end...) @parameters t @variables u(t)[1:1] u = collect(u) D = Differential(t) h = [monomial_basis(u[1:1], 4)...] basis = Basis([h; h .* (D(u[1]))], u, implicits = D.(u), iv = t) opt = ImplicitOptimizer(1e-1:1e-1:5e-1) res = solve(prob, basis, opt) summarystats(res) # This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl ``` -------------------------------- ### Get Default Parameter Values Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/basis Returns the default numeric values for the parameters of a Basis. If no default value is stored, it returns zero of the parameter's symbolic type. ```julia get_parameter_values(x) ``` -------------------------------- ### Initialize SR3 Sparse Regression Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/sparse_regression Instantiate the SR3 optimizer framework with sparsity threshold, relaxation parameter, and an optional proximal operator. ```julia opt = SR3() opt = SR3(1e-2) opt = SR3(1e-3, 1.0) opt = SR3(1e-3, 1.0, SoftThreshold()) ``` -------------------------------- ### Get Degrees of Freedom Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/solutions Returns the degrees of freedom for a DataDrivenSolution. ```julia dof(sol) ``` -------------------------------- ### Setting up Continuous Data-Driven Problem Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_05 Creates a ContinuousDataDrivenProblem instance using the simulated data. It requires the state trajectories (X), time points (t), and the derivatives (DX). External control inputs can also be provided. ```julia ddprob = ContinuousDataDrivenProblem(X, t, DX = DX[3:4, :], U = (u, p, t) -> [-0.2 + 0.5 * sin(6 * t)]) ``` -------------------------------- ### Get Problem Name Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/problems Utility function to retrieve the name of a DataDrivenProblem. ```julia get_name(p) ``` -------------------------------- ### Get Number of Observations Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/solutions Returns the number of observations used in the DataDrivenSolution. ```julia nobs(sol) ``` -------------------------------- ### Get Recovered Basis Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/solutions Retrieves the recovered Basis representation from a DataDrivenSolution. ```julia get_basis(r) ``` -------------------------------- ### Initialize STLSQ Sparse Regression Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/sparse_regression Instantiate the STLSQ algorithm with different sparsity thresholds and optional ridge regression parameters. ```julia opt = STLSQ() opt = STLSQ(1e-1) opt = STLSQ(1e-1, 1.0) # Set rho to 1.0 opt = STLSQ(Float32[1e-2; 1e-1]) ``` -------------------------------- ### Create DataDrivenProblem from Solution Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensr/examples/example_02 Initializes a DataDrivenProblem using the solution of the ODE. This problem object will be used as input for the symbolic regression algorithm. ```julia prob = DataDrivenProblem(sol) ``` -------------------------------- ### Get Log-Likelihood Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/solutions Returns the log-likelihood of the DataDrivenSolution, assuming normally distributed errors. ```julia loglikelihood(sol) ``` -------------------------------- ### Initialize ImplicitOptimizer Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/sparse_regression Instantiate the ImplicitOptimizer with an explicit optimizer or parameters for sparse implicit relationship finding. ```julia ImplicitOptimizer(STLSQ()) ImplicitOptimizer(0.1f0, ADMM) ``` -------------------------------- ### Get Residual Sum of Squares Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/solutions Returns the residual sum of squares (RSS) for a DataDrivenSolution. ```julia rss(sol) ``` -------------------------------- ### Import Necessary Libraries Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_01 Import the required libraries for DataDrivenDiffEq.jl, ModelingToolkit, LinearAlgebra, and DataDrivenSparse. ```julia using DataDrivenDiffEq using ModelingToolkit using LinearAlgebra using DataDrivenSparse ``` -------------------------------- ### Create DataDrivenProblem and Basis for Sparse Regression Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_04 Initializes a DataDrivenProblem from the ODE solution and defines a basis including polynomial terms, derivatives, and products for sparse regression. ```julia dd_prob = DataDrivenProblem(de_solution) x = sys.x eqs = [polynomial_basis(x, 4); D.(x); x .* D(x[1]); x .* D(x[2])] basis = Basis(eqs, x, independent_variable = t, implicits = D.(x)) plot(dd_prob) ``` -------------------------------- ### Create Continuous DataDrivenProblem Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensr/examples/example_01 Prepares the data from the solved ODE problem for symbolic regression. It extracts the state trajectories, time points, and control signals, including a sinusoidal control input. ```julia X = Array(sol) t = sol.t U = permutedims(sin.(0.5 * t)) prob = ContinuousDataDrivenProblem(X, t, U = U) ``` -------------------------------- ### Get Summary Statistics Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/solutions Returns summary statistics for each row of the error term within the DataDrivenSolution. ```julia summarystats(sol) ``` -------------------------------- ### Get Log-Likelihood Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensr/examples/example_01 Calculates and retrieves the log-likelihood of the inferred model, which is a measure of how well the model fits the data. ```julia loglikelihood(res) ``` -------------------------------- ### Cart-Pole System Simulation and Data Generation Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_05 Simulates the cart-pole system using OrdinaryDiffEq and generates data for system identification. Requires initial conditions, time span, and a time step for simulation. ```julia using DataDrivenDiffEq using ModelingToolkit using OrdinaryDiffEq using LinearAlgebra using DataDrivenSparse function cart_pole(u, p, t) du = similar(u) F = -0.2 + 0.5 * sin(6 * t) # the input du[1] = u[3] du[2] = u[4] du[3] = -(19.62 * sin(u[1]) + sin(u[1]) * cos(u[1]) * u[3]^2 + F * cos(u[1])) / (2 - cos(u[1])^2) du[4] = -(sin(u[1]) * u[3]^2 + 9.81 * sin(u[1]) * cos(u[1]) + F) / (2 - cos(u[1])^2) return du end u0 = [0.3; 0; 1.0; 0] tspan = (0.0, 5.0) dt = 0.05 cart_pole_prob = ODEProblem(cart_pole, u0, tspan) solution = solve(cart_pole_prob, Tsit5(), saveat = dt) X = solution[:, :] DX = similar(X) for (i, xi) in enumerate(eachcol(X)) DX[:, i] = cart_pole(xi, [], solution.t[i]) end t = solution.t ``` -------------------------------- ### Get Null Log-Likelihood Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/solutions Returns the null log-likelihood for a DataDrivenSolution, corresponding to a model with only an intercept and normally distributed errors. ```julia nullloglikelihood(sol) ``` -------------------------------- ### Create DataDrivenProblem from Solution Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivendmd/examples/example_01 Transforms a simulated solution object into a DataDrivenProblem. This is a straightforward conversion when the solution is known to be discrete. ```julia prob = DataDrivenProblem(sol) ``` -------------------------------- ### Validate DataDrivenProblem Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/problems Checks if a DataDrivenProblem is valid by ensuring no NaN or Inf values and consistent measurement counts. Example usage provided. ```julia is_valid(x) ``` ```julia is_valid(problem) ``` -------------------------------- ### Configure EQSearch Algorithm Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensr/examples/example_01 Sets up the EQSearch algorithm, a wrapper for SymbolicRegression.jl. It configures options such as binary operators, loss function, verbosity, and timeout. ```julia eqsearch_options = SymbolicRegression.Options(binary_operators = [+, *], loss = L1DistLoss(), verbosity = -1, progress = false, npop = 30, timeout_in_seconds = 60.0) alg = EQSearch(eq_options = eqsearch_options) ``` -------------------------------- ### Create DataDrivenProblem with Collocation and Controls Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_02 Initializes a ContinuousDataDrivenProblem using noisy measurements and timestamps. It employs a GaussianKernel for smoothing and incorporates a control signal and parameters. ```julia prob = ContinuousDataDrivenProblem(X, ts, GaussianKernel(), U = (u, p, t) -> [exp(-((t - 5.0) / 5.0)^2)], p = ones(2)) plot(prob, size = (600,600)) ``` -------------------------------- ### Initialize ADMM Sparse Regression Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/sparse_regression Instantiate the ADMM algorithm for Lasso regression with specified threshold and augmented Lagrangian parameters. ```julia opt = ADMM() opt = ADMM(1e-1, 2.0) ``` -------------------------------- ### Get Coefficient of Determination (R-squared) Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/solutions Returns the coefficient of determination (R²) for the DataDrivenSolution. Note: Only implements Cox & Snell R² based on log-likelihoods. ```julia r2(sol) ``` -------------------------------- ### Specify Custom Model Selector Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/solvers/common Use `DataDrivenCommonOptions` with a custom selector function to control model selection. This example uses the mean squared error. ```julia options = DataDrivenCommonOptions(selector = (x) -> rss(x) / nobs(x)) ``` -------------------------------- ### Simulate Linear Discrete System Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivendmd/examples/example_01 Simulates a linear discrete system using OrdinaryDiffEq.jl and generates a DiscreteDataDrivenProblem from the solution. Ensure necessary packages are imported. ```julia using DataDrivenDiffEq using LinearAlgebra using OrdinaryDiffEq using DataDrivenDMD using Plots A = [0.9 -0.2; 0.0 0.2] u0 = [10.0; -10.0] tspan = (0.0, 11.0) f(u, p, t) = A * u sys = DiscreteProblem(f, u0, tspan) sol = solve(sys, FunctionMap()); ``` -------------------------------- ### Solve Implicit Sparse Identification Problem Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_03 Initializes an ImplicitOptimizer with a range of regularization parameters and solves the sparse identification problem using the generated data and defined basis. This process finds the coefficients for the basis functions that best represent the underlying dynamics. ```julia opt = ImplicitOptimizer(1e-1:1e-1:5e-1) res = solve(prob, basis, opt) ``` -------------------------------- ### Compare Derivatives Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivendmd/examples/example_02 Compares the automatically computed derivatives with the exact derivatives from the ODE solution. Uses scatter and plot! for visualization. ```julia DX = Array(sol(t, Val{1})) scatter(t, DX', label = ["Solution" nothing], color = :red, legend = :bottomright) plot!(t, prob.DX', label = ["Linear Interpolation" nothing], color = :black) ``` -------------------------------- ### Sparse System Identification with Implicit Optimizer Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_05 Performs sparse system identification using the ImplicitOptimizer with a predefined set of regularization parameters (lambda). The result is a sparse representation of the system's dynamics. ```julia λ = [1e-4; 5e-4; 1e-3; 2e-3; 3e-3; 4e-3; 5e-3; 6e-3; 7e-3; 8e-3; 9e-3; 1e-2; 2e-2; 3e-2; 4e-2; 5e-2] opt = ImplicitOptimizer(λ) res = solve(ddprob, basis, opt) system = get_basis(res) ``` -------------------------------- ### Get Internal Dynamics Function Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/basis Retrieves the internal function representing the dynamics of a Basis. This function can be called in-place or out-of-place with standard SciML signatures, including support for control variables. ```julia dynamics(b) ``` -------------------------------- ### Solve the Problem Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_01 Solve the DataDrivenProblem using the defined basis and the STLSQ solver. ```julia res = solve(problem, basis, STLSQ()) ``` -------------------------------- ### Pendulum System Simulation and Data Generation Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_02 Simulates a pendulum system using OrdinaryDiffEq and generates noisy data for system identification. Requires importing necessary libraries and defining the ODE problem. ```julia using DataDrivenDiffEq using LinearAlgebra using OrdinaryDiffEq using DataDrivenSparse using StableRNGs rng = StableRNG(1337) function pendulum(u, p, t) x = u[2] y = -9.81sin(u[1]) - 0.3u[2]^3 - 3.0 * cos(u[1]) - 10.0 * exp(-((t - 5.0) / 5.0)^2) return [x; y] end u0 = [0.99π; -1.0] tspan = (0.0, 15.0) prob = ODEProblem(pendulum, u0, tspan) sol = solve(prob, Tsit5(), saveat = 0.01); X = sol[:, :] + 0.2 .* randn(rng, size(sol)); ts = sol.t; ``` -------------------------------- ### Visualize Original and Inferred Systems Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_02 Plots the original noisy data and the solved system alongside each other for a visual comparison of the identification results. ```julia plot( plot(prob), plot(res), layout = (1,2) ) ``` -------------------------------- ### Simulate a Noisy Pendulum System Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_02 Defines a pendulum system and solves it using OrdinaryDiffEq. Noise is added to the solution to simulate real-world measurements. ```julia using DataDrivenDiffEq using LinearAlgebra using OrdinaryDiffEq using DataDrivenSparse using StableRNGs using Plots gr() rng = StableRNG(1337) function pendulum(u, p, t) x = u[2] y = -9.81sin(u[1]) - 0.3u[2]^3 - 3.0 * cos(u[1]) - 10.0 * exp(-((t - 5.0) / 5.0)^2) return [x; y] end u0 = [0.99π; -1.0] tspan = (0.0, 15.0) prob = ODEProblem(pendulum, u0, tspan) sol = solve(prob, Tsit5(), saveat = 0.01); ``` ```julia X = sol[:, :] + 0.2 .* randn(rng, size(sol)); ts = sol.t; plot(ts, X', color = :red) plot!(sol, color = :black) ``` -------------------------------- ### Create DataDrivenProblem Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_01 Create a DirectDataDrivenProblem instance using the generated data X and Y. ```julia problem = DirectDataDrivenProblem(X, Y, name = :Test) ``` -------------------------------- ### Define and Solve ODE Problem Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensr/examples/example_01 Sets up a linear time-continuous system and solves it using OrdinaryDiffEq.jl. This generates the data that will be used for symbolic regression. ```julia using DataDrivenDiffEq using LinearAlgebra using OrdinaryDiffEq using DataDrivenSR using Plots A = [-0.9 0.2; 0.0 -0.5] B = [0.0; 1.0] u0 = [10.0; -10.0] tspan = (0.0, 20.0) f(u, p, t) = A * u .+ B .* sin(0.5 * t) sys = ODEProblem(f, u0, tspan) sol = solve(sys, Tsit5(), saveat = 0.01); ``` -------------------------------- ### Check Convergence of Solution Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/solutions Asserts the convergence status of a DataDrivenSolution, returning true if successful and false otherwise. ```julia is_converged(r) ``` -------------------------------- ### Print Solution Summary Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensr/examples/example_01 Displays a summary of the symbolic regression result, including the return code, number of equations, and residual sum of squares. ```julia println(res) ``` -------------------------------- ### DMDPINV Algorithm Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivendmd/koopman Approximates the Koopman operator K using the formula K = Y / X. This method is suitable when a direct matrix inversion is feasible and computationally efficient. It returns an Eigen factorization of the operator. ```julia mutable struct DMDPINV <: DataDrivenDMD.AbstractKoopmanAlgorithm end ``` -------------------------------- ### Create DataDrivenDataset from Multiple Trajectories Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_03 Generates multiple trajectories for the ODE problem by varying the initial condition and collects them into a DataDrivenDataset. This dataset is used for training the sparse identification model. Plotting the dataset visualizes the generated trajectories. ```julia prob = DataDrivenDataset(map(1:2) do i solve(remake(ode_problem, u0 = i * u0), Tsit5(), saveat = 0.1, tspan = (0.0, 4.0)) end...) plot(prob) ``` -------------------------------- ### Initialize ClippedAbsoluteDeviation Proximal Operator Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/sparse_regression Instantiate the ClippedAbsoluteDeviation proximal operator with an optional upper threshold parameter. ```julia opt = ClippedAbsoluteDeviation() opt = ClippedAbsoluteDeviation(1e-1) ``` -------------------------------- ### ContinuousDataDrivenProblem constructor Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/problems A time continuous DataDrivenProblem constructor for problems of the form f(x,p,t,u) ↦ dx/dt. Automatically constructs derivatives via a collocation method. ```julia ContinuousDataDrivenProblem(X, DX; kwargs...) ``` -------------------------------- ### Copy-Pasteable Code for Nonlinear System Analysis Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivendmd/examples/example_04 A consolidated block of code for setting up and solving a nonlinear ODE system, creating a DataDrivenProblem, and applying Extended DMD. This is useful for quick reproduction and testing. ```julia using DataDrivenDiffEq using LinearAlgebra using OrdinaryDiffEq using DataDrivenDMD function slow_manifold(du, u, p, t) du[1] = p[1] * u[1] du[2] = p[2] * (u[2] - u[1]^2) end u0 = [3.0; -2.0] tspan = (0.0, 5.0) p = [-0.8; -0.7] problem = ODEProblem{true, SciMLBase.NoSpecialize}(slow_manifold, u0, tspan, p) solution = solve(problem, Tsit5(), saveat = 0.1); prob = DataDrivenProblem(solution) @parameters t @variables u(t)[1:2] Ψ = Basis([u; u[1]^2], u, independent_variable = t) res = solve(prob, Ψ, DMDPINV(), digits = 2) # This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl ``` -------------------------------- ### Define and Solve ODE with Controls Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivendmd/examples/example_03 Defines a linear time-continuous system with a sinusoidal control input and solves the ODE problem. Ensure OrdinaryDiffEq.jl and DataDrivenDiffEq.jl are imported. ```julia using DataDrivenDiffEq using LinearAlgebra using OrdinaryDiffEq using DataDrivenDMD using Plots A = [-0.9 0.2; 0.0 -0.2] B = [0.0; 1.0] u0 = [10.0; -10.0] tspan = (0.0, 10.0) f(u, p, t) = A * u .+ B .* sin(0.5 * t) sys = ODEProblem(f, u0, tspan) sol = solve(sys, Tsit5(), saveat = 0.05); ``` -------------------------------- ### Simulate Linear Time Continuous System Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivendmd/examples/example_02 Defines and solves an ODE system representing a linear time-continuous system. Requires OrdinaryDiffEq.jl. ```julia using DataDrivenDiffEq using LinearAlgebra using OrdinaryDiffEq using DataDrivenDMD using Plots A = [-0.9 0.2; 0.0 -0.2] u0 = [10.0; -10.0] tspan = (0.0, 10.0) f(u, p, t) = A * u sys = ODEProblem(f, u0, tspan) sol = solve(sys, Tsit5(), saveat = 0.05); ``` -------------------------------- ### Construct DiscreteDataset Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/problems Constructor for a time-discrete DataDrivenDataset, used for problems of the form f(x,p,t,u) ↦ x(t+1). ```julia DiscreteDataset(s; name, kwargs...) ``` -------------------------------- ### Extracting and Printing the Identified System Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_02 Retrieves the identified symbolic system and its parameter map from the sparse regression results and prints them. This provides the final discovered equations. ```julia system = get_basis(res) params = get_parameter_map(system) println(system) # hide println(params) # hide ``` -------------------------------- ### Define Cartpole System and Generate Data Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_05 Defines the Cartpole system's differential equations and solves them to generate training data. It then prepares the data for a ContinuousDataDrivenProblem, specifying the derivatives to be learned. ```julia using DataDrivenDiffEq using ModelingToolkit using OrdinaryDiffEq using LinearAlgebra using DataDrivenSparse using Plots gr() function cart_pole(u, p, t) du = similar(u) F = -0.2 + 0.5 * sin(6 * t) # the input du[1] = u[3] du[2] = u[4] du[3] = -(19.62 * sin(u[1]) + sin(u[1]) * cos(u[1]) * u[3]^2 + F * cos(u[1])) / (2 - cos(u[1])^2) du[4] = -(sin(u[1]) * u[3]^2 + 9.81 * sin(u[1]) * cos(u[1]) + F) / (2 - cos(u[1])^2) return du end u0 = [0.3; 0; 1.0; 0] tspan = (0.0, 5.0) dt = 0.05 cart_pole_prob = ODEProblem(cart_pole, u0, tspan) solution = solve(cart_pole_prob, Tsit5(), saveat = dt) X = solution[:, :] DX = similar(X) for (i, xi) in enumerate(eachcol(X)) DX[:, i] = cart_pole(xi, [], solution.t[i]) end t = solution.t ddprob = ContinuousDataDrivenProblem(X, t, DX = DX[3:4, :], U = (u, p, t) -> [-0.2 + 0.5 * sin(6 * t)]) plot(ddprob) ``` -------------------------------- ### Construct ContinuousDataset Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/problems Constructor for a time-continuous DataDrivenDataset, used for problems of the form f(x,p,t,u) ↦ dx/dt. Automatically constructs derivatives via a collocation method. ```julia ContinuousDataset(s; name, collocation, kwargs...) ``` -------------------------------- ### Solve for Sparse System using STLSQ Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_02 Infers the system structure using the STLSQ algorithm with specified lambda values and data processing options for minibatching and shuffling. ```julia sampler = DataProcessing(split = 0.8, shuffle = true, batchsize = 30, rng = rng) λs = exp10.(-10:0.1:0) opt = STLSQ(λs) res = solve(prob, basis, opt, options = DataDrivenCommonOptions(data_processing = sampler, digits = 1)) ``` -------------------------------- ### Define Basis and Solve with Extended DMD Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivendmd/examples/example_04 Defines a nonlinear basis for lifting the state space and solves the DataDrivenProblem using the DMDPINV algorithm. Ensure the basis includes all necessary terms for accurate system identification. ```julia @parameters t @variables u(t)[1:2] Ψ = Basis([u; u[1]^2], u, independent_variable = t) res = solve(prob, Ψ, DMDPINV(), digits = 2) ``` -------------------------------- ### DataProcessing Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/utils Defines a preprocessing pipeline for the data using MLUtils.jl, including options for train-test split, shuffling, batching, and random number generation. ```APIDOC ## Type: DataProcessing ### Description Defines a preprocessing pipeline for the data using `MLUtils.jl`. All of the fields can be set using keyword arguments. ### Fields * `split` : Train test split, indicates the (rough) percentage of training data Default: 1.0 * `shuffle`: Shuffle the training data Default: false * `batchsize`: Batch size to use, if zero no batching is performed Default: 0 * `partial`: Using partial batches Default: true * `rng`: Random seed Default: Random.default_rng() ### Note Currently, only `splitobs` for a train-test split and `DataLoader` is wrapped. Other algorithms may follow. ``` -------------------------------- ### Create Continuous DataDrivenProblem with Controls Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivendmd/examples/example_03 Creates a ContinuousDataDrivenProblem using the solved ODE data and a defined control function. The `U` keyword argument accepts a function that returns the control input at a given time. ```julia X = Array(sol) t = sol.t control(u, p, t) = [sin(0.5 * t)] prob = ContinuousDataDrivenProblem(X, t, U = control) ``` -------------------------------- ### DiscreteDataDrivenProblem constructor Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/problems A time discrete DataDrivenProblem constructor for problems of the form f(x[i],p,t,u) ↦ x[i+1]. ```julia DiscreteDataDrivenProblem(X; kwargs...) ``` -------------------------------- ### FBDMD Algorithm Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivendmd/koopman Approximates the Koopman operator K using the forward-backward DMD method, calculated as K = sqrt(K₁*inv(K₂)). It incorporates truncation similar to DMDSVD for rank reduction. This method can be beneficial for systems where forward and backward dynamics provide complementary information. ```julia mutable struct FBDMD{R} <: DataDrivenDMD.AbstractKoopmanAlgorithm alg end ``` -------------------------------- ### System Identification with Sparse Regression Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_02 Performs system identification using sparse regression (STLSQ) on the defined basis and data. Includes data processing options like splitting, shuffling, and batching. ```julia sampler = DataProcessing(split = 0.8, shuffle = true, batchsize = 30, rng = rng) λs = exp10.(-10:0.1:0) opt = STLSQ(λs) res = solve(prob, basis, opt, options = DataDrivenCommonOptions(data_processing = sampler, digits = 1)) ``` -------------------------------- ### Initialize SoftThreshold Proximal Operator Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/sparse_regression Instantiate the SoftThreshold proximal operator. This operator is used within the SR3 algorithm. ```julia struct SoftThreshold <: DataDrivenSparse.AbstractProximalOperator end ``` -------------------------------- ### Define Direct DataDrivenProblem Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/problems Construct a direct mapping problem. Defined by measurements X and observed output Y, with optional time, input, and parameter arguments. ```julia problem = DirectDataDrivenProblem(X, Y) problem = DirectDataDrivenProblem(X, t, Y) problem = DirectDataDrivenProblem(X, t, Y, U) problem = DirectDataDrivenProblem(X, t, Y, p = p) problem = DirectDataDrivenProblem(X, t, Y, (x, p, t) -> u(x, p, t), p = p) ``` -------------------------------- ### Display Inferred Equations of Motion Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_04 Prints the inferred equations of motion derived from the sparse regression, showing the functional form and parameters. ```julia Model ##Basis#371 with 2 equations States : (x(t))[1] (x(t))[2] Parameters : 10 Independent variable: t Equations Differential(t)((x(t))[1]) = (p₁ + p₂*(x(t))[1] + p₃*(x(t))[1]*(x(t))[2]) / (-p₄ - p₅*(x(t))[2]) Differential(t)((x(t))[2]) = (p₆ + p₇*(x(t))[2] + p₈*(x(t))[1]*(x(t))[2]) / (-p₉ - p₁₀*(x(t))[1]) ``` -------------------------------- ### Inspect Identified Basis and Parameters Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivendmd/examples/example_04 Retrieves the identified basis and parameter mapping from the DataDrivenSolution. This allows for examination of the learned equations and their coefficients. ```julia basis = get_basis(res) ``` ```julia get_parameter_map(basis) ``` -------------------------------- ### Define Continuous DataDrivenProblem Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/problems Construct a continuous time problem. Requires measurements and derivatives, or measurements, time, and a method to derive derivatives. Can include time points, control inputs, and parameters. ```julia prob = ContinuousDataDrivenProblem(X, DX) # Define a continuous time problem without explicit derivatives prob = ContinuousDataDrivenProblem(X, t) ``` ```julia # Using available data problem = ContinuousDataDrivenProblem(X, DX) problem = ContinuousDataDrivenProblem(X, t, DX) problem = ContinuousDataDrivenProblem(X, t, DX, U, p = p) problem = ContinuousDataDrivenProblem(X, t, DX, (x, p, t) -> u(x, p, t)) # Using collocation problem = ContinuousDataDrivenProblem(X, t, InterpolationMethod()) problem = ContinuousDataDrivenProblem(X, t, GaussianKernel()) problem = ContinuousDataDrivenProblem(X, t, U, InterpolationMethod()) problem = ContinuousDataDrivenProblem(X, t, U, GaussianKernel(), p = p) ``` -------------------------------- ### DirectDataDrivenProblem constructor Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/problems A direct DataDrivenProblem constructor for problems of the form f(x,p,t,u) ↦ y. ```julia DirectDataDrivenProblem(X, Y; kwargs...) ``` -------------------------------- ### Extract and Display Inferred System Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_02 Retrieves the inferred system basis and parameter map from the DataDrivenSolution object for analysis and visualization. ```julia system = get_basis(res) params = get_parameter_map(system) ``` -------------------------------- ### Define Pendulum System and Solve ODE Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensr/examples/example_02 Sets up and solves the ordinary differential equation for a pendulum system. This provides the data for subsequent symbolic regression. ```julia using DataDrivenDiffEq using LinearAlgebra using OrdinaryDiffEq using DataDrivenSR using Plots function pendulum!(du, u, p, t) du[1] = u[2] du[2] = -9.81 * sin(u[1]) end u0 = [0.1, π / 2] tspan = (0.0, 10.0) sys = ODEProblem{true, SciMLBase.NoSpecialize}(pendulum!, u0, tspan) sol = solve(sys, Tsit5()); ``` -------------------------------- ### Construct DataDrivenProblem from DESolution Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/problems Create a DataDrivenProblem directly from a DESolution object. Evaluates the function at specific time points using the original problem's parameters. ```julia problem = DataDrivenProblem(sol; kwargs...) ``` -------------------------------- ### Define and Solve Nonlinear ODE System Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivendmd/examples/example_04 Defines a nonlinear ODE system and solves it using OrdinaryDiffEq. This is a prerequisite for creating a DataDrivenProblem. ```julia using DataDrivenDiffEq using LinearAlgebra using OrdinaryDiffEq using DataDrivenDMD using Plots function slow_manifold(du, u, p, t) du[1] = p[1] * u[1] du[2] = p[2] * (u[2] - u[1]^2) end u0 = [3.0; -2.0] tspan = (0.0, 5.0) p = [-0.8; -0.7] problem = ODEProblem{true, SciMLBase.NoSpecialize}(slow_manifold, u0, tspan, p) solution = solve(problem, Tsit5(), saveat = 0.1); plot(solution) ``` -------------------------------- ### DMDSVD Algorithm with Truncation Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivendmd/koopman Approximates the Koopman operator K using Singular Value Decomposition (SVD). The truncation parameter allows for controlling the rank of the approximation, either by specifying an integer index or a real-valued tolerance. This is useful for reducing noise and computational cost by focusing on dominant singular values. ```julia mutable struct DMDSVD{T} <: DataDrivenDMD.AbstractKoopmanAlgorithm truncation end ``` -------------------------------- ### Evaluate Solution Metrics Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivendmd/examples/example_04 Calculates various statistical metrics for the DataDrivenSolution, such as AIC, AICC, BIC, log-likelihood, and degrees of freedom. These metrics help assess the quality and complexity of the identified model. ```julia aic(res) ``` ```julia aicc(res) ``` ```julia bic(res) ``` ```julia loglikelihood(res) ``` ```julia dof(res) ``` -------------------------------- ### Plot Solution and DataDrivenProblem Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivendmd/examples/example_01 Visualizes the simulated solution and the data points contained within the DataDrivenProblem. Useful for verifying the simulation and data representation. ```julia plot(sol, label = string.([:x₁ :x₂])) scatter!(prob) ``` -------------------------------- ### Solve for Implicit Dynamics with Data Processing Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_04 Performs sparse regression using ImplicitOptimizer with a specified sparsity penalty and data processing options including shuffling and batching. ```julia sampler = DataProcessing(split = 0.8, shuffle = true, batchsize = 30) res = solve(dd_prob, basis, ImplicitOptimizer(STLSQ(1e-2:1e-2:1.0)), options = DataDrivenCommonOptions(data_processing = sampler, digits = 2)) ``` -------------------------------- ### Create DataDrivenProblem from ODE Solution Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivendmd/examples/example_04 Creates a DataDrivenProblem object from an existing ODE solution. This object is used for further analysis with DataDrivenDiffEq. ```julia prob = DataDrivenProblem(solution) plot(prob) ``` -------------------------------- ### Define Basis and EQSearch Options Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensr/examples/example_02 Defines the basis functions for symbolic regression, including polynomial and sine terms, and configures the EQSearch algorithm with specific operators and loss function. The search space is lifted by including sin(u). ```julia @variables u[1:2] u = collect(u) basis = Basis([polynomial_basis(u, 2); sin.(u)], u) eqsearch_options = SymbolicRegression.Options(binary_operators = [+, *], loss = L1DistLoss(), verbosity = -1, progress = false, npop = 30, timeout_in_seconds = 60.0) alg = EQSearch(eq_options = eqsearch_options) ``` -------------------------------- ### Copy-Pasteable Code for Linear System with Controls Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivendmd/examples/example_03 A consolidated block of code for defining, solving, and analyzing a linear time-continuous system with control signals, suitable for direct copy-pasting. ```julia using DataDrivenDiffEq using LinearAlgebra using OrdinaryDiffEq using DataDrivenDMD A = [-0.9 0.2; 0.0 -0.2] B = [0.0; 1.0] u0 = [10.0; -10.0] tspan = (0.0, 10.0) f(u, p, t) = A * u .+ B .* sin(0.5 * t) sys = ODEProblem(f, u0, tspan) sol = solve(sys, Tsit5(), saveat = 0.05); X = Array(sol) t = sol.t control(u, p, t) = [sin(0.5 * t)] prob = ContinuousDataDrivenProblem(X, t, U = control) res = solve(prob, DMDSVD(), digits = 1) # This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl ``` -------------------------------- ### Symbolic Basis Definition Source: https://docs.sciml.ai/DataDrivenDiffEq/stable/libs/datadrivensparse/examples/example_02 Defines a symbolic basis for the system using DataDrivenDiffEq's symbolic variables and parameters. This includes trigonometric functions, polynomial terms, and control inputs. ```julia @variables u[1:2] c[1:1] @parameters w[1:2] u = collect(u) c = collect(c) w = collect(w) h = Num[sin.(w[1] .* u[1]); cos.(w[2] .* u[1]); polynomial_basis(u, 5); c] basis = Basis(h, u, parameters = w, controls = c); println(basis) # hide ```