class_docstr: Jit-compatible helper to build blockwise matrices.
  Syntax is similar to :func:`torch.zeros` ::
  
      x = BlockMatrix((100, 20, 20))
      x[..., 0:4, 0:4] = x11
      x[..., 0:4, 6:10] = x12
      x[..., 6:10, 0:4] = x12.transpose(-1, -2)
      x[..., 6:10, 6:10] = x22
      x = x.as_tensor()
      assert x.shape == (100, 20, 20)
class_docstr_tok: ["Jit-compatible","helper","to","build","blockwise","matrices",".","Syntax","is","similar","to",":","func",":","`","torch.zeros","`",":",":","x","=","BlockMatrix","(","(","100",",","20",",","20",")",")","x","[","...",",","0:4",",","0:4","]","=","x11","x","[","...",",","0:4",",","6:10","]","=","x12","x","[","...",",","6:10",",","0:4","]","=","x12.transpose","(","-1",",","-2",")","x","[","...",",","6:10",",","6:10","]","=","x22","x","=","x.as_tensor","(",")","assert","x.shape","==","(","100",",","20",",","20",")"]
code: def as_tensor(self):
      # TODO optimize this to use backend-specific block setters:
      # .__setitem__ for numpy and torch; .at(...).set(...) for jax.
  
      # Fill gaps with zeros.
      arbitrary_row = next(iter(self.parts.values()))
      prototype = next(iter(arbitrary_row.values()))
      js = set().union(*(part.keys() for part in self.parts.values()))
      rows = _find_intervals(self.parts.keys(), self.shape[-2])
      cols = _find_intervals(js, self.shape[-1])
      for i in rows:
          for j in cols:
              if j not in self.parts[i]:
                  shape = self.shape[:-2] + (i[1] - i[0], j[1] - j[0])
                  self.parts[i][j] = ops.new_zeros(prototype, shape)
  
      # Concatenate parts.
      columns = {
          i: ops.cat([v for j, v in sorted(part.items())], -1)
          for i, part in self.parts.items()
      }
      result = ops.cat([v for i, v in sorted(columns.items())], -2)
      if not get_tracing_state():
          assert result.shape == self.shape
      return result
  
imports: import math
  from collections import OrderedDict, defaultdict
  from contextlib import contextmanager
  from functools import reduce
  import funsor.ops
  from funsor.affine import affine_inputs, extract_affine, is_affine
  from funsor.delta import Delta
  from funsor.domains import Real, Reals
  from funsor.interpretations import compress_gaussians
  from funsor.ops import AddOp, SubOp
  from funsor.tensor import Tensor, align_tensor, align_tensors
  from funsor.terms import Binary, Funsor, FunsorMeta, Number, Slice, Subs, Variable, eager, reflect
  from funsor.util import broadcast_shape, get_tracing_state, lazy_property
label_desc: Use image node_id 3 for calling the BlockMatrix obj's underlying member method code with example usage: obj.as_tensor() and returns: result