function filterPredefinedReachableNodes(orderedNodes, predefinedNodes) {
    const nameToNode = new Map(orderedNodes.map((node)=>[
            node.name,
            node
        ]));
    // TODO: Filter out more nodes when >=2 nodes are predefined in a path.
    const stack = predefinedNodes.map((node)=>node.name);
    const predefinedReachableNodeNames = new Set(stack);
    // Perform a DFS starting from the set of all predefined nodes
    // to find the set of all nodes reachable from the predefined nodes.
    while(stack.length > 0){
        const nodeName = stack.pop();
        const node = nameToNode.get(nodeName);
        for (const child of node.children){
            if (!nameToNode.has(child.name) || predefinedReachableNodeNames.has(child.name)) continue;
            predefinedReachableNodeNames.add(child.name);
            stack.push(child.name);
        }
    }
    // Filter out unreachable nodes and build the ordered node list.
    const filteredOrderedNodes = orderedNodes.filter((node)=>predefinedReachableNodeNames.has(node.name));
    return filteredOrderedNodes;
}
This is a helper function of `getNodesInTopologicalOrder`.
Returns ordered nodes reachable by at least one predefined node.
This can help us filter out redundant nodes from the returned node list.
For example:
If we have four nodes with dependencies like this:
  a --> b --> c --> d
when node `c` is predefined (e.g. given as an input tensor), we can
skip node `a` and `b` since their outputs will never be used.

@param orderedNodes Graph nodes in execution order.
@param predefinedNodes Graph inputs, weights, and init nodes. Nodes in this
    list must have distinct names.