class_docstr: A cheap sparse version of :class:`MarginalAssignment`.
  
  :param int num_detections: the number of detections
  :param int num_objects: the number of (potentially existing) objects
  :param torch.LongTensor edges: a ``[2, num_edges]``-shaped tensor of
      (detection, object) index pairs specifying feasible associations.
  :param torch.Tensor exists_logits: a tensor of shape ``[num_objects]``
      representing per-object factors for existence of each potential object.
  :param torch.Tensor assign_logits: a tensor of shape ``[num_edges]``
      representing per-edge factors of assignment probability, where each
      edge denotes that a given detection associates with a single object.
  :param int bp_iters: optional number of belief propagation iterations. If
      unspecified or ``None`` an expensive exact algorithm will be used.
  
  :ivar int num_detections: the number of detections
  :ivar int num_objects: the number of (potentially existing) objects
  :ivar pyro.distributions.Bernoulli exists_dist: a mean field posterior
      distribution over object existence.
  :ivar pyro.distributions.Categorical assign_dist: a mean field posterior
      distribution over the object (or None) to which each detection
      associates.  This has ``.event_shape == (num_objects + 1,)`` where the
      final element denotes spurious detection, and
      ``.batch_shape == (num_frames, num_detections)``.
class_docstr_tok: ["A","cheap","sparse","version","of",":","class",":","`","MarginalAssignment","`",".",":","param","int","num_detections",":","the","number","of","detections",":","param","int","num_objects",":","the","number","of","(","potentially","existing",")","objects",":","param","torch.LongTensor","edges",":","a","``","[","2",",","num_edges","]","``","-shaped","tensor","of","(","detection",",","object",")","index","pairs","specifying","feasible","associations",".",":","param","torch.Tensor","exists_logits",":","a","tensor","of","shape","``","[","num_objects","]","``","representing","per-object","factors","for","existence","of","each","potential","object",".",":","param","torch.Tensor","assign_logits",":","a","tensor","of","shape","``","[","num_edges","]","``","representing","per-edge","factors","of","assignment","probability",",","where","each","edge","denotes","that","a","given","detection","associates","with","a","single","object",".",":","param","int","bp_iters",":","optional","number","of","belief","propagation","iterations",".","If","unspecified","or","``","None","``","an","expensive","exact","algorithm","will","be","used",".",":","ivar","int","num_detections",":","the","number","of","detections",":","ivar","int","num_objects",":","the","number","of","(","potentially","existing",")","objects",":","ivar","pyro.distributions.Bernoulli","exists_dist",":","a","mean","field","posterior","distribution","over","object","existence",".",":","ivar","pyro.distributions.Categorical","assign_dist",":","a","mean","field","posterior","distribution","over","the","object","(","or","None",")","to","which","each","detection","associates",".","This","has","``",".event_shape","==","(","num_objects","+","1",",",")","``","where","the","final","element","denotes","spurious","detection",",","and","``",".batch_shape","==","(","num_frames",",","num_detections",")","``","."]
code: def __init__(
      self,
      num_objects,
      num_detections,
      edges,
      exists_logits,
      assign_logits,
      bp_iters,
  ):
      assert edges.dim() == 2, edges.shape
      assert edges.shape[0] == 2, edges.shape
      assert exists_logits.shape == (num_objects,), exists_logits.shape
      assert assign_logits.shape == edges.shape[1:], assign_logits.shape
      self.num_objects = num_objects
      self.num_detections = num_detections
      self.edges = edges
  
      # Clamp to avoid NANs.
      exists_logits = exists_logits.clamp(min=-40, max=40)
      assign_logits = assign_logits.clamp(min=-40, max=40)
  
      # This does all the work.
      exists, assign = compute_marginals_sparse_bp(
          num_objects,
          num_detections,
          edges,
          exists_logits,
          assign_logits,
          bp_iters,
      )
  
      # Wrap the results in Distribution objects.
      # This adds a final logit=0 element denoting spurious detection.
      padded_assign = torch.full(
          (num_detections, num_objects + 1),
          -float("inf"),
          dtype=assign.dtype,
          device=assign.device,
      )
      padded_assign[:, -1] = 0
      padded_assign[edges[0], edges[1]] = assign
      self.assign_dist = dist.Categorical(logits=padded_assign)
      self.exists_dist = dist.Bernoulli(logits=exists)
  
file_path: pyro/pyro/contrib/tracking/assignment.py
imports: import itertools
  import math
  import numbers
  import torch
  import pyro.distributions
  from pyro.util import warn_if_nan
label_desc: Use image node_id 1 to create a new MarginalAssignmentSparse object  with example: obj = MarginalAssignmentSparse(num_objects, num_detections, edges, exists_logits, assign_logits, bp_iters)