is_entry_node(node::Node) = length(node.children) == 0 is_exit_node(node::Node) = length(node.parents) == 0 # children = prerequisite nodes, nodes that need to execute before the task, edges point into this task function children(node::Node) return copy(node.children) end # parents = subsequent nodes, nodes that need this node to execute, edges point from this task function parents(node::Node) return copy(node.parents) end # siblings = all children of any parents, no duplicates, includes the node itself function siblings(node::Node) result = Set{Node}() push!(result, node) for parent in node.parents union!(result, parent.children) end return result end # partners = all parents of any children, no duplicates, includes the node itself function partners(node::Node) result = Set{Node}() push!(result, node) for child in node.children union!(result, child.parents) end return result end # alternative version to partners(Node), avoiding allocation of a new set # works on the given set and returns nothing function partners(node::Node, set::Set{Node}) push!(set, node) for child in node.children union!(set, child.parents) end return nothing end function is_parent(potential_parent, node) return potential_parent in node.parents end function is_child(potential_child, node) return potential_child in node.children end