import enum

from tensorflow.python.util import compat
from tensorflow.python.util.tf_export import tf_export

is_oss = True  # Updated by copybara.

@tf_export("saved_model.experimental.VariablePolicy")
class VariablePolicy(enum.Enum):
  """Enum defining options for variable handling when saving.

  NONE
    No policy applied: Distributed variables are saved as one variable, with no
    device attached.

  SAVE_VARIABLE_DEVICES
    When saving variables, also save their device assignment.
    This is useful if one wants to hardcode devices in saved models, but it also
    makes them non-portable if soft device placement is disabled (more details
    in `tf.config.set_soft_device_placement`). This is currently not
    fully supported by `saved_model.load`, and is mainly intended to be used
    when one will be reading the saved model at a lower API level. In the
    example below, the graph saved by the call to `saved_model.save` will have
    the variable devices correctly specified:
    ```python
    exported = tf.train.Checkpoint()
    with tf.device('/GPU:0'):
      exported.x_gpu = tf.Variable(1.0)
    with tf.device('/CPU:0'):
      exported.x_cpu = tf.Variable(1.0)
    tf.saved_model.save(exported, export_dir,
        options = tf.saved_model.SaveOptions(
            experimental_variable_policy=
              tf.saved_model.experimental.VariablePolicy.SAVE_VARIABLE_DEVICES))
    ```
    Distributed variables are still saved as one variable under this policy.

  EXPAND_DISTRIBUTED_VARIABLES
    Distributed variables will be saved with information about their components,
    allowing for their restoration on load. Also, the saved graph will contain
    references to those variables. This is useful when one wants to use the
    model for training in environments where the original distribution strategy
    is not available.
  """

  NONE = None

  SAVE_VARIABLE_DEVICES = "save_variable_devices"

  EXPAND_DISTRIBUTED_VARIABLES = "expand_distributed_variables"

  def _save_variable_devices(self):
    """Checks whether variable devices should be saved."""
    return self != VariablePolicy.NONE

  def _expand_distributed_variables(self):
    """Checks whether distributed variables should be expanded."""
    return self == VariablePolicy.EXPAND_DISTRIBUTED_VARIABLES

  @staticmethod
  def from_obj(obj):
    """Tries to convert `obj` to a VariablePolicy instance."""
    if obj is None:
      return VariablePolicy.NONE
    if isinstance(obj, VariablePolicy):
      return obj
    key = str(obj).lower()
    for policy in VariablePolicy:
      if key == policy.value:
        return policy
    raise ValueError(f"Received invalid VariablePolicy value: {obj}.")

@tf_export("saved_model.SaveOptions")
class SaveOptions:
  """Options for saving to SavedModel.

  This function may be used in the `options` argument in functions that
  save a SavedModel (`tf.saved_model.save`, `tf.keras.models.save_model`).
  """

  # Define object attributes in __slots__ for improved memory and performance.
  __slots__ = (
      "namespace_whitelist",
      "save_debug_info",
      "function_aliases",
      "experimental_io_device",
      "experimental_variable_policy",
      "experimental_custom_gradients",
      "experimental_image_format",
      "experimental_skip_saver",
  )

  def __init__(
      self,
      namespace_whitelist=None,
      save_debug_info=False,
      function_aliases=None,
      experimental_io_device=None,
      experimental_variable_policy=None,
      experimental_custom_gradients=True,
      experimental_image_format=False,
      experimental_skip_saver=False,
  ):
    """Creates an object that stores options for SavedModel saving.

    Args:
      namespace_whitelist: List of strings containing op namespaces to whitelist
        when saving a model. Saving an object that uses namespaced ops must
        explicitly add all namespaces to the whitelist. The namespaced ops must
        be registered into the framework when loading the SavedModel. If no
        whitelist is provided, all namespaced ops will be allowed.
      save_debug_info: Boolean indicating whether debug information is saved. If
        True, then a debug/saved_model_debug_info.pb file will be written with
        the contents of a GraphDebugInfo binary protocol buffer containing stack
        trace information for all ops and functions that are saved.
      function_aliases: Python dict. Mapping from string to object returned by
        @tf.function. A single tf.function can generate many ConcreteFunctions.
        If a downstream tool wants to refer to all concrete functions generated
        by a single tf.function you can use the `function_aliases` argument to
        store a map from the alias name to all concrete function names. E.g. >>>
        class Adder(tf.Module): ...   @tf.function ...   def double(self, x):
        ...     return x + x  >>> model = Adder() >>>
        model.double.get_concrete_function( ...   tf.TensorSpec(shape=[],
        dtype=tf.float32, name="float_input")) >>>
        model.double.get_concrete_function( ...   tf.TensorSpec(shape=[],
        dtype=tf.string, name="string_input"))  >>> options =
        tf.saved_model.SaveOptions( ...   function_aliases={'double':
        model.double}) >>> tf.saved_model.save(model, '/tmp/adder',
        options=options)
      experimental_io_device: string. Applies in a distributed setting.
        Tensorflow device to use to access the filesystem. If `None` (default)
        then for each variable the filesystem is accessed from the CPU:0 device
        of the host where that variable is assigned. If specified, the
        filesystem is instead accessed from that device for all variables.  This
        is for example useful if you want to save to a local directory, such as
        "/tmp" when running in a distributed setting. In that case pass a device
        for the host where the "/tmp" directory is accessible.
      experimental_variable_policy: The policy to apply to variables when
        saving. This is either a `saved_model.experimental.VariablePolicy` enum
        instance or one of its value strings (case is not important). See that
        enum documentation for details. A value of `None` corresponds to the
        default policy.
      experimental_custom_gradients: Boolean. When True, will save traced
        gradient functions for the functions decorated by `tf.custom_gradient`.
        Defaults to `True`.
      experimental_image_format: New (highly) experimental format that is
        capable of saving models larger than the 2GB protobuf limit. Enabling
        this option will likely break compatibility with downstream consumers.
        This option is currently disabled in OSS.
      experimental_skip_saver: If True, will prevent SavedModel from creating
        its native checkpointing ops - this is for models that do not use
        SavedModel's native checkpointing functionality to avoid the costs
        associated with creating and serializing those ops.
    """
    self.namespace_whitelist = _validate_namespace_whitelist(
        namespace_whitelist
    )
    self.save_debug_info = save_debug_info
    self.function_aliases = function_aliases if function_aliases else dict()
    self.experimental_custom_gradients = experimental_custom_gradients
    self.experimental_io_device = experimental_io_device
    self.experimental_variable_policy = VariablePolicy.from_obj(
        experimental_variable_policy
    )
    self.experimental_skip_saver = experimental_skip_saver

    # TODO(b/277279153): Enable image format in OSS after proto splitter is
    #  public.
    if experimental_image_format and is_oss:
      raise ValueError(
          "The option `experimental_image_format` is disabled in OSS."
      )
    self.experimental_image_format = experimental_image_format

def _validate_namespace_whitelist(namespace_whitelist):
  """Validates namespace whitelist argument."""
  if namespace_whitelist is None:
    return None
  if not isinstance(namespace_whitelist, list):
    raise TypeError(
        "`namespace_whitelist` must be a list of strings. Got: "
        f"{namespace_whitelist} with type "
        f"{type(namespace_whitelist)}."
    )

  processed = []
  for namespace in namespace_whitelist:
    if not isinstance(namespace, str):
      raise ValueError(
          "Whitelisted namespace must be a string. Got: "
          f"{namespace} of type {type(namespace)}."
      )
    processed.append(compat.as_str(namespace))
  return processed


import socket
from time import sleep
from math import *
from PyQt4 import QtGui, QtCore

DISH = False
DISH_ADDRESS = "192.168.101.98"
DISH_PORT = 5003

class dishHandlerThread(QtCore.QThread):
	def __init__(self):
		QtCore.QThread.__init__(self)

		try:
			self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
			self.sock.connect((DISH_ADDRESS, DISH_PORT))
		except:
			return 0

		self.old_az = -1
		self.new_az = self.old_az

		self.old_el = -1
		self.new_el = self.old_el

		self.firstRun = True

	def degrees(self, rad):
		return rad * 180.0 / pi

	def compute_bearing(self, blat, blon, balt):
		# Spanagel's coordinates
		llat = 36.594947
		llon = -121.874647
		lalt = 25

		Rearth = 3958.76

		llat_rad = llat * pi / 180.0
		llon_rad = llon * pi / 180.0
		blat_rad = blat * pi / 180.0
		blon_rad = blon * pi / 180.0
		dlon_rad = blon_rad - llon_rad
		lalt_mi = 0.000621371192 * lalt
		balt_mi = 0.000621371192 * balt

		a = (cos(blat_rad) * sin(dlon_rad)) ** 2
		b = (cos(llat_rad) * sin(blat_rad) - sin(llat_rad) * cos(blat_rad) * cos(dlon_rad)) ** 2
		c = sin(llat_rad) * sin(blat_rad) + cos(llat_rad) * cos(blat_rad) * cos(dlon_rad)
		sab = sqrt((a + b))

		dist = Rearth * atan2(sab, c)
		dist_km = dist * 1.609344
		el = atan((balt_mi - lalt_mi) / dist) * 180.0 / pi

		dx = cos(llat_rad) * sin(blat_rad) - sin(llat_rad) * cos(blat_rad) * cos(dlon_rad)
		dy = sin(dlon_rad) * cos(blat_rad)
		az = (self.degrees(atan2(dy, dx)) + 360) % 360

		return (az, el)

	def close(self):
		self.sock.send("AS;ES;\n")  # standby
		self.sock.close()

	def point(self, az, el):

		# Update positions
		self.new_az = az
		self.new_el = el

		print("Checking first run")
		if self.firstRun:
			self.sock.send("SQ\n")
			data = self.sock.recv(1024)
			temp = data.split(",")
			dish_az = temp[0].split("=")[1]
			dish_el = temp[1].split("=")[1]
			dish_az = float(dish_az)
			dish_el = float(dish_el)
			print("Current dish position %03d %03d" % (dish_az, dish_el))
			self.old_az = dish_az
			self.old_el = dish_el
			self.firstRun = False

		# Set some hard values for the dish
		minEl = 0
		minAz = 1
		maxEl = 90
		maxAz = 359

		print ("Checking max ranges")
		# Correct out-of-range AZ or ELs
		el = el if el > minEl else minEl
		el = el if el < maxEl else maxEl
		az = az if az > minAz else minAz
		az = az if az < maxAz else maxAz

		az_err = abs(self.new_az - self.old_az)
		el_err = abs(self.new_el - self.old_el)

		print ("Done checking ranges, starting socket stuff")

		if  az_err >= 0.5 or el_err >= 0.5:
			try:
				self.sock.send("AM%0.2f;EM%0.2f;\n" % (az, el))
				print("Pointing to %03d %03d" % (az, el))

				# print("Sleeping %f" % max(az_err,el_err)*4 + 1)
				sleep(max(az_err, el_err) / 4 + 5)
				self.sock.send("AS;ES;\n")  # standby
				self.old_az = self.new_az
				self.old_el = self.new_el

			except:
				print("Can't update position to dish ACU")
				self.close()


import random
import os

from art import logo, vs
from game_data import data

def print_formatted_stuff(stuff, position):
    text = "Compare A: " if position == "A" else "Against B: "
    print(f'{text}{stuff["name"]}, a(n) {stuff["description"]}, from {stuff["country"]}')

