class_docstr: Helper class to fuse computation of multiple aggregations together.
  
  Used internally in :class:`~torch_geometric.nn.aggr.MultiAggregation` to
  speed-up computation.
  Currently, the following optimizations are performed:
  
  * :class:`MeanAggregation` will share the output with
    :class:`SumAggregation` in case it is present as well.
  
  * :class:`VarAggregation` will share the output with either
    :class:`MeanAggregation` or :class:`SumAggregation` in case one of them
    is present as well.
  
  * :class:`StdAggregation` will share the output with either
    :class:`VarAggregation`, :class:`MeanAggregation` or
    :class:`SumAggregation` in case one of them is present as well.
  
  In addition, temporary values such as the count per group index are shared
  as well.
  
  Benchmarking results on PyTorch 1.12 (summed over 1000 runs):
  
  +------------------------------+---------+---------+
  | Aggregators                  | Vanilla | Fusion  |
  +==============================+=========+=========+
  | :obj:`[sum, mean]`           | 0.3325s | 0.1996s |
  +------------------------------+---------+---------+
  | :obj:`[sum, mean, min, max]` | 0.7139s | 0.5037s |
  +------------------------------+---------+---------+
  | :obj:`[sum, mean, var]`      | 0.6849s | 0.3871s |
  +------------------------------+---------+---------+
  | :obj:`[sum, mean, var, std]` | 1.0955s | 0.3973s |
  +------------------------------+---------+---------+
  
  Args:
      aggrs (list): The list of aggregation schemes to use.
class_docstr_tok: ["Helper","class","to","fuse","computation","of","multiple","aggregations","together",".","Used","internally","in",":","class",":","`","~torch_geometric.nn.aggr.MultiAggregation","`","to","speed-up","computation",".","Currently",",","the","following","optimizations","are","performed",":","*",":","class",":","`","MeanAggregation","`","will","share","the","output","with",":","class",":","`","SumAggregation","`","in","case","it","is","present","as","well",".","*",":","class",":","`","VarAggregation","`","will","share","the","output","with","either",":","class",":","`","MeanAggregation","`","or",":","class",":","`","SumAggregation","`","in","case","one","of","them","is","present","as","well",".","*",":","class",":","`","StdAggregation","`","will","share","the","output","with","either",":","class",":","`","VarAggregation","`",",",":","class",":","`","MeanAggregation","`","or",":","class",":","`","SumAggregation","`","in","case","one","of","them","is","present","as","well",".","In","addition",",","temporary","values","such","as","the","count","per","group","index","are","shared","as","well",".","Benchmarking","results","on","PyTorch","1.12","(","summed","over","1000","runs",")",":","+","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","+","--","--","--","--","-+","--","--","--","--","-+","|","Aggregators","|","Vanilla","|","Fusion","|","+==============================+=========+=========+","|",":","obj",":","`","[","sum",",","mean","]","`","|","0.3325s","|","0.1996s","|","+","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","+","--","--","--","--","-+","--","--","--","--","-+","|",":","obj",":","`","[","sum",",","mean",",","min",",","max","]","`","|","0.7139s","|","0.5037s","|","+","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","+","--","--","--","--","-+","--","--","--","--","-+","|",":","obj",":","`","[","sum",",","mean",",","var","]","`","|","0.6849s","|","0.3871s","|","+","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","+","--","--","--","--","-+","--","--","--","--","-+","|",":","obj",":","`","[","sum",",","mean",",","var",",","std","]","`","|","1.0955s","|","0.3973s","|","+","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","+","--","--","--","--","-+","--","--","--","--","-+","Args",":","aggrs","(","list",")",":","The","list","of","aggregation","schemes","to","use","."]
code: def __init__(self, aggrs: List[Union[Aggregation, str]]):
      super().__init__()
  
      if not isinstance(aggrs, (list, tuple)):
          raise ValueError(
              f"'aggrs' of '{self.__class__.__name__}' should "
              f"be a list or tuple (got '{type(aggrs)}')."
          )
  
      if len(aggrs) == 0:
          raise ValueError(
              f"'aggrs' of '{self.__class__.__name__}' should "
              f"not be empty."
          )
  
      aggrs = [aggregation_resolver(aggr) for aggr in aggrs]
      aggr_classes = [aggr.__class__ for aggr in aggrs]
      self.aggr_names = [cls.__name__ for cls in aggr_classes]
      self.aggr_index: Dict[str, int] = {
          name: i for i, name in enumerate(self.aggr_names)
      }
  
      for cls in aggr_classes:
          if cls not in self.FUSABLE_AGGRS:
              raise ValueError(
                  f"Received aggregation '{cls.__name__}' in "
                  f"'{self.__class__.__name__}' which is not "
                  f"fusable"
              )
  
      self.semi_grad = False
      for aggr in aggrs:
          if hasattr(aggr, "semi_grad"):
              self.semi_grad = self.semi_grad or aggr.semi_grad
  
      # Check whether we need to compute degree information:
      self.need_degree = False
      for cls in aggr_classes:
          if cls in self.DEGREE_BASED_AGGRS:
              self.need_degree = True
  
      # Determine which reduction to use for each aggregator:
      # An entry of `None` means that this operator re-uses intermediate
      # outputs from other aggregators.
      reduce_ops: List[Optional[str]] = []
      # Determine which `(Aggregator, index)` to use as intermediate output:
      lookup_ops: List[Optional[Tuple[str, int]]] = []
  
      for name in self.aggr_names:
          if name == "MeanAggregation":
              # Directly use output of `SumAggregation`:
              if "SumAggregation" in self.aggr_index:
                  reduce_ops.append(None)
                  lookup_ops.append(
                      (
                          "SumAggregation",
                          self.aggr_index["SumAggregation"],
                      )
                  )
              else:
                  reduce_ops.append(self.REDUCE[name])
                  lookup_ops.append(None)
  
          elif name == "VarAggregation":
              if "MeanAggregation" in self.aggr_index:
                  reduce_ops.append(self.REDUCE[name])
                  lookup_ops.append(
                      (
                          "MeanAggregation",
                          self.aggr_index["MeanAggregation"],
                      )
                  )
              elif "SumAggregation" in self.aggr_index:
                  reduce_ops.append(self.REDUCE[name])
                  lookup_ops.append(
                      (
                          "SumAggregation",
                          self.aggr_index["SumAggregation"],
                      )
                  )
              else:
                  reduce_ops.append(self.REDUCE[name])
                  lookup_ops.append(None)
  
          elif name == "StdAggregation":
              # Directly use output of `VarAggregation`:
              if "VarAggregation" in self.aggr_index:
                  reduce_ops.append(None)
                  lookup_ops.append(
                      (
                          "VarAggregation",
                          self.aggr_index["VarAggregation"],
                      )
                  )
              elif "MeanAggregation" in self.aggr_index:
                  reduce_ops.append(self.REDUCE[name])
                  lookup_ops.append(
                      (
                          "MeanAggregation",
                          self.aggr_index["MeanAggregation"],
                      )
                  )
              elif "SumAggregation" in self.aggr_index:
                  reduce_ops.append(self.REDUCE[name])
                  lookup_ops.append(
                      (
                          "SumAggregation",
                          self.aggr_index["SumAggregation"],
                      )
                  )
              else:
                  reduce_ops.append(self.REDUCE[name])
                  lookup_ops.append(None)
  
          else:
              reduce_ops.append(self.REDUCE[name])
              lookup_ops.append(None)
  
      self.reduce_ops: List[Optional[str]] = reduce_ops
      self.lookup_ops: List[Optional[Tuple[str, int]]] = lookup_ops
  
file_path: pytorch_geometric/torch_geometric/nn/aggr/fused.py
imports: import math
  from typing import Dict, List, Optional, Tuple, Union
  from torch import Tensor
  from torch_geometric.nn.aggr.base import Aggregation
  from torch_geometric.nn.aggr.basic import MaxAggregation, MeanAggregation, MinAggregation, MulAggregation, StdAggregation, SumAggregation, VarAggregation
  from torch_geometric.nn.resolver import aggregation_resolver
  from torch_geometric.utils import scatter
label_desc: Use image node_id 1 to create a new FusedAggregation object from inherited base classes: Aggregation with example: obj = FusedAggregation(aggrs)