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: Returns dict: variable K -> list of variables [v1, v2, v3, ...]
  for each K in variables.
  
  The variables v1, v2, ... are the full set of variables that depend
  directly on K. When we know that none of them will need to be
  computed, we know that:
  * K will not need to be computed.
  * If K is already computed, it can be released for garbage collection.
  
  Parameters
  ----------
  variables
      Iterable over the variables used in a graph computation.
  
  Notes
  -----
  It doesn't take care of the view_map/destroy_map. So it means it relies
  on Python gc no to free the object real storage.
  
  N.B. gc means garbage collection
docstr_tok: ["Returns","dict",":","variable","K","-",">","list","of","variables","[","v1",",","v2",",","v3",",","...","]","for","each","K","in","variables",".","The","variables","v1",",","v2",",","...","are","the","full","set","of","variables","that","depend","directly","on","K.","When","we","know","that","none","of","them","will","need","to","be","computed",",","we","know","that",":","*","K","will","not","need","to","be","computed",".","*","If","K","is","already","computed",",","it","can","be","released","for","garbage","collection",".","Parameters","--","--","--","--","--","variables","Iterable","over","the","variables","used","in","a","graph","computation",".","Notes","--","--","-","It","does","n't","take","care","of","the","view_map\/destroy_map",".","So","it","means","it","relies","on","Python","gc","no","to","free","the","object","real","storage",".","N.B",".","gc","means","garbage","collection"]
code: def compute_gc_dependencies(self, variables):
      """
      Returns dict: variable K -> list of variables [v1, v2, v3, ...]
      for each K in variables.
  
      The variables v1, v2, ... are the full set of variables that depend
      directly on K. When we know that none of them will need to be
      computed, we know that:
      * K will not need to be computed.
      * If K is already computed, it can be released for garbage collection.
  
      Parameters
      ----------
      variables
          Iterable over the variables used in a graph computation.
  
      Notes
      -----
      It doesn't take care of the view_map/destroy_map. So it means it relies
      on Python gc no to free the object real storage.
  
      N.B. gc means garbage collection
  
      """
      dependencies = {}
      for k in variables:
          dependencies[k] = []
          # If k has no owner, it is an input / constant and its value
          # should not be removed from the storage_map because we have no
          # way of getting it back.
          #
          # XXX if k has no clients... what is it doing in the computation?
          # Fred guess: it could happen for node with multiple outputs when
          # we don't use all outputs.
  
          if k.owner and self.fgraph.clients[k]:
              ls = []
              for cl in self.fgraph.clients[k]:
                  if cl[0] != "output":
                      ls += cl[0].outputs
              dependencies[k] += ls
      return dependencies
  
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 4 for calling the VMLinker obj's underlying member method code with example usage: obj.compute_gc_dependencies(variables) and returns: dependencies