# Path: third_party/bi_att_flow/my/tensorflow/general.py
# def grouper(iterable, n, fillvalue=None, shorten=False, num_groups=None):
#   args = [iter(iterable)] * n
#   out = zip_longest(*args, fillvalue=fillvalue)
#   out = list(out)
#   if num_groups is not None:
#     default = (fillvalue,) * n
#     assert isinstance(num_groups, int)
#     out = list(
#         each
#         for each, _ in zip_longest(out, range(num_groups), fillvalue=default))
#   if shorten:
#     assert fillvalue is None
#     out = (tuple(e for e in each if e is not None) for each in out)
#   return out
# 
# Path: third_party/bi_att_flow/my/utils.py
# def index(l, i):
#   return index(l[i[0]], i[1:]) if len(i) > 1 else l[i[0]]


import json
import os
import random
import itertools
import math
import numpy as np
import tensorflow as tf
from collections import defaultdict
from third_party.bi_att_flow.my.tensorflow.general import grouper
from third_party.bi_att_flow.my.utils import index
    num_batches_per_epoch = int(math.ceil(self.num_examples / batch_size))
    if num_batches is None:
      num_batches = num_batches_per_epoch
    num_epochs = int(math.ceil(num_batches / num_batches_per_epoch))

    if shuffle:
      random_idxs = random.sample(self.valid_idxs, len(self.valid_idxs))
      if cluster:
        sorted_idxs = sorted(random_idxs, key=self._sort_key)
        sorted_grouped = lambda: list(grouper(sorted_idxs, batch_size))
        grouped = lambda: random.sample(sorted_grouped(), num_batches_per_epoch)
      else:
        random_grouped = lambda: list(grouper(random_idxs, batch_size))
        grouped = random_grouped
    else:
      raw_grouped = lambda: list(grouper(self.valid_idxs, batch_size))
      grouped = raw_grouped
    batch_idx_tuples = itertools.chain.from_iterable(grouped()
                                                     for _ in range(num_epochs))
    for _ in range(num_batches):
      batch_idxs = tuple(i for i in next(batch_idx_tuples) if i is not None)
      batch_data = self.get_by_idxs(batch_idxs)
      shared_batch_data = {}
      for key, val in batch_data.items():
        if key.startswith('*'):
          if key == '*cx' and 'cx' not in self.shared:
            continue
          assert self.shared is not None
          shared_key = key[1:]
          shared_batch_data[shared_key] = [

# Path: third_party/bi_att_flow/my/tensorflow/general.py
# def grouper(iterable, n, fillvalue=None, shorten=False, num_groups=None):
#   args = [iter(iterable)] * n
#   out = zip_longest(*args, fillvalue=fillvalue)
#   out = list(out)
#   if num_groups is not None:
#     default = (fillvalue,) * n
#     assert isinstance(num_groups, int)
#     out = list(
#         each
#         for each, _ in zip_longest(out, range(num_groups), fillvalue=default))
#   if shorten:
#     assert fillvalue is None
#     out = (tuple(e for e in each if e is not None) for each in out)
#   return out
# 
# Path: third_party/bi_att_flow/my/utils.py
# def index(l, i):
#   return index(l[i[0]], i[1:]) if len(i) > 1 else l[i[0]]


# Path: third_party/bi_att_flow/basic/read_data.py
import json
import os
import random
import itertools
import math
import numpy as np
import tensorflow as tf
from collections import defaultdict
from third_party.bi_att_flow.my.tensorflow.general import grouper
from third_party.bi_att_flow.my.utils import index

    num_batches_per_epoch = int(math.ceil(self.num_examples / batch_size))
    if num_batches is None:
      num_batches = num_batches_per_epoch
    num_epochs = int(math.ceil(num_batches / num_batches_per_epoch))

    if shuffle:
      random_idxs = random.sample(self.valid_idxs, len(self.valid_idxs))
      if cluster:
        sorted_idxs = sorted(random_idxs, key=self._sort_key)
        sorted_grouped = lambda: list(grouper(sorted_idxs, batch_size))
        grouped = lambda: random.sample(sorted_grouped(), num_batches_per_epoch)
      else:
        random_grouped = lambda: list(grouper(random_idxs, batch_size))
        grouped = random_grouped
    else:
      raw_grouped = lambda: list(grouper(self.valid_idxs, batch_size))
      grouped = raw_grouped
    batch_idx_tuples = itertools.chain.from_iterable(grouped()
                                                     for _ in range(num_epochs))
    for _ in range(num_batches):
      batch_idxs = tuple(i for i in next(batch_idx_tuples) if i is not None)
      batch_data = self.get_by_idxs(batch_idxs)
      shared_batch_data = {}
      for key, val in batch_data.items():
        if key.startswith('*'):
          if key == '*cx' and 'cx' not in self.shared:
            continue
          assert self.shared is not None
          shared_key = key[1:]
          shared_batch_data[shared_key] = [

              index(self.shared[shared_key], each) for each in val