def game():
    score = 0
    lives = 1

    #later on ,the second one will be the first one, will not be random
    compare1 = random.randint(0,len(data)-1)

    while lives>0:

        #get random index for comparing data first
        compare2 = random.randint(0,len(data)-1)
        #if they are equal, keep getting another one, till ok
        while compare1==compare2:
            compare2 = random.randint(0,len(data)-1)

        stuff_A = data[compare1]
        stuff_B = data[compare2]

        #print stuff
        print(logo)
        print('\n')
        print_formatted_stuff(stuff_A, "A")
        print(vs)
        print_formatted_stuff(stuff_B, "B")
        guess = input("\nWho has more followers? Type 'A' or 'B': ").lower()

        if guess == 'a' and stuff_A["follower_count"]>=stuff_B["follower_count"]:
            score +=1
            print(f"You are right!. Current score: {score}")
            #save second as first
            compare1 = compare2
        elif guess == 'b' and stuff_A["follower_count"]<=stuff_B["follower_count"]:
            score +=1
            print(f"You are right!. Current score: {score}")
            #save second as first
            compare1 = compare2
        else:
            lives -= 1
            os.system('cls')
            print (logo)
            print(f"Sorry, you are wrong. Final score: {score}")
            should_continue = input("Type 'y' for another game, any other to quit: ")
            if should_continue == 'y':
                os.system('cls')
                game()

game()


from odoo import fields, models

class ResConfigSettings(models.TransientModel):
    _inherit = "res.config.settings"

    initiating_party_issuer = fields.Char(
        related="company_id.initiating_party_issuer", readonly=False
    )
    initiating_party_identifier = fields.Char(
        related="company_id.initiating_party_identifier", readonly=False
    )
    initiating_party_scheme = fields.Char(
        related="company_id.initiating_party_scheme", readonly=False
    )
    group_pain_multiple_identifier = fields.Boolean(
        string="Multiple identifiers",
        implied_group="account_banking_pain_base." "group_pain_multiple_identifier",
        help="Enable this option if your country requires several SEPA/PAIN "
        "identifiers like in Spain.",
    )


import os
import random
import torch
import torch.nn as nn
import torch.nn.parallel
import torch.backends.cudnn as cudnn
import torch.optim as optim
import torch.utils.data
import torchvision.datasets as dset
import torchvision.transforms as transforms
import torchvision.utils as vutils
import numpy as np
import matplotlib.pyplot as plt

# import the necessary packages
# from __future__ import print_function
import numpy as np
# import argparse
import cv2
def adjust_gamma(image, gamma=1.0):
	# build a lookup table mapping the pixel values [0, 255] to
	# their adjusted gamma values
	invGamma = 1.0 / gamma
	table = np.array([((i / 255.0) ** invGamma) * 255
		for i in np.arange(0, 256)]).astype("uint8")
	# apply gamma correction using the lookup table
	return cv2.LUT(image, table)

# import torch
# # import kornia
# import cv2
# import numpy as np
# import matplotlib.pyplot as plt
#
# def torchRotate(data: torch.tensor ,alpha: float = 45.0):
#     # create transformation (rotation)
#     alpha: float = 45.0  # in degrees
#     angle: torch.tensor = torch.ones(1) * alpha
#
#     # define the rotation center
#     center: torch.tensor = torch.ones(1, 2)
#     center[..., 0] = data.shape[3] / 2  # x
#     center[..., 1] = data.shape[2] / 2  # y
#
#     # define the scale factor
#     scale: torch.tensor = torch.ones(1, 2)
#
#     # compute the transformation matrix
#     M: torch.tensor = kornia.get_rotation_matrix2d(center, angle, scale)
#
#     # apply the transformation to original image
#     _, _, h, w = data.shape
#     data_warped: torch.tensor = kornia.warp_affine(data.float(), M, dsize=(h, w))
#     return data_warped

def Augmentation(I,lam,aug_type='translationX',device='cuda'):
    # I shape: n
    I_out = torch.zeros_like(I,device=device)
    if aug_type == 'translationX':
        W = I.shape[3]
        for i in range(I.shape[0]):
            a = np.random.uniform(-lam, lam,1).item()
            num_cols = round(abs(a)*W)
            if a>=0:
                I_out[i,:,:,list(np.arange(0,num_cols))] = I[i,:,:,list(np.arange(0,num_cols))[::-1]]
                I_out[i,:,:,num_cols:] = I[i,:,:,0:(W-num_cols)]
            else:
                I_out[i,:,:,(W-num_cols):]  = I[i,:,:,list(np.arange(W-num_cols,W))[::-1]]
                I_out[i,:,:,0:(W-num_cols)] = I[i,:,:,num_cols:]
    elif aug_type == 'translationY':
        H = I.shape[2]
        # with torch.no_grad():
        for i in range(I.shape[0]):
            a = np.random.uniform(-lam, lam, 1).item()
            num_rows = round(abs(a) * H)
            if a >= 0:
                I_out[i, :, list(np.arange(0, num_rows)), :] = I[i, :, list(np.arange(0, num_rows))[::-1],:]
                I_out[i, :, num_rows:, :] = I[i, :, 0:(H - num_rows), :]
            else:
                I_out[i, :, (H - num_rows): , :] = I[i, :, list(np.arange(H - num_rows, H))[::-1], :]
                I_out[i, :, 0:(H - num_rows), :] = I[i, :, num_rows:, :]
    elif aug_type == 'colorNoise': # colorNoise
        I_out = I.clone()
        for i in range(I.shape[0]):
            for c in range(3):
                a = torch.tensor(np.random.normal(0, lam, 1).item())
                # a= torch.tensor(np.random.randint(1,int(lam*10),1))
                I_out[i, c, :, :] += a
            # I_out[i, :, :, :] **= I_out[i, :, :, :].pow(a)
            # I_out[i, :, :, :] -= 1

            # I_out[i,:,:,:] = (I[i,:,:,:]+a).clamp(-1,1)

        #     I_out[i, :, :, :]=I_out[i, :, :, :]**2
        # I_out.requires_grad = True

        # with torch.no_grad():
        #     I[1,:,:,:] = torch.tensor(torch.zeros_like(I).numpy())[1,:,:,:]

        # with torch.no_grad():
        # for i in range(I.shape[0]):
        #     I_out[i,:,:,:] =
        #     I_out = Image[i, :, :, :]
            # a = abs(np.random.normal(1, lam, 1).item())+1e-10
            # image = I[i,:,:,:]
            # for c in range(3):
                # min, max = torch.min(I[i,c,:,:]), torch.max(I[i,c,:,:])
                # imageGrey = (image[c,:,:] - min) / (max - min)
                # imageGrey = imageGrey**a
                # imageGrey = imageGrey*(max - min) + min
                # I_out[i,c,:,:] = I[i,c,:,:].pow(0.9)
                # I_out[i,:,:,:] = torch.tensor(adjust_gamma(image.mul_(255).add_(0.5).clamp_(0, 255).permute(1, 2, 0).to(torch.uint8).numpy(), gamma=a),dtype=torch.float).permute(2, 0, 1).mul_(1/255)
    else:
        raise NotImplementedError()
    return I_out.to(device).clamp(-1,1)


#!/usr/bin/python3

import signal
import keyboard
import time
from datetime import datetime

# CONSTANTS, REPLACE THESE WITH YOUR OWN VARIABLES FOR YOUR OWN KEYBOARD
TIMEOUT_SECS = 0.2
LEFT_CTRL_CODE = 44
RIGHT_CTRL_CODE = 53
LEFT_SHIFT_CODE = 42
RIGHT_SHIFT_CODE = 54
LEFT_CTRL_REPLACE = 29
RIGHT_CTRL_REPLACE = 97
LEFT_SHIFT_REPLACE = 'shift+9'
RIGHT_SHIFT_REPLACE= 'shift+0'

class ReleaseQuickListener(object):
    left_shift_down = False
    right_shift_down = False
    left_ctrl_down = False
    right_ctrl_down = False
    left_shift_time = None
    right_shift_time = None
    left_ctrl_time = None
    right_ctrl_time = None

    def __init__(self):
        self.done = False
        signal.signal(signal.SIGINT, self.cleanup)
        keyboard.hook(self.my_on_key_event)
        while not self.done:
            time.sleep(1)  #  Wait for Ctrl+C

    def cleanup(self, signum, frame):
        self.done = True

    def reset_times(self):
        self.left_shift_time = None
        self.right_shift_time = None
        self.left_ctrl_time = None
        self.right_ctrl_time = None

    @staticmethod
    def is_time_valid_and_quick(press_time):
        if (press_time == None):
            #print("it's none")
            return False
        diff = datetime.now() - press_time
        if (diff.total_seconds() > TIMEOUT_SECS):
            #print("time not right " + str(diff.total_seconds()))
            return False
        return True

    def my_on_key_event(self, e):
        #print("Got key release event: " + str(e) + " scancode: " + str(e.scan_code))
        if (e.event_type == "down"):
            if (e.scan_code == LEFT_CTRL_CODE): #Left CTRL
                if (self.left_ctrl_down == False):
                    self.left_ctrl_time = datetime.now()
                    self.left_ctrl_down = True
            elif (e.scan_code == RIGHT_CTRL_CODE): #Right CTRL
                if (self.right_ctrl_down == False):
                    self.right_ctrl_time = datetime.now()
                    self.right_ctrl_down = True
            elif (e.scan_code == LEFT_SHIFT_CODE): #Left Shift
                if (self.left_shift_down == False):
                    self.left_shift_time = datetime.now()
                    self.left_shift_down = True
            elif (e.scan_code == RIGHT_SHIFT_CODE): #Right Shift
                if (self.right_shift_down == False):
                    self.right_shift_time = datetime.now()
                    self.right_shift_down = True
            elif (e.name != "alt"):
                self.reset_times()
        elif (e.event_type == "up"):
            if (e.scan_code == LEFT_CTRL_CODE): #Left CTRL
                self.left_ctrl_down = False
                if (ReleaseQuickListener.is_time_valid_and_quick(self.left_ctrl_time)):
                    keyboard.press_and_release(LEFT_CTRL_REPLACE)
                    self.reset_times()
            elif (e.scan_code == RIGHT_CTRL_CODE): #Right CTRL
                self.right_ctrl_down = False
                if (ReleaseQuickListener.is_time_valid_and_quick(self.right_ctrl_time)):
                    keyboard.press_and_release(RIGHT_CTRL_REPLACE)
                    self.reset_times()
            elif (e.scan_code == LEFT_SHIFT_CODE): #Left Shift
                self.left_shift_down = False
                if (ReleaseQuickListener.is_time_valid_and_quick(self.left_shift_time)):
                    keyboard.press_and_release(LEFT_SHIFT_REPLACE)
                    self.reset_times()
            elif (e.scan_code == RIGHT_SHIFT_CODE): #Right Shift
                self.right_shift_down = False
                if (ReleaseQuickListener.is_time_valid_and_quick(self.right_shift_time)):
                    keyboard.press_and_release(RIGHT_SHIFT_REPLACE)
                    self.reset_times()
            #print(e.scan_code)

a = ReleaseQuickListener()


# 공원 산책 문제

# 지나다니는 길을 'O', 장애물을 'X'로 나타낸 직사각형 격자 모양의 공원에서 로봇 강아지가 산책을 하려합니다. 산책은 로봇 강아지에 미리 입력된 명령에 따라 진행하며, 명령은 다음과 같은 형식으로 주어집니다.

# ["방향 거리", "방향 거리" … ]
# 예를 들어 "E 5"는 로봇 강아지가 현재 위치에서 동쪽으로 5칸 이동했다는 의미입니다. 로봇 강아지는 명령을 수행하기 전에 다음 두 가지를 먼저 확인합니다.

# 주어진 방향으로 이동할 때 공원을 벗어나는지 확인합니다.
# 주어진 방향으로 이동 중 장애물을 만나는지 확인합니다.
# 위 두 가지중 어느 하나라도 해당된다면, 로봇 강아지는 해당 명령을 무시하고 다음 명령을 수행합니다.
# 공원의 가로 길이가 W, 세로 길이가 H라고 할 때, 공원의 좌측 상단의 좌표는 (0, 0), 우측 하단의 좌표는 (H - 1, W - 1) 입니다.

# 공원을 나타내는 문자열 배열 park, 로봇 강아지가 수행할 명령이 담긴 문자열 배열 routes가 매개변수로 주어질 때, 로봇 강아지가 모든 명령을 수행 후 놓인 위치를 [세로 방향 좌표, 가로 방향 좌표] 순으로 배열에 담아 return 하도록 solution 함수를 완성해주세요.

