from tables import *
import os.path
from PyQt4 import QtGui
import datetime

def checkFileHasGroup(file, name):
        for group in file.walkNodes():
            if group._v_name == name:
                return True
        return False

def checkIfFileExists(file):
        return os.path.exists(file)

def checkIfPathExist(dir,create=True):
        if not os.path.exists(dir):
            if create:
                try:
                    os.makedirs(dir)
                    return True
                except(WindowsError):
                    return(False)
            else: return False
        else: return True

def createDefaultPath(beamtime,groupname):
    now=datetime.datetime.now()
    if not groupname=="": groupname="/"+groupname
    if not beamtime=="": beamtime=beamtime+"/"
    path="C:/Data/Measurements/TAS-DATA/FU_%d/"%(now.year) + beamtime+now.strftime("%Y-%m-%d")+groupname
    return (path)

def fileOverwriteDialog(file,path="C:/"):
        msgBox=QtGui.QMessageBox()
        msgBox.setText("The File "+file+" already exist!")
        msgBox.setInformativeText("How do you want to proceed?")
        msgBox.addButton("Save as", QtGui.QMessageBox.YesRole)
        msgBox.addButton("Don't Save",  QtGui.QMessageBox.NoRole)
        msgBox.addButton("Replace",  QtGui.QMessageBox.AcceptRole)
        msgBox.setIcon(QtGui.QMessageBox.Warning)
        ret=msgBox.exec_()
        if(ret==0):
            file=str(QtGui.QFileDialog.getSaveFileName(None, "Save as...", path,"All Files (*)"))
            if file=="":
                return None
        if(ret==1):
            file=None
        return(file)


from catboost import CatBoostClassifier, Pool
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, mean_absolute_error
import numpy as np

class CatForest:
    def __init__(self, params=None):
        # Initialize Random Forest parameters
        self.params = params if params else {
            'iterations': 500,
            'learning_rate': 0.1,
            'depth': 6,
            'n_estimators' : 50,
        }
        self.create_model()
        # Initialize the model
    def filter_params(self, valid_params):
        return {k: v for k, v in self.params.items() if k in valid_params}

    def create_model(self):
        # List of valid arguments for CatBoostRegressor
        valid_params = [
        'iterations',
        'learning_rate',
        'n_estimators'
        ]
        filtered_params = self.filter_params(valid_params)
        self.model = CatBoostClassifier(**filtered_params)

    def prepare_data(self, X, y, test_size=0.2, random_state=0):
        """
        Split the data into training and testing datasets.
        """
        self.X_train, self.X_test, self.y_train, self.y_test = train_test_split(
            X, y, test_size=test_size, random_state=random_state
        )
        self.train_pool = Pool(self.X_train, self.y_train)
        self.test_pool = Pool(self.X_test, self.y_test)

    def train(self, verbose=True):
        """
        Train the CatBoost model.
        """
        self.model.fit(self.train_pool, eval_set=self.test_pool, verbose=verbose)

    def predict(self, X):
        """
        Make predictions using the trained model.
        """
        return self.model.predict(X)

    def evaluate(self):
        """
        Evaluate the trained model on the test dataset.
        """
        y_pred = self.predict(self.X_test)
        rmse = np.sqrt(mean_squared_error(self.y_test, y_pred))
        mae = mean_absolute_error(self.y_test, y_pred)
        return {'RMSE': rmse, 'MAE': mae}


import time
import threading
from pynput.mouse import Button, Controller
from pynput.keyboard import Listener, KeyCode

delay = 0.1
button = Button.left
hold_key = KeyCode(char='b')
clicking_key = KeyCode(char='n')
exit_key = KeyCode(char='m')

class ClickingThread(threading.Thread):
    def __init__(self, delay, button):
        super(ClickingThread, self).__init__()
        self.delay = delay
        self.button = button
        self.running = False
        self.program_running = True

    def start_clicking(self):
        self.running = True

    def stop_clicking(self):
        self.running = False

    def exit(self):
        self.stop_clicking()
        self.program_running = False

    def run(self):
        while self.program_running:
            while self.running:
                mouse.click(self.button)
                time.sleep(self.delay)
            time.sleep(0.1)

mouse = Controller()
clicking_thread = ClickingThread(delay, button)
clicking_thread.start()
holding = False

def on_press(key):
    global holding
    if key == clicking_key:
        if clicking_thread.running:
            clicking_thread.stop_clicking()
        else:
            clicking_thread.start_clicking()
    elif key == hold_key:
        if not holding:
            mouse.press(Button.left)
        else:
            mouse.release(Button.left)
        holding=not holding
    elif key == exit_key:
        clicking_thread.exit()
        listener.stop()

with Listener(on_press=on_press) as listener:
    listener.join()


import pygame as pg
import re
from os import listdir
from os.path import isfile, join

vec = pg.math.Vector2

def parse_tuple_to_list(string):
    """
    Parses a string into a tuple
    :param string: The string to convert
    :return: the newly formed tuple
    """
    try:
        t = eval(string)
        if type(t) == tuple:
            return t
    except:
        return

def collide_hit_rect(first, second):
    """
    Call back function which checks if two rectangles have collided with each other
    :param first: the first rectangle
    :param second: the second rectangle
    :return: True if first collided with second. False otherwise
    """
    return first.hit_rect.colliderect(second.hit_rect) or first.hit_rect.colliderect(second.hit_rect)

def world_shift_pos(position, camera):
    vector = vec(position[0], position[1])
    vector.x -= camera.x
    vector.y -= camera.y
    return vector

def collide_with_obstacles(sprite, group, direction):
    """
    Checks where the sprite has collided with an obstacle

    direction is needed to allow a sprite that collides
    horizontally to continue moving vertically if its movement
    was in a diagonal. Same goes for blocked vertical movement
    and continued horizontal movement.
    :param sprite: The sprite to check
    :param group: The group of obstacles to check
    :param direction: For vertical or horizontal movement
    :return: True if there is a collision. False otherwise
    """
    collided = False
    if direction == 'x':
        collided = True
        hits = pg.sprite.spritecollide(sprite, group, False, collide_hit_rect)
        if hits:
            # If the sprite is moving right, stop it and
            # set its right face on the left side of the object it collided with.
            if hits[0].rect.centerx > sprite.hit_rect.centerx:
                sprite.pos.x = hits[0].rect.left - sprite.hit_rect.width / 2
            # If the sprite is moving right, stop it and
            # set its left face on the left side of the object it collided with.
            if hits[0].rect.centerx < sprite.hit_rect.centerx:
                sprite.pos.x = hits[0].rect.right + sprite.hit_rect.width / 2
            # Update the sprite's center to the new position
            sprite.hit_rect.centerx = sprite.pos.x
    if direction == 'y':
        collided = True
        hits = pg.sprite.spritecollide(sprite, group, False, collide_hit_rect)
        if hits:
            # If the sprite is moving upwards, then
            # set its top to the bottom of the sprite it collided with.
            if hits[0].rect.centery < sprite.hit_rect.centery:
                sprite.pos.y = hits[0].rect.bottom + sprite.hit_rect.height / 2
            # If the sprite is moving downwards, then
            # set its bottom to the top of the sprite it collided with.
            if hits[0].rect.centery > sprite.hit_rect.centery:
                sprite.pos.y = hits[0].rect.top - sprite.hit_rect.height / 2
            sprite.hit_rect.centery = sprite.pos.y
    return collided

def get_image_names(path, index=2):
    files = [file for file in listdir(path) if isfile(join(path, file))]
    return [path + file for file in sorted(files, key=lambda x: int(re.split(r'[_.]', x)[index]))]


import random

class QAgent:
    def __init__(self,num_states,num_actions) -> None:
        self.q = {}
        self.gamma = 0.9
        q_init = 0
        self.learning_rate = 0.01
        self.epsilon = 0.99
        self.actions = range(num_actions)
        for state in range(num_states):
            action_values = {}
            for action in range(num_actions):
                action_values[action] = q_init
            self.q[state] = action_values

    def updateQtable(self,old_state,action,reward,new_state,done):
        if done:
            self.q[old_state][action] += self.learning_rate*(reward-self.q[old_state][action])
        else:
            self.q[old_state][action] += self.learning_rate*(reward+self.gamma*max(self.q[new_state])-self.q[old_state][action])
        self.updateEpsilon()

    def updateEpsilon(self):
        self.epsilon *= 0.999999
        if self.epsilon < 0.01:
            self.epsilon = 0.01

    def chooseAction(self,state):

        if random.random() < self.epsilon:
            return random.choice(self.actions)
        else:
            return max(self.q[state],key=self.q[state].get)


import sys
sys.path.append('..')

from typing import Union, List, Generator, Tuple, Match
import re

from aiess.common import memoized

AND_GATES = (" and ",)
OR_GATES  = (" or ",)
NOT_GATES = ("not ",)

# Regular expression for cases like "not A and (not B or not C)"
# Any group captured may be removed.
NOT_GATE_PATTERNS = [r"(?i)(?:(?:^|[^A-Za-z0-9_ ])|(?: ))(not)(?:(?:[^A-Za-z0-9_ ])|( ))"]

QUOTE_CHARS = ["\"", "“", "”"]

