import math

import torch
import torch.nn as nn
from torch_scatter import scatter

from DataPrepareUtils import cal_msg_edge_index
from DimeModule import DimeModule
from CoulombLayer import CoulombLayer
from D3DispersionLayer import D3DispersionLayer
from PhysModule import PhysModule
from AtomToEdgeLayer import AtomToEdgeLayer
from EdgeToAtomLayer import EdgeToAtomLayer
from EmbeddingLayer import EmbeddingLayer
from MCDropout import ConcreteDropout
from BesselCalculator import bessel_expansion_raw
from BesselCalculatorFast import BesselCalculator
from utils_functions import floating_type, device, dime_edge_expansion, softplus_inverse, \
    gaussian_rbf, info_resolver, expansion_splitter, error_message, option_solver
#from tags import tags

class PhysDimeNet(nn.Module):
    """
    Combination of PhyNet and DimeNet
    For non-bonding interaction, using atom-atom interaction in PhysNet
    For bonding interaction, using directional message passing
    Final prediction is the combination of PhysNet and DimeNet

    Next time I will use **kwargs :<
    """

    def __init__(self,
                 n_atom_embedding,
                 modules,
                 bonding_type,
                 n_feature,
                 n_output,
                 n_dime_before_residual,
                 n_dime_after_residual,
                 n_output_dense,
                 n_phys_atomic_res,
                 n_phys_interaction_res,
                 n_phys_output_res,
                 n_bi_linear,
                 nh_lambda,
                 normalize,
                 shared_normalize_param,
                 activations,
                 restrain_non_bond_pred,
                 expansion_fn,
                 uncertainty_modify,
                 coulomb_charge_correct,
                 energy_shift=None,
                 energy_scale=None,
                 debug_mode=False,
                 action="E",
                 target_names=None,
                 batch_norm=False,
                 dropout=False,
                 requires_atom_prop=False,
                 get_atom_embedding=False,
                 use_qmd=False,
                 use_solvent=False,
                 **kwargs):
        """

        :param n_atom_embedding: number of atoms to embed, usually set to 95
        :param n_feature:
        :param n_output:
        :param n_dime_before_residual:
        :param n_dime_after_residual:
        :param n_output_dense:
        :param n_bi_linear: Dimension of bi-linear layer in DimeNet, also called N_tensor in paper
        :param nh_lambda: non-hierarchical penalty coefficient
        :param debug_mode:
        """
        super().__init__()
        #print("------unused keys in model-----")
        #for key in kwargs:
        #    print("{}: {}".format(key, kwargs[key]))

        #self.logger = logging.getLogger()
        self.use_qmd = use_qmd
        self.use_solvent=use_solvent
        self.requires_atom_prop = requires_atom_prop
        self.get_atom_embedding = get_atom_embedding
        #if action in tags.requires_atomic_prop:
            #self.logger.info("Overwriting self.requires_atom_prop = True because you require atomic props")
        self.requires_atom_prop = True
        # convert input into a dictionary
        self.target_names = target_names
        self.action = action
        self.coulomb_charge_correct = coulomb_charge_correct
        self.uncertainty_modify = uncertainty_modify
        self.expansion_fn = expansion_splitter(expansion_fn)

        self.activations = activations.split(' ')
        module_str_list = modules.split()
        bonding_str_list = bonding_type.split()
        # main modules, including P (PhysNet), D (DimeNet), etc.
        self.main_module_str = []
        self.main_bonding_str = []
        # post modules are either C (Coulomb) or D3 (D3 Dispersion)
        self.post_module_str = []
        self.post_bonding_str = []
        for this_module_str, this_bonding_str in zip(module_str_list, bonding_str_list):
            '''
            Separating main module and post module
            '''
            this_module_str = this_module_str.split('[')[0]
            if this_module_str in ['D', 'P', 'D-noOut', 'P-noOut']:
                self.main_module_str.append(this_module_str)
                self.main_bonding_str.append(this_bonding_str)
            elif this_module_str in ['C', 'D3']:
                self.post_module_str.append(this_module_str)
                self.post_bonding_str.append(this_bonding_str)
            else:
                error_message(this_module_str, 'module')
        self.bonding_type_keys = set(bonding_str_list)

        # whether calculate long range interaction or not
        self.contains_lr = False
        for _bonding_type in self.bonding_type_keys:
            if _bonding_type.find('L') >= 0:
                self.contains_lr = True

        module_bond_combine_str = []
        msg_bond_type = []
        for module, bond in zip(module_str_list, bonding_str_list):
            module = module.split('[')[0]
            module_bond_combine_str.append('{}_{}'.format(module, bond))
            if module == 'D':
                msg_bond_type.append(bond)
        self.module_bond_combine_str = set(module_bond_combine_str)
        # These bonds need to be expanded into message version (i.e. 3 body interaction)
        self.msg_bond_type = set(msg_bond_type)

        self.restrain_non_bond_pred = restrain_non_bond_pred
        self.shared_normalize_param = shared_normalize_param
        self.normalize = normalize
        self.n_phys_output_res = n_phys_output_res
        self.n_phys_interaction_res = n_phys_interaction_res
        self.n_phys_atomic_res = n_phys_atomic_res
        self.debug_mode = debug_mode
        self.n_output = n_output
        self.nhlambda = nh_lambda

        # A dictionary which parses an expansion combination into detailed information
        self.expansion_info_getter = {
            combination: info_resolver(self.expansion_fn[combination])
            for combination in self.module_bond_combine_str
        }

        # registering necessary parameters for some expansions if needed
        for combination in self.expansion_fn.keys():
            expansion_fn_info = self.expansion_info_getter[combination]
            if expansion_fn_info['name'] == "gaussian":
                n_rbf = expansion_fn_info['n']
                feature_dist = expansion_fn_info['dist']
                feature_dist = torch.as_tensor(feature_dist).type(floating_type)
                self.register_parameter('cutoff' + combination, torch.nn.Parameter(feature_dist, False))
                # Centers are params for Gaussian RBF expansion in PhysNet
                centers = softplus_inverse(torch.linspace(1.0, math.exp(-feature_dist), n_rbf))
                centers = torch.nn.functional.softplus(centers)
                self.register_parameter('centers' + combination, torch.nn.Parameter(centers, True))

                # Widths are params for Gaussian RBF expansion in PhysNet
                widths = [softplus_inverse((0.5 / ((1.0 - torch.exp(-feature_dist)) / n_rbf)) ** 2)] * n_rbf
                widths = torch.as_tensor(widths).type(floating_type)
                widths = torch.nn.functional.softplus(widths)
                self.register_parameter('widths' + combination, torch.nn.Parameter(widths, True))
            elif expansion_fn_info['name'] == 'defaultDime':
                n_srbf = self.expansion_info_getter[combination]['n_srbf']
                n_shbf = self.expansion_info_getter[combination]['n_shbf']
                envelop_p = self.expansion_info_getter[combination]['envelop_p']
                setattr(self, f"bessel_calculator_{n_srbf}_{n_shbf}", BesselCalculator(n_srbf, n_shbf, envelop_p))

        self.base_unit_getter = {
            'D': "edge",
            'D-noOut': "edge",
            'P': "atom",
            'P-noOut': "atom",
            'C': "atom",
            'D3': "atom"
        }

        self.dist_calculator = nn.PairwiseDistance(keepdim=True)

        if self.use_qmd: self.embedding_layer = EmbeddingLayer(n_atom_embedding, 157)
        elif self.use_solvent: self.embedding_layer = EmbeddingLayer(n_atom_embedding, 148)
        else: self.embedding_layer = EmbeddingLayer(n_atom_embedding, n_feature) # if addiing QMD features, substract from the n_feature

        previous_module = 'P'
        '''
        registering main modules
        '''
        self.main_module_list = nn.ModuleList()
        # stores extra info including module type, bonding type, etc
        self.main_module_info = []
        for i, (module_str, bonding_str) in enumerate(zip(module_str_list, bonding_str_list)):
            # contents within '[]' will be considered options
            _options = option_solver(module_str)
            module_str = module_str.split('[')[0]
            combination = module_str + "_" + bonding_str
            if module_str in ['D', 'D-noOut']:
                n_dime_rbf = self.expansion_info_getter[combination]['n']
                n_srbf = self.expansion_info_getter[combination]['n_srbf']
                n_shbf = self.expansion_info_getter[combination]['n_shbf']
                dim_sbf = n_srbf * (n_shbf + 1)
                this_module_str = DimeModule(dim_rbf=n_dime_rbf,
                                             dim_sbf=dim_sbf,
                                             dim_msg=n_feature,
                                             n_output=n_output,
                                             n_res_interaction=n_dime_before_residual,
                                             n_res_msg=n_dime_after_residual,
                                             n_dense_output=n_output_dense,
                                             dim_bi_linear=n_bi_linear,
                                             activation=self.activations[i],
                                             uncertainty_modify=uncertainty_modify)
                if self.uncertainty_modify == 'concreteDropoutModule':
                    this_module_str = ConcreteDropout(this_module_str, module_type='DimeNet')
                self.main_module_list.append(this_module_str)
                self.main_module_info.append({"module_str": module_str, "bonding_str": bonding_str,
                                              "combine_str": "{}_{}".format(module_str, bonding_str),
                                              "is_transition": False})
                if self.base_unit_getter[previous_module] == "atom":
                    self.main_module_list.append(AtomToEdgeLayer(n_dime_rbf, n_feature, self.activations[i]))
                    self.main_module_info.append({"is_transition": True})

            elif module_str in ['P', 'P-noOut']:
                this_module_str = PhysModule(F=n_feature,
                                             K=self.expansion_info_getter[combination]['n'],
                                             n_output=n_output,
                                             n_res_atomic=n_phys_atomic_res,
                                             n_res_interaction=n_phys_interaction_res,
                                             n_res_output=n_phys_output_res,
                                             activation=self.activations[i],
                                             uncertainty_modify=uncertainty_modify,
                                             n_read_out=int(_options['n_read_out']) if 'n_read_out' in _options else 0,
                                             batch_norm=batch_norm,
                                             dropout=dropout)
                if self.uncertainty_modify == 'concreteDropoutModule':
                    this_module_str = ConcreteDropout(this_module_str, module_type='PhysNet')
                self.main_module_list.append(this_module_str)
                self.main_module_info.append({"module_str": module_str, "bonding_str": bonding_str,
                                              "combine_str": "{}_{}".format(module_str, bonding_str),
                                              "is_transition": False})
                if self.base_unit_getter[previous_module] == "edge":
                    self.main_module_list.append(EdgeToAtomLayer())
                    self.main_module_info.append({"is_transition": True})
            elif module_str in ['C', 'D3']:
                pass
            else:
                error_message(module_str, 'module')
            previous_module = module_str

        # TODO Post modules to list
        for i, (module_str, bonding_str) in enumerate(zip(self.post_module_str, self.post_bonding_str)):
            if module_str == 'C':
                combination = module_str + "_" + bonding_str
                self.add_module('post_module{}'.format(i),
                                CoulombLayer(cutoff=self.expansion_info_getter[combination]['dist']))
            elif module_str == 'D3':
                self.add_module('post_module{}'.format(i), D3DispersionLayer(s6=0.5, s8=0.2130, a1=0.0, a2=6.0519))
            else:
                error_message(module_str, 'module')

        # TODO normalize to list
        if self.normalize:
            '''
            Atom-wise shift and scale, used in PhysNet
            '''
            if shared_normalize_param:
                shift_matrix = torch.zeros(95, n_output).type(floating_type)
                scale_matrix = torch.zeros(95, n_output).type(floating_type).fill_(1.0)
                if energy_shift is not None:
                    if isinstance(energy_shift, torch.Tensor):
                        if shift_matrix.shape == energy_shift.shape:
                            shift_matrix = energy_shift
                        else:
                            shift_matrix[:, :] = energy_shift.view(1, -1)
                    else:
                        shift_matrix[:, 0] = energy_shift
                if energy_scale is not None:
                    if isinstance(energy_scale, torch.Tensor):
                        if scale_matrix.shape == energy_scale.shape:
                            scale_matrix = energy_scale
                        else:
                            scale_matrix[:, :] = energy_scale.view(1, -1)
                    else:
                        scale_matrix[:, 0] = energy_scale
                shift_matrix = shift_matrix / len(self.bonding_type_keys)
                self.register_parameter('scale', torch.nn.Parameter(scale_matrix, requires_grad=True))
                self.register_parameter('shift', torch.nn.Parameter(shift_matrix, requires_grad=True))
            else:
                for key in self.bonding_type_keys:
                    shift_matrix = torch.zeros(95, n_output).type(floating_type)
                    scale_matrix = torch.zeros(95, n_output).type(floating_type).fill_(1.0)
                    if energy_shift is not None:
                        shift_matrix[:, 0] = energy_shift
                    if energy_scale is not None:
                        scale_matrix[:, 0] = energy_scale
                    shift_matrix = shift_matrix / len(self.bonding_type_keys)
                    self.register_parameter('scale{}'.format(key), torch.nn.Parameter(scale_matrix, requires_grad=True))
                    self.register_parameter('shift{}'.format(key), torch.nn.Parameter(shift_matrix, requires_grad=True))

    def freeze_prev_layers(self, freeze_extra=False):
        if freeze_extra:
            # Freeze scale, shift and Gaussian RBF parameters
            for param in self.parameters():
                param.requires_grad_(False)
        for i in range(len(self.main_module_str)):
            self.main_module_list[i].freeze_prev_layers()

    def forward(self, data):
        # torch.cuda.synchronize(device=device)
        # t0 = time.time()

        R = data.R.type(floating_type)
        Z = data.Z
        N = data.N
        '''
        Note: non_bond_edge_index is for non-bonding interactions
              bond_edge_index is for bonding interactions
        '''
        atom_mol_batch = data.atom_mol_batch
        edge_index_getter = {}
        for bonding_str in self.bonding_type_keys:
            # prepare edge index
            edge_index = getattr(data, bonding_str + '_edge_index', False)
            if edge_index is not False:
                edge_index_getter[bonding_str] = edge_index + getattr(data, bonding_str + '_edge_index_correct')
            else:
                edge_index_getter[bonding_str] = torch.cat(
                    [data[_type + '_edge_index'] + data[_type + '_edge_index_correct'] for _type in bonding_str],
                    dim=-1)

        msg_edge_index_getter = {}
        for bonding_str in self.msg_bond_type:
            # prepare msg edge index
            this_msg_edge_index = getattr(data, bonding_str + '_msg_edge_index', False)
            if this_msg_edge_index is not False:
                msg_edge_index_getter[bonding_str] = this_msg_edge_index + \
                                                     getattr(data, bonding_str + '_msg_edge_index_correct')
            else:
                msg_edge_index_getter[bonding_str] = cal_msg_edge_index(edge_index_getter[bonding_str]).to(device)

        # t0 = record_data('edge index prepare', t0)

        expansions = {}
        '''
        calculating expansion
        '''
        for combination in self.module_bond_combine_str:
            module_str = combination.split('_')[0]
            this_bond = combination.split('_')[1]
            this_expansion = self.expansion_info_getter[combination]['name']
            if module_str in ['D', 'D-noOut']:
                # DimeNet, calculate sbf and rbf
                if this_expansion == "defaultDime":
                    n_srbf = self.expansion_info_getter[combination]['n_srbf']
                    n_shbf = self.expansion_info_getter[combination]['n_shbf']
                    expansions[combination] = dime_edge_expansion(R, edge_index_getter[this_bond],
                                                                  msg_edge_index_getter[this_bond],
                                                                  self.expansion_info_getter[combination]['n'],
                                                                  self.dist_calculator,
                                                                  getattr(self, f"bessel_calculator_{n_srbf}_{n_shbf}"),
                                                                  self.expansion_info_getter[combination]['dist'],
                                                                  return_dict=True)
                else:
                    raise ValueError("Double check your expansion input!")
            elif module_str in ['P', 'P-noOut']:
                # PhysNet, calculate rbf
                if this_expansion == 'bessel':
                    this_edge_index = edge_index_getter[this_bond]
                    dist_atom = self.dist_calculator(R[this_edge_index[0, :], :], R[this_edge_index[1, :], :])
                    rbf = bessel_expansion_raw(dist_atom, self.expansion_info_getter[combination]['n'],
                                               self.expansion_info_getter[combination]['dist'])
                    expansions[combination] = {"rbf": rbf}
                elif this_expansion == 'gaussian':
                    this_edge_index = edge_index_getter[this_bond]
                    pair_dist = self.dist_calculator(R[this_edge_index[0, :], :], R[this_edge_index[1, :], :])
                    expansions[combination] = gaussian_rbf(pair_dist, getattr(self, 'centers' + combination),
                                                           getattr(self, 'widths' + combination),
                                                           getattr(self, 'cutoff' + combination),
                                                           return_dict=True)
                else:
                    error_message(this_expansion, 'expansion')
            elif (module_str == 'C') or (module_str == 'D3'):
                '''
                In this situation, we only need to calculate pair-wise distance.
                '''
                this_edge_index = edge_index_getter[this_bond]
                # TODO pair dist was calculated twice here
                expansions[combination] = {"pair_dist": self.dist_calculator(R[this_edge_index[0, :], :],
                                                                             R[this_edge_index[1, :], :])}
            else:
                # something went wrong
                error_message(module_str, 'module')

        # t0 = record_data('calculate rbf', t0)

        '''
        mji: edge diff
        vi:  node diff
        '''
        vi = self.embedding_layer(Z) # atomic number embedding
        if self.use_qmd:
            vi = torch.cat([vi, data.qmd_features], axis=-1)
        elif self.use_solvent:
            vi = torch.cat([vi, data.qmd_features, data.solvents], axis=-1)

        # t0 = record_data('diff layer', t0)

        separated_last_out = {key: None for key in self.bonding_type_keys}
        separated_out_sum = {key: 0. for key in self.bonding_type_keys}

        nh_loss = torch.zeros(1).type(floating_type).to(device)
        mji = None
        out_dict = {"vi": vi, "mji": mji}
        '''
        Going through main modules
        '''
        for info, _module in zip(self.main_module_info, self.main_module_list):

            # t0 = time.time()

            out_dict["info"] = info
            if not info["is_transition"]:
                out_dict["edge_index"] = edge_index_getter[info["bonding_str"]]
                out_dict["edge_attr"] = expansions[info["combine_str"]]
            if info["module_str"].split("-")[0] == "D":
                out_dict["msg_edge_index"] = msg_edge_index_getter[info["bonding_str"]]

            # t0 = record_data('assign values', t0)

            out_dict = _module(out_dict)

            # t0 = record_data('main modules', t0)

            if info["is_transition"] or info["module_str"].split("-")[-1] == '-noOut':
                pass
            else:
                nh_loss = nh_loss + out_dict["regularization"]
                if separated_last_out[info["bonding_str"]] is not None:
                    # Calculating non-hierarchical penalty
                    out2 = out_dict["out"] ** 2
                    last_out2 = separated_last_out[info["bonding_str"]] ** 2
                    nh_loss = nh_loss + torch.mean(out2 / (out2 + last_out2 + 1e-7)) * self.nhlambda
                separated_last_out[info["bonding_str"]] = out_dict["out"]
                separated_out_sum[info["bonding_str"]] = separated_out_sum[info["bonding_str"]] + out_dict["out"]

            # t0 = record_data('nh loss calculation', t0)

        # t0 = record_data('main modules', t0)

        if self.normalize:
            '''
            Atom-wise shifting and scale
            '''
            if self.shared_normalize_param:
                for key in self.bonding_type_keys:
                    separated_out_sum[key] = self.scale[Z, :] * separated_out_sum[key] + self.shift[Z, :]
            else:
                for key in self.bonding_type_keys:
                    separated_out_sum[key] = getattr(self, 'scale{}'.format(key))[Z, :] * separated_out_sum[key] + \
                                             getattr(self, 'shift{}'.format(key))[Z, :]

        atom_prop = 0.
        for key in self.bonding_type_keys:
            atom_prop = atom_prop + separated_out_sum[key]

        '''
        Post modules: Coulomb or D3 Dispersion layers
        '''
        for i, (module_str, bonding_str) in enumerate(zip(self.post_module_str, self.post_bonding_str)):
            this_edge_index = edge_index_getter[bonding_str]
            this_expansion = expansions["{}_{}".format(module_str, bonding_str)]
            if module_str == 'C':
                if self.coulomb_charge_correct:
                    Q = data.Q
                    coulomb_correction = self._modules["post_module{}".format(i)](atom_prop[:, -1],
                                                                                this_expansion["pair_dist"],
                                                                                this_edge_index, q_ref=Q, N=N,
                                                                                atom_mol_batch=atom_mol_batch)
                else:
                    print("one of the variables needed for gradient computation has been modified by an inplace"
                          " operation: need to be fixed here, probably in function cal_coulomb_E")
                    coulomb_correction = self._modules["post_module{}".format(i)](atom_prop[:, -1], this_expansion,
                                                                                this_edge_index)
                atom_prop[:, 0] = atom_prop[:, 0] + coulomb_correction
            elif module_str == 'D3':
                d3_correction = self._modules["post_module{}".format(i)](Z, this_expansion, this_edge_index)
                atom_prop[:, 0] = atom_prop[:, 0] + d3_correction
            else:
                error_message(module_str, 'module')

        # t0 = record_data('post modules', t0)

        if self.restrain_non_bond_pred and ('N' in self.bonding_type_keys):
            # Bonding energy should be larger than non-bonding energy
            atom_prop2 = atom_prop ** 2
            non_bond_prop2 = separated_out_sum['N'] ** 2
            nh_loss = nh_loss + torch.mean(non_bond_prop2 / (atom_prop2 + 1e-7)) * self.nhlambda

        # Total prediction is the summation of bond and non-bond prediction
        mol_pred_properties = scatter(reduce='add', src=atom_prop, index=atom_mol_batch, dim=0)

        # t0 = record_data('atom prop to molecule', t0)

        # t0 = record_data('others', t0)
        if self.debug_mode:
            if torch.abs(mol_pred_properties.detach()).max() > 1e4:
                error_message(torch.abs(mol_pred_properties.detach()).max(), 'Energy prediction')

        output = {}
        if self.action in ["E", "names_and_QD", "atomMol"]:
            mol_prop = mol_pred_properties[:, :-1]
            assert self.n_output > 1
            # the last property is considered as atomic charge prediction
            Q_pred = mol_pred_properties[:, -1]
            Q_atom = atom_prop[:, -1]
            atom_prop = atom_prop[:, :-1]
            D_atom = Q_atom.view(-1, 1) * R
            D_pred = scatter(reduce='add', src=D_atom, index=atom_mol_batch, dim=0)
            output["Q_pred"] = Q_pred
            output["D_pred"] = D_pred
            if self.requires_atom_prop:
                output["Q_atom"] = Q_atom
        else:
            mol_prop = mol_pred_properties
        output["mol_prop"] = mol_prop
        output["nh_loss"] = nh_loss

        if self.get_atom_embedding:
            out_dict['atom_mol_batch'] = atom_mol_batch
            return out_dict

        if self.requires_atom_prop:
            output["atom_prop"] = atom_prop
            output["atom_mol_batch"] = atom_mol_batch
        return output


