class_docstr: Class that satisfies the `Linker` interface by acting as a `VM` factory.
  
  Parameters
  ----------
  allow_gc
      Force the virtual machine to clean up unnecessary references, in order
      to allow garbage collection on intermediate values during computation
      of a function.  If ``None``, use as default the value of the PyTensor
      flag `allow_gc`.
  use_cloop
      Use the C-based virtual machine if possible
  callback
      A callable object to call after each call to a thunk within the virtual
      machine.  It will be called with four arguments: ``node``, ``thunk``,
      ``storage_map``, and ``compute_map``.
  callback_input
      A callable object to call on each input to the graph (variables with no
      owner).  This includes constants and shared variables values.  It will
      be called with two arguments: ``var``, ``value``.
  lazy
      Useful only when `use_cloop` is False. When `lazy` is ``None``, use the
      PyTensor flag ``vm__lazy`` value. Then if we have a ``None`` (default) we
      auto detect if lazy evaluation is needed and use the appropriate
      version. If `lazy` is ``True`` or ``False``, we force the version used
      between `Loop` and `Stack`.
  c_thunks
      If ``None`` or ``True``, don't change the default. If ``False``, don't
      compile C code for the thunks.
  allow_partial_eval
      If ``True``, enforces usage of `Stack` or `CVM`, to allow for partial
      evaluation of functions (calculating a subset of outputs).
class_docstr_tok: ["Class","that","satisfies","the","`","Linker","`","interface","by","acting","as","a","`","VM","`","factory",".","Parameters","--","--","--","--","--","allow_gc","Force","the","virtual","machine","to","clean","up","unnecessary","references",",","in","order","to","allow","garbage","collection","on","intermediate","values","during","computation","of","a","function",".","If","``","None","``",",","use","as","default","the","value","of","the","PyTensor","flag","`","allow_gc","`",".","use_cloop","Use","the","C-based","virtual","machine","if","possible","callback","A","callable","object","to","call","after","each","call","to","a","thunk","within","the","virtual","machine",".","It","will","be","called","with","four","arguments",":","``","node","``",",","``","thunk","``",",","``","storage_map","``",",","and","``","compute_map","``",".","callback_input","A","callable","object","to","call","on","each","input","to","the","graph","(","variables","with","no","owner",")",".","This","includes","constants","and","shared","variables","values",".","It","will","be","called","with","two","arguments",":","``","var","``",",","``","value","``",".","lazy","Useful","only","when","`","use_cloop","`","is","False",".","When","`","lazy","`","is","``","None","``",",","use","the","PyTensor","flag","``","vm__lazy","``","value",".","Then","if","we","have","a","``","None","``","(","default",")","we","auto","detect","if","lazy","evaluation","is","needed","and","use","the","appropriate","version",".","If","`","lazy","`","is","``","True","``","or","``","False","``",",","we","force","the","version","used","between","`","Loop","`","and","`","Stack","`",".","c_thunks","If","``","None","``","or","``","True","``",",","do","n't","change","the","default",".","If","``","False","``",",","don't","compile","C","code","for","the","thunks",".","allow_partial_eval","If","``","True","``",",","enforces","usage","of","`","Stack","`","or","`","CVM","`",",","to","allow","for","partial","evaluation","of","functions","(","calculating","a","subset","of","outputs",")","."]
docstr: Records in the `Linker` which variables have update expressions.
  
  It does not imply that the `Linker` will actually implement these updates
  (see `VM.need_update_inputs`).  This mechanism is admittedly confusing, and
  it could use some cleaning up. The base `Linker` object should probably
  go away completely.
  
  TODO: Remove this after refactoring the `VM`/`Linker` interfaces.
docstr_tok: ["Records","in","the","`","Linker","`","which","variables","have","update","expressions",".","It","does","not","imply","that","the","`","Linker","`","will","actually","implement","these","updates","(","see","`","VM.need_update_inputs","`",")",".","This","mechanism","is","admittedly","confusing",",","and","it","could","use","some","cleaning","up",".","The","base","`","Linker","`","object","should","probably","go","away","completely",".","TODO",":","Remove","this","after","refactoring","the","`","VM","`","\/","`","Linker","`","interfaces","."]
code: def accept_var_updates(self, updated_vars):
      """Records in the `Linker` which variables have update expressions.
  
      It does not imply that the `Linker` will actually implement these updates
      (see `VM.need_update_inputs`).  This mechanism is admittedly confusing, and
      it could use some cleaning up. The base `Linker` object should probably
      go away completely.
  
      TODO: Remove this after refactoring the `VM`/`Linker` interfaces.
      """
      self.updated_vars = updated_vars
  
imports: import platform
  import sys
  import time
  import warnings
  from abc import ABC, abstractmethod
  from collections import defaultdict
  from collections.abc import Sequence
  from itertools import zip_longest
  from typing import TYPE_CHECKING, Any, Optional
  from pytensor.configdefaults import config
  from pytensor.graph.basic import Apply, Constant, Variable
  from pytensor.link.basic import Container, LocalLinker
  from pytensor.link.c.exceptions import MissingGXX
  from pytensor.link.utils import gc_helper, get_destroy_dependencies, map_storage, raise_with_op
label_desc: Use image node_id 3 for calling the VMLinker obj's underlying member method code with example usage: obj.accept_var_updates(updated_vars) without return types