# -*- coding: utf-8 -*-

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import os
import re
from tensorflow.python.platform import gfile

# 1-1. Define Symbols

# 1-1-1. Define special vocabulary symbols.
_PAD = "_PAD"
_UNK = "_UNK"
_START_VOCAB = [_PAD, _UNK]
START_VOCAB_dict = dict()
START_VOCAB_dict['with_padding'] = [_PAD, _UNK]
START_VOCAB_dict['no_padding'] = [_UNK]
PAD_ID = 0
UNK_ID_dict = dict()
UNK_ID_dict['with_padding'] = 1
UNK_ID_dict['no_padding'] = 0

# 1-1-2. Regular expressions used to tokenize.
_WORD_SPLIT = re.compile("([.,!?\"':;)(])")
_DIGIT_RE = re.compile(r"\d")

# 1-2. Define Tokenizers.
# 1-2-1. Basic tokenizer
def basic_tokenizer(sentence):
  words = []
  for space_separated_fragment in sentence.strip().split():
    words.extend(re.split(_WORD_SPLIT, space_separated_fragment))
  return [w for w in words if w]
# 1-2-2. Naive tokenizer
def naive_tokenizer(sentence):
  return sentence.split()

# 1-3. Make vocabulary list which are in dictionary
def create_vocabulary(vocabulary_path, data_path, max_vocabulary_size,
                      tokenizer = None, normalize_digits = True):
    # vocabulary_path = data_dir + "in_vocab_%d.txt"
    #       data_path = train_path + ".seq.in"

  if not gfile.Exists(vocabulary_path): # If don`t exist yet
    print("Creating vocabulary %s from data %s" % (vocabulary_path, data_path))
    vocab = {}

    # 1-3-1. Read data using gfile.
    with gfile.GFile(data_path, mode="r") as f:

      # Count the number of line.
      counter = 0
      for line in f:
        counter += 1
        if counter % 1 == 0:
          print("processing line %d" % counter)

        # 1-3-2. Tokenize the line.
        tokens = tokenizer(line) if tokenizer else basic_tokenizer(line)

        # 1-3-3. Normalize digits to zero and Make frequency vocab.
        for w in tokens:
          word = re.sub(_DIGIT_RE, "0", w) if normalize_digits else w

          if word in vocab:
            vocab[word] += 1
          else:
            vocab[word] = 1

      vocab_list = START_VOCAB_dict['with_padding'] + sorted(vocab, key=vocab.get, reverse=True)
      if len(vocab_list) > max_vocabulary_size:
        vocab_list = vocab_list[:max_vocabulary_size]

      # 1-3-4. Save the vocab in "vocabulary_path"
      with gfile.GFile(vocabulary_path, mode="w") as vocab_file:
        for w in vocab_list:
          vocab_file.write(w + "\n")

# 1-4. Make index dictionary and word list
def initialize_vocab(vocabulary_path):

  if gfile.Exists(vocabulary_path):
    rev_vocab = []

    with gfile.GFile(vocabulary_path, mode="r") as f:
      rev_vocab.extend(f.readlines())
    rev_vocab = [line.strip() for line in rev_vocab]
    vocab = dict([(x, y) for (y, x) in enumerate(rev_vocab)])
    return vocab, rev_vocab
         # rev_vocab = [word1, word2, ...], vocab = {word1:index1, ...}

  else: # If not exist the file from "3"
    raise ValueError("Vocabulary file %s not found.", vocabulary_path)

# 1-5. String Sentence --) Index Sentence
def sentence_to_token_ids(sentence, vocabulary, UNK_ID,
                          tokenizer=None, normalize_digits=True):

  # 1-5-1.
  if tokenizer:
    words = tokenizer(sentence)
  else:
    words = basic_tokenizer(sentence)

  # 1-5-2.
  if not normalize_digits:
    return [vocabulary.get(w, UNK_ID) for w in words] # Use UNK_ID () If doesn`t exist in dic.
  return [vocabulary.get(re.sub(_DIGIT_RE, "0", w), UNK_ID) for w in words] # Normalize digits

# 1-6. Tokenize data and turn into token_index.
def data_to_token_ids(data_path, target_path, vocabulary_path,
                      tokenizer=None, normalize_digits=True, use_padding=True):

  if not gfile.Exists(target_path): # If there exists, Omit

    # 1-6-1.
    print("Tokenizing data in %s" % data_path)
    vocab, _ = initialize_vocab(vocabulary_path) # vocab = {word1 : idx1 , .. , ..}

    # 1-6-2.
    with gfile.GFile(data_path, mode="r") as data_file:
      with gfile.GFile(target_path, mode="w") as tokens_file:

        counter = 0
        for line in data_file:
          counter += 1
          if counter % 3 == 0:
            print("  tokenizing line %d" % counter)

          # 1-6-3.
          if use_padding:
            UNK_ID = UNK_ID_dict['with_padding'] # 1
          else:
            UNK_ID = UNK_ID_dict['no_padding'] # 0 --) UNK

          # 1-6-4.
          token_ids = sentence_to_token_ids(line, vocab, UNK_ID, tokenizer,
                                            normalize_digits) # tokenize the data by line
          tokens_file.write(" ".join([str(tok) for tok in token_ids]) + "\n")

# 1-7. Make index vocab (= labelling)
def create_label_vocab(vocabulary_path, data_path):

  if not gfile.Exists(vocabulary_path): # If exist, omit.
    print("Creating vocabulary %s from data %s" % (vocabulary_path, data_path))
    vocab = {}

    # 1-7-1. Read Data and get list of words.
    with gfile.GFile(data_path, mode="r") as f:

      # line counter
      counter = 0
      for line in f:
        counter += 1
        if counter % 3 == 0:
          print("  processing line %d" % counter)

        label = line.strip()
        vocab[label] = 1
      label_list = START_VOCAB_dict['no_padding'] + sorted(vocab) # [UNK, word1, word2, ...]

      # 1-7-2. Labeling (=Indexing)
      with gfile.GFile(vocabulary_path, mode="w") as vocab_file:
        for k in label_list:
          vocab_file.write(k + "\n")

# 1-8. string data --) token_index / make word and indec dictionary
def prepare_multi_task_data(data_dir, in_vocab_size, out_vocab_size):

    # data_dir = data/ATIS-sample
    # in_vocab_size = 10000 = out_vocab_size

    # 1-8-1. Get Path of train/dev/test Data.
    train_path = data_dir + '/train/train'
    dev_path = data_dir + '/valid/valid'
    test_path = data_dir + '/test/test'

    # 1-8-2. Get the vocab list and label vocab(=indexing) in dictionary.
    # 1-8-2-1. Make the vocab file path.
    in_vocab_path = os.path.join(data_dir, "in_vocab_%d.txt" % in_vocab_size)
    out_vocab_path = os.path.join(data_dir, "out_vocab_%d.txt" % out_vocab_size)
    label_path = os.path.join(data_dir, "label.txt")

    # 1-8-2-2. Make vocab list and label vocab(=indexing) in dictionary
    create_vocabulary(in_vocab_path,  train_path + ".seq.in",
                      in_vocab_size,  tokenizer=naive_tokenizer) # a
    create_vocabulary(out_vocab_path, train_path + ".seq.out",
                      out_vocab_size, tokenizer=naive_tokenizer) # b
    create_label_vocab(label_path, train_path + ".label")

    # 1-8-3. String data --) Token_index
    # 1-8-3-1. Get the path of indexing train data set.
    in_seq_train_ids_path = train_path + (".ids%d.seq.in" % in_vocab_size) # a
    out_seq_train_ids_path = train_path + (".ids%d.seq.out" % out_vocab_size) # b
    label_train_ids_path = train_path + (".ids.label")

    # 1-8-3-2. String data --) Token_idx
    # for train data
    data_to_token_ids(train_path + ".seq.in",
                      in_seq_train_ids_path,
                      in_vocab_path,
                      tokenizer=naive_tokenizer)
    data_to_token_ids(train_path + ".seq.out",
                      out_seq_train_ids_path,
                      out_vocab_path,
                      tokenizer=naive_tokenizer)
    data_to_token_ids(train_path + ".label",
                      label_train_ids_path,
                      label_path,
                      normalize_digits=False,
                      use_padding=False)
    # for dev data
    in_seq_dev_ids_path = dev_path + (".ids%d.seq.in" % in_vocab_size)
    out_seq_dev_ids_path = dev_path + (".ids%d.seq.out" % out_vocab_size)
    label_dev_ids_path = dev_path + (".ids.label")

    data_to_token_ids(dev_path + ".seq.in",
                      in_seq_dev_ids_path,
                      in_vocab_path,
                      tokenizer=naive_tokenizer)
    data_to_token_ids(dev_path + ".seq.out",
                      out_seq_dev_ids_path,
                      out_vocab_path,
                      tokenizer=naive_tokenizer)
    data_to_token_ids(dev_path + ".label",
                      label_dev_ids_path,
                      label_path,
                      normalize_digits=False,
                      use_padding=False)
    # for test data.
    in_seq_test_ids_path = test_path + (".ids%d.seq.in" % in_vocab_size)
    out_seq_test_ids_path = test_path + (".ids%d.seq.out" % out_vocab_size)
    label_test_ids_path = test_path + (".ids.label")

    data_to_token_ids(test_path + ".seq.in",
                      in_seq_test_ids_path,
                      in_vocab_path,
                      tokenizer=naive_tokenizer)
    data_to_token_ids(test_path + ".seq.out",
                      out_seq_test_ids_path,
                      out_vocab_path,
                      tokenizer=naive_tokenizer)
    data_to_token_ids(test_path + ".label",
                      label_test_ids_path,
                      label_path,
                      normalize_digits=False,
                      use_padding=False)

    return [(in_seq_train_ids_path,out_seq_train_ids_path,label_train_ids_path),
            (in_seq_dev_ids_path, out_seq_dev_ids_path, label_dev_ids_path),
            (in_seq_test_ids_path, out_seq_test_ids_path, label_test_ids_path),
            (in_vocab_path, out_vocab_path, label_path)]


