from turtle import Turtle

ALIGNMENT = "center"
FONT = ("Courier", 30, 'bold')

class Score(Turtle):
    def __init__(self):
        super().__init__()
        self.color("white")
        self.penup()
        self.hideturtle()
        self.l_score = 0
        self.r_score = 0
        self.update_score()

    def update_score(self):
        y_coordinate = -280
        self.goto(100, 250)
        self.write(f"{self.r_score}", False, align=ALIGNMENT, font=FONT)
        self.goto(-100, 250)
        self.write(f"{self.l_score}", False, align=ALIGNMENT, font=FONT)
        for index in range(0, 10):
            self.goto(0, y_coordinate)
            self.write("|", False, align=ALIGNMENT, font=FONT)
            y_coordinate += 56

    def left_player_points(self):
        self.clear()
        self.l_score += 1
        self.update_score()

    def right_player_points(self):
        self.clear()
        self.r_score += 1
        self.update_score()


#!/usr/bin/env python
import numpy as np
import matplotlib.pyplot as plt

def GetMuTilde(buf, buf_idx, a, sigma):
    result = sum([a[ii]*buf[(buf_idx+len(buf)-ii-1)%len(buf)] for ii in range(len(a))]) \
            + sigma*np.random.normal()
    return result
mu = 0.142
a = [0.783, 0.116]
sigma = 0.0148
# sigma = 0.
buf = [0]*3
buf_idx = 0

data = []
for ii in range(200):
    mu_tilde = GetMuTilde(buf, buf_idx, a, sigma)
    # data.append(mu + mu_tilde)
    # buf[buf_idx] = mu_tilde
    data.append(mu_tilde)
    buf_idx = (buf_idx+1) % (len(a)+1)
data = np.array(data)
plt.figure()
plt.plot(data, '-x')
plt.figure()
plt.specgram(data, Fs=44100.)
plt.show()


import time
import machine
from machine import Pin, Timer

LED_BLINK_TIMER_CLOCK_ms = 1000
timer_period = 1000
led_blink_active_flag = 1
ledstate = 1
timer_interrupt_flag = 1

#right front wheel - good
p18 = Pin(18, Pin.OUT)
p19 = Pin(19, Pin.OUT)
p5 = Pin(5,Pin.OUT)  #p5 - enable
p5.value(1)

#left back wheel - good
p15 = Pin(15, Pin.OUT)
p32 = Pin(32, Pin.OUT)
p14 = Pin(22, Pin.OUT) #p14 - enable
p14.value(1)

#left front wheel - good
p27 = Pin(27,Pin.OUT)
p33 = Pin(33,Pin.OUT)
p22 = Pin(22,Pin.OUT) #p22 - enable
p22.value(1)

#right back wheel - good
p16 = Pin(16,Pin.OUT)
p17 = Pin(17,Pin.OUT)
p21 = Pin(21,Pin.OUT) #p21 - enable
p21.value(1)

def turnLeft():
    #move forward right front;
    p18.value(0)
    p19.value(1)
    #move forware right back;
    p16.value(1)
    p17.value(0)
    #move backward left back;
    p15.value(0)
    p32.value(1)
    #move backward left front;
    p27.value(1)
    p33.value(0)

def turnRight():
    #move backward right front;
    p18.value(1)
    p19.value(0)
    #move backware right back;
    p16.value(0)
    p17.value(1)
    #move forward left back;
    p15.value(1)
    p32.value(0)
    #move forward left front;
    p27.value(0)
    p33.value(1)

def moveFront():
    #move forward right front;
    p18.value(0)
    p19.value(1)
    #move forward left back;
    p15.value(1)
    p32.value(0)
    #move forward left front;
    p27.value(0)
    p33.value(1)
    #move forware right back;
    p16.value(1)
    p17.value(0)

def moveBack():
    #move backward right front;
    p18.value(1)
    p19.value(0)
    #move backward left back;
    p15.value(0)
    p32.value(1)
    #move backward left front;
    p27.value(1)
    p33.value(0)
    #move backware right back;
    p16.value(0)
    p17.value(1)

def toggle_led(timer):
    global ledstate
    ledstate = ledstate ^ 1
    if led_blink_active_flag == 1:
        led(ledstate)

def handle_input():  #new functions to handle input values, T,A,B,I
    global timer_period, led_blink_active_flag

    Command = input('')
    if Command == 'T':
        if led_blink_active_flag == 1:
            print("TLED blinking paused \r\n")
        else:
            print("TLED blinking resumed \r\n")
        led_blink_active_flag ^= 1
    elif Command == 'A':
        print('AReceived the A command\r\n')
        timer_period = LED_BLINK_TIMER_CLOCK_ms
        t1.init(period=timer_period, mode=t1.PERIODIC, callback=toggle_led)
    elif Command == 'B':
        print('BReceived the B command\r\n')
        timer_period = timer_period - 100
        if timer_period < 200:
            timer_period = 200
        t1.init(period=timer_period, mode=t1.PERIODIC, callback=toggle_led)
    elif Command == 'L': # car left turn 90 degree
        turnLeft()
        print('LReceived the L command\r\n')
    elif Command == 'R': # car right turn 90 degree
        turnRight()
        print('RReceived the R command\r\n')
    elif Command == 'F': # car going forward a little bit
        moveFront()
        print('FReceived the F command\r\n')
    elif Command == 'C': #trick the cat
        print('CReceived the C command\r\n')
    elif Command == 'V':
        moveBack()
        print('VReceived the V command\r\n')
    elif Command == 'I':
        print('IESP32\r\n')

led = Pin(13, mode=Pin.OUT)
led(ledstate)
t1 = Timer(1)
t1.init(period=LED_BLINK_TIMER_CLOCK_ms, mode=t1.PERIODIC, callback=toggle_led)
#re-initalize values so ESP32 doesn't reboot itself after typing A and B
print('\r\nESP32 Ready to accept Commands\r\n')

try:
    while True:
        handle_input()
except KeyboardInterrupt:
    t1.deinit()


#! /usr/bin/env python

from __future__ import annotations
import numpy as np
import time
import math
from termcolor import colored
from typing import List, Dict, Tuple

class Utilities(object):

	@staticmethod
	def q_from_pol(mdp: HighDimMDP, pol: np.ndarray, task_idx: int = None) -> np.ndarray:
		X = mdp.states
		A = mdp.actions
		P = mdp.transitions_prob
		if task_idx is not None:
			c = mdp.costs[task_idx]
		else:
			c = mdp.costs
		gamma = mdp.gamma
		nX, nA = len(X), len(A)

		q = np.zeros((nX, nA))
		J = mdp.evaluate_pol(pol, task_idx)

		for act in range(nA):
			p = np.zeros((nX, nX))
			for state_idx in range(nX):
				state_tansitions = P[A[act]][state_idx]
				for state in state_tansitions:
					p[state_idx, int(state[0])] += state[1]
			q[:, act, None] = c[:, act, None] + gamma * p.dot(J)

		return q

	@staticmethod
	def v_from_q(q: np.ndarray, pol: np.ndarray) -> np.ndarray:
		return (q * pol).sum(axis=1)

	@staticmethod
	def Ppi(transitions: Dict[str, np.ndarray], actions: List[str], pol: np.ndarray) -> np.ndarray:
		nX = len(transitions[actions[0]])
		nA = len(actions)
		ppi = np.zeros((nX, nX))
		for act_idx in range(nA):
			for state_idx in range(nX):
				state_tansitions = transitions[actions[act_idx]][state_idx]
				for state in state_tansitions:
					ppi[state_idx, int(state[0])] += pol[state_idx, act_idx] * state[1]

		return ppi

	@staticmethod
	def softmax(param: np.ndarray, temp: float) -> np.ndarray:
		tmp = np.exp((param - np.max(param, axis=1)[:, None]) / temp)
		return tmp / tmp.sum(axis=1)[:, None]

	@staticmethod
	def softmax_grad(param: np.ndarray, temp: float) -> np.ndarray:
		softmax_pol = Utilities.softmax(param, temp)
		nX, nA = softmax_pol.shape
		sofmax_grad = np.zeros((nX * nA, nX * nA))

		for x in range(nX):
			for a in range(nA):
				for a2 in range(nA):
					sofmax_grad[x * a, x * a2] = softmax_pol[x, a] * ((1 if a == a2 else 0) - softmax_pol[x, a2])

		return np.diagonal(sofmax_grad).reshape((nX, nA), order='F')

	@staticmethod
	def get_goal_state(states: np.ndarray, goal: Tuple, obj_locs: List[Tuple]) -> List[int]:
		state_lst = list(states)
		goal_loc = ''
		for obj_loc in obj_locs:
			if obj_loc[2] in goal:
				goal_loc += str(obj_loc[0]) + ' ' + str(obj_loc[1]) + ', '
		return [state_lst.index(x) for x in states if x.find(goal_loc[:-2]) != -1]

