class_docstr: Assigns weights to each type in the column type tree and attempts to traverse it using a weight percentage threshold.
class_docstr_tok: ["Assigns","weights","to","each","type","in","the","column","type","tree","and","attempts","to","traverse","it","using","a","weight","percentage","threshold","."]
docstr: Find the appropriate type for a column by traversing through the type tree.
  
  It traverses the tree by giving weights to all nodes and greedily finding the path with the most
  weight until it either finds a leaf or there is a "weight bifurcation" in the path with respect
  to the provided `weight_percent_threshold`.
docstr_tok: ["Find","the","appropriate","type","for","a","column","by","traversing","through","the","type","tree",".","It","traverses","the","tree","by","giving","weights","to","all","nodes","and","greedily","finding","the","path","with","the","most","weight","until","it","either","finds","a","leaf","or","there","is","a","``","weight","bifurcation","''","in","the","path","with","respect","to","the","provided","`","weight_percent_threshold","`","."]
code: def solve_column(
      self, column: SqlColumn, signals: List[InferenceSignal]
  ) -> InferenceResult:
      """Find the appropriate type for a column by traversing through the type tree.
  
      It traverses the tree by giving weights to all nodes and greedily finding the path with the most
      weight until it either finds a leaf or there is a "weight bifurcation" in the path with respect
      to the provided `weight_percent_threshold`.
      """
      if len(signals) == 0:
          return InferenceResult(
              column=column,
              type_node=InferenceSignalType.UNKNOWN,
              reasons=[],
              problems=[
                  "No signals were extracted for this column",
                  "Inference solver could not determine if column was an entity, a dimension, or a measure",
              ],
          )
  
      reasons_by_type: Dict[
          InferenceSignalNode, List[str]
      ] = defaultdict(list)
      for signal in signals:
          reasons_by_type[signal.type_node].append(
              f"{signal.reason} ({signal.type_node.name})"
          )
  
      node_weights = self._get_cumulative_weights(signals)
  
      reasons: List[str] = []
      problems: List[str] = []
      node = InferenceSignalType.UNKNOWN
      while len(node.children) > 0:
          children_weight_total = sum(
              node_weights[child] for child in node.children
          )
  
          if children_weight_total == 0:
              break
  
          next_node = None
          for child in node.children:
              if (
                  node_weights[child] / children_weight_total
                  >= self._weight_percent_threshold
              ):
                  next_node = child
                  reasons += reasons_by_type[child]
                  break
  
          if next_node is None:
              if len(node.children) > 0:  # there was confusion
                  children_weight_strings = [
                      f"{child.name} (weight {node_weights[child]})"
                      for child in node.children
                      if node_weights[child] != 0
                  ]
                  child_str = " / ".join(children_weight_strings)
                  problems.append(
                      f"Solver is confused between {child_str}"
                  )
              break
  
          node = next_node
  
      if node == InferenceSignalType.UNKNOWN:
          problems.append(
              "Inference solver could not determine if column was an entity, a dimension, or a measure"
          )
  
      return InferenceResult(
          column=column,
          type_node=node,
          reasons=reasons,
          problems=problems,
      )
  
file_path: metricflow/metricflow/inference/solver/weighted_tree.py
imports: from __future__ import annotations
  from collections import defaultdict
  from typing import Callable, Dict, List, Optional
  from metricflow.dataflow.sql_column import SqlColumn
  from metricflow.inference.models import InferenceResult, InferenceSignal, InferenceSignalConfidence, InferenceSignalNode, InferenceSignalType
  from metricflow.inference.solver.base import InferenceSolver
label_desc: Use image node_id 5 for calling the WeightedTypeTreeInferenceSolver obj's underlying member method code with example usage: obj.solve_column(column, signals) and returns: InferenceResult, InferenceResult