Integer ZERO = new Integer(0);
Integer ONE = new Integer(1);
    public SDEPData computeSDEP(        LatencyNode upstreamNode,        LatencyNode downstreamNode) throws NoPathException    {        // first find all the edges that need to be traversed when figuring        // out the dependencies between nodes        OSet edgesToTraverse;        {            StreamInterface ancestor =                findLowestCommonAncestor(upstreamNode, downstreamNode);            edgesToTraverse =                visitGraph(                    upstreamNode,                    false,                    true,                    ancestor,                    false,                    true);            OSet edgesUpstream =                visitGraph(                    downstreamNode,                    true,                    false,                    ancestor,                    false,                    true);            // find an intersection between these two sets:            {                OSetIterator edgesIter = edgesToTraverse.begin();                OSetIterator edgesLastIter = edgesToTraverse.end();                OSetIterator upstreamEdgesLastIter = edgesUpstream.end();                DLList uselessEdges = new DLList();                for (; !edgesIter.equals(edgesLastIter); edgesIter.next())                {                    // if the edgesUpstream set doesn't have this edge,                    // store it to be removed from the set                    if (edgesUpstream                        .find(edgesIter.get())                        .equals(upstreamEdgesLastIter))                        uselessEdges.pushBack(edgesIter.get());                }                // remove useless edges                while (!uselessEdges.empty())                {                    edgesToTraverse.erase(uselessEdges.front().get());                    uselessEdges.popFront();                }                // now edgesToTraverse holds all edges that can be traversed                // between upstreamNode and downstreamNode            }            // remove the backward pointing edges:            {                OSet backwardPointingEdges =                    findBackPointingEdges(upstreamNode, ancestor);                OSetIterator backEdgeLastIter = backwardPointingEdges.end();                for (OSetIterator backEdgeIter =                    backwardPointingEdges.begin();                    !backEdgeIter.equals(backEdgeLastIter);                    backEdgeIter.next())                {                    edgesToTraverse.erase(backEdgeIter.get());                }            }            // make sure that there are SOME edges between the two nodes            // if this ASSERT fails, then either the srcIsUpstream is reversed            // or there is no path between upstreamNode and downstreamNode            // within their lowest common ancestor.            // if you don't understand this, or think it's wrong, ask karczma             // (03/07/15)            //ASSERT(!edgesToTraverse.empty());	    if (edgesToTraverse.empty()) {		throw new NoPathException();	    }        }        // now go through all the edges and count how many useful edges        // arrive at each node that will be traversed        OMap nodes2numEdges = new OMap();        OMapIterator lastN2NEIter = nodes2numEdges.end();        {            OSetIterator edgeIter = edgesToTraverse.begin();            OSetIterator lastEdgeIter = edgesToTraverse.end();            Integer ZERO = new Integer(0);            for (; !edgeIter.equals(lastEdgeIter); edgeIter.next())            {                LatencyNode nodeDst =                    ((LatencyEdge)edgeIter.get()).getDst();                OMapIterator n2eIter = nodes2numEdges.find(nodeDst);                Integer useCount = ZERO;                if (!n2eIter.equals(lastN2NEIter))                {                    useCount = (Integer)n2eIter.getData();                }                useCount = new Integer(useCount.intValue() + 1);                nodes2numEdges.insert(nodeDst, useCount);            }        }        /*         * The following map maps LatencyNode to LatencyEdge         * The LatencyEdge is a latency LatencyEdge (meaning that it         * never is concerned about # of data items that travel on tapes,         * only which execution of the src translates to an execution of         * the dst) going from upstreamNode to the key node.          */        OMap nodes2latencyEdges = new OMap();        OMapIterator lastNodes2latencyEdgesIter = nodes2latencyEdges.end();        // insert an identity latency edge from src to src into the map        nodes2latencyEdges.insert(            upstreamNode,            new LatencyEdge(upstreamNode));        OSet nodesToVisit = new OSet();        nodesToVisit.insert(upstreamNode);        // compute the dependency list for all the nodes        // wrt to the upstreamNode        while (!nodesToVisit.empty())        {            OSetIterator nodesToVisitIter = nodesToVisit.begin();            LatencyNode node = (LatencyNode)nodesToVisitIter.get();            nodesToVisit.erase(nodesToVisitIter);            DLList_const dependants = node.getDependants();            DLListIterator dependantIter = dependants.begin();            DLListIterator lastDependant = dependants.end();            OSetIterator edgesLastIter = edgesToTraverse.end();            for (;                !dependantIter.equals(lastDependant);                dependantIter.next())            {                LatencyEdge edge = (LatencyEdge)dependantIter.get();                LatencyNode edgeSrc = edge.getSrc();                LatencyNode edgeDst = edge.getDst();                // if this edge doesn't need to be traversed, don't                OSetIterator edgeDstNodeIter = edgesToTraverse.find(edge);                if (edgeDstNodeIter.equals(edgesLastIter))                    continue;                // create an edge from upstreamNode to edgeDst                {                    // first just create an edge by combining edges:                    // upstreamNode->edge.src and edge                    LatencyEdge newEdge;                    {                        OMapIterator upstreamNode2srcIter =                            nodes2latencyEdges.find(edgeSrc);                        ASSERT(                            !upstreamNode2srcIter.equals(                                lastNodes2latencyEdgesIter));                        newEdge =                            new LatencyEdge(                                (LatencyEdge)upstreamNode2srcIter.getData(),                                edge);                    }                    // if there already is an edge going from upstreamNode                     // to edgeDst, I need to combine that edge with this                     // newEdge                    {                        OMapIterator upstreamNode2dstIter =                            nodes2latencyEdges.find(edgeDst);                        if (!upstreamNode2dstIter                            .equals(lastNodes2latencyEdgesIter))                        {                            newEdge =                                new LatencyEdge(                                    newEdge,                                    (LatencyEdge)upstreamNode2dstIter                                        .getData());                        }                    }                    // and finally, insert the new edge into the map.                    // if an edge going to edgeDst already exists there,                    // this will replace it, which is good                    nodes2latencyEdges.insert(edgeDst, newEdge);                }                // find how many more edges need to lead to this node                int nodeNumEdges =                    ((Integer)nodes2numEdges.find(edge.getDst()).getData())                        .intValue();                ASSERT(nodeNumEdges > 0);                // decrease the number of edges that need to lead to this node                // by one                nodeNumEdges--;                nodes2numEdges.insert(                    edge.getDst(),                    new Integer(nodeNumEdges));                // if there are no more edges leading into this node,                // I'm ready to visit the node                if (nodeNumEdges == 0)                {                    nodesToVisit.insert(edge.getDst());                }            }        }        return (LatencyEdge)            (nodes2latencyEdges.find(downstreamNode).getData());    }