class_docstr: A class that models and constructs operations in a graph.
  
  A `Op` instance has several responsibilities:
  
  * construct `Apply` nodes via :meth:`Op.make_node` method,
  * perform the numeric calculation of the modeled operation via the
    :meth:`Op.perform` method,
  * and (optionally) build the gradient-calculating sub-graphs via the
    :meth:`Op.grad` method.
  
  To see how `Op`, `Type`, `Variable`, and `Apply` fit together see the
  page on :doc:`graph`.
  
  For more details regarding how these methods should behave: see the `Op
  Contract` in the sphinx docs (advanced tutorial on `Op` making).
class_docstr_tok: ["A","class","that","models","and","constructs","operations","in","a","graph",".","A","`","Op","`","instance","has","several","responsibilities",":","*","construct","`","Apply","`","nodes","via",":","meth",":","`","Op.make_node","`","method",",","*","perform","the","numeric","calculation","of","the","modeled","operation","via","the",":","meth",":","`","Op.perform","`","method",",","*","and","(","optionally",")","build","the","gradient-calculating","sub-graphs","via","the",":","meth",":","`","Op.grad","`","method",".","To","see","how","`","Op","`",",","`","Type","`",",","`","Variable","`",",","and","`","Apply","`","fit","together","see","the","page","on",":","doc",":","`","graph","`",".","For","more","details","regarding","how","these","methods","should","behave",":","see","the","`","Op","Contract","`","in","the","sphinx","docs","(","advanced","tutorial","on","`","Op","`","making",")","."]
docstr: Create a thunk.
  
  This function must return a thunk, that is a zero-arguments
  function that encapsulates the computation to be performed
  by this op on the arguments of the node.
  
  Parameters
  ----------
  node
      Something previously returned by :meth:`Op.make_node`.
  storage_map
      A ``dict`` mapping `Variable`\s to single-element lists where a
      computed value for each `Variable` may be found.
  compute_map
      A ``dict`` mapping `Variable`\s to single-element lists where a
      boolean value can be found. The boolean indicates whether the
      `Variable`'s `storage_map` container contains a valid value
      (i.e. ``True``) or whether it has not been computed yet
      (i.e. ``False``).
  no_recycling
      List of `Variable`\s for which it is forbidden to reuse memory
      allocated by a previous call.
  impl : str
      Description for the type of node created (e.g. ``"c"``, ``"py"``,
      etc.)
  
  Notes
  -----
  If the thunk consults the `storage_map` on every call, it is safe
  for it to ignore the `no_recycling` argument, because elements of the
  `no_recycling` list will have a value of ``None`` in the `storage_map`.
  If the thunk can potentially cache return values (like `CLinker` does),
  then it must not do so for variables in the `no_recycling` list.
  
  :meth:`Op.prepare_node` is always called. If it tries ``'c'`` and it
  fails, then it tries ``'py'``, and :meth:`Op.prepare_node` will be
  called twice.
docstr_tok: ["Create","a","thunk",".","This","function","must","return","a","thunk",",","that","is","a","zero-arguments","function","that","encapsulates","the","computation","to","be","performed","by","this","op","on","the","arguments","of","the","node",".","Parameters","--","--","--","--","--","node","Something","previously","returned","by",":","meth",":","`","Op.make_node","`",".","storage_map","A","``","dict","``","mapping","`","Variable","`","\\s","to","single-element","lists","where","a","computed","value","for","each","`","Variable","`","may","be","found",".","compute_map","A","``","dict","``","mapping","`","Variable","`","\\s","to","single-element","lists","where","a","boolean","value","can","be","found",".","The","boolean","indicates","whether","the","`","Variable","`","'s","`","storage_map","`","container","contains","a","valid","value","(","i.e",".","``","True","``",")","or","whether","it","has","not","been","computed","yet","(","i.e",".","``","False","``",")",".","no_recycling","List","of","`","Variable","`","\\s","for","which","it","is","forbidden","to","reuse","memory","allocated","by","a","previous","call",".","impl",":","str","Description","for","the","type","of","node","created","(","e.g",".","``","``","c","''","``",",","``","``","py","''","``",",","etc",".",")","Notes","--","--","-","If","the","thunk","consults","the","`","storage_map","`","on","every","call",",","it","is","safe","for","it","to","ignore","the","`","no_recycling","`","argument",",","because","elements","of","the","`","no_recycling","`","list","will","have","a","value","of","``","None","``","in","the","`","storage_map","`",".","If","the","thunk","can","potentially","cache","return","values","(","like","`","CLinker","`","does",")",",","then","it","must","not","do","so","for","variables","in","the","`","no_recycling","`","list",".",":","meth",":","`","Op.prepare_node","`","is","always","called",".","If","it","tries","``","'","c","'","``","and","it","fails",",","then","it","tries","``","'py","'","``",",","and",":","meth",":","`","Op.prepare_node","`","will","be","called","twice","."]
code: def make_thunk(
      self,
      node: Apply,
      storage_map: StorageMapType,
      compute_map: ComputeMapType,
      no_recycling: list[Variable],
      impl: Optional[str] = None,
  ) -> ThunkType:
      r"""Create a thunk.
  
      This function must return a thunk, that is a zero-arguments
      function that encapsulates the computation to be performed
      by this op on the arguments of the node.
  
      Parameters
      ----------
      node
          Something previously returned by :meth:`Op.make_node`.
      storage_map
          A ``dict`` mapping `Variable`\s to single-element lists where a
          computed value for each `Variable` may be found.
      compute_map
          A ``dict`` mapping `Variable`\s to single-element lists where a
          boolean value can be found. The boolean indicates whether the
          `Variable`'s `storage_map` container contains a valid value
          (i.e. ``True``) or whether it has not been computed yet
          (i.e. ``False``).
      no_recycling
          List of `Variable`\s for which it is forbidden to reuse memory
          allocated by a previous call.
      impl : str
          Description for the type of node created (e.g. ``"c"``, ``"py"``,
          etc.)
  
      Notes
      -----
      If the thunk consults the `storage_map` on every call, it is safe
      for it to ignore the `no_recycling` argument, because elements of the
      `no_recycling` list will have a value of ``None`` in the `storage_map`.
      If the thunk can potentially cache return values (like `CLinker` does),
      then it must not do so for variables in the `no_recycling` list.
  
      :meth:`Op.prepare_node` is always called. If it tries ``'c'`` and it
      fails, then it tries ``'py'``, and :meth:`Op.prepare_node` will be
      called twice.
      """
      self.prepare_node(
          node,
          storage_map=storage_map,
          compute_map=compute_map,
          impl="py",
      )
      return self.make_py_thunk(
          node, storage_map, compute_map, no_recycling
      )
  
imports: import copy
  import sys
  import warnings
  from abc import ABC, abstractmethod
  from collections.abc import Sequence
  from typing import TYPE_CHECKING, Any, Callable, Optional, Protocol, TypeVar, Union, cast
  import pytensor
  from pytensor.configdefaults import config
  from pytensor.graph.basic import Apply, Variable
  from pytensor.graph.utils import MetaObject, TestValueError, add_tag_trace, get_variable_trace_string
label_desc: Use image node_id 11 for calling the Op obj's underlying member method code with example usage: obj.make_thunk(node, storage_map, compute_map, no_recycling, impl) and returns: self