Skip to content

Commit

Permalink
- Added transposed version of Tarjan's algorithm
Browse files Browse the repository at this point in the history
git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@25602 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
  • Loading branch information
lochel committed Apr 17, 2015
1 parent 8da9195 commit 5604fc8
Showing 1 changed file with 154 additions and 110 deletions.
264 changes: 154 additions & 110 deletions Compiler/BackEnd/BackendDAETransform.mo
Expand Up @@ -757,123 +757,167 @@ algorithm
end matchcontinue;
end getEquationAndSolvedVarIndxes;

public function Tarjan_Transposed "author: lochel"
input BackendDAE.IncidenceMatrixT mT;
input array<Integer> ass2 "var := ass2[eqn]";
output list<list<Integer>> outComponents = {} "eqn indices";
protected
Integer N = arrayLength(ass2);
array<Integer> ass1;
list<list<Integer>> comps;
list<Integer> comp;
algorithm
ass1 := Matching.invertMatching(ass2);
comps := Tarjan(mT, ass2);
for i in comps loop
comp := {};
for j in i loop
comp := arrayGet(ass1, j)::comp;
public function Tarjan "author: lochel"
input BackendDAE.IncidenceMatrix m;
input array<Integer> ass1 "eqn := ass1[var]";
output list<list<Integer>> outComponents = {} "eqn indices";
protected
Integer index = 0;
list<Integer> S = {};

array<Integer> number, lowlink;
array<Boolean> onStack;
Integer N = arrayLength(ass1);
algorithm
//BackendDump.dumpIncidenceMatrix(m);
//BackendDump.dumpMatchingVars(ass1);

number := arrayCreate(N, -1);
lowlink := arrayCreate(N, -1);
onStack := arrayCreate(N, false);

for eqn in 1:N loop
if number[eqn] == -1 then
(S, index, outComponents) := StrongConnect(m, ass1, eqn, S, index, number, lowlink, onStack, outComponents);
end if;
end for;
outComponents := comp::outComponents;
end for;
end Tarjan_Transposed;

public function Tarjan_Transposed2 "author: lochel"
input BackendDAE.IncidenceMatrixT mT;
input array<Integer> ass2 "var := ass2[eqn]";
output list<list<Integer>> outComponents = {} "eqn indices";
protected
Integer N = arrayLength(ass2);
BackendDAE.IncidenceMatrixT m;
array<Integer> ass1;
algorithm
m := BackendDAEUtil.transposeMatrix(mT, N);
ass1 := Matching.invertMatching(ass2);
outComponents := Tarjan(m, ass1);
end Tarjan_Transposed2;

public function Tarjan "author: lochel"
input BackendDAE.IncidenceMatrix m;
input array<Integer> ass1 "eqn := ass1[var]";
output list<list<Integer>> outComponents = {} "eqn indices";
protected
Integer index = 0;
list<Integer> S = {};

array<Integer> number, lowlink;
array<Boolean> onStack;
Integer n = arrayLength(ass1);
algorithm
//BackendDump.dumpIncidenceMatrix(m);
//BackendDump.dumpMatchingVars(ass1);

number := arrayCreate(n, -1);
lowlink := arrayCreate(n, -1);
onStack := arrayCreate(n, false);
outComponents := listReverse(outComponents);
end Tarjan;

protected function StrongConnect "author: lochel"
input BackendDAE.IncidenceMatrix m;
input array<Integer> ass1 "eqn := ass1[var]";
input Integer eqn;
input list<Integer> S;
input Integer index;
input array<Integer> number;
input array<Integer> lowlink;
input array<Boolean> onStack;
input list<list<Integer>> inComponents;
output list<Integer> outS = S;
output Integer outIndex = index;
output list<list<Integer>> outComponents = inComponents;
protected
list<Integer> SCC;
Integer eqn2;
algorithm
// Set the depth index for eqn to the smallest unused index
arrayUpdate(number, eqn, outIndex);
arrayUpdate(lowlink, eqn, outIndex);
arrayUpdate(onStack, eqn, true);
outIndex := outIndex + 1;
outS := eqn::outS;

// Consider successors of v
for i in m[eqn] loop
if i > 0 then // just consider positive items
eqn2 := arrayGet(ass1, i);
if eqn <> eqn2 then
if number[eqn2] == -1 then
// Successor eqn2 has not yet been visited; recurse on it
(outS, outIndex, outComponents) := StrongConnect(m, ass1, eqn2, outS, outIndex, number, lowlink, onStack, outComponents);
arrayUpdate(lowlink, eqn, intMin(lowlink[eqn], lowlink[eqn2]));
elseif onStack[eqn2] then
// Successor eqn2 is in stack S and hence in the current SCC
arrayUpdate(lowlink, eqn, intMin(lowlink[eqn], number[eqn2]));
end if;
end if;
end if;
end for;

for v in 1:n loop
if number[v] == -1 then
(S, index, outComponents) := StrongConnect(m, ass1, v, S, index, number, lowlink, onStack, outComponents);
// If eqn is a root node, pop the stack and generate an SCC
if lowlink[eqn] == number[eqn] then
eqn2::outS := outS;
arrayUpdate(onStack, eqn2, false);
SCC := {eqn2};
while eqn <> eqn2 loop
eqn2::outS := outS;
arrayUpdate(onStack, eqn2, false);
SCC := eqn2::SCC;
end while;
outComponents := SCC::outComponents;
end if;
end for;