from pandas import DataFrame, concat, date_range
import torch
import torch.nn as nn
from torch.utils.data import DataLoader, Dataset
import sklearn.preprocessing
import yfinance as yf
import numpy as np

""" This class returns a dataloader for the financial data for a ticker. """
class Load_financial_data():
    def __init__(self, stock, from_date, to_date, split=0.8, step=7, batch_size=1):
        self.stock = stock
        self.from_date = from_date
        self.to_date = to_date
        self.split = split
        self.step = step
        self.batch_size = batch_size

    # Create a differenced series
    def percentile_changes(self, data):
        changes = []
        for i in range(len(data)-1):
            p = data[i+1]/data[i]
            p -= 1
            p *= 100
            changes.append(p)
        return np.array(changes)

    def inverse_percentile_changes(self, x, dy):
        values = []
        values.append(x)
        for d in dy:
            p = (1+d/100.0)*values[-1]
            values.append(p)
        return values

    # Frame a sequence as a supervised learning problem
    def timeseries_to_supervised(self, data, lag=1):
        df = DataFrame(data)
        columns = [df.shift(i) for i in range(lag, 0, -1)]
        columns.append(df)
        df = concat(columns, axis=1)
        df.fillna(0, inplace=True)
        return df
    # Split into train and valid data
    def train_valid(self, data):
        data = np.array(self.percentile_changes(data))
        supervised = self.timeseries_to_supervised(data, self.step).values
        train = supervised[:self.split]
        valid = supervised[self.split:]
        return train[:,:-1], valid[:,:-1], train[:,-1], valid[:,-1]
    # Create dataloader for the financial data
    def get_loader(self):
        self.df = yf.download(self.stock,
                 start=self.from_date,
                 end=self.to_date,
                 progress=False)
        # Custom dataset
        class MyDataset(Dataset):
            def __init__(self, datas, labels):
                self.datas = datas
                self.labels = labels

            def __getitem__(self, index):
                data, target = self.datas[index], self.labels[index]
                return data, target

            def __len__(self):
                return len(self.datas)

        self.opening = list(self.df['Open'].values)
        self.high = list(self.df['High'].values)
        self.low = list(self.df['Low'].values)
        self.diff = list(self.df['High'].values-self.df['Low'].values)
        self.closing = list(self.df['Close'].values)
        self.adj = list(self.df['Adj Close'].values)
        self.volume = list(self.df['Volume'].values)

        self.split = int(self.split*len(self.opening))-1
        self.n = len(self.opening)-1

        thr = 0.6

        opening_train, opening_valid, _, _ = self.train_valid(self.opening)
        high_train, high_valid, _, _ = self.train_valid(self.high)
        low_train, low_valid, _, _ = self.train_valid(self.low)
        diff_train, diff_valid, _, _ = self.train_valid(self.diff)
        closing_train, closing_valid, self.y_train, self.y_valid = self.train_valid(self.closing)
        adj_train, adj_valid, _, _ = self.train_valid(self.adj)
        vol_train, vol_valid, _, _ = self.train_valid(self.volume)

        self.closing_train = self.closing[:self.split+1]
        self.closing_valid = self.closing[self.split+1:]

        self.x_train_tensor = torch.cat(
            (
                torch.tensor(opening_train).float().view(-1, 1, self.step),
                torch.tensor(high_train).float().view(-1, 1, self.step),
                torch.tensor(low_train).float().view(-1, 1, self.step),
                torch.tensor(closing_train).float().view(-1, 1, self.step),
                torch.tensor(adj_train).float().view(-1, 1, self.step),
                torch.tensor(vol_train).float().view(-1, 1, self.step)
            ),
            1
        )

        for i in range(len(self.y_train)):
            if self.y_train[i].item()<-thr:
                self.y_train[i] = 0
            elif self.y_train[i].item()>thr:
                self.y_train[i] = 2
            else:
                self.y_train[i] = 1
        self.y_train = torch.from_numpy(self.y_train).clone().long()
        self.y_train_tensor = self.y_train.clone()

        self.x_valid_tensor = torch.cat(
            (
                torch.tensor(opening_valid).float().view(-1, 1, self.step),
                torch.tensor(high_valid).float().view(-1, 1, self.step),
                torch.tensor(low_valid).float().view(-1, 1, self.step),
                torch.tensor(closing_valid).float().view(-1, 1, self.step),
                torch.tensor(adj_valid).float().view(-1, 1, self.step),
                torch.tensor(vol_valid).float().view(-1, 1, self.step)
            ),
            1
        )
        for i in range(len(self.y_valid)):
            if self.y_valid[i].item()<-thr:
                self.y_valid[i] = 0
            elif self.y_valid[i].item()>thr:
                self.y_valid[i] = 2
            else:
                self.y_valid[i] = 1
        self.y_valid = torch.from_numpy(self.y_valid).clone().long()
        self.y_valid_tensor = self.y_valid.clone()

        self.train_loader = DataLoader(MyDataset(self.x_train_tensor,
                                                 self.y_train_tensor),
                                       batch_size=self.batch_size, shuffle=False,
                                       num_workers=0,
                                       pin_memory=True)
        self.valid_loader = DataLoader(MyDataset(self.x_valid_tensor,
                                                self.y_valid_tensor),
                                      batch_size=self.batch_size, shuffle=False,
                                      num_workers=0,
                                      pin_memory=True)

        return self.train_loader, self.valid_loader,\
               self.closing_train, self.closing_valid,\
               self.y_train, self.y_valid


while True:
    a = int(input())
    r = 0
    if a == -1:
        break
    for i in range(2, int(a**0.5)+1):
        if a % i == 0:
            print(f"{a} is COMPOSITE TT")
            break
        elif i == int(a**0.5):
            print(f"{a} is PRIME!!")

Contests/CSEC Contests -3rd-Year/2nd Contest/primeOrNot.py


# Author: Jiafeng Cui
# cjfacl@gmail.com

import os
import time
import random
import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
from tqdm import tqdm
from eval.evaluate import evaluate
from losses.loss_factory import make_inc_loss
from misc.util import AverageMeter
from models.model_factory import model_factory
from datasets.dataset_util_inc import make_dataloader
from torchpack.utils.config import configs

