我试图避免使用嵌套循环并降低从On ^ 2开始的运行时间,该代码旨在实现一种有效的算法,以计算给定功能的所有路径。 I.深度优先遍历(DFS):实现必须遵循DFS 二。多重性的使用:跟踪每个节点的多重性 三,推送触发器:合并触发器以适当地将多样性从一个节点推送到其后继节点 IV。使用您的实现来列出XINU中所有XINU函数的路径计数。 V.将路径计数存储在电子表格中(使用ExportResults.export) VI。线性和正确性的证明:通过将实现与给定的实现(DFSPathCounter.java)进行比较来证明实现的正确性和线性,这是一种简单得多的指数路径计数算法。
public class DFSPathCounter extends PathCounter {
public DFSPathCounter() {}
/**
* Counts the number of paths in a given CFG
*
* Example Atlas Shell Usage:
* var dskqopt = functions("dskqopt")
* var dskqoptCFG = cfg(dskqopt)
* var dfsCounter = new DFSPathCounter
* dfsCounter.countPaths(dskqoptCFG)
*
* @param cfg
* @return
*/
public CountingResult countPaths(Q cfg) {
// the total number of paths discovered
// and the number of additions required to count the path
long numPaths = 0;
long additions = 0;
// create a directed acyclic graph (DAG)
DAGTransform transformer = new DAGTransform();
Q dag = transformer.transform(cfg);
// the roots and leaves of the DAG
AtlasSet<Node> dagLeaves = dag.leaves().eval().nodes();
Node dagRoot = dag.roots().eval().nodes().one();
// handle some trivial edge cases
if(dagRoot == null) {
// function is empty, there are no paths
return new CountingResult(0L,0L);
} else if(dagLeaves.contains(dagRoot)) {
// function contains a single node there must be 1 path
return new CountingResult(0L,1L);
}
// stack for depth first search (DFS)
Stack<Node> stack = new Stack<Node>();
// start searching from the root
stack.push(dagRoot);
// depth first search on directed acyclic graph
while (!stack.isEmpty()) {
// next node to process
Node currentNode = stack.pop();
// get the children of the current node
// note: we iterate by edge in case there are multiple edges from a predecessor to a successor
for (Edge outgoingEdge : dag.forwardStep(Common.toQ(currentNode)).eval().edges()) {
Node successor = outgoingEdge.to();
if(dagLeaves.contains(successor)) {
// if we reached a leaf increment the counter by 1
numPaths++;
additions++;
} else {
// push the child node on the stack to be processed
stack.push(successor);
}
}
}
// at the end, we have traversed all paths once, so return the count
return new CountingResult(additions, numPaths);
}