class HighDimMDP(object):

	def __init__(self, x: np.ndarray, a: List[str], p: Dict[str, np.ndarray], c: np.ndarray, gamma: float, goal_states: List[int], feedback_type: str,
				 verbose: bool):
		self._mdp = (x, a, p, c, gamma)
		self._goal_states = goal_states
		self._verbose = verbose
		if feedback_type.lower().find('cost') != -1 or feedback_type.lower().find('reward') != -1:
			self._feedback_type = feedback_type
		else:
			print('Invalid feedback type, defaulting to use costs.')
			self._feedback_type = 'cost'

	@property
	def states(self) -> np.ndarray:
		return self._mdp[0]

	@property
	def actions(self) -> List[str]:
		return self._mdp[1]

	@property
	def transitions_prob(self) -> Dict[str, np.ndarray]:
		return self._mdp[2]

	@property
	def costs(self) -> np.ndarray:
		return self._mdp[3]

	@property
	def gamma(self) -> float:
		return self._mdp[4]

	@property
	def goals(self) -> List[int]:
		return self._goal_states

	@property
	def mdp(self) -> Tuple[np.ndarray, List[str], Dict[str, np.ndarray], np.ndarray, float]:
		return self._mdp

	@property
	def verbose(self) -> bool:
		return self._verbose

	@mdp.setter
	def mdp(self, mdp: Tuple[np.ndarray, List[str], Dict[str, np.ndarray], np.ndarray, float]):
		self._mdp = mdp

	@goals.setter
	def goals(self, goals: List[str]):
		self._goal_states = goals

	@verbose.setter
	def verbose(self, verbose: bool):
		self._verbose = verbose

	def get_possible_states(self, q: np.ndarray) -> np.ndarray:
		nonzerostates = np.nonzero(q.sum(axis=1))[0]
		possible_states = [np.delete(nonzerostates, np.argwhere(nonzerostates == g)) for g in self._goal_states][0]
		return possible_states

	def evaluate_pol(self, pol: np.ndarray, task_idx: int = None) -> np.ndarray:
		X = self._mdp[0]
		A = self._mdp[1]
		P = self._mdp[2]
		if task_idx is None:
			c = self._mdp[3]
		else:
			c = self._mdp[3][task_idx]
		gamma = self._mdp[4]

		nS = len(X)

		# Cost and Probs averaged by policy
		cpi = (pol * c).sum(axis=1)
		ppi = Utilities.Ppi(P, A, pol)

		# J = (I - gamma*P)^-1 * c
		J = np.linalg.inv(np.eye(nS) - gamma * ppi).dot(cpi)

		return J[:, None]

	def value_iteration(self, task_idx: int = None) -> np.ndarray:
		X = self._mdp[0]
		A = self._mdp[1]
		P = self._mdp[2]
		if task_idx is not None:
			c = self._mdp[3][task_idx]
		else:
			c = self._mdp[3]
		gamma = self._mdp[4]

		nX = len(X)
		nA = len(A)

		J = np.zeros(nX)
		err = 1
		i = 0

		while err > 1e-8:
			Q = []
			for act in range(nA):
				p = np.zeros((nX, nX))
				for state_idx in range(nX):
					state_tansitions = P[A[act]][state_idx]
					for state in state_tansitions:
						p[state_idx, int(state[0])] += state[1]
				Q += [c[:, act] + gamma * p.dot(J)]

			if self._feedback_type.find('cost') != -1:
				Jnew = np.min(Q, axis=0)
			else:
				Jnew = np.max(Q, axis=0)
			err = np.linalg.norm(J - Jnew)
			J = Jnew

			i += 1

		return J[:, None]

	def policy_iteration(self, task_idx: int = None) -> (np.ndarray, np.ndarray):
		X = self._mdp[0]
		A = self._mdp[1]
		P = self._mdp[2]
		if task_idx is not None:
			c = self._mdp[3][task_idx]
		else:
			c = self._mdp[3]
		gamma = self._mdp[4]

		nX = len(X)
		nA = len(A)

		# Initialize pol
		pol = np.ones((nX, nA)) / nA

		# Initialize Q
		Q = np.zeros((nX, nA))

		quit = False
		i = 0

		while not quit:
			if self._verbose:
				print('Iteration %d' % (i + 1), end='\r')

			J = self.evaluate_pol(pol, task_idx)

			for act in range(nA):
				p = np.zeros((nX, nX))
				for state_idx in range(nX):
					state_tansitions = P[A[act]][state_idx]
					for transition in state_tansitions:
						p[state_idx, int(transition[0])] += transition[1]
				Q[:, act, None] = c[:, act, None] + gamma * p.dot(J)

			if self._feedback_type.find('cost') != -1:
				Qbest = Q.min(axis=1, keepdims=True)
			else:
				Qbest = Q.max(axis=1, keepdims=True)
			polnew = np.isclose(Q, Qbest, atol=1e-10, rtol=1e-10).astype(int)
			polnew = polnew / polnew.sum(axis=1, keepdims=True)

			quit = (pol == polnew).all()
			pol = polnew
			i += 1

		if self._verbose:
			print('N. iterations: ', i)

		return pol, Q

	def trajectory_len(self, x0: str, pol: np.ndarray, traj_len: int, rng_gen: np.random.Generator) -> (np.ndarray, np.ndarray):
		X = self._mdp[0]
		A = self._mdp[1]
		P = self._mdp[2]

		nA = len(A)

		traj = [x0]
		actions = []
		x = list(X).index(x0)

		for _ in range(traj_len):
			a = rng_gen.choice(nA, p=pol[x, :])
			next_states = P[A[a]][x, :]
			x = rng_gen.choice(next_states[:, :, 0], p=next_states[:, :, 1])

			traj += [X[x]]
			actions += [A[a]]

		actions += [A[rng_gen.choice(nA, p=pol[x, :])]]
		return np.array(traj), np.array(actions)

	def trajectory(self, x0: str, pol: np.ndarray, rng_gen: np.random.Generator) -> (np.ndarray, np.ndarray):
		X = self._mdp[0]
		A = self._mdp[1]
		P = self._mdp[2]

		nX = len(X)
		nA = len(A)

		traj = [x0]
		actions = []
		x = list(X).index(x0)
		stop = False
		i = 0

		while not stop:
			a = rng_gen.choice(nA, p=pol[x, :])
			nxt_states = P[A[a]][x, :]
			x = int(rng_gen.choice(nxt_states[:, 0], p=nxt_states[:, 1]))

			traj += [X[x]]
			actions += [A[a]]

			stop = (x in self._goal_states or i > 500)
			if stop:
				actions += [A[rng_gen.choice(nA, p=pol[x, :])]]

			i += 1

		return np.array(traj), np.array(actions)

	def all_trajectories(self, x0: str, pol: np.ndarray, rng_gen: np.random.Generator) -> (np.ndarray, np.ndarray):
		X = self._mdp[0]
		A = self._mdp[1]
		P = self._mdp[2]

		nX = len(X)
		nA = len(A)

		i = 0
		trajs = []
		acts = []
		started_trajs = [[[x0], []]]
		stop = False

		while not stop:
			traj = started_trajs[i][0]
			a_traj = started_trajs[i][1]
			x = list(X).index(traj[-1])
			stop_inner = False
			it = 0
			add_traj = False

			while not stop_inner:
				if x in self._goal_states:
					a_traj += [A[rng_gen.choice(nA, p=pol[x, :])]]
					add_traj = True
					break

				else:
					pol_act = np.nonzero(pol[x, :])[0]
					if len(pol_act) > 1:
						for j in range(1, len(pol_act)):
							if len(np.nonzero(P[A[pol_act[j]]][x, :])) > 1:
								next_states = P[A[pol_act[j]]][x, :]
								x_tmp = rng_gen.choice(next_states[:, :, 0], p=next_states[:, :, 1])
								while x_tmp == x:
									x_tmp = rng_gen.choice(nX, p=P[A[pol_act[j]]][x, :])
							else:
								next_states = P[A[pol_act[j]]][x, :]
								x_tmp = rng_gen.choice(next_states[:, :, 0], p=next_states[:, :, 1])
							tmp_traj = [list(traj) + [X[x_tmp]], list(a_traj) + [A[pol_act[j]]]]
							if tmp_traj not in started_trajs:
								started_trajs += [tmp_traj]

					a = pol_act[0]
					x = rng_gen.choice(nX, p=P[A[a]][x, :])

					if X[x] != traj[-1]:
						traj += [X[x]]
						a_traj += [A[a]]

						stop_inner = (x in self._goal_states)
						if stop_inner:
							a_traj += [A[rng_gen.choice(nA, p=pol[x, :])]]

						add_traj = True

					else:
						if it > 500:
							stop_inner = True

					it += 1

			i += 1
			stop = (i >= len(started_trajs) or i > 500)
			if add_traj:
				trajs += [np.array(traj)]
				acts += [np.array(a_traj)]

		return np.array(trajs, dtype=object), np.array(acts, dtype=object)

	def trajectory_reward(self, trajs: np.ndarray, task_idx: int = None) -> float:
		r_avg = 0
		X = list(self._mdp[0])
		A = list(self._mdp[1])
		if task_idx is not None:
			c = self._mdp[3][task_idx]
		else:
			c = self._mdp[3]
		gamma = self._mdp[4]
		n_trajs = len(trajs)
		t_idx = 1

		for traj in trajs:
			states = traj[0]
			actions = traj[1]
			r_traj = 0
			g = 1

			for idx in range(len(actions)):
				x = states[idx]
				a = actions[idx]
				r_traj += g * c[X.index(x), A.index(a)]
				g *= gamma

			r_avg += r_traj / n_trajs
			if self._verbose:
				print('MDP trajectory reward! Trajectory nr.%d. %.2f%% done' % (t_idx, t_idx / n_trajs * 100), end='\r')
				t_idx += 1

		if self._verbose:
			print('MDP trajectory reward finished!', end='\n')

		return r_avg

