diff --git a/docs/src/api.md b/docs/src/api.md index fc2b4e7..60f46bc 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -6,6 +6,8 @@ SymbolicNeuralNetwork @SymbolicNeuralNetwork multi_layer_feed_forward ModelingToolkitNeuralNets.isneuralnetwork +ModelingToolkitNeuralNets.hasneuralnetwork ModelingToolkitNeuralNets.isneuralnetworkps +ModelingToolkitNeuralNets.hasneuralnetworkps ModelingToolkitNeuralNets.get_nn_chain ``` diff --git a/src/nn_par_accessors.jl b/src/nn_par_accessors.jl index 9515bed..32d8080 100644 --- a/src/nn_par_accessors.jl +++ b/src/nn_par_accessors.jl @@ -24,6 +24,25 @@ function isneuralnetwork(p::Symbolics.SymbolicT) getmetadata(p, NeuralNetworkParameter, false) end +""" + ModelingToolkitNeuralNets.hasneuralnetwork(p) + +Returns `true` if the parameter has the `neuralnetwork` metadata set (whenever the value is `true` or `false`). This function is primarily intended for internal use within dependent packages. + +Example: +```julia +@parameters d +@SymbolicNeuralNetwork NN, θ = chain +ModelingToolkitNeuralNets.hasneuralnetwork(d) # false +ModelingToolkitNeuralNets.hasneuralnetwork(NN) # true +ModelingToolkitNeuralNets.hasneuralnetwork(θ) # false +```` +""" +hasneuralnetwork(p::Union{Symbolics.Num, Symbolics.Arr, Symbolics.CallAndWrap}) = hasneuralnetwork(Symbolics.unwrap(p)) +function hasneuralnetwork(p::Symbolics.SymbolicT) + hasmetadata(p, NeuralNetworkParameter) +end + """ ModelingToolkitNeuralNets.isneuralnetworkps(p) @@ -43,6 +62,25 @@ function isneuralnetworkps(p::Symbolics.SymbolicT) getmetadata(p, NeuralNetworkParametrisation, false) end +""" + ModelingToolkitNeuralNets.hasneuralnetworkps(p) + +Returns `true` if the parameter has the `neuralnetworkps` metadata set (whenever the value is `true` or `false`). This function is primarily intended for internal use within dependent packages. + +Example: +```julia +@parameters d +@SymbolicNeuralNetwork NN, θ = chain +ModelingToolkitNeuralNets.hasneuralnetworkps(d) # false +ModelingToolkitNeuralNets.hasneuralnetworkps(NN) # false +ModelingToolkitNeuralNets.hasneuralnetworkps(θ) # true +```` +""" +hasneuralnetworkps(p::Union{Symbolics.Num, Symbolics.Arr, Symbolics.CallAndWrap}) = hasneuralnetworkps(Symbolics.unwrap(p)) +function hasneuralnetworkps(p::Symbolics.SymbolicT) + hasmetadata(p, NeuralNetworkParametrisation) +end + ### Defines Other Accessors ### diff --git a/test/nn_ps_accessors.jl b/test/nn_ps_accessors.jl index 269feab..5e58f29 100644 --- a/test/nn_ps_accessors.jl +++ b/test/nn_ps_accessors.jl @@ -9,7 +9,9 @@ let @parameters p q[1:3] for s in [X, Y, Y[1], p, q, q[1]] @test !ModelingToolkitNeuralNets.isneuralnetwork(s) + @test !ModelingToolkitNeuralNets.hasneuralnetwork(s) @test !ModelingToolkitNeuralNets.isneuralnetworkps(s) + @test !ModelingToolkitNeuralNets.hasneuralnetworkps(s) end # Tests on MTKNeuralNets parameters @@ -23,9 +25,18 @@ let @test !ModelingToolkitNeuralNets.isneuralnetwork(θ) @test ModelingToolkitNeuralNets.isneuralnetwork(U) @test !ModelingToolkitNeuralNets.isneuralnetwork(p) + @test ModelingToolkitNeuralNets.hasneuralnetwork(NN) + @test !ModelingToolkitNeuralNets.hasneuralnetwork(θ) + @test ModelingToolkitNeuralNets.hasneuralnetwork(U) + @test !ModelingToolkitNeuralNets.hasneuralnetwork(p) @test !ModelingToolkitNeuralNets.isneuralnetworkps(NN) @test ModelingToolkitNeuralNets.isneuralnetworkps(θ) @test !ModelingToolkitNeuralNets.isneuralnetworkps(U) + @test ModelingToolkitNeuralNets.hasneuralnetworkps(p) + @test !ModelingToolkitNeuralNets.hasneuralnetworkps(NN) + @test ModelingToolkitNeuralNets.hasneuralnetworkps(θ) + @test !ModelingToolkitNeuralNets.hasneuralnetworkps(U) + @test ModelingToolkitNeuralNets.hasneuralnetworkps(p) end # Check that `isneuralnetwork` and `isneuralnetworkps` give correct input on parameters stored in a model created using symbolic approach. @@ -49,10 +60,18 @@ let @test !ModelingToolkitNeuralNets.isneuralnetwork(sys.d) @test ModelingToolkitNeuralNets.isneuralnetwork(sys.NN) @test !ModelingToolkitNeuralNets.isneuralnetwork(sys.θ) + @test !ModelingToolkitNeuralNets.hasneuralnetwork(sys.X) + @test !ModelingToolkitNeuralNets.hasneuralnetwork(sys.d) + @test ModelingToolkitNeuralNets.hasneuralnetwork(sys.NN) + @test !ModelingToolkitNeuralNets.hasneuralnetwork(sys.θ) @test !ModelingToolkitNeuralNets.isneuralnetworkps(sys.X) @test !ModelingToolkitNeuralNets.isneuralnetworkps(sys.d) @test !ModelingToolkitNeuralNets.isneuralnetworkps(sys.NN) @test ModelingToolkitNeuralNets.isneuralnetworkps(sys.θ) + @test !ModelingToolkitNeuralNets.hasneuralnetworkps(sys.X) + @test !ModelingToolkitNeuralNets.hasneuralnetworkps(sys.d) + @test !ModelingToolkitNeuralNets.hasneuralnetworkps(sys.NN) + @test ModelingToolkitNeuralNets.hasneuralnetworkps(sys.θ) end # Check that `isneuralnetwork` and `isneuralnetworkps` give correct input on parameters stored in a model created using NNBlock approach. @@ -83,6 +102,15 @@ let @test !ModelingToolkitNeuralNets.isneuralnetwork(sys_nnblock.x) @test !ModelingToolkitNeuralNets.isneuralnetwork(sys_nnblock.y) + @test ModelingToolkitNeuralNets.hasneuralnetwork(sys_nnblock.nn.lux_apply) + @test !ModelingToolkitNeuralNets.hasneuralnetwork(sys_nnblock.nn.lux_model) + @test !ModelingToolkitNeuralNets.hasneuralnetwork(sys_nnblock.nn.p) + @test !ModelingToolkitNeuralNets.hasneuralnetwork(sys_nnblock.nn.T) + @test !ModelingToolkitNeuralNets.hasneuralnetwork(sys_nnblock.α) + @test !ModelingToolkitNeuralNets.hasneuralnetwork(sys_nnblock.δ) + @test !ModelingToolkitNeuralNets.hasneuralnetwork(sys_nnblock.x) + @test !ModelingToolkitNeuralNets.hasneuralnetwork(sys_nnblock.y) + @test !ModelingToolkitNeuralNets.isneuralnetworkps(sys_nnblock.nn.lux_apply) @test !ModelingToolkitNeuralNets.isneuralnetworkps(sys_nnblock.nn.lux_model) @test ModelingToolkitNeuralNets.isneuralnetworkps(sys_nnblock.nn.p) @@ -91,6 +119,32 @@ let @test !ModelingToolkitNeuralNets.isneuralnetworkps(sys_nnblock.δ) @test !ModelingToolkitNeuralNets.isneuralnetworkps(sys_nnblock.x) @test !ModelingToolkitNeuralNets.isneuralnetworkps(sys_nnblock.y) + + @test !ModelingToolkitNeuralNets.hasneuralnetworkps(sys_nnblock.nn.lux_apply) + @test !ModelingToolkitNeuralNets.hasneuralnetworkps(sys_nnblock.nn.lux_model) + @test ModelingToolkitNeuralNets.hasneuralnetworkps(sys_nnblock.nn.p) + @test !ModelingToolkitNeuralNets.hasneuralnetworkps(sys_nnblock.nn.T) + @test !ModelingToolkitNeuralNets.hasneuralnetworkps(sys_nnblock.α) + @test !ModelingToolkitNeuralNets.hasneuralnetworkps(sys_nnblock.δ) + @test !ModelingToolkitNeuralNets.hasneuralnetworkps(sys_nnblock.x) + @test !ModelingToolkitNeuralNets.hasneuralnetworkps(sys_nnblock.y) +end + +# Specific `hasneuralnetwork` and `hasneuralnetworkps` tests. +let + @parameters p1 [neuralnetwork = true] p2 [neuralnetwork = false] p3 [neuralnetworkps = true] p4 [neuralnetworkps = false] p5 p6 + @test ModelingToolkitNeuralNets.hasneuralnetwork(p1) + @test ModelingToolkitNeuralNets.hasneuralnetwork(p2) + @test !ModelingToolkitNeuralNets.hasneuralnetwork(p3) + @test !ModelingToolkitNeuralNets.hasneuralnetwork(p4) + @test !ModelingToolkitNeuralNets.hasneuralnetwork(p5) + @test !ModelingToolkitNeuralNets.hasneuralnetwork(p6) + @test !ModelingToolkitNeuralNets.hasneuralnetworkps(p1) + @test !ModelingToolkitNeuralNets.hasneuralnetworkps(p2) + @test ModelingToolkitNeuralNets.hasneuralnetworkps(p3) + @test ModelingToolkitNeuralNets.hasneuralnetworkps(p4) + @test !ModelingToolkitNeuralNets.hasneuralnetworkps(p5) + @test !ModelingToolkitNeuralNets.hasneuralnetworkps(p6) end # Checks the `get_nn_chain` accessor function.