import sys
sys.path.append("..")
from ifqi.envs import TaxiEnv
from ifqi.evaluation import evaluation
from policy_old import BoltzmannPolicy, TaxiEnvPolicy, EpsilonGreedyBoltzmannPolicy
import numpy as np
import numpy.linalg as la
import matplotlib.pyplot as plt
import argparse
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from reward_space.utils.discrete_env_sample_estimator import DiscreteEnvSampleEstimator
from reward_space.utils.discrete_mdp_wrapper import DiscreteMdpWrapper
from reward_space.proto_value_functions.proto_value_functions_estimator import  ProtoValueFunctionsEstimator
import reward_space.utils.linalg2 as la2
from sklearn.preprocessing import OneHotEncoder, MinMaxScaler
from sklearn.linear_model import LogisticRegression
from reward_space.policy_gradient.gradient_estimator import MaximumLikelihoodEstimator
#import cvxpy
import time
from reward_space.utils.utils import kullback_leibler_divergence
from reward_space.inverse_reinforcement_learning.hessian_optimization import HeuristicOptimizerNegativeDefinite
from reward_space.proto_value_functions.proto_value_functions_estimator import DiscreteProtoValueFunctionsEstimator
from prettytable import PrettyTable

from reward_space.policy_gradient.policy_gradient_learner import \
    PolicyGradientLearner

def plot_state_action_function(mdp, f, title, _cmap='coolwarm'):
    actions_names = ['S', 'N', 'W', 'E', 'up', 'down']
    Q = np.zeros((5,5,6))
    for i in range(0,f.shape[0],6):
        idx = list(mdp.decode(i/6))
        if idx[2] == 4 and idx[3] == 3:
            Q[idx[0], idx[1], :] = f[i:i+6]

    fig = plt.figure()

    x, y = np.meshgrid(range(1,6), range(1,6))
    for i in range(6):
        ax = fig.add_subplot(2, 3, i+1, projection='3d')
        ax.plot_surface(x,y, Q[:,:, i], rstride=1, cstride=1, cmap=plt.get_cmap(_cmap),
                       linewidth=0.3, antialiased=True)
        ax.set_title(actions_names[i])
        ax.xaxis.set_ticks(np.arange(1, 6))
        ax.yaxis.set_ticks(np.arange(1, 6))

    fig.suptitle(title)

def plot_state_function(mdp, f, title, _cmap='coolwarm'):
    V = np.zeros((5,5))
    for i in range(0,f.shape[0]):
        idx = list(mdp.decode(i))
        if idx[2] == 4 and idx[3] == 3:
            V[idx[0], idx[1]] = f[i]

    fig = plt.figure()

    x, y = np.meshgrid(range(1,6), range(1,6))
    ax = fig.add_subplot(1, 1, 1, projection='3d')
    ax.plot_surface(x,y, V, rstride=1, cstride=1, cmap=plt.get_cmap(_cmap),
                       linewidth=0.3, antialiased=True)
    ax.xaxis.set_ticks(np.arange(1, 6))
    ax.yaxis.set_ticks(np.arange(1, 6))

    fig.suptitle(title)

def estimate_hessian(dataset, n_episodes, policy_gradient, policy_hessian, reward_features, state_space, action_space, gamma, horizon):

    if np.ndim(reward_features) == 1:
        reward_features = reward_features[:, np.newaxis]

    n_samples = dataset.shape[0]
    n_features = reward_features.shape[1]
    n_params = policy_hessian.shape[1]
    n_states, n_actions = len(state_space), len(action_space)

    episode_reward_features = np.zeros((n_episodes, n_features))

    baseline = estimate_hessian_baseline(dataset, n_episodes, policy_gradient, policy_hessian, reward_features, state_space, action_space, gamma, horizon)

    episode_policy_gradient = np.zeros((n_episodes, n_params))
    episode_policy_hessian = np.zeros((n_episodes, n_params, n_params))

    i = 0
    episode = 0
    while i < n_samples:
        s = np.argwhere(state_space == dataset[i, 0])
        a = np.argwhere(action_space == dataset[i, 1])
        index = s * n_actions + a

        d = dataset[i, 4]

        episode_reward_features[episode, :] += d * reward_features[index, :].squeeze()
        episode_policy_gradient[episode, :] += policy_gradient[index, :].squeeze()
        episode_policy_hessian[episode, :, :] += policy_hessian[index, :, :].squeeze()

        if dataset[i, -2] == 1:

            if d == 1:
                diff = horizon - 1
            else:
                diff = horizon - np.log(d) / np.log(gamma)
            disc = (gamma * d - gamma ** (horizon + 1)) / (1 - gamma)

            episode_policy_gradient[episode, :] += diff * policy_gradient[-n_actions, :].squeeze()
            episode_policy_hessian[episode, :, :] += diff * policy_hessian[-n_actions, :, :].squeeze()
            episode_reward_features[episode, :] += disc * \
                (reward_features[-n_actions, :].squeeze())

        if dataset[i, -1] == 1:
            episode += 1

        i += 1

    episode_hessian = episode_policy_gradient.reshape(n_episodes, 1, n_params) * episode_policy_gradient.reshape(n_episodes, 1, n_params) + episode_policy_hessian
    episode_reward_features_baseline = episode_reward_features - baseline

    return_hessians = 1. / n_episodes * np.tensordot(episode_reward_features_baseline.T,
                                                     episode_hessian, axes=1)

    return return_hessians

def estimate_gradient(dataset, n_episodes, policy_gradient, reward_features, state_space, action_space, gamma, horizon):
    if np.ndim(reward_features) == 1:
        reward_features = reward_features[:, np.newaxis]

    n_samples = dataset.shape[0]
    n_features = reward_features.shape[1]
    n_params = policy_gradient.shape[1]
    n_states, n_actions = len(state_space), len(action_space)

    episode_reward_features = np.zeros((n_episodes, n_features))
    episode_gradient = np.zeros((n_episodes, n_params))

    baseline = estimate_gradient_baseline(dataset, n_episodes, policy_gradient, reward_features, state_space, action_space, gamma, horizon)

    i = 0
    episode = 0
    while i < n_samples:
        s = np.argwhere(state_space == dataset[i, 0])
        a = np.argwhere(action_space == dataset[i, 1])
        index = s * n_actions + a

        d = dataset[i, 4]

        episode_reward_features[episode, :] += d * reward_features[index, :].squeeze()
        episode_gradient[episode, :] +=  policy_gradient[index, :].squeeze()

        if dataset[i, -2] == 1:
            if d == 1:
                diff = horizon - 1
            else:
                diff = horizon - np.log(d) / np.log(gamma)
            disc = (gamma * d - gamma ** (horizon + 1)) / (1 - gamma)

            episode_gradient[episode, :] += diff * policy_gradient[-n_actions, :].squeeze()
            episode_reward_features[episode, :] += disc * \
                (reward_features[-n_actions, :].squeeze())

        if dataset[i, -1] == 1:
            episode += 1

        i += 1

    episode_reward_features_baseline = episode_reward_features - baseline

    return_gradient = 1. / n_episodes * np.dot(episode_reward_features_baseline.T,
                                                     episode_gradient)

    return return_gradient

def estimate_gradient_baseline(dataset, n_episodes, policy_gradient, reward_features, state_space, action_space, gamma, horizon):
    n_samples = dataset.shape[0]
    n_features = reward_features.shape[1]
    n_params = policy_gradient.shape[1]
    n_states, n_actions = len(state_space), len(action_space)

    episode_reward_features = np.zeros((n_episodes, n_features))
    episode_gradient = np.zeros((n_episodes, n_params))
    numerator = denominator = 0.

    i = 0
    episode = 0
    while i < n_samples:
        s = np.argwhere(state_space == dataset[i, 0])
        a = np.argwhere(action_space == dataset[i, 1])
        index = s * n_actions + a

        d = dataset[i, 4]

        episode_reward_features[episode, :] += d * reward_features[index, :].squeeze()
        episode_gradient[episode, :] += policy_gradient[index, :].squeeze()

        if dataset[i, -2] == 1:
            if d == 1:
                diff = horizon - 1
            else:
                diff = horizon - np.log(d) / np.log(gamma)
            disc = (gamma * d - gamma ** (horizon + 1)) / (1 - gamma)

            episode_gradient[episode, :] += diff * policy_gradient[-n_actions, :].squeeze()
            episode_reward_features[episode, :] += disc * \
                (reward_features[-n_actions, :].squeeze())

        if dataset[i, -1] == 1:
            vectorized_gradient = episode_gradient[episode, :].ravel()
            numerator += episode_reward_features[episode, :] * la.norm(vectorized_gradient) ** 2
            denominator += la.norm(vectorized_gradient) ** 2
            episode += 1

        i += 1

    baseline = numerator / denominator

    return baseline

def estimate_hessian_baseline(dataset, n_episodes, policy_gradient, policy_hessian, reward_features, state_space, action_space, gamma, horizon):
    n_samples = dataset.shape[0]
    n_features = reward_features.shape[1]
    n_params = policy_hessian.shape[1]
    n_states, n_actions = len(state_space), len(action_space)

    episode_reward_features = np.zeros((n_episodes, n_features))
    numerator = denominator = 0.

    episode_policy_gradient = np.zeros((n_episodes, n_params))
    episode_policy_hessian = np.zeros((n_episodes, n_params, n_params))

    i = 0
    episode = 0
    while i < n_samples:
        s = np.argwhere(state_space == dataset[i, 0])
        a = np.argwhere(action_space == dataset[i, 1])
        index = s * n_actions + a

        d = dataset[i, 4]

        episode_reward_features[episode, :] += d * reward_features[index, :].squeeze()
        episode_policy_gradient[episode, :] += policy_gradient[index, :].squeeze()
        episode_policy_hessian[episode, :, :] += policy_hessian[index, :, :].squeeze()

        if dataset[i, -2] == 1:

            if d == 1:
                diff = horizon - 1
            else:
                diff = horizon - np.log(d) / np.log(gamma)
            disc = (gamma * d - gamma ** (horizon + 1)) / (1 - gamma)

            episode_policy_gradient[episode, :] += diff * policy_gradient[-n_actions, :].squeeze()
            episode_policy_hessian[episode, :, :] += diff * policy_hessian[-n_actions, :, :].squeeze()
            episode_reward_features[episode, :] += disc * reward_features[-n_actions, :].squeeze()

        if dataset[i, -1] == 1:
            episode_hessian = np.outer(episode_policy_gradient[episode], episode_policy_gradient[episode]) + episode_policy_hessian[episode]
            vectorized_hessian = episode_hessian.ravel()
            numerator += episode_reward_features[episode, :] * la.norm(vectorized_hessian) ** 2
            denominator += la.norm(vectorized_hessian) ** 2
            episode += 1

        i += 1

    baseline = numerator / denominator

    return baseline

