# Path: ehr_prediction_modeling/models/snrnn_model.py
# class SNRNNModel(rnn_model.BaseRNNModel):
#   def __init__(self, config: configdict.ConfigDict, tasks: List[Text],
#                embedding_size: int) -> None:
#   def input_size_fn(self, layer_i: int,
#                     use_task_specific_routing: bool) -> Union[int, None]:
#     def _compute_input_size_for_list(inputs):
#   def _init_rnn(self) -> None:
#   def initial_state(
#       self,
#       batch_size: int,
#       dtype: tf.dtypes.DType = tf.float32) -> List[List[tf.Tensor]]:
#   def _build(
#       self, features: tf.Tensor, beginning_of_sequence_mask: tf.Tensor,
#       t_vect: tf.Tensor,
#       prev_states: List[List[tf.Tensor]]) -> types.ForwardFunctionReturns:
#   def _get_snr_connections(self) -> List[tf.Variable]:
#   def _get_variables_for_regularization(self) -> List[tf.Variable]:
#   def get_task_routing_connections(self) -> Dict[str, List[tf.Variable]]:
#   def get_snr_regularization_loss(self) -> tf.Tensor:
#   def get_model_regularization_loss(self) -> tf.Tensor:
# 
# Path: ehr_prediction_modeling/models/nets/deep_encoders.py
# class FullyConnectedEncoder(encoder_base.DeepEncoderBase):
# class ResidualEncoder(encoder_base.DeepEncoderBase):
# class SNREncoder(encoder_base.DeepEncoderBase):
#   def _build(
#       self,
#       input_data: encoder_base.EncoderInput,
#       context: encoder_base.EncoderContext = None
#   ) -> tf.Tensor:
#   def _build(
#       self,
#       input_data: encoder_base.EncoderInput,
#       context: encoder_base.EncoderContext = None
#   ) -> tf.Tensor:
#   def __init__(self, *args, **kwargs):
#   def embed_out(self) -> int:
#   def initial_embed_size(self) -> int:
#   def _tasks(self) -> List[str]:
#   def get_task_routing_connections(self):
#   def get_regularization_penalty(self) -> tf.Tensor:
#   def _build(
#       self,
#       input_data: encoder_base.EncoderInput,
#       context: encoder_base.EncoderContext = None
#   ) -> tf.Tensor:
# def get_snr_embed_out_size(config, feat):
#   def _snr_embed_out_skip(feat_layer_size):
# def get_snr_embedding_dim_dict(config):
# def compute_combined_snr_embedding(embedding_dict):
# def get_encoder(encoder_type: str) -> Type[encoder_base.DeepEncoderTypes]:


