class_docstr: DiNTS topology search space of neural architectures.
  
  Examples:
  
  .. code-block:: python
  
      from monai.networks.nets.dints import TopologySearch
  
      topology_search_space = TopologySearch(
          channel_mul=0.5, num_blocks=8, num_depths=4, use_downsample=True, spatial_dims=3)
      topology_search_space.get_ram_cost_usage(in_size=(2, 16, 80, 80, 80), full=True)
      multi_res_images = [
          torch.randn(2, 16, 80, 80, 80),
          torch.randn(2, 32, 40, 40, 40),
          torch.randn(2, 64, 20, 20, 20),
          torch.randn(2, 128, 10, 10, 10)]
      prediction = topology_search_space(image)
      for x in prediction: print(x.shape)
      # torch.Size([2, 16, 80, 80, 80])
      # torch.Size([2, 32, 40, 40, 40])
      # torch.Size([2, 64, 20, 20, 20])
      # torch.Size([2, 128, 10, 10, 10])
  
  Class method overview:
  
      - ``get_prob_a()``: convert learnable architecture weights to path activation probabilities.
      - ``get_ram_cost_usage()``: get estimated ram cost.
      - ``get_topology_entropy()``: get topology entropy loss in searching stage.
      - ``decode()``: get final binarized architecture code.
      - ``gen_mtx()``: generate variables needed for topology search.
  
  Predefined variables:
      - `tidx`: index used to convert path activation matrix T = (depth,depth) in transfer_mtx to
        path activation arch_code (1,3*depth-2), for depth = 4, tidx = [0, 1, 4, 5, 6, 9, 10, 11, 14, 15],
        A tidx (10 binary values) represents the path activation.
      - `transfer_mtx`: feasible path activation matrix (denoted as T) given a node activation pattern.
        It is used to convert path activation pattern (1, paths) to node activation (1, nodes)
      - `node_act_list`: all node activation [2^num_depths-1, depth]. For depth = 4, there are 15 node activation
        patterns, each of length 4. For example, [1,1,0,0] means nodes 0, 1 are activated (with input paths).
      - `all_connect`: All possible path activations. For depth = 4,
        all_connection has 1024 vectors of length 10 (10 paths).
        The return value will exclude path activation of all 0.