#Manuel Ortiz Hernández at 2020
#Python Problems. Extracted from: https://www.hackerrank.com/challenges/nested-list/problem
def readData():
	group = []

	for _ in range(int(input())):
		name = input("Name: ")
		score = float(input("Score: "))
		group.append([name,score])
	return group

def getSecondMinimum(group):
	minimum = 0
	second_minimum = 0
	final_list = []
	j = 0
	for i in range(len(group)):
		if group[minimum][1] > group[i][1]:
			second_minimum = minimum
			minimum = i
		else:
			if group[i][1] > group[minimum][1] and group[i][1] < group[second_minimum][1]:
				second_minimum = i
		if group[second_minimum][1] == group[minimum][1]:
			second_minimum+=1

	while j< len(group):
		if group[second_minimum][1] == group[j][1]:
			final_list.append(group[j])
		j+=1

	return final_list

def print_students(group):
	group.sort()
	for i in group:
		print(i[0])

def main():
	group = readData()
	printStudents(getSecondMinimum(group))

main()


# coding: UTF-8
import sys
#確認のためPythonのバージョンを出力させる
print(sys.version_info)
import io
#標準出力で処理できない文字を「？」に置き換えて処理するため、
#sys.stdoutのio.TextIOWrapperを設定する。
#http://www.madopro.net/entry/ReplaceCharsCausingUnicodeEncodeError
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding=sys.stdout.encoding, errors="replace")