class HighDimLegibleMDP(HighDimMDP):

	def __init__(self, x: np.ndarray, a: List[str], p: Dict[str, np.ndarray], gamma: float, verbose: bool, task: str, task_states: List[Tuple[int, int, str]],
				 tasks: List[str], beta: float, goal_states: List[int], sign: int, q_mdps: Dict[str, np.ndarray]):
		self._task = task
		self._tasks = tasks
		self._task_states = {}
		for task_state in task_states:
			self._task_states[task_state[2]] = tuple([task_state[0], task_state[1]])
		self._tasks_q = q_mdps
		self._beta = beta
		nX = len(x)
		nA = len(a)
		nT = len(tasks)
		c = np.zeros((nT, nX, nA))

		super().__init__(x, a, p, c, gamma, goal_states, 'rewards', verbose)
		for t in range(nT):
			for i in range(nX):
				for j in range(nA):
					c[t, i, j] = self.optimal_legible_cost(i, j, t, sign)

		self._mdp = (x, a, p, c, gamma)

	def update_cost_function(self, sign: int):
		mdp = self.mdp
		x = mdp[0]
		a = mdp[1]
		p = mdp[2]
		gamma = mdp[4]
		nX = len(x)
		nA = len(a)
		nT = len(self._tasks)
		c = np.zeros((nT, nX, nA))

		for t in range(nT):
			for i in range(nX):
				for j in range(nA):
					c[t, i, j] = self.optimal_legible_cost(i, j, t, sign)

		self._mdp = (x, a, p, c, gamma)

	def optimal_legible_cost(self, x: int, a: int, t: int, sign: int) -> float:
		task_cost = np.exp(sign * self._beta * self._tasks_q[self._tasks[t]][x, a])
		tasks_sum = task_cost
		for task in self._tasks:
			if task != self._tasks[t]:
				tasks_sum += np.exp(sign * self._beta * self._tasks_q[task][x, a])

		return task_cost / tasks_sum

	def legible_cost(self, x: int, a: int, t: int, sign: int, dist: np.ndarray) -> float:
		task_cost = np.exp(sign * self._beta * self._tasks_q[self._tasks[t]][x, a]) / (1 / dist[t, x])
		tasks_sum = task_cost
		for task in self._tasks:
			if task != self._tasks[t]:
				tasks_sum += np.exp(sign * self._beta * self._tasks_q[task][x, a]) / (1 / dist[self._tasks.index(task), x])

		return task_cost / tasks_sum


import argparse

from train import main

parser = argparse.ArgumentParser(description='Train prototypical networks')

# data args
default_dataset = 'omniglot'
parser.add_argument('--data.dataset', type=str, default=default_dataset, metavar='DS',
                    help="data set name (default: {:s})".format(default_dataset))
default_split = 'vinyals'
parser.add_argument('--data.split', type=str, default=default_split, metavar='SP',
                    help="split name (default: {:s})".format(default_split))
parser.add_argument('--data.way', type=int, default=60, metavar='WAY',
                    help="number of classes per episode (default: 60)")
parser.add_argument('--data.shot', type=int, default=5, metavar='SHOT',
                    help="number of support examples per class (default: 5)")
parser.add_argument('--data.query', type=int, default=5, metavar='QUERY',
                    help="number of query examples per class (default: 5)")
parser.add_argument('--data.test_way', type=int, default=5, metavar='TESTWAY',
                    help="number of classes per episode in test. 0 means same as data.way (default: 5)")
parser.add_argument('--data.test_shot', type=int, default=0, metavar='TESTSHOT',
                    help="number of support examples per class in test. 0 means same as data.shot (default: 0)")
parser.add_argument('--data.test_query', type=int, default=15, metavar='TESTQUERY',
                    help="number of query examples per class in test. 0 means same as data.query (default: 15)")
parser.add_argument('--data.train_episodes', type=int, default=100, metavar='NTRAIN',
                    help="number of train episodes per epoch (default: 100)")
parser.add_argument('--data.test_episodes', type=int, default=100, metavar='NTEST',
                    help="number of test episodes per epoch (default: 100)")
parser.add_argument('--data.trainval', action='store_true', help="run in train+validation mode (default: False)")
parser.add_argument('--data.sequential', action='store_true', help="use sequential sampler instead of episodic (default: False)")
parser.add_argument('--data.cuda', action='store_true', help="run in CUDA mode (default: False)")

# model args
default_model_name = 'protonet_conv'
default_encoding = 'C64'
parser.add_argument('--model.model_name', type=str, default=default_model_name, metavar='MODELNAME',
                    help="model name (default: {:s})".format(default_model_name))
parser.add_argument('--model.x_dim', type=str, default='1,28,28', metavar='XDIM',
                    help="dimensionality of input images (default: '1,28,28')")
parser.add_argument('--model.hid_dim', type=int, default=64, metavar='HIDDIM',
                    help="dimensionality of hidden layers (default: 64)")
parser.add_argument('--model.z_dim', type=int, default=64, metavar='ZDIM',
                    help="dimensionality of input images (default: 64)")
parser.add_argument('--model.encoding', type=str, default=default_encoding, metavar='MODELENC',
                    help="model encoding (default: {:s})".format(default_encoding))
# train args
parser.add_argument('--train.epochs', type=int, default=10000, metavar='NEPOCHS',
                    help='number of epochs to train (default: 10000)')
parser.add_argument('--train.optim_method', type=str, default='Adam', metavar='OPTIM',
                    help='optimization method (default: Adam)')
parser.add_argument('--train.learning_rate', type=float, default=0.001, metavar='LR',
                    help='learning rate (default: 0.0001)')
parser.add_argument('--train.decay_every', type=int, default=20, metavar='LRDECAY',
                    help='number of epochs after which to decay the learning rate')
default_weight_decay = 0.0
parser.add_argument('--train.weight_decay', type=float, default=default_weight_decay, metavar='WD',
                    help="weight decay (default: {:f})".format(default_weight_decay))
parser.add_argument('--train.patience', type=int, default=200, metavar='PATIENCE',
                    help='number of epochs to wait before validation improvement (default: 1000)')

# log args
default_fields = 'loss,acc'
parser.add_argument('--log.fields', type=str, default=default_fields, metavar='FIELDS',
                    help="fields to monitor during training (default: {:s})".format(default_fields))
default_exp_dir = 'results'
parser.add_argument('--log.exp_dir', type=str, default=default_exp_dir, metavar='EXP_DIR',
                    help="directory where experiments should be saved (default: {:s})".format(default_exp_dir))

# speech data args
parser.add_argument('--speech.include_background', action='store_true', help="mix background noise with samples (default: False)")
parser.add_argument('--speech.include_silence', action='store_true', help="one of the classes out of n should be silence (default: False)")
parser.add_argument('--speech.include_unknown', action='store_true', help="one of the classes out of n should be unknown (default: False)")
parser.add_argument('--speech.sample_rate', type=int, default=16000, help='desired sampling rate of the input')
parser.add_argument('--speech.clip_duration', type=int, default=1000, help='clip duration in milliseconds')
parser.add_argument('--speech.window_size', type=int, default=40)
parser.add_argument('--speech.window_stride', type=int,default=20)
parser.add_argument('--speech.num_features', type=int, default=40, help='Number of mfcc features to extract')
parser.add_argument('--speech.time_shift', type=int, default=100, help='time shift the audio in milliseconds')
parser.add_argument('--speech.bg_volume', type=float, default=0.1, help='background volumen to mix in between 0 and 1')
parser.add_argument('--speech.bg_frequency', type=float, default=1.0, help='Amount of samples that should be mixed with background noise (between 0 and 1)')
parser.add_argument('--speech.num_silence', type=int, default=1000, help='Number of silence samples to generate')
parser.add_argument('--speech.foreground_volume', type=float, default=1)
args = vars(parser.parse_args())

main(args)


#Immediate type casting
""" here we are coverting the data at the run time"""
import os
import datetime

os.system("cls")

today = datetime.date.today()
year = today.year
age = int(input("Please enter your age, we will show the year you are born :"))
BirthYear = year-age
print(BirthYear)


import argparse
from inspect import getmembers, isfunction

import numpy

from deepsparse import compile_model, cpu
from deepsparse.utils import verify_outputs
from sparsezoo.models import classification
from sparsezoo.objects import Model

CORES_PER_SOCKET, AVX_TYPE, _ = cpu.cpu_details()

model_registry = dict(getmembers(classification, isfunction))

def fetch_model(model_name: str) -> Model:
    if model_name not in model_registry:
        raise Exception(
            f"Could not find model '{model_name}' in classification model registry."
        )
    return model_registry[model_name]()

def parse_args():
    parser = argparse.ArgumentParser(
        description="Benchmark and check accuracy of image classification models"
    )

    parser.add_argument(
        "model_name",
        type=str,
        choices=model_registry.keys(),
        help="Model type to analyze",
    )

    parser.add_argument(
        "-s",
        "--batch_size",
        type=int,
        default=64,
        help="The batch size to run the analysis for",
    )
    parser.add_argument(
        "-j",
        "--num_cores",
        type=int,
        default=CORES_PER_SOCKET,
        help=(
            "The number of physical cores to run the analysis on, "
            "defaults to all physical cores available on the system"
        ),
    )

    return parser.parse_args()

def calculate_top1_accuracy(pred: numpy.array, labels: numpy.array) -> float:
    """
    :param pred: the model's prediction to compare with
    :param labels: the labels for the data to compare to
    :return: the calculated top1 accuracy
    """
    batch_size = pred.shape[0]
    pred = numpy.argmax(pred, axis=-1)
    labels = numpy.argmax(labels, axis=-1)

    correct = (pred == labels).sum()
    correct *= 100.0 / batch_size

    return correct

def main():
    args = parse_args()
    model = fetch_model(args.model_name)
    batch_size = args.batch_size
    num_cores = args.num_cores

    # Gather batch of data
    batch = model.sample_batch(batch_size=batch_size)
    batched_inputs = batch["inputs"]
    batched_outputs = batch["outputs"]

    # Compile model for inference
    print("Compiling {} model with DeepSparse Engine".format(model.architecture_id))
    engine = compile_model(model, batch_size, num_cores)
    print(engine)

    # INFERENCE
    # Record output from inference through the DeepSparse Engine
    print("Executing...")
    predicted_outputs = engine(batched_inputs)

    # Compare against reference model output
    verify_outputs(predicted_outputs, batched_outputs)

    if "labels" in batch:
        batched_labels = batch["labels"]
        # Measure accuracy against ground truth labels
        accuracy = calculate_top1_accuracy(predicted_outputs[-1], batched_labels[0])
        print("Top-1 Accuracy for batch size {}: {:.2f}%".format(batch_size, accuracy))

    # BENCHMARK
    # Record output from executing through the DeepSparse engine
    print("Benchmarking...")
    results = engine.benchmark(batched_inputs)
    print(results)