outComponents := listReverse(outComponents);
end Tarjan;

protected function StrongConnect "author: lochel"
input BackendDAE.IncidenceMatrix m;
input array<Integer> ass1 "eqn := ass1[var]";
input Integer v;
input list<Integer> S;
input Integer index;
input array<Integer> number;
input array<Integer> lowlink;
input array<Boolean> onStack;
input list<list<Integer>> inComponents;
output list<Integer> outS = S;
output Integer outIndex = index;
output list<list<Integer>> outComponents = inComponents;
protected
list<Integer> SCC = {};
Integer w;
algorithm
// Set the depth index for v to the smallest unused index
arrayUpdate(number, v, outIndex);
arrayUpdate(lowlink, v, outIndex);
arrayUpdate(onStack, v, true);
outIndex := outIndex + 1;
outS := v::outS;

// Consider successors of v
for i in m[v] loop
if i > 0 then // just consider positive items
w := arrayGet(ass1, i);
if w <> v then
if number[w] == -1 then
// Successor w has not yet been visited; recurse on it
(outS, outIndex, outComponents) := StrongConnect(m, ass1, w, outS, outIndex, number, lowlink, onStack, outComponents);
arrayUpdate(lowlink, v, intMin(lowlink[v], lowlink[w]));
elseif onStack[w] then
// Successor w is in stack S and hence in the current SCC
arrayUpdate(lowlink, v, intMin(lowlink[v], number[w]));
end StrongConnect;

public function TarjanTransposed "author: lochel"
input BackendDAE.IncidenceMatrixT mT;
input array<Integer> ass2 "var := ass2[eqn]";
output list<list<Integer>> outComponents = {} "eqn indices";
protected
Integer index = 0;
list<Integer> S = {};

array<Integer> number, lowlink;
array<Boolean> onStack;
Integer N = arrayLength(ass2);
algorithm
//BackendDump.dumpIncidenceMatrixT(mT);
//BackendDump.dumpMatchingEqns(ass2);

number := arrayCreate(N, -1);
lowlink := arrayCreate(N, -1);
onStack := arrayCreate(N, false);

for eqn in 1:N loop
if number[eqn] == -1 then
(S, index, outComponents) := StrongConnectTransposed(mT, ass2, eqn, S, index, number, lowlink, onStack, outComponents);
end if;
end for;
end TarjanTransposed;

protected function StrongConnectTransposed "author: lochel"
input BackendDAE.IncidenceMatrixT mT;
input array<Integer> ass2 "var := ass2[eqn]";
input Integer eqn;
input list<Integer> S;
input Integer index;
input array<Integer> number;
input array<Integer> lowlink;
input array<Boolean> onStack;
input list<list<Integer>> inComponents;
output list<Integer> outS = S;
output Integer outIndex = index;
output list<list<Integer>> outComponents = inComponents;
protected
list<Integer> SCC;
Integer var, eqn2;
algorithm
// Set the depth index for var to the smallest unused index
arrayUpdate(number, eqn, outIndex);
arrayUpdate(lowlink, eqn, outIndex);
arrayUpdate(onStack, eqn, true);
outIndex := outIndex + 1;
outS := eqn::outS;

// Consider successors of var
var := ass2[eqn];
for eqn2 in mT[var] loop
if eqn <> eqn2 then
if arrayGet(number, eqn2) == -1 then
// Successor eqn2 has not yet been visited; recurse on it
(outS, outIndex, outComponents) := StrongConnectTransposed(mT, ass2, eqn2, outS, outIndex, number, lowlink, onStack, outComponents);
arrayUpdate(lowlink, eqn, intMin(lowlink[eqn], arrayGet(lowlink, eqn2)));
elseif arrayGet(onStack, eqn2) then
// Successor eqn2 is in stack S and hence in the current SCC
arrayUpdate(lowlink, eqn, intMin(lowlink[eqn], arrayGet(number, eqn2)));
end if;
end if;
end if;
end for;
end for;

// If v is a root node, pop the stack and generate an SCC
if (lowlink[v] == number[v]) then
w::outS := outS;
arrayUpdate(onStack, w, false);
SCC := w::SCC;
while w <> v loop
w::outS := outS;
arrayUpdate(onStack, w, false);
SCC := w::SCC;
end while;
outComponents := SCC::outComponents;
end if;
end StrongConnect;
// If eqn is a root node, pop the stack and generate an SCC
if lowlink[eqn] == number[eqn] then
eqn2::outS := outS;
arrayUpdate(onStack, eqn2, false);
SCC := {eqn2};
while eqn <> eqn2 loop
eqn2::outS := outS;
arrayUpdate(onStack, eqn2, false);
SCC := eqn2::SCC;
end while;
outComponents := SCC::outComponents;
end if;
end StrongConnectTransposed;

public function tarjanAlgorithm "author: PA

Expand Down

0 comments on commit 5604fc8

Please sign in to comment.