private StagedHoudiniPlan ComputeCoarseStages()
        {
            foreach(var n in StagesDAG.Nodes) {
              Debug.Assert(!StagesDAG.Successors(n).Contains(n));
            }

            Graph<ScheduledStage> Dependences = new Graph<ScheduledStage>();

            var done = new Dictionary<SCC<string>, ScheduledStage>();
            done[GetStartNodeOfStagesDAG()] = new ScheduledStage(0, new HashSet<string>());

            for(int stageId = 1; done.Count() != StagesDAG.Nodes.Count(); stageId++)
            {
            var Stage = new ScheduledStage(stageId, new HashSet<string>());
            HashSet<SCC<string>> AssignedToThisStage = new HashSet<SCC<string>>();

            foreach (var n in StagesDAG.Nodes.Where(Item => !done.ContainsKey(Item)))
            {
              if(StagesDAG.Successors(n).Where(Item => !done.ContainsKey(Item)).Count() == 0) {
                foreach(var s in StagesDAG.Successors(n)) {
                  Debug.Assert(s != n);
                  Debug.Assert(Stage != done[s]);
                  Dependences.AddEdge(Stage, done[s]);
                }
                foreach (var c in n)
                {
                  Stage.AddCandidate(c);
                }
                Console.Write(n.Count() + ", ");
                AssignedToThisStage.Add(n);
              }
            }

            Console.WriteLine("total: " + Stage.Count());

            foreach(var n in AssignedToThisStage) {
              done[n] = Stage;
            }
            }
            return new StagedHoudiniPlan(Dependences);
        }
        private StagedHoudiniPlan ComputeFineStages()
        {
            Graph<ScheduledStage> Dependences = new Graph<ScheduledStage>();
              var done = new Dictionary<SCC<string>, ScheduledStage>();

              List<SCC<string>> components = StagesDAG.TopologicalSort().ToList();
              components.Reverse();

              for (int i = 0; i < components.Count(); i++)
              {
            ScheduledStage Stage = new ScheduledStage(i, new HashSet<string>());
            done[components[i]] = Stage;
            foreach (var c in components[i])
            {
              Stage.AddCandidate(c);
            }
            foreach(var s in StagesDAG.Successors(components[i])) {
              Dependences.AddEdge(Stage, done[s]);
            }
              }
              return new StagedHoudiniPlan(Dependences);
        }
        private StagedHoudiniPlan ComputeBalancedStages()
        {
            Graph<ScheduledStage> Dependences = new Graph<ScheduledStage>();
              var done = new Dictionary<SCC<string>, ScheduledStage>();
              done[GetStartNodeOfStagesDAG()] = new ScheduledStage(0, new HashSet<string>());

              int maxStageSize = 200;

              for(int stageId = 1; done.Count() != StagesDAG.Nodes.Count(); stageId++)
              {
            int stageSize = 0;
            ScheduledStage Stage = new ScheduledStage(stageId, new HashSet<string>());
            HashSet<SCC<string>> AddedToThisStage = new HashSet<SCC<string>>();

            foreach (var n in StagesDAG.Nodes.Where(Item => !done.ContainsKey(Item)))
            {
              if(stageSize + n.Count() > maxStageSize) {
            continue;
              }
              if(StagesDAG.Successors(n).Where(Item => !done.ContainsKey(Item)).Count() == 0) {
            foreach (var c in n)
            {
              Stage.AddCandidate(c);
              stageSize++;
            }
            foreach(var s in StagesDAG.Successors(n)) {
              Dependences.AddEdge(Stage, done[s]);
            }
            AddedToThisStage.Add(n);
              }
            }
            foreach(var n in AddedToThisStage) {
              done[n] = Stage;
            }
            if(stageSize == 0) {
              maxStageSize *= 2;
            }
              }
              return new StagedHoudiniPlan(Dependences);
        }