if __name__ == "__main__":
    main()


"""Demonstrates peculiarities of if, for, while and other statements.
"""

#%%
def demonstrate_branching():
    """Details and peculiarities of if statements.
    - is compares id()'s, == compares contents
    - id()'s are the same for equal strings and numbers, but not for lists, user class instances,...
    - the condition of an if-statement need not necessarily be a boolean
    - there can be more than one elif after if (no switch statement, use multiple elif instead)
    """

    from datetime import date
    d1 = date(1942, 6, 18)
    d2 = date.today()
    d3 = date(1942, 6, 18)

    if d1 == d3:
        print(True)
    else:
        print(False)

    if id(d1) == id(d3):
        print(True)
    else:
        print(False)

    print()

    a = 1
    b = 1
    if id(a) == id(b):
        print(True)
    else:
        print(False)

    print()

    if 'Paul':
        print(True)
    else:
        print(False)
    print()

    i = int(input('Enter an int: '))
    if i > 5:
        print('\ni > 5')
    elif i > 7:
        print('\ni > 7')
    elif i > 8:
        print('\ni > 8')
    else:
        print('\ni < 5')
    print()

    return

#%%

# Test demonstrate_branching()
demonstrate_branching()

#%%

def demonstrate_loops():
    """Different kinds of loops. Also break and continue.
    - it is not necessary to iterate through all elements of an iterable
    - step in range()
    - unimportant counter (_)
    - break and continue
    - while loop
    """

    from random import seed, randint
    seed(12)
    l = []
    for i in range(100):
        l.append(randint(10, 20))
    for i in range(10, 20, 2):
        print(i, l[i])
    print()

    for _ in range(5):
        print('Paul McCartney')
    print()

    return

#%%
# Test demonstrate_loops()
demonstrate_loops()


from tensorflow import keras
import losses, train, models
import tensorflow_addons as tfa
import os

# basic_model = models.buildin_models("ResNet101V2", dropout=0.4, emb_shape=512, output_layer="E")
# basic_model = models.buildin_models("ResNest50", dropout=0.4, emb_shape=512, output_layer="E")
# basic_model = models.buildin_models('EfficientNetB4', dropout=0, emb_shape=256, output_layer="GDC")
# basic_model = mobile_facenet.mobile_facenet(256, dropout=0, name="mobile_facenet_256")
# basic_model = mobile_facenet.mobile_facenet(256, dropout=0, name="se_mobile_facenet_256", use_se=True)
#basic_model = models.buildin_models("MobileNet", dropout=0, emb_shape=256, output_layer="GDC")
model_name = "binarydensenet"
basic_model = models.buildin_models(model_name, dropout=0, emb_shape=256, output_layer="GDC")
dataset_name = 'ms1m-retinaface-t1'
data_path = os.path.join('.','datasets',dataset_name)
eval_paths = [os.path.join(data_path,bin_file) for bin_file in ['lfw.bin','cfp_fp.bin','agedb_30.bin']]

tt = train.Train(data_path, save_path='keras_'+model_name+'_'+dataset_name+'.h5', eval_paths=eval_paths,
                basic_model=basic_model, lr_base=0.1, batch_size=128, random_status=2)
#optimizer = tfa.optimizers.AdamW(weight_decay=5e-5)
optimizer = tfa.optimizers.SGDW(learning_rate=0.1, weight_decay=5e-4, momentum=0.9)

sch = [
  #{"loss": keras.losses.CategoricalCrossentropy(label_smoothing=0.1), "centerloss": 0.01, "optimizer": optimizer, "epoch": 20},
  #{"loss": keras.losses.CategoricalCrossentropy(label_smoothing=0.1), "centerloss": 0.1, "epoch": 20},
  #{"loss": keras.losses.CategoricalCrossentropy(label_smoothing=0.1), "centerloss": 0.5, "epoch": 20},
  #{"loss": losses.ArcfaceLoss(), "epoch": 20, "triplet": 64, "alpha": 0.3},
  #{"loss": losses.ArcfaceLoss(), "epoch": 20, "triplet": 64, "alpha": 0.25},
  {"loss": losses.ArcfaceLoss(scale=64), "epoch": 50,"optimizer":optimizer},
]
tt.train(sch, 0)


import unittest
from typing import List, Type

import casadi as cs
import numpy as np
from parameterized import parameterized, parameterized_class
from scipy import io

from csnlp import Nlp, Solution, scaling, wrappers
from csnlp.multistart import ParallelMultistartNlp, StackedMultistartNlp
from csnlp.multistart.multistart_nlp import MultistartNlp

OPTS = {
    "expand": True,
    "print_time": False,
    "ipopt": {
        "max_iter": 500,
        "sb": "yes",
        # for debugging
        "print_level": 0,
        "print_user_options": "no",
        "print_options_documentation": "no",
    },
}
EXAMPLES_DATA_FILENAME = r"tests/examples_data.mat"
RESULTS = io.loadmat(EXAMPLES_DATA_FILENAME, simplify_cells=True)
# io.savemat(EXAMPLES_DATA_FILENAME, {**RESULTS, "multistart_nlp_fs": fs})

