From bd482b12dc94463288f0cd7655cb9ce3e82c14e7 Mon Sep 17 00:00:00 2001 From: Harrison Grodin Date: Wed, 13 Feb 2019 21:13:06 -0500 Subject: [PATCH 1/5] Use `isequal` instead of `==` --- src/differentials.jl | 2 +- src/equations.jl | 4 +- src/function_registration.jl | 8 ++- src/operations.jl | 14 ++--- src/simplify.jl | 2 +- src/systems/diffeqs/diffeqsystem.jl | 4 +- src/systems/diffeqs/first_order_transform.jl | 2 +- src/utils.jl | 2 +- src/variables.jl | 16 +++--- test/derivatives.jl | 54 ++++++++++---------- test/simplify.jl | 8 +-- test/system_construction.jl | 20 ++++---- test/variable_parsing.jl | 12 +++-- 13 files changed, 78 insertions(+), 70 deletions(-) diff --git a/src/differentials.jl b/src/differentials.jl index 08bd80de3d..ed87dcdfde 100644 --- a/src/differentials.jl +++ b/src/differentials.jl @@ -12,7 +12,7 @@ function (D::Differential)(x::Variable) return Operation(D, Expression[x]) end (::Differential)(::Any) = Constant(0) -Base.:(==)(D1::Differential, D2::Differential) = D1.x == D2.x +Base.:(==)(D1::Differential, D2::Differential) = isequal(D1.x, D2.x) function expand_derivatives(O::Operation) @. O.args = expand_derivatives(O.args) diff --git a/src/equations.jl b/src/equations.jl index e721eb70f9..a914b81142 100644 --- a/src/equations.jl +++ b/src/equations.jl @@ -5,7 +5,7 @@ struct Equation lhs::Expression rhs::Expression end -Base.:(==)(a::Equation, b::Equation) = (a.lhs, a.rhs) == (b.lhs, b.rhs) +Base.:(==)(a::Equation, b::Equation) = isequal((a.lhs, a.rhs), (b.lhs, b.rhs)) Base.:~(lhs::Expression, rhs::Expression) = Equation(lhs, rhs) Base.:~(lhs::Expression, rhs::Number ) = Equation(lhs, rhs) @@ -13,7 +13,7 @@ Base.:~(lhs::Number , rhs::Expression) = Equation(lhs, rhs) _is_dependent(x::Variable) = !x.known && !isempty(x.dependents) -_is_parameter(iv) = x -> x.known && x ≠ iv +_is_parameter(iv) = x -> x.known && !isequal(x, iv) _is_known(x::Variable) = x.known _is_unknown(x::Variable) = !x.known diff --git a/src/function_registration.jl b/src/function_registration.jl index cc72ba685f..61a2e8a15a 100644 --- a/src/function_registration.jl +++ b/src/function_registration.jl @@ -32,7 +32,13 @@ for (M, f, arity) in DiffRules.diffrules() @eval @register $sig end -for fun = (:<, :>, :(==), :!, :&, :|, :div) +for fun ∈ [:!] + basefun = Expr(:., Base, QuoteNode(fun)) + sig = :($basefun(x)) + @eval @register $sig +end + +for fun ∈ [:<, :>, :(==), :&, :|, :div] basefun = Expr(:., Base, QuoteNode(fun)) sig = :($basefun(x,y)) @eval @register $sig diff --git a/src/operations.jl b/src/operations.jl index f024b848e3..03c794f16e 100644 --- a/src/operations.jl +++ b/src/operations.jl @@ -4,15 +4,15 @@ struct Operation <: Expression end # Recursive == -function Base.:(==)(x::Operation,y::Operation) +function Base.isequal(x::Operation,y::Operation) x.op == y.op && length(x.args) == length(y.args) && all(isequal.(x.args,y.args)) end -Base.:(==)(::Operation, ::Number ) = false -Base.:(==)(::Number , ::Operation) = false -Base.:(==)(::Operation, ::Variable ) = false -Base.:(==)(::Variable , ::Operation) = false -Base.:(==)(::Operation, ::Constant ) = false -Base.:(==)(::Constant , ::Operation) = false +Base.isequal(::Operation, ::Number ) = false +Base.isequal(::Number , ::Operation) = false +Base.isequal(::Operation, ::Variable ) = false +Base.isequal(::Variable , ::Operation) = false +Base.isequal(::Operation, ::Constant ) = false +Base.isequal(::Constant , ::Operation) = false Base.convert(::Type{Expr}, O::Operation) = build_expr(:call, Any[Symbol(O.op); convert.(Expr, O.args)]) diff --git a/src/simplify.jl b/src/simplify.jl index 0c897face3..d5a57529c4 100644 --- a/src/simplify.jl +++ b/src/simplify.jl @@ -4,7 +4,7 @@ function simplify_constants(O::Operation, shorten_tree) if is_operation(O′) O′ = Operation(O′.op, simplify_constants.(O′.args, shorten_tree)) end - O == O′ && return O + isequal(O, O′) && return O O = O′ end end diff --git a/src/systems/diffeqs/diffeqsystem.jl b/src/systems/diffeqs/diffeqsystem.jl index ad1e35393c..ad5ea1537b 100644 --- a/src/systems/diffeqs/diffeqsystem.jl +++ b/src/systems/diffeqs/diffeqsystem.jl @@ -10,7 +10,7 @@ function flatten_differential(O::Operation) @assert is_derivative(O) "invalid differential: $O" is_derivative(O.args[1]) || return (O.args[1], O.op.x, 1) (x, t, order) = flatten_differential(O.args[1]) - t == O.op.x || throw(ArgumentError("non-matching differentials on lhs: $t, $(O.op.x)")) + isequal(t, O.op.x) || throw(ArgumentError("non-matching differentials on lhs: $t, $(O.op.x)")) return (x, t, order + 1) end @@ -26,7 +26,7 @@ function Base.convert(::Type{DiffEq}, eq::Equation) (x, t, n) = flatten_differential(eq.lhs) return DiffEq(x, t, n, eq.rhs) end -Base.:(==)(a::DiffEq, b::DiffEq) = (a.x, a.t, a.n, a.rhs) == (b.x, b.t, b.n, b.rhs) +Base.:(==)(a::DiffEq, b::DiffEq) = isequal((a.x, a.t, a.n, a.rhs), (b.x, b.t, b.n, b.rhs)) get_args(eq::DiffEq) = Expression[eq.x, eq.t, eq.rhs] struct DiffEqSystem <: AbstractSystem diff --git a/src/systems/diffeqs/first_order_transform.jl b/src/systems/diffeqs/first_order_transform.jl index 706de49f9a..7fecf3c318 100644 --- a/src/systems/diffeqs/first_order_transform.jl +++ b/src/systems/diffeqs/first_order_transform.jl @@ -17,7 +17,7 @@ function ode_order_lowering(eqs, iv) var, maxorder = eq.x, eq.n if maxorder > get(var_order, var, 0) var_order[var] = maxorder - var ∈ vars || push!(vars, var) + any(isequal(var), vars) || push!(vars, var) end var′ = lower_varname(eq.x, eq.t, eq.n - 1) rhs′ = rename(eq.rhs) diff --git a/src/utils.jl b/src/utils.jl index f5e83aeae3..e8753f7500 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -65,4 +65,4 @@ is_derivative(::Any) = false has_dependent(t::Variable) = Base.Fix2(has_dependent, t) has_dependent(x::Variable, t::Variable) = - t ∈ x.dependents || any(has_dependent(t), x.dependents) + any(isequal(t), x.dependents) || any(has_dependent(t), x.dependents) diff --git a/src/variables.jl b/src/variables.jl index 32f4a9ff79..b5c5faf3a7 100644 --- a/src/variables.jl +++ b/src/variables.jl @@ -22,14 +22,14 @@ Base.isone(ex::Expression) = isa(ex, Constant) && isone(ex.value) # Variables use isequal for equality since == is an Operation -Base.:(==)(x::Variable, y::Variable) = (x.name, x.known) == (y.name, y.known) -Base.:(==)(::Variable, ::Number) = false -Base.:(==)(::Number, ::Variable) = false -Base.:(==)(::Variable, ::Constant) = false -Base.:(==)(::Constant, ::Variable) = false -Base.:(==)(c::Constant, n::Number) = c.value == n -Base.:(==)(n::Number, c::Constant) = c.value == n -Base.:(==)(a::Constant, b::Constant) = a.value == b.value +Base.isequal(x::Variable, y::Variable) = (x.name, x.known) == (y.name, y.known) +Base.isequal(::Variable, ::Number) = false +Base.isequal(::Number, ::Variable) = false +Base.isequal(::Variable, ::Constant) = false +Base.isequal(::Constant, ::Variable) = false +Base.isequal(c::Constant, n::Number) = c.value == n +Base.isequal(n::Number, c::Constant) = c.value == n +Base.isequal(a::Constant, b::Constant) = a.value == b.value function Base.convert(::Type{Expr}, x::Variable) x.known || return x.name diff --git a/test/derivatives.jl b/test/derivatives.jl index 768fd80b14..cee1fdc0aa 100644 --- a/test/derivatives.jl +++ b/test/derivatives.jl @@ -6,52 +6,52 @@ using Test @Unknown x(t) y(t) z(t) @Deriv D'~t D2''~t -@test expand_derivatives(D(t)) == 1 -@test expand_derivatives(D(D(t))) == 0 +@test isequal(expand_derivatives(D(t)), 1) +@test isequal(expand_derivatives(D(D(t))), 0) dsin = D(sin(t)) -@test expand_derivatives(dsin) == cos(t) +@test isequal(expand_derivatives(dsin), cos(t)) dcsch = D(csch(t)) -@test expand_derivatives(dcsch) == simplify_constants(coth(t) * csch(t) * -1) +@test isequal(expand_derivatives(dcsch), simplify_constants(coth(t) * csch(t) * -1)) -@test expand_derivatives(D(-7)) == 0 -@test expand_derivatives(D(sin(2t))) == simplify_constants(cos(2t) * 2) -@test expand_derivatives(D2(sin(t))) == simplify_constants(-sin(t)) -@test expand_derivatives(D2(sin(2t))) == simplify_constants(sin(2t) * -4) -@test expand_derivatives(D2(t)) == 0 -@test expand_derivatives(D2(5)) == 0 +@test isequal(expand_derivatives(D(-7)), 0) +@test isequal(expand_derivatives(D(sin(2t))), simplify_constants(cos(2t) * 2)) +@test isequal(expand_derivatives(D2(sin(t))), simplify_constants(-sin(t))) +@test isequal(expand_derivatives(D2(sin(2t))), simplify_constants(sin(2t) * -4)) +@test isequal(expand_derivatives(D2(t)), 0) +@test isequal(expand_derivatives(D2(5)), 0) # Chain rule dsinsin = D(sin(sin(t))) -@test expand_derivatives(dsinsin) == cos(sin(t))*cos(t) +@test isequal(expand_derivatives(dsinsin), cos(sin(t))*cos(t)) d1 = D(sin(t)*t) d2 = D(sin(t)*cos(t)) -@test expand_derivatives(d1) == t*cos(t)+sin(t) -@test expand_derivatives(d2) == simplify_constants(cos(t)*cos(t)+sin(t)*(-1*sin(t))) +@test isequal(expand_derivatives(d1), t*cos(t)+sin(t)) +@test isequal(expand_derivatives(d2), simplify_constants(cos(t)*cos(t)+sin(t)*(-1*sin(t)))) eqs = [0 ~ σ*(y-x), 0 ~ x*(ρ-z)-y, 0 ~ x*y - β*z] sys = NonlinearSystem(eqs,[x,y,z],[σ,ρ,β]) jac = calculate_jacobian(sys) -@test jac[1,1] == σ*-1 -@test jac[1,2] == σ -@test jac[1,3] == 0 -@test jac[2,1] == ρ-z -@test jac[2,2] == -1 -@test jac[2,3] == x*-1 -@test jac[3,1] == y -@test jac[3,2] == x -@test jac[3,3] == -1*β +@test isequal(jac[1,1], σ*-1) +@test isequal(jac[1,2], σ) +@test isequal(jac[1,3], 0) +@test isequal(jac[2,1], ρ-z) +@test isequal(jac[2,2], -1) +@test isequal(jac[2,3], x*-1) +@test isequal(jac[3,1], y) +@test isequal(jac[3,2], x) +@test isequal(jac[3,3], -1*β) # Variable dependence checking in differentiation @Unknown a(t) b(a) -@test D(b) ≠ 0 +@test !isequal(D(b), 0) -@test expand_derivatives(D(x * y)) == simplify_constants(y*D(x) + x*D(y)) -@test_broken expand_derivatives(D(x * y)) == simplify_constants(D(x)*y + x*D(y)) +@test isequal(expand_derivatives(D(x * y)), simplify_constants(y*D(x) + x*D(y))) +@test_broken isequal(expand_derivatives(D(x * y)), simplify_constants(D(x)*y + x*D(y))) -@test expand_derivatives(D(2t)) == 2 -@test expand_derivatives(D(2x)) == 2D(x) +@test isequal(expand_derivatives(D(2t)), 2) +@test isequal(expand_derivatives(D(2x)), 2D(x)) diff --git a/test/simplify.jl b/test/simplify.jl index 0e2f876bc5..7daae19fed 100644 --- a/test/simplify.jl +++ b/test/simplify.jl @@ -5,14 +5,14 @@ using Test @Unknown x(t) y(t) z(t) null_op = 0*t -@test simplify_constants(null_op) == 0 +@test isequal(simplify_constants(null_op), 0) one_op = 1*t -@test simplify_constants(one_op) == t +@test isequal(simplify_constants(one_op), t) identity_op = Operation(identity,[x]) -@test simplify_constants(identity_op) == x +@test isequal(simplify_constants(identity_op), x) minus_op = -x -@test simplify_constants(minus_op) == -1*x +@test isequal(simplify_constants(minus_op), -1*x) simplify_constants(minus_op) diff --git a/test/system_construction.jl b/test/system_construction.jl index 7fa89c2a08..7211164b6c 100644 --- a/test/system_construction.jl +++ b/test/system_construction.jl @@ -22,7 +22,7 @@ ModelingToolkit.generate_ode_iW(de) de2 = DiffEqSystem(eqs, t) function test_vars_extraction(de, de2) - @test de.iv == de2.iv + @test isequal(de.iv, de2.iv) for el in (:dvs, :ps) names2 = sort(collect(var.name for var in getfield(de2,el))) names = sort(collect(var.name for var in getfield(de,el))) @@ -110,15 +110,15 @@ eqs = [0 ~ σ*(y-x), ns = NonlinearSystem(eqs, [x,y,z], [σ,ρ,β]) jac = calculate_jacobian(ns) @testset "nlsys jacobian" begin - @test jac[1,1] == σ * -1 - @test jac[1,2] == σ - @test jac[1,3] == 0 - @test jac[2,1] == ρ - z - @test jac[2,2] == -1 - @test jac[2,3] == x * -1 - @test jac[3,1] == y - @test jac[3,2] == x - @test jac[3,3] == -1 * β + @test isequal(jac[1,1], σ * -1) + @test isequal(jac[1,2], σ) + @test isequal(jac[1,3], 0) + @test isequal(jac[2,1], ρ - z) + @test isequal(jac[2,2], -1) + @test isequal(jac[2,3], x * -1) + @test isequal(jac[3,1], y) + @test isequal(jac[3,2], x) + @test isequal(jac[3,3], -1 * β) end nlsys_func = generate_function(ns) jac_func = generate_jacobian(ns) diff --git a/test/variable_parsing.jl b/test/variable_parsing.jl index 96ba18aecd..df27994b7d 100644 --- a/test/variable_parsing.jl +++ b/test/variable_parsing.jl @@ -8,9 +8,9 @@ using Test x1 = Unknown(:x, [t]) y1 = Unknown(:y, [t]) z1 = Unknown(:z, [t]) -@test x1 == x -@test y1 == y -@test z1 == z +@test isequal(x1, x) +@test isequal(y1, y) +@test isequal(z1, z) @test convert(Expr, x) == :x @test convert(Expr, y) == :y @test convert(Expr, z) == :z @@ -21,8 +21,8 @@ z1 = Unknown(:z, [t]) end t1 = Parameter(:t) s1 = Parameter(:s) -@test t1 == t -@test s1 == s +@test isequal(t1, t) +@test isequal(s1, s) @test convert(Expr, t) == :t @test convert(Expr, s) == :s @test convert(Expr, cos(t + sin(s))) == :(cos(t + sin(s))) @@ -31,3 +31,5 @@ s1 = Parameter(:s) D1 = Differential(t) @test D1 == D @test convert(Expr, D) == D + +@test isequal(x ≤ y + 1, (x < y + 1) | (x == y + 1)) From e42a074bd32630e63f6983614195965b9f7a5d91 Mon Sep 17 00:00:00 2001 From: Harrison Grodin Date: Wed, 13 Feb 2019 21:51:42 -0500 Subject: [PATCH 2/5] Replace @Unknown with @Variable, remove Parameter --- README.md | 28 ++++++++++++++-------------- src/systems/diffeqs/diffeqsystem.jl | 2 +- src/variables.jl | 19 +++++++++---------- test/derivatives.jl | 4 ++-- test/simplify.jl | 2 +- test/system_construction.jl | 6 +++--- test/variable_parsing.jl | 16 ++++++++-------- 7 files changed, 38 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 2073663147..0b6cdc8c31 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ to manipulate. ### Example: ODE Let's build an ODE. First we define some variables. In a differential equation -system, we need to differentiate between our unknown (dependent) variables +system, we need to differentiate between our (dependent) variables and parameters. Therefore we label them as follows: ```julia @@ -29,7 +29,7 @@ using ModelingToolkit # Define some variables @Param t σ ρ β -@Unknown x(t) y(t) z(t) +@Variable x(t) y(t) z(t) @Deriv D'~t ``` @@ -78,10 +78,10 @@ f = ODEFunction(de) We can also build nonlinear systems. Let's say we wanted to solve for the steady state of the previous ODE. This is the nonlinear system defined by where the -derivatives are zero. We use unknown variables for our nonlinear system. +derivatives are zero. We use (unknown) variables for our nonlinear system. ```julia -@Unknown x y z +@Variable x y z @Param σ ρ β # Define a nonlinear system @@ -173,7 +173,7 @@ structure is as follows: the system of equations. - Name to subtype mappings: these describe how variable `subtype`s are mapped to the contexts of the system. For example, for a differential equation, - the unknown variable corresponds to given subtypes and then the `eqs` can + the variable corresponds to given subtypes and then the `eqs` can be analyzed knowing what the state variables are. - Variable names which do not fall into one of the system's core subtypes are treated as intermediates which can be used for holding subcalculations and @@ -244,21 +244,21 @@ syntactic sugar in some form. For example, the variable construction: ```julia @Param t σ ρ β -@Unknown x(t) y(t) z(t) +@Variable x(t) y(t) z(t) @Deriv D'~t ``` is syntactic sugar for: ```julia -t = Parameter(:t) -x = Unknown(:x, [t]) -y = Unknown(:y, [t]) -z = Unknown(:z, [t]) +t = Variable(:t; known = true) +x = Variable(:x, [t]) +y = Variable(:y, [t]) +z = Variable(:z, [t]) D = Differential(t) -σ = Parameter(:σ) -ρ = Parameter(:ρ) -β = Parameter(:β) +σ = Variable(:σ; known = true) +ρ = Variable(:ρ; known = true) +β = Variable(:β; known = true) ``` ### Intermediate Calculations @@ -266,7 +266,7 @@ D = Differential(t) The system building functions can handle intermediate calculations. For example, ```julia -@Unknown x y z +@Variable x y z @Param σ ρ β a = y - x eqs = [0 ~ σ*a, diff --git a/src/systems/diffeqs/diffeqsystem.jl b/src/systems/diffeqs/diffeqsystem.jl index ad5ea1537b..24204c4832 100644 --- a/src/systems/diffeqs/diffeqsystem.jl +++ b/src/systems/diffeqs/diffeqsystem.jl @@ -79,7 +79,7 @@ end function generate_ode_iW(sys::DiffEqSystem, simplify=true; version::FunctionVersion = ArrayFunction) jac = calculate_jacobian(sys) - gam = Parameter(:gam) + gam = Variable(:gam; known = true) W = LinearAlgebra.I - gam*jac W = SMatrix{size(W,1),size(W,2)}(W) diff --git a/src/variables.jl b/src/variables.jl index b5c5faf3a7..60cb708cd5 100644 --- a/src/variables.jl +++ b/src/variables.jl @@ -1,15 +1,14 @@ -export Variable, Unknown, Parameter, @Unknown, @Param +export Variable, @Variable, @Param struct Variable <: Expression name::Symbol - known::Bool dependents::Vector{Variable} + known::Bool + Variable(name, dependents = Variable[]; known = false) = + new(name, dependents, known) end -Parameter(name, dependents = Variable[]) = Variable(name, true, dependents) -Unknown(name, dependents = Variable[]) = Variable(name, false, dependents) - struct Constant <: Expression value::Number @@ -41,7 +40,7 @@ Base.convert(::Type{Expr}, c::Constant) = c.value Base.show(io::IO, x::Variable) = print(io, x.name) # Build variables more easily -function _parse_vars(macroname, fun, x) +function _parse_vars(macroname, known, x) ex = Expr(:block) var_names = Symbol[] # if parsing things in the form of @@ -65,15 +64,15 @@ function _parse_vars(macroname, fun, x) end push!(var_names, var_name) - expr = :($var_name = $fun($(Meta.quot(var_name)), $dependents)) + expr = :($var_name = $Variable($(Meta.quot(var_name)), $dependents; known = $known)) push!(ex.args, expr) end push!(ex.args, build_expr(:tuple, var_names)) return ex end -macro Unknown(xs...) - esc(_parse_vars(:Unknown, Unknown, xs)) +macro Variable(xs...) + esc(_parse_vars(:Variable, false, xs)) end macro Param(xs...) - esc(_parse_vars(:Param, Parameter, xs)) + esc(_parse_vars(:Param, true, xs)) end diff --git a/test/derivatives.jl b/test/derivatives.jl index cee1fdc0aa..8337efaa53 100644 --- a/test/derivatives.jl +++ b/test/derivatives.jl @@ -3,7 +3,7 @@ using Test # Derivatives @Param t σ ρ β -@Unknown x(t) y(t) z(t) +@Variable x(t) y(t) z(t) @Deriv D'~t D2''~t @test isequal(expand_derivatives(D(t)), 1) @@ -47,7 +47,7 @@ jac = calculate_jacobian(sys) @test isequal(jac[3,3], -1*β) # Variable dependence checking in differentiation -@Unknown a(t) b(a) +@Variable a(t) b(a) @test !isequal(D(b), 0) @test isequal(expand_derivatives(D(x * y)), simplify_constants(y*D(x) + x*D(y))) diff --git a/test/simplify.jl b/test/simplify.jl index 7daae19fed..6bd97ea1b0 100644 --- a/test/simplify.jl +++ b/test/simplify.jl @@ -2,7 +2,7 @@ using ModelingToolkit using Test @Param t -@Unknown x(t) y(t) z(t) +@Variable x(t) y(t) z(t) null_op = 0*t @test isequal(simplify_constants(null_op), 0) diff --git a/test/system_construction.jl b/test/system_construction.jl index 7211164b6c..19e13a73c0 100644 --- a/test/system_construction.jl +++ b/test/system_construction.jl @@ -3,7 +3,7 @@ using Test # Define some variables @Param t σ ρ β -@Unknown x(t) y(t) z(t) +@Variable x(t) y(t) z(t) @Deriv D'~t # Define a differential equation @@ -48,7 +48,7 @@ end # Conversion to first-order ODEs #17 @Deriv D3'''~t @Deriv D2''~t -@Unknown u(t) u_tt(t) u_t(t) x_t(t) +@Variable u(t) u_tt(t) u_t(t) x_t(t) eqs = [D3(u) ~ 2(D2(u)) + D(u) + D(x) + 1 D2(x) ~ D(x) + 2] de = DiffEqSystem(eqs, t) @@ -100,7 +100,7 @@ test_vars_extraction(de, DiffEqSystem(eqs)) end # Now nonlinear system with only variables -@Unknown x y z +@Variable x y z @Param σ ρ β # Define a nonlinear system diff --git a/test/variable_parsing.jl b/test/variable_parsing.jl index df27994b7d..a5c4488cb5 100644 --- a/test/variable_parsing.jl +++ b/test/variable_parsing.jl @@ -2,12 +2,12 @@ using ModelingToolkit using Test @Param t -@Unknown x(t) -@Unknown y(t) -@Unknown z(t) -x1 = Unknown(:x, [t]) -y1 = Unknown(:y, [t]) -z1 = Unknown(:z, [t]) +@Variable x(t) +@Variable y(t) +@Variable z(t) +x1 = Variable(:x, [t]) +y1 = Variable(:y, [t]) +z1 = Variable(:z, [t]) @test isequal(x1, x) @test isequal(y1, y) @test isequal(z1, z) @@ -19,8 +19,8 @@ z1 = Unknown(:z, [t]) t s end -t1 = Parameter(:t) -s1 = Parameter(:s) +t1 = Variable(:t; known = true) +s1 = Variable(:s; known = true) @test isequal(t1, t) @test isequal(s1, s) @test convert(Expr, t) == :t From 1d92c523dc2267c8c45b80724f6a105f613ea06b Mon Sep 17 00:00:00 2001 From: Harrison Grodin Date: Wed, 13 Feb 2019 21:59:49 -0500 Subject: [PATCH 3/5] Remove unnecessary capitalization Fixes #100. --- README.md | 24 ++++++++++---------- src/differentials.jl | 12 +++++----- src/systems/diffeqs/first_order_transform.jl | 2 +- src/variables.jl | 6 ++--- test/derivatives.jl | 8 +++---- test/simplify.jl | 4 ++-- test/system_construction.jl | 22 +++++++++--------- test/variable_parsing.jl | 12 +++++----- 8 files changed, 45 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 0b6cdc8c31..ba50af4f20 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,9 @@ and parameters. Therefore we label them as follows: using ModelingToolkit # Define some variables -@Param t σ ρ β -@Variable x(t) y(t) z(t) -@Deriv D'~t +@param t σ ρ β +@variable x(t) y(t) z(t) +@deriv D'~t ``` Then we build the system: @@ -81,8 +81,8 @@ state of the previous ODE. This is the nonlinear system defined by where the derivatives are zero. We use (unknown) variables for our nonlinear system. ```julia -@Variable x y z -@Param σ ρ β +@variable x y z +@param σ ρ β # Define a nonlinear system eqs = [0 ~ σ*(y-x), @@ -223,7 +223,7 @@ function via the dispatch: ```julia # `N` arguments are accepted by the relevant method of `my_function` -ModelingToolkit.Derivative(::typeof(my_function), args::NTuple{N,Any}, ::Val{i}) +ModelingToolkit.derivative(::typeof(my_function), args::NTuple{N,Any}, ::Val{i}) ``` where `i` means that it's the derivative of the `i`th argument. `args` is the @@ -233,7 +233,7 @@ You should return an `Operation` for the derivative of your function. For example, `sin(t)`'s derivative (by `t`) is given by the following: ```julia -ModelingToolkit.Derivative(::typeof(sin), args::NTuple{1,Any}, ::Val{1}) = cos(args[1]) +ModelingToolkit.derivative(::typeof(sin), args::NTuple{1,Any}, ::Val{1}) = cos(args[1]) ``` ### Macro-free Usage @@ -243,9 +243,9 @@ is accessible via a function-based interface. This means that all macros are syntactic sugar in some form. For example, the variable construction: ```julia -@Param t σ ρ β -@Variable x(t) y(t) z(t) -@Deriv D'~t +@param t σ ρ β +@variable x(t) y(t) z(t) +@deriv D'~t ``` is syntactic sugar for: @@ -266,8 +266,8 @@ D = Differential(t) The system building functions can handle intermediate calculations. For example, ```julia -@Variable x y z -@Param σ ρ β +@variable x y z +@param σ ρ β a = y - x eqs = [0 ~ σ*a, 0 ~ x*(ρ-z)-y, diff --git a/src/differentials.jl b/src/differentials.jl index ed87dcdfde..2466ff8891 100644 --- a/src/differentials.jl +++ b/src/differentials.jl @@ -21,7 +21,7 @@ function expand_derivatives(O::Operation) D = O.op o = O.args[1] isa(o, Operation) || return O - return simplify_constants(sum(i->Derivative(o,i)*expand_derivatives(D(o.args[i])),1:length(o.args))) + return simplify_constants(sum(i->derivative(o,i)*expand_derivatives(D(o.args[i])),1:length(o.args))) end return O @@ -29,13 +29,13 @@ end expand_derivatives(x) = x # Don't specialize on the function here -Derivative(O::Operation, idx) = Derivative(O.op, (O.args...,), Val(idx)) +derivative(O::Operation, idx) = derivative(O.op, (O.args...,), Val(idx)) # Pre-defined derivatives import DiffRules, SpecialFunctions, NaNMath for (modu, fun, arity) ∈ DiffRules.diffrules() for i ∈ 1:arity - @eval function Derivative(::typeof($modu.$fun), args::NTuple{$arity,Any}, ::Val{$i}) + @eval function derivative(::typeof($modu.$fun), args::NTuple{$arity,Any}, ::Val{$i}) M, f = $(modu, fun) partials = DiffRules.diffrule(M, f, args...) dx = @static $arity == 1 ? partials : partials[$i] @@ -60,7 +60,7 @@ function _differential_macro(x) lhss = Symbol[] x = flatten_expr!(x) for di in x - @assert di isa Expr && di.args[1] == :~ "@Deriv expects a form that looks like `@Deriv D''~t E'~t`" + @assert di isa Expr && di.args[1] == :~ "@deriv expects a form that looks like `@deriv D''~t E'~t`" lhs = di.args[2] rhs = di.args[3] order, lhs = count_order(lhs) @@ -72,7 +72,7 @@ function _differential_macro(x) ex end -macro Deriv(x...) +macro deriv(x...) esc(_differential_macro(x)) end @@ -80,4 +80,4 @@ function calculate_jacobian(eqs,vars) Expression[Differential(vars[j])(eqs[i]) for i in 1:length(eqs), j in 1:length(vars)] end -export Differential, expand_derivatives, @Deriv, calculate_jacobian +export Differential, expand_derivatives, @deriv, calculate_jacobian diff --git a/src/systems/diffeqs/first_order_transform.jl b/src/systems/diffeqs/first_order_transform.jl index 7fecf3c318..40dbda0f7d 100644 --- a/src/systems/diffeqs/first_order_transform.jl +++ b/src/systems/diffeqs/first_order_transform.jl @@ -1,7 +1,7 @@ function lower_varname(var::Variable, idv, order) order == 0 && return var name = Symbol(var.name, :_, string(idv.name)^order) - return Variable(name, var.known, var.dependents) + return Variable(name, var.dependents; known = var.known) end function ode_order_lowering(sys::DiffEqSystem) diff --git a/src/variables.jl b/src/variables.jl index 60cb708cd5..88a3fb22ca 100644 --- a/src/variables.jl +++ b/src/variables.jl @@ -1,4 +1,4 @@ -export Variable, @Variable, @Param +export Variable, @variable, @param struct Variable <: Expression @@ -70,9 +70,9 @@ function _parse_vars(macroname, known, x) push!(ex.args, build_expr(:tuple, var_names)) return ex end -macro Variable(xs...) +macro variable(xs...) esc(_parse_vars(:Variable, false, xs)) end -macro Param(xs...) +macro param(xs...) esc(_parse_vars(:Param, true, xs)) end diff --git a/test/derivatives.jl b/test/derivatives.jl index 8337efaa53..e6bf9e0065 100644 --- a/test/derivatives.jl +++ b/test/derivatives.jl @@ -2,9 +2,9 @@ using ModelingToolkit using Test # Derivatives -@Param t σ ρ β -@Variable x(t) y(t) z(t) -@Deriv D'~t D2''~t +@param t σ ρ β +@variable x(t) y(t) z(t) +@deriv D'~t D2''~t @test isequal(expand_derivatives(D(t)), 1) @test isequal(expand_derivatives(D(D(t))), 0) @@ -47,7 +47,7 @@ jac = calculate_jacobian(sys) @test isequal(jac[3,3], -1*β) # Variable dependence checking in differentiation -@Variable a(t) b(a) +@variable a(t) b(a) @test !isequal(D(b), 0) @test isequal(expand_derivatives(D(x * y)), simplify_constants(y*D(x) + x*D(y))) diff --git a/test/simplify.jl b/test/simplify.jl index 6bd97ea1b0..6853ec6e8e 100644 --- a/test/simplify.jl +++ b/test/simplify.jl @@ -1,8 +1,8 @@ using ModelingToolkit using Test -@Param t -@Variable x(t) y(t) z(t) +@param t +@variable x(t) y(t) z(t) null_op = 0*t @test isequal(simplify_constants(null_op), 0) diff --git a/test/system_construction.jl b/test/system_construction.jl index 19e13a73c0..876b265ffc 100644 --- a/test/system_construction.jl +++ b/test/system_construction.jl @@ -2,9 +2,9 @@ using ModelingToolkit using Test # Define some variables -@Param t σ ρ β -@Variable x(t) y(t) z(t) -@Deriv D'~t +@param t σ ρ β +@variable x(t) y(t) z(t) +@deriv D'~t # Define a differential equation eqs = [D(x) ~ σ*(y-x), @@ -32,7 +32,7 @@ end test_vars_extraction(de, de2) @testset "time-varying parameters" begin - @Param σ′(t) + @param σ′(t) eqs = [D(x) ~ σ′*(y-x), D(y) ~ x*(ρ-z)-y, D(z) ~ x*y - β*z] @@ -46,9 +46,9 @@ test_vars_extraction(de, de2) end # Conversion to first-order ODEs #17 -@Deriv D3'''~t -@Deriv D2''~t -@Variable u(t) u_tt(t) u_t(t) x_t(t) +@deriv D3'''~t +@deriv D2''~t +@variable u(t) u_tt(t) u_t(t) x_t(t) eqs = [D3(u) ~ 2(D2(u)) + D(u) + D(x) + 1 D2(x) ~ D(x) + 2] de = DiffEqSystem(eqs, t) @@ -84,8 +84,8 @@ end generate_function(ns) -@Deriv D'~t -@Param A B C +@deriv D'~t +@param A B C _x = y / C eqs = [D(x) ~ -A*x, D(y) ~ A*x - B*_x] @@ -100,8 +100,8 @@ test_vars_extraction(de, DiffEqSystem(eqs)) end # Now nonlinear system with only variables -@Variable x y z -@Param σ ρ β +@variable x y z +@param σ ρ β # Define a nonlinear system eqs = [0 ~ σ*(y-x), diff --git a/test/variable_parsing.jl b/test/variable_parsing.jl index a5c4488cb5..9a97f4da19 100644 --- a/test/variable_parsing.jl +++ b/test/variable_parsing.jl @@ -1,10 +1,10 @@ using ModelingToolkit using Test -@Param t -@Variable x(t) -@Variable y(t) -@Variable z(t) +@param t +@variable x(t) +@variable y(t) +@variable z(t) x1 = Variable(:x, [t]) y1 = Variable(:y, [t]) z1 = Variable(:z, [t]) @@ -15,7 +15,7 @@ z1 = Variable(:z, [t]) @test convert(Expr, y) == :y @test convert(Expr, z) == :z -@Param begin +@param begin t s end @@ -27,7 +27,7 @@ s1 = Variable(:s; known = true) @test convert(Expr, s) == :s @test convert(Expr, cos(t + sin(s))) == :(cos(t + sin(s))) -@Deriv D'~t +@deriv D'~t D1 = Differential(t) @test D1 == D @test convert(Expr, D) == D From 47b5b00b6b9e6836c6815f259686118ccda39222 Mon Sep 17 00:00:00 2001 From: Harrison Grodin Date: Wed, 13 Feb 2019 22:21:46 -0500 Subject: [PATCH 4/5] Clean up exports --- src/ModelingToolkit.jl | 10 +++++----- src/differentials.jl | 5 +++-- src/simplify.jl | 5 +++-- src/systems/diffeqs/first_order_transform.jl | 5 +++-- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/ModelingToolkit.jl b/src/ModelingToolkit.jl index 56693a3441..5ad35ad2ce 100644 --- a/src/ModelingToolkit.jl +++ b/src/ModelingToolkit.jl @@ -1,5 +1,10 @@ module ModelingToolkit +export Operation, Expression +export calculate_jacobian, generate_jacobian, generate_function +export @register + + using DiffEqBase using StaticArrays, LinearAlgebra @@ -30,9 +35,4 @@ include("function_registration.jl") include("simplify.jl") include("utils.jl") -export Operation, Expression, AbstractComponent -export calculate_jacobian, generate_jacobian, generate_function -export ArrayFunction, SArrayFunction -export @register - end # module diff --git a/src/differentials.jl b/src/differentials.jl index 2466ff8891..ae5c6b75d2 100644 --- a/src/differentials.jl +++ b/src/differentials.jl @@ -1,3 +1,6 @@ +export Differential, expand_derivatives, @deriv + + struct Differential <: Function x::Expression end @@ -79,5 +82,3 @@ end function calculate_jacobian(eqs,vars) Expression[Differential(vars[j])(eqs[i]) for i in 1:length(eqs), j in 1:length(vars)] end - -export Differential, expand_derivatives, @deriv, calculate_jacobian diff --git a/src/simplify.jl b/src/simplify.jl index d5a57529c4..53206f0688 100644 --- a/src/simplify.jl +++ b/src/simplify.jl @@ -1,3 +1,6 @@ +export simplify_constants + + function simplify_constants(O::Operation, shorten_tree) while true O′ = _simplify_constants(O, shorten_tree) @@ -72,5 +75,3 @@ function _simplify_constants(O::Operation, shorten_tree) end _simplify_constants(x, shorten_tree) = x _simplify_constants(x) = _simplify_constants(x, true) - -export simplify_constants diff --git a/src/systems/diffeqs/first_order_transform.jl b/src/systems/diffeqs/first_order_transform.jl index 40dbda0f7d..c0db1574cf 100644 --- a/src/systems/diffeqs/first_order_transform.jl +++ b/src/systems/diffeqs/first_order_transform.jl @@ -1,3 +1,6 @@ +export ode_order_lowering + + function lower_varname(var::Variable, idv, order) order == 0 && return var name = Symbol(var.name, :_, string(idv.name)^order) @@ -45,5 +48,3 @@ function rename(O::Expression) end return Operation(O.op, rename.(O.args)) end - -export ode_order_lowering From 63794852be7ab9dd7ca5398b399c22a42f7311e7 Mon Sep 17 00:00:00 2001 From: Harrison Grodin Date: Thu, 7 Mar 2019 17:35:52 -0500 Subject: [PATCH 5/5] Make macro naming consistent --- README.md | 20 ++++++++++---------- src/differentials.jl | 6 +++--- src/variables.jl | 6 +++--- test/derivatives.jl | 8 ++++---- test/simplify.jl | 4 ++-- test/system_construction.jl | 22 +++++++++++----------- test/variable_parsing.jl | 12 ++++++------ 7 files changed, 39 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index ba50af4f20..0fcd128f7a 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,9 @@ and parameters. Therefore we label them as follows: using ModelingToolkit # Define some variables -@param t σ ρ β -@variable x(t) y(t) z(t) -@deriv D'~t +@parameters t σ ρ β +@variables x(t) y(t) z(t) +@derivatives D'~t ``` Then we build the system: @@ -81,8 +81,8 @@ state of the previous ODE. This is the nonlinear system defined by where the derivatives are zero. We use (unknown) variables for our nonlinear system. ```julia -@variable x y z -@param σ ρ β +@variables x y z +@parameters σ ρ β # Define a nonlinear system eqs = [0 ~ σ*(y-x), @@ -243,9 +243,9 @@ is accessible via a function-based interface. This means that all macros are syntactic sugar in some form. For example, the variable construction: ```julia -@param t σ ρ β -@variable x(t) y(t) z(t) -@deriv D'~t +@parameters t σ ρ β +@variables x(t) y(t) z(t) +@derivatives D'~t ``` is syntactic sugar for: @@ -266,8 +266,8 @@ D = Differential(t) The system building functions can handle intermediate calculations. For example, ```julia -@variable x y z -@param σ ρ β +@variables x y z +@parameters σ ρ β a = y - x eqs = [0 ~ σ*a, 0 ~ x*(ρ-z)-y, diff --git a/src/differentials.jl b/src/differentials.jl index ae5c6b75d2..25a0498e76 100644 --- a/src/differentials.jl +++ b/src/differentials.jl @@ -1,4 +1,4 @@ -export Differential, expand_derivatives, @deriv +export Differential, expand_derivatives, @derivatives struct Differential <: Function @@ -63,7 +63,7 @@ function _differential_macro(x) lhss = Symbol[] x = flatten_expr!(x) for di in x - @assert di isa Expr && di.args[1] == :~ "@deriv expects a form that looks like `@deriv D''~t E'~t`" + @assert di isa Expr && di.args[1] == :~ "@derivatives expects a form that looks like `@derivatives D''~t E'~t`" lhs = di.args[2] rhs = di.args[3] order, lhs = count_order(lhs) @@ -75,7 +75,7 @@ function _differential_macro(x) ex end -macro deriv(x...) +macro derivatives(x...) esc(_differential_macro(x)) end diff --git a/src/variables.jl b/src/variables.jl index 88a3fb22ca..4777eed673 100644 --- a/src/variables.jl +++ b/src/variables.jl @@ -1,4 +1,4 @@ -export Variable, @variable, @param +export Variable, @variables, @parameters struct Variable <: Expression @@ -70,9 +70,9 @@ function _parse_vars(macroname, known, x) push!(ex.args, build_expr(:tuple, var_names)) return ex end -macro variable(xs...) +macro variables(xs...) esc(_parse_vars(:Variable, false, xs)) end -macro param(xs...) +macro parameters(xs...) esc(_parse_vars(:Param, true, xs)) end diff --git a/test/derivatives.jl b/test/derivatives.jl index e6bf9e0065..999cad9a70 100644 --- a/test/derivatives.jl +++ b/test/derivatives.jl @@ -2,9 +2,9 @@ using ModelingToolkit using Test # Derivatives -@param t σ ρ β -@variable x(t) y(t) z(t) -@deriv D'~t D2''~t +@parameters t σ ρ β +@variables x(t) y(t) z(t) +@derivatives D'~t D2''~t @test isequal(expand_derivatives(D(t)), 1) @test isequal(expand_derivatives(D(D(t))), 0) @@ -47,7 +47,7 @@ jac = calculate_jacobian(sys) @test isequal(jac[3,3], -1*β) # Variable dependence checking in differentiation -@variable a(t) b(a) +@variables a(t) b(a) @test !isequal(D(b), 0) @test isequal(expand_derivatives(D(x * y)), simplify_constants(y*D(x) + x*D(y))) diff --git a/test/simplify.jl b/test/simplify.jl index 6853ec6e8e..be6c1554df 100644 --- a/test/simplify.jl +++ b/test/simplify.jl @@ -1,8 +1,8 @@ using ModelingToolkit using Test -@param t -@variable x(t) y(t) z(t) +@parameters t +@variables x(t) y(t) z(t) null_op = 0*t @test isequal(simplify_constants(null_op), 0) diff --git a/test/system_construction.jl b/test/system_construction.jl index 876b265ffc..120607e6b6 100644 --- a/test/system_construction.jl +++ b/test/system_construction.jl @@ -2,9 +2,9 @@ using ModelingToolkit using Test # Define some variables -@param t σ ρ β -@variable x(t) y(t) z(t) -@deriv D'~t +@parameters t σ ρ β +@variables x(t) y(t) z(t) +@derivatives D'~t # Define a differential equation eqs = [D(x) ~ σ*(y-x), @@ -32,7 +32,7 @@ end test_vars_extraction(de, de2) @testset "time-varying parameters" begin - @param σ′(t) + @parameters σ′(t) eqs = [D(x) ~ σ′*(y-x), D(y) ~ x*(ρ-z)-y, D(z) ~ x*y - β*z] @@ -46,9 +46,9 @@ test_vars_extraction(de, de2) end # Conversion to first-order ODEs #17 -@deriv D3'''~t -@deriv D2''~t -@variable u(t) u_tt(t) u_t(t) x_t(t) +@derivatives D3'''~t +@derivatives D2''~t +@variables u(t) u_tt(t) u_t(t) x_t(t) eqs = [D3(u) ~ 2(D2(u)) + D(u) + D(x) + 1 D2(x) ~ D(x) + 2] de = DiffEqSystem(eqs, t) @@ -84,8 +84,8 @@ end generate_function(ns) -@deriv D'~t -@param A B C +@derivatives D'~t +@parameters A B C _x = y / C eqs = [D(x) ~ -A*x, D(y) ~ A*x - B*_x] @@ -100,8 +100,8 @@ test_vars_extraction(de, DiffEqSystem(eqs)) end # Now nonlinear system with only variables -@variable x y z -@param σ ρ β +@variables x y z +@parameters σ ρ β # Define a nonlinear system eqs = [0 ~ σ*(y-x), diff --git a/test/variable_parsing.jl b/test/variable_parsing.jl index 9a97f4da19..759652f110 100644 --- a/test/variable_parsing.jl +++ b/test/variable_parsing.jl @@ -1,10 +1,10 @@ using ModelingToolkit using Test -@param t -@variable x(t) -@variable y(t) -@variable z(t) +@parameters t +@variables x(t) +@variables y(t) +@variables z(t) x1 = Variable(:x, [t]) y1 = Variable(:y, [t]) z1 = Variable(:z, [t]) @@ -15,7 +15,7 @@ z1 = Variable(:z, [t]) @test convert(Expr, y) == :y @test convert(Expr, z) == :z -@param begin +@parameters begin t s end @@ -27,7 +27,7 @@ s1 = Variable(:s; known = true) @test convert(Expr, s) == :s @test convert(Expr, cos(t + sin(s))) == :(cos(t + sin(s))) -@deriv D'~t +@derivatives D'~t D1 = Differential(t) @test D1 == D @test convert(Expr, D) == D