class_docstr: Distribution over spanning trees on a fixed number ``V`` of vertices.
  
  A tree is represented as :class:`torch.LongTensor` ``edges`` of shape
  ``(V-1,2)`` satisfying the following properties:
  
  1. The edges constitute a tree, i.e. are connected and cycle free.
  2. Each edge ``(v1,v2) = edges[e]`` is sorted, i.e. ``v1 < v2``.
  3. The entire tensor is sorted in colexicographic order.
  
  Use :func:`validate_edges` to verify `edges` are correctly formed.
  
  The ``edge_logits`` tensor has one entry for each of the ``V*(V-1)//2``
  edges in the complete graph on ``V`` vertices, where edges are each sorted
  and the edge order is colexicographic::
  
      (0,1), (0,2), (1,2), (0,3), (1,3), (2,3), (0,4), (1,4), (2,4), ...
  
  This ordering corresponds to the size-independent pairing function::
  
      k = v1 + v2 * (v2 - 1) // 2
  
  where ``k`` is the rank of the edge ``(v1,v2)`` in the complete graph.
  To convert a matrix of edge logits to the linear representation used here::
  
      assert my_matrix.shape == (V, V)
      i, j = make_complete_graph(V)
      edge_logits = my_matrix[i, j]
  
  :param torch.Tensor edge_logits: A tensor of length ``V*(V-1)//2``
      containing logits (aka negative energies) of all edges in the complete
      graph on ``V`` vertices. See above comment for edge ordering.
  :param dict sampler_options: An optional dict of sampler options including:
      ``mcmc_steps`` defaulting to a single MCMC step (which is pretty good);
      ``initial_edges`` defaulting to a cheap approximate sample;
      ``backend`` one of "python" or "cpp", defaulting to "python".
code: def log_partition_function(self):
      # By Kirchoff's matrix-tree theorem, the partition function is the
      # determinant of a truncated version of the graph Laplacian matrix. We
      # use a Cholesky decomposition to compute the log determinant.
      # See https://en.wikipedia.org/wiki/Kirchhoff%27s_theorem
      V = self.num_vertices
      v1, v2 = make_complete_graph(V).unbind(0)
      logits = self.edge_logits.new_full((V, V), -math.inf)
      logits[v1, v2] = self.edge_logits
      logits[v2, v1] = self.edge_logits
      log_diag = logits.logsumexp(-1)
      # Numerically stabilize so that laplacian has 1's on the diagonal.
      shift = 0.5 * log_diag
      laplacian = torch.eye(V) - (logits - shift - shift[:, None]).exp()
      truncated = laplacian[:-1, :-1]
      try:
          import gpytorch
  
          log_det = gpytorch.lazy.NonLazyTensor(truncated).logdet()
      except ImportError:
          log_det = (
              torch.linalg.cholesky(truncated).diag().log().sum() * 2
          )
      return log_det + log_diag[:-1].sum()
  
imports: import itertools
  import math
  import torch
  from torch.distributions import constraints
  from torch.distributions.utils import lazy_property
  from pyro.distributions.torch_distribution import TorchDistribution
label_desc: Use image node_id 3 for calling the SpanningTree obj's underlying member method code with example usage: obj.log_partition_function() and returns: unknown