class TrainerIncremental(nn.Module):
    def __init__(self, logger, memory, old_environment_pickle, new_environment_pickle, pretrained_checkpoint, env_idx):
        # Initialise inputs
        super(TrainerIncremental, self).__init__()
        self.debug = configs.debug
        self.logger = logger
        self.env_idx = env_idx
        self.epochs = configs.train.optimizer.epochs

        # Set up meters and stat trackers
        self.loss_total_meter = AverageMeter()
        self.loss_contrastive_meter = AverageMeter()
        self.loss_inc_meter = AverageMeter()
        self.positive_score_meter = AverageMeter()
        self.negative_score_meter = AverageMeter()
        # contrastive
        self.K = 1000
        self.m = 0.99
        self.T = 0.07
        # Make dataloader
        self.dataloader = make_dataloader(pickle_file = new_environment_pickle, memory = memory)

        # Build models and init from pretrained_checkpoint
        assert torch.cuda.is_available, 'CUDA not available.  Make sure CUDA is enabled and available for PyTorch'
        self.model_frozen = model_factory(ckpt = pretrained_checkpoint, device = 'cuda')
        self.model_new_q = model_factory(ckpt = pretrained_checkpoint, device = 'cuda')
        self.model_new_k = model_factory(ckpt = None, device = 'cuda')
        for param_q, param_k in zip(self.model_new_q.parameters(), self.model_new_k.parameters()):
            param_k.data.copy_(param_q.data)
            param_k.requires_grad = False
        self.register_buffer('queue_pcd', torch.randn(128, len(self.dataloader.dataset.queries)))
        self.queue_pcd = nn.functional.normalize(self.queue_pcd, dim=0).cuda()
        self.queue_pcd_index = set(range(len(self.dataloader.dataset.queries)))
        print("loading all embeddings")
        # loading queue
        for idx, (queries, keys, memories, labels) in enumerate(self.dataloader):
            query_size = int(len(labels)/2)
            queries = {x: queries[x].to('cuda') if x!= 'coords' else queries[x] for x in queries}
            with torch.no_grad():  # no gradient to keys
                embeddings, projectors = self.model_new_k(queries)
                projectors = nn.functional.normalize(projectors, dim=1)
            self._dequeue_and_enqueue_pcd_fast(projectors, labels[:query_size])
        print(f"finish constructing incremental_environments,size: {len(self.dataloader.dataset.queries)}")
        # Make optimizer
        if configs.train.optimizer.name == "SGD":
            self.optimizer = torch.optim.SGD(self.model_new_q.parameters(), lr=configs.train.optimizer.lr,
                                        momentum=configs.train.optimizer.momentum,
                                        weight_decay=configs.train.optimizer.weight_decay)
        else:
            self.optimizer = torch.optim.Adam(self.model_new_q.parameters(), lr=configs.train.optimizer.lr, weight_decay=configs.train.optimizer.weight_decay)

        # Scheduler
        if configs.train.optimizer.scheduler is None:
            self.scheduler = None
        else:
            if configs.train.optimizer.scheduler == 'CosineAnnealingLR':
                self.scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(self.optimizer, T_max=configs.train.optimizer.epochs+1,
                                                                    eta_min=configs.train.optimizer.min_lr)
            elif configs.train.optimizer.scheduler == 'MultiStepLR':
                if not isinstance(configs.train.optimizer.scheduler_milestones, list):
                    configs.train.optimizer.scheduler_milestones = [configs.train.optimizer.scheduler_milestones]
                self.scheduler = torch.optim.lr_scheduler.MultiStepLR(self.optimizer, configs.train.optimizer.scheduler_milestones, gamma=0.1)
            else:
                raise NotImplementedError('Unsupported LR scheduler: {}'.format(configs.train.optimizer.scheduler))

        # Make loss functions
        self.inc_fn = make_inc_loss()
        self.criterion = nn.CrossEntropyLoss().cuda()

    @torch.no_grad()
    def _momentum_update_key_encoder(self):
        """
        Momentum update of the key encoder
        """
        for param_q, param_k in zip(self.model_new_q.parameters(), self.model_new_k.parameters()):
            param_k.data = param_k.data * self.m + param_q.data * (1. - self.m)

    @torch.no_grad()
    def _dequeue_and_enqueue_pcd_fast(self, keys, labels):
        self.queue_pcd[:, labels] = keys.T

    '''
        reset epoch metrics
    '''
    def before_epoch(self, epoch):
        # Reset meters
        self.loss_total_meter.reset()
        self.loss_inc_meter.reset()
        self.loss_contrastive_meter.reset()
        self.positive_score_meter.reset()
        self.negative_score_meter.reset()
        # Adjust weight of incremental loss function if constraint relaxation enabled
        self.inc_fn.adjust_weight(epoch)

    '''
        1. clear the gradient of weights -------> self.optimizer.zero_grad()
        2. model forward
        3. calculate the loss
        4. calculate the gradients -------------> loss.backward()
        5. update the weights ------------------> self.optimizer.step()
        6. empty CUDA cache
        7. update epoch metrics
    # '''
    def training_step(self, queries, keys, memories, labels):
        memories = {x: memories[x].to('cuda') if x!= 'coords' else memories[x] for x in memories}
        queries = {x: queries[x].to('cuda') if x!= 'coords' else queries[x] for x in queries}
        keys = {x: keys[x].to('cuda') if x!= 'coords' else keys[x] for x in keys}
        anchor_size = int(len(labels)/4)
        key_labels = labels[anchor_size:2*anchor_size] + labels[:anchor_size]
        # Get embeddings and Loss
        self.optimizer.zero_grad()
        embeddings, projectors = self.model_new_q(queries)
        projectors = nn.functional.normalize(projectors, dim=1)
        embeddings_memories, projectors_memories = self.model_new_q(memories)
        projectors_memories = nn.functional.normalize(projectors_memories, dim=1)
        with torch.no_grad():
            self._momentum_update_key_encoder()
            _, key_projectors_new = self.model_new_k(keys)
            key_projectors_new = nn.functional.normalize(key_projectors_new, dim=1)
            embeddings_memories_frozen, projectors_memories_frozen = self.model_frozen(memories)
            projectors_memories_frozen = nn.functional.normalize(projectors_memories_frozen, dim=1)

        # compute logits
        # positive logits: Nx1
        l_pos_pcd = torch.einsum('nc,nc->n', [projectors, key_projectors_new]).unsqueeze(-1)
        queue_pcd_clone = self.queue_pcd.clone().detach()
        negatives_list = []
        for index in range(len(labels[:2*anchor_size])):
            negative_index = random.sample(list(self.queue_pcd_index.difference(set(self.dataloader.dataset.queries[labels[index]].non_negatives))), self.K)
            negatives_list.append(queue_pcd_clone[:,negative_index])
        negatives_tensor = torch.stack(negatives_list, dim=0)
        # negative logits: NxK
        l_neg_pcd = torch.einsum('nc,nck->nk', [projectors, negatives_tensor])
        positive_score = torch.mean(l_pos_pcd)
        negative_score = torch.mean(l_neg_pcd)

        logits_pcd = torch.cat([l_pos_pcd, l_neg_pcd], dim=1)
        logits_pcd_contrastive = logits_pcd / self.T
        labels_pcd = torch.zeros(logits_pcd_contrastive.shape[0], dtype=torch.long).cuda()
        loss_contrastive = self.criterion(logits_pcd_contrastive, labels_pcd)

        loss_distill = self.inc_fn(projectors_memories_frozen, projectors_memories)
        loss_total = loss_contrastive + loss_distill

        # dequeue and enqueue
        self._dequeue_and_enqueue_pcd_fast(key_projectors_new, key_labels)
        # Backwards
        loss_total.backward()
        self.optimizer.step()
        torch.cuda.empty_cache() # Prevent excessive GPU memory consumption by SparseTensors

        # Stat tracking
        self.loss_total_meter.update(loss_total.item())
        self.loss_contrastive_meter.update(loss_contrastive.item())
        self.loss_inc_meter.update(loss_distill.item())
        self.positive_score_meter.update(positive_score.item())
        self.negative_score_meter.update(negative_score.item())

    '''
        # 1. update learning rate
        # 2. update batch size
        # 3. save log data
    '''
    def after_epoch(self, epoch):
        # Scheduler
        if self.scheduler is not None:
            self.scheduler.step()

        # Tensorboard plotting
        self.logger.add_scalar(f'Step_{self.env_idx}/Total_Loss_epoch', self.loss_total_meter.avg, epoch)
        self.logger.add_scalar(f'Step_{self.env_idx}/Contrastive_Loss_epoch', self.loss_contrastive_meter.avg, epoch)
        self.logger.add_scalar(f'Step_{self.env_idx}/Increment_Loss_epoch', self.loss_inc_meter.avg, epoch)
        self.logger.add_scalar(f'Step_{self.env_idx}/positive_score_epoch', self.positive_score_meter.avg, epoch)
        self.logger.add_scalar(f'Step_{self.env_idx}/negative_score_epoch', self.negative_score_meter.avg, epoch)

    # for loop on epochs
    def train(self):
        for epoch in tqdm(range(1, self.epochs + 1)):
            self.before_epoch(epoch)
            for idx, (queries, keys, memories, labels) in enumerate(self.dataloader):
                self.training_step(queries, keys, memories, labels)
                if self.debug and idx > 2:
                    break

            self.after_epoch(epoch)
            if self.debug and epoch > 2:
                break

        return self.model_new_q


import sys
import threading
import traceback

from reporter.HtmlReporter import HtmlReporter
from data_handler.Xlsx_File_Handler import Xlsx_File_Handler
import properties as config
from dateutil.parser import parse
from data_handler.DB_Connection_Provider import DB_Connection_Provider

class ErrorEncounterException(Exception):
    def __init__(self, message):
        super().__init__(message)

class ValidationFailedException(Exception):
    def __init__(self, message):
        super().__init__(message)

