#!/usr/bin/env python
# coding: utf-8

# In[1]:

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import torch
import torch.nn as nn
import torch.nn.functional as F

# In[2]:

train_set = pd.read_csv('/home/kandpal/Downloads/mnist_train.csv', header=None, dtype='float64')
test_set = pd.read_csv('/home/kandpal/Downloads/mnist_test.csv', header=None, dtype='float64')

train_labels = train_set[0]
test_label = test_set[0]

train_set.drop(columns=0, inplace=True)
test_set.drop(columns=0, inplace=True)

## Add dataLoader part below ##

# In[3]:

class Model(nn.Module):

    def __init__(self):
        super(Model, self).__init__()

        self.conv1 = nn.Conv2d(1, 10, 5)
        self.conv2 = nn.Conv2d(10, 20, 5)
        self.linear1 = nn.Linear(8000, 4000)
        self.linear2 = nn.Linear(4000, 25)
        self.convtrans1 = nn.ConvTranspose2d(1, 10, 1)
        self.convtrans2 = nn.ConvTranspose2d(10, 30, 3)
        self.linear3 = nn.Linear(1470, 800)
        self.reconst = nn.Linear(800, 784)

    def encoder(self, image):

        image = torch.unsqueeze(torch.unsqueeze(image, 0), 0)

        conv1 = F.relu( self.conv1(image) )
        conv2 = F.relu( self.conv2(conv1) )
        linear = F.relu( self.linear1( conv2.reshape(-1) ) )
        bottleneck = F.relu( self.linear2( linear ) )

        return bottleneck

    def decoder(self, bottleneck):

        bottleneck = bottleneck.reshape(5, 5)
        bottleneck = torch.unsqueeze(torch.unsqueeze(bottleneck, 0), 0)

        deconv1 = F.relu( self.convtrans1( bottleneck ) )
        deconv2 = F.relu( self.convtrans2( deconv1 ))
        reconstr = F.relu( self.linear3( deconv2.reshape(-1) ) )
        reconstr = F.relu( self.reconst( reconstr ) )

        return reconstr

# In[4]:

net = Model().cuda()

loss_fn = nn.MSELoss()
optimizer = torch.optim.AdamW(net.parameters())
epochs = 10

# In[5]:

costs = []

for iterations in range(epochs):

    for image_number in range(len(train_set.index)):

        image = torch.from_numpy(np.array(list(train_set.iloc[1])).reshape(28,28))
        image = image.float()

        gaussian_noise = torch.randn(image.shape)
        noisy_image = image + 100*gaussian_noise

        latent_space = net.encoder(noisy_image.cuda())
        reconstruction = net.decoder(latent_space.cuda())

        loss = loss_fn(image.flatten().cuda(), reconstruction.cuda())
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        costs.append(loss.item())
    print(f'average loss {np.mean(costs)}')
    plt.figure(1)
    plt.subplot(131)
    plt.imshow(image.cpu().detach().reshape(28,28).numpy())

    plt.subplot(132)
    plt.imshow(noisy_image.reshape(28,28))

    plt.subplot(133)
    plt.imshow(reconstruction.cpu().detach().reshape(28,28).numpy())

# In[ ]:

from scipy.ndimage import gaussian_filter
plt.plot(costs)
plt.plot(gaussian_filter(costs, 10))
plt.show()


from shop.models import *
from django.shortcuts import *
from django.db.models import Sum
from django.core.exceptions import ObjectDoesNotExist

def brand(request, name):
	rtx = {}
	rtx['isUser'] = request.session.get('type', '') == 'user'
	rtx['user_id'] = request.session.get('id', '')

	rtx['brand'] = Brand.objects.get(pk=name)
	rtx['turnover'] = Buy.objects.filter(computer_id__brand=rtx['brand']).aggregate(Sum('price'))[r'price__sum']
	rtx['likeNumber'] = like.objects.filter(brand_name=rtx['brand']).count()
	rtx['followers'] = like.objects.filter(brand_name=rtx['brand'])

	rtx['like'] = '取消关注' if like.objects.filter(brand_name__name=name, user_id__user_id=rtx['user_id']).count() > 0 else '关注'

	rtx['computers'] = []
	for c in Computer.objects.filter(brand__name=name):
		rtx['computers'].append((c.computer_id, c.cpu, c.memory, Buy.objects.filter(computer_id__brand__name=name).count()))

	rtx['net'] = rtx['brand'].net
	if rtx['net'][:4] != 'http':
		rtx['net'] = 'http://' + rtx['net']

	return render(request, 'Dashio/brand.html', rtx)

def makeLike(request, name, user_id):
  try:
    m = like.objects.get(brand_name__name=name, user_id__user_id=user_id)
    m.delete()
  except ObjectDoesNotExist:
    brand = get_object_or_404(Brand, pk=name)
    user = get_object_or_404(User, pk=user_id)
    like(brand_name=brand, user_id=user).save()

  return HttpResponseRedirect(reverse('shop:brand', args=(name, )))

def allBrands(request):
	brands = Brand.objects.all()
	rtx = {'brands': []}
	for b in brands:
		rtx['brands'].append([b.name, b.country, b.found_date, Computer.objects.filter(brand=b).count(), Buy.objects.filter(computer_id__brand=b).aggregate(Sum('price'))[r'price__sum']])
		if rtx['brands'][-1][4] is None:
			rtx['brands'][-1][4] = 0.0

	if request.method == 'POST':
		sortKey = {'name': 0, 'country': 1, 'found_date': 2, 'computerNumber': 3, 'turnover': 4}
		rtx['brands'].sort(key=lambda x: x[sortKey[request.POST['sort']]], reverse=(request.POST['sortType'] == '-'))

	return render(request, 'Dashio/allbrand.html', rtx)


from itertools import permutations

def solution(k, dungeons):
    answer = 0
    for p in permutations(dungeons, len(dungeons)):
        cnt = 0
        now = k
        for required, v in p:
            if now >= required:
                now -= v
                cnt += 1
        answer = max(answer, cnt)
    return answer


class Solution(object):
    def merge(self, intervals):
        """
        :type intervals: List[List[int]]
        :rtype: List[List[int]]
        """
        if len(intervals) == 0:
            return []
        intervals.sort(key=lambda x: x[0])
        ret = [intervals[0]]
        for interval in intervals[1:]:
            if interval[0] <= ret[-1][1]:
                ret[-1][1] = max(ret[-1][1], interval[1])
            else:
                ret.append(interval)
            print(ret)
        return ret

def execute():
    sol = Solution()
    intervals = [[1, 6], [5, 2], [8, 10], [15, 18]]
    print(sol.merge(intervals))

if __name__ == '__main__':
    execute()


## -> JSON(JavaScript Object Notation)
## -> It is mainly used for storing and transferring data between the browser and the server.
## -> JSON is test, written with JavaScript Object Notation
## -> Python to Supports JSON with a built-in package called json.

## JSON_Supports_maily_6_datatypes:
    # String
    # Number
    # Boolean
    # Null
    # Object
    # Array

import json
p = "{'name':'WS', 'lang':['Python', 'Java']}"
blog = {"URL": 'www.wscubetech', 'name':'wscubetech'}
to_json = json.dumps(blog)

d = {"cousre_name":'Python', "Fees":12000}
f = json.dumps(d)
print(f)
print(type(f))


from codeschool.core.tests import *
from codeschool.models import Page
from codeschool.core import models

def _test_page(page):
    assert isinstance(page, Page)
    assert page.pk is not None

@pytest.mark.django_db
def test_rogue_root(db):
    page = models.RogueRoot.instance()
    _test_page(page)

@pytest.mark.django_db
def test_hidden_root(db):
    page = models.HiddenRoot.instance()
    _test_page(page)
    assert page.live is False


import datetime
import os
from math import inf, lcm, log10, sqrt
import Eratosthenes
import random
time = datetime.datetime.now()

board = {0:'GO',1:'A1',2:'CC1',3:'A2',4:'T1',5:'R1',6:'B1',7:'CH1',8:'B2',9:'B3',10:'JAIL',11:'C1',12:'U1',13:'C2',14:'C3',15:'R2',16:'D1',17:'CC2',18:'D2',19:'D3',20:'FP',21:'E1',22:'CH2',23:'E2',24:'E3',25:'R3',26:'F1',27:'F2',28:'U2',29:'F3',30:'G2J',31:'G1',32:'G2 ',33:'CC3',34:'G3',35:'R4',36:'CH3',37:'H1',38:'T2',39:'H2'
}
communityChest = {1:'Advance to GO', 2:'Go to JAIL'}
communityChestOrder = list(range(16))
chance = {1:'Advance to GO',2:'Go to JAIL',3:'Go to C1',4:'Go to E3',5:'Go to H2',6:'Go to R1',7:'Go to next R',8:'Go to next R',9:'Go to next U',10:'Go back 3 squares'}
chanceOrder = list(range(16))

