"""
The :mod:`sklearn.QuantumUtility` module includes quantum routines like tomography, amplitude estimation and
phase estimation
"""

from collections import Counter
import math
import random
import re
import time
from scipy.stats import truncnorm
import numpy as np
from bisect import bisect
import warnings

# import gc

warnings.simplefilter('always', UserWarning)
import matplotlib.pyplot as plt
from multiprocessing import *

# random.seed(a=31337)

class QuantumState(object):
    """This class simulates a simple Quantum Register

    Parameters
    ----------

    registers: list, ndarray.
        List of values that represents the superposition of the states of the quantum state.

    amplitudes: list, ndarray.
        List of values that represents the amplitudes of each register.
    """

    def __init__(self, registers, amplitudes):
        super(QuantumState, self).__init__()
        self.registers = registers

        # Amplitudes must be normalized to have the right probabilities for each register
        self.norm_factor = math.sqrt(sum([pow(x, 2) for x in amplitudes]))
        self.amplitudes = [x / self.norm_factor for x in amplitudes]

        # Each register_i appears with probability amplitude_i^2
        self.probabilities = [pow(x, 2) for x in self.amplitudes]
        assert (len(self.registers) == len(self.amplitudes))
        assert (abs(sum(self.probabilities) - 1) < 0.0000000001)

    def measure(self, n_times=1):
        # return random.choices(self.registers, weights=self.probabilities, k=n_times)
        LocalProcRandGen = np.random.RandomState()
        return LocalProcRandGen.choice(self.registers, p=self.probabilities, size=n_times)
        # return np.random.choice(self.registers, p=self.probabilities, size=n_times)

    def get_state(self):
        return {self.registers[i]: self.probabilities[i] for i in range(len(self.registers))}

def estimate_wald(measurements):
    counter = Counter(measurements)
    estimate = {x: counter[x] / len(measurements) for x in counter}
    return estimate

## Introduce +-epsilon error in a value
def introduce_error(value, epsilon):
    return value + truncnorm.rvs(-epsilon, epsilon, size=1)

def coupon_collect(quantum_state):
    counter = 0
    collection_dict = {value: 0 for value in quantum_state.get_state().keys()}

    # Until you don't collect all the values, keep sampling and increment the counter
    while sum(collection_dict.values()) != len(collection_dict):
        value = quantum_state.measure()[0]
        if not collection_dict[value]:
            collection_dict[value] = 1
        counter += 1
    return counter

def make_gaussian_est(vec, noise):
    """This function is used to estimate vec with tomography or with Gaussian Noise Approximation.

    Parameters
    ----------
    vec: array-like that has to be estimated.

    noise: float. It represent the error that you want to introduce to estimate the representation of vector V.
    """
    noise_per_component = noise / np.sqrt(len(vec))
    if noise_per_component != 0:
        errors = truncnorm.rvs(-noise_per_component, noise_per_component, size=len(vec))
        # print('noise_per_comp:', noise_per_component, 'errors:', errors)
        somma = lambda x, y: x + y
        # new_vec = np.array([vec[i] + errors[i] for i in range(len(vec))])
        new_vec = np.apply_along_axis(somma, 0, vec, errors)
    return new_vec

def tomography(A, noise, true_tomography=True, stop_when_reached_accuracy=True, N=None, norm='L2',
               incremental_measure=True, faster_measure_increment=0):
    """ Tomography function (real and approximate).

    Parameters
    ----------
    A: array-like that has to be estimated.

    noise: float value.
        It represent the error that you want to introduce to estimate the representation of vector V.

    true_tomography: bool, default=True.
        If true means that the quantum estimations are are done with real tomography,
        otherwise the estimations are approximated with a Truncated Gaussian Noise.

    stop_when_reached_accuracy: bool value, default=True.
        If True it stops the execution of the tomography when the L2(or Linf)-norm of the
        difference between V and its estimation is less or equal then delta. Otherwise
        N measures are done (very memory intensive for large vectors).

    N: int value, default=None.
        Number of measures of the quantum state. If None it is computed in the function itself.

    norm: string value, default='L2'
        If true_tomography is True:
            'L2':
                L2-tomography is computed
            'inf':
                L-inf tomography is computed

    incremental_measure: bool, default=True.
        If True the tomography is computed incrementally up to N measures. If False, the routine is
        performed once using N measures.

    faster_measure_increment: int, default=0.
        It speeds up the tomography increasing the number of measurements in the incremental way.

    Returns
    -------
    A_est: array-like that was estimated.

    Notes
    -----
    This method returns an estimation of the true array/matrix A using quantum tomography algorithm 4.1 proposed in
    "A Quantum Interior Point Method for LPs and SDPs" paper, or using an approximation of the tomography computation.
    """

    assert noise >= 0

    if noise == 0:
        return A

    if true_tomography == False:
        if len(A.shape) == 2:
            vector_A = A.reshape(A.shape[0] * A.shape[1])
            vector_B = make_gaussian_est(vector_A, noise)
            A_est = vector_B.reshape(A.shape[0], A.shape[1])
        else:
            A_est = make_gaussian_est(A, noise)

    else:
        if len(A.shape) == 2:
            A_est = np.array([np.array(list(
                real_tomography(A[idx], delta=noise, stop_when_reached_accuracy=stop_when_reached_accuracy,
                                N=N, norm=norm, incremental_measure=incremental_measure,
                                faster_measure_increment=faster_measure_increment).values())[-1]) for idx in
                              range(len(A))])
        else:
            A_est = np.array(
                list(real_tomography(A, delta=noise, stop_when_reached_accuracy=stop_when_reached_accuracy, N=N,
                                     norm=norm, incremental_measure=incremental_measure,
                                     faster_measure_increment=faster_measure_increment).values())[-1])

    return A_est

def create_rand_vec(n_vec, len_vec, scale=None, type='uniform'):
    v = []
    for i in range(n_vec):
        if type == 'uniform':
            vv = np.random.uniform(-1, 1, (len_vec))
        elif type == 'exp':
            vv = np.random.exponential(scale=scale, size=len_vec)
        vv = vv / np.linalg.norm(vv, ord=2)
        v.append(vv)

    return v

def __mu(p, matrix):
    def s(p, A):
        if p == 0:
            result = np.max([np.count_nonzero(A[i]) for i in range(len(A))])
        else:
            norms = np.sum(np.power(np.abs(A), p), axis=1)
            result = max(norms)
            del norms
        # gc.collect()
        return result

    s1 = s(2 * p, matrix)
    s2 = s(2 * (1 - p), matrix.T)
    mu = np.sqrt(s1 * s2)

    # gc.collect()
    return mu

def linear_search(matrix, start=0.0, end=1.0, step=0.05):
    domain = [i for i in np.arange(start, end, step)] + [end]
    values = [__mu(i, matrix) for i in domain]
    best_p = domain[values.index(min(values))]
    return best_p, min(values)

def best_mu(matrix, start=0.0, end=1.0, step=0.05):
    p, val = linear_search(matrix, start=start, end=end, step=step)
    val_list = [val, np.linalg.norm(matrix)]
    index = val_list.index(min(val_list))
    if index == 0:
        best_norm = f"p={p}"
    elif index == 1:
        best_norm = "Frobenius"

    return best_norm, val_list[index]

def L2_tomogrphy_fakeSign(V, N=None, delta=None):
    d = len(V)
    # index = np.arange(0,d)
    if N is None:
        N = (36 * d * np.log(d)) / (delta ** 2)

    q_state = QuantumState(amplitudes=V, registers=V)
    P = estimate_wald(q_state.measure(n_times=int(N)))
    # P = {V[k]: v for (k, v) in P.items()}

    # Manage the mismatch problem of the length of the measurements for some values
    if len(P) < d:
        keys = set(list(P.keys()))
        v_set = set(V)
        missing_values = list(v_set - keys)
        P.update({l: 0 for l in missing_values})

    P_sqrt = {k: (-np.sqrt(v) if k < 0 else np.sqrt(v)) for (k, v) in P.items()}

    x_sign = list(map(P_sqrt.get, V))
    # x_sign = np.array(list(P_sqrt.values()))
    # print(np.linalg.norm(x_sign,ord=2))
    return x_sign

def real_tomography(V, N=None, delta=None, stop_when_reached_accuracy=True, norm='L2', incremental_measure=True,
                    faster_measure_increment=0):
    """ Official version of the tomography function.

    Parameters
    ----------
    V: array-like that has to be estimated.

    N: int value, default=None.
        Number of measures of the quantum state. If None it is computed in the function itself.

    delta: float value, default=None.
        It represent the error that you want to introduce to estimate the representation of vector V.

    stop_when_reached_accuracy: bool, default=True.
        If True it stops the execution of the tomography when the L2-norm of the
        difference between V and its estimation is less or equal then delta. Otherwise
        N measures are done (very memory intensive for large vectors).

    norm: string, default='L2'.
        If 'L2':
            perform L2-norm tomography.
        If 'inf':
            perform L-inf tomography.

    incremental_measure: bool, default=True.
        If True the tomography is computed incrementally up to N measures. If False, the routine is
        performed once using N measures.

    faster_measure_increment: int, default=0.
        It speeds up the tomography increasing the number of measurements in the incremental way.

    Returns
    -------
    dict_res: dictionary of shape {N_measure: vector_estimation}.

    Notes
    -----
    This method returns an estimation of the true array V using quantum tomography algorithm 4.1 proposed in
    "A Quantum Interior Point Method for LPs and SDPs" paper.

    """
    if np.isclose(np.linalg.norm(V), 1, rtol=1e-2):
        pass
    else:
        V = V / np.linalg.norm(V, ord=2)
    d = len(V)
    index = np.arange(0, d)
    if N is None:
        if norm == 'L2':
            N = int((36 * d * np.log(d)) / (delta ** 2))
        elif norm == 'inf':
            N = int((36 * np.log(d)) / (delta ** 2))

    q_state = QuantumState(amplitudes=V, registers=index)
    dict_res = {}
    if incremental_measure:

        measure_indexes = np.geomspace(1, N, num=100, dtype=np.int64)

        measure_indexes = check_measure(measure_indexes, faster_measure_increment=faster_measure_increment)

        for i in measure_indexes:

            P = estimate_wald(q_state.measure(n_times=int(i)))
            P_i = np.zeros(d)
            P_i[list(P.keys())] = np.sqrt(list(P.values()))

            # Part2 of algorithm 4.1
            max_index = max(index)
            digits = len(str(max_index)) + 1
            registers = [str(j).zfill(digits) for j in index] + [re.sub('0', '1', str(j).zfill(digits), 1) for j in
                                                                 index]

            amplitudes = np.asarray([V[k] + P_i[k] for k in range(len(V))] + [V[k] - P_i[k] for k in range(len(V))])

            amplitudes *= 0.5

            new_quantum_state = QuantumState(registers=registers, amplitudes=amplitudes)

            measure = new_quantum_state.measure(n_times=int(i))

            str_ = [str(ind).zfill(digits) for ind in index]
            dictionary = dict(Counter(measure))

            if len(dictionary) < len(registers):
                keys = set(list(dictionary.keys()))
                tot_keys = set(registers)
                missing_keys = list(tot_keys - keys)
                dictionary.update({l: 0 for l in missing_keys})

            d_ = list(map(dictionary.get, str_))

            P_i = [P_i[e] if x > 0.4 * P_i[e] ** 2 * i else P_i[e] * -1 for e, x in enumerate(d_)]

            dict_res.update({i: P_i})
            if stop_when_reached_accuracy:
                if norm == 'L2':
                    sample = np.linalg.norm(V - P_i, ord=2)
                elif norm == 'inf':
                    sample = np.linalg.norm(V - P_i, ord=np.inf)
                if sample > delta:
                    pass
                else:
                    break

    else:
        P = estimate_wald(q_state.measure(n_times=int(N)))
        P_i = np.zeros(d)
        # indexes = [list(q_state.registers).index(key) for key in list(P.keys())]
        P_i[list(P.keys())] = np.sqrt(list(P.values()))
        # P_i[indexes] = np.sqrt(list(P.values()))

        # Part2 of algorithm 4.1
        max_index = max(index)
        digits = len(str(max_index)) + 1
        registers = [str(j).zfill(digits) for j in index] + [re.sub('0', '1', str(j).zfill(digits), 1) for j in index]

        amplitudes = np.asarray([V[k] + P_i[k] for k in range(len(V))] + [V[k] - P_i[k] for k in range(len(V))])

        amplitudes *= 0.5

        new_quantum_state = QuantumState(registers=registers, amplitudes=amplitudes)

        measure = new_quantum_state.measure(n_times=int(N))

        str_ = [str(ind).zfill(digits) for ind in index]
        dictionary = dict(Counter(measure))

        if len(dictionary) < len(registers):
            keys = set(list(dictionary.keys()))
            tot_keys = set(registers)
            missing_keys = list(tot_keys - keys)
            dictionary.update({l: 0 for l in missing_keys})

        d_ = list(map(dictionary.get, str_))

        P_i = [P_i[e] if x > 0.4 * P_i[e] ** 2 * N else P_i[e] * -1 for e, x in enumerate(d_)]

        dict_res.update({N: P_i})

        # print('error_tomography:',np.linalg.norm(V - P_i, ord=2))

    return dict_res