def expand(string: str) -> str:
    """Converts the given expression into disjunctive normal form.
    Only supports literal operators (e.g. `and` / `or` / `not`), case insensitive.

    As an example,
    \"A or E and not (B and (C or not D))\"
    would be converted to
    \"A or E and not B or E and not C and E and D\"."""

    # e.g. "not (A and B)" -> "(not A or not B)"
    string = de_morgans_law(string)

    # Performing expansion individually for each OR group ensures we don't
    # get stuck in an infinite loop for inputs such as:
    # "(A or B) and (C or D)" -> "A and (C or D) or B and (C or D)"
    temp_string = ""
    has_delimiter = False
    for split, delimiter in split_unescaped(string, OR_GATES):
        if delimiter:
            has_delimiter = True

        if has_delimiter:
            temp_string += expand(split) + (delimiter if delimiter else "")
        else:
            temp_string += split

    dist_string = distribute(temp_string)
    if string == dist_string:
        return string

    if (len(dist_string) > 100000):
        raise ValueError("Logical expression expanded infinitely, try writing it differently. Could be caused by a missing gate.")

    return expand(dist_string)

def distribute(string: str) -> str:
    """Returns an equivalent more distributed expression
    (e.g. "abc(type:(A and B))" -> "abc(type:A and type:B)")."""
    start, end = deepest_parentheses_range(string)
    if not start and not end:
        # No more parentheses, we're done after normalizing NOT gates.
        # e.g. "type:not nominate" -> "not type:nominate"
        return normalize_not(string)

    # first some (things or here (and then more) along with) even more
    #             ^^^^^^^^^^^^^^^               ^^^^^^^^^^^
    #             pre                           post
    #                      ^^^^^^               ^^^^^^^^^^^
    #                      pre_or               post_or

    content = string[start+1:end]
    pre = backwards_leveled(string[:start])
    post = forwards_leveled(string[end+1:])

    pre_or = None
    for pre_or, _ in split_unescaped(pre, OR_GATES):
        pass
    post_or, _ = next(split_unescaped(post, OR_GATES))

    expanded_content = pre[:-len(pre_or)] if pre_or else pre
    # In this case there's no difference between AND or OR gates, as they maintain their relative orders.
    # e.g. "pre(x or y and z)post" would just become "prexpost or preypost and prezpost"
    for split, gate in split_unescaped(content, AND_GATES + OR_GATES):
        split = surround_nonspace(split, pre_or, post_or)
        expanded_content += split + (gate if gate else "")
    expanded_content += post[len(post_or):] if post_or else post

    # first some (things or here (and then more) along with) even more
    # ^^^^^^^^^^^^               ^             ^           ^^^^^^^^^^^
    # pre_start                  start         end         post_end

    pre_start = string[:start - len(pre)]
    post_end = string[end + len(post) + 1:]

    return cleanup(pre_start + expanded_content + post_end)

def cleanup(string: str) -> str:
    """Returns the string without double spaces and without pairs of parentheses around."""
    while "  " in string:
        string = string.replace("  ", " ")

    while string.startswith("(") and string.endswith(")"):
        string = string[1:-1]

    return string

def parenthesis_equal(string: str) -> bool:
    """Returns whether this string has an equal amount of opening and closing parentheses."""
    parentheses = 0
    for char in string:
        if char == "(": parentheses += 1
        if char == ")": parentheses -= 1
    return parentheses == 0

def deepest_parentheses(string: str) -> str:
    """Returns the string within the deepest level of parentheses, without the parentheses. Raises ValueError on parenthesis inequality."""
    start, end = deepest_parentheses_range(string)
    return string[start:end].strip("()")

def deepest_parentheses_range(string: str) -> Tuple[Union[int, None], Union[int, None]]:
    """Returns a tuple of the indexes of the first deepest level of opening and closing parenthesis.
    Raises ValueError on parenthesis inequality."""
    if not parenthesis_equal(string):
        raise ValueError("There are not an equal amount of opening and closing parentheses.")

    depth = 0
    deepest = 0
    first_deepest = False
    deepest_start = None
    deepest_end = None

    for index, char in enumerate(string):
        if char == "(":
            depth += 1
            if depth > deepest:
                deepest = depth
                deepest_start = index
                first_deepest = True
        if char == ")":
            if depth == deepest and first_deepest:
                deepest_end = index
                first_deepest = False
            depth -= 1

    return (deepest_start, deepest_end)

def backwards_leveled(string: str) -> str:
    """Returns the content before a given position in the string, until our parenthesis level reduces
    (i.e. more opening parentheses are hit than closing ones)."""
    read = ""
    level = 0
    for char in reversed(string):
        if char == "(": level -= 1  # Reading backwards, so we're stepping behind this.
        if char == ")": level += 1
        if level < 0:
            break
        read = char + read  # Reading backwards, so prepend.
    return read

def forwards_leveled(string: str) -> str:
    """Returns the content after a given position in the string, until our parenthesis level reduces
    (i.e. more closing parentheses are hit than opening ones)."""
    read = ""
    level = 0
    for char in string:
        if char == "(": level += 1
        if char == ")": level -= 1
        if level < 0:
            break
        read += char
    return read

@memoized
def split_unescaped(string: str, delimiters: Tuple[str]) -> Generator[Tuple[str, str], None, None]:
    """Returns a generator of tuples consisting of splits and their respective following
    unescaped delimiters (or None if at the end) from the given string. Escaped delimiters are ones
    inside quotes or parentheses.

    So for example splitting \"\"A or B\" or C\" by \" or \" would result in (\"\"A or B\"\", \" or \") and (\"C\", None)."""
    read = ""
    quotes = 0
    parentheses = 0
    for char in string:

        if char in QUOTE_CHARS:
            # So, "this "would work"", but "not"this"".
            if not quotes or read.endswith(" "):
                quotes += 1
            else:
                quotes -= 1

        if char == "(": parentheses += 1
        if char == ")": parentheses -= 1

        read += char

        # Quotes and parentheses are considered escaped, so we ignore delimiters inside them.
        if not quotes and not parentheses:
            for delimiter in delimiters:
                if read.lower().endswith(delimiter):
                    split = read[:-len(delimiter)]  # Don't include the delimiter itself in the split.
                    yield (split, delimiter)
                    read = ""

    yield (read, None)

def de_morgans_law(string: str) -> str:
    """Returns the equivalent boolean expression without NOT gates in front of parentheses,
    including double negation elimination."""
    string = double_negation_elimination(string)

    found_not_gate = None
    not_gate_start, not_gate_end = (None, None)
    needs_negating = None
    needs_negating_index = -1
    read = ""
    for index, char in enumerate(string):
        read += char

        if char == "(":
            for pattern_index, not_gate_pattern in enumerate(NOT_GATE_PATTERNS):
                match = None
                for temp_match in re.finditer(not_gate_pattern, read):
                    if not any(gate in read[temp_match.start(0):].lower() for gate in (AND_GATES + OR_GATES)):
                        match = temp_match

                if match:
                    found_not_gate = NOT_GATES[pattern_index]
                    not_gate_start, not_gate_end = combined_captured_span(match)

                    needs_negating = forwards_leveled(string[index + 1:])
                    needs_negating_index = index + 1

                    break

        if found_not_gate:
            break

    if not needs_negating:
        return string

    # Excludes the found NOT gate.
    prefix = string[:not_gate_start] + string[not_gate_end:needs_negating_index - len("(")]
    postfix = string[needs_negating_index + len(needs_negating) + len(")"):]

    negated_part = negate(needs_negating, not_gate=found_not_gate)
    negated_part = double_negation_elimination(negated_part)

    # Recursively try to negate parentheses until no longer needed.
    return de_morgans_law(prefix + "(" + negated_part + ")" + postfix)

def negate(string: str, not_gate: str=NOT_GATES[0]) -> str:
    """Returns an expression where everything in the string outside parentheses is negated, including OR and AND gates.
    Uses the first available NOT gate, unless another is given."""

    reconstruction = ""
    for or_split, or_gate in split_unescaped(string, OR_GATES):

        # e.g. "A and B" -> "A or B"
        and_temp = ""
        for and_split, and_gate in split_unescaped(or_split, AND_GATES):
            and_split = surround_nonspace(and_split, not_gate, "")
            if and_gate: and_temp += and_split + flip_gate(and_gate)
            else:        and_temp += and_split

        # e.g. "A " -> "A ", but "A or B " -> "(A or B) "
        if any(or_gate in and_temp for or_gate in OR_GATES):
            and_temp = surround_nonspace(and_temp, "(", ")")

        if or_gate: reconstruction += and_temp + flip_gate(or_gate)
        else:       reconstruction += and_temp

    return reconstruction

def flip_gate(gate: str) -> str:
    """Returns any AND gate as the equivalent OR gate, and vice versa. If no such gate exists, we raise a ValueError."""
    for index, and_gate in enumerate(AND_GATES):
        if gate.lower() == and_gate.lower():
            return OR_GATES[index]

    for index, or_gate in enumerate(OR_GATES):
        if gate.lower() == or_gate.lower():
            return AND_GATES[index]

    raise ValueError(f"Cannot flip the gate \"{gate}\".")

def double_negation_elimination(string: str) -> str:
    """Returns the same string, but where all double NOT gates are removed (e.g. "not type:not A" -> "type:A")."""
    matches = []
    for pattern in NOT_GATE_PATTERNS:
        temp = list(re.finditer("(?=(?:" + pattern + "))", string))
        for index, match in enumerate(temp):
            next_match = temp[index + 1] if len(temp) > index + 1 else None
            if not next_match:
                continue

            substring = string[match.start(0):next_match.end(1)].lower()
            if not any(gate in substring for gate in (AND_GATES + OR_GATES + ("(", ")"))):
                matches.append(match)
                matches.append(next_match)

    if len(matches) > 1:
        start1, end1 = combined_captured_span(matches[0])
        start2, end2 = combined_captured_span(matches[1])

        # Recursively remove double NOT gates.
        string = string[:start1] + string[end1:start2] + string[end2:]
        return double_negation_elimination(string)

    # No more double NOT gates.
    return string

