Condensed Graphs provide a simple way of expressing complex dependencies in a program task graph or a work flow. In these graphs, nodes represent tasks and edges represent associated sequencing constraint. The sequence of task execution can be altered by altering the relationship between various nodes. These simple topological changes do not, in general, alter the meaning of the task graph or work flow (although they can affect program termination). Rather, they result in a change in execution order, reflecting either an imperative, data-driven or demand-driven computation. In fact, any desired combination of all three paradigms can be represented within the same task graph or work flow. This flexibility leads to many advantages both in the expression of task graphs and in their implementation.