class Comparator:
    fr = None
    cursor_1 = None
    cursor_2 = None
    columns_to_exclude_in_comparison = ['year']
    out_csv = None
    xlsx_fh = None
    total_pass = 0
    total_fail = 0

    def __init__(self, report_name, table_name, number_of_records_to_match, partition_1, partition_2):
        self.report_name = report_name
        self.table_name = table_name
        self.number_of_records_to_match = number_of_records_to_match
        self.reporter = HtmlReporter(report_name=report_name)
        self.partition_1 = partition_1
        self.partition_2 = partition_2

    def validate_result(self,
                        scenario_name,
                        exp_result,
                        actual_result,
                        status=None,
                        exit_on_failure=False,
                        comment=''):

        if status is None:
            if exp_result == actual_result:
                status = 'pass'
            else:
                status = 'fail'
            if comment != '':
                status = 'error'
        self.reporter.add_scenario_result(scenario_name, str(exp_result), str(actual_result),
                                          status, comment)
        if status == 'fail' and exit_on_failure:
            self.teardown()
            raise ValidationFailedException('Validation failed! Stopped further processing!')
        elif status == 'error' and exit_on_failure:
            self.teardown()
            # raise ErrorEncounterException.ErrorEncounterException('Some error occurred! Stopped processing')

    def start_comparison(self):
        try:
            # get database connection and execute fetch query
            db_con = DB_Connection_Provider().get_db_connection()
            self.cursor_1 = db_con.cursor()
            self.cursor_2 = db_con.cursor()
            sql_query_1 = f'Select * from {self.table_name} PARTITION ({self.partition_1})'
            sql_query_2 = f'Select * from {self.table_name} PARTITION ({self.partition_2})'
            print(f'Querying DB with -- {sql_query_1}')
            rs1 = self.cursor_1.execute(sql_query_1)
            print(f'Querying DB with -- {sql_query_2}')
            rs2 = self.cursor_2.execute(sql_query_2)

            partition_1 = rs1.fetchmany(config.BUFFER_NUMBER_OF_DB_ROWS)
            partition_2 = rs2.fetchmany(config.BUFFER_NUMBER_OF_DB_ROWS)

            table_headers = [d[0].lower() for d in rs1.description]

            # adding db table columns as table headers in html report
            self.reporter.add_db_column_names_as_headers(table_headers)

            # opening an xlsx file to store the comparison result
            self.xlsx_fh = Xlsx_File_Handler(self.report_name.replace('.html', '.xlsx'),
                                             table_headers)

            number_of_row_checked = 0
            progress_update_count = int(self.number_of_records_to_match / 100)
            slider_count = 1
            print('\nComparison started ... ')
            while True and number_of_row_checked <= self.number_of_records_to_match:
                # iterate all the rows in result set and check against the file
                for index, db_row_partition_1 in enumerate(partition_1):
                    if number_of_row_checked == self.number_of_records_to_match:
                        number_of_row_checked += 1
                        break
                    if number_of_row_checked == (progress_update_count * slider_count):
                        self.update_progress(slider_count)
                        slider_count += 1

                    partition_1_row = partition_1[index]
                    partition_2_row = partition_2[index]
                    current_row_matched = True

                    unmatched_values = {}
                    unmatched_indexes = []
                    for i, header in enumerate(table_headers):
                        if header in self.columns_to_exclude_in_comparison:
                            continue
                        if str(partition_1_row[i]) == str(partition_2_row[i]):
                            continue
                        else:
                            current_row_matched = False
                            unmatched_values[header] = f'{partition_1_row[i]} <==> {partition_2_row[i]}'
                            unmatched_indexes.append(i)

                    if current_row_matched:
                        self.total_pass += 1

                        # writing comparison result in html report
                        threading.Thread(target=self.reporter.add_scenario_result_as_table_formatted_data,
                                         args=('Comparing DB row ',
                                               partition_1_row,
                                               partition_2_row,
                                               'pass')).start()

                        # writing comparison result in xlsx file
                        if self.total_pass <= config.MAX_NUMBER_OF_SUCCESS_CASES_TO_REPORT:
                            threading.Thread(target=self.xlsx_fh.write_partition1_and_partition2_row_in_xlsx_file,
                                             args=(
                                                 partition_1_row,
                                                 partition_2_row,
                                             )).start()
                    else:
                        self.total_fail += 1
                        # writing comparison result in html report
                        threading.Thread(target=self.reporter.add_scenario_result_as_table_formatted_data,
                                         args=('Comparing DB row ',
                                               partition_1_row,
                                               partition_2_row,
                                               'fail', '',
                                               unmatched_indexes
                                               )).start()

                        # writing comparison result in xlsx file
                        if self.total_fail <= config.MAX_NUMBER_OF_FAILURE_CASES_TO_REPORT:
                            threading.Thread(target=self.xlsx_fh.write_partition1_and_partition2_row_in_xlsx_file,
                                             args=(
                                                 partition_1_row,
                                                 partition_2_row,
                                                 unmatched_indexes
                                             )).start()
                    number_of_row_checked += 1

                # fetch next chuck of data from database
                partition_1 = rs1.fetchmany(config.BUFFER_NUMBER_OF_DB_ROWS)
                partition_2 = rs2.fetchmany(config.BUFFER_NUMBER_OF_DB_ROWS)

                # check if we have reached to the end of table
                if not partition_1:
                    break
            self.update_progress(100)
            print('\nprocessed data file completely.')
            self.teardown()
        except Exception as e:
            if isinstance(e, ValidationFailedException):
                return
            print('Some error occurred while processing the file.')
            print(f'full traceback --- {traceback.format_exc()}')
            self.validate_result('Checking for any error while execution',
                                 'No Error should be encountered',
                                 'Error occurred',
                                 exit_on_failure=False,
                                 comment=f'error -- {traceback.format_exc()}')
            self.teardown()

    def is_date(self, string, fuzzy=False):
        """
        Return whether the string can be interpreted as a date.

        :param string: str, string to check for date
        :param fuzzy: bool, ignore unknown tokens in string if True
        """
        try:
            parse(string, fuzzy=fuzzy)
            return True

        except ValueError:
            return False

    def teardown(self):
        self.reporter.save_report()
        if self.fr is not None:
            print('closing data file ... !')
            self.fr.close_file()
            print('data file closed successfully !!')
            del self.fr
        if self.cursor_1 is not None:
            print('closing database connection ... !')
            self.cursor_1.close()
            print('database connection closed successfully !!')
            del self.cursor_1
        if self.cursor_2 is not None:
            print('closing database connection ... !')
            self.cursor_2.close()
            print('database connection closed successfully !!')
            del self.cursor_2
        if self.out_csv is not None:
            print('Closing out_csv file ... !')
            self.out_csv.flush()
            self.out_csv.close()
            print('Closed out_csv file successfully !!')
            del self.out_csv
        if self.xlsx_fh is not None:
            self.xlsx_fh.save_xlsx_file()
            del self.xlsx_fh

    def update_progress(self, progress):
        sys.stdout.write('\r[{0}] {1}%'.format('#' * progress, progress))
        sys.stdout.flush()


import os
import sys
import time
os.environ["CUDA_VISIBLE_DEVICES"] = "-1"  # This line is commented out to use gpu, uncommented is to use cpu
import tensorflow as tf
from tensorflow.keras.preprocessing import image
gpus = tf.config.list_physical_devices("GPU")
print(gpus)
if gpus:
    gpu0 = gpus[0]  # If there are multiple GPUs, only the 0th GPU is used
    tf.config.experimental.set_memory_growth(gpu0, True)  # GPU memory usage on demand
    tf.config.set_visible_devices([gpu0], "GPU")
from matplotlib.pyplot import imshow
from tensorflow.keras.layers import Input
from tensorflow.keras import backend as K
from tensorflow.keras.models import Model
from tensorflow.keras import optimizers
from mmd import MMD
from tensorflow.keras.layers import Flatten
import matplotlib.pyplot as pyplot
import matplotlib
import matplotlib.pyplot as plt
import keras_metrics as km
# import tensorflow
from tensorflow.keras import regularizers
from tensorflow.keras.layers import GlobalMaxPooling1D,GlobalMaxPooling2D,Permute,Lambda,Concatenate,multiply,GlobalAveragePooling2D,Reshape,Add
# from tensorflow.keras import optimizers
from tensorflow.keras.layers import Conv2D
from tensorflow.keras.layers import MaxPooling2D
from tensorflow.keras.layers import concatenate
import numpy as np
from sklearn.metrics import precision_recall_fscore_support
from sklearn.metrics import accuracy_score
from tensorflow.keras.layers import Dense, Dropout, Flatten
from tensorflow.keras.layers import Activation
from tensorflow.keras.layers import Conv1D, MaxPooling1D
from tensorflow.keras.layers import BatchNormalization
# from sklearn.preprocessing import OneHotEncoder  # LabelBinarizer
from multiinputmodel import AdaBoostClassifiermulti as Ada_CNN
import cv2

trainend=1000
trainend1=65000
testend=87300
testshape=testend-trainend1
#所有数据
X_data1=np.load('X_dataall1.npy')
X_train1=X_data1[0:trainend,:,:].reshape((trainend, 29, 78, 1))
X_test1=X_data1[trainend1:testend,:,:].reshape((testshape, 29, 78, 1))
X_data2=np.load('X_dataall2.npy')
X_train2=X_data2[0:trainend,:,:].reshape((trainend, 29, 78, 1))
X_test2=X_data2[trainend1:testend,:,:].reshape((testshape, 29, 78, 1))
X_data3=np.load('X_dataall3.npy')
X_train3=X_data3[0:trainend,:].reshape((trainend, 64,1))
X_test3=X_data3[trainend1:testend,:].reshape((testshape, 64,1))
X_data4=np.load('X_dataall4.npy')
X_train4=X_data4[0:trainend,:].reshape((trainend,64,1))
X_test4=X_data4[trainend1:testend,:].reshape((testshape,64,1))
Y_data=np.load('Y_labelall.npy')
Y_data=Y_data[0]
y_train=Y_data[0:trainend]
y_test=Y_data[trainend1:testend]

def cbam_block(cbam_feature, ratio=8):#attention module
    cbam_feature = channel_attention(cbam_feature, ratio)#channel_attention
    cbam_feature = spatial_attention(cbam_feature)#spatial_attention
    return cbam_feature
def channel_attention(input_feature, ratio=8):
    channel_axis = 1 if K.image_data_format() == "channels_first" else -1
    channel = input_feature.shape[channel_axis]
    shared_layer_one = Dense(channel // ratio,
                             activation='relu',
                             kernel_initializer='he_normal',
                             use_bias=True,
                             bias_initializer='zeros')
    shared_layer_two = Dense(channel,
                             kernel_initializer='he_normal',
                             use_bias=True,
                             bias_initializer='zeros')

    avg_pool = GlobalAveragePooling2D()(input_feature)
    avg_pool = Reshape((1, 1, channel))(avg_pool)
    # assert avg_pool.shape[1:] == (1, 1, channel)
    avg_pool = shared_layer_one(avg_pool)
    # assert avg_pool.shape[1:] == (1, 1, channel // ratio)
    avg_pool = shared_layer_two(avg_pool)
    # assert avg_pool.shape[1:] == (1, 1, channel)

    max_pool = GlobalMaxPooling2D()(input_feature)
    max_pool = Reshape((1, 1, channel))(max_pool)
    # assert max_pool.shape[1:] == (1, 1, channel)
    max_pool = shared_layer_one(max_pool)
    # assert max_pool.shape[1:] == (1, 1, channel // ratio)
    max_pool = shared_layer_two(max_pool)
    # assert max_pool.shape[1:] == (1, 1, channel)
    cbam_feature = Add()([avg_pool, max_pool])
    cbam_feature = Activation('sigmoid')(cbam_feature)

    if K.image_data_format() == "channels_first":
        cbam_feature = Permute((3, 1, 2))(cbam_feature)

    return multiply([input_feature, cbam_feature])
