#Intially install all these libraries
#Import the libraries
import speech_recognition as sr
import pyttsx3
import pywhatkit
import datetime
import pyjokes
import wikipedia

#Need to initiate the system to recognize your voice
listener = sr.Recognizer() #Create a recognizer object
engine = pyttsx3.init() #Initialize the text-to-speech engine from pyttsx3 library

def talk(text):
    engine.say(text) #Convert Speech to Text
    engine.runAndWait()

def take_command():
    try:
        with sr.Microphone() as source: #Microphone as the audio source
            listener.adjust_for_ambient_noise(source) #Adjust for ambient noise
            print("listening....")
            voice = listener.listen(source) #Listen for audio input
            command = listener.recognize_google(voice) #Use Google Speech Recognizer to convert speech to text
            command = command.lower()
            if 'Friday' in command: #Check if the wake word Friday is present in the command
                command = command.replace('Friday', '') #Removing the way word when responding
                print(command)

    except:
        pass
    return command

def run_candy():
    command = take_command() #Get command from user
    print(command)
    if 'youtube' in command:
        play = command.replace('youtube', '')
        talk('playing' + play)
        pywhatkit.playonyt(play) #Use the pywhatkit to play the Youtube video

    elif 'time' in command:
        time = datetime.datetime.now().strftime('%I:%M %p')
        talk('Current time is ' + time) #Speak the current time
        print(time)

    elif 'joke' in command:
        joke = pyjokes.get_joke() #Get a random joke from pyjokes library
        talk(joke)
        print(joke)

    elif 'who is' in command:
        search_query = command.replace('who is', '')
        results = wikipedia.summary(search_query, sentences=2) #Get a summary from Wikipedia about the search query
        talk('Here is what I found on Wikipedia: ' + results)
        print(results)

    else:
        talk('Sorry, I didn\'t understand that. Can you please repeat?') #Speak a default message
        print('Sorry, I didn\'t understand that. Can you please repeat?')

run_candy() #Run the main function


import cv2 as cv

# read image
img = cv.imread("./data/3-people.jpg")
cv.imshow("Messi", img)

# grayscale
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
cv.imshow("Gray", gray)

haar_cascade = cv.CascadeClassifier('haarcascade_frontalface_default.xml')
faces_rect = haar_cascade.detectMultiScale(gray, scaleFactor=1.5, minNeighbors=6)
print(len(faces_rect))
for (x, y, w, h) in faces_rect:
    cv.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)

cv.imshow("Face Detection", img)

cv.waitKey(0)


##encoding=utf-8

"""
Unique index是指对某个所有的值两两不同的关键字创建的索引, 也就是和_id关键字具有相同的性质。类似
与关系数据库中的unique constrain。
"""

from introduction import client, db
from pprint import pprint as ppt
import pymongo

col = db.col # 使用col这个collection进行演示
col.drop() # 重置collection

def initialize_collection():
    col.insert({"a": 1, "b": 1})
    col.insert({"a": 2, "b": 2})
    col.insert({"a": 3, "b": 3})

def use_unique_index():
    """建立了unique index之后, 该field就跟_id一样, 不可以重复了
    """
    col.create_index([("a", pymongo.ASCENDING)], unique=True)
    col.insert({"a": 1})

def use_multiple_unique_index():
    """为多个field建立unique index, 可以保证多个field的组合的唯一性。
    """
    col.create_index([("a", pymongo.ASCENDING), ("b", pymongo.ASCENDING)],
                     unique=True)
    col.insert({"a": 1, "b": 2}) # ok
    col.insert({"a": 1, "b": 1, "c": 1}) # DuplicateKeyError

if __name__ == "__main__":
    """本例用于演示unique index对唯一性的限制
    """
    initialize_collection()
#     use_unique_index()
#     use_multiple_unique_index()
    client.close()


from pylab import *
import cv2
from Right_or_Left import left_right
img1 = cv2.imread('left.png',0)
img2 = cv2.imread('right.png',0)
order121=left_right(img1,img2)
order122=left_right(img2,img1)
print(order121)
print(order122)
if order121:
    print('The img1 is captured from the left side')
    imgl=img1
    imgr=img2
else:
    print('The img2 is captured from the left side')
    imgl=img2
    imgr=img1
stereo = cv2.StereoBM_create( 16, 15)
disparity = stereo.compute(imgl, imgr)
imshow(disparity,'gray')


#parts of variables: 1.variable name(exp: num1) 2. variable value(exp: 5)
#exp of using def as function
#the def RETURNS the sum of 2 PARAMETERS(variables passed into the function)

def ratiocalculator (num1, num2):
    global sum
    sum = num1/num2

def sumsqr():
    return sum**2   # equals to 2/(Sum*Sum)

Num1 = int(input('Enter first numer:'))
Num2 = int(input('Enter second numer:'))

#call def sumcalculator
ratiocalculator(Num1, Num2) #specified argument
print(sum)
#
#call def sumsqr
squared_sum = sumsqr()  #none specified argument
print(squared_sum)
#


"""

 scrape_google_images.py  (author: Anson Wong / git: ankonzoid)

 Scrapes the top k images from Google Images for a particular query.

"""
import os, json, time
import requests
import urllib.request as urllibreq
from bs4 import BeautifulSoup

def scrape_google_images(query, k, outDir, dt_stall):
    print("Scraping top k={} Google images for query: '{}'".format(k, query))

    # Create output directory
    if not os.path.exists(outDir):
        os.mkdir(outDir)

    # Construct image url to scrape from
    url = "https://www.google.co.in/search?q=" + \
          '+'.join(query.split()) + "&source=lnms&tbm=isch"
    header = {'User-Agent': "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36"}

    # Download html + parse it to get all image urls
    html = urllibreq.urlopen(urllibreq.Request(url, headers=header))
    soup = BeautifulSoup(html,'html.parser')
    urls = [json.loads(x.text)["ou"]
            for x in soup.find_all("div", {"class": "rg_meta"})]
    print("Parsed {} google image urls!".format(len(urls)))

    # Download top-k images
    for i, url in enumerate(urls[:min(k, len(urls))]):
        imgFile = os.path.join(outDir, query + "-" + str(i+1) + ".jpg")
        print("[{}/{}] Downloading image {} to '{}'...".format(i+1, k, url, imgFile))
        try:
            with open(imgFile, 'wb') as handle:
                response = requests.get(url, stream=True)
                if not response.ok:
                    print(response)
                for block in response.iter_content(1024):
                    if not block:
                        break
                    handle.write(block)
            time.sleep(dt_stall)  # force pause
        except:
            raise Exception("  -> Failed downloading: " + url)

query = "drake"  # google images query text
k = 5  # top-k images will be scraped
outDir = os.path.join(os.getcwd(), "output")  # output directory to save images
dt_stall = 2  # number of seconds to stall between image scrapes
scrape_google_images(query=query, k=k, outDir=outDir, dt_stall=dt_stall)


from tkinter import filedialog
from tkinter import *
from math import pi

html_template1 = """

<title>Title</title>

Текст в формате html

"""
html_template2 = """.

"""

def click():
    if entry.get().isdigit():
        inp = float(entry.get())
        try:
            res = (4 * pi * inp ** 3) / 3
            label_answer.config(text=res)
        except:
            label_answer.config(text="Ошибка, введите число!")
    else:
        label_answer.config(text="Ошибка, введите число!")

def savefileastxt():
    var = str(label_answer.cget("text"))
    if var != "":
        try:
            path = filedialog.asksaveasfile(filetypes=(("Text files", "*.txt"), ("All files", "*.*"))).name
            window.title('Результат сохранен')
        except:
            return
        with open(path + ".txt", 'w') as f:
            f.write("Ответ для радиуса длины " + str(entry.get()) + " = " + str(label_answer.cget("text")))
            f.close()
    else:
        pass

def savefileashtml():
    var = str(label_answer.cget("text"))
    if var != "":
        try:
            path = filedialog.asksaveasfile(filetypes=(("Html file", "*.html"), ("All files", "*.*"))).name
            window.title('Результат сохранен')
        except:
            return
        with open(path + ".html", 'w') as f:
            f.write(html_template1)
            f.write("Ответ для радиуса длины " + str(entry.get()) + " = " + str(label_answer.cget("text")))
            f.write(html_template2)
            f.close()
    else:
        pass

window = Tk()
window.title('Сохранение текста')
window.config(bg="DarkGray")

label_inp = Label(text="Введите радиус ->", width=30, borderwidth=1, relief="solid", font=('Courier', 16), bg="Cyan")
label_inp.grid(row=0, column=0, pady=10, padx=10)

label_ans = Label(text="Результат вычислений ->", width=30, borderwidth=1, relief="solid",
                  font=('Courier', 16), bg="Cyan")
label_ans.grid(row=3, column=0, pady=10, padx=10)

label_answer = Label(width=30, borderwidth=1, relief="solid", font=('Courier', 16), bg="Cyan")
label_answer.grid(row=3, column=1, pady=10, padx=10)

entry = Entry(width=30, borderwidth=1, relief="solid", font=('Courier', 16))
entry.grid(row=0, column=1, pady=10, padx=10)

button_calc = Button(text="Вычислить", width=20, command=click, font=('Courier', 16), bg="lime")
button_calc.grid(row=1, column=0, columnspan=3, pady=10, padx=10)

button_txt_save = Button(text="Сохранить в .txt", width=20, command=savefileastxt, font=('Courier', 16), bg="lime")
button_txt_save.grid(row=4, column=0, columnspan=1, pady=10, padx=10)

button_html_save = Button(text="Сохранить в .html", width=20, command=savefileashtml, font=('Courier', 16), bg="lime")
button_html_save.grid(row=4, column=1, columnspan=1, pady=10, padx=10)

button_exit = Button(window, text='Выход', width=20, command=window.destroy, font=('Courier', 16), bg="lime")
button_exit.grid(row=6, column=0, columnspan=3, pady=10, padx=10)

window.mainloop()


from sympy import symbols, Matrix, cos, sin, diff, transpose

"""
This is a basic example of how to compute jacobians and
turn it into simpler c++ code using symbolic programming (sympy).

The equations can be much more complicated and sympy will easily
calculate the derivatives for you.
"""

phi, theta, psi, mx, my, mz = symbols("phi theta psi mx my mz")
R2 = Matrix([[cos(psi), -sin(psi), 0], [sin(psi), cos(psi), 0], [0, 0, 1]])
R1 = Matrix([[cos(theta), 0, sin(theta)], [0, 1, 0], [-sin(theta), 0, cos(theta)]])
R0 = Matrix([[1, 0, 0], [0, cos(phi), -sin(phi)], [0, sin(phi), cos(phi)]])
m = Matrix([mx, my, mz])

print(diff(transpose(R2 * R1 * R0) * m, phi))
print(diff(transpose(R2 * R1 * R0) * m, theta))
print(diff(transpose(R2 * R1 * R0) * m, psi))

j1 = str(diff(transpose(R2 * R1 * R0) * m, phi))
j2 = str(diff(transpose(R2 * R1 * R0) * m, theta))
j3 = str(diff(transpose(R2 * R1 * R0) * m, psi))

assert (
    j1
    == "Matrix([[0], [mx*(sin(phi)*sin(psi) + sin(theta)*cos(phi)*cos(psi)) + my*(-sin(phi)*cos(psi) + sin(psi)*sin(theta)*cos(phi)) + mz*cos(phi)*cos(theta)], [mx*(-sin(phi)*sin(theta)*cos(psi) + sin(psi)*cos(phi)) + my*(-sin(phi)*sin(psi)*sin(theta) - cos(phi)*cos(psi)) - mz*sin(phi)*cos(theta)]])"
)
assert (
    j2
    == "Matrix([[-mx*sin(theta)*cos(psi) - my*sin(psi)*sin(theta) - mz*cos(theta)], [mx*sin(phi)*cos(psi)*cos(theta) + my*sin(phi)*sin(psi)*cos(theta) - mz*sin(phi)*sin(theta)], [mx*cos(phi)*cos(psi)*cos(theta) + my*sin(psi)*cos(phi)*cos(theta) - mz*sin(theta)*cos(phi)]])"
)
assert (
    j3
    == "Matrix([[-mx*sin(psi)*cos(theta) + my*cos(psi)*cos(theta)], [mx*(-sin(phi)*sin(psi)*sin(theta) - cos(phi)*cos(psi)) + my*(sin(phi)*sin(theta)*cos(psi) - sin(psi)*cos(phi))], [mx*(sin(phi)*cos(psi) - sin(psi)*sin(theta)*cos(phi)) + my*(sin(phi)*sin(psi) + sin(theta)*cos(phi)*cos(psi))]])"
)

