diff --git a/src/ModelingToolkit.jl b/src/ModelingToolkit.jl index 5ad35ad2ce..cc4f3e8d4a 100644 --- a/src/ModelingToolkit.jl +++ b/src/ModelingToolkit.jl @@ -30,6 +30,7 @@ include("differentials.jl") include("equations.jl") include("systems/diffeqs/diffeqsystem.jl") include("systems/diffeqs/first_order_transform.jl") +include("systems/diffeqs/pantelides.jl") include("systems/nonlinear/nonlinear_system.jl") include("function_registration.jl") include("simplify.jl") diff --git a/src/systems/diffeqs/pantelides.jl b/src/systems/diffeqs/pantelides.jl new file mode 100644 index 0000000000..49a0561c86 --- /dev/null +++ b/src/systems/diffeqs/pantelides.jl @@ -0,0 +1,76 @@ +struct BiGraph{TA,TB,TC} + eqs::TA + vars::TB + edges::TC +end + +function init_assign(G) + assign = Dict{eltype(G.vars), Union{Nothing, eltype(G.eqs)}}() + # second function + for j in G.vars + assign[j] = nothing + end + return assign +end + +function augmentpath!(i, pathfound, color, assign, vars, edges) + union!(color, i) + idx = -1 + for j in vars + assign[j] === nothing || continue + (i => j) in edges && (idx = j; break) + end + if idx != -1 + pathfound[] = true + assign[idx] = i + return nothing + end + for j in vars + !((i => j) in edges && !(j in color)) && continue + union!(color, j) + k = assign[j] + augmentpath!(k, pathfound, color, assign, vars, edges) + pathfound[] && (assign[j] = i; return nothing) + end + return nothing +end + +function construct_augmentpath!(G, assign, pathfound) + #main operation in function + color = Set(similar(G.eqs, 0)) + for i in G.eqs + empty!(color) + pathfound[] = false + while !pathfound[] + pathfound[] = false + augmentpath!(i, pathfound, color, assign, G.vars, G.edges) + pathfound[] || break + end + end + return nothing +end + +#function pantelides(m,n,G,diff) +# assign = Dict() +# b = Dict() +# for j=1:m # dict and vector() which is better. for loop? +# assign[j] = 0 +# end +# for j=1:n +# b[j] = 0 +# end +# pathfound = false +# for k = 1:n +# while !pathfound +# # 3b-1 +# filter!(a -> a!=0,diff) +# filter!(a -> a[2] in diff,G.edges) +# color=Vector() +# pathfound=Ref(false) +# augmentpath!(k,pathfound,color,assign,G.vars,G.edges) +# # 3b-5 to do +# pathfound[] || return assign +# end +# end +# return assign +#end diff --git a/test/pantelides.jl b/test/pantelides.jl new file mode 100644 index 0000000000..b28a6aaa52 --- /dev/null +++ b/test/pantelides.jl @@ -0,0 +1,36 @@ +using Test +using ModelingToolkit: BiGraph, construct_augmentpath!, init_assign + +function augment_path(G) + assign = init_assign(G) + pathfound = Ref(false) + construct_augmentpath!(G, assign, pathfound) + return assign, pathfound[] +end + +# E node using integer from 1 represents the equation mark (the first +# Vector in BiGraph). V node using integer from 11 represents the variables +# (the second vector) Edge in the third part represents their relations + +G = BiGraph([1, 2, 3, 4, 5], [11, 12, 13, 14, 15, 16, 17, 18, 19], [1=>15, 2=>16, 3=>17, 4=>18, 3=>19, 4=>19, 5=>0]) +#test1 pantelides fig1-b trivial test +@test augment_path(G) == (Dict(11=>nothing,12=>nothing,13=>nothing,14=>nothing,15=>1,16=>2,17=>3,18=>4,19=>nothing), false) + +G = BiGraph([1, 2, 3, 4, 5, 6, 7, 8, 9], [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], [1=>15, 2=>16, 3=>17, 4=>18, 3=>19, 4=>19, 5=>0, 6=>15, 6=>16, 7=>20, 8=>21]) +@test augment_path(G) == (Dict(11=>nothing,12=>nothing,13=>nothing,14=>nothing,15=>1,16=>2,17=>3,18=>4,19=>nothing,20=>7,21=>8), false) + +G = BiGraph([1, 2, 3, 4, 5, 6, 7, 8, 9], [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], [1=>15, 2=>16, 3=>17, 4=>18, 3=>19, 4=>19, 5=>0, 7=>20, 8=>21, 7=>17, 8=>18, 9=>20, 9=>21]) +#test3 pantelides fig1-d test +@test augment_path(G) == (Dict(11=>nothing,12=>nothing,13=>nothing,14=>nothing,15=>1,16=>2,17=>7,18=>4,19=>3,20=>9,21=>8), true) + +G = BiGraph([1, 2, 3, 4], [11, 12, 13, 14, 15, 16], [1=>13, 1=>15, 2=>14, 2=>15, 2=>16, 3=>15]) +#test4 pantelides fig2-b test +@test augment_path(G) == (Dict(11=>nothing,12=>nothing,13=>1,14=>2,15=>3,16=>nothing), false) + +G = BiGraph([1, 2, 3, 4, 5, 6, 7, 8], [11, 12, 13, 14, 15, 16, 17, 18], [1=>13, 2=>14, 2=>16, 3=>15, 4=>0, 5=>0, 6=>17, 6=>18, 7=>14, 7=>18, 8=>17]) +#test5 pantelides fig2-d test +@test augment_path(G) == (Dict(11=>nothing,12=>nothing,13=>1,14=>7,15=>3,16=>2,17=>8,18=>6), true) + +G = BiGraph([1, 2, 3, 4], [11, 12, 13, 14], [1=>13, 1=>14, 2=>12, 1=>0]) +#test6 pantelides fig3-b trivial test +@test augment_path(G) == (Dict(11=>nothing,12=>2,13=>1,14=>nothing), false) diff --git a/test/runtests.jl b/test/runtests.jl index 00a80ece02..bc13b49024 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,3 +4,4 @@ using ModelingToolkit, Test @testset "Differentiation Test" begin include("derivatives.jl") end @testset "Simplify Test" begin include("simplify.jl") end @testset "System Construction Test" begin include("system_construction.jl") end +@testset "Pantelides Test" begin include("pantelides.jl") end