def spatial_attention(input_feature):
    kernel_size = 3
    if K.image_data_format() == "channels_first":
        channel = input_feature.shape[1]
        cbam_feature = Permute((2, 3, 1))(input_feature)
    else:
        channel = input_feature.shape[-1]
        cbam_feature = input_feature

    avg_pool = Lambda(lambda x: K.mean(x, axis=3, keepdims=True))(cbam_feature)
    assert avg_pool.shape[-1] == 1
    max_pool = Lambda(lambda x: K.max(x, axis=3, keepdims=True))(cbam_feature)
    assert max_pool.shape[-1] == 1
    concat = Concatenate(axis=3)([avg_pool, max_pool])
    assert concat.shape[-1] == 2
    cbam_feature = Conv2D(filters=1,
                          kernel_size=kernel_size,
                          strides=1,
                          padding='same',
                          activation='sigmoid',
                          kernel_initializer='he_normal',
                          use_bias=False)(concat)
    assert cbam_feature.shape[-1] == 1

    if K.image_data_format() == "channels_first":
        cbam_feature = Permute((3, 1, 2))(cbam_feature)

    return multiply([input_feature, cbam_feature])
def lossall(model):
    def binary_loss(y_true, y_pred):
        loss1 = tf.keras.losses.binary_crossentropy(y_true, y_pred)
        return loss1
    return binary_loss
    # loss1 = tf.keras.losses.BinaryCrossentropy
    fea1=model.get_layer('conv2d').output
    fea2 = model.get_layer('conv2d_4').output
    fea3 = model.get_layer('conv2d_1').output
    fea4 = model.get_layer('conv2d_5').output
    fea5 = model.get_layer('conv2d_2').output
    fea6 = model.get_layer('conv2d_6').output
    lossconv1 = tf.square(MMD(tf.reshape(fea1[:,:,:,1], [15, 39]), tf.reshape(fea2[:,:,:,1], [15, 39]), beta=1))#maximum mean discrepancy
    lossconv2 = tf.square(MMD(tf.reshape(fea3[:, :, :, 1], [7, 19]), tf.reshape(fea4[:, :, :, 1], [7, 19]), beta=1))
    lossconv3 = tf.square(MMD(tf.reshape(fea5[:, :, :, 1], [3, 9]), tf.reshape(fea6[:, :, :, 1], [3, 9]), beta=1))
    loss=1*lossconv1/1+1*lossconv2/1+1*lossconv3/1+loss1
    print(lossconv1)
    return loss
def baseline_model():
    visible1 = Input(shape=(29, 78, 1))
    # sam11 = spatial_attention(visible1)
    conv11 = Conv2D(2, kernel_size=16,padding= "same",strides=2)(visible1)
    BatchNormalization11 = BatchNormalization()(conv11)
    act11 = Activation('relu')(BatchNormalization11)
    pool11 = MaxPooling2D(pool_size=2,strides=2)(act11)
    conv12 = Conv2D(4, kernel_size=8,padding= "same")(pool11)
    BatchNormalization12 = BatchNormalization()(conv12)
    act12 = Activation('relu')(BatchNormalization12)
    pool12 = MaxPooling2D(pool_size=2,strides=2)(act12)
    conv13 = Conv2D(8, kernel_size=4, padding="same")(pool12)
    BatchNormalization13 = BatchNormalization()(conv13)
    act13 = Activation('relu')(BatchNormalization13)
    pool13 = MaxPooling2D(pool_size=3,strides=2)(act13)
    sam1 = cbam_block(pool13)
    # sam1=pool13
    # pool13 = MaxPooling2D(pool_size=4,strides=2)(act13)
    flat11 = GlobalMaxPooling2D()(sam1)
    # flat12 = GlobalMaxPooling2D()(sam11)
    # flat13 = GlobalMaxPooling2D()(sam12)
    # flat1 = Flatten()(pool13)
    visible2 = Input(shape=(29,78,1))
    conv21 = Conv2D(2, kernel_size=16, padding="same", strides=2)(visible2)
    BatchNormalization21 = BatchNormalization()(conv21)
    act21 = Activation('relu')(BatchNormalization21)
    pool21 = MaxPooling2D(pool_size=2, strides=2)(act21)
    conv22 = Conv2D(4, kernel_size=8, padding="same")(pool21)
    BatchNormalization22 = BatchNormalization()(conv22)
    act22 = Activation('relu')(BatchNormalization22)
    pool22 = MaxPooling2D(pool_size=2, strides=2)(act22)
    conv23 = Conv2D(8, kernel_size=4, padding="same")(pool22)
    BatchNormalization23 = BatchNormalization()(conv23)
    act23 = Activation('relu')(BatchNormalization23)
    pool23 = MaxPooling2D(pool_size=3, strides=2)(act23)
    sam2 = cbam_block(pool23)
    # sam2=pool23
    flat21 = GlobalMaxPooling2D()(sam2)
    visible3 = Input(shape=(64, 1))
    conv31 = Conv1D(2, kernel_size=32,padding= "same",strides=2)(visible3)
    BatchNormalization31 = BatchNormalization()(conv31)
    act31 = Activation('relu')(BatchNormalization31)
    pool31 = MaxPooling1D(pool_size=2,strides=2)(act31)
    conv32 = Conv1D(4, kernel_size=16,padding= "same",strides=2)(pool31)
    BatchNormalization32 = BatchNormalization()(conv32)
    act32 = Activation('relu')(BatchNormalization32)
    pool32 = MaxPooling1D(pool_size=2,strides=2)(act32)
    conv33 = Conv1D(8, kernel_size=8, padding="same")(pool32)
    BatchNormalization33 = BatchNormalization()(conv33)
    act33 = Activation('relu')(BatchNormalization33)
    pool33 = MaxPooling1D(pool_size=3, strides=2)(act33)
    flat3 = GlobalMaxPooling1D()(pool33)
    # flat3 = Flatten()(pool33)
    # second input model
    visible4 = Input(shape=(64, 1))
    conv41 = Conv1D(2, kernel_size=32, padding="same", strides=2)(visible4)
    BatchNormalization41 = BatchNormalization()(conv41)
    act41 = Activation('relu')(BatchNormalization41)
    pool41 = MaxPooling1D(pool_size=2, strides=2)(act41)
    conv42 = Conv1D(4, kernel_size=16, padding="same", strides=2)(pool41)
    BatchNormalization42 = BatchNormalization()(conv42)
    act42 = Activation('relu')(BatchNormalization42)
    pool42 = MaxPooling1D(pool_size=2, strides=2)(act42)
    conv43 = Conv1D(8, kernel_size=8, padding="same")(pool42)
    BatchNormalization43 = BatchNormalization()(conv43)
    act43 = Activation('relu')(BatchNormalization43)
    pool43 = MaxPooling1D(pool_size=4,strides=2)(act43)
    flat4 = GlobalMaxPooling1D()(pool43)
    # flat4 = Flatten()(pool43)
    # merge input models
    # merge = concatenate([flat1, flat2,flat3,flat4])
    merge = concatenate([flat11,flat21,flat3,flat4])
    # # interpretation model
    hidden1 = Dense(16, activation='relu')(merge)
    # # # 在分类器之前使用
    dropout1=Dropout(0.5)(hidden1)
    hidden2 = Dense(8, activation='relu',kernel_regularizer=regularizers.l2(0.01))(dropout1)
    output = Dense(2, activation='softmax')(hidden2)
    model = Model(inputs=[visible1, visible2,visible3,visible4], outputs=output)
    model.summary()
    adam = optimizers.Adam(learning_rate=0.003)
    model.compile(loss=[lossall(model)], optimizer='adam', metrics=[km.f1_score(), km.precision(), km.recall()])
    # optimizer = tf.compat.v1.train.AdamOptimizer(learning_rate=util.learning_rate).minimize(loss)
    # adam=optimizers.Adam(learning_rate=0.001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)
    # model.compile(loss='BinaryCrossentropy', optimizer='adam', metrics=[km.f1_score(), km.precision(), km.recall()])  # adagrad metrics=['accuracy'])
    return model
list1=[]
batch_size = [32]#8,16,32,64,128,256 ...
n_estimators =[15]#5,10,15,20,25,30,40,50...
epochs = [25]#15,20,25,30,40,50...
a=np.linspace(1,2,5)
aa=a.tolist()
b=np.linspace(3,10,7)
bb=a.tolist()
learning_rate=[0.1]#sample weight 0.1,0.5,1,1.5,2,3...
imbalance=[3]#initial 0.1,0.5,1,3,5,10...
probacoefficient=[1]
algrithom=['SAMME.R']