j1 = j1.replace("sin(phi)", "s0")
j1 = j1.replace("cos(phi)", "c0")
j1 = j1.replace("sin(theta)", "s1")
j1 = j1.replace("cos(theta)", "c1")
j1 = j1.replace("sin(psi)", "s2")
j1 = j1.replace("cos(psi)", "c2")

print(j1)

j2 = j2.replace("sin(phi)", "s0")
j2 = j2.replace("cos(phi)", "c0")
j2 = j2.replace("sin(theta)", "s1")
j2 = j2.replace("cos(theta)", "c1")
j2 = j2.replace("sin(psi)", "s2")
j2 = j2.replace("cos(psi)", "c2")

print(j2)

j3 = j3.replace("sin(phi)", "s0")
j3 = j3.replace("cos(phi)", "c0")
j3 = j3.replace("sin(theta)", "s1")
j3 = j3.replace("cos(theta)", "c1")
j3 = j3.replace("sin(psi)", "s2")
j3 = j3.replace("cos(psi)", "c2")

print(j3)


import igraph
import matplotlib
import numpy as np
from igraph import Graph
from numpy.core.fromnumeric import mean, size
import matplotlib.pyplot as plt
from numpy.random.bit_generator import SeedlessSeedSequence

from game import HDG

class Lattice2d:
    """
    Class use to create and manipulate 2d lattices of individuals of 2 types (here in our case dove and hawk).

    Parameters
    ----------
    width : int, dim of the 2dlattice
    height : int, dim of the 2dlattice
    radius : int, radius use to generate edges ine the lattice (cf lattice)
    """

    def __init__(self, width: int, height: int, radius: int) -> None:
        self.w = width
        self.h = height
        self.graph = Graph.Lattice(dim=[height,width],circular=True,nei= radius)

    def fill_graph(self, population: list) -> None:
        """
        Fill the 2d graph by the sample population sent as parameter.

        Parameters
        ----------
        population : list
            Population is a list of D/H that will be placed in the graph vertices dictionnary under the key value.
        """
        if( len(population) != self.w*self.h):
            raise NameError("The given population does not match the size of the graph")
        self.graph.vs["value"] = population

    def get_neighborhood_conformation(self, id: int) -> tuple[int,int]:
        """
        Return a tuple of int containing the number of Hawk and  the number of Dove in the neighborhood

        Parameters
        ----------
        id : list, id of the vertice at for which we want to know the neighborhood.
        """
        if( (id > self.w*self.h-1) or id<0):
            raise NameError("Id is invalid")

        neis = self.graph.neighbors(id)
        vertices = self.graph.vs
        nb_dove = 0
        nb_hawk = 0

        for elem in neis:
            nb_dove += vertices[elem].attributes()["value"]
        nb_hawk = len(neis)-nb_dove

        return (nb_hawk, nb_dove)

    def change_edges(self, p: float) -> None:
        """
        Update the graph by selecting each edge and changing it by an edge between two random vertices with a proba p.
        We will not choose edges that leaves isolated points.

        Parameters
        ----------
        p : float, proba of changing an edge
        """
        edges = []
        for elem in self.graph.es:
            edges.append(elem.tuple)

        id_limit = len(self.graph.vs)
        neighbors_numbers = [len(self.get_neighbors(i)) for i in range(id_limit)]
        replaced_edges = []
        new_edges = []
        for id, e in enumerate(edges):
            if(np.random.random() <= p):
                replaced_edges.append(e)
                end = False
                id_v1 = 0
                id_v2 = 0
                edge = (0,0)
                while( not end):
                    id_v1 = np.random.randint(0,id_limit)
                    id_v2 = np.random.randint(0,id_limit)
                    edge = (id_v1, id_v2)
                    if( (id_v1 != id_v2) and (not edge in edges) and (not edge in new_edges)):
                        end = True
                        new_edges.append(edge)

        for new_edge,edge in zip(new_edges,replaced_edges):
            # We make sure that no point is left alone without edge
            if ( (neighbors_numbers[edge[0]] > 1) and (neighbors_numbers[edge[1]] > 1) ):
                self.graph.delete_edges([edge])
                self.graph.add_edges([new_edge])
                # We update the number of neighbors
                neighbors_numbers[edge[0]] -= 1
                neighbors_numbers[edge[1]] -= 1
                neighbors_numbers[new_edge[0]] += 1
                neighbors_numbers[new_edge[1]] += 1

    def get_neighbors(self, index: int) -> list:
        return self.graph.neighbors(index)

    def get_vertices(self):
        return self.graph.vs

    def print_vertices(self) -> None:
        for v in self.graph.vs:
            print(v)

class InfiniteNPlayerHDGNetworkDynamic:
    """
    Class that will generate a network as a 2dLattice and include the methods used to update the graph following a game
    payoff matrix.

    Parameters
    ----------
    c_h : float, Cost for the hawks
    R : float, Reward
    width : int, dim of the 2dlattice
    height : int, dim of the 2dlattice
    radius : int, radius use to generate edges ine the lattice (cf lattice)
    population : list, list of values to put in the graph (each vertice will contain a value)
    mode : int, 0 for lattice only and 1 for small world
    """

    CONST_HAWK = 0
    CONST_DOVE = 1
    CONST_W = 5
    CONST_MODE_LATTICE = 0
    CONST_MODE_SW = 1
    CONST_PROBA_EDGE_SW = 0.05 # Probrability of an edge changing in the small world sim

    def __init__(self, c_h: float, R: float, width: int, height: int, radius: int, population: list, mode: int) -> None:
        # generate the network that contains all the information/method concerning the graph
        self.network = Lattice2d(width, height, radius)
        self.network.fill_graph(population)
        self.mode = mode

        # Create a game with N = numbers of neigbhorhood of each vertices  + the one being tested which is fixed for the Lattice
        # but the N will change for each loop and vertex when using smal world (cf update)
        self.game = HDG(len(self.network.get_neighbors(0))+1, c_h, R)

    def update(self) -> None:
        """
        Update the graph vertices values by following the process:
            - If small world mode update the graph by changing the edges following a fixed probability
            - Calculate a G_i (gain) for the vertice i by playing against all the neighbor link to this vertex
            - Select a vertex j in the neighborhood
            - If the strategy of j !=i then we calculate G_j as if i was of type j
            - Calculate the probablity of replacing i by j by following a fermi function
            - Update the graph vertices with the new list of values
        """
        # If small world we change the edges
        if( self.mode == self.CONST_MODE_SW):
            self.network.change_edges(self.CONST_PROBA_EDGE_SW)

        gain_i_list = []
        gain_j_list = []
        new_pop = []
        vertices = self.network.get_vertices()
        for i in range(len(vertices)):
            # For Hawk the strategy is zero and for Dove it is 1
            strategy = vertices[i].attributes()["value"]

            nb_dove = self.network.get_neighborhood_conformation(i)[1] + strategy

            # If we are in the small world configuration we need to update N of the game before calculating the payoff
            if(self.mode == self.CONST_MODE_SW):
                self.game.set_N(len(self.network.get_neighbors(i))+1)

            gains = self.game.expected_payoffs(nb_dove)
            gain_i_list.append(gains[strategy])

            neis = self.network.get_neighbors(i)
            index_selected = np.random.randint(0,len(neis))
            # If the selected neighbor is of the same type we put -1 if not we put Gj
            if(vertices[neis[index_selected]].attributes()["value"] == strategy):
                gain_j_list.append(-1)
                new_pop.append(strategy)
            else:
                gain_j_list.append(gains[not strategy])
                # We need to calculate the probability of changing the strategy of the vertice i p = 1/(1+exp(-w*(G_i-G_j)))
                proba = 1/(1+ np.exp(-self.CONST_W*( gains[not strategy] - gains[strategy])))
                if( np.random.random() <= proba):
                    new_pop.append(not strategy)

                else:
                    new_pop.append(strategy)

        self.network.fill_graph(new_pop)

    def calculate_dove_ratio(self) -> float:
        value_list = self.network.graph.vs()["value"]
        return sum(value_list)/len(value_list)

    @staticmethod
    def generate_population(size: int, ratio_dove: float) -> list:
        if( ratio_dove > 1 or ratio_dove < 0):
            raise NameError("Invalid ratio of doves")

        binomial_samples = np.random.binomial(1,ratio_dove,size)

        return binomial_samples

if __name__ == "__main__":

    if True:
        w = 25
        h = 25
        x = 0.5
        radius_list = [i for i in range(1,5)]
        R = 1.0
        c_h_list = [i/100 for i in range(0,101)]
        results = []
        mode = InfiniteNPlayerHDGNetworkDynamic.CONST_MODE_SW

        nb_saved = 10
        steps = 50

        results = []
        for radius in radius_list:
            result = []
            # We iterate over all values of c_h and simulate for each the comportement of a population randomly sample with a
            # fixed ratio of dove/hawk and save the ratio of dove at the end of each loop of a c_h
            for elem in c_h_list:
                pop = InfiniteNPlayerHDGNetworkDynamic.generate_population(w*h, x)
                obj = InfiniteNPlayerHDGNetworkDynamic(c_h=elem, R=R, width=w, height=h, population=pop, radius=radius, mode=mode)

                list_values = []
                for i in range(steps):
                    if(i >= steps-nb_saved):
                        list_values.append(obj.calculate_dove_ratio())
                    obj.update()

                result.append(np.around(mean(list_values),decimals=4))
                print("End of step : " + str(elem) )

            results.append(result)

        N = [5, 13, 25, 41]

        plt.figure(figsize=(10,10))
        if(mode == InfiniteNPlayerHDGNetworkDynamic.CONST_MODE_LATTICE):
            plt.title("Equilibria of the HDG in 2d lattice network")
        elif( mode == InfiniteNPlayerHDGNetworkDynamic.CONST_MODE_SW):
            plt.title("Equilibria of the HDG in small world network")
        plt.axis([0,1,0,1])
        font = {'family':'serif','size':15}
        plt.xlabel("C_h",fontdict=font)
        plt.ylabel("x*",fontdict=font)
        for id,elem in enumerate(results):
            plt.plot(c_h_list, elem, label="N = "+str(N[id]))
            plt.scatter(c_h_list, elem)
        plt.legend(loc="lower right",fontsize="x-large")
        plt.show()


import subprocess
import logging
import sys
from os import walk
from collections import defaultdict
import matplotlib as mpl
import matplotlib.pyplot as plt
from statistics import mean

FORMAT = '%(asctime)-15s - %(levelname)s - %(module)10s:%(lineno)-5d - %(message)s'
logging.basicConfig(stream=sys.stdout, level=logging.INFO, format=FORMAT)
LOG = logging.getLogger(__name__)

def read_file(file_name):
    f = open(file_name, "r")
    result = {}
    idx = -1
    for l in f:
        if "master" in l:
            idx = int(l.split()[1])

        else:
            if idx != -1:
                result[idx] = float(l.split()[2])
                idx = -1

    return mean(result.values())

def plot(w_num):
    data = defaultdict(lambda : [[], []])
    fs = []
    dir_path = "result/100k/"
    for (dirpath, dirnames, filenames) in walk(dir_path):
        fs.extend(filenames)

    for f in fs:
        cats = f.split("&")
        hash_type = cats[0]
        m = int(cats[1].split("m")[0])
        w = int(cats[2].split("w")[0])

        if w == w_num:
            data[hash_type][0].append(m)
            val = read_file(dir_path + f)
            data[hash_type][1].append(val)

    plt.xlabel('Number of masters')
    plt.ylabel('Calculation time')

    plot_line = ['ro-', 'go-']
    for idx, (k, v) in enumerate(data.items()):
        v = list(zip(*sorted(zip(v[0], v[1]))))
        plt.plot(v[0], v[1], plot_line[idx], label=k)

    leg = plt.legend(loc='best', ncol=2, mode="expand", shadow=True, fancybox=True)
    leg.get_frame().set_alpha(0.3)

    plt.savefig(f'plot/result_w{w_num}.png')
    plt.figure().clear()
    plt.close()
    plt.cla()
    plt.clf()

