Integer lowDegreeNodeId = tuple.getMiddle();
        
        //first add all the tuple nodes with the higher degree node in the center, no redundancy
        if(!traveledNodesId.contains(highDegreeNodeId)){
          traveledNodesId.add(highDegreeNodeId);
          DNVNode middlenode = graph.getNode(level, highDegreeNodeId);
          //List<DNVNode> neighbors = middlenode.getNeighbors();
          
          //get all the neighbors of the higher degree node which haven't been traveled
          ArrayList<DNVNode> neighbors = new ArrayList<DNVNode>();
          for(DNVEdge edge : middlenode.getFromEdges()){
            if(!traveledNodesId.contains(edge.getToId())){
              neighbors.add(graph.getNode(level, edge.getToId()));
            }
          }
          for(DNVEdge edge : middlenode.getToEdges()){
            if(!traveledNodesId.contains(edge.getFromId())){
              neighbors.add(graph.getNode(level, edge.getFromId()));
            }
          }
          
          for(int i = 0; i < neighbors.size(); i++){
            for(int j = i + 1; j < neighbors.size(); j++){
              Integer degree1 = neighbors.get(i).getConnectivity();
              Integer degree2 = neighbors.get(j).getConnectivity();              
              Integer leftNodeId, rightNodeId;
              DNVNode leftNode, rightNode;
              DNVEdge leftEdge, rightEdge, middleEdge;
              Tuple<Integer, Integer, Integer> degreeTuple; 
              //for each node tuple, the left node degree should be no smaller than the right one
              if(degree1 >= degree2){
                leftNode = neighbors.get(i);
                rightNode = neighbors.get(j);              
                degreeTuple = new Tuple<Integer, Integer, Integer>(degree1, highDegree,degree2);
              }else{
                leftNode = neighbors.get(j);
                rightNode = neighbors.get(i);
                degreeTuple = new Tuple<Integer, Integer, Integer>(degree2, highDegree,degree1);
              }
              leftNodeId = leftNode.getId();
              rightNodeId = rightNode.getId();
              leftEdge = middlenode.getEdgeToNeighbor(leftNodeId);
              rightEdge = middlenode.getEdgeToNeighbor(rightNodeId);
              
              if(!degreeOccurTableDK3.containsKey(degreeTuple)){
                degreeOccurTableDK3.put(degreeTuple, 0);  
                degreeUniqueEdgeTableDK3.put(degreeTuple, new HashSet<DNVEdge>());
                degreeUniqueNodeTableDK3.put(degreeTuple, new HashSet<DNVNode>());
              }          
              degreeOccurTableDK3.put(degreeTuple, degreeOccurTableDK3.get(degreeTuple) + 1);
              degreeUniqueEdgeTableDK3.get(degreeTuple).add(leftEdge);
              degreeUniqueEdgeTableDK3.get(degreeTuple).add(rightEdge);
              degreeUniqueNodeTableDK3.get(degreeTuple).add(middlenode);
              degreeUniqueNodeTableDK3.get(degreeTuple).add(leftNode);
              degreeUniqueNodeTableDK3.get(degreeTuple).add(rightNode);
              
              if(leftNode.getNeighbors().contains(rightNode) || rightNode.getNeighbors().contains(leftNode)){
                middleEdge = leftNode.getEdgeToNeighbor(rightNodeId);
                Triangle triangle = new Triangle(leftNode, middlenode, rightNode, leftEdge, middleEdge, rightEdge);
                triangles.add(triangle);
                degreeUniqueEdgeTableDK3.get(degreeTuple).add(middleEdge);
                triangleCnt++;
              }else{
                Line line = new Line(leftNode, middlenode, rightNode, leftEdge, rightEdge);
                lines.add(line);
                lineCnt++;
              }
              cnt++;
            }
          }
        }
        
        if(traveledNodesId.contains(lowDegreeNodeId)){
          continue;
        }
        //next get all the tuple nodes with the lower degree node in the center and the higher degree node at one end
        DNVNode middlenode = graph.getNode(level, lowDegreeNodeId);
        DNVNode leftNode = graph.getNode(level, highDegreeNodeId);
        DNVEdge leftEdge = tuple.getRight();
        DNVEdge rightEdge, middleEdge;
        //get all the neighbors of the lower degree node which haven't been traveled
        ArrayList<DNVNode> neighbors = new ArrayList<DNVNode>();
        for(DNVEdge edge : middlenode.getFromEdges()){
          if(!traveledNodesId.contains(edge.getToId())){
            neighbors.add(graph.getNode(level, edge.getToId()));
          }
        }
        for(DNVEdge edge : middlenode.getToEdges()){
          if(!traveledNodesId.contains(edge.getFromId())){
            neighbors.add(graph.getNode(level, edge.getFromId()));
          }
        }
        for(DNVNode neighbor : neighbors){
          Integer neighborId = neighbor.getId();
          Integer neighborDegree = neighbor.getConnectivity();
          rightEdge = middlenode.getEdgeToNeighbor(neighborId);
          Tuple<Integer, Integer, Integer> degreeTuple = new Tuple<Integer, Integer, Integer>(highDegree, lowDegree, neighborDegree);
          if(!degreeOccurTableDK3.containsKey(degreeTuple)){
            //degreeEdgeTableDK3.put(degreeTuple, new ArrayList<Pair<DNVEdge, DNVEdge>>());
            degreeOccurTableDK3.put(degreeTuple, 0);  
            degreeUniqueEdgeTableDK3.put(degreeTuple, new HashSet<DNVEdge>());
            degreeUniqueNodeTableDK3.put(degreeTuple, new HashSet<DNVNode>());
          }
          //degreeEdgeTableDK3.get(degreeTuple).add(new Pair<DNVEdge,DNVEdge>(tuple.getRight(),middlenode.getEdgeToNeighbor(neighborId)));
          degreeOccurTableDK3.put(degreeTuple, degreeOccurTableDK3.get(degreeTuple) + 1);
          degreeUniqueEdgeTableDK3.get(degreeTuple).add(leftEdge);
          degreeUniqueEdgeTableDK3.get(degreeTuple).add(rightEdge);
          degreeUniqueNodeTableDK3.get(degreeTuple).add(middlenode);
          degreeUniqueNodeTableDK3.get(degreeTuple).add(leftNode);
          degreeUniqueNodeTableDK3.get(degreeTuple).add(neighbor);
          
          
          if(leftNode.getNeighbors().contains(neighbor) || neighbor.getNeighbors().contains(leftNode)){
            middleEdge = leftNode.getEdgeToNeighbor(neighborId);
            Triangle triangle = new Triangle(leftNode, middlenode, neighbor, leftEdge, middleEdge, rightEdge);
            triangles.add(triangle);
            degreeUniqueEdgeTableDK3.get(degreeTuple).add(middleEdge);
            triangleCnt++;
          }else{