class_docstr: Rule for pushing down the limit operator.
  
  When a limit operator is present, we apply the limit on the
  most upstream operator that supports it. Notably, we move the
  Limit operator downstream from Read op, any other non-OneToOne operator,
  or any operator which could potentially change the number of output rows.
  
  In addition, we also fuse consecutive Limit operators into a single
  Limit operator, i.e. `Limit[n] -> Limit[m]` becomes `Limit[min(n, m)]`.
class_docstr_tok: ["Rule","for","pushing","down","the","limit","operator",".","When","a","limit","operator","is","present",",","we","apply","the","limit","on","the","most","upstream","operator","that","supports","it",".","Notably",",","we","move","the","Limit","operator","downstream","from","Read","op",",","any","other","non-OneToOne","operator",",","or","any","operator","which","could","potentially","change","the","number","of","output","rows",".","In","addition",",","we","also","fuse","consecutive","Limit","operators","into","a","single","Limit","operator",",","i.e",".","`","Limit","[","n","]","-",">","Limit","[","m","]","`","becomes","`","Limit","[","min","(","n",",","m",")","]","`","."]
code: def apply(self, plan: LogicalPlan) -> LogicalPlan:
      optimized_dag = self._apply_limit_pushdown(plan.dag)
      optimized_dag = self._apply_limit_fusion(optimized_dag)
      return LogicalPlan(dag=optimized_dag)
  
file_path: ray/python/ray/data/_internal/logical/rules/limit_pushdown.py
imports: import copy
  from collections import deque
  from typing import Iterable, List
  from ray.data._internal.logical.interfaces import LogicalOperator, LogicalPlan, Rule
  from ray.data._internal.logical.operators.one_to_one_operator import AbstractOneToOne, Limit
  from ray.data._internal.logical.operators.read_operator import Read
label_desc: Use image node_id 1 for calling the LimitPushdownRule obj's underlying member method code with example usage: obj.apply(plan) and returns: LogicalPlan