def plot2(m_num):
    data = defaultdict(lambda : [[], []])
    fs = []
    dir_path = "result/100k/"
    for (dirpath, dirnames, filenames) in walk(dir_path):
        fs.extend(filenames)
    for f in fs:
        cats = f.split("&")
        hash_type = cats[0]
        m = int(cats[1].split("m")[0])
        w = int(cats[2].split("w")[0])
        if m == m_num:
            data[hash_type][0].append(w)
            val = read_file(dir_path + f)
            data[hash_type][1].append(val)

    plt.xlabel('Number of workers')
    plt.ylabel('Speed up')

    plot_line = ['ro-', 'go-']
    for idx, (k, v) in enumerate(data.items()):
        v = list(zip(*sorted(zip(v[0], v[1]))))
        v[1] = [(v[1][0] / val) for val in v[1]]
        plt.plot(v[0], v[1], plot_line[idx], label=k)

    leg = plt.legend(loc='best', ncol=2, mode="expand", shadow=True, fancybox=True)
    leg.get_frame().set_alpha(0.3)

    plt.savefig(f'plot/result_m{m_num}.png')
    plt.figure().clear()
    plt.close()
    plt.cla()
    plt.clf()

if __name__ == '__main__':
    LOG.info("start tracing\n")
    w_num = [1]
    m_num = [1, 2, 4, 8]
    for w in w_num:
        plot(w)
    for m in m_num:
        plot2(m)


bl_info = {
    "name": "JSON scene export",
    "author": "Henry Kielmann",
    "blender": (2, 57, 0),
    "version": (0,0,1),
    "location": "File > Export",
    "category": "Import-Export",
    "description": "Exports the scene as JSON document",
    "wiki_url": "http://github.com/henry4k/io_scene_json",
    "tracker_url": "http://github.com/henry4k/io_scene_json"}

import bpy
from bpy.props import StringProperty, FloatProperty, BoolProperty
from bpy_extras.io_utils import ExportHelper

# To support reload properly, try to access a package var, if it's there, reload everything
if "bpy" in locals():
    import imp
    if "export_json" in locals():
        imp.reload(export_json)

class ExportJSON(bpy.types.Operator, ExportHelper):
    bl_idname = "export_scene.json"
    bl_label = "Export JSON"
    bl_options = {'PRESET'}

    filename_ext = ".json"
    filter_glob = StringProperty(default="*.json", options={'HIDDEN'})

    def execute(self, context):
        from . import export_json

        if not self.filepath:
            raise Exception("filepath not set")

        keywords = self.as_keywords(ignore=("check_existing", "filter_glob"))

        return export_json.save(context.scene, **keywords)

def menu_func(self, context):
    self.layout.operator(ExportJSON.bl_idname, text="JSON (.json)")

def register():
    bpy.utils.register_module(__name__)
    bpy.types.INFO_MT_file_export.append(menu_func)

def unregister():
    bpy.utils.unregister_module(__name__)
    bpy.types.INFO_MT_file_export.remove(menu_func)

if __name__ == "__main__":
    register()


from turtle import *
setup()
face=[90,0,-90,180]
n=200
while True:
    for i in range(0,4):
        seth(face[i])
        fd(n)
        n-=3
    if n<=0:
        break


###########################
# 라이브러리 사용
import pandas as pd
import tensorflow as tf

"""1.   과거의 데이터를 준비합니다
2.   모델의 구조를 만듭니다.
3.   데이터로 모델을 학습(FIT)합니다
4.   모델을 이용합니다
"""

###########################
# 파일로부터 데이터 읽어오기
파일경로 = 'https://raw.githubusercontent.com/blackdew/tensorflow1/master/csv/lemonade.csv'
레모네이드 = pd.read_csv(파일경로)
레모네이드.head()

###########################
# 종속변수, 독립변수
독립 = 레모네이드[['온도']]
종속 = 레모네이드[['판매량']]

###########################
# 모델을 만듭니다.
X = tf.keras.layers.Input(shape=[1])    # shape=[독립변수의 갯수]
Y = tf.keras.layers.Dense(1)(X)         # Dense(종속변수의 갯수)(X)
model = tf.keras.models.Model(X, Y)
model.compile(loss='mse')

###########################
# 모델을 학습시킵니다.
model.fit(독립, 종속, epochs=1000, verbose=0)     # epoches : 학습 횟수  / 시간 / 손실률(학습률 지표 = (예측 - 결과)^2)
model.fit(독립, 종속, epochs=10)                  # 손실률이 낮을수록 정확한 것
                                                 # verbose는 출력을 없애는 것
###########################
# 모델을 이용합니다.
print(model.predict(독립))
print(model.predict([[15]]))


"""Variation autoencoder."""

import numpy as np
import tensorflow as tf

from tensorflow import contrib
from tensorflow.contrib import layers

class VariationalAutoencoder(object):
    """Varational Autoencoder.
    """
    def __init__(self, ndims=784, nlatent=2):
        """Initializes a VAE

        Args:
            ndims(int): Number of dimensions in the feature.
            nlatent(int): Number of dimensions in the latent space.
        """

        self._ndims = ndims
        self._nlatent = nlatent

        # Create session
        self.session = tf.Session()
        self.x_placeholder = tf.placeholder(tf.float32, [None, ndims])
        self.learning_rate_placeholder = tf.placeholder(tf.float32, [])

        # Build graph.
        self.z_mean, self.z_log_var = self._encoder(self.x_placeholder)
        self.z = self._sample_z(self.z_mean, self.z_log_var)
        self.outputs_tensor = self._decoder(self.z)

        # Setup loss tensor, predict_tensor, update_op_tensor
        self.loss_tensor = self.loss(self.outputs_tensor, self.x_placeholder,
                                     self.z_mean, self.z_log_var)

        self.update_op_tensor = self.update_op(self.loss_tensor,
                                               self.learning_rate_placeholder)

        # Initialize all variables.
        self.session.run(tf.global_variables_initializer())

    def _sample_z(self, z_mean, z_log_var):
        """Sample z using reparametrize trick.

        Args:
            z_mean (tf.Tensor): The latent mean,
                tensor of dimension (None, 2)
            z_log_var (tf.Tensor): The latent log variance,
                tensor of dimension (None, 2)
        Returns:
            z (tf.Tensor): Random z sampled of dimension (None, 2)
        """
        eps=tf.random_normal(tf.shape(z_mean), 0, 1, dtype=tf.float32)
        z=tf.add(z_mean,tf.multiply(tf.sqrt(tf.exp(z_log_var)),eps))
        return z

    def _encoder(self, x,reuse=True):
        """Encoder block of the network.

        Build a two layer network of fully connected layers, with 100 nodes,
        then 50 nodes. Then two output branches each two 2 nodes representing
        the z_mean and z_log_var.

                             |-> 2 (z_mean)
        Input --> 100 --> 50 -
                             |-> 2 (z_log_var)

        Use activation of tf.nn.softplus.

        Args:
            x (tf.Tensor): The input tensor of dimension (None, 784).
        Returns:
            z_mean(tf.Tensor): The latent mean, tensor of dimension (None, 2).
            z_log_var(tf.Tensor): The latent log variance, tensor of dimension
                (None, 2).
        """
        w0 = tf.Variable(tf.truncated_normal([int(self._ndims), 100],stddev=0.1,dtype=tf.float32))
        b0 = tf.constant(0.,shape=[100],dtype=tf.float32)
        h0 = tf.matmul(x, w0) + b0
        h0 = tf.nn.softplus(h0)
        w1 = tf.Variable(tf.truncated_normal([100, 50],stddev=0.1,dtype=tf.float32))
        b1 = tf.constant(0., shape=[50],dtype=tf.float32)
        h1 = tf.matmul(h0, w1) + b1
        h1 = tf.nn.softplus(h1)
        wo = tf.Variable(tf.truncated_normal([50, self._nlatent * 2],stddev=0.1,dtype=tf.float32))
        bo = tf.constant(0., shape=[self._nlatent * 2],dtype=tf.float32)
        output = tf.matmul(h1, wo) + bo
        z_mean = output[:, :self._nlatent]
        z_log_var = 1e-6 + output[:, self._nlatent:]

        return z_mean, z_log_var

    def _decoder(self, z):
        """From a sampled z, decode back into image.

        Build a three layer network of fully connected layers,
        with 50, 100, 784 nodes. Use activation tf.nn.softplus.
        z (2) --> 50 --> 100 --> 784.

        Args:
            z(tf.Tensor): z from _sample_z of dimension (None, 2).
        Returns:
            f(tf.Tensor): Predicted score, tensor of dimension (None, 784).
        """

        w0 = tf.Variable(tf.truncated_normal([self._nlatent, 50],stddev=0.1,dtype=tf.float32))
        b0 = tf.constant(0., shape=[50],dtype=tf.float32)
        h0 = tf.matmul(z, w0) + b0
        h0 = tf.nn.softplus(h0)
        w1 = tf.Variable(tf.truncated_normal( [50, 100],stddev=0.1,dtype=tf.float32))
        b1 = tf.constant(0, shape=[100],dtype=tf.float32)
        h1 = tf.matmul(h0, w1) + b1
        h1 = tf.nn.softplus(h1)
        wo = tf.Variable(tf.truncated_normal( [100, 784],stddev=0.1,dtype=tf.float32))
        bo = tf.constant(0, shape=[784],dtype=tf.float32)
        f = tf.nn.sigmoid(tf.matmul(h1, wo) + bo)
        f=tf.clip_by_value(f, 1e-8, 1 - 1e-8)

        return f

    def _latent_loss(self, z_mean, z_log_var):
        """Constructs the latent loss.

        Args:
            z_mean(tf.Tensor): Tensor of dimension (None, 2)
            z_log_var(tf.Tensor): Tensor of dimension (None, 2)

        Returns:
            latent_loss: Tensor of dimension (None,). Sum the loss over
            dimension 1.
        """
        latent_loss =0.5 * tf.reduce_sum(tf.square(z_mean) + tf.square(z_log_var) - tf.log(1e-8 + tf.square(z_log_var)) - 1, 1)
        latent_loss=tf.reduce_mean(latent_loss)
        return latent_loss

    def _reconstruction_loss(self, f, y):
        """Constructs the reconstruction loss.
        Args:
            f(tf.Tensor): Predicted score for each example, dimension (None,
                784).
            y(tf.Tensor): Ground truth for each example, dimension (None, 784)
        Returns:
            Tensor for dimension (None,). Sum the loss over dimension 1.
        """
        loss=tf.reduce_sum(tf.squared_difference(f, y))
        loss=tf.reduce_mean(loss)
        return loss
    def loss(self, f, y, z_mean, z_var):
        """Computes the total loss.

        Computes the sum of latent and reconstruction loss then average over
        dimension 0.

        Returns:
            (1) averged loss of latent_loss and reconstruction loss over
                dimension 0.
        """
        REC=self._reconstruction_loss( f, y)
        KLD=self._latent_loss(z_mean,z_var)
        loss=KLD+REC
        return loss
    def update_op(self, loss, learning_rate):
        """Creates the update optimizer.

        Use tf.train.AdamOptimizer to obtain the update op.

        Args:
            loss: Tensor containing the loss function.
            learning_rate: A scalar, learning rate for gradient descent.
        Returns:
            (1) Update opt tensorflow operation.
        """
        train_step = tf.train.AdamOptimizer(learning_rate).minimize(loss)
        return train_step

    def generate_samples(self, z_np):
        """Generates a random sample from the provided z_np.

        Args:
            z_np(numpy.ndarray): Numpy array of dimension (batch_size, 2).

        Returns:
            (1) The sampled images (numpy.ndarray) of dimension (batch_size,
                748).
        """

        y=self.session.run(self.outputs_tensor,feed_dict={self.z:z_np})
        return y


from tkinter import *
from PIL import ImageTk, Image
import subprocess

# widget =GUI elements: button, textboxes,labels, images
# windows= serves as a container to hold or contain these widgets

window = Tk()  # instantiate an instance of a window
window.geometry("1000x650")
window.title("Prodigy's Pursuit")

logo = PhotoImage(file='Grand Logo.png')
window.iconphoto(True, logo)
window.config(background="#E7C6FF")

img = ImageTk.PhotoImage(Image.open("About.png"))
label = Label(window, image=img)
label.pack()
label.place(x=0, y=0)

label = Label(window,
              text="About",
              font=('Grand Royal', 22),
              fg='#3A0CA3',
              bg='#E5B3FE')
label.pack()
label.place(x=60, y=80)

label = Label(window,
              text="Prodigy's Pursuit",
              font=('Grand Royal', 32),
              fg='#3A0CA3',
              bg='#E5B3FE')
label.pack()
label.place(x=60, y=120)