@parameterized_class("sym_type", [("SX",), ("MX",)])
class TestExamples(unittest.TestCase):
    def test__chain(self):
        N = 40
        m = 40 / N
        D = 70 * N / 2
        g = 9.81
        L = 1
        nlp = Nlp(sym_type=self.sym_type)
        p = nlp.variable("p", (2, N))[0]
        x, y = p[0, :], p[1, :]
        V = D * cs.sum2(
            (cs.sqrt(cs.diff(x) ** 2 + cs.diff(y) ** 2) - L / N) ** 2
        ) + g * m * cs.sum2(y)
        nlp.minimize(V)
        nlp.init_solver(OPTS)
        nlp.constraint("c1", p[:, 0], "==", [-2, 1])
        nlp.constraint("c2", p[:, -1], "==", [2, 1])
        nlp.constraint("c3", y, ">=", cs.cos(0.1 * x) - 0.5)
        nlp = nlp.copy()
        sol = nlp(vals0={"p": np.row_stack((np.linspace(-2, 2, N), np.ones(y.shape)))})
        np.testing.assert_allclose(sol.vals["p"], RESULTS["chain_p"])

    def test__multistart_nlp(self):
        def func(x):
            return (
                -0.3 * x**2
                - np.exp(-10 * x**2)
                + np.exp(-100 * (x - 1) ** 2)
                + np.exp(-100 * (x - 1.5) ** 2)
            )

        N = 3
        LB, UB = -0.5, 1.4
        x0s = [0.9, 0.5, 1.1]
        args = ([{"p0": 0, "p1": 1} for _ in x0s], [{"x": x0} for x0 in x0s])

        nlps: List[MultistartNlp] = [
            StackedMultistartNlp(starts=N, sym_type=self.sym_type),
            ParallelMultistartNlp(starts=N, n_jobs=N, sym_type=self.sym_type),
        ]
        sols = []
        for nlp in nlps:
            x = nlp.variable("x", lb=LB, ub=UB)[0]
            nlp.parameter("p0")
            nlp.parameter("p1")
            nlp.minimize(func(x))
            nlp.init_solver(OPTS)
            nlp = nlp.copy()

            best_sol: Solution = nlp.solve_multi(*args)
            all_sols: List[Solution] = nlp.solve_multi(*args, return_all_sols=True)
            fs = [all_sol.f for all_sol in all_sols]
            self.assertEqual(best_sol.f, min(fs))
            np.testing.assert_allclose(fs, RESULTS["multistart_nlp_fs"])

            all_sols.sort()
            sols.append(all_sols)

        for sol1, sol2 in zip(*sols):
            self.assertEqual(sol1.success, sol2.success)
            np.testing.assert_allclose(sol1.f, sol2.f)
            np.testing.assert_allclose(sol1.vals["x"], sol2.vals["x"])
            np.testing.assert_allclose(
                sol1.value(nlps[0].lam_lbx), sol2.value(nlps[1].lam_lbx), atol=1e-6
            )
            np.testing.assert_allclose(
                sol1.value(nlps[0].lam_ubx), sol2.value(nlps[1].lam_ubx), atol=1e-6
            )

    @parameterized.expand([("single",), ("multi",)])
    def test__optimal_ctrl(self, shooting: str):
        x = cs.MX.sym("x", 2)
        u = cs.MX.sym("u")
        ode = cs.vertcat((1 - x[1] ** 2) * x[0] - x[1] + u, x[0])
        f = cs.Function("f", [x, u], [ode], ["x", "u"], ["ode"])
        T = 10
        N = 20
        intg_options = {"simplify": True, "number_of_finite_elements": 4}
        dae = {"x": x, "p": u, "ode": f(x, u)}
        intg = cs.integrator("intg", "rk", dae, 0.0, T / N, intg_options)
        res = intg(x0=x, p=u)
        x_next = res["xf"]
        F = cs.Function("F", [x, u], [x_next], ["x", "u"], ["x_next"])
        mpc = wrappers.Mpc(
            nlp=Nlp(sym_type=self.sym_type),
            prediction_horizon=N,
            shooting=shooting,
        )
        u, _ = mpc.action("u", lb=-1, ub=+1)
        if shooting == "single":
            mpc.state("x", 2)
            mpc.set_dynamics(F)
            x = mpc.states["x"]  # only accessible after dynamics have been set
            mpc.constraint("c0", x, ">=", -0.2)
        else:
            x, _ = mpc.state("x", 2, lb=-0.2)  # must be created before dynamics
            mpc.set_dynamics(F)
        mpc.minimize(cs.sumsqr(x) + cs.sumsqr(u))
        mpc.init_solver(OPTS)
        mpc = mpc.copy()
        sol = mpc.solve(pars={"x_0": [0, 1]})
        u_opt = sol.vals["u"].full().flat
        np.testing.assert_allclose(
            u_opt, RESULTS["optimal_ctrl_u"], rtol=1e-6, atol=1e-6
        )

    def test__rosenbrock(self):
        nlp = Nlp(sym_type=self.sym_type)
        x = nlp.variable("x", (2, 1))[0]
        r = nlp.parameter("r")
        f = (1 - x[0]) ** 2 + (x[1] - x[0] ** 2) ** 2
        nlp.minimize(f)
        nlp.constraint("con1", cs.sumsqr(x), "<=", r)
        nlp.init_solver(OPTS)
        nlp = nlp.copy()
        r_values = np.linspace(1, 3, 25)
        f_values = []
        lam_values = []
        for r_value in r_values:
            sol = nlp.solve(pars={"r": r_value})
            f_values.append(sol.f)
            lam_values.append(sol.dual_vals["lam_h_con1"])
        f_values = np.asarray(f_values).squeeze()
        lam_values = np.asarray(lam_values).squeeze()
        np.testing.assert_allclose(f_values, RESULTS["rosenbrock_f"])
        np.testing.assert_allclose(lam_values, RESULTS["rosenbrock_lam"])

    def test__sensitivity(self):
        def z1(x, lam, p):
            return (x[1, :] ** p[1] - x[0, :]) * cs.exp(-10 * lam + p[0]) / p[1]

        def z2(x):
            return x[1, :] - x[0, :]

        def z3(x, p):
            return x[1, :] ** (1 / p[1]) - x[0, :]

        def z4(lam, p):
            return cs.exp(-10 * lam + p[0]) / p[1]

        nlp = wrappers.NlpSensitivity(Nlp(sym_type=self.sym_type))
        x = nlp.variable("x", (2, 1), lb=[[0], [-np.inf]])[0]
        p = nlp.parameter("p", (2, 1))
        nlp.minimize((1 - x[0]) ** 2 + p[0] * (x[1] - x[0] ** 2) ** 2)
        g = (x[0] + 0.5) ** 2 + x[1] ** 2
        nlp.constraint("c1", (p[1] / 2) ** 2, "<=", g)
        _, lam = nlp.constraint("c2", g, "<=", p[1] ** 2)
        opts = {"print_time": False, "ipopt": {"sb": "yes", "print_level": 0}}
        nlp.init_solver(opts)
        nlp = nlp.copy()
        Z = cs.blockcat(
            [
                [z1(x, lam, p) ** 2, z2(x)],
                [1 / (1 + z3(x, p)), z4(lam, p)],
                [z3(x, p) * (-1 - 10 * z1(x, lam, p)), z4(lam, p) / (1 + z2(x))],
            ]
        )
        z0, j0, h0 = [], [], []
        J, H = nlp.parametric_sensitivity(expr=Z, second_order=True)
        for p0 in (1.2, 1.45, 1.9):
            sol = nlp.solve(pars={"p": [0.2, p0]})
            z0.append(sol.value(Z))
            j0.append(sol.value(J))
            h0.append(sol.value(H))
        z0 = np.asarray(z0).squeeze()
        j0 = np.asarray(j0).squeeze()
        h0 = np.asarray(h0).squeeze()
        np.testing.assert_allclose(RESULTS["sensitivity_z"], z0, rtol=1e-6, atol=1e-7)
        np.testing.assert_allclose(RESULTS["sensitivity_j"], j0, rtol=1e-6, atol=1e-7)
        np.testing.assert_allclose(RESULTS["sensitivity_h"], h0, rtol=1e-6, atol=1e-7)

    @parameterized.expand([(StackedMultistartNlp,), (ParallelMultistartNlp,)])
    def test__scaling(self, multinlp_cls: Type):
        def get_dynamics(g: float, alpha: float, dt: float) -> cs.Function:
            x, u = cs.SX.sym("x", 3), cs.SX.sym("u")
            x_next = x + cs.vertcat(x[1], u / x[2] - g, -alpha * u) * dt
            return cs.Function("F", [x, u], [x_next], ["x", "u"], ["x+"])

        N = 100
        T = 100
        K = 3
        dt = T / N
        m0 = 500000
        yT = 100000
        g = 9.81
        alpha = 1 / (300 * g)
        seed = 69
        rng = np.random.default_rng(seed)
        kwargs = {"n_jobs": -1} if multinlp_cls is ParallelMultistartNlp else {}
        nlp = multinlp_cls(sym_type="SX", starts=K, **kwargs)

        y_nom = 1e5
        v_nom = 2e3
        m_nom = 3e5
        x_nom = cs.vertcat(y_nom, v_nom, m_nom)
        u_nom = 1e8
        scaler = scaling.Scaler()
        scaler.register("x", scale=x_nom)
        scaler.register("x_0", scale=x_nom)
        scaler.register("u", scale=u_nom)
        nlp = wrappers.NlpScaling(nlp, scaler=scaler)

        mpc = wrappers.Mpc(nlp, prediction_horizon=N)
        x, _ = mpc.state("x", 3, lb=cs.DM([-cs.inf, -cs.inf, 0]))
        y = x[0, :]
        m = x[2, :]
        u, _ = mpc.action("u", lb=0, ub=5e7)
        mpc.set_dynamics(get_dynamics(g, alpha, dt))
        x0 = cs.vertcat(0, 0, m0)
        mpc.constraint("yT", y[-1], "==", yT)
        mpc.minimize(m[0] - m[-1])
        mpc.init_solver(OPTS)
        mpc = mpc.copy()

        x_init = cs.repmat([0, 0, 1e5], 1, N + 1)

        pars = [{"x_0": x0}] * K
        vals0 = [
            {
                "x": x_init + rng.random(x_init.shape) * 1e4,
                "u": rng.random() * 1e8,
            }
            for _ in range(K)
        ]
        us, fs = [], []
        for i in range(K + 1):
            sol = mpc.solve(pars[i], vals0[i]) if i != K else mpc(pars, vals0)
            fs.append(sol.f)
            us.append(sol.value(u))
        us, fs = np.asarray(us).squeeze(), np.asarray(fs).squeeze()

        np.testing.assert_almost_equal(fs[-1], fs[:-1].min(), decimal=2)
        np.testing.assert_allclose(RESULTS["scaling_fs"], fs, rtol=1e-6, atol=1e-7)
        np.testing.assert_allclose(RESULTS["scaling_us"], us, rtol=1e-6, atol=1e-7)

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


from time import perf_counter_ns
import cv2
from cv2 import THRESH_BINARY
import numpy as np
import imutils
import pytesseract
import Sudoku
import argparse

input_board = [[0,0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0,0]]

# Check for arguments in command line
parser = argparse.ArgumentParser()
parser.add_argument('-d', action='store_true')
args = parser.parse_args()

# First match the image with the sudoku board template
# to locate the sudoku board within the template ###########################################################################################
# Read the template
template = cv2.imread('template.jpg')
# Convert the template to grayscale
template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
# Get the Canny edges for increased accuracy
#template = cv2.Canny(template, 50, 200)

# Store width and height of template
(tH, tW) = template.shape[:2]

# Display the template's canny edges
if args.d:
    cv2.imshow("Template", template)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

# Create a mask for the contents of each box
ret, mask = cv2.threshold(template, 200, 255, cv2.THRESH_BINARY)

# Invert the colours of the mask
mask = cv2.bitwise_not(mask)

# Display the Mask
if args.d:
    cv2.imshow("Mask", mask)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

# Now begin multiscaling the image
# Read the main image
img_rgb = cv2.imread('pic.jpg')

# Convert it to grayscale
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)

# Keep track of the region and scale of the image with the best match
found = None

# Loop over the scales of the image
for scale in np.linspace(0.2, 1.0, 40)[::-1] :
    # resize the image according to the scale, and keep track
    # of the ratio of the resizing
    resized = imutils.resize(img_gray, width = int(img_gray.shape[1] * scale))
    r = img_gray.shape[1] / float(resized.shape[1])

    # if the resized image is smaller than the template, then break
    # from the loop
    if resized.shape[0] < tH or resized.shape[1] < tW:
        break

    # detect edges in the resized, grayscale image and apply template
    # matching to find the template in the image
    result = cv2.matchTemplate(resized, template, cv2.TM_SQDIFF, None, mask)
    (minVal, _, minLoc, _) = cv2.minMaxLoc(result)

    # Visualize the iteration
    # draw a bounding box around the detected region
    if args.d:
        print("Smaller value = closer the match")
        print(minVal)
        clone = np.dstack([resized, resized, resized])
        cv2.rectangle(clone, (minLoc[0], minLoc[1]),
            (minLoc[0] + tW, minLoc[1] + tH), (0, 0, 255), 2)
        cv2.imshow("Visualize", clone)
        cv2.waitKey(0)

    # if we have found a new maximum correlation value, then update
    # the bookkeeping variable
    if found is None or minVal < found[0]:
        found = (minVal, minLoc, r)

# unpack the bookkeeping variable and compute the (x, y) coordinates
# of the bounding box based on the resized ratio
(_, minLoc, r) = found
(startX, startY) = (int(minLoc[0] * r), int(minLoc[1] * r))
(endX, endY) = (int((minLoc[0] + tW) * r), int((minLoc[1] + tH) * r))

# draw a bounding box around the detected result and display the image
if args.d:
    cv2.rectangle(img_rgb, (startX, startY), (endX, endY), (0, 0, 255), 2)
    cv2.imshow("Image", img_rgb)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

# Next we will detect the numbers that are found within the bounding box #################################################################
pytesseract.pytesseract.tesseract_cmd = 'C:\\Program Files\\Tesseract-OCR\\tesseract.exe'

