"""
Created by Joseph Edradan
Github: https://github.com/josephedradan

Date created: 11/18/2020

Purpose:
    Solve sum of values from each rows of a matrix to equal a target value with recursive calls under certain
    conditions.

Details:
    1 Loop, DFS Recursive using a set for the answer

Description:

Notes:
    Conditions to follow
        Let {P_1, P_2, ..., P_k, ... P_n} be a set of solutions for this problem where P_k = {M(i, j)_1 + M(i, j)_2 +
        M(i, j)_3 + ... + M(i, j)_m-1 + M(i, j)_m} = S is a set of coordinates for integers values in a matrix,
        and S the sum of those integers for that solution P_k. The S sum is valid only if:
            1. All the indexes i and j for that sum of Pk are unique

                Explanation:    i is unique and j is unique regardless

            2. The integer in M(i, j) is not zero

                Explanation:    Value at (i, j) is not 0

            3. Index j in M(i, j)_x must be the same as index i in M(i, j)_x+1

                Explanation:    Index j of M_sub_x is Index i of M_sub_x+1

            4. Index i in M(i, j)_1 and index j in M(i, j)_m must be zero for all the solutions Pk

                Explanation:    Index i of M_sub_1 IS 0 AND Index j of M_sub_m IS 0

            5. A possible solution P_k is only considered an optimal solution if the sum S of all its integers is
               the minimum or the maximum sum S from all the solutions P_k

                Explanation:    A Solution has its sum of values in its list equal to value S and all Solutions must be
                                equal to that value S for that particular list of solutions

    Notice that the left to right diagonal of the matrix are never used because it will bring the following row back
    to the same row which is invalid.

IMPORTANT NOTES:

Explanation:

Reference:

"""
# from joseph_library.decorators._old.callgraph_simple import callgraph, create_callgraph

from typing import FrozenSet, Set, List, Tuple

# Recursive call
# @callgraph
def dfs_recursive(list_list_given: List[List[int]],
                  index_row: int = 0,
                  index_row_final=None,
                  set_indices_traversed: Set = None,
                  index_list_solution_possible: int = 0,
                  list_solution_possible: List[List[int]] = None,
                  solution_possible: List[int] = None,
                  set_frozenset_solution: Set[FrozenSet[Tuple[int]]] = None) -> Set[FrozenSet[Tuple[int]]]:
    """
    Solve sum of values from each rows of a matrix to equal a target value with recursive calls under certain
    conditions.

    :param list_list_given: Matrix
    :param index_row: Current row via index in the matrix
    :param set_indices_traversed: Set containing index_row that we have already traversed
    :param index_list_solution_possible: Keeps track if we added a solution_possible to list_solution_possible
    :param list_solution_possible: List containing solution_possible
    :param solution_possible: List containing values from the matrix
    :param set_frozenset_solution: List of list_solution_possible which are the solutions that meet the conditions listed
    above
    :return: set_frozenset_solution
    """

    # Allows for resets for new calls from the initial call
    if set_frozenset_solution is None:
        index_row_final = index_row
        set_indices_traversed = set()
        list_solution_possible = []
        solution_possible = []
        set_frozenset_solution = set()

    if index_row in set_indices_traversed:
        return set_frozenset_solution

    # Current row you are working on
    row_current = list_list_given[index_row]

    set_indices_traversed.add(index_row)

    # Find min value's index
    index_value_minimum = None
    value_minimum = None
    for index, value in enumerate(row_current):
        if value == 0:
            continue

        if value_minimum is None:
            index_value_minimum = index
            value_minimum = value

        if value < value_minimum:
            index_value_minimum = index
            value_minimum = value

    # Loop through the values of the given row based on index_row
    for index_col, value in enumerate(row_current):

        # DEBUG PRINTING
        # print("Current Row: {}".format(row_current))
        # print("Row Index: {}".format(index_row))
        # print("Set Indices Traversed: {}".format(set_indices_traversed))
        # print("index_list_solution_possible: {}".format(index_list_solution_possible))
        # print("list_solution_possible: {}".format(list_solution_possible))
        # print("solution_possible: {}".format(solution_possible))
        # print("Value: {}".format(value))
        # [print(i) for i in list_list_given]  # Matrix
        # print()

        if value == 0:
            continue

        list_list_given[index_row][index_col] = 0

        # Add the value from the current row to the list of possible solutions
        solution_possible.append(value)

        if len(solution_possible) == len(list_list_given) and index_col == 0:
            # If solution is found then add it to list_solution_possible
            list_solution_possible.append(solution_possible.copy())

        if len(list_solution_possible) > index_list_solution_possible:

            # Assume that the most recently added solution has the same sum
            sum_same = True

            # Check if the sum of the 0th solution is equal to the sum of the most recently added solution
            if len(list_solution_possible) > 1:

                if sum(list_solution_possible[0]) != sum(list_solution_possible[-1]):
                    sum_same = False

            # If sum_same is true then sum(list_solution_possible[0]) == sum(list_solution_possible[-1])
            if sum_same:
                dfs_recursive(list_list_given, 0, set(),
                              index_list_solution_possible + 1,
                              list_solution_possible,
                              [],
                              set_frozenset_solution)

                set_frozenset_solution.add(
                    frozenset(
                        tuple(i) for i in list_solution_possible
                    )
                )

            list_solution_possible.pop(-1)

        if len(solution_possible) < len(list_list_given):
            dfs_recursive(list_list_given, index_col, set_indices_traversed,
                          index_list_solution_possible,
                          list_solution_possible,
                          solution_possible,
                          set_frozenset_solution)

        # Value of the popped from solution_possible
        value_from_solution_possible_last_added = solution_possible.pop(-1)

        # Restore the value in the Matrix from 0 to it's original value
        list_list_given[index_row][index_col] = value_from_solution_possible_last_added

    set_indices_traversed.remove(index_row)

    # Return set_frozenset_solution
    return set_frozenset_solution

if __name__ == '__main__':

    # Matrix to solve
    list_given = [[0, 14, 4, 10, 20],
                  [14, 0, 7, 8, 7],
                  [4, 5, 0, 7, 16],
                  [11, 7, 9, 0, 2],
                  [18, 7, 17, 4, 0]
                  ]

    # list_given = [[0, 1, 2, 3],
    #               [1, 0, 4, 5],
    #               [2, 3, 0, 6],
    #               [4, 5, 6, 0]]

    # list_given = [[0, 7, 1, 0, 0, 8],
    #               [7, 0, 5, 0, 9, 6],
    #               [1, 5, 0, 4, 0, 0],
    #               [0, 0, 4, 0, 2, 0],
    #               [0, 9, 0, 2, 0, 3],
    #               [8, 6, 0, 0, 3, 0]]

    set_frozenset_solution = dfs_recursive(list_given)

    # For print spacing
    try:
        length_of_a_row = len(list_given)
    except IndexError as e:
        print("There are no solutions for the given Matrix")
        length_of_a_row = 1

    print("All Possible Combination of Solutions (Unique)")
    # Print All possible solutions
    for index, solution in enumerate(set_frozenset_solution):
        # print(i, sum(i))
        # print(f"\t{str(i):<{length_of_a_row * 3 + 1}} {sum(i)}")

        print("Solution Combination {}".format(index + 1))
        for solution_partial in solution:
            print(f"\t{str(solution_partial):<{length_of_a_row * 3 + 1}} {sum(solution_partial)}")
        print()

    # create_callgraph()


# -*- coding: UTF-8 -*-
"""
The class Text extends estnltk's class Text and adds abbreviation layer.

Usage:

    >> from abresolver import Text
    >> t = Text(u'kolmas p palavik')
    >> t.tokenize_abs()
    [{
      'text': 'p',
      'start': 7,
      'end': 8,
      'expansions': ['päev',
                     'parem',
                     'parietaalne',
                     'pupill',
                     'pool'],
      'scores': [0.99974249284129602,
                 0.00013896032431022265,
                 0.00010385371199489893,
                 9.3145225880433136e-06,
                 5.3785998108879645e-06],
      }]
"""
import logging

import pandas as pd
from estnltk import Text as EstnltkText
from estnltk.names import START, END, TEXT
from cached_property import cached_property

from . import config
from .abmodel import Model as AbbreviationModel
from .word2vec import Word2VecContextModel
from .abdisambiguation import Word2VecDisambiguator

log = logging.getLogger(__name__)
config = config.Config()
ab_disambiguator = None

ABR = 'abr'
EXPANSIONS = 'expansions'
SCORES = 'scores'

def get_disambiguator():
    global ab_disambiguator
    if ab_disambiguator is None:
        log.debug('Loading models...')
        ab_disambiguator = Word2VecDisambiguator(
                       AbbreviationModel(pd.read_csv(config.ABBREVIATION_MODEL, encoding='utf8')),
                       Word2VecContextModel(config.WORD2VEC_MODEL))
    return ab_disambiguator

class Text(EstnltkText):

    def __init__(self, *args, **kwargs):
        super(Text, self).__init__(*args, **kwargs)

    @cached_property
    def layer_tagger_mapping(self):
        mapping = super(Text, self).layer_tagger_mapping
        mapping[ABR] = self.tokenize_abr
        return mapping

    @cached_property
    def abr(self):
        """ A list of personally identifiable information in `abr` layer """
        if not self.is_tagged(ABR):
            self.tokenize_abr()
        return self[ABR]

    @cached_property
    def abr_texts(self):
        """The list of words representing `abr` layer elements."""
        if not self.is_tagged(ABR):
            self.tokenize_abr()
        return [pii[TEXT] for pii in self[ABR]]

    @cached_property
    def abr_spans(self):
        """The list of spans representing `abr` layer elements."""
        if not self.is_tagged(ABR):
            self.tokenize_abr()
        return self.spans(ABR)

    @cached_property
    def abr_starts(self):
        """The list of start positions representing `abr` layer elements."""
        if not self.is_tagged(ABR):
            self.tokenize_abr()
        return self.starts(ABR)

    @cached_property
    def abr_ends(self):
        """The list of end positions representing `abr` layer elements."""
        if not self.is_tagged(ABR):
            self.tokenize_abr()
        return self.ends(ABR)

    @cached_property
    def abr_expansions(self):
        if not self.is_tagged(ABR):
            self.tokenize_abr()
        return [item[EXPANSIONS] for item in self[ABR]]

    @cached_property
    def abr_scores(self):
        if not self.is_tagged(ABR):
            self.tokenize_abr()
        return [item[SCORES] for item in self[ABR]]

    def tokenize_abr(self):
        """ Add `abr`-layer annotations."""
        items = []
        for snt, snt_start in zip(self.split_by_sentences(), self.sentence_starts):
            snt_words = [w.lower() for w in snt.word_texts]
            for i, w in enumerate(snt.words):
                expansions, context_fitness = get_disambiguator().process(snt_words, i)
                if expansions:
                    items.append({START:      snt_start + w[START],
                                  END:        snt_start + w[END],
                                  TEXT:       w[TEXT],
                                  EXPANSIONS: [e.term for e in expansions],
                                  SCORES:     [e.score for e in expansions],
                                  })
        self[ABR] = items
        return items


# -*- encoding: utf-8 -*-
"""
@File    : MINE.py
@Time    : 1/30/21 1:42 PM
@Author  : Liangliang
@Software: PyCharm
"""
'''
参考代码 https://blog.csdn.net/xyisv/article/details/111354132
参考文献: Belghazi M I, Baratin A, Rajeshwar S, et al. Mutual information neural estimation. International Conference on Machine Learning. 2018: 531-540.
'''
import torch
import torch.nn as nn
import numpy as np