label = Label(window,
              text="This career counselling platform for engineers is\n"
                   "designed to help users explore different engineering\n"
                   "career paths and make informed decisions about their\n"
                   "professional futures. It provides personalized career\n "
                   "guidance based on the user's qualifications, skills, and\n"
                   "interests, along with insights into the current job\n"
                   "market,educational resources, and networking \n"
                   "opportunities.Overall, it is a comprehensive \n"
                   "and user-friendly platform for engineers \n"
                   "to receive guidance and support \n"
                   "throughout their professional journeys.",
              justify="left",
              font=('Cambria', 12),
              fg='#3A0CA3',
              bg='#E5B3FE')
label.pack()
label.place(x="60", y=200)

submit_button = Button(window,
                       text="BACK",
                       font=("Jacques Francois", 15),
                       fg="#E7C6FF",
                       bg="#F72585",
                       activeforeground="#E7C6FF",
                       activebackground="#7209B7",
                       state=ACTIVE)
submit_button.pack(side=RIGHT)
submit_button.place(x=60, y=453)

def on_button_click():
    # Close the current file
    window.destroy()
    # Open the new file
    subprocess.Popen(["python", "HomePage.py"])

button = Button(window,
                text=" ← ",
                command=on_button_click,
                font=("Montserrat", 15),
                fg="#E7C6FF",
                bg="#F72585",
                activeforeground="#E7C6FF",
                activebackground="#7209B7",
                state=ACTIVE)
button.pack()
button.place(x=950, y=10)

window.mainloop()


import re
import random
import os.path as osp

tmp = ''
# 统计正样本数量
pp = 0
# 统计负样本数量
n = 0
# p使用正则表达式将fasta序列进行分词，其中数字决定分词方式
p = re.compile(r'(\w{1})(?!$)')

with open('./input.fasta', 'r') as f1:
    with open('./out/19/train_sorted.tsv', 'w') as f2:
        with open('./out/19/dev_sorted.tsv', 'w') as f3:
            for line in f1.readlines():
                line = line.strip()
                if len(line) == 0:
                    continue
                if line[0] == '>' and len(tmp) == 0:
                    continue
                if line[0] == '>' and len(tmp) > 0:
                    tmp += '\n'
                    res = "train\t0\t\t" + p.sub(r'\1 ', tmp)
                    if random.random() < 0.1:
                        n += 1
                        if random.random() < 0.1:
                            f3.writelines(res)
                        else:
                            f2.writelines(res)
                    tmp = ''
                    continue
                tmp += line


import sys
import dataskema
import dataskema.lang
from dataskema.data_types import DataTypes as t

def test_incoming_params(pat_value):
    args2 = dataskema.Args({'pat_value': pat_value})
    args2.validate({'pat_value': {
        'label': 'Valor del PAT',
        'min-size': 8,
        'max-size': 64,
        'regexp': '^[A-Za-z0-9+/]+\\={0,2}$',
    }})
    print(f"pat_value={str(pat_value)}")

if __name__ == '__main__':
    args = sys.argv[1:]
    dataskema.lang.DEFAULT = 'fr'
    test_incoming_params(pat_value="MTM5M!jQwMzkwNTg2OkHPKja/jsXVAFSSeFEEwHk5oLvA")


from setuptools import setup

package_name = 'teleop_joy'

setup(
    name=package_name,
    version='0.0.0',
    packages=[package_name],
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='turtle01',
    maintainer_email='turtle01@todo.todo',
    description='TODO: Package description',
    license='TODO: License declaration',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
        'remote_joy     = teleop_joy.remote_joy:main',
        ],
    },
)


n=int(input('Введите n: '))
fib0=0
fib1=1
print(fib0)
i=2
if n!=0:
    while i<=n:
        fib=fib1+fib0
        print(fib)
        fib0=fib1
        fib1=fib
        i=i+1


import math
import yaml
import os
import matplotlib.pyplot as plt
from datetime import datetime, timedelta

from robotino_core.Graph import Graph
from robotino_core.agv.AGV_Routing import Routing
from robotino_core.agv.AGV_Main import AGV
from robotino_core.Comm import Comm
from robotino_core.solvers.astar_solver import find_shortest_path

def calculate_euclidean_distance(a, b):
	return math.sqrt(math.pow(b[0] - a[0], 2) + math.pow(b[1] - a[1], 2))

def cost_estimator(executing_task, local_task_list, current_node, current_loc, start_time, routing):

	# Start point
	current_loc = current_loc
	current_node = current_node

	# Outputs
	task_slots = []
	total_cost = timedelta()

	if routing:

		# Evaluate executing task
		end_time = reserved_slots[executing_task][-1][0] + reserved_slots[executing_task][-1][1]
		duration = end_time - start_time

		# Update executing task
		task_slots.append((start_time, end_time, duration))
		total_cost += duration

		# Evaluate local task list
		for task in local_task_list:
			start_time = reserved_slots[task][0][0]
			end_time = reserved_slots[task][-1][0] + reserved_slots[task][-1][1]
			duration = end_time - start_time
			task_slots.append((start_time, end_time, duration))
			total_cost += duration

	else:

		# Evaluate executing task
		dist = calculate_euclidean_distance((current_loc[0], current_loc[1]), graph.nodes[current_node].pos)
		dist += find_shortest_path(graph, current_node, executing_task)[1]
		cost = timedelta(seconds=dist / 1.0)

		# End time
		end_time = start_time + cost
		duration = end_time - start_time

		# Update executing task
		task_slots.append((start_time, end_time, duration))
		total_cost += cost

		# Evaluate local task list
		start_time = end_time
		start_node = executing_task
		for task in local_task_list:
			dist = find_shortest_path(graph, start_node, task)[1]
			cost = timedelta(seconds=dist / 1.0)
			end_time = start_time + cost
			duration = end_time - start_time
			task_slots.append((start_time, end_time, duration))
			total_cost += cost
			start_time = end_time
			start_node = task

	return task_slots, total_cost

if __name__== "__main__":

	# Params
	robot_id = 15

	# Start time
	start_time_init = datetime(2000,1,1,0,0,0,0)

	# AGV
	agv = AGV('localhost', 10015, 15, 'localhost', 'matthias', 'matthias', 'kb', (10, 30), False, False, False)

	# Open connection to database
	comm = Comm('localhost', 10015, 'localhost', 'matthias', 'matthias', 'kb')
	comm.sql_open()

	# Calculate estimated end time and duration
	routing = Routing(agv)

	# Read params
	this_dir = os.path.dirname(os.path.dirname(__file__))
	data_path = os.path.join(this_dir, "src/robotino_core/params", "setup.yaml")
	with open(data_path, 'r') as file:
		params = yaml.load(file, Loader=yaml.FullLoader)

	# Create graph
	graph = Graph()
	node_neighbors = params['node_neighbors']
	node_locations = params['node_locations']
	graph.create_nodes(list(node_locations.values()), list(node_locations.keys()))
	graph.create_edges(list(node_neighbors.keys()), list(node_neighbors.values()))
	graph.plot()

	# Current loc
	current_loc = (20, 30)

	# Current node
	current_node = 'pos_5'

	# Executing_task
	executing_task = 'pos_6'

	# Get tasks in local task list
	local_task_list = ['pos_11', 'pos_14','pos_16']

	# Dmas update
	reserved_paths = {}
	reserved_slots  = {}
	total_path = []

	# Update paths for executing task
	start_time = start_time_init + timedelta(seconds=calculate_euclidean_distance((current_loc[0], current_loc[1]), graph.nodes[current_node].pos) / 1.0)
	best_path, best_slots = routing.dmas(current_node, [executing_task], start_time, comm)
	reserved_paths[executing_task] = best_path
	reserved_slots[executing_task] = best_slots

	# Update paths for each task in local task list
	estimated_start_time = best_slots[-1][0] + best_slots[-1][1]
	start_node = executing_task
	for task in local_task_list:

		# Do dmas
		best_path, best_slots = routing.dmas(start_node, [task], estimated_start_time, comm)

		# If a solution exist
		if best_path:

			# Set total planned path
			total_path.extend(best_path)

			# Estimated end time and duration
			estimated_end_time = best_slots[-1][0] + best_slots[-1][1]
			estimated_duration = estimated_end_time - estimated_start_time

			# Set paths towards all tasks
			reserved_paths[task] = best_path
			reserved_slots[task] = best_slots

			# Estimated start time for next task
			estimated_start_time = estimated_end_time

			# Start node for next task is end node of previous task
			start_node = task

	# Print
	print()
	for key, value in reserved_paths.items():
		print(key + ': ' + str(value))
	print()
	for key, value in reserved_slots.items():
		print(key + ': ' + str(value))

	# Evaluate current route
	task_slots, cost = cost_estimator(executing_task, local_task_list, current_node, current_loc, start_time_init, False)

	# Print results
	print()
	print("Astar: ")
	for task in task_slots:
		print(task)
	print(cost.total_seconds())

	# Evaluate current route
	task_slots, cost = cost_estimator(executing_task, local_task_list, current_node, current_loc, start_time_init, True)

	# Print results
	print()
	print("Dmas: ")
	for task in task_slots:
		print(task)
	print(cost.total_seconds())

	# Plot graph
	plt.show()


import os, sys
import math
import numpy as np
import cv2
import time
import progressbar

from ompl import base as ob
from ompl import geometric as og

dir_root = os.path.abspath('..')
if os.path.abspath(dir_root) not in sys.path:
    sys.path.append(dir_root)
from simulator import SimBullet
from simulator import distance_angle

from cellphysics import CellPhysicsBase

# for debug
import matplotlib.pyplot as plt

