class_docstr: The planner to convert optimized logical to physical operators.
  
  Note that planner is only doing operators conversion. Physical optimization work is
  done by physical optimizer.
class_docstr_tok: ["The","planner","to","convert","optimized","logical","to","physical","operators",".","Note","that","planner","is","only","doing","operators","conversion",".","Physical","optimization","work","is","done","by","physical","optimizer","."]
docstr: Convert logical to physical operators recursively in post-order.
docstr_tok: ["Convert","logical","to","physical","operators","recursively","in","post-order","."]
code: def plan(self, logical_plan: LogicalPlan) -> PhysicalPlan:
      """Convert logical to physical operators recursively in post-order."""
      physical_dag = self._plan(logical_plan.dag)
      return PhysicalPlan(physical_dag, self._physical_op_to_logical_op)
  
imports: from typing import Dict
  from ray.data._internal.execution.interfaces import PhysicalOperator
  from ray.data._internal.execution.operators.union_operator import UnionOperator
  from ray.data._internal.execution.operators.zip_operator import ZipOperator
  from ray.data._internal.logical.interfaces import LogicalOperator, LogicalPlan, PhysicalPlan
  from ray.data._internal.logical.operators.all_to_all_operator import AbstractAllToAll
  from ray.data._internal.logical.operators.from_operators import AbstractFrom
  from ray.data._internal.logical.operators.input_data_operator import InputData
  from ray.data._internal.logical.operators.map_operator import AbstractUDFMap
  from ray.data._internal.logical.operators.n_ary_operator import Union, Zip
  from ray.data._internal.logical.operators.one_to_one_operator import Limit
  from ray.data._internal.logical.operators.read_operator import Read
  from ray.data._internal.logical.operators.write_operator import Write
  from ray.data._internal.planner.plan_all_to_all_op import plan_all_to_all_op
  from ray.data._internal.planner.plan_from_op import plan_from_op
  from ray.data._internal.planner.plan_input_data_op import plan_input_data_op
  from ray.data._internal.planner.plan_limit_op import plan_limit_op
  from ray.data._internal.planner.plan_read_op import plan_read_op
  from ray.data._internal.planner.plan_udf_map_op import plan_udf_map_op
  from ray.data._internal.planner.plan_write_op import plan_write_op
label_desc: Use image node_id 2 for calling the Planner obj's underlying member method code with example usage: obj.plan(logical_plan) and returns: PhysicalPlan