class_docstr_tok: ["DiNTS","topology","search","space","of","neural","architectures",".","Examples",":","..","code-block",":",":","python","from","monai.networks.nets.dints","import","TopologySearch","topology_search_space","=","TopologySearch","(","channel_mul=0.5",",","num_blocks=8",",","num_depths=4",",","use_downsample=True",",","spatial_dims=3",")","topology_search_space.get_ram_cost_usage","(","in_size=","(","2",",","16",",","80",",","80",",","80",")",",","full=True",")","multi_res_images","=","[","torch.randn","(","2",",","16",",","80",",","80",",","80",")",",","torch.randn","(","2",",","32",",","40",",","40",",","40",")",",","torch.randn","(","2",",","64",",","20",",","20",",","20",")",",","torch.randn","(","2",",","128",",","10",",","10",",","10",")","]","prediction","=","topology_search_space","(","image",")","for","x","in","prediction",":","print","(","x.shape",")","#","torch.Size","(","[","2",",","16",",","80",",","80",",","80","]",")","#","torch.Size","(","[","2",",","32",",","40",",","40",",","40","]",")","#","torch.Size","(","[","2",",","64",",","20",",","20",",","20","]",")","#","torch.Size","(","[","2",",","128",",","10",",","10",",","10","]",")","Class","method","overview",":","-","``","get_prob_a","(",")","``",":","convert","learnable","architecture","weights","to","path","activation","probabilities",".","-","``","get_ram_cost_usage","(",")","``",":","get","estimated","ram","cost",".","-","``","get_topology_entropy","(",")","``",":","get","topology","entropy","loss","in","searching","stage",".","-","``","decode","(",")","``",":","get","final","binarized","architecture","code",".","-","``","gen_mtx","(",")","``",":","generate","variables","needed","for","topology","search",".","Predefined","variables",":","-","`","tidx","`",":","index","used","to","convert","path","activation","matrix","T","=","(","depth",",","depth",")","in","transfer_mtx","to","path","activation","arch_code","(","1,3","*","depth-2",")",",","for","depth","=","4",",","tidx","=","[","0",",","1",",","4",",","5",",","6",",","9",",","10",",","11",",","14",",","15","]",",","A","tidx","(","10","binary","values",")","represents","the","path","activation",".","-","`","transfer_mtx","`",":","feasible","path","activation","matrix","(","denoted","as","T",")","given","a","node","activation","pattern",".","It","is","used","to","convert","path","activation","pattern","(","1",",","paths",")","to","node","activation","(","1",",","nodes",")","-","`","node_act_list","`",":","all","node","activation","[","2^num_depths-1",",","depth","]",".","For","depth","=","4",",","there","are","15","node","activation","patterns",",","each","of","length","4",".","For","example",",","[","1,1,0,0","]","means","nodes","0",",","1","are","activated","(","with","input","paths",")",".","-","`","all_connect","`",":","All","possible","path","activations",".","For","depth","=","4",",","all_connection","has","1024","vectors","of","length","10","(","10","paths",")",".","The","return","value","will","exclude","path","activation","of","all","0","."]
docstr: Decode network log_alpha_a/log_alpha_c using dijkstra shortest path algorithm.
  
  `[node_a, arch_code_a, arch_code_c, arch_code_a_max]` is decoded when using ``self.decode()``.
  
  For example, for a ``num_depths=4``, ``num_blocks=12`` search space:
  
      - ``node_a`` is a 4x13 binary matrix representing if a feature node is activated
        (13 because of multi-resolution inputs).
      - ``arch_code_a`` is a 12x10 (10 paths) binary matrix representing if a path is activated.
      - ``arch_code_c`` is a 12x10x5 (5 operations) binary matrix representing if a cell operation is used.
  
  Return:
      arch_code with maximum probability