def auxiliary_fun(q_state, i):
    P = q_state.measure(n_times=int(i))
    return P

def vectorize_aux_fun(dic, i):
    return np.sqrt(dic[i]) if i in dic else 0

def check_measure(arr, faster_measure_increment):
    incr = 5 + faster_measure_increment

    for i in range(len(arr) - 1):
        if arr[i + 1] == arr[i]:
            arr[i + 1] += incr
        if arr[i + 1] <= arr[i]:
            arr[i + 1] = arr[i] + incr
    return arr

def check_division(v, n_jobs):
    a = float(v) / n_jobs
    d = a - int(a)
    remaining = int(d * n_jobs)
    process_values = [int(a) for _ in range(n_jobs)]
    for i in range(remaining):
        process_values[i] += 1
    return process_values

def amplitude_est_dist(w0, w1):
    c = -np.ceil(w1 - w0)
    f = -np.floor(w1 - w0)
    distance = min(np.abs(c + w1 - w0), np.abs(f + w1 - w0))
    return distance

def amplitude_estimation(a, epsilon=0.01, gamma=None, M=None, nqubit=False, plot_distribution=False):
    """ Official version of the amplitude estimation function.

    Parameters
    ----------
    a: float or int value.
         Value that has to be estimated by the amplitude estimation. It must be in the range of [0,1].

    epsilon: float value, default=0.01
        Error that you want to tolerate in the estimate of amplitude estimation.

    gamma: float value, default=None.
        It represent the probability of failure of amplitude estimation. If specified, median evaluation is performed
        to boost the probability of success of this routine.

    M: int value, default=None.
        The number of iteration executes in the routine.

    nqubit: bool value, default=False.
        If True, the routine returns also the number of qubits to represent an estimate with the specified precision
        and the parameter M (see the amplitude estimation routine description for more details).

    plot_distribution: bool value, default=False.
        If True, a plot of the probability distribution for the output of amplitude estimation is done.

    Returns
    -------
    a_tilde: float value.
        Estimate of the probability of measure a "good" state.

    Notes
    -----
    This method performs the amplitude estimation routine following the approach described in "Quantum Amplitude Amplification
    and Estimation" paper. Amplitude estimation is the problem of estimating the probability that a measurements of
    a quantum state yields a good state.
    """
    if gamma:
        return median_evaluation(amplitude_estimation, gamma=gamma, Q=None, a=a, epsilon=epsilon, M=M,
                                 nqubit=False, plot_distribution=plot_distribution)

    if M == None:
        M = (math.ceil((np.pi / (2 * epsilon)) * (1 + np.sqrt(1 + 4 * epsilon))))
        n_qubits = np.ceil(np.log2(M))
        # M = int(2 ** n_qubits)  # If M is a power of 2. In Mosca book they said this.
    else:
        n_qubits = np.ceil(np.log2(M))

        warnings.warn(
            "Attention! The value of M that will be considered is the one you passed. Epsilon in this case is "
            "useless")

    theta_a = math.asin(np.sqrt(a))
    p = []
    theta_j = []

    for j in range(M):
        theta_est = np.pi * j / M
        theta_j.append(theta_est)
        distance = amplitude_est_dist(theta_est / np.pi, theta_a / np.pi)
        if distance != 0:
            p_aj = np.abs(math.sin(M * distance * np.pi) / (M * math.sin(distance * np.pi))) ** 2
        else:
            p_aj = 1
        p.append(p_aj)
    # sum_at_one = np.sum(p)
    theta_tilde = random.choices(theta_j, weights=p, k=1)[0]

    if plot_distribution:
        relative_error = epsilon * max(theta_a, 1)
        plt.annotate((float('%.2f' % (theta_j[p.index(max(p))])), float('%.2f' % (max(p)))),
                     xy=(theta_j[p.index(max(p))], max(p)))
        plt.bar(theta_j, p, 0.001)
        plt.axvline(theta_a - relative_error, c='red', ls='dashed')
        plt.axvline(theta_a + relative_error, c='red', ls='dashed')
        plt.xlim(theta_j[p.index(max(p))] - 0.03, theta_j[p.index(max(p))] + 0.03)
        plt.title(r'Probability distribution for the output of amplitude estimation for $\theta$ = ' + str(
            float('%.2f' % (theta_a))) + r' with $\epsilon$ =' + str(epsilon) + r'$\rightarrow$ M=' + str(M),
                  fontdict={'family': 'serif',
                            'color': 'darkblue',
                            'weight': 'bold',
                            'size': 8})
        plt.xlabel(r'$\hat a$')
        plt.ylabel("probability")

        plt.show()
    if nqubit:
        return theta_tilde, n_qubits, M
    a_tilde = np.sin(theta_tilde) ** 2
    return a_tilde

def median_evaluation(func, gamma=0.1, Q=None, *args, **kwargs):
    """Median evaluation.

    Parameters
    ----------
    func: Callable.
        The function that you want to execute Q time.

    gamma: float value, default=0.1.
        The probability that the median estimation gives a value satisfying the error bounds.

    Q: int value, default=None.
        Number of iterations to execute func.

    args:
        list of parameters values to pass to the callable function.

    kwargs:
        arguments of type key->value to pass to the callable function.

    Returns
    -------
    final_estimate : float value.
        Median estimation of the function passed as arguments.

    Notes
    -----
    This procedure at high level computes Q times the result of the callable func passed, and extract the median
    to be more accurate in the estimation. It is used to boost the probability and precision for the estimation.
    """
    if Q == None:
        z = np.log(1 / gamma) / (2 * (8 / np.pi ** 2 - 0.5) ** 2)
        Q = np.ceil(z)
        if Q % 2 == 0:
            Q += 1

    estimates = [func(*args, **kwargs) for _ in range(int(Q))]
    final_estimate = np.median(estimates)
    return final_estimate

def wrapper_phase_est_arguments(argument, type='sv'):
    if type == 'sv':
        theta_i = 2 * math.acos(argument)
        return theta_i
    if type == 'distance':
        theta_i = math.asin(np.sqrt(argument))
        return theta_i

def unwrap_phase_est_arguments(argument, eps, type='sv'):
    if type == 'sv':
        return math.cos(argument * (eps + np.pi) / 2)
    if type == 'distance':
        return math.sin(argument * np.pi) ** 2

def phase_estimation(omega, m=None, epsilon=None, gamma=0.1, plot_distribution=False, nqubit=False):
    """ Official version of the phase estimation function.

        Parameters
        ----------
        omega: float or int value.
             Value that has to be estimated by the phase estimation. It must be in the range of [0,1).

        m: int value, default=None.
            The number of qubits you want to use for the computation.

        epsilon: float value, default=None.
            Precision that you want to have in the phase estimation procedure. If not None, it's used to compute m.

        nqubit: bool value, default=False.
            If True, the routine returns the estimation of omega, the k_est and also the number of qubits to represent
            an estimate with the specified precision and the parameter M.

        gamma: float value, default=0.1.
            It represent the probability of success of the routine.

        plot_distribution: bool value, default=False.
            If True, a plot of the probability distribution for the output of phase estimation is done.

        Returns
        -------
        omega_tilde: float value.
            Estimate of the true omega value.

        Notes
        -----
        This method performs the phase estimation routine following the approach described in "An Introduction
        to Quantum computing" book and "Quantum Algorithm for Unsupervised ML and NN" thesis.
        Phase estimation is the problem of estimating the phase of the eigenvectors of a unitary U using m qubits of
        precision. From this method is derived the :mod:`sklearn.QuantumUtility.Utility.amplitude_estimation` procedure.
    """
    # omega must be between [0,1). The estimation must have shape of x/2^n
    assert m != None or epsilon != None, "Attention! You need to specify the number of qubits m or the precision epsilon."
    if m != None and nqubit == True:
        warnings.warn("Attention! You are specifying that you want to return also the number of qubits" \
                      " used, but you are already specifying it with the m parameter.")
    if epsilon != None:
        warnings.warn('Attention! The m value is computed using the epsilon parameter passed.')
        # From Nielsen and Chuang (eq. 5.35).
        m = int(np.ceil(np.log2(1 / epsilon)) + np.ceil(np.log2(2 + 1 / (2 * gamma))))

    p = []
    omega_k = []
    M = 2 ** m  # in P.E., M is fixed in this way
    if omega == 1 or np.isclose(omega, 1):
        return (M - 1) / M
    for k in range(M):
        omega_est = k / M
        omega_k.append(omega_est)
        # Landman
        try:
            p.append(np.abs((math.sin((M * omega - k) * np.pi)) / (M * (math.sin((omega - k / M) * np.pi)))) ** 2)
        except:
            # if the division is 0/0 -> case when M*omega is an integer.
            p.append(1)

    # sum_at_one = np.sum(p)
    omega_tilde = random.choices(omega_k, weights=p, k=1)[0]

    k_est = omega_tilde * M

    if plot_distribution:
        # rel_error = epsilon * max(omega, 1)
        rel_error = epsilon * omega
        plt.annotate((float('%.4f' % (omega_k[p.index(max(p))])), float('%.2f' % (max(p)))),
                     xy=(omega_k[p.index(max(p))], max(p)))
        plt.bar(omega_k, p, 0.0001)

        plt.axvline(omega - rel_error, c='red', ls='dashed')
        plt.axvline(omega + rel_error, c='red', ls='dashed')
        plt.axvline(omega, c='yellow', ls='dashed', label=r'$\omega$=' + str(omega))

        mask = (np.array(omega_k) >= (omega - rel_error)) & (np.array(omega_k) <= omega + rel_error)
        print(np.array(omega_k)[mask], len(omega_k), omega + rel_error, omega - rel_error)
        print(len(np.array(omega_k)[mask]) * 100 / len(omega_k))
        plt.xlim(omega_k[p.index(max(p))] - 0.006, omega_k[p.index(max(p))] + 0.006)
        if epsilon:
            '''plt.title(r'Probability distribution for the output of phase estimation for $\theta$ = ' + str(
                float('%.2f' % (omega))) + r' with $\epsilon$ =' + str(epsilon) + r'$\rightarrow$ M=' + str(M),
                      fontdict={'family': 'serif',
                                'color': 'darkblue',
                                'weight': 'bold',
                                'size': 8})'''
        else:
            '''plt.title(r'Probability distribution for the output of phase estimation for $\theta$ = ' + str(
                float('%.2f' % (omega))) + r' with M=' + str(M),
                      fontdict={'family': 'serif',
                                'color': 'darkblue',
                                'weight': 'bold',
                                'size': 8})'''
        plt.xlabel(r'$\hat \omega$')
        plt.ylabel("probability")
        plt.legend()

        plt.show()
    if nqubit:
        return omega_tilde, k_est, m, M

    return omega_tilde