#必要機能インポート
import codecs
import urllib
from bs4 import BeautifulSoup
import re
import datetime
import time
import requests

#時間計測
start = time.time()

#グローバル変数定義
deletecnt = 0
updatecount = 0
deletelists = []
updateists = []

# sqlite3 標準モジュールをインポート
import sqlite3
msg = ""

##SQLite登録処理
def sqliteinsert(mvid,mvtitle,mvtag):
        msg = "test"

        # データベースファイルのパス
        #dbpath = '/home/ubuntu/workspace/ex50/development.sqlite3'
        dbpath = 'development.sqlite3'

        # データベース接続とカーソル生成
        connection = sqlite3.connect(dbpath,isolation_level="IMMEDIATE")
        connection.set_trace_callback(print)
        # 自動コミットにする場合は下記を指定（コメントアウトを解除のこと）
        # connection.isolation_level = None
        cursor = connection.cursor()
        #return str(mvid) + "ismvid"
        #http://code.i-harness.com/ja/q/253bd3
        cursor.execute("select thisavid from thisavlists where thisavid = ?", (str(mvid),))
        row = cursor.fetchone()
        #return str(row) + "ismvid"
        if row is None:
                msg = str(mvid) + " is Not Exist! Insert"
                dt_now = datetime.datetime.now()
                dt_today = datetime.date.today()
                # INSERT処理。必要項目と、NOTNUL項目をアップデートする。
                #RubyはActiverecordでやってくれていた項目もあるが、
                #こちらは手動になる。
                html2 = 'https://www.thisav.com/video/' + str(mvid) + '/'
                sql = 'insert into thisavlists (thisavid, thisavtitle, thisavurl, tags, updatedate,created_at,updated_at) values (?,?,?,?,?,?,?)'
                data = (mvid,mvtitle,html2,mvtag,dt_today,dt_now,dt_now)
                cursor.execute(sql, data)
                connection.commit()
                global deletecnt
                deletecnt = deletecnt + 1
                # 接続を閉じる
                connection.close()
                msg = str(mvid) + " is Not Exist! Insert :" + str(deletecnt)
                return msg
        else:
                # 接続を閉じる
                connection.close()
                # データベース接続とカーソル生成
                #return dbpath
                connection2 = sqlite3.connect(dbpath,isolation_level="IMMEDIATE")
                connection2.set_trace_callback(print)
                # 自動コミットにする場合は下記を指定（コメントアウトを解除のこと）
                # connection.isolation_level = None
                cursor2 = connection2.cursor()
                msg = str(mvid) + " is Exist Update"
                dt_now = datetime.datetime.now()
                dt_today = datetime.date.today()
                # UPDATE処理。時間のみアップデートする
                sql = 'update thisavlists set updatedate = ?,updated_at = ? WHERE thisavid =?'
                data = (dt_today,dt_now,mvid)
                #return data
                #cursor = connection.cursor()
                cursor2.execute(sql, data)
                #return msg
                connection2.commit()
                global updatecount
                updatecount = updatecount + 1
                msg = str(mvid) + " is Exist Update " + str(updatecount)
                # 接続を閉じる
                connection.close()
                return msg
##SQLite削除・更新処理
#mentecodeが１＝日付のみ更新
#mentecodeが２＝レコード削除
def sqlitemente(mvid,mmentecode):
        msg = "test"

        # データベースファイルのパス
        #dbpath = '/home/ubuntu/workspace/ex50/development.sqlite3'
        dbpath = 'development.sqlite3'

        # データベース接続とカーソル生成
        connection = sqlite3.connect(dbpath,isolation_level="IMMEDIATE")
        connection.set_trace_callback(print)
        # 自動コミットにする場合は下記を指定（コメントアウトを解除のこと）
        # connection.isolation_level = None
        cursor = connection.cursor()
        #return str(mvid) + "ismvid"
        #http://code.i-harness.com/ja/q/253bd3
        #cursor.execute("select thisavid from thisavlists where thisavid = ?", (str(mvid),))
        #row = cursor.fetchone()
        #return str(row) + "ismvid"
        if str(mmentecode) == "2":
                #削除処理
                msg = str(mvid) + " is Not Exist! Delete"
                #sql = ("delete from thisavlists WHERE thisavid = ?", (str(mvid),))
                #data = "('" + mvid + "',)"
                #return data
                #thisavlists削除
                cursor.execute("delete from thisavlists WHERE thisavid = ?", (str(mvid),))

                #relationlists削除
                cursor.execute("delete from relationlists WHERE tomvid = ? and relationid = ?", (str(mvid),"dmmtothisav"))

                #genrerelationlists削除
                cursor.execute("delete from genrerelationlists WHERE mvid = ? and medianame = ?", (str(mvid),"thisav"))

                connection.commit()
                global deletecnt
                deletecnt = deletecnt + 1
                # 接続を閉じる
                connection.close()
                msg = str(mvid) + " is Not Exist! Delete:" + str(deletecnt)
                return msg
        else:
                #return "test"
                # 接続を閉じる
                #connection.close()
                # データベース接続とカーソル生成
                #return dbpath
                connection = sqlite3.connect(dbpath,isolation_level="IMMEDIATE")
                connection.set_trace_callback(print)
                # 自動コミットにする場合は下記を指定（コメントアウトを解除のこと）
                # connection.isolation_level = None
                cursor2 = connection.cursor()
                msg = str(mvid) + " is Exist Update"
                dt_now = datetime.datetime.now()
                dt_today = datetime.date.today()
                # UPDATE処理。時間のみアップデートする
                sql = 'update thisavlists set updatedate = ?,updated_at = ? WHERE thisavid =?'
                data = (dt_today,dt_now,mvid)
                #return data
                #cursor = connection.cursor()
                cursor2.execute(sql, data)
                #return msg
                connection.commit()
                global updatecount
                updatecount = updatecount + 1
                msg = str(mvid) + " is Exist Update " + str(updatecount)
                # 接続を閉じる
                connection.close()
                return msg

##メインループ
# データベースファイルのパス
#dbpath = '/home/ubuntu/workspace/ex50/development.sqlite3'
dbpath = 'development.sqlite3'

# データベース接続とカーソル生成
connection = sqlite3.connect(dbpath,isolation_level="IMMEDIATE")
connection.set_trace_callback(print)
# 自動コミットにする場合は下記を指定（コメントアウトを解除のこと）
# connection.isolation_level = None
cursor = connection.cursor()
#return str(mvid) + "ismvid"
#http://code.i-harness.com/ja/q/253bd3
# エラー処理（例外処理）
try:
        rows = cursor.execute("select thisavid from thisavlists order by updatedate asc limit 40")
        #connection.close()
        #cursor.close()
        #print("test")
        for row in rows:
            #print("test")
            mvid = row[0]
            print(mvid)
            #IDを元に個別ページへアクセス
            url = 'https://www.thisav.com/video/' + str(mvid) + '/'
            print(url)
            r = requests.get(url,allow_redirects=False)
            print(str(requests.get(url,allow_redirects=False)))
            if r.status_code == 404:
                    #存在がなければ削除する
                    deletelists.append(str(mvid))
            elif r.status_code == 301 or r.status_code == 302:
                        #存在しなければ「error404」へリダイレクトされるため、その場合は削除されたとみなす。
                        #存在していなければ削除する。
                        #https://dev.classmethod.jp/cloud/python-requests-status-code/
                        deletelists.append(str(mvid))

            else:
                        #存在していれば更新する
                        updateists.append(str(mvid))

#エラー処理
except sqlite3.Error as e:
    print('sqlite3.Error occurred:', e.args[0])
# 接続を閉じる
connection.close()

#DB操作
for deletelist in deletelists:
        #存在がなければ削除する
        print(sqlitemente(deletelist,'2'))

for updateist in updateists:
        #存在していれば更新する
        print(sqlitemente(updateist,'1'))

print(deletelists)
print(updateists)
elapsed_time = time.time() - start
print ("elapsed_time:{0}".format(elapsed_time) + "[sec]")
print ("削除件数：" + str(deletecnt))
print ("更新件数：" + str(updatecount))


import os
from .resnet import (
    resnet32_test,
    resnet8,
    resnet14,
    resnet20,
    resnet20_test,
    resnet32,
    resnet44,
    resnet56,
    resnet56_test,
    resnet110,
    resnet110_test,
    resnet8x4,
    resnet8x4_test,
    resnet32x4,
    resnet32x4_test,
)
from .resnetv2 import ResNet50, ResNet18, ResNet50_test
from .wrn import wrn_16_1, wrn_16_2, wrn_16_2_test, wrn_40_1, wrn_40_1_test, wrn_40_2, wrn_40_2_test
from .vgg import vgg19_bn, vgg16_bn, vgg13_bn, vgg13_bn_test, vgg11_bn, vgg8_bn, vgg8_bn_test
from .mobilenetv2 import mobile_half, mobile_half_test
from .ShuffleNetv1 import ShuffleV1, ShuffleV1_test
from .ShuffleNetv2 import ShuffleV2, ShuffleV2_test
cifar100_model_prefix = os.path.join(
    os.path.dirname(os.path.abspath(__file__)),
    "../../../download_ckpts/cifar_teachers/"
)
cifar_model_dict = {

    # teachers
    "resnet32x4_test": (
        resnet32x4_test,
        None
    ),
    "resnet56": (
        resnet56,
        cifar100_model_prefix + "resnet56_vanilla/ckpt_epoch_240.pth",
    ),
    "resnet56_test": (
        resnet56_test,
        None
    ),
    "resnet110": (
        resnet110,
        cifar100_model_prefix + "resnet110_vanilla/ckpt_epoch_240.pth",
    ),
    "resnet110_test": (
        resnet110_test,
        None
    ),
    "resnet32x4": (
        resnet32x4,
        cifar100_model_prefix + "resnet32x4_vanilla/ckpt_epoch_240.pth",
    ),
    "ResNet50": (
        ResNet50,
        cifar100_model_prefix + "ResNet50_vanilla/ckpt_epoch_240.pth",
    ),
    "ResNet50_test": (
        ResNet50_test,
        None
    ),
    "wrn_40_2": (
        wrn_40_2,
        cifar100_model_prefix + "wrn_40_2_vanilla/ckpt_epoch_240.pth",
    ),
    "wrn_40_2_test": (
        wrn_40_2_test,
        None
    ),
    "vgg13": (vgg13_bn, cifar100_model_prefix + "vgg13_vanilla/ckpt_epoch_240.pth"),
    "vgg13_test": (vgg13_bn_test,None),

    # students
    "resnet8": (resnet8, None),
    "resnet14": (resnet14, None),
    "resnet20": (resnet20, None),
    "resnet20_test": (resnet20_test, None),
    "resnet32": (resnet32, None),
    "resnet32_test": (resnet32_test, None),
    "resnet44": (resnet44, None),
    "resnet8x4": (resnet8x4, None),
    "resnet8x4_test": (resnet8x4_test, None),
    "ResNet18": (ResNet18, None),
    "wrn_16_1": (wrn_16_1, None),
    "wrn_16_2": (wrn_16_2, None),
    "wrn_16_2_test": (wrn_16_2_test, None),
    "wrn_40_1": (wrn_40_1, None),
    "wrn_40_1_test": (wrn_40_1_test, None),
    "vgg8": (vgg8_bn, None),
    "vgg8_test": (vgg8_bn_test, None),
    "vgg11": (vgg11_bn, None),
    "vgg16": (vgg16_bn, None),
    "vgg19": (vgg19_bn, None),
    "MobileNetV2": (mobile_half, None),
    "MobileNetV2_test": (mobile_half_test, None),
    "ShuffleV1": (ShuffleV1, None),
    "ShuffleV1_test": (ShuffleV1_test, None),
    "ShuffleV2": (ShuffleV2, None),
    "ShuffleV2_test": (ShuffleV2_test, None),
}