def build_state_features(mdp, binary=True):
    '''
    Builds the features of the state based on the current position of the taxi,
    whether it has already pick up the passenger, the relative position of the
    destination and source cell.

    :param mdp: the taxi mdp
    :param binary: whether the feature has to be one hot encoded
    :return: a (n_states, n_features) matrix containing the features for each
             state
    '''
    state_features = np.zeros((mdp.nS, 6))
    locs = [(0, 0), (0, 4), (4, 0), (4, 3)] #source and destination location
    for i in range(mdp.nS):
        lst = list(mdp.decode(i))
        pos_x, pos_y = lst[0], lst[1]

        if lst[2] == 4:
            start_x, start_y = 5, 5
        else:
            start_x, start_y = locs[lst[2]]
        arr_x, arr_y = locs[lst[3]]

        if start_x == 5:
            if arr_x == pos_x:
                delta_x = 2
            else:
                delta_x = 1 if arr_x > pos_x else 0

            if arr_y == pos_y:
                delta_y = 2
            else:
                delta_y = 1 if arr_y > pos_y else 0
        else:
            if start_x == pos_x:
                delta_x = 2
            else:
                delta_x = 1 if start_x > pos_x else 0

            if start_y == pos_y:
                delta_y = 2
            else:
                delta_y = 1 if start_y > pos_y else 0

        if delta_y == 2 and delta_x == 2:
            if start_x == 5:
                is_pos = 0
            else:
                is_pos = 1
        else:
            is_pos = 2

        '''
        A feature is encoded as a 5-tuple:
        - the (x,y) position of the taxi combined as 5x+y
        - the index of the starting location
        - the index of the destination location
        - whether the current x-position is on the same row, on the left or on the
          right wrt the source position if the passenger has not been pick up yet
          or wrt the destination position
        - whether the current y-position is on the same column, on the left or on the
          right wrt the source position if the passenger has not been pick up yet
          or wrt the destination position
        '''

        state_features[i, :] = [pos_x*5 + pos_y, lst[2], lst[3], delta_x, delta_y, is_pos]

    if not binary:
        return state_features
    else:
        enc = OneHotEncoder(n_values=[25, 4, 4, 2, 2, 3], sparse=False,
                            handle_unknown='ignore')
        enc.fit(state_features)
        state_features_binary = enc.transform(state_features)
        state_features_binary = state_features_binary[:, :state_features_binary.shape[1]-1]
        state_features_binary = np.vstack([state_features_binary, np.zeros((1, state_features_binary.shape[1]))])
        state_features_binary = np.hstack([state_features_binary, np.eye(mdp.nS + 1, 1, -mdp.nS)])
        return state_features_binary

def fit_maximum_likelihood_boltzmann_policy(state_features, optimal_action):
    '''
    Finds the maximum likelihood Boltzmann policy that best approximates a given
    deterministic policy.
    :param state_features: a (n_states, n_features) matrix representing the
                           feature vector for each state
    :param optimal_action: a (n_states,) vector containg for each state the index
                           of the optimal action
    :return: a pair: (action_weights, pi_prox)
             action_weights is a (n_actions, n_features) matrix representing the
                parameter estimated for each action
             pi_prox is a (n_states,n_actions) matrix representing the approximated
                probability distribution
    '''

    lr = LogisticRegression(penalty='l2',
                            tol=1e-10,
                            C=np.inf,
                            solver='newton-cg',
                            fit_intercept=False,
                            intercept_scaling=1,
                            max_iter=300,
                            multi_class='multinomial',
                            verbose=0,
                            n_jobs=1)

    lr.fit(state_features, np.concatenate([optimal_action, [0]]))
    action_weights = lr.coef_
    return action_weights

def fit_maximum_likelihood_policy_from_trajectories(state_features,
                                                      state_space,
                                                      action_space,
                                                      trajectories,
                                                      policy,
                                                      initial_parameter,
                                                      max_iter=100,
                                                      learning_rate=0.01):
    n_trajectories = int(trajectories[:, -1].sum())
    n_samples = trajectories.shape[0]
    n_states, n_actions = len(state_space), len(action_space)
    indexes = []
    for i in range(n_samples):
        s = np.argwhere(state_space == trajectories[i, 0])
        a = np.argwhere(action_space == trajectories[i, 1])
        indexes.append(s * n_actions + a)

    parameter = initial_parameter
    ite = 0
    i = 0
    while ite < max_iter:
        ite += 1
        policy.set_parameter(parameter, build_hessian=False)
        G = policy.gradient_log()

        #Gradient computation
        gradient = 0.
        while trajectories[i, -1] == 0:
            gradient += G[indexes[i]]
            i += 1
        gradient += G[indexes[i]]
        gradient /= -n_trajectories
        gradient = gradient.ravel()[:, np.newaxis]
        i = (i + 1) % n_samples

        parameter = parameter - learning_rate * gradient

    policy.set_parameter(parameter)
    return policy

def fit_maximum_likelihood_policy_from_expert_policy(state_features,
                                                      state_space,
                                                      action_space,
                                                      expert_policy,
                                                      policy,
                                                      initial_parameter,
                                                      max_iter=100,
                                                      learning_rate=0.01):
    expert_pi = policy.pi.ravel()[:, np.newaxis]
    n_states, n_actions = len(state_space), len(action_space)

    parameter = initial_parameter
    ite = 0
    while ite < max_iter:
        ite += 1

        policy.set_parameter(parameter, build_hessian=False)
        G = policy.gradient_log()

        # Gradient computation
        gradient = -1. / n_states * (expert_pi * G).sum(axis=0)
        gradient = gradient.ravel()[:, np.newaxis]
        print(gradient)
        parameter = parameter - learning_rate * gradient

    policy.set_parameter(parameter)
    return policy

def estimate(features, target, scorer, ks):
    error = []
    target_hat = []
    for k in ks:
        X = la2.range(features[:, :k])
        y_hat, _, _, _, = la2.lsq(X, target)
        error.append(scorer.score(target, y_hat))
        target_hat.append(y_hat)
    return target_hat, error

class Scorer(object):

    def __init__(self,
                 weights,
                 p=2):
        self.weights = weights
        self.p = p

    def score(self,
              actual,
              predicted):

        return self.norm(actual - predicted) / self.norm(actual)

    def norm(self, vector):
        weighted_vector = vector * np.power(self.weights, 1. / self.p)
        return la.norm(weighted_vector, self.p)

    def __str__(self):
        return '||.||%s weighted' % self.p

class RangeScaler(object):

    def __init__(self, copy=True):
        self.copy = copy

    def fit_transform(self, X):
        if self.copy:
            self.X = np.copy(X)
        else:
            self.X = X

        _max, _min = self.X.max(axis=0), self.X.min(axis=0)
        self.X = self.X / (_max - _min)
        return self.X