class KinoPlanner:

    def __init__(self, contact_resolution=0.02, pushing_dists=[0.02,0.04,0.06,0.08,0.10], debug=False):

        self.name2cells = {}

        self.space = ob.SE2StateSpace()
        bounds = ob.RealVectorBounds(2)
        bounds.setLow(-1)
        bounds.setHigh(1)
        self.space.setBounds(bounds)
        self.si = ob.SpaceInformation(self.space)

        self.name_actor = 'finger'
        self.type_actor = 'finger'
        self.color_actor = [1,1,0,1]
        self.dims_actor = [0.03, 0.03]

        self.sim = SimBullet(gui=False)
        self.sim_col = SimBullet(gui=False)
        self.sim_objs = {}
        self.trans_objs = {}
        self.actions_objs = {}
        self.n_actions_objs = {}
        self.uvec_contact2com = {}
        self.com_objs = {}

        self.debug = debug
        if self.debug:
            self.sim_debug = SimBullet(gui=self.debug)
            self.sim_debug.addObject('table_round','table_round',[1,1,1,1])
            self.sim_debug.setObjectPose('table_round',0.63,0,0)
            self.sim_debug.addObject(self.name_actor,self.type_actor,self.color_actor)
        self.sim.addObject('plane','plane')
        self.sim.addObject(self.name_actor,self.type_actor,self.color_actor)

        self.resolution_contact = contact_resolution
        self.pushing_dists = sorted(pushing_dists)

    def createState(self, x, y, yaw):

        state = ob.State(self.space)
        state().setX(x)
        state().setY(y)
        state().setYaw(yaw)
        return state

    def action2key(self, action):
        return tuple(action.items()) if type(action)==dict else action

    def genActions(self, cells, interval):

        cell_size = cells['cell_size']
        meter_per_pixel = 0.001

        img = np.zeros([500,500],dtype=np.uint8)
        for cell in cells['cells']:
            pt1 = np.array([-cell['pos'][1],-cell['pos'][0]]) - cell_size
            pt2 = pt1 + cell_size*2
            pt1 = (pt1/float(meter_per_pixel) + np.array([img.shape[1],img.shape[0]])*0.5).astype(int)
            pt2 = (pt2/float(meter_per_pixel) + np.array([img.shape[1],img.shape[0]])*0.5).astype(int)
            cv2.rectangle(img, tuple(pt1), tuple(pt2), (255,255,255))

        points = {(1,0):[], (-1,0):[], (0,1):[], (0,-1):[]}

        for c in range(img.shape[1]):
            for r in range(img.shape[0]):
                if img[r,c] > 0:
                    x = (-(r-img.shape[0]*0.5)*meter_per_pixel)
                    y = (-(c-img.shape[1]*0.5)*meter_per_pixel)
                    points[(-1,0)].append((x,y))
                    break

        for c in range(img.shape[1]):
            for r in range(img.shape[0]-1,-1,-1):
                if img[r,c] > 0:
                    x = (-(r-img.shape[0]*0.5)*meter_per_pixel)
                    y = (-(c-img.shape[1]*0.5)*meter_per_pixel)
                    points[(1,0)].append((x,y))
                    break

        for r in range(img.shape[0]):
            for c in range(img.shape[1]):
                if img[r,c] > 0:
                    x = (-(r-img.shape[0]*0.5)*meter_per_pixel)
                    y = (-(c-img.shape[1]*0.5)*meter_per_pixel)
                    points[(0,-1)].append((x,y))
                    break

        for r in range(img.shape[0]):
            for c in range(img.shape[1]-1,-1,-1):
                if img[r,c] > 0:
                    x = (-(r-img.shape[0]*0.5)*meter_per_pixel)
                    y = (-(c-img.shape[1]*0.5)*meter_per_pixel)
                    points[(0,1)].append((x,y))
                    break

        interval_px = int(interval/float(meter_per_pixel))
        for key in points:
            n_points = len(points[key])
            n_contacts = n_points // interval_px - 2
            i_beg = n_points//2 - (n_contacts-1)//2*interval_px
            i_end = n_points//2 + (n_contacts-1)//2*interval_px

            contacts = []
            for i in range(i_beg,i_end+1,interval_px):
                contacts.append(points[key][i])
            points[key] = contacts

        print('Generating Actions ... ')
        actions = {}
        for direction in points:
            actions[direction] = []
            for pos in points[direction]:
                actions[direction].append([])
                for length in self.pushing_dists:
                    velocity = tuple(np.array(direction) * length)
                    action = {'pos':pos, 'velocity':velocity, 'duration':1.0,
                              'direction':direction,
                              'idx':len(actions[direction])-1,
                              'ldx':len(actions[direction][-1])              }
                    actions[direction][-1].append(action)
            print('direction {}: {} x {} (# of contacts) x (# of pushing length)'.format(direction,len(actions[direction]),len(self.pushing_dists)))
        return actions

    def addObject(self, name, fp_label, masses, meter_per_pixel, color=[0.5,0.5,0.5,1], x=0, y=0, yaw=0):

        if type(fp_label)==str:
            img = cv2.imread(fp_label, cv2.IMREAD_UNCHANGED)
        else:
            img = fp_label

        cells = CellPhysicsBase.createCells(img,masses,meter_per_pixel=meter_per_pixel)
        self.name2cells[name] = cells
        self.sim.addObject(name, cells, color, x, y, yaw)
        self.sim_col.addObject(name, cells, color, x, y, yaw)
        if self.debug:
            self.sim_debug.addObject(name, cells, color, x, y, yaw)

        self.sim_objs[name] = SimBullet(gui=False)
        self.sim_objs[name].setupCamera(0.50,-90,-89.99)
        self.sim_objs[name].addObject('plane','plane')
        self.sim_objs[name].addObject(name, cells, color, x, y, yaw)
        self.sim_objs[name].addObject(self.name_actor,self.type_actor,self.color_actor)

        self.trans_objs[name] = {}
        self.actions_objs[name] = self.genActions(cells, self.resolution_contact)
        self.n_actions_objs[name] = sum([len(self.actions_objs[name][key]) for key in self.actions_objs[name]]) * len(self.pushing_dists)
        self.uvec_contact2com[name] = {}
        cellprop = self.sim_objs[name].getCellBodyProperties(name)
        self.updateObjectProperties(name, cellprop)

    def updateObjectProperties(self, name, cellprop):

        self.trans_objs[name] = {} # clear

        if self.debug:
            self.sim_debug.setCellBodyProperties(name, cellprop)
        self.sim_objs[name].setCellBodyProperties(name, cellprop)

        com = np.array([0,0])
        mass_sum = 0
        self.sim_objs[name].setObjectPose(name,0,0,0)
        cellpos = self.sim_objs[name].getCellBodyPose(name)
        cellprop = self.sim_objs[name].getCellBodyProperties(name)
        for pos, prop in zip(cellpos, cellprop):
            com[0] = pos[0] * prop['mass']
            com[1] = pos[1] * prop['mass']
            mass_sum = mass_sum + prop['mass']
        com[0] = com[0] / float(mass_sum)
        com[1] = com[1] / float(mass_sum)
        self.com_objs[name] = com

        for direction in self.actions_objs[name]:
            uvecs = []
            for actions in self.actions_objs[name][direction]:
                vec = com - np.array(actions[-1]['pos'])
                uvecs.append(vec/np.linalg.norm(vec))
            self.uvec_contact2com[name][direction] = np.array(uvecs)

    def applyAction(self, sim, name, x, y, yaw, action):

        for key, value in action.items() if type(action)==dict else action:
            if key=='pos':
                pos = [0,0]
                pos[0] = np.cos(yaw)*value[0]-np.sin(yaw)*value[1] + x
                pos[1] = np.sin(yaw)*value[0]+np.cos(yaw)*value[1] + y
            elif key=='velocity':
                velocity = [0,0,0]
                velocity[0] = np.cos(yaw)*value[0]-np.sin(yaw)*value[1]
                velocity[1] = np.sin(yaw)*value[0]+np.cos(yaw)*value[1]
            elif key=='duration':
                duration = value

        length = np.linalg.norm(velocity)
        sim.setObjectPose(name,x,y,yaw)
        sim.setObjectPose(self.name_actor,
            pos[0]-velocity[0]/float(length)*self.dims_actor[0],\
            pos[1]-velocity[1]/float(length)*self.dims_actor[1],yaw)

        #duration = duration + self.dims_actor[0] / length

        sim.applyConstantVelocity(self.name_actor,velocity,duration)

    def getCellPos(self, name, x, y, yaw):

        self.sim_objs[name].setObjectPose(name, x, y, yaw)
        return self.sim_objs[name].getCellBodyPose(name)

    def computeTransition(self, name, action):

        key = self.action2key(action)
        if key in self.trans_objs[name]:
            return self.trans_objs[name][key]

        self.applyAction(self.sim_objs[name],name,0,0,0,action)
        x,y,yaw = self.sim_objs[name].getObjectPose(name)
        cellpos = self.sim_objs[name].getCellBodyPose(name)

        self.trans_objs[name][key] = {'vec':[x,y],'yaw':yaw,'cellpos':cellpos}
        return self.trans_objs[name][key]

    def buildTransitionTable(self, name):

        print('Building a transition table for \"%s\" ...' % name)
        prog = progressbar.ProgressBar(widgets=[progressbar.Percentage(), progressbar.Bar()], maxval=self.n_actions_objs[name])
        prog.start()
        for direction in self.actions_objs[name]:
            for actions in self.actions_objs[name][direction]:
                for action in actions:
                    self.lookupTransitionTable(name,0,0,0,action)
                    prog.update(len(self.trans_objs[name])-1)
        prog.finish()

    def lookupTransitionTable(self, name, x, y, yaw, action):

        key = self.action2key(action)
        if key in self.trans_objs[name]:
            tran = self.trans_objs[name][key]
        else:
            tran = self.computeTransition(name, action)

        vec = tran['vec']
        x_next = np.cos(yaw)*vec[0]-np.sin(yaw)*vec[1] + x
        y_next = np.sin(yaw)*vec[0]+np.cos(yaw)*vec[1] + y
        yaw_next = yaw + tran['yaw']
        cellpos_next = self.getCellPos(name,x_next,y_next,yaw_next)

        return (x_next,y_next,yaw_next,cellpos_next)

    def costAction(self, action_prv, action):

        for key, value in action.items() if type(action)==dict else action:
            if key=='pos':
                pos = value
            elif key=='velocity':
                velocity = value
            elif key=='duration':
                duration = value

        #cost = np.linalg.norm(velocity) * duration
        cost = 0.1

        if action_prv is None:
            return cost

        for key, value in action_prv.items() if type(action_prv)==dict else action_prv:
            if key=='pos':
                pos_prv = value
                break

        length = np.linalg.norm(np.array(pos)-np.array(pos_prv))
        return 0.1 + length + 0.1 + cost

    def centerOfMass(self, name, x, y, yaw):

        cx = np.cos(yaw)*self.com_objs[name][0]-np.sin(yaw)*self.com_objs[name][1] + x
        cy = np.sin(yaw)*self.com_objs[name][0]+np.cos(yaw)*self.com_objs[name][1] + y

        return (cx,cy)

    def isStateValid(self, state):

        x   = state.getX()
        y   = state.getY()
        yaw = state.getYaw()
        cx,cy = self.centerOfMass(self.name_target, x,y,yaw)
        dist = np.linalg.norm([cx-0.63,cy])
        if dist > 0.45:
            return False

        self.sim_col.setObjectPose(self.name_target, x, y, yaw)
        if self.sim_col.isObjectCollide(self.name_target)==True:
            return False
        return True

    def split(self, path, xy_min=0.05, yaw_min=15.0/180.0*np.pi, method='rotNpushNrot' ):

        res = [path[0]]
        for i in range(1,len(path)):

            x0,y0,yaw0 = path[i-1]
            x1,y1,yaw1 = path[i]

            if method=='smooth':
                vec_xy = np.array([x1-x0,y1-y0])
                vec_yaw = distance_angle(yaw1,yaw0)
                dist_xy  = np.linalg.norm(vec_xy)
                dist_yaw = abs(vec_yaw)
                n_xy  = int(np.ceil(dist_xy  / xy_min))
                n_yaw = int(np.ceil(dist_yaw / yaw_min))
                n_split = n_xy if n_xy > n_yaw else n_yaw
                vec_xy = vec_xy / n_split
                vec_yaw = vec_yaw / n_split
                for i in range(n_split):
                    res.append([x0+vec_xy[0]*(i+1),
                                y0+vec_xy[1]*(i+1),
                                yaw0+vec_yaw*(i+1)])
            elif method=='rotNpushNrot':

                vec_xy = np.array([x1-x0,y1-y0])
                dist_xy  = np.linalg.norm(vec_xy)
                yaw01 = math.acos(vec_xy[1]/dist_xy)

                vec_yaw = distance_angle(yaw01,yaw0)
                dist_yaw = abs(vec_yaw)
                n_yaw = int(np.ceil(dist_yaw / yaw_min))
                if n_yaw > 0:
                    vec_yaw = vec_yaw / n_yaw
                    for i in range(n_yaw):
                        res.append([x0,y0,yaw0+vec_yaw*(i+1)])

                vec_xy = np.array([x1-x0,y1-y0])
                dist_xy  = np.linalg.norm(vec_xy)
                n_xy  = int(np.ceil(dist_xy  / xy_min))
                if n_xy > 0:
                    vec_xy = vec_xy / n_xy
                    for i in range(n_xy):
                        res.append([x0+vec_xy[0]*(i+1),
                                    y0+vec_xy[1]*(i+1), yaw01])

                vec_yaw = distance_angle(yaw1,yaw01)
                dist_yaw = abs(vec_yaw)
                n_yaw = int(np.ceil(dist_yaw / yaw_min))
                if n_yaw > 0:
                    vec_yaw = vec_yaw / n_yaw
                    for i in range(n_yaw):
                        res.append([x1,y1,yaw01+vec_yaw*(i+1)])

        return res

    def plan_rrt(self, name, init, goal):

        init = self.createState(*tuple(init))
        goal = self.createState(*tuple(goal))

        self.name_target = name

        planner = og.RRTstar(self.si)
        ss = og.SimpleSetup(self.si)
        ss.setStateValidityChecker(ob.StateValidityCheckerFn(self.isStateValid))
        ss.setPlanner(planner)
        ss.setStartAndGoalStates(init, goal)
        solved = ss.solve(1.0)
        if solved:
            ss.simplifySolution()
            path = ss.getSolutionPath()

            path_res = []
            for state in path.getStates():
                path_res.append((state.getX(),state.getY(),state.getYaw()))
            return path_res
        else:
            return None

    def plan_guided(self, name, path_guide, pred_step=np.inf):

        def findBestAction(name, x, y, yaw, cellpos_goal):
            err_min = -1
            for action in self.trans_objs[name]:
                x_next, y_next, yaw_next, cellpos_next\
                 = self.lookupTransitionTable(name,x,y,yaw,action)
                err = CellPhysicsBase.distanceCellPos(cellpos_next,cellpos_goal)
                if err_min==-1 or err_min > err:
                    err_min = err
                    ret = (action, err, x_next, y_next, yaw_next, cellpos_next)
            return ret

        waypoints = self.split(path_guide)
        path_res = [path_guide[0]]
        actions_res = []

        i_cur  = 0
        x_cur, y_cur, yaw_cur = path_guide[0]
        while i_cur < len(waypoints)-1:
            i_min = -1
            err_min = -1
            for i_next in range(min(i_cur+5,len(waypoints)-1),i_cur,-1):

                x,y,yaw = waypoints[i_next]
                cellpos = self.getCellPos(name,x,y,yaw)
                action_next, err, x_next, y_next, yaw_next, cellpos_next\
                 = findBestAction(name,x_cur,y_cur,yaw_cur,cellpos)

                if err_min==-1 or err_min > err:
                    err_min = err
                    i_min = i_next
                    next_min = (action_next,x_next,y_next,yaw_next,cellpos_next)
                    cellpos_guide = cellpos

            i_cur = i_min
            action_cur,x_cur,y_cur,yaw_cur,cellpos_next = next_min
            path_res.append([x_cur,y_cur,yaw_cur])
            actions_res.append(action_cur)

            if len(actions_res) >= pred_step:
                break

        return path_res, actions_res

    def plan_bfs(self, name, waypoints, horizon=1, thres=0.03, pred_step=np.inf):

        def get_best_action(x,y,yaw,cellpos_goal,path,actions,cost,depth):

            if depth==0:
                self.sim_objs[name].setObjectPose(name,x,y,yaw)
                cellpos = self.sim_objs[name].getCellBodyPose(name)
                err = CellPhysicsBase.distanceCellPos(cellpos,cellpos_goal)
                return (err,list(path),list(actions))

            actions_sorted = []
            action_prv = actions[-1] if len(actions)>0 else None
            for action in self.trans_objs[name]:
                cost_cur = self.costAction(action_prv,action)
                actions_sorted.append((action,cost_cur))
            actions_sorted = sorted(actions_sorted, key=lambda a: a[1])

            err_min = -1
            for action, cost_cur in actions_sorted:
                x_next,y_next,yaw_next,_\
                 = self.lookupTransitionTable(name,x,y,yaw,action)

                err, path_res, actions_res\
                 = get_best_action( x_next,y_next,yaw_next,cellpos_goal,
                                    path+[(x_next,y_next,yaw_next)],
                                    actions+[action],
                                    cost + cost_cur, depth-1 )
                if err < thres:
                    return (err, path_res, actions_res)
                elif err_min==-1 or err_min > err:
                    err_min = err
                    path_min = path_res
                    actions_min = actions_res

            return (err_min, path_min, actions_min)

        path = [waypoints[0]]
        actions = []

        for i in range(1,len(waypoints)):

            x0,y0,yaw0 = waypoints[i-1]
            x1,y1,yaw1 = waypoints[i]
            cellpos0 = self.getCellPos(name,x0,y0,yaw0)
            cellpos1 = self.getCellPos(name,x1,y1,yaw1)

            if i==len(waypoints)-1:
                thres = 0.02

            err = np.inf
            while err > thres:
                err_prv = err
                err, path_tmp, actions_tmp\
                 = get_best_action(x0,y0,yaw0,cellpos1,[],[],0,horizon)

                if self.debug:
                    for action in actions_tmp:
                        self.applyAction(self.sim_debug,name,x0,y0,yaw0,action)
                        (x0,y0,yaw0) = self.sim_debug.getObjectPose(name)
                        actions.append(action)
                        path.append((x0,y0,yaw0))
                else:
                    x0,y0,yaw0 = path_tmp[-1]
                    actions = actions + actions_tmp
                    path = path + path_tmp

                if len(actions) >= pred_step:
                    break
            if len(actions) >= pred_step:
                break

        return path, actions

    def plan_diff(self, name, waypoints, horizon=1, thres=0.03, pred_step=np.inf):

        path = [waypoints[0]]
        actions = []
        for i in range(1,len(waypoints)):

            x0,y0,yaw0 = waypoints[i-1]
            x1,y1,yaw1 = waypoints[i]
            cellpos0 = self.getCellPos(name,x0,y0,yaw0)
            cellpos1 = self.getCellPos(name,x1,y1,yaw1)

            if i==len(waypoints)-1:
                thres = 0.02

            err = np.inf
            while err > thres:

                # cached simulation result
                errs = []
                for action in self.trans_objs[name]:
                    for key, value in action:
                        if key=='direction':
                            direction = value
                        elif key=='idx':
                            idx = value
                        elif key=='ldx':
                            ldx = value

                    (x_cur,y_cur,yaw_cur,cellpos_cur)\
                     = self.lookupTransitionTable(name,x0,y0,yaw0,action)
                    err = CellPhysicsBase.distanceCellPos(cellpos_cur,cellpos1)
                    errs.append((err,(direction,idx,ldx),(x_cur,y_cur,yaw_cur)))

                if len(errs)>0:
                    err_min = min(errs,key=lambda x: x[0])
                    errs = [err_min]

                # fix the pushing length (ldx)
                dist = np.sqrt((x1-x0)*(x1-x0)+(y1-y0)*(y1-y0))
                for ldx, length in enumerate(self.pushing_dists):
                    if dist < length:
                        break

                vec_com2goal = np.array(self.centerOfMass(name,x1,y1,yaw1))\
                                - np.array(self.centerOfMass(name,x0,y0,yaw0))
                np.array(self.centerOfMass(name,x1,y1,yaw1))
                for direction in self.actions_objs[name]:

                    # ignore the opposite direction
                    vec = [0,0]
                    vec[0] = np.cos(yaw0)*direction[0]-np.cos(yaw0)*direction[1]
                    vec[1] = np.sin(yaw0)*direction[0]+np.cos(yaw0)*direction[1]
                    if vec_com2goal.dot(np.array(vec)) < 0:
                        continue

                    # start searching from the point that is closest to the line between center of mass
                    uvec_c2c = self.uvec_contact2com[name][direction]
                    vec = np.zeros(uvec_c2c.shape)
                    vec[:,0] = np.cos(yaw0)*uvec_c2c[:,0]-np.sin(yaw0)*uvec_c2c[:,1]
                    vec[:,1] = np.sin(yaw0)*uvec_c2c[:,0]+np.cos(yaw0)*uvec_c2c[:,1]

                    projs = vec.dot(vec_com2goal)
                    idx = np.argmax(projs)

                    action = self.actions_objs[name][direction][idx][ldx]
                    (x_cur,y_cur,yaw_cur,cellpos_cur)\
                     = self.lookupTransitionTable(name,x0,y0,yaw0,action)
                    err_cur = CellPhysicsBase.distanceCellPos(cellpos_cur,cellpos1)
                    errs.append((err_cur,(direction,idx,ldx),(x_cur,y_cur,yaw_cur)))

                    for incr in [-1,1]:
                        j = idx + incr
                        while 0<=j and j<len(self.actions_objs[name][direction]):
                            actioni = self.actions_objs[name][direction][j][ldx]
                            (xi,yi,yawi,cellposi)\
                             = self.lookupTransitionTable(name,x0,y0,yaw0,actioni)
                            erri = CellPhysicsBase.distanceCellPos(cellposi,cellpos1)
                            if erri > err_cur:
                                break

                            errs.append((erri,(direction,j,ldx),(xi,yi,yawi)))
                            err_cur = erri
                            j = j + incr

                # fix the contact point (direction,idx)
                err_min = min(errs,key=lambda x: x[0])
                (err,(direction,idx,ldx),(x,y,yaw)) = err_min

                errs = [err_min]
                err_cur = err
                for incr in [-1,1]:
                    l = ldx + incr
                    while 0<=l and l<len(self.pushing_dists):
                        actionl = self.actions_objs[name][direction][idx][l]
                        (xl,yl,yawl,cellposl)\
                         = self.lookupTransitionTable(name,x0,y0,yaw0,actionl)
                        errl = CellPhysicsBase.distanceCellPos(cellposl,cellpos1)
                        if errl > err_cur:
                            break

                        errs.append((errl,(direction,idx,l),(xl,yl,yawl)))
                        err_cur = errl
                        l = l + incr

                err_min = min(errs,key=lambda x: x[0])
                (err,(direction,idx,ldx),(x,y,yaw)) = err_min

                action = self.actions_objs[name][direction][idx][ldx]
                self.applyAction(self.sim,name,x0,y0,yaw0,action)
                (x,y,yaw) = self.sim.getObjectPose(name)

                actions.append(action)
                path.append((x,y,yaw))
                (x0,y0,yaw0) = (x,y,yaw)
                cellpos0 = self.getCellPos(name,x0,y0,yaw0)

                print('# of simulation: {}/{}, err: {}'.format(len(self.trans_objs[name]),self.n_actions_objs[name],err))

                if len(actions) >= pred_step:
                    break
            if len(actions) >= pred_step:
                break

        return path, actions

    def draw_cellpos(self, ax, cellpos, color=[0,0,0], marker='s'):
        cellpos = np.array(cellpos)
        ax.plot(-cellpos[:,2],cellpos[:,1],'.',marker=marker,color=color)

    def draw_action(self, ax, x,y,yaw, action, color='g', marker='o'):
        for key, value in action.items() if type(action)==dict else action:
            if key=='pos':
                pos = value
            elif key=='velocity':
                velocity = value
        tmp = [0,0]
        tmp[0] = np.cos(yaw)*pos[0]-np.sin(yaw)*pos[1] + x
        tmp[1] = np.sin(yaw)*pos[0]+np.cos(yaw)*pos[1] + y
        ax.plot(-tmp[1],tmp[0],'.',color=color,marker=marker)

        tmp2 = [0,0]
        tmp2[0] = np.cos(yaw)*velocity[0]-np.sin(yaw)*velocity[1] + tmp[0]
        tmp2[1] = np.sin(yaw)*velocity[0]+np.cos(yaw)*velocity[1] + tmp[1]
        ax.plot([-tmp[1],-tmp2[1]],[tmp[0],tmp2[0]],'-',color=color,marker=marker)

    def draw_plan(self, ax, name, path, actions):

        circle = plt.Circle((0,0.63),0.5, color='k', fill=False)
        ax.add_artist(circle)
        clrs = np.linspace(0.3,1,len(path)+1)
        for i in range(len(path)-1):
            cellpos = self.getCellPos(name,path[i][0],path[i][1],path[i][2])
            self.draw_cellpos(ax,cellpos,color=(clrs[i+1],0,0))
            action = actions[i]
            self.draw_action(ax,path[i][0],path[i][1],path[i][2], action )
        cellpos = self.getCellPos(name,path[-1][0],path[-1][1],path[-1][2])
        self.draw_cellpos(ax,cellpos,color=(clrs[-1],0,0))
        ax.set_aspect('equal')

    def plan(self, name, init, goal, method='diff', pred_step=np.inf):

        waypoints = self.plan_rrt(name, init, goal)
        print('waypoints: ',waypoints)
        if method=='guided':
            for obj in self.sim_objs:
                self.buildTransitionTable(obj)
            path_res, actions_res = self.plan_guided(name, waypoints, pred_step=pred_step)
        elif method=='bfs':
            for obj in self.sim_objs:
                self.buildTransitionTable(obj)
            path_res, actions_res = self.plan_bfs(name, waypoints, pred_step=pred_step)
        elif method=='diff':
            path_res, actions_res = self.plan_diff(name, waypoints, pred_step=pred_step)

        if self.debug:

            fig = plt.figure()
            ax = fig.add_subplot(111)
            self.draw_plan(ax, name, path_res, actions_res)
            plt.show()
            fig.savefig(os.path.join('./',method+'.png'))

            self.sim_debug.recordStart(os.path.join('./',method+'.mp4'))
            self.sim_debug.setupCamera(0.75,-90,-89.99, 0.63,0,0)
            x,y,yaw = init
            for action in actions_res:
                self.applyAction(self.sim_debug,name,x,y,yaw,action)
                x,y,yaw = self.sim_debug.getObjectPose(name)
            self.sim_debug.recordStop()

        return (path_res, actions_res)