# 제한사항
# 3 ≤ park의 길이 ≤ 50
# 3 ≤ park[i]의 길이 ≤ 50
# park[i]는 다음 문자들로 이루어져 있으며 시작지점은 하나만 주어집니다.
# S : 시작 지점
# O : 이동 가능한 통로
# X : 장애물
# park는 직사각형 모양입니다.
# 1 ≤ routes의 길이 ≤ 50
# routes의 각 원소는 로봇 강아지가 수행할 명령어를 나타냅니다.
# 로봇 강아지는 routes의 첫 번째 원소부터 순서대로 명령을 수행합니다.
# routes의 원소는 "op n"과 같은 구조로 이루어져 있으며, op는 이동할 방향, n은 이동할 칸의 수를 의미합니다.
# op는 다음 네 가지중 하나로 이루어져 있습니다.
# N : 북쪽으로 주어진 칸만큼 이동합니다.
# S : 남쪽으로 주어진 칸만큼 이동합니다.
# W : 서쪽으로 주어진 칸만큼 이동합니다.
# E : 동쪽으로 주어진 칸만큼 이동합니다.
# 1 ≤ n ≤ 9

# 입출력 예

#   park	                        routes	                result
# ["SOO","OOO","OOO"]	        ["E 2","S 2","W 1"]	        [2,1]
# ["SOO","OXX","OOO"]	        ["E 2","S 2","W 1"]	        [0,1]
# ["OSO","OOO","OXO","OOO"]	    ["E 2","S 3","W 1"]	        [0,0]

# 나는 routes를 딕셔너리 이용해서 풀이하려 했으나 리스트로도 풀이가 가능했다.

# https://velog.io/@m2nja201/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EA%B3%B5%EC%9B%90%EC%82%B0%EC%B1%85-python-%EC%9E%85%EB%AC%B8

# def solution(park, routes):
#     answer = []

#     matrix = []

#     for p in park:
#         matrix.append(list(p))

#     # 리스트의 공백으로 구분된 문자를 딕셔너리로 저장
#     dic_routes = dict(map(lambda x: (x.split()[0], int(x.split()[1])), routes))

#     x, y = 0, 0

#     # 좌표의 초기 위치 S를 찾아야한다.
#     for i in range(len(matrix)):
#         for j in range(len(matrix[0])):
#             if matrix[i][j] == 'S':
#                 x, y = i, j
#                 break

#     dx , dy = x, y

#     # 해당 딕셔너리로 저장한 route를 돌면서 확인
#     for k, v in dic_routes.items():

#         if k == 'E':
#             # v 길이만큼 반복문 돌면서 해당 위치 정보 확인
#             for _ in range(v):
#                 dy += 1 # 행 증가
#                 # 조건문으로 갈 위치가 x이거나 matrix[0]의 범위(행)를 벗어나면 -1
#                 if dy >= len(matrix[0]) or matrix[dx][dy] == 'X':
#                     dy = y
#                     break

#         elif k == 'S':

#             for _ in range(v):
#                 dx += 1 # 열 증가
#                 # 조건문으로 갈 위치가 x이거나 matrix(열)의 범위(행)를 벗어나면 -1
#                 if dx >= len(matrix) or matrix[dx][dy] == 'X':
#                     dx = x
#                     break

#         elif k == 'W':

#             for _ in range(v):
#                 dy -= 1
#                 if dy < 0 or matrix[dx][dy] == 'X':
#                     dy = y
#                     break

#         elif k == 'N':

#             for _ in range(v):
#                 dx -= 1
#                 if dx < 0 or matrix[dx][dy] == 'X':
#                     dx = x
#                     break

#     answer.append(dx)
#     answer.append(dy)

#     return answer

def solution(park, routes):
    # idx
    x = 0
    y = 0

    # 시작 위치 찾기
    for i in range(len(park)):
        for j in range(len(park[i])):
            if park[i][j] == 'S':
                x = j # 행
                y = i # 열
                break

        # 찾은 시작점 x, y 를 기준으로 각 routes 명령을 실행한다.
    for route in routes:

        # 위치 초기화
        xx = x
        yy = y

            # 문자열에서 문자 인덱스를 0,1,2 로 분기해서 각 조건 성립 시 이동
        for step in range(int(route[2])):
                # 방향과 일치하고 park 범위를 벗어나지 않는다면
            if route[0] == 'E' and xx != len(park[0]) - 1 and park[yy][xx+1] != 'X':
                xx += 1
                if step == int(route[2]) - 1: # 해당 스텝만큼 움직였다면
                    x = xx # dx만큼 x를 갱신

            elif route[0] == 'W' and xx != 0 and park[yy][xx-1] != 'X':
                xx -= 1
                if step == int(route[2]) - 1:
                    x = xx

            elif route[0] == 'S' and yy != len(park) - 1 and park[yy+1][xx] != 'X':
                yy += 1
                if step == int(route[2]) - 1:
                    y = yy

            elif route[0] == 'N' and yy != 0 and park[yy-1][xx] != 'X':
                yy -= 1

                if step == int(route[2]) - 1:
                    y = yy

    return [y, x]

print(solution(["SOO","OOO","OOO"], ["E 2","S 2","W 1"]))


from dolfin import RectangleMesh, FiniteElement, FunctionSpace, TestFunctions, TrialFunctions, Point, inner, grad, \
    Expression, Function, DOLFIN_EPS, DirichletBC, LogLevel, UserExpression, split, dx, set_log_level
from gryphon import backwardEuler

class InitialConditions(UserExpression):
    def eval(self, values, x):
        values[0] = 0.0
        values[1] = 0.0

    def value_shape(self):
        return (2,)

# Define mesh, function space and test functions
mesh = RectangleMesh(Point(0.0, 0.0), Point(1.0, 1.0), 49, 49)
P1 = FiniteElement("Lagrange", mesh.ufl_cell(), 1)
ME = FunctionSpace(mesh, P1 * P1)
q1, q2 = TestFunctions(ME)
U1, U2 = TrialFunctions(ME)

# Define and interpolate initial condition
W = Function(ME)
W.interpolate(InitialConditions())
u, v = split(W)

domainSource = Expression("0.1*t*exp(-((x[0]-0.7)*(x[0]-0.7) + (x[1]-0.5)*(x[1]-0.5))/0.01)", t=0, degree=1)

# Define the right hand side for each of the PDEs
F1 = (-inner(grad(U1), grad(q1)) + U2 * q1 + domainSource * q1) * dx
F2 = (-inner(grad(U2), grad(q2)) - U1 * q2) * dx

# Define Dirichlet boundary, zero on all edges.
def boundary(x):
    return x[0] < DOLFIN_EPS or x[0] > 1.0 - DOLFIN_EPS or x[1] < DOLFIN_EPS or x[1] > 1.0 - DOLFIN_EPS

bc_u = DirichletBC(ME.sub(0), 0.0, boundary)
bc_v = DirichletBC(ME.sub(1), 0.0, boundary)

# Define the time domain
T = [0, 10]

# Create the solver object and adjust tolerance
obj = backwardEuler(T, W, [F1, F2], tdf=[domainSource], bcs=[bc_u, bc_v])

# Turn on some output and save run time statistics
obj.parameters["verbose"] = True
obj.parameters["drawplot"] = False
obj.parameters["output"]["path"] = "CoupledHeatEquation_folder"
obj.parameters["output"]["statistics"] = True
obj.parameters["timestepping"]["dt"] = T[1] / 40.0

# Suppress some FEniCS output
set_log_level(LogLevel.WARNING)

# Solve the problem
obj.solve()


import time
from collections import namedtuple
from functools import lru_cache

data = '''
The first floor contains a polonium generator, a thulium generator, a thulium-compatible microchip, a promethium generator, a ruthenium generator, a ruthenium-compatible microchip, a cobalt generator, and a cobalt-compatible microchip.
The second floor contains a polonium-compatible microchip and a promethium-compatible microchip.
The third floor contains nothing relevant.
The fourth floor contains nothing relevant.
'''.strip()

data = '''
The first floor contains a hydrogen-compatible microchip and a lithium-compatible microchip.
The second floor contains a hydrogen generator.
The third floor contains a lithium generator.
The fourth floor contains nothing relevant.
'''.strip()

items = {
    'H-C': 1,
    'L-C': 1,
    'H-G': 2,
    'L-G': 3,
}

items = {
    'PL-G': 1,
    'TH-G': 1,
    'TH-C': 1,
    'PR-G': 1,
    'RU-G': 1,
    'RU-C': 1,
    'CO-G': 1,
    'CO-C': 1,
    'PL-C': 1,
    'PR-C': 1,
}

target = {
    'PL-G': 4,
    'TH-G': 4,
    'TH-C': 4,
    'PR-G': 4,
    'RU-G': 4,
    'RU-C': 4,
    'CO-G': 4,
    'CO-C': 4,
    'PL-C': 4,
    'PR-C': 4,
}

def floor_to_text(floors, cur_floor=1):
    text = []
    all_items = sum(floors, ())
    for floor_num, floor in enumerate(floors, start=1):
        if floor_num == cur_floor:
            elevator = '\x1b[;41m{}\x1b[0m'.format(floor_num)
        else:
            elevator = floor_num
        thing = ' '.join('{: ^{}}'.format((item if item in floor else '.'), len(all_items[0])) for item in all_items)
        text.insert(0, '{} {}'.format(elevator, thing))

    return '\n'.join(text)

def colorize(item, items):
    stuff_on_floor = [i for i in items if items[i] == items[item] and i != item]
    if item.endswith('-C') and stuff_on_floor and not item.replace('-C', '-G') in stuff_on_floor:
        return '\x1b[;31m{}\x1b[0m'.format(item)
    elif item.endswith('-G') and any(chip.replace('-C', '-G') not in stuff_on_floor for chip in stuff_on_floor if chip.endswith('-C')):
        return '\x1b[;31m{}\x1b[0m'.format(item)
    elif can_go_up(item, items):
        return '\x1b[;32m{}\x1b[0m'.format(item)
    else:
        return '\x1b[;33m{}\x1b[0m'.format(item)

def can_go_up(item, items):
    next_floor = items[item]+1
    stuff_on_floor = [i for i in items if items[i] == items[item]]
    stuff_on_next_floor = [i for i in items if items[i] == next_floor]
    if not stuff_on_next_floor:
        return True
    elif ((item.endswith('-C') and item.replace('-C', '-G') in stuff_on_floor)
            or item.endswith('-G') and item.replace('-G', '-C') in stuff_on_floor):
        return True
    elif item.endswith('-C') and item.replace('-C', '-G') in stuff_on_next_floor:
        return True
    return False

def fried(floors):
    for floor in floors:
        for chip in (chip for chip in floor if chip.endswith('-C')):
            if chip.replace('-C', '-G') not in floor and any(thing.endswith('-G') for thing in floor):
                return True

def to_dict(floors):
    items = {}
    for num, floor in enumerate(floors, 1):
        for item in floor:
            items[item] = num
    return items

def to_tuple(items):
    floors = []
    for i in range(4):
        floor_num = i+1
        floors.append(tuple(sorted(item for item in items if items[item] == floor_num)))
    return tuple(floors)

def possible_moves(item, floors, floor_limit=4):
    items = to_dict(floors)
    elevator = items[item]
    moves = []

    other_items = [i for i in items if i != item and items[item] == items[i]]

    next_floors = []
    if elevator < floor_limit:
        next_floors.append(elevator+1)
    if elevator > 1:
        next_floors.append(elevator-1)

    for next_floor in next_floors:
        for paired_item in other_items:
            if items[paired_item] == items[item]:
                items[paired_item] = next_floor
                items[item] = next_floor
                moves.append((next_floor, to_tuple(items)))
                items[paired_item] = elevator
                items[item] = elevator
            items[item] = next_floor
            moves.append((next_floor, to_tuple(items)))
            items[item] = elevator

    moves = [move for move in moves if not fried(move[1])]
    return moves

