code: def fuse(
      self,
      chunk_graph,
      chunk_to_colors,
      color_to_chunks,
      chunk_to_bands,
  ):
      fuse_count = 0
      for c, c_color in self._typed_chunks[self.type_DataFrameConcat]:
          if len(color_to_chunks[c_color]) == 1:
              succ_colors = set()
              for succ in chunk_graph.iter_successors(c):
                  succ_color = chunk_to_colors[succ]
                  succ_colors.add(succ_color)
                  if len(succ_colors) > 1:
                      break
              else:
                  if len(succ_colors) == 1:
                      fuse_count += 1
                      fuse_color = next(iter(succ_colors))
                      chunk_to_colors[c] = fuse_color
                      chunk_to_bands[c] = None
                      color_to_chunks.pop(c_color)
                      color_to_chunks[fuse_color].insert(0, c)
      logger.info("Fuse %s subtasks.", fuse_count)
  
imports: import itertools
  import logging
  from collections import deque, defaultdict
  from typing import Dict, List, Tuple, Type, Union
  from ....config import Config
  from ....core import ChunkGraph, ChunkType, enter_mode, DAG
  from ....core.operand import Fetch, VirtualOperand, LogicKeyGenerator, MapReduceOperand, OperandStage, ShuffleProxy, ShuffleFetchType
  from ....lib.ordered_set import OrderedSet
  from ....resource import Resource
  from ....typing import BandType, OperandType
  from ....utils import build_fetch, build_fetch_shuffle, tokenize
  from ...subtask import SubtaskGraph, Subtask
  from ..core import Task, new_task_id, MapReduceInfo
  from .assigner import AbstractGraphAssigner, GraphAssigner
  from .fusion import Coloring
label_desc: Use image node_id 3 for calling the SubtaskFusion obj's underlying member method code with example usage: obj.fuse(chunk_graph, chunk_to_colors, color_to_chunks, chunk_to_bands) without return types