/** The main function */
  @Override
  public void run() {
    if (mDepth > 0) {
      /** Specially for Montage workflow since it has duplicate edges */
      if (Parameters.getReduceMethod().equals("montage")) {
        removeDuplicateMontage();
      }
      Task root = super.addRoot();
      Task node = root;
      ArrayList taskList = new ArrayList<Task>();
      Stack stack = new Stack<Task>();
      stack.push(root);
      while (!stack.empty()) {
        node = (Task) stack.pop();
        if (!getCheck(node.getCloudletId())) {
          setCheck(node.getCloudletId());

          int pNum = node.getParentList().size();
          int cNum = node.getChildList().size();

          for (Iterator it = node.getChildList().iterator(); it.hasNext(); ) {
            Task cNode = (Task) it.next();
            stack.push(cNode);
          }

          if (pNum == 0) {
            // root skip it
          } else if (pNum > 1) {
            if (cNum > 1 || cNum == 0) {

              if (!taskList.isEmpty()) {
                addTasks2Job(taskList);
                taskList.clear();
              }
              taskList.add(node);
              addTasks2Job(taskList);
              taskList.clear();

            } else { // cNum==1
              // cut and add new

              if (!taskList.isEmpty()) {
                addTasks2Job(taskList);
                taskList.clear();
              }
              if (!taskList.contains(node)) {
                taskList.add(node);
              }
            }
          } else { // pNum == 1
            if (cNum > 1 || cNum == 0) {
              // This is different to the case of pNum > 1
              taskList.add(node);
              addTasks2Job(taskList);
              taskList.clear();
            } else {
              // This is also different to the case of pNum > 1
              if (!taskList.contains(node)) {
                taskList.add(node);
              }
            }
          }

        } else {
          if (!taskList.isEmpty()) {
            addTasks2Job(taskList);
            taskList.clear();
          }
        }
      }
    }
    mHasChecked.clear();
    super.clean();

    updateDependencies();
    addClustDelay();
  }
  /** Remove duplicate just for Montage Set in reducer.method */
  public void removeDuplicateMontage() {

    List jobList = this.getTaskList();
    for (int i = 0; i < jobList.size(); i++) {
      Task node = (Task) jobList.get(i);
      String name = node.getType();
      if (name.equals("mBackground")) {
        // remove all of its parents of mProjectPP

        for (int j = 0; j < node.getParentList().size(); j++) {

          Task parent = (Task) node.getParentList().get(j);
          if (parent.getType().equals("mProjectPP")) {
            j--;
            node.getParentList().remove(parent);
            parent.getChildList().remove(node);
          }
        }

      } else if (name.equals("mAdd")) {
        for (int j = 0; j < node.getParentList().size(); j++) {

          Task parent = (Task) node.getParentList().get(j);
          String pName = parent.getType();
          if (pName.equals("mBackground") || pName.equals("mShrink")) {
            j--;
            node.getParentList().remove(parent);
            parent.getChildList().remove(node);
          }
        }
      }
    }
  }