Move = namedtuple('Move', ('from_', 'to'))

def find_shortest(floors, elevator=1, steps=0, seen=None):
    start = (elevator, floors)
    states = {
        (elevator, floors): set(sum((possible_moves(item, floors, floor_limit=4) for item in floors[elevator-1]), []))
    }
    traversed_edges = set()
    for dest in states[(elevator, floors)]:
        states[dest] = None
        traversed_edges.add(Move(from_=(elevator, floors), to=dest))

    while any(states[state] is None for state in states):
        state = next(state for state in states if states[state] is None)
        state_floor = state[0]-1
        states[state] = states.get(state) or set()
        for item in state[1][state_floor]:
            for move in possible_moves(item, state[1], floor_limit=4):
                states[state].add(move)
                transition = Move(from_=state, to=move)
                traversed_edges.add(transition)
                states[move] = states.get(move, None)

    distances = {state:float('inf') for state in states}
    distances[start] = 0
    unvisited = set(distances)

    while unvisited:
        current = min((distances[state], state) for state in unvisited)[1]
        unvisited.remove(current)
        dist = distances[current]+1
        for neighbor in states[current]:
            distances[neighbor] = min(distances[neighbor], dist)

    for thing in distances:
        if not any(thing[1][:3]):
            print(thing)
    return distances

if __name__ == '__main__':
    target = (
        (),
        (),
        (),
        ('PL-G', 'TH-G', 'TH-C', 'PR-G', 'RU-G',
         'RU-C', 'CO-G', 'CO-C', 'PL-C', 'PR-C',
         ),
    )
    assert fried([['H-C', 'F-G'],])
    assert not fried((['H-C', 'H-G'],))
    assert fried((['H-C', 'H-G', 'F-C'],))
    assert not fried((['H-C', 'H-G', 'F-C', 'F-G'],))
    assert not fried((['H-G',  'F-G'], ['H-C', 'F-C']))

    items = {
        'H-C': 1,
        'L-C': 1,
        'H-G': 2,
        'L-G': 3,
    }

    items = {
        'PL-G': 1,
        'TH-G': 1,
        'TH-C': 1,
        'PR-G': 1,
        'RU-G': 1,
        'RU-C': 1,
        'CO-G': 1,
        'CO-C': 1,
        'PL-C': 2,
        'PR-C': 2,
    }
    target = {
        'PL-G': 4,
        'TH-G': 4,
        'TH-C': 4,
        'PR-G': 4,
        'RU-G': 4,
        'RU-C': 4,
        'CO-G': 4,
        'CO-C': 4,
        'PL-C': 4,
        'PR-C': 4,
    }

    initial_state = (
        ('H-C', 'L-C'),
        ('H-G',),
        ('L-G',),
        (),
    )
    target = (
        (), (), (),
        tuple(sorted(('H-C', 'L-C', 'H-G', 'L-G')))
    )

    assert to_dict(initial_state) == to_dict(initial_state)
    assert to_tuple(to_dict(initial_state)) == initial_state

    valid_moves_hc = [
        (2, (('L-C',),
             ('H-C', 'H-G'),
             ('L-G',),
             (),
             )
         ),
    ]
    assert possible_moves('H-C', initial_state, floor_limit=4) == valid_moves_hc
    assert possible_moves('L-C', initial_state, floor_limit=4) == []

    assert possible_moves('H-G', (('L-C',), ('H-C', 'H-G'), ('L-G',), ())) == [(3, (('L-C',), (), ('H-C', 'H-G', 'L-G'), ())),
                                                                               (3, (('L-C',), ('H-C',), ('H-G', 'L-G'), ())),
                                                                               ]

    initial_state = (
        ('H-C', 'L-C'),
        ('H-G',),
        ('L-G',),
        (),
    )
    target = (4, (
        (), (), (),
        tuple(sorted(('H-C', 'L-C', 'H-G', 'L-G')))
    ))

    print(find_shortest(initial_state, elevator=1)[target]-2)

    initial_state = (
        ('PL-G',
         'TH-G',
         'TH-C',
         'PR-G',
         'RU-G',
         'RU-C',
         'CO-G',
         'CO-C',
         ),
        ('PL-C',
         'PR-C',
         ),
         (),(),
    )
    target = (4, ((), (), (),
                  ('PL-G', 'TH-G', 'TH-C', 'PR-G', 'RU-G',
                   'RU-C', 'CO-G', 'CO-C', 'PL-C', 'PR-C',
                   )))
    print(find_shortest(initial_state, elevator=1)[target]-2)


#Encapsulation Challenge
class Test:
    def __init__(self):
        self.foo = 11
        #protected variable
        self._bar = 23
        #private variable
        self.__baz = 42

    def getPrivate(self):
        print(self.__baz)

    def setPrivate(self, private):
        self.__baz = private

#instantiates the class as t variable
t = Test()
#creating object using _bar
bar = t._bar
#below prints the same value by different means. the first is instatiating the variable as an object, the second uses the class to access the protected variable
print(bar)
print(t._bar)

# as shown above it is easy to access a protected variable, there is a few more steps to access the private variable
#allows us to access our private variable by defined function
t.getPrivate()
#changes the private variable to a new value
t.setPrivate(9)
#obtains new value of private variable
t.getPrivate()
'''
this wont retrieve the private variable, instead it states there is no variable assigned.
in order to access the private variable, look at above steps.
t.__baz
'''


#############################################################################
# https://geocoder.readthedocs.io/
# Before running this code, install the geocoder module on command line:
#
# pip install geocoder
#
# Task 1: make a function called geocode() that take an address as a positional
# parameter and writes the results to a file.
#############################################################################
import geocoder
import json
import os
from time import sleep

address = 'Northwestern University, Evanston, IL, USA'
# sends a request over the web to geocode the address:
g = geocoder.osm(address)
# print(g.json)  # entire standardized address
print(g.latlng)

# output to a file:
dir_path = os.path.dirname(os.path.realpath(__file__))
file_name = os.path.join(dir_path,"addresses.tsv")
my_file = open(file_name, "a")
print(address, g.latlng[0], g.latlng[1], sep='\t',
        file=my_file
    )

addresses = [
    'Mountain View, CA, USA',
    'Northwestern University, Evanston, IL, USA',
    'Chicago, IL, USA',
    'New York, USA'
]


import requests
from lxml import etree
from lxml.etree import ParseError
from requests import RequestException
import csv

# 单页url
def get_one_page_url(url, URLlist):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                      'Chrome/76.0.3809.132 Safari/537.36 '
    }

    try:
        response = requests.get(url, headers=headers)
        body = response.text
    except RequestException as e:
        print("request is error", e)
    try:
        html = etree.HTML(body, etree.HTMLParser())
        result = html.xpath('//div[@class="maincontent"]//div[@class="sep"]/div[@class="block unwrap"]/h2/a/@href')
        for item in result:
            URLlist.append(item)
    except ParseError as e:
        print(e.position)

# 所有url
def get_all_urls(page, URLlist):
    if page != 1:
        url = "https://www.usnews.com/education/best-global-universities/search?country=china&region=asia&page=" + str(
            page)
        get_one_page_url(url, URLlist)
    else:
        url = "https://www.usnews.com/education/best-global-universities/search?country=china&region=asia"
        get_one_page_url(url, URLlist)

# 进入每个url获取数据
def get_one_detail(url, college_data):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                      'Chrome/76.0.3809.132 Safari/537.36 '
    }

    try:
        response = requests.get(url, headers=headers)
        body = response.text
    except RequestException as e:
        print("request is error", e)
    try:
        html = etree.HTML(body, etree.HTMLParser())
        school_name = html.xpath('//h1[@class="h-biggest"]/text()')
        for item in school_name:
            college_data.append(item)

        paths = ['Total number of students',
                 'Number of international students',
                 'Total number of academic staff',
                 'Number of international staff',
                 'Number of undergraduate degrees awarded',
                 'Number of master\'s degrees awarded',
                 'Number of doctoral degrees awarded',
                 'Number of research only staff',
                 'Number of new undergraduate students',
                 'Number of new master\'s students',
                 'Number of new doctoral students']

        for item in paths:
            # 通过兄弟节点判断数据存在:加入列表,去除多于空格
            if html.xpath(
                    '//div[@class="data-item first"]//div[@class="t-slack sep"]/div[@class="t-dim" and text()=$val]',
                    val=item):
                text = html.xpath(
                    '//div[@class="data-item first"]//div[@class="t-slack sep"]/div[@class="t-dim" and text()=$val]/preceding-sibling::*[1]/text()',
                    val=item)
                text = text[0].replace(' ', '').replace('\n', '')
            # 否则:列表中加入空元素占位
            else:
                text = ''
            college_data.append(text)

    except ParseError as e:
        print(e.position)

# 入口
if __name__ == '__main__':
    college_list = []
    URLlist = []
    for i in range(1, 5):
        get_all_urls(page=i, URLlist=URLlist)
    print(URLlist)

    for url in URLlist:
        college_data = []
        get_one_detail(url, college_data)
        college_list.append(college_data)
    print(college_list)
    with open('data.csv', 'w') as csvfile:
        writer = csv.writer(csvfile)
        writer.writerow(
            ['学校', '学生总数', '国际学生数', '学术教职工', '国际教职工', '学士学位授予数', '硕士学位授予数', '博士学位授予数', '专职科研人员数', '本科新生总数', '硕士新生总数',
             '博士新生总数'])
        for item in college_list:
            writer.writerow(item)


class Solution(object):
    def permute(self,nums):
        res=[]
        def backtrack(candidates,select):
            if len(candidates)==len(select):
                res.append(select[:])
                return
            for candidate in candidates:
                if candidate in select:
                    continue
                select.append(candidate)
                backtrack(candidates,select)
                select.pop()
        select=[]
        backtrack(nums,select)
        return res

if __name__ == "__main__":
    print(Solution().permute([1,2,3]))


import drawSvg as draw
import src.compile as comp
import random
from pathlib import Path

things = [
    ("lsystems/leaf.json", 6)
    , ("lsystems/leaf.json", 7)
    , ("lsystems/leaf.json", 8) , ("lsystems/bush1.json", 4) , ("lsystems/bush1.json", 5) , ("lsystems/bush2.json", 4) , ("lsystems/bush2.json", 5)
          , ("lsystems/bush3.json", 4)
    , ("lsystems/bush3.json", 5)
    , ("lsystems/bush4.json", 4)
    , ("lsystems/bush5.json", 6)
    , ("lsystems/bush5.json", 7)
    , ("lsystems/bush5.json", 8)
]

fnames_png = [comp.compile(l, n, True, "figs/" + Path(l).stem + "_transparent") for l, n in things]
PATHS = [Path(x).with_suffix('.svg') for x in fnames_png]

N_TREES = 50

forest = draw.Drawing(1000,1000)

forest.append(
    draw.Rectangle(0,0,1000,1000,fill='white')
)

for _ in range(N_TREES):
    x = random.randint(0, 1000)
    y = random.randint(0, 500)
    p = random.choice(PATHS)
    im = draw.Image(x, y, width=200, height=200, path=p, embed=True)
    forest.append(im)

forest.saveSvg("figs/forest.svg")


from heapq import heappop, heappush
from collections import defaultdict
class Node:
    cnt = 0
    def __init__(self, val) -> None:
        self.val = val
        self.l = []
        self.id = Node.cnt
        Node.cnt += 1
        self.visited = False

    def __str__(self) -> str:
        return f"<NODE {self.id}, val:{self.val}, n_vos:{len(self.l)}>"

    def __repr__(self) -> str:
        return f"<node {self.val}, id:{self.id}, {len(self.l)} vos>"

    def __lt__(self, other):
        return self.val < other.val

ls = []
#with open("input.txt", "r") as f:
with open("test.txt", "r") as f:
    ls = [x.strip() for x in f.readlines()]