def normalize_not(string: str) -> str:
    """Returns the string, but where NOT gates are moved as far back in the string as possible without
    changing the expression. Only works for expressions in disjunctive normal form."""
    reconstruction = ""
    for split, gate in split_unescaped(string, AND_GATES + OR_GATES):

        without_not_gate, not_gate = extract_not(split)

        normalized_split = surround_nonspace(without_not_gate, not_gate, "") if not_gate else split
        reconstruction += normalized_split + (gate if gate else "")

    return reconstruction

def extract_not(expr: str) -> Tuple[str, str]:
    """Returns a tuple of the given expression without the first NOT gate found and
    the NOT gate that was found, if any, otherwise None."""
    for index, pattern in enumerate(NOT_GATE_PATTERNS):
        match = re.search(pattern, expr)
        if match:
            not_gate = NOT_GATES[index]
            start, end = combined_captured_span(match)
            without_not_gate = expr[:start] + expr[end:]

            return (without_not_gate, not_gate)

    return (expr, None)

def surround_nonspace(string: str, pre: str, post: str) -> str:
    """Returns the string surrounded by the given characters, maintaining spaces outside the surrounding."""
    pre_spaces = ""
    for char in string:
        if char == " ": pre_spaces += char
        else:           break

    post_spaces = ""
    for char in reversed(string):
        if char == " ": post_spaces += char
        else:           break

    string = string.strip(" ")
    return pre_spaces + pre + string + post + post_spaces

def combined_captured_span(match: Match) -> Tuple[int, int]:
    """Returns the span of all capture groups in the match. That is, from the first start to the last end."""
    first_start = None
    last_end = None
    for start, end in match.regs[1:]:
        if (first_start is None or first_start > start) and start >= 0:
            first_start = start
        if (last_end is None or last_end < end) and end >= 0:
            last_end = end

    return first_start, last_end


marks={
    'Math': 80,
    'Science': 77,
    'Computer': 95
}

sum = 0
for i in marks.values():
    sum += i;
percentage = float ((sum/300) * 100)
print(percentage)

if percentage < 33:
    print("fail")
elif percentage < 60:
    print("2nd")
elif percentage < 80:
    print("1st")
else:
    print("dictinction")


import os
import sys
import json
import math
import numpy as np
import pandas as pd
import nltk
import re
from sklearn.metrics.pairwise import pairwise_distances
import pysnooper

dataset_dir = os.path.join(
	os.path.dirname(__file__), 'movielens_latest')

title_baselink = 'https://www.imdb.com/title/tt'

class MovieBase:

	def __init__(self, dataset_dir=dataset_dir,
		dataset_name='small_set_movies',
		storage_format='csv',
		rec_df_name='rec_vec_df'):

		filename = os.path.join(
			dataset_dir, dataset_name+'.'+storage_format)

		if storage_format == 'csv':
			self.dataset = pd.read_csv(filename)
		elif storage_format == 'json':
			self.dataset = pd.read_json(filename)
		if rec_df_name is not None:
			self.rec_df = pd.read_csv(os.path.join(dataset_dir, rec_df_name+'.'+storage_format))

		self.dataset.loc[:, 'imdbUrl'] = self.dataset['imdbId'].astype(str)
		self.dataset.loc[:, 'imdbUrl'] = self.dataset['imdbUrl'].apply(pad_to_len)
		self.dataset.loc[:, 'imdbUrl'] = self.dataset['imdbUrl'].apply(lambda x: title_baselink+x)

		self.rec_df = pd.read_csv(os.path.join(dataset_dir, 'rec_df_small'+'.'+storage_format))

	def __len__(self):
		return len(self.dataset)

	def _build_title_vocab(self):
		vocab = []

	def _build_user_matrix(self, movies=None, ratings=None, userId=7777):
		n_items = self.rec_df['movieId'].unique().shape[0]
		user_matrix = np.zeros((1, n_items))
		if movie is None:
			pass
		else:
			for movie, rate in zip(movies, rating):
				pass
				#movie, rating =
		#vec = pd.DataFrame({'userId': })

	def get_movie_genres(self, idx):
		genres = self.dataset.loc[idx, 'genres'].split('|')
		return genres

	def get_imdb_link(self, idx):
		link = self.dataset.loc[idx, 'imdbId']
		return title_baselink+link

	def get_records(self, idx, columns=['title', 'imdbId']):
		return self.dataset.loc[idx, columns]

	def list_genres(self):
		genres = self.dataset.genres.apply(
			lambda x: x.split('|') if '|' in x else [x])
		genres_set = set()
		for g in genres:
			for each in g:
				genres_set.add(each)
		genres_set.remove('(no genres listed)')
		return list(genres_set)

	def get_top_rated(self, num=10, genre=None, actor=None):

		if genre is None:
			top = self.dataset.sort_values('median_rate')[-num:]
		elif genre is not None:
			genres = self.list_genres()
			top = pd.DataFrame()
			while len(top)<num:
				for genre in genres:
					top_by_genre = self.dataset[self.dataset['genres'].str.contains(
						genre.capitalize())].sort_values('median_rate') #[self.dataset.index[-1]]
					if len(top_by_genre)!=0:
						top_by_genre = top_by_genre.loc[top_by_genre.index[-1], :]
						top = top.append(top_by_genre, ignore_index=True)
		if len(top)>num:
			return top.loc[top.index[:num], :]
		return top

	@pysnooper.snoop()
	def get_by_reviewed(self, reviewed, num=10):

		recs = self.rec_df.pivot_table(index ='userId', columns ='title', values ='rating')
		recommended_df = pd.DataFrame()

		while len(recommended_df)<num:

			for movie in reviewed:
				recommendation = recs.corrwith(recs[movie])
				recommendation = recommendation.dropna().sort_values(ascending = False).index[:num]
				recommendation = self.dataset[self.dataset['title'].isin(recommendation)]
				recommended_df = recommended_df.append(recommendation, ignore_index=True)
				recommended_df = recommended_df[~recommended_df['title'].isin(reviewed)]
				recommended_df = recommended_df.drop_duplicates(subset=['title'], keep='first')
				#print(recommended_df.columns)
			break

		pred = recommended_df.sort_values(by=['median_rate'], ascending = False)[:num]
		print(pred[['title', 'median_rate']])

		return pred

	def lookup_movie(self, query, by='title'):

		movie = self.dataset[self.dataset[by].str.contains(
			query, regex=False, case=False)]

		return movie['title'].values[0], movie['imdbUrl'].values[0], movie['imdbId'].values[0]

def pad_to_len(value, length=7):
    value = str(value)
    while len(value)<length:
        value = '0'+value
    return value


class node:
    def __init__(self, value):
        self.value = value
        self.next = None

class LinkedList:
    def __init__(self, value):
        new_node = node(value)
        self.head = new_node
        self.tail = new_node
        self.length = 1

    def print_list(self):
        temp = self.head
        while temp is not None:
            print(temp.value)
            temp = temp.next

    def append(self, value):
        new_node = node(value)
        if self.length == 0:
            self.head = new_node
            self.tail = new_node
        else:
            self.tail.next = new_node
            self.tail = new_node
        self.length += 1
        return True

    def pop(self):
        if self.length == 0:
            return None
        temp = self.head
        pre = self.head
        while(temp.next):
            pre = temp
            temp = temp.next
        self.tail = pre
        self.tail.next = None
        self.length -= 1
        if self.length == 0:
            self.head = None
            self.tail = None
        return temp

    def prepend(self, value):
        new_node = node(value)
        if self.length == 0:
            self.head = new_node
            self.tail = new_node
        else:
            new_node.next = self.head
            self.head = new_node
        self.length +=1
        return True
    def pop_first(self):
        if self.length == 0:
            return None
        temp = self.head
        self.head = self.head.next
        temp.next = None
        self.length -= 1
        if self.length == 0:
            self.tail = None
        return temp
    def get(self, index):
        if index < 0 or index >= self.length:
            return None
        temp = self.head
        for _ in range(index):
            temp = temp.next
        return temp
    def set_value(self, index, value):
        temp = self.get(index)
        if temp:
            temp.value = value
            return True
        return False
    def insert(self, index, value):
        if index < 0 or index > self.length:
            return False
        if index == 0:
            return self.prepend(value)
        if index == self.length:
            return self.append(value)
        new_node = node(value)
        temp = self.get(index - 1)
        new_node.next = temp.next
        temp.next = new_node
        self.length += 1
        return True

    def remove(self, index):
        if index < 0 or index >= self.length:
            return None
        if index == 0:
            return self.pop_first()
        if index == self.length - 1:
            return self.pop()
        pre = self.get(index - 1)
        temp = pre.next
        pre.next = temp.next
        temp.next = None
        self.length -= 1
        return True

    def add_priority(self, data, priority):
        new_node = node(data)
        if self.head is None:
            self.head = new_node
            self.tail = new_node
            return
        if priority == 1:
            new_node.next = self.head
            self.head = new_node
            return
        count = 1
        temp = self.head
        while temp.next and count < priority - 1:
            temp = temp.next
            count += 1
        new_node.next = temp.next
        temp.next = new_node
        if new_node.next is None:
            self.tail = new_node

amal_bansos = LinkedList("")

while True:
    print("""
--------------------------------------------
        Program Amal Bantuan Sosial
--------------------------------------------
1. Menambahkan data penerima bantuan
2. Melihat data penerima bantuan
3. Menambah data prioritas
4. Menghapus data penerima bantuan
5. Keluar
--------------------------------------------
          """)
    pilihan = input("Masukkan pilihan: ")
    if pilihan == "1":
        data = input("Masukkan nama penerima bantuan: ")
        amal_bansos.append(data)
        print("Data berhasil ditambahkan")
    elif pilihan == "2":
        amal_bansos.print_list()
        print("Data berhasil ditampilkan")
    elif pilihan == "3":
        data = input("Masukkan nama data prioritas: ")
        priority = int(input("Masukkan prioritas: "))
        amal_bansos.add_priority(data, priority)
        print("Data menjadi antrian prioritas")
    elif pilihan == "4":
        antrian = int(input("Masukkan antrian yang ingin dihapus : "))
        result = amal_bansos.remove(antrian)
        if result:
            print("Data berhasil dihapus")
        else:
            print("Antrian tidak valid. Gagal menghapus data.")
    elif pilihan == "5":
        print("Terimakasih telah menggunakan program ini")
        exit()
    else:
        print("Pilihan tidak ada")