import collections
import itertools
from absl import logging
from ehr_prediction_modeling.models import snrnn_model
from ehr_prediction_modeling.models.nets import deep_encoders
  """Returns the task-specific SNR connections.

  If use_task_specific_routing is disabled in both the model and the encoder
  it will return an (empty dictionary, empty list) tuple.

  For sub-network routing when optimizing task specific connections we
  want to optimize each corresponding to the specific task loss they're
  associated with.

  If the model type is not SNRNN and the encoder type is not SNR then this
  function will return empty collections.

  Args:
    model: The instantiated model. Must be an SNRNN in order to have
      any connections returned.
    encoder: The instantiated encoder. Must have SNREncoders associated
      with the embedding in order to have any connections returned.
    losses_per_task: A dictionary from task name to associated total loss for
      that task.

  Returns:
    A tuple where the first element is a dictionary from a task specific loss
    to a variable list that will be optimized wrt to it, and the second element
    is a set of all the routing connections in the architecture.
  """
  loss_to_vars = {}
  routing_connections_for_task = collections.defaultdict(set)
  # In some cases the model is wrapped in an RNNModelWithPersistentState
  # class.
  if (isinstance(model, snrnn_model.SNRNNModel) or

# Path: ehr_prediction_modeling/models/snrnn_model.py
# class SNRNNModel(rnn_model.BaseRNNModel):
#   def __init__(self, config: configdict.ConfigDict, tasks: List[Text],
#                embedding_size: int) -> None:
#   def input_size_fn(self, layer_i: int,
#                     use_task_specific_routing: bool) -> Union[int, None]:
#     def _compute_input_size_for_list(inputs):
#   def _init_rnn(self) -> None:
#   def initial_state(
#       self,
#       batch_size: int,
#       dtype: tf.dtypes.DType = tf.float32) -> List[List[tf.Tensor]]:
#   def _build(
#       self, features: tf.Tensor, beginning_of_sequence_mask: tf.Tensor,
#       t_vect: tf.Tensor,
#       prev_states: List[List[tf.Tensor]]) -> types.ForwardFunctionReturns:
#   def _get_snr_connections(self) -> List[tf.Variable]:
#   def _get_variables_for_regularization(self) -> List[tf.Variable]:
#   def get_task_routing_connections(self) -> Dict[str, List[tf.Variable]]:
#   def get_snr_regularization_loss(self) -> tf.Tensor:
#   def get_model_regularization_loss(self) -> tf.Tensor:
# 
# Path: ehr_prediction_modeling/models/nets/deep_encoders.py
# class FullyConnectedEncoder(encoder_base.DeepEncoderBase):
# class ResidualEncoder(encoder_base.DeepEncoderBase):
# class SNREncoder(encoder_base.DeepEncoderBase):
#   def _build(
#       self,
#       input_data: encoder_base.EncoderInput,
#       context: encoder_base.EncoderContext = None
#   ) -> tf.Tensor:
#   def _build(
#       self,
#       input_data: encoder_base.EncoderInput,
#       context: encoder_base.EncoderContext = None
#   ) -> tf.Tensor:
#   def __init__(self, *args, **kwargs):
#   def embed_out(self) -> int:
#   def initial_embed_size(self) -> int:
#   def _tasks(self) -> List[str]:
#   def get_task_routing_connections(self):
#   def get_regularization_penalty(self) -> tf.Tensor:
#   def _build(
#       self,
#       input_data: encoder_base.EncoderInput,
#       context: encoder_base.EncoderContext = None
#   ) -> tf.Tensor:
# def get_snr_embed_out_size(config, feat):
#   def _snr_embed_out_skip(feat_layer_size):
# def get_snr_embedding_dim_dict(config):
# def compute_combined_snr_embedding(embedding_dict):
# def get_encoder(encoder_type: str) -> Type[encoder_base.DeepEncoderTypes]:


# Path: ehr_prediction_modeling/losses.py
import collections
import itertools
from absl import logging
from ehr_prediction_modeling.models import snrnn_model
from ehr_prediction_modeling.models.nets import deep_encoders

  """Returns the task-specific SNR connections.

  If use_task_specific_routing is disabled in both the model and the encoder
  it will return an (empty dictionary, empty list) tuple.

  For sub-network routing when optimizing task specific connections we
  want to optimize each corresponding to the specific task loss they're
  associated with.

  If the model type is not SNRNN and the encoder type is not SNR then this
  function will return empty collections.

  Args:
    model: The instantiated model. Must be an SNRNN in order to have
      any connections returned.
    encoder: The instantiated encoder. Must have SNREncoders associated
      with the embedding in order to have any connections returned.
    losses_per_task: A dictionary from task name to associated total loss for
      that task.

  Returns:
    A tuple where the first element is a dictionary from a task specific loss
    to a variable list that will be optimized wrt to it, and the second element
    is a set of all the routing connections in the architecture.
  """
  loss_to_vars = {}
  routing_connections_for_task = collections.defaultdict(set)
  # In some cases the model is wrapped in an RNNModelWithPersistentState
  # class.
  if (isinstance(model, snrnn_model.SNRNNModel) or

      isinstance(model.get_model, snrnn_model.SNRNNModel)):