if __name__ == '__main__':

    parser = argparse.ArgumentParser()
    parser.add_argument('--epsilon', type=float, default=0.)
    parser.add_argument('--episodes', type=int, default=100)

    args = parser.parse_args()
    epsilon = args.epsilon
    n_episodes = args.episodes

    plot = True
    plot_gradient = True
    plot_hessians = True

    tol = 1e-24
    mdp = TaxiEnv()
    mdp.horizon = 100

    mdp_wrap = DiscreteMdpWrapper(mdp, episodic=True)
    n_states, n_actions = mdp_wrap.nS, mdp_wrap.nA

    print('Computing expert deterministic policy...')
    expert_deterministic_policy = TaxiEnvPolicy()
    expert_deterministic_pi = expert_deterministic_policy.pi

    print('Building state features...')
    state_features = build_state_features(mdp, binary=True)
    n_parameters = state_features.shape[1]

    print('Fitting eps-boltz expert policy...')
    action_weights = fit_maximum_likelihood_boltzmann_policy(state_features,
                     expert_deterministic_policy.pi.argmax(axis=1))
    expert_policy = EpsilonGreedyBoltzmannPolicy(epsilon, state_features,
                                                 action_weights)
    d_kl_det_expert = kullback_leibler_divergence(
        expert_deterministic_policy.pi, expert_policy.pi[:n_states - 1])
    print('KL-divergence expert deterministic - expert eps-boltz %s' % d_kl_det_expert)

    print('Collecting %s trajectories with expert policy...' % n_episodes)
    trajectories_ex = evaluation.collect_episodes(mdp, expert_policy, n_episodes)
    n_samples_ex = trajectories_ex.shape[0]
    print('Dataset made of %s samples' % n_samples_ex)

    action_weights = np.zeros((n_actions, n_parameters))
    ml_policy = BoltzmannPolicy(state_features, action_weights)
    print('Fitting Maximum Likelihood eps-boltz policy from trajectories...')
    ml_policy = fit_maximum_likelihood_policy_from_trajectories(state_features,
                                                    mdp_wrap.state_space,
                                                    mdp_wrap.action_space,
                                                    trajectories_ex,
                                                    ml_policy,
                                                    action_weights.ravel()[:, np.newaxis],
                                                    max_iter=1,
                                                    learning_rate=1000.)
    d_kl_det_ml = kullback_leibler_divergence(expert_deterministic_policy.pi,
                                              ml_policy.pi[:n_states - 1])
    print('KL-divergence expert deterministic - maximum likelihood %s' % d_kl_det_ml)

    print('Collecting %s trajectories with ML policy...' % n_episodes)
    trajectories_ml = evaluation.collect_episodes(mdp, ml_policy, 1000)
    n_samples_ml = trajectories_ml.shape[0]
    print('Dataset made of %s samples' % n_samples_ml)

    estimator_ml = DiscreteEnvSampleEstimator(trajectories_ml,
                               mdp_wrap.gamma,
                               mdp_wrap.state_space,
                               mdp_wrap.action_space,
                               mdp_wrap.horizon)

    saveme_bc = np.zeros(2, dtype=object)
    saveme_bc[0] = ml_policy.pi
    saveme_bc[1] = estimator_ml.get_J()

    estimator_ex = DiscreteEnvSampleEstimator(trajectories_ex,
                               mdp_wrap.gamma,
                               mdp_wrap.state_space,
                               mdp_wrap.action_space,
                               mdp_wrap.horizon)

    print('J ML policy %s' % estimator_ml.get_J())
    print('J expert policy %s' % estimator_ex.get_J())

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

    trajectories_random = evaluation.collect_episodes(mdp, n_episodes=n_episodes)

    from reward_space.inverse_reinforcement_learning.reirl import RelativeEntropyIRL

    re_state = RelativeEntropyIRL(state_features,
                                 trajectories_ex,
                                 trajectories_random,
                                 mdp_wrap.gamma,
                                 mdp_wrap.horizon,
                                 n_states,
                                 n_actions,
                                 learning_rate=0.01,
                                 max_iter=100)
    re_reward = re_state.fit()
    re_reward = np.repeat(re_reward, n_actions)
    print('RELATIVE ENTROPY: %s', re_reward)

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

    policy = expert_policy
    mdp_wrap.set_policy(policy.pi2, fix_episodic=False)
    G = policy.gradient_log()

    count_sa_hat = estimator_ex.get_count_sa()
    d_s_hat = estimator_ex.get_d_s_mu()
    d_sa_hat = estimator_ex.get_d_sa_mu()
    d_sa = mdp_wrap.compute_d_sa_mu()
    D = np.diag(d_sa)
    D_hat = np.diag(d_sa_hat)

    mdp_wrap.set_policy(policy.pi2)
    Q = mdp_wrap.compute_Q_function()
    V = mdp_wrap.compute_V_function()
    A = Q - np.repeat(V, n_actions)
    R = mdp_wrap.R

    G_norm = np.sqrt(la.multi_dot([G.T, D_hat, G]).diagonal())
    Q_norm = np.sqrt(la.multi_dot([Q.T, D_hat, Q]))
    GQ_dot = la.multi_dot([G.T, D_hat, Q])
    GQ_cos = GQ_dot / (G_norm * Q_norm + 1e-24)
    GQ_cos_norm_inf = la.norm(GQ_cos, np.inf) #Note: the expert is likely to be suboptimal

    sa_idx = count_sa_hat.nonzero()
    X = np.dot(G[sa_idx].T, np.diag(d_sa_hat[sa_idx]))

    print('Computing ECO-Qs...')
    phi = la2.nullspace(X, criterion='tol')
    print('%s ECO-Qs found' % phi.shape[1])

    print('Computing model-based ECO-Rs')
    Z = np.dot(np.eye(sa_idx[0].shape[0]) - mdp_wrap.gamma * np.dot(estimator_ex.P[sa_idx], policy.pi2[:, sa_idx].squeeze()), phi)
    psi_mb = la2.range(Z)
    print('%s model-based ECO-Rs found' % psi_mb.shape[1])

    print('Computing model-free ECO-Rs')
    pi_tilde = np.repeat(policy.pi2, n_actions, axis=0)
    Y = np.dot(np.eye(sa_idx[0].shape[0]) - pi_tilde[sa_idx][:, sa_idx].squeeze(), phi)
    psi = la2.range(Y)
    print('%s model-free ECO-Rs found' % psi.shape[1])

    psi_padded = np.zeros((n_states * n_actions, psi.shape[1]))
    psi_padded_mb = np.zeros((n_states * n_actions, psi_mb.shape[1]))
    for i in range(psi.shape[0]):
        psi_padded[sa_idx[0][i], :] = psi[i, :]
        psi_padded_mb[sa_idx[0][i], :] = psi_mb[i, :]

    non_visited = np.setdiff1d(np.arange(psi_padded.shape[0]), sa_idx[0])
    for j in range(psi_padded.shape[1]):
        _min = min(psi_padded[:, j])
        _max = max(psi_padded[:, j])
        if _min == _max:
            psi_padded[non_visited, j] = -1
        else:
            psi_padded[non_visited, j] = min(psi_padded[:, j])

    for j in range(psi_padded_mb.shape[1]):
        _min = min(psi_padded_mb[:, j])
        _max = max(psi_padded_mb[:, j])
        if _min == _max:
            psi_padded_mb[non_visited, j] = -1
        else:
            psi_padded_mb[non_visited, j] = min(psi_padded_mb[:, j])

    del X
    del Y
    del Z

    # --------------------------------------------------------------------------P
    # Standard IRL algorithms on natural features
    from reward_space.inverse_reinforcement_learning.lpal import LPAL
    from reward_space.inverse_reinforcement_learning.maximum_entropy_irl import MaximumEntropyIRL

    # Standard features
    state_action_features = np.repeat(state_features, n_actions, axis=0)
    state_action_features = np.hstack([state_action_features, np.tile(np.eye(n_actions), (n_states, 1))])

    rs = RangeScaler()
    scaled_psi_padded = rs.fit_transform(psi_padded)
    scaled_psi_padded_mb = rs.fit_transform(psi_padded_mb)

    # LPAL
    lpal_policies = []
    lpal = LPAL(state_action_features,
                trajectories_ex,
                estimator_ex.get_P(),
                estimator_ex.get_mu(),
                mdp_wrap.gamma,
                mdp_wrap.horizon)

    lpal_policies.append(lpal.fit())

    lpal = LPAL(scaled_psi_padded,
                trajectories_ex,
                estimator_ex.get_P(),
                estimator_ex.get_mu(),
                mdp_wrap.gamma,
                mdp_wrap.horizon)

    lpal_policies.append(lpal.fit())

    lpal = LPAL(scaled_psi_padded_mb,
                trajectories_ex,
                estimator_ex.get_P(),
                estimator_ex.get_mu(),
                mdp_wrap.gamma,
                mdp_wrap.horizon)

    lpal_policies.append(lpal.fit())

    from policy_old import TabularPolicy
    lpal_tab_policies = map(TabularPolicy, lpal_policies)
    lpal_returns = []
    lpal_labels = ['LPAL natural features', 'LPAL ECO-R model free', 'LPAL ECO-R model based']

    print('Collecting %s trajectories with LPAL policy...' % 100)
    for lpal_tab_policy in lpal_tab_policies:
        trajectories_lpal = evaluation.collect_episodes(mdp, lpal_tab_policy, 100)
        estimator_lpal = DiscreteEnvSampleEstimator(trajectories_lpal,
                                   mdp_wrap.gamma,
                                   mdp_wrap.state_space,
                                   mdp_wrap.action_space,
                                   mdp_wrap.horizon)

        lpal_returns.append(estimator_lpal.get_J())

    print('J LPAL policy %s' % lpal_returns)

    #Linear IRL
    transition_model = np.zeros((n_states, n_actions, n_states))
    for s in range(n_states):
        for a in range(n_actions):
            for s1 in range(n_states):
                transition_model[s, a, s1] = estimator_ex.P[s * n_actions + a, s1]

    #Maximum entropy natural features
    me_state = MaximumEntropyIRL(state_features,
                                 trajectories_ex,
                                 transition_model,
                                 mdp_wrap.mu,
                                 mdp_wrap.gamma,
                                 mdp_wrap.horizon,
                                 learning_rate=0.01,
                                 max_iter=100)
    me_reward = me_state.fit()
    me_reward = np.repeat(me_reward, n_actions)

    # Maximum entropy natural features mf
    eco_state_features_mf = np.dot(mdp_wrap.PI, psi_padded)
    eco_state_features_mb = np.dot(mdp_wrap.PI, psi_padded_mb)
    rs = RangeScaler()
    eco_state_features_mf = rs.fit_transform(eco_state_features_mf)
    eco_state_features_mb = rs.fit_transform(eco_state_features_mb)

    me_state = MaximumEntropyIRL(eco_state_features_mf,
                                 trajectories_ex,
                                 transition_model,
                                 mdp_wrap.mu,
                                 mdp_wrap.gamma,
                                 mdp_wrap.horizon,
                                 learning_rate=0.01,
                                 max_iter=100)
    me_eco_mf = me_state.fit()
    me_eco_mf = np.repeat(me_eco_mf, n_actions)

    # Maximum entropy natural features mb

    me_state = MaximumEntropyIRL(eco_state_features_mb,
                                 trajectories_ex,
                                 transition_model,
                                 mdp_wrap.mu,
                                 mdp_wrap.gamma,
                                 mdp_wrap.horizon,
                                 learning_rate=0.01,
                                 max_iter=100)
    me_eco_mb = me_state.fit()
    me_eco_mb = np.repeat(me_eco_mb, n_actions)

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

    names = []
    basis_functions = []
    gradients = []
    hessians = []
    H = policy.hessian_log()

    # Hessian estimation - model free

    print('Estimating hessians model free...')

    hessian_hat = estimate_hessian(trajectories_ex, n_episodes, G, H, psi_padded, \
                                   mdp_wrap.state_space, mdp_wrap.action_space, mdp_wrap.gamma, mdp_wrap.horizon)

    eigval_hat, _ = la.eigh(hessian_hat)
    eigmax_hat, eigmin_hat = eigval_hat[:, -1], eigval_hat[:, 0]
    trace_hat = np.trace(hessian_hat, axis1=1, axis2=2)

    #Heuristic for negative semidefinite
    neg_idx = np.argwhere(eigmax_hat < -eigmin_hat / 10).ravel()
    hessian_hat_neg = hessian_hat[neg_idx]

    optimizer = HeuristicOptimizerNegativeDefinite(hessian_hat_neg)
    w = optimizer.fit(skip_check=True)
    eco_r = np.dot(psi_padded[:, neg_idx], w)

    # ---------------------------------------------------------------------------
    # Hessian estimation - model based

    print('Estimating hessians model based...')

    hessian_hat = estimate_hessian(trajectories_ex, n_episodes, G, H, psi_padded_mb, \
                                   mdp_wrap.state_space, mdp_wrap.action_space, mdp_wrap.gamma, mdp_wrap.horizon)

    eigval_hat, _ = la.eigh(hessian_hat)
    eigmax_hat, eigmin_hat = eigval_hat[:, -1], eigval_hat[:, 0]
    trace_hat = np.trace(hessian_hat, axis1=1, axis2=2)

    #Heuristic for negative semidefinite
    neg_idx = np.argwhere(eigmax_hat < -eigmin_hat / 10).ravel()
    hessian_hat_neg = hessian_hat[neg_idx]

    optimizer = HeuristicOptimizerNegativeDefinite(hessian_hat_neg)
    w = optimizer.fit(skip_check=True)
    eco_r_mb = np.dot(psi_padded_mb[:, neg_idx], w)

    # ---------------------------------------------------------------------------
    # Hessian estimation - natural

    print('Estimating hessians model based...')
    natural = la2.range(state_action_features)
    hessian_hat = estimate_hessian(trajectories_ex, n_episodes, G, H, natural, \
                                   mdp_wrap.state_space, mdp_wrap.action_space, mdp_wrap.gamma, mdp_wrap.horizon)

    eigval_hat, _ = la.eigh(hessian_hat)
    eigmax_hat, eigmin_hat = eigval_hat[:, -1], eigval_hat[:, 0]
    trace_hat = np.trace(hessian_hat, axis1=1, axis2=2)

    #Heuristic for negative semidefinite
    neg_idx = np.argwhere(eigmax_hat < -eigmin_hat).ravel()
    hessian_hat_neg = hessian_hat[neg_idx]

    optimizer = HeuristicOptimizerNegativeDefinite(hessian_hat_neg)
    w = optimizer.fit(skip_check=True)
    natural_r = np.dot(state_action_features[:, neg_idx], w)

    # ---------------------------------------------------------------------------
    # Build feature sets
    names.append('RE-IRL')
    basis_functions.append(re_reward)
    names.append('ME-IRL')
    basis_functions.append(me_reward)
    names.append('Hessian model_free ECOR')
    basis_functions.append(eco_r)
    names.append('Hessian model_based ECOR')
    basis_functions.append(eco_r_mb)
    names.append('Hessian natural features')
    basis_functions.append(natural_r)

    '''
    #Gradient and hessian estimation
    '''

    # Rescale rewards into to have difference between max and min equal to 1
    scaler = RangeScaler()

    scaled_basis_functions = []
    for bf in basis_functions:
        sbf = scaler.fit_transform(bf[:, np.newaxis]).ravel()
        scaled_basis_functions.append(sbf)

    gradients, hessians, gradient_norms2, gradient_normsinf, eigvals, traces, eigvals_max = [], [], [], [], [], [], []
    print('Estimating gradient and hessians...')
    for sbf in scaled_basis_functions:
        gradient = estimate_gradient(trajectories_ex, n_episodes,G, sbf, \
                                mdp_wrap.state_space, mdp_wrap.action_space, mdp_wrap.gamma, mdp_wrap.horizon)[0]
        hessian = estimate_hessian(trajectories_ex, n_episodes, G, H, sbf, \
                              mdp_wrap.state_space, mdp_wrap.action_space, mdp_wrap.gamma, mdp_wrap.horizon)[0]
        gradients.append(gradient)
        hessians.append(hessian)
        eigval, _ = la.eigh(hessian)
        gradient_norms2.append(la.norm(gradient, 2))
        gradient_normsinf.append(la.norm(gradient, np.inf))
        eigvals_max.append(eigval[-1])
        eigvals.append(eigval)
        traces.append(np.trace(hessian))

    gradients_np = np.array(gradients)
    hessians_np = np.array(hessians)
    gradient_norms2_np = np.array(gradient_norms2)
    gradient_normsinf_np = np.array(gradient_normsinf)
    eigvals_max_np = np.array(eigvals_max)
    eigvals_np = np.array(eigvals)
    traces_np = np.array(traces)

    if plot:
        fig, ax = plt.subplots()
        ax.set_xlabel('trace')
        ax.set_ylabel('max eigval')
        fig.suptitle('Hessians')
        ax.scatter(trace_hat, eigmax_hat, color='k', marker='+',
                   label='Estimated hessians')
        for i in range(len(names)):
            ax.plot(traces_np[i], eigvals_max_np[i], marker='o', label=names[i])
        ax.legend(loc='upper right')

        _range = np.arange(len(eigvals_np[0]))
        fig, ax = plt.subplots()
        ax.set_xlabel('index')
        ax.set_ylabel('eigenvalue')
        fig.suptitle('Hessian Eigenvalues')
        for i in range(len(names)):
            ax.plot(_range, eigvals_np[i], marker='+', label=names[i])

        ax.legend(loc='upper right')
        plt.yscale('symlog', linthreshy=1e-6)

    '''
    #REINFORCE training
    '''

    def reward_function(sbf, traj):
        diff = mdp_wrap.horizon - traj.shape[0]
        disc = (1 - mdp_wrap.gamma ** (diff + 1)) / (1 - mdp_wrap.gamma)
        abs_reward = disc * sbf[-n_actions, ]
        rewards = sbf[(traj[:, 0] * n_actions + traj[:, 1]).astype(int)]
        rewards[-1] += abs_reward
        return rewards

    iterations = 1000

    policy = BoltzmannPolicy(state_features, action_weights)
    learner = PolicyGradientLearner(mdp, policy, lrate=0.008, verbose=0,
                                    max_iter_opt=iterations, max_iter_eval=100, tol_opt=-1., tol_eval=0.,
                                    estimator='reinforce',
                                    gradient_updater='adam')

    theta0 = np.zeros((240, 1))

    theta, history = learner.optimize(theta0, return_history=True)

    names = ['Reward'] + names
    histories = [history]
    for i in range(len(scaled_basis_functions)):
        print(names[i])
        sbf = scaled_basis_functions[i]
        theta, history = learner.optimize(theta0, reward=lambda traj: reward_function(sbf, traj),return_history=True)
        print(np.array(history)[-1, 1])

        histories.append(history)

    histories = np.array(histories)

    t = PrettyTable()
    t.add_column('Basis function', names)
    t.add_column('Final return', histories[:, -1, 1])
    print(t)

    if plot:
        _range = np.arange(iterations+1)
        fig, ax = plt.subplots()
        ax.set_xlabel('average return')
        ax.set_ylabel('iterations')
        fig.suptitle('REINFORCE - Average return')

        ax.plot([0, iterations], [estimator_ex.get_J(), estimator_ex.get_J()], color='k',
                label='Expert')
        for i in range(len(lpal_returns)):
            ax.plot([0, iterations], [lpal_returns[i], lpal_returns[i]],
                label=lpal_labels[i])
        for i in range(len(histories)):
            ax.plot(_range, histories[i, :, 1], marker='+', label=names[i])

        ax.legend(loc='lower right')