# Crop the image to only read the sudoku box
img_crop = img_rgb[startY:endY, startX:endX].copy()

# Resizing to a larger image will help tesseract detect the numbers
img_crop = cv2.resize(img_crop, None, fx=1.3, fy=1.3, interpolation=cv2.INTER_CUBIC)

# Tesseract only works with RGB images, OpenCV uses BGR
img_text = cv2.cvtColor(img_crop, cv2.COLOR_BGR2GRAY)

hImg, wImg = img_text.shape

# Define the size of each box in the sudoku grid
boxW = int(wImg/9)
boxH = int(hImg/9)

# Remove horizontal and vertical lines
kernel_vertical = cv2.getStructuringElement(cv2.MORPH_RECT, (1,50))
temp1 = 255 - cv2.morphologyEx(img_text, cv2.MORPH_CLOSE, kernel_vertical)
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (50,1))
temp2 = 255 - cv2.morphologyEx(img_text, cv2.MORPH_CLOSE, horizontal_kernel)
temp3 = cv2.add(temp1, temp2)
result = cv2.add(temp3, img_text)
img_text = result

img_text = cv2.medianBlur(img_text, 5)

img_text = cv2.adaptiveThreshold(img_text,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
            cv2.THRESH_BINARY,11,2)

boxes = pytesseract.image_to_boxes(img_text, config="--psm 6 -c tessedit_char_whitelist=0123456789 --tessdata-dir 'C:\\Program Files\\Tesseract-OCR\\tessdata'")

for b in boxes.splitlines() :
    b = b.split(' ')
    print(b)
    x, y, w, h = int(b[1]), int(b[2]), int(b[3]), int(b[4])
    cv2.rectangle(img_text, (x,hImg-y), (w,hImg-h), (0,0,255), 1)
    cv2.putText(img_text, b[0], (x, hImg-y+25), cv2.FONT_HERSHEY_PLAIN, 1, (50, 50, 255), 2)

    # Get the coordinates of the found digit
    centerx = int((x+w)/2)
    centery = int(hImg - (y+h)/2)

    # Check which row the digit is in
    row = 0
    for row_ in range(9) :
        if centerx < (row_ * boxW + boxW) :
            row = row_
            break

    # Check which col the digit is in
    col = 0
    for col_ in range(9) :
        if centery < (col_ * boxH + boxH) :
            col = col_
            break

    # Enter the digit into our board
    input_board[col][row] = int(b[0])

# Display the detected board in the terminal
print("\nThe input board is:")
print(np.matrix(input_board))

# Show the detected digits
if args.d:
    cv2.imshow("Text", img_text)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

# Solve the sudoku puzzle
print("\nThe solved board is:")
Sudoku.solve(input_board)

# Remove unnecessary characters from text document
with open(r'Solution.txt', 'r') as infile, \
     open(r'Formatted_Solution.txt', 'w') as outfile:
    data = infile.read()
    data = data.replace("[", " ")
    data = data.replace("]", " ")
    outfile.write(data)

# Generate an array from the text document
solved_board = np.genfromtxt("Formatted_Solution.txt", dtype=int)

# Iterate through the rows and columns, entering the solutions into the empty spaces
for row in range (9) :
    for col in range (9) :
        Xcoord = int(row * boxW + 0.25 * boxW)
        Ycoord = int(col * boxH + 0.75 * boxH)

        if input_board[col][row] == 0:
            cv2.putText(img_crop, str(solved_board[col][row]), (Xcoord, Ycoord), cv2.FONT_HERSHEY_DUPLEX, 3, (50, 50, 255), 2)

cv2.imshow("Solution", img_crop)

cv2.waitKey(0)
cv2.destroyAllWindows()


from django.contrib.auth import get_user_model

from rest_framework import serializers

from apps.chat.models import Message, Room

User = get_user_model()

class UserSerializer(serializers.ModelSerializer):
    """Сериализатор пользователя"""
    class Meta:
        model = User
        fields = ["id", "username"]

class MessageSerializer(serializers.ModelSerializer):
    """Сериализатор сообщения"""
    user = UserSerializer()
    read_count = serializers.SerializerMethodField()
    members_count = serializers.SerializerMethodField()

    class Meta:
        model = Message
        fields = [
            "id", "text", "user", "created_at", "read_count", "members_count"
        ]

    def get_read_count(self, obj: Message):
        return obj.read_users.count()

    def get_members_count(self, obj: Message):
        return obj.room.current_users.count()

class RoomDetailSerializer(serializers.ModelSerializer):
    """Сериализатор комнаты"""
    room_messages = MessageSerializer(many=True)

    class Meta:
        model = Room
        fields = ["id", "name", "room_messages", "current_users"]

    def to_representation(self, instance):
        data = super().to_representation(instance)
        data['user'] = self.context["request"].user.id
        return data

class RoomSerializer(serializers.ModelSerializer):
    """Сериализатор комнат"""
    messages = MessageSerializer(many=True, read_only=True)

    class Meta:
        model = Room
        fields = ["id", "name", "host", "messages", "current_users"]
        read_only_fields = ["id", "messages", "host", "current_users"]

    def create(self, validated_data):
        validated_data["host"] = self.context["request"].user
        return super().create(validated_data)


# -*- coding: utf-8 -*-
"""
Created on Wed Sep  7 09:05:37 2022

@author: Lala
"""
# TALLER 3

import numpy as np
import sympy as sym

# Ejercicios raíces

# 3)

def f(x):
    return 3*x**5 + 5*x**4 - x**3

def deriv(f,x,h=1e-6):
    return (f(x+h)-f(x-h))/(2*h)

def NewtonMethod(f,df,xn,itmax=1000,precision=1e-5):
    error = 1
    it = 0

    while error > precision and it < itmax:
        try:
            xn1 = xn - f(xn)/df(f,xn)
            error = np.abs(f(xn)/df(f,xn))

        except ZeroDivisionError:
            print('Division entre cero')

        xn = xn1
        it += 1

    if it == itmax:
        return False
    else:
        return xn

def GetAllRoots(x,tolerancia=6):
    roots = np.array([])

    for i in x:
        root = NewtonMethod(f, deriv, i)

        if root != False:
            croot = np.round(root,tolerancia)

            if croot not in roots:
                roots = np.append(roots,croot)

    roots.sort()
    return roots

xtrial = np.linspace(-1000,1000,1000)
roots = GetAllRoots(xtrial)
print("raíces:", roots, "\n")

# 4)

def GetLegendre(n):
    x = sym.Symbol('x',Real=True)
    y = sym.Symbol('y',Real=True)

    y = (x**2-1)**n

    p = sym.diff(y,x,n)/(2**n * np.math.factorial(n))
    return p

n=20
Legendre = []

for i in range(n):
    Legendre.append(GetLegendre(i))

def GetAllRootsLegendre(X,tolerancia=6):
        roots = np.array([])

        for i in X:
            for i in range(n):
                root = NewtonMethod(Legendre[n], deriv, i)

            if root != False:
                croot = np.round(root,tolerancia)

                if croot not in roots:
                    roots = np.append(roots,croot)

        roots.sort()
        return roots

roots_Legendre = []
for i in range(n):
    root_Legendre = GetAllRootsLegendre(xtrial)
    roots_Legendre.append(root_Legendre)

# 5)

def GetLaguerre(n):
    x = sym.Symbol('x',Real=True)
    y = sym.Symbol('y',Real=True)

    y = sym.exp(-x)*x**n

    p = sym.exp(x)*sym.diff(y,x,n)/(np.math.factorial(n))
    return p

Laguerre = []

for i in range(n):
    Laguerre.append(GetLaguerre(i))

def GetAllRootsLaguerre(X,tolerancia=6):
        roots = np.array([])

        for i in X:
            for i in range(n):
                root = NewtonMethod(Laguerre[n], deriv, i)

            if root != False:
                croot = np.round(root,tolerancia)

                if croot not in roots:
                    roots = np.append(roots,croot)

        roots.sort()
        return roots

roots_Laguerre = []
for i in range(n):
    root_Laguerre = GetAllRootsLaguerre(xtrial)
    roots_Laguerre.append(root_Laguerre)


# https://atcoder.jp/contests/abc133/tasks/abc133_d

# Ai= xi+x(i+1) と置くと
# x1は即座に求まる。なぜならば、A1-A2+A3-A4...+AN = 2*x1となることは式変形からすぐにわかる。
# x1がわかるとx2以降は芋づる式に求まる。
# 入力が10**5とかになったときに100ms程度早い
import sys
read = sys.stdin.readline

def read_ints():
    return list(map(int, read().split()))

N = int(input())
A = read_ints()

x1 = 0
for i, a in enumerate(A):
    if i & 1:  # 奇数ならば
        x1 -= a
    else:  # 偶数ならば
        x1 += a
# x1 //= 2

ans = [x1]
xi = x1
for a in A:
    xi = 2 * a - xi
    ans.append(xi)
print(*ans[:-1])


import time
import requests
from fastapi import Form, Depends, File
from fastapi import APIRouter, UploadFile, HTTPException
from sqlalchemy.orm import Session

from core.config import settings
from db.session import get_db
from db.repository.csam_ratio import get_db_data
from schemas.ng import ShowNG

from apis.inspect.base import inspect

router = APIRouter()