#!/usr/bin/python

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

import tensorflow as tf

import numpy as np
from six.moves import xrange  # pylint: disable=redefined-builtin

from datetime import datetime
import re
import time
import os
import time
from tflearn.datasets import cifar10

## Import Customized Functions
#import Model
from Data import ReadData, Augmentation
from flags import FLAGS
import tflearn
from tensorflow.python.framework import ops
from utils import *
import network

_FLOATX = tf.float32
_EPSILON = 1e-10

class Train():
	def __init__(self, model, img_size, learning_rate, run_id, config, weight_decay):
		self.model = model
		self.img_size = img_size
		self.learning_rate = learning_rate
		self.run_id = run_id
		self.dict_widx = None
		self.tf_config = config
		self.wd = weight_decay

	def _placeholders(self):
		"""
		Define Placeholders used to building the graph
		"""
		self.batch_data = tf.placeholder(name='data_pl', dtype=tf.float32,
			shape=(FLAGS.train_batch_size,)+self.img_size)
		self.batch_labels = tf.placeholder(name='label_pl', dtype=tf.float32,
			shape=(FLAGS.train_batch_size,10))

	def _build_graph(self):
		global_step = tf.contrib.framework.get_or_create_global_step()

		# Calculate logits using training data and vali data seperately
		logits = getattr(network, 'baseline_rescale')(self.batch_data, 0.5, 0.5, 0.0005, 0, True)

		with tf.name_scope("Crossentropy"):
			#logits /= tf.reduce_sum(logits,reduction_indices=len(logits.get_shape())-1, keep_dims=True)
			# manual computation of crossentropy
			#logits = tf.clip_by_value(logits, tf.cast(_EPSILON, dtype=_FLOATX),
		    #                      tf.cast(1.-_EPSILON, dtype=_FLOATX))
			#cross_entropy = - tf.reduce_mean(self.batch_labels * tf.log(logits))
			cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(
				labels=self.batch_labels, logits=logits, name='corss_entropy'))

			weight_loss = tf.get_collection('losses')
			self.loss = cross_entropy
			if len(weight_loss)>0:
				self.total_loss = tf.add(tf.divide(tf.add_n(weight_loss), FLAGS.train_batch_size), cross_entropy, name='total_loss')
			else:
				self.total_loss = cross_entropy

		with tf.name_scope("train"):
			opt = tf.train.AdamOptimizer(self.learning_rate)
			grads_and_vars = opt.compute_gradients(self.total_loss)

			if self.dict_widx is None:
				apply_gradient_op = opt.apply_gradients(grads_and_vars, global_step=global_step)
			else:
				grads_and_vars = apply_prune_on_grads(grads_and_vars, self.dict_widx)
				apply_gradient_op = opt.apply_gradients(grads_and_vars, global_step=global_step)

			for var in tf.trainable_variables():
				tf.summary.histogram(var.op.name, var)

		with tf.name_scope("accuracy"):
			logits = tf.nn.softmax(logits)
			self.prediction = tf.argmax(logits,1)
			correct_prediction = tf.equal(self.prediction, tf.argmax(self.batch_labels,1))
			self.accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

		self.train_op = tf.group(apply_gradient_op)
		self.summary_op = tf.summary.merge_all()

	def train(self, **kwargs):
		ops.reset_default_graph()
		sess = tf.Session(config=self.tf_config)
		with sess.as_default():
			(X, Y), (X_test, Y_test) = cifar10.load_data()
			X, Y = shuffle(X, Y)
			X = samplewise_zero_center(X)
			X = samplewise_stdnorm(X)
			X_test = samplewise_zero_center(X_test)
			X_test = samplewise_stdnorm(X_test)
			Y = to_categorical(Y, 10)
			Y_test = to_categorical(Y_test, 10)

			self.train_data, self.train_label = np.array(X, dtype=np.float32), np.array(Y, dtype=np.int32)
			self.vali_data, self.vali_label = np.array(X_test, dtype=np.float32), np.array(Y_test, dtype=np.int32)

			print(len(self.train_data))
			# Data Reading objects
			self._placeholders()
			if len(kwargs)==0:
				self.dict_widx = None
				self._build_graph()
				self.saver = tf.train.Saver(tf.global_variables())
				# Build an initialization operation to run below
				init = tf.global_variables_initializer()
				sess.run(init)

			else:
				self.dict_widx = kwargs['dict_widx']
				pruned_model = kwargs['pruned_model_path']
				tflearn.config.init_training_mode()
				self._build_graph()
				init = tf.global_variables_initializer()
				sess.run(init)

				self.saver = tf.train.Saver(tf.global_variables())
				self.saver.restore(sess, pruned_model)
				print('Pruned model restored from ', pruned_model)

			# This summary writer object helps write summaries on tensorboard
			summary_writer = tf.summary.FileWriter(FLAGS.log_dir+self.run_id)
			summary_writer.add_graph(sess.graph)

			train_error_list = []
			val_error_list = []

			print('Start training...')
			print('----------------------------------')

			train_steps_per_epoch = FLAGS.num_train_images//FLAGS.train_batch_size
			report_freq = train_steps_per_epoch

			train_steps = FLAGS.train_epoch * train_steps_per_epoch

			durations = []
			train_loss_list = []
			train_accuracy_list = []
			train_total_loss_list = []

			best_accuracy = 0

			log_file = open(os.path.join(FLAGS.log_dir, self.run_id, 'loss_accuracy_list'), 'a')

			for step in range(train_steps):
				tflearn.is_training(True)

				start_time = time.time()

				train_batch_data, train_batch_labels = self._generate_batch(self.train_data, self.train_label,
													   FLAGS.train_batch_size, step, train=True)

				_, summary_str, loss_value, total_loss, accuracy = sess.run([self.train_op, self.summary_op, self.loss, self.total_loss, self.accuracy],
													   feed_dict={self.batch_data: train_batch_data,
													   			  self.batch_labels: train_batch_labels})

				#summary_str = ''
				duration = time.time() - start_time
				durations.append(duration)
				#print(duration)
				train_loss_list.append(loss_value)
				train_total_loss_list.append(total_loss)
				train_accuracy_list.append(accuracy)

				assert not np.isnan(loss_value), 'Model diverged with loss = NaN'

				if step%report_freq == 0:
					summary_writer.add_summary(summary_str, step)

					sec_per_report = np.sum(np.array(durations))*1.2
					train_loss_value = np.mean(np.array(train_loss_list))
					train_total_loss = np.mean(np.array(train_total_loss_list))
					train_accuracy_value = np.mean(np.array(train_accuracy_list))

					train_loss_list = []
					train_total_loss_list = []
					train_accuracy_list = []
					durations = []

					train_summ = tf.Summary()
					train_summ.value.add(tag="train_loss", simple_value=train_loss_value.astype(np.float))
					train_summ.value.add(tag="train_total_loss", simple_value=train_total_loss.astype(np.float))
					train_summ.value.add(tag="train_accuracy", simple_value=train_accuracy_value.astype(np.float))

					summary_writer.add_summary(train_summ, step)

					vali_loss_value, vali_accuracy_value = self._full_validation(sess)

					if vali_accuracy_value>best_accuracy:
						best_accuracy = vali_accuracy_value

						model_dir = os.path.join(FLAGS.log_dir, self.run_id, 'model')
						if not os.path.isdir(model_dir):
							os.mkdir(model_dir)
						checkpoint_path = os.path.join(model_dir, 'vali_{:.3f}'.format(vali_accuracy_value))

						self.saver.save(sess, checkpoint_path, global_step=step)

					vali_summ = tf.Summary()
					vali_summ.value.add(tag="vali_loss", simple_value=vali_loss_value.astype(np.float))
					vali_summ.value.add(tag="vali_accuracy", simple_value=vali_accuracy_value.astype(np.float))

					summary_writer.add_summary(vali_summ, step)
					summary_writer.flush()

					format_str = ('Epoch %d, loss = %.4f, total_loss = %.4f, accuracy = %.4f, vali_loss = %.4f, vali_accuracy = %.4f (%.3f ' 'sec/report)')
					print(format_str % (step//report_freq, train_loss_value, train_total_loss, train_accuracy_value, vali_loss_value, vali_accuracy_value, sec_per_report))
					log_file.write('{},{},{},{} \n'.format(train_loss_value, train_accuracy_value, vali_loss_value, vali_accuracy_value))
			log_file.close()

	def test(self):
		ops.reset_default_graph()
		(X, Y), (X_test, Y_test) = cifar10.load_data()
		X, Y = shuffle(X, Y)
		X = samplewise_zero_center(X)
		X = samplewise_stdnorm(X)
		X_test = samplewise_zero_center(X_test)
		X_test = samplewise_stdnorm(X_test)

		test_batch_data = tf.placeholder(name='data_pl', dtype=tf.float32,
			shape=(FLAGS.test_batch_size,)+self.img_size)
		test_batch_labels = tf.placeholder(name='label_pl', dtype=tf.int32,
			shape=(FLAGS.test_batch_size,))

		logits = getattr(Model, self.model)(test_batch_data)
		prediction = tf.cast(tf.argmax(logits,1), tf.int32)
		correct_prediction = tf.equal(prediction, test_batch_labels)
		accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

		saver = tf.train.Saver(tf.global_variables())
		sess = tf.Session(config=self.tf_config)

		saver.restore(sess, FLAGS.test_ckpt_path)
		print('Model restored from ', FLAGS.test_ckpt_path)

		prediction_array = np.array([]).reshape(-1, FLAGS.num_categories)

		num_batches = FLAGS.num_test_images//FLAGS.test_batch_size
		accuracy_list = []

		for step in range(num_batches):
			batch_data, batch_labels = self._generate_batch(X_test, Y_test,
													   FLAGS.test_batch_size, step, train=False)

			batch_prediction_array, batch_accuracy = sess.run([prediction, accuracy], feed_dict={test_batch_data: batch_data,
													   			  test_batch_labels: test_batch_labels})
			#prediction_array = np.concatenate((prediction_array, batch_prediction_array))
			accuracy_list.append(batch_accuracy)

		accuracy = np.mean(np.array(accuracy_list, dtype=np.float32))

		return prediction_array, accuracy_list

	def _full_validation(self, sess):
		tflearn.is_training(True)
		num_batches_vali = FLAGS.num_eval_images // FLAGS.test_batch_size

		loss_list = []
		accuracy_list = []

		start_time = time.time()

		for step_vali in range(num_batches_vali):
			vali_batch_data, vali_batch_labels = self._generate_batch(self.vali_data, self.vali_label,
													  			 	  FLAGS.train_batch_size, step_vali, train=False)

			loss, accuracy = sess.run([self.loss, self.accuracy],  feed_dict={self.batch_data: vali_batch_data,
													   	                  self.batch_labels: vali_batch_labels})

			loss_list.append(loss)
			accuracy_list.append(accuracy)

		duration = time.time() - start_time

		vali_loss_value = np.mean(np.array(loss_list))
		vali_accuracy_value = np.mean(np.array(accuracy_list))

		return vali_loss_value, vali_accuracy_value

	def _generate_batch(self, all_data, all_labels, batch_size, step, train=True):
		train_steps_per_epoch = FLAGS.num_train_images//FLAGS.train_batch_size
		if step % train_steps_per_epoch ==0:
			all_data, all_labels = shuffle(all_data, all_labels)
		num_batches = FLAGS.num_train_images//batch_size
		offset = step%num_batches

		batch_data = np.copy(all_data[offset*batch_size:(offset+1)*batch_size, :])
		#batch_data = random_crop_and_flip(batch_data, padding_size=FLAGS.padding_size)

		#batch_data = whitening_image(batch_data)
		batch_labels = np.copy(all_labels[offset*batch_size:(offset+1)*batch_size,:])

		#batch_data = samplewise_zero_center(batch_data)
		#batch_data = samplewise_stdnorm(batch_data)
		'''
		if train:
			aug = Augmentation(batch_data)

			aug.random_flip_leftright()
			aug.random_rotation(max_angle=25.)
			batch_data = aug.output()
		'''
		return batch_data, batch_labels

def main(argv=None):
	os.environ["CUDA_VISIBLE_DEVICES"]="3"
	tf_config=tf.ConfigProto()
	tf_config.gpu_options.allow_growth=True
	tf_config.gpu_options.per_process_gpu_memory_fraction=0.9
	img_size = (32,32,3)

	model = 'vgg16_all'
	learning_rate = 0.01
	option = 1
	weight_decay = 0

	if option == 1:
		run_name = 'test'
		run_id = '{}_{}_lr_{}_wd_{}_{}'.format(model, run_name, learning_rate, weight_decay, time.strftime("%b_%d_%H_%M", time.localtime()))

		# First Training
		train = Train(model, img_size, learning_rate, run_id, tf_config, weight_decay)
		train.train()

	elif option == 2:
		# Filter pruning
		trained_path = '/home/spc/Dropbox/tf_GDCNN/log/model/Test_0.0001_Aug_07_18_28_33_vali_0.8699822425842285-22320'
		layers = getattr(Model, model+'_variable_of_interest')()
		sel_layer_names = layers[2:len(layers)]
		run_name = 'Prune_Test'
		run_id = '{}_{}'.format(run_name,time.strftime("%b_%d_%H_%M_%S", time.gmtime()))

		dict_widx, pruned_model_path = apply_pruning(sel_layer_names, trained_path, run_id, tf_config)

		train = Train(model, img_size, learning_rate, run_id='{}_retrain_{}'.format(run_id, learning_rate), config=tf_config)
		train.train(dict_widx=dict_widx, pruned_model_path=pruned_model_path)

	elif option == 3:
		train = Train(model, img_size, learning_rate, run_name, tf_config)
		_, accuracy = train.test()
		print(accuracy)

if __name__ == '__main__':
	tf.app.run()


from flask import Flask, jsonify, request
import os
import cv2
import urllib.request
import numpy as np

app = Flask(__name__)

faceProto = "opencv_face_detector.pbtxt"
faceModel = "opencv_face_detector_uint8.pb"

ageProto = "age_deploy.prototxt"
ageModel = "age_net.caffemodel"

genderProto = "gender_deploy.prototxt"
genderModel = "gender_net.caffemodel"

MODEL_MEAN_VALUES = (78.4263377603, 87.7689143744, 114.895847746)
ageList = ['0-2', '4-6', '8-12', '15-20', '25-32', '38-43', '48-53', '60-100']
genderList = ['Male', 'Female']

def load_model():
    global ageNet, genderNet, faceNet
    ageNet = cv2.dnn.readNet(ageModel, ageProto)
    genderNet = cv2.dnn.readNet(genderModel, genderProto)
    faceNet = cv2.dnn.readNet(faceModel, faceProto)

def getFaceBox(net, frame, conf_threshold=0.7):
    frameHeight = frame.shape[0]
    frameWidth = frame.shape[1]
    blob = cv2.dnn.blobFromImage(frame, 1.0, (300, 300), [104, 117, 123], True, False)

    net.setInput(blob)
    detections = net.forward()
    bboxes = []
    for i in range(detections.shape[2]):
        confidence = detections[0, 0, i, 2]
        if confidence > conf_threshold:
            x1 = int(detections[0, 0, i, 3] * frameWidth)
            y1 = int(detections[0, 0, i, 4] * frameHeight)
            x2 = int(detections[0, 0, i, 5] * frameWidth)
            y2 = int(detections[0, 0, i, 6] * frameHeight)
            bboxes.append([x1, y1, x2, y2])

    return bboxes

@app.route("/detectFace", methods=["POST"])
def detectFace():
    if request.method == 'POST':
        bboxes = []
        if(request.files):
            img_file = request.files['img_file']
            file_data = img_file.read()
            nparr = np.fromstring(file_data, np.uint8)
            img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
            bboxes = getFaceBox(faceNet, img)

        elif(request.form):
            headers = {
                "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:47.0) Gecko/20100101 Firefox/47.0",
            }
            req = urllib.request.Request(url=request.form['url'], headers=headers)
            resp = urllib.request.urlopen(req)
            nparr = np.asarray(bytearray(resp.read()), dtype="uint8")
            img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
            bboxes = getFaceBox(faceNet, img)

        faces = []
        padding = 20
        for bbox in bboxes:
            face = img[max(0,bbox[1]-padding):min(bbox[3]+padding,img.shape[0]-1),max(0,bbox[0]-padding):min(bbox[2]+padding, img.shape[1]-1)]
            face_location = {"left":bbox[0], "top":bbox[1], "width":bbox[2]-bbox[0], "height":bbox[3]-bbox[1]}

            blob = cv2.dnn.blobFromImage(face, 1.0, (227, 227), MODEL_MEAN_VALUES, swapRB=False)
            genderNet.setInput(blob)
            genderPreds = genderNet.forward()
            gender = genderList[genderPreds[0].argmax()]
            gender = {"gender":gender, "confidence":"{:.3f}".format(genderPreds[0].max())}

            ageNet.setInput(blob)
            agePreds = ageNet.forward()
            age = ageList[agePreds[0].argmax()]
            age = {"min":"{}".format(age.split("-")[0]), "max":"{}".format(age.split("-")[1]), "confidence":"{:.3f}".format(agePreds[0].max())}

            faces.append({"face_location":face_location, "gender":gender, "age":age})

    return jsonify({"faces":faces})

port = os.getenv('PORT', '5000')
if __name__ == "__main__":
    load_model()
    print(" * Flask starting server...")
    app.run(host='0.0.0.0', port=int(port))


"""
 Exercise replace string with a different word
"""

filename = "../Chap 9 - Class/learning_python.txt"
with open(filename) as fileobject:
    content = fileobject.read()

new_content = content.replace('Python', 'C')
print(new_content)

Python Crash Course/Chap 10 - Files Execption/Chap10-2.Learning C.py


# Question Name: Reverse Integer
# Difficuly level: EASY

# Question prompt:
    # Given a 32-bit signed integer, reverse digits of an integer.
    # Note: Assume we are dealing with an environment that could only store integers within the 32-bit signed integer range: [−231,  231 − 1]. For the purpose of this problem, assume that your function returns 0 when the reversed integer overflows.

# Question Intuition:
    # given a negative integer solve for modulus integer and add negative sign.
    # as long as the number isn't 0 you divide it by 10 to get the digit at the end
    # you successively multiply by 10 and add the remainder to create the reversed number.
    # add the size constraint.

# SOLUTION 1:

class Solution:
    def reverse(self, x: int) -> int: # x = 1234
        rev = 0
        is_neg = x < 0
        if is_neg:
            x = -x

        while(x != 0):
            a = x % 10 #4 #3 #2 #1
            rev = rev * 10 + a #4 #4*10 + 3 # (4 * 10 + 3)* 10 + 2 ...
            x = (x - a) / 10 #123 #12 #1

        factor = -1 if is_neg else 1

        ans = (factor * int(rev))

        if -math.pow(2,31) <= ans <= math.pow(2,31) - 1:
            return ans
        else:
            return 0


import matplotlib.pyplot as plt
import numpy as np
import torch
from torch import nn
from torch import tensor
from torch import optim
import torch.nn.functional as F
from torch.autograd import Variable
from torchvision import datasets, transforms
import torchvision.models as models
from collections import OrderedDict
import json
import PIL
from PIL import Image
import argparse

structures = {"vgg16":25088,
              "vgg13":25088}

def transform_image(root):

    data_dir = root
    train_dir = data_dir + '/train'
    valid_dir = data_dir + '/valid'
    test_dir = data_dir + '/test'
    data_transforms ={
    'train_transforms':transforms.Compose([transforms.RandomRotation(30),
                                       transforms.RandomResizedCrop(224),
                                       transforms.RandomHorizontalFlip(),
                                       transforms.ToTensor(),
                                       transforms.Normalize([0.485, 0.456, 0.406],
                                                            [0.229, 0.224, 0.225])]),
    'test_transforms' : transforms.Compose([transforms.Resize(256),
                                      transforms.CenterCrop(224),
                                      transforms.ToTensor(),
                                      transforms.Normalize([0.485, 0.456, 0.406],
                                                           [0.229, 0.224, 0.225])]),
    'validation_transforms' : transforms.Compose([transforms.Resize(256),
                                      transforms.CenterCrop(224),
                                      transforms.ToTensor(),
                                      transforms.Normalize([0.485, 0.456, 0.406],
                                                           [0.229, 0.224, 0.225])])}
    image_datasets = {'train_data' : datasets.ImageFolder(data_dir + '/train', transform=data_transforms['train_transforms']),
    'test_data' : datasets.ImageFolder(data_dir + '/test', transform=data_transforms['test_transforms']),
    'valid_data' : datasets.ImageFolder(data_dir + '/valid', transform=data_transforms['validation_transforms'])
                 }

    return image_datasets['train_data'] , image_datasets['valid_data'], image_datasets['test_data']

def load_data(root):

    data_dir = root
    tr_data,val_data,te_data=transform_image(data_dir)

    dataloaders = {'trainloader' : torch.utils.data.DataLoader(tr_data, batch_size=64, shuffle=True),
    'testloader' : torch.utils.data.DataLoader(te_data, batch_size=32),
    'validloader' : torch.utils.data.DataLoader(val_data, batch_size=32)}

    return dataloaders['trainloader'] , dataloaders['validloader'], dataloaders['testloader']

train_data,valid_data,test_data=transform_image('./flowers/')
trdl,vdl,tsdl=load_data('./flowers/')

def neural_network(structure='vgg16',dropout=0.5, hidden_layer1 = 4096,lr = 0.001,power='gpu'):
    '''
    Arguments: The architecture for the network(alexnet,densenet121,vgg16), the hyperparameters for the network (hidden layer 1 nodes, dropout and learning rate) and whether to use gpu or not
    Returns: The set up model, along with the criterion and the optimizer fo the Training
    '''

    if structure == 'vgg16':
        model = models.vgg16(pretrained=True)

    elif structure == 'vgg13':
        model = models.vgg13(pretrained=True)

    else:
        print("Please try vgg16 or vgg13")

    for param in model.parameters():
        param.requires_grad = False

    classifier = nn.Sequential(OrderedDict([
            ('dropout',nn.Dropout(dropout)),
            ('inputs', nn.Linear(structures[structure], hidden_layer1)),
            ('relu1', nn.ReLU()),
            ('hidden_layer1', nn.Linear(hidden_layer1, 90)),
            ('relu2',nn.ReLU()),
            ('hidden_layer2',nn.Linear(90,80)),
            ('relu3',nn.ReLU()),
            ('hidden_layer3',nn.Linear(80,102)),
            ('output', nn.LogSoftmax(dim=1))
                          ]))

    model.classifier = classifier
    criterion = nn.NLLLoss()
    optimizer = optim.Adam(model.classifier.parameters(), lr )

    if torch.cuda.is_available() and power == 'gpu':
        model.cuda()

    return model , criterion , optimizer

def train_network(model, criterion, optimizer, epochs = 6, print_every=40, loader=0, power='gpu'):

    '''
    Arguments: The model, the criterion, the optimizer, the number of epochs, teh dataset, and whether to use a gpu or not
    Returns: Nothing
    This function trains the model over a certain number of epochs and displays the training,validation and accuracy every "print_every" step using cuda if specified. The training method is specified by the criterion and the optimizer which are NLLLoss and Adam respectively
    '''
    steps = 0

    print("--------------Training is starting------------- ")
    for e in range(epochs):
        running_loss = 0
        for ii, (inputs, labels) in enumerate(loader):
            steps += 1
            if torch.cuda.is_available() and power =='gpu':
                inputs, labels = inputs.to('cuda'), labels.to('cuda')

            optimizer.zero_grad()

            # Forward and backward passes
            outputs = model.forward(inputs)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()

            running_loss += loss.item()

            if steps % print_every == 0:
                model.eval()
                vlost = 0
                accuracy=0

                for ii, (inputs2,labels2) in enumerate(vdl):
                    optimizer.zero_grad()
                    if torch.cuda.is_available():
                        inputs2, labels2 = inputs2.to('cuda') , labels2.to('cuda')
                        model.to('cuda')

                    with torch.no_grad():
                        outputs = model.forward(inputs2)
                        vlost = criterion(outputs,labels2)
                        ps = torch.exp(outputs).data
                        equality = (labels2.data == ps.max(1)[1])
                        accuracy += equality.type_as(torch.FloatTensor()).mean()

                vlost = vlost / len(vdl)
                accuracy = accuracy /len(vdl)

                print("Epoch: {}/{}... ".format(e+1, epochs),
                      "Loss: {:.4f}".format(running_loss/print_every),
                      "Validation Lost: {:.4f}".format(vlost),
                       "Accuracy: {:.4f}".format(accuracy))

                running_loss = 0

    print("-------------- Finished training -----------------------")
    print("Dear User I the ulitmate NN machine trained your model. It required")
    print("----------Epochs: {}------------------------------------".format(epochs))
    print("----------Steps: {}-----------------------------".format(steps))
    print("That's a lot of steps")

def save_checkpoint(path='checkpoint.pth',structure ='vgg16', hidden_layer1 = 4096,dropout=0.5,lr=0.001,epochs=6):

    model.class_to_idx =  train_data.class_to_idx
    model.cpu()
    torch.save({'structure' :structure,
                'hidden_layer1':hidden_layer1,
                'dropout':dropout,
                'lr':lr,
                'nb_of_epochs':epochs,
                'state_dict':model.state_dict(),
                'class_to_idx':model.class_to_idx},
                path)

def load_checkpoint(path='checkpoint.pth'):
    checkpoint = torch.load(path)
    lr=checkpoint['lr']
    hidden_layer1 = checkpoint['hidden_layer1']
    dropout = checkpoint['dropout']
    structure = checkpoint['structure']

    model,_,_ = neural_network(structure , dropout,hidden_layer1,lr)

    model.class_to_idx = checkpoint['class_to_idx']
    model.load_state_dict(checkpoint['state_dict'])

    return model

def process_image(image_path):

    proc_img = Image.open(image_path)

    prepoceess_img = transforms.Compose([
        transforms.Resize(256),
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
    ])

    pymodel_img = prepoceess_img(proc_img)
    return pymodel_img

def predict(image_path, model, topk=5,power='gpu'):

    if torch.cuda.is_available() and device =='gpu':
        model.to('cuda')

    img_torch = process_image(image)
    img_torch = img_torch.unsqueeze_(0)
    img_torch = img_torch.float()

    if device == 'gpu':
        with torch.no_grad():
            output = model.forward(img_torch.cuda())
    else:
        with torch.no_grad():
            output=model.forward(img_torch)

    probability = F.softmax(output.data,dim=1)

    return probability.topk(topk)


import random

def partition(li, left, right):
    # You are given a list of size N, ans an element from the list called as'pivot element'.
    # You need to segeregate all the elements lesser than pivot on the left side & greater than pivot on the right side in any order.    m = left
    m = left
    pivot_index = random.randrange(left, right)
    pivot = li[pivot_index]
    li[right], li[pivot_index] = li[pivot_index], li[right]
    for i in range(left, right):
        if li[i] <= pivot:
            li[i], li[m] = li[m], li[i]
            m+=1
    li[right], li[m] = li[m], li[right]
    return m

def quick_sort(li, left, right):
    if left>=right:
        return
    pivot_index = partition(li, left, right)
    quick_sort(li, left, pivot_index-1)
    quick_sort(li, pivot_index+1, right)

    return
li = [2, 3, 4, 1, 4, 6, 3, 9, -1, -7, 10]
quick_sort(li, 0, len(li)-1)
print(li)


#!/usr/bin/python3
# -*- coding: utf-8 -*-

from gnr.web.gnrbaseclasses import BaseComponent
from gnr.core.gnrdecorator import public_method

class View(BaseComponent):

    def th_struct(self,struct):
        r = struct.view().rows()
        r.fieldcell('arrival_id')
        r.fieldcell('ora_arr')
        r.fieldcell('data_arr')
        r.fieldcell('sosta_gg')
        r.fieldcell('rif_alim')
        r.fieldcell('bilge')
        r.fieldcell('cargo_res')
        r.fieldcell('altro')
        r.fieldcell('altro_spec')
        r.fieldcell('invio_fat')

    def th_order(self):
        return 'arrival_id'

    def th_query(self):
        return dict(column='id', op='contains', val='')

class ViewFromGarbage(BaseComponent):

    def th_struct(self,struct):
        r = struct.view().rows()
        r.fieldcell('arrival_id')
        r.fieldcell('ora_arr', edit=dict(validate_notnull=True))
        r.fieldcell('data_arr', edit=dict(validate_notnull=True))
        r.fieldcell('sosta_gg', edit=dict(validate_notnull=True))
        r.fieldcell('rif_alim', edit=True)
        r.fieldcell('bilge', edit=True)
        r.fieldcell('cargo_res', edit=True)
        r.fieldcell('altro', edit=True)
        r.fieldcell('altro_spec', edit=True, width='25em')
        r.fieldcell('invio_fat', edit=True, width='40em')

class Form(BaseComponent):

    def th_form(self, form):
        pane = form.record
        fb = pane.formbuilder(cols=2, border_spacing='4px')
        fb.field('arrival_id' )
        fb.field('ora_arr' )
        fb.field('data_arr' )
        fb.field('sosta_gg' )
        fb.field('rif_alim' )
        fb.field('bilge' )
        fb.field('cargo_res' )
        fb.field('altro' )
        fb.field('altro_spec' )
        fb.field('invio_fat' )

    def th_options(self):
        return dict(dialog_height='400px', dialog_width='600px' )


from glob import glob
import os
from setuptools import setup

package_name = 'ros2_rtimulib'
share_dir = os.path.join('share', package_name)

setup(
    name=package_name,
    version='0.1.0',
    packages=[package_name],
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
        (os.path.join(share_dir, 'launch'), glob('launch/*.launch.py')),
        (os.path.join(share_dir, 'config'), glob('config/*.yaml')),
        (share_dir, glob('config/*.ini')),
    ],
    install_requires=['pyyaml'],
    zip_safe=True,
    author='Kurt Kiefer',
    maintainer='Kurt Kiefer',
    keywords=['ROS2'],
    maintainer_email='kekiefer@gmail.com',
    description='A package to publish IMU messages from an rtimulib-compatible sensor.',
    license='MIT',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
            'imu_node = ros2_rtimulib.imu_node:main'
        ],
    },
)