for i in range(len(n_estimators)):
    for z in range(len(epochs)):
        for a in range(len(learning_rate)):
            for k in range(len(batch_size)):
                for f in range(len(imbalance)):
                    for j in range(len(probacoefficient)):
                        for l in range(len(algrithom)):
                                bdt_real_test_CNN = Ada_CNN(
                                base_estimator=baseline_model(),
                                n_estimators=n_estimators[i],
                                learning_rate=learning_rate[a],
                                imbalance=imbalance[f],
                                probacoefficient=probacoefficient[j],
                                algorithm=algrithom[l],
                                epochs=epochs[z])
                                time_start = time.time()
                                bdt_real_test_CNN.fit([X_train1,X_train2,X_train3,X_train4],y_train,batch_size[k])
                                time_end = time.time()
                                print(time_end-time_start)
                                # joblib.dump(bdt_real_test_CNN, "train_model.m")#save
                                # bdt_real_test_CNN = joblib.load("train_model.m")
                                # test_real_errors_CNN=bdt_real_test_CNN.estimator_errors_[:]
                                y_pred_CNN = bdt_real_test_CNN.predict([X_test1,X_test2,X_test3,X_test4])
                                print('\n Training accuracy of bdt_real_test_CNN (AdaBoost+CNN): {}'.format(
                                accuracy_score(y_pred_CNN, y_test)))
                                # y_pred_CNN = bdt_real_test_CNN.predict([X_test1, X_test2, X_test3, X_test4])
                                p_class, r_class, f_class, support_micro = precision_recall_fscore_support(y_pred_CNN, y_test, average=None)
                                print(p_class,r_class,f_class)
                                line = [p_class[1],r_class[1],f_class[1]]
                                list1.append(line)
                                print(list1)
                                indexerror=np.arange(0,len(y_pred_CNN))
                                classerror=indexerror[y_pred_CNN != y_test]
                                IndexError = [y_test[index] for index in classerror]
                                ERROR=y_test[classerror]
                                # for i in range(0,len(classerror)):
                                #         plt.subplot(2, 2, 1)
                                #         plt.imshow(X_test1[classerror[i], :, :, :])
                                #         plt.subplot(2, 2, 2)
                                #         plt.imshow(X_test2[classerror[i], :, :, :])
                                #         plt.subplot(2, 2, 3)
                                #         plt.plot(X_test3[classerror[i], :,:])
                                #         plt.subplot(2, 2, 4)
                                #         plt.plot(X_test4[classerror[i], :,:])
                                #         plt.show()
                                # aaaaaa = bdt_real_test_CNN.estimators_[0]
                                # # time_start1 = time.time()
                                # y_pred1111 = aaaaaa.predict([X_test1, X_test2, X_test3, X_test4])
                                # # time_end1 = time.time()
                                # # time1=time_end1-time_start1
                                # # print(time1)
                                # y_pred111 = np.argmax(y_pred1111, axis=1)
                                # p_class1, r_class1, f_class1, support_micro1 = precision_recall_fscore_support(y_pred111,
                                #                                                                         y_test,
                                #                                                                         average=None)

time111=time_end-time_start


from socket import *
s = socket(AF_INET, SOCK_STREAM)
s.bind(('', 3333))
s.listen(5)
print('waiting...')
while True:
    client, addr = s.accept()
    print('connection from ', addr)
    while True:
        data = client.recv(1024)
        if not data:
            break
        temp = data.decode()
        if '+' in temp:
            temp = temp.split('+')
            a,b = temp
            result = str(int(a)+int(b))
            client.send(result.encode())
        elif '-' in temp:
            temp = temp.split('-')
            a,b = temp
            result = str(int(a)-int(b))
            client.send(result.encode())
        elif '*' in temp:
            temp = temp.split('*')
            a,b = temp
            result = str(int(a)*int(b))
            client.send(result.encode())
        elif '/' in temp:
            temp = temp.split('/')
            a,b = temp
            t = round(int(a)/int(b),1)
            result = str(t)
            client.send(result.encode())

    client.close()


from unittest import TestCase

from marshmallow import EXCLUDE, fields

from ...models.base import BaseModel, BaseModelSchema

from ..base import BaseDecoratorSet
from ..default import DecoratorSet, DEFAULT_MODELS

class SimpleModel(BaseModel):
    class Meta:
        schema_class = "SimpleModelSchema"

    def __init__(self, *, value: str = None, handled_decorator: str = None, **kwargs):
        super().__init__(**kwargs)
        self.handled_decorator = handled_decorator
        self.value = value

class SimpleModelSchema(BaseModelSchema):
    class Meta:
        model_class = SimpleModel
        unknown = EXCLUDE

    value = fields.Str(required=True)
    handled_decorator = fields.Str(required=False, data_key="handled~decorator")

class TestDecoratorSet(TestCase):
    def test_deco_set(self):
        deco_set = DecoratorSet()
        assert all(k in deco_set.models for k in DEFAULT_MODELS)

    def test_extract(self):
        decor_value = {}
        message = {"~decorator": decor_value, "one": "TWO"}

        decors = BaseDecoratorSet()
        remain = decors.extract_decorators(message)

        # check original is unmodified
        assert "~decorator" in message

        assert decors["decorator"] is decor_value
        assert remain == {"one": "TWO"}

    def test_dict(self):
        decors = BaseDecoratorSet()
        decors["test"] = "TEST"
        assert decors["test"] == "TEST"
        result = decors.to_dict()
        assert result == {"~test": "TEST"}

    def test_decorator_model(self):
        decor_value = {}
        message = {"~test": {"value": "TEST"}}

        decors = BaseDecoratorSet()
        decors.add_model("test", SimpleModel)
        remain = decors.extract_decorators(message, SimpleModelSchema)

        tested = decors["test"]
        assert isinstance(tested, SimpleModel) and tested.value == "TEST"

        result = decors.to_dict()
        assert result == message

    def test_field_decorator(self):
        decor_value = {}
        message = {"test~decorator": decor_value, "one": "TWO"}

        decors = BaseDecoratorSet()
        remain = decors.extract_decorators(message, SimpleModelSchema)

        # check original is unmodified
        assert "test~decorator" in message

        assert decors.field("test")
        assert decors.field("test")["decorator"] is decor_value
        assert remain == {"one": "TWO"}
        assert "test~decorator" in decors.to_dict()

    def test_skip_decorator(self):
        decor_value = {}
        message = {"handled~decorator": decor_value, "one": "TWO"}

        decors = BaseDecoratorSet()
        remain = decors.extract_decorators(message, SimpleModelSchema)

        # check original is unmodified
        assert "handled~decorator" in message

        assert not decors.field("handled")
        assert remain == message
        assert not decors.to_dict()


import matplotlib.pyplot as plt
import numpy as np

def _invert(x, limits):
    """inverts a value x on a scale from
    limits[0] to limits[1]"""
    return limits[1] - (x - limits[0])

def _scale_data(data, ranges):
    """scales data[1:] to ranges[0],
    inverts if the scale is reversed"""
    for d, (y1, y2) in zip(data[1:], ranges[1:]):
        assert (y1 <= d <= y2) or (y2 <= d <= y1)
    x1, x2 = ranges[0]
    d = data[0]
    if x1 > x2:
        d = _invert(d, (x1, x2))
        x1, x2 = x2, x1
    sdata = [d]
    for d, (y1, y2) in zip(data[1:], ranges[1:]):
        if y1 > y2:
            d = _invert(d, (y1, y2))
            y1, y2 = y2, y1
        sdata.append((d-y1) / (y2-y1)
                     * (x2 - x1) + x1)
    return sdata

class ComplexRadar():
    def __init__(self, fig, variables, ranges, n_ordinate_levels=6):
        angles = np.arange(0, 360, 360./len(variables))

        axes = [fig.add_axes([0.1,0.1,0.9,0.9], polar=True,
            label = "axes{}".format(i))
            for i in range(len(variables))]

        l, text = axes[0].set_thetagrids(angles, labels=variables)

        [[txt.set_fontweight('bold'),
              txt.set_fontsize(12),
              txt.set_position((0,-0.2))] for txt in text]

        for ax in axes[1:]:
            ax.patch.set_visible(False)
            ax.grid("off")
            ax.xaxis.set_visible(False)

        for i, ax in enumerate(axes):
            grid = np.linspace(*ranges[i], num=n_ordinate_levels)
            gridlabel = ["{}".format(round(x,2)) for x in grid]

            gridlabel[0] = "" # clean up origin
            ax.set_rgrids(grid, labels=gridlabel,angle=angles[i])

            ax.set_ylim(*ranges[i])

        # variables for plotting
        self.angle = np.deg2rad(np.r_[angles, angles[0]])
        self.ranges = ranges
        self.ax = axes[0]

    def plot(self, data, *args, **kw):
        sdata = self.scale_data(data, self.ranges)
        self.ax.plot(self.angle, np.r_[sdata, sdata[0]], *args, **kw)

    def fill(self, data, *args, **kw):
        sdata = self.scale_data(data, self.ranges)
        self.ax.fill(self.angle, np.r_[sdata, sdata[0]], *args, **kw)

    def scale_data(self, data, ranges):
        """scales data[1:] to ranges[0]"""
        for d, (y1, y2) in zip(data[1:], ranges[1:]):
            assert (y1 <= d <= y2) or (y2 <= d <= y1)
        x1, x2 = ranges[0]
        d = data[0]
        sdata = [d]
        for d, (y1, y2) in zip(data[1:], ranges[1:]):
            if y1 > y2:
                d = _invert(d, (y1, y2))
                y1, y2 = y2, y1
            sdata.append((d-y1) / (y2-y1) * (x2 - x1) + x1)
        return sdata

def plot_comparison(df_1,df_2, player_names):

    df_1_dict = {key: value[df_1.index[0]] for key, value in df_1.to_dict().items()}
    df_2_dict = {key: value[df_2.index[0]] for key, value in df_2.to_dict().items()}

    # plotting

    variables = ['PTS','AST','TRB','STL','BLK', 'TOV']
    ranges = [(0, 30), (0, 11), (0, 10), (0, 3), (0, 3), (0, 5)]

    fig1 = plt.figure(figsize=(6, 6))
    radar = ComplexRadar(fig1, variables, ranges)

    for player,dictionary in zip(player_names,[df_1_dict,df_2_dict]):
        data = list(dictionary.values())
        radar.plot(data, label=player)
        radar.fill(data, alpha=0.2)

    radar.ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.10),
        fancybox=True, shadow=True, ncol=4, fontsize=13)

    return fig1


import math
import torch
import numpy as np
import pandas as pd

from torch import nn
from torch.utils.data.dataset import random_split
from sklearn.metrics import confusion_matrix

from neural_network import NeuralNetwork, train, test
from helper_functions import get_data, create_datasets, get_dataloaders
from helper_functions import plot_loss, plot_accuracy