def ipe(x, y, epsilon, Q=1, gamma=0.1):
    """Official version of the Robust Inner Product Estimation Routine ((R)IPE).

    Parameters
    ----------
    x: ndarray of shape (n,).
        One of the two vector needed to compute the inner product.

    y: ndarray of shape (n,).
        The second vector needed to compute the inner product.

    epsilon: float value, default=None.
        Precision that you want to have in the inner product estimation procedure.

    Q: int value, default=1.
        Number of iteration for the median evaluation of implicit amplitude estimation output.

    gamma: float value, default=0.1.
        Probability of success to insert in median evaluation.

    Returns
    -------
    s: float value.
        Estimate of the inner product between x and y vectors.

    Notes
    -----
    This method performs the Robust Inner Product Estimation as described in the supplemental material of
    "Quantum algorithms for feedforward neural networks" paper. Implicitly it uses amplitude estimation routine
    :mod:`sklearn.QuantumUtility.Utility.amplitude_estimation` and if the number of iteration Q are >1, implicitly it
    uses also median evaluation to boost the amplitude estimation output.
    """
    a = (np.linalg.norm(x) ** 2 + np.linalg.norm(y) ** 2 - 2 * np.inner(x, y)) / (2 * (
            np.linalg.norm(x) ** 2 + np.linalg.norm(y) ** 2))

    epsilon_a = epsilon * max(1, np.abs(np.inner(x, y))) / (np.linalg.norm(x) ** 2 + np.linalg.norm(y) ** 2)
    if math.isclose(a, 0.0, abs_tol=1e-15):
        a = 0
    a_tilde = amplitude_estimation(a=a, gamma=gamma, epsilon=epsilon_a)
    s = (np.linalg.norm(x) ** 2 + np.linalg.norm(y) ** 2) * (1 - 2 * a_tilde) / 2
    return s

def consistent_phase_estimation(omega, epsilon, gamma, n=None, shift=None):
    """Official version of the Consistent Phase Estimation routine.

    Parameters
    ----------
    omega: float value.
        Value that you want to estimate. It must be a value in the range of [0,1).

    epsilon: float value.
        The accuracy value that you want to have in your estimations.

    gamma: float value.
        Probability error that you want to have.

    n: int value, default=None.
        Number of qubits that you want to use in the routine. If None, this value is computed using the accuracy value
        passed.

    shift: int value, default=None.
        If not None, this fix the shift of the algorithm, otherwise it is computed inside the function.

    Returns
    -------
    estimate: float value.
        Estimate of the omega value.

    Notes
    -----
    This method performs the Consistent Phase Estimation as described in the "Inverting Well Conditioned Matrices in
    Quantum Logspace" paper. Implicitly it uses normal phase estimation routine :mod:`sklearn.QuantumUtility.Utility.phase_estimation`.
    It is useful because different from the normal phase estimation, this is consistent in the sense that it return almost
    always the same result.
    """
    if n == None:
        n = int(np.ceil(np.log2(1 / epsilon)) + np.ceil(np.log2(2 + 1 / (2 * gamma))))

    C = gamma / n
    delta_prime = (epsilon * C) / 2
    L = np.floor(2 / C)
    # shift = random.randint(1, L)
    if shift == None:
        shift = int(L / 2) + 1
    intervals = np.arange(-1 - shift * delta_prime, 1 + epsilon - shift * delta_prime, epsilon)
    intervals = np.append(intervals, 1 + epsilon - shift * delta_prime)
    pe_estimate = phase_estimation(omega=omega, epsilon=delta_prime, gamma=gamma)
    index = bisect(intervals, pe_estimate)
    section = (intervals[(index - 1)], intervals[index])
    estimate = np.mean(section)

    if estimate < 0:
        estimate = 0
    # print('true_value:', omega, 'pe_estimate:', pe_estimate, 'consistent_pe_estimate:', estimate)
    return estimate


#forfact.py
n = int(input('Enter an integer >= 0: '))
fact = 1
for i in range(2,n+1):
    fact = fact * i
print(str(n)+ ' factorial is ' + str(fact))

#whilefact.py
n = int(input('Enter an integer >=0: '))
fact = 1
i = 2
while i<=n:
    fact = fact*i
    i = i+1
print(str(n) + ' factorial is ' + str(fact))

#forsum.py
n = int(input('How many numbers to sum? '))
total = 0
for i in range(n):
    s = input('Enter number ' + str(i+1) + ': ')
    total = total + int(s)
print('The sum is ' + str(total))

#whilesum.py
n = int(input('How many numbers to sum? '))
total = 0
i = 1
while i<=n:
    s = input('Enter number ' + str(i) + ': ')
    total = total+int(s)
    i = i + 1
print('The sum is ' + str(total))

#just while, summing unknown number of numbers
#donesum.py
total = 0
s = input('Enter a number(or "done"): ')
while s != 'done':
    num = int(s)
    total = total + num
    s = input('Enter a number (or "done"): ')
print('The sum is ' + str(total))

#donesum_break.py
total = 0
while True:
    s = input('Enter a number (or "done"): ')
    if s=='done':
        break # jump out of loop
    num = int(s)
    total = total + num
print('The sum is ' + str(total))

#nested loops
#timestable.py times tables up to 10
for row in range(1,10):
    for col in range(1,10):
        prod = row*col
        if prod < 10:
            print(' ', end='')
        print(row*col, ' ', end='')
    print()


#otsu's thresholding with Gaussian blur for noise reduction

import numpy as np
import cv2