def nextMove(currentPos, instruction):
    if instruction == 'Advance to GO':
        return 1
    elif instruction == 'Go to JAIL':
        return 11
    elif instruction == 'Go to E3':
        return 25
    elif instruction == 'Go to H2':
        return 39
    elif instruction == 'Go to R1':
        return 6
    elif instruction == 'Go to next R':
        return (((currentPos+5)//10)*10+5)%40
    elif instruction == 'Go to next U':
        if currentPos > 12 and currentPos < 28:
            return 28
        else:
            return 12
    elif instruction == 'Go back 3 squares':
        return (currentPos-3)%40

print(chanceOrder)
random.shuffle(chanceOrder)
random.shuffle(communityChestOrder)
print (communityChestOrder)

runtime  = datetime.datetime.now() - time
print (runtime)


from confluent_kafka import Producer
import json
import time
import logging
from datetime import datetime, timedelta

import os
from dotenv import load_dotenv
load_dotenv()
SOCRATA_APP_TOKEN=os.getenv("SOCRATA_APP_TOKEN")
KAFKA_BOOTSTRAP_SERVER=os.getenv("KAFKA_BOOTSTRAP_SERVER")
KAFKA_TOPIC=os.getenv("KAFKA_TOPIC")

def _callback(err,msg):
    if err is not None:
        print('Error: {}'.format(err))
    else:
        message = 'Topic {} -> value {}\n'.format(msg.topic(), msg.value().decode('utf-8'))
        logger.debug(message)

def request_current_congestion_data() -> list:
    import requests

    headers = {'X-App-Token': SOCRATA_APP_TOKEN}
    url = 'https://data.cityofchicago.org/resource/n4j6-wkkf.json'
    url = url + '?$limit=10000&$order=_last_updt DESC, segmentid ASC'

    response = requests.get(
        url, headers=headers
    )

    return response.json()

def filter_congestion_records_after(records: list, filter_after: datetime) -> list:
    if filter_after is None:
        return records

    filter_after_chicago = filter_after - timedelta(hours=(7 - (-5)))

    return list(filter(
        lambda record: datetime.fromisoformat(record["_last_updt"][:-2]) > filter_after_chicago,
        records
    ))

def loop(kafka_producer: Producer, kafka_topic: str):
    most_recent_request = None

    while True:
        records = request_current_congestion_data()
        logger.info(f"Requested {len(records)} from Socrata API")

        records = filter_congestion_records_after(records, most_recent_request)
        filtered_count = len(records)
        logger.info(f"{filtered_count} remaining after filter condition {most_recent_request}")

        for record in records:
            send = json.dumps(record)

            kafka_producer.poll(0)
            kafka_producer.produce(kafka_topic, send.encode('utf-8'), callback=_callback)
            # kafka_producer.flush()

        kafka_producer.flush()

        if filtered_count != 0:
            most_recent_request = datetime.now()
            logger.info(f"Checkpoint changed to {most_recent_request}")

        # Do request every 5 minutes
        print("Pausing for 5 minutes")
        time.sleep(5 * 60)
        print("Continue")

if __name__ == "__main__":

    logging.basicConfig(format='%(asctime)s %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S',
                        filename='producer.log',
                        filemode='w')
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)

    p = Producer({
        'bootstrap.servers': KAFKA_BOOTSTRAP_SERVER
    })

    print('Kafka Producer has been initiated...')

    loop(p, KAFKA_TOPIC)


import itertools
import sys
import time
import random
import math
import pygame

from pygame.locals import *
from MyLibrary import *

def calc_velocity(direction, vel=1.0):
    velocity = Point(0,0)
    if direction == 0: #north
        velocity.y = -vel
    elif direction == 2: #east
        velocity.x = vel
    elif direction == 4: #south
        velocity.y = vel
    elif direction == 6: # west
        velocity.x = -vel
    return velocity

def be_bound():
    if player.X < 0:
        player.X = 0
    elif player.X > 700:
        player.X = 700
    if player.Y < 0:
        player.Y = 0
    elif player.Y > 500:
        player.Y = 500

def move_player():
    player.X += player.velocity.x
    player.Y += player.velocity.y

def reverse_direction(sprite):
    if sprite.direction == 0:
        sprite.direction = 4
    elif sprite.direction == 2:
        sprite.direction = 6
    elif sprite.direction == 4:
        sprite.direction = 0
    elif sprite.direction == 6:
        sprite.direction = 2

def draw_energy_bar():
    pygame.draw.rect(screen, (50,150,50), Rect(300,570,player_health*2,25))
    pygame.draw.rect(screen, (100,200,100), Rect(300,570,200,25), 2)

def update_player():
    player.first_frame = player.direction * player.colums
    player.last_frame = player.first_frame + player.colums - 1
    if player.frame < player.first_frame:
        player.frame = player.first_frame
        pass
    if not player_moving:
        #stop animating when player is not pressing a key
        player.frame = player.first_frame = player.last_frame
    else:
        #move player in direction
        player.velocity = calc_velocity(player.direction, 1.5)
        player.velocity.x *= 1.5
        player.velocity.y *= 1.5

    #manually move the player
    if player_moving:
        move_player()
        be_bound()
    player_group.update(ticks, 50)

def add_health():
    global health_group
    health = MySprite()
    health.load("health.png", 32, 32, 1)
    health.position = random.randint(0,700),random.randint(0,500)
    health_group.add(health)

def add_zombie_to_group():
    global zombie_group
    zombie = MySprite()
    zombie.load("zombie walk.png", 96, 96, 8)
    zombie.position = random.randint(0,700), random.randint(0,500)
    zombie.direction = random.randint(0,3) * 2
    zombie_group.add(zombie)

def add_fire():
    global fire_group
    arrow_image = pygame.image.load("flame.png").convert_alpha()
    width,height = arrow_image.get_size()
    arrow_image = pygame.transform.smoothscale(arrow_image, (width//2,height//2))

    vel = 5
    if player.direction == 0:
        arrow_image = pygame.transform.rotate(arrow_image, 270)
        fire_velocity = Point(0,-vel)
    elif player.direction == 2:
        arrow_image = pygame.transform.rotate(arrow_image, 180)
        fire_velocity = Point(vel,0)
    elif player.direction == 4:
        arrow_image = pygame.transform.rotate(arrow_image, 90)
        fire_velocity = Point(0,vel)
    elif player.direction == 6:
        fire_velocity = Point(-vel,0)

    width,height = arrow_image.get_size()

    arrow = MySprite()
    arrow.load_image(arrow_image, width, height, 1)
    arrow.fire_velocity = fire_velocity
    #arrow.load("flame.png", 40, 16, 1)
    arrow.X = player.X + player.frame_width//2
    arrow.Y = player.Y + player.frame_height//2
    fire_group.add(arrow)

def update_zombie():
    global start_time
    now_time = time.clock()
    seconds = now_time - start_time
    if seconds > 1.0:
        add_zombie_to_group()
        start_time = now_time
    #manually iterate through all the zombies
    for z in zombie_group:
        #set the zombie's animation range
        z.first_frame = z.direction * z.colums
        z.last_frame = z.first_frame + z.colums - 1
        if z.frame < z.first_frame:
            z.frame = z.first_frame

        z.velocity = calc_velocity(z.direction)
        #keep the zombie on the screen
        z.X += z.velocity.x
        z.Y += z.velocity.y
        if z.X < 0 or z.X > 700 or z.Y < 0 or z.Y > 500:
            reverse_direction(z)

    zombie_group.update(ticks, 50)

def check_collistion_zombie():
    #check for collistion with zombies
    attacker = None
    attacker = pygame.sprite.spritecollideany(player, zombie_group)
    global player_health
    if attacker != None:
        #we got a hit, now do a more precise check
        if pygame.sprite.collide_rect_ratio(0.5)(player, attacker):
            player_health -= 10
            if attacker.X < player.X:
                attacker.X -= 10
            elif attacker.X > player.X:
                attacker.X += 10
        else:
            attacker = None

def check_collistion_fire():
    pygame.sprite.groupcollide(fire_group, zombie_group, True, True)

def update_health():
    health_group.update(ticks, 50)
    #check for collistion with health
    global player_health
    healther = None
    healther = pygame.sprite.spritecollideany(player, health_group)
    if healther != None:
        if pygame.sprite.collide_rect_ratio(0.5)(player, healther):
            player_health += 10
            if player_health > 100 : player_health = 100
            healther.X = random.randint(0,700)
            healther.Y = random.randint(0,500)

def update_fire():
    fire_group.update(ticks, 50)

    for fire in fire_group:
        #fire.velocity = calc_velocity(fire.direction,0.5)
        fire.X += fire.fire_velocity.x
        fire.Y += fire.fire_velocity.y
        if fire.X < 0 or fire.X > 700 or fire.Y < 0 or fire.Y > 500:
            fire_group.remove(fire)

#main program begins
pygame.init()
pygame.display.set_caption("Zombie Mob Game")
screen = pygame.display.set_mode((800,600))
font = pygame.font.Font(None, 36)
timer = pygame.time.Clock()

#create sprite groups
player_group = pygame.sprite.Group()
zombie_group = pygame.sprite.Group()
health_group = pygame.sprite.Group()
fire_group = pygame.sprite.Group()

#create player sprite
player = MySprite()
player.load("farmer walk.png", 96, 96, 8)
player.position = 80,80
player.direction = 4
player_group.add(player)

#create health sprite
for n in range(0,3):
    add_health()

player_moving = False
game_over = False
player_health = 100
start_time = time.clock()

#create zombie sprite
zombie_image = pygame.image.load("zombie walk.png").convert_alpha()
for n in range(0, 10):
    add_zombie_to_group()

while True:
    timer.tick(30)
    ticks = pygame.time.get_ticks()

    for event in pygame.event.get():
        if event.type == QUIT:
            sys.exit()
        elif event.type == KEYUP:
            if event.key == K_SPACE:
                if not game_over:
                    add_fire()
    keys = pygame.key.get_pressed()
    if keys[K_ESCAPE]:
        sys.exit()
    elif keys[K_UP] or keys[K_w]:
        player.direction = 0
        player_moving = True
    elif keys[K_RIGHT] or keys[K_d]:
        player.direction = 2
        player_moving = True
    elif keys[K_DOWN] or keys[K_s]:
        player.direction = 4
        player_moving = True
    elif keys[K_LEFT] or keys[K_a]:
        player.direction = 6
        player_moving = True
    else:
        player_moving = False

    if not game_over:
        update_player()
        update_zombie()
        check_collistion_zombie()
        update_health()
        update_fire()
        check_collistion_fire()

    if player_health <= 0:
        game_over = True

    screen.fill((50,50,100))

    player_group.draw(screen)
    zombie_group.draw(screen)
    health_group.draw(screen)
    fire_group.draw(screen)

    #draw energy bar
    draw_energy_bar()

    if game_over:
        print_text(font, 300, 100, "G A M E  O V E R")

    pygame.display.update()


import numpy as np
import tensorflow

import matplotlib.pyplot as plt
from tensorflow import keras
print(tensorflow.__version__)
print(keras.__version__)
from tensorflow.keras.datasets import cifar10
(x_train,y_train), (x_test,y_test) = cifar10.load_data()
from tensorflow.keras.models import Sequential
from tensorflow.keras.optimizers import RMSprop
from tensorflow.keras.layers import Convolution2D, MaxPool2D, Flatten, Dense, Dropout, BatchNormalization
from tensorflow.keras import regularizers
from tensorflow.keras.utils import to_categorical

gpus = tensorflow.config.experimental.list_physical_devices('GPU')
if gpus:
  try:
    for gpu in gpus:
      tensorflow.config.experimental.set_memory_growth(gpu, True)
  except RuntimeError as e:
    print(e)

model = Sequential([
   Convolution2D(filters=128, kernel_size=(5,5), input_shape=(32,32,3), activation='relu', padding='same'),
   BatchNormalization(),
   Convolution2D(filters=128, kernel_size=(5,5), activation='relu', padding='same'),
   BatchNormalization(),
   MaxPool2D((2,2)),
   Convolution2D(filters=64, kernel_size=(5,5), activation='relu', padding='same'),
   BatchNormalization(),
   Convolution2D(filters=64, kernel_size=(5,5), activation='relu', padding='same'),
   BatchNormalization(),
   MaxPool2D((2,2)),
   Convolution2D(filters=32, kernel_size=(5,5), activation='relu', padding='same'),
   BatchNormalization(),
   Convolution2D(filters=32, kernel_size=(5,5), activation='relu', padding='same'),
   BatchNormalization(),
   MaxPool2D((2,2)),
   Convolution2D(filters=16, kernel_size=(3,3), activation='relu', padding='same'),
   BatchNormalization(),
   Convolution2D(filters=16, kernel_size=(3,3), activation='relu', padding='same'),
   BatchNormalization(),
   Flatten(),
   Dense(units=32, activation="relu"),
   Dropout(0.15),
   Dense(units=16, activation="relu"),
   Dropout(0.05),
   Dense(units=10, activation="softmax")
])
optim = RMSprop(lr=0.001)
model.compile(optimizer=optim, loss='categorical_crossentropy', metrics=['accuracy'])

#model = keras.models.load_model(r'C:\Users\Student240914\Desktop\PycharmProjects\keylogger\Praca')
from tensorflow.keras.preprocessing.image import ImageDataGenerator

datagen = ImageDataGenerator(
    rotation_range=10,
    horizontal_flip=True,
    vertical_flip = False,
    width_shift_range=0.1,
    height_shift_range=0.1,
    rescale = 1. / 255,
    shear_range=0.05,
    zoom_range=0.05,
)
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)

batch_size = 32
train_generator = datagen.flow(x_train, y_train, batch_size=batch_size)
datagen_valid = ImageDataGenerator(
   rescale = 1. / 255,)

x_valid = x_train[:100*batch_size]
y_valid = y_train[:100*batch_size]

valid_steps = x_valid.shape[0] // batch_size
validation_generator = datagen_valid.flow(x_valid, y_valid, batch_size=batch_size)

history = model.fit(
   train_generator,
   steps_per_epoch=len(x_train) // batch_size,
   epochs=50,
   validation_data=validation_generator,
   validation_freq=1,
   validation_steps=valid_steps,
   verbose=2
)
model.save(r'C:\Users\Student240914\Desktop\PycharmProjects\keylogger\Praca\Model_cifar_10')

plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('Model accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['Train', 'Valid'], loc='upper left')
plt.show()

x_final_test = x_test / 255.0
eval = model.evaluate(x_final_test, y_test)


# This more efficient program counts up or counts down depending on which button is clicked

from tkinter import *
from functools import partial

root =Tk()
root.title("Counting")

def change_number(change):
    """ This function changes the number and prints it. """

    global number
    number += change
    print(number)

# setting the starting value
number = 0

values = [1, -1]

# add butons
for value in values:
    textdisplay = "Change by "+str(value)
    button = Button(root, text=textdisplay, command=partial(change_number,value)).grid()

root.mainloop()


import time

def part1(grid):
    risk = 0
    for i in range(len(grid)):
        for j in range(len(grid)):
            if i == 0 and j == 0:
                continue
            elif i > 0 and grid[i][j] >= grid[i-1][j]:
                continue
            elif i < len(grid) - 1 and grid[i][j] >= grid[i+1][j]:
                continue
            elif j > 0 and grid[i][j] >= grid[i][j-1]:
                continue
            elif j < len(grid[0]) - 1 and grid[i][j] >= grid[i][j+1]:
                continue
            else:
                risk += grid[i][j] + 1
    print(risk)

def depth_first_search(grid, visited, i, j):
    node = (i, j)
    if i < 0 or j < 0 or i >= len(grid) or j >= len(grid[0]):
        return
    if node in visited or grid[i][j] == 9:
        return
    visited.add(node)
    depth_first_search(grid, visited, i-1, j)
    depth_first_search(grid, visited, i+1, j)
    depth_first_search(grid, visited, i, j-1)
    depth_first_search(grid, visited, i, j+1)

def part2(grid):
    visited = set()
    basins = []
    for i in range(len(grid)):
        for j in range(len(grid)):
            if (i, j) not in visited and grid[i][j] != 9:
                previous_node = len(visited)
                depth_first_search(grid, visited, i, j)
                basins.append(len(visited) - previous_node)
    basins.sort()
    print(basins[-1] * basins[-2] * basins[-3])

def main():
    grid = [[int(y) for y in x] for x in open('./Input/Day9.txt').read().strip().split('\n')]
    part1(grid)
    part2(grid)

if __name__ == "__main__":
    start_time = time.time()
    main()
    print("--- %s seconds ---" % (time.time() - start_time))


from pmlb import fetch_data

import numpy as np

from standardgp import GP

def get_data(dataset_name) -> np.ndarray:
    # data from https://github.com/EpistasisLab/pmlb
    data = fetch_data(dataset_name, local_cache_dir="./datasets")
    y = data["target"].to_numpy()
    x = []
    for i, key in enumerate(data):
        if key == "target":
            continue
        x.append(data[key].to_numpy())
    return np.array(x).T, y

if __name__ == "__main__":
    GP.seed(149)
    # example for regression tasks
    # see all regression datasets available at:
    # https://epistasislab.github.io/pmlb/
    x, y = get_data("579_fri_c0_250_5")
    gp = GP(x[::2, :], y[::2])  # half of the data to train
    error, model = gp.run(show=True, threads=8)
    print("Error: {}, Model: {}".format(error, model))
    print("RMSE train:", np.sqrt(np.mean(np.square(gp.predict(x) - y))))
    x, y = x[1::2, :], y[1::2]  # rest of the data to test on unknown data
    print("RMSE test:", np.sqrt(np.mean(np.square(gp.predict(x) - y))))


from argparse import ArgumentError
import logging
from pathlib import Path
from typing import Union
import zarr
import numpy as np
from db.file_system.models import FileSystemVolumeMedatada
from db.file_system.constants import ANNOTATION_METADATA_FILENAME, GRID_METADATA_FILENAME
from preprocessor.src.preprocessors.i_data_preprocessor import IDataPreprocessor
from preprocessor.src.preprocessors.implementations.sff.preprocessor._zarr_methods import get_volume_downsampling_from_zarr, get_segmentation_downsampling_from_zarr
from preprocessor.src.preprocessors.implementations.sff.preprocessor.constants import MESH_SIMPLIFICATION_CURVE_LINEAR, MESH_SIMPLIFICATION_N_LEVELS, MESH_SIMPLIFICATION_LEVELS_PER_ORDER, TEMP_ZARR_HIERARCHY_STORAGE_PATH
from preprocessor.src.tools.magic_kernel_downsampling_3d.magic_kernel_downsampling_3d import MagicKernel3dDownsampler
import mrcfile
import dask.array as da
import math

def open_zarr_structure_from_path(path: Path) -> zarr.hierarchy.Group:
    store: zarr.storage.DirectoryStore = zarr.DirectoryStore(str(path))
    # Re-create zarr hierarchy from opened store
    root: zarr.hierarchy.group = zarr.group(store=store)
    return root

class SFFPreprocessor(IDataPreprocessor):
    from ._hdf5_to_zarr import hdf5_to_zarr
    from ._volume_map_methods import normalize_axis_order_mrcfile
    from ._process_X_data_methods import process_volume_data, process_segmentation_data
    from ._metadata_methods import temp_save_metadata, extract_annotations, extract_metadata

    def __init__(self, temp_zarr_hierarchy_storage_path: Path):
        if not temp_zarr_hierarchy_storage_path:
            raise ArgumentError('No temp_zarr_hierarchy_storage_path is provided')
        # path to root of temporary storage for zarr hierarchy
        self.temp_root_path = temp_zarr_hierarchy_storage_path
        self.magic_kernel = MagicKernel3dDownsampler()
        self.temp_zarr_structure_path = None

    def preprocess(self, segm_file_path: Path, volume_file_path: Path, params_for_storing: dict, volume_force_dtype: Union[np.dtype, None], entry_id: str,
        source_db_id: str,
        source_db_name: str
        ):
        '''
        Returns path to temporary zarr structure that will be stored permanently using db.store
        '''
        try:
            if segm_file_path is not None:
                self.temp_zarr_structure_path = SFFPreprocessor.hdf5_to_zarr(self.temp_root_path, segm_file_path, entry_id)
            else:
                self.__init_empty_zarr_structure(volume_file_path)
            # Re-create zarr hierarchy
            zarr_structure: zarr.hierarchy.group = open_zarr_structure_from_path(
                self.temp_zarr_structure_path)

            # read map
            with mrcfile.mmap(str(volume_file_path.resolve())) as mrc_original:
                data: np.memmap = mrc_original.data
                if volume_force_dtype is not None:
                    data = data.astype(volume_force_dtype)
                else:
                    volume_force_dtype = data.dtype

                header = mrc_original.header

            if ('quantize_dtype_str' in params_for_storing) and \
                (
                    (volume_force_dtype in (np.uint8, np.int8)) or \
                    ((volume_force_dtype in (np.uint16, np.int16)) and (params_for_storing['quantize_dtype_str'] in ['u2', '|u2', '>u2', '<u2'] ))
                ):
                print(f'Quantization is skipped because input volume dtype is {volume_force_dtype} and requested quantization dtype is {params_for_storing["quantize_dtype_str"]}')
                del params_for_storing['quantize_dtype_str']

            print(f"Processing volume file {volume_file_path}")
            dask_arr = da.from_array(data)
            # print('shape', dask_arr.shape)
            # print('crs', int(header.mapc) - 1, int(header.mapr) - 1, int(header.maps) - 1)
            # print('n', int(header.nx), int(header.ny), int(header.nz))

            dask_arr = SFFPreprocessor.normalize_axis_order_mrcfile(dask_arr=dask_arr, mrc_header=header)
            # print('after', dask_arr.shape)

            print(f"Processing segmentation file {segm_file_path}")
            # mesh_simplification_curve = MESH_SIMPLIFICATION_CURVE_LINEAR
            mesh_simplification_curve = make_simplification_curve(MESH_SIMPLIFICATION_N_LEVELS, MESH_SIMPLIFICATION_LEVELS_PER_ORDER)
            if segm_file_path is not None:
                SFFPreprocessor.process_segmentation_data(self.magic_kernel, zarr_structure, mesh_simplification_curve, params_for_storing=params_for_storing)

            SFFPreprocessor.process_volume_data(zarr_structure=zarr_structure, dask_arr=dask_arr, params_for_storing=params_for_storing, force_dtype=volume_force_dtype)

            grid_metadata = SFFPreprocessor.extract_metadata(
                zarr_structure,
                mrc_header=header,
                mesh_simplification_curve=mesh_simplification_curve,
                volume_force_dtype=volume_force_dtype,
                source_db_id=source_db_id,
                source_db_name=source_db_name
            )

            # grid_dimensions: list = list(FileSystemVolumeMedatada(grid_metadata).grid_dimensions())
            # zarr_volume_arr_shape: list = list(get_volume_downsampling_from_zarr(1, zarr_structure).shape)
            # if segm_file_path is not None and zarr_structure.primary_descriptor[0] == b'three_d_volume':
            #     zarr_segm_arr_shape: list = list(get_segmentation_downsampling_from_zarr(1, zarr_structure, 0).shape)
            #     assert grid_dimensions == zarr_segm_arr_shape, \
            #     f'grid dimensions from metadata {grid_dimensions} are not equal to segmentation arr shape {zarr_segm_arr_shape}'
            # assert grid_dimensions == zarr_volume_arr_shape, \
            #         f'grid dimensions from metadata {grid_dimensions} are not equal to volume arr shape {zarr_volume_arr_shape}'

            SFFPreprocessor.temp_save_metadata(grid_metadata, GRID_METADATA_FILENAME, self.temp_zarr_structure_path)

            if segm_file_path is not None:
                annotation_metadata = SFFPreprocessor.extract_annotations(segm_file_path)
                SFFPreprocessor.temp_save_metadata(annotation_metadata, ANNOTATION_METADATA_FILENAME, self.temp_zarr_structure_path)
        except Exception as e:
            logging.error(e, stack_info=True, exc_info=True)
            raise e

        return self.temp_zarr_structure_path

    def __init_empty_zarr_structure(self, volume_file_path: Path):
        '''
        Creates EMPTY temp zarr structure for the case when just volume file is provided
        '''
        self.temp_zarr_structure_path = self.temp_root_path / volume_file_path.stem
        try:
            assert self.temp_zarr_structure_path.exists() == False, \
                f'temp_zarr_structure_path: {self.temp_zarr_structure_path} already exists'
            store: zarr.storage.DirectoryStore = zarr.DirectoryStore(str(self.temp_zarr_structure_path))
        except Exception as e:
            logging.error(e, stack_info=True, exc_info=True)
            raise e

def make_simplification_curve(n_levels: int, levels_per_order: int) -> dict[int, float]:
    result = {}
    for i in range(n_levels):
        ratio = 10 ** (-i / levels_per_order)
        result[i + 1] = _round_to_significant_digits(ratio, 2)
    return result

def _round_to_significant_digits(number: float, digits: int) -> float:
    first_digit = -math.floor(math.log10(number))
    return round(number, first_digit + digits - 1)


__all__ = ('UIKit', 'ObjCClass', 'objc_method', 'from_value', 'to_value',
           'NSObject', 'NSString', 'NSArray', 'NSDictionary',
           'UIResponder', 'UIScreen', 'UIView', 'UIViewController', 'UIWindow',
           'UINavigationController', 'UITableViewController')

from ctypes import cdll, c_int, c_void_p, util
from rubicon.objc import ObjCClass, objc_method
from rubicon.objc.core_foundation import from_value, to_value

UIKit = cdll.LoadLibrary(util.find_library('UIKit'))
UIKit.UIApplicationMain.restypes = (c_int, c_void_p, c_void_p,
                                    c_void_p)
UIKit.UIApplicationMain.restype = c_int

for item in __all__:
    if item not in globals():
        globals()[item] = ObjCClass(item)


import json
import unittest
from io import StringIO
from unittest.mock import MagicMock
from unittest.mock import patch

from tr.parsers.csv_parser import CSVParser

class TestXMLParser(unittest.TestCase):

    @patch('os.path.exists')
    @patch('tr.parsers.csv_parser.open')
    def test_read(self, mock_open: MagicMock, mock_exists: MagicMock):
        mock_exists.return_value = True
        mock_open.return_value.__enter__.side_effect = [StringIO("""
"id","name","address","phone","date"
"ID5410","Melissa T Miller","2837  Fidler Drive","210-624-7306","31/01/2020"
"ID9857","Daniel I Walker","3853  Hilltop Street","413-655-7397","25/04/2020"
""".strip()),
StringIO(r"""
"id","make","vin_number","owner_id"
"V3015","Chevrolet","1HGFA16548L016469","ID9857"
"V2014","Honda","1G6KD57Y46U180996","ID9857"
"V1475","Ford","2HKYF18575H574967","ID5410"
""".strip())]
        parser = CSVParser()
        parser.read(('csv/customers.csv', 'csv/vehicles.csv'))
        expected_data = [{
            "file_name": "csv/customers.csv",
            "transaction": {
                "date": "31/01/2020",
                "customer": {
                    "id": "ID5410",
                    "name": "Melissa T Miller",
                    "address": "2837  Fidler Drive",
                    "phone": "210-624-7306"
                },
                "vehicles": [
                    {
                        "id": "V1475",
                        "make": "Ford",
                        "vin_number": "2HKYF18575H574967"
                    }]
            }
        }, {
            "file_name": "csv/customers.csv",
            "transaction": {
                "date": "25/04/2020",
                "customer": {
                    "id": "ID9857",
                    "name": "Daniel I Walker",
                    "address": "3853  Hilltop Street",
                    "phone": "413-655-7397"
                },
                "vehicles": [
                    {
                        "id": "V3015",
                        "make": "Chevrolet",
                        "vin_number": "1HGFA16548L016469"
                    },
                    {
                        "id": "V2014",
                        "make": "Honda",
                        "vin_number": "1G6KD57Y46U180996"
                    }
                ]
            }
        }
        ]

        actual_data = parser.data
        self.assertEqual(json.dumps(expected_data), json.dumps(actual_data))


#recursive

class Tree:
    def __init__(self,value):
        self.val = value
        self.left = None
        self.right = None
def validate_bst(root,low = float('-inf'),high = float('inf')):

    if not root:
        return True

    value = root.val

    if value <= low or value >= high:
        return False

    if not validate_bst(root.left,low,value):
        return False

    if not validate_bst(root.right,value,high):
        return False

    return True

root = Tree(12)

print(validate_bst(root))

#iterative

#Inorder

def validate_bst_itr(root):
    stack = []
    prev = float('-inf')
    while stack or root:
        if root:
            stack.append(root)
            root = root.left
        elif stack:
            root  = stack.pop()

            if not root.val > prev:
                return False
            root = root.right
    return True


from flask import Flask, request,jsonify #import main Flask class and request object
import subprocess
import hid
import time
from commands import *
from usb_comm import *
#import Tkinter as tk
import pandas as pd
import math

app = Flask(__name__) #create the Flask app

@app.route('/postData',methods=['POST','GET'])
def sensor():

    set_active_config(0)
    get_scan_config_id()

    start_scan(0) # donot store in sd card

    results = get_results() # get scan results
    ref_scan = get_ref_data() # get reference values

    # Convert the results into a dataframe

    values = {"wavelength":results["wavelength"],"intensity":results["intensity"],"reference":ref_scan["intensity"]}
    df = pd.DataFrame(values)
    df = df[(df[['wavelength','intensity']] > 0).all(axis=1)].reset_index() # drop values of 0 or less
    df['reflectance'] = df['intensity']/df['reference'] #reflectance = sample/reference
    df['absorption'] = -(np.log10(df['reflectance']))#absorption = -log(reflectance)

    final_out=df.to_json(orient='records')
    return final_out

if __name__ == '__main__':
    a= 0x0451
    b = 0x4200

    setup(a,b)
    time.sleep(1)
    app.run(port=5000)


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

from django.db import models, migrations

class Migration(migrations.Migration):

    dependencies = [
        ('f_info', '0001_initial'),
        ('f_user', '__first__'),
        ('f_order', '0001_initial'),
    ]

    operations = [
        migrations.CreateModel(
            name='Evaluate',
            fields=[
                ('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)),
                ('value', models.CharField(max_length=300)),
                ('date', models.DateTimeField(auto_now=True)),
                ('efruit', models.ForeignKey(to='f_info.FruInfo')),
                ('euser', models.ForeignKey(to='f_user.UserInfo')),
            ],
        ),
    ]


import sys
from PIL import Image
import argparse
import math

def image_dimensions(x):
    output = []
    for i in range(1, x + 1):
        if x % i == 0:
            output.append(i)
    center = output[len(output)//2]
    return (x//center, center)

def convertImageToBinary(args):
    image = Image.open(args.image)
    imageData = image.tobytes()
    return imageData

def convertBinToImage(args):
    with open(args.binary, "rb") as f:
        binaryCollections = f.read()
    if not args.fullColour:
        print("Using single colour")
        dimensions =  image_dimensions(len(binaryCollections))
        image = Image.frombytes('L',dimensions,binaryCollections)
    else:
        print("Using colour")
        dimensions =  image_dimensions(int(len(binaryCollections)/3))
        print(dimensions)
        image = Image.frombytes('RGB',dimensions,binaryCollections)
    return image

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("binary", help="The path to the binary/data")
    parser.add_argument("image", help="The path to the image")
    parser.add_argument("output", help="The direction to convert the data (Either: 'image' or 'binary')")
    parser.add_argument("-rgb","--fullColour",action="store_true",required=False,help="Store the data in the colour bands, not just greyscale",dest="fullColour")
    args = parser.parse_args()

    if args.output == "image":
        output = convertBinToImage(args)
        output.save(args.image)
    elif args.output == "binary":
        output = convertImageToBinary(args)
        with open(args.binary,"wb+") as f:
            f.write(output)

    else:
        print("Unknown arg for output: ",args.output)

if __name__ == '__main__':
    main()


import math
from conf import conf

def polar_to_rect(a, c):
    b = conf['width']
    gamma = math.acos((a*a+b*b-c*c)/(2.0*a*b))
    y = math.sin(gamma) * a
    x = math.cos(gamma) * a
    return(x,y)

def rect_to_polar(x,y):
    width = conf['width']
    l = math.sqrt(pow(x,2)+pow(y,2))
    r = math.sqrt(pow((width-x),2)+pow(y,2))
    return(l,r)


import tensorflow as tf

class ModelConfig():
    u_hidden_sizes = [2048, 1024]
    v_hidden_sizes = [2048, 1024]
    loss_weights = [1.0, 0.1] # weights for: reconstruction loss, boundary loss
    dropout_keep_prob = 0.2
    use_bn = True
    activation_fn = 'relu'
    base_lambda_ = 0.1
    anneal_rate = 1.015
    # discretization parameters
    bs = [1.5,2.5,3.5,4.5]      # b_v in eq.(5)
    qs = [1.0,2.0,3.0,4.0,5.0]  # q_v in eq.(5)
    Is = [1.0,2.0,3.0,4.0]      # I_v in eq.(5)
    Delta = 1.0     # \Delta in eq.(5))

class TrainConfig(object):
    """Sets the default training hyperparameters."""
    batch_size_x = 300
    batch_size_y = 200
    optimizer = "adam" # "SGD", "momentum", "adam", "adadelta", "rmsprop"

    initial_lr = 1e-2 # initial learning rate
    lr_decay_factor = 0.65
    num_epochs_per_decay = 50
    weight_decay = 0.0

    sigmoid_schedule = 'exp' # 'step'
    write_summary = False

def arr_to_string(arr):
    for i in xrange(len(arr)):
        arr[i] = str(arr[i])
    return ','.join(arr)

# model configs
tf.flags.DEFINE_string('u_hidden_sizes', arr_to_string(ModelConfig.u_hidden_sizes),'')
tf.flags.DEFINE_string('v_hidden_sizes', arr_to_string(ModelConfig.v_hidden_sizes),'')
tf.flags.DEFINE_string('loss_weights', arr_to_string(ModelConfig.loss_weights),'')
tf.flags.DEFINE_float('dropout_keep_prob', ModelConfig.dropout_keep_prob,'')
tf.flags.DEFINE_boolean('use_bn', ModelConfig.use_bn,'')
tf.flags.DEFINE_string('activation_fn', ModelConfig.activation_fn,'')
tf.flags.DEFINE_float('base_lambda_', ModelConfig.base_lambda_,'')
tf.flags.DEFINE_float('anneal_rate', ModelConfig.anneal_rate,'')
tf.flags.DEFINE_string('bs', arr_to_string(ModelConfig.bs),'')
tf.flags.DEFINE_string('qs', arr_to_string(ModelConfig.qs),'')
tf.flags.DEFINE_string('Is', arr_to_string(ModelConfig.Is),'')
tf.flags.DEFINE_float('Delta', ModelConfig.Delta,'')

# training configs
tf.flags.DEFINE_integer('batch_size_x', TrainConfig.batch_size_x,'')
tf.flags.DEFINE_integer('batch_size_y', TrainConfig.batch_size_y,'')
tf.flags.DEFINE_string('optimizer', TrainConfig.optimizer,'')
tf.flags.DEFINE_float('initial_lr', TrainConfig.initial_lr,'')
tf.flags.DEFINE_float('lr_decay_factor', TrainConfig.lr_decay_factor,'')
tf.flags.DEFINE_integer('num_epochs_per_decay', TrainConfig.num_epochs_per_decay,'')
tf.flags.DEFINE_float('weight_decay', TrainConfig.weight_decay,'')
tf.flags.DEFINE_string('sigmoid_schedule', TrainConfig.sigmoid_schedule,'')
tf.flags.DEFINE_boolean('write_summary', TrainConfig.write_summary,'')

CONFIGS = tf.app.flags.FLAGS


#!/usr/bin/env python
#DOC: https://www.rabbitmq.com/tutorials/tutorial-six-python.html

import pika
from time import sleep
from random import randint

connection = pika.BlockingConnection(pika.ConnectionParameters(
        host='localhost'))

channel = connection.channel()

#por aqui te entran los mensajes
channel.queue_declare(queue='rpc_queue')

def fib(n):
    if n == 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fib(n-1) + fib(n-2)

#props son las pripiedades. Aqui tiene de nuevo:
#   correlation_id (lo que identifica al mensaje)
#   routing_key (la cola donde mandas de vuelta la respuesta)
#   ack: pa decir cuando haya llegado

def on_request(ch, method, props, body):
    n = int(body)

    print(" [.] fib(%s)" % n)
    sleep (randint(1,5))
    response = fib(n)

    ch.basic_publish(exchange='',
                     routing_key=props.reply_to,
                     properties=pika.BasicProperties(correlation_id = \
                                                         props.correlation_id),
                     body=str(response))
    ch.basic_ack(delivery_tag = method.delivery_tag)

channel.basic_qos(prefetch_count=1)
channel.basic_consume(on_request, queue='rpc_queue')

print(" [x] Awaiting RPC requests")
channel.start_consuming()


# Standard library imports
import os
import tempfile
from typing import Dict
import unittest

# Third party imports
import numpy as np
import pandas as pd

# Local imports
from mg_nmf.nmf import selection

# Define a test dataset
TEST_DATA: pd.DataFrame = pd.read_csv('data/k2_testdata.csv', index_col=0)

class TestNMFConsensusSelection(unittest.TestCase):
    """Test consensus based selection methods. NMFModelSelection is abstract, so testing the base functions here."""

    sel: selection.NMFConsensusSelection
    data: pd.DataFrame

    @classmethod
    def setUpClass(cls) -> None:
        """Initialise a selection object for our test class to work with, and load some synthetic data."""

        cls.sel = selection.NMFConsensusSelection(
            data=TEST_DATA, k_min=2, k_max=3, solver='mu', beta_loss='frobenius', iterations=10, nmf_max_iter=1000
        )

    def test_run(self):
        """Perform an NMF run on the simple data, check we get the expected outputs."""

        # Run the selection object we set up in the classSetUp
        coph, disp = self.sel.run()
        # Assert that we get two NMFResults objects
        self.assertIsInstance(coph, selection.NMFResults)
        self.assertIsInstance(disp, selection.NMFResults)

    def test_properties(self):
        """Set properties, and check they get changed or throw exceptions as expected. These are base class properties,
        don't need to be tested in other subclasses."""

        # Create a new object to mess with it's properties
        sel: selection.NMFConsensusSelection = selection.NMFConsensusSelection(
            data=TEST_DATA, k_min=2, k_max=3, solver='mu', beta_loss='frobenius', iterations=10, nmf_max_iter=1000
        )

        # Metrics
        with self.assertRaises(Exception, msg='Setting metric to invalid value should raise exception'):
            sel.metric = 'coph'
        sel.metric = 'cophenetic'
        self.assertEqual(sel.metric, 'cophenetic')

        # Solvers
        with self.assertRaises(Exception, msg='Setting solver to invalid value should raise exception'):
            sel.solver = 'magic'
        sel.solver = 'cd'
        self.assertEqual(sel.solver, 'cd')

        # Beta-loss
        with self.assertRaises(Exception, msg='Setting beta-loss to invalid value should raise exception'):
            sel.beta_loss = 'magic'
        sel.beta_loss = 'kullback-leibler'
        self.assertEqual(sel.beta_loss, 'kullback-leibler')

        # k min/max
        # Should refuse values which are too low
        prev_kmin: int = sel.k_min
        sel.k_min = 1
        self.assertEqual(sel.k_min, prev_kmin)
        sel.k_min = -3
        self.assertEqual(sel.k_min, prev_kmin)
        # Max canot be lower than min
        sel.k_min = 4
        sel.k_max = 3
        # Max cannot be changed to lower than min
        self.assertEqual(sel.k_max, sel.k_min)
        sel.k_max = 10
        self.assertEqual(sel.k_max, 10)
        # Ensure iterations cannot be below 1
        sel.iterations = -100
        self.assertEqual(sel.iterations, 1)
        # Ensure nmf_max_iter cannot be below 0, should reset to default
        sel.nmf_max_iter = 0
        self.assertEqual(sel.nmf_max_iter, sel.DEF_NMF_MAX_ITER)

class TestNMFConcordanceSelection(unittest.TestCase):
    """Test Jiang stability based selection methods."""

    sel: selection.NMFConcordanceSelection
    data: pd.DataFrame

    @classmethod
    def setUpClass(cls) -> None:
        """Initialise a selection object for our test class to work with, and load some synthetic data."""

        cls.sel = selection.NMFConcordanceSelection(
            data=TEST_DATA, k_min=2, k_max=3, solver='mu', beta_loss='frobenius', iterations=10, nmf_max_iter=1000
        )

    def test_run(self):
        """Perform an NMF run on the simple data, check we get the expected outputs."""

        # Run the selection object we set up in the classSetUp
        jiang = self.sel.run()
        # Assert that we get two NMFResults objects
        self.assertIsInstance(jiang, selection.NMFResults)

class TestNMFSplitHalfSelection(unittest.TestCase):
    """Test split half based selection methods."""

    sel: selection.NMFSplitHalfSelection
    data: pd.DataFrame

    @classmethod
    def setUpClass(cls) -> None:
        """Initialise a selection object for our test class to work with, and load some synthetic data."""

        cls.sel = selection.NMFSplitHalfSelection(
            data=TEST_DATA, k_min=2, k_max=3, solver='mu', beta_loss='frobenius', iterations=10, nmf_max_iter=1000
        )

    def test_run(self):
        """Perform an NMF run on the simple data, check we get the expected outputs."""

        # Run the selection object we set up in the classSetUp
        ari = self.sel.run()
        # Assert that we get two NMFResults objects
        self.assertIsInstance(ari, selection.NMFResults)

class TestNMFPermutationSelection(unittest.TestCase):
    """Test permutation based selection methods."""

    sel: selection.NMFPermutationSelection
    data: pd.DataFrame

    @classmethod
    def setUpClass(cls) -> None:
        """Initialise a selection object for our test class to work with, and load some synthetic data."""

        cls.sel = selection.NMFPermutationSelection(
            data=TEST_DATA, k_min=2, k_max=3, solver='mu', beta_loss='frobenius', iterations=10, nmf_max_iter=1000
        )

    def test_run(self):
        """Perform an NMF run on the simple data, check we get the expected outputs."""

        # Run the selection object we set up in the classSetUp
        kprop = self.sel.run()
        # Assert that we get two NMFResults objects
        self.assertIsInstance(kprop, selection.NMFResults)

class TestNMFImputationSelection(unittest.TestCase):
    """Test Jiang stability based selection methods."""

    sel: selection.NMFImputationSelection
    data: pd.DataFrame

    @classmethod
    def setUpClass(cls) -> None:
        """Initialise a selection object for our test class to work with, and load some synthetic data."""

        cls.sel = selection.NMFImputationSelection(
            data=TEST_DATA, k_min=2, k_max=3, solver='mu', beta_loss='frobenius', iterations=10, nmf_max_iter=1000,
            p_holdout=0.1, metric='both'
        )

    def test_run(self):
        """Perform an NMF run on the simple data, check we get the expected outputs."""

        # Run the selection object we set up in the classSetUp
        mse, mad = self.sel.run()
        # Assert that we get two NMFResults objects
        self.assertIsInstance(mse, selection.NMFResults)
        self.assertIsInstance(mad, selection.NMFResults)

class TestNMFMultiSelect(unittest.TestCase):
    """Tests for class which allows running of multiple methods of model selection and returns their results."""

    multi: selection.NMFMultiSelect

    @classmethod
    def setUp(cls) -> None:
        """Intialise a model selection object, to use multiple model selection methods."""

        # TEMP - Testing threading
        import os
        os.environ["OMP_NUM_THREADS"] = "1"  # export OMP_NUM_THREADS=4
        os.environ["OPENBLAS_NUM_THREADS"] = "1"  # export OPENBLAS_NUM_THREADS=4
        os.environ["MKL_NUM_THREADS"] = "1"  # export MKL_NUM_THREADS=6
        os.environ["VECLIB_MAXIMUM_THREADS"] = "1"  # export VECLIB_MAXIMUM_THREADS=4
        os.environ["NUMEXPR_NUM_THREADS"] = "1"  # export NUMEXPR_NUM_THREADS=6
        cls.multi = selection.NMFMultiSelect(
            ranks=(2, 6), iterations=100, nmf_max_iter=1000, solver='mu', beta_loss='frobenius'
        )

    def test_run(self) -> None:
        """Perform model selection using different methods."""

        # Temp - used large test data
        import mg_nmf.nmf.synthdata as synthdata
        large_td = synthdata.sparse_overlap_even((50, 150), 6, 0.1, 0.1, 0.1, (0, 1))
        res: Dict[str, selection.NMFResults] = self.multi.run(large_td, 1)

        # Ensure all methods were run, and returned correct type
        for method in selection.NMFMultiSelect.PERMITTED_METHODS:
            self.assertIn(method, res)
            self.assertIsInstance(res[method], selection.NMFResults)

    def test_properties(self) -> None:
        """Test property changes."""

        # Iterations should throw exception if  < 1
        with self.assertRaises(Exception):
            self.multi.iterations = 0
        with self.assertRaises(Exception):
            self.multi.iterations = -1
        self.multi.iterations = 6
        self.assertEqual(self.multi.iterations, 6)

        # Methods should throw an error if asking for method not in list
        with self.assertRaises(Exception):
            self.multi.methods = ['coph', 'error']
        self.multi.methods = ['coph', 'disp']
        self.assertEqual(self.multi.methods, ['coph', 'disp'])

        # Solver should throw an error if asking for solver not in list
        with self.assertRaises(Exception):
            self.multi.solver = 'error'
        self.multi.solver = 'cd'
        self.assertEqual(self.multi.solver, 'cd')

        # Beta loss should throw an error if asking for function not in list
        with self.assertRaises(Exception):
            self.multi.beta_loss = 'error'
        self.multi.beta_loss = 'kullback-leibler'
        self.assertEqual(self.multi.beta_loss, 'kullback-leibler')

class TestNMFResults(unittest.TestCase):
    """Tests for class which holds results for model selection runs for multiple values of k."""

    sel: selection.NMFConcordanceSelection
    res: selection.NMFResults
    K_FROM: int = 2
    K_TO: int = 4
    ITER: int = 5

    @classmethod
    def setUp(cls) -> None:
        """Run a simple model selection method, to obtain an NMFResults object to work with."""

        cls.sel = selection.NMFConcordanceSelection(
            k_min=cls.K_FROM, k_max=cls.K_TO, iterations=cls.ITER, nmf_max_iter=1000, solver='mu',
            beta_loss='frobenius', data=TEST_DATA
        )
        cls.res = cls.sel.run()

    def test_properties(self) -> None:
        """Ensure properties behave as expected."""

        # Correct number of results returned
        self.assertEqual(len(self.res.results), self.K_TO - self.K_FROM + 1)
        # Check that the selected result does actually have optimal value for selection criteria
        top_metric: float = -np.inf
        top_res: selection.NMFModelSelectionResults
        for res in self.res.results:
            if res.metric >= top_metric:
                top_metric = res.metric
                top_k = res
        self.assertIs(self.res.selected, top_k)

    def test_cophenetic_table(self) -> None:
        """Make sure the table of cophenetic correlation comes out as expected."""

        c_tbl: pd.DataFrame = self.res.measure(None, None)
        # Test has expected length
        self.assertEqual(len(c_tbl.columns), len(self.res.results))
        # Test each value in the table, check matches it's table entry
        for i in range(0, len(self.res.results)):
            res_val: float = self.res.results[i].metric
            tbl_val: float = float(c_tbl.iloc[1,i])
            self.assertAlmostEqual(res_val, tbl_val, places=7)

        # Test both plot and file can be written
        with tempfile.TemporaryDirectory() as tmpdirname:
            plot_f, table_f = os.path.join(tmpdirname, 'tmp_plot.png'), os.path.join(tmpdirname, 'tmp_tbl.csv')
            self.res.measure(plot_f, table_f)
            self.assertTrue(os.path.exists(plot_f))
            self.assertTrue(os.path.exists(table_f))

# TODO: NMFModelSelectionResults, Connectivity Matrix

if __name__ == '__main__':
    unittest.main()


import numpy as np
from unityagents import UnityEnvironment
from model_es import ModelES
import json
from collections import deque
from json import encoder
import termios, fcntl, sys, os
import keyboard
import time
import random
encoder.FLOAT_REPR = lambda o: format(o, '.16f')

def compute_ranks(x):
  """
  Returns ranks in [0, len(x))
  Note: This is different from scipy.stats.rankdata, which returns ranks in [1, len(x)].
  (https://github.com/openai/evolution-strategies-starter/blob/master/es_distributed/es.py)
  """
  assert x.ndim == 1
  ranks = np.empty(len(x), dtype=int)
  ranks[x.argsort()] = np.arange(len(x))
  return ranks

def compute_centered_ranks(x):
  """
  https://github.com/openai/evolution-strategies-starter/blob/master/es_distributed/es.py
  """
  y = compute_ranks(x.ravel()).reshape(x.shape).astype(np.float32)
  y /= (x.size - 1)
  y -= .5
  return y

def compute_weight_decay(weight_decay, model_param_list):
  model_param_grid = np.array(model_param_list)
  return - weight_decay * np.mean(model_param_grid * model_param_grid, axis=1)

# adopted from:
# https://github.com/openai/evolution-strategies-starter/blob/master/es_distributed/optimizers.py

class Optimizer(object):
  def __init__(self, pi, epsilon=1e-08):
    self.pi = pi
    self.dim = pi.num_params
    self.epsilon = epsilon
    self.t = 0

  def update(self, globalg):
    self.t += 1
    step = self._compute_step(globalg)
    theta = self.pi.mu
    ratio = np.linalg.norm(step) / (np.linalg.norm(theta) + self.epsilon)
    self.pi.mu = theta + step
    return ratio

  def _compute_step(self, globalg):
    raise NotImplementedError

class BasicSGD(Optimizer):
  def __init__(self, pi, stepsize):
    Optimizer.__init__(self, pi)
    self.stepsize = stepsize

  def _compute_step(self, globalg):
    step = -self.stepsize * globalg
    return step

class SGD(Optimizer):
  def __init__(self, pi, stepsize, momentum=0.9):
    Optimizer.__init__(self, pi)
    self.v = np.zeros(self.dim, dtype=np.float32)
    self.stepsize, self.momentum = stepsize, momentum

  def _compute_step(self, globalg):
    self.v = self.momentum * self.v + (1. - self.momentum) * globalg
    step = -self.stepsize * self.v
    return step

class Adam(Optimizer):
  def __init__(self, pi, stepsize, beta1=0.99, beta2=0.999):
    Optimizer.__init__(self, pi)
    self.stepsize = stepsize
    self.beta1 = beta1
    self.beta2 = beta2
    self.m = np.zeros(self.dim, dtype=np.float32)
    self.v = np.zeros(self.dim, dtype=np.float32)

  def _compute_step(self, globalg):
    a = self.stepsize * np.sqrt(1 - self.beta2 ** self.t) / (1 - self.beta1 ** self.t)
    self.m = self.beta1 * self.m + (1 - self.beta1) * globalg
    self.v = self.beta2 * self.v + (1 - self.beta2) * (globalg * globalg)
    step = -a * self.m / (np.sqrt(self.v) + self.epsilon)
    return step

class CMAES:
  '''CMA-ES wrapper.'''
  def __init__(self, num_params,      # number of model parameters
               sigma_init=0.10,       # initial standard deviation
               popsize=255,           # population size
               weight_decay=0.01):    # weight decay coefficient

    self.num_params = num_params
    self.sigma_init = sigma_init
    self.popsize = popsize
    self.weight_decay = weight_decay
    self.solutions = None

    import cma
    self.es = cma.CMAEvolutionStrategy( self.num_params * [0],
                                        self.sigma_init,
                                        {'popsize': self.popsize,
                                        })

  def rms_stdev(self):
    sigma = self.es.result[6]
    return np.mean(np.sqrt(sigma*sigma))

  def ask(self):
    '''returns a list of parameters'''
    self.solutions = np.array(self.es.ask())
    return self.solutions

  def tell(self, reward_table_result):
    reward_table = -np.array(reward_table_result)
    if self.weight_decay > 0:
      l2_decay = compute_weight_decay(self.weight_decay, self.solutions)
      reward_table += l2_decay
    self.es.tell(self.solutions, (reward_table).tolist()) # convert minimizer to maximizer.

  def current_param(self):
    return self.es.result[5] # mean solution, presumably better with noise

  def set_mu(self, mu):
    pass

  def best_param(self):
    return self.es.result[0] # best evaluated solution

  def result(self): # return best params so far, along with historically best reward, curr reward, sigma
    r = self.es.result
    return (r[0], -r[1], -r[2], r[6])

class SimpleGA:
  '''Simple Genetic Algorithm.'''
  def __init__(self, num_params,      # number of model parameters
               sigma_init=0.1,        # initial standard deviation
               sigma_decay=0.999,     # anneal standard deviation
               sigma_limit=0.01,      # stop annealing if less than this
               popsize=256,           # population size
               elite_ratio=0.1,       # percentage of the elites
               forget_best=False,     # forget the historical best elites
               weight_decay=0.01,     # weight decay coefficient
              ):

    self.num_params = num_params
    self.sigma_init = sigma_init
    self.sigma_decay = sigma_decay
    self.sigma_limit = sigma_limit
    self.popsize = popsize

    self.elite_ratio = elite_ratio
    self.elite_popsize = int(self.popsize * self.elite_ratio)

    self.sigma = self.sigma_init
    self.elite_params = np.zeros((self.elite_popsize, self.num_params))
    self.elite_rewards = np.zeros(self.elite_popsize)
    self.best_param = np.zeros(self.num_params)
    self.best_reward = 0
    self.first_iteration = True
    self.forget_best = forget_best
    self.weight_decay = weight_decay

  def rms_stdev(self):
    return self.sigma # same sigma for all parameters.

  def ask(self):
    '''returns a list of parameters'''
    self.epsilon = np.random.randn(self.popsize, self.num_params) * self.sigma
    solutions = []

    def mate(a, b):
      c = np.copy(a)
      idx = np.where(np.random.rand((c.size)) > 0.5)
      c[idx] = b[idx]
      return c

    elite_range = range(self.elite_popsize)
    for i in range(self.popsize):
      idx_a = np.random.choice(elite_range)
      idx_b = np.random.choice(elite_range)
      child_params = mate(self.elite_params[idx_a], self.elite_params[idx_b])
      solutions.append(child_params + self.epsilon[i])

    solutions = np.array(solutions)
    self.solutions = solutions

    return solutions

  def tell(self, reward_table_result):
    # input must be a numpy float array
    assert(len(reward_table_result) == self.popsize), "Inconsistent reward_table size reported."

    reward_table = np.array(reward_table_result)

    if self.weight_decay > 0:
      l2_decay = compute_weight_decay(self.weight_decay, self.solutions)
      reward_table += l2_decay

    if self.forget_best or self.first_iteration:
      reward = reward_table
      solution = self.solutions
    else:
      reward = np.concatenate([reward_table, self.elite_rewards])
      solution = np.concatenate([self.solutions, self.elite_params])

    idx = np.argsort(reward)[::-1][0:self.elite_popsize]

    self.elite_rewards = reward[idx]
    self.elite_params = solution[idx]

    self.curr_best_reward = self.elite_rewards[0]

    if self.first_iteration or (self.curr_best_reward > self.best_reward):
      self.first_iteration = False
      self.best_reward = self.elite_rewards[0]
      self.best_param = np.copy(self.elite_params[0])

    if (self.sigma > self.sigma_limit):
      self.sigma *= self.sigma_decay

  def current_param(self):
    return self.elite_params[0]

  def set_mu(self, mu):
    pass

  def best_param(self):
    return self.best_param

  def result(self): # return best params so far, along with historically best reward, curr reward, sigma
    return (self.best_param, self.best_reward, self.curr_best_reward, self.sigma)

class OpenES:
  ''' Basic Version of OpenAI Evolution Strategies.'''
  def __init__(self, num_params,             # number of model parameters
               sigma_init=0.1,               # initial standard deviation
               sigma_decay=0.999,            # anneal standard deviation
               sigma_limit=0.01,             # stop annealing if less than this
               learning_rate=0.01,           # learning rate for standard deviation
               learning_rate_decay = 0.9999, # annealing the learning rate
               learning_rate_limit = 0.001,  # stop annealing learning rate
               popsize=256,                  # population size
               antithetic=False,             # whether to use antithetic sampling
               weight_decay=0.01,            # weight decay coefficient
               rank_fitness=True,            # use rank rather than fitness numbers
               forget_best=True):            # forget historical best

    self.num_params = num_params
    self.sigma_decay = sigma_decay
    self.sigma = sigma_init
    self.sigma_init = sigma_init
    self.sigma_limit = sigma_limit
    self.learning_rate = learning_rate
    self.learning_rate_decay = learning_rate_decay
    self.learning_rate_limit = learning_rate_limit
    self.popsize = popsize
    self.antithetic = antithetic
    if self.antithetic:
      assert (self.popsize % 2 == 0), "Population size must be even"
      self.half_popsize = int(self.popsize / 2)

    self.reward = np.zeros(self.popsize)
    self.mu = np.zeros(self.num_params)
    self.best_mu = np.zeros(self.num_params)
    self.best_reward = 0
    self.first_interation = True
    self.forget_best = forget_best
    self.weight_decay = weight_decay
    self.rank_fitness = rank_fitness
    if self.rank_fitness:
      self.forget_best = True # always forget the best one if we rank
    # choose optimizer
    self.optimizer = Adam(self, learning_rate)

  def rms_stdev(self):
    sigma = self.sigma
    return np.mean(np.sqrt(sigma*sigma))

  def ask(self):
    '''returns a list of parameters'''
    # antithetic sampling
    if self.antithetic:
      self.epsilon_half = np.random.randn(self.half_popsize, self.num_params)
      self.epsilon = np.concatenate([self.epsilon_half, - self.epsilon_half])
    else:
      self.epsilon = np.random.randn(self.popsize, self.num_params)

    self.solutions = self.mu.reshape(1, self.num_params) + self.epsilon * self.sigma

    return self.solutions

  def tell(self, reward_table_result):
    # input must be a numpy float array
    assert(len(reward_table_result) == self.popsize), "Inconsistent reward_table size reported."

    reward = np.array(reward_table_result)

    if self.rank_fitness:
      reward = compute_centered_ranks(reward)

    if self.weight_decay > 0:
      l2_decay = compute_weight_decay(self.weight_decay, self.solutions)
      reward += l2_decay

    idx = np.argsort(reward)[::-1]

    best_reward = reward[idx[0]]
    best_mu = self.solutions[idx[0]]

    self.curr_best_reward = best_reward
    self.curr_best_mu = best_mu

    if self.first_interation:
      self.first_interation = False
      self.best_reward = self.curr_best_reward
      self.best_mu = best_mu
    else:
      if self.forget_best or (self.curr_best_reward > self.best_reward):
        self.best_mu = best_mu
        self.best_reward = self.curr_best_reward

    # main bit:
    # standardize the rewards to have a gaussian distribution
    normalized_reward = (reward - np.mean(reward)) / np.std(reward)
    change_mu = 1./(self.popsize*self.sigma)*np.dot(self.epsilon.T, normalized_reward)

    #self.mu += self.learning_rate * change_mu

    self.optimizer.stepsize = self.learning_rate
    update_ratio = self.optimizer.update(-change_mu)

    # adjust sigma according to the adaptive sigma calculation
    if (self.sigma > self.sigma_limit):
      self.sigma *= self.sigma_decay

    if (self.learning_rate > self.learning_rate_limit):
      self.learning_rate *= self.learning_rate_decay

  def current_param(self):
    return self.curr_best_mu

  def set_mu(self, mu):
    self.mu = np.array(mu)

  def best_param(self):
    return self.best_mu

  def set_sigma(self, sigma):
    self.sigma = sigma

  def set_pop(self, pop):
    self.popsize = pop

  def set_lr(self, lr):
    self.learning_rate = lr

  def result(self): # return best params so far, along with historically best reward, curr reward, sigma
    return (self.best_mu, self.best_reward, self.curr_best_reward, self.sigma)

class PEPG:
  '''Extension of PEPG with bells and whistles.'''
  def __init__(self, num_params,             # number of model parameters
               sigma_init=0.10,              # initial standard deviation
               sigma_alpha=0.20,             # learning rate for standard deviation
               sigma_decay=0.999,            # anneal standard deviation
               sigma_limit=0.01,             # stop annealing if less than this
               sigma_max_change=0.2,         # clips adaptive sigma to 20%
               learning_rate=0.01,           # learning rate for standard deviation
               learning_rate_decay = 0.9999, # annealing the learning rate
               learning_rate_limit = 0.01,   # stop annealing learning rate
               elite_ratio = 0,              # if > 0, then ignore learning_rate
               popsize=256,                  # population size
               average_baseline=True,        # set baseline to average of batch
               weight_decay=0.01,            # weight decay coefficient
               rank_fitness=True,            # use rank rather than fitness numbers
               forget_best=True):            # don't keep the historical best solution

    self.num_params = num_params
    self.sigma_init = sigma_init
    self.sigma_alpha = sigma_alpha
    self.sigma_decay = sigma_decay
    self.sigma_limit = sigma_limit
    self.sigma_max_change = sigma_max_change
    self.learning_rate = learning_rate
    self.learning_rate_decay = learning_rate_decay
    self.learning_rate_limit = learning_rate_limit
    self.popsize = popsize
    self.average_baseline = average_baseline
    if self.average_baseline:
      assert (self.popsize % 2 == 0), "Population size must be even"
      self.batch_size = int(self.popsize / 2)
    else:
      assert (self.popsize & 1), "Population size must be odd"
      self.batch_size = int((self.popsize - 1) / 2)

    # option to use greedy es method to select next mu, rather than using drift param
    self.elite_ratio = elite_ratio
    self.elite_popsize = int(self.popsize * self.elite_ratio)
    self.use_elite = False
    if self.elite_popsize > 0:
      self.use_elite = True

    self.forget_best = forget_best
    self.batch_reward = np.zeros(self.batch_size * 2)
    self.mu = np.zeros(self.num_params)
    self.sigma = np.ones(self.num_params) * self.sigma_init
    self.curr_best_mu = np.zeros(self.num_params)
    self.best_mu = np.zeros(self.num_params)
    self.best_reward = 0
    self.first_interation = True
    self.weight_decay = weight_decay
    self.rank_fitness = rank_fitness
    if self.rank_fitness:
      self.forget_best = True # always forget the best one if we rank
    # choose optimizer
    self.optimizer = Adam(self, learning_rate)

  def rms_stdev(self):
    sigma = self.sigma
    return np.mean(np.sqrt(sigma*sigma))

  def ask(self):
    '''returns a list of parameters'''
    # antithetic sampling
    self.epsilon = np.random.randn(self.batch_size, self.num_params) * self.sigma.reshape(1, self.num_params)
    self.epsilon_full = np.concatenate([self.epsilon, - self.epsilon])
    if self.average_baseline:
      epsilon = self.epsilon_full
    else:
      # first population is mu, then positive epsilon, then negative epsilon
      epsilon = np.concatenate([np.zeros((1, self.num_params)), self.epsilon_full])
    solutions = self.mu.reshape(1, self.num_params) + epsilon
    self.solutions = solutions
    return solutions

  def tell(self, reward_table_result):
    # input must be a numpy float array
    assert(len(reward_table_result) == self.popsize), "Inconsistent reward_table size reported."

    reward_table = np.array(reward_table_result)

    if self.rank_fitness:
      reward_table = compute_centered_ranks(reward_table)

    if self.weight_decay > 0:
      l2_decay = compute_weight_decay(self.weight_decay, self.solutions)
      reward_table += l2_decay

    reward_offset = 1
    if self.average_baseline:
      b = np.mean(reward_table)
      reward_offset = 0
    else:
      b = reward_table[0] # baseline

    reward = reward_table[reward_offset:]
    if self.use_elite:
      idx = np.argsort(reward)[::-1][0:self.elite_popsize]
    else:
      idx = np.argsort(reward)[::-1]

    best_reward = reward[idx[0]]
    if (best_reward > b or self.average_baseline):
      best_mu = self.mu + self.epsilon_full[idx[0]]
      best_reward = reward[idx[0]]
    else:
      best_mu = self.mu
      best_reward = b

    self.curr_best_reward = best_reward
    self.curr_best_mu = best_mu

    if self.first_interation:
      self.sigma = np.ones(self.num_params) * self.sigma_init
      self.first_interation = False
      self.best_reward = self.curr_best_reward
      self.best_mu = best_mu
    else:
      if self.forget_best or (self.curr_best_reward > self.best_reward):
        self.best_mu = best_mu
        self.best_reward = self.curr_best_reward

    # short hand
    epsilon = self.epsilon
    sigma = self.sigma

    # update the mean

    # move mean to the average of the best idx means
    if self.use_elite:
      self.mu += self.epsilon_full[idx].mean(axis=0)
    else:
      rT = (reward[:self.batch_size] - reward[self.batch_size:])
      change_mu = np.dot(rT, epsilon)
      self.optimizer.stepsize = self.learning_rate
      update_ratio = self.optimizer.update(-change_mu) # adam, rmsprop, momentum, etc.
      #self.mu += (change_mu * self.learning_rate) # normal SGD method

    # adaptive sigma
    # normalization
    if (self.sigma_alpha > 0):
      stdev_reward = 1.0
      if not self.rank_fitness:
        stdev_reward = reward.std()
      S = ((epsilon * epsilon - (sigma * sigma).reshape(1, self.num_params)) / sigma.reshape(1, self.num_params))
      reward_avg = (reward[:self.batch_size] + reward[self.batch_size:]) / 2.0
      rS = reward_avg - b
      delta_sigma = (np.dot(rS, S)) / (2 * self.batch_size * stdev_reward)

      # adjust sigma according to the adaptive sigma calculation
      # for stability, don't let sigma move more than 10% of orig value
      change_sigma = self.sigma_alpha * delta_sigma
      change_sigma = np.minimum(change_sigma, self.sigma_max_change * self.sigma)
      change_sigma = np.maximum(change_sigma, - self.sigma_max_change * self.sigma)
      self.sigma += change_sigma

    if (self.sigma_decay < 1):
      self.sigma[self.sigma > self.sigma_limit] *= self.sigma_decay

    if (self.learning_rate_decay < 1 and self.learning_rate > self.learning_rate_limit):
      self.learning_rate *= self.learning_rate_decay

  def current_param(self):
    return self.curr_best_mu

  def set_mu(self, mu):
    self.mu = np.array(mu)

  def best_param(self):
    return self.best_mu

  def result(self): # return best params so far, along with historically best reward, curr reward, sigma
    return (self.best_mu, self.best_reward, self.curr_best_reward, self.sigma)

def reset():
    env_info = env.reset(train_mode=True, config=None)[brain_name]
    return env_info.vector_observations[0]

def step(action):
    env_info = env.step(action)[brain_name]        # send the action to the environment
    next_state = env_info.vector_observations[0]   # get the next state
    reward = env_info.rewards[0]+EPS                  # get the reward
    done = env_info.local_done[0]
    return next_state, reward, done

def test_reset():
  for i in range(10):
    env.reset_parameters()
    env_info = env.reset(train_mode=True)[brain_name]
    initial_state = env_info.vector_observations[0]

def fit_func(model, num_steps):
    episode_return = 0.0
    epsilon = 0.1
    state = reset()
    for t in range(num_steps):
        if (random.uniform(0, 1) < epsilon):
          state = reset()

        action =  model.get_action(state)
        state, reward, done = step(action)
        episode_return += reward
        if done:
            break

    return episode_return

def test(train_mode):
    history = []
    for j in range(10):
      episode_return = 0.0
      env_info = env.reset(train_mode=train_mode)[brain_name]
      state = env_info.vector_observations[0]
      for t in range(101):
          action =  model.get_action(state)
          env_info = env.step(action)[brain_name]        # send the action to the environment
          next_state = env_info.vector_observations[0]   # get the next state
          reward = env_info.rewards[0]                  # get the reward
          done = env_info.local_done[0]
          episode_return += reward
          if done:
              break
      history.append(episode_return)
    return print("Test mode",np.mean(history))

def test_solver(solver):
    history = []
    changed = False
    scores_window = deque(maxlen=100)
    num_steps = 60
    print("Num steps", num_steps, "Params", NPARAMS, "Population", NPOPULATION)
    for j in range(MAX_ITERATION):

      if keyboard.is_pressed('s'):
        print("Put value for sigma")
        solver.set_sigma(float(sys.stdin.readline().strip()))
      if keyboard.is_pressed('l'):
        print("Put value for lr")
        solver.set_lr(float(sys.stdin.readline().strip()))
      if keyboard.is_pressed('p'):
        print("Put value for population")
        solver.set_pop(int(sys.stdin.readline().strip()))

      solutions = solver.ask()
      fitness_list = np.zeros(solver.popsize)
      start = time.time()
      for i in range(solver.popsize):
        model.set_model_params(solutions[i])
        fitness_list[i] = fit_func(model, num_steps)
        print('\rPopulation element {}\t'.format(i), end='\r')
      end = time.time()
      print("Episode takes:",end - start,end='\r')
      solver.tell(fitness_list)
      result = solver.result() # first element is the best solution, second element is the best fitness
      history.append(result[2])
      scores_window.append(result[2])
      print(j, "Best candidate", result[1], "Max in generation", result[2], "Total Average", np.mean(scores_window), "Sigma", result[3])

      if (not changed and (np.mean(scores_window) > 1.82 or j == 500)):
        changed = True
        num_steps = 1001
        solver.set_pop(20)
        solver.set_sigma(0.1)
        solver.set_lr(0.01)
        with open("best_one_smalstep", 'wt') as out:
          res = json.dump([np.array(result[0]).round(8).tolist()], out, sort_keys=True, indent=0, separators=(',', ': '))
      if (np.mean(scores_window)>30):
        print("Solved")
        with open("best_one_bigstep", 'wt') as out:
          res = json.dump([np.array(result[0]).round(8).tolist()], out, sort_keys=True, indent=0, separators=(',', ': '))

      # if j % 200 == 0:
        # with open("best_one", 'wt') as out:
        #   res = json.dump([np.array(result[0]).round(8).tolist()], out, sort_keys=True, indent=0, separators=(',', ': '))
        # model.set_model_params(result[0])
        # test(True)

    return history

# cmaes = CMAES(NPARAMS,
#               popsize=NPOPULATION,
#               weight_decay=0.0,
#               sigma_init = 0.1
#           )

# pepg = PEPG(NPARAMS,                         # number of model parameters
#             sigma_init=0.5,                  # initial standard deviation
#             learning_rate=0.1,               # learning rate for standard deviation
#             learning_rate_decay=1.0,       # don't anneal the learning rate
#             popsize=NPOPULATION,             # population size
#             average_baseline=False,          # set baseline to average of batch
#             weight_decay=0.00,            # weight decay coefficient
#             rank_fitness=False,           # use rank rather than fitness numbers
#             forget_best=False)            # don't keep the historical best solution)
# oes = OpenES(NPARAMS,                  # number of model parameters
#             sigma_init=0.5,            # initial standard deviation
#             sigma_decay=0.999,         # don't anneal standard deviation
#             learning_rate=0.07,         # learning rate for standard deviation
#             learning_rate_decay = 1.0, # annealing the learning rate
#             popsize=NPOPULATION,       # population size
#             antithetic=True,          # whether to use antithetic sampling
#             weight_decay=0.01,         # weight decay coefficient
#             rank_fitness=False,        # use rank rather than fitness numbers
#             forget_best=False)
env = UnityEnvironment(file_name='./Reacher.app',worker_id=1,no_graphics=True)
print(str(env))
model = ModelES()
# model.load_model('best_one')
brain_name = env.brain_names[0]
NPARAMS = model.param_count        # make this a 100-dimensinal problem.
NPOPULATION = 200    # use population size of 101.
LR = 0.03
MAX_ITERATION = 4000 # run each solver for 5000 generations.
EPS = 0.0001
SIGMA = 0.3
solver = OpenES(NPARAMS,                  # number of model parameters
            sigma_init=SIGMA,            # initial standard deviation
            sigma_decay=1.0,         # don't anneal standard deviation
            learning_rate=LR,         # learning rate for standard deviation
            learning_rate_decay = 1.0, # annealing the learning rate
            popsize=NPOPULATION,       # population size
            antithetic=True,          # whether to use antithetic sampling
            weight_decay=0.01,         # weight decay coefficient
            rank_fitness=False,        # use rank rather than fitness numbers
            forget_best=False)
scores = test_solver(solver)
fig = plt.figure()
ax = fig.add_subplot(111)
plt.plot(np.arange(1, len(scores)+1), scores)
plt.ylabel('Score')
plt.xlabel('Episode #')
plt.show()

# test_reset()


#!/usr/bin/python
# coding: utf8

'''
This script convert an image to black and white
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade Pillow
python convert_image_to_black_and_white.py
'''

from PIL import Image

print("Converting...")

img = Image.open("kub.png")
result = img.convert("L")
result.save("kub-bw.png")
result.show()


import numpy as np
from utils import *

class rBergomi(object):
    """
    Class for generating paths of the rBergomi model.
    """
    def __init__(self, n = 100, N = 1000, T = 1.00, a = -0.4):
        """
        Constructor for class.
        """
        # Basic assignments
        self.T = T # Maturity
        self.n = n # Granularity (steps per year)
        self.dt = 1.0/self.n # Step size
        self.s = int(self.n * self.T) # Steps
        self.t = np.linspace(0, self.T, 1 + self.s)[np.newaxis,:] # Time grid
        self.a = a # Alpha
        self.N = N # Paths

        # Construct hybrid scheme correlation structure for kappa = 1
        self.e = np.array([0,0])
        self.c = cov(self.a, self.n)

    def dW1(self):
        """
        Produces random numbers for variance process with required
        covariance structure.
        """
        rng = np.random.multivariate_normal
        return rng(self.e, self.c, (self.N, self.s))

    def Y(self, dW):
        """
        Constructs Volterra process from appropriately
        correlated 2d Brownian increments.
        """
        Y1 = np.zeros((self.N, 1 + self.s)) # Exact integrals
        Y2 = np.zeros((self.N, 1 + self.s)) # Riemann sums

        # Construct Y1 through exact integral
        for i in np.arange(1, 1 + self.s, 1):
            Y1[:,i] = dW[:,i-1,1] # Assumes kappa = 1

        # Construct arrays for convolution
        G = np.zeros(1 + self.s) # Gamma
        for k in np.arange(2, 1 + self.s, 1):
            G[k] = g(b(k, self.a)/self.n, self.a)

        X = dW[:,:,0] # Xi

        # Initialise convolution result, GX
        GX = np.zeros((self.N, len(X[0,:]) + len(G) - 1))

        # Compute convolution, FFT not used for small n
        # Possible to compute for all paths in C-layer?
        for i in range(self.N):
            GX[i,:] = np.convolve(G, X[i,:])

        # Extract appropriate part of convolution
        Y2 = GX[:,:1 + self.s]

        # Finally contruct and return full process
        Y = np.sqrt(2 * self.a + 1) * (Y1 + Y2)
        return Y

    def dW2(self):
        """
        Obtain orthogonal increments.
        """
        return np.random.randn(self.N, self.s) * np.sqrt(self.dt)

    def dB(self, dW1, dW2, rho = 0.0):
        """
        Constructs correlated price Brownian increments, dB.
        """
        self.rho = rho
        dB = rho * dW1[:,:,0] + np.sqrt(1 - rho**2) * dW2
        return dB

    def V(self, Y, xi = 1.0, eta = 1.0):
        """
        rBergomi variance process.
        """
        self.xi = xi
        self.eta = eta
        a = self.a
        t = self.t
        V = xi * np.exp(eta * Y - 0.5 * eta**2 * t**(2 * a + 1))
        return V

    def S(self, V, dB, S0 = 1):
        """
        rBergomi price process.
        """
        self.S0 = S0
        dt = self.dt
        rho = self.rho

        # Construct non-anticipative Riemann increments
        increments = np.sqrt(V[:,:-1]) * dB - 0.5 * V[:,:-1] * dt

        # Cumsum is a little slower than Python loop.
        integral = np.cumsum(increments, axis = 1)

        S = np.zeros_like(V)
        S[:,0] = S0
        S[:,1:] = S0 * np.exp(integral)
        return S

    def S1(self, V, dW1, rho, S0 = 1):
        """
        rBergomi parallel price process.
        """
        dt = self.dt

        # Construct non-anticipative Riemann increments
        increments = rho * np.sqrt(V[:,:-1]) * dW1[:,:,0] - 0.5 * rho**2 * V[:,:-1] * dt

        # Cumsum is a little slower than Python loop.
        integral = np.cumsum(increments, axis = 1)

        S = np.zeros_like(V)
        S[:,0] = S0
        S[:,1:] = S0 * np.exp(integral)
        return S


import sys
from io import StringIO
import unittest

class TestClass(unittest.TestCase):
    def assertIO(self, input, output):
        stdout, stdin = sys.stdout, sys.stdin
        sys.stdout, sys.stdin = StringIO(), StringIO(input)
        resolve()
        sys.stdout.seek(0)
        out = sys.stdout.read()[:-1]
        sys.stdout, sys.stdin = stdout, stdin
        self.assertEqual(out, output)

    def test_Sample_Input_1(self):
        input = """5
WEEWW"""
        output = """1"""
        self.assertIO(input, output)

    def test_Sample_Input_2(self):
        input = """12
WEWEWEEEWWWE"""
        output = """4"""
        self.assertIO(input, output)

    def test_Sample_Input_3(self):
        input = """8
WWWWWEEE"""
        output = """3"""
        self.assertIO(input, output)

    def test_Sample_Input_4(self):
        input = """1
E"""
        output = """0"""
        self.assertIO(input, output)

def resolve():
  # E と W で区間和をとると、i 番目の人をリーダーにした時の振り向く人数が O(1) で出せる。
  # 全体で O(N)
  N = int(input())
  S = list(input())
  E = [0]*(N+1)
  W = [0]*(N+1)
  for i in range(N):
    if S[i]=="E":
      E[i+1] = E[i]+1
      W[i+1] = W[i]
    else:
      E[i+1] = E[i]
      W[i+1] = W[i]+1
  print(min(E[-1] - E[i+1] + W[i] for i in range(N)))

resolve()

if __name__ == "__main__":
    unittest.main()


from datetime import date
import json

from kombu.serialization import register
from celery import Celery

from example.models import CashFlowStatement

class Encoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, date):
            return {"__type__": "__date__", "epoch": o.isoformat()}

        if isinstance(o, CashFlowStatement):
            return {"__type__": "cfstmt", "kwargs": o.to_dict()}

        return json.JSONEncoder.default(self, o)

def decoder(o):
    if "__type__" in o:
        if o["__type__"] == "__date__":
            return date.fromisoformat(o["epoch"])
        if o["__type__"] == "cfstmt":
            return CashFlowStatement(**o["kwargs"])
    return o

def dumps(o):
    return json.dumps(o, cls=Encoder)

def loads(s):
    return json.loads(s, object_hook=decoder)

register(
    "fiberjson",
    dumps,
    loads,
    content_type="application/x-fiberjson",
    content_encoding="utf-8",
)

app = Celery(
    "tasks", backend="amqp://redis", broker="amqp://rabbitmq", include="example.tasks"
)

app.conf.update(
    accept_content=["fiberjson"],
    task_serializer="fiberjson",
    result_serializer="fiberjson",
)


#! /usr/bin/env python3

import logging
import os
import re
import sys

LOG = logging.getLogger( 'scad' )

LIBRARIES = []

LINE_LENGTH = 120
INCLUDE = re.compile( '^include <(.*)>;$' )
BARS = '/'*LINE_LENGTH + '\n'

def section_comment( string ):
    line = "// ===== %s %s" % ( string, '='*LINE_LENGTH)
    return line[0:LINE_LENGTH]+'\n'

def expand_path( src_path, dst_file ):
    canonical = os.path.abspath( src_path )
    if canonical not in LIBRARIES:
        LOG.info( "Expanding %s", canonical )
        LIBRARIES.append( canonical )
        with open( canonical, 'r' ) as src_file:
            dst_file.write( section_comment( 'Start ' + src_path ) )

            here = os.path.curdir
            os.chdir( os.path.dirname( canonical ) )

            for dummy_index, line in enumerate( src_file ):
                match = INCLUDE.match( line )
                if match:
                    filename = match.group( 1 )
                    expand_path( filename, dst_file )
                else:
                    dst_file.write( line )

            os.chdir( here )

            dst_file.write( section_comment( 'End ' + src_path ) )

if __name__ == '__main__':
    logging.basicConfig( level=logging.WARNING, format='%(asctime)s %(message)s', datefmt='%H:%M:%S' )

    if len( sys.argv ) < 3:
        LOG.error( "usage: %s <source> <destination>", sys.argv[0] )
        sys.exit( 1 )

    src = sys.argv[1]
    dst = sys.argv[2]

    if not os.path.exists( src ):
        LOG.error( "Unable to locate source: %s", src )
        sys.exit( 2 )

    with open( dst, 'w' ) as output:
        expand_path( src, output )


def minSubArrayLen(target, nums) :
    l, r = 0, 0
    res = 10 ** 9
    total = 0
    counter = 0
    exist = False
    while l < len(nums):
        if total < target and r < len(nums):
            total += nums[r]
            counter += 1
            r += 1

        elif total >= target:
            exist = True
            res = min(res, counter)
            total -= nums[l]
            counter -= 1
            l += 1
        if total < target and r == len(nums):
            break
    if exist == False: return 0
    return res
print(minSubArrayLen(7,[2,3,1,2,4,3]))


import math

def knn(k, training_data, testing_data):

    # get number of attributes
    num_attributes = len(training_data[0])-1
    # array to stored neighbours
    euclieden_dist = []

    for x in range(len(training_data)):
        # for all training attributes, find euclieden distance to testing data
        distance = euclidean_distance(training_data[x],testing_data)
        euclieden_dist.append((distance,training_data[x][-1]))

    # sort the distances
    euclieden_dist.sort(key=lambda i:i[0])

    num_yes = 0;
    num_no = 0;

    for i in range(k):
        if euclieden_dist[i][1] == "yes":
            num_yes += 1
        else:
            num_no +=1
    # if there is a tie we take yes
    if num_yes >= num_no:
        return "yes"
    else:
        return "no"

def euclidean_distance(old_attribute, new_attribute):
    distance = 0;
    for i in range(len(new_attribute)):
        distance += pow((old_attribute[i]-new_attribute[i]), 2)
    return math.sqrt(distance)


import os
from pathlib import Path

path2 = './photos'
for i in range(4):
    file_name = "photo{}.jpg"
    open(os.path.join(path2, file_name.format(i)), 'a').close()
files = os.listdir(path2)
print(files)
for file in files:
    fPath = Path(os.path.join(path2, file))
    fPath.rename(fPath.with_suffix('.png'))
files = os.listdir(path2)
print(files)


VOWELS = 'aeiou'
CONSONANTS = 'bcdfghjklmnpqrstvwxyz'
HAND_SIZE = 7

SCRABBLE_LETTER_VALUES = {
    'a': 1, 'b': 3, 'c': 3, 'd': 2, 'e': 1, 'f': 4, 'g': 2, 'h': 4, 'i': 1, 'j': 8, 'k': 5, 'l': 1, 'm': 3, 'n': 1,
    'o': 1, 'p': 3, 'q': 10, 'r': 1, 's': 1, 't': 1, 'u': 1, 'v': 4, 'w': 4, 'x': 8, 'y': 4, 'z': 10
}

WORDLIST_FILENAME = "words.txt"

def load_words():

    wordlist = []
    print("Loading word list from file...")
    inFile = open(WORDLIST_FILENAME, 'r')
    for line in inFile:
        wordlist.append(line.strip().lower())
    print("  ", len(wordlist), "words loaded.")
    return wordlist

def get_frequency_dict(sequence):

    freq = {}
    for x in sequence:
        freq[x] = freq.get(x, 0) + 1
    return freq

def get_word_score(word, n):

    score_fc = 0

    word = str.lower(word)
    wordlen = len(word)

    if '*' in word:
        word = word.replace('*', '')
    for letter in word:
        score_fc += SCRABBLE_LETTER_VALUES[letter]
    score_sc = max(7 * wordlen - 3 * (n - wordlen), 1)

    return score_fc * score_sc

def display_hand(hand):

    for letter in hand.keys():
        for j in range(hand[letter]):
            print(letter, end = ' ')
    print()

def deal_hand(n):

    hand = {}
    num_vowels = int(math.ceil(n / 3)) - 1

    for i in range(num_vowels):
        x = random.choice(VOWELS)
        hand[x] = hand.get(x, 0) + 1

    hand['*'] = 1

    for i in range(num_vowels, n - 1):
        x = random.choice(CONSONANTS)
        hand[x] = hand.get(x, 0) + 1

    return hand

def update_hand(hand, word):

    word = str.lower(word)
    word = get_frequency_dict(word)
    new_hand = {}

    for letter in hand.keys():
        if letter in word.keys():
            freq_remained = hand[letter] - word[letter]
            if freq_remained > 0:
                new_hand[letter] = new_hand.get(letter, freq_remained)
        else:
            new_hand[letter] = hand[letter]

    return new_hand

def is_valid_word(word, hand, word_list):

    word = str.lower(word)
    word_freq = get_frequency_dict(word)
    valid_word = []

    for letter in word_freq.keys():
        valid_word.append(letter in hand.keys() and hand[letter] >= word_freq[letter])
    if False not in valid_word:
        if word in word_list:
            return True
        elif '*' in word:
            for vowel in VOWELS:
                possible_word = word.replace('*', vowel)
                if possible_word in word_list:
                    return True
    else:
        return False

def calculate_handlen(hand):

    return sum(hand.values())

def play_hand(hand, word_list):

    total_score = 0
    while calculate_handlen(hand) > 0:

        print('\nCurrent Hand: '), display_hand(hand)
        word = input('Please enter a word or '"!!"' to indicate you are done: ')
        word = str.lower(word)

        if word == '!!':
            print('Total score for this hand:', total_score, 'points')
            break
        elif is_valid_word(word, hand, word_list):
            word_score = get_word_score(word, calculate_handlen(hand))
            total_score += word_score
            print('"' + word + '"', 'earned', word_score, 'points. Total:', total_score, 'points')
        else:
            print('That is not a valid word. Please choose another word.')
        hand = update_hand(hand, word)
        if calculate_handlen(hand) == 0:
            print('\nRan out of letters.', '\nTotal score for this hand:', total_score, 'points')

    return total_score

def substitute_hand(hand, letter):

    letter = str.lower(letter)
    substitute_letter = letter

    while substitute_letter in hand:
        if letter == '*':
            return hand
            break

        LETTERS = VOWELS + CONSONANTS
        substitute_letter = random.choice(LETTERS)

    hand[substitute_letter] = hand.get(letter, 0)
    del (hand[letter])

    return hand

def play_game(word_list):

    n = int(input('Enter hand size: '))
    number_of_hands = int(input('Enter total number of hands: '))
    total_game_score = 0
    substitute_letter_used = 0
    replay_hand_used = 0
    replay_hand = 0
    substitute_letter = 0

    for i in range(number_of_hands):
        hand = deal_hand(n)

        if substitute_letter_used == 0:
            print('Current Hand: '), display_hand(hand)
            substitute_letter = input('Would you like to substitute a letter? ')
            substitute_letter = str.lower(substitute_letter)
            if substitute_letter in 'yes':
                substitute_letter_used += 1
                letter = input('Which letter would you like to replace: ')
                letter = str.lower(letter)
                hand = substitute_hand(hand, letter)
        hand_score = play_hand(hand, word_list)
        print('----------')

        if replay_hand_used == 0:
            replay_hand = input('Would you like to replay the hand? ')
            replay_hand = str.lower(replay_hand)
            if replay_hand in 'yes':
                replay_hand_used += 1
                replay_hand_score = play_hand(hand, word_list)
                hand_score = max(hand_score, replay_hand_score)
        total_game_score += hand_score

        if i == number_of_hands - 1:
            print('Total score over all hands:', total_game_score)

    return total_game_score

if __name__ == '__main__':
    word_list = load_words()
    play_game(word_list)