def single_run(stack, learning_rate, stopping_criteria, returnVals):
    # Init model
    model = NeuralNetwork(stack)
    print(model)

    # exit()
    # CSV data as tensor objects
    X, y = get_data()

    # Tensor data set objects that are split for train, validation, and test
    trainSize = .8
    dsTrain, dsTest = create_datasets(X, y, trainSize)

    numTrainB = math.ceil(len(dsTrain)*.9)
    numVal = len(dsTrain) - numTrainB
    dsTrainB, dsVal = random_split(dsTrain, [numTrainB, numVal])

    # Data Loader objects that are use in training and testing, describe batchSize
    batchSize = 32
    dlTrain, dlTest = get_dataloaders(dsTrain, dsTest, 1)
    dlTrainB, dlVal = get_dataloaders(dsTrainB, dsVal, batchSize)

    # Model Paramaters
    loss_fn = torch.nn.CrossEntropyLoss()
    optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

    epochs = 1000

    # Train and Plot Train Loss / Validation Loss / Validation Accuracy
    countEpochsTrain, training_loss, validation_loss, validation_accuracy, predictions, true = train(
        dlTrainB, dlVal, model, loss_fn, optimizer, epochs, stopping_criteria, 100)
    confMatVal = confusion_matrix(true, predictions)
    print('Number of Epochs to Train = {}'.format(countEpochsTrain))
    print('Final Training Loss = {}'.format(training_loss[-1]))
    print('Validation Loss = {}'.format(validation_loss[-1]))
    print('Validation Accuracy = {}'.format(validation_accuracy[-1]))
    print('Validation Confusion Matrix\n{}'.format(str(confMatVal)))

    plot_loss(training_loss, validation_loss)
    plot_accuracy(validation_accuracy)

    # Retrain with all data and Test, no stopping criteria but same number of epochs
    test_loss, test_accuracy, predictions, true = test(
        dlTest, model, loss_fn, False)

    # print(predictions,  true)
    confMatTest = confusion_matrix(true, predictions)
    print('Test Accuracy = {}'.format(test_accuracy))
    print('Test Confusion Matrix\n{}'.format(str(confMatTest)))

    if returnVals == True:
        return [countEpochsTrain, training_loss[-1], validation_loss[-1], validation_accuracy[-1], test_accuracy]

hidden_layers = [
    [nn.Linear(13, 12), nn.ReLU(), nn.Linear(12, 3)],
    [nn.Linear(13, 12), nn.ReLU(), nn.Linear(
        12, 6), nn.ReLU(), nn.Linear(6, 3)],
    [nn.Linear(13, 12), nn.ReLU(), nn.Linear(12, 8), nn.ReLU(),
     nn.Linear(8, 4), nn.ReLU(), nn.Linear(4, 3)]
]

learning_rate_arr = [.0001, .001, .01]
stopping_criteria_arr = ['trainLoss', 'valLoss', 'valAccuracy']

# # # Part A
single_run(hidden_layers[0], learning_rate_arr[2], stopping_criteria_arr[1], False)

# # # Part B

# Hidden Layers and Nodes: Average performance accross other parameters
# metrics_avg = np.zeros((3, 5))
# for a in range(len(hidden_layers)):
#     hidden_layer_a = hidden_layers[a]
#     metrics_matrix = np.zeros((9, 5))
#     count = 0
#     for b in range(len(stopping_criteria_arr)):
#         stopping_criteria_b = stopping_criteria_arr[b]
#         for c in range(len(learning_rate_arr)):
#             learning_rate_c = learning_rate_arr[c]
#             metrics_arr = single_run(
#                 hidden_layer_a, learning_rate_c, stopping_criteria_b, True)
#             metrics_matrix[count] = metrics_arr
#             count +=1

#     metrics_avg[a] = np.mean(metrics_matrix, axis=0)

# pd.DataFrame(np.around(metrics_avg.T, decimals=2)).to_csv("compare_hidden_layers_and_nodes.csv")

# Learning Rate: Average performance accross other parameters
# metrics_avg = np.zeros((3, 5))
# for a in range(len(learning_rate_arr)):
#     learning_rate_a = learning_rate_arr[a]
#     metrics_matrix = np.zeros((9, 5))
#     count = 0
#     for b in range(len(stopping_criteria_arr)):
#         stopping_criteria_b = stopping_criteria_arr[b]
#         for c in range(len(hidden_layers)):
#             hidden_layers_c = hidden_layers[c]
#             metrics_arr = single_run(
#                 hidden_layers_c, learning_rate_a, stopping_criteria_b, True)
#             metrics_matrix[count] = metrics_arr
#             count +=1

#     metrics_avg[a] = np.mean(metrics_matrix, axis=0)

# pd.DataFrame(np.around(metrics_avg.T, decimals=2)).to_csv("compare_learning_rate.csv")

# # Stopping Crteria: Average performance accross other parameters
# metrics_avg = np.zeros((3, 5))
# for a in range(len(stopping_criteria_arr)):
#     stopping_criteria_a = stopping_criteria_arr[a]
#     metrics_matrix = np.zeros((9, 5))
#     count = 0
#     for b in range(len(learning_rate_arr)):
#         learning_rate_b = learning_rate_arr[b]
#         for c in range(len(hidden_layers)):
#             hidden_layers_c = hidden_layers[c]
#             metrics_arr = single_run(
#                 hidden_layers_c, learning_rate_b, stopping_criteria_a, True)
#             metrics_matrix[count] = metrics_arr
#             count +=1

#     metrics_avg[a] = np.mean(metrics_matrix, axis=0)

# pd.DataFrame(np.around(metrics_avg.T, decimals=2)).to_csv("compare_stopping_criteria.csv")


from copy import deepcopy
from collections import namedtuple
from rst import TreeNode
import config
import torch
import numpy

Step = namedtuple('Step', 'action label direction')

class TransitionSystem:

    def __init__(self, edus=None):
        self.reset()
        if edus is not None:
            self.buffer.extend(edus)

    def reset(self):
        self.buffer = []
        self.stack = []

    def is_done(self):
        return len(self.buffer) == 0 and len(self.stack) == 1

    def get_result(self):
        if self.is_done():
            return deepcopy(self.stack[0])

    def take_action(self, action, *args, **kwargs):
        if action == 'shift':
            self.shift()
        elif action == 'reduce':
            self.reduce(*args, **kwargs)

    def shift(self):
        node = self.buffer.pop(0)
        self.stack.append(node)

    def reduce(self, label=None, direction=None, reduce_fn=None, rel_embedding=None):
        rhs = self.stack.pop()
        lhs = self.stack.pop()

        # print("label: ", lhs.label)
        # relation_one_hot = torch.FloatTensor(1, len(config.ID_TO_LABEL))
        # print(relation_one_hot)
        # relation_one_hot(1, config.LABEL_TO_ID[label]) = 1.0
        # print(relation_one_hot)
        # print("lhs shape: ", )

        emb = None if reduce_fn is None else reduce_fn(lhs.embedding, rhs.embedding, rel_embedding)
        # print(emb)

        node = TreeNode(children=[lhs, rhs], label=label, direction=direction, embedding=emb)
        node.calc_span()
        self.stack.append(node)

    @staticmethod
    def all_actions():
        return ['shift', 'reduce']

    def all_legal_actions(self):
        actions = []
        if self.can_shift():
            actions.append('shift')
        if self.can_reduce():
            actions.append('reduce')
        return actions

    def can_shift(self):
        return len(self.buffer) >= 1

    def can_reduce(self):
        return len(self.stack) >= 2

    def gold_path(self, gold_tree):
        """The correct sequence of steps according to the given gold tree."""
        parser = deepcopy(self)
        while not parser.is_done():
            step = parser.gold_step(gold_tree)
            parser.take_action(*step)
            yield step

    def gold_step(self, gold_tree):
        """The right step to take. If there are several then it returns an arbitrary one."""
        correct_steps = self.all_correct_steps(gold_tree)
        if len(correct_steps) > 0:
            return correct_steps[0]

    def all_correct_steps(self, gold_tree):
        """All steps that would take us from the current state to a state from which it is still possible to reach the gold tree."""
        correct_steps = []
        if self.can_reduce():
            rhs = self.stack[-1]
            lhs = self.stack[-2]
            new_span = range(lhs.span.start, rhs.span.stop)

            for n in gold_tree.iter_nodes():
                if n.span == new_span:
                    correct_steps.append(Step('reduce', n.label, n.direction))
                    break
            else:
                if self.can_shift():
                    correct_steps.append(Step('shift', 'None', 'None'))
                else:
                    # print("all spans:")
                    # for s in [x.span for x in list(gold_tree.iter_nodes())]:
                    #     print("\t", s)
                    raise Exception("There is no correct action given the current state of the parser.")
        elif self.can_shift():
            correct_steps.append(Step('shift', 'None', 'None'))
        return correct_steps


def goDown(x, y, house):
	x += 1
	while house[x][y] not in "\/x":
		x += 1
	if house[x][y] == "/":
		return goleft(x, y, house)
	elif house[x][y] == "x":
		return x, y
	else:
		return goRight(x, y, house)

def goUp(x, y, house):
	x -= 1
	while house[x][y] not in "\/x":
		x -= 1
	if house[x][y] == "/":
		return goRight(x, y, house)
	elif house[x][y] == "x":
		return x, y
	else:
		return goleft(x, y, house)

def goRight(x, y, house):
	y += 1
	while house[x][y] not in "\/x":
		y += 1
	if house[x][y] == "/":
		return goUp(x, y, house)
	elif house[x][y] == "x":
		return x, y
	else:
		return goDown(x, y, house)