def findDiff():
	#get both images
	img1 = cv2.imread('aligned_A.jpg',0)
	img2 = cv2.imread('aligned_B.jpg',0)

	#cv2.imwrite('inter_A.jpg', img1)
	#cv2.imwrite('inter_B.jpg', img2)

	#get dimensions
	h, w = img2.shape

	#create a zeroed out image of same dimensions
	res1 = np.zeros((h,w,1), np.uint8)

	#find difference b/w 1st and 2nd image and vice versa
	disappear = cv2.subtract(img1, img2)
	appear = cv2.subtract(img2, img1)

	#set threshold values
	thresh = 70
	maxValue = 255

	# apply gaussian blur and otsu's threshold
	blur1 = cv2.GaussianBlur(disappear,(5,5),0)
	ret,disappear = cv2.threshold(blur1,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
	blur2 = cv2.GaussianBlur(appear,(5,5),0)
	ret,appear = cv2.threshold(blur2,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

	#intermediate results
	#cv2.imwrite('disappear.jpg', disappear)
	cv2.imwrite('appeared.jpg', appear)

	#OR intermediate results
	#joined = cv2.add(disappear,appear)

	#write final results
	#cv2.imwrite('joined.jpg', joined)


# -*- coding: gb18030 -*-
#
# $Id: StatWindow.py,fangpengjun Exp $

"""
implement StoreWindow
"""
from Time import Time
from bwdebug import *
from guis import *
import BigWorld
from LabelGather import labelGather
from guis.common.Window import Window
from guis.controls.ODPagesPanel import ODPagesPanel
from guis.general.tradewindow.WareItem import WareItem
from guis.controls.ODComboBox import ODComboBox
from guis.controls.ComboBox import ComboItem
from guis.controls.TextBox import TextBox
from guis.controls.StaticText import StaticText
from guis.controls.ButtonEx import HButtonEx
from guis.controls.ListItem import MultiColListItem
from guis.controls.CheckBox import CheckBoxEx
import event.EventCenter as ECenter
from GUIFacade import MerchantFacade
from config.client.msgboxtexts import Datas as mbmsgs
import csstatus
import csdefine
import csconst
import GUIFacade
import Const
import ShareTexts

g_chs_class = { csdefine.CLASS_FIGHTER	: ShareTexts.PROFESSION_FIGHTER,
			csdefine.CLASS_SWORDMAN	: ShareTexts.PROFESSION_SWORD,
			csdefine.CLASS_ARCHER	: ShareTexts.PROFESSION_ARCHER,
			csdefine.CLASS_MAGE		: ShareTexts.PROFESSION_MAGIC,
		}

class TongSpecialShop( Window ):
	"""
	帮会特殊商城
	"""

	_cc_items_rows = ( 6, 2 )

	_item_dragMark = DragMark.TONG_SPECIAL_ITEM

	def __init__( self ):
		wnd = GUI.load( "guis/general/tongabout/specialshop/wnd.gui" )
		uiFixer.firstLoadFix( wnd )
		Window.__init__( self, wnd )
		self.posZSegment = ZSegs.L4
		self.activable_ = True
		self.escHide_ 	= True
		self.__memberInfos = {}
		self.__selPost = 0
		self.__selProf = 0
		self.__offlineChecked = True
		self.__pyMsgBox = None
		self.__triggers = {}
		self.__registerTriggers()
		self.__initialize( wnd )

	def __initialize( self, wnd ):
		itemsBg = wnd.itemsBg												# 商品面板
		self.__pageItemsPanel = ODPagesPanel( itemsBg.itemsPanel, itemsBg.pgIdxBar )			#商品购买界面
		self.__pageItemsPanel.onViewItemInitialized.bind( self.__initInvoiceItem )
		self.__pageItemsPanel.onDrawItem.bind( self.__drawInvoiceItem )
		self.__pageItemsPanel.selectable = True
		self.__pageItemsPanel.onItemSelectChanged.bind( self.__onItemSelectedChange )
		self.__pageItemsPanel.viewSize = self._cc_items_rows

		self.__pyLbGold = StaticText( wnd.moneyPanel.lbGold )
		self.__pyLbGold.text = ""
		self.__pyLbSilver = StaticText( wnd.moneyPanel.lbSilver )
		self.__pyLbSilver.text = ""
		self.__pyLbCopper = StaticText( wnd.moneyPanel.lbCoin )
		self.__pyLbCopper.text = ""

		cdtPanel = wnd.conditPanel
		self.__pyTbName = TextBox( cdtPanel.tbName.box )						#名称输入框
		self.__pyTbName.inputMode = InputMode.COMMON
		self.__pyTbName.text = ""
		self.__pyTbName.onTextChanged.bind( self.__onChangeName )
		self.__pyTbName.text = ""

		self.__pyTbMin = TextBox( cdtPanel.tbMin.box )							#最小输入
		self.__pyTbMin.inputMode = InputMode.INTEGER
		self.__pyTbMin.filterChars = ['-', '+']
		self.__pyTbMin.onTextChanged.bind( self.__onChangeMin )
		self.__pyTbMin.text = ""

		self.__pyTbMax = TextBox( cdtPanel.tbMax.box )							#最大输入
		self.__pyTbMax.inputMode = InputMode.INTEGER
		self.__pyTbMax.filterChars = ['-', '+']
		self.__pyTbMax.onTextChanged.bind( self.__onChangeMax )
		self.__pyTbMax.text = ""

		self.__pyCBPost = ODComboBox( cdtPanel.cbPost )							#职务下拉菜单
		self.__pyCBPost.autoSelect = False
		self.__pyCBPost.pyBox_.foreColor = ( 236, 215, 157, 255 )
		self.__pyCBPost.pyBox_.text = labelGather.getText( "TongAbout:SpecialShop", "post" )
		self.__pyCBPost.onItemSelectChanged.bind( self.__onPostSelected )
		duties = Const.TONG_GRADE_MAPPING.keys()
		duties.sort( reverse = True )
		for duty in duties:
			if duty == 0:continue
			dutyName = Const.TONG_GRADE_MAPPING.get( duty, "" )
			if len( dutyName ) <= 0:continue
			self.__pyCBPost.addItem( dutyName )
#		self.__pyCBPost.selItem = Const.TONG_GRADE_MAPPING[self.__selPost]

		self.__pyCBProf = ODComboBox( cdtPanel.cbProf )							#职业下拉菜单
		self.__pyCBProf.autoSelect = False
		self.__pyCBProf.pyBox_.foreColor = ( 236, 215, 157, 255 )
		self.__pyCBProf.pyBox_.text = labelGather.getText( "TongAbout:SpecialShop", "prof" )
		self.__pyCBProf.onItemSelectChanged.bind( self.__onProfSelected )
		profs = g_chs_class.keys()
		profs.sort()
		for prof in profs:
			profName = g_chs_class.get( prof )
			if profName is None:continue
			self.__pyCBProf.addItem( profName )
#		self.__pyCBProf.selItem = g_chs_class[self.__selProf]

		self.__pyBtnSearch = HButtonEx( cdtPanel.btnSearch )						#搜索
		self.__pyBtnSearch.setExStatesMapping( UIState.MODE_R4C1 )
		self.__pyBtnSearch.onLClick.bind( self.__onSearch )
		labelGather.setPyBgLabel( self.__pyBtnSearch, "TongAbout:SpecialShop", "reaschBtn" )

		self.__pyBtnReset = HButtonEx( cdtPanel.btnReset )							#重置
		self.__pyBtnReset.setExStatesMapping( UIState.MODE_R4C1 )
		self.__pyBtnReset.onLClick.bind( self.__onReset )
		labelGather.setPyBgLabel( self.__pyBtnReset, "TongAbout:SpecialShop", "resetBtn" )

		self.__pyCKOffline = CheckBoxEx( cdtPanel.ckOffline ) 			#是否离线
		self.__pyCKOffline.checked = True
		self.__pyCKOffline.onCheckChanged.bind( self.__onOfflineCheck )
		labelGather.setPyLabel( self.__pyCKOffline.pyText_, "TongAbout:SpecialShop", "showOffline" )

		memPanel = wnd.memberPanel					#成员面板
		self.__pyCndBtns = {}
		for name, child in memPanel.children:
			if not name.startswith( "cndBtn_" ):continue
			index = int( name.split( "_" )[-1] )
			pyCndBtn = HButtonEx( child )
			pyCndBtn.setExStatesMapping( UIState.MODE_R3C1 )
			pyCndBtn.isSort = True
			pyCndBtn.sortByCnd = False
			pyCndBtn.sortIndex = index
			pyCndBtn.onLClick.bind( self.__sortByCnd )
			labelGather.setPyBgLabel( pyCndBtn, "TongAbout:SpecialShop", "cnd_%d"%index )
			self.__pyCndBtns[index] = pyCndBtn

		self.__pageMembersPanel = ODPagesPanel( memPanel.itemsPanel, memPanel.pgIdxBar )			#帮会成员列表
		self.__pageMembersPanel.onViewItemInitialized.bind( self.__initMemberItem )
		self.__pageMembersPanel.onDrawItem.bind( self.__drawMemberItem )
		self.__pageMembersPanel.ownerDraw = True
		self.__pageMembersPanel.selectable = True
		self.__pageMembersPanel.onItemSelectChanged.bind( self.__onMemberSeleted )
		self.__pageMembersPanel.viewSize = (10, 1)

		self.__pyBtnConfirm = HButtonEx( wnd.btnConfirm )
		self.__pyBtnConfirm.setExStatesMapping( UIState.MODE_R4C1 )
		labelGather.setPyBgLabel( self.__pyBtnConfirm, "TongAbout:SpecialShop", "confirm" )
		self.__pyBtnConfirm.onLClick.bind( self.__onConfirm )
		self.__pyBtnConfirm.enable = False

		labelGather.setPyLabel( self.pyLbTitle_,"TongAbout:SpecialShop", "title" )
		labelGather.setLabel( itemsBg.title.stTitle, "TongAbout:SpecialShop", "invioceList" )
		labelGather.setLabel( cdtPanel.title.stTitle, "TongAbout:SpecialShop", "invioceAssign" )
		labelGather.setLabel( cdtPanel.cdtRangeText, "TongAbout:SpecialShop", "searchrange" )
		labelGather.setLabel( cdtPanel.nameText, "TongAbout:SpecialShop", "name" )

	def __initInvoiceItem( self, pyViewItem ):
		"""
		初始化商品
		"""
		item = GUI.load( "guis/general/tradewindow/item.gui" )
		uiFixer.firstLoadFix( item )
		pyInvoice = WareItem( item, self._item_dragMark, self )
		pyViewItem.pyInvoice = pyInvoice
		pyViewItem.addPyChild( pyInvoice )
		pyViewItem.dragFocus = False
		pyInvoice.left = 0
		pyInvoice.top = 0

	def __drawInvoiceItem( self, pyViewItem ):
		"""
		重置商品信息
		"""
		itemInfo = pyViewItem.pageItem
		pyInvoice = pyViewItem.pyInvoice
		pyViewItem.focus = itemInfo is not None
		pyInvoice.crossFocus = itemInfo is not None
		pyInvoice.selected = pyViewItem.selected
		pyInvoice.update( itemInfo )

	def __initMemberItem( self, pyViewItem ):
		"""
		初始化成员
		"""
		pyMember = MemberItem()
		pyMember.focus = False
		pyViewItem.addPyChild( pyMember )
		pyViewItem.focus = True
		pyMember.pos = -1.0, 1
		pyViewItem.pyItem = pyMember

	def __drawMemberItem( self, pyViewItem ):
		"""
		设置成员信息
		"""
		pyMember = pyViewItem.pyItem
		itemInfo = pyViewItem.pageItem
		pyMember.setMemberInfo( itemInfo )
		pyViewItem.focus = itemInfo is not None
		pyMember.crossFocus = itemInfo is not None
		pyViewItem.visible = itemInfo is not None
		pyMember.selected = pyViewItem.selected

	# ----------------------------------------------------------------
	# private
	# ----------------------------------------------------------------
	def __registerTriggers( self ) :
		self.__triggers["EVT_ON_TRADE_WITH_TONG_SPECIAL_CHAPMAN"] = self.__onShopShow
		self.__triggers["EVT_ON_TONG_SEPCIAL_ITEM_ADDED"] = self.__onAddSpecialItem
		self.__triggers["EVT_ON_TONG_SEPCIAL_ITEM_AMOUNT_CHANGED"] = self.__onItemAmountChanged
		self.__triggers["EVT_ONTRADE_STATE_LEAVE"] = self.__onStateLeave
		self.__triggers["EVT_ON_TOGGLE_TONG_MONEY_CHANGE"] = self.__onTongMoneyChanged
		self.__triggers["EVT_ON_TOGGLE_TONG_UPDATE_ONLINE_STATE"] = self.__onMemberOnlineStateChanged
		self.__triggers["EVT_ON_TOGGLE_TONG_UPDATE_CONTRIBUTE"] = self.__onContributeChange
		self.__triggers["EVT_ON_TOGGLE_TONG_UPDATE_TCONTRIBUTE"] = self.__onTContributeChange

		for key in self.__triggers :
			GUIFacade.registerEvent( key, self )

	def __deregisterTriggers( self ) :
		for key in self.__triggers :
			GUIFacade.unregisterEvent( key, self )
	# ---------------------------------------------------------------
	def __onShopShow( self, chapman ):
		"""
		显示商店界面
		"""
		player = BigWorld.player()
		self.__onReset( self.__pyBtnReset )
		self.__setTongCanUseMoney( player.tong_getCanUseMoney() )
		self.show()

	def __onAddSpecialItem( self, index, invoiceInfo, tradeObj = "" ):
		"""
		商店添加商品
		"""
		itemInfo = ItemInfo( index, invoiceInfo, tradeObj )
		if not itemInfo in self.__pageItemsPanel.items:
			self.__pageItemsPanel.addItem( itemInfo )

	def __onItemAmountChanged( self, index, itemInfo, tradeObject ):
		"""
		物品数量改变
		"""
		if index < 1:
			return
		else:
			for pyViewItem in self.__pageItemsPanel.pyViewItems:
				pyInvoice = pyViewItem.pyInvoice
				if pyInvoice.index == index:
					itemInfo = ItemInfo( index, itemInfo, tradeObject )
					pyInvoice.update( itemInfo )
					break

	def __onStateLeave( self, state ):
		"""
		离开交易状态
		"""
		if state == csdefine.TRADE_CHAPMAN:
			GUIFacade.tradeOverWithNPC()
			self.hide()
			BigWorld.player().tradeState = csdefine.TRADE_NONE

	def __onTongMoneyChanged( self, money ):
		"""
		帮会资金改变
		"""
		money = BigWorld.player().tong_getCanUseMoney()
		if money <= 0:
			money = 0
		self.__setTongCanUseMoney( money )

	def __setTongCanUseMoney( self, money ):
		"""
		设置可用资金
		"""
		gold = money/10000
		sliver = ( money/100 )%100
		copper = ( money%100 )%100
		self.__pyLbGold.text = str( gold )
		self.__pyLbSilver.text = str( sliver )
		self.__pyLbCopper.text = str( copper )

	def __onMemberOnlineStateChanged( self, memberDBID, isOnline ):
		"""
		帮会成员在线状态改变
		"""
		stateText = ""
		if isOnline:
			stateText = labelGather.getText( "TongAbout:SpecialShop", "online" )
		else:
			stateText = labelGather.getText( "TongAbout:SpecialShop", "offline" )
		self.__onMemberInfoChange( memberDBID, 7, 6, stateText )

	def __onContributeChange( self, memberID, contribute ):
		"""
		成员帮贡改变
		"""
		self.__onMemberInfoChange( memberDBID, 5, 4, contribute )

	def __onTContributeChange( self, memberDBID, totalContribute ):
		"""
		成员总帮贡改变
		"""
		self.__onMemberInfoChange( memberDBID, 6, 5, totalContribute )

	def __onMemberInfoChange( self, memberDBID, infoIndex, colIndex, infoValue ):
		"""
		帮会成员属性值统一更新接口
		"""
		for pyViewItem in self.__pageMembersPanel.pyViewItems:
			member = pyViewItem.pageItem
			if member is None:continue
			if member[0] == memberDBID:
				member = self.__memberInfos.get( memberDBID )
				if member is None:return
				member[infoIndex] = str( infoValue )
				pyMember = pyViewItem.pyItem
				pyMember.pyCols[colIndex].text = str( infoValue )

	def __onItemSelectedChange( self, index ):
		"""
		选取某个商品
		"""
		if index < 0: return
		itemInfo = self.__pageItemsPanel.selItem
		if itemInfo is None:return
		baseInfo = itemInfo.baseInfo
		baseItem = baseInfo.baseItem
		memberInfo = self.__pageMembersPanel.selItem
		self.__pyBtnConfirm.enable = itemInfo is not None and memberInfo is not None

	def __onMemberSeleted( self, index ):
		"""
		选择帮会成员
		"""
		if index < 0: return
		memberInfo = self.__pageMembersPanel.selItem
		for pyViewItem in self.__pageMembersPanel.pyViewItems:
			member = pyViewItem.pageItem
			if member is None:continue
			pyMember = pyViewItem.pyItem
			pyMember.selected = member[0] == memberInfo[0]
		itemInfo = self.__pageItemsPanel.selItem
		self.__pyBtnConfirm.enable = memberInfo is not None and itemInfo is not None

	def __onChangeName( self ):
		"""
		姓名改变
		"""
		pass

	def __onChangeMin( self ):
		"""
		最小值改变
		"""
		pass

	def __onChangeMax( self ):
		"""
		最大值改变
		"""
		pass

	def __onPostSelected( self, index ):
		"""
		职务选择
		"""
		if index < 0:return
		post_map = {0:csdefine.TONG_DUTY_CHIEF, 1:csdefine.TONG_DUTY_DEPUTY_CHIEF, 2:csdefine.TONG_DUTY_TONG, 3:csdefine.TONG_DUTY_MEMBER}
		self.__selPost = post_map.get( index )

	def __onProfSelected( self, index ):
		"""
		职业选择
		"""
		if index < 0:return
		prof_map = {0:csdefine.CLASS_FIGHTER, 1:csdefine.CLASS_SWORDMAN, 2:csdefine.CLASS_ARCHER, 3:csdefine.CLASS_MAGE}
		self.__selProf = prof_map.get( index )

	def __onSearch( self, pyBtn ):
		"""
		搜索
		"""
		if pyBtn is None:return
		player = BigWorld.player()
		memberName = self.__pyTbName.text
		min = 0
		max = 0
		minText = self.__pyTbMin.text
		maxText =  self.__pyTbMax.text
		if len( minText ) > 0:
			min = int( minText )
		if len( maxText ) > 0:
			max = int( maxText )
		if min > max:
			if self.__pyMsgBox is not None:
				self.__pyMsgBox.visible = False
				self.__pyMsgBox = None
			self.__pyMsgBox = showMessage( mbmsgs[0x11b1],"", MB_OK, None, pyOwner = self )
			return
		self.__pageMembersPanel.clearItems()
		members = player.tong_memberInfos
		for dbid, member in members.items():
			prof = member._class&csdefine.RCMASK_CLASS
			if not self.__offlineChecked and not member.isOnline():
				continue
			if min > 0 and member._contribute < min:
				continue
			if max > 0 and member._contribute > max:
				continue
			if self.__selPost > 0 and self.__selPost != member._grade:
				continue
			if self.__selProf > 0 and self.__selProf != prof:
				continue
			if len( memberName ) > 0 and member._name != memberName:
				continue
			memberInfo = [dbid, member._name, member._level, prof, member._grade, str(member._contribute), str(member._totalContribute), member._isOnline]
			self.__pageMembersPanel.addItem( memberInfo )

	def __onReset( self, pyBtn ):
		"""
		重置
		"""
		if pyBtn is None:return
		self.__pyTbName.text = ""
		self.__pyTbMin.text = ""
		self.__pyTbMax.text = ""
		self.__selPost = 0
		self.__selProf = 0
		self.__offlineChecked = True
		self.__pyCBPost.pyBox_.text = labelGather.getText( "TongAbout:SpecialShop", "post" )
		self.__pyCBProf.pyBox_.text = labelGather.getText( "TongAbout:SpecialShop", "prof" )
		self.__pyCKOffline.checked = self.__offlineChecked
		player = BigWorld.player()
		self.__memberInfos = {}
		self.__pageMembersPanel.clearItems()
		self.__pyTbName.tabStop = True
		for dbid, member in player.tong_memberInfos.items():
			if not dbid in self.__memberInfos:
				prof = member._class&csdefine.RCMASK_CLASS
				memberInfo = [dbid, member._name, member._level, prof, member._grade, str(member._contribute), str(member._totalContribute), member._isOnline]
				self.__memberInfos[dbid] = memberInfo
				self.__pageMembersPanel.addItem( memberInfo )

	def __onOfflineCheck( self, checked ):
		"""
		是否显示离线
		"""
		self.__offlineChecked = checked
		if checked:
			self.__showAlls()
		else:
			self.__showOnlines()

	def __showAlls( self ):
		"""
		显示全部
		"""
		self.__pageMembersPanel.clearItems()
		onlineMembers = []
		offlineMembers = []
		members = BigWorld.player().tong_memberInfos
		for dbid, member in members.iteritems():
			if member.isOnline():
				onlineMembers.append( member )
			else:
				offlineMembers.append( member )
		onlineMembers.sort( key = lambda n: n.getGrade(), reverse = True )
		offlineMembers.sort( key = lambda n: n.getGrade(), reverse = True )
		allMembers = onlineMembers + offlineMembers
		for member in allMembers:
			prof = member._class&csdefine.RCMASK_CLASS
			memberInfo = [dbid, member._name, member._level, prof, member._grade, str(member._contribute), str(member._totalContribute), member._isOnline]
			self.__pageMembersPanel.addItem( memberInfo )

	def __showOnlines( self ):
		"""
		显示在线
		"""
		self.__pageMembersPanel.clearItems()
		onlineMembers = []
		members = BigWorld.player().tong_memberInfos
		for dbid, member in members.iteritems():
			if member.isOnline():
				onlineMembers.append( member )
		onlineMembers.sort( key = lambda n: n.getGrade(), reverse = True )
		for member in onlineMembers:
			prof = member._class&csdefine.RCMASK_CLASS
			memberInfo = [dbid, member._name, member._level, prof, member._grade, str(member._contribute), str(member._totalContribute), member._isOnline]
			self.__pageMembersPanel.addItem( memberInfo )

	def __sortByCnd( self, pyCnd ):
		"""
		按条件排序
		"""
		if pyCnd is None:return
		sortIndex = pyCnd.sortIndex + 1
		flag = pyCnd.sortByCnd and True or False
		self.__pageMembersPanel.sort( key = lambda item : item[sortIndex], reverse = flag )
		pyCnd.sortByCnd = not pyCnd.sortByCnd

	def __onConfirm( self, pyBtn ):
		"""
		确认分配
		"""
		if pyBtn is None:return
		chapman = MerchantFacade.chapman
		memInfo = self.__pageMembersPanel.selItem
		itemInfo = self.__pageItemsPanel.selItem
		itemName = itemInfo.baseInfo.name_()
		amount = 1
		if chapman and chapman.__class__.__name__ == "TongSpecialChapman":
			def query( rs_id ):
				if rs_id == RS_OK:
					chapman.cell.sellArrayTo( memInfo[0], [itemInfo.index], [amount] )
		if self.__pyMsgBox is not None:
			self.__pyMsgBox.visible = False
			self.__pyMsgBox = None
		self.__pyMsgBox = showMessage( mbmsgs[0x11b0] %( itemName, memInfo[1] ),"", MB_OK_CANCEL, query, pyOwner = self )

	# ----------------------------------------------------------
	#public
	# ---------------------------------------------------------
	def onEvent( self, eventMacro, *args ) :
		"""
		respond base triggering
		"""
		self.__triggers[eventMacro]( *args )

	def onLeaveWorld( self ):
		self.hide()

	def show( self ):
		Window.show( self )

	def hide( self ):
		if rds.statusMgr.isInWorld() :
			GUIFacade.tradeOverWithNPC()
			BigWorld.player().tradeState = csdefine.TRADE_NONE
		self.__pageItemsPanel.clearItems()
		self.__pageMembersPanel.clearItems()
		self.__memberInfos = {}
		Window.hide( self )

# ------------------------------------------------------------------------------------------
# 帮会成员信息列表
class MemberItem( MultiColListItem ):

	_ITEM = None

	def __init__( self ):
		if MemberItem._ITEM is None:
			MemberItem._ITEM = GUI.load( "guis/general/tongabout/specialshop/membitem.gui" )
		item = util.copyGuiTree( MemberItem._ITEM )
		uiFixer.firstLoadFix( item )
		MultiColListItem.__init__( self, item )
		self.commonBackColor = ( 255, 255, 255, 255 )
		self.selectedBackColor = ( 255, 255, 255, 255 )
		self.highlightBackColor = ( 255, 255, 255, 255 )
		self._selected = False

	def setMemberInfo( self, member ):
		"""
		更新成员信息
		"""
		if member is None:return
		online = member[-1]
		state = labelGather.getText( "TongAbout:SpecialShop", "online" )
		self.pyCols[-1].foreColor = (255, 248, 158, 255)
		if not online:
			self.pyCols[-1].foreColor = ( 128, 128, 128, 255 )
			state = labelGather.getText( "TongAbout:SpecialShop", "offline" )
		levelText = "%d级"%member[2]
		profName = g_chs_class.get( member[3], "" )
		dutyName = Const.TONG_GRADE_MAPPING.get( member[4], "" )
		self.setTextes( member[1],
					levelText,
					profName,
					dutyName,
					member[5],
					member[6],
					state
		 )

	def onStateChanged_( self, state ) :
		"""
		状态改变时调用
		"""
		elements = self.getGui().elements
		for element in elements.values():
			element.visible = state in [ UIState.HIGHLIGHT, UIState.SELECTED ]

	def onMouseEnter_( self ):
		MultiColListItem.onMouseEnter_( self )
		if self.selected:return
		self.setState( UIState.HIGHLIGHT )

	def onMouseLeave_( self ):
		MultiColListItem.onMouseLeave_( self )
		if self.selected:return
		self.setState( UIState.COMMON )

	def _select( self ):
		self.setState( UIState.HIGHLIGHT )

	def _deselect( self ):
		self.setState( UIState.COMMON )

	def _getSelected( self ):
		return self._selected

	def _setSelected( self, selected ):
		if selected:
			self._select()
		else:
			self._deselect()
		self._selected = selected

	selected = property( _getSelected, _setSelected )

class ItemInfo:
	def __init__( self, index, baseInfo, npcName = "" ):
		self.index = index
		self.baseInfo = baseInfo
		self.npcName = npcName
		self.uid = -1

	def update( self, uid, itemInfo ):
		self.uid = uid
		self.baseInfo = itemInfo


from Chern_insulator import *
import matplotlib.pyplot as plt
import time
import argparse
import pickle
import numpy as np
from mpi4py.futures import MPIPoolExecutor
from copy import copy
import itertools

def run(p):
    Lx,Ly,m,prob=p
    params=Params(m=m,Lx=Lx,Ly=Ly)
    # prob=list(np.random.permutation([1,0]*(Lx//4*Ly)))
    params.measure_all_Born([np.arange(Lx//4,Lx//2),np.arange(Ly)],prob=prob)
    LN=params.log_neg([np.arange(Lx//4),np.arange(Ly)],[np.arange(Lx//4)+Lx//2,np.arange(Ly)])
    fn=params.fermion_number([np.arange(Lx//4,Lx//2),np.arange(Ly)])
    total_prob=params.snap_prob([np.arange(Lx//4,Lx//2),np.arange(Ly)],occ=np.array(prob)).prod()
    return LN,fn,total_prob

if __name__=="__main__":
    st=time.time()
    parser=argparse.ArgumentParser()
    parser.add_argument('--kmax',default=2,type=int)
    parser.add_argument('--Lx',default=32,type=int)
    parser.add_argument('--Ly',default=4,type=int)
    parser.add_argument('--m',default=1,type=float)

    args=parser.parse_args()
    executor=MPIPoolExecutor()
    kmax=args.kmax
    Lx=args.Lx
    Ly=args.Ly
    m=args.m
    prob=([1,0]*(Lx//4*Ly))
    prob1_list=[[prob,]]
    for k in range(1,kmax):
        prob_k_list=[]
        nchoosek=list(itertools.combinations(np.arange(Lx*Ly//4),k))
        for i1 in (nchoosek):
            for i2 in (nchoosek):
                prob_k=copy(prob)
                prob_k=np.array(prob_k)
                prob_k[2*np.array(list(i1))]=0
                prob_k[2*np.array(list(i2))+1]=1
                prob_k_list.append(list(prob_k))
        prob1_list.append(prob_k_list)

    LN_map=[]
    fn_map=[]
    total_prob_map=[]
    for k,prob_list in enumerate(prob1_list):
        st=time.time()
        inputs=[(Lx,Ly,m,prob) for prob in prob_list]
        LN_list=np.zeros(len(prob_list))
        fn_list=np.zeros(len(prob_list))
        total_prob_list=np.zeros(len(prob_list))
        pool=executor.map(run, inputs)
        # pool=map(run, inputs)
        for es_i,result in enumerate(pool):
            LN,fn,total_prob=result
            LN_list[es_i]=LN
            fn_list[es_i]=fn
            total_prob_list[es_i]=total_prob
        LN_map.append(LN_list)
        fn_map.append(fn_list)
        total_prob_map.append(total_prob_list)

        with open('CI_kmax{:d}_Lx{:d}_Ly{:d}_m{:.1f}.pickle'.format(kmax,Lx,Ly,m),'wb') as f:
            pickle.dump([LN_map,fn_map,total_prob_map],f)

        print('k={:d}, len={:d}, {:.1f}'.format(k,len(prob_list),time.time()-st))


import pygame
import Levels
from random import randint
import sys

class GameClass:
    def __init__(self):
        self.WIDTH = 1000  # ширина игрового окна
        self.HEIGHT = 800  # высота игрового окна
        self.FPS = 60  # частота кадров в секунду
        # создаем игру и окно
        pygame.init()
        pygame.font.init()  # для текста!
        pygame.mixer.init()  # для звука
        pygame.mixer.music.load('Sources/Sounds/PPK - Ressurection .wav')
        pygame.mixer.music.set_volume(0.3)
        pygame.mixer.music.play(-1)
        self.sound_of_touch = pygame.mixer.Sound('Sources/Sounds/Запись.wav')
        self.org_screen = pygame.display.set_mode((self.WIDTH, self.HEIGHT))
        self.screen = self.org_screen.copy()
        self.delta_x = 0
        self.delta_y = 0
        self.shake_ticks = 0
        pygame.display.set_caption("DMD907")
        self.clock = pygame.time.Clock()
        self.PURPURN = (0, 0, 100)
        self.nlo_img = pygame.image.load('Sources/Images/nlo.png').convert_alpha()
        self.bullet_img = pygame.image.load('Sources/Images/bullet.png').convert_alpha()
        self.background_image = pygame.image.load('Sources/Images/фон.jpg').convert_alpha()
        self.background_image = pygame.transform.scale(self.background_image, (self.WIDTH, self.HEIGHT))
        self.is_running = True

        file = open('score.data', 'r+')
        self.score = [0] * 3
        for i, line in enumerate(file):
            self.score[i] = float(line)
        file.close()

        self.objects = []
        self.objects_dict = {}
        self.scripts = []
        self.scripts_dict = {}
        self.handlers = []
        self.handlers_dict = {}

        self.current_level = Levels.MenuLevel(self)

    def add_object(self, obj, name: str = ''):
        self.objects.append(obj)
        if name:
            self.objects_dict[name] = obj

    def add_handler(self, handler, name: str = ''):
        self.handlers.append(handler)
        if name:
            self.handlers_dict[name] = handler

    def add_script(self, script, name: str = ''):
        self.scripts.append(script)
        if name:
            self.scripts_dict[name] = script

    def fps(self):
        self.clock.tick(self.FPS)

    def run_scripts(self):
        for script in self.scripts:
            if script.run():
                return
        for o in self.objects:
            if o.run_scripts():
                return

    def events(self):
        all_events = pygame.event.get()
        # все события за текущий кадр
        for handler in self.handlers:
            handler.process(all_events)

    def update(self):
        for o in self.objects:
            if o.update():
                break

    def draw(self):
        self.screen.fill(self.PURPURN)
        self.screen.blit(self.background_image, (0, 0))

        for o in self.objects:
            o.draw()
        if self.shake_ticks > 0:
            self.shake_ticks -= 1
            if self.shake_ticks % 5 == 0:
                self.delta_x = randint(-10, 10)
                self.delta_y = randint(-10, 10)
        else:
            self.delta_x = 0
            self.delta_y = 0
        self.org_screen.blit(self.screen, (self.delta_x, self.delta_y))

    def start(self):
        while self.is_running:
            self.fps()
            self.run_scripts()
            self.events()
            self.update()
            self.draw()
            pygame.display.flip()

    def clear(self):
        self.objects.clear()
        self.objects_dict.clear()
        self.handlers.clear()
        self.handlers_dict.clear()
        self.scripts.clear()
        self.scripts_dict.clear()


from collections import deque

n, m = map(int, input().split())
arr = [list(map(int, str(input()))) for _ in range(n)]

visited = [[[0] * 2 for _ in range(m)] for _ in range(n)]  # 특정 위치와 벽을 부쉈을 경우, 안부쉈을경우를 나타내기위해 3차원 리스트로 초기화

# visited의 [x]는 행 [y]는 열 [z][0]은 벽을 안부순경우, [z][1] 부순경우 이다

def bfs():
    queue = deque([(0, 0, 0)])
    visited[0][0][0] = 1
    dxy = [(1, 0), (-1, 0), (0, 1), (0, -1)]
    while queue:
        x, y, z = queue.popleft()
        if x == n - 1 and y == m - 1:  # 목표 지점에 도달할 경우 리턴, 일단 먼저 도착하는게 최단경로이므로 이래도 됨
            return visited[x][y][z]
        for dx, dy in dxy:
            nx = x + dx
            ny = y + dy
            if nx < 0 or nx >= n or ny < 0 or ny >= m:
                continue
            if arr[nx][ny] == 0 and visited[nx][ny][z] == 0:  # 만약 벽이 없고 방문 하지 않았다면
                visited[nx][ny][z] = visited[x][y][z] + 1  # 거리를 기존 위치에서 1 늘려서 저장
                queue.append((nx, ny, z))  # 다음 위치를 큐에 넣음
            elif arr[nx][ny] == 1 and z == 0:  # 만약 벽이고 지금까지 벽을 부순적이 없다면
                visited[nx][ny][z + 1] = visited[x][y][z] + 1  # 벽을 부순 경우의 값을 현재 위치 +1로 저장
                queue.append((nx, ny, z + 1))  # 벽을 부순 경우를 큐에 넣음
    return -1

print(bfs())

백준/Gold/2206. 벽 부수고 이동하기/벽 부수고 이동하기.py

벽 부수고 이동하기.py


#!/usr/bin/env python
# -*- coding: utf-8 -*-

import numpy as np
from scipy.spatial import distance_matrix

class OEM_batch:
    """
    On line Elastic Similarity class

    Parameters
    ----------
    R : 1-D array_like
        time series pattern
    w : float
        On-line similarity measure memory. Must be between 0 and 1.
    rateX : float, optional, default: 1
        Reference Time series generate_files rate
    rateY : float, optional, default: None
        Query Time series generate_files rate. If rateY = None it takes rateX value
    dist : string, optional, default: 'euclidean'
        cost function
        OPTIONS:
        'euclidean': np.sqrt((x_i - y_j)**2)
        'edr':       1 if abs(x_i - y_j) >= epsilon else 0
        'edit':      1 if x_i != y_j else 0
        'erp':       abs(x_i - y_j) if abs(x_i - y_j) >= epsilon else 0
    epsilon : float, optional, default: None
        edr threshold parameter
    """

    def __init__(self, R, w, dist='euclidean', epsilon=None):

        if dist in ['euclidean', 'edr', 'erp', 'edit', 'euclidean_new']:
            self.dist = dist
        else:
            raise ValueError('Not valid dist value')

        if isinstance(R, (np.ndarray)) and R.size > 2:
            self.R = R

        if (w >= 0) and (w <= 1):
            self.w = w
        else:
            raise ValueError('w must be between 0 and 1')

        if (epsilon is None) and (dist in ['edr', 'erp']):
            raise ValueError(
                'for dist edr or erp epsilon must be a non negative float')
        elif (epsilon is not None) and epsilon < 0:
            raise ValueError('epsilon must be a non negative float')
        self.epsilon = epsilon

    def init_dist(self, S):
        """
        Initial Similarity Measure

        Parameters
        ----------
        S : 1-D array_like
            Array containing time series observations

        Returns
        -------
        dist: float
            Elastic Similarity Measure between R (pattern time series) and S (query time series)
        """

        if isinstance(S, (np.ndarray)) and S.size > 2:
            pass
        else:
            raise ValueError('S time series must have more than 2 instances')

        # Compute point-wise distance
        if self.dist == 'euclidean':
            RS = self.__euclidean(self.R, S)
        if self.dist == 'euclidean_new':
            RS = self.__euclidean_new(self.R, S)
        elif self.dist == 'edr':
            RS = self.__edr(self.R, S, self.epsilon)
        elif self.dist == 'erp':
            RS = self.__erp(self.R, S, self.epsilon)
        elif self.dist == 'edit':
            RS = self.__edit(self.R, S)

        # compute recursive distance matrix using dynamic programing
        r, s = np.shape(RS)

        # Solve first row
        for j in range(1, s):
            RS[0, j] += self.w * RS[0, j - 1]

        # Solve first column
        for i in range(1, r):
            RS[i, 0] += RS[i - 1, 0]

        # Solve the rest
        for i in range(1, r):
            for j in range(1, s):
                RS[i, j] += np.min([RS[i - 1, j], self.w *
                                    RS[i - 1, j - 1], self.w * RS[i, j - 1]])

        # save statistics
        self.dtwR = RS[:, -1]

        return RS

    def update_dist(self, Y):
        '''
        Add new observations to query time series

        Parameters
        ----------
        Y : array_like or float
            new query time series observation(s)

        Returns
        -------
        dist : float
            Updated distance

        Warning: the time series have to be non-empty
        (at least composed by a single measure)

          -----------
        R | RS | RY |
          -----------
            S    Y
        '''

        if isinstance(Y, (np.ndarray)):
            pass
        else:
            Y = np.array([Y])

        # Solve RY
        dtwRY = self._solveRY(Y, self.dtwR)

        # Save statistics
        self.dtwR = dtwRY

        return dtwRY

    def __euclidean(self, X, Y):
        Y_tmp, X_tmp = np.meshgrid(Y, X)
        XY = np.sqrt((X_tmp - Y_tmp)**2)
        return XY

    def __euclidean_new(self, X, Y):
        return distance_matrix(X, Y, p=2)**2

    def __edr(self, X, Y, epsilon):
        Y_tmp, X_tmp = np.meshgrid(Y, X)
        XY = 1.0 * (abs(X_tmp - Y_tmp) < epsilon)
        return XY

    def __erp(self, X, Y, epsilon):
        Y_tmp, X_tmp = np.meshgrid(Y, X)
        XY = abs(X_tmp - Y_tmp)
        XY[XY < epsilon] = 0
        return XY

    def __edit(self, X, Y):
        Y_tmp, X_tmp = np.meshgrid(Y, X)
        XY = 1.0 * (X_tmp == Y_tmp)
        return XY

    def _solveRY(self, Y, dtwR):
        '''
        R, Y: to (partial) time series
         -----------
        R|prev| RY |
         -----------
           S    Y

        dtwR: partial solutions of DTW(R,S)
        iniI: Index of the first point of R in the complete time series
        iniJ: Index of the first point of Y in the complete time series

        * Warning *: R and Y have to be nonempty (partial) series
        '''

        # Compute point-wise distance
        if self.dist == 'euclidean':
            RY = self.__euclidean(self.R, Y)
        if self.dist == 'euclidean_new':
            RY = self.__euclidean_new(self.R, Y)
        elif self.dist == 'edr':
            RY = self.__edr(self.R, Y, self.epsilon)
        elif self.dist == 'erp':
            RY = self.__erp(self.R, Y, self.epsilon)
        elif self.dist == 'edit':
            RY = self.__edit(self.R, Y)

        r, n = np.shape(RY)

        # First first column
        RY[0, 0] += self.w * dtwR[0]
        for i in range(1, r):
            RY[i, 0] += np.min([
                RY[i - 1, 0], self.w * dtwR[i - 1], self.w * dtwR[i]])

        # Solve first row
        for j in range(1, n):
            RY[0, j] += self.w * RY[0, j - 1]

        # Solve the rest
        for j in range(1, n):
            for i in range(1, r):
                RY[i, j] += np.min([RY[i - 1, j], self.w *
                                    RY[i - 1, j - 1], self.w * RY[i, j - 1]])

        return RY[:, -1]


from icecream import ic

from data_storage import dbControl
from data_storage.sql_tools import sql_selects, sql_update
from data_storage.sql_creates import sql_creates
from data_storage.re_patterns import identify_item, items_data

item_name = 'directory'
db_filename = r'F:\Kazak\GoogleDrive\1_KK\Job_CNAC\Python_projects\development\Quotes_parsing_SQLite\output\Quotes.sqlite'

with dbControl(db_filename) as db:
    db.run_execute("""DROP TABLE IF EXISTS tblCatalogs;""")
    db.run_execute(sql_creates["create_table_catalogs"])

    code = '0'
    period = 0
    # period, code, description, raw_parent, ID_parent, FK_tblCatalogs_tblCatalogItems
    query = sql_selects["select_name_catalog_items"]
    id_catalog_items = db.get_id(query, items_data[item_name].name)
    ic(id_catalog_items)
    data = (period, code, 'Справочник расценок', code, 1, id_catalog_items)
    message = f"вставка 'Справочник' код: {code!r}"
    inserted_id = db.try_insert(sql_creates["insert_catalog"], data, message)
    if inserted_id:
        ic(inserted_id)
        # ссылка родителя самого на себя
        up_data = (inserted_id, inserted_id)
        message = f"UPDATE код родителя 'Справочник' {code!r}"

        inserted_id = db.run_execute(sql_update["update_catalog_id_parent"], up_data)
        # inserted_id = db.try_insert(sql_update["update_catalog_id_parent"], up_data, message)

        log = f"добавлена запись: {items_data[item_name].name.capitalize()!r} id: {inserted_id}"
        ic(log)
    else:
        log = f"запись НЕ добавлена: {items_data[item_name].name.capitalize()!r} id: {inserted_id}"
        ic(log)


import django.db.models.deletion
from django.db import migrations, models

class Migration(migrations.Migration):

    dependencies = [
        ('cms', '__first__'),
    ]

    operations = [
        migrations.CreateModel(
            name='GoogleMap',
            fields=[
                ('cmsplugin_ptr', models.OneToOneField(serialize=False, parent_link=True, auto_created=True, to='cms.CMSPlugin', primary_key=True, on_delete=django.db.models.deletion.CASCADE)),
                ('title', models.CharField(verbose_name='map title', blank=True, null=True, max_length=100)),
                ('address', models.CharField(verbose_name='address', max_length=150)),
                ('zipcode', models.CharField(verbose_name='zip code', max_length=30)),
                ('city', models.CharField(verbose_name='city', max_length=100)),
                ('content', models.CharField(help_text='Displayed under address in the bubble.', blank=True, max_length=255, verbose_name='additional content')),
                ('zoom', models.PositiveSmallIntegerField(verbose_name='zoom level', default=13, choices=[(0, '0'), (1, '1'), (2, '2'), (3, '3'), (4, '4'), (5, '5'), (6, '6'), (7, '7'), (8, '8'), (9, '9'), (10, '10'), (11, '11'), (12, '12'), (13, '13'), (14, '14'), (15, '15'), (16, '16'), (17, '17'), (18, '18'), (19, '19'), (20, '20'), (21, '21')])),
                ('lat', models.DecimalField(help_text='Use latitude & longitude to fine tune the map position.', blank=True, max_digits=10, verbose_name='latitude', null=True, decimal_places=6)),
                ('lng', models.DecimalField(max_digits=10, verbose_name='longitude', blank=True, null=True, decimal_places=6)),
                ('route_planer_title', models.CharField(verbose_name='route planer title', blank=True, null=True, max_length=150, default='Calculate your fastest way to here')),
                ('route_planer', models.BooleanField(verbose_name='route planer', default=False)),
                ('width', models.CharField(help_text='Plugin width (in pixels or percent).', default='100%', max_length=6, verbose_name='width')),
                ('height', models.CharField(help_text='Plugin height (in pixels).', default='400px', max_length=6, verbose_name='height')),
                ('info_window', models.BooleanField(help_text='Show textbox over marker', default=True, verbose_name='info window')),
                ('scrollwheel', models.BooleanField(help_text='Enable scrollwheel zooming on the map', default=True, verbose_name='scrollwheel')),
                ('double_click_zoom', models.BooleanField(verbose_name='double click zoom', default=True)),
                ('draggable', models.BooleanField(verbose_name='draggable', default=True)),
                ('keyboard_shortcuts', models.BooleanField(verbose_name='keyboard shortcuts', default=True)),
                ('pan_control', models.BooleanField(verbose_name='Pan control', default=True)),
                ('zoom_control', models.BooleanField(verbose_name='zoom control', default=True)),
                ('street_view_control', models.BooleanField(verbose_name='Street View control', default=True)),
            ],
            options={
                'abstract': False,
            },
            bases=('cms.cmsplugin',),
        ),
    ]


from unittest import TestCase
from sliding_window.buy_sell_stock import Solution
class TestSolution(TestCase):
    def test_buy_sell_stock_1(self):
        solution = Solution()
        prices = [7,1,5,3,6,4]
        expected_result = 5
        actual_result = solution.buy_sell_stock(prices)
        self.assertEqual(expected_result,actual_result)

    def test_buy_sell_stock_2(self):
        solution = Solution()
        prices = [7,6,4,3,1]
        expected_result = 0
        actual_result = solution.buy_sell_stock(prices)
        self.assertEqual(expected_result,actual_result)


import torchvision
import torch
import csv

from os.path import join
from collections import OrderedDict
from itertools import islice

import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
from io import BytesIO

def get_image_pairs():
    test_dir = './CW_data/test/'
    training_dir = './CW_data/training/'
    answers = OrderedDict()
    with open('test-training_map.txt', mode='r') as csv_file:
        csv_reader = csv.DictReader(csv_file)
        for row in csv_reader:
            if 'f' in row['training']:
                continue
            answers[ join(test_dir, row['test']) ] = join(training_dir, row['training'])

    return answers

def do_img(filename):
    image = Image.open(filename)

    image_tensor = torchvision.transforms.functional.to_tensor(image)

    # pass a list of (potentially different sized) tensors
    # to the model, in 0-1 range. The model will take care of
    # batching them together and normalizing
    output = do_img.model([image_tensor])
    # output is a list of dict, containing the postprocessed predictions

    plt.subplots(figsize=(50,100))
    tmp = np.array(image)
    mask = torch.zeros(tmp.shape)
    for keypoints in output[0]["keypoints"]:
        for keypoint in keypoints:
            x,y,_ = keypoint.data
            # print(int(y), int(x))
            for dx in range(-5,6):
                # mask[int(y), int(x),1] = 1
                mask[int(y+dx), int(x+dx),1] = 1
                mask[int(y-dx), int(x+dx),1] = 1
        break
    mask = mask  + tmp / 255  *0.6
    # plt.subplot(2,1,1)
    # plt.imshow(tmp)
    # plt.subplot(2,1,1)
    plt.imshow(mask)
    plt.show()

def main():

    do_img.model = torchvision.models.detection.keypointrcnn_resnet50_fpn(pretrained=True).eval()
    test_training_mapping = get_image_pairs()

    num_of_pairs = 22
    sliced = islice(test_training_mapping.items(), num_of_pairs)
    trimmed_mapping = OrderedDict(sliced)

    for test,training in trimmed_mapping.items():
        print (test, training)
        do_img(test)
        do_img(training)

if __name__ == "__main__":
    main()


# Solution part

def deepest_node(tree):
    if tree.root != None:
        height, deepest_node = __deepest_node(tree.root, 0)
        print(deepest_node.value)

def __deepest_node(cur_node, height):
    if cur_node.left_child == None and cur_node.right_child == None:
        return height, cur_node

    left_height = right_height = 0

    if cur_node.left_child != None:
        left_height, left_node = __deepest_node(cur_node.left_child, height+1)
    if cur_node.right_child != None:
        right_height, right_node = __deepest_node(cur_node.right_child, height+1)

    if left_height > right_height:
        return left_height, left_node
    return right_height, right_node

# Testing part

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

class Tree:
    def __init__(self):
        self.root = None

    def add(self, value):
        if self.root == None:
            self.root = node(value)
        else:
            self.__add(self.root, value)

    def __add(self, cur_node, value):
        if value < cur_node.value:
            if cur_node.left_child == None:
                cur_node.left_child = node(value)
            else:
                self.__add(cur_node.left_child, value)
        elif value > cur_node.value:
            if cur_node.right_child == None:
                cur_node.right_child = node(value)
            else:
                self.__add(cur_node.right_child, value)

tree = Tree()
for i in range(5):
    tree.add(i)

deepest_node(tree)


# 抓資料要跑很久! 要留30分鐘

import requests
import pandas as pd
import bs4
import time

name_col = ['titl', 'link', 'push', 'auth', 'date', 'text','reply']
tt1_col = []  # 做一個空的list
list1 = []
#1925
for num in range(1925, 2586):
    print(num)
    res = requests.get('https://www.ptt.cc/bbs/creditcard/index' + str(num) + '.html')
    soup = bs4.BeautifulSoup(res.text, "html.parser")
    time.sleep(10)
    aa = soup.select('div[class="nrec"] > span')
    titl = soup.select('div[class="title"] > a')
    link = soup.select('div[class="title"] > a')
    push = soup.select('.nrec')
    auth = soup.select('.author')
    date = soup.select('.date')

    list2 = []
    for i in range(len(titl)):
        #print(link[i])
        main = requests.get('https://www.ptt.cc' + link[i]['href'])
        main_soup = bs4.BeautifulSoup(main.text, "html.parser")
        main_text = main_soup.select('div[id="main-content"]')
        text = ""

        if main_text != []:
            for p in main_text[0].contents:
                if type(p) == bs4.element.NavigableString:
                    text = text + "\n" + p.string
            # content = filter(lambda x: type(x) != bs4.element.Tag, main_text[0].contents)
            # content1 = reduce(lambda x,y: x+y,map(lambda x: x.string,content))
            #print(text)

            push_tag = main_soup.select('div[class="push"]')
            #print(list(map(lambda x:len(x.contents), push_tag)))
            #print(push_tag)

            def get_push(x):
                if x.contents[2].string != None :
                    return x.contents[2].string[2::]
                else :
                    return " "

            #print(list(map(lambda x:len(x.contents), aa)))
            #push_type = list(map(lambda x:x.contents[0].string, push_tag))
            auth_push = list(map(lambda x:x.contents[1].string, push_tag))
            #content = list(map(get_push, push_tag))
            #sss = list(map(lambda x:x.contents[3].string, push_tag))
            uni_auth = []
            for x in auth_push:
                if x not in uni_auth:
                    uni_auth.append(x)
    # =============================================================================
    #         x = {}
    #         for a, b in zip(auth_push, content):
    #             if a not in x:
    #                 x[a] = ""
    #             x[a] = x[a] + b
    # =============================================================================

            #list2.append(text)
            #print(list2[1])
            if  push[i].string == None:
                push[i].string = '0'
            if  titl[i].string != None:
                list1.append([titl[i].string, link[i]['href'], push[i].string, auth[i].string, date[i].string, text, len(uni_auth)])

df_data_PTT = pd.DataFrame(list1, columns=name_col)
df_data_PTT.to_csv("C:/Users/TSR/Desktop/python/17Q4 ptt/Data1_ptt.csv")


import torch
import torch.nn as nn
import torch.nn.functional as F
from torch import distributions as dist
from torch.autograd import Function
import numpy as np
import math

# from torch_geometric.nn.pool import voxel_grid
import logging

def maxpool(x, dim=-1, keepdim=False):
    out, _ = x.max(dim=dim, keepdim=keepdim)
    return out

# Resnet Blocks
class ResnetBlockFC(nn.Module):
    ''' Fully connected ResNet Block class.

    Args:
        size_in (int): input dimension
        size_out (int): output dimension
        size_h (int): hidden dimension
    '''

    def __init__(self, size_in, size_out=None, size_h=None):
        super().__init__()
        # Attributes
        if size_out is None:
            size_out = size_in

        if size_h is None:
            size_h = min(size_in, size_out)

        self.size_in = size_in
        self.size_h = size_h
        self.size_out = size_out
        # Submodules
        self.fc_0 = nn.Linear(size_in, size_h)
        self.fc_1 = nn.Linear(size_h, size_out)
        self.actvn = nn.ReLU()

        if size_in == size_out:
            self.shortcut = None
        else:
            self.shortcut = nn.Linear(size_in, size_out, bias=False)
        # Initialization
        nn.init.zeros_(self.fc_1.weight)

    def forward(self, x):
        net = self.fc_0(self.actvn(x))
        dx = self.fc_1(self.actvn(net))

        if self.shortcut is not None:
            x_s = self.shortcut(x)
        else:
            x_s = x

        return x_s + dx

class ResnetPointnet(nn.Module):
    ''' PointNet-based encoder network with ResNet blocks.
    Args:
        c_dim (int): dimension of latent code c
        dim (int): input points dimension
        hidden_dim (int): hidden dimension of the network
    '''

    def __init__(self, c_dim=128, dim=3, VAE=False):
        super().__init__()
        self.c_dim = c_dim
        self.vae = VAE

        hidden_dim=128

        self.fc_pos = nn.Linear(dim, 2*hidden_dim)
        self.block_0 = ResnetBlockFC(2*hidden_dim, hidden_dim)
        self.block_1 = ResnetBlockFC(2*hidden_dim, hidden_dim)
        self.block_2 = ResnetBlockFC(2*hidden_dim, hidden_dim)
        self.block_3 = ResnetBlockFC(2*hidden_dim, hidden_dim)
        self.block_4 = ResnetBlockFC(2*hidden_dim, hidden_dim)

        if self.vae:
            self.fc_mean = nn.Linear(hidden_dim, c_dim)
            self.fc_std = nn.Linear(hidden_dim, c_dim)
            torch.nn.init.constant_(self.fc_mean.weight,0)
            torch.nn.init.constant_(self.fc_mean.bias, 0)
            torch.nn.init.constant_(self.fc_std.weight, 0)
            torch.nn.init.constant_(self.fc_std.bias, -10)
            self.fc_c = None
        else:
            self.fc_c = nn.Linear(hidden_dim, c_dim)
            self.fc_mean = None
            self.fc_std = None

        self.actvn = nn.ReLU()
        self.pool = maxpool

    def name(self):
        if self.vae:
            return "ResNetPointNet_VAE"
        else:
            return "ResNetPointNet"

    def forward(self, p):
        batch_size, T, D = p.size()

        # # output size: B x T X F
        net = self.fc_pos(p)
        net = self.block_0(net)
        pooled = self.pool(net, dim=1, keepdim=True).expand(net.size())
        net = torch.cat([net, pooled], dim=2)

        net = self.block_1(net)
        pooled = self.pool(net, dim=1, keepdim=True).expand(net.size())
        net = torch.cat([net, pooled], dim=2)

        net = self.block_2(net)
        pooled = self.pool(net, dim=1, keepdim=True).expand(net.size())
        net = torch.cat([net, pooled], dim=2)

        net = self.block_3(net)
        pooled = self.pool(net, dim=1, keepdim=True).expand(net.size())
        net = torch.cat([net, pooled], dim=2)

        net = self.block_4(net)

        # Recude to  B x F
        net = self.pool(net, dim=1)

        if self.vae:
            c_mean = self.fc_mean(self.actvn(net))
            c_std = self.fc_std(self.actvn(net))
            return c_mean,c_std
        else:
            c = self.fc_c(self.actvn(net))
            return c, None


def welcome():
    print('bienvenido a tu agenda personalizada!')

def get_option():
    accion=input('1- Agendar nuevo evento\n2- Ver eventos guardados\n3- Salir\n-=> ')
    while accion!='1' and accion!='2' and accion!='3':
        accion=input('ingreso invalido, seleccione una opcion\n1- Agendar nuevo evento\n2- Ver eventos guardados\n=> ')
    return accion

def tomar_nombre():

    nombre_evento=input('indique el nombre del evento a agendar:  ')
    while not nombre_evento.isalpha():
        nombre_evento=input('ingreso invalido. indique el nombre del evento a agendar:  ')

    return nombre_evento

def tomar_fecha(meses,dias,horas):
    print('***seleccione el mes del evento***')
    for mes in meses:
        print(mes)
    mes_seleccionado=input('=> ')

    print('***seleccione el dia del evento***')
    if mes_seleccionado.lower=='febrero':
        for dia in range(1,29):
            print (dia)
    elif mes_seleccionado.lower=='abril' or mes_seleccionado=='junio' or mes_seleccionado=='septimebre' or mes_seleccionado=='noviembre':
        for dia in range(1,31):
            print(dia)
    else:
        for dia in dias:
            print(dia)
    dia_seleccionado=input('=> ')

    print('***seleccione la hora del evento***')
    for hora in horas:
        print(hora)
    hora_seleccionada=input('=> ')

    evento=[mes_seleccionado,dia_seleccionado,hora_seleccionada]
    return evento

def crear_evento(nombre_evento,fecha):
    evento={nombre_evento:fecha}
    return evento

def verificar_disponibilidad(nombre_evento,fecha,ocupado,meses,dias,horas):
    for evento in ocupado:
        if fecha[0] and fecha[1] and fecha[2] in evento:
            print(f'\n Ya hay un evento agendado para esta fecha: {evento[0]}  {evento[1]}  {evento[2]}')
            print('\npor favor ingrese una nueva fecha\n')
            fecha=tomar_fecha(meses,dias,horas)
            break
        return True, ocupado
    print(f'Evento agendado con exito: {nombre_evento} :  {fecha[0]}  {fecha[1]}  {fecha[2]}')
    fecha.append(nombre_evento)
    ocupado.append(fecha)
    return False, ocupado

def mostrar_eventos(ocupado):
    print('\nNOMBRE: MES - DIA - HORA')
    for evento in ocupado:
        print(f'{evento[-1]}: {evento[0]} - {evento[1]} - {evento[2]}')

def main():
    welcome()
    ocupado=[]
    meses=['enero','febrero','marzo','abril','mayo','junio','julio','agosto','septiembre','octubre','noviembre','diciembre']
    dias=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]
    horas=['12:00 AM','1:00 AM','2:00 AM','3:00 AM','4:00 AM','5:00 AM','6:00 AM','7:00 AM','8:00 AM','9:00 AM','10:00 AM','11:00 AM','12:00 PM','1:00 PM','2:00 PM','3:00 PM','4:00 PM','5:00 PM','6:00 PM','7:00 PM','8:00 PM','9:00 PM','10:00 PM','11:00 PM']
    while True:
        accion=get_option()
        if accion=='1':
            nombre_evento=tomar_nombre()
            fecha=tomar_fecha(meses,dias,horas)
            evento=crear_evento(nombre_evento,fecha)
            #ocupado.append(evento)
            unavailable=True
            while unavailable:
                unavailable, ocupado=verificar_disponibilidad(nombre_evento,fecha,ocupado,meses,dias,horas)

        elif accion=='2':
            if ocupado==[]:
                print('Por los momento no hay ningun evento agendado')
            else:
                mostrar_eventos(ocupado)

            pass
        else:
            break

main()


def solution(n, results):
    answer = 0
    win = [set() for _ in range(n+1)]
    lose = [set() for _ in range(n+1)]
    for w,l in results:
        win[w].add(l) # w이 이긴애들
        lose[l].add(w) # l이 진 애들

    for i in range(1,n+1):
        for loser in win[i]: # i한테 진 애들은 i가 진애들한테도 진다
            lose[loser].update(lose[i])
        for winner in lose[i]: #i한테 이긴 애들은 i가 진 애들한테도 이긴다
            win[winner].update(win[i])

    cnt = 0
    for i in range(1,n+1):
        if len(lose[i]) + len(win[i]) == n-1:
            cnt += 1
    answer = cnt
    return answer


class Solution:
    def maximumUnits(self, boxTypes: List[List[int]], truckSize: int) -> int:
        ret = 0
        boxTypes.sort(key = lambda unit:-unit[1])

        for box in boxTypes:
            amt = box[0]
            unit = box[1]

            if amt <= truckSize:
                ret += amt * unit
                truckSize -= amt
            else:
                ret += truckSize * unit
                truckSize = 0;

            if truckSize == 0:
                break

        return ret


class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def isSymmetric(root):
    if not root:
        return True
    return isSame(root.left, root.right)

def isSame(leftroot, rightroot):
    if (not leftroot and rightroot) or (leftroot and not rightroot) or (leftroot and rightroot and leftroot.val != rightroot.val):
        return False
    if leftroot and rightroot:
        return isSame(leftroot.left, rightroot.right) and isSame(leftroot.right, rightroot.left)
    return True