class_docstr: Shared RNN model.
class_docstr_tok: ["Shared","RNN","model","."]
docstr: Computes a single pass through the discovered RNN cell.
docstr_tok: ["Computes","a","single","pass","through","the","discovered","RNN","cell","."]
code: def cell(self, x, h_prev, dag):
      """Computes a single pass through the discovered RNN cell."""
      c = {}
      h = {}
      f = {}
  
      f[0] = self.get_f(dag[-1][0].name)
      c[0] = F.sigmoid(self.w_xc(x) + F.linear(h_prev, self.w_hc, None))
      h[0] = (
          c[0] * f[0](self.w_xh(x) + F.linear(h_prev, self.w_hh, None))
          + (1 - c[0]) * h_prev
      )
  
      leaf_node_ids = []
      q = collections.deque()
      q.append(0)
  
      # NOTE(brendan): Computes connections from the parent nodes `node_id`
      # to their child nodes `next_id` recursively, skipping leaf nodes. A
      # leaf node is a node whose id == `self.args.num_blocks`.
      #
      # Connections between parent i and child j should be computed as
      # h_j = c_j*f_{ij}{(W^h_{ij}*h_i)} + (1 - c_j)*h_i,
      # where c_j = \sigmoid{(W^c_{ij}*h_i)}
      #
      # See Training details from Section 3.1 of the paper.
      #
      # The following algorithm does a breadth-first (since `q.popleft()` is
      # used) search over the nodes and computes all the hidden states.
      while True:
          if len(q) == 0:
              break
  
          node_id = q.popleft()
          nodes = dag[node_id]
  
          for next_node in nodes:
              next_id = next_node.id
              if next_id == self.args.num_blocks:
                  leaf_node_ids.append(node_id)
                  assert len(nodes) == 1, (
                      "parent of leaf node should have "
                      "only one child"
                  )
                  continue
  
              w_h = self.w_h[node_id][next_id]
              w_c = self.w_c[node_id][next_id]
  
              f[next_id] = self.get_f(next_node.name)
              c[next_id] = F.sigmoid(w_c(h[node_id]))
              h[next_id] = (
                  c[next_id] * f[next_id](w_h(h[node_id]))
                  + (1 - c[next_id]) * h[node_id]
              )
  
              q.append(next_id)
  
      # TODO(brendan): Instead of averaging loose ends, perhaps there should
      # be a set of separate unshared weights for each "loose" connection
      # between each node in a cell and the output.
      #
      # As it stands, all weights W^h_{ij} are doing double duty by
      # connecting both from i to j, as well as from i to the output.
  
      # average all the loose ends
      leaf_nodes = [h[node_id] for node_id in leaf_node_ids]
      output = torch.mean(torch.stack(leaf_nodes, 2), -1)
  
      # stabilizing the Updates of omega
      if self.batch_norm is not None:
          output = self.batch_norm(output)
  
      return output, h[self.args.num_blocks - 1]
  
imports: import numpy
  import collections
  import torch
  from torch import nn
  import torch.nn.functional
  from torch.autograd import Variable
  import models.shared_base
  import utils
label_desc: Use image node_id 3 for calling the RNN obj's underlying member method code with example usage: obj.cell(x, h_prev, dag) and returns: output,  h