grid = []
all_nodes = []
for l in ls:
    grid.append([])
    for c in l:
        c = int(c)
        x = Node(c)
        grid[-1].append(x)

for i, row in enumerate(grid):
    for j, x in enumerate(row):
        p = q = r = s = None
        try:
            if i > 0:
                p = grid[i - 1][j]
        except Exception:
            pass
        try:
            q = grid[i + 1][j]
        except Exception:
            pass
        try:
            if j > 0:
                r = grid[i][j - 1]
        except Exception:
            pass
        try:
            s = grid[i][j + 1]
        except Exception:
            pass

        x.l.extend([x for x in [p, q, r, s] if x])
        all_nodes.append(x)

def buildgraph(lines):
    V = set()
    E = defaultdict(set)
    w = dict()

    for l in lines:
        v, u, weight = l
        V.add(v)
        V.add(u)
        E[v].add(u)
        w[(v, u)] = weight
    return V, E, w

l = []
for x in all_nodes:
    for y in x.l:
        l.append((x.id, y.id, y.val))
lt = l

def dijkstra(G, s):
    V, E, w = G
    Q = [(0, s)]
    D = defaultdict(lambda: float("inf"))
    D[s] = 0

    while Q:
        cost, v = heappop(Q)
        for u in E[v]:
            c = cost + w[(v, u)]
            if c < D[u]:
                D[u] = c
                heappush(Q, (c, u))
    return D

gr = buildgraph(lt)
d = dijkstra(gr, all_nodes[0].id)
print("res:", d[all_nodes[-1].id])


import numpy as np
import matplotlib.pyplot as plt
import math
npr = np.random
from rllab.policies.gaussian_mlp_policy import GaussianMLPPolicy
import tensorflow as tf
from six.moves import cPickle
from collect_samples import CollectSamples
from get_true_action import GetTrueAction
import os
import copy
from helper_funcs import create_env
from helper_funcs import perform_rollouts
from helper_funcs import add_noise
from feedforward_network import feedforward_network
from helper_funcs import visualize_rendering
import argparse

#TRPO things
from rllab.envs.normalized_env import normalize
from rllab.algos.trpo import TRPO
from rllab.baselines.linear_feature_baseline import LinearFeatureBaseline
from rllab.optimizers.conjugate_gradient_optimizer import ConjugateGradientOptimizer
from rllab.optimizers.conjugate_gradient_optimizer import FiniteDifferenceHvp
from rllab.misc.instrument import run_experiment_lite

def nn_policy(inputState, junk1, outputSize, junk2, junk3, junk4):
	#init vars
	x = inputState
	initializer = tf.contrib.layers.xavier_initializer(uniform=False, seed=None, dtype=tf.float64)
	fc = tf.contrib.layers.fully_connected
	weights_reg = tf.contrib.layers.l2_regularizer(scale=0.001)
	#hidden layer 1
	fc1 = fc(x, num_outputs= 64, activation_fn=None, trainable=True, reuse=False, weights_initializer=initializer,
			biases_initializer=initializer, weights_regularizer=weights_reg)
	h1 = tf.tanh(fc1)
	#hidden layer 2
	fc2 = fc(h1, num_outputs= 64, activation_fn=None, trainable=True, reuse=False, weights_initializer=initializer,
			biases_initializer=initializer, weights_regularizer=weights_reg)
	h2 = tf.tanh(fc2)
	# output layer
	output = fc(h2, num_outputs=outputSize, activation_fn=None, trainable=True, reuse=False,
				weights_initializer=initializer, biases_initializer=initializer)
	return output

def run_task(v):

	which_agent=v["which_agent"]
	env,_ = create_env(which_agent)
	baseline = LinearFeatureBaseline(env_spec=env.spec)
	optimizer_params = dict(base_eps=1e-5)

	#how many iters
	num_trpo_iters = 2500
	if(which_agent==1):
		num_trpo_iters = 2500
	if(which_agent==2):
		steps_per_rollout=333
		num_trpo_iters = 200
	if(which_agent==4):
		num_trpo_iters= 2000
	if(which_agent==6):
		num_trpo_iters= 2000

	#recreate the policy
	policy = GaussianMLPPolicy(env_spec=env.spec, hidden_sizes=(v["depth_fc_layers"], v["depth_fc_layers"]), init_std=v["std_on_mlp_policy"])
	all_params = np.concatenate((v["policy_values"], policy._l_log_std.get_params()[0].get_value()))
	policy.set_param_values(all_params)

	algo = TRPO(
		env=env,
		policy=policy,
		baseline=baseline,
		batch_size=v["trpo_batchsize"],
		max_path_length=v["steps_per_rollout"],
		n_itr=num_trpo_iters,
		discount=0.995,
		optimizer=v["ConjugateGradientOptimizer"](hvp_approach=v["FiniteDifferenceHvp"](**optimizer_params)),
		step_size=0.05,
		plot_true=True)

	#train the policy
	algo.train()

##########################################
##########################################

#ARGUMENTS TO SPECIFY
parser = argparse.ArgumentParser()
parser.add_argument('--save_trpo_run_num', type=int, default='1')
parser.add_argument('--run_num', type=int, default=1)
parser.add_argument('--which_agent', type=int, default=1)
parser.add_argument('--std_on_mlp_policy', type=float, default=0.5)
parser.add_argument('--num_workers_trpo', type=int, default=2)
parser.add_argument('--might_render', action="store_true", dest='might_render', default=False)
parser.add_argument('--visualize_mlp_policy', action="store_true", dest='visualize_mlp_policy', default=False)
parser.add_argument('--visualize_on_policy_rollouts', action="store_true", dest='visualize_on_policy_rollouts', default=False)
parser.add_argument('--print_minimal', action="store_true", dest='print_minimal', default=False)
parser.add_argument('--use_existing_pretrained_policy', action="store_true", dest='use_existing_pretrained_policy', default=False)
args = parser.parse_args()

##########################################
##########################################

#save args
save_trpo_run_num= args.save_trpo_run_num
run_num = args.run_num
which_agent = args.which_agent
visualize_mlp_policy = args.visualize_mlp_policy
visualize_on_policy_rollouts = args.visualize_on_policy_rollouts
print_minimal = args.print_minimal
std_on_mlp_policy = args.std_on_mlp_policy

#swimmer
trpo_batchsize = 50000
if(which_agent==2):
	#training vars for new policy
	batchsize = 512
	nEpoch = 70
	learning_rate = 0.001
	#aggregation for training of new policy
	num_agg_iters = 3
	num_rollouts_to_agg= 5
	num_rollouts_testperformance = 2
	start_using_noised_actions = 0
	#other
	do_trpo = True
#cheetah
if(which_agent==4):
	#training vars for new policy
	batchsize = 512
	nEpoch = 300
	learning_rate = 0.001
	#aggregation for training of new policy
	num_agg_iters = 3
	num_rollouts_to_agg= 2
	num_rollouts_testperformance = 2
	start_using_noised_actions = 10
	#other
	do_trpo = True
#hopper
if(which_agent==6):
	#training vars for new policy
	batchsize = 512
	nEpoch = 200 #70
	learning_rate = 0.001
	#aggregation for training of new policy
	num_agg_iters = 5 #10
	num_rollouts_to_agg= 5 ###10
	num_rollouts_testperformance = 3
	start_using_noised_actions = 50
	#other
	do_trpo = True
	trpo_batchsize = 25000
#ant
if(which_agent==1):
	#training vars for new policy
	batchsize = 512
	nEpoch = 200
	learning_rate = 0.001
	#aggregation for training of new policy
	num_agg_iters = 5
	num_rollouts_to_agg= 5
	num_rollouts_testperformance = 3
	start_using_noised_actions = 50
	#other
	do_trpo = True

##########################################
##########################################

#get vars from saved MB run
param_dict = np.load('run_'+ str(run_num) + '/params.pkl')
N = param_dict['num_control_samples']
horizon = param_dict['horizon']
num_fc_layers_old = param_dict['num_fc_layers']
depth_fc_layers_old = param_dict['depth_fc_layers']
lr_olddynmodel = param_dict['lr']
batchsize_olddynmodel = param_dict['batchsize']
dt_steps = param_dict['dt_steps']
steps_per_rollout = param_dict['steps_per_episode']
tf_datatype = param_dict['tf_datatype']
seed = param_dict['seed']
if(tf_datatype=="<dtype: 'float64'>"):
	tf_datatype = tf.float64
else:
	tf_datatype = tf.float32

#load the saved MPC rollouts
f = open('run_'+ str(run_num)+'/savedRollouts.save', 'rb')
allData = cPickle.load(f)
f.close()

##########################################
##########################################

#create env
env, dt_from_xml = create_env(which_agent)

# set tf seed
npr.seed(seed)
tf.set_random_seed(seed)

#init vars
noise_onpol_rollouts=0.005
plot=False
print_frequency = 20
validation_frequency = 50
num_fc_layers=2
depth_fc_layers=64
save_dir = 'run_'+ str(run_num)+'/mbmf'
if not os.path.exists(save_dir):
    os.makedirs(save_dir)

#convert saved rollouts into array
allDataArray=[]
allControlsArray=[]
for i in range(len(allData)):
	allDataArray.append(allData[i]['observations'])
	allControlsArray.append(allData[i]['actions'])
training_data=np.concatenate(allDataArray)
labels=np.concatenate(allControlsArray)

if(len(labels.shape)==3):
	labels=np.squeeze(labels)
print("\n(total) Data size ", training_data.shape[0],"\n\n")

##################################################################################

# set aside some of the training data for validation
validnum = 10000
if((which_agent==6)or(which_agent==2)or(which_agent==1)):
	validnum=700
num = training_data.shape[0]-validnum
validation_x = training_data[num:num+validnum,:]
training_data=training_data[0:num,:]
validation_z = labels[num:num+validnum,:]
labels=labels[0:num,:]
print("\nTraining data size ", training_data.shape[0])
print("Validation data size ", validation_x.shape[0],"\n")

if(args.might_render or args.visualize_mlp_policy or args.visualize_on_policy_rollouts):
	might_render=True
else:
	might_render=False
#this somehow prevents a seg fault from happening in the later visualization
if(might_render):
    new_env = copy.deepcopy(env)
    new_env.render()

#gpu options for tensorflow
gpu_device = 0
gpu_frac = 0.3
os.environ["CUDA_VISIBLE_DEVICES"] = str(gpu_device)
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=gpu_frac)
config = tf.ConfigProto(gpu_options=gpu_options,
                        log_device_placement=False,
                        allow_soft_placement=True,
                        inter_op_parallelism_threads=1,
                        intra_op_parallelism_threads=1)

#add SL noise to training data inputs and outputs
'''TO DO'''

#keep track of sample complexity
datapoints_used_forMB = np.load('run_'+ str(run_num) + '/datapoints_MB.npy')[-1]
datapoints_used_to_init_imit = training_data.shape[0]
total_datapoints = datapoints_used_forMB + datapoints_used_to_init_imit #points used thus far
imit_list_num_datapoints = []
imit_list_avg_rew = []