if __name__=='__main__':

    obj = 'hammer'
    obj2mpp = {'hammer':0.35/500.0}

    planner = KinoPlanner(0.02,[0.10,0.08,0.06,0.04],debug=True)
    fp_label = '../../dataset/sims/%s_label.pgm' % obj
    planner.addObject(obj,fp_label, meter_per_pixel=obj2mpp[obj])

    time_beg = time.time()
    path, actions = planner.plan(obj,[0.63,0,0],[0.25,0.00,-90.0/180.0*np.pi], method='diff')
    time_end = time.time()
    print('time: {}'.format(time_end - time_beg))
    print('# of actions: {}'.format(len(actions)))


"""A simple, flexible implementation of a GPT model.

Inspired by https://github.com/karpathy/minGPT/blob/master/mingpt/model.py
"""
import math
import warnings
from typing import List, Optional, Tuple, Union
import torch
import torch.nn as nn
import torch.nn.functional as F
from transformers import PreTrainedModel, PreTrainedTokenizer, PreTrainedTokenizerFast
from transformers.modeling_outputs import BaseModelOutputWithPast, CausalLMOutputWithPast
from .attention import attn_bias_shape, build_attn_bias
from .blocks import MPTBlock
from .custom_embedding import SharedEmbedding
from .norm import NORM_CLASS_REGISTRY
from .configuration_mpt import MPTConfig
from .adapt_tokenizer import AutoTokenizerForMOD, adapt_tokenizer_for_denoising
from .hf_prefixlm_converter import add_bidirectional_mask_if_missing, convert_hf_causal_lm_to_prefix_lm
from .meta_init_context import init_empty_weights
from .param_init_fns import MODEL_INIT_REGISTRY, generic_param_init_fn_
try:
    from .flash_attn_triton import flash_attn_func