from collections import namedtuple
from pytest import approx, fixture, raises
from symplyphysics import (
    errors,
    units,
    Quantity,
    SI,
    convert_to,
)
from symplyphysics.laws.relativistic.waves import longitudinal_frequency_shift_from_velocity as doppler_law

# Description. With help of online calculator at https://physics.icalculator.com/the-doppler-effect-in-light-waves-calculator.html:
## For red wave with frequency 384THz (3.84e14 Hz) emitted by object moving away from observer with velocity 0.1c = 29979245.8 m/s
## observed frequency should be 347341068940800

@fixture(name="test_args")
def test_args_fixture():
    object_velocity = Quantity(29979245.8 * units.meter / units.second)
    emitted_frequency = Quantity(3.84e14 * units.hertz)
    Args = namedtuple("Args", ["object_velocity", "emitted_frequency"])
    return Args(object_velocity=object_velocity, emitted_frequency=emitted_frequency)

def test_basic_frequency(test_args):
    result = doppler_law.calculate_observed_frequency(test_args.emitted_frequency,
        test_args.object_velocity)
    assert SI.get_dimension_system().equivalent_dims(result.dimension, units.frequency)
    result_freq = convert_to(result, units.hertz).evalf(6)
    assert result_freq == approx(3.473e14, 0.001)

def test_bad_velocity(test_args):
    vb = Quantity(1 * units.coulomb)
    with raises(errors.UnitsError):
        doppler_law.calculate_observed_frequency(test_args.emitted_frequency, vb)
    with raises(TypeError):
        doppler_law.calculate_observed_frequency(test_args.emitted_frequency, 100)

def test_bad_frequency(test_args):
    fb = Quantity(1 * units.coulomb)
    with raises(errors.UnitsError):
        doppler_law.calculate_observed_frequency(fb, test_args.object_velocity)
    with raises(TypeError):
        doppler_law.calculate_observed_frequency(100, test_args.object_velocity)


# -*- coding: utf-8 -*-
from openerp import fields, models

class WkfConfigPurchaseUnit(models.Model):
    _name = 'wkf.config.purchase.unit'
    _description = 'Purchasing Unit'

    name = fields.Char(
        string='Name',
        required=True,
        size=500,
    )
    description = fields.Text(
        string='Description',
        size=1000,
    )
    org_id = fields.Many2one(
        'res.org',
        string='Org',
        required=True,
    )
    doctype_id = fields.Many2one(
        'wkf.config.doctype',
        domain="[('module', 'in', ('purchase', 'purchase_pd'))]",
        string='Document Type',
        required=True,
    )
    responsible_ids = fields.One2many(
        'wkf.config.purchase.unit.responsible',
        'purchasing_unit_id',
        string='Responsible',
        copy=True,
    )
    section_ids = fields.Many2many(
        'res.section',
        'purchasingunit_section_rel',
        'purchasing_unit_id',
        'section_id',
        string='Section',
    )

class WkfConfigPurchaseUnitResponsible(models.Model):
    _name = 'wkf.config.purchase.unit.responsible'
    _description = 'Purchasing Unit Responsible'

    purchasing_unit_id = fields.Many2one(
        'wkf.config.purchase.unit',
        string='Purchasing Unit',
        required=True,
        ondelete='cascade',
    )
    employee_id = fields.Many2one(
        'hr.employee',
        string='Employee',
        required=True,
    )
    level = fields.Selection([
        ('L01', "L01"),
        ('L02', "L02"), ],
        string='Level',
        required=True,
    )


import heapq
from sys import stdin
input = stdin.readline

n, m = map(int, input().split())
heap = list(map(int, input().split()))
heapq.heapify(heap)
for _ in range(m) :
    temp = heapq.heappop(heap) + heapq.heappop(heap)
    heapq.heappush(heap, temp)
    heapq.heappush(heap, temp)
print(sum(heap))


from tkinter import *
from PIL import ImageTk, Image

# Create root widget
root = Tk()
root.title("Hello World")  # change window title text
root.iconbitmap("C:/Users/Janice/Desktop/Coding/Code/Python/Notes/freeCodeCamp.org/Tkinter/images/bayern_icon.ico")
root.geometry("400x400")

# Create function to show sum of checked boxes
def sum():
	global label_1
	label_1.destroy()
	label_1 = Label(root, text=str(var_1.get()+var_2.get()+var_3.get()))
	label_1.pack()

# Create variables to hold checkbox values
var_1 = IntVar()
var_2 = IntVar()
var_3 = IntVar()

# Create checkboxes
cb_1 = Checkbutton(root, text="1", variable=var_1, onvalue=1, offvalue=0)
cb_1.deselect()
cb_1.pack()

cb_2 = Checkbutton(root, text="2", variable=var_2, onvalue=2, offvalue=0)
cb_2.deselect()
cb_2.pack()

cb_3 = Checkbutton(root, text="3", variable=var_3, onvalue=3, offvalue=0)
cb_3.deselect()
cb_3.pack()

# Create button to apply values
button_1 = Button(root, text="Submit", command=sum)
button_1.pack()

label_1 = Label(root, text="0")
label_1.pack()

# Create main event loop
root.mainloop()


""" Cash movement GUI """
import tkinter
from gui.amount_textbox import AmountTextbox
from gui.company_combobox import CompanyCombobox
from gui.labeled_textbox import LabeledTextbox
from gui.labeled_combobox import LabeledCombobox
from gui.prime_singleton import PrimeSingleton
from gui.font import default_font
from model.payment import payment
import config

class CashMovement:
    """ GUI to record a cash movement
    The movement may be an incoming, outcoming or transfer payment
    """
    _WINDOW_WIDTH = 450
    _WINDOW_HEIGHT = 200

    def __init__(self):
        self._window = tkinter.Toplevel()
        self._window.wm_geometry(str(self._WINDOW_WIDTH) + "x" + str(self._WINDOW_HEIGHT))
        cell_y = 0

        self._company = CompanyCombobox(self._window, "Company", 0, cell_y)
        cell_y += config.CONSTANTS["GUI_CELL_HEIGHT"]

        self._direction = LabeledCombobox(self._window, "Direction", ["I", "O"], 0, cell_y)
        cell_y += config.CONSTANTS["GUI_CELL_HEIGHT"]

        self._amount = AmountTextbox(
            self._window,
            "Amount",
            0,
            config.CONSTANTS["HOME_CURRENCY"],
            0,
            cell_y)
        cell_y += config.CONSTANTS["GUI_CELL_HEIGHT"]

        self._description = LabeledTextbox(self._window, "Description", "", 0, cell_y)
        cell_y += config.CONSTANTS["GUI_CELL_HEIGHT"]

        save_button = tkinter.Button(self._window,
                                     text="OK",
                                     command=self._ok_click,
                                     font=default_font())
        save_button.place(x=config.CONSTANTS["GUI_CELL_WIDTH"], y=cell_y)

    def _ok_click(self):

        payment.record_cash_movement(
            company=self._company.company_name,
            direction=self._direction.selected_value,
            amount=self._amount.amount,
            currency=self._amount.currency,
            description=self._description.value
        )

        PrimeSingleton.get().refresh()
        self._window.destroy()


import argparse
import glob
import json
import logging
import os
import random

import numpy as np
import torch
from torch.utils.data import DataLoader, RandomSampler, SequentialSampler, TensorDataset
from torch.utils.data.distributed import DistributedSampler
from tqdm import tqdm, trange

from transformers import (
    WEIGHTS_NAME,
    AdamW,
    get_linear_schedule_with_warmup,
    BertConfig,
    BertModel,
    BertPreTrainedModel,
    BertTokenizer,
)
from transformers import glue_compute_metrics as compute_metrics
from transformers import glue_convert_examples_to_features as convert_examples_to_features
from transformers import glue_output_modes as output_modes
from transformers import glue_processors as processors

from transformers.data.processors.utils import InputExample, DataProcessor

try:
    from torch.utils.tensorboard import SummaryWriter
except ImportError:
    from tensorboardX import SummaryWriter

import code
import os
import pickle
from sklearn.metrics.pairwise import cosine_similarity

import torch
import torch.nn as nn
import torch.nn.functional as F

import numpy as np
import pandas as pd

logger = logging.getLogger(__name__)
model_path = "/share/data/lang/users/zeweichu/projs/qa-chinese/chinese_wwm_ext_pytorch"

MODEL_CLASSES = {
    "bert": (BertConfig, BertTokenizer),
}

def set_seed(args):
    random.seed(args.seed)
    np.random.seed(args.seed)
    torch.manual_seed(args.seed)
    if args.n_gpu > 0:
        torch.cuda.manual_seed_all(args.seed)

class FAQProcessor(DataProcessor):
    """Processor for the CoLA data set (GLUE version)."""

    def get_example_from_tensor_dict(self, tensor_dict):
        """See base class."""
        return InputExample(
            tensor_dict["idx"].numpy(),
            tensor_dict["sentence"].numpy().decode("utf-8"),
            None,
            str(tensor_dict["label"].numpy()),
        )

    def prepare_data(self, file_dir):
        train_df = pd.read_csv(file_dir, sep="\t")
        self.candidate_title = train_df["title"].tolist()
        self.candidate_reply = train_df["reply"].tolist()
        self.candidate_translated = train_df["translated"].tolist()

    def get_train(self):
        return self._create_pos_examples(self.candidate_title, self.candidate_translated, "pos"), self._create_neg_examples(self.candidate_title, "neg")

    def _create_pos_examples(self, lines_a, lines_b, set_type):
        """Creates examples for the training and dev sets."""
        examples = []
        for (i, (line_a, line_b)) in enumerate(zip(lines_a, lines_b)):
            guid = "%s-%s" % (set_type, i)
            examples.append(InputExample(guid=guid, text_a=line_a, text_b=line_b, label=1))
        return examples

    def _create_neg_examples(self, lines, set_type):
        """Creates examples for the training and dev sets."""
        examples = []
        for (i, line_a) in enumerate(zip(lines)):
            guid = "%s-%s" % (set_type, i)
            line_b = random.sample(lines, 1)[0]
            while line_b == line_a:
                line_b = random.sample(1)[0]
            examples.append(InputExample(guid=guid, text_a=line_a, text_b=line_b, label=1))
        return examples