with tf.Session(config=config) as sess:

	if(not(args.use_existing_pretrained_policy)):

		#init vars
		g=GetTrueAction()
		g.make_model(sess, env, 'run_'+ str(run_num), tf_datatype, num_fc_layers_old, depth_fc_layers_old, which_agent,
					lr_olddynmodel, batchsize_olddynmodel, N, horizon, steps_per_rollout, dt_steps, print_minimal)
		nData=training_data.shape[0]
		inputSize = training_data.shape[1]
		outputSize = labels.shape[1]

		#placeholders
		inputs_placeholder = tf.placeholder(tf_datatype, shape=[None, inputSize], name='inputs')
		labels_placeholder = tf.placeholder(tf_datatype, shape=[None, outputSize], name='outputs')

		#output of nn
		curr_output = nn_policy(inputs_placeholder, inputSize, outputSize, num_fc_layers, depth_fc_layers, tf_datatype)

		#define training
		theta = tf.trainable_variables()
		loss = tf.reduce_mean(tf.square(curr_output - labels_placeholder))
		opt = tf.train.AdamOptimizer(learning_rate)
		gv = [(g,v) for g,v in opt.compute_gradients(loss, theta) if g is not None]
		train_step = opt.apply_gradients(gv)

		#get all the uninitialized variables (ie right now all of them)
		list_vars=[]
		for var in tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES):
			if(not(tf.is_variable_initialized(var).eval())):
				list_vars.append(var)
		sess.run(tf.variables_initializer(list_vars))

		#aggregation iterations
		for agg_iter in range(num_agg_iters):

			print("ON AGGREGATION ITERATION ", agg_iter)
			rewards_for_this_iter=[]
			plot_trainingloss_x=[]
			plot_trainingloss_y=[]
			plot_validloss_x=[]
			plot_validloss_y=[]

			for i in range(nEpoch):

				################################
				############ TRAIN #############
				################################

				avg_loss=0
				iters_in_batch=0
				range_of_indeces = np.arange(training_data.shape[0])
				indeces = npr.choice(range_of_indeces, size=(training_data.shape[0],), replace=False)

				for batch in range(int(math.floor(nData / batchsize))):
					# Batch the training data
					inputs = training_data[indeces[batch*batchsize:(batch+1)*batchsize], :]
					outputs = labels[indeces[batch*batchsize:(batch+1)*batchsize], :]

					#one iteration of feedforward training
					_, my_loss = sess.run([train_step, loss],
								feed_dict={inputs_placeholder: inputs, labels_placeholder: outputs})

					#loss
					avg_loss+= np.sqrt(my_loss)
					iters_in_batch+=1

				################################
				###### SAVE TRAIN LOSSES #######
				################################

				if(iters_in_batch==0):
					iters_in_batch=1

				current_loss = avg_loss/iters_in_batch

				#save training losses
				if(not(print_minimal)):
					if(i%print_frequency==0):
						print("training loss: ", current_loss, ", 	nEpoch: ", i)
				plot_trainingloss_x.append(i)
				plot_trainingloss_y.append(current_loss)
				np.save(save_dir + '/plot_trainingloss_x.npy', plot_trainingloss_x)
				np.save(save_dir + '/plot_trainingloss_y.npy', plot_trainingloss_y)

				################################
				########## VALIDATION ##########
				################################

				if((i%validation_frequency)==0):
					avg_valid_loss=0
					iters_in_valid=0

					range_of_indeces = np.arange(validation_x.shape[0])
					indeces = npr.choice(range_of_indeces, size=(validation_x.shape[0],), replace=False)

					for batch in range(int(math.floor(validation_x.shape[0] / batchsize))):
						# Batch the training data
						inputs = validation_x[indeces[batch*batchsize:(batch+1)*batchsize], :]
						outputs = validation_z[indeces[batch*batchsize:(batch+1)*batchsize], :]

						#one iteration of feedforward training
						my_loss, _ = sess.run([loss, curr_output],
									feed_dict={inputs_placeholder: inputs, labels_placeholder: outputs})

						#loss
						avg_valid_loss+= np.sqrt(my_loss)
						iters_in_valid+=1

					curr_valid_loss = avg_valid_loss/iters_in_valid

					#save validation losses
					plot_validloss_x.append(i)
					plot_validloss_y.append(curr_valid_loss)
					if(not(print_minimal)):
						print("validation loss: ", curr_valid_loss, ", 	nEpoch: ", i, "\n")
					np.save(save_dir + '/plot_validloss_x.npy', plot_validloss_x)
					np.save(save_dir + '/plot_validloss_y.npy', plot_validloss_y)

			print("DONE TRAINING.")
			print("final training loss: ", current_loss, ", 	nEpoch: ", i)
			print("final validation loss: ", curr_valid_loss, ", 	nEpoch: ", i)

			##################
			##### PLOT #######
			##################
			if(plot):
				plt.plot(plot_validloss_x, plot_validloss_y, 'r')
				plt.plot(plot_trainingloss_x, plot_trainingloss_y, 'g')
				plt.show()

			##################################################
			##### RUN ON-POLICY ROLLOUTS --- DAGGER ##########
			##################################################

			print("\n\nCollecting on-policy rollouts...\n\n")
			starting_states = []
			observations = []
			actions=[]
			true_actions=[]

			for rollout in range(num_rollouts_to_agg):
				if(not(print_minimal)):
					print("\nOn rollout #", rollout)
				total_rew = 0

				starting_observation, starting_state = env.reset(returnStartState=True)
				curr_ob=np.copy(starting_observation)

				observations_for_rollout = []
				actions_for_rollout = []
				true_actions_for_rollout=[]
				for step in range(steps_per_rollout):

					#get action
					action = sess.run([curr_output], feed_dict={inputs_placeholder: np.expand_dims(curr_ob, axis=0)})
					action=np.copy(action[0][0]) #1x8

					#### add exploration noise to the action
					if(agg_iter>start_using_noised_actions):
						action = action + noise_onpol_rollouts*npr.normal(size=action.shape)

					#save obs and ac
					observations_for_rollout.append(curr_ob)
					actions_for_rollout.append(action)

					#####################################
					##### GET LABEL OF TRUE ACTION ######
					#####################################

					true_action = g.get_action(curr_ob)
					true_actions_for_rollout.append(true_action)

					#take step
					next_ob, rew, done, _ = env.step(action, collectingInitialData=False)
					total_rew+= rew
					curr_ob= np.copy(next_ob)

					if(done):
						break

					if((step%100)==0):
						print("   Done with step #: ", step)

				total_datapoints+= step
				print("rollout ", rollout," .... reward = ", total_rew)
				if(not(print_minimal)):
					print("number of steps: ", step)
					print("number of steps so far: ", total_datapoints)

				if(visualize_on_policy_rollouts):
					input("\n\nPAUSE BEFORE VISUALIZATION... Press Enter to continue...")
					visualize_rendering(starting_state, actions_for_rollout, env, dt_steps, dt_from_xml, which_agent)

				starting_states.append(starting_state)
				observations.append(observations_for_rollout)
				actions.append(actions_for_rollout)
				true_actions.append(true_actions_for_rollout)

				rewards_for_this_iter.append(total_rew)

			print("Avg reward for this iter: ", np.mean(rewards_for_this_iter), "\n\n")

			##################################################
			##### RUN CLEAN ROLLOUTS TO SEE PERFORMANCE ######
			##################################################

			print("\n\nTEST DAGGER PERFORMANCE (clean rollouts)...")
			rewards_for_this_iter2=[]
			for rollout in range(num_rollouts_testperformance):
				total_rew = 0
				starting_observation, starting_state = env.reset(returnStartState=True)
				curr_ob=np.copy(starting_observation)

				for step in range(steps_per_rollout):

					#get action
					action = sess.run([curr_output], feed_dict={inputs_placeholder: np.expand_dims(curr_ob, axis=0)})
					action=np.copy(action[0][0]) #1x8

					#take step
					next_ob, rew, done, _ = env.step(action, collectingInitialData=False)
					total_rew+= rew
					curr_ob= np.copy(next_ob)

					if(done):
						break
				if(not(print_minimal)):
					print("reward = ", total_rew)
				rewards_for_this_iter2.append(total_rew)
			print("Avg DAGGER performance at this iter: ", np.mean(rewards_for_this_iter2), "\n\n")

			###### SAVE datapoints vs performance
			imit_list_num_datapoints.append(total_datapoints)
			imit_list_avg_rew.append(total_rew)

			###########################
			##### AGGREGATE DATA ######
			###########################
			if(not(print_minimal)):
				print("\nAggregating Data...\n")
			training_data = np.concatenate([training_data, np.concatenate(observations)], axis=0)
			labels = np.concatenate([labels, np.concatenate(true_actions)], axis=0)

		#save the datapoints vs performance
		np.save('run_'+ str(run_num) + '/datapoints_IMIT.npy', imit_list_num_datapoints)
		np.save('run_'+ str(run_num) + '/performance_IMIT.npy', imit_list_avg_rew)

		if(not(print_minimal)):
			print("Done training the TF policy")

		######################
		### SAVE NN PARAMS ###
		######################

		#prepare the params for saving
		values = []
		for t in list_vars[0:6]:
			if(t.eval().shape==()):
				junk=1
			else:
				values.append(np.ndarray.flatten(t.eval()))
		values = np.concatenate(values)

		#save the TF policy params
		if(not(print_minimal)):
			print("Saving learned TF nn model parameters.")
		f = open(save_dir + '/policy_tf_values.save', 'wb')
		cPickle.dump(values, f, protocol=cPickle.HIGHEST_PROTOCOL)
		f.close()

	else: #use_existing_pretrained_policy is True

		f = open(save_dir + '/policy_tf_values.save', 'rb')
		values = cPickle.load(f)
		f.close()

	#######################
	### INIT MLP POLICY ###
	#######################

	policy = GaussianMLPPolicy(env_spec=env.spec, hidden_sizes=(depth_fc_layers, depth_fc_layers), init_std=std_on_mlp_policy)

	#copy params over to the MLP policy
	all_params = np.concatenate((values, policy._l_log_std.get_params()[0].get_value()))
	policy.set_param_values(all_params)

	#save the MLP policy
	f = open(save_dir + '/policy_mlp.save', 'wb')
	cPickle.dump(policy, f, protocol=cPickle.HIGHEST_PROTOCOL)
	f.close()
	if(not(print_minimal)):
		print("Done initializing MLP policy with a pre-trained policy.")

	##see what this initialized MLP policy looks like
	if(visualize_mlp_policy):
		input("\n\nPAUSE BEFORE VISUALIZATION... Press Enter to continue...")
	states, controls, starting_states, rewards = perform_rollouts(policy, 1, steps_per_rollout, visualize_mlp_policy,
																CollectSamples, env, which_agent, dt_steps, dt_from_xml, False)
	print("Std of the MLP policy: ", std_on_mlp_policy)
	print("Reward of the MLP policy: ", rewards)

	################################
	### TRAIN MLP POLICY W/ TRPO ###
	################################

	if(do_trpo):
		run_experiment_lite(run_task, plot=True, snapshot_mode="all", use_cloudpickle=True, n_parallel=str(args.num_workers_trpo),
						exp_name='run_' + str(run_num)+'_std' + str(std_on_mlp_policy)+ '_run'+ str(save_trpo_run_num),
						variant=dict(policy_values=values.tolist(), which_agent=which_agent,
								trpo_batchsize=trpo_batchsize, steps_per_rollout=steps_per_rollout,
								FiniteDifferenceHvp=FiniteDifferenceHvp, ConjugateGradientOptimizer=ConjugateGradientOptimizer,
								depth_fc_layers=depth_fc_layers, std_on_mlp_policy=std_on_mlp_policy))


import numpy as np
import torch
import dgl
from dgl import DGLGraph
from rdkit import Chem
from rdkit.Chem import rdMolDescriptors as rdDesc

#辅助函数
def one_of_k_encoding_unk(x, allowable_set):
    '将x与allowable_set逐个比较，相同为True， 不同为False, 都不同则认为是最后一个相同'
    if x not in allowable_set:
        x = allowable_set[-1]
    return list(map(lambda s: x == s, allowable_set))

def get_atom_features(atom):
    possible_atom = ['C', 'N', 'O', 'F', 'P', 'Cl', 'Br', 'I', 'H', 'S', 'Fe', 'Mg', 'B', 'DU'] #DU代表其他原子
    atom_features = one_of_k_encoding_unk(atom.GetSymbol(), possible_atom)
    atom_features += one_of_k_encoding_unk(atom.GetImplicitValence(), [0, 1])
    atom_features += one_of_k_encoding_unk(atom.GetNumRadicalElectrons(), [0, 1])
    atom_features += one_of_k_encoding_unk(atom.GetDegree(), [0, 1, 2, 3, 4, 5, 6])
    atom_features += one_of_k_encoding_unk(atom.GetFormalCharge(), [-1, 1])
    atom_features += one_of_k_encoding_unk(atom.GetHybridization(),
                                           [Chem.rdchem.HybridizationType.SP,
                                            Chem.rdchem.HybridizationType.SP2,
                                            Chem.rdchem.HybridizationType.SP3,
                                            Chem.rdchem.HybridizationType.SP3D])
    return np.array(atom_features)