docstr_tok: ["Decode","network","log_alpha_a\/log_alpha_c","using","dijkstra","shortest","path","algorithm",".","`","[","node_a",",","arch_code_a",",","arch_code_c",",","arch_code_a_max","]","`","is","decoded","when","using","``","self.decode","(",")","``",".","For","example",",","for","a","``","num_depths=4","``",",","``","num_blocks=12","``","search","space",":","-","``","node_a","``","is","a","4x13","binary","matrix","representing","if","a","feature","node","is","activated","(","13","because","of","multi-resolution","inputs",")",".","-","``","arch_code_a","``","is","a","12x10","(","10","paths",")","binary","matrix","representing","if","a","path","is","activated",".","-","``","arch_code_c","``","is","a","12x10x5","(","5","operations",")","binary","matrix","representing","if","a","cell","operation","is","used",".","Return",":","arch_code","with","maximum","probability"]
code: def decode(self):
      """
      Decode network log_alpha_a/log_alpha_c using dijkstra shortest path algorithm.
  
      `[node_a, arch_code_a, arch_code_c, arch_code_a_max]` is decoded when using ``self.decode()``.
  
      For example, for a ``num_depths=4``, ``num_blocks=12`` search space:
  
          - ``node_a`` is a 4x13 binary matrix representing if a feature node is activated
            (13 because of multi-resolution inputs).
          - ``arch_code_a`` is a 12x10 (10 paths) binary matrix representing if a path is activated.
          - ``arch_code_c`` is a 12x10x5 (5 operations) binary matrix representing if a cell operation is used.
  
      Return:
          arch_code with maximum probability
      """
      probs, arch_code_prob_a = self.get_prob_a(child=True)
      arch_code_a_max = self.child_list[
          torch.argmax(probs, -1).data.cpu().numpy()
      ]
      arch_code_c = (
          torch.argmax(F.softmax(self.log_alpha_c, -1), -1)
          .data.cpu()
          .numpy()
      )
      probs = probs.data.cpu().numpy()
  
      # define adjacency matrix
      amtx = np.zeros(
          (
              1 + len(self.child_list) * self.num_blocks + 1,
              1 + len(self.child_list) * self.num_blocks + 1,
          )
      )
  
      # build a path activation to child index searching dictionary
      path2child = {
          str(self.child_list[i]): i
          for i in range(len(self.child_list))
      }
  
      # build a submodel to submodel index
      sub_amtx = np.zeros((len(self.child_list), len(self.child_list)))
      for child_idx in range(len(self.child_list)):
          _node_act = np.zeros(self.num_depths).astype(int)
          for path_idx in range(len(self.child_list[child_idx])):
              _node_act[
                  self.arch_code2out[path_idx]
              ] += self.child_list[child_idx][path_idx]
          _node_act = (_node_act >= 1).astype(int)
          for mtx in self.transfer_mtx[str(_node_act)]:
              connect_child_idx = path2child[
                  str(mtx.flatten()[self.tidx].astype(int))
              ]
              sub_amtx[child_idx, connect_child_idx] = 1
  
      # fill in source to first block, add 1e-5/1e-3 to avoid log0 and negative edge weights
      amtx[0, 1 : 1 + len(self.child_list)] = (
          -np.log(probs[0] + 1e-5) + 0.001
      )
  
      # fill in the rest blocks
      for blk_idx in range(1, self.num_blocks):
          amtx[
              1
              + (blk_idx - 1) * len(self.child_list) : 1
              + blk_idx * len(self.child_list),
              1
              + blk_idx * len(self.child_list) : 1
              + (blk_idx + 1) * len(self.child_list),
          ] = sub_amtx * np.tile(
              -np.log(probs[blk_idx] + 1e-5) + 0.001,
              (len(self.child_list), 1),
          )
  
      # fill in the last to the sink
      amtx[
          1
          + (self.num_blocks - 1) * len(self.child_list) : 1
          + self.num_blocks * len(self.child_list),
          -1,
      ] = 0.001
  
      graph = csr_matrix(amtx)
      dist_matrix, predecessors, sources = dijkstra(
          csgraph=graph,
          directed=True,
          indices=0,
          min_only=True,
          return_predecessors=True,
      )
      index, a_idx = -1, -1
      arch_code_a = np.zeros((self.num_blocks, len(self.arch_code2out)))
      node_a = np.zeros((self.num_blocks + 1, self.num_depths))
  
      # decoding to paths
      while True:
          index = predecessors[index]
          if index == 0:
              break
          child_idx = (index - 1) % len(self.child_list)
          arch_code_a[a_idx, :] = self.child_list[child_idx]
          for res_idx in range(len(self.arch_code2out)):
              node_a[a_idx, self.arch_code2out[res_idx]] += arch_code_a[
                  a_idx, res_idx
              ]
          a_idx -= 1
      for res_idx in range(len(self.arch_code2out)):
          node_a[a_idx, self.arch_code2in[res_idx]] += arch_code_a[
              0, res_idx
          ]
      node_a = (node_a >= 1).astype(int)
      return node_a, arch_code_a, arch_code_c, arch_code_a_max
  
imports: from __future__ import annotations
  import datetime
  import warnings
  from typing import Optional
  import numpy
  import torch
  import torch.nn
  import torch.nn.functional
  from monai.networks.blocks.dints_block import ActiConvNormBlock, FactorizedIncreaseBlock, FactorizedReduceBlock, P3DActiConvNormBlock
  from monai.networks.layers.factories import Conv
  from monai.networks.layers.utils import get_act_layer, get_norm_layer
  from monai.utils import optional_import
label_desc: Use image node_id 7 for calling the TopologySearch obj's underlying member method code with example usage: obj.decode() and returns: node_a,  arch_code_a,  arch_code_c,  arch_code_a_max