@router.post("/upload_file", response_model=ShowNG)
def predict_NG_chips(
    file: UploadFile = File(...), lot_no: str = Form(...), db: Session = Depends(get_db)
):
    print("Received file to process, please wait...")
    start = time.time()
    # Check if lot number exists or if its for testing
    if lot_no.lower()[:4] == "test":
        chip_type = settings.CHIPTYPE
    else:
        prass = requests.get(settings.PRASS_URL + lot_no).json()
        if prass[settings.LOT_NO_COL] == None:
            raise HTTPException(
                status_code=404, detail=f"Lot number: {lot_no} not found in database"
            )
        chip_type = prass[settings.CHIP_TYPE_COL]
    try:
        chips_dict, save_dir, img_shape, no_of_batches, no_of_chips = inspect(
            file, lot_no, db
        )
    except:
        raise HTTPException(
            status_code=400, detail=f"Error while processing uploaded file"
        )

    res = ShowNG(
        plate_no=file.filename.split(".")[0],
        chips=chips_dict,
        img_shape=img_shape,
        no_of_chips=no_of_chips,
        no_of_batches=no_of_batches,
        directory=save_dir,
        chip_type=chip_type,
    )

    print(f"Total Time taken: {round(time.time()-start,2)}")

    return res

@router.get("/read_db")
def read_db(db: Session = Depends(get_db)):
    ratio = get_db_data(db=db)
    return ratio


import matplotlib.pyplot as plt;
import pandas as pd
import numpy as np
from sklearn.naive_bayes import GaussianNB
from sklearn.ensemble import RandomForestClassifier , AdaBoostClassifier
from sklearn import tree
from sklearn.ensemble import VotingClassifier
from sklearn import preprocessing
from sklearn import metrics
from sklearn.metrics import accuracy_score

trainSize = 400000
testSize = 50000
size = trainSize+testSize # 400000 for taining and 50000 for testing
data = pd.read_csv("mixed.csv", nrows=size)
data = data.drop(columns="No.")
columns_titles = ["Time", "Source", "Destination", "Length", "Info", "Protocol"]
data = data.reindex(columns=columns_titles)
label_names = np.unique(data.iloc[:,5])

le = preprocessing.LabelEncoder()
data.iloc[:,1] = le.fit_transform(data.iloc[:,1])
data.iloc[:,2] = le.fit_transform(data.iloc[:,2])
data.iloc[:,4] = le.fit_transform(data.iloc[:,4])
data.iloc[:,5] = le.fit_transform(data.iloc[:,5])

def chooseObsMan(dic_f):
    chosenIDs=np.array(())
    for k,d in dic_f.items():
        temp=np.where(y_train==k)[0]
        if temp.size < dic_f[k]:
            temp = dic_f[k]
        z=np.random.choice(temp,dic_f[k],replace=False)
        chosenIDs=np.concatenate((chosenIDs,z))
    return np.int64(chosenIDs)
def label_index(row,threshold=0):

    if threshold==0:
        threshold=np.max(row)
    temp_i=np.where(row>=threshold)[0]
    if temp_i.shape[0]>0:
        return temp_i[0]+1
    else:
        return -1

y_train = data.iloc[:trainSize,5]
x_train = data.iloc[:trainSize,:-1]
#x_train = preprocessing.normalize(data.iloc[:trainSize,:-1])

y_test = data.iloc[trainSize:,5]
x_test = data.iloc[trainSize:,:-1]
#x_test = preprocessing.normalize(data.iloc[trainSize:,:-1])

li = {}
r = int(size/100000 + 1)*30
for i in np.unique(data.iloc[:,-1]):
    if data['Protocol'].value_counts()[i] < r:
        li.update({i : data['Protocol'].value_counts()[i]})
    else :
        li.update({i : r})

labelled=np.zeros(x_train.shape[0])
labelled[:]=-1
labelledIndex=chooseObsMan(li)
labelled[labelledIndex]=y_train[labelledIndex]

#---------------------------------------------OurModel----------------------------------------
clfs ={}

#clf1=GaussianNB()
#clf2=KNeighborsClassifier(n_jobs=-1)
clf3=RandomForestClassifier ( n_estimators = 20 , random_state = 0 ,n_jobs=-1)
#clf4=SVC(kernel='rbf', probability=True)
clf5=tree.DecisionTreeClassifier()
clf7=AdaBoostClassifier()
#clf8=QuadraticDiscriminantAnalysis()

clfs1=[('AdaBoost', clf7),('j48', clf5), ('RFC', clf3)]
ensemble_models = VotingClassifier(estimators=clfs1, voting='soft')

threshold=0.3
leftNumber=-1
temp_left_Group=np.arange(x_train.shape[0])
for i in range(0,x_train.shape[0]):
    temp_left=sum(labelled==-1)
    #print(i, temp_left)
    if temp_left<=0:
        break
    #ensemble_models = VotingClassifier(estimators=clfs1, voting='soft')
    ensemble_models.fit(x_train[labelled!=-1],y_train[labelled!=-1])
    predicted=ensemble_models.predict_proba(x_train[labelled==-1])
    final_decition=np.apply_along_axis(label_index, 1, predicted,threshold)
    labelled[labelled==-1]=final_decition
    if temp_left==leftNumber:
        threshold-0.01
    threshold_step=0.01
    leftNumber=temp_left
    temp_left=sum(labelled==-1)
    temp_left_Group[i]=temp_left
    #print(temp_left, threshold, (final_decition != -1).mean() *400000 , (predicted != -1).mean() *400000)
    if i >0:
        change_rate=temp_left_Group[i-1] - temp_left_Group[i]
        #print(change_rate)
        if(change_rate<1000):
            threshold=threshold-threshold_step

print("------------------------------------Our Module---------------------------------------")
print('threshold step=',threshold_step)

print('\n*********Training*********\n')

pre=labelled[labelled!=-1]
org=y_train[labelled!=-1]
pop=metrics.precision_recall_fscore_support(org, pre)
results = pd.DataFrame()
for i in range(0,len(pop)):
    if len(pop[0]) > np.unique(data.iloc[:,5]).shape[0]:
        temp = pd.DataFrame([pop[i][:-1]],columns=label_names)
    else :
        temp = pd.DataFrame([pop[i]],columns=label_names)

    results=results.append(temp, ignore_index=True)
#print(len(clfs1),'Classifier')

results.insert(0,'  ',['Precision','Recall','Fscore','Support'])
print(results)
resultsDataFrame1 = results
correctLabelled=metrics.accuracy_score(org, pre,normalize=False)
incorrectLabelled=sum(results.iloc[3,1:])-correctLabelled
print([correctLabelled,incorrectLabelled])
numbers=results.iloc[3,1:]
correctLabelledForEachclass=results.iloc[3,1:] *results.iloc[1,1:]
incorrectLabelledForEachclass=results.iloc[3,1:]-correctLabelledForEachclass
results1 = pd.DataFrame(columns = ['Total','Correct', 'Incorrect'])
results1['Total'] = numbers
results1['Correct'] = correctLabelledForEachclass
results1['Incorrect'] = incorrectLabelledForEachclass
print(results1)


from django.conf.urls import url, include
from jerarquia import views

urlpatterns = [
    url(r'^jerarquia/$', views.jerarquia, name='jerarquia'),
    url(r'^editar/(?P<codigo_unico>\w+)/$', views.consulta_codigo, name='consulta'),
    url(r'^aprobar/', views.aprobar, name='aprobar'),
    url(r'^aprobar_cambio/(?P<codigo_unico>\w+)/$', views.consulta_cambio, name='aprobar_cambio'),
    url(r'^cerrar/$', views.cerrar_jerarquia, name='cerrar'),
    url(r'^descarga_especial/$', views.descarga_especial, name='descarga_especial'),
    url(r'^descarga_jerarquia/$', views.descarga_jerarquia, name='descarga_jerarquia'),
    url(r'^formulario_aprobador/$', views.formularios_vista_aprobador, name='vista_aprobador'),
    url(r'^nuevo_agente/$', views.nuevo_agente, name='agregar_agente'),]


import logging

import torch
from torch import nn
import torch.nn.functional as F
from torchmetrics.functional.classification.accuracy import accuracy
import pytorch_lightning as pl
import numpy as np

from .warmup_scheduler import WarmupScheduler