def get_bond_features(bond):
    bond_type = bond.GetBondType()
    bond_feats = [
        bond_type == Chem.rdchem.BondType.SINGLE, bond_type == Chem.rdchem.BondType.DOUBLE,
        bond_type == Chem.rdchem.BondType.TRIPLE, bond_type == Chem.rdchem.BondType.AROMATIC,
        bond.GetIsConjugated(),
        bond.IsInRing()
    ]
    return np.array(bond_feats)

def gen_graph(molecule_smiles):
    G = DGLGraph()
    #加载smile生成mol对象
    molecule = Chem.MolFromSmiles(molecule_smiles)

    G.add_nodes(molecule.GetNumAtoms())

    node_features = []
    edge_features = []

    for i in range(molecule.GetNumAtoms()):
        atom_i = molecule.GetAtomWithIdx(i)
        atom_i_features = get_atom_features(atom_i)
        node_features.append(atom_i_features)

        for j in range(molecule.GetNumAtoms()):
            bond_ij = molecule.GetBondBetweenAtoms(i, j)
            if bond_ij is not None:
                G.add_edges(i,j)
                bond_features_ij = get_bond_features(bond_ij)
                edge_features.append(bond_features_ij)

    G.ndata['x'] = torch.from_numpy(np.array(node_features)) #dgl添加原子/节点特征
    G.edata['w'] = torch.from_numpy(np.array(edge_features)) #dgl添加键/边特征

    return G

from collections import namedtuple
from  rdkit  import  Chem
from  rdkit.Chem  import  Draw
from  rdkit.Chem.Draw  import  IPythonConsole
from  rdkit.Chem  import  rdChemReactions
import  rdkit
from rdkit.Chem import AllChem
#from PIL.Image import Image

AtomInfo = namedtuple('AtomInfo',('mapnum','reactant','reactantAtom','product','productAtom'))
def map_reacting_atoms_to_products(rxn,reactingAtoms):
    ''' figures out which atoms in the products each mapped atom in the reactants maps to '''
    res = []
    for ridx,reacting in enumerate(reactingAtoms):
        reactant = rxn.GetReactantTemplate(ridx)
        for raidx in reacting:
            mapnum = reactant.GetAtomWithIdx(raidx).GetAtomMapNum()
            foundit=False
            for pidx,product in enumerate(rxn.GetProducts()):
                for paidx,patom in enumerate(product.GetAtoms()):
                    if patom.GetAtomMapNum()==mapnum:
                        res.append(AtomInfo(mapnum,ridx,raidx,pidx,paidx))
                        foundit = True
                        break
                    if foundit:
                        break
    return res
def get_mapped_neighbors(atom):
    ''' test all mapped neighbors of a mapped atom'''
    res = {}
    amap = atom.GetAtomMapNum()
    if not amap:
        return res
    for nbr in atom.GetNeighbors():
        nmap = nbr.GetAtomMapNum()
        if nmap:
            if amap>nmap:
                res[(nmap,amap)] = (atom.GetIdx(),nbr.GetIdx())
            else:
                res[(amap,nmap)] = (nbr.GetIdx(),atom.GetIdx())
    return res

BondInfo = namedtuple('BondInfo',('product','productAtoms','productBond','status'))
def find_modifications_in_products(rxn):
    ''' returns a 2-tuple with the modified atoms and bonds from the reaction '''
    reactingAtoms = rxn.GetReactingAtoms()
    amap = map_reacting_atoms_to_products(rxn,reactingAtoms)
    res = []
    seen = set()
    # this is all driven from the list of reacting atoms:
    for _,ridx,raidx,pidx,paidx in amap:
        reactant = rxn.GetReactantTemplate(ridx)
        ratom = reactant.GetAtomWithIdx(raidx)
        product = rxn.GetProductTemplate(pidx)
        patom = product.GetAtomWithIdx(paidx)

        rnbrs = get_mapped_neighbors(ratom)
        pnbrs = get_mapped_neighbors(patom)
        for tpl in pnbrs:
            pbond = product.GetBondBetweenAtoms(*pnbrs[tpl])
            if (pidx,pbond.GetIdx()) in seen:
                continue
            seen.add((pidx,pbond.GetIdx()))
            if not tpl in rnbrs:
                # new bond in product
                res.append(BondInfo(pidx,pnbrs[tpl],pbond.GetIdx(),'New'))
            else:
                # present in both reactants and products, check to see if it changed
                rbond = reactant.GetBondBetweenAtoms(*rnbrs[tpl])
                if rbond.GetBondType()!=pbond.GetBondType():
                    res.append(BondInfo(pidx,pnbrs[tpl],pbond.GetIdx(),'Changed'))
    return amap,res

def gen_graph_with_broken_bonds(molecule_smiles, reaction, template_label):
    rxn = rdChemReactions.ReactionFromSmarts(reaction)
    rxn.Initialize()
    atms, bnds = find_modifications_in_products(rxn)

    G = DGLGraph()
    #加载smile生成mol对象
    molecule = Chem.MolFromSmiles(molecule_smiles)

    G.add_nodes(molecule.GetNumAtoms())

    node_features = []
    edge_features = []
    edge_labels = []

    for i in range(molecule.GetNumAtoms()):
        atom_i = molecule.GetAtomWithIdx(i)
        atom_i_features = get_atom_features(atom_i)
        node_features.append(atom_i_features)

        for j in range(molecule.GetNumAtoms()):
            bond_ij = molecule.GetBondBetweenAtoms(i, j)
            if bond_ij is not None:
                G.add_edges(i,j)
                bond_features_ij = get_bond_features(bond_ij)
                edge_features.append(bond_features_ij)
                l = 0
                for b in bnds:
                    if (b.productAtoms[0] == i and b.productAtoms[1] == j) or (b.productAtoms[1] == i and b.productAtoms[0] == j):
                        l = template_label + 1
                edge_labels.append(l)

    G.ndata['x'] = torch.from_numpy(np.array(node_features)) #dgl添加原子/节点特征
    G.edata['w'] = torch.from_numpy(np.array(edge_features)) #dgl添加键/边特征
    G.edata['l'] = torch.from_numpy(np.array(edge_labels)) #dgl添加键/边特征

    return G


from typing import List

class Solution:
    def longestConsecutive(self, nums: List[int]) -> int:
        s = set(nums)
        max_len = 0
        for n in s:
            if n - 1 not in s:
                i = 1
                while n + i in s:
                    i += 1
                max_len = max([max_len, i])
        return max_len

if __name__ == '__main__':
    print(Solution().longestConsecutive([100, 4, 200, 1 ,6]))


from django.conf.urls import patterns, include, url

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'getin.views.home', name='home'),
    url(r'^api/', include('api.urls')),

    url(r'^dashboard/', include('dashboard.urls')),

    # Authentication
    url(r'^login/', 'django.contrib.auth.views.login', {'template_name': 'login.html'}, name="login"),
    url(r'^accounts/login/', 'django.contrib.auth.views.login', {'template_name': 'login.html'}, name="login"),
    url(r'^logout/$', 'django.contrib.auth.views.logout', {'next_page': '/'}, name="logout"),

    url(r'^admin/', include(admin.site.urls)),
)


from app_config import config
from env_setup import setup_test_paths

setup_test_paths()

from agar.test import BaseTest
from models import Domain, Distributor

__author__ = 'Bob MacNeal <bob.macneal@agosto.com>'

class TestDomainModel(BaseTest):
    DISTRIBUTOR_NAME = 'agosto'
    CHROME_DEVICE_DOMAIN = 'dev.agosto.com'
    CURRENT_CLASS_VERSION = 1
    IMPERSONATION_EMAIL = 'test@test.com'
    OU_PATH = '/abc/123/skykit'

    def setUp(self):
        super(TestDomainModel, self).setUp()
        self.distributor = Distributor.create(name=self.DISTRIBUTOR_NAME,
                                              active=True)
        self.distributor_key = self.distributor.put()
        self.domain = Domain.create(name=self.CHROME_DEVICE_DOMAIN,
                                    distributor_key=self.distributor_key,
                                    impersonation_admin_email_address=self.IMPERSONATION_EMAIL,
                                    active=True)
        self.domain_key = self.domain.put()

    def test_create_sets_distributor_key(self):
        domain = Domain.find_by_name(self.CHROME_DEVICE_DOMAIN)
        self.assertEqual(domain.distributor_key, self.distributor_key)

    def test_find_by_name_returns_expected_domain_representation(self):
        domain = Domain.find_by_name(self.CHROME_DEVICE_DOMAIN)
        domain.organization_path = self.OU_PATH
        self.assertEqual(domain.distributor_key, self.distributor_key)
        self.assertEqual(domain.name, self.CHROME_DEVICE_DOMAIN)
        self.assertEqual(domain.impersonation_admin_email_address, self.IMPERSONATION_EMAIL)
        self.assertTrue(domain.active)
        self.assertEqual(self.OU_PATH, domain.organization_path)
        self.assertIsNotNone(domain.created)

    def test_create_sets_an_inactive_domain(self):
        name = 'some domain'
        domain = Domain.create(name=name,
                               distributor_key=self.distributor_key,
                               impersonation_admin_email_address=self.IMPERSONATION_EMAIL,
                               active=False)
        domain.put()
        domain_created = Domain.find_by_name(name)
        self.assertEqual(domain_created.name, name)
        self.assertFalse(domain_created.active)

    def test_get_distributor_returns_distributor_representation(self):
        distributor = self.domain.get_distributor()
        self.assertEqual(distributor.name, self.DISTRIBUTOR_NAME)

    def test_get_distributor_returns_distributor_default_properties(self):
        distributor = self.domain.get_distributor()
        self.assertEqual(distributor.content_manager_url, config.DEFAULT_CONTENT_MANAGER_URL)
        self.assertEqual(distributor.player_content_url, config.DEFAULT_PLAYER_CONTENT_URL)

    def test_class_version_is_only_set_by_pre_put_hook_method(self):
        self.domain.class_version = 47
        self.domain.put()
        self.assertEqual(self.domain.class_version, self.CURRENT_CLASS_VERSION)

    def test_already_exists_for_existing_active(self):
        name = 'existing-active.skykit.com'
        domain = Domain.create(name=name,
                               distributor_key=self.distributor_key,
                               impersonation_admin_email_address=self.IMPERSONATION_EMAIL,
                               active=True)
        domain.put()
        self.assertTrue(Domain.already_exists(name))

    def test_already_exists_for_existing_active_false(self):
        name = 'existing-non-active.skykit.com'
        domain = Domain.create(name=name,
                               distributor_key=self.distributor_key,
                               impersonation_admin_email_address=self.IMPERSONATION_EMAIL,
                               active=False)
        domain.put()
        self.assertFalse(Domain.already_exists(name))

    def test_already_exists_for_non_existing(self):
        name = 'non-existing.skykit.com'
        self.assertFalse(Domain.already_exists(name))

    def test_get_impersonation_email_when_domain_name_found(self):
        expected_impersonation_email = Domain.get_impersonation_email_by_domain_name(
            domain_name=self.CHROME_DEVICE_DOMAIN)
        self.assertEqual(self.domain.impersonation_admin_email_address, expected_impersonation_email)

    def test_get_impersonation_email_when_domain_name__not_found(self):
        expected = Domain.get_impersonation_email_by_domain_name(domain_name='foobar.com')
        self.assertIsNone(expected)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Jul 23 15:39:18 2020