class BertForFAQHinge(BertPreTrainedModel):
    r"""
        **labels**: (`optional`) ``torch.LongTensor`` of shape ``(batch_size,)``:
            Labels for computing the sequence classification/regression loss.
            Indices should be in ``[0, ..., config.num_labels - 1]``.
            If ``config.num_labels == 1`` a regression loss is computed (Mean-Square loss),
            If ``config.num_labels > 1`` a classification loss is computed (Cross-Entropy).
    Outputs: `Tuple` comprising various elements depending on the configuration (config) and inputs:
        **loss**: (`optional`, returned when ``labels`` is provided) ``torch.FloatTensor`` of shape ``(1,)``:
            Classification (or regression if config.num_labels==1) loss.
        **logits**: ``torch.FloatTensor`` of shape ``(batch_size, config.num_labels)``
            Classification (or regression if config.num_labels==1) scores (before SoftMax).
        **hidden_states**: (`optional`, returned when ``config.output_hidden_states=True``)
            list of ``torch.FloatTensor`` (one for the output of each layer + the output of the embeddings)
            of shape ``(batch_size, sequence_length, hidden_size)``:
            Hidden-states of the model at the output of each layer plus the initial embedding outputs.
        **attentions**: (`optional`, returned when ``config.output_attentions=True``)
            list of ``torch.FloatTensor`` (one for each layer) of shape ``(batch_size, num_heads, sequence_length, sequence_length)``:
            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention heads.
    Examples::
        tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
        model = BertForSequenceClassification.from_pretrained('bert-base-uncased')
        input_ids = torch.tensor(tokenizer.encode("Hello, my dog is cute", add_special_tokens=True)).unsqueeze(0)  # Batch size 1
        labels = torch.tensor([1]).unsqueeze(0)  # Batch size 1
        outputs = model(input_ids, labels=labels)
        loss, logits = outputs[:2]
    """

    def __init__(self, config):
        super(BertPreTrainedModel, self).__init__(config)
        self.num_labels = config.num_labels

        self.bert = BertModel(config)
        self.dropout = nn.Dropout(config.hidden_dropout_prob)
        self.scoring = nn.Linear(config.hidden_size, 1)

        self.init_weights()

    def forward(
        self,
        input_ids=None,
        attention_mask=None,
        token_type_ids=None,
        position_ids=None,
        head_mask=None,
        inputs_embeds=None,
        labels=None,
    ):
        outputs = self.bert(
            input_ids,
            attention_mask=attention_mask,
            token_type_ids=token_type_ids,
            position_ids=position_ids,
            head_mask=head_mask,
            inputs_embeds=inputs_embeds,
        )

        pooled_output = outputs[1]
        pooled_output = self.dropout(pooled_output)
        score = self.scoring(pooled_output)

        outputs = (score,) + outputs[2:]  # add hidden states and attention if they are here

        return outputs  # (loss), logits, (hidden_states), (attentions)

def train(args, train_dataset, model, processor, tokenizer):
    """ Train the model """
    if args.local_rank in [-1, 0]:
        tb_writer = SummaryWriter()

    # Prepare optimizer and schedule (linear warmup and decay)
    no_decay = ["bias", "LayerNorm.weight"]
    optimizer_grouped_parameters = [
        {
            "params": [p for n, p in model.named_parameters() if not any(nd in n for nd in no_decay)],
            "weight_decay": args.weight_decay,
        },
        {"params": [p for n, p in model.named_parameters() if any(nd in n for nd in no_decay)], "weight_decay": 0.0},
    ]

    t_total = len(train_dataset) // args.gradient_accumulation_steps * args.num_train_epochs
    optimizer = AdamW(optimizer_grouped_parameters, lr=args.learning_rate, eps=args.adam_epsilon)
    scheduler = get_linear_schedule_with_warmup(
        optimizer, num_warmup_steps=args.warmup_steps, num_training_steps=t_total
    )

    # Train!
    logger.info("***** Running training *****")
    logger.info("  Num examples = %d", len(train_dataset))
    logger.info("  Num Epochs = %d", args.num_train_epochs)
    logger.info("  Instantaneous batch size per GPU = %d", args.per_gpu_train_batch_size)
    logger.info("  Gradient Accumulation steps = %d", args.gradient_accumulation_steps)
    logger.info("  Total optimization steps = %d", t_total)

    epochs_trained = 0
    global_step = 0
    steps_trained_in_current_epoch = 0

    tr_loss, logging_loss = 0.0, 0.0
    model.zero_grad()
    train_iterator = trange(
        epochs_trained, int(args.num_train_epochs), desc="Epoch", disable=args.local_rank not in [-1, 0]
    )
    set_seed(args)  # Added here for reproductibility
    for k in train_iterator:
        if k != 0:
            dataset, _, _ = load_examples(args, args.task_name, tokenizer, processor)
        args.train_batch_size = args.per_gpu_train_batch_size * max(1, args.n_gpu)
        train_sampler = SequentialSampler(train_dataset)
        train_dataloader = DataLoader(train_dataset, sampler=train_sampler, batch_size=args.train_batch_size)
        epoch_iterator = tqdm(train_dataloader, desc="Iteration", disable=args.local_rank not in [-1, 0])
        for step, batch in enumerate(epoch_iterator):

            # Skip past any already trained steps if resuming training
            if steps_trained_in_current_epoch > 0:
                steps_trained_in_current_epoch -= 1
                continue

            model.train()
            batch = tuple(t.to(args.device) for t in batch)
            pos_inputs = {"input_ids": batch[0], "attention_mask": batch[1], "token_type_ids": batch[2]}
            neg_inputs = {"input_ids": batch[3], "attention_mask": batch[4], "token_type_ids": batch[5]}
            pos_outputs = model(**pos_inputs)
            neg_outputs = model(**neg_inputs)

            pos_score = pos_outputs[0]
            neg_score = neg_outputs[0]

            loss = -(pos_score - neg_score - args.margin) # pos必须要比neg高一定的margin
            loss[loss < 0] = 0
            loss = torch.mean(loss)
            loss.backward()

            tr_loss += loss.item()
            if (step + 1) % args.gradient_accumulation_steps == 0:
                torch.nn.utils.clip_grad_norm_(model.parameters(), args.max_grad_norm)

                optimizer.step()
                scheduler.step()  # Update learning rate schedule
                model.zero_grad()
                global_step += 1
        logger.info("average loss: " + str(tr_loss/global_step))

    return global_step, tr_loss / global_step

def evaluate(args, model, eval_dataset):
    # 把所有的问题全部用BERT编码
    # Loop to handle MNLI double evaluation (matched, mis-matched)
    scores = []

    args.eval_batch_size = args.per_gpu_eval_batch_size * max(1, args.n_gpu)
    # Note that DistributedSampler samples randomly
    eval_sampler = SequentialSampler(eval_dataset)
    eval_dataloader = DataLoader(eval_dataset, sampler=eval_sampler, batch_size=args.eval_batch_size)

    # multi-gpu eval
    if args.n_gpu > 1:
        model = torch.nn.DataParallel(model)

    # Eval!
    logger.info("  Num examples = %d", len(eval_dataset))
    logger.info("  Batch size = %d", args.eval_batch_size)
    eval_loss = 0.0
    nb_eval_steps = 0
    preds = None
    out_label_ids = None
    for batch in tqdm(eval_dataloader, desc="Evaluating"):
        model.eval()
        batch = tuple(t.to(args.device) for t in batch)

        with torch.no_grad():
            inputs = {"input_ids": batch[0], "attention_mask": batch[1], "token_type_ids": batch[2]}
            outputs = model(**inputs)

            score = outputs[0]
            scores.append(score)

    scores = [score.data.cpu().view(-1) for score in scores]
    scores = torch.cat(scores)

    return scores.numpy()

def load_examples(args, task, tokenizer, processor):
    if args.local_rank not in [-1, 0] and not evaluate:
        torch.distributed.barrier()  # Make sure only the first process in distributed training process the dataset, and the others will use the cache

    pos_data, neg_data = processor.get_train()

    # Load data features from cache or dataset file
    logger.info("Creating features from dataset file at %s", args.data_dir)
    pos_features = convert_examples_to_features(
        pos_data,
        tokenizer,
        label_list=[1],
        output_mode="classification",
        max_length=args.max_seq_length,
        pad_on_left=bool(args.model_type in ["xlnet"]),  # pad on the left for xlnet
        pad_token=tokenizer.convert_tokens_to_ids([tokenizer.pad_token])[0],
        pad_token_segment_id=4 if args.model_type in ["xlnet"] else 0,
    )
    neg_features = convert_examples_to_features(
        neg_data,
        tokenizer,
        label_list=[1],
        output_mode="classification",
        max_length=args.max_seq_length,
        pad_on_left=bool(args.model_type in ["xlnet"]),  # pad on the left for xlnet
        pad_token=tokenizer.convert_tokens_to_ids([tokenizer.pad_token])[0],
        pad_token_segment_id=4 if args.model_type in ["xlnet"] else 0,
    )

    if args.local_rank == 0 and not evaluate:
        torch.distributed.barrier()  # Make sure only the first process in distributed training process the dataset, and the others will use the cache

    # Convert to Tensors and build dataset
    pos_input_ids = torch.tensor([f.input_ids for f in pos_features], dtype=torch.long)
    pos_attention_mask = torch.tensor([f.attention_mask for f in pos_features], dtype=torch.long)
    pos_token_type_ids = torch.tensor([f.token_type_ids for f in pos_features], dtype=torch.long)
    neg_input_ids = torch.tensor([f.input_ids for f in neg_features], dtype=torch.long)
    neg_attention_mask = torch.tensor([f.attention_mask for f in neg_features], dtype=torch.long)
    neg_token_type_ids = torch.tensor([f.token_type_ids for f in neg_features], dtype=torch.long)
    dataset = TensorDataset(pos_input_ids, pos_attention_mask, pos_token_type_ids, neg_input_ids, neg_attention_mask, neg_token_type_ids)

    return dataset, processor.candidate_title, processor.candidate_reply