# Pen control
# Drawing state
import turtle

turtle = turtle.Turtle()

# Pull the pen down – drawing when moving.
# turtle. pendown()
# turtle. pd()
# turtle. down()
turtle.pd()
print(turtle.pos())

# Pull the pen up – no drawing when moving.
# turtle. penup()
# turtle. pu()
# turtle. up()
turtle.pu()
turtle.fd(100)
print(turtle.pos())
print(turtle.pensize())
# turtle. pensize(width=None)
# turtle. width(width=None)
# Parameters: width – a positive number
# Set the line thickness to width or return it.
# If resizemode is set to “auto” and turtleshape is a polygon, that polygon is drawn with the same line thickness.
#  If no argument is given, the current pensize is returned.

turtle.pensize(20)
turtle.pd()
turtle.fd(100)
print(turtle.pensize())


# -*- coding: utf-8 -*-
# @Time : 2019/10/19 12:59
# @Author : ljf
# @File : train.py

# !/usr/bin/python
import requests
import json
import mysql
import datetime
from urllib.parse import quote

def save(trainData):
    """
    Args:
        planeDate:  保存信息
    """
    path = "./TrainInfo.txt"
    f = open(path, "a+")
    f.write(trainData + "\n")
    f.close()

def TrainInfo(DepartureDate):
    """
    获取直达火车信息
    Args:
        DepartureDate:      时间
    """
    DepartureCityName = input("请输入出发地：")
    ArrivalCityName = input("请输入目的地：")
    # DepartureCityName = "北京"
    # ArrivalCityName = "上海"
    # DepartureDate = "2019-10-20"
    # 分割取年月日，然后加上 2 天
    DepartureDateReturn = str(datetime.date(*map(int, DepartureDate.split('-'))) + datetime.timedelta(2))
    sql1 = "select * from t_train where city_name='%s'" % DepartureCityName
    sql2 = "select * from t_train where city_name='%s'" % ArrivalCityName
    DepartureCity = mysql.mysql_select(sql1)[0][2]
    ArrivalCity = mysql.mysql_select(sql2)[0][2]
    quote1 = quote(DepartureCityName, encoding='gb2312')
    quote2 = quote(ArrivalCityName, encoding='gb2312')

    print(DepartureCityName, ArrivalCityName, DepartureCity, ArrivalCity, DepartureDate, DepartureDateReturn, quote1, quote2)

    url = "https://trains.ctrip.com/TrainBooking/Ajax/SearchListHandler.ashx?Action=getSearchList"
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0",
        "Referer": "https://trains.ctrip.com/TrainBooking/Search.aspx?from=()&to=()&day=()&fromCn=()&toCn=()".format(DepartureCity, ArrivalCity, DepartureDate, quote1, quote2),
        "Connection": "close",
    }
    request_payload = {
        "IsBus": False, "Filter": "0", "Catalog": "", "IsGaoTie": False, "IsDongChe": False, "CatalogName": "",
        "DepartureCity": DepartureCity, "ArrivalCity": ArrivalCity,
        "HubCity": "",
        "DepartureCityName": DepartureCityName, "ArrivalCityName": ArrivalCityName,
        "DepartureDate": DepartureDate, "DepartureDateReturn": DepartureDateReturn,
        "ArrivalDate": "", "TrainNumber": ""
    }
    data = {
        'value': json.dumps(request_payload)
    }
    res = requests.post(url, headers=headers, data=data)
    # print(res.text)
    TrainItemsList = json.loads(res.text)['TrainItemsList']
    for trainItems in TrainItemsList:
        trainData = [
            DepartureDate,
            trainItems['TrainName'],
            trainItems['StartStationName'],
            trainItems['EndStationName'],
            trainItems['StratTime'],
            trainItems['EndTime'],
            trainItems['TakeTime'],
            trainItems['TakeDays'],
        ]
        print(trainData)
        save(str(trainData))

def start():
    DepartureDate = input("请输入时间（格式2008-08-08）：")
    TrainInfo(DepartureDate)

if __name__ == "__main__":
    start()


import heapq

class Solution:
    # def findKthLargest(self, nums: List[int], k: int) -> int:
    #
        #         heap = []
        #         heapq.heapify(heap)

        #         for num in nums:

        #             if len(heap) >= k:
        #                 heapq.heappushpop(heap, num)
        #             else:
        #                 heapq.heappush(heap, num)

        #         return heapq.heappop(heap)

    def partition(self, nums, left, right):

        pivot = nums[right]
        index = left

        for j in range(left, right):

            if nums[j] < pivot:
                nums[j], nums[index] = nums[index], nums[j]
                index += 1

        nums[index], nums[right] = nums[right], nums[index]

        return index

    def quick_sort(self, nums, start, end):

        if start > end:
            return num

        pivot_index = self.partition(nums, start, end)

        if pivot_index == self.k:
            return nums[pivot_index]

        if pivot_index < self.k:
            return self.quick_sort(nums, pivot_index + 1, end)

        elif pivot_index > self.k:
            return self.quick_sort(nums, start, pivot_index - 1)

    def findKthLargest(self, nums: List[int], k: int) -> int:

        self.k = len(nums) - k
        return self.quick_sort(nums, 0, len(nums) - 1)


"""
Module that defines the `KubernetesSession` class.
"""

import logging
import os
import random
import secrets
import time

import kubernetes

from .session import Session

logger = logging.getLogger(__name__)

api_client = None
if "KUBERNETES_SERVICE_HOST" in os.environ:
    # Running in a pod on the cluster so load the cluster's config
    kubernetes.config.load_incluster_config()
    api_client = kubernetes.client.CoreV1Api()
else:
    # Running outside of a cluster, probably during development
    # so only connect to a Minikube cluster to avoid polluting
    # a production cluster accidentally.
    # Do not raise an exception so that devs without Minikube
    # installed can at least import this file. Just warn.
    try:
        api_client = kubernetes.config.new_client_from_config(context="minikube")
    except kubernetes.config.config_exception.ConfigException as exc:
        logger.warning(exc)

class KubernetesSession(Session):
    """
    Runs a session as a pod in a Kubernetes cluster.

    This class in intended for scalably provisioning
    untrusted sessions. It uses the K8s API to create
    a new pod inside a cluster, possible the same cluster
    this process is in.
    """

    api_instance = kubernetes.client.CoreV1Api(api_client) if api_client else None
    namespace = "default"

    def __init__(self):
        """Create a session."""
        super().__init__()
        self.name = "session-" + secrets.token_hex(16)
        self.port = random.randint(1024, 65535)

        self.api_instance.create_namespaced_pod(
            body={
                "apiVersion": "v1",
                "kind": "Pod",
                "metadata": {"name": self.name},
                "spec": {
                    "containers": [
                        {
                            "name": "executa",
                            "image": "stencila/executa",
                            "args": [
                                "executa",
                                "serve",
                                "--debug",
                                "--{}=0.0.0.0:{}".format(self.protocol, self.port),
                            ],
                        }
                    ],
                    "restartPolicy": "Never",
                },
            },
            namespace=self.namespace,
        )

        while True:
            pod = self.api_instance.read_namespaced_pod(
                name=self.name, namespace=self.namespace
            )
            if pod.status.phase != "Pending":
                break
            time.sleep(0.1)

        self.ip = pod.status.pod_ip

    def start(self):
        """Start the session."""
        return

        response = kubernetes.stream.stream(
            self.api_instance.connect_get_namespaced_pod_attach,
            name=self.name,
            namespace=self.namespace,
            container="executa",
            stderr=True,
            stdout=True,
            stdin=False,
            tty=False,
        )
        while response.is_open():
            response.update(timeout=1)
            stdout = response.readline_stdout(timeout=3)
            print(stdout)

    def stop(self):
        """Stop the session."""
        super().stop()
        if self.name:
            self.api_instance.delete_namespaced_pod(
                name=self.name, namespace=self.namespace
            )
            self.name = None


xCoord = random(0, 200)
yCoord = random (0, 200)
xSpeed = 6
ySpeed = 6
ellipseSize = 40
def setup():
    size(600, 800)

def draw():
    background(0)
    global xCoord, yCoord, xSpeed, ySpeed, ellipseSize
    leftBoundry = ellipseSize / 2
    rightBoundry = 600 - ellipseSize / 2
    topBoundry = ellipseSize / 2
    bottomBoundry = 800 - ellipseSize /2
    xCoord += xSpeed
    yCoord += ySpeed
    if xCoord >= rightBoundry or xCoord<= leftBoundry:
        xSpeed = -xSpeed
    if yCoord >= bottomBoundry or yCoord<= topBoundry:
        ySpeed = -ySpeed
    fill(0, 255, 255)
    ellipse(xCoord, yCoord, ellipseSize, ellipseSize)


import socket
import sys
import struct
import time

# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Connect the socket to the port where the server is listening
server_address = ('localhost', 8080)
print('connecting to %s port %s' % server_address, file=sys.stderr)
sock.connect(server_address)

try:
    # Send data

    while True:
        time.sleep(8)
        data = sock.recv(16, socket.MSG_WAITALL)
        print(sys.stderr, file=sys.stderr)
        if not data:
            print('no more data, received', type(data), file=sys.stderr)
            break
        data = struct.unpack('i' * 4, data)
        print('received "', data, file=sys.stderr)
finally:
    print('closing socket', file=sys.stderr)
    sock.close()