"""Standard Experiment for Learning Control in RL."""
import click
from collections import defaultdict
from copy import deepcopy
import json
import logging
import numpy as np
import os
import re
from rlpy.tools import (
    checkNCreateDirectory,
    clock,
    deltaT,
    hhmmss,
    plt,
    with_pdf_fonts,
    MARKERS,
)
from rlpy.tools.encoders import NpAwareEncoder
import rlpy.tools.results

__copyright__ = "Copyright 2013, RLPy http://acl.mit.edu/RLPy"
__credits__ = [
    "Alborz Geramifard",
    "Robert H. Klein",
    "Christoph Dann",
    "William Dabney",
    "Jonathan P. How",
]
__license__ = "BSD 3-Clause"

class Experiment(object):

    """
    The Experiment controls the training, testing, and evaluation of the
    agent. Reinforcement learning is based around
    the concept of training an :py:class:`~agents.agent.Agent` to solve a task,
    and later testing its ability to do so based on what it has learned.
    This cycle forms a loop that the experiment defines and controls. First
    the agent is repeatedly tasked with solving a problem determined by the
    :py:class:`~domains.Domain.Domain`, restarting after some termination
    condition is reached.
    (The sequence of steps between terminations is known as an *episode*.)

    Each time the Agent attempts to solve the task, it learns more about how
    to accomplish its goal. The experiment controls this loop of "training
    sessions", iterating over each step in which the Agent and Domain interact.
    After a set number of training sessions defined by the experiment, the
    agent's current policy is tested for its performance on the task.
    The experiment collects data on the agent's performance and then puts the
    agent through more training sessions. After a set number of loops, training
    sessions followed by an evaluation, the experiment is complete and the
    gathered data is printed and saved. For each section, training and
    evaluation, the experiment determines whether or not the visualization
    of the step should generated.

    The Experiment class is a base class that provides
    the basic framework for all RL experiments. It provides the methods and
    attributes that allow child classes to interact with the Agent
    and Domain classes within the RLPy library.

    .. note::
        All experiment implementations should inherit from this class.
    """

    #: The Main Random Seed used to generate other random seeds (we use a different seed for each experiment id)
    MAIN_SEED = 999999999
    #: Maximum number of runs used for averaging, specified so that enough
    #: random seeds are generated
    MAX_RUNS = 1000
    result = None

    log_template = "{total_steps: >6}: E[{elapsed}]-R[{remaining}]: Return={totreturn: >10.4g}, Steps={steps: >4}, Features = {num_feat}"
    performance_log_template = "{total_steps: >6}: >>> E[{elapsed}]-R[{remaining}]: Return={totreturn: >10.4g}, Steps={steps: >4}, Features = {num_feat}"

    def __init__(
        self,
        agent,
        domain,
        exp_id=1,
        max_steps=1000,
        config_logging=True,
        num_policy_checks=10,
        log_interval=1,
        path="Results/Temp",
        checks_per_policy=1,
        stat_bins_per_state_dim=0,
        capture_evaluation=False,
        **kwargs
    ):
        """
        :param agent: the :py:class:`~agents.agent.Agent` to use for learning the task.
        :param domain: the problem :py:class:`~domains.Domain.Domain` to learn
        :param exp_id: ID of this experiment (main seed used for calls to np.rand)
        :param max_steps: Total number of interactions (steps) before experiment termination.

        .. note::
            ``max_steps`` is distinct from ``episode_cap``; ``episode_cap`` defines the
            the largest number of interactions which can occur in a single
            episode / trajectory, while ``max_steps`` limits the sum of all
            interactions over all episodes which can occur in an experiment.

        :param num_policy_checks: Number of Performance Checks uniformly
            scattered along timesteps of the experiment
        :param log_interval: Number of seconds between log prints to console
        :param path: Path to the directory to be used for results storage
            (Results are stored in ``path/output_filename``)
        :param checks_per_policy: defines how many episodes should be run to
            estimate the performance of a single policy

        """
        self.exp_id = exp_id
        assert exp_id > 0
        self.agent = agent
        self.checks_per_policy = checks_per_policy
        self.domain = domain
        self.max_steps = max_steps
        self.num_policy_checks = num_policy_checks
        self.logger = logging.getLogger("rlpy.experiments.Experiment")
        self.log_interval = log_interval
        self.config_logging = config_logging
        self.path = path
        #: The name of the file used to store the data
        self.output_filename = ""
        # Array of random seeds. This is used to make sure all jobs start with
        # the same random seed
        self.random_seeds = np.random.RandomState(self.MAIN_SEED).randint(
            1, self.MAIN_SEED, self.MAX_RUNS
        )
        self.capture_evaluation = capture_evaluation
        self.result = defaultdict(list)
        if stat_bins_per_state_dim > 0:
            self.state_counts_learn = np.zeros(
                (domain.statespace_limits.shape[0], stat_bins_per_state_dim),
                dtype=np.long,
            )
            self.state_counts_perf = np.zeros(
                (domain.statespace_limits.shape[0], stat_bins_per_state_dim),
                dtype=np.long,
            )

    def _update_path(self, path):

        # compile and create output path
        self.full_path = self.compile_path(path)
        checkNCreateDirectory(self.full_path + "/")
        self.logger.info("Output:\t\t\t%s/%s" % (self.full_path, self.output_filename))
        # TODO set up logging to file for rlpy loggers
        self.log_filename = "{:0>3}.log".format(self.exp_id)
        if self.config_logging:
            rlpy_logger = logging.getLogger("rlpy")
            for h in rlpy_logger.handlers:
                rlpy_logger.removeHandler(h)
            rlpy_logger.addHandler(logging.StreamHandler())
            rlpy_logger.addHandler(
                logging.FileHandler(os.path.join(self.full_path, self.log_filename))
            )
            rlpy_logger.setLevel(logging.INFO)

    def seed_components(self):
        """
        set the initial seeds for all random number generators used during
        the experiment run based on the currently set ``exp_id``.
        """
        self._update_path(self.path)
        self.output_filename = "{:0>3}-results.json".format(self.exp_id)
        np.random.seed(self.random_seeds[self.exp_id - 1])
        self.domain.set_seed(self.random_seeds[self.exp_id - 1])
        # make sure the performance_domain has a different seed
        self.performance_domain.set_seed(self.random_seeds[self.exp_id + 20])

        # Its ok if use same seed as domain, random calls completely different
        self.agent.set_seed(self.random_seeds[self.exp_id - 1])

        self.log_filename = "{:0>3}.log".format(self.exp_id)
        if self.config_logging:
            rlpy_logger = logging.getLogger("rlpy")
            for h in rlpy_logger.handlers:
                if isinstance(h, logging.FileHandler):
                    rlpy_logger.removeHandler(h)
            rlpy_logger.addHandler(
                logging.FileHandler(os.path.join(self.full_path, self.log_filename))
            )

    def performance_run(self, total_steps, visualize=False):
        """
        Execute a single episode using the current policy to evaluate its
        performance. No exploration or learning is enabled.

        :param total_steps: int
            maximum number of steps of the episode to peform
        :param visualize: boolean, optional
            defines whether to show each step or not (if implemented by the domain)
        """

        # Set Exploration to zero and sample one episode from the domain
        eps_length, eps_return, eps_discount_return, eps_term = 0, 0, 0, 0
        a = None

        self.agent.policy.turn_off_exploration()

        s, eps_term, p_actions = self.performance_domain.s0()

        while not eps_term and eps_length < self.domain.episode_cap:
            a = self.agent.policy.pi(s, eps_term, p_actions)
            if visualize:
                self.performance_domain.show_domain(a)
                if self.capture_evaluation:
                    click.pause("Get ready to capture the window?")
                    self.capture_evaluation = False

            r, ns, eps_term, p_actions = self.performance_domain.step(a)
            self._gather_transition_statistics(s, a, ns, r, learning=False)
            s = ns
            eps_return += r
            eps_discount_return += (
                self.performance_domain.discount_factor ** eps_length * r
            )
            eps_length += 1
        if visualize:
            self.performance_domain.show_domain(a)
        self.agent.policy.turn_on_exploration()
        # This hidden state is for domains (such as the noise in the helicopter domain)
        # that include unobservable elements that are evolving over time
        # Ideally the domain should be formulated as a POMDP but we are trying
        # to accomodate them as an MDP

        return eps_return, eps_length, eps_term, eps_discount_return

    def _gather_transition_statistics(self, s, a, sn, r, learning=False):
        """
        This function can be used in subclasses to collect statistics
        about the transitions
        """
        if hasattr(self, "state_counts_learn") and learning:
            counts = self.state_counts_learn
        elif hasattr(self, "state_counts_perf") and not learning:
            counts = self.state_counts_perf
        else:
            return
        rng = self.domain.statespace_width
        d = counts.shape[-1] - 2
        s_norm = s - self.domain.statespace_limits[:, 0]
        idx = np.floor(s_norm / rng * d).astype("int")
        idx += 1
        idx[idx < 0] = 0
        idx[idx >= d + 2] = d + 1
        # import ipdb; ipdb.set_trace()
        counts[list(range(counts.shape[0])), idx] += 1

    def run(
        self, visualize_performance=0, visualize_learning=False, visualize_steps=False
    ):
        """
        Run the experiment and collect statistics / generate the results

        :param visualize_performance: (int)
            determines whether a visualization of the steps taken in
            performance runs are shown. 0 means no visualization is shown.
            A value n > 0 means that only the first n performance runs for a
            specific policy are shown (i.e., for n < checks_per_policy, not all
            performance runs are shown)
        :param visualize_learning: (boolean)
            show some visualization of the learning status before each
            performance evaluation (e.g. Value function)
        :param visualize_steps: (boolean)
            visualize all steps taken during learning
        """
        self.performance_domain = deepcopy(self.domain)
        self.performance_domain.performance = True
        self.seed_components()

        self.result = defaultdict(list)
        self.result["seed"] = self.exp_id
        total_steps = 0
        eps_steps = 0
        eps_return = 0
        episode_number = 0

        # show policy or value function of initial policy
        if visualize_learning:
            self.domain.show_learning(self.agent.representation)

        # Used to bound the number of logs in the file
        start_log_time = clock()
        # Used to show the total time took the process
        self.start_time = clock()
        self.elapsed_time = 0
        # do a first evaluation to get the quality of the inital policy
        self.evaluate(total_steps, episode_number, visualize_performance)
        self.total_eval_time = 0.0
        terminal = True
        while total_steps < self.max_steps:
            if terminal or eps_steps >= self.domain.episode_cap:
                s, terminal, p_actions = self.domain.s0()
                a = self.agent.policy.pi(s, terminal, p_actions)
                # Visual
                if visualize_steps:
                    self.domain.show(a, self.agent.representation)

                # Output the current status if certain amount of time has been
                # passed
                eps_return = 0
                eps_steps = 0
                episode_number += 1
            # Act,Step
            r, ns, terminal, np_actions = self.domain.step(a)

            self._gather_transition_statistics(s, a, ns, r, learning=True)
            na = self.agent.policy.pi(ns, terminal, np_actions)

            total_steps += 1
            eps_steps += 1
            eps_return += r

            # Print Current performance
            if (terminal or eps_steps == self.domain.episode_cap) and deltaT(
                start_log_time
            ) > self.log_interval:
                start_log_time = clock()
                elapsedTime = deltaT(self.start_time)
                self.logger.info(
                    self.log_template.format(
                        total_steps=total_steps,
                        elapsed=hhmmss(elapsedTime),
                        remaining=hhmmss(
                            elapsedTime * (self.max_steps - total_steps) / total_steps
                        ),
                        totreturn=eps_return,
                        steps=eps_steps,
                        num_feat=self.agent.representation.features_num,
                    )
                )

            # learning
            self.agent.learn(s, p_actions, a, r, ns, np_actions, na, terminal)
            s, a, p_actions = ns, na, np_actions
            # Visual
            if visualize_steps:
                self.domain.show(a, self.agent.representation)

            # Check Performance
            if total_steps % (self.max_steps // self.num_policy_checks) == 0:
                self.elapsed_time = deltaT(self.start_time) - self.total_eval_time

                # show policy or value function
                if visualize_learning:
                    self.domain.show_learning(self.agent.representation)

                self.evaluate(total_steps, episode_number, visualize_performance)
                self.total_eval_time += (
                    deltaT(self.start_time) - self.elapsed_time - self.total_eval_time
                )
                start_log_time = clock()

        # Visual
        if visualize_steps:
            self.domain.show(a, self.agent.representation)
        self.logger.info(
            "Total Experiment Duration %s" % (hhmmss(deltaT(self.start_time)))
        )

    def evaluate(self, total_steps, episode_number, visualize=0):
        """
        Evaluate the current agent within an experiment

        :param total_steps: (int)
                     number of steps used in learning so far
        :param episode_number: (int)
                        number of episodes used in learning so far
        """
        random_state = np.random.get_state()
        # random_state_domain = copy(self.domain.random_state)
        elapsedTime = deltaT(self.start_time)
        performance_return = 0.0
        performance_steps = 0.0
        performance_term = 0.0
        performance_discounted_return = 0.0
        for j in range(self.checks_per_policy):
            p_ret, p_step, p_term, p_dret = self.performance_run(
                total_steps, visualize=visualize > j
            )
            performance_return += p_ret
            performance_steps += p_step
            performance_term += p_term
            performance_discounted_return += p_dret
        performance_return /= self.checks_per_policy
        performance_steps /= self.checks_per_policy
        performance_term /= self.checks_per_policy
        performance_discounted_return /= self.checks_per_policy
        self.result["learning_steps"].append(total_steps)
        self.result["return"].append(performance_return)
        self.result["learning_time"].append(self.elapsed_time)
        self.result["num_features"].append(self.agent.representation.features_num)
        self.result["steps"].append(performance_steps)
        self.result["terminated"].append(performance_term)
        self.result["learning_episode"].append(episode_number)
        self.result["discounted_return"].append(performance_discounted_return)
        # reset start time such that performanceRuns don't count
        self.start_time = clock() - elapsedTime
        if total_steps > 0:
            remaining = hhmmss(
                elapsedTime * (self.max_steps - total_steps) / total_steps
            )
        else:
            remaining = "?"
        self.logger.info(
            self.performance_log_template.format(
                total_steps=total_steps,
                elapsed=hhmmss(elapsedTime),
                remaining=remaining,
                totreturn=performance_return,
                steps=performance_steps,
                num_feat=self.agent.representation.features_num,
            )
        )

        np.random.set_state(random_state)
        # self.domain.rand_state = random_state_domain

    def save(self):
        """Saves the experimental results to the ``results.json`` file
        """
        results_fn = os.path.join(self.full_path, self.output_filename)
        if not os.path.exists(self.full_path):
            os.makedirs(self.full_path)
        with open(results_fn, "w") as f:
            json.dump(self.result, f, indent=4, sort_keys=True, cls=NpAwareEncoder)

    def load(self):
        """loads the experimental results from the ``results.txt`` file
        If the results could not be found, the function returns ``None``
        and the results array otherwise.
        """
        results_fn = os.path.join(self.full_path, self.output_filename)
        self.results = rlpy.tools.results.load_single(results_fn)
        return self.results

    def _plot_impl(self, y="return", x="learning_steps", save=False, show=True):
        labels = rlpy.tools.results.default_labels
        performance_fig = plt.figure("Performance")
        res = self.result
        plt.plot(res[x], res[y], lw=2, markersize=4, marker=MARKERS[0])
        plt.xlim(0, res[x][-1] * 1.01)
        y_arr = np.array(res[y])
        m = y_arr.min()
        M = y_arr.max()
        delta = M - m
        if delta > 0:
            plt.ylim(m - 0.1 * delta - 0.1, M + 0.1 * delta + 0.1)
        xlabel = labels[x] if x in labels else x
        ylabel = labels[y] if y in labels else y
        plt.xlabel(xlabel, fontsize=16)
        plt.ylabel(ylabel, fontsize=16)
        if save:
            path = os.path.join(
                self.full_path, "{:03}-performance.pdf".format(self.exp_id)
            )
            performance_fig.savefig(path, transparent=True, pad_inches=0.1)
        if show:
            plt.ioff()
            plt.show()

    def plot(self, y="return", x="learning_steps", save=False, show=True):
        """Plots the performance of the experiment
        This function has only limited capabilities.
        For more advanced plotting of results consider
        :py:class:`tools.Merger.Merger`.
        """
        with with_pdf_fonts():
            self._plot_impl(y, x, save, show)

    def compile_path(self, path):
        """
        An experiment path can be specified with placeholders. For
        example, ``Results/Temp/{domain}/{agent}/{representation}``.
        This functions replaces the placeholders with actual values.
        """
        variables = re.findall("{([^}]*)}", path)
        replacements = {}
        for v in variables:
            if v.lower().startswith("representation") or v.lower().startswith("policy"):
                obj = "self.agent." + v
            else:
                obj = "self." + v

            if obj.lower() in [
                "self.domain",
                "self.agent",
                "self.agent.policy",
                "self.agent.representation",
            ]:
                replacements[v] = "class_name({})".format(obj)
            else:
                replacements[v] = str(v)

        return path.format(**replacements)