docs: public int nondominated_sorting_add(S indiv) {
  
      int flag = 0;
      int flag1, flag2, flag3;
  
      // count the number of non-domination levels
      int num_ranks = 0;
      ArrayList<Integer> frontSize = new ArrayList<>();
      for (int i = 0; i < populationSize; i++) {
        int rankCount = countRankOnes(i);
        if (rankCount != 0) {
          frontSize.add(rankCount);
          num_ranks++;
        } else {
          break;
        }
      }
  
      ArrayList<Integer> dominateList = new ArrayList<>();  // used to keep the solutions dominated by 'indiv'
      int level = 0;
      for (int i = 0; i < num_ranks; i++) {
        level = i;
        if (flag == 1) {  // 'indiv' is non-dominated with all solutions in the ith non-domination level, then 'indiv' belongs to the ith level
          //indiv.setRank(i - 1);
          indiv.setAttribute(ranking.getAttributeIdentifier(), i - 1);
          return num_ranks;
        } else if (flag == 2) {  // 'indiv' dominates some solutions in the ith level, but is non-dominated with some others, then 'indiv' belongs to the ith level, and move the dominated solutions to the next level
          //indiv.setRank(i - 1);
          indiv.setAttribute(ranking.getAttributeIdentifier(), i - 1);
          int prevRank = i - 1;
  
          // process the solutions belong to 'prevRank'th level and are dominated by 'indiv' ==> move them to 'prevRank+1'th level and find the solutions dominated by them
          int curIdx;
          int newRank = prevRank + 1;
          int curListSize = dominateList.size();
          for (int j = 0; j < curListSize; j++) {
            curIdx = dominateList.get(j);
            rankIdx[prevRank][curIdx] = 0;
            rankIdx[newRank][curIdx] = 1;
            //((DoubleSolution) population.get(curIdx)).setRank(newRank);
            population.get(curIdx).setAttribute(ranking.getAttributeIdentifier(), newRank);
          }
          for (int j = 0; j < populationSize; j++) {
            if (rankIdx[newRank][j] == 1) {
              for (int k = 0; k < curListSize; k++) {
                curIdx = dominateList.get(k);
                if (checkDominance(population.get(curIdx), population.get(j)) == 1) {
                  dominateList.add(j);
                  break;
                }
  
              }
            }
          }
          for (int j = 0; j < curListSize; j++) {
            dominateList.remove(0);
          }
  
          // if there are still some other solutions moved to the next level, check their domination situation in their new level
          prevRank = newRank;
          newRank = newRank + 1;
          curListSize = dominateList.size();
          if (curListSize == 0) {
            return num_ranks;
          } else {
            int allFlag = 0;
            do {
              for (int j = 0; j < curListSize; j++) {
                curIdx = dominateList.get(j);
                rankIdx[prevRank][curIdx] = 0;
                rankIdx[newRank][curIdx] = 1;
                //((DoubleSolution) population.get(curIdx)).setRank(newRank);
                population.get(curIdx).setAttribute(ranking.getAttributeIdentifier(), newRank);
              }
              for (int j = 0; j < populationSize; j++) {
                if (rankIdx[newRank][j] == 1) {
                  for (int k = 0; k < curListSize; k++) {
                    curIdx = dominateList.get(k);
                    if (checkDominance(population.get(curIdx), population.get(j)) == 1) {
                      dominateList.add(j);
                      break;
                    }
                  }
                }
              }
              for (int j = 0; j < curListSize; j++) {
                dominateList.remove(0);
              }
  
              curListSize = dominateList.size();
              if (curListSize != 0) {
                prevRank = newRank;
                newRank = newRank + 1;
                if (frontSize.size() > prevRank && curListSize == frontSize.get(prevRank)) {  // if all solutions in the 'prevRank'th level are dominated by the newly added solution, move them all to the next level
                  allFlag = 1;
                  break;
                }
              }
            } while (curListSize != 0);
  
            if (allFlag == 1) {  // move the solutions after the 'prevRank'th level to their next levels
              int remainSize = num_ranks - prevRank;
              int[][] tempRecord = new int[remainSize][populationSize];
  
              int tempIdx = 0;
              for (int j = 0; j < dominateList.size(); j++) {
                tempRecord[0][tempIdx] = dominateList.get(j);
                tempIdx++;
              }
  
              int k = 1;
              int curRank = prevRank + 1;
              while (curRank < num_ranks) {
                tempIdx = 0;
                for (int j = 0; j < populationSize; j++) {
                  if (rankIdx[curRank][j] == 1) {
                    tempRecord[k][tempIdx] = j;
                    tempIdx++;
                  }
                }
                curRank++;
                k++;
              }
  
              k = 0;
              curRank = prevRank;
              while (curRank < num_ranks) {
                int level_size = frontSize.get(curRank);
  
                int tempRank;
                for (int j = 0; j < level_size; j++) {
                  curIdx = tempRecord[k][j];
                  //tempRank = ((DoubleSolution) population.get(curIdx)).getRank();
                  tempRank = (int) population.get(curIdx).getAttribute(ranking.getAttributeIdentifier());
                  newRank = tempRank + 1;
                  //((DoubleSolution) population.get(curIdx)).setRank(newRank);
                  population.get(curIdx).setAttribute(ranking.getAttributeIdentifier(), newRank);
                  rankIdx[tempRank][curIdx] = 0;
                  rankIdx[newRank][curIdx] = 1;
                }
                curRank++;
                k++;
              }
              num_ranks++;
            }
  
            if (newRank == num_ranks) {
              num_ranks++;
            }
  
            return num_ranks;
          }
        } else if (flag == 3 || flag == 0) {  // if 'indiv' is dominated by some solutions in the ith level, skip it, and term to the next level
          flag1 = flag2 = flag3 = 0;
          for (int j = 0; j < populationSize; j++) {
            if (rankIdx[i][j] == 1) {
              switch (checkDominance(indiv, population.get(j))) {
                case 1: {
                  flag1 = 1;
                  dominateList.add(j);
                  break;
                }
                case 0: {
                  flag2 = 1;
                  break;
                }
                case -1: {
                  flag3 = 1;
                  break;
                }
              }
  
              if (flag3 == 1) {
                flag = 3;
                break;
              } else if (flag1 == 0 && flag2 == 1) {
                flag = 1;
              } else if (flag1 == 1 && flag2 == 1) {
                flag = 2;
              } else if (flag1 == 1 && flag2 == 0) {
                flag = 4;
              } else {
              }
            }
          }
  
        } else {  // (flag == 4) if 'indiv' dominates all solutions in the ith level, solutions in the current level and beyond move their current next levels
          //indiv.setRank(i - 1);
          indiv.setAttribute(ranking.getAttributeIdentifier(), i - 1);
          i = i - 1;
          int remainSize = num_ranks - i;
          int[][] tempRecord = new int[remainSize][populationSize];
  
          int k = 0;
          while (i < num_ranks) {
            int tempIdx = 0;
            for (int j = 0; j < populationSize; j++) {
              if (rankIdx[i][j] == 1) {
                tempRecord[k][tempIdx] = j;
                tempIdx++;
              }
            }
            i++;
            k++;
          }
  
          k = 0;
          //i = indiv.getRank();
          i = (int) indiv.getAttribute(ranking.getAttributeIdentifier());
          while (i < num_ranks) {
            int level_size = frontSize.get(i);
  
            int curIdx;
            int curRank, newRank;
            for (int j = 0; j < level_size; j++) {
              curIdx = tempRecord[k][j];
              //curRank = ((DoubleSolution) population.get(curIdx)).getRank();
              curRank = (int) population.get(curIdx).getAttribute(ranking.getAttributeIdentifier());
              newRank = curRank + 1;
              //((DoubleSolution) population.get(curIdx)).setRank(newRank);
              population.get(curIdx).setAttribute(ranking.getAttributeIdentifier(), newRank);
  
              rankIdx[curRank][curIdx] = 0;
              rankIdx[newRank][curIdx] = 1;
            }
            i++;
            k++;
          }
          num_ranks++;
  
          return num_ranks;
        }
      }
      // if flag is still 3 after the for-loop, it means that 'indiv' is in the current last level
      switch (flag) {
        case 1:
          //indiv.setRank(level);
          indiv.setAttribute(ranking.getAttributeIdentifier(), level);
          break;
        case 2:
          //indiv.setRank(level);
          indiv.setAttribute(ranking.getAttributeIdentifier(), level);
          int curIdx;
          int tempSize = dominateList.size();
          for (int i = 0; i < tempSize; i++) {
            curIdx = dominateList.get(i);
            //((DoubleSolution) population.get(curIdx)).setRank(level + 1);
            population.get(curIdx).setAttribute(ranking.getAttributeIdentifier(), level + 1);
  
            rankIdx[level][curIdx] = 0;
            rankIdx[level + 1][curIdx] = 1;
          }
          num_ranks++;
          break;
        case 3:
          //indiv.setRank(level + 1);
          indiv.setAttribute(ranking.getAttributeIdentifier(), level + 1);
          num_ranks++;
          break;
        default:
          //indiv.setRank(level);
          indiv.setAttribute(ranking.getAttributeIdentifier(), level);
          for (int i = 0; i < populationSize; i++) {
            if (rankIdx[level][i] == 1) {
              //((DoubleSolution) population.get(i)).setRank(level + 1);
  
              population.get(i).setAttribute(ranking.getAttributeIdentifier(), level + 1);
              rankIdx[level][i] = 0;
              rankIdx[level + 1][i] = 1;
            }
          }
          num_ranks++;
          break;
      }
  
      return num_ranks;
    }