def read_data():
    import numpy as np
    import csv
    import sys
    import os

    # Ensure correct directory
    script_dir = os.path.dirname(__file__) #<-- absolute dir the script is in
    rel_path = "data/train(1).csv"
    abs_file_path = os.path.join(script_dir, rel_path)

    # Make a list for every element
    content = [[] for x in range(12)]
    np.array_1 = [[] for x in range(12)]

    with open(abs_file_path,newline='') as csvfile:
        contreader = csv.reader(csvfile,delimiter= ',')
        for row in contreader:
            i = 0
            for element in row:
                np.array_1[i].append(element)
                i = i + 1

    return np.array_1


from NumericalMethods.util.sympy_init import *

def secant(function, section, accuracy_order=None, iterations=None, level_of_details=3):
    """
    Решение трансцендентного уравнения методом хорд

    Args:
        function (str): уравнение в виде строки
        section (tuple): отрезок, на котором будет произведен поиск
        accuracy_order (int): необходимая точность
        iterations (int): необходимое количество итераций
        level_of_details (int): необходимы уровень детализации решения

    Yields:
        dict: информация о текущем шаге решения
    """
    def draw_secant():
        return (left_edge * function(right_edge) - right_edge * function(left_edge)) / \
               (function(right_edge) - function(left_edge))

    def stop_iteration():
        if iteration_counter > (100 if iterations is None else iterations * 10):
            raise IndexError(f"\nОбнаружено нарушение работы функции. Работа аварийно остановлена. Сводка:\n"
                             f"abs(f(x)): {abs(function(suppression))} < {10 ** (-accuracy_order)} "
                             f"-> {abs(function(suppression)) < 10 ** (-accuracy_order)}\n"
                             f"abs(old_x - x): {abs(old_c - suppression)} < {10 ** (-accuracy_order)} -> "
                             f"{abs(function(suppression)) < 10 ** (-accuracy_order)}\n"
                             f"i: {iteration_counter} >= {iterations} -> "
                             f"{iteration_counter >= 0 if iterations is None else iterations}\n"
                             f"Для нормальной остановки требуется, чтобы все значения были True")
        return all([
            True if accuracy_order is None else abs(function(suppression)) < 10 ** (-accuracy_order),
            True if accuracy_order is None else abs(old_c - suppression) < 10 ** (-accuracy_order),
            True if iterations is None else iteration_counter >= iterations,
        ])

    if accuracy_order is None and iterations is None:
        accuracy_order = 8

    left_edge = min(section)
    right_edge = max(section)
    function = parse_expr(function)
    answer = {}
    if level_of_details < 3:
        yield {
            'Этап': 'Получены значения',
            'Отрезок': (left_edge, right_edge),
            'Введенная функция': function,
            'Красиво введенная функция': pretty(function, use_unicode=False)
        }
    function = lambdify(x, function)
    suppression = None
    f_a = function(left_edge)
    f_c = None
    f_b = function(right_edge)
    iteration_counter = 1
    old_c = 0
    while True:
        if level_of_details < 3:
            yield {
                'Номер итерации': iteration_counter,
                'a': left_edge,
                'c': suppression,
                'b': right_edge,
                'f(a)': f_a,
                'f(c)': f_c,
                'f(b)': f_b
            }
        suppression = draw_secant()
        f_c = function(suppression)
        if level_of_details < 3:
            yield {
                'Номер итерации': iteration_counter,
                'a': None,
                'c': suppression,
                'b': None,
                'f(a)': None,
                'f(c)': f_c,
                'f(b)': None
            }
        if stop_iteration():
            if level_of_details < 4:
                answer.update({'Решение': suppression})
            if level_of_details < 3:
                answer.update({'f(c)': f_c})
            yield answer
            break
        old_c = suppression
        if function(left_edge) * function(suppression) > 0:
            left_edge = suppression
            suppression = None
        else:
            right_edge = suppression
            suppression = None
        f_a = function(left_edge)
        f_c = None
        f_b = function(right_edge)
        iteration_counter += 1


import sys
import shutil
import fileinput
import os
import glob
import os.path

def deletePrecompiledHexFiles():
    fileList = glob.glob('./precompiled/ha2.5.1*/ha*.hex', recursive=True)
    for filePath in fileList:
        try:
            os.remove(filePath)
        except:
            print("Error while deleting file : ", filePath)

def deleteFiles():
    fileList = glob.glob('./hamcp2515.c')
    fileList.extend(glob.glob('./mv.h'))
    fileList.extend(glob.glob('./haam.h'))
    for filePath in fileList:
        try:
            os.remove(filePath)
        except:
            print("Error while deleting file : ", filePath)

def copySourceFiles(mv,hamcp2515,haam):
    shutil.copy(os.path.join(os.getcwd(),"files",mv), os.path.join(os.getcwd(),"mv.h"))
    shutil.copy(os.path.join(os.getcwd(),"files",hamcp2515), os.path.join(os.getcwd(),"hamcp2515.c"))
    shutil.copy(os.path.join(os.getcwd(),"files",haam), os.path.join(os.getcwd(),"haam.h"))

def buildHexFile():
    os.system("make all")

def copyHexFile(destinationPath):
    if not os.path.exists(os.path.join("../precompiled",destinationPath)):
        os.makedirs(os.path.join("../precompiled",destinationPath))
    shutil.copy(os.path.join(os.getcwd(),"ha.hex"), os.path.join("../precompiled",destinationPath,"ha.hex"))

def cleanUp():
    os.system("make clean")

def concatFlashAndBootloader(destinationPath):
    for l in range(4,6):
        for i in range(16):
            id = hex(int(i))[2:].zfill(1)

            f1 = open(destinationPath + "/ha.hex")
            f1_contents = f1.read()
            f1_without_last_line = f1_contents[:f1_contents.rfind(':00000001FF\n')]
            f1.close()

            f2 = open("Bootloader/HAPBootLoader-2893" + str(l) + id + ".hex")
            f2_contents = f2.read()
            f2.close()

            f3 = open(destinationPath + "/" + "ha_withBootLoader-2893" + str(l) + id + ".hex", "w") # open in `w` mode to write
            f3.write(f1_without_last_line + f2_contents) # concatenate the contents
            f3.close()

def deleteHexFiles():
    fileList = glob.glob('./ha2.5.1*/ha.hex', recursive=True)
    for filePath in fileList:
        try:
            os.remove(filePath)
        except:
            print("Error while deleting file : ", filePath)

haam_List = ["4shutter","8shutter"]
hamcp2515_List = ["10kBit","125kBit"]
mv_List = ["DimmerNoSerialCan","DimmerSerialCan","DimmerSerialNoCan","NoDimmerNoSerialCan","NoDimmerSerialCan","NoDimmerSerialNoCan"]

deletePrecompiledHexFiles()

os.chdir("./2.5.11/")

for m in range(len(haam_List)):
    for n in range(len(hamcp2515_List)):
        for o in range(len(mv_List)):
            copySourceFiles(''.join(["mv_",mv_List[o],".h"]),''.join(["hamcp2515_",hamcp2515_List[n],".c"]),''.join(["haam_",haam_List[m],".h"]))
            buildHexFile()
            copyHexFile(''.join(["ha2.5.11_",mv_List[o],"_",hamcp2515_List[n],"_",haam_List[m]]))
            cleanUp()
            deleteFiles()

os.chdir("../precompiled/")

for m in range(len(haam_List)):
    for n in range(len(hamcp2515_List)):
        for o in range(len(mv_List)):
            concatFlashAndBootloader(''.join(["ha2.5.11_",mv_List[o],"_",hamcp2515_List[n],"_",haam_List[m]]))

os.chdir("../2.5.13/")

for m in range(len(haam_List)):
    for n in range(len(hamcp2515_List)):
        for o in range(len(mv_List)):
            copySourceFiles(''.join(["mv_",mv_List[o],".h"]),''.join(["hamcp2515_",hamcp2515_List[n],".c"]),''.join(["haam_",haam_List[m],".h"]))
            buildHexFile()
            copyHexFile(''.join(["ha2.5.13_",mv_List[o],"_",hamcp2515_List[n],"_",haam_List[m]]))
            cleanUp()
            deleteFiles()

os.chdir("../precompiled/")

for m in range(len(haam_List)):
    for n in range(len(hamcp2515_List)):
        for o in range(len(mv_List)):
            concatFlashAndBootloader(''.join(["ha2.5.13_",mv_List[o],"_",hamcp2515_List[n],"_",haam_List[m]]))

os.chdir("../")

deleteHexFiles()


import os
from collections import OrderedDict
try:
    from torch.utils.tensorboard import SummaryWriter
except:
    print('WARNING: You are using tensorboardX instead sis you have a too old pytorch version.')
    from tensorboardX import SummaryWriter

class TensorboardWriter:
    def __init__(self, directory, loader_names):
        self.directory = directory
        self.writer = OrderedDict({name: SummaryWriter(os.path.join(self.directory, name)) for name in loader_names})

    def write_info(self, module_name, script_name, description):
        tb_info_writer = SummaryWriter(os.path.join(self.directory, 'info'))
        tb_info_writer.add_text('Modulet_name', module_name)
        tb_info_writer.add_text('Script_name', script_name)
        tb_info_writer.add_text('Description', description)
        tb_info_writer.close()

    def write_epoch(self, stats: OrderedDict, epoch: int, ind=-1):
        for loader_name, loader_stats in stats.items():
            if loader_stats is None:
                continue
            for var_name, val in loader_stats.items():
                if hasattr(val, 'history') and getattr(val, 'has_new_data', True):
                    self.writer[loader_name].add_scalar(var_name, val.history[ind], epoch)


##Multi-thread client creator
# Author: Zex Li <top_zlynch@yahoo.com>
#
# \node g++ -std=c++11 -o epoll_server epoll_server.cpp
# \note ulimit -n 65536
# \note ulimit -s unlimited
import socket, threading
from datetime import datetime

MAX_RECV_SZ = 1024
TOTAL_TASK_NR = 30000
addr = '192.168.1.185'
port = 58713

mutex = threading.Lock()

def request_task():
    sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
    sock.connect((addr, port))
    sock.send('%s: %s' % (threading.current_thread().name, datetime.now()))
    #mutex.acquire()
    rdbuf = sock.recv(MAX_RECV_SZ)
    print('[%s]' % rdbuf)
    #mutex.release()
    sock.close()

def start_request():
    tasks = []

    [tasks.append(threading.Thread(target=request_task)) for n in range(TOTAL_TASK_NR)]
    [task.start() for task in tasks]

start_request()


import pandas as pd
import os
pd.set_option('display.max_rows',1000)
pd.set_option('display.max_columns',1000)
pd.set_option('display.width', 1000)
pd.set_option('display.max_colwidth',1000)

savePath=r"H:\@chengfu\车场数据\later\new\exit"

def getNumber(str1):
    index=1
    haha=str1.split(":")
    number=int(haha[-2])
    shizhong=haha[0].split(" ")[-1]
    if number<30:
        index=2*int(shizhong)
    else:
        index=2*int(shizhong)+1
    return str1[:10]+" "+str(index)

str1="2020-12-04 11:59:34"

# print(getNumber(str1))

pd_csv=pd.read_excel(r"H:\@chengfu\车场数据\later\20210201-20210207车场数据\2021-02-01出车.xlsx",usecols=["park_id","time"])
newData=group = pd_csv.groupby(["park_id"],as_index=False)

DataLen=len(list(newData))
DataLen=1
print(len(list(newData)))
sum=0
for i in range(len(list(newData))):
    myData=list(newData)[i][1]
    sum+=len(myData)

# myData["time_half"]=myData["time"].apply(lambda  x:x[:13])
    myData["date_day"]=myData["time"].apply(lambda  x:x[:10])
    myData["Hour"]=myData["time"].apply(lambda  x:int(x[10:13]))
    myData=myData.drop(["time"],axis=1)
    print(myData)

    parkId=myData["park_id"]
    print(str(myData["park_id"].values[0]))
    print(myData)
    csvName = str(myData["park_id"].values[0])+".csv"
    csvPath=os.path.join(savePath,csvName)
    myData.to_csv(csvPath,mode='a',header=False)