class AbstractBaseClassifierModel(pl.LightningModule):
    """Abstract class classifiers.
    Reusable code for clasifier models.
    To make new classifiers, just implement the initializer and the forward method
    """

    def __init__(self,
                 optimizer=None, optimizer_kwargs={},
                 scheduler=None, scheduler_kwargs={},
                 param_scheduler=None, param_scheduler_kwargs={},
                 warmup_epochs=0, eval_mode='class_accuracy',
                 shift_seed=7,shift_max=None,
                 shift_samples=None,shift_patch_size=None
    ):
        super().__init__()
        self.optimizer_fn = optimizer if optimizer is not None else torch.optim.Adam
        self.optimizer_kwargs = optimizer_kwargs
        self.scheduler_fn = scheduler
        self.scheduler_kwargs = scheduler_kwargs
        self.param_scheduler_fn = param_scheduler
        self.param_scheduler_kwargs = param_scheduler_kwargs
        self.warmup_epochs = warmup_epochs

        # Evaluation settings
        self.eval_mode = eval_mode
        self.shift_seed = shift_seed
        self.shift_max = shift_max
        self.shift_samples = shift_samples
        self.shift_patch_size = shift_patch_size
        logging.info(f'Evaluation mode: {self.eval_mode}')

    # logic for a single training step
    def training_step(self, batch, batch_idx):
        x, y = batch
        logits = self(x)
        loss = F.nll_loss(logits, y)

        # training metrics
        preds = torch.argmax(logits, dim=1)
        acc = accuracy(preds, y)
        self.log('train_loss', loss, on_step=True, on_epoch=True, logger=True)
        self.log('train_acc', acc, on_step=True, on_epoch=True, logger=True)
        return loss

    # logic for a single validation step
    def validation_step(self, batch, batch_idx):
        x, y = batch
        logits = self(x)
        loss = F.nll_loss(logits, y)

        # validation metrics
        preds = torch.argmax(logits, dim=1)
        acc = accuracy(preds, y)
        self.log('val_loss',loss,prog_bar=True,sync_dist=True)
        self.log('val_acc',acc,prog_bar=True,sync_dist=True)
        return loss

    def on_test_start(self) -> None:
        """Called when the test begins."""
        np.random.seed(self.shift_seed)

    # logic for a single testing step
    def test_step(self, batch, batch_idx):
        x, y = batch
        logits = self(x)
        loss = F.nll_loss(logits, y)

        # test metrics
        if self.eval_mode=='class_accuracy':
            preds = torch.argmax(logits,dim=1)
            acc = accuracy(preds,y)
            self.log('test_loss',loss,prog_bar=True,sync_dist=True)
            self.log('test_acc',acc,prog_bar=True,sync_dist=True)
        elif self.eval_mode=='shift_consistency':
            self.eval_consistency_step(batch,batch_idx,'test','shift')
            self.eval_consistency_step(batch,batch_idx,'test','circular')
        return loss

    def eval_consistency_step(self, batch, batch_idx,
                              val_mode='test', mode='shift'):
        assert mode in ['shift', 'circular']
        x,_ = batch

        # Read dataset from 'inc_conv1_support'
        if self.inc_conv1_support: dataset = 'imagenet'
        else: dataset = 'cifar10'

        if dataset=='imagenet':
            outputs = []
            if mode == 'shift':
                # Pass shifted inputs
                offsets = [np.random.randint(self.shift_max,size=2) for j in range(0,self.shift_samples)]
                for j in range(0,self.shift_samples):
                    outputs.append(self(x[:,:,offsets[j][0]:offsets[j][0]+self.shift_patch_size,offsets[j][1]:offsets[j][1]+self.shift_patch_size]))
                # Compute consistency
                cur_agree = self.agreement(outputs,self.shift_samples).type(torch.FloatTensor).to(outputs[0].device)
            elif mode == 'circular':
                # Pass rolled inputs
                # -max to max for comparison purposes
                offsets = [np.random.randint(-self.shift_max,self.shift_max,size=2) for j in range(0,self.shift_samples)]
                for j in range(0,self.shift_samples):
                    outputs.append(self(torch.roll(x,shifts=(offsets[j][0],offsets[j][1]),dims=(2,3))))
                # Compute consistency
                cur_agree = self.agreement(outputs,self.shift_samples).type(torch.FloatTensor).to(outputs[0].device)
        elif dataset=='cifar10':
            max_shift = 3
            random_shift1 = torch.randint(-max_shift, max_shift, (2,))
            random_shift2 = torch.randint(-max_shift, max_shift, (2,))
            if mode == 'shift':
                pad_lengths = (max_shift, max_shift, max_shift, max_shift)
                i1_l, i1_r = random_shift1[0] + max_shift, random_shift1[0]-max_shift
                j1_l, j1_r = random_shift1[1] + max_shift, random_shift1[1]-max_shift
                i2_l, i2_r = random_shift2[0] + max_shift, random_shift2[0]-max_shift
                j2_l, j2_r = random_shift2[1] + max_shift, random_shift2[1]-max_shift
                shifted_x1 = F.pad(x, pad_lengths)[:, :, i1_l:i1_r, j1_l:j1_r ]
                shifted_x2 = F.pad(x, pad_lengths)[:, :, i2_l:i2_r, j2_l:j2_r ]
            elif mode == 'circular':
                shifted_x1 = torch.roll(x, shifts = (random_shift1[0], random_shift1[1]), dims = (2, 3))
                shifted_x2 = torch.roll(x, shifts = (random_shift2[0], random_shift2[1]), dims = (2, 3))

            # Compute consistency
            shifted_preds1 = torch.argmax(self(shifted_x1),1)
            shifted_preds2 = torch.argmax(self(shifted_x2),1)
            cur_agree = accuracy(shifted_preds1,shifted_preds2)
        self.log('%s_%s_consistency' % (val_mode, mode), cur_agree, prog_bar=True)
        return

    # (Core) Compute consistency
    def agreement(self,outputs,robust_num):
        preds = torch.stack([output.argmax(dim=1,keepdim=False) for output in outputs], dim=0)
        similarity = torch.sum((preds == preds[0:1,:]).int(), dim=0)
        agree = 100*torch.mean((similarity == robust_num).float())
        return agree

    def optimizer_step( self,epoch,batch_idx,
                        optimizer,optimizer_idx,optimizer_closure,
                        on_tpu,using_native_amp,using_lbfgs):
        """Called when the train epoch begins."""
        # Lr warmup
        if self.current_epoch < self.warmup_epochs:
            it_curr = self.trainer.num_training_batches*self.current_epoch+1+batch_idx
            it_max = self.trainer.num_training_batches*self.warmup_epochs
            lr_scale = float(it_curr) / it_max
            for pg in self.trainer.optimizers[0].param_groups:
                pg['lr'] = lr_scale * self.learning_rate

        # Update params
        optimizer.step(closure=optimizer_closure)
        optimizer.zero_grad()

    def configure_optimizers(self):
        logging.info(f'Configuring optimizer: {self.optimizer_fn} with {self.optimizer_kwargs}')

        # Filter net/pool parameters
        net_pars, pool_pars = [], []
        for n,p in self.named_parameters():
            if "component_selection" in n and p.requires_grad_:
                pool_pars.append(p)
            elif p.requires_grad_:
                net_pars.append(p)

        # Set opt
        # Start lr at 0 if warmup #moved to WarmUpScheduler
        #_lr = self.learning_rate
        #print('*************************************************************_lr',_lr)
        _lr= 0 if self.warmup_epochs!=0 else self.learning_rate
        #optimizer = self.optimizer_fn([{'params': net_pars,
        #                                'lr': _lr},
        #                               {'params': pool_pars,
        #                                'weight_decay': 0,
        #                                'lr': _lr}],
        #                              lr=_lr,
        #                              **self.optimizer_kwargs)
        optimizer = self.optimizer_fn([{'params': net_pars},
                                       {'params': pool_pars,'weight_decay': 0}],
                                      lr=_lr,
                                      **self.optimizer_kwargs)

        if self.scheduler_fn is None:
            return optimizer

        logging.info(f'Configuring lr scheduler: {self.scheduler_fn} with {self.scheduler_kwargs}')
        if isinstance(self.scheduler_fn, list):
            schedulers = [sch_fn(optimizer, **sch_kwargs) for sch_fn, sch_kwargs in zip(self.scheduler_fn, self.scheduler_kwargs)]
        else:
            schedulers = [
                {'scheduler': self.scheduler_fn(optimizer, **self.scheduler_kwargs),
                 'frequency': 1,
                 'name': 'main_lr_scheduler'
                 }]

        #if self.warmup_epochs > 0:
        #    schedulers.append({'scheduler': WarmupScheduler(optimizer,
        #                                                    warmup_steps=self.warmup_epochs),
        #                       'frequency': 1,
        #                       'name': 'warmup_scaled_lr'})

        return [optimizer], schedulers

    def configure_callbacks(self):
        if self.param_scheduler_fn is not None:
            logging.info(f'Configuring tau scheduler: {self.param_scheduler_fn} with {self.param_scheduler_kwargs}')
            return [self.param_scheduler_fn('gumbel_tau', **self.param_scheduler_kwargs)]
        return super().configure_callbacks()


def search_in_matrix(matrix, size, search):
    for row in range(size):
        for col in range(size):
            if matrix[row][col] == search:
                return row, col

def get_new_position(command, current_position):
    new_row, new_col = current_position[0], current_position[1]
    if command == "up":
        new_row -= 1
    elif command == "down":
        new_row += 1
    elif command == "right":
        new_col += 1
    elif command == "left":
        new_col -= 1
    return new_row, new_col

def is_inside_territory(row, col, size):
    return 0 <= row < size and 0 <= col < size

def print_result(food_quantity, matrix):
    print(f"Food eaten: {food_quantity}")
    [print("".join(row)) for row in matrix]

size = int(input())
field = [list(input()) for _ in range(size)]
snake_position = search_in_matrix(field, size, "S")
eaten_food = 0

while eaten_food < 10:
    command = input()
    new_row, new_col = get_new_position(command, snake_position)

    if not is_inside_territory(new_row, new_col, size):
        field[snake_position[0]][snake_position[1]] = "."
        print("Game over!")
        break

    elif field[new_row][new_col] == "*":
        eaten_food += 1

    elif field[new_row][new_col] == "B":
        field[new_row][new_col] = "."
        new_row, new_col = search_in_matrix(field, size, "B")

    field[new_row][new_col] = "S"
    field[snake_position[0]][snake_position[1]] = "."
    snake_position = search_in_matrix(field, size, "S")

else:
    print("You won! You fed the snake.")

print_result(eaten_food, field)


import pytest

from vexl import parse
from vexl.visitors import EvaluationVisitor

cases = [
    # Null
    ["null", None],
    # Booleans
    ["false", False],
    ["true", True],
    # Numbers
    ["0", 0],
    ["1", 1],
    ["3.14", 3.14],
    ["0.6", 0.6],
    ["42.0", 42],
    ["999999999", 999999999],
    # Identifiers
    ["a", None],
    ["word", None],
    ["b6_a4_c3", None],
    # Unary operators
    ["not null", None],
    ["not false", True],
    ["not true", False],
    ["not not null", None],
    ["not not false", False],
    ["not not true", True],
    # Boolean operators
    ["1 and 2", 2],
    ["1 and 2 and 3", 3],
    ["1 or 2", 1],
    ["1 or 2 or 3", 1],
    ["not 1 and 2", False],
    ["not 1 or 2", 2],
    ["1 and not 2", False],
    ["1 or not 2", 1],
    ["1 and 2 or 3", 2],
    ["1 or 2 and 3", 1],
    ["(1 or 2) and 3", 3],
    # Binary operators
]

@pytest.mark.parametrize("expr,value", cases)
def test_evaluate(expr, value):
    assert EvaluationVisitor({}).visit(parse(expr)) == value