class_docstr: apply a transformation or implementation rule
class_docstr_tok: ["apply","a","transformation","or","implementation","rule"]
code: def execute(self):
      # return if already explored
      if self.root_expr.is_rule_explored(self.rule.rule_type):
          return
      binder = Binder(
          self.root_expr, self.rule.pattern, self.optimizer_context.memo
      )
      for match in iter(binder):
          if not self.rule.check(match, self.optimizer_context):
              continue
          after = self.rule.apply(match, self.optimizer_context)
          for plan in after:
              new_expr = self.optimizer_context.add_opr_to_group(
                  plan, self.root_expr.group_id
              )
  
              if new_expr.is_logical():
                  # optimize expressions
                  self.optimizer_context.task_stack.push(
                      OptimizeExpression(
                          new_expr, self.optimizer_context, self.explore
                      )
                  )
              else:
                  # cost the physical expressions
                  self.optimizer_context.task_stack.push(
                      OptimizeInputs(new_expr, self.optimizer_context)
                  )
  
      self.root_expr.mark_rule_explored(self.rule.rule_type)
  
imports: from __future__ import annotations
  from abc import abstractmethod
  from enum import IntEnum, auto
  from typing import TYPE_CHECKING, List
  from evadb.optimizer.binder import Binder
  from evadb.optimizer.group import Group
  from evadb.optimizer.group_expression import GroupExpression
  from evadb.optimizer.property import PropertyType
  from evadb.optimizer.rules.rules_base import Rule
  from evadb.utils.logging_manager import logger
label_desc: Use image node_id 2 for calling the ApplyRule obj's underlying member method code with example usage: obj.execute() without return types