print(sum)

# group = myData.groupby(["date_day","Hour"],as_index=False).count()
# print(group)
# usrTime=group["time"]
# groupTime=group["time_half"]
# array=group.values
# # print(list(groupTime))
#
# clockTime=[int(x.split(" ")[-1]) for x in list(groupTime) ]
# print(clockTime)
# print(list(usrTime))
# #
#
# newDict=dict(zip(list(groupTime),list(usrTime)))
# print(newDict)
# print(group)


from bs4 import BeautifulSoup
from tornado import ioloop, httpclient
from random import randint
import requests
import xml.etree.ElementTree as ET
import re
import json
import os

# optimise speed and add option to fix invalid data
# create a server running this that constantly keeps track of products and price changes
# store data in a database that the website can query using php or maybe js and API/Widget
# rate limit and comply with robots.txt
# fix time outs and 404's

file_name = "data.json"
directory = "data/"
i = 0
product_ids = []
threads = 2
first = True
last = False
total = 0
counter = 1

def init():
    global file_name,directory
    try:
        os.stat(directory)
    except:
        os.mkdir(directory)
    try:
        with open(directory+file_name, "r") as file:
            pass
    except:
        with open(directory+file_name, "w") as file:
            file.write("")

def get_product_ids():
    global product_ids,total
    url = "https://www.danmurphys.com.au/robots.txt"
    headers = {"User-Agent":"Mozilla 5.0/"}

    robots_text = requests.get(url, headers=headers).text.strip().split("\n")

    for line in robots_text:
        if "Sitemap:" in line and "Products" in line:
            product_sitemap_url = line.split("Sitemap:")[1].strip()

    print(product_sitemap_url)
    product_sitemap = requests.get(product_sitemap_url, headers=headers).text

    print("SiteMap FileSize:",len(product_sitemap.encode('utf-8')))

    with open("product_sitemap.xml", "w") as file:
        file.write(product_sitemap)

    root = ET.fromstring(product_sitemap)

    product_ids = []

    for child in root:
        if "product" in child[0].text:
            product_id = child[0].text.split("/")[-2]
            product_ids.append(product_id.split("DM_")[-1])

    total = len(product_ids)
    print("Products:",total)

    with open("product_ids.txt", "w") as file:
        file.write("\n".join(product_ids))

def get_info():
    global product_ids,threads
    http_client = httpclient.AsyncHTTPClient(force_instance=True,defaults=dict(user_agent="Mozilla/5.0"),max_clients=threads)
    for product_id_new in product_ids:
        global i
        i += 1
        url = "https://api.danmurphys.com.au/apis/ui/Product/"+str(product_id_new)
        http_client.fetch(url.strip(),handle_request_index, method='GET',connect_timeout=10000,request_timeout=10000)
    ioloop.IOLoop.instance().start()

def save_to_json(html,url):
    global file_name,directory,first,last,counter
    json = "\"Products"+str(counter)+"\":["+html+"]" #converts it to a sub json part of the larger data file
    full_path = directory + file_name
    if i == 0:
        last = True
    with open(full_path, "a", encoding="utf-8") as data_json:
        if first:
            data_json.write("{"+json)
            first = False
        elif last:
            data_json.write(","+json+"}")
        else:
            data_json.write(","+json)
    counter += 1

def handle_request_index(response):
    global total
    if response.code == 599:
        print(response.effective_url)
        http_client.fetch(response.effective_url.strip(), handle_request, method='GET',connect_timeout=10000,request_timeout=10000)
    else:
        global i
        i -= 1
        html = response.body.decode('utf-8')
        url = response.effective_url
        time = response.request_time
        percent = 100 - ((i/total)*100)
        percent_str = '{:.2f}'.format(round(percent, 2))+"%"
        print(percent_str,url,time)
        save_to_json(html,url)
        if i == 0:
            ioloop.IOLoop.instance().stop()

init()
get_product_ids()
get_info()


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

''

__author__ = 'Locke Lee'

class Check_branket(object):
	"""docstring for Check_branket"""
	def __init__(self):
		super(Check_branket, self).__init__()

	dic_check = {'}':'{', ']':'[', ')':'('}

	def check(self, str_check):
		stack = [0]
		for char in str_check:
			if char in Check_branket.dic_check:
				if stack[-1] == Check_branket.dic_check[char]:
					stack.pop()
				else:
					return False
			else:
				stack.append(char)
		if stack == [0]:
			return True
		return False

str_input = input("input the brankets\n")

print(Check_branket().check(str_input))


import time
from selenium import webdriver
from selenium.webdriver.common.by import By
chromeOptions = webdriver.ChromeOptions()
chromeOptions.add_experimental_option('useAutomationExtension', False)
driver=webdriver.Chrome(executable_path="D:\Software\Selenium_Python\chromedriver_win32\chromedriver.exe", desired_capabilities = chromeOptions.to_capabilities())
driver.implicitly_wait(5)
driver.get("http://www.newtours.demoaut.com/")
driver.maximize_window()
time.sleep(2)
links = driver.find_elements(By.TAG_NAME,"a")
print(" Number of links present : ",len(links))
for link in links:
    print(link.text)

time.sleep(2)
driver.find_element(By.LINK_TEXT,"REGISTER").click()
time.sleep(2)
driver.quit()


# <-- comments in python are denoted by the pound sign, like this one

import numpy          # we import the array library
from matplotlib import pyplot   # import plotting library

myarray = numpy.linspace(0, 5, 10)
myarray

a = 5
b = 'five'
c = 5.0

type(a)
type(b)
type(c)

for i in range(5):
    print("Hi \n")

for i in range(3):
    for j in range(3):
        print(i, j)

    print("This statement is within the i-loop, but not the j-loop")

myvals = numpy.array([1, 2, 3, 4, 5])
myvals

myvals[0], myvals[4]

print(myvals[0:3])

# Assigning Array Variables

a = numpy.linspace(1, 5, 5)
a

b = a
b

a[2] = 17
a
b

c = a.copy()
a
c


global header_output_path
global source_output_path
header_output_path = "../include/flo/dev/ast.h"
source_output_path = "../source/ast.cpp"

class Field:
    """ Defines a field in a class. """
    def __init__(self, typename, name, constructor=True, init=""):
        self.typename = typename
        self.name = name
        self.constructor = constructor
        self.init = (self.typename + " " + self.name
                     + (" " + init if init else "")
                     + ";")

class ClassDef:
    """ Defines an AST node class. """
    def __init__(self, superclass, name, fields, doc, abstract=False):
        self.superclass = superclass
        self.name = name
        self.fields = fields
        self.doc = doc
        self.abstract = abstract
        self.branch = self.abstract and self.superclass

        if not self.abstract and self.superclass:
            self.ptrName = superclass.name + "Ptr"

        self.constructor = ""
        for field in filter(lambda f: f.constructor, self.fields):
            self.constructor += field.typename + " " + field.name + ", "
        self.constructor = self.constructor[:-2]

base = ClassDef(None, "AstNode", [], "Base for AST nodes.", True)

stmt = ClassDef(base, "Stmt",
                [],
                "Base for statement nodes.",
                True)

expr = ClassDef(base, "Expr",
                [],
                "Base for expression nodes.",
                True)

nodes = [
    ClassDef(stmt, "ExprStmt",
             [Field("ExprPtr", "expression")],
             "Statement containing a single expression."
             ),
    ClassDef(stmt, "OutStmt",
             [Field("ExprPtr", "expression")],
             "Print the result of an expression."
             ),

    ClassDef(expr, "BinaryExpr",
             [Field("ExprPtr", "left"), Field("Token", "op"), Field("ExprPtr", "right")],
             "Expression which operates on two other expressions."
             ),
    ClassDef(expr, "UnaryExpr",
             [Field("Token", "op"), Field("ExprPtr", "right")],
             "Expression which operates on a single other expression."
             ),
    ClassDef(expr, "LiteralExpr",
             [Field("Token", "token", "Token defining the literal.")],
             "A literal value defined in source code."
             ),

    ClassDef(expr, "GroupExpr",
             [Field("ExprPtr", "expression", "Inner expression.")],
             "A parenthesised expression."
             ),

    ClassDef(expr, "ErrorExpr",
             [Field("Token", "token", "The unparsable token.")],
             "A parse error."
             )
]

class Source:
    """ Helper for building cpp source code. """
    def __init__(self):
        self.str = ""
        self.indent = 0

    def append(self, s):
        if self.str and self.str[-1] == "\n":
            # Indent if new line.
            self.str += "\t" * self.indent
        self.str += str(s)

    def ln(self, s):
        self.append(s + "\n")

    def doc(self, s):
        self.ln("/** " + s + " */")

    def br(self, num=1):
        self.append("\n" * num)

    def block_begin(self):
        self.ln("{")
        self.indent += 1

    def block_end(self, s=""):
        self.indent -= 1
        self.ln("}" + s)

    def access_mod(self, s):
        self.indent -= 1
        self.ln(s + ":")
        self.indent += 1

    def include(self, s):
        self.ln("#include " + s)

    def un_br(self):
        """Remove a line break if it was the last thing appended. """
        if self.str[-1] == "\n":
            self.str = self.str[:-1]

if __name__ == "__main__":
    def generate_header():
        src = Source()

        def generate_class(cls):
            src.br()
            src.doc(cls.doc)
            src.ln("struct " + cls.name + (" : public " + cls.superclass.name if cls.superclass else ""))
            src.block_begin()

            if cls.branch:
                src.access_mod("protected")

                if(not cls.superclass):
                    src.ln("AstNode* parent = nullptr;")

                src.ln(cls.name + "() {}")
                src.block_end(";")
                src.ln("typedef std::shared_ptr<" + cls.name + "> " + cls.name + "Ptr;")
                src.br()
                return

            # Expressions are friends with every other non-abstract node
            # to allow setting of their parent ptr.
            if cls.abstract:
                for other in nodes:
                    if not other.abstract and other.name != cls.name:
                        src.ln("friend struct " + other.name + ";")
                src.br()

            # Fields
            if cls.fields:
                src.un_br()
                if cls.fields:
                    src.br()
                    for field in cls.fields:
                        src.ln("const " + field.init)

                src.br()

            # Methods
            if not cls.abstract:
                src.ln("AstNode* getParent() final;")
                src.ln("void accept(AstVisitor& visitor) final;")
                src.ln("static " + cls.ptrName + " create(" + cls.constructor + ");")

            # Base AstNode
            elif not cls.superclass:
                src.ln("virtual ~" + cls.name + "() {}")
                src.ln("virtual AstNode* getParent() = 0;")
                src.ln("virtual void accept(AstVisitor& visitor) = 0;")
                src.access_mod("protected")
                src.ln("AstNode* parent;\n")

            # Constructor
            if cls.constructor:
                src.ln(cls.name + "(" + cls.constructor + ");")

            src.block_end(";")
            src.br()

        src.ln("#pragma once")
        src.br()
        src.include("\"flo/dev/token.h\"")
        src.include("<memory>")
        src.br(2)
        src.ln("namespace flo")
        src.ln("{")

        src.ln("class AstVisitor;")

        # Base classes
        generate_class(base)
        generate_class(stmt)
        generate_class(expr)

        # Node classes
        for cls in nodes:
            generate_class(cls)

        # Visitor
        src.ln("class AstVisitor");
        src.block_begin()
        src.access_mod("public")
        for cls in nodes:
            src.ln("virtual void visit(" + cls.name + "& " + cls.name[-4:].lower() + ");")

        src.block_end(";")

        src.br()
        src.ln("}")   # namespace

        return src.str

    def generate_cpp():
        src = Source()

        def generate_class(cls):
            # Constructor
            src.ln(cls.name + "::" + cls.name + "(" + cls.constructor + ")")
            src.append("\t: ")

            init = ""
            for field in cls.fields:
                init += field.name + "(" + field.name + "), "
            init = init[:-2] + " {}"
            src.ln(init)
            src.br()

            # Parent getter
            src.ln("AstNode* " + cls.name + "::getParent() { return parent; }\n")

            # Visitor
            src.ln("void " + cls.name + "::accept(AstVisitor& visitor) { visitor.visit(*this); }")

            # factory
            src.ln(cls.ptrName + " " + cls.name + "::create(" + cls.constructor + ")")
            src.block_begin()

            new = cls.name + "* n = new " + cls.name + "("
            for field in cls.fields:
                new += field.name + ", "
            new = new[:-2] + ");"
            src.ln(new)

            for field in cls.fields:
                if field.typename in ("ExprPtr", "StmtPtr"):
                    src.ln(field.name + "->parent = n;")

            src.ln("return std::shared_ptr<" + cls.name + ">(n);")
            src.block_end()
            src.br()

        src.include("\"flo/dev/ast.h\"")
        src.br()
        src.ln("using namespace flo;")
        src.br()

        # Classes
        for cls in nodes:
            generate_class(cls)

        # Visitor
        for cls in nodes:
            arg = cls.name[-4:].lower()
            src.ln("void flo::AstVisitor::visit(" + cls.name + "& " + arg + ")")
            src.block_begin()

            for field in cls.fields:
                if field.typename[-3:] == "Ptr":
                    src.ln(arg + "." + field.name + "->accept(*this);")

            src.block_end()

        return src.str

    def write(path, s):
        with open(path, "w") as outfile:
            outfile.write(s)

    write(header_output_path, generate_header())
    write(source_output_path, generate_cpp())