@author: yochai_yemini
"""

import torch
import numpy as np
from collections import OrderedDict

eps=2.2204*np.exp(-16)

def stft(z, K, overlap, spec_mode='abs'):
    if spec_mode not in ['abs', 'log']:
        raise ValueError("spec_mode must be one of ")
    sub_num = 1 / (1 - overlap) - 1
    SEG_NO = np.fix(len(z) / (K * (1 - overlap))) - sub_num
    Z = np.zeros((int(K / 2 + 1), int(SEG_NO)))
    P = np.zeros((int(K / 2 + 1),int(SEG_NO)))
    for seg in np.arange(1, SEG_NO + 1):
        time_cal = np.arange((seg - 1) * K * (1 - overlap) + 1,
                             (seg - 1) * K * (1 - overlap) + K + 1) - 1
        time_cal = time_cal.astype('int')
        V = np.fft.fft(z[time_cal] * np.append(np.hanning(K - 1), 0))
        time_freq = np.arange(1, K / 2 + 1 + 1) - 1
        time_freq = time_freq.astype('int')
        P[:,int(seg-1)] = np.angle(V[time_freq])
        Z[:, int(seg - 1)] = np.abs(V[time_freq])

    if spec_mode == 'abs':
        return Z, P
    elif spec_mode == 'log':
        return np.log(Z + eps), P

def istft(A, P, synt_win):
    '''
    Returns the ISTFT of a FREQ x TIME signal
    param: A is the log-magnitude of the STFT, dimensions are FREQ x TIME.
    param: P is the phase is the phase of the STFT, dimensions are FREQ X TIME.
    param: synt_win is the synthesis window of length FREQ.
    '''
    # s_est=np.zeros((len(z),1))
    K = 512
    overlap = 0.75

    #Switch back from log-magnitude to magnitude
    A = np.exp(A)
    A[0:3] *= 0.001

    # Create the a KxTIME STFT from the (K/2+1)xTIME STFT
    A_inv, P_inv = A[::-1], P[::-1]
    A_inv, P_inv = A_inv[1:-1], P_inv[1:-1]
    P_full = np.concatenate([P, -P_inv], 0)
    A_full = np.concatenate([A, A_inv], 0)
    # A_full, P_full = A_full.numpy(), P_full.numpy()

    # Attach the phase with the magnitude
    S = A_full * np.exp(1j*P_full)
    S = np.real(np.fft.ifft(S, axis=0))
    S = synt_win * S

    SEG_NO = S.shape[1]
    long = 0.008*16000*SEG_NO + K
    long = int(long)
    s_est = np.zeros((long,1))
    for seg in np.arange(1,SEG_NO+1):
        time_cal = np.arange((seg-1)*K*(1-overlap)+1,(seg-1)*K*(1-overlap)+K+1)-1
        time_cal = time_cal.astype('int64')
        s_est[time_cal,:] = s_est[time_cal,:] + np.expand_dims(S[:, seg-1], axis=1)

    return s_est.squeeze()

def normalize_mc(z, desired_rms = 0.1, eps = 1e-4):
    '''
    Parameters
    ----------
    samples : numpy array comprising the multichannel reverberated speech
    desired_rms : desired rms after notmalisation. The default is 0.1.
                  rms is calculated over all samples and across channels.
    eps : The default is 1e-4.

    Returns
    -------
    samples : the normalised multichannel signals.

    '''
    if len(z) == 1:
        z = z/1.1/np.max(np.abs(z))
    else:
        rms = np.maximum(eps, np.sqrt(np.mean(z**2)))
        z = z * (desired_rms / rms)
    return z

def update_max(max_val, S):
    poten_max = np.max(S)
    if poten_max > max_val:
        return poten_max
    else:
        return max_val

def update_min(min_val, S):
    poten_min = np.min(S)
    if poten_min < min_val:
        return poten_min
    else:
        return min_val

def normalize_log_spec(z, max_val, min_val):
    normalized_z = (2*(z-max_val))/(max_val-min_val) + 1
    return normalized_z

def denormalize_log_spec (normelized_z, max_num = 1.0, min_num = 0.0):
    z = (normelized_z-1)*(max_num-min_num)/2 + max_num
    return z

def remove_module_str(state_dict):
    state_dict_rename = OrderedDict()
    for k, v in state_dict.items():
        name = k.replace("module.", "") # remove `module.`
        state_dict_rename[name] = v
    return state_dict_rename


# Everest 2

STARTING_HEIGHT = 5364
DESTINATION_HEIGHT = 8848
current_day = 0
current_height = 5364

command = input()
is_climbed_successful = False
while not command == "END":

    if command == "No" and current_day == 1:
        pass
    else:
        current_day += 1

    if current_day == 5:
        break

    day_climbed = int(input())
    current_height += day_climbed
    if current_height >= DESTINATION_HEIGHT:
        is_climbed_successful = True
        break

    command = input()

if is_climbed_successful:
    print(f"Goal reached for {current_day} days!")
else:
    print("Failed!")
    print(f"{current_height}")


from __future__ import print_function

import fnmatch
import io
import os
from tqdm import tqdm
import subprocess

def create_manifest(data_path, output_path, min_duration=None, max_duration=None):
    file_paths = [os.path.join(dirpath, f)
                  for dirpath, dirnames, files in os.walk(data_path)
                  for f in fnmatch.filter(files, '*.wav')]
    file_paths = order_and_prune_files(file_paths, min_duration, max_duration)
    with io.FileIO(output_path, "w") as file:
        for wav_path in tqdm(file_paths, total=len(file_paths)):
            transcript_path = wav_path.replace('/wav/', '/txt/').replace('.wav', '.txt')
            sample = os.path.abspath(wav_path) + ',' + os.path.abspath(transcript_path) + '\n'
            file.write(sample.encode('utf-8'))
    print('\n')

def order_and_prune_files(file_paths, min_duration, max_duration):
    print("Sorting manifests...")
    duration_file_paths = [(path, float(subprocess.check_output(
        ['soxi -D \"%s\"' % path.strip()], shell=True))) for path in file_paths]
    if min_duration and max_duration:
        print("Pruning manifests between %d and %d seconds" % (min_duration, max_duration))
        duration_file_paths = [(path, duration) for path, duration in duration_file_paths if
                               min_duration <= duration <= max_duration]

    def func(element):
        return element[1]

    duration_file_paths.sort(key=func)
    return [x[0] for x in duration_file_paths]  # Remove durations


"""
-------------------------------------------------------
Linked version of the Deque ADT.
-------------------------------------------------------
Author: Kevin Lee
ID:     210872060
Email:  leex7206@mylaurier.ca
__updated__ = '2022-01-15'
-------------------------------------------------------
"""

# Imports
from copy import deepcopy
from _collections import _deque_iterator

class _Deque_Node:

    def __init__(self, value, _prev, _next):
        """
        -------------------------------------------------------
        Initializes a deque node.
        Use: node = _Deque_Node(value, _prev, _next)
        -------------------------------------------------------
        Parameters:
            value - value value for node (?)
            _prev - another deque node (_Deque_Node)
            _next - another deque node (_Deque_Node)
        Returns:
            a new _Deque_Node object (_Deque_Node)

        -------------------------------------------------------
        """
        self._value = deepcopy(value)
        self._prev = _prev
        self._next = _next

class Deque:

    def __init__(self):
        """
        -------------------------------------------------------
        Initializes an empty deque.
        Use: d = deque()
        -------------------------------------------------------
        Returns:
            a new Deque object (Deque)
        -------------------------------------------------------
        """
        self._front = None
        self._rear = None
        self._count = 0

    def is_empty(self):
        """
        -------------------------------------------------------
        Determines if the deque is empty.
        Use: b = deque.is_empty()
        -------------------------------------------------------
        Returns:
            True if the deque is empty, False otherwise.
        -------------------------------------------------------
        """

        return self._count == 0

    def __len__(self):
        """
        -------------------------------------------------------
        Returns the size of the deque.
        Use: n = len(deque)
        -------------------------------------------------------
        Returns:
            the number of values in the deque (int)
        -------------------------------------------------------
        """

        return self._count

    def insert_front(self, value):
        """
        -------------------------------------------------------
        Inserts a copy of value into the front of the deque.
        Use: deque.insert_front(value)
        -------------------------------------------------------
        Parameters:
            value - a data element (?)
        Returns:
            None
        -------------------------------------------------------
        """

        node = _Deque_Node(deepcopy(value), None, self._front)

        if self._front is not None:
            self._front._prev = node
        else:
            self._rear = node
        self._front = node
        self._count += 1

        return

    def insert_rear(self, value):
        """
        -------------------------------------------------------
        Inserts a copy of value into the rear of the deque.
        Use: deque.insert_rear(value)
        -------------------------------------------------------
        Parameters:
            value - a data element (?)
        Returns:
            None
        -------------------------------------------------------
        """

        node = _Deque_Node(deepcopy(value), self._rear, None)

        if self._rear is not None:
            self._rear._next = node
        else:
            self._front = node
        self._rear = node
        self._count += 1

        return

    def remove_front(self):
        """
        -------------------------------------------------------
        Removes and returns value from the front of the deque.
        Use: v = deque.remove_front()
        -------------------------------------------------------
        Returns:
            value - the value at the front of deque (?)
        -------------------------------------------------------
        """
        assert self._front is not None, "Cannot remove from an empty deque"

        value = self._front._value
        self._front = self._front._next

        if self._front is not None:
            self._front._prev = None

        self._count -= 1

        if self._count == 0:
            self._rear = None

        return value

    def remove_rear(self):
        """
        -------------------------------------------------------
        Removes and returns value from the rear of the deque.
        Use: v = deque.remove_rear()
        -------------------------------------------------------
        Returns:
            value - the value at the rear of deque (?)
        -------------------------------------------------------
        """
        assert self._rear is not None, "Cannot remove from an empty deque"

        value = self._rear._value
        self._rear = self._rear._prev

        if self._rear is not None:
            self._rear._next = None
        else:
            self._front = None

        self._count -= 1

        return value

    def peek_front(self):
        """
        -------------------------------------------------------
        Peeks at the front of deque.
        Use: v = deque.peek_front()
        -------------------------------------------------------
        Returns:
            value - a copy of the value at the front of deque (?)
        -------------------------------------------------------
        """
        assert self._front is not None, "Cannot peek at an empty deque"

        return deepcopy(self._front._value)

    def peek_rear(self):
        """
        -------------------------------------------------------
        Peeks at the rear of deque.
        Use: v = deque.peek_rear()
        -------------------------------------------------------
        Returns:
            value - a copy of the value at the rear of deque (?)
        -------------------------------------------------------
        """
        assert self._rear is not None, "Cannot peek at an empty deque"

        return deepcopy(self._rear._value)

    def _swap(self, l, r):
        """
        -------------------------------------------------------
        Swaps two nodes within a deque. l has taken the place of r,
        r has taken the place of l and _front and _rear are updated
        as appropriate. Data is not moved.
        Use: self._swap(self, l, r):
        -------------------------------------------------------
        Parameters:
            l - a pointer to a deque node (_Deque_Node)
            r - a pointer to a deque node (_Deque_Node)
        Returns:
            None
        -------------------------------------------------------
        """
        assert l is not None and r is not None, "nodes to swap cannot be None"

        temp = l._value
        l._value = r._value
        r._value = temp

        if self._front == l:
            self._front = r
        elif self._front == r:
            self._front = l

        if self._rear == l:
            self._rear = r
        elif self._rear == r:
            self._rear = l

        temp1, temp2 = l._prev, l._next
        l._prev, l._next = r._prev, r._next
        r._prev, r._next = temp1, temp2

        return

    def __iter__(self):
        """
        USE FOR TESTING ONLY
        -------------------------------------------------------
        Generates a Python iterator. Iterates through the deque
        from front to rear.
        Use: for v in d:
        -------------------------------------------------------
        Returns:
            yields
            value - the next value in the deque (?)
        -------------------------------------------------------
        """
        current = self._front

        while current is not None:
            yield current._value
            current = current._next