except:
    pass
Tokenizer = Union[PreTrainedTokenizer, PreTrainedTokenizerFast]

class MPTPreTrainedModel(PreTrainedModel):
    config_class = MPTConfig
    base_model_prefix = 'model'
    _no_split_modules = ['MPTBlock']

class MPTModel(MPTPreTrainedModel):

    def __init__(self, config: MPTConfig):
        config._validate_config()
        super().__init__(config)
        self.attn_impl = config.attn_config['attn_impl']
        self.prefix_lm = config.attn_config['prefix_lm']
        self.attn_uses_sequence_id = config.attn_config['attn_uses_sequence_id']
        self.alibi = config.attn_config['alibi']
        self.alibi_bias_max = config.attn_config['alibi_bias_max']
        if config.init_device == 'mixed':
            if dist.get_local_rank() == 0:
                config.init_device = 'cpu'
            else:
                config.init_device = 'meta'
        if config.norm_type.lower() not in NORM_CLASS_REGISTRY.keys():
            norm_options = ' | '.join(NORM_CLASS_REGISTRY.keys())
            raise NotImplementedError(f'Requested norm type ({config.norm_type}) is not implemented within this repo (Options: {norm_options}).')
        norm_class = NORM_CLASS_REGISTRY[config.norm_type.lower()]
        self.embedding_fraction = config.embedding_fraction
        self.wte = SharedEmbedding(config.vocab_size, config.d_model, device=config.init_device)
        if not self.alibi:
            self.wpe = torch.nn.Embedding(config.max_seq_len, config.d_model, device=config.init_device)
        self.emb_drop = nn.Dropout(config.emb_pdrop)
        self.blocks = nn.ModuleList([MPTBlock(device=config.init_device, **config.to_dict()) for _ in range(config.n_layers)])
        self.norm_f = norm_class(config.d_model, device=config.init_device)
        if config.init_device != 'meta':
            print(f'You are using config.init_device={config.init_device!r}, but you can also use config.init_device="meta" with Composer + FSDP for fast initialization.')
            self.apply(self.param_init_fn)
        self.is_causal = not self.prefix_lm
        self._attn_bias_initialized = False
        self.attn_bias = None
        self.attn_bias_shape = attn_bias_shape(self.attn_impl, config.n_heads, config.max_seq_len, self.alibi, prefix_lm=self.prefix_lm, causal=self.is_causal, use_sequence_id=self.attn_uses_sequence_id)
        if config.no_bias:
            for module in self.modules():
                if hasattr(module, 'bias') and isinstance(module.bias, nn.Parameter):
                    if config.verbose:
                        warnings.warn(f'Removing bias ({module.bias}) from {module}.')
                    module.register_parameter('bias', None)
        if config.verbose and config.verbose > 2:
            print(self)
        if 'verbose' not in self.config.init_config:
            self.config.init_config['verbose'] = self.config.verbose
        if self.config.init_config['verbose'] > 1:
            init_fn_name = self.config.init_config['name']
            warnings.warn(f'Using {init_fn_name} initialization.')
        self.gradient_checkpointing = False

    def get_input_embeddings(self):
        return self.wte

    def set_input_embeddings(self, value):
        self.wte = value

    @torch.no_grad()
    def _attn_bias(self, device, dtype, attention_mask: Optional[torch.ByteTensor]=None, prefix_mask: Optional[torch.ByteTensor]=None, sequence_id: Optional[torch.LongTensor]=None):
        if not self._attn_bias_initialized:
            if self.attn_bias_shape:
                self.attn_bias = torch.zeros(self.attn_bias_shape, device=device, dtype=dtype)
                self.attn_bias = build_attn_bias(self.attn_impl, self.attn_bias, self.config.n_heads, self.config.max_seq_len, causal=self.is_causal, alibi=self.alibi, alibi_bias_max=self.alibi_bias_max)
            self._attn_bias_initialized = True
        if self.attn_impl == 'flash':
            return (self.attn_bias, attention_mask)
        if self.attn_bias is not None:
            self.attn_bias = self.attn_bias.to(dtype=dtype, device=device)
        attn_bias = self.attn_bias
        if self.prefix_lm:
            assert isinstance(attn_bias, torch.Tensor)
            assert isinstance(prefix_mask, torch.Tensor)
            attn_bias = self._apply_prefix_mask(attn_bias, prefix_mask)
        if self.attn_uses_sequence_id and sequence_id is not None:
            assert isinstance(attn_bias, torch.Tensor)
            attn_bias = self._apply_sequence_id(attn_bias, sequence_id)
        if attention_mask is not None:
            s_k = attention_mask.shape[-1]
            if attn_bias is None:
                attn_bias = torch.zeros((1, 1, 1, s_k), device=device, dtype=dtype)
            else:
                _s_k = max(0, attn_bias.size(-1) - s_k)
                attn_bias = attn_bias[:, :, :, _s_k:]
            if prefix_mask is not None and attention_mask.shape != prefix_mask.shape:
                raise ValueError(f'attention_mask shape={attention_mask.shape} ' + f'and prefix_mask shape={prefix_mask.shape} are not equal.')
            min_val = torch.finfo(attn_bias.dtype).min
            attn_bias = attn_bias.masked_fill(~attention_mask.view(-1, 1, 1, s_k), min_val)
        return (attn_bias, None)

    def _apply_prefix_mask(self, attn_bias: torch.Tensor, prefix_mask: torch.Tensor):
        (s_k, s_q) = attn_bias.shape[-2:]
        if s_k != self.config.max_seq_len or s_q != self.config.max_seq_len:
            raise ValueError('attn_bias does not match the expected shape. ' + f'The last two dimensions should both be {self.config.max_length} ' + f'but are {s_k} and {s_q}.')
        seq_len = prefix_mask.shape[-1]
        if seq_len > self.config.max_seq_len:
            raise ValueError(f'prefix_mask sequence length cannot exceed max_seq_len={self.config.max_seq_len}')
        attn_bias = attn_bias[..., :seq_len, :seq_len]
        causal = torch.tril(torch.ones((seq_len, seq_len), dtype=torch.bool, device=prefix_mask.device)).view(1, 1, seq_len, seq_len)
        prefix = prefix_mask.view(-1, 1, 1, seq_len)
        cannot_attend = ~torch.logical_or(causal, prefix.bool())
        min_val = torch.finfo(attn_bias.dtype).min
        attn_bias = attn_bias.masked_fill(cannot_attend, min_val)
        return attn_bias

    def _apply_sequence_id(self, attn_bias: torch.Tensor, sequence_id: torch.LongTensor):
        seq_len = sequence_id.shape[-1]
        if seq_len > self.config.max_seq_len:
            raise ValueError(f'sequence_id sequence length cannot exceed max_seq_len={self.config.max_seq_len}')
        attn_bias = attn_bias[..., :seq_len, :seq_len]
        cannot_attend = torch.logical_not(torch.eq(sequence_id.view(-1, seq_len, 1), sequence_id.view(-1, 1, seq_len))).unsqueeze(1)
        min_val = torch.finfo(attn_bias.dtype).min
        attn_bias = attn_bias.masked_fill(cannot_attend, min_val)
        return attn_bias

    def forward(self, input_ids: torch.LongTensor, past_key_values: Optional[List[Tuple[torch.FloatTensor]]]=None, attention_mask: Optional[torch.ByteTensor]=None, prefix_mask: Optional[torch.ByteTensor]=None, sequence_id: Optional[torch.LongTensor]=None, return_dict: Optional[bool]=None, output_attentions: Optional[bool]=None, output_hidden_states: Optional[bool]=None, use_cache: Optional[bool]=None, inputs_embeds: Optional[torch.Tensor]=None):
        return_dict = return_dict if return_dict is not None else self.config.return_dict
        use_cache = use_cache if use_cache is not None else self.config.use_cache
        if attention_mask is not None:
            attention_mask = attention_mask.bool()
        if prefix_mask is not None:
            prefix_mask = prefix_mask.bool()
        if not return_dict:
            raise NotImplementedError('return_dict False is not implemented yet for MPT')
        if output_attentions:
            if self.attn_impl != 'torch':
                raise NotImplementedError('output_attentions is not implemented for MPT when using attn_impl `flash` or `triton`.')
        if attention_mask is not None and attention_mask[:, 0].sum() != attention_mask.shape[0] and self.training:
            raise NotImplementedError('MPT does not support training with left padding.')
        if self.prefix_lm and prefix_mask is None:
            raise ValueError('prefix_mask is a required argument when MPT is configured with prefix_lm=True.')
        if self.training:
            if self.attn_uses_sequence_id and sequence_id is None:
                raise ValueError('sequence_id is a required argument when MPT is configured with attn_uses_sequence_id=True ' + 'and the model is in train mode.')
            elif self.attn_uses_sequence_id is False and sequence_id is not None:
                warnings.warn('MPT received non-None input for `sequence_id` but is configured with attn_uses_sequence_id=False. ' + 'This input will be ignored. If you want the model to use `sequence_id`, set attn_uses_sequence_id to True.')
        if input_ids is not None:
            S = input_ids.size(1)
            assert S <= self.config.max_seq_len, f'Cannot forward input with seq_len={S}, this model only supports seq_len<={self.config.max_seq_len}'
            tok_emb = self.wte(input_ids)
        else:
            assert inputs_embeds is not None
            assert self.alibi, 'inputs_embeds is not implemented for MPT unless for alibi.'
            S = inputs_embeds.size(1)
            tok_emb = inputs_embeds
        if self.alibi:
            x = tok_emb
        else:
            past_position = 0
            if past_key_values is not None:
                if len(past_key_values) != self.config.n_layers:
                    raise ValueError(f'past_key_values must provide a past_key_value for each attention ' + f'layer in the network (len(past_key_values)={len(past_key_values)!r}; self.config.n_layers={self.config.n_layers!r}).')
                past_position = past_key_values[0][0].size(1)
                if self.attn_impl == 'torch':
                    past_position = past_key_values[0][0].size(3)
            if S + past_position > self.config.max_seq_len:
                raise ValueError(f'Cannot forward input with past sequence length {past_position} and current sequence length {S + 1}, this model only supports total sequence length <= {self.config.max_seq_len}.')
            pos = torch.arange(past_position, S + past_position, dtype=torch.long, device=input_ids.device).unsqueeze(0)
            if attention_mask is not None:
                pos = torch.clamp(pos - torch.cumsum((~attention_mask).to(torch.int32), dim=1)[:, past_position:], min=0)
            pos_emb = self.wpe(pos)
            x = tok_emb + pos_emb
        if self.embedding_fraction == 1:
            x = self.emb_drop(x)
        else:
            x_shrunk = x * self.embedding_fraction + x.detach() * (1 - self.embedding_fraction)
            assert isinstance(self.emb_drop, nn.Module)
            x = self.emb_drop(x_shrunk)
        (attn_bias, attention_mask) = self._attn_bias(device=x.device, dtype=torch.float32, attention_mask=attention_mask, prefix_mask=prefix_mask, sequence_id=sequence_id)
        if use_cache and past_key_values is None:
            past_key_values = [() for _ in range(self.config.n_layers)]
        all_hidden_states = () if output_hidden_states else None
        all_self_attns = () if output_attentions else None
        for (b_idx, block) in enumerate(self.blocks):
            if output_hidden_states:
                assert all_hidden_states is not None
                all_hidden_states = all_hidden_states + (x,)
            past_key_value = past_key_values[b_idx] if past_key_values is not None else None
            if self.gradient_checkpointing and self.training:
                (x, attn_weights, past_key_value) = torch.utils.checkpoint.checkpoint(block, x, past_key_value, attn_bias, attention_mask, self.is_causal)
            else:
                (x, attn_weights, past_key_value) = block(x, past_key_value=past_key_value, attn_bias=attn_bias, attention_mask=attention_mask, is_causal=self.is_causal)
            if past_key_values is not None:
                past_key_values[b_idx] = past_key_value
            if output_attentions:
                assert all_self_attns is not None
                all_self_attns = all_self_attns + (attn_weights,)
        x = self.norm_f(x)
        if output_hidden_states:
            assert all_hidden_states is not None
            all_hidden_states = all_hidden_states + (x,)
        return BaseModelOutputWithPast(last_hidden_state=x, past_key_values=past_key_values, hidden_states=all_hidden_states, attentions=all_self_attns)

    def param_init_fn(self, module):
        init_fn_name = self.config.init_config['name']
        MODEL_INIT_REGISTRY[init_fn_name](module=module, n_layers=self.config.n_layers, d_model=self.config.d_model, **self.config.init_config)

    def fsdp_wrap_fn(self, module):
        return isinstance(module, MPTBlock)

    def activation_checkpointing_fn(self, module):
        return isinstance(module, MPTBlock)