class MINE(nn.Module):
    def __init__(self, data_dim=5, hidden_size=10):
        super(MINE, self).__init__()
        self.layers = nn.Sequential(nn.Linear(2 * data_dim, hidden_size),
                                    nn.ReLU(),
                                    nn.Linear(hidden_size, 1))
    def forward(self, x, y):
        batch_size = x.size(0)
        tiled_x = torch.cat([x, x, ], dim=0)
        idx = torch.randperm(batch_size)

        shuffled_y = y[idx]
        concat_y = torch.cat([y, shuffled_y], dim=0)
        inputs = torch.cat([tiled_x, concat_y], dim=1)
        logits = self.layers(inputs)

        pred_xy = logits[:batch_size]
        pred_x_y = logits[batch_size:]
        loss = - np.log2(np.exp(1)) * (torch.mean(pred_xy) - torch.log(torch.mean(torch.exp(pred_x_y))))
        # compute loss, you'd better scale exp to bit
        return loss

def Mutual_information(X,Y):
    hidden_size = 200
    n_epoch = 450
    data_dim = X.shape[1]
    model = MINE(data_dim, hidden_size).cuda()
    optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
    plot_loss = []
    all_mi = []
    for epoch in range(n_epoch):
        x_sample = X.cuda()
        y_sample = Y.cuda()
        loss = model(x_sample, y_sample)
        model.zero_grad()
        loss.backward()
        optimizer.step()
        all_mi.append(-loss.item())
    return sum(all_mi[-100:])/100


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Created on Sat Dec 09 14:38:12 2017

