From 209db7126cbb13027701ada0719a11079cfd5940 Mon Sep 17 00:00:00 2001 From: Junpeng <1025946044@qq.com> Date: Mon, 1 Apr 2019 02:13:04 +0800 Subject: [PATCH 1/3] Add the matching (`augment_path`) for the Pantelides algorithm --- src/ModelingToolkit.jl | 1 + src/systems/diffeqs/pantelides.jl | 81 +++++++++++++++++++++++++++++++ test/pantelides.jl | 29 +++++++++++ test/runtests.jl | 1 + 4 files changed, 112 insertions(+) create mode 100644 src/systems/diffeqs/pantelides.jl create mode 100644 test/pantelides.jl 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..13bf7716ca --- /dev/null +++ b/src/systems/diffeqs/pantelides.jl @@ -0,0 +1,81 @@ +struct BiGraph + nodese + nodesv + edges +end + +function augment_path(G) + assign = Dict() + # second function + function check_alg!(G,assign,pathfound) + function augmentpath!(i,pathfound,color,assign,nodesv,edges) + function checkcond(assign,nodesv,edges) + for j in nodesv + if assign[j] == 0 && (count(x -> x[2]==j && x[1]==i,edges) > 0) + return j + end + end + return false + end + union!(color,i) + j = checkcond(assign,nodesv,edges) + if j != false + pathfound[1]=true + assign[j] = i + return nothing + end + for j in nodesv + if count(x -> x[2]==j && x[1]==i,edges) > 0 && !(j in color) + union!(color,j) + k=assign[j] + augmentpath!(k,pathfound,color,assign,nodesv,edges) + if pathfound[1] + assign[j] = i + return nothing + end + end + end + return assign + end + #main operation in function + for i in G.nodese + pathfound[1] = false + while !pathfound[1] + color=Vector() + pathfound[1] = false + augmentpath!(i,pathfound,color,assign,G.nodesv,G.edges) + pathfound[1] || break + end + end + end + for j in G.nodesv + assign[j] = 0 + end + check_alg!(G,assign,[false]) + return assign +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=false + augmentpath!(k,pathfound,color,assign,G.nodesv,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..fb8d60f26d --- /dev/null +++ b/test/pantelides.jl @@ -0,0 +1,29 @@ +using Test +using ModelingToolkit: BiGraph, augment_path +# 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(Vector([1,2,3,4,5]),Vector([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=>0,12=>0,13=>0,14=>0,15=>1,16=>2,17=>3,18=>4,19=>0) + +G=BiGraph(Vector([1,2,3,4,5,6,7,8,9]),Vector([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=>0,12=>0,13=>0,14=>0,15=>1,16=>2,17=>3,18=>4,19=>0,20=>7,21=>8) + +G=BiGraph(Vector([1,2,3,4,5,6,7,8,9]),Vector([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=>0,12=>0,13=>0,14=>0,15=>1,16=>2,17=>7,18=>4,19=>3,20=>9,21=>8) + +G=BiGraph(Vector([1,2,3,4]),Vector([11,12,13,14,15,16]),[[1,13],[1,15],[2,14],[2,15],[2,16],[3,15]])#[1,1],[1,3],[2,2],[2,4],[2,5],[2,6],[3,1],[3,2],[3,5],[4,1] +#test4 pantelides fig2-b test +@test augment_path(G) == Dict(11=>0,12=>0,13=>1,14=>2,15=>3,16=>0) + +G=BiGraph(Vector([1,2,3,4,5,6,7,8]),Vector([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]])#[1,1],[1,3],[2,2],[2,4],[2,5],[2,6],[3,1],[3,2],[3,5],[4,1] +#test5 pantelides fig2-d test +@test augment_path(G) == Dict(11=>0,12=>0,13=>1,14=>7,15=>3,16=>2,17=>8,18=>6) + +G=BiGraph(Vector([1,2,3,4]),Vector([11,12,13,14]),[[1,13],[1,14],[2,12],[1,0]]) +#test6 pantelides fig3-b trivial test +@test augment_path(G) == Dict(11=>0,12=>2,13=>1,14=>0) 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 From dfe8ae8f5cec4bd6b490fc0ab88476579bed8667 Mon Sep 17 00:00:00 2001 From: Yingbo Ma Date: Sun, 31 Mar 2019 16:59:20 -0400 Subject: [PATCH 2/3] Code clean up --- src/systems/diffeqs/pantelides.jl | 140 +++++++++++++++--------------- test/pantelides.jl | 41 +++++---- 2 files changed, 95 insertions(+), 86 deletions(-) diff --git a/src/systems/diffeqs/pantelides.jl b/src/systems/diffeqs/pantelides.jl index 13bf7716ca..fb09c810b0 100644 --- a/src/systems/diffeqs/pantelides.jl +++ b/src/systems/diffeqs/pantelides.jl @@ -1,81 +1,83 @@ -struct BiGraph - nodese - nodesv - edges +struct BiGraph{TA,TB,TC} + eqs::TA + vars::TB + edges::TC end -function augment_path(G) - assign = Dict() +function init_assign(G) + assign = Dict{eltype(G.vars), Union{Nothing, eltype(G.eqs)}}() # second function - function check_alg!(G,assign,pathfound) - function augmentpath!(i,pathfound,color,assign,nodesv,edges) - function checkcond(assign,nodesv,edges) - for j in nodesv - if assign[j] == 0 && (count(x -> x[2]==j && x[1]==i,edges) > 0) - return j - end - end - return false - end - union!(color,i) - j = checkcond(assign,nodesv,edges) - if j != false - pathfound[1]=true - assign[j] = i - return nothing - end - for j in nodesv - if count(x -> x[2]==j && x[1]==i,edges) > 0 && !(j in color) - union!(color,j) - k=assign[j] - augmentpath!(k,pathfound,color,assign,nodesv,edges) - if pathfound[1] - assign[j] = i - return nothing - end - end - end - return assign - end - #main operation in function - for i in G.nodese - pathfound[1] = false - while !pathfound[1] - color=Vector() - pathfound[1] = false - augmentpath!(i,pathfound,color,assign,G.nodesv,G.edges) - pathfound[1] || break - end - end - end - for j in G.nodesv - assign[j] = 0 + for j in G.vars + assign[j] = nothing end - check_alg!(G,assign,[false]) return assign 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 +function has_vnode(i, j, edges) + for edge in edges + (edge == ( i=>j ) ) && return true + end + return false +end + +function augmentpath!(i, pathfound, color, assign, vars, edges) + union!(color, i) + idx = -1 + for j in vars + assign[j] === nothing || continue + has_vnode(i, j, edges) && (idx = j; break) end - for j=1:n - b[j] = 0 + if idx != -1 + pathfound[] = true + assign[idx] = i + return nothing 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=false - augmentpath!(k,pathfound,color,assign,G.nodesv,G.edges) - # 3b-5 to do - pathfound || return assign + for j in vars + !(has_vnode(i, j, 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 assign + 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 index fb8d60f26d..b28a6aaa52 100644 --- a/test/pantelides.jl +++ b/test/pantelides.jl @@ -1,29 +1,36 @@ using Test -using ModelingToolkit: BiGraph, augment_path +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(Vector([1,2,3,4,5]),Vector([11,12,13,14,15,16,17,18,19]),[[1,15],[2,16],[3,17],[4,18],[3,19],[4,19],[5,0]]) - +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=>0,12=>0,13=>0,14=>0,15=>1,16=>2,17=>3,18=>4,19=>0) +@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(Vector([1,2,3,4,5,6,7,8,9]),Vector([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=>0,12=>0,13=>0,14=>0,15=>1,16=>2,17=>3,18=>4,19=>0,20=>7,21=>8) +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(Vector([1,2,3,4,5,6,7,8,9]),Vector([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=>0,12=>0,13=>0,14=>0,15=>1,16=>2,17=>7,18=>4,19=>3,20=>9,21=>8) +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(Vector([1,2,3,4]),Vector([11,12,13,14,15,16]),[[1,13],[1,15],[2,14],[2,15],[2,16],[3,15]])#[1,1],[1,3],[2,2],[2,4],[2,5],[2,6],[3,1],[3,2],[3,5],[4,1] -#test4 pantelides fig2-b test -@test augment_path(G) == Dict(11=>0,12=>0,13=>1,14=>2,15=>3,16=>0) +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(Vector([1,2,3,4,5,6,7,8]),Vector([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]])#[1,1],[1,3],[2,2],[2,4],[2,5],[2,6],[3,1],[3,2],[3,5],[4,1] -#test5 pantelides fig2-d test -@test augment_path(G) == Dict(11=>0,12=>0,13=>1,14=>7,15=>3,16=>2,17=>8,18=>6) +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(Vector([1,2,3,4]),Vector([11,12,13,14]),[[1,13],[1,14],[2,12],[1,0]]) +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=>0,12=>2,13=>1,14=>0) +@test augment_path(G) == (Dict(11=>nothing,12=>2,13=>1,14=>nothing), false) From ae3830aaf0b244a1a65445e8f2931b63b8c41a5f Mon Sep 17 00:00:00 2001 From: Yingbo Ma Date: Sun, 31 Mar 2019 17:06:52 -0400 Subject: [PATCH 3/3] rm `has_vnode` --- src/systems/diffeqs/pantelides.jl | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/systems/diffeqs/pantelides.jl b/src/systems/diffeqs/pantelides.jl index fb09c810b0..49a0561c86 100644 --- a/src/systems/diffeqs/pantelides.jl +++ b/src/systems/diffeqs/pantelides.jl @@ -13,19 +13,12 @@ function init_assign(G) return assign end -function has_vnode(i, j, edges) - for edge in edges - (edge == ( i=>j ) ) && return true - end - return false -end - function augmentpath!(i, pathfound, color, assign, vars, edges) union!(color, i) idx = -1 for j in vars assign[j] === nothing || continue - has_vnode(i, j, edges) && (idx = j; break) + (i => j) in edges && (idx = j; break) end if idx != -1 pathfound[] = true @@ -33,7 +26,7 @@ function augmentpath!(i, pathfound, color, assign, vars, edges) return nothing end for j in vars - !(has_vnode(i, j, edges) && !(j in color)) && continue + !((i => j) in edges && !(j in color)) && continue union!(color, j) k = assign[j] augmentpath!(k, pathfound, color, assign, vars, edges)