def main():
    parser = argparse.ArgumentParser()

    # Required parameters
    parser.add_argument(
        "--data_dir",
        default=None,
        type=str,
        required=True,
        help="The input data dir. Should contain the .tsv files (or other data files) for the task.",
    )
    parser.add_argument(
        "--model_type",
        default=None,
        type=str,
        required=True,
        help="Model type selected in the list: " + ", ".join(MODEL_CLASSES.keys()),
    )
    parser.add_argument(
        "--model_name_or_path",
        default=None,
        type=str,
        required=True,
        help="Path to pre-trained model or shortcut name selected in the list",
    )
    parser.add_argument(
        "--task_name",
        default=None,
        type=str,
        required=True,
        help="The name of the task to train selected in the list: " + ", ".join(processors.keys()),
    )
    parser.add_argument(
        "--output_dir",
        default=None,
        type=str,
        required=True,
        help="The output directory where the model predictions and checkpoints will be written.",
    )

    # Other parameters
    parser.add_argument(
        "--config_name", default="", type=str, help="Pretrained config name or path if not the same as model_name"
    )
    parser.add_argument(
        "--tokenizer_name",
        default="",
        type=str,
        help="Pretrained tokenizer name or path if not the same as model_name",
    )
    parser.add_argument(
        "--cache_dir",
        default="",
        type=str,
        help="Where do you want to store the pre-trained models downloaded from s3",
    )
    parser.add_argument(
        "--max_seq_length",
        default=128,
        type=int,
        help="The maximum total input sequence length after tokenization. Sequences longer "
        "than this will be truncated, sequences shorter will be padded.",
    )
    parser.add_argument("--do_train", action="store_true", help="Whether to run training.")
    parser.add_argument("--do_eval", action="store_true", help="Whether to run eval on the dev set.")
    parser.add_argument(
        "--evaluate_during_training", action="store_true", help="Rul evaluation during training at each logging step."
    )
    parser.add_argument(
        "--do_lower_case", action="store_true", help="Set this flag if you are using an uncased model."
    )

    parser.add_argument("--per_gpu_train_batch_size", default=8, type=int, help="Batch size per GPU/CPU for training.")
    parser.add_argument(
        "--per_gpu_eval_batch_size", default=8, type=int, help="Batch size per GPU/CPU for evaluation."
    )
    parser.add_argument(
        "--gradient_accumulation_steps",
        type=int,
        default=1,
        help="Number of updates steps to accumulate before performing a backward/update pass.",
    )
    parser.add_argument("--margin", default=5, type=float, help="The margin of hinge loss.")
    parser.add_argument("--learning_rate", default=5e-5, type=float, help="The initial learning rate for Adam.")
    parser.add_argument("--weight_decay", default=0.0, type=float, help="Weight decay if we apply some.")
    parser.add_argument("--adam_epsilon", default=1e-8, type=float, help="Epsilon for Adam optimizer.")
    parser.add_argument("--max_grad_norm", default=1.0, type=float, help="Max gradient norm.")
    parser.add_argument(
        "--num_train_epochs", default=3.0, type=float, help="Total number of training epochs to perform."
    )
    parser.add_argument(
        "--max_steps",
        default=-1,
        type=int,
        help="If > 0: set total number of training steps to perform. Override num_train_epochs.",
    )
    parser.add_argument("--warmup_steps", default=0, type=int, help="Linear warmup over warmup_steps.")

    parser.add_argument("--logging_steps", type=int, default=50, help="Log every X updates steps.")
    parser.add_argument("--save_steps", type=int, default=50, help="Save checkpoint every X updates steps.")
    parser.add_argument(
        "--eval_all_checkpoints",
        action="store_true",
        help="Evaluate all checkpoints starting with the same prefix as model_name ending and ending with step number",
    )
    parser.add_argument("--no_cuda", action="store_true", help="Avoid using CUDA when available")
    parser.add_argument(
        "--overwrite_cache", action="store_true", help="Overwrite the cached training and evaluation sets"
    )
    parser.add_argument("--seed", type=int, default=42, help="random seed for initialization")

    parser.add_argument(
        "--fp16",
        action="store_true",
        help="Whether to use 16-bit (mixed) precision (through NVIDIA apex) instead of 32-bit",
    )
    parser.add_argument(
        "--fp16_opt_level",
        type=str,
        default="O1",
        help="For fp16: Apex AMP optimization level selected in ['O0', 'O1', 'O2', and 'O3']."
        "See details at https://nvidia.github.io/apex/amp.html",
    )
    parser.add_argument("--local_rank", type=int, default=-1, help="For distributed training: local_rank")
    parser.add_argument("--server_ip", type=str, default="", help="For distant debugging.")
    parser.add_argument("--server_port", type=str, default="", help="For distant debugging.")
    args = parser.parse_args()

    # Setup distant debugging if needed
    if args.server_ip and args.server_port:
        # Distant debugging - see https://code.visualstudio.com/docs/python/debugging#_attach-to-a-local-script
        import ptvsd

        print("Waiting for debugger attach")
        ptvsd.enable_attach(address=(args.server_ip, args.server_port), redirect_output=True)
        ptvsd.wait_for_attach()

    # Setup CUDA, GPU & distributed training
    if args.local_rank == -1 or args.no_cuda:
        device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
        args.n_gpu = torch.cuda.device_count()
    else:  # Initializes the distributed backend which will take care of sychronizing nodes/GPUs
        torch.cuda.set_device(args.local_rank)
        device = torch.device("cuda", args.local_rank)
        torch.distributed.init_process_group(backend="nccl")
        args.n_gpu = 1
    args.device = device

    # Setup logging
    logging.basicConfig(
        format="%(asctime)s - %(levelname)s - %(name)s -   %(message)s",
        datefmt="%m/%d/%Y %H:%M:%S",
        level=logging.INFO if args.local_rank in [-1, 0] else logging.WARN,
    )
    logger.warning(
        "Process rank: %s, device: %s, n_gpu: %s, distributed training: %s, 16-bits training: %s",
        args.local_rank,
        device,
        args.n_gpu,
        bool(args.local_rank != -1),
        args.fp16,
    )

    # Set seed
    set_seed(args)

    # Prepare GLUE task
    args.task_name = args.task_name.lower()

    # Load pretrained model and tokenizer
    if args.local_rank not in [-1, 0]:
        torch.distributed.barrier()  # Make sure only the first process in distributed training will download model & vocab

    args.model_type = args.model_type.lower()
    config_class, tokenizer_class = MODEL_CLASSES[args.model_type]
    model_class = BertForFAQHinge
    config = config_class.from_pretrained(
        args.config_name if args.config_name else args.model_name_or_path,
        finetuning_task=args.task_name,
        cache_dir=args.cache_dir if args.cache_dir else None,
    )
    tokenizer = tokenizer_class.from_pretrained(
        args.tokenizer_name if args.tokenizer_name else args.model_name_or_path,
        do_lower_case=args.do_lower_case,
        cache_dir=args.cache_dir if args.cache_dir else None,
    )
    model = model_class.from_pretrained(
        args.model_name_or_path,
        from_tf=bool(".ckpt" in args.model_name_or_path),
        config=config,
        cache_dir=args.cache_dir if args.cache_dir else None,
    )

    if args.local_rank == 0:
        torch.distributed.barrier()  # Make sure only the first process in distributed training will download model & vocab

    model.to(args.device)

    logger.info("Training/evaluation parameters %s", args)

    processor = FAQProcessor()
    processor.prepare_data(args.data_dir)
    dataset, candidate_title, candidate_reply = load_examples(args, args.task_name, tokenizer, processor)
    if args.do_train:
        train(args, dataset, model, processor, tokenizer)
        # Create output directory if needed
        if not os.path.exists(args.output_dir) and args.local_rank in [-1, 0]:
            os.makedirs(args.output_dir)

        logger.info("Saving model checkpoint to %s", args.output_dir)
        # Save a trained model, configuration and tokenizer using `save_pretrained()`.
        # They can then be reloaded using `from_pretrained()`
        model_to_save = (
            model.module if hasattr(model, "module") else model
        )  # Take care of distributed/parallel training
        model_to_save.save_pretrained(args.output_dir)
        tokenizer.save_pretrained(args.output_dir)

        # Good practice: save your training arguments together with the trained model
        torch.save(args, os.path.join(args.output_dir, "training_args.bin"))

        # Load a trained model and vocabulary that you have fine-tuned
        model = model_class.from_pretrained(args.output_dir)
        tokenizer = tokenizer_class.from_pretrained(args.output_dir)
        model.to(args.device)

    if args.do_eval:
        while True:
            title = input("你的问题是？\n")
            if len(title.strip()) == 0:
                continue

            examples = [InputExample(guid=0, text_a=title, text_b=c, label=1) for c in candidate_title]
            features = convert_examples_to_features(
                examples,
                tokenizer,
                label_list=[1],
                output_mode="classification",
                max_length=args.max_seq_length,
                pad_on_left=bool(args.model_type in ["xlnet"]),  # pad on the left for xlnet
                pad_token=tokenizer.convert_tokens_to_ids([tokenizer.pad_token])[0],
                pad_token_segment_id=4 if args.model_type in ["xlnet"] else 0,
            )

            # Convert to Tensors and build dataset
            all_input_ids = torch.tensor([f.input_ids for f in features], dtype=torch.long)
            all_attention_mask = torch.tensor([f.attention_mask for f in features], dtype=torch.long)
            all_token_type_ids = torch.tensor([f.token_type_ids for f in features], dtype=torch.long)

            dataset = TensorDataset(all_input_ids, all_attention_mask, all_token_type_ids)
            scores = evaluate(args, model, dataset)
            top5_indices = scores.argsort()[-5:][::-1]
            for index in top5_indices:
                print("可能的答案，参考问题：" + candidate_title[index] + "\t答案：" + candidate_reply[index] + "\t得分：" + str(scores[index]))
                print()

if __name__ == "__main__":
    main()


import urllib.request as dw

imgUrl = "https://search.pstatic.net/common/?src=http%3A%2F%2Fblogfiles.naver.net%2F20150823_231%2Fcodn9_14403263840439uB4A_JPEG%2Ftumblr_n0forjSMuW1qgyg6yo1_540.jpg&type=sc960_832"
htmlURL = "http://google.com"

savePath1 = "/Users/armian/Inflearn/tmp/test1.jpg"
savePath2 = "/Users/armian/Inflearn/tmp/index.html"

f = dw.urlopen(imgUrl).read()
f2 = dw.urlopen(htmlURL).read()

saveFile1 = open(savePath1, 'wb') # w : write, r : read, a : add
saveFile1.write(f)
saveFile1.close()

with open(savePath2, 'wb') as saveFile2:
    saveFile2.write(f2)

print("다운로드 완료!")


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

a = np.zeros(4)
step = 0.01
action = [-step, step]
epsilon = 0.9
max_episodes = 100
M_state = 100
N_action = 2
#建立Q表
def build_Qtable(M_state,N_action):
    data = np.zeros((M_state, N_action))
    Q = pd.DataFrame(data,columns=action)
    print(Q)

#生成功率分配因子
def get_a(a):
    for i in range(len(a)):
        a[i] = '%.2f' % np.random.uniform(0,1)
        if np.sum(a) > 1:
            a[i] = 0
    print(a, np.sum(a))

#更新动作
def update_action(a,action):
    for i in range(len(a)):
        if a[i] >= step:
            a[i] = '%.2f' % (a[i] + np.random.choice(action))
        if np.sum(a) > 1:
            a[i] = '%.2f' % (a[i] - step)

    print(a, np.sum(a))

#从Q表选择动作
def choose_action(state, Q):
    state_action = Q.iloc[state, :]
    if np.random.uniform(0,1) > 0.9:
        action_name = np.random.choice(action)

    else:
        action_name = state_action.idxmax()
    return action_name

def RL():
    Q = build_Qtable(M_state, N_action)
    for episode in range(max_episodes):
        step_counter = 0
        s = 0
        is_terminated = False

#更新Q表

build_Qtable(M_state,N_action)
get_a(a)
update_action(a,action)


from json_cpp import JsonObject
from .world import World
from .shape import Polygon_list
from .visibility import to_radians, angle_difference, Location_visibility
from .location import Location
from .util import Timer

class Capture_parameters(JsonObject):

    def __init__(self, distance: float = 0.0, angle: float = 0.0, cool_down: float = 0.0):
        self.distance = distance
        self.angle = angle
        self.cool_down = cool_down

class Capture:

    def __init__(self, parameters: Capture_parameters, world: World):
        self.dist_max = parameters.distance * world.implementation.cell_transformation.size
        self.theta_diff_max = to_radians(parameters.angle / 2)
        occlusions_locations = world.cells.occluded_cells().get("location")
        occlusions_polygons = Polygon_list.get_polygons(occlusions_locations, world.configuration.cell_shape.sides, world.implementation.cell_transformation.size / 2, world.implementation.space.transformation.rotation + world.implementation.cell_transformation.rotation)
        self.visibility = Location_visibility(occlusions_polygons)
        self.cool_down = Timer(parameters.cool_down)

    def is_captured(self, predator_location: Location, predator_theta : float, prey_location: Location) -> bool:
        if self.cool_down:
            return False
        if predator_location.dist(prey_location) > self.dist_max:
            return False
        theta = predator_location.atan(prey_location)
        theta_diff, direction = angle_difference(predator_theta, theta)
        if theta_diff > self.theta_diff_max:
            return False
        if self.visibility.is_visible(predator_location, prey_location):
            self.cool_down.reset()
            return True
        else:
            return False


from typing import List
from enum import Enum
from threading import Lock
from datetime import datetime, timezone
from .exceptions import InvalidPriceError, InvalidDividendError, InvalidTradeError
import logging
#config.configure_logging()
logger = logging.getLogger(__name__)

class StockType(Enum):
    COMMON = 1
    PREFERRED = 2

class Stock:
    def __init__(self, symbol: str, stock_type: StockType, last_dividend: int, fixed_dividend: float, par_value: int):
        self.symbol = symbol
        self.stock_type = stock_type
        self.last_dividend = last_dividend
        self.fixed_dividend = fixed_dividend
        self.par_value = par_value
        self._trades = []
        self.lock = Lock()

    def dividend_yield(self, price: float) -> float:
        """
        Calculate the dividend yield for a stock based on its type and price.
        """
        if price == 0:
            raise InvalidPriceError("Price cannot be zero")
        if self.stock_type == StockType.COMMON:
            return self.last_dividend / price
        else:  # StockType.PREFERRED
            return (self.fixed_dividend * self.par_value) / price

    def pe_ratio(self, price: float) -> float:
        """
        Calculate the P/E Ratio for a stock based on the price.
        """
        dividend = self.dividend_yield(price) * price
        if dividend == 0:
            raise InvalidDividendError("Dividend cannot be zero")
        return price / dividend

    @property
    def trades(self):
        with self.lock:
            return self._trades.copy()

    def record_trade(self, quantity: int, buy_sell: str, price: float):
        """
        Record a trade for the stock with the provided details.
        """
        if quantity <= 0 or price <= 0:
            raise InvalidTradeError("Quantity and price must be positive values")
        if buy_sell not in ("BUY", "SELL"):
            raise InvalidTradeError("Invalid buy/sell indicator value")
        trade = {
            'timestamp': datetime.now(timezone.utc),
            'quantity': quantity,
            'buy_sell': buy_sell,
            'price': price
        }
        with self.lock:
            self._trades.append(trade)
        logger.info(f"Recorded trade: {trade}")

    def volume_weighted_stock_price(self, time_period: int = 300) -> float:
        """
        Calculate the Volume Weighted Stock Price for the stock based on the trades within the provided time period.
        """
        current_time = datetime.now(timezone.utc)
        with self.lock:
            trades = [trade for trade in self._trades if (current_time - trade['timestamp']).total_seconds() <= time_period]

        if not trades:
            return 0

        total_quantity = sum(trade['quantity'] for trade in trades)
        weighted_sum = sum(trade['price'] * trade['quantity'] for trade in trades)

        return weighted_sum / total_quantity