@author: Ashish Katiyar
"""
import torch
from torch.optim.optimizer import Optimizer

class Nadam(Optimizer):
    """Implements Adam algorithm.

    It has been proposed in `Adam: A Method for Stochastic Optimization`_.

    Arguments:
        params (iterable): iterable of parameters to optimize or dicts defining
            parameter groups
        lr (float, optional): learning rate (default: 1e-3)
        betas (Tuple[float, float], optional): coefficients used for computing
            running averages of gradient and its square (default: (0.9, 0.999))
        eps (float, optional): term added to the denominator to improve
            numerical stability (default: 1e-8)
        weight_decay (float, optional): weight decay (L2 penalty) (default: 0)

    .. _Adam\: A Method for Stochastic Optimization:
        https://arxiv.org/abs/1412.6980

    """

    def __init__(self, params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8,
                 weight_decay=0, schedule_decay=0.004):
        defaults = dict(lr=lr, betas=betas, eps=eps, weight_decay=weight_decay)
        self.schedule_decay = schedule_decay
        super(Nadam, self).__init__(params, defaults)

    def step(self, closure=None):
        """Performs a single optimization step.

        Arguments:
            closure (callable, optional): A closure that reevaluates the model
                and returns the loss.
        """
        loss = None

        if closure is not None:
            loss = closure()

        for group in self.param_groups:
            for p in group['params']:
                if p.grad is None:
                    continue

                grad = p.grad.data

                if grad.is_sparse:
                    raise RuntimeError('Nadam does not support sparse gradients, please consider SparseAdam instead')

                state = self.state[p]

                # State initialization
                if len(state) == 0:
                    state['step'] = 0
                    # Exponential moving average of gradient values
                    state['exp_avg'] = torch.zeros_like(p.data)
                    # Exponential moving average of squared gradient values
                    state['exp_avg_sq'] = torch.zeros_like(p.data)
                    #
                    state['m_schedule'] = 1.

                state['step'] += 1

                exp_avg, exp_avg_sq = state['exp_avg'], state['exp_avg_sq']
                beta1, beta2 = group['betas']

                if group['weight_decay'] != 0:
                    grad = grad.add(group['weight_decay'], p.data)

                # Calculate the momentum
                momentum_cache_t = beta1 * (1 - 0.5 * 0.96 ** (state['step'] * self.schedule_decay))
                momentum_cache_t_1 = beta1 * (1 - 0.5 * 0.96 ** ((state['step'] + 1) * self.schedule_decay))

                m_schedule_new = state['m_schedule'] * momentum_cache_t
                m_schedule_next = m_schedule_new * momentum_cache_t_1

                state['m_schedule'] = m_schedule_next

                g_prime = grad / (1. - m_schedule_new)

                # Decay the first and second moment running average coefficient
                # m_t = \beta_1 m_{t-1} + (1 - \beta_1) g
                exp_avg.mul_(beta1).add_(1 - beta1, grad)

                exp_avg_prime = exp_avg / (1 - m_schedule_next)

                # v_t = \beta_2 v_{t-1} + (1 - \beta_2) g^2
                exp_avg_sq.mul_(beta2).addcmul_(1 - beta2, grad, grad)

                exp_avg_sq_prime = exp_avg_sq / (1. - beta2 ** state['step'])

                exp_avg_bar = (1. - momentum_cache_t) * g_prime + (
                        momentum_cache_t_1 * exp_avg_prime)

                denom = exp_avg_sq_prime.sqrt().add_(group['eps'])

                step_size = group['lr']

                p.data.addcdiv_(-step_size, exp_avg_bar, denom)

        return loss


#Important modules
import pygame
from pygame.sprite import Sprite

class Bullet(Sprite):
	"""docstring for ClassName"""

	def __init__(self, ai_game):

		super().__init__() #Inheritance from Sprite

		self.screen = ai_game.screen
		self.settings = ai_game.settings
		self.color = self.settings.bullet_color

		#Create a bullet rect at (0,0) and then correct the position
		self.rect = pygame.Rect(0,0,self.settings.bullet_width,
			self.settings.bullet_height)

		#Link the bullet to the ship's position.
		#Midtop to make it look like he bullet comes out from the top of the ship
		self.rect.midtop = ai_game.ship.rect.midtop

		#Store the bullet's position
		self.y = float(self.rect.y)

	def update(self):
		#Move the bullet upwards
		#Update its decimal position
		self.y -= self.settings.bullet_speed

		#Update the rect position
		self.rect.y = self.y

	def draw_bullet(self):
		#Moving the bullet onto the screen
		pygame.draw.rect(self.screen,self.color,self.rect)


import sys
import torch
import torch.nn as nn
from torch.autograd import Variable
from util_hessian import Datamanager, CNN, DNN
import numpy as np
import argparse
assert torch and nn and Variable

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''''''''''''       setting option                           '''
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

EPOCH = 20001
BATCH_SIZE = 512

parser = argparse.ArgumentParser(description='setting module parameter.')
parser.add_argument('-lo','--loss_output', dest='loss_output',type=str,required=True)
#parser.add_argument('-no','--norm_output', dest='norm_output',type=str,required=True)
parser.add_argument('-ra','--ratio_output', dest='ratio_output',type=str,required=True)
parser.add_argument('-u','--unit', dest='unit',type=int,nargs='+',required=True)
args = parser.parse_args()
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''''''''''''       reading data                             '''
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
dm=Datamanager()
print('reading data...',end='')
sys.stdout.flush()
dm.get_data('train',BATCH_SIZE)
dm.get_data('test',BATCH_SIZE)
print('\rreading data...finish')
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''''''''''''       training                                 '''
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
print(args.loss_output)
print(args.ratio_output)
dnn = DNN(args).cuda().double()
print(dnn)
print('total parameters: {}'.format(dm.count_parameters(dnn)))
#training and testing
loss_list=[]
ratio_list=[]

for epoch in range(EPOCH):
    loss , norm , min_ratio = dm.train(dnn,dm.data['train'],epoch,'mse')
    if epoch == 20000:
        loss_list.append(loss)
        ratio_list.append(min_ratio)
    print('*'*50)
#print(len(loss_list))
#print(len(norm_list))
np.save('result/'+args.loss_output,np.array(loss_list))
np.save('result/'+args.ratio_output,np.array(ratio_list))


from django.contrib import admin
from myapp.models import BloodRequestStatus,BloodRequestSession,UserDetail,BloodGroup, BloodGroupSessionMapper

#Register your models here.

admin.site.register(BloodGroup)
admin.site.register(BloodGroupSessionMapper)

@admin.register(UserDetail)
class UserDetailAdmin(admin.ModelAdmin):
    list_display = ('user', 'blood_group', 'pincode', 'last_donated_date')

@admin.register(BloodRequestSession)
class BloodRequestSessionAdmin(admin.ModelAdmin):
    list_display = ['req_user', 'pincode', 'total_unit', 'req_date', 'till_date']

@admin.register(BloodRequestStatus)
class BloodRequestStatusAdmin(admin.ModelAdmin):
    list_display = ['donner', 'session', 'invitation_status', 'donation_status', 'donation_date']

# class BloodRequestadmin(admin.ModelAdmin):
#     pass

# @admin.register(RequestBlood)
# class RequestBloodadmin(admin.ModelAdmin):
#     pass

# @admin.register(BloodNeedSatisfaction)
# class BloodNeedSatisfactionadmin(admin.ModelAdmin):
#     pass

# @admin.register(Invitation)
# class Invitationadmin(admin.ModelAdmin):
#     pass

# @admin.register(BloodDonationHistory)
# class BloodDonationHistoryadmin(admin.ModelAdmin):
    # pass


import argparse
import logging
import os
import pprint
import sys

from googlecloudsdk.tools.regen_apis import regen
import yaml

def main(argv=None):
  if argv is None:
    argv = sys.argv

  parser = argparse.ArgumentParser(
      description='Regenerates apitools clients in given directory.')

  parser.add_argument('--config',
                      required=True,
                      help='Regeneration config filename.')

  parser.add_argument('--base-dir',
                      default=os.getcwd(),
                      help='Regeneration config filename.')

  parser.add_argument('--api',
                      help='api_name/api_version which to regenerate.'
                      'If ommited all will be regenerated.')

  parser.add_argument('-l',
                      '--log-level',
                      choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
                      default='INFO',
                      help='Set the logging level')

  args = parser.parse_args(argv[1:])

  if args.log_level:
    logging.basicConfig(
        format='%(asctime)s %(filename)s:%(lineno)d %(message)s',
        level=getattr(logging, args.log_level))

  with open(args.config, 'r') as stream:
    config = yaml.load(stream)

  logging.debug('Config %s', pprint.pformat(config))

  root_dir = config['root_dir']
  logging.debug('Based dir %s', args.base_dir)
  if args.api is not None:
    api_name, api_version = args.api.split('/')
    api_config = config['apis'][api_name][api_version]
    regen.GenerateApi(args.base_dir, root_dir,
                      api_name, api_version, api_config)
  else:
    for api_name, api_version_config in config['apis'].iteritems():
      for api_version, api_config in api_version_config.iteritems():
        logging.info('Generating %s %s', api_name, api_version)
        regen.GenerateApi(args.base_dir, root_dir,
                          api_name, api_version, api_config)

if __name__ == '__main__':
  main()


#!/usr/bin/env python3.7
def solution(xs):
    # Your code here
    import functools
    from decimal import Decimal

    negatives = list(filter(lambda x: x < 0, xs))

    if len(xs) == 1 and len(negatives) == 1: # case [-10]
        print("{:.0f}".format(xs.pop(0)))
        return

    if len(negatives) % 2 == 1:
        use_negatives = sorted(negatives)[:len(negatives)-1]
    else:
        use_negatives = negatives # even negatives

    use_positives = list(filter(lambda x: x > 0, xs))

    uses = use_positives + use_negatives
    print(uses)

    uses = list(filter(lambda x: x > 1 or x < -1, uses))
    print(uses)

    # if len(uses) == len(xs):
    #     uses = list(map(lambda x: abs(x), uses))
    #     uses.remove(min(uses))

    if len(uses) > 1:
        res = functools.reduce(lambda x,y: Decimal(str(x)) * Decimal(str(y)), uses)
    else:
        if len(uses) == 0:      # case: [-10, 0]
            res = 0
        else:
            res = uses.pop(0)
    print("{:.0f}".format(res))

if __name__ == "__main__":

    """
    array: 1-50 panels
    pwoer out level: no greater than 1000

    """
    # test 0
    solution([2,-3,1,0,-5])     # 30
    """
    maximum product found
    xs[0] = 2, xs[1] = -3, xs[4] = -5
    2*(-3)*(-5) = 30
    """

    # test 1
    solution([2, 0, 2, 2, 0]) # 8

    # test 2
    solution([-2, -3, 4, -5]) # 60

    # original
    solution([0.5, 1, 2, 10])   # 20

    # original
    solution([10])   # 10

    # original
    solution([-10])   # -10

    # original
    solution([-10, 0])   # 0

    # original
    solution([1000 for f in range(50)])   # 1000**50

    # original
    solution([100000000,200000000,300000000])   #

    # original
    solution([5, 4, 2, 10])   # 200


import streamlit as st
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split

df= pd.read_csv("test.csv")
X_train,X_test,y_train, y_test = train_test_split(df[["length(m)","height(cm)","X1","X2"]],df['color_type'])

options=["KNN","Logistic Regression","Random Forest"]
def get_score(model_name):
    if model_name==options[0]:
        model = KNeighborsClassifier()
    if model_name==options[1]:
        model = LogisticRegression()
    if model_name==options[2]:
        model = RandomForestClassifier()
    model.fit(X_train,y_train)
    return(model.score(X_test,y_test))

def get_predictions(model_name,user_inputs):
    if model_name==options[0]:
        model = KNeighborsClassifier()
    if model_name==options[1]:
        model = LogisticRegression()
    if model_name==options[2]:
        model = RandomForestClassifier()
    model.fit(X_train,y_train)
    return(model.predict(user_inputs))

page = st.sidebar.radio("Choose a page", options=["Presentation","Visualization","Modeling"])
if page == "Presentation":
    st.title('An introduction on streamlit')
    st.header("By Datascientest")
    st.dataframe(df.head())
    st.image("dataset-cover.jpeg",caption="A cool picture about the dataset")
    st.write("The columns' names are",df.columns)
    st.markdown("This is the [link](https://www.kaggle.com/datasets/ppsheth91/two-target-variables-classification-problem) towards the original dataset")
if page == "Visualization":
    fig,ax = plt.subplots()
    sns.barplot(data = df, y= "color_type",x= "length(m)",orient='h')
    ax.set_yticks([i for i in range(len(df["color_type"].unique()) )if i%2==0 ],rotation='vertical',fontsize=12)
    st.pyplot(fig)

    fig,ax = plt.subplots()
    sns.boxplot(data = df, y= "color_type",x= "height(cm)",orient='h')
    ax.set_yticks([i for i in range(len(df["color_type"].unique()) )if i%2==0 ],rotation='vertical',fontsize=12)
    st.pyplot(fig)

    fig3 = plt.figure()
    sns.scatterplot(data=df,x='X1',y='X2')
    st.pyplot(fig3)
if page == "Modeling":
    model_name =st.selectbox("Choose a ML Model to train",options=["KNN","Logistic Regression","Random Forest"])
    st.write(f"The performance of the ML model is {get_score(model_name)}")

    var1 = st.slider("Choose the value for length(m)",df["length(m)"].min(),df["length(m)"].max(), 0.1)
    var2 = st.slider("Choose the value for height(cm)",df["height(cm)"].min(),df["height(cm)"].max(), 1.)
    var3 = st.number_input(" Choose the value for X1 :" )
    var4 = st.number_input(" Choose the value for X2 :" )
    inputs = pd.DataFrame({'length(m)': var1, 'height(cm)' :var2,
                    'X1': var3,'X2':var4},index=[1])
    st.write(f'The prediction of the ML model is ',get_predictions(model_name,inputs))
    st.write( ' "Cogito ergo sum" Descartes')


import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton, QHBoxLayout, QVBoxLayout
from PyQt5.QtCore import Qt, QThread, pyqtSignal
import requests

class FileUploadThread(QThread):
  # Set up a signal to be emitted when the file is uploaded
  uploaded = pyqtSignal()

  def __init__(self, file_path):
    super().__init__()
    self.file_path = file_path

  def run(self):
    # Send a POST request to the server with the file attached
    with open(self.file_path, 'rb') as f:
      files = {'file': f}
      response = requests.post('http://localhost:5000/upload', files=files)
    # Emit the uploaded signal
    self.uploaded.emit()

class FileUploadWidget(QWidget):
  def __init__(self):
    super().__init__()

    # Set up the user interface
    self.file_path_label = QLabel("File path:")
    self.file_path_edit = QLineEdit()
    self.upload_button = QPushButton("Upload")

    self.upload_button.clicked.connect(self.upload_file)

    layout = QVBoxLayout()
    layout.add


# -*- coding: utf-8 -*-
"""Backtracking implementation."""

import numpy as np
from numba import jit

@jit(nopython=True)
def _backtrack_jit(D, p_ar, last_idx=-1):
    """Fast implementation by numba.jit.

    D : 2D array
        cumsum cost matrix
    p_ar : 3D array
        step pattern array (see step_pattern.py)
    """
    # number of patterns
    num_pattern = p_ar.shape[0]
    # initialize index
    i, j = D.shape
    i -= 1
    if last_idx == -1:
        j -= 1
    else:
        j = last_idx
    # alignment path
    path = np.array(((i, j),), dtype=np.int64)
    # cache to memorize D
    D_cache = np.ones(num_pattern, dtype=np.float64) * np.inf

    while True:
        if i == 0 and j == 0:
            break
        for pidx in range(num_pattern):
            # get D value corresponds to end of pattern node
            pattern_index = p_ar[pidx, 0, 0:2]
            ii = int(i + pattern_index[0])
            jj = int(j + pattern_index[1])
            if ii < 0 or jj < 0:
                D_cache[pidx] = np.inf
            else:
                D_cache[pidx] = D[ii, jj]

        if (D_cache == np.inf).all():
            # break if there is no direction can be taken
            break

        # find path minimize D_chache
        min_pattern_idx = np.argmin(D_cache)
        # get where pattern passed
        path_to_add = _get_local_path(D, p_ar[min_pattern_idx, :, :], i, j)
        # concatenate
        path = np.vstack((path, path_to_add))

        i += p_ar[min_pattern_idx, 0, 0]
        j += p_ar[min_pattern_idx, 0, 1]

    return path[::-1]

@jit(nopython=True)
def _get_local_path(D, p_ar, i, j):
    """Helper function to get local path.
    D : cumsum matrix
    p_ar : array of pattern that minimize D at i,j
    """
    weight_col = p_ar[:, 2]
    step_selector = np.where(weight_col != 0)[0]
    # note: starting point of pattern was already added
    step_selector = step_selector[:-1]
    # initialize local path
    local_path = np.ones((step_selector.size, 2),
        dtype=np.int64) * -1
    for sidx in step_selector:
        # memorize where passed
        pattern_index = p_ar[sidx, 0:2]

        ii = int(i + pattern_index[0])
        jj = int(j + pattern_index[1])

        local_path[sidx, :] = (ii, jj)
    return local_path[::-1]


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

# convolution layer template
def convTemp(in_channels, out_channels, k_size, padding=1, stride=1):
    return nn.Conv2d(in_channels=in_channels,
                     out_channels=out_channels,
                     kernel_size=k_size,
                     stride=stride,
                     padding=padding,
                     bias=False)

class Discriminator(nn.Module):
    def __init__(self):
        super(Discriminator, self).__init__()

        # convolution layers
        self.conv1 = convTemp(3, 196, 3, 1, 1)
        self.conv2 = convTemp(196, 196, 3, 1, 2)
        self.conv3 = convTemp(196, 196, 3, 1, 1)
        self.conv4 = convTemp(196, 196, 3, 1, 2)
        self.conv5 = convTemp(196, 196, 3, 1, 1)
        self.conv6 = convTemp(196, 196, 3, 1, 1)
        self.conv7 = convTemp(196, 196, 3, 1, 1)
        self.conv8 = convTemp(196, 196, 3, 1, 2)

        # layer normalizations
        self.ln1 = nn.LayerNorm([32, 32])
        self.ln2 = nn.LayerNorm([16, 16])
        self.ln3 = nn.LayerNorm([16, 16])
        self.ln4 = nn.LayerNorm([8, 8])
        self.ln5 = nn.LayerNorm([8, 8])
        self.ln6 = nn.LayerNorm([8, 8])
        self.ln7 = nn.LayerNorm([8, 8])
        self.ln8 = nn.LayerNorm([4, 4])

        # leaky relu
        self.leaky_relu = nn.LeakyReLU()

        # pool layer
        self.pool = nn.MaxPool2d(kernel_size=4, stride=4)

        # critic
        self.fc1 = nn.Linear(196, 1)

        # auxiliary classifier
        self. fc10 = nn.Linear(196, 10)

    def forward(self, x, extract_features=8):
        x = self.conv1(x)
        x = self.ln1(x)
        x = self.leaky_relu(x)

        x = self.conv2(x)
        x = self.ln2(x)
        x = self.leaky_relu(x)

        x = self.conv3(x)
        x = self.ln3(x)
        x = self.leaky_relu(x)

        x = self.conv4(x)
        x = self.ln4(x)
        x = self.leaky_relu(x)
        if extract_features == 4:
            x = F.max_pool2d(x, 8, 8)
            x = x.view(-1, 196)

            return x

        x = self.conv5(x)
        x = self.ln5(x)
        x = self.leaky_relu(x)

        x = self.conv6(x)
        x = self.ln6(x)
        x = self.leaky_relu(x)

        x = self.conv7(x)
        x = self.ln7(x)
        x = self.leaky_relu(x)

        x = self.conv8(x)
        x = self.ln8(x)
        x = self.leaky_relu(x)
        if extract_features == 8:
            x = F.max_pool2d(x, 4, 4)
            x = x.view(-1, 196)

            return x

        x = self.pool(x)

        x = x.view(x.size(0), -1)
        critic = self.fc1(x)
        output = self.fc10(x)

        return critic, output

class Generator(nn.Module):
    def __init__(self):
        super(Generator, self).__init__()

        # input layer
        self.fc1 = nn.Linear(100, 196*4*4)

        # convolution layers
        self.conv1 = nn.ConvTranspose2d(in_channels=196,
                                        out_channels=196,
                                        kernel_size=4,
                                        padding=1,
                                        stride=2)
        self.conv2 = convTemp(196, 196, 3, 1, 1)
        self.conv3 = convTemp(196, 196, 3, 1, 1)
        self.conv4 = convTemp(196, 196, 3, 1, 1)
        self.conv5 = nn.ConvTranspose2d(in_channels=196,
                                        out_channels=196,
                                        kernel_size=4,
                                        padding=1,
                                        stride=2)
        self.conv6 = convTemp(196, 196, 3, 1, 1)
        self.conv7 = nn.ConvTranspose2d(in_channels=196,
                                        out_channels=196,
                                        kernel_size=4,
                                        padding=1,
                                        stride=2)
        self.conv8 = convTemp(196, 3, 3, 1, 1)

        # batch normalizations
        self.bn0 = nn.BatchNorm1d(196*4*4)
        self.bn1 = nn.BatchNorm2d(196)
        self.bn2 = nn.BatchNorm2d(196)
        self.bn3 = nn.BatchNorm2d(196)
        self.bn4 = nn.BatchNorm2d(196)
        self.bn5 = nn.BatchNorm2d(196)
        self.bn6 = nn.BatchNorm2d(196)
        self.bn7 = nn.BatchNorm2d(196)

        # activations
        self.relu = nn.ReLU()
        self.tanh = nn.Tanh()

    def forward(self, x):
        x = self.fc1(x)
        x = self.bn0(x)
        x = x.view(-1, 196, 4, 4)
        x = self.conv1(x)
        x = self.bn1(x)
        x = self. relu(x)
        x = self.conv2(x)
        x = self.bn2(x)
        x = self. relu(x)
        x = self.conv3(x)
        x = self.bn3(x)
        x = self. relu(x)
        x = self.conv4(x)
        x = self.bn4(x)
        x = self. relu(x)
        x = self.conv5(x)
        x = self.bn5(x)
        x = self. relu(x)
        x = self.conv6(x)
        x = self.bn6(x)
        x = self. relu(x)
        x = self.conv7(x)
        x = self.bn7(x)
        x = self. relu(x)
        x = self.conv8(x)
        out = self.tanh(x)

        return out


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations

class Migration(migrations.Migration):

    dependencies = [
        ('main', '0017_auto_20150624_1438'),
    ]

    operations = [
        migrations.AlterField(
            model_name='article',
            name='content',
            field=models.TextField(blank=True, verbose_name='글 내용', default=1),
            preserve_default=False,
        ),
        migrations.AlterField(
            model_name='article',
            name='file_image',
            field=models.ImageField(blank=True, verbose_name='이미지:', upload_to='img/%Y/%m'),
            preserve_default=True,
        ),
    ]


import json
import bilby
import matplotlib.pyplot as plt
from pathlib import Path

from QPOEstimation.utils import get_injection_outdir

injection_mode = "qpo_plus_red_noise"
band_minimum = 5
band_maximum = 64

band = f"{band_minimum}_{band_maximum}Hz"

Path(f"injections/{injection_mode}_injections/").mkdir(parents=True, exist_ok=True)

for i in range(100, 200):
    try:
        with open(f"injections/injection_files/{injection_mode}/{str(i).zfill(2)}_params.json") as f:
            injection_params = json.load(f)

        res = bilby.result.read_in_result(outdir=get_injection_outdir(
            injection_mode=injection_mode, recovery_mode=injection_mode,
            likelihood_model="celerite_windowed"), label=f"{str(i).zfill(2)}")
        plt.hist(res.posterior["window_maximum"], bins="fd", density=True)
        plt.axvline(injection_params["window_maximum"], color="orange")
        plt.savefig(f"injections/{injection_mode}_injections/{str(i).zfill(2)}.png")
        plt.clf()
    except (OSError, FileNotFoundError) as e:
        print(e)
        continue


# given survival times of specific (mu,eb, 7 *ap) values, makes a large data frame with all survival times, - with respective ap values --along with each surival time event observation (0 or 1).
# Then conduct survival regression for the ap covariates.
# EVENTUALLY - will need to be able to regress against multiple covariates (including mu and eb values).

import matplotlib.pyplot as plt
from matplotlib import ticker
from matplotlib.colors import LogNorm
import matplotlib
import numpy as np
import pandas as pd
#FOR SURVIVAL REGRESSION
from lifelines import CoxPHFitter, KaplanMeierFitter, NelsonAalenFitter, LogLogisticFitter
from myfunctions import PlottingLL, CureModel

get_ipython().run_line_magic('matplotlib', 'inline')

def CureModelLL(ebs, aps_0, mu, stime, Np):

    #*************************************EVENT OBSERVATION**************************************************#
    E = np.zeros(Np).astype(int)

    for i in range(0,30,1):
        if ((stime[0,i]) > 62831):
            E[i] = 0
        else:
            E[i] = 1

     #**************************************MAKING A DATA FRAME 2************************************************#
    data1 = {'T':stime[0], 'E':E}
    df = pd.DataFrame(data=data1)

    T = df['T']
    E = df['E']

    #************************************CURE MODEL FITTER*************************************#

    fig, ax = plt.subplots(figsize=(12, 4))

    #ax.set_ylabel("S(t)")
    plt.rc('legend', fontsize=(7))

    cure_model = CureModel.CureFitter().fit(T, E, timeline=np.arange(1, 10000))
    ax = cure_model.plot_survival_function(figsize=(8,4))
    cure_model.print_summary(4)

    kmf = KaplanMeierFitter()
    kmf.fit(T, E).plot(ax=ax)

    ax.set_xscale('log')

    p_val = np.array([cure_model.p_])
    lambda_val =  np.array([cure_model.lambda_])

    return p_val, lambda_val

#     print("---")
#
#     print("Estimated lower bound: {:.2f} ({:.2f}, {:.2f})".format(
#             cure_model.summary.loc['p_', 'coef'],
#             cure_model.summary.loc['lambda_', 'coef'],
#             cure_model.summary.loc['p_',  'coef upper 95%'],
#             cure_model.summary.loc['p_',  'coef lower 95%'],
#         )
#     )

    plt.title('(eb,ap,mu)={}'.format((round(ebs,3),round(aps_0,3),mu)), fontsize = 12)
#     plt.savefig('aps+ aps3+ aps5(210 values)) : (eb,ap,mu)={}.png'.format((round(ebs,3),round(aps_0,3),mu)),dpi = 250)


from django.utils.safestring import mark_safe
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as DjangoUserAdmin
from django.contrib.contenttypes.admin import GenericTabularInline
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.forms import UserChangeForm, UserCreationForm
from django.contrib.sites.models import Site
from django.utils.translation import gettext_lazy as _
from django.db.models import Value
from django.db.models.functions import Concat
from django.http import HttpResponse
from django import forms
from django.utils.timezone import datetime
from django.urls import path
from django.shortcuts import render
from django.core.serializers.json import DjangoJSONEncoder
from grappelli.dashboard import modules, Dashboard
from import_export.admin import ImportMixin, ImportExportActionModelAdmin
from rest_framework.authtoken.models import Token

from vjit_network.core import utils, customfields, resources, business, forms
from vjit_network.core.models import Post, File, Company, Comment, View, Industry, Tag, Skill, Link, User, Student, Group, GroupUser, Contact, get_type, UserSetting, AttachPost, Approval, Experience, Education
from vjit_network.common.utils import truncate_string, reverse

from io import BytesIO
import pandas as pd
import json

# Register your models here
EXCEL_MIME_TYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'

class ModelAdmin(admin.ModelAdmin):
    list_per_page = 10

    class Media:
        css = {
            "all": ("core/css/grappelli.css",)
        }

class CustomImportExportActionModelAdmin(ImportExportActionModelAdmin):
    import_template_name = 'core/import_export/import.html'

class MyDashboard(Dashboard):
    template = 'core/dashboard/dashboard.html'

    def __init__(self, **kwargs):
        Dashboard.__init__(self, **kwargs)

        self.children.append(modules.Group(
            title=_("System maintenance"),
            column=1,
            collapsible=True,
            children=[
                modules.ModelList(
                    title=_('User types'),
                    column=1,
                    collapsible=True,
                    models=[
                        'vjit_network.core.models.User',
                        'vjit_network.core.models.Student',
                        'vjit_network.core.models.Company',
                    ],
                ),
                modules.ModelList(
                    title=_('Social'),
                    column=1,
                    collapsible=True,
                    models=[
                        'vjit_network.core.models.Post',
                        'vjit_network.core.models.View',
                        'vjit_network.core.models.Comment',
                        'vjit_network.core.models.Link',
                    ],
                ),
                modules.ModelList(
                    title=_('Media'),
                    column=1,
                    collapsible=True,
                    models=[
                        'vjit_network.core.models.File',
                    ],
                ),
                modules.ModelList(
                    title=_('Group'),
                    column=1,
                    collapsible=True,
                    models=[
                        'vjit_network.core.models.Group',
                        'vjit_network.core.models.GroupUser',
                    ],
                ),
                modules.ModelList(
                    title=_('Contact'),
                    column=1,
                    collapsible=True,
                    models=[
                        'vjit_network.core.models.Contact',
                    ],
                )
            ]
        ))

        self.children.append(modules.Group(
            title=_("System API"),
            column=1,
            collapsible=True,
            children=[
                modules.ModelList(
                    title=_('User devices'),
                    column=1,
                    collapsible=True,
                    models=[
                        'vjit_network.api.models.Device',
                    ],
                ),
                modules.ModelList(
                    title=_('Notification'),
                    column=1,
                    collapsible=True,
                    models=[
                        'vjit_network.api.models.NotificationTemplate',
                        'vjit_network.api.models.Notification',
                    ],
                ),
            ]
        ))

        # append a recent actions module
        self.children.append(modules.AppList(
            title=_('Administration'),
            column=2,
            collapsible=True,
            models=('django.contrib.*',),
        ))

        self.children.append(modules.RecentActions(
            title=_('Recent actions'),
            column=2,
            collapsible=True,
            limit=10,
        ))

    class Media:
        css = {
            'all': (
                'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.css',
            ),
        }
        js = (
            'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.min.js',
            'core/js/dashboard.js',
        )

class industry_inline(admin.TabularInline):
    model = Industry
    fields = ('id', 'name')

class UserAdmin(DjangoUserAdmin):
    fieldsets = (
        (None, {'fields': ('username', 'password')}),
        (_('Personal info'), {
         'fields': ('first_name', 'last_name', 'email', 'avatar', 'gender',)}),
        (_('User type'), {
            'fields': ('is_student', 'is_company', 'is_staff',)}),
        (_('Permissions'), {
            'fields': ('is_active', 'is_superuser', 'groups', 'user_permissions'),
        }),
        (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
    )
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('username', 'password1', 'password2'),
        }),
    )
    list_display = ('username', 'email', 'full_name',
                    'is_staff', 'is_student', 'is_company',)
    list_filter = ('is_company', 'is_student', 'is_staff',
                   'is_superuser', 'is_active')
    list_per_page = 10
    date_hierarchy = 'date_joined'
    exclude = ('is_online',)

    class user_setting_inline(admin.StackedInline):
        model = UserSetting
        fields = ('language',)

    class group_user_inline(admin.TabularInline):
        search_fields = ('group__name',)
        model = GroupUser
        fields = ('group', 'is_active',)
        autocomplete_fields = ('group',)

    inlines = [group_user_inline, user_setting_inline]

class GroupAdmin(CustomImportExportActionModelAdmin, ModelAdmin):
    list_display = ('name', 'slug', 'create_at', 'view_all_member',)
    date_hierarchy = 'create_at'
    search_fields = ('name', 'create_at')
    filter_horizontal = ('users',)
    readonly_fields = ('members_count', 'posts_count', 'create_by')
    resource_class = resources.GroupResource

    class group_user_inline(admin.TabularInline):
        model = GroupUser
        fields = ('user', 'is_active',)
        autocomplete_fields = ('user',)

        # filter_vertical = ('user',)

    inlines = [group_user_inline]
    list_per_page = 10

    def view_all_member(self, instance):
        ct = get_type(GroupUser)
        link = reverse('admin:{0}_{1}_{2}'.format(ct.app_label, ct.model, 'changelist'), query_kwargs={
            'group__id': instance.id
        })
        # print(link)
        return mark_safe(
            '{1} - members'.format(
                link, instance.members_count)
        )

    def save_model(self, request, obj, form, change):
        obj.create_by = request.user
        super().save_model(request, obj, form, change)

    view_all_member.allow_tags = True

class PostAdmin(ModelAdmin):
    list_display = ('id', 'create_by', 'public_code', 'group', 'create_at')
    date_hierarchy = 'create_at'
    search_fields = ('id', 'create_by__username', 'content', 'create_at')
    list_filter = ('via_type', 'public_code')
    exclude = ('extra',)
    autocomplete_lookup_fields = {
        'generic': [['via_type', 'via_id'], ],
    }

    class attach_post_inline(admin.TabularInline):
        model = AttachPost
        extra = 1
        related_lookup_fields = {
            'generic': [['content_type', 'object_id'], ],
        }

    class approval_inline(admin.TabularInline):
        model = Approval
        readonly_fields = ('user_reason', 'user_accept', 'create_at')
        extra = 0
        ordering = ['id']

    autocomplete_fields = ('group', 'create_by',)
    inlines = [attach_post_inline, approval_inline]
    readonly_fields = ('create_at', 'comments_count',
                       'views_count', 'public_code', 'via_type', 'via_id', 'create_by')
    list_per_page = 10

    def save_model(self, request, obj, form, change):
        via_type, via_id = None, None
        req_user: User = request.user
        if req_user.is_staff:
            via_type = get_type(User)
            via_id = req_user.pk
        elif req_user.is_student:
            via_type = get_type(Student)
            via_id = req_user.student.pk
        elif req_user.is_company:
            via_type = get_type(Company)
            via_id = req_user.company.pk
        if via_id is None:
            raise Exception('you need update the profile')
        obj.via_type = via_type
        obj.via_id = via_id
        obj.create_by = req_user
        super().save_model(request, obj, form, change)

class FileAdmin(ModelAdmin):
    list_display = ('id', 'name', 'mimetype', 'create_at')
    readonly_fields = ('create_at', 'name', 'size',
                       'mimetype', 'create_by', 'thumbnails')
    date_hierarchy = 'create_at'
    search_fields = ('id', 'name')
    list_filter = ('mimetype', 'create_at')
    list_per_page = 10

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        return qs.filter(create_by=request.user)

    def save_model(self, request, obj, form, change):
        obj.create_by = request.user
        super().save_model(request, obj, form, change)

class LinkAdmin(ModelAdmin):
    list_display = ('id', 'create_by', 'create_at', 'name',)
    readonly_fields = ('create_by',)
    search_fields = ('id', 'title',)
    list_filter = ('name', 'link')
    list_per_page = 10

    def save_model(self, request, obj, form, change):
        obj.create_by = request.user
        super().save_model(request, obj, form, change)

class CompanyAdmin(ModelAdmin):
    # list_display = ('owner',  'name', )
    date_hierarchy = 'create_at'
    search_fields = ('name',)
    list_per_page = 10

class CommentAdmin(ModelAdmin):
    list_display = ('id', 'parent', 'create_by', 'create_at', 'short_content')
    search_fields = ('id', 'create_by', 'content', 'create_at')
    list_filter = ('content_type',)
    date_hierarchy = 'create_at'
    list_per_page = 10
    readonly_fields = ('replies_count', 'create_by')

    class reply_inline(GenericTabularInline):
        model = Comment
        verbose_name = _('Reply comment')
        verbose_name_plural = _('Replies comment')
        readonly_fields = ('replies_count',)
        extra = 1

    inlines = [reply_inline]

    def short_content(self, obj):
        return truncate_string(obj.content)

    def save_model(self, request, obj, form, change):
        obj.create_by = request.user
        super().save_model(request, obj, form, change)

class ContentTypeAdmin(ModelAdmin):
    list_display = ('id', 'app_label', 'model')
    readonly_fields = ('app_label', 'model',)
    actions = None

    def get_queryset(self, request):
        qs = super(ContentTypeAdmin, self).get_queryset(request)
        return qs.filter(app_label='core')

class ViewAdmin(ModelAdmin):
    list_display = ('id', 'create_by', 'post', 'create_at')
    date_hierarchy = "create_at"
    list_per_page = 10
    readonly_fields = ('create_by',)

    def save_model(self, request, obj, form, change):
        obj.create_by = request.user
        super().save_model(request, obj, form, change)

class GroupUserAdmin(ModelAdmin):
    search_fields = ('user__username', 'user__full_name',
                     'user__email', 'group__name')
    list_display = ('group', 'user', 'is_active')
    autocomplete_fields = ('group', 'user',)
    # readonly_fields = ('create_by',)

    class group_name_filter(customfields.InputFilter):
        title = _('group name')
        parameter_name = 'group__name'

        def queryset(self, request, queryset):
            value = self.value()
            if value is not None:
                return queryset.filter(group__name=value)

    class group_id_filter(customfields.InputFilter):
        title = _('group id')
        parameter_name = 'group__id'

        def queryset(self, request, queryset):
            value = self.value()
            if value is not None:
                return queryset.filter(group__id=value)

    list_filter = ('is_active', group_name_filter, group_id_filter,)

    def save_model(self, request, obj, form, change):
        obj.create_by = request.user
        super().save_model(request, obj, form, change)

class StudentAdmin(ModelAdmin):
    search_fields = ('user__username', 'user__full_name', 'user__email',)
    # list_filter = ('gender',)
    autocomplete_fields = ('user',)
    list_display = ('username', 'full_name', 'email', 'phone')
    filter_horizontal = ('skills', 'industries')
    actions = ('export_as_xlsx',)
    date_hierarchy = 'user__date_joined'

    change_list_template = 'core/students/change_list.html'
    student_import_template = "core/students/import.html"

    class experience_inlines(admin.StackedInline):
        model = Experience
        autocomplete_fields = ('company_lookup',)
        extra = 1

    class education_inlines(admin.StackedInline):
        model = Education
        extra = 1
        exclude = ('activities', 'description',)

    inlines = [experience_inlines, education_inlines, ]

    def username(self, instance):
        return instance.user.username

    username.admin_order_field = 'user__username'

    def email(self, instance):
        return instance.user.email

    email.admin_order_field = 'user__email'

    def full_name(self, instance):
        return instance.user.full_name

    full_name.admin_order_field = 'user__full_name'

    def export_as_xlsx(self, request, queryset):
        results = business.dump_student_to_xlsx(queryset)
        with BytesIO() as io:
            # Use the StringIO object as the filehandle.
            writer = pd.ExcelWriter(io, engine='xlsxwriter')
            results.to_excel(writer, sheet_name='Student', index=False)
            writer.save()
            response = HttpResponse(
                io.getvalue(), content_type=EXCEL_MIME_TYPE)
            filename = int(datetime.now().timestamp())
            response['Content-Disposition'] = f'attachment; filename={filename}.xlsx'
            return response

    export_as_xlsx.short_description = _("Export Selected")

    def get_urls(self):
        urls = super().get_urls()
        app_label = self.model._meta.app_label
        model_name = self.model._meta.model_name
        my_urls = [
            path('import/',
                 self.admin_site.admin_view(self.import_student),
                 name='{0}_{1}_{2}'.format(app_label, model_name, 'import')),
        ]
        return my_urls + urls

    def import_student(self, request):
        validated_data = []
        if request.method == 'POST':
            form = forms.StudentUploadForm(
                data=request.POST, files=request.FILES)
            if form.is_valid():
                validated_data = form.get_validated()
        else:
            form = forms.StudentUploadForm()
        context = dict(
            # Include common variables for rendering the admin template.
            self.admin_site.each_context(request),
            # Anything else you want in the context...
            opts=self.model._meta,
            app_label=self.model._meta.app_label,
            title='Import Students',
            form=form,
            validated_data=json.dumps(validated_data, cls=DjangoJSONEncoder)
        )
        return render(request, self.student_import_template, context)

class ContactAdmin(ModelAdmin):
    search_fields = ('name',)
    list_display = ('name', 'phone', 'email', 'create_at')
    date_hierarchy = "create_at"

admin.site.unregister(Site)
admin.site.unregister(Token)
admin.site.register(Post, PostAdmin)
admin.site.register(File, FileAdmin)
admin.site.register(Company, CompanyAdmin)
admin.site.register(Comment, CommentAdmin)
admin.site.register(View, ViewAdmin)
admin.site.register(Industry)
admin.site.register(Tag)
admin.site.register(Skill)
admin.site.register(Link, LinkAdmin)
admin.site.register(User, UserAdmin)
admin.site.register(Student, StudentAdmin)
admin.site.register(Group, GroupAdmin)
admin.site.register(GroupUser, GroupUserAdmin)
admin.site.register(Contact, ContactAdmin)


# All rights reserved by forest fairy.
# You cannot modify or share anything without sacrifice.
# If you don't agree, keep calm and don't look at code bellow!

__author__ = "VirtualV <https://github.com/virtualvfix>"
__date__ = "12/11/2017 4:26 PM"

from config import CONFIG
from unittest import result
from libs.core.template import TEST_ERROR
from ..config import RESULT_DELIMITER_1, RESULT_DELIMITER_2
from libs.core.logger import getLogger, getSysLogger, LEVEL

class LoggerResult(result.TestResult):
    """
    Custom unittest result class
    """

    def __init__(self, logger=None):
        super(LoggerResult, self).__init__()
        self.logger = logger or getLogger(__file__)
        self.syslogger = getSysLogger()
        self.failfast = False
        self.testIndex = 0
        self.time = []
        self.errors = []
        self.skipped = []
        self.success = []
        self.failures = []
        self.expectedFailures = []
        self.unexpectedSuccesses = []

    def getDescription(self, test):
        doc_first_line = test.shortDescription()
        if doc_first_line:
            return ['%s' % TEST_ERROR.safe_substitute(index=test.testIndex, test=test)] \
                   + [x for x in doc_first_line.split('\n') if x != '']
        else:
            return ['%s' % TEST_ERROR.safe_substitute(index=test.testIndex, test=test)]

    def startTest(self, test):
        self.testIndex += 1
        test.testIndex = self.testIndex
        super(LoggerResult, self).startTest(test)

    def addTime(self, test, time):
        """ Add spent time """
        self.time.append((test, time))

    def addSubTest(self, test, subtest, err):
        # add testIndex to sub test
        if not hasattr(subtest, 'testIndex'):
            subtest.testIndex = self.testIndex

        if err is not None:
            if getattr(self, 'failfast', False):
                self.stop()
            if issubclass(err[0], test.failureException):
                self.addFailure(subtest, err)
            else:
                self.addError(subtest, err)

    def addSuccess(self, test):
        self.success.append((self.testIndex, test))

    def addError(self, test, err):
        # add test index
        if not hasattr(test, 'testIndex'):
            test.testIndex = self.testIndex
        self.errors.append((self.testIndex, test, self._exc_info_to_string(err, test)))
        self.printError('ERROR', test, self.errors)

    def addFailure(self, test, err):
        self.failures.append((self.testIndex, test, self._exc_info_to_string(err, test)))
        self.printError('FAIL', test, self.failures)

    def addSkip(self, test, reason):
        self.skipped.append((self.testIndex, test, reason))
        self.logger.warning('<skipped>', self.syslogger)

    def addExpectedFailure(self, test, err):
        self.expectedFailures.append((self.testIndex, test, self._exc_info_to_string(err, test)))
        self.logger.info('<expected failure>', self.syslogger)

    def addUnexpectedSuccess(self, test):
        self.unexpectedSuccesses.append((self.testIndex, test))
        self.logger.warning('<unexpected success>', self.syslogger)

    def __printErrorViaLogger(self, flavour, level, test, err, inside=True, print_prepare_errors=False):
        """
        Print error using logger. Used in :func:`printError` and :func:`printErrorList` functions.

        Args:
            flavour (str): Error or Fail string
            level (int): Error level
            test ({shortDescription}): Description of test
            err (str): Error traceback
            inside (bool, default True): Use different delimiter. True if error inside test run and False
                if error in total result
            print_prepare_errors (bool, default False): Don't print errors in **setUpClass**
                and **tearDownClass** functions
        """
        # skip prepare errors if required
        if str(test).startswith(('setUpClass', 'tearDownClass')) and not print_prepare_errors :
            return

        # test name
        self.logger.newline(self.syslogger)
        self.logger.table('%s*' % (RESULT_DELIMITER_2 if inside else RESULT_DELIMITER_1), ' *', self.syslogger,
                          border_delimiter='', level=level)
        for i, msg in enumerate(self.getDescription(test)):
            self.logger.table('%s%s' % ((flavour + ': ') if i == 0 else '', msg), self.syslogger,
                              column_delimiter='', level=level)
        # error
        self.logger.table('%s*' % RESULT_DELIMITER_2, ' *', self.syslogger, border_delimiter='', level=level)
        if CONFIG.SYSTEM.DEBUG:
            for e in [x for x in err.split('\n') if x != '']:
                self.logger.table('. %s' % e, self.syslogger, column_delimiter='', level=level)
        else:
            self.logger.table('. %s' % [x for x in err.split('\n') if x != ''][-1], self.syslogger,
                              column_delimiter='', level=level)
            for e in [x for x in err.split('\n') if x != '']:
                self.syslogger.table('. %s' % e, column_delimiter='', level=level)
        self.logger.table('%s*' % RESULT_DELIMITER_2, ' *', self.syslogger, border_delimiter='', level=level)

    def printError(self, flavour, test, errors):
        """ Print error or fail """
        level = LEVEL.ERROR if 'error' in flavour.lower() else LEVEL.WARNING
        for index, _test, err in errors:
            # if test == _test:
            if self.testIndex == index and test == _test and str(test) == str(_test):
                self.__printErrorViaLogger(flavour, level, test, err)
                break

    def printErrors(self):
        self.printErrorList('ERROR', self.errors, print_prepare_errors=True)
        self.printErrorList('FAIL', self.failures)

    def printErrorList(self, flavour, errors, print_prepare_errors=False):
        level = LEVEL.ERROR if 'error' in flavour.lower() else LEVEL.WARNING
        for index, test, err in errors:
            self.__printErrorViaLogger(flavour, level, test, err, inside=False,
                                       print_prepare_errors=print_prepare_errors)


#!/usr/local/bin/python3

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.pyplot import style
plt.style.use('ggplot')

from sklearn import svm, metrics, model_selection, preprocessing
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix, plot_precision_recall_curve, plot_roc_curve, roc_auc_score
from sklearn.model_selection import train_test_split, StratifiedKFold, GridSearchCV, cross_val_score
from sklearn_pandas import DataFrameMapper
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import Normalizer, MinMaxScaler, StandardScaler, RobustScaler, QuantileTransformer, LabelEncoder
from sklearn.neural_network import MLPClassifier

import seaborn as sns

wdbc_train = pd.read_csv("./WDBC_dat/WDBC_train.csv", sep=',')
print("training set:")
print(wdbc_train.head(5))

wdbc_test = pd.read_csv("./WDBC_dat/WDBC_test.csv", sep=',')
print("test set:")
print(wdbc_test.head(5))

counts = wdbc_train['diagnosis'].value_counts()
print(counts)

##create training set
X_train = wdbc_train.drop(['diagnosis'], axis=1)
print(X_train.head(5))
print(X_train.shape)
print(X_train.describe())

Y_train = wdbc_train['diagnosis']
print(Y_train.head(5))
print(Y_train.shape)

##create test set:
X_test = wdbc_test.drop(['diagnosis'], axis=1)
print(X_test.head(5))
print(X_test.shape)
print(X_test.describe())
#X_test.plot()

Y_test = wdbc_test['diagnosis']
print(Y_test.head(5))
print(Y_test.shape)

##scaling so that me
scaler = preprocessing.StandardScaler().fit(X_train)
X_train_scaled_features = scaler.transform(X_train)
X_train_scaled = pd.DataFrame(X_train_scaled_features, index=X_train.index, columns=X_train.columns)
print(X_train_scaled.shape)
print(X_train_scaled)

X_test_scaled_features = scaler.transform (X_test)
X_test_scaled = pd.DataFrame(X_test_scaled_features, index=X_test.index, columns=X_test.columns)
print(X_test_scaled.shape)
print(X_test_scaled)

###model fitting postnorm: tried both linear models.
pipe = Pipeline(steps=[
    ('preprocess', StandardScaler()),
    ('classification', MLPClassifier())
])

# mlp_activation = ['identity', 'logistic', 'tanh', 'relu']
# mlp_solver = ['sgd', 'adam']
# mlp_alpha = [1e-4, 1e-3, 0.01, 0.1, 1]
# preprocess = [MinMaxScaler(), StandardScaler()]
# hidden_layer_sizes = [10, 100, 200]
# #learning_rate = ['constant', 'invscaling', 'adaptive']
# momentum = [.1, .2, .3, .4, .5, .6, .7, .8, .9]
# random_state = 0
#
# mlp_param_grid = [
#     {
#         'preprocess': preprocess,
#         'classification__activation': mlp_activation,
#         'classification__solver': mlp_solver,
#         'classification__hidden_layer_sizes': hidden_layer_sizes,
#         'classification__alpha': mlp_alpha,
#         #'classifiation__learning_rate': learning_rate,
#         'classification__momentum': momentum,
#         'classification__random_state': [random_state]
#     }
# ]
#
# strat_k_fold = StratifiedKFold(
#     n_splits=5
# )
#
# mlp_grid = GridSearchCV(
#     pipe,
#     param_grid=mlp_param_grid,
#     cv=strat_k_fold,
#     verbose=2,
#     n_jobs=-1
# )
#
#
# print("params")
# print(mlp_grid.get_params().keys())
#
#
# mlp_grid.fit(X_train_scaled, Y_train)
# print("mlp grid values")
# # Best MLPClassifier parameters
# print(mlp_grid.best_params_)
# # Best score for MLPClassifier with best parameters
# print('\nBest F1 score for MLP: {:.2f}%'.format(mlp_grid.best_score_ * 100))
#
# best_params = mlp_grid.best_params_
# print(best_params)

## after finding best params:

mlp = MLPClassifier(
    max_iter=1000,
    alpha=1,
    activation='relu',
    solver='adam',
    random_state=0,
    momentum=0.1,
    learning_rate='constant',
    hidden_layer_sizes = 100
)

mlp.fit(X_train_scaled, Y_train)
mlp_predict = mlp.predict(X_test_scaled)
mlp_predict_proba = mlp.predict_proba(X_test_scaled)[:, 1]

print('MLP Accuracy: {:.2f}%'.format(accuracy_score(Y_test, mlp_predict) * 100))
print('MLP AUC: {:.2f}%'.format(roc_auc_score(Y_test, mlp_predict_proba) * 100))
print('MLP Classification report:\n\n', classification_report(Y_test, mlp_predict))
print('MLP Training set score: {:.2f}%'.format(mlp.score(X_train_scaled, Y_train) * 100))
print('MLP Testing set score: {:.2f}%'.format(mlp.score(X_test_scaled, Y_test) * 100))
#plot ROC AUC post norm
metrics.plot_roc_curve(mlp, X_test_scaled, Y_test)
plt.show()


# Importing ML Libraries.
import sklearn
import pandas as pd
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from matplotlib import pyplot as plt
import seaborn as sn
from sklearn.metrics import mean_squared_error, r2_score

import os
cls = lambda:os.system('cls')

data_file_path = './/FilteredData.csv'

dataFrame = pd.read_csv(data_file_path)
features = ['District','U/R','CPN']
target = ['Discp.']

# ==================================================
# ======== New Static + Reversable Encoding ========
# ==================================================
# Prepare Map for Encoding or Decoding.

# Maping Dicplines
temp = dataFrame['Discp.'].value_counts()

tech_map = {}
start = 1

for idx in temp.index.values:
    tech_map[idx] = start
    start = start + 1

temp = dataFrame['District'].value_counts()

district_map = {}
# Maping Districts
start = 1
for idx in temp.index.values:
    district_map[idx] = start
    start = start + 1

# Maping U/R
temp = dataFrame['U/R'].value_counts()
ur_map = {}
start = 1

for idx in temp.index.values:
    ur_map[idx] = start
    start = start + 1

print('========== Data Frame =========')
print(dataFrame)
print('======== Data Frame End =======')
print('\n')

print('=========== Statistics ============')
print(dataFrame.describe())
print('========= Statistics End ===========')
print('\n')

# ==================================================

# Encoding Categorical DATA.
# Dealing with categorical data...
# Applying real work...

for key in district_map:
    dataFrame['District'].loc[dataFrame['District'] == key] = district_map[key]

for key in ur_map:
    dataFrame['U/R'].loc[dataFrame['U/R'] == key] = ur_map[key]

for key in tech_map:
    dataFrame['Discp.'].loc[dataFrame['Discp.'] == key] = tech_map[key]

# Displaying the Data Frame

print('========== Data Frame =========')
print(dataFrame.head())
print('======== Data Frame End =======')
print('\n')

print('=========== Statistics ============')
print(dataFrame.describe())
print('========= Statistics End ===========')
print('\n')

# ==================================================

X = dataFrame[features]
Y = dataFrame[target]

# Create Test/Train
x_train,x_test,y_train,y_test = train_test_split(X,Y,test_size=0.25)

# Scikit Logistic Regression
scikit_log_reg = LogisticRegression(solver='lbfgs',multi_class='multinomial' ,max_iter=20000)
scikit_log_reg.fit(x_train, y_train.values.reshape(-1,))

y_pred = scikit_log_reg.predict(x_test[features])

#Evaluation of the results.
from sklearn import metrics
print('Algorithm Accuracy: ',metrics.accuracy_score(y_test,y_pred))
print('\n')

rmse = (np.sqrt(mean_squared_error(y_test, y_pred)))
r2 = r2_score(y_test, y_pred)

print('Root Mean Squared Error: ',rmse)
print('R2 Score :',r2)
print('\n')

cfm = metrics.confusion_matrix(y_test, y_pred)
plt.figure(figsize = (10,7))
sn.heatmap(cfm, annot=True)
plt.show()
# print(cfm)

# ================ MY TEST ====================

# Displaying the Data Frame
print('============ District =============')
print(district_map)
print('========== District End ===========')
print('\n')

print('========== Urban Rural ===========')
print(ur_map)
print('======== Urban Rural End =========')
print('\n')

print('============ Discpline =============')
print(tech_map)
print('========== Discpline End ===========')
print('\n')

def getKey(dictionary, item):
    for key in dictionary:
        if dictionary[key] == item:
            return key
    return None

again = True
while again:
    mDistrict = input('Enter District: ').upper()
    mUR = input('Urban Or Rural U/R? ').upper()
    mCPN = float(input('Enter CPN: '))
    testData = np.array([[district_map[mDistrict],ur_map[mUR],mCPN]])
    result = scikit_log_reg.predict(testData)[0]
    mTech = getKey(tech_map,result)
    print('Based On Your Results You Could Be Awarded: ',mTech,' Technology')
    again = input('Again (Y/N)? ')
    again = again.lower()
    again = True if again == 'y' else False

# ================ MY TEST END ==================

Technology PREDICTOR/Linear Model Traning.py


#!/usr/bin/python3

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

import argparse
import logging
import os
import matplotlib.pyplot as plt
import numpy as np
import torch
from ordered_set import OrderedSet
from torch.utils.data import DataLoader
import torch.nn.functional as F
from torch.utils.data import DataLoader
import KCA_model

from util import override_config,save_model,read_triple,set_logger,log_metrics,plot_config
from dataloader import TrainDataset, TestDataset, BidirectionalOneShotIterator,Emb_MKG_WY,Emb_MMKB_DB15K

def parse_args(args=None):
    parser = argparse.ArgumentParser()

    parser.add_argument('--do_train', action='store_true')
    parser.add_argument('--do_valid', action='store_true')
    parser.add_argument('--do_test', action='store_true')
    parser.add_argument('--evaluate_train', action='store_true', help='Evaluate on training data')

    parser.add_argument('--perf_file', type=str, default=None)

    parser.add_argument('--data_path', type=str, default='data/MKG-W')
    parser.add_argument('--model', default='TransE', type=str)
    parser.add_argument('-init', '--init_checkpoint', default=None, type=str)
    parser.add_argument('-save', '--save_path', default='./models', type=str)

    parser.add_argument('-de', '--double_entity_embedding', action='store_true')
    parser.add_argument('-dr', '--double_relation_embedding', action='store_true')

    parser.add_argument('-n', '--negative_sample_size', default=3, type=int)
    parser.add_argument('-d', '--hidden_dim', default=200, type=int)
    parser.add_argument('-g', '--gamma', default=12.0, type=float)
    parser.add_argument('-adv', '--negative_adversarial_sampling', action='store_true')
    parser.add_argument('-a', '--adversarial_temperature', default=1.0, type=float)
    parser.add_argument('-r', '--regularization', default=0.0, type=float)

    parser.add_argument('-lr', '--learning_rate', default=0.0001, type=float)
    parser.add_argument('-kca_lr', '--kca_learning_rate', default=0.001, type=float)
    parser.add_argument('--sample_method', default='gumbel',choices=['uni','gumbel'],type=str)
    parser.add_argument('--pre_sample_num', default=1500,type=int)
    parser.add_argument('--loss_rate', default=100,type=int)
    parser.add_argument('--exploration_temp', default=10,type=int)

    parser.add_argument('-b', '--batch_size', default=256, type=int)
    parser.add_argument('--test_batch_size', default=2, type=int, help='valid/test batch size')
    parser.add_argument('--uni_weight', default=False,type=bool,
                        help='Otherwise use subsampling weighting like in word2vec')

    parser.add_argument('-cpu', '--cpu_num', default=3, type=int)
    parser.add_argument('--gpu', default='0', type=str)
    parser.add_argument('--max_steps', default=100000, type=int)
    parser.add_argument('--warm_up_steps', default=None, type=int)
    parser.add_argument('--save_checkpoint_steps', default=10000, type=int)
    parser.add_argument('--valid_steps', default=10000, type=int)
    parser.add_argument('--test_log_steps', default=1000, type=int, help='valid/test log every xx steps')
    parser.add_argument('--nentity', type=int, default=0, help='DO NOT MANUALLY SET')
    parser.add_argument('--nrelation', type=int, default=0, help='DO NOT MANUALLY SET')

    return parser.parse_args(args)

def train_step(kge_model, optimizer, positive_sample, negative_sample, subsampling_weight,
         mode, args,device,simil_img, simil_text,simil_t,pre_sample,pos_neg_mask,neg_for_adv):
    kge_model.train()
    optimizer.zero_grad()

    positive_sample = positive_sample.to(device)
    negative_sample = negative_sample.to(device)
    subsampling_weight = subsampling_weight.to(device)

    negative_score = kge_model((positive_sample, negative_sample), mode,'train')  # batch * neg

    if args.sample_method=='uni':
        if args.model in ['RotatE','PairRE']:
            self_adversarial_weight = F.softmax(negative_score * args.adversarial_temperature, dim=1).detach()  # batch * neg
            negative_score = (self_adversarial_weight * F.logsigmoid(-negative_score)).sum(dim=1)
        else:
            negative_score = F.logsigmoid(-negative_score).mean(dim=1)
    elif args.sample_method=='gumbel':
            # In self-adversarial sampling, we do not apply back-propagation on the sampling weight
        self_adversarial_weight = F.softmax(negative_score * args.adversarial_temperature, dim=1).detach()  # batch * neg
        negative_score = (self_adversarial_weight * F.logsigmoid(-negative_score)).sum(dim=1)

        ####  contrastive loss self_adversarial
        self_adversarial_weight_for_presample = torch.ones_like(simil_img,device=device,requires_grad=False) /simil_img.shape[-1]  # batchsize x pre_sample
        batch_index = torch.arange(args.batch_size)
        for n in range(neg_for_adv.shape[-1]):
            self_adversarial_weight_for_presample[batch_index,neg_for_adv[:,n]] *= self_adversarial_weight[:,n]

        simil_img = torch.mul( torch.exp(simil_img), self_adversarial_weight_for_presample )  # batchsize x pre_sample
        simil_text = torch.mul( torch.exp(simil_text) , self_adversarial_weight_for_presample )  # batchsize x pre_sample
        simil_t = torch.mul( torch.exp(simil_t) ,self_adversarial_weight_for_presample)   # batchsize x pre_sample

        # pre_sample
        contra_loss_img = - torch.log( torch.sum(simil_img[pos_neg_mask[:,pre_sample]])  / torch.sum(simil_img[~pos_neg_mask[:,pre_sample]])  )
        contra_loss_text = - torch.log( torch.sum(simil_text[pos_neg_mask[:,pre_sample]])  / torch.sum(simil_text[~pos_neg_mask[:,pre_sample]])  )
        contra_loss_t = - torch.log( torch.sum(simil_t[pos_neg_mask[:,pre_sample]])  / torch.sum(simil_t[~pos_neg_mask[:,pre_sample]]))

    positive_score = kge_model(positive_sample,'single','train')
    positive_score = F.logsigmoid(positive_score).squeeze(dim=1)

    if args.uni_weight:
        positive_sample_loss = - positive_score.mean()
        negative_sample_loss = - negative_score.mean()
    else:
        positive_sample_loss = - (subsampling_weight * positive_score).sum() / subsampling_weight.sum()
        negative_sample_loss = - (subsampling_weight * negative_score).sum() / subsampling_weight.sum()

    if args.sample_method=='uni':
        loss = (positive_sample_loss + negative_sample_loss) / 2
    else:
        loss = (positive_sample_loss + negative_sample_loss) / 2  + (contra_loss_img+ contra_loss_text+contra_loss_t)  / (3 * args.loss_rate)

    if args.regularization != 0.0:
        # Use L3 regularization for ComplEx and DistMult
        regularization = args.regularization * (
            kge_model.entity_embedding.norm(p=3) ** 3 +
            kge_model.relation_embedding.norm(p=3).norm(p=3) ** 3
        )
        loss = loss + regularization
        regularization_log = {'regularization': regularization.item()}
    else:
        regularization_log = {}

    loss.backward()
    optimizer.step()
    log = {
        **regularization_log,
        'positive_sample_loss': positive_sample_loss.item(),
        'negative_sample_loss': negative_sample_loss.item(),
        'loss': loss.item()
    }

    return log

def test_step(kge_model, test_triples, all_true_triples, args,device):
    kge_model.eval()

    test_dataloader_head = DataLoader(
        TestDataset(
            test_triples,
            all_true_triples,
            args.nentity,
            args.nrelation,
            'head-batch'
        ),
        batch_size=args.test_batch_size,
        num_workers=max(1, args.cpu_num // 2),
        collate_fn=TestDataset.collate_fn
    )

    test_dataloader_tail = DataLoader(
        TestDataset(
            test_triples,
            all_true_triples,
            args.nentity,
            args.nrelation,
            'tail-batch'
        ),
        batch_size=args.test_batch_size,
        num_workers=max(1, args.cpu_num // 2),
        collate_fn=TestDataset.collate_fn
    )

    test_dataset_list = [test_dataloader_head, test_dataloader_tail]

    logs = []

    step = 0
    total_steps = sum([len(dataset) for dataset in test_dataset_list])

    with torch.no_grad():
        for test_dataset in test_dataset_list:
            for positive_sample, negative_sample, filter_bias, mode in test_dataset:

                positive_sample = positive_sample.to(device)
                negative_sample = negative_sample.to(device)
                filter_bias = filter_bias.to(device)

                batch_size = positive_sample.size(0)

                score = kge_model((positive_sample, negative_sample), mode,'test')
                score += filter_bias

                # Explicitly sort all the entities to ensure that there is no test exposure bias
                argsort = torch.argsort(score, dim=1, descending=True)

                if mode == 'head-batch':
                    positive_arg = positive_sample[:, 0]
                elif mode == 'tail-batch':
                    positive_arg = positive_sample[:, 2]
                else:
                    raise ValueError('mode %s not supported' % mode)

                for i in range(batch_size):
                    # Notice that argsort is not ranking
                    ranking = (argsort[i, :] == positive_arg[i]).nonzero()
                    assert ranking.size(0) == 1

                    # ranking + 1 is the true ranking used in evaluation metrics
                    ranking = 1 + ranking.item()
                    logs.append({
                        'MRR': 1.0 / ranking,
                        'MR': float(ranking),
                        'HITS@1': 1.0 if ranking <= 1 else 0.0,
                        'HITS@3': 1.0 if ranking <= 3 else 0.0,
                        'HITS@10': 1.0 if ranking <= 10 else 0.0,
                    })

                if step % args.test_log_steps == 0:
                    logging.info('Evaluating the model... (%d/%d)' % (step, total_steps))

                step += 1

    metrics = {}
    for metric in logs[0].keys():
        metrics[metric] = sum([log[metric] for log in logs]) / len(logs)

    return metrics

def main(args):
    torch.set_num_threads(args.cpu_num)
    device = 'cuda:'+args.gpu if torch.cuda.is_available() else 'cpu'

    if args.perf_file == None:
        args.perf_file = 'results/'+ args.data_path.split('/')[1]  +'-' + args.model + '-' + args.sample_method  + '.txt'
    plot_config(args)
    from KGC_model import KGEModel

    if (not args.do_train) and (not args.do_valid) and (not args.do_test):
        raise ValueError('one of train/val/test mode must be choosed.')

    if args.init_checkpoint:
        override_config(args)
    elif args.data_path is None:
        raise ValueError('one of init_checkpoint/data_path must be choosed.')

    if args.do_train and args.save_path is None:
        raise ValueError('Where do you want to save your trained model?')

    if args.save_path and not os.path.exists(args.save_path):
        os.makedirs(args.save_path)

    set_logger(args)

    ent_set, rel_set = OrderedSet(), OrderedSet()
    for split in ['train', 'test', 'valid']:
        for line in open('{}/{}.txt'.format(args.data_path, split), encoding='utf-8'):
            sub, rel, obj = line.strip().split('\t')
            ent_set.add(sub)
            rel_set.add(rel)
            ent_set.add(obj)

    entity2id = {ent: idx for idx, ent in enumerate(ent_set)}
    relation2id = {rel: idx for idx, rel in enumerate(rel_set)}

    nentity = len(entity2id)
    nrelation = len(relation2id)

    args.nentity = nentity
    args.nrelation = nrelation

    logging.info('Model: %s' % args.model)
    logging.info('Data Path: %s' % args.data_path)
    logging.info('#entity: %d' % nentity)
    logging.info('#relation: %d' % nrelation)

    train_triples = read_triple(os.path.join(args.data_path, 'train.txt'), entity2id, relation2id)
    logging.info('#train: %d' % len(train_triples))
    valid_triples = read_triple(os.path.join(args.data_path, 'valid.txt'), entity2id, relation2id)
    logging.info('#valid: %d' % len(valid_triples))
    test_triples = read_triple(os.path.join(args.data_path, 'test.txt'), entity2id, relation2id)
    logging.info('#test: %d' % len(test_triples))

    #All true triples
    all_true_triples = train_triples + valid_triples + test_triples

    kge_model = KGEModel(
        sample_method = args.sample_method,
        device=device,
        model_name=args.model,
        nentity=nentity,
        nrelation=nrelation,
        hidden_dim=args.hidden_dim,
        gamma=args.gamma,
        double_entity_embedding=args.double_entity_embedding,
        double_relation_embedding=args.double_relation_embedding,

    )

    logging.info('Model Parameter Configuration:')
    for name, param in kge_model.named_parameters():
        logging.info('Parameter %s: %s, require_grad = %s' % (name, str(param.size()), str(param.requires_grad)))

    kge_model = kge_model.to(device)

    if args.do_train:
        # Set training dataloader iterator
        train_dataloader_head = DataLoader(
            TrainDataset(train_triples, nentity, nrelation, args.negative_sample_size, 'head-batch',args),
            batch_size=args.batch_size,
            shuffle=True,
            num_workers=max(1, args.cpu_num//2),
            collate_fn=TrainDataset.collate_fn,
            drop_last=True
        )

        train_dataloader_tail = DataLoader(
            TrainDataset(train_triples, nentity, nrelation, args.negative_sample_size, 'tail-batch',args),
            batch_size=args.batch_size,
            shuffle=True,
            num_workers=max(1, args.cpu_num//2),
            collate_fn=TrainDataset.collate_fn,
            drop_last=True
        )

        train_iterator = BidirectionalOneShotIterator(train_dataloader_head, train_dataloader_tail)

        # Set training configuration
        current_learning_rate = args.learning_rate
        if args.sample_method=='uni':
            optimizer = torch.optim.Adam( filter(lambda p: p.requires_grad, kge_model.parameters()), lr=current_learning_rate )
        elif args.sample_method=='gumbel':
            if args.data_path == 'data/MMKB-DB15K':
                ent_text_emb, ent_img_emb = Emb_MMKB_DB15K(args,entity2id,device)
            else:
                ent_text_emb, ent_img_emb = Emb_MKG_WY(args,entity2id,device)
            KCA = KCA_model.KCA(args,None, args.nentity,ent_text_emb, ent_img_emb)
            KCA = KCA.to(device)
            optimizer = torch.optim.Adam([{'params':kge_model.parameters(),'lr':current_learning_rate},
                                            {'params':KCA.parameters(),'lr':args.kca_learning_rate},
                                            ])

        if args.warm_up_steps:
            warm_up_steps = args.warm_up_steps
        else:
            warm_up_steps = args.max_steps // 2

    if args.init_checkpoint:
        # Restore model from checkpoint directory
        logging.info('Loading checkpoint %s...' % args.init_checkpoint)
        checkpoint = torch.load(os.path.join(args.init_checkpoint, 'checkpoint'))
        init_step = checkpoint['step']
        kge_model.load_state_dict(checkpoint['model_state_dict'])
        if args.do_train:
            current_learning_rate = checkpoint['current_learning_rate']
            warm_up_steps = checkpoint['warm_up_steps']
            optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
    else:
        logging.info('Ramdomly Initializing %s Model...' % args.model)
        init_step = 0

    step = init_step

    logging.info('Start Training...')
    logging.info('init_step = %d' % init_step)
    logging.info('batch_size = %d' % args.batch_size)
    logging.info('negative_adversarial_sampling = %d' % args.negative_adversarial_sampling)
    logging.info('hidden_dim = %d' % args.hidden_dim)
    logging.info('gamma = %f' % args.gamma)
    logging.info('negative_adversarial_sampling = %s' % str(args.negative_adversarial_sampling))
    if args.negative_adversarial_sampling:
        logging.info('adversarial_temperature = %f' % args.adversarial_temperature)

    if args.do_train:
        logging.info('learning_rate = %d' % current_learning_rate)

        training_logs = []

        positive_sample_loss,negative_sample_loss,loss = [],[],[]
        # pre_sample_pro = torch.ones([args.batch_size,args.nentity],device=device)
        for step in range(init_step, args.max_steps):

            positive_sample, negative_uniform_sample, subsampling_weight,mask, mode = next(train_iterator)

            if args.sample_method=='uni':
                negative_sample = negative_uniform_sample
                log = train_step(kge_model, optimizer, positive_sample, negative_sample, subsampling_weight, mode, args,device,0)

            elif args.sample_method=='gumbel':
                temperature = args.exploration_temp / (1+ torch.log( torch.tensor([step +1],device=device)))

                # pre_sample = torch.multinomial(pre_sample_pro, args.pre_sample_num, replacement=False,device=device)  # B x pre_sample
                pre_sample = torch.randperm(args.nentity)[:args.pre_sample_num].to(device) # pre_sample_num

                pos_neg_mask = torch.le(mask,0.5) # B x num_entity

                neg_distribution,simil_img, simil_text,simil_t = KCA(kge_model,positive_sample,mode,temperature,pre_sample,pos_neg_mask) # batch * num_entity

                ## mask for filter
                if args.pre_sample_num:
                    neg_distribution = torch.log(neg_distribution) + torch.log(mask.to(device)[:,pre_sample])
                else:
                    neg_distribution = torch.log(neg_distribution) + torch.log(mask.to(device))

                neg_all = []
                neg_for_adv = []
                for it in range(args.negative_sample_size):
                    neg_onehot = F.gumbel_softmax(neg_distribution,tau=1,hard=True,dim=1)  # batch * presample_entity（one hot）
                    neg_all.append(neg_onehot)
                    neg_for_adv.append(torch.argmax(neg_onehot, dim=1,keepdim=True))
                    # sampling without replacement
                    neg_distribution[neg_onehot.bool()] += torch.log(torch.tensor([1e-38],device=device))

                neg_all = torch.stack(neg_all,dim=1) # batch * neg_num * presample_entity (one-hot)
                neg_for_adv = torch.cat(neg_for_adv,dim=1) # batch * neg_num

                if args.pre_sample_num:
                    neg_emb = torch.matmul(neg_all,kge_model.entity_embedding[pre_sample]) # batch * neg_num * ent_dim
                else:
                    neg_emb = torch.matmul(neg_all,kge_model.entity_embedding) # batch * neg_num * ent_dim

                log = train_step(kge_model, optimizer, positive_sample, neg_emb, subsampling_weight, mode, args,device,simil_img, simil_text,simil_t,pre_sample,pos_neg_mask,neg_for_adv)

            training_logs.append(log)

            if step >= warm_up_steps:
                current_learning_rate = current_learning_rate / 10
                logging.info('Change learning_rate to %f at step %d' % (current_learning_rate, step))
                # optimizer = torch.optim.Adam(
                #     #filter(lambda p: p.requires_grad, kge_model.parameters()),
                #     lr=current_learning_rate
                # )
                warm_up_steps = warm_up_steps * 3

            if step!= 0 and step % args.save_checkpoint_steps == 0:
                save_variable_list = {
                    'step': step,
                    'current_learning_rate': current_learning_rate,
                    'warm_up_steps': warm_up_steps
                }
                save_model(kge_model, optimizer, save_variable_list, args)

            if step!= 0 and step % 1000 == 0:
                metrics = {}
                for metric in training_logs[0].keys():
                    metrics[metric] = sum([log[metric] for log in training_logs])/len(training_logs)
                # log_metrics('Training average', step, metrics)
                for metric in metrics:
                    logging.info('Training average %s at step %d: %f' % (metric, step, metrics[metric]))
                training_logs = []
                positive_sample_loss.append(metrics['positive_sample_loss'])
                negative_sample_loss.append(metrics['negative_sample_loss'])
                loss.append(metrics['loss'])

            if step!= 0 and args.do_valid and step % args.valid_steps == 0:
                logging.info('Evaluating on Valid Dataset...')
                metrics = test_step(kge_model, valid_triples, all_true_triples, args,device)
                a = log_metrics('Valid', step, metrics)
                with open(args.perf_file, 'a') as f:
                    f.write(' Valid at step %d: %.4f|%.2f|%.4f|%.4f|%.4f|\n' %( step, a[0]*100,a[1],a[2]*100,a[3]*100,a[4]*100))

                logging.info('Evaluating on Test Dataset...')
                metrics = test_step(kge_model, test_triples, all_true_triples, args,device)
                a = log_metrics('Test', step, metrics)
                with open(args.perf_file, 'a') as f:
                    f.write('Test at step %d: %.4f|%.2f|%.4f|%.4f|%.4f|\n' %( step, a[0]*100,a[1],a[2]*100,a[3]*100,a[4]*100))

        save_variable_list = {
            'step': step,
            'current_learning_rate': current_learning_rate,
            'warm_up_steps': warm_up_steps
        }
        save_model(kge_model, optimizer, save_variable_list, args)

    if args.do_valid:
        logging.info('Evaluating on Valid Dataset...')
        metrics = test_step(kge_model, valid_triples, all_true_triples, args,device)
        a = log_metrics('Valid', step, metrics)
        with open(args.perf_file, 'a') as f:
            f.write(' Valid at step %d: %.4f|%.2f|%.4f|%.4f|%.4f|\n' %( step, a[0]*100,a[1],a[2]*100,a[3]*100,a[4]*100))
    if args.do_test:
        logging.info('Evaluating on Test Dataset...')
        metrics = test_step(kge_model, test_triples, all_true_triples, args,device)
        a = log_metrics('Test', step, metrics)
        with open(args.perf_file, 'a') as f:
            f.write('Test at step %d: %.4f|%.2f|%.4f|%.4f|%.4f|\n' %( step, a[0]*100,a[1],a[2]*100,a[3]*100,a[4]*100))

    if args.evaluate_train:
        logging.info('Evaluating on Training Dataset...')
        metrics = test_step(kge_model, train_triples, all_true_triples, args,device)
        log_metrics('Train', step, metrics)

def setup_seed(seed):
     torch.manual_seed(seed)
     torch.cuda.manual_seed_all(seed)
     np.random.seed(seed)
     torch.backends.cudnn.deterministic = True

if __name__ == '__main__':
    setup_seed(42)
    main(parse_args())