def goleft(x, y, house):
	y -= 1
	while house[x][y] not in "\/x":
		y -= 1
	if house[x][y] == "/":
		return goDown(x, y, house)
	elif house[x][y] == "x":
		return x, y
	else:
		return goUp(x, y, house)

def findStart(house):
	i = 0
	while i < len(house):
		j = 0
		while j < len(house[i]):
			if house[i][j] == "*":
				return i, j
			j += 1
		i += 1

def findExit(x, y, house):
	if x == 0:
		return goDown(x, y, house)
	elif x == len(house) - 1:
		return goUp(x, y, house)
	elif y == 0:
		return goRight(x, y, house)
	else:
		return goleft(x, y, house)

n = list(map(int, input().strip().split()))
k = 0
while n != [0, 0]:
	k += 1
	house = []
	for i in range(0, n[1]):
		house.append(input().strip())
	x, y = findStart(house)
	x, y = findExit(x, y, house)
	house[x] = house[x][:y] + "&" + house[x][y+1:]
	print("HOUSE {}".format(k))
	for wall in house:
		print(wall)
	n = list(map(int, input().strip().split()))


import datetime

""" Write the string to stdout with a timestamp. """
def logMsg(string):
	print("[{}] {}".format(datetime.datetime.now(), string))

	return string

""" read a file named fname and return its contents as a string """
def getValueFromFileContents(fname):
	token = ""

	try:
		f_token = open(fname, "r")
		f_token_lines = f_token.readlines()

		for line in f_token_lines:
			line = line.rstrip()
			if len(line) > 0:
				token = line
	except IOError:
		token = ""
		print("Could not read {} file.".format(fname))
	finally:
		f_token.close()

	return token

""" get the Discord API token from the config file on disk """
def getToken():
	return getValueFromFileContents("token")


import numpy as np
from matplotlib import pyplot as plt
from typing import Tuple, List, Dict

import torch
import torch.utils.data

import config as cf
import data_process.augment as aug
from data_process.record import Record

class Dataset(torch.utils.data.Dataset):

    def __init__(self) -> None:
        ''' Init the dataset data structures.
        '''
        self.size = 0
        self.positive_size = 0
        self.track_data = {'center_pos': None, 'center_rot': None, 'marker_pos': None}
        self.imu_data = {'acc': None, 'gyro': None}
        self.labels = None
        self.reindex_map = None

    def __len__(self) -> int:
        return self.size

    def __getitem__(self, idx:int) -> Dict[str, np.ndarray]:
        ''' Get an action sample data.
        args:
            idx: int, the index of the action sample.
                the idx will be reindexed before retrieving the actual sample data.]
        '''
        # TODO: no track augmentation yet, directly return imu data
        # If idx after reindex_map >= positive size, it means the sample at idx is negative data,
        # which does not has track_data. Return imu data directly.
        if self.reindex_map is not None: idx = self.reindex_map[idx]
        w_cut = int(cf.CUT_DURATION * cf.FS_PREPROCESS)
        w_train = int(cf.TRAIN_DURATION * cf.FS_PREPROCESS)
        if cf.RAND_SAMPLE_EN: start = np.random.randint(0, w_cut - w_train)
        else: start = (w_cut - w_train) // 2
        sample = np.concatenate([self.imu_data['acc'][idx,start:start+w_train,:],
            self.imu_data['gyro'][idx,start:start+w_train,:]], axis=1)
        sample = aug.down_sample_by_step(sample, axis=0, step=(cf.FS_PREPROCESS//cf.FS_TRAIN))
        return {'data': sample, 'label': self.labels[idx]}

    def insert_records(self, records:List[Record], labels:List[int]) -> None:
        ''' Insert a list of records.
        args:
            records: List[Record], a list or records.
            labels: List[int], the labels of these records,
                must have the same length as records.
        '''
        # a simple version based on insert_record()
        for record, label in zip(records, labels):
            self.insert_record(record, label)

    def insert_record(self, record:Record, label:int) -> None:
        ''' Insert a single record with all samples have the same group id.
            NOTE: always insert negative after positive data.
        args:
            record: Record, the action record.
            label: int, the label of the record.
        '''
        # insert imu data
        clean_mask = record.clean_mask
        cnt = np.sum(clean_mask)
        imu_data = self.imu_data
        cutted_imu_data = record.cutted_imu_data
        if imu_data['acc'] is None:
            imu_data['acc'] = cutted_imu_data['acc'][clean_mask,...]
            imu_data['gyro'] = cutted_imu_data['gyro'][clean_mask,...]
        else:
            imu_data['acc'] = np.concatenate([imu_data['acc'],
                cutted_imu_data['acc'][clean_mask,...]], axis=0)
            imu_data['gyro'] = np.concatenate([imu_data['gyro'],
                cutted_imu_data['gyro'][clean_mask,...]], axis=0)
        self.imu_data = imu_data
        # insert track data
        track_data = self.track_data
        cutted_track_data = record.cutted_track_data
        if track_data['center_pos'] is None:
            track_data['center_pos'] = cutted_track_data['center_pos'][clean_mask,...]
            track_data['center_rot'] = cutted_track_data['center_rot'][clean_mask,...]
            track_data['marker_pos'] = cutted_track_data['marker_pos'][clean_mask,...]
        else:
            track_data['center_pos'] = np.concatenate([track_data['center_pos'],
                cutted_track_data['center_pos'][clean_mask,...]], axis=0)
            track_data['center_rot'] = np.concatenate([track_data['center_rot'],
                cutted_track_data['center_rot'][clean_mask,...]], axis=0)
            track_data['marker_pos'] = np.concatenate([track_data['marker_pos'],
                cutted_track_data['marker_pos'][clean_mask,...]], axis=0)
        self.track_data = track_data
        self.positive_size += cnt
        # insert labels
        if self.labels is None:
            self.labels = np.zeros(cnt, dtype=np.int64) + label
        else: self.labels = np.concatenate([self.labels, np.zeros(cnt, dtype=np.int64) + label])
        self.size += cnt

    def insert_record_raise_drop(self, record:Record, raise_label:int, drop_label:int) -> None:
        ''' An adapter for insert raise and drop data only.
        args:
            record: Record, the action record.
            raise_label: int, the label of raise.
            drop_label: int, the label of drop.
        '''
        clean_mask = record.clean_mask
        cnt = np.sum(clean_mask)
        imu_data = self.imu_data
        cutted_imu_data = record.cutted_imu_data
        # insert imu data
        if imu_data['acc'] is None:
            imu_data['acc'] = cutted_imu_data['acc'][clean_mask,...]
            imu_data['gyro'] = cutted_imu_data['gyro'][clean_mask,...]
        else:
            imu_data['acc'] = np.concatenate([imu_data['acc'],
                cutted_imu_data['acc'][clean_mask,...]], axis=0)
            imu_data['gyro'] = np.concatenate([imu_data['gyro'],
                cutted_imu_data['gyro'][clean_mask,...]], axis=0)
        self.imu_data = imu_data
        # insert track data
        track_data = self.track_data
        cutted_track_data = record.cutted_track_data
        if track_data['center_pos'] is None:
            track_data['center_pos'] = cutted_track_data['center_pos'][clean_mask,...]
            track_data['center_rot'] = cutted_track_data['center_rot'][clean_mask,...]
            track_data['marker_pos'] = cutted_track_data['marker_pos'][clean_mask,...]
        else:
            track_data['center_pos'] = np.concatenate([track_data['center_pos'],
                cutted_track_data['center_pos'][clean_mask,...]], axis=0)
            track_data['center_rot'] = np.concatenate([track_data['center_rot'],
                cutted_track_data['center_rot'][clean_mask,...]], axis=0)
            track_data['marker_pos'] = np.concatenate([track_data['marker_pos'],
                cutted_track_data['marker_pos'][clean_mask,...]], axis=0)
        self.track_data = track_data
        # insert labels
        labels = np.zeros(cutted_imu_data['acc'].shape[0], dtype=np.int64) + raise_label
        labels[1::2] = drop_label
        if self.labels is None:
            self.labels = labels[clean_mask]
        else: self.labels = np.concatenate([self.labels, labels[clean_mask]])
        self.positive_size += cnt
        self.size += cnt

    def insert_negativa_data(self, negative_data:np.ndarray, label:int):
        ''' Insert negative data in batch.
        args:
            negative_data: np.ndarray[(N, int(FS_PREPROCESS*WINDOW_DURATION), 6), np.float32].
            label: int, the negative label.
        '''
        cnt = negative_data.shape[0]
        imu_data = self.imu_data
        if imu_data['acc'] is None:
            imu_data['acc'] = negative_data[:,:,:3]
            imu_data['gyro'] = negative_data[:,:,3:]
        else:
            imu_data['acc'] = np.concatenate([imu_data['acc'], negative_data[:,:,:3]], axis=0)
            imu_data['gyro'] = np.concatenate([imu_data['gyro'], negative_data[:,:,3:]], axis=0)
        self.imu_data = imu_data
        labels = np.zeros(cnt, dtype=np.int64) + label
        if self.labels is None:
            self.labels = labels
        else: self.labels = np.concatenate([self.labels, labels])
        self.size += cnt

    def shuffle(self) -> None:
        ''' Shuffle the reindex mapping.
            NOTE: always call shuffle after inserting records.
        '''
        self.reindex_map = np.arange(self.size, dtype=np.int32)
        np.random.shuffle(self.reindex_map)

class DataLoader(torch.utils.data.DataLoader):

    def __init__(self, dataset:Dataset, *args, **kwargs) -> None:
        super(DataLoader, self).__init__(dataset, *args, **kwargs)

if __name__ == '__main__':
    pass