'''
N x N 행렬 각 칸에 -1 0 1 중 하나 저장
1. 종이가 모두 같은 수이면 그 종이를 사용
2. -1의수 0의수 1의수

_dict 선언 순서에 따라서 error 발생 global 상관x
'''
import sys
input = sys.stdin.readline

_dict = {-1 : 0, 0 : 0, 1 : 0}

def chk(r, c, n):
    for i in range(r, r + n):
        for j in range(c, c + n):
            if _board[i][j] != _board[r][c]:
                return False
    return True

def recur(r, c, n):
    global _dict, _board
    if chk(r, c, n):
        _dict[_board[r][c]] += 1
        return

    t = n // 3
    for i in range(3):
        for j in range(3):
            recur(r + i*t, c + j*t, t)
    return

N = int(input())
_board = [list(map(int, input().split())) for _ in range(N)]
recur(0, 0, N)
print(*_dict.values(), sep='\n')


import sys
input = sys.stdin.readline

coins = [500, 100, 50, 10, 5]
n = int(input())
n = 1000 - n
result = 0
for coin in coins:
    result += (n // coin) #나눈만큼 저장
    n = n % coin

result += n #1원짜리 저장
print(result)


# -*- coding: utf-8 -*-
from Gramatica import NoTerminal
from Gramatica import Gramatica
from AFD import verificarExistencia,Existe
from AFD import ElimiarInicial
import os
import AFD

listaGramatica = list()

def MenuG():
    nombreGramatica = str(input("Ingrese el nombre de la Gramatica: "))
    os.system("cls")
    op = 0
    listaNT = list()
    listaT = list()
    listaProducciones = list()
    while op!= 7:
        #os.system('cls')
        print("################## MENU GRAMATICA ##################")
        print("################ "+nombreGramatica+" ################")
        print("(1) Ingresar No Terminales")
        print("(2) Ingresar Terminales")
        print("(3) No Terminal Inicial ")
        print("(4) Producciones")
        print("(5) Mostrar Gramatica")
        print("(6) Ayuda")
        print("(7) Salir")
        op = int(input("####################Seleccione su opcion: "))
        if op==1:
            os.system('cls')
            NT=' '
            while NT!='':
                NT=""
                NT= str(input("Ingrese NT: "))
                if verificarExistencia(listaNT,NT) or Existe(listaT,NT):
                    print("El NT: "+NT+" ya existe")
                else:
                    NuevoNT = NoTerminal(NT)
                    listaNT.append(NuevoNT)
            listaNT.pop()
        elif op==2:
            os.system('cls')
            se=' '
            while se!='':
                se=""
                se= str(input("Ingrese Terminal: "))
                if Existe(listaT,se):
                    print(se+" ya existe")
                else:
                    listaT.append(se)
            listaT.pop()
        elif op==3:
            os.system('cls')
            print("Escoja NT Inicial")
            estdo = str(input("Nombre: "))
            if verificarExistencia(listaNT,estdo):
                ElimiarInicial(listaNT)
                for estado in listaNT:
                    if estado.Nombre==estdo:
                        estado.Inicial=True
            else:
                print(estdo+" no existe")
            for estado in listaNT:
                if estado.Inicial:
                    print("El estado inicial es "+estado.Nombre)
        elif op==4:
            os.system('cls')
            pr=' '
            while pr!='':
                pr = str(input("Ingrese Produccion: "))
                aux=pr
                aux=aux.split('>')
                for buscar in listaNT:
                    if buscar.Nombre==aux[0]:
                        if Existe(buscar.Producciones,aux[1]):
                            print("Ya existe esta produccion")
                        else:
                            buscar.Producciones.append(aux[1])
                for nt in listaNT:
                    for produc in nt.Producciones:
                        if produc=='epsilon':
                            nt.Aceptacion=True
        elif op==7:
            print("Desea Guardar los cambios?")
            guardar = str(input("(S/N)/(s/n): "))
            if guardar=='s' or guardar=='S':
                NuevaGramatica = Gramatica(nombreGramatica,listaT,listaNT)
                listaGramatica.append(NuevaGramatica)

def cargarGram(nombre):
    os.system('cls')
    ruta=nombre+".grm"
    arch=open(ruta,'r')
    lectura = arch.read()
    #lectura=lectura.replace(';',',')
    arch.close()
    lectura = lectura.split('\n')
    listaNT = list()
    listaterminales = list()
    auxiliar=""
    for produccion in lectura:
        print(produccion)
        produccion=produccion.replace('>',' ')
        produccion = produccion.split(' ')
        print(produccion)
        auxiliar=produccion[0]
        print(auxiliar+"  ...")
        break
    NuevoNT = NoTerminal(auxiliar)
    listaNT.append(NuevoNT)
    for state in listaNT:
        if auxiliar==state.Nombre:
            state.Inicial=True
            break
    for terminal in lectura:
        print(terminal)
        terminal=terminal.replace('>',' ')
        terminal=terminal.split(' ')
        if AFD.verificarExistencia(listaNT,terminal[0]):
            print("ya exisste"+terminal[0])
        else:
            NuevoNT = NoTerminal(terminal[0])
            listaNT.append(NuevoNT)
            print("valor: "+terminal[1])
        if AFD.Existe(listaterminales,terminal[1]):
            print("ya exisste"+terminal[1])
        else:
            listaterminales.append(terminal[1])
    for produc in lectura:
        produc=produc.split('>')
        for buscar in listaNT:
            if produc[0]==buscar.Nombre:
                if AFD.Existe(buscar.Producciones,produc[1]):
                    print("la produccion ya existe")
                else:
                    buscar.Producciones.append(produc[1])
    print("NT--------------------")
    for nt in listaNT:
        print(nt.Nombre)
    print("Terminales--------------")
    for ter in listaterminales:
        print(ter)
    print("Producciones: -------------------")
    for nt in listaNT:
        print(nt.Nombre)
        for produc in nt.Producciones:
            print("     "+produc)
            if produc=='epsilon':
                nt.Aceptacion=True
    print("Aceptacion----------")
    for nt in listaNT:
        if nt.Aceptacion:
            print(nt.Nombre)
    NuevaGramatica = Gramatica(nombre,listaterminales,listaNT)
    listaGramatica.append(NuevaGramatica)

def AceptacionXD(nombre,nt):
    for gram in listaGramatica:
        if gram.Nombre==nombre:
            for NT in gram.ListaNoTerminales:
                if NT.Nombre==nt:
                    if NT.Aceptacion:
                        return True
                    else:
                        return False

def EvaluarCadena(cadena,nombreGramatica,rutaAFD,rutaGramatica):
    listaRuta=list()
    listaRutaG=list()
    State=""
    per=""
    for gramatica in listaGramatica:
        if nombreGramatica==gramatica.Nombre:
            for NT in gramatica.ListaNoTerminales:
                if NT.Inicial:
                    State=NT.Nombre
    for gramatica in listaGramatica:
        if nombreGramatica==gramatica.Nombre:
            for letra in cadena:
                per=per+letra
                cambia=False
                for NT in gramatica.ListaNoTerminales:
                    for produccion in NT.Producciones:
                        produccion= produccion.split(' ')
                        if produccion[0]=='epsilon':
                            continue
                        elif (State==NT.Nombre) and (NT.Nombre==produccion[1]):
                            if letra==produccion[0]:
                                listaRuta.append(State+","+produccion[1]+","+produccion[0]+"; ")
                                listaRutaG.append(State+"-->"+per+produccion[1])
                                State=produccion[1]
                                cambia=True
                                break
                        elif State==NT.Nombre:
                            if letra==produccion[0]:
                                listaRuta.append(State+","+produccion[1]+","+produccion[0]+"; ")
                                listaRutaG.append(State+"-->"+per+produccion[1]+" ")
                                State=produccion[1]
                                cambia=True
                                break
                    if cambia:
                        break
    if rutaAFD:
        print("Ruta AFD: ",end="")
        for ruta in listaRuta:
            print(str(ruta),end="")
    if rutaGramatica:
        print("Expansion Gramatica: ",end="")
        for ruta in listaRutaG:
            print(str(ruta),end="")
    if AceptacionXD(nombreGramatica,State):
        print("valida")
    else:
        print("no valida")


import random

def isnum(k):  # 각 자리수가 0 ~ 9 사이 숫자인지 확인하는 함수
    if 48 <= ord(k) <= 57:
        return 1
    else:
        return 0

def right(t):  # 사용자가 입력한 문자열이 입력 조건에 부합하는지 확인하는 함수
    if len(t) != 3:  # 세 글자가 아니면 부합하지 않음
        return 0
    else:
        if t[0] == t[1] or t[1] == t[2] or t[2] == t[0]:  # 세 글자 중 어느 두 글자가 같다면 부합하지 않음
            return 0
        else:
            if isnum(t[0]) and isnum(t[1]) and isnum(t[2]):  # 세 글자 모두 0 ~ 9 사이 숫자일때만 부합함.
                return 1
            else:
                return 0

def scan(i):  # 사용자가 입력한 문자열을 받아 입력 조건에 부합하는지 판단하는 함수
    print('-' * 20)
    t = input('take %d: ' % i)  # 몇 번째 입력 시도인지 출력
    if right(t):  # 입력 조건에 부합하는 문자열이라면 gamestart 함수로 리턴
        return t
    else:
        print('잘못된 입력입니다. 다시 입력하세요.')  # 잘못된 입력이라면 횟수 차감 없이 재시도
        return scan(i)

def gamestart():  # 게임을 진행하는 함수
    num = []  # (line 31 ~ 42) 컴퓨터가 생각한 세자리 수 abc 를 num 에 [a, b, c]형태로 저장 (a, b, c : int)
    print('게임을 시작합니다.')
    a1 = random.randrange(0, 10)
    num.append(a1)
    a2 = a1
    while a1 == a2:
        a2 = random.randrange(0, 10)
    num.append(a2)
    a3 = a1
    while a1 == a3 or a2 == a3:
        a3 = random.randrange(0, 10)
    num.append(a3)

    print('규칙에 맞는 세 자리 수를 입력하세요. 10번의 기회가 주어집니다.')
    for i in range(1, 11):  # 시도 횟수를 10번으로 제한
        num2 = []  # (line 46 ~ 49) 사용자가 입력한 수 abc 를 num2에 [a, b, c]형태로 저장 (a, b, c : int)
        k = scan(i)
        for i2 in range(3):
            num2.append(int(k[i2]))

        if num == num2:  # 정답을 맞췄다면 정답 메시지 출력 후 게임 종료
            print("정답! %d번 만에 맞추셨습니다." % i)
            break;

        s = b = o = 0  # (line 55 ~ 63) 정답이 아니라면 strike, ball, out 의 수 출력
        for i2 in range(3):
            if num[i2] == num2[i2]:
                s += 1
            for i3 in range(3):
                if num[i3] != num2[i3] and num[i3] == num2[i2]:
                    b += 1
        o = 3 - s - b
        print("%d S  %d B  %d O" % (s, b, o))

        if i == 10:  # 10번의 기회를 모두 차감했다면 실패 메시지 출력 후 게임 종료
            print("실패!")

def question1():  # 가장 처음 실행되어 게임 시작/종료를 결정하는 함수
    st = input()
    if st == 'y':
        gamestart()
        print("다시 시작하시겠습니까? (y/n)")  # 한 번의 게임이 끝났다면 다시 시작할 것인지 사용자에게 확인
        question1()
    elif st == 'n':
        print('게임 종료')
    else:
        print('y/n으로 입력하세요')
        question1()

print('게임 시작 (y/n)')  # y:시작, n:종료
question1()


#!/usr/bin/env python3
#Lesson 4-Trigrams Excercise
import random
import sys

def read_in_data(filename):
    '''
    Reads in file and returns either basic text back or cleaned
    Up text if it is a more complex file
    '''
    line_by_line = []
    with open(filename,'r') as f:
        #checks to see if its a basic txt doc or something more complex
        text = f.read()
        if 'Gutenberg' not in text:
            return text
        else:
            f.seek(0,0)
            for line in f:
                line = line.strip(',\n *' )
                if 'START OF THIS PROJECT GUTENBERG' in line:
                    line_by_line.append(line)
                elif 'End of the Project Gutenberg' in line:
                    line_by_line.append(line)
                elif 'Gutenberg' in line:
                    continue
                elif line.isspace() == True:
                    continue
                elif line.startswith(('I','V','X')):
                    continue
                elif line.isupper():
                    continue
                elif not line:
                    continue
                line = line.replace('.','')
                line_by_line.append(line)

            for i, elem in enumerate(line_by_line):
                if 'START OF THIS PROJECT GUTENBERG' in elem:
                    start = i
                elif 'End of the Project Gutenberg' in elem:
                    end = i

            line_by_line = line_by_line[start + 1:end]
            line_by_line = " ".join(line_by_line)

            return line_by_line

def clean_words(data):
    '''
    Splits cleaned text into a list to be used in trigrams dictionary
    '''
    cleaned_data = data.split()

    return cleaned_data

def build_dict(words):
    '''
    Creates the needed dictionary for trigrams text
    '''
    tri_dict = {}
    for i in range(len(words)-2):
        pair = tuple(words[i:i + 2])
        follower = words[i + 2]
        f_list = []
        f_list.append(follower)

        if pair in tri_dict:
            value = tri_dict.get(pair).extend(f_list)
        else:
            tri_dict[pair] = f_list

    return tri_dict

def build_trigram(tri_dict):
    '''
    Builds up the trigrams text using the trigrams dictionary
    '''
    #Creates first trigram of sequence
    num_of_keys = len(tri_dict.keys()) - 1
    ran_num = random.randint(0,num_of_keys)
    first_key = list(tri_dict.keys())[ran_num]
    next_word = tri_dict.get(first_key)[0]
    trigram_list = []
    trigram_list.append(first_key[0])
    trigram_list.append(first_key[1])
    trigram_list.append(next_word)

    #builds random trigram text
    for i in range(100):
        new_seq = tuple(trigram_list[-2:])
        if len(trigram_list) >= 250:
                break

        elif new_seq in tri_dict:
            next_word = random.choice(tri_dict.get(new_seq))
            trigram_list.append(next_word)

        else:
            break

    full_text = " ".join(trigram_list)
    print(full_text)

if __name__ == '__main__':
    try:
        filename = sys.argv[1]
    except IndexError:
        print('Please Pass In An Available File')
        sys.exit(1)

    data = read_in_data(filename)
    words = clean_words(data)
    tri_dict = build_dict(words)
    build_trigram(tri_dict)


# 백준 20922번 - 겹치는 건 싫어
import sys
from collections import deque

si = sys.stdin.readline
n, k = map(int, si().rstrip().split())
seq = list(map(int, si().rstrip().split()))

max_len = 0
# 투 포인터 선언
start = end = 0

pointer_dict = {}

while end < n:
    if seq[end] not in pointer_dict:
        pointer_dict[seq[end]] = deque([end])
        max_len = max(end - start + 1, max_len)
        end += 1
    else:
        if len(pointer_dict[seq[end]]) == k:
            pointer_dict[seq[start]].popleft()
            start += 1
            continue
        else:
            pointer_dict[seq[end]].append(end)
            max_len = max(end - start + 1, max_len)
            end += 1

print(max_len)


#Calculate eigenvectors and eigenvalues for 2x2 matrices
import numpy as np
import random
import math

def input_matrix():
    print('Input your 2X2 matrix one number at a time.')
    numbers=[0.0,0.0,0.0,0.0]
    numbers[0]=input('Input the first number in the first row and press Enter:')
    numbers[1]=input('Input the second number in the first row and press Enter:')
    numbers[2]=input('Input the first number in the second row and press Enter:')
    numbers[3]=input('Input the second number in the second row and press Enter:')

    for i in range(0,4):
        try:
            numbers[i]=int(numbers[i])
        except ValueError:
            try:
                numbers[i]=float(numbers[i])
            except ValueError:
                numbers[i]=random.randint(0,100)
    matrix=np.array([[numbers[0],numbers[1]],[numbers[2],numbers[3]]])
    print('This is your matrix:')
    print(matrix)
    return matrix

def find_eigenvalue(matrix):
    a=1
    b=-1*(matrix[0][0]+matrix[1][1])
    c=matrix[0][0]*matrix[1][1]-matrix[0][1]*matrix[1][0]
    d=b*b-4*a*c
    l=[]
    if d>0:
        l.append((-b+math.sqrt(d))/2)
        l.append((-b-math.sqrt(d))/2)
    if d==0:
        l.append(-b/2)
    if d<0:
        l.append((-b+math.sqrt(d)*1j)/2)
        l.append((-b-math.sqrt(d)*1j)/2)
    print(l)
    return l

def plug_value_into_matrix(value, matrix):
    return np.array([[matrix[0][0]-value,matrix[0][1]],[matrix[1][0],matrix[1][1]-value]])

def row_reduce_operations(matrix):
    for i in range(0,2):
        if (matrix[0][0]==0):
            #swap
            matrix=np.array([matrix[1],matrix[0]])
        if (matrix[0][0]*matrix[1][0]!=0):
            #row op
            matrix[1][1]=-matrix[0][1]*(matrix[1][0]/matrix[0][0])+matrix[1][1]
            matrix[1][0]=0
        #if (matrix[0][1]*matrix[1][1]!=0):
            #row op
            #matrix[0][1]=0

    if (matrix[0][0]!=0):
        matrix[0][1]/=matrix[0][0]
        matrix[0][0]=1
    #if (matrix[1][1]!=0):
        #scale to 1
        #matrix[1][0]/=matrix[1][1]
        #matrix[1][1]=1
    return matrix

def find_eigenvector(matrix):
    vector=[]
    if matrix[0][0]!=0:
        vector=[-matrix[0][1], 1]
    return vector

#referenced: https://www.emathhelp.net/calculators/linear-algebra/eigenvalue-and-eigenvector-calculator/?i=%5B%5B1%2C2%5D%2C%5B3%2C4%5D%5D&steps=on
#referenced: https://gist.github.com/DingWeizhe/d087c6869a596fc01e04
if __name__ == '__main__':
    matrix=input_matrix()
    print('These are your eigenvalues:')
    vals=find_eigenvalue(matrix)
    print('------------------------')
    for val in vals:
        print('For eigenvalue ', val)
        m=plug_value_into_matrix(val, matrix)
        print('Plug the eigenvalue into the matrix')
        print(m)
        m2=row_reduce_operations(m)
        print('Obtain the rref of the matrix')
        print(m2)
        v=find_eigenvector(m2)
        print('Solve to find the eigenvector')
        print(v)
        print('------------------------')


__doc__ = """
Investigate the temperature relaxation of 1D MOT.
"""

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from scipy.interpolate import Akima1DInterpolator

import numpy as np
from tqdm import tqdm

class MOT1DModel:
    def __init__(self, s, delta, b):
        """
        Parameters:
        s: normalized intensity
        delta: normalized detuning
        b: coefficient before x
        """

        def prob1(x, u):
            tmp = u + b * x
            return s / (1 + s + 4 * (delta - tmp)**2) * 1.6  # counter

        def prob2(x, u):
            tmp = u + b * x
            return s / (1 + s + 4 * (delta + tmp)**2) * 1.6

        self.prob1 = prob1
        self.prob2 = prob2

    def simulate(self, u0, step, tot_steps=2000000):
        """
        In a thermodynamic setup, the atoms are assumed to located at the origin;

        The SDE is solved with vanilla Euler method
        """

        ys = [0]
        us = [u0]

        cnt = 0
        for _ in tqdm(range(tot_steps)):
            delta_u = 0
            # scatter in 2D
            # # scatter a photon with -k
            # if np.random.rand() < self.prob1(ys[-1], us[-1]) * step:
            #     delta_u += +1/1.6 * (1 + np.cos(np.random.random()*np.pi))
            # # scatter a photon with +k
            # if np.random.rand() < self.prob2(ys[-1], us[-1]) * step:
            #     delta_u += -1/1.6 * (1 + np.cos(np.random.random()*np.pi))

            # pure 1D
            # scatter a photon with -k
            if np.random.rand() < self.prob1(ys[-1], us[-1]) * step /2 :
                delta_u += +1/1.6
                cnt += 1
            # scatter a photon with +k
            if np.random.rand() < self.prob2(ys[-1], us[-1]) * step / 2:
                delta_u += -1/1.6
                cnt += 1

            ys.append(ys[-1] + us[-1] * step)
            us.append(us[-1] + delta_u)

        print('Scattered rate:', cnt / tot_steps)
        return np.array(ys), np.array(us)

def binning(x, max_bin=400):
    def mean_every_n(arr, n):
        return np.mean(arr[:(len(arr)//n)*n].reshape(-1, n), axis=1)
    return np.array([np.std(mean_every_n(x, b)) for b in range(1, max_bin)])

model = MOT1DModel(284, -16, .048)
ys, us = model.simulate(0, .05)

# plt.plot(us)
# plt.show()

def autocorr(x, t=1):
    return np.corrcoef(np.array([x[:-t], x[t:]]))[0, 1]

burnin = 5000
ys = ys[burnin:]
us = us[burnin:]
print(us[:1000])
plt.hist2d(us, ys,bins=10)
# plt.plot(*np.unique(us, return_counts=True),'+')
plt.xlabel('$x$')
plt.ylabel('$u$')
plt.tight_layout()
plt.show()
lags = list(range(1, 5000, 20))
plt.plot(lags, [autocorr(us, l) for l in tqdm(lags)])
plt.show()

ys = ys[::1000]
us = us[::1000]

print(np.mean(us**2))
plt.plot(binning(us**2))
plt.show()


from random import shuffle
nums = [n for n in range(10)]
shuffle(nums)

def selection_sort(lst):
    # go through list
    # i= index where unsorted part of list is
    for i in range(len(lst)):
        # The min_index is the
        # smallest item in the unsorted area
        min_index = i
        # for every item in unsorted
        # check if the item is smaller than the current min
        # and assign that index as the new min_index.
        for curr_index in range(i+1, len(lst)):
            if lst[min_index] > lst[curr_index]:
                min_index = curr_index
        # Swap the min item with the first item of the
        # unsorted portion of the list.
        lst[i], lst[min_index] = lst[min_index], lst[i]
    return lst
print(selection_sort(nums))


"""Add status column to post

Revision ID: 788a36cc3f02
Revises: 6f4fa871d902
Create Date: 2023-07-25 04:16:46.384582

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '788a36cc3f02'
down_revision = '6f4fa871d902'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    with op.batch_alter_table('post', schema=None) as batch_op:
        batch_op.add_column(sa.Column('status', sa.String(length=10), nullable=True))

    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    with op.batch_alter_table('post', schema=None) as batch_op:
        batch_op.drop_column('status')

    # ### end Alembic commands ###