def validTriangle(a, b, c):
    Max = max(a, b, c)
    if Max < a + b + c - Max:
        isValidTriangle = True
        return(isValidTriangle)
    else:
        isValidTriangle = False
        return(isValidTriangle)
def main():
    a, b, c = eval(input('Please enter 3 lengths: '))
    if a > 0 and b > 0 and c > 0:
        if validTriangle(a, b, c):
            print('It is a valid triangle')
        else:
            print('It is not a valid triangle')
    else:
        print('error')
main()


#python program to check the prime number
#creating a array load the prime number
l = []
#take input from the user
for x in range(int (input("please enter a number:"))):
   #when the range less than 2
   if x <2:
      continue
   #check for factors
   for i in range(2,x):
      if x%i ==0:
         break
   #record the prime number
   else:
      l.append(x)
#output the array
print(l)


import math
import random

import numpy as np
from matplotlib import pyplot

from lina.linear_algebra import matrix_sub, dot, transpose
from lina.vectors import to_vec, vector_multiply, vector_init, vector_add, unwrap
from utils.generate_points import generate_points

max_iter = 10000
d = 2
k = 2
centers = [to_vec([0.0, 0.0]), to_vec([15.0, 15.0])]
clusters = [[], []]

def initialize(samples):
    sep = len(samples) / 2
    clusters[0] = samples[:int(sep)]
    clusters[1] = samples[int(sep):]

def decide_membership():
    samples = []

    for c in range(k):
        samples.extend((y, c) for y in clusters[c])

    for y_oc in samples:
        nc = nearest_cluster(y_oc[0])

        if y_oc[1] != nc:
            clusters[y_oc[1]].remove(y_oc[0])
            clusters[nc].append(y_oc[0])

def reestimate_centers():
    for c in range(k):
        centers[c] = cluster_mean(c)

def cluster_distance(y, i):
    y_m_mean = matrix_sub(y, centers[i])
    return math.sqrt(dot(y_m_mean, transpose(y_m_mean))[0][0])

def nearest_cluster(y):
    distances = [(i, cluster_distance(y, i)) for i in range(k)]
    # pick element with minimum distance
    el = min(distances, key=lambda x: x[1])

    return el[0]

def cluster_mean(i):
    norm = 1 / max(len(clusters[i]), 1)
    t_vec = vector_init(dim=d)

    for y in clusters[i]:
        t_vec = vector_add(t_vec, y)
    t_vec = vector_multiply(t_vec, norm)

    return t_vec

def cluster_variance(i):
    c_sum = 0.0
    for y in clusters[i]:
        y_m_mean = matrix_sub(y, centers[i])
        c_sum += dot(y_m_mean, transpose(y_m_mean))[0][0]

    return c_sum

def sum_of_cluster_variances():
    return sum(cluster_variance(i) for i in range(len(clusters)))

n = 100

x1 = 5
y1 = 5
sigma = 1

x2 = 10
y2 = 10

x3 = 7.5
y3 = 7.5

# generate class distributions using R

c1 = generate_points([x1, y1], sigma, n).tolist()
c2 = generate_points([x2, y2], sigma, n).tolist()
c3 = generate_points([x3, y3], sigma, n).tolist()

c1_vec = [to_vec(x) for x in c1]
c2_vec = [to_vec(x) for x in c2]
c3_vec = [to_vec(x) for x in c3]

all_samples = c1_vec + c2_vec + c3_vec

random.shuffle(all_samples)

initialize(all_samples)
last_means = centers.copy()
last_j = sum_of_cluster_variances()
converged = False

for i in range(max_iter):
    decide_membership()
    reestimate_centers()

    new_j = sum_of_cluster_variances()

    means_close = True

    for c in range(k):
        l_c = unwrap(last_means[c])
        c_c = unwrap(centers[c])

        if not (math.isclose(l_c[0], c_c[0]) and math.isclose(l_c[1], l_c[1])):
            means_close = False

    if means_close:
        print("Converged at iter {}!".format(i))
        converged = True
        break

    print("New J: {}".format(new_j))
    last_means = centers.copy()
    last_j = new_j
    print("Not converged yet ({}/{})".format(i, max_iter))

if converged:
    print("Center C1: {} | Center C2: {}".format(centers[0], centers[1]))
    print("Final Clusters, C1: {}".format(clusters[0]))
    print("Final Clusters, C2: {}".format(clusters[1]))

    unwrapped_c1 = np.array([unwrap(x) for x in clusters[0]])
    unwrapped_c2 = np.array([unwrap(x) for x in clusters[1]])
    unwrapped_centers = np.array([unwrap(x) for x in centers])

    pyplot.plot(unwrapped_c1[:, 0], unwrapped_c1[:, 1], 'ro')
    pyplot.plot(unwrapped_c2[:, 0], unwrapped_c2[:, 1], 'bo')

    pyplot.plot(unwrapped_centers[:, 0], unwrapped_centers[:, 1], 'go')
    for i in range(k):
        pyplot.annotate("C{}".format(i), xy=(unwrapped_centers[i][0], unwrapped_centers[i][1]), size='xx-large',
                        color='g')

    pyplot.show()

else:
    print("Did not converge in {} iterations".format(max_iter))


from collections import defaultdict

class FamilyForest:

    family = {}
    def make_family(self, s: str) -> None:
        # Create new individual group/Family
        famm = self.family
        famm[s] = 1

    def union(self, s: str, t: str) -> str:
        # Add s and t to make a new family and return representative
        fam = self.family
        parent = ""
        if type(fam[s]) and type(fam[t]) == int:
            xweight = fam[s]
            yweight = fam[t]
            fam[t] = s
            fam[s] = xweight + yweight
            parent = s
        else:
            parent1 = self.find(s)
            parent2 = self.find(t)
            weight1 = fam[parent1]
            weight2 = fam[parent2]

            if weight1 > weight2:
                parent = parent1
                fam[parent2] = parent1
                fam[parent1] = weight1 + weight2
            else:
                parent = parent2
                fam[parent1] = parent2
                fam[parent2] = weight1 + weight2
        return parent

    def find(self, s: str) -> str:
        fam = self.family
        if isinstance(fam[s], int):
            return s
        else:
            return self.find(fam[s])

if __name__ == "__main__":

    f = FamilyForest()

    for s in ["Ricardo", "Sean", "Maya", "Ishaan", "Chia-Lin"]:
        f.make_family(s)
        # each person should now be their own family representative
        assert f.find(s) == s

    rep = f.union("Sean", "Ishaan")
    var1 = f.find("Sean")
    var2 = f.find("Ishaan")
    print(var1)
    print(var2)

    f.union("Maya", "Ishaan")
    f.union("Ricardo", "Chia-Lin")

    # families: {"Sean", "Ishaan", "Maya"}, {"Ricardo", "Chia-Lin"}

    assert f.find("Sean") == f.find("Ishaan") == f.find("Maya")
    assert f.find("Ricardo") == f.find("Chia-Lin")
    assert f.find("Sean") != f.find("Chia-Lin")


"""
Author: Alec Arcand
Minimax algorithm implemented to solve
the game Mancala. The Mancala board is represented
by a string.
"""

def makeMove(board, position):
    boardCopy = board.copy()
    if position == -1:
        return boardCopy
    marbles = boardCopy[position]
    if marbles == 0:
        return board
    bLength = len(boardCopy) - 1
    boardCopy[position] = 0
    while marbles != 0:
        if position == bLength:
            return boardCopy
        boardCopy[position + 1] = boardCopy[position + 1] + 1
        marbles = marbles - 1
        position = position + 1

    return boardCopy

def possibleMoves(board):
    possible = []
    index = 0
    for i in board:
        if i != 0:
            possible.append(index)
        index = index + 1
    return possible

def isEmpty(board):
    for i in board:
        if i != 0:
            return False
    return True

def MiniMax(board, move, isMax):
    newBoard = makeMove(board, move)

    if isEmpty(newBoard):
        if isMax:
            return (move, -1) # Min win
        else:
            return (move, 1)  # Max win

    if isMax:
        highest = float('-inf')

        for pos in possibleMoves(newBoard):
            tmp = MiniMax(newBoard, pos, not isMax)
            if tmp[1] > highest:
                highest = tmp[1]
                move = pos
        return (move, highest)
    else:
        lowest = float('inf')

        for pos in possibleMoves(newBoard):
            tmp = MiniMax(newBoard, pos, not isMax)
            if tmp[1] < lowest:
                lowest = tmp[1]
                move = pos
        return (move, lowest)

def search(board):
    lstBoard = [int(i) for i in board]

    score = MiniMax(lstBoard, -1, True)

    if score[1] == 1:
        result = "win"
    else:
        result = "lose"

    solution = (score[0] + 1, result)

    return solution


import keras
from keras.models import Model
from keras.layers import Dense, Dropout, Input
import keras.backend as K
import tensorflow as tf

import numpy as np

from matplotlib import pyplot as plt
plt.style.use('seaborn-white')
from matplotlib import cm

from utils import iter_or_rep
from Architectures.dnn import DNN
from Architectures.ifn import IFN, GaussianAnsatz
from Architectures.utils import build_gaussianAnsatz_DNN

# #################################
# ########## PARAMETERS ###########
# #################################

x_dim = 1
y_dim = 1

epochs = 50
pre_train_epochs = 5
batch_size = 2048
pre_train_batch_size = 1024

# #############################
# ########## DATASET ##########
# #############################

N = 100000
scale = 5.0

# Gaussian Noise Dataset
X = np.random.uniform(low = -5, high = 5, size = (N, x_dim)) / scale
Y = X + np.random.normal(scale = 1, size = (N, x_dim)) / scale

# ############################
# ########## MODELS ##########
# ############################

