Monday, December 28, 2009

Finding circular dependencies in Flex/AS3

I was looking for cycles in a directed graph in a task chart implementation I was doing for a client. My implementation of the Tarjan algorithm is hard coded for a linkage of task objects linked by constraints. I’d be interested to find out if anyone else has dug into this algorithm and gotten it to work.

package model.task {
import ilog.gantt.TaskChart;


public class Tarjan {
private var index:int = 0;
private var stack:Array = new Array();
private var SCC:Array = new Array();
public var taskChart:ilog.gantt.TaskChart;

/**
* N.B. Don't forget to reset the *.index = -1 after checking
*
* DJH 12/24/2009 This will only work for task nodes connected by constraints. It does not traverse
* the entire task hierachical data
*
* I don't fully understand but all nodes are treated as loops. Look through the SCC
* array for child arrays which with more than 1 node and those the the cycles.
*
*/
public function tarjan(task:Object /* node */ /*, adjacencyList:Array*/ ):Array {
trace("tarjan():: push task " + task.id);
task.index = index;
task.lowLink = index;
index++;
stack.push(task);
var constraints:Array = taskChart.getFromConstraints(task);
// Collect the successors
if(constraints) {
for each(var c:Object in constraints) {
var toTask:Object = taskChart.getToTask(c);
if(toTask == null) {
// DJH 12/9/2009, fix the constraint does not chain to a successor, so ignore
continue;
}
if(toTask.index == -1) {
tarjan(toTask /*, adjacencyList*/ );
task.lowLink = Math.min(task.lowLink, toTask.lowLink);
} else if(stack.indexOf(toTask) >= 0) {
task.lowLink = Math.min(task.lowLink, toTask.index);
}
}
}
if(task.lowLink == task.index) {
var arr:Array = new Array();
do {
toTask = stack.pop();
arr.push(toTask);
} while(toTask != task)
SCC.push(arr);
}
return SCC;
}
}
}

No comments: