class_docstr: Reduces the number of scans (ReadSqlSourceNodes) in a dataflow plan.
  
  This attempts to reduce the number of scans by combining the parent nodes of CombineAggregatedOutputsNode via the
  ComputeMetricsBranchCombiner.
  
  A plan with a structure similar to
      ...
      <CombineAggregatedOutputsNode>
          <ComputeMetricsNode metrics="[metric0]">
              <AggregateMeasuresNode>
              ...
              </AggregateMeasuresNode>
          </ComputeMetricsNode>
          <ComputeMetricsNode metrics="[metrics1]">
              <AggregateMeasuresNode>
              ...
              </AggregateMeasuresNode>
          </ComputeMetricsNode>
          <ComputeMetricsNode metric="[metrics2]">
              <AggregateMeasuresNode>
              ...
              </AggregateMeasuresNode>
          </ComputeMetricsNode>
      </CombineAggregatedOutputsNode>
      ...
  will be converted to
      ...
      <CombineAggregatedOutputsNode>
          <ComputeMetricsNode metrics="[metric0, metric1]">
              <AggregateMeasuresNode>
              ...
              </AggregateMeasuresNode>
          </ComputeMetricsNode>
          <ComputeMetricsNode metrics="[metric2]">
              <AggregateMeasuresNode>
              ...
              </AggregateMeasuresNode>
          </ComputeMetricsNode>
      </CombineAggregatedOutputsNode>
      ...
  when possible.
  
  In cases where all ComputeMetricsNodes can be combined into a single one, the CombineAggregatedOutputsNode may be removed as
  well.
  
  This traverses the dataflow plan using DFS. When visiting a node (current_node), it first runs the optimization
  process on the parent branches, then tries to create a more optimal version of the current_node with those optimized
  parents.
class_docstr_tok: ["Reduces","the","number","of","scans","(","ReadSqlSourceNodes",")","in","a","dataflow","plan",".","This","attempts","to","reduce","the","number","of","scans","by","combining","the","parent","nodes","of","CombineAggregatedOutputsNode","via","the","ComputeMetricsBranchCombiner",".","A","plan","with","a","structure","similar","to","...","<","CombineAggregatedOutputsNode",">","<","ComputeMetricsNode","metrics=","''","[","metric0","]","''",">","<","AggregateMeasuresNode",">","...","<","\/AggregateMeasuresNode",">","<","\/ComputeMetricsNode",">","<","ComputeMetricsNode","metrics=","''","[","metrics1","]","''",">","<","AggregateMeasuresNode",">","...","<","\/AggregateMeasuresNode",">","<","\/ComputeMetricsNode",">","<","ComputeMetricsNode","metric=","''","[","metrics2","]","''",">","<","AggregateMeasuresNode",">","...","<","\/AggregateMeasuresNode",">","<","\/ComputeMetricsNode",">","<","\/CombineAggregatedOutputsNode",">","...","will","be","converted","to","...","<","CombineAggregatedOutputsNode",">","<","ComputeMetricsNode","metrics=","''","[","metric0",",","metric1","]","''",">","<","AggregateMeasuresNode",">","...","<","\/AggregateMeasuresNode",">","<","\/ComputeMetricsNode",">","<","ComputeMetricsNode","metrics=","''","[","metric2","]","''",">","<","AggregateMeasuresNode",">","...","<","\/AggregateMeasuresNode",">","<","\/ComputeMetricsNode",">","<","\/CombineAggregatedOutputsNode",">","...","when","possible",".","In","cases","where","all","ComputeMetricsNodes","can","be","combined","into","a","single","one",",","the","CombineAggregatedOutputsNode","may","be","removed","as","well",".","This","traverses","the","dataflow","plan","using","DFS",".","When","visiting","a","node","(","current_node",")",",","it","first","runs","the","optimization","process","on","the","parent","branches",",","then","tries","to","create","a","more","optimal","version","of","the","current_node","with","those","optimized","parents","."]
code: def __init__(self) -> None:  # noqa: D
      self._log_level = logging.DEBUG
  
imports: from __future__ import annotations
  import logging
  from dataclasses import dataclass
  from typing import List, Optional, Sequence
  from metricflow.dag.id_generation import OPTIMIZED_DATAFLOW_PLAN_PREFIX, IdGeneratorRegistry
  from metricflow.dataflow.dataflow_plan import AddGeneratedUuidColumnNode, AggregateMeasuresNode, BaseOutput, CombineAggregatedOutputsNode, ComputeMetricsNode, ConstrainTimeRangeNode, DataflowPlan, DataflowPlanNode, DataflowPlanNodeVisitor, FilterElementsNode, JoinConversionEventsNode, JoinOverTimeRangeNode, JoinToBaseOutputNode, JoinToTimeSpineNode, MetricTimeDimensionTransformNode, MinMaxNode, OrderByLimitNode, ReadSqlSourceNode, SemiAdditiveJoinNode, SinkOutput, WhereConstraintNode, WriteToResultDataframeNode, WriteToResultTableNode
  from metricflow.dataflow.dataflow_plan_to_text import dataflow_dag_as_text
  from metricflow.dataflow.optimizer.dataflow_plan_optimizer import DataflowPlanOptimizer
  from metricflow.dataflow.optimizer.source_scan.cm_branch_combiner import ComputeMetricsBranchCombiner, ComputeMetricsBranchCombinerResult
label_desc: Use image node_id 1 to create a new SourceScanOptimizer object from inherited base classes: DataflowPlanNodeVisitor, DataflowPlanOptimizer with example: obj = SourceScanOptimizer()