# # Need to initialize T(x,y) = a(x) + (y-b(x))d(x) + 1/2 (y-b(x))^T c(x,y) (y-b(x))
# model_A = DNN(x_dim, [32, 32, 32], 1)
# model_B = DNN(x_dim, [32, 32, 32], y_dim)
# model_C = DNN([x_dim, y_dim], [32, 32, 32], [y_dim, y_dim], symmetrize=False)
# model_D = DNN(x_dim, [32, 32, 32], y_dim, l2_regs= 0.1)

ifn = build_gaussianAnsatz_DNN(x_dim, y_dim, [32,32,32], opt = "adam", d_l1_reg=0.1)

# Loss Function
def f_loss(out_joint, out_marginal):
    return -(tf.reduce_mean(out_joint, axis=0) - tf.reduce_mean(tf.math.exp(out_marginal - 1), axis = 0))
# MI Metric (Does not include l2 Reg losses)
def MI(out_joint, out_marginal):
    return (tf.reduce_mean(out_joint, axis=0) - tf.reduce_mean(tf.math.exp(out_marginal - 1), axis = 0))

# Compile and fit
ifn.pre_train([X,Y], epochs = pre_train_epochs, batch_size= pre_train_batch_size, verbose = True)
ifn.fit([X, Y],
            batch_size= batch_size,
            epochs = epochs)

# #####################################
# ########## PLOTS AND TESTS ##########
# #####################################

x_test = np.array([-5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0]).reshape((11, 1))
y_pred, sigmas = ifn.eval(x_test / scale)
y_pred *= scale
sigmas *= scale

for i,j,k in zip(x_test, y_pred, sigmas):
    print("For x = %.3f, infer y = %.3f +- %.3f" % (i, j, k))

# Plotting meshes
x = np.linspace(-5, 5, 40)
y = np.linspace(-5, 5, 40)

X, Y = np.meshgrid(x, y)
Z = scale * np.reshape(ifn([np.ravel(X).reshape(-1,1) / scale, np.ravel(Y).reshape(-1,1) / scale]).numpy(), X.shape)

contours = plt.contour(X, Y, Z, 8, colors='black')
plt.clabel(contours, inline=True, fontsize=8)
plt.contourf(X, Y, Z, 50, cmap = 'RdGy_r', origin='lower',  alpha=0.5)
plt.xlabel("Measured X")
plt.ylabel("Inferred Z")
plt.title("Maximum Likelihood Task")
cbar = plt.colorbar()
cbar.set_label("T(x,z)")

print(x_test.shape, y_pred.shape, sigmas.shape)
plt.errorbar(x_test[:,0], y_pred[:,0], yerr=sigmas, fmt='o', color='blue',
             ecolor='skyblue', elinewidth=3, capsize=0)

plt.xlim(-5, 5)
plt.ylim(-5, 5)

plt.savefig("test.png")


""" Unit testing for basic_operations """

from unittest import TestCase
from peewee import IntegrityError, DoesNotExist
from customer_model import Customer, DATABASE
import logging
import basic_operations as bo

TEST_USER1 = {'customer_id': 1,
              'name': 'Sterling',
              'lastname': 'Archer',
              'home_address': '123 Elm Street',
              'phone_number': '123-456-7890',
              'email_address': 'sterling.archer@gmail.com',
              'status': 'active',
              'credit_limit': 1000.00}

TEST_USER2 = {'customer_id': 2,
              'name': 'Lana',
              'lastname': 'Kane',
              'home_address': '123 Aspen Street',
              'phone_number': '123-456-7891',
              'email_address': 'lana.kane@gmail.com',
              'status': 'inactive',
              'credit_limit': 1500.00}

class OperationalTests(TestCase):
    """ Define a class for testing operations """

    def setUp(self):
        """ Ensure we start with a clean table """

        # Configure logging for test activity
        bo.configure_logger()

        logging.info("Dropping Customer table")
        DATABASE.drop_tables([Customer])
        logging.info("Creating Customer table")
        DATABASE.create_tables([Customer])

    def test_add_customer(self):
        """ Test adding customers """

        # Add a customer and ensure it is in the DB
        bo.add_customer(**TEST_USER1)
        test_customer = Customer.get(Customer.customer_id == TEST_USER1['customer_id'])
        self.assertEqual(test_customer.name, TEST_USER1['name'])

        # Ensure adding a non-unique customer_id fails
        with self.assertRaises(IntegrityError):
            bo.add_customer(**TEST_USER1)

        # Delete the test user
        bo.delete_customer(TEST_USER1['customer_id'])

    def test_search_customer(self):
        """ Test searching for a customer """

        # Add a customer and ensure it is in the DB
        bo.add_customer(**TEST_USER1)

        # Search for a valid user created in the first test
        test_customer = bo.search_customer(TEST_USER1['customer_id'])
        self.assertEqual(test_customer.name, TEST_USER1['name'])

        # Search for an invalid user
        with self.assertRaises(DoesNotExist):
            test_customer = bo.search_customer(50)

        # Delete the test user
        bo.delete_customer(TEST_USER1['customer_id'])

    def test_delete_customer(self):
        """ Test deleting customers """

        # Add a user to ensure we have something to delete
        bo.add_customer(**TEST_USER2)

        # Delete the test user
        bo.delete_customer(TEST_USER2['customer_id'])

        # Search for an invalid user
        with self.assertRaises(DoesNotExist):
            Customer.get(Customer.customer_id == TEST_USER2['customer_id'])

    def test_update_customer_credit(self):
        """ Test updating a customer's credit limit """

        # Add a user to ensure we have something to delete
        bo.add_customer(**TEST_USER1)

        # Update the limit for the first test user
        bo.update_customer_credit(TEST_USER1['customer_id'], 2500.00)
        test_customer = Customer.get(Customer.customer_id == TEST_USER1['customer_id'])
        self.assertEqual(test_customer.credit_limit, 2500.00)

        # Update the limit for a customer that doesn't exist
        with self.assertRaises(DoesNotExist):
            bo.update_customer_credit(50, 3000.00)

        # Delete the test user
        bo.delete_customer(TEST_USER1['customer_id'])

    def test_list_customers(self):
        """ Test listing all customers in the database """

        # Add an active customer
        bo.add_customer(**TEST_USER1)

        # Add an inactive customer
        bo.add_customer(**TEST_USER2)

        # Print the active customers
        active_customers = bo.list_active_customers()
        self.assertEqual(active_customers, 1)

    def tearDown(self):
        """ Ensure we start with a clean table """

        DATABASE.drop_tables([Customer])
        DATABASE.create_tables([Customer])


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Oct  3 14:00:31 2018

@author: engels
"""
class bcolors:
        HEADER = '\033[95m'
        OKBLUE = '\033[94m'
        OKGREEN = '\033[92m'
        WARNING = '\033[93m'
        FAIL = '\033[91m'
        ENDC = '\033[0m'
        BOLD = '\033[1m'
        UNDERLINE = '\033[4m'

def err( msg ):
    print("")
    print( bcolors.FAIL + "ERROR! " + bcolors.ENDC + msg)
    print("")

def warn( msg ):
    print("")
    print( bcolors.WARNING + "WARNING! " + bcolors.ENDC + msg)
    print("")

print("----------------------------------------")
print("%sIRENE%s submission preflight  " %(bcolors.OKGREEN, bcolors.ENDC))
print("----------------------------------------")

import sys
import os
import wabbit_tools
import numpy as np

# fetch jobfile from call
jobfile = sys.argv[1]

if os.path.isfile( jobfile ):
    auto_resub=False

    # read jobfile
    with open(jobfile) as f:
        # loop over all lines
        for line in f:
            if "ccc_mprun" in line:
                runline = line
            elif "#MSUB -n " in line:
                cpuline = line
            elif "#MSUB -T" in line:
                wtimeline = line
            elif "INIFILE=" in line:
                iniline = line
            elif "MEMORY=" in line:
                memline = line
            elif "AUTO_RESUB=" in line:
                line = line.replace('"','').replace('AUTO_RESUB=','')
                if float(line) > 0:
                    auto_resub=True

    if "./wabbit" in runline:
        # OLD STYLE: one line call
        # now runline contains the actual run:
        #       ccc_mprun ./wabbit suzuki.ini --memory=550.0GB
        runlist = runline.split()

        progfile   = runlist[1]
        paramsfile = runlist[2]
        memory     = float( runlist[3].replace('--memory=','').replace('GB','').replace('gb','') )
    else:
        # NEW STYLE: as on turing
        progfile = ""
        paramsfile = iniline.replace('INIFILE=','').replace('"','').replace('\n','')
        memory = float( memline.replace('"','').replace('GB','').replace('MEMORY=','').replace('\n',''))

    cpulist = cpuline.split()
    ncpu = float(cpulist[2])

    wtimelist = wtimeline.split()
    wtime = float(wtimelist[2])

    core_per_node = 48
    maxmem = ncpu*3.75 #GB

    if not os.path.isfile(paramsfile):
        print('paramsfile check  : %snot found%s' % (bcolors.FAIL,bcolors.ENDC) )
    else:
        print('paramsfile check  : %sfound%s' % (bcolors.OKGREEN,bcolors.ENDC) )

    print("program           = %s%s%s" % (bcolors.OKBLUE, progfile, bcolors.ENDC) )
    print("paramsfile        = %s%s%s" % (bcolors.OKBLUE, paramsfile, bcolors.ENDC) )
    print("memory in call    = %s%2.2f%s GB (%s%2.2f%s GB/core)" % (bcolors.OKBLUE, memory, bcolors.ENDC, bcolors.OKBLUE, memory/ncpu, bcolors.ENDC) )
    print("max memory        = %s%i%s GB" % (bcolors.OKBLUE, maxmem, bcolors.ENDC) )
    print("max memory (safe) = %s%i%s GB" % (bcolors.OKBLUE, maxmem-5.0, bcolors.ENDC) )
    print("ncpu              = %s%i%s" % (bcolors.OKBLUE, ncpu, bcolors.ENDC) )
    print("wtime (jobfile)   = %s%i%s sec (%2.2f hours)" % (bcolors.OKBLUE, wtime, bcolors.ENDC, wtime/3600.0) )
    wtime_ini = wabbit_tools.get_ini_parameter(paramsfile, "Time", "walltime_max", float)
    # hours to seconds
    wtime_ini *= 3600.0
    print("wtime (inifile)   = %s%i%s sec (%2.2f hours)" % (bcolors.OKBLUE, wtime_ini, bcolors.ENDC, wtime_ini/3600.0) )

    if auto_resub:
        print('RESUBMISSION      : %sAutomatic resubmission is ACTIVE%s' % (bcolors.WARNING,bcolors.ENDC) )
    else:
        print('RESUBMISSION      : %sAutomatic resubmission is DEACTIVTÀTED!!%s' % (bcolors.WARNING,bcolors.ENDC) )

    if memory >= 0.98*maxmem:
        print('Memory check      : %sEXCEEDED%s' % (bcolors.FAIL,bcolors.ENDC) )
    else:
        print('Memory check      : %sokay%s' % (bcolors.OKGREEN,bcolors.ENDC) )

    if abs(ncpu/core_per_node - float(round(ncpu/core_per_node))) > 0.0:
        print('Complete node(s)  : %sYou did not specify N*48 CPUS%s' % (bcolors.FAIL,bcolors.ENDC) )
    else:
        print('Complete node(s)  : %sokay%s' % (bcolors.OKGREEN,bcolors.ENDC) )

    if wtime_ini > wtime:
        print('walltime *.SH/INI : %s Walltime in ini file greater than walltime in job file!%s' % (bcolors.FAIL,bcolors.ENDC) )
    else:
        print('walltime *.SH/INI : %sokay%s' % (bcolors.OKGREEN,bcolors.ENDC) )

    print("----------------------------------------")
    wabbit_tools.check_parameters_for_stupid_errors( paramsfile )

else:
    err("Jobfile %s not found" % (jobfile))
    raise ValueError( )