class MPTForCausalLM(MPTPreTrainedModel):

    def __init__(self, config: MPTConfig):
        super().__init__(config)
        if not config.tie_word_embeddings:
            raise ValueError('MPTForCausalLM only supports tied word embeddings')
        print(f'Instantiating an MPTForCausalLM model from {__file__}')
        self.transformer = MPTModel(config)
        for child in self.transformer.children():
            if isinstance(child, torch.nn.ModuleList):
                continue
            if isinstance(child, torch.nn.Module):
                child._fsdp_wrap = True
        self.logit_scale = None
        if config.logit_scale is not None:
            logit_scale = config.logit_scale
            if isinstance(logit_scale, str):
                if logit_scale == 'inv_sqrt_d_model':
                    logit_scale = 1 / math.sqrt(config.d_model)
                else:
                    raise ValueError(f"logit_scale={logit_scale!r} is not recognized as an option; use numeric value or 'inv_sqrt_d_model'.")
            self.logit_scale = logit_scale

    def get_input_embeddings(self):
        return self.transformer.wte

    def set_input_embeddings(self, value):
        self.transformer.wte = value

    def get_output_embeddings(self):
        return self.transformer.wte

    def set_output_embeddings(self, new_embeddings):
        self.transformer.wte = new_embeddings

    def set_decoder(self, decoder):
        self.transformer = decoder

    def get_decoder(self):
        return self.transformer

    def forward(self, input_ids: torch.LongTensor, past_key_values: Optional[List[Tuple[torch.FloatTensor]]]=None, attention_mask: Optional[torch.ByteTensor]=None, prefix_mask: Optional[torch.ByteTensor]=None, sequence_id: Optional[torch.LongTensor]=None, labels: Optional[torch.LongTensor]=None, return_dict: Optional[bool]=None, output_attentions: Optional[bool]=None, output_hidden_states: Optional[bool]=None, use_cache: Optional[bool]=None, inputs_embeds: Optional[torch.FloatTensor]=None):
        return_dict = return_dict if return_dict is not None else self.config.return_dict
        use_cache = use_cache if use_cache is not None else self.config.use_cache
        if inputs_embeds is not None:
            raise NotImplementedError('inputs_embeds has to be None (for hf/peft support).')
        outputs = self.transformer(input_ids=input_ids, past_key_values=past_key_values, attention_mask=attention_mask, prefix_mask=prefix_mask, sequence_id=sequence_id, return_dict=return_dict, output_attentions=output_attentions, output_hidden_states=output_hidden_states, use_cache=use_cache)
        logits = self.transformer.wte(outputs.last_hidden_state.to(self.transformer.wte.weight.device), True)
        if self.logit_scale is not None:
            if self.logit_scale == 0:
                warnings.warn(f'Multiplying logits by self.logit_scale={self.logit_scale!r}. This will produce uniform (uninformative) outputs.')
            logits *= self.logit_scale
        loss = None
        if labels is not None:
            labels = torch.roll(labels, shifts=-1)
            labels[:, -1] = -100
            loss = F.cross_entropy(logits.view(-1, logits.size(-1)), labels.to(logits.device).view(-1))
        return CausalLMOutputWithPast(loss=loss, logits=logits, past_key_values=outputs.past_key_values, hidden_states=outputs.hidden_states, attentions=outputs.attentions)

    def param_init_fn(self, module):
        init_fn_name = self.config.init_config['name']
        MODEL_INIT_REGISTRY[init_fn_name](module=module, n_layers=self.config.n_layers, d_model=self.config.d_model, **self.config.init_config)

    def fsdp_wrap_fn(self, module):
        return isinstance(module, MPTBlock)

    def activation_checkpointing_fn(self, module):
        return isinstance(module, MPTBlock)

    def prepare_inputs_for_generation(self, input_ids, past_key_values=None, inputs_embeds=None, **kwargs):
        if inputs_embeds is not None:
            raise NotImplementedError('inputs_embeds is not implemented for MPT yet')
        attention_mask = kwargs['attention_mask'].bool()
        if attention_mask[:, -1].sum() != attention_mask.shape[0]:
            raise NotImplementedError('MPT does not support generation with right padding.')
        if self.transformer.attn_uses_sequence_id and self.training:
            sequence_id = torch.zeros_like(input_ids[:1])
        else:
            sequence_id = None
        if past_key_values is not None:
            input_ids = input_ids[:, -1].unsqueeze(-1)
        if self.transformer.prefix_lm:
            prefix_mask = torch.ones_like(attention_mask)
            if kwargs.get('use_cache') == False:
                raise NotImplementedError('MPT with prefix_lm=True does not support use_cache=False.')
        else:
            prefix_mask = None
        return {'input_ids': input_ids, 'attention_mask': attention_mask, 'prefix_mask': prefix_mask, 'sequence_id': sequence_id, 'past_key_values': past_key_values, 'use_cache': kwargs.get('use_cache', True)}

    @staticmethod
    def _reorder_cache(past_key_values, beam_idx):
        """Used by HuggingFace generate when using beam search with kv-caching.

        See https://github.com/huggingface/transformers/blob/3ec7a47664ebe40c40f4b722f6bb1cd30c3821ec/src/transformers/models/gpt2/modeling_gpt2.py#L1122-L1133
        for an example in transformers.
        """
        reordered_past = []
        for layer_past in past_key_values:
            reordered_past += [tuple((past_state.index_select(0, beam_idx) for past_state in layer_past))]
        return reordered_past


import csv

# utility functions --------------------------------------------------------

def tryParseToNumber(s):
    result = s
    try:
        if len(s) > 0:
            result = int(float(str(s).strip().replace(",","")))
        else:
            result = "NaN"
    except:
        result = "NaN"
    return result

def tryToSum(v1, v2):
    result = ""
    if len(str(v1)) > 0 and len(str(v2)) > 0:
        result = int(float(str(v1).strip().replace(",",""))) + int(float(str(v2).strip().replace(",","")))
    return result

def tryToDiff(v1, v2):
    result = ""
    if len(str(v1)) > 0 and len(str(v2)) > 0:
        result = int(float(str(v1).strip().replace(",",""))) - int(float(str(v2).strip().replace(",","")))
    return result

def cleanFile(filename, new_file_name):
    new_filtered = ""
    with open(filename, encoding="utf8", errors='ignore') as file_opened:
        for line in file_opened:
            new_filtered += line.replace('\0', '')
    new_file = open(new_file_name, "w")
    new_file.write(new_filtered)
    new_file.close()

def updateOnMortality(country_name, mortality, structure, metric):
    for row in data["HEALTH_MORTALITY"]:
        row_ad_dict = dict(row)
        row_ad_dict_country_name = row_ad_dict["Country"].strip()
        if mortality != "NaN" and country_name == row_ad_dict_country_name:
            if row_ad_dict[metric] == "Yes":
                structure["mortality_yes"] += mortality
                structure["mortality_yes_n_countries"] += 1
            elif row_ad_dict[metric] == "No":
                structure["mortality_no"] += mortality
                structure["mortality_no_n_countries"] += 1

            break

#  ----------------------------------------------------------------------

data = dict()

final_inspection = list()
final_assessment = list()

final_inspection_n_countries = 0
final_assessment_n_countries = 0

with open("../data/final.csv") as csvfile:
    data["FINAL"] = list(csv.DictReader(csvfile))

with open("../data/healt_assessment_WHO.csv") as csvfile:
    data["HEALTH_MORTALITY"] = list(csv.DictReader(csvfile))

# filtering null char from dirty file
# cleanFile("../data/_prison_mortality.csv", "../data/prison_mortality.csv")

# headers = ["year", "mortality_yes", "mortality_no", "mortality_yes_n_countries", "mortality_no_n_countries", "mortality_yes_tot", "mortality_no_tot"]
headers = ["year", "mortality_yes", "mortality_no"]

for row in data["FINAL"]:
    row_as_dict_tot = dict(row)
    inspection = dict()
    assessment = dict()

    country_name = row_as_dict_tot["country_name"].strip()
    year = row_as_dict_tot["year"].strip()
    mortality = tryParseToNumber(row_as_dict_tot["total_mortality"])

    inspection_found = False
    for insp in final_inspection:
        if insp["year"] == year:
            inspection_found = True
            final_inspection_n_countries += 1
            updateOnMortality(country_name, mortality, insp, "Medical document inspections")
            break

    if not inspection_found:
        inspection["year"] = year
        inspection["mortality_yes"] = 0
        inspection["mortality_no"] = 0
        inspection["mortality_yes_n_countries"] = 0
        inspection["mortality_no_n_countries"] = 0
        updateOnMortality(country_name, mortality, inspection, "Medical document inspections")
        final_inspection.append(inspection)

    # -------------------------------------------------------------------------

    assessment_found = False
    for ass in final_assessment:
        if ass["year"] == year:
            assessment_found = True
            final_assessment_n_countries += 1
            updateOnMortality(country_name, mortality, ass, "Assessment of prison health services")
            break

    if not assessment_found:
        assessment["year"] = year
        assessment["mortality_yes"] = 0
        assessment["mortality_no"] = 0
        assessment["mortality_yes_n_countries"] = 0
        assessment["mortality_no_n_countries"] = 0
        updateOnMortality(country_name, mortality, assessment, "Assessment of prison health services")
        final_assessment.append(assessment)

    # -------------------------------------------------------------------------

# filter zero values
final_assessment_filtered = list()
final_inspection_filtered = list()
for x in final_assessment:
    if x["mortality_yes"] != 0 or x["mortality_no"] != 0:
        temp_ass = dict()
        temp_ass["year"] = x["year"]
        temp_ass["mortality_yes"] = x["mortality_yes"]/x["mortality_yes_n_countries"]
        temp_ass["mortality_no"] = x["mortality_no"]/x["mortality_no_n_countries"]
        # temp_ass["mortality_yes_n_countries"] = x["mortality_yes_n_countries"]
        # temp_ass["mortality_no_n_countries"] = x["mortality_no_n_countries"]
        # temp_ass["mortality_yes_tot"] = x["mortality_yes"]
        # temp_ass["mortality_no_tot"] = x["mortality_no"]
        final_assessment_filtered.append(temp_ass)
for x in final_inspection:
    if x["mortality_yes"] != 0 or x["mortality_no"] != 0:
        temp_insp = dict()
        temp_insp["year"] = x["year"]
        temp_insp["mortality_yes"] = x["mortality_yes"]/x["mortality_yes_n_countries"]
        temp_insp["mortality_no"] = x["mortality_no"]/x["mortality_no_n_countries"]
        # temp_insp["mortality_yes_n_countries"] = x["mortality_yes_n_countries"]
        # temp_insp["mortality_no_n_countries"] = x["mortality_no_n_countries"]
        # temp_insp["mortality_yes_tot"] = x["mortality_yes"]
        # temp_insp["mortality_no_tot"] = x["mortality_no"]
        final_inspection_filtered.append(temp_insp)

with open("./visualizzazione_4/visualition4.csv", "w", newline="") as csvfile:
    dict_writer = csv.DictWriter(csvfile, headers)
    dict_writer.writeheader()
    dict_writer.writerows(final_inspection_filtered)

with open("./visualizzazione_5/visualition5.csv", "w", newline="") as csvfile:
    dict_writer = csv.DictWriter(csvfile, headers)
    dict_writer.writeheader()